示例#1
0
def get_center_wolf_statements(
        player_obj: Any,
        knowledge_base: KnowledgeBase) -> tuple[Statement, ...]:
    """Center Wolf Player logic."""
    statements: tuple[Statement, ...] = ()
    player_index = player_obj.player_index
    wolf_indices = player_obj.wolf_indices
    center_role = player_obj.center_role
    center_index = player_obj.center_index

    if center_role is Role.VILLAGER:
        statements += Villager.get_villager_statements(player_index)
    elif center_role is Role.HUNTER:
        statements += Hunter.get_hunter_statements(player_index)
    elif center_role is Role.INSOMNIAC:
        # TODO check for switches and prioritize those statements
        statements += Insomniac.get_insomniac_statements(
            player_index, Role.INSOMNIAC)
    elif center_role is Role.ROBBER:
        for i, stated_role in enumerate(knowledge_base.stated_roles):
            if stated_role not in (Role.NONE, Role.ROBBER):
                statements += Robber.get_robber_statements(
                    player_index, i, stated_role)
    elif center_role is Role.TROUBLEMAKER:
        num_stated = len(knowledge_base.stated_roles)
        for i in range(num_stated):
            for j in range(i + 1, num_stated):
                if j not in wolf_indices:
                    statements += Troublemaker.get_troublemaker_statements(
                        player_index, i, j)
    elif center_role is Role.DRUNK:
        statements += Drunk.get_drunk_statements(player_index, center_index)
    elif center_role is Role.SEER:
        for i, stated_role in enumerate(knowledge_base.stated_roles):
            # 'Hey, I'm a Seer and I saw another Seer...'
            if i not in wolf_indices and stated_role not in (Role.NONE,
                                                             Role.SEER):
                statements += Seer.get_seer_statements(player_index,
                                                       (i, stated_role))
        for role2 in const.SORTED_ROLE_SET:
            for cent1 in range(const.NUM_CENTER):
                if cent1 != center_index:
                    for role1 in const.SORTED_ROLE_SET:
                        if role1 is not Role.SEER and role2 is not Role.SEER:
                            if role1 != role2 or const.ROLE_COUNTS[role1] >= 2:
                                statements += Seer.get_seer_statements(
                                    player_index,
                                    (cent1 + const.NUM_PLAYERS, role1),
                                    (center_index, role2),
                                )
    elif center_role is Role.DOPPELGANGER:
        statements += Doppelganger.get_doppelganger_statements(
            player_index, center_role)
    elif center_role in const.EVIL_ROLES:
        pass
    else:
        raise UnhandledEnumValueError(center_role)
    return statements
示例#2
0
    def test_lru_cache_hit() -> None:
        """Correctly cache a function call cache hit."""
        result_1 = Seer.get_seer_statements(1, (6, Role.ROBBER))

        result_2 = Seer.get_seer_statements(1, (6, Role.ROBBER))
        info = Seer.get_seer_statements.cache_info()

        assert result_1 == result_2
        assert info.hits == 1
        assert info.misses == 1
        assert info.currsize == 1
示例#3
0
    def test_json_repr(example_small_saved_game: SavedGame) -> None:
        """Should convert a SavedGame into a dict with all of its fields."""
        result = example_small_saved_game.json_repr()

        assert result == {
            "all_statements": (
                Statement("I am a Villager.",
                          ((0, frozenset({Role.VILLAGER})), )),
                Statement(
                    "I am a Robber and I swapped with Player 2. I am now a Seer.",
                    ((1, frozenset({Role.ROBBER})),
                     (2, frozenset({Role.SEER}))),
                    ((SwitchPriority.ROBBER, 1, 2), ),
                ),
                Statement(
                    "I am a Seer and I saw that Player 1 was a Robber.",
                    ((2, frozenset({Role.SEER})),
                     (1, frozenset({Role.ROBBER}))),
                ),
            ),
            "game_roles": (Role.VILLAGER, Role.SEER, Role.ROBBER),
            "original_roles": (Role.VILLAGER, Role.ROBBER, Role.SEER),
            "player_objs": (
                Villager(0),
                Robber(1, 2, Role.SEER),
                Seer(2, (1, Role.ROBBER)),
            ),
            "type":
            "SavedGame",
        }
示例#4
0
    def test_medium_individual_preds(
        medium_game_roles: tuple[Role, ...],
        medium_statement_list: tuple[Statement, ...],
    ) -> None:
        """Should get the individual predictions for all players."""
        player_objs: tuple[Player, ...] = (
            Seer(0, (2, Role.DRUNK)),
            Wolf(1, (1, ), 5, Role.TROUBLEMAKER),
            Drunk(2, 5),
            Robber(3, 1, Role.WOLF),
            Minion(4, (1, )),
        )

        result = one_night.get_individual_preds(player_objs,
                                                medium_statement_list)

        assert result == (
            (
                Role.SEER,
                Role.MINION,
                Role.TROUBLEMAKER,
                Role.DRUNK,
                Role.WOLF,
                Role.ROBBER,
            ),
            (
                Role.MINION,
                Role.SEER,
                Role.TROUBLEMAKER,
                Role.WOLF,
                Role.ROBBER,
                Role.DRUNK,
            ),
            (
                Role.SEER,
                Role.MINION,
                Role.TROUBLEMAKER,
                Role.DRUNK,
                Role.WOLF,
                Role.ROBBER,
            ),
            (
                Role.SEER,
                Role.MINION,
                Role.TROUBLEMAKER,
                Role.DRUNK,
                Role.WOLF,
                Role.ROBBER,
            ),
            (
                Role.MINION,
                Role.WOLF,
                Role.TROUBLEMAKER,
                Role.DRUNK,
                Role.SEER,
                Role.ROBBER,
            ),
        )
示例#5
0
    def test_get_seer_statements() -> None:
        """Execute initialization actions and return the possible statements."""
        player_index = 1

        result = Seer.get_seer_statements(player_index, (6, Role.ROBBER))

        assert result == (Statement(
            "I am a Seer and I saw that Player 6 was a Robber.",
            ((1, frozenset({Role.SEER})), (6, frozenset({Role.ROBBER}))),
        ), )
示例#6
0
    def test_find_evil_players(medium_game_roles: tuple[str, ...]) -> None:
        """Should determine if a player has turned evil after night falls."""
        player_list: tuple[Player, ...] = (
            Seer(0, (2, Role.DRUNK)),
            Wolf(1, (1, ), 5, Role.TROUBLEMAKER),
            Drunk(2, 5),
            Robber(3, 2, Role.DRUNK),
            Minion(4, (1, )),
        )

        result = [player.is_evil() for player in player_list]

        assert result == [False, True, False, False, True]
示例#7
0
def example_small_saved_game(small_game_roles: tuple[Role, ...]) -> SavedGame:
    return SavedGame(
        (Role.VILLAGER, Role.ROBBER, Role.SEER),
        (Role.VILLAGER, Role.SEER, Role.ROBBER),
        (
            Statement("I am a Villager.", ((0, frozenset({Role.VILLAGER})),)),
            Statement(
                "I am a Robber and I swapped with Player 2. I am now a Seer.",
                ((1, frozenset({Role.ROBBER})), (2, frozenset({Role.SEER}))),
                ((SwitchPriority.ROBBER, 1, 2),),
            ),
            Statement(
                "I am a Seer and I saw that Player 1 was a Robber.",
                ((2, frozenset({Role.SEER})), (1, frozenset({Role.ROBBER}))),
            ),
        ),
        (Villager(0), Robber(1, 2, Role.SEER), Seer(2, (1, Role.ROBBER), (None, None))),
    )
示例#8
0
    def test_default_saved_game(example_small_saved_game: SavedGame) -> None:
        """Should convert objects of different types to JSON."""
        player_objs = [
            Villager(0),
            Robber(1, 2, Role.SEER),
            Seer(2, (1, Role.ROBBER))
        ]
        player_strs = ", ".join(
            [json.dumps(player, cls=WolfBotEncoder) for player in player_objs])
        statement_objs = [
            Statement(
                "I am a Villager.",
                ((0, frozenset({Role.VILLAGER})), ),
                speaker=Role.VILLAGER,
            ),
            Statement(
                "I am a Robber and I swapped with Player 2. I am now a Seer.",
                ((1, frozenset({Role.ROBBER})), (2, frozenset({Role.SEER}))),
                ((SwitchPriority.ROBBER, 1, 2), ),
                Role.ROBBER,
            ),
            Statement(
                "I am a Seer and I saw that Player 1 was a Robber.",
                ((2, frozenset({Role.SEER})), (1, frozenset({Role.ROBBER}))),
                speaker=Role.SEER,
            ),
        ]
        statement_strs = ", ".join([
            json.dumps(statement, cls=WolfBotEncoder)
            for statement in statement_objs
        ])

        result = json.dumps(example_small_saved_game, cls=WolfBotEncoder)
        assert result == (
            '{"type": "SavedGame",'
            ' "original_roles": [{"type": "Role", "data": "Villager"},'
            ' {"type": "Role", "data": "Robber"}, {"type": "Role", "data": "Seer"}],'
            ' "game_roles": [{"type": "Role", "data": "Villager"},'
            ' {"type": "Role", "data": "Seer"}, {"type": "Role", "data": "Robber"}],'
            f' "all_statements": [{statement_strs}],'
            f' "player_objs": [{player_strs}]}}')

        reverted_result = json.loads(result, cls=WolfBotDecoder)
        assert reverted_result == example_small_saved_game
示例#9
0
    def test_awake_init_player_choice(
            large_game_roles: tuple[Role, ...]) -> None:
        """
        Should initialize a Seer. Note that the player_index of the Seer is
        not necessarily the index where the true Seer is located.
        """
        player_index = 11
        const.CENTER_SEER_PROB = 0
        game_roles = list(large_game_roles)
        expected = (Statement(
            "I am a Seer and I saw that Player 6 was a Mason.",
            ((11, frozenset({Role.SEER})), (6, frozenset({Role.MASON}))),
        ), )

        seer = Seer.awake_init(player_index, game_roles)

        assert seer.choice_1 == (6, Role.MASON)
        assert seer.choice_2 == (None, None)
        assert seer.statements == expected
示例#10
0
def example_medium_saved_game(medium_game_roles: tuple[Role, ...]) -> SavedGame:
    return SavedGame(
        (Role.SEER, Role.WOLF, Role.DRUNK, Role.ROBBER, Role.MINION, Role.TROUBLEMAKER),
        (Role.SEER, Role.WOLF, Role.TROUBLEMAKER, Role.DRUNK, Role.MINION, Role.ROBBER),
        (
            Statement(
                "I am a Seer and I saw that Player 2 was a Drunk.",
                ((0, frozenset({Role.SEER})), (2, frozenset({Role.DRUNK}))),
            ),
            Statement(
                "I am a Robber and I swapped with Player 0. I am now a Seer.",
                ((1, frozenset({Role.ROBBER})), (0, frozenset({Role.SEER}))),
                ((SwitchPriority.ROBBER, 1, 0),),
            ),
            Statement(
                "I am a Drunk and I swapped with Center 0.",
                ((2, frozenset({Role.DRUNK})),),
                ((SwitchPriority.DRUNK, 2, 5),),
            ),
            Statement(
                "I am a Robber and I swapped with Player 2. I am now a Drunk.",
                ((3, frozenset({Role.ROBBER})), (2, frozenset({Role.DRUNK}))),
                ((SwitchPriority.ROBBER, 3, 2),),
            ),
            Statement(
                "I am a Seer and I saw that Player 3 was a Robber.",
                ((4, frozenset({Role.SEER})), (3, frozenset({Role.ROBBER}))),
            ),
        ),
        (
            Seer(0, (2, Role.DRUNK)),
            Wolf(1, (1,), 5, Role.TROUBLEMAKER),
            Drunk(2, 5),
            Robber(3, 2, Role.DRUNK),
            Minion(4, (1,)),
        ),
    )
示例#11
0
    def test_awake_init_center_choice(
            large_game_roles: tuple[Role, ...]) -> None:
        """
        Should initialize a Seer. Note that the player_index of the Seer is
        not necessarily the index where the true Seer is located.
        """
        player_index = 11
        const.CENTER_SEER_PROB = 1
        game_roles = list(large_game_roles)
        expected = (Statement(
            ("I am a Seer and I saw that Center 1 was a Insomniac "
             "and that Center 0 was a Troublemaker."),
            (
                (11, frozenset({Role.SEER})),
                (13, frozenset({Role.INSOMNIAC})),
                (12, frozenset({Role.TROUBLEMAKER})),
            ),
        ), )

        seer = Seer.awake_init(player_index, game_roles)

        assert seer.choice_1 == (13, Role.INSOMNIAC)
        assert seer.choice_2 == (12, Role.TROUBLEMAKER)
        assert seer.statements == expected
示例#12
0
    def test_get_all_statements() -> None:
        """Should return possible statements from all possible initializations."""
        player_index = 1
        set_roles(Role.WOLF, Role.SEER, Role.VILLAGER, Role.WOLF)
        const.NUM_PLAYERS = 2
        const.NUM_CENTER = 2
        expected = (
            Statement(
                "I am a Seer and I saw that Player 0 was a Villager.",
                ((1, frozenset({Role.SEER})), (0, frozenset({Role.VILLAGER}))),
            ),
            Statement(
                "I am a Seer and I saw that Player 1 was a Villager.",
                ((1, frozenset({Role.SEER})), (1, frozenset({Role.VILLAGER}))),
            ),
            Statement(
                "I am a Seer and I saw that Player 0 was a Wolf.",
                ((1, frozenset({Role.SEER})), (0, frozenset({Role.WOLF}))),
            ),
            Statement(
                "I am a Seer and I saw that Player 1 was a Wolf.",
                ((1, frozenset({Role.SEER})), (1, frozenset({Role.WOLF}))),
            ),
            Statement(
                "I am a Seer and I saw that Player 0 was a Seer.",
                ((1, frozenset({Role.SEER})), (0, frozenset({Role.SEER}))),
            ),
            Statement(
                "I am a Seer and I saw that Player 1 was a Seer.",
                ((1, frozenset({Role.SEER})), (1, frozenset({Role.SEER}))),
            ),
            Statement(
                ("I am a Seer and I saw that Center 0 was a Villager and "
                 "that Center 1 was a Wolf."),
                (
                    (1, frozenset({Role.SEER})),
                    (2, frozenset({Role.VILLAGER})),
                    (3, frozenset({Role.WOLF})),
                ),
            ),
            Statement(
                ("I am a Seer and I saw that Center 0 was a Wolf and "
                 "that Center 1 was a Villager."),
                (
                    (1, frozenset({Role.SEER})),
                    (2, frozenset({Role.WOLF})),
                    (3, frozenset({Role.VILLAGER})),
                ),
            ),
            Statement(
                ("I am a Seer and I saw that Center 0 was a Wolf "
                 "and that Center 1 was a Wolf."),
                (
                    (1, frozenset({Role.SEER})),
                    (2, frozenset({Role.WOLF})),
                    (3, frozenset({Role.WOLF})),
                ),
            ),
        )

        result = Seer.get_all_statements(player_index)

        assert set(result) == set(expected)
示例#13
0
def example_large_saved_game(large_game_roles: tuple[Role, ...]) -> SavedGame:
    mason_roles = tuple(
        (i, const.ROLE_SET - frozenset({Role.MASON}))
        for i in range(const.NUM_PLAYERS)
        if i != 2
    )
    return SavedGame(
        (
            Role.VILLAGER,
            Role.DRUNK,
            Role.MASON,
            Role.TANNER,
            Role.VILLAGER,
            Role.ROBBER,
            Role.SEER,
            Role.WOLF,
            Role.MINION,
            Role.VILLAGER,
            Role.WOLF,
            Role.HUNTER,
            Role.TROUBLEMAKER,
            Role.MASON,
            Role.INSOMNIAC,
        ),
        (
            Role.VILLAGER,
            Role.INSOMNIAC,
            Role.MASON,
            Role.TANNER,
            Role.VILLAGER,
            Role.DRUNK,
            Role.SEER,
            Role.WOLF,
            Role.MINION,
            Role.VILLAGER,
            Role.WOLF,
            Role.HUNTER,
            Role.TROUBLEMAKER,
            Role.MASON,
            Role.ROBBER,
        ),
        (
            Statement("I am a Villager.", ((0, frozenset({Role.VILLAGER})),)),
            Statement(
                "I am a Drunk and I swapped with Center 2.",
                ((1, frozenset({Role.DRUNK})),),
                ((SwitchPriority.DRUNK, 1, 14),),
            ),
            Statement(
                "I am a Mason. The other Mason is not present.",
                ((2, frozenset({Role.MASON})),) + mason_roles,
            ),
            Statement(
                "I am a Robber and I swapped with Player 10. I am now a Insomniac.",
                ((3, frozenset({Role.ROBBER})), (10, frozenset({Role.INSOMNIAC}))),
                ((SwitchPriority.ROBBER, 3, 10),),
            ),
            Statement("I am a Villager.", ((4, frozenset({Role.VILLAGER})),)),
            Statement(
                "I am a Robber and I swapped with Player 1. I am now a Drunk.",
                ((5, frozenset({Role.ROBBER})), (1, frozenset({Role.DRUNK}))),
                ((SwitchPriority.ROBBER, 5, 1),),
            ),
            Statement(
                (
                    "I am a Seer and I saw that Center 1 was a Mason and that "
                    "Center 0 was a Troublemaker."
                ),
                (
                    (6, frozenset({Role.SEER})),
                    (13, frozenset({Role.MASON})),
                    (12, frozenset({Role.TROUBLEMAKER})),
                ),
            ),
            Statement(
                "I am a Seer and I saw that Player 3 was a Robber.",
                ((7, frozenset({Role.SEER})), (3, frozenset({Role.ROBBER}))),
            ),
            Statement(
                "I am a Troublemaker and I swapped Player 0 and Player 1.",
                ((8, frozenset({Role.TROUBLEMAKER})),),
                ((SwitchPriority.TROUBLEMAKER, 0, 1),),
            ),
            Statement("I am a Villager.", ((9, frozenset({Role.VILLAGER})),)),
            Statement(
                "I am a Troublemaker and I swapped Player 3 and Player 4.",
                ((10, frozenset({Role.TROUBLEMAKER})),),
                ((SwitchPriority.TROUBLEMAKER, 3, 4),),
            ),
            Statement("I am a Hunter.", ((11, frozenset({Role.HUNTER})),)),
        ),
        (
            Villager(0),
            Drunk(1, 14),
            Mason(2, (2,)),
            Tanner(3),
            Villager(4),
            Robber(5, 1, Role.DRUNK),
            Seer(6, (13, Role.MASON), (12, Role.TROUBLEMAKER)),
            Wolf(7, (7, 10), None, None),
            Minion(8, (7, 10)),
            Villager(9),
            Wolf(10, (7, 10), None, None),
            Hunter(11),
        ),
    )
示例#14
0
def get_wolf_statements(
    player_obj: Any, knowledge_base: KnowledgeBase
) -> tuple[Statement, ...]:
    """
    Gets Regular Wolf statement, which chooses Villager statements
    with hardcoded logic to maximize Wolf win rate.
    """
    statements: tuple[Statement, ...] = ()
    stated_roles = knowledge_base.stated_roles
    player_index = player_obj.player_index
    counts_dict = Counter(
        {
            role: count
            for role, count in const.ROLE_COUNTS.items()
            if role in const.VILLAGE_ROLES
        }
    ) - Counter(stated_roles)

    if Role.VILLAGER in const.ROLE_SET and should_include_role(
        counts_dict, Role.VILLAGER
    ):
        statements += Villager.get_villager_statements(player_index)
    if Role.HUNTER in const.ROLE_SET and should_include_role(counts_dict, Role.HUNTER):
        statements += Hunter.get_hunter_statements(player_index)
    if Role.INSOMNIAC in const.ROLE_SET and should_include_role(
        counts_dict, Role.INSOMNIAC
    ):
        # TODO check for switches and prioritize those statements
        statements += Insomniac.get_insomniac_statements(player_index, Role.INSOMNIAC)
    if Role.MASON in const.ROLE_SET and should_include_role(counts_dict, Role.MASON):
        # Only say you are a Mason if you are the last player and there are no Masons.
        if player_index == const.NUM_PLAYERS - 1 and Role.MASON not in stated_roles:
            statements += Mason.get_mason_statements(player_index, (player_index,))
    if Role.DRUNK in const.ROLE_SET and should_include_role(counts_dict, Role.DRUNK):
        statements += Drunk.get_all_statements(player_index)
    if Role.TROUBLEMAKER in const.ROLE_SET and should_include_role(
        counts_dict, Role.TROUBLEMAKER
    ):
        num_stated = len(stated_roles)
        for i in range(num_stated):
            for j in range(i + 1, num_stated):
                # Do not reference a Wolf as the second index.
                if j not in player_obj.wolf_indices:
                    statements += Troublemaker.get_troublemaker_statements(
                        player_index, i, j
                    )
    if Role.ROBBER in const.ROLE_SET and should_include_role(counts_dict, Role.ROBBER):
        for i, stated_role in enumerate(stated_roles):
            if stated_role not in (Role.NONE, Role.ROBBER):
                # Only say you robbed a Seer if the real
                # Seer did not reference a Robber.
                if stated_role is Role.SEER:
                    use_index = True
                    for _, poss_set in knowledge_base.all_statements[i].knowledge:
                        if Role.ROBBER in poss_set:
                            use_index = False
                            break
                    if not use_index:
                        continue
                statements += Robber.get_robber_statements(player_index, i, stated_role)
    if Role.SEER in const.ROLE_SET and should_include_role(counts_dict, Role.SEER):
        for i, stated_role in enumerate(stated_roles):
            # 'Hey, I'm a Seer and I saw another Seer...'
            if (
                stated_role not in (Role.NONE, Role.SEER)
                and i not in player_obj.wolf_indices
            ):
                statements += Seer.get_seer_statements(player_index, (i, stated_role))
    return statements