Exemple #1
0
def test_get_all_possible_attacks_or_moves():
    world = P.World(P.Map.load('maps/mini.json'), ['one', 'two', 'three'],
                    has_neutral=False)
    # territory     0  1  2  3  4  5
    world.owners = [1, 0, 1, 2, 1, 1]
    world.armies = [5, 2, 2, 2, 1, 3]

    assert set(P.get_all_possible_attacks(P.PlayerState(world, 1))) == {
        P.Attack(from_, to, count)
        for from_, to, count in [
            (0, 1, 4),
            (2, 1, 1),
            (2, 3, 1),
            (5, 3, 2),
        ]
    }

    assert set(P.get_all_possible_moves(P.PlayerState(world, 1))) == {
        P.Move(from_, to, count)
        for from_, to, count in [
            (0, 2, 4),
            (2, 0, 1),
            (5, 4, 2),
        ]
    }
Exemple #2
0
def test_reinforce_error():
    map_ = P.Map.load('maps/tiny3.json')
    world = P.World(map_, ['p0', 'p1', 'neutral'], has_neutral=True)
    world.armies = [1, 1, 1]
    world.owners = [0, 0, 1]

    agent_0 = um.Mock(__str__=um.Mock(return_value='BadMockAgent'))
    state_0 = P.PlayerState(world, 0)

    # redeem
    C = P.Card
    state_0.cards = [C(2, 0), C(2, 1), C(1, 2)]
    agent_0.redeem = um.Mock(return_value=[C(2, 0), C(2, 1),
                                           C(2, 2)])  # card not owned
    with pytest.raises(ValueError) as e:
        list(P._reinforce(agent_0, state_0, um.Mock()))
    assert 'redeem' in str(e) and 'BadMockAgent' in str(e)

    agent_0.redeem = um.Mock(return_value=[C(2, 0), C(2, 1),
                                           C(1, 2)])  # not a matching set
    with pytest.raises(ValueError) as e:
        list(P._reinforce(agent_0, state_0, um.Mock()))
    assert 'redeem' in str(e) and 'BadMockAgent' in str(e)

    state_0.cards = [C(2, 0), C(2, 1), C(1, 2), C(1, 0), C(0, 1), C(0, 2)]
    agent_0.redeem = um.Mock(return_value=None)  # fail to redeem with 6 cards
    with pytest.raises(ValueError) as e:
        list(P._reinforce(agent_0, state_0, um.Mock()))
    assert 'redeem' in str(e) and 'BadMockAgent' in str(e)
    assert '6' in str(e) and '5' in str(e)

    # reinforce
    state_0.cards = []
    agent_0.redeem = um.Mock(return_value=None)

    agent_0.reinforce = um.Mock(return_value={2: 3})  # enemy territory
    with pytest.raises(ValueError) as e:
        list(P._reinforce(agent_0, state_0, um.Mock()))
    assert 'reinforce' in str(e) and 'BadMockAgent' in str(e) and '2' in str(e)

    agent_0.reinforce = um.Mock(return_value={
        0: 2,
        1: 2
    })  # selected the wrong number of reinforcements
    with pytest.raises(ValueError) as e:
        list(P._reinforce(agent_0, state_0, um.Mock()))
    assert 'reinforce' in str(e) and 'BadMockAgent' in str(e)
    assert '4' in str(e) and '3' in str(e)

    agent_0.reinforce = um.Mock(return_value={
        0: 5,
        1: -2
    })  # negative number of reinforcements
    with pytest.raises(ValueError) as e:
        list(P._reinforce(agent_0, state_0, um.Mock()))
    assert 'reinforce' in str(e) and 'BadMockAgent' in str(e)
    assert '-2' in str(e)
Exemple #3
0
def test_attack_and_move_error():
    map_ = P.Map.load('maps/tiny4.json')
    # disconnect (0, 2), so that there can be a "not connected" error
    map_.edges[0].remove(2)
    map_.edges[2].remove(0)
    world = P.World(map_, ['p0', 'p1', 'neutral'], has_neutral=True)
    world.armies = [5, 5, 3, 5]
    world.owners = [0, 0, 1, 1]

    agents = [um.Mock(), um.Mock(), None]
    states = [
        P.PlayerState(world, 0),
        P.PlayerState(world, 1),
        P.PlayerState(world, 2)
    ]
    agents_and_states = list(zip(agents, states))
    rand = um.Mock()

    for action in [
            P.Attack(0, 1, 2),  # attacking from enemy
            P.Attack(2, 3, 2),  # attacking to friendly
            P.Attack(2, 1, 3),  # attacking with too many units
            P.Attack(2, 0, 2),  # attacking to disconnected territory
            P.Attack(2, 1, 0),  # attacking with 0 or negative units
            P.Move(2, 1, 2),  # moving to enemy
            P.Move(1, 2, 2),  # moving from enemy
            P.Move(2, 3, 3),  # moving too many units
            P.Move(2, 3, 0)
    ]:  # moving 0 or negative units
        agents[1].act = um.Mock(return_value=action)
        with pytest.raises(ValueError) as e:
            list(
                P._attack_and_move(agents[1], states[1], um.Mock(),
                                   agents_and_states, rand))
        assert str(action) in str(e)

    # sanity check that a correct attack & move are indeed possible
    agents[1].act = um.Mock(side_effect=[P.Attack(2, 1, 2), P.Move(3, 2, 4)])
    rand.choices = um.Mock(return_value=[(2, 0)])  # attacker loses
    assert len(
        list(
            P._attack_and_move(agents[1], states[1], um.Mock(),
                               agents_and_states, rand))) == 2
    assert len(states[1].cards) == 0, "didn't earn a card"
    assert world.armies == [5, 5, 5, 1]
    assert world.owners == [0, 0, 1, 1]
Exemple #4
0
def test_attack_and_move():
    map_ = P.Map.load('maps/tiny3.json')
    world = P.World(map_, ['p0', 'p1', 'neutral'], has_neutral=True)
    world.owners = [0, 1, 2]
    world.armies = [5, 2, 1]

    agents = [um.Mock(), um.Mock(), None]
    states = [
        P.PlayerState(world, 0),
        P.PlayerState(world, 1, cards=[P.Card(2, 2)]),
        P.PlayerState(world, 2)
    ]
    agents_and_states = list(zip(agents, states))
    deck = um.Mock()
    rand = um.Mock()

    # 1. Don't take any action - no card earnt
    agents[0].act = um.Mock(return_value=None)
    events = list(
        P._attack_and_move(agents[0], states[0], deck, agents_and_states,
                           rand))
    assert events == [
        P.Event(agents[0], states[0], 'act', dict(earned_card=False), None)
    ]
    assert len(states[0].cards) == 0, 'no cards earnt'

    # 2. Attack (knock out Neutral) then Move
    agents[0].act = um.Mock(side_effect=[P.Attack(0, 2, 3), P.Move(2, 0, 1)])
    rand.choices = um.Mock(return_value=[(0, 1)])
    events = list(
        P._attack_and_move(agents[0], states[0], deck, agents_and_states,
                           rand))
    assert events == [
        P.Event(agents[0], states[0], 'act', dict(earned_card=False),
                P.Attack(0, 2, 3)),
        P.Event(agents[0], states[0], 'act', dict(earned_card=True),
                P.Move(2, 0, 1))
    ]
    assert len(states[0].cards) == 1, 'earnt a card'
    assert world.owners == [0, 1, 0]
    assert world.armies == [3, 2, 2]
    # dice rolls
    alternatives, probabilities = rand.choices.call_args[0]
    assert alternatives == ((0, 1), (1, 0))
    np.testing.assert_almost_equal(probabilities, [855 / 1296, 441 / 1296])

    # 3. Attack (knock out other player, claim their cards), win
    agents[0].act = um.Mock(return_value=P.Attack(0, 1, 2))
    rand.choices = um.Mock(return_value=[(0, 2)])
    with pytest.raises(P._GameOverException):
        list(
            P._attack_and_move(agents[0], states[0], deck, agents_and_states,
                               rand))
    assert world.owners == [0, 0, 0]
    assert world.armies == [1, 2, 2]
    # dice rolls
    alternatives, probabilities = rand.choices.call_args[0]
    assert alternatives == ((0, 2), (1, 1), (2, 0))
    np.testing.assert_almost_equal(probabilities,
                                   [295 / 1296, 420 / 1296, 581 / 1296])
    # cards
    assert len(
        states[0].cards
    ) == 2, 'conquered a card (haven\'t earnt one as the game ended too soon)'
    assert P.Card(2, 2) in states[0].cards
    assert len(states[1].cards) == 0, 'conquered = lost card'
    assert world.n_cards == [2, 0, 0]
Exemple #5
0
def test_reinforce():
    map_ = P.Map.load('maps/quad.json')
    tid = map_.territory_names.index
    C = P.Card
    deck = um.Mock()

    # Set up the world
    world = P.World(map_, ['p0', 'p1', 'p2'], has_neutral=False)
    for i in range(map_.n_territories):
        world.armies[i] = 1
        world.owners[i] = 2
    world.owners[tid('A4')] = 0
    world.owners[tid('B4')] = 1
    agent_0 = um.Mock()
    state_0 = P.PlayerState(world, 0)

    # 1. Minimum territory reinforcements, no continents, no sets
    agent_0.reinforce = um.Mock(return_value={tid('A4'): 3})
    events = list(P._reinforce(agent_0, state_0, deck))
    assert events == [
        P.Event(agent_0, state_0, 'reinforce', dict(count=3), {tid('A4'): 3})
    ]
    assert world.armies[tid('A4')] == 1 + 3
    assert world.sets_redeemed == 0

    # 2. Minimum territory, no continents, declaring a set
    cards = [
        C(0, tid('B1')),
        C(1, tid('B2')),
        C(2, tid('B3')),
        C(2, tid('B4'))
    ]
    cards_to_redeem = [cards[0], cards[1], cards[3]]
    state_0.cards = cards.copy()
    world.n_cards[0] = len(cards)
    agent_0.redeem = um.Mock(return_value=cards_to_redeem.copy())
    agent_0.reinforce = um.Mock(return_value={tid('A4'):
                                              7})  # 3 (territory) + 4 (set)
    events = list(P._reinforce(agent_0, state_0, deck))
    assert events == [
        P.Event(agent_0, state_0, 'redeem', {}, cards_to_redeem.copy()),
        P.Event(agent_0, state_0, 'reinforce', dict(count=7), {tid('A4'): 7})
    ]
    assert world.armies[tid('A4')] == 4 + 7
    assert world.sets_redeemed == 1
    assert world.n_cards[0] == 1
    assert state_0.cards == [C(2, tid('B3'))]
    deck.redeem.assert_called_with(cards_to_redeem)

    # 3. Multiple territory, multiple continents, declaring a set
    agent_2 = um.Mock()
    cards = [C(2, tid('A2')), C(2, tid('A3')), C(2, tid('A4'))]
    state_2 = P.PlayerState(world, 2, cards=cards)
    world.n_cards[2] = len(state_2.cards)
    agent_2.redeem = um.Mock(return_value=cards.copy())
    # Need to make 17 reinforcements: 6 (=18/3, territory) + 6 (set) + 5 (=2+3, continents)
    reinforcements = {tid('A3'): 11, tid('B5'): 6}
    agent_2.reinforce = um.Mock(return_value=reinforcements)
    events = list(P._reinforce(agent_2, state_2, deck))
    assert events == [
        P.Event(agent_2, state_2, 'redeem', {}, cards.copy()),
        P.Event(agent_2, state_2, 'reinforce', dict(count=17), reinforcements)
    ]
    assert world.armies[tid(
        'A4')] == 11, 'matches set but not owned, so unchanged'
    assert world.armies[tid('A2')] == 3, 'bonus armies'
    assert world.armies[tid(
        'A3')] == 1 + 2 + 11, 'bonus armies & reinforcements'
    assert world.armies[tid('B5')] == 1 + 6, 'reinforcements'
    assert world.sets_redeemed == 2
    assert world.n_cards[2] == 0
    assert state_2.cards == []
    deck.redeem.assert_called_with(cards)
Exemple #6
0
def _make_world(map_, agents):
    world = P.World(map_, [str(a) for a in agents],
                    isinstance(agents[-1], P._NeutralAgent))
    return world, [(agent, P.PlayerState(world, n))
                   for n, agent in enumerate(agents)]