shinyaishida / mjai

Game server for Japanese Mahjong AI.
0 stars 0 forks source link

mjai-shanten の構成を調べる #12

Closed shinyaishida closed 3 years ago

shinyaishida commented 3 years ago

https://github.com/shinyaishida/mjai/blob/master/bin/mjai-shanten

これらの構造を把握する。特に、牌譜の状態管理と打つ手を決めるロジックの関係を理解する。

shinyaishida commented 3 years ago
require "mjai/mjai_command"

Mjai::MjaiCommand.execute("mjai-shanten", ARGV)

とあるので、mjai/mjai_command を見てみる。

https://github.com/shinyaishida/mjai/blob/master/lib/mjai/mjai_command.rb

shinyaishida commented 3 years ago

Mjai::MjaiCommand.execute() の第一引数のコマンド名は 2 種類。mjaimjai-*

shinyaishida commented 3 years ago

コマンド名が mjai のときはサーバーを起動するかユーティリティを使うとき。

shinyaishida commented 3 years ago

mjai-*mjai-shantenmjai-tsumogiri のどちらか。

require "mjai/tsumogiri_player"
require "mjai/shanten_player"

...

              case player_type
                when "tsumogiri"
                  player = TsumogiriPlayer.new()
                when "shanten"
                  player = Mjai::ShantenPlayer.new({:use_furo => opts["t"] == "f"})
                else
                  raise("should not happen")
              end
shinyaishida commented 3 years ago

Mjai::ShantenPlayerMjai::Player を継承しているので、Mjai::Player を見てみる。

require "mjai/player"
require "mjai/shanten_analysis"
require "mjai/pai"

module Mjai

    class ShantenPlayer < Player
shinyaishida commented 3 years ago

https://techacademy.jp/magazine/41659

shinyaishida commented 3 years ago

Mjai::Player がもつステート

        attr_reader(:id)
        attr_reader(:tehais)  # 手牌
        attr_reader(:furos)  # 副露
        attr_reader(:ho)  # 河 (鳴かれた牌を含まない)
        attr_reader(:sutehais)  # 捨牌 (鳴かれた牌を含む)
        attr_reader(:extra_anpais)  # sutehais以外のこのプレーヤに対する安牌
        attr_reader(:reach_state)
        attr_reader(:reach_ho_index)
        attr_reader(:pao_for_id)
        attr_reader(:attributes)
        attr_accessor(:name)
        attr_accessor(:game)
        attr_accessor(:score)
shinyaishida commented 3 years ago

Mjai::ShantenPlayer にある respond_to_action() メソッドは Mjai::Player にはない。Mjai::ShantenPlayerMjai::Player のメソッドをそのまま使っている (オーバーライド・オーバーロードなし)。

shinyaishida commented 3 years ago

mjai_command.rb 内で Mjai::Player のサブクラスのインスタンスが作られて、次のブロックでサーバーに接続され、対戦が始まる。

game = TCPClientGame.new({
                  :player => player,
                  :url => url,
                  :name => opts["name"] || player_type,
              })
game.play()
shinyaishida commented 3 years ago

Mjai::PlayerMjai::ShantenPlayer のメソッドは TCPClientGame の中で呼ばれていることになる。

shinyaishida commented 3 years ago

TCPClientGame のここでアクションタイプに応じて打ち手を決めている。do_action() の先に打ち手を決めるロジックが存在する。

                  action = Action.from_json(action_json, self)
                  responses = do_action(action)
shinyaishida commented 3 years ago
        # Executes the action and returns responses for it from players.
        def do_action(action)

          if action.is_a?(Hash)
            action = Action.new(action)
          end

          update_state(action)

          @on_action.call(action) if @on_action

          responses = (0...4).map() do |i|
            @players[i].respond_to_action(action_in_view(action, i, true))
          end

          action_with_logs = action.merge({:logs => responses.map(){ |r| r && r.log }})
          responses = responses.map(){ |r| (!r || r.type == :none) ? nil : r.merge({:log => nil}) }
          @on_responses.call(action_with_logs, responses) if @on_responses

          @previous_action = action
          validate_responses(responses, action)
          return responses

        end
shinyaishida commented 3 years ago

牌譜の状態管理は update_state() に任せればよい。

shinyaishida commented 3 years ago

player は respond_to_action() メソッドをもっていないといけない。

shinyaishida commented 3 years ago

@on_action もしくは @on_responses を使って牌譜を表示させるといいかも。