*All archives* |  *Admin*

<<01  2017/02  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28  03>>
floodgate for mahjong へ参戦その6・一人麻雀再帰計算関数の作り直し
ただの棒テン即リー全ツッパAIから一人麻雀計算機のときに作った再帰計算による打牌選択をさせるように試みてみます。

今回は受け入れ枚数の多寡ではなく、手役や最終的な和了率まで考慮した局収支が最も多い打牌を選択させるようにします。
計算時間の問題で、シャンテン数ごとに
・聴牌…ダマ(手替わり1回までと途中で立直に切り替えも考慮)と即リーチと聴牌取らず(再聴牌する有効牌が最も多い1打のみ)
・1シャンテン…手替わり1回で再帰計算(シャンテン戻し考慮せず)
・2シャンテン…手替わり0回で再帰計算(シャンテン戻し考慮せず)
・3シャンテン以上→基本的には棒テン即リー全ツッパAI。ただし、国士チートイがらみは面子手シャンテン数との兼ね合いで別途場合分け。

という規則で計算させます。

プログラムの大枠は一人麻雀計算機のときに作っていましたが、後々いろいろと融通が利くようにグローバル変数をなるべく使わない方式にするために引数とか関数の使い方をいろいろと作り替えました。

とりあえずそれっぽいのができたのでテストしてみます。
牌姿は1m3m4m5m6m3p4p5p8p8p3s4s5s6s。
親の1巡目。(ただし、ダブリーは考慮しない。)
を、入力値として、最適打が出力値として出るようにします。

聴牌なので、設計通りなら3sか6s切ってダマ聴牌取り、即リーチ、聴牌外し(今回は一番広い1m切り)の中で最も局収支がいいものが出力値として出てきます。
今回はあからさまに聴牌外しが有利になるような牌姿(打1mでタンピン三色狙い)にしておきました。

デバッグ開始。
170215-01.png
一応、目論見通り、結果は「1」(牌番号1は1m)になっていますが、けっこう計算時間が遅いです。
およそ10秒超。
まぁ複数打牌候補でそれぞれダマとリーチと聴牌外しをやってるのでこのくらいは想定はしていたけど、まだツモしか見てない段階でこれはけっこうつらい。

各パーツごとにかかった時間も一緒に測定してみました。
分け方は↓のときとだいたい同じ。
一人麻雀計算機その9・テストと改善その2
3番(局収支とかの記憶検索)と6番(打牌候補選定)で時間を食っています。

ここをなんとかするか…といろいろと省力化のために知恵を絞ってみました。

・記憶検索について、検索のキーにしてるのがString型(「1m3m4m5m6m3p4p5p8p8p3s4s5s6s」とか)にしてるのを整数のLong型に変換してみた。
37種の牌から14枚を取る組み合わせ、ということでパッと思い浮かんだのが重複組み合わせ(nHr=(n+r-1)Cr)です。
14個の○と37個の仕分け線/の50個の図形を並べた組み合わせの数です。
○//○/○/○/○///…
1m1枚、2m0枚、3m1枚、4m1枚、5m1枚、6m1枚、7m0枚…
50C14で10の11乗くらいなのでLong型(8バイト)あれば手牌1式(String型orInteger型配列)と整数1個が1対1対応できる、と思います。(実際は同じ牌を5枚以上使えないので手牌として適さない○/列もありますが、数え上げやすさ重視で。)
この○と/の列を0と1に置き換えてビット演算子によってLong型の整数にすればString型で検索するよりは速度が上がるかなーと。
この数え方だと2^50=10^15乗まで膨れるが、なんとかぎりぎりLong型で収まる。

・それによって文字列を使う必要がなくなったので、手牌のInteger配列を文字列に直す工程を削除(デバッグでのチェックが見づらくなったが、速度には代えられない。)

・打牌候補選定のためのシャンテンチェックも一度計算した手牌は再計算しないで記憶情報から引っ張ってくる方式に変更。

そうしていろいろ改善した結果がこちら。
170215-02.png
4秒まで縮めることができました。
これなら今のところは使用に耐えるか。

もうしばらくいろんな牌姿を入力してテストをやっていきます。
スポンサーサイト
プロフィール

nisi5028

Author:nisi5028
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
フリーエリア
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード