def test_no_vote_dead(demo_game):

    demo_game.join(uuid())
    demo_game.join(uuid())

    other_player = uuid()
    demo_game.join(other_player)

    demo_game.start_game()

    # add a narrator too
    narrator_id = uuid()
    demo_game.join(narrator_id)
    demo_game.spectator_night_action(narrator_id)

    # 6 player game

    # Kill one of the players and set to VOTING
    player = demo_game.get_player_model(USER_ID)
    demo_game.kill_player(player.id, PlayerState.LYNCHED)
    demo_game._set_stage(GameStage.VOTING)

    # Ensure that the dead player can't see the vote button
    dead_state = WurwolvesGame(GAME_ID).parse_game_to_state(USER_ID)
    alive_state = WurwolvesGame(GAME_ID).parse_game_to_state(other_player)

    assert not dead_state.controls_state.button_visible
    assert alive_state.controls_state.button_visible
예제 #2
0
def test_start_game(db_session):
    g = WurwolvesGame(GAME_ID)
    g.join(USER_ID)
    g.join(uuid())
    g.join(uuid())

    db_game = get_game(db_session, GAME_ID)

    assert db_game.stage == GameStage.LOBBY

    p: Player
    for p in db_game.players:
        assert p.role == PlayerRole.SPECTATOR
        assert p.state == PlayerState.SPECTATING

    g.start_game()

    db_session.expire_all()

    assert db_game.stage == GameStage.NIGHT

    p: Player
    for p in db_game.players:
        assert p.role != PlayerRole.SPECTATOR
        assert p.state == PlayerState.ALIVE

    new_user_id = uuid()
    g.join(new_user_id)
    db_session.expire_all()

    p = get_player(db_session, GAME_ID, new_user_id)

    assert p.role == PlayerRole.SPECTATOR
예제 #3
0
def test_rejoin_no_change_hash(api_client, db_session):
    """
    Rejoining a game you're already in shouldn't update everyone's state
    """
    g = WurwolvesGame(GAME_ID)
    api_client.post("/api/{}/join".format(GAME_ID))
    game_hash = g.get_hash_now()
    api_client.post("/api/{}/join".format(GAME_ID))
    assert game_hash == g.get_hash_now()
def test_parse_spectator(db_session, demo_game):
    state = WurwolvesGame(GAME_ID).parse_game_to_state(USER_ID)

    json = state.json()

    assert "Welcome to Wurwolves" in json
    assert "Spectator" in state.controls_state.title
    assert state.stage == GameStage.LOBBY
    assert state.controls_state.button_enabled
예제 #5
0
def five_player_game(db_session) -> WurwolvesGame:

    g = WurwolvesGame(GAME_ID)

    # Make players
    user_ids = [uuid() for _ in range(5)]
    roles = [
        PlayerRole.WOLF,
        PlayerRole.MEDIC,
        PlayerRole.SEER,
        PlayerRole.VILLAGER,
        PlayerRole.VILLAGER,
    ]
    names = ["Wolf", "Medic", "Seer", "Villager 1", "Villager 2"]

    for i, id in enumerate(user_ids):
        g.join(id)

    g.start_game()

    # Override the roles
    for id, role, name in zip(user_ids, roles, names):
        u = g.get_player(id)
        u.role = role
        g.set_user_name(id, name)

    g._session.commit()

    roles_map = {name: user_id for name, user_id in zip(names, user_ids)}

    return g, roles_map
예제 #6
0
def test_keepalive_no_change_hash(api_client, db_session):
    g = WurwolvesGame(GAME_ID)

    api_client.post("/api/{}/join".format(GAME_ID))
    api_client.get("/api/{}/state_hash".format(GAME_ID))

    first_game_hash = g.get_hash_now()
    api_client.get("/api/{}/state_hash".format(GAME_ID))

    second_game_hash = g.get_hash_now()

    assert first_game_hash == second_game_hash
예제 #7
0
def test_single_render(api_client_factory, caplog):
    caplog.set_level(logging.DEBUG)
    caplog.set_level(logging.DEBUG, logger="sqltimings")

    num_players = 10

    clients = [api_client_factory() for _ in range(num_players)]
    rand_ids = [random.random() for _ in clients]

    # Join game
    for c, rand_id in zip(clients, rand_ids):
        response = c.post("/api/{}/join".format(GAME_ID),
                          params={"temporary_id": rand_id})

    # Send a few messages
    messages = [
        "Hello world!",
        "This is going to be fun",
        "Guys, how does the prostitute work?",
    ]
    g = WurwolvesGame(GAME_ID)
    for m in messages:
        g.send_chat_message(m)

    # Render states
    rand_id = rand_ids[0]
    c = clients[0]

    caplog.clear()

    start = time.time()
    response = c.get("/api/{}/state".format(GAME_ID),
                     params={"temporary_id": rand_id})
    total_time = time.time() - start

    render_logs = caplog.records

    render_database_times = _get_database_times(render_logs)

    assert response.ok

    logging.warning(f"total_time = {total_time:.3f}s")

    logging.warning(f"total_time = {total_time:.3f}s of which "
                    f"{sum(render_database_times):.3f}s in "
                    f"{len(render_database_times)} DB calls")

    assert total_time < 0.1
def test_parse_player(db_session, demo_game):
    demo_game.start_game()

    state = WurwolvesGame(GAME_ID).parse_game_to_state(USER_ID)

    assert state.stage == GameStage.NIGHT
    assert "Spectator" not in state.controls_state.title
예제 #9
0
    async def tester():
        initial_hash = demo_game.get_hash_now()

        task_waiter = asyncio.ensure_future(
            demo_game.get_hash(known_hash=initial_hash))

        await asyncio.sleep(0.1)
        assert not task_waiter.done()

        demo_game.get_player_model(USER_ID)

        await asyncio.sleep(0.1)
        assert not task_waiter.done()

        WurwolvesGame.set_user_name(USER_ID, "Something else")

        await asyncio.sleep(0.1)
        assert task_waiter.done()
def test_parse_new_spectator(db_session, demo_game):
    demo_game.start_game()

    u = uuid()
    demo_game.join(u)

    state = WurwolvesGame(GAME_ID).parse_game_to_state(u)

    assert "You're not playing" in state.controls_state.text
    assert "Spectator" in state.controls_state.title
    assert state.stage == GameStage.NIGHT
예제 #11
0
    def factory():
        random_id = str(uuid())
        g = WurwolvesGame(random_id)

        # You need at least three players for start_game() to work
        g.join(USER_ID)
        g.join(uuid())
        g.join(uuid())

        return g
예제 #12
0
def demo_game(db_session) -> WurwolvesGame:
    g = WurwolvesGame(GAME_ID)

    # You need at least three players for start_game() to work
    ids = [USER_ID, uuid(), uuid()]
    for i, id in enumerate(ids):
        g.join(id)
        g.set_user_name(id, f"Player {i}")

    return g
예제 #13
0
def test_end_game(api_client, db_session):
    from uuid import uuid4 as uuid

    g = WurwolvesGame(GAME_ID)

    with api_client as s:
        r = s.post(f"/api/{GAME_ID}/join")
        assert r.ok

        for _ in range(4):
            g.join(uuid())

        g.start_game()

        assert g.get_game_model().stage == GameStage.NIGHT

        r = s.post(f"/api/{GAME_ID}/end_game")
        assert r.ok

        assert g.get_game_model().stage == GameStage.ENDED
예제 #14
0
def test_name_player(db_session):
    g = WurwolvesGame(GAME_ID)
    g.join(USER_ID)

    assert len(db_session.query(User).all()) == 1
    u = db_session.query(User).filter(User.id == USER_ID).first()
    assert u.name_is_generated

    g.set_user_name(USER_ID, "Charles")
    db_session.expire_all()

    u = db_session.query(User).filter(User.id == USER_ID).first()
    assert not u.name_is_generated
    assert u.name == "Charles"
    def func(num_players):
        import random

        random.seed(123)

        g = WurwolvesGame(GAME_ID)

        # You need at least three players for start_game() to work
        g.join(USER_ID)

        for _ in range(num_players - 1):
            g.join(uuid())

        return g
예제 #16
0
def test_prostitute_prevents_seer(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    seer_id = uuid()
    prostitute_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(seer_id)
    game.join(prostitute_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    # Seer checks villager but prostitute sleeps with seer.
    # Wolf kills villager, so villager dies
    game.prostitute_night_action(prostitute_id, seer_id)
    game.seer_night_action(seer_id, villager_id)
    game.wolf_night_action(wolf_id, villager_id)

    assert game.get_player_model(villager_id).state == PlayerState.WOLFED

    summary = get_summary_of_chat(game, seer_id)

    assert re.search(r"you couldn't concentrate", summary)
예제 #17
0
def test_prostitute_saves_villager(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    prostitute_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(prostitute_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    # Prostitute sleep with villager, wolf attacks villager.
    # Villager isn't home, so doesn't die
    game.prostitute_night_action(prostitute_id, villager_id)
    game.wolf_night_action(wolf_id, villager_id)

    assert game.get_player_model(villager_id).state == PlayerState.ALIVE
예제 #18
0
def test_prostitute_prevents_medic(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    medic_id = uuid()
    prostitute_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(medic_id)
    game.join(prostitute_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    # Medic saves villager but prostitute sleeps with medic.
    # Wolf kills villager, so villager dies
    game.prostitute_night_action(prostitute_id, medic_id)
    game.medic_night_action(medic_id, villager_id)
    game.wolf_night_action(wolf_id, villager_id)

    assert game.get_player_model(villager_id).state == PlayerState.WOLFED
예제 #19
0
def test_prostitute_not_choose_self(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    medic_id = uuid()
    prostitute_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(medic_id)
    game.join(prostitute_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    # Check that the pristitute can't sleep with themselves
    with pytest.raises(HTTPException):
        game.prostitute_night_action(prostitute_id, prostitute_id)
예제 #20
0
def test_miller_works(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    seer_id = uuid()
    miller_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(seer_id)
    game.join(miller_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())

    game.start_game()
    game.seer_night_action(seer_id, miller_id)
    game.wolf_night_action(wolf_id, villager_id)

    summary = get_summary_of_chat(game, seer_id)

    assert "they are a wolf!" in summary
예제 #21
0
def test_priest_works(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    priest_id = uuid()
    villager1_id = uuid()
    villager2_id = uuid()

    game.join(wolf_id)
    game.join(priest_id)
    game.join(villager1_id)
    game.join(villager2_id)
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    with pytest.raises(HTTPException):
        game.priest_night_action(priest_id, villager1_id)
    game.wolf_night_action(wolf_id, villager1_id)

    assert game.get_player_model(villager1_id).state == PlayerState.WOLFED

    game._set_stage(GameStage.NIGHT)

    game.priest_night_action(priest_id, villager1_id)
    game.wolf_night_action(wolf_id, villager2_id)

    summary = get_summary_of_chat(game, priest_id)

    assert re.search(r"You remember that .+ was a Villager", summary)
예제 #22
0
def test_wolves_announced(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    villager_1_id = uuid()

    game.join(wolf_id)
    game.join(villager_1_id)
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    assert "There is only one wolf in the game" in get_summary_of_chat(
        game, villager_1_id)
    assert "There is only one wolf in the game" in get_summary_of_chat(
        game, wolf_id)
예제 #23
0
def test_masons_announced(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    mason_1_id = uuid()
    mason_2_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(mason_1_id)
    game.join(mason_2_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    mason_1_name = game.get_user_name(mason_1_id)
    mason_2_name = game.get_user_name(mason_2_id)

    assert f"Your fellow masons are {mason_2_name}" in get_summary_of_chat(
        game, mason_1_id)
    assert f"Your fellow masons are {mason_1_name}" in get_summary_of_chat(
        game, mason_2_id)

    assert "Your fellow masons are" not in get_summary_of_chat(game, wolf_id)
    assert "Your fellow masons are" not in get_summary_of_chat(
        game, villager_id)
예제 #24
0
def test_announced_to_wolves(mock_roles, db_session, role, search):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()

    game.join(wolf_id)
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    summary = get_summary_of_chat(game, wolf_id)

    assert f"There's {search} in the game" in summary
예제 #25
0
def test_prostitute_dooms_villager(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    prostitute_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(prostitute_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    # Prostitute sleeps with villager, wolf attacks prostitute.
    # Both die.
    game.prostitute_night_action(prostitute_id, villager_id)
    game.wolf_night_action(wolf_id, prostitute_id)

    assert game.get_player_model(villager_id).state == PlayerState.WOLFED
    assert game.get_player_model(prostitute_id).state == PlayerState.WOLFED
예제 #26
0
def test_seer_saved_no_fail(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_id = uuid()
    medic_id = uuid()
    seer_id = uuid()
    villager_id = uuid()

    game.join(wolf_id)
    game.join(medic_id)
    game.join(seer_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    game.seer_night_action(seer_id, wolf_id)
    game.wolf_night_action(wolf_id, seer_id)
    game.medic_night_action(medic_id, seer_id)

    assert game.get_player_model(seer_id).state == PlayerState.ALIVE

    summary = get_summary_of_chat(game, seer_id)

    assert re.search(r"they are a wolf", summary)
예제 #27
0
def test_prostitute_prevents_only_one_wolf_alt(mock_roles, db_session):
    game = WurwolvesGame("test_game")

    wolf_1_id = uuid()
    wolf_2_id = uuid()
    prostitute_id = uuid()
    villager_id = uuid()

    game.join(wolf_1_id)
    game.join(wolf_2_id)
    game.join(prostitute_id)
    game.join(villager_id)
    game.join(uuid())
    game.join(uuid())
    game.join(uuid())

    game.start_game()

    # Prostitute sleep with wolf 1, wolves attack villager.
    # First wolf if disabled but second wolf kills
    game.prostitute_night_action(prostitute_id, wolf_1_id)
    game.wolf_night_action(wolf_2_id, villager_id)

    assert game.get_player_model(villager_id).state == PlayerState.WOLFED
예제 #28
0
def test_name_changes_state(update_mock, db_session):
    """
    Join two players to a game and confirm that
       a) the second one joining changes the game hash and
       b) the second one changing their name changes the game hash
    """
    g = WurwolvesGame(GAME_ID)
    g.join(USER_ID)

    update_mock.assert_called()
    update_mock.reset_mock()

    game_hash_1 = g.get_game().update_tag

    new_user_id = uuid()
    g.join(new_user_id)

    update_mock.assert_called()
    update_mock.reset_mock()

    game_hash_2 = g.get_game().update_tag

    WurwolvesGame.set_user_name(new_user_id, "Stinky Smelly")

    update_mock.assert_called()
    update_mock.reset_mock()

    game_hash_3 = g.get_game().update_tag

    assert game_hash_1 != game_hash_2
    assert game_hash_1 != game_hash_3
    assert game_hash_2 != game_hash_3
예제 #29
0
def test_fool_no_mention_seer(empty_game):
    from unittest.mock import patch
    import backend
    from backend.roles import DistributionSettings

    game = WurwolvesGame("test_game")

    # Make some players in a game
    num_players = 10
    user_ids = [uuid() for _ in range(num_players)]
    [game.join(u) for u in user_ids]

    # Customise the probabilitites to get a fool
    settings = DistributionSettings(role_weights={PlayerRole.FOOL: 1000000})
    game.set_game_config(settings)

    game.start_game()

    # Find the fool (there's almost certainly one)
    fool_player = [p for p in game.get_players() if p.role == PlayerRole.FOOL]
    assert len(fool_player) == 1
    fool_id = fool_player[0].user_id

    game.set_user_name(fool_id, "The one who isn't the seer")
    game._session.commit()

    # Confirm that the fool's state doesn't mention the fool anywhere
    def fool_in_state(fool_state):
        # Unfortunately, it does in one place: the function call. A savvy user could
        # therefore cheat. I should change it so that all player actions call the
        # same function in game. The game would then pass the call on to the
        # appropriate method, depending on the player's role.
        # For now, so this test passes, remove that reference
        fool_state_filtered = fool_state.dict()
        fool_state_filtered["controls_state"]["button_submit_func"] = "removed"
        fool_state = type(fool_state).parse_obj(fool_state_filtered)

        print("Fool state:")
        from pprint import pprint

        pprint(fool_state.dict())

        return "fool" in fool_state.json().lower()

    game._set_stage(GameStage.NIGHT)
    fool_state = game.parse_game_to_state(fool_id)
    assert not fool_in_state(fool_state)

    game._set_stage(GameStage.VOTING)
    fool_state = game.parse_game_to_state(fool_id)
    assert not fool_in_state(fool_state)

    game._set_stage(GameStage.DAY)
    fool_state = game.parse_game_to_state(fool_id)
    assert not fool_in_state(fool_state)

    # Move to the end of the game and confirm that the fool is revealed
    game._set_stage(GameStage.ENDED)
    fool_state = game.parse_game_to_state(fool_id)
    assert fool_in_state(fool_state)
예제 #30
0
def empty_game(db_session) -> WurwolvesGame:
    return WurwolvesGame(GAME_ID)