From fe97307078ccc6491441e858cc0b74ca83a06ef8 Mon Sep 17 00:00:00 2001 From: johnpooch Date: Mon, 17 May 2021 17:34:11 +0100 Subject: [PATCH] Fix issue with can_retreat --- adjudicator/piece.py | 2 +- adjudicator/territory.py | 16 ++++++ core/tests/test_adjudicator.py | 102 +++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/adjudicator/piece.py b/adjudicator/piece.py index e2d64f3..91f6eac 100644 --- a/adjudicator/piece.py +++ b/adjudicator/piece.py @@ -123,7 +123,7 @@ def can_retreat(self): """ for territory in self.territory.neighbours: accessible = territory.accessible_by_piece_type(self) - unoccupied = not territory.occupied + unoccupied = not territory.occupied_after_processing uncontested = not territory.bounce_occurred if accessible and unoccupied and uncontested: return True diff --git a/adjudicator/territory.py b/adjudicator/territory.py index c25a600..9cbea51 100644 --- a/adjudicator/territory.py +++ b/adjudicator/territory.py @@ -1,3 +1,4 @@ +from adjudicator.decisions.base import Outcomes from . import decisions from .state import register @@ -75,6 +76,21 @@ def hold_strength(self): def occupied(self): return bool(self.piece) + @property + def occupied_after_processing(self): + """ + Whether the territory will be occupied after orders are processed. + Used to determine if pieces can retreat here. + """ + if any([p.order.outcome == Outcomes.SUCCEEDS for p in self.attacking_pieces]): + return False + if self.piece: + return not ( + (self.piece.order.is_move and self.piece.order.outcome == Outcomes.SUCCEEDS) + or (self.piece.destroyed) + ) + return False + def adjacent_to(self, territory): return territory in self.neighbours diff --git a/core/tests/test_adjudicator.py b/core/tests/test_adjudicator.py index 6983c61..44362db 100644 --- a/core/tests/test_adjudicator.py +++ b/core/tests/test_adjudicator.py @@ -23,11 +23,22 @@ def setUp(self): season=Season.SPRING, year=1900, ) + self.austria = models.Nation.objects.get(id='standard-austria-hungary') self.england = models.Nation.objects.get(id='standard-england') + self.italy = models.Nation.objects.get(id='standard-italy') self.russia = models.Nation.objects.get(id='standard-russia') self.turkey = models.Nation.objects.get(id='standard-turkey') self.patch_process_turn_apply_async() + self.adriatic_sea = models.Territory.objects.get(id='standard-adriatic-sea') + self.apulia = models.Territory.objects.get(id='standard-apulia') + self.rome = models.Territory.objects.get(id='standard-rome') + self.naples = models.Territory.objects.get(id='standard-naples') + self.piedmont = models.Territory.objects.get(id='standard-piedmont') + self.tuscany = models.Territory.objects.get(id='standard-tuscany') + self.tyrrhenian_sea = models.Territory.objects.get(id='standard-tyrrhenian-sea') + self.venice = models.Territory.objects.get(id='standard-venice') + self.livonia = models.Territory.objects.get(id='standard-livonia') self.norway = models.Territory.objects.get(id='standard-norway') self.st_petersburg = models.Territory.objects.get(id='standard-st-petersburg') @@ -357,3 +368,94 @@ def test_disband(self): self.assertEqual(order_st_petersburg.outcome, OutcomeType.SUCCEEDS) self.assertTrue(piece.turn_disbanded, self.turn) self.assertEqual(new_turn.piecestates.count(), 0) + + def test_retreat_rome_not_auto_destroy(self): + self.turn.phase = Phase.ORDER + self.turn.save() + army_rome = self.turn.piecestates.create( + piece=models.Piece.objects.create( + game=self.game, + nation=self.austria, + type=PieceType.ARMY + ), + territory=self.rome, + ) + self.turn.piecestates.create( + piece=models.Piece.objects.create( + game=self.game, + nation=self.italy, + type=PieceType.ARMY + ), + territory=self.naples, + ) + self.turn.piecestates.create( + piece=models.Piece.objects.create( + game=self.game, + nation=self.italy, + type=PieceType.FLEET + ), + territory=self.tyrrhenian_sea, + ) + army_tuscany = self.turn.piecestates.create( + piece=models.Piece.objects.create( + game=self.game, + nation=self.austria, + type=PieceType.ARMY + ), + territory=self.tuscany, + ) + self.turn.piecestates.create( + piece=models.Piece.objects.create( + game=self.game, + nation=self.austria, + type=PieceType.FLEET + ), + territory=self.apulia, + ) + self.turn.piecestates.create( + piece=models.Piece.objects.create( + game=self.game, + nation=self.austria, + type=PieceType.FLEET + ), + territory=self.venice, + ) + self.turn.orders.create( + nation=self.austria, + source=self.apulia, + target=self.adriatic_sea, + type=OrderType.MOVE, + ) + self.turn.orders.create( + nation=self.austria, + source=self.rome, + type=OrderType.HOLD, + ) + self.turn.orders.create( + nation=self.austria, + source=self.venice, + type=OrderType.HOLD, + ) + self.turn.orders.create( + nation=self.italy, + source=self.tuscany, + target=self.piedmont, + type=OrderType.MOVE, + ) + self.turn.orders.create( + nation=self.italy, + source=self.apulia, + target=self.rome, + type=OrderType.MOVE, + ) + self.turn.orders.create( + nation=self.italy, + source=self.tyrrhenian_sea, + target=self.rome, + aux=self.naples, + type=OrderType.SUPPORT, + ) + process_turn(self.turn) + army_rome.refresh_from_db() + self.assertFalse(army_rome.destroyed) + self.assertIsNone(army_rome.destroyed_message)