Closed shinyaishida closed 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
Mjai::MjaiCommand.execute()
の第一引数のコマンド名は 2 種類。mjai
か mjai-*
。
コマンド名が mjai
のときはサーバーを起動するかユーティリティを使うとき。
mjai-*
は mjai-shanten
か mjai-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
Mjai::ShantenPlayer
は Mjai::Player
を継承しているので、Mjai::Player
を見てみる。
require "mjai/player"
require "mjai/shanten_analysis"
require "mjai/pai"
module Mjai
class ShantenPlayer < Player
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)
Mjai::ShantenPlayer
にある respond_to_action()
メソッドは Mjai::Player
にはない。Mjai::ShantenPlayer
は Mjai::Player
のメソッドをそのまま使っている (オーバーライド・オーバーロードなし)。
mjai_command.rb
内で Mjai::Player
のサブクラスのインスタンスが作られて、次のブロックでサーバーに接続され、対戦が始まる。
game = TCPClientGame.new({
:player => player,
:url => url,
:name => opts["name"] || player_type,
})
game.play()
Mjai::Player
と Mjai::ShantenPlayer
のメソッドは TCPClientGame
の中で呼ばれていることになる。
TCPClientGame
のここでアクションタイプに応じて打ち手を決めている。do_action()
の先に打ち手を決めるロジックが存在する。
action = Action.from_json(action_json, self)
responses = do_action(action)
# 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
牌譜の状態管理は update_state()
に任せればよい。
player は respond_to_action()
メソッドをもっていないといけない。
@on_action
もしくは @on_responses
を使って牌譜を表示させるといいかも。
https://github.com/shinyaishida/mjai/blob/master/bin/mjai-shanten
これらの構造を把握する。特に、牌譜の状態管理と打つ手を決めるロジックの関係を理解する。