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)))
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)
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
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: 現在のターンでプレイヤーが取ることのできる有効なアクションのリスト