Esempio n. 1
0
    def test_circular_invasions(self):
        p1, p2, p3 = self.generate_players(3)
        t1, t2, t3 = self.generate_territories(owners=[p1, p2, p3])
        self.generate_troops({t1: 5, t2: 20, t3: 20})
        iset = InstructionSet()

        i1 = Movement(issuer=p1,
                      origin=t1,
                      destination=t2,
                      num_troops=4,
                      instruction_set=iset)
        i2 = Movement(issuer=p2,
                      origin=t2,
                      destination=t3,
                      num_troops=4,
                      instruction_set=iset)
        i3 = Movement(issuer=p3,
                      origin=t3,
                      destination=t1,
                      num_troops=4,
                      instruction_set=iset)

        i1.execute()

        self.assertTrue(i1.is_executed)
        self.assertTrue(i3.is_executed)
        self.assertTrue(i2.is_executed)
        # First, player 1 slays 2 troops of player 2 with 4 units, leaving 18 in territory 2 and one in territory 1.
        # Then, player 2 slays 2 troops of player 3, leaving 14 in territory 2 and 18 in territory 3.
        # Finally, player 3 slays the remaining troop of player 1 and overtakes territory 1 with one troop.
        self.assertTerritoryHasTroops(t2, 14)
        self.assertTerritoryHasTroops(t3, 14)
        self.assertTerritoryHasTroops(t1, 1)
        self.assertTerritoryOwner(t1, p3)
Esempio n. 2
0
    def test_invasion_can_be_rendered_partial_by_circular_invasions(self):
        p1, p2, p3 = self.generate_players(3)
        t1, t2, t3 = self.generate_territories(owners=[p1, p2, p3])
        self.generate_troops({t1: 5, t2: 5, t3: 5})

        iset = InstructionSet()
        i1 = Movement(issuer=p1,
                      origin=t1,
                      destination=t2,
                      num_troops=4,
                      instruction_set=iset)
        i2 = Movement(issuer=p2,
                      origin=t2,
                      destination=t3,
                      num_troops=4,
                      instruction_set=iset)
        i3 = Movement(issuer=p3,
                      origin=t3,
                      destination=t1,
                      num_troops=4,
                      instruction_set=iset)

        # At this point, all instructions are valid: 4 troops are being moved and 5 are in the territory.
        # However, due to the circular resolve, instruction 1 kills some troops from territory 2, rendering
        # instruction 2 partially valid. This should be permitted.
        i1.execute()
Esempio n. 3
0
    def test_simple_invasion_from_multiple_origins(self):
        p1, p2 = self.generate_players()
        t1, t2, t3 = self.generate_territories(owners=[p1, p1, p2])
        self.generate_troops({t1: 3, t2: 4, t3: 20})

        iset = InstructionSet()
        i1 = Movement(issuer=p1,
                      origin=t1,
                      destination=t3,
                      num_troops=2,
                      instruction_set=iset)
        Movement(issuer=p1,
                 origin=t2,
                 destination=t3,
                 num_troops=3,
                 instruction_set=iset)

        i1.execute()

        # Both movements have been executed
        self.assertTerritoryHasTroops(t1, 1)
        self.assertTerritoryHasTroops(t2, 1)

        # Invasion penalty applied only once
        self.assertTerritoryHasTroops(t3, 20 - (5 - 2))
Esempio n. 4
0
    def test_multiple_origin_skirmish_with_different_players(self):
        p1, p2, p3 = self.generate_players(3)
        t1, t2, t3 = self.generate_territories(owners=[p1, p2, p3])
        self.generate_troops({t1: 6, t2: 4, t3: 10})

        iset = InstructionSet()
        i1 = Movement(issuer=p1,
                      origin=t1,
                      destination=t3,
                      num_troops=5,
                      instruction_set=iset)
        i2 = Movement(issuer=p2,
                      origin=t2,
                      destination=t3,
                      num_troops=2,
                      instruction_set=iset)

        i1.execute()

        # There is a skirmish between Player 1 and Player 2, even though Player 3 is the one whose territory
        # is being attacked. Both troops from player 2 that were sent should be destroyed by Player 1, and
        # the remainder of Player 1's troops should trigger an invasion to Player 3's territory.
        self.assertTerritoryHasTroops(t1, 1)
        self.assertTerritoryHasTroops(t2, 2)

        # Player 1 should have 3 of its 5 units remaining that go onward to invade.
        # This means one of Player 3's troops is expected to be slain.
        self.assertTerritoryHasTroops(t3, 9)

        # In executing the first order, the second order involved in the skirmish was also executed automatically.
        self.assertTrue(i2.is_executed)
Esempio n. 5
0
    def test_mutual_invasion(self):
        p1, p2 = self.generate_players()
        t1, t2 = self.generate_territories(owners=[p1, p2])
        self.generate_troops({t1: 6, t2: 10})

        iset = InstructionSet()
        i1 = Movement(issuer=p1,
                      origin=t1,
                      destination=t2,
                      num_troops=3,
                      instruction_set=iset)
        i2 = Movement(issuer=p2,
                      origin=t2,
                      destination=t1,
                      num_troops=3,
                      instruction_set=iset)

        i1.execute()

        # The first Instruction in the mutual invasion has triggered the other Instruction as well,
        # due to the circular loop. Note that the Troop penalty should be incurred only once for each
        # Territory, hence, the second territory should have 4 Troops remaining (10 - 2 - (3-2) - 3).
        # The first territory is neutralized: 6 - 3 (invasion) - 3 (being invaded).
        self.assertTerritoryHasTroops(t1, 0)
        self.assertTerritoryHasTroops(t2, 4)
        self.assertTerritoryNeutral(t1)
        self.assertTerritoryOwner(t2, p2)
        self.assertTrue(i2.is_executed)
Esempio n. 6
0
    def test_movement_can_be_executed_only_once(self):
        p1, = self.generate_players(1)
        t1, t2 = self.generate_territories(owners=[p1])
        self.generate_troops({t1: 3})

        iset = InstructionSet()
        order = Movement(issuer=p1,
                         origin=t1,
                         destination=t2,
                         num_troops=1,
                         instruction_set=iset).execute()

        with self.assertRaises(InstructionAlreadyExecuted):
            order.execute()
Esempio n. 7
0
    def test_triple_skirmish_with_three_players(self):
        p1, p2, p3, p4 = self.generate_players(4)
        t1, t2, t3, t4 = self.generate_territories(owners=[p1, p2, p3, p4])
        self.generate_troops({t1: 6, t2: 3, t3: 10, t4: 1})

        iset = InstructionSet()

        i1 = Movement(issuer=p1,
                      origin=t1,
                      destination=t4,
                      num_troops=5,
                      instruction_set=iset)
        i2 = Movement(issuer=p2,
                      origin=t2,
                      destination=t4,
                      num_troops=2,
                      instruction_set=iset)
        i3 = Movement(issuer=p3,
                      origin=t3,
                      destination=t4,
                      num_troops=9,
                      instruction_set=iset)

        # FIXME: This test passes because we execute the instruction with the biggest army set.
        #   This should not be relevant.
        i3.execute()

        # All attackers have sent the maximum number of troops they had available.
        self.assertTerritoryHasTroops(t1, 1)
        self.assertTerritoryHasTroops(t2, 1)
        self.assertTerritoryHasTroops(t3, 1)

        # Notice that in the skirmishes, all troops are to be vanquished save 4 of Player 3's troops.
        # These 4 troops then go on to invade the single troop in t4 and take over.
        self.assertTerritoryHasTroops(t4, 1)
        self.assertTerritoryOwner(t4, p3)

        # In resolving the skirmishes, all orders are finalized.
        self.assertTrue(i1.is_executed)
        self.assertTrue(i2.is_executed)
        self.assertTrue(i3.is_executed)
Esempio n. 8
0
    def test_order_of_chain_of_invasions(self):
        p1, p2, p3 = self.generate_players(3)
        t1, t2, t3 = self.generate_territories(owners=[p1, p2, p3])
        self.generate_troops({t1: 6, t2: 6, t3: 6})

        iset = InstructionSet()
        i1 = Movement(issuer=p1,
                      origin=t1,
                      destination=t2,
                      num_troops=4,
                      instruction_set=iset)
        i2 = Movement(issuer=p2,
                      origin=t2,
                      destination=t3,
                      num_troops=4,
                      instruction_set=iset)

        i1.execute()

        self.assertTerritoryHasTroops(t1, 2)
        self.assertTrue(i1.is_executed)
        self.assertTrue(i2.is_executed)
        self.assertTerritoryHasTroops(t2, 0)
        self.assertTerritoryHasTroops(t3, 4)