hanabiapp.game.hint_knowledge_manager
ヒントの知識を管理するクラス
- 以下のコードを参考にしています: GitHub - yawgmoth/pyhanabi: A research-focused, Python implementation of Hanabi, including a browser-based user interface https://github.com/yawgmoth/pyhanabi
ヒント情報を記録するknowledge記録・管理します.
knowledge:は,各プレイヤーの知識を保持する4次元リストで,ヒント情報は保存されます.
knowledge[player_number][card_position][color][number-1] でアクセス可能です.
- 各プレイヤの各手札(デフォルトは5枚)に対し,各色(デフォルトは5色),ありうるカードの可能性を示します.
例1 2人プレイ時のknowledgeの初期状態は以下の通りです: [ (プレイヤー 0 の知識) (手札 0:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 1:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 2:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 3:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 4:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] ], [ (プレイヤー 1 の知識) (手札 0:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 1:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 2:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 3:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] (手札 4:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] ]
初期状態のプレイヤー 0の手札0に着目します.
- なにも情報がないので,各色に対して3,2,2,2,1枚ずつある可能性が示されています.
- 色はlogic.pyのGameConst.COLOR_NAMESで定義された(デフォルトは["B", "G", "R", "W", "Y"])の順になっています.
例2 プレイヤー1からプレイヤー0に「プレイヤー0の手札0は青色です」とヒントが与えられたときの知識更新は以下の通りです(少し表記を簡単にしています): プレイヤー 0 の知識: 手札 0: [[3, 2, 2, 2, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] 手札 1: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 2: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 3: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 4: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] プレイヤー 1 の知識: 手札 0: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 1: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 2: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 3: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 4: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]]
- プレイヤー 0の手札0-4に着目します.
- 手札0は青色であり,手札1-4は青色ではないことがわかりました.
- ですので,手札0は青色以外の色は存在しえない[0, 0, 0, 0, 0]とすることで,青であることを確定させています.
- 一方,手札1-4は青色である可能性がなくなったので,青色の可能性を[0, 0, 0, 0, 0]としています.
- プレイヤー 0の手札0-4に着目します.
例3 プレイヤー1からプレイヤー0に「プレイヤー0の手札0の数字は3です」とヒントが与えられたときの知識更新は以下の通りです: プレイヤー 0 の知識: 手札 0: [[0, 0, 2, 0, 0], [0, 0, 2, 0, 0], [0, 0, 2, 0, 0], [0, 0, 2, 0, 0], [0, 0, 2, 0, 0]] 手札 1: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] 手札 2: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] 手札 3: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] 手札 4: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] プレイヤー 1 の知識: 手札 0: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 1: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 2: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 3: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 手札 4: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]]
- プレイヤー 0の手札0-4に着目します.
- 手札0はの数字は3であり,手札1-4の数字は3ではないことがわかりました.
- ですので,手札0は3以外の色は存在しえない[0, 0, 2, 0, 0]とすることで,3であることを確定させています.
- 一方,手札1-4は3である可能性がなくなったので,3の可能性を排除した[3, 2, 0, 2, 1]としています.
- プレイヤー 0の手札0-4に着目します.
注意点
- 相手の手札とか,捨て札とか,ボードの情報は加味した絞り込みはしてないので注意してください.
- 例えば,場にすでにR1が出ている⇒観測できないところにあるR1は1枚減ったな⇒knowledge更新,とかはしてないです
- そういう絞り込みしたければ別配列ですること.少なくとも上記で参考にしたもの&AIはその仕様なので合わせています.
- knowledgeはAIに渡され活用されるもので,直接的にゲームロジックに関係しません.
- 相手の手札とか,捨て札とか,ボードの情報は加味した絞り込みはしてないので注意してください.
1"""ヒントの知識を管理するクラス 2 * 以下のコードを参考にしています: 3 GitHub - yawgmoth/pyhanabi: A research-focused, Python implementation of Hanabi, including a browser-based user interface 4 https://github.com/yawgmoth/pyhanabi 5 6 - ヒント情報を記録するknowledge記録・管理します. 7 8 - knowledge:は,各プレイヤーの知識を保持する4次元リストで,ヒント情報は保存されます. 9 - knowledge[player_number][card_position][color][number-1] でアクセス可能です. 10 - 各プレイヤの各手札(デフォルトは5枚)に対し,各色(デフォルトは5色),ありうるカードの可能性を示します. 11 12 - 例1 2人プレイ時のknowledgeの初期状態は以下の通りです: 13 [ (プレイヤー 0 の知識) 14 (手札 0:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 15 (手札 1:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 16 (手札 2:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 17 (手札 3:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 18 (手札 4:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 19 ], 20 [ (プレイヤー 1 の知識) 21 (手札 0:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 22 (手札 1:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 23 (手札 2:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 24 (手札 3:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 25 (手札 4:) [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 26 ] 27 - 初期状態のプレイヤー 0の手札0に着目します. 28 - なにも情報がないので,各色に対して3,2,2,2,1枚ずつある可能性が示されています. 29 - 色はlogic.pyのGameConst.COLOR_NAMESで定義された(デフォルトは["B", "G", "R", "W", "Y"])の順になっています. 30 31 - 例2 プレイヤー1からプレイヤー0に「プレイヤー0の手札0は青色です」とヒントが与えられたときの知識更新は以下の通りです(少し表記を簡単にしています): 32 プレイヤー 0 の知識: 33 手札 0: [[3, 2, 2, 2, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] 34 手札 1: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 35 手札 2: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 36 手札 3: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 37 手札 4: [[0, 0, 0, 0, 0], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 38 プレイヤー 1 の知識: 39 手札 0: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 40 手札 1: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 41 手札 2: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 42 手札 3: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 43 手札 4: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 44 - プレイヤー 0の手札0-4に着目します. 45 - 手札0は青色であり,手札1-4は青色ではないことがわかりました. 46 - ですので,手札0は青色以外の色は存在しえない[0, 0, 0, 0, 0]とすることで,青であることを確定させています. 47 - 一方,手札1-4は青色である可能性がなくなったので,青色の可能性を[0, 0, 0, 0, 0]としています. 48 49 - 例3 プレイヤー1からプレイヤー0に「プレイヤー0の手札0の数字は3です」とヒントが与えられたときの知識更新は以下の通りです: 50 プレイヤー 0 の知識: 51 手札 0: [[0, 0, 2, 0, 0], [0, 0, 2, 0, 0], [0, 0, 2, 0, 0], [0, 0, 2, 0, 0], [0, 0, 2, 0, 0]] 52 手札 1: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] 53 手札 2: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] 54 手札 3: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] 55 手札 4: [[3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1], [3, 2, 0, 2, 1]] 56 プレイヤー 1 の知識: 57 手札 0: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 58 手札 1: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 59 手札 2: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 60 手札 3: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 61 手札 4: [[3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1], [3, 2, 2, 2, 1]] 62 - プレイヤー 0の手札0-4に着目します. 63 - 手札0はの数字は3であり,手札1-4の数字は3ではないことがわかりました. 64 - ですので,手札0は3以外の色は存在しえない[0, 0, 2, 0, 0]とすることで,3であることを確定させています. 65 - 一方,手札1-4は3である可能性がなくなったので,3の可能性を排除した[3, 2, 0, 2, 1]としています. 66 67 - 注意点 68 - 相手の手札とか,捨て札とか,ボードの情報は加味した絞り込みはしてないので注意してください. 69 - 例えば,場にすでにR1が出ている⇒観測できないところにあるR1は1枚減ったな⇒knowledge更新,とかはしてないです 70 - そういう絞り込みしたければ別配列ですること.少なくとも上記で参考にしたもの&AIはその仕様なので合わせています. 71 - knowledgeはAIに渡され活用されるもので,直接的にゲームロジックに関係しません. 72""" 73 74class KnowledgeManager(): 75 """ 76 Note: 77 - knowledge配列の更新タイミングは以下の通り 78 1. ゲーム開始時に手札を配ったとき:initialize_all_knowledge()で初期化 79 2. ヒントを受けたとき:update_knowledge_after_color_hint()か,update_knowledge_after_number_hint()で更新 80 3. カードをプレイしたとき:update_knowledge_after_play()で更新 81 4. カードを捨てたとき:update_knowledge_after_discard()で更新 82 5. カードを引いたとき:update_knowledge_after_draw()で更新 83 ※3-5については絞り込みはしていません. 84 ただプレイした,捨てた,引いた,ときにカードが新しくなる 85 """ 86 87 def __init__(self, game): 88 """ 89 KnowledgeManager クラスのコンストラクタ. 90 91 Args: 92 game (Game): ゲームインスタンス 93 """ 94 self.game = game 95 96 def initialize_one_card_knowledge(self): 97 """ 98 すべての色と数字が存在する状態でカード『1枚』の知識を初期化 99 Returns: 100 list: 各色と数字の可能性を示すリスト 101 """ 102 new_card_knowledge = [] 103 for _ in range(5): # 各色に対して初期状態のカウントを設定 104 new_card_knowledge.append(self.game.game_const.COUNTS[:]) 105 return new_card_knowledge 106 107 def initialize_all_knowledge(self): 108 """ 109 ゲーム開始時,各プレイヤーの手札に対する知識をすべて初期化する関数. 110 111 Returns: 112 dict: 各プレイヤーの知識を格納した辞書 113 """ 114 knowledge = {} 115 for player in self.game.players: 116 player_knowledge = [] 117 for _ in range(self.game.hand_size): # プレイヤーの手札枚数に対して知識を設定 118 player_knowledge.append(self.initialize_one_card_knowledge()) 119 knowledge[player.player_number] = player_knowledge 120 return knowledge 121 122 def update_knowledge_after_color_hint(self, target_player_number, color_cards_positions, color): 123 """ 124 色のヒントを受け取ったときの知識を更新する. 125 126 Args: 127 target_player_number (int): ヒントを受け取ったプレイヤーの番号 128 color_cards_positions (list): ヒントを受けたカードの位置 129 color (int): ヒントを与えられた色 130 """ 131 # 1. ヒントを受けたカードに対する知識更新 132 for pos in color_cards_positions: 133 for i in range(len(self.game.knowledge[target_player_number][pos])): 134 if i != color: 135 self.game.knowledge[target_player_number][pos][i] = [0] * len(self.game.knowledge[target_player_number][pos][i]) 136 137 # 2. ヒントを受けなかったカードに対して、その色は少なくともありえないので,更新 138 for pos in range(len(self.game.knowledge[target_player_number])): 139 if pos not in color_cards_positions: # ヒントを受けたカードの位置以外 140 self.game.knowledge[target_player_number][pos][color] = [0] * len(self.game.knowledge[target_player_number][pos][color]) 141 142 def update_knowledge_after_number_hint(self, target_player_number, number_cards_positions, number): 143 """ 144 数字のヒントを受け取ったときの知識を更新する. 145 146 Args: 147 target_player_number (int): ヒントを受け取ったプレイヤーの番号 148 number_cards_positions (list): ヒントを受けたカードの位置 149 number (int): ヒントを与えられた数字 150 """ 151 # 1. ヒントを受けたカードに対する知識更新 152 for pos in number_cards_positions: 153 for i in range(len(self.game.knowledge[target_player_number][pos])): 154 for j in range(len(self.game.knowledge[target_player_number][pos][i])): 155 if j + 1 != number: 156 self.game.knowledge[target_player_number][pos][i][j] = 0 157 158 # 2. ヒントを受けなかったカードは、その数字は少なくともありえないので,更新 159 for pos in range(len(self.game.knowledge[target_player_number])): 160 if pos not in number_cards_positions: # ヒントを受けたカードの位置以外 161 for i in range(len(self.game.knowledge[target_player_number][pos])): 162 self.game.knowledge[target_player_number][pos][i][number - 1] = 0 163 164 def update_knowledge_after_draw(self, player_number): 165 """ 166 カードを引いた後の知識更新処理. 167 168 Args: 169 player_number (int): カードを引いたプレイヤーの番号 170 """ 171 # カードを引いた後の知識更新処理 172 new_card_knowledge = self.initialize_one_card_knowledge() 173 self.game.knowledge[player_number].append(new_card_knowledge) 174 175 def update_knowledge_after_play(self, player_number, card_position): 176 """ 177 カードをプレイした後の知識更新処理. 178 179 Args: 180 player_number (int): カードをプレイしたプレイヤーの番号 181 card_position (int): プレイしたカードの位置 182 """ 183 # カードをプレイした後の知識更新処理 184 del self.game.knowledge[player_number][card_position] 185 186 def update_knowledge_after_discard(self, player_number, card_position): 187 """ 188 カードを捨てた後の知識更新処理. 189 190 Args: 191 player_number (int): カードを捨てたプレイヤーの番号 192 card_position (int): 捨てたカードの位置 193 """ 194 # カードを捨てた後の知識更新処理 195 del self.game.knowledge[player_number][card_position] 196 197 def __str__(self): 198 """ 199 プレイヤーごとの知識を文字列として表示する関数. 200 201 Returns: 202 str: 各プレイヤーの知識を表す文字列 203 """ 204 status = [] 205 status.append("プレイヤーの知識:") 206 for player in self.game.players: 207 status.append(f"プレイヤー {player.player_number} の知識:") 208 for i, card_knowledge in enumerate(self.game.knowledge[player.player_number]): 209 status.append(f" 手札 {i}: {card_knowledge}") 210 return "\n".join(status)
75class KnowledgeManager(): 76 """ 77 Note: 78 - knowledge配列の更新タイミングは以下の通り 79 1. ゲーム開始時に手札を配ったとき:initialize_all_knowledge()で初期化 80 2. ヒントを受けたとき:update_knowledge_after_color_hint()か,update_knowledge_after_number_hint()で更新 81 3. カードをプレイしたとき:update_knowledge_after_play()で更新 82 4. カードを捨てたとき:update_knowledge_after_discard()で更新 83 5. カードを引いたとき:update_knowledge_after_draw()で更新 84 ※3-5については絞り込みはしていません. 85 ただプレイした,捨てた,引いた,ときにカードが新しくなる 86 """ 87 88 def __init__(self, game): 89 """ 90 KnowledgeManager クラスのコンストラクタ. 91 92 Args: 93 game (Game): ゲームインスタンス 94 """ 95 self.game = game 96 97 def initialize_one_card_knowledge(self): 98 """ 99 すべての色と数字が存在する状態でカード『1枚』の知識を初期化 100 Returns: 101 list: 各色と数字の可能性を示すリスト 102 """ 103 new_card_knowledge = [] 104 for _ in range(5): # 各色に対して初期状態のカウントを設定 105 new_card_knowledge.append(self.game.game_const.COUNTS[:]) 106 return new_card_knowledge 107 108 def initialize_all_knowledge(self): 109 """ 110 ゲーム開始時,各プレイヤーの手札に対する知識をすべて初期化する関数. 111 112 Returns: 113 dict: 各プレイヤーの知識を格納した辞書 114 """ 115 knowledge = {} 116 for player in self.game.players: 117 player_knowledge = [] 118 for _ in range(self.game.hand_size): # プレイヤーの手札枚数に対して知識を設定 119 player_knowledge.append(self.initialize_one_card_knowledge()) 120 knowledge[player.player_number] = player_knowledge 121 return knowledge 122 123 def update_knowledge_after_color_hint(self, target_player_number, color_cards_positions, color): 124 """ 125 色のヒントを受け取ったときの知識を更新する. 126 127 Args: 128 target_player_number (int): ヒントを受け取ったプレイヤーの番号 129 color_cards_positions (list): ヒントを受けたカードの位置 130 color (int): ヒントを与えられた色 131 """ 132 # 1. ヒントを受けたカードに対する知識更新 133 for pos in color_cards_positions: 134 for i in range(len(self.game.knowledge[target_player_number][pos])): 135 if i != color: 136 self.game.knowledge[target_player_number][pos][i] = [0] * len(self.game.knowledge[target_player_number][pos][i]) 137 138 # 2. ヒントを受けなかったカードに対して、その色は少なくともありえないので,更新 139 for pos in range(len(self.game.knowledge[target_player_number])): 140 if pos not in color_cards_positions: # ヒントを受けたカードの位置以外 141 self.game.knowledge[target_player_number][pos][color] = [0] * len(self.game.knowledge[target_player_number][pos][color]) 142 143 def update_knowledge_after_number_hint(self, target_player_number, number_cards_positions, number): 144 """ 145 数字のヒントを受け取ったときの知識を更新する. 146 147 Args: 148 target_player_number (int): ヒントを受け取ったプレイヤーの番号 149 number_cards_positions (list): ヒントを受けたカードの位置 150 number (int): ヒントを与えられた数字 151 """ 152 # 1. ヒントを受けたカードに対する知識更新 153 for pos in number_cards_positions: 154 for i in range(len(self.game.knowledge[target_player_number][pos])): 155 for j in range(len(self.game.knowledge[target_player_number][pos][i])): 156 if j + 1 != number: 157 self.game.knowledge[target_player_number][pos][i][j] = 0 158 159 # 2. ヒントを受けなかったカードは、その数字は少なくともありえないので,更新 160 for pos in range(len(self.game.knowledge[target_player_number])): 161 if pos not in number_cards_positions: # ヒントを受けたカードの位置以外 162 for i in range(len(self.game.knowledge[target_player_number][pos])): 163 self.game.knowledge[target_player_number][pos][i][number - 1] = 0 164 165 def update_knowledge_after_draw(self, player_number): 166 """ 167 カードを引いた後の知識更新処理. 168 169 Args: 170 player_number (int): カードを引いたプレイヤーの番号 171 """ 172 # カードを引いた後の知識更新処理 173 new_card_knowledge = self.initialize_one_card_knowledge() 174 self.game.knowledge[player_number].append(new_card_knowledge) 175 176 def update_knowledge_after_play(self, player_number, card_position): 177 """ 178 カードをプレイした後の知識更新処理. 179 180 Args: 181 player_number (int): カードをプレイしたプレイヤーの番号 182 card_position (int): プレイしたカードの位置 183 """ 184 # カードをプレイした後の知識更新処理 185 del self.game.knowledge[player_number][card_position] 186 187 def update_knowledge_after_discard(self, player_number, card_position): 188 """ 189 カードを捨てた後の知識更新処理. 190 191 Args: 192 player_number (int): カードを捨てたプレイヤーの番号 193 card_position (int): 捨てたカードの位置 194 """ 195 # カードを捨てた後の知識更新処理 196 del self.game.knowledge[player_number][card_position] 197 198 def __str__(self): 199 """ 200 プレイヤーごとの知識を文字列として表示する関数. 201 202 Returns: 203 str: 各プレイヤーの知識を表す文字列 204 """ 205 status = [] 206 status.append("プレイヤーの知識:") 207 for player in self.game.players: 208 status.append(f"プレイヤー {player.player_number} の知識:") 209 for i, card_knowledge in enumerate(self.game.knowledge[player.player_number]): 210 status.append(f" 手札 {i}: {card_knowledge}") 211 return "\n".join(status)
Note:
- knowledge配列の更新タイミングは以下の通り
- ゲーム開始時に手札を配ったとき:initialize_all_knowledge()で初期化
- ヒントを受けたとき:update_knowledge_after_color_hint()か,update_knowledge_after_number_hint()で更新
- カードをプレイしたとき:update_knowledge_after_play()で更新
- カードを捨てたとき:update_knowledge_after_discard()で更新
- カードを引いたとき:update_knowledge_after_draw()で更新 ※3-5については絞り込みはしていません. ただプレイした,捨てた,引いた,ときにカードが新しくなる
88 def __init__(self, game): 89 """ 90 KnowledgeManager クラスのコンストラクタ. 91 92 Args: 93 game (Game): ゲームインスタンス 94 """ 95 self.game = game
KnowledgeManager クラスのコンストラクタ.
Arguments:
- game (Game): ゲームインスタンス
97 def initialize_one_card_knowledge(self): 98 """ 99 すべての色と数字が存在する状態でカード『1枚』の知識を初期化 100 Returns: 101 list: 各色と数字の可能性を示すリスト 102 """ 103 new_card_knowledge = [] 104 for _ in range(5): # 各色に対して初期状態のカウントを設定 105 new_card_knowledge.append(self.game.game_const.COUNTS[:]) 106 return new_card_knowledge
すべての色と数字が存在する状態でカード『1枚』の知識を初期化
Returns:
list: 各色と数字の可能性を示すリスト
108 def initialize_all_knowledge(self): 109 """ 110 ゲーム開始時,各プレイヤーの手札に対する知識をすべて初期化する関数. 111 112 Returns: 113 dict: 各プレイヤーの知識を格納した辞書 114 """ 115 knowledge = {} 116 for player in self.game.players: 117 player_knowledge = [] 118 for _ in range(self.game.hand_size): # プレイヤーの手札枚数に対して知識を設定 119 player_knowledge.append(self.initialize_one_card_knowledge()) 120 knowledge[player.player_number] = player_knowledge 121 return knowledge
ゲーム開始時,各プレイヤーの手札に対する知識をすべて初期化する関数.
Returns:
dict: 各プレイヤーの知識を格納した辞書
123 def update_knowledge_after_color_hint(self, target_player_number, color_cards_positions, color): 124 """ 125 色のヒントを受け取ったときの知識を更新する. 126 127 Args: 128 target_player_number (int): ヒントを受け取ったプレイヤーの番号 129 color_cards_positions (list): ヒントを受けたカードの位置 130 color (int): ヒントを与えられた色 131 """ 132 # 1. ヒントを受けたカードに対する知識更新 133 for pos in color_cards_positions: 134 for i in range(len(self.game.knowledge[target_player_number][pos])): 135 if i != color: 136 self.game.knowledge[target_player_number][pos][i] = [0] * len(self.game.knowledge[target_player_number][pos][i]) 137 138 # 2. ヒントを受けなかったカードに対して、その色は少なくともありえないので,更新 139 for pos in range(len(self.game.knowledge[target_player_number])): 140 if pos not in color_cards_positions: # ヒントを受けたカードの位置以外 141 self.game.knowledge[target_player_number][pos][color] = [0] * len(self.game.knowledge[target_player_number][pos][color])
色のヒントを受け取ったときの知識を更新する.
Arguments:
- target_player_number (int): ヒントを受け取ったプレイヤーの番号
- color_cards_positions (list): ヒントを受けたカードの位置
- color (int): ヒントを与えられた色
143 def update_knowledge_after_number_hint(self, target_player_number, number_cards_positions, number): 144 """ 145 数字のヒントを受け取ったときの知識を更新する. 146 147 Args: 148 target_player_number (int): ヒントを受け取ったプレイヤーの番号 149 number_cards_positions (list): ヒントを受けたカードの位置 150 number (int): ヒントを与えられた数字 151 """ 152 # 1. ヒントを受けたカードに対する知識更新 153 for pos in number_cards_positions: 154 for i in range(len(self.game.knowledge[target_player_number][pos])): 155 for j in range(len(self.game.knowledge[target_player_number][pos][i])): 156 if j + 1 != number: 157 self.game.knowledge[target_player_number][pos][i][j] = 0 158 159 # 2. ヒントを受けなかったカードは、その数字は少なくともありえないので,更新 160 for pos in range(len(self.game.knowledge[target_player_number])): 161 if pos not in number_cards_positions: # ヒントを受けたカードの位置以外 162 for i in range(len(self.game.knowledge[target_player_number][pos])): 163 self.game.knowledge[target_player_number][pos][i][number - 1] = 0
数字のヒントを受け取ったときの知識を更新する.
Arguments:
- target_player_number (int): ヒントを受け取ったプレイヤーの番号
- number_cards_positions (list): ヒントを受けたカードの位置
- number (int): ヒントを与えられた数字
165 def update_knowledge_after_draw(self, player_number): 166 """ 167 カードを引いた後の知識更新処理. 168 169 Args: 170 player_number (int): カードを引いたプレイヤーの番号 171 """ 172 # カードを引いた後の知識更新処理 173 new_card_knowledge = self.initialize_one_card_knowledge() 174 self.game.knowledge[player_number].append(new_card_knowledge)
カードを引いた後の知識更新処理.
Arguments:
- player_number (int): カードを引いたプレイヤーの番号
176 def update_knowledge_after_play(self, player_number, card_position): 177 """ 178 カードをプレイした後の知識更新処理. 179 180 Args: 181 player_number (int): カードをプレイしたプレイヤーの番号 182 card_position (int): プレイしたカードの位置 183 """ 184 # カードをプレイした後の知識更新処理 185 del self.game.knowledge[player_number][card_position]
カードをプレイした後の知識更新処理.
Arguments:
- player_number (int): カードをプレイしたプレイヤーの番号
- card_position (int): プレイしたカードの位置
187 def update_knowledge_after_discard(self, player_number, card_position): 188 """ 189 カードを捨てた後の知識更新処理. 190 191 Args: 192 player_number (int): カードを捨てたプレイヤーの番号 193 card_position (int): 捨てたカードの位置 194 """ 195 # カードを捨てた後の知識更新処理 196 del self.game.knowledge[player_number][card_position]
カードを捨てた後の知識更新処理.
Arguments:
- player_number (int): カードを捨てたプレイヤーの番号
- card_position (int): 捨てたカードの位置