Closed nissymori closed 3 years ago
TransServerを立てるときにmjaiと通信するためのサーバーを立てて、mjaiのクライアントと同じ数のTCPPlayer(socket, name)
を立てる必要がある。(do_action(action)
の中で全てのTCPPlayer
がrespond_to_action(action)
を実行している)
方針
def do_action(action)
#mjaiと同じ実装
if action.is_a?(Hash)
action = Action.new(action)
end
#update_state(action)これはmjxがやる
#@on_action.call(action) if @on_action
responses = (0...4).map() do |i|
@players[i].respond_to_action(action_in_view(action, i, true)) # aciton_in_view()実装する必要あり
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
respond_to_action(action)とaction_in_view(action)の二つ実行できれば良い
respond_to_action
def respond_to_action(action)
begin
puts("server -> player %d\t%s" % [self.id, action.to_json()])
@socket.puts(action.to_json())
line = nil
Timeout.timeout(TIMEOUT_SEC) do
line = @socket.gets()
end
if line
puts("server <- player %d\t%s" % [self.id, line])
return Action.from_json(line.chomp(), self.game)
else
puts("server : Player %d has disconnected." % self.id)
return Action.new({:type => :none})
end
rescue Timeout::Error
return create_action({
:type => :error,
:message => "Timeout. No response in %d sec." % TIMEOUT_SEC,
})
rescue JSON::ParserError => ex
return create_action({
:type => :error,
:message => "JSON syntax error: %s" % ex.message,
})
rescue ValidationError => ex
return create_action({
:type => :error,
:message => ex.message,
})
end
end
引数のactionの情報があれば実行できそう。
action_in_view(action)
def action_in_view(action, player_id, for_response)
player = @players[player_id]
with_response_hint = for_response && expect_response_from?(player)
case action.type
when :start_game
return action.merge({:id => player_id})
when :start_kyoku
tehais_list = action.tehais.dup()
for i in 0...4
if i != player_id
tehais_list[i] = [Pai::UNKNOWN] * tehais_list[i].size
end
end
return action.merge({:tehais => tehais_list})
when :tsumo
if action.actor == player
return action.merge({
:possible_actions =>
with_response_hint ? player.possible_actions : nil,
})
else
return action.merge({:pai => Pai::UNKNOWN})
end
when :dahai, :kakan
if action.actor != player
return action.merge({
:possible_actions =>
with_response_hint ? player.possible_actions : nil,
})
else
return action
end
when :chi, :pon
if action.actor == player
return action.merge({
:cannot_dahai =>
with_response_hint ? player.kuikae_dahais : nil,
})
else
return action
end
when :reach
if action.actor == player
return action.merge({
:cannot_dahai =>
with_response_hint ? (player.tehais.uniq() - player.possible_dahais) : nil,
})
else
return action
end
else
return action
end
end
TCPPlayerクラスが覚えている情報を多分に使っている。
TCPPlayerクラスに逐次的に情報を覚えさせるにはdo_aciton(action)
の中のupdate_states
を実行する必要があるが、そうすると依存するmjaiのクラスが増えてしまって望ましくない。
ここをobservationをもとに実装するのが良いか??→そうする。 testを正確に書く
24