def __init__(self, context: Context): self.context = context self.clues = Clues(context) self.knowledge_table = KnowledgeTable(self.context.players, self.context.cards) self.brute_forcer = BruteForcer(self.clues, self.knowledge_table) self.deriver = Deriver(self.clues, self.knowledge_table)
class Watson: def __init__(self, context: Context): self.context = context self.clues = Clues(context) self.knowledge_table = KnowledgeTable(self.context.players, self.context.cards) self.brute_forcer = BruteForcer(self.clues, self.knowledge_table) self.deriver = Deriver(self.clues, self.knowledge_table) def add_knowledge(self, player: Player, card: Card, knowledge: Knowledge): self.clues.add_card(card, player) self.deriver.derive_from_new_knowledge(player, card, knowledge) self.brute_force_and_derive_from_findings() def add_rumour(self, rumour: Rumour) -> None: self.clues.add_rumour(rumour) self.deriver.derive_from_new_rumour(rumour) self.brute_force_and_derive_from_findings() def brute_force_and_derive_from_findings(self): for player in self.context.players: for card in self.context.cards: if self.knowledge_table.get(player, card) == Knowledge.MAYBE: knowledge = self.brute_forcer.brute_force_on_card( player, card) if knowledge != Knowledge.MAYBE: self.deriver.derive_from_new_knowledge( player, card, knowledge) def add_info_from_clues(self, clues: Clues): self._add_cards_from_clues(clues) self._add_rumours_from_clues(clues) self.brute_force_and_derive_from_findings() def _add_cards_from_clues(self, clues): for player, cards in clues.cards_seen.items(): for card in cards: self.clues.add_card(card, player) self.deriver.derive_from_new_knowledge(player, card, Knowledge.TRUE) def _add_rumours_from_clues(self, clues): for rumour in clues.get_rumours(): self.clues.add_rumour(rumour) self.deriver.derive_from_new_rumour(rumour) def display_state(self) -> str: formatter = KnowledgeTableFormatter() return formatter.format_knowledge_table(self.knowledge_table) def get_knowledge_table(self) -> KnowledgeTable: return self.knowledge_table def get_context(self) -> Context: return self.context def get_clues(self) -> Clues: return self.clues
def setUp(self) -> None: context = context_fixture self.empty_solution_finder = SolutionFinder(Clues(context), KnowledgeTable(context.players, context.cards)) knowledge_table = KnowledgeTable(context.players, context.cards) tom_cards = [Cards.BLAAUWVANDRAET, Cards.BUBBELBAD, Cards.BIJL, Cards.HALTER] menno_cards = [Cards.ROODHART, Cards.ZITKAMER, Cards.KNUPPEL, Cards.GASTENVERBLIJF] michiel_cards = [Cards.DEWIT, Cards.THEATER, Cards.TOUW] for card in tom_cards: knowledge_table.set(tom, card, Knowledge.TRUE) for card in menno_cards: knowledge_table.set(menno, card, Knowledge.TRUE) for card in michiel_cards: knowledge_table.set(michiel, card, Knowledge.TRUE) self.half_full_solution_finder = SolutionFinder(Clues(context), knowledge_table)
def format_category_table(self, category: Category, knowledge_table: KnowledgeTable): players = knowledge_table.players category_cards = [card for card in knowledge_table.cards if card.category == category] category_cards.sort(key=lambda card: card.name) table = TableFormatter(len(category_cards) + 1, len(players) + 1) # Set the player names in the table for p in range(len(players)): table.set(0, p + 1, players[p].name) # Set the card names in the table for c in range(len(category_cards)): table.set(c + 1, 0, category_cards[c].name) # fill the table for card_i in range(len(category_cards)): for player_i in range(len(players)): card = category_cards[card_i] player = players[player_i] s = knowledge_to_str(knowledge_table.get(player, card)) table.set(card_i + 1, player_i + 1, s) return table.to_string()
def check_knowledge(knowledge_table: KnowledgeTable, clues: Clues, new_player_hands: Dict[Player, List[Card]] = None) -> bool: player_hands, murder_cards, free_cards = knowledge_table.current_player_hands( ) for cat in Category: if len([c.category for c in murder_cards if c.category is cat]) > 1: return False players = clues.context.players for player in players: if new_player_hands is not None: player_hands[player] += new_player_hands[player] player_hands[player] = list(set( player_hands[player])) # To get unique elements from list for card in new_player_hands[player]: if card in free_cards: free_cards.remove(card) if len(player_hands[player]) > player.cardAmount: return False for rumour in clues.rumours: rumour_cards = rumour.rumour_cards for replier, knowledge in rumour.replies: has_rumour_card = set(rumour_cards).isdisjoint( player_hands[replier]) if knowledge == Knowledge.FALSE: # Replier should not have any of the rumoured cards if not has_rumour_card: return False elif knowledge == Knowledge.TRUE: # Replier should have any of the rumoured cards if replier.cardAmount == len( player_hands[replier]) and has_rumour_card: return False if set(rumour_cards).isdisjoint( free_cards) and has_rumour_card: return False return True
def test_format_knowledge_table(self): context = context_fixture knowledge_table = KnowledgeTable(context.players, context.cards) knowledge_table.set(knowledge_table.players[0], Cards.EETKAMER, Knowledge.FALSE) knowledge_table.set(knowledge_table.players[2], Cards.ROODHART, Knowledge.TRUE) printer = KnowledgeTableFormatter() result = printer.format_knowledge_table(knowledge_table) expected = '\n'.join([ " Tom Menno Michiel", "Blaauw van Draet . . . ", " De Wit . . . ", " Groenewoud . . . ", " Pimpel . . . ", " Roodhart . . v ", "", " Tom Menno Michiel", " Bijl . . . ", " Halter . . . ", "Kandelaar . . . ", " Knuppel . . . ", " Mes . . . ", " Pistool . . . ", " Touw . . . ", " Vergif . . . ", "", " Tom Menno Michiel", " Bubbelbad . . . ", " Eetkamer x . . ", "Gastenverblijf . . . ", " Hal . . . ", " Keuken . . . ", " Theater . . . ", " Werkkamer . . . ", " Zitkamer . . . ", ]) self.assertEqual(result, expected)
def setUp(self) -> None: clues = Clues(context_fixture) self.context = clues.get_context() self.empty_knowledge_table = KnowledgeTable(self.context.players, self.context.cards) self.empty_deriver = Deriver(clues, self.empty_knowledge_table)
def setUp(self) -> None: self.knowledge_table = KnowledgeTable(context_fixture.players, context_fixture.cards) self.clues = Clues(context_fixture) self.empty_brute_forcer = BruteForcer(self.clues, self.knowledge_table)
def setUp(self): self.context = context_fixture self.some_player = tom self.knowledge_table = KnowledgeTable(self.context.players, self.context.cards)
class TestKnowledgeTable(TestCase): def setUp(self): self.context = context_fixture self.some_player = tom self.knowledge_table = KnowledgeTable(self.context.players, self.context.cards) def test_new_knowledge_table(self): for player in self.context.players: for card in self.context.cards: self.assertEqual(self.knowledge_table.get(player, card), Knowledge.MAYBE) def test_set(self): self.knowledge_table.set(self.some_player, Cards.KNUPPEL, Knowledge.TRUE) self.assertEqual( self.knowledge_table.get(self.some_player, Cards.KNUPPEL), Knowledge.TRUE ) def test_invalid_set(self): self.knowledge_table.set(self.some_player, Cards.KNUPPEL, Knowledge.TRUE) with self.assertRaises(ValueError): self.knowledge_table.set(self.some_player, Cards.KNUPPEL, Knowledge.FALSE) def test_set_forcefully(self): self.knowledge_table.set(self.some_player, Cards.KNUPPEL, Knowledge.TRUE) self.knowledge_table.set_forcefully(self.some_player, Cards.KNUPPEL, Knowledge.FALSE) def test_current_player_hands(self): knowledge_table = self.knowledge_table for player in self.context.players: knowledge_table.set(player, Cards.KNUPPEL, Knowledge.FALSE) knowledge_table.set(self.some_player, Cards.TOUW, Knowledge.TRUE) player_hands, murderer_cards, free_cards = knowledge_table.current_player_hands() self.assertIn(Cards.KNUPPEL, murderer_cards) self.assertIn(Cards.TOUW, player_hands[self.some_player]) self.assertIn(Cards.PIMPEL, free_cards)