hanabiapp.game.agent.(regacy)internal_state_agent

  1from .agent import Agent
  2from ..action import Action
  3
  4class InternalStateAgent(Agent):
  5  def __init__(self, name, player_number):
  6    super().__init__(name, player_number)
  7    self.need_hle_convert= False
  8
  9  def get_possible(self,knowledge):
 10    """
 11    各カードに対する知識に基づいて、プレイヤーが持っている可能性があるカードのリストを返す。
 12    """
 13    possible = []
 14    for color in self.game.game_const.ALL_COLORS:
 15      for number, count in enumerate(knowledge[color]):
 16        if count > 0:
 17          possible.append((color, number + 1))  # 色と数字のペアを追加
 18    #check_type_and_dtype(possible)
 19    return possible
 20  
 21  def playable(self,possible, board):
 22    #self.print_log("playable関数")
 23    for (color,number) in possible:
 24      #self.print_log(f"color:{color},number:{number}")
 25      #self.print_log(f"{color}色の最大値:{board[color]}")
 26      if board[color] + 1 != number:
 27        #self.print_log(f"Playable:{color,number} is False")
 28        return False # possibleのリスト内で、少なくとも1つでもplayableでないタプルが含まれていると、そのリスト全体に対してFalseが返されます
 29    #self.print_log(f"Playable:{possible} is True")
 30    return True 
 31  
 32  def discardable(self,possible, board):
 33    for (color,number) in possible:
 34      if board[color] < number: 
 35        return False
 36    #self.print_log("Discardable: ",possible)
 37    return True # ボード上のその色のカードよりも小さい数字なら破棄しても問題ない
 38
 39  def act(self, game_ins):
 40    """
 41    プレイヤーの次のアクションを決定するメソッド
 42    valid_actions: 現在のターンでプレイヤーが取ることのできる有効なアクションのリスト
 43    """
 44    #===============================================================================================
 45    # もしプレイヤがプレイ可能カードを持っていれば,それをプレイする
 46    # 破棄可能カードを持っていたら,それを破棄する
 47    possible = []
 48
 49    # 己のknowledgeから,持ちうるカードの(色,数字)をリストアップ(枚数情報除く)
 50    for k in game_ins.knowledge[self.player_number]:
 51      possible.append(self.get_possible(k))
 52      
 53    # for idx, p in enumerate(possible):
 54    #     self.print_log("Possible for Card {}: {}".format(idx + 1, p))
 55
 56    playable_cards= []
 57    discardable_cards = []
 58    for i, card in enumerate(possible):
 59      # ボード上のその色のカードが次に必要な数字かどうかを確認
 60      if self.playable(card,game_ins.board):
 61        # possibleの中から,プレイ可能なカードが見つかったら、それを格納
 62        playable_cards.append(i)
 63        self.print_log("Internal-state:プレイ可能カードを持っていれるので,それをプレイします.")
 64        return Action(game_ins.game_const.PLAY, card_position=i)
 65      if self.discardable(card,game_ins.board):
 66        discardable_cards.append(i)
 67
 68    #self.print_log(f"playable_cards:{playable_cards},discardable_cards:{discardable_cards}")
 69      
 70    if discardable_cards:
 71      self.print_log("Internal-state:破棄可能カードを持っていれるので,それを捨てます.")
 72      return Action(game_ins.game_const.DISCARD, card_position=game_ins.random.choice(discardable_cards))
 73    #===============================================================================================
 74    # もし相手がプレイ可能なカードを持っていれば,プレイヤはそのカードの色か数字に関するヒントを与える
 75    opponent_playable_info = [] # (player_number,card_position)のタプルのリスト
 76    ai_player_number = self.player_number
 77
 78    for i,(player_number,hand) in enumerate(game_ins.hands.items()):
 79      if player_number != ai_player_number:
 80        opponent_hand = hand
 81        for card_position,(color,number) in enumerate(opponent_hand):
 82          if game_ins.board[color] + 1 == number:
 83            opponent_playable_info.append((player_number,card_position))
 84    
 85    if opponent_playable_info and game_ins.hints > 0:
 86      player_number,card_position = opponent_playable_info[0] # 一個目のプレイ可能なカードを選択
 87      self.print_log("Internal-state:相手がプレイ可能なカードを持っているので,半々の確率で色ヒントか数字ヒントを出します.")
 88      # 半々の確率で色ヒントか数字ヒントを選択し,アクション確定
 89      if game_ins.random.random() < 0.5:
 90        return Action(game_ins.game_const.HINT_COLOR, pnr=player_number, color=game_ins.hands[player_number][card_position][0])
 91      return Action(game_ins.game_const.HINT_NUMBER, pnr=player_number, number=game_ins.hands[player_number][card_position][1])
 92    #===============================================================================================
 93    # もし相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手が情報を持っていないカードのうち1枚をランダムに選択してヒントを与える
 94    ai_player_number = self.player_number
 95    
 96    for player in game_ins.players:
 97      if player.player_number == ai_player_number:
 98        continue # player_number == ai_player_numberの場合は自分自身であるため、ヒントを与える相手から除外される
 99
100      # 相手の手札からランダムに1枚を選び、そのカードに対してヒントを与える準備
101      cards = list(range(len(opponent_hand)))
102      game_ins.random.shuffle(cards)
103      random_pick_card_position = cards[0] # ランダムにシャッフルして1枚目を選ぶ   
104      #self.print_log(f"random_pick_card:{random_pick_card}")
105
106      self.print_log(f"opponent_hand:{opponent_hand}")
107      self.print_log(f"cards:{cards}")
108      self.print_log(f"random_pick_card_position:{random_pick_card_position}")
109      
110      (color,number) = game_ins.hands[player.player_number][random_pick_card_position]
111      hint_type = [game_ins.game_const.HINT_COLOR, game_ins.game_const.HINT_NUMBER]
112      if game_ins.hints > 0:
113        if game_ins.random.choice(hint_type) == game_ins.game_const.HINT_COLOR:
114          self.print_log("Internal-state:相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手カードのうち1枚をランダムに選択,色か数字,どちらかのヒントを与えます.")
115          return Action(game_ins.game_const.HINT_COLOR, pnr=player.player_number, color=color)
116        else:
117          self.print_log("Internal-state:相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手カードのうち1枚をランダムに選択,色か数字,どちらかのヒントを与えます.")
118          return Action(game_ins.game_const.HINT_NUMBER, pnr=player.player_number, number=number)
119      
120    #===============================================================================================
121    # もし相手がプレイ可能なカードを持っておらず,ヒントトークンがない場合,自分のカードをランダムに選んで捨てる
122    
123    self.print_log("自分のカードをランダムに選んで捨てます.")
124    #print(f"random_pick_card_position:{random_pick_card_position}")
125    # c = [0,1,2,3,4]
126    # print("randomchoice:",game_ins.random.choice(c))
127    # l = [Action(game_ins.game_const.DISCARD, card_position=i) for i in range(len(game_ins.hands[player_number]))]
128    # for action in l:
129    #     print(action)
130    # return game_ins.random.choice([Action(game_ins.game_const.DISCARD, card_position=i) for i in range(len(game_ins.hands[player_number]))])
131    return Action(game_ins.game_const.DISCARD, card_position=game_ins.random.choice(range(game_ins.hand_size)))
class InternalStateAgent(hanabiapp.game.agent.agent.Agent):
  5class InternalStateAgent(Agent):
  6  def __init__(self, name, player_number):
  7    super().__init__(name, player_number)
  8    self.need_hle_convert= False
  9
 10  def get_possible(self,knowledge):
 11    """
 12    各カードに対する知識に基づいて、プレイヤーが持っている可能性があるカードのリストを返す。
 13    """
 14    possible = []
 15    for color in self.game.game_const.ALL_COLORS:
 16      for number, count in enumerate(knowledge[color]):
 17        if count > 0:
 18          possible.append((color, number + 1))  # 色と数字のペアを追加
 19    #check_type_and_dtype(possible)
 20    return possible
 21  
 22  def playable(self,possible, board):
 23    #self.print_log("playable関数")
 24    for (color,number) in possible:
 25      #self.print_log(f"color:{color},number:{number}")
 26      #self.print_log(f"{color}色の最大値:{board[color]}")
 27      if board[color] + 1 != number:
 28        #self.print_log(f"Playable:{color,number} is False")
 29        return False # possibleのリスト内で、少なくとも1つでもplayableでないタプルが含まれていると、そのリスト全体に対してFalseが返されます
 30    #self.print_log(f"Playable:{possible} is True")
 31    return True 
 32  
 33  def discardable(self,possible, board):
 34    for (color,number) in possible:
 35      if board[color] < number: 
 36        return False
 37    #self.print_log("Discardable: ",possible)
 38    return True # ボード上のその色のカードよりも小さい数字なら破棄しても問題ない
 39
 40  def act(self, game_ins):
 41    """
 42    プレイヤーの次のアクションを決定するメソッド
 43    valid_actions: 現在のターンでプレイヤーが取ることのできる有効なアクションのリスト
 44    """
 45    #===============================================================================================
 46    # もしプレイヤがプレイ可能カードを持っていれば,それをプレイする
 47    # 破棄可能カードを持っていたら,それを破棄する
 48    possible = []
 49
 50    # 己のknowledgeから,持ちうるカードの(色,数字)をリストアップ(枚数情報除く)
 51    for k in game_ins.knowledge[self.player_number]:
 52      possible.append(self.get_possible(k))
 53      
 54    # for idx, p in enumerate(possible):
 55    #     self.print_log("Possible for Card {}: {}".format(idx + 1, p))
 56
 57    playable_cards= []
 58    discardable_cards = []
 59    for i, card in enumerate(possible):
 60      # ボード上のその色のカードが次に必要な数字かどうかを確認
 61      if self.playable(card,game_ins.board):
 62        # possibleの中から,プレイ可能なカードが見つかったら、それを格納
 63        playable_cards.append(i)
 64        self.print_log("Internal-state:プレイ可能カードを持っていれるので,それをプレイします.")
 65        return Action(game_ins.game_const.PLAY, card_position=i)
 66      if self.discardable(card,game_ins.board):
 67        discardable_cards.append(i)
 68
 69    #self.print_log(f"playable_cards:{playable_cards},discardable_cards:{discardable_cards}")
 70      
 71    if discardable_cards:
 72      self.print_log("Internal-state:破棄可能カードを持っていれるので,それを捨てます.")
 73      return Action(game_ins.game_const.DISCARD, card_position=game_ins.random.choice(discardable_cards))
 74    #===============================================================================================
 75    # もし相手がプレイ可能なカードを持っていれば,プレイヤはそのカードの色か数字に関するヒントを与える
 76    opponent_playable_info = [] # (player_number,card_position)のタプルのリスト
 77    ai_player_number = self.player_number
 78
 79    for i,(player_number,hand) in enumerate(game_ins.hands.items()):
 80      if player_number != ai_player_number:
 81        opponent_hand = hand
 82        for card_position,(color,number) in enumerate(opponent_hand):
 83          if game_ins.board[color] + 1 == number:
 84            opponent_playable_info.append((player_number,card_position))
 85    
 86    if opponent_playable_info and game_ins.hints > 0:
 87      player_number,card_position = opponent_playable_info[0] # 一個目のプレイ可能なカードを選択
 88      self.print_log("Internal-state:相手がプレイ可能なカードを持っているので,半々の確率で色ヒントか数字ヒントを出します.")
 89      # 半々の確率で色ヒントか数字ヒントを選択し,アクション確定
 90      if game_ins.random.random() < 0.5:
 91        return Action(game_ins.game_const.HINT_COLOR, pnr=player_number, color=game_ins.hands[player_number][card_position][0])
 92      return Action(game_ins.game_const.HINT_NUMBER, pnr=player_number, number=game_ins.hands[player_number][card_position][1])
 93    #===============================================================================================
 94    # もし相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手が情報を持っていないカードのうち1枚をランダムに選択してヒントを与える
 95    ai_player_number = self.player_number
 96    
 97    for player in game_ins.players:
 98      if player.player_number == ai_player_number:
 99        continue # player_number == ai_player_numberの場合は自分自身であるため、ヒントを与える相手から除外される
100
101      # 相手の手札からランダムに1枚を選び、そのカードに対してヒントを与える準備
102      cards = list(range(len(opponent_hand)))
103      game_ins.random.shuffle(cards)
104      random_pick_card_position = cards[0] # ランダムにシャッフルして1枚目を選ぶ   
105      #self.print_log(f"random_pick_card:{random_pick_card}")
106
107      self.print_log(f"opponent_hand:{opponent_hand}")
108      self.print_log(f"cards:{cards}")
109      self.print_log(f"random_pick_card_position:{random_pick_card_position}")
110      
111      (color,number) = game_ins.hands[player.player_number][random_pick_card_position]
112      hint_type = [game_ins.game_const.HINT_COLOR, game_ins.game_const.HINT_NUMBER]
113      if game_ins.hints > 0:
114        if game_ins.random.choice(hint_type) == game_ins.game_const.HINT_COLOR:
115          self.print_log("Internal-state:相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手カードのうち1枚をランダムに選択,色か数字,どちらかのヒントを与えます.")
116          return Action(game_ins.game_const.HINT_COLOR, pnr=player.player_number, color=color)
117        else:
118          self.print_log("Internal-state:相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手カードのうち1枚をランダムに選択,色か数字,どちらかのヒントを与えます.")
119          return Action(game_ins.game_const.HINT_NUMBER, pnr=player.player_number, number=number)
120      
121    #===============================================================================================
122    # もし相手がプレイ可能なカードを持っておらず,ヒントトークンがない場合,自分のカードをランダムに選んで捨てる
123    
124    self.print_log("自分のカードをランダムに選んで捨てます.")
125    #print(f"random_pick_card_position:{random_pick_card_position}")
126    # c = [0,1,2,3,4]
127    # print("randomchoice:",game_ins.random.choice(c))
128    # l = [Action(game_ins.game_const.DISCARD, card_position=i) for i in range(len(game_ins.hands[player_number]))]
129    # for action in l:
130    #     print(action)
131    # return game_ins.random.choice([Action(game_ins.game_const.DISCARD, card_position=i) for i in range(len(game_ins.hands[player_number]))])
132    return Action(game_ins.game_const.DISCARD, card_position=game_ins.random.choice(range(game_ins.hand_size)))

エージェントを表現する抽象クラス.

ゲームのプレイヤーとして動作するエージェントの基底クラスであり, すべてのエージェントが共通して持つべきインターフェースを定義する.

Attributes:
  • game_const (GameConst): ゲームの定数
  • name (str): エージェントの名前
  • player_number (int): エージェントの番号
  • need_hle_convert (bool): HLE形式の変換が必要かどうか
  • game (Game): ゲームのインスタンス(後で設定される)
  • is_cui (bool): CUIモードかどうか
InternalStateAgent(name, player_number)
6  def __init__(self, name, player_number):
7    super().__init__(name, player_number)
8    self.need_hle_convert= False

エージェントの初期化.

Arguments:
  • name (str): エージェントの名前
  • player_number (int): エージェントの番号
  • need_hle_convert (bool, optional): HLE形式の変換が必要かどうか(デフォルトはTrue)
need_hle_convert
def get_possible(self, knowledge):
10  def get_possible(self,knowledge):
11    """
12    各カードに対する知識に基づいて、プレイヤーが持っている可能性があるカードのリストを返す。
13    """
14    possible = []
15    for color in self.game.game_const.ALL_COLORS:
16      for number, count in enumerate(knowledge[color]):
17        if count > 0:
18          possible.append((color, number + 1))  # 色と数字のペアを追加
19    #check_type_and_dtype(possible)
20    return possible

各カードに対する知識に基づいて、プレイヤーが持っている可能性があるカードのリストを返す。

def playable(self, possible, board):
22  def playable(self,possible, board):
23    #self.print_log("playable関数")
24    for (color,number) in possible:
25      #self.print_log(f"color:{color},number:{number}")
26      #self.print_log(f"{color}色の最大値:{board[color]}")
27      if board[color] + 1 != number:
28        #self.print_log(f"Playable:{color,number} is False")
29        return False # possibleのリスト内で、少なくとも1つでもplayableでないタプルが含まれていると、そのリスト全体に対してFalseが返されます
30    #self.print_log(f"Playable:{possible} is True")
31    return True 
def discardable(self, possible, board):
33  def discardable(self,possible, board):
34    for (color,number) in possible:
35      if board[color] < number: 
36        return False
37    #self.print_log("Discardable: ",possible)
38    return True # ボード上のその色のカードよりも小さい数字なら破棄しても問題ない
def act(self, game_ins):
 40  def act(self, game_ins):
 41    """
 42    プレイヤーの次のアクションを決定するメソッド
 43    valid_actions: 現在のターンでプレイヤーが取ることのできる有効なアクションのリスト
 44    """
 45    #===============================================================================================
 46    # もしプレイヤがプレイ可能カードを持っていれば,それをプレイする
 47    # 破棄可能カードを持っていたら,それを破棄する
 48    possible = []
 49
 50    # 己のknowledgeから,持ちうるカードの(色,数字)をリストアップ(枚数情報除く)
 51    for k in game_ins.knowledge[self.player_number]:
 52      possible.append(self.get_possible(k))
 53      
 54    # for idx, p in enumerate(possible):
 55    #     self.print_log("Possible for Card {}: {}".format(idx + 1, p))
 56
 57    playable_cards= []
 58    discardable_cards = []
 59    for i, card in enumerate(possible):
 60      # ボード上のその色のカードが次に必要な数字かどうかを確認
 61      if self.playable(card,game_ins.board):
 62        # possibleの中から,プレイ可能なカードが見つかったら、それを格納
 63        playable_cards.append(i)
 64        self.print_log("Internal-state:プレイ可能カードを持っていれるので,それをプレイします.")
 65        return Action(game_ins.game_const.PLAY, card_position=i)
 66      if self.discardable(card,game_ins.board):
 67        discardable_cards.append(i)
 68
 69    #self.print_log(f"playable_cards:{playable_cards},discardable_cards:{discardable_cards}")
 70      
 71    if discardable_cards:
 72      self.print_log("Internal-state:破棄可能カードを持っていれるので,それを捨てます.")
 73      return Action(game_ins.game_const.DISCARD, card_position=game_ins.random.choice(discardable_cards))
 74    #===============================================================================================
 75    # もし相手がプレイ可能なカードを持っていれば,プレイヤはそのカードの色か数字に関するヒントを与える
 76    opponent_playable_info = [] # (player_number,card_position)のタプルのリスト
 77    ai_player_number = self.player_number
 78
 79    for i,(player_number,hand) in enumerate(game_ins.hands.items()):
 80      if player_number != ai_player_number:
 81        opponent_hand = hand
 82        for card_position,(color,number) in enumerate(opponent_hand):
 83          if game_ins.board[color] + 1 == number:
 84            opponent_playable_info.append((player_number,card_position))
 85    
 86    if opponent_playable_info and game_ins.hints > 0:
 87      player_number,card_position = opponent_playable_info[0] # 一個目のプレイ可能なカードを選択
 88      self.print_log("Internal-state:相手がプレイ可能なカードを持っているので,半々の確率で色ヒントか数字ヒントを出します.")
 89      # 半々の確率で色ヒントか数字ヒントを選択し,アクション確定
 90      if game_ins.random.random() < 0.5:
 91        return Action(game_ins.game_const.HINT_COLOR, pnr=player_number, color=game_ins.hands[player_number][card_position][0])
 92      return Action(game_ins.game_const.HINT_NUMBER, pnr=player_number, number=game_ins.hands[player_number][card_position][1])
 93    #===============================================================================================
 94    # もし相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手が情報を持っていないカードのうち1枚をランダムに選択してヒントを与える
 95    ai_player_number = self.player_number
 96    
 97    for player in game_ins.players:
 98      if player.player_number == ai_player_number:
 99        continue # player_number == ai_player_numberの場合は自分自身であるため、ヒントを与える相手から除外される
100
101      # 相手の手札からランダムに1枚を選び、そのカードに対してヒントを与える準備
102      cards = list(range(len(opponent_hand)))
103      game_ins.random.shuffle(cards)
104      random_pick_card_position = cards[0] # ランダムにシャッフルして1枚目を選ぶ   
105      #self.print_log(f"random_pick_card:{random_pick_card}")
106
107      self.print_log(f"opponent_hand:{opponent_hand}")
108      self.print_log(f"cards:{cards}")
109      self.print_log(f"random_pick_card_position:{random_pick_card_position}")
110      
111      (color,number) = game_ins.hands[player.player_number][random_pick_card_position]
112      hint_type = [game_ins.game_const.HINT_COLOR, game_ins.game_const.HINT_NUMBER]
113      if game_ins.hints > 0:
114        if game_ins.random.choice(hint_type) == game_ins.game_const.HINT_COLOR:
115          self.print_log("Internal-state:相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手カードのうち1枚をランダムに選択,色か数字,どちらかのヒントを与えます.")
116          return Action(game_ins.game_const.HINT_COLOR, pnr=player.player_number, color=color)
117        else:
118          self.print_log("Internal-state:相手がプレイ可能なカードを持っておらず,ヒントトークンがある場合は,相手カードのうち1枚をランダムに選択,色か数字,どちらかのヒントを与えます.")
119          return Action(game_ins.game_const.HINT_NUMBER, pnr=player.player_number, number=number)
120      
121    #===============================================================================================
122    # もし相手がプレイ可能なカードを持っておらず,ヒントトークンがない場合,自分のカードをランダムに選んで捨てる
123    
124    self.print_log("自分のカードをランダムに選んで捨てます.")
125    #print(f"random_pick_card_position:{random_pick_card_position}")
126    # c = [0,1,2,3,4]
127    # print("randomchoice:",game_ins.random.choice(c))
128    # l = [Action(game_ins.game_const.DISCARD, card_position=i) for i in range(len(game_ins.hands[player_number]))]
129    # for action in l:
130    #     print(action)
131    # return game_ins.random.choice([Action(game_ins.game_const.DISCARD, card_position=i) for i in range(len(game_ins.hands[player_number]))])
132    return Action(game_ins.game_const.DISCARD, card_position=game_ins.random.choice(range(game_ins.hand_size)))

プレイヤーの次のアクションを決定するメソッド valid_actions: 現在のターンでプレイヤーが取ることのできる有効なアクションのリスト