mjx-project / mjx_mjai_translater

Translation server between mjx and mjai protocols
MIT License
2 stars 0 forks source link

全てツモぎりのプレイヤーで変換サーバーを使ってゲームを行う2 #30

Closed nissymori closed 3 years ago

nissymori commented 3 years ago

24

nissymori commented 3 years ago

TransServerを立てるときにmjaiと通信するためのサーバーを立てて、mjaiのクライアントと同じ数のTCPPlayer(socket, name)を立てる必要がある。(do_action(action)の中で全てのTCPPlayerrespond_to_action(action)を実行している)

nissymori commented 3 years ago

方針

nissymori commented 3 years ago
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)の二つ実行できれば良い

nissymori commented 3 years ago

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の情報があれば実行できそう。

nissymori commented 3 years ago

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を正確に書く