Ichijoji Sagarimatsu

統計モデリング 生態学のデータ解析・麻雀の解析など

【天鳳】天鳳位なるまでシミュレーションを回してみた【閲覧注意?】

天鳳位になるまで打ち続けた場合」にどれだけの試合数がかかるのか気になったので調べてみました。

私の知る範囲ではこれについて調べた記事は見つからなかったので、自作関数を作ってシミュレーションを回してみました。

記事の前半では天鳳位なるまでチャレンジ後半では十段なるまでチャレンジの結果を紹介します。


設定としては、7段原点(1400pt)を開始地点として、(実力としての)安定段位が9.5段・9段・8.5段・8段の4通りについて、天鳳位(十段)になるまでのシミュレーションを1000回まわし、何半荘かかったかを調べました。

なお、順位分布は各安定段位になるような等差順列(1>2>3>4型)を想定しました。

天鳳位チャレンジのシミュレーション

天鳳位チャレンジ:安定9.5段(.284-.261-.239-.216)

中央値で2890半荘、平均にすると3739半荘かかりました。
中央値で2890半荘というのは、この実力の人たちを集めて打たせたら2890半荘以内に半数が天鳳位になってるということです。
逆に言うと残り半数は2890半荘時点で天鳳位になれていないということです。
実力安定9.5段というとウルトラ鉄強なんですが、意外に時間がかかりますね。イヤな予感がしてきました。

天鳳位チャレンジ:安定9段(.278-.259-.241-.222)

中央値で5936半荘、平均で8145半荘かかりました。
安定9段も超鉄強なんですが、沼ると20000半荘以上かかるようです。
そういったケースに引っ張られて、中央値と平均値の乖離は大きくなっています。

天鳳位チャレンジ:安定8.5段(.271-.257-.243-.229)

中央値で17243半荘、平均で25722半荘かかりました。
安定8.5段も十分に鉄強です。

天鳳位チャレンジ:安定8段(.265-.255-.245-.235)

中央値で89517半荘、平均で125743半荘かかりました。
一方で100人に1人は2000半荘程度で天鳳位をとれるようです。

十段チャレンジのシミュレーション

では初めて十段になるまでには何半荘かかるでしょうか。
ここからは十段チャレンジの結果を紹介します。

十段チャレンジ:安定9.5段(.284-.261-.239-.216)

中央値で1018半荘、平均で1198半荘かかりました

十段チャレンジ:安定9段(.278-.259-.241-.222)

中央値で1418半荘、平均で1767半荘かかりました

十段チャレンジ:安定8.5段(.271-.257-.243-.229)

中央値で2351半荘、平均で3044半荘かかりました

十段チャレンジ:安定8段(.265-.255-.245-.235)

中央値で5754半荘、平均で7592半荘かかりました

おわりに:天鳳との向き合い方

改めて天鳳の闇が深すぎることがわかりました。

安定9段といえば超鉄強なんですが、それでも下振れると20000半荘天鳳位を取れない一方で、安定8段が上振れれば2000半荘で取ってしまうようです。

どれだけ麻雀の腕に自信があっても、天鳳位獲得を目標にするのは気が狂ってしまう可能性があるためお勧めできません。

私も一応、一鳳凰民として天鳳位は目指していますが、自分で結果を見て正直ゲンナリしてしまいました。

まぁ、(良い意味でも悪い意味でも)所詮はゲームということですね。

純粋に天鳳ではレベルの高い麻雀が(サクサク)打てる、という点に天鳳の魅力があることは変わらないと思います。

また一方で、天鳳位を目標にするのは現実的ではないが、ある程度の実力があれば十段は達成できることもわかりました

ちなみに、各安定段位における十段→天鳳位チャレンジの成功率は以下のようになっています。

安定8.5段あれば、(十段になれさえすれば)10回に1回は天鳳位を取れるようです。

成功率に差はあれど、やはり十段は天鳳位ガチャのチケットと考えるのがよさそうですね。

この記事を読んでいただいた天鳳民がどう思うかはわかりませんが、私としては、まだ十段にもなったことはないので、とりあえず十段は目指して頑張りたいと思います。

①十段を目指す(ちゃんと実力があればある程度の試行回数で達成できそうであるため)
②数%の可能性にかけて天鳳位ガチャを目指す
③降段したら...その時考える

って感じでしょうか。

なお、本記事は1>2>3>4型の着順分布の結果のみ示しましたが、1=2=3>4型や2=3>1=4型も試してみました。
後者2つの分布では、1>2>3>4型と比べて、天鳳位達成までに若干時間がかかるようでした(中央値で300~400半荘くらい)。

最後に、ここまで書いておいてなんですが、本記事の執筆にあたっては誰の校正も受けていないので、私のシミュレーションのコードが間違えている可能性もあります。
Rのコードになりますが、再現性のため載せておきます。

for(i in 1:nsimu){
  dani <- 7      # 初期段位
  point <- 1400  # 初期ポイント
  loop <- 0      # 試合数の初期設定
  
  while (dani <= 10 & dani >= 4){   # 4段から10段の間は以下を繰り返す
    if(dani == 10){
      while (point >= 0 & point < 4000){
        tmp <- rmultinom(1, 1, juni)
        tmp.point <- 90*tmp[1] + 45*tmp[2] - 180*tmp[4]
        point <- point + tmp.point
        loop <- loop + 1
        cat(i, loop, dani, "段", point, "\n")
      }
    } else if (dani == 9){
      while (point >= 0 & point < 3600){
        tmp <- rmultinom(1, 1, juni)
        tmp.point <- 90*tmp[1] + 45*tmp[2] - 165*tmp[4]
        point <- point + tmp.point
        loop <- loop + 1
        cat(i, loop, dani, "段", point, "\n")
      }
    } else if (dani == 8){
      while (point >= 0 & point < 3200){
        tmp <- rmultinom(1, 1, juni)
        tmp.point <- 90*tmp[1] + 45*tmp[2] - 150*tmp[4]
        point <- point + tmp.point
        loop <- loop + 1
        cat(i, loop, dani, "段", point, "\n")
      }
    } else if (dani == 7){
      while (point >= 0 & point < 2800){
        tmp <- rmultinom(1, 1, juni)
        tmp.point <- 90*tmp[1] + 45*tmp[2] - 135*tmp[4]
        point <- point + tmp.point
        loop <- loop + 1
        cat(i, loop, dani, "段", point, "\n")
      }
    } else if (dani == 6){
      while (point >= 0 & point < 2400){
        tmp <- rmultinom(1, 1, juni)
        tmp.point <- 90*tmp[1] + 45*tmp[2] - 120*tmp[4]
        point <- point + tmp.point
        loop <- loop + 1
        cat(i, loop, dani, "段", point, "\n")
      }
    } else if (dani == 5){
      while (point >= 0 & point < 2000){
        tmp <- rmultinom(1, 1, juni)
        tmp.point <- 90*tmp[1] + 45*tmp[2] - 105*tmp[4]
        point <- point + tmp.point
        loop <- loop + 1
        cat(i, loop, dani, "段", point, "\n")
      }
    } else if (dani == 4){
      while (point >= 0 & point < 1600){
        tmp <- rmultinom(1, 1, juni)
        tmp.point <- 90*tmp[1] + 45*tmp[2] - 90*tmp[4]
        point <- point + tmp.point
        loop <- loop + 1
        cat(i, loop, dani, "段", point, "\n")
      }
    }
  
    # 各段位における昇段降段シミュレーションを終えて段位変動
    if (point < 0){
      dani <- dani - 1
    } else {
      dani <- dani + 1
    }
  
    # 変動後段位に応じてポイントを原点に設定
    if (dani == 10){
      point <- 2000
    } else if (dani == 9){
      point <- 1800
    } else if (dani == 8){
      point <- 1600
    } else if (dani == 7){
      point <- 1400
    } else if (dani == 6){
      point <- 1200
    } else if (dani == 5){
      point <- 1000
    } else if (dani == 4){
      point <- 800
    } 
  }
  
  loop_all[i] <- loop
  dani_end[i] <- dani
}