aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/tests/test_datc.py
diff options
context:
space:
mode:
Diffstat (limited to 'diplomacy/tests/test_datc.py')
-rw-r--r--diplomacy/tests/test_datc.py5395
1 files changed, 5395 insertions, 0 deletions
diff --git a/diplomacy/tests/test_datc.py b/diplomacy/tests/test_datc.py
new file mode 100644
index 0000000..aca8079
--- /dev/null
+++ b/diplomacy/tests/test_datc.py
@@ -0,0 +1,5395 @@
+# ==============================================================================
+# Copyright (C) 2019 - Philip Paquette
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program. If not, see <https://www.gnu.org/licenses/>.
+# ==============================================================================
+""" DATC Test Cases
+ - Contains the diplomacy adjudication test cases
+"""
+# pylint: disable=too-many-lines
+from diplomacy.engine.game import Game
+
+# -----------------
+# DATC TEST CASES
+# -----------------
+class TestDATC():
+ """ DATC test cases"""
+ # pylint: disable=too-many-public-methods
+
+ @staticmethod
+ def create_game():
+ """ Creates a game object"""
+ return Game()
+
+ @staticmethod
+ def clear_units(game):
+ """ Clears units """
+ game.clear_units()
+
+ @staticmethod
+ def clear_centers(game):
+ """ Clears supply centers """
+ game.clear_centers()
+
+ @staticmethod
+ def set_units(game, power_name, units):
+ """ Sets units on the map """
+ game.set_units(power_name, units)
+
+ @staticmethod
+ def set_centers(game, power_name, centers):
+ """ Transfers SC ownership to power """
+ game.set_centers(power_name, centers)
+
+ @staticmethod
+ def set_orders(game, power_name, orders):
+ """ Submit orders """
+ game.set_orders(power_name, orders)
+
+ @staticmethod
+ def process(game):
+ """ Processes the game """
+ # Calculating hash before
+ hash_before_1 = game.get_hash()
+ hash_before_2 = game.rebuild_hash()
+
+ # Processing
+ game.process()
+
+ # Calculating hash after
+ hash_after_1 = game.get_hash()
+ hash_after_2 = game.rebuild_hash()
+
+ # Checking
+ assert hash_before_1 == hash_before_2
+ assert hash_after_1 == hash_after_2
+
+ @staticmethod
+ def owner_name(game, unit):
+ """ Retrieves owner name """
+ has_coast = '/' in unit
+ owner = game._unit_owner(unit, coast_required=has_coast) # pylint: disable=protected-access
+ if owner is not None:
+ return owner.name
+ return None
+
+ @staticmethod
+ def check_results(game, unit, value, phase='M'):
+ """ Checks adjudication results """
+ # pylint: disable=too-many-return-statements
+ if not game:
+ return False
+
+ result = game.result_history.last_value()
+
+ # Checking if the results contain duplicate values
+ unit_result = result.get(unit, [])
+ if len(unit_result) != len(set(unit_result)):
+ raise RuntimeError('Duplicate values detected in %s' % unit_result)
+
+ # Done self.processing a retreats phase
+ if phase == 'R':
+ if value == 'void' and 'void' in unit_result:
+ return True
+ if value == '':
+ success = unit not in game.popped and unit_result == []
+ if not success:
+ print('Results: %s - Expected: []' % result.get(unit, '<Not Found>'))
+ return success
+
+ success = unit in game.popped and value in unit_result
+ if not success:
+ print('Results: %s - Expected: %s' % (result.get(unit, '<Not Found>'), value))
+ return success
+
+ # Done self.processing a retreats phase
+ if phase == 'A':
+ if value == 'void' and 'void' in unit_result:
+ return True
+ success = value == unit_result
+ if not success:
+ print('Results: %s - Expected: %s' % (result.get(unit, '<Not Found>'), value))
+ return success
+
+ order_status = game.get_order_status(unit=unit)
+
+ # Finding all ordered units
+ ordered_units = []
+ for power_name in game.ordered_units:
+ ordered_units += game.ordered_units[power_name]
+
+ # Invalid order
+ if value == 'void':
+ if 'void' in result.get(unit, []):
+ return True
+ if unit not in ordered_units:
+ return True
+ return False
+
+ # Invalid unit
+ if unit not in game.command:
+ print('Results: %s NOT FOUND - Expected: %s' % (unit, value))
+ return False
+
+ # Expected no errors
+ if value == '':
+ if order_status:
+ print('Results: %s - Expected: []' % order_status)
+ return False
+ return True
+
+ # Incorrect error
+ if value not in game.get_order_status(unit=unit):
+ print('Results: %s - Expected: %s' % (order_status, value))
+ return False
+
+ # Correct value
+ return True
+
+ @staticmethod
+ def move_to_phase(game, new_phase):
+ """ Move to a specific phase"""
+ if not game:
+ raise RuntimeError()
+ game.set_current_phase(new_phase)
+
+ # ------------- Tests --------------------
+ def test_6_a_1(self):
+ """ 6.A.1 TEST CASE, MOVING TO AN AREA THAT IS NOT A NEIGHBOUR
+ Check if an illegal move (without convoy) will fail.
+ England: F North Sea - Picardy
+ Order should fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', 'F NTH')
+ self.set_orders(game, 'ENGLAND', 'F NTH - PIC')
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'void')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F PIC') is None
+
+ def test_6_a_2(self):
+ """ 6.A.2. TEST CASE, MOVE ARMY TO SEA
+ Check if an army could not be moved to open sea.
+ England: A Liverpool - Irish Sea
+ Order should fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', 'A LVP')
+ self.set_orders(game, 'ENGLAND', 'A LVP - IRI')
+ self.process(game)
+ assert self.check_results(game, 'A LVP', 'void')
+ assert self.owner_name(game, 'A LVP') == 'ENGLAND'
+ assert self.owner_name(game, 'A IRI') is None
+
+ def test_6_a_3(self):
+ """ 6.A.3. TEST CASE, MOVE FLEET TO LAND
+ Check whether a fleet can not move to land.
+ Germany: F Kiel - Munich
+ Order should fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', 'F KIE')
+ self.set_orders(game, 'GERMANY', 'F KIE - MUN')
+ self.process(game)
+ assert self.check_results(game, 'F KIE', 'void')
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'F MUN') is None
+
+ def test_6_a_4(self):
+ """ 6.A.4. TEST CASE, MOVE TO OWN SECTOR
+ Moving to the same sector is an illegal move (2000 rulebook, page 4,
+ "An Army can be ordered to move into an adjacent inland or coastal province.").
+ Germany: F Kiel - Kiel
+ Program should not crash.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', 'F KIE')
+ self.set_orders(game, 'GERMANY', 'F KIE - KIE')
+ self.process(game)
+ assert self.check_results(game, 'F KIE', 'void')
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+
+ def test_6_a_5(self):
+ """ 6.A.5. TEST CASE, MOVE TO OWN SECTOR WITH CONVOY
+ Moving to the same sector is still illegal with convoy (2000 rulebook, page 4,
+ "Note: An Army can move across water provinces from one coastal province to another...").
+ England: F North Sea Convoys A Yorkshire - Yorkshire
+ England: A Yorkshire - Yorkshire
+ England: A Liverpool Supports A Yorkshire - Yorkshire
+ Germany: F London - Yorkshire
+ Germany: A Wales Supports F London - Yorkshire
+ The move of the army in Yorkshire is illegal. This makes the support of Liverpool also illegal and without
+ the support, the Germans have a stronger force. The army in London dislodges the army in Yorkshire.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A YOR', 'A LVP'])
+ self.set_units(game, 'GERMANY', ['F LON', 'A WAL'])
+ self.set_orders(game, 'ENGLAND', ['F LON C A YOR - YOR', 'A YOR - YOR', 'A LVP S A YOR - YOR'])
+ self.set_orders(game, 'GERMANY', ['F LON - YOR', 'A WAL S F LON - YOR'])
+ self.process(game)
+ assert self.check_results(game, 'A YOR', 'void')
+ assert self.check_results(game, 'A YOR', 'dislodged')
+ assert self.check_results(game, 'A LVP', 'void')
+ assert check_dislodged(game, 'A YOR', 'F LON')
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'A WAL', '')
+ assert self.owner_name(game, 'F YOR') == 'GERMANY'
+
+ def test_6_a_6(self):
+ """ 6.A.6. TEST CASE, ORDERING A UNIT OF ANOTHER COUNTRY
+ Check whether someone can not order a unit that is not his own unit.
+ England has a fleet in London.
+ Germany: F London - North Sea
+ Order should fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON'])
+ self.set_orders(game, 'GERMANY', ['F LON - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F LON', '')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') is None
+
+ def test_6_a_7(self):
+ """ 6.A.7. TEST CASE, ONLY ARMIES CAN BE CONVOYED
+ A fleet can not be convoyed.
+ England: F London - Belgium
+ England: F North Sea Convoys A London - Belgium
+ Move from London to Belgium should fail.
+ """
+ # -------------------------------------------
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON', 'F NTH'])
+ self.set_orders(game, 'ENGLAND', ['F LON - BEL', 'F NTH C A LON - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F LON', 'void')
+ assert self.check_results(game, 'F NTH', 'void')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F BEL') is None
+ # -------------------------------------------
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON', 'F NTH'])
+ self.set_orders(game, 'ENGLAND', ['F LON - BEL', 'F NTH C LON - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F LON', 'void')
+ assert self.check_results(game, 'F NTH', 'void')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F BEL') is None
+ # -------------------------------------------
+
+ def test_6_a_8(self):
+ """ 6.A.8. TEST CASE, SUPPORT TO HOLD YOURSELF IS NOT POSSIBLE
+ An army can not get an additional hold power by supporting itself.
+ Italy: A Venice - Trieste
+ Italy: A Tyrolia Supports A Venice - Trieste
+ Austria: F Trieste Supports F Trieste
+ The army in Trieste should be dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', ['A VEN', 'A TYR'])
+ self.set_units(game, 'AUSTRIA', 'F TRI')
+ self.set_orders(game, 'ITALY', ['A VEN - TRI', 'A TYR S A VEN - TRI'])
+ self.set_orders(game, 'AUSTRIA', 'F TRI S F TRI')
+ self.process(game)
+ assert self.check_results(game, 'F TRI', 'void')
+ assert self.check_results(game, 'F TRI', 'dislodged')
+ assert check_dislodged(game, 'F TRI', 'A VEN')
+ assert self.owner_name(game, 'A TRI') == 'ITALY'
+ assert self.owner_name(game, 'A VEN') is None
+
+ def test_6_a_9(self):
+ """ 6.A.9. TEST CASE, FLEETS MUST FOLLOW COAST IF NOT ON SEA
+ If two places are adjacent, that does not mean that a fleet can move between
+ those two places. An implementation that only holds one list of adj. places for each place, is incorrect
+ Italy: F Rome - Venice
+ Move fails. An army can go from Rome to Venice, but a fleet can not.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', 'F ROM')
+ self.set_orders(game, 'ITALY', 'F ROM - VEN')
+ self.process(game)
+ assert self.check_results(game, 'F ROM', 'void')
+ assert self.owner_name(game, 'F ROM') == 'ITALY'
+ assert self.owner_name(game, 'F VEN') is None
+
+ def test_6_a_10(self):
+ """ 6.A.10. TEST CASE, SUPPORT ON UNREACHABLE DESTINATION NOT POSSIBLE
+ The destination of the move that is supported must be reachable by the supporting unit.
+ Austria: A Venice Hold
+ Italy: F Rome Supports A Apulia - Venice
+ Italy: A Apulia - Venice
+ The support of Rome is illegal, because Venice can not be reached from Rome by a fleet.
+ Venice is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', ['F ROM', 'A APU'])
+ self.set_units(game, 'AUSTRIA', 'A VEN')
+ self.set_orders(game, 'ITALY', ['F ROM S A APU - VEN', 'A APU - VEN'])
+ self.set_orders(game, 'AUSTRIA', 'A VEN H')
+ self.process(game)
+ assert self.check_results(game, 'F ROM', 'void')
+ assert self.check_results(game, 'A APU', 'bounce')
+ assert self.owner_name(game, 'F ROM') == 'ITALY'
+ assert self.owner_name(game, 'A VEN') == 'AUSTRIA'
+
+ def test_6_a_11(self):
+ """ 6.A.11. TEST CASE, SIMPLE BOUNCE
+ Two armies bouncing on each other.
+ Austria: A Vienna - Tyrolia
+ Italy: A Venice - Tyrolia
+ The two units bounce.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', 'A VEN')
+ self.set_units(game, 'AUSTRIA', 'A VIE')
+ self.set_orders(game, 'ITALY', 'A VEN - TYR')
+ self.set_orders(game, 'AUSTRIA', 'A VIE - TYR')
+ self.process(game)
+ assert self.check_results(game, 'A VEN', 'bounce')
+ assert self.check_results(game, 'A VIE', 'bounce')
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TYR') is None
+
+ def test_6_a_12(self):
+ """ 6.A.12. TEST CASE, BOUNCE OF THREE UNITS
+ If three units move to the same place, the adjudicator should not bounce
+ the first two units and then let the third unit go to the now open place.
+ Austria: A Vienna - Tyrolia
+ Germany: A Munich - Tyrolia
+ Italy: A Venice - Tyrolia
+ The three units bounce.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', 'A VIE')
+ self.set_units(game, 'GERMANY', 'A MUN')
+ self.set_units(game, 'ITALY', 'A VEN')
+ self.set_orders(game, 'AUSTRIA', 'A VIE - TYR')
+ self.set_orders(game, 'GERMANY', 'A MUN - TYR')
+ self.set_orders(game, 'ITALY', 'A VEN - TYR')
+ self.process(game)
+ assert self.check_results(game, 'A VEN', 'bounce')
+ assert self.check_results(game, 'A VIE', 'bounce')
+ assert self.check_results(game, 'A MUN', 'bounce')
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'A TYR') is None
+
+ # 6.B. TEST CASES, COASTAL ISSUES
+ def test_6_b_1(self):
+ """ 6.B.1. TEST CASE, MOVING WITH UNSPECIFIED COAST WHEN COAST IS NECESSARY
+ Coast is significant in this case:
+ France: F Portugal - Spain
+ Some adjudicators take a default coast (see issue 4.B.1).
+ I prefer that the move fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', 'F POR')
+ self.set_orders(game, 'FRANCE', 'F POR - SPA')
+ self.process(game)
+ assert self.check_results(game, 'F POR', 'void')
+ assert self.owner_name(game, 'F POR') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+
+ def test_6_b_2(self):
+ """ 6.B.2. TEST CASE, MOVING WITH UNSPECIFIED COAST WHEN COAST IS NOT NECESSARY
+ There is only one coast possible in this case:
+ France: F Gascony - Spain
+ Since the North Coast is the only coast that can be reached, it seems logical that
+ the a move is attempted to the north coast of Spain. Some adjudicators require that a coast
+ is also specified in this case and will decide that the move fails or take a default coast (see 4.B.2).
+ I prefer that an attempt is made to the only possible coast, the north coast of Spain.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', 'F GAS')
+ self.set_orders(game, 'FRANCE', 'F GAS - SPA')
+ self.process(game)
+ assert self.check_results(game, 'F GAS', '')
+ assert self.owner_name(game, 'F GAS') is None
+ assert self.owner_name(game, 'F SPA/NC') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA/SC') is None
+
+ def test_6_b_3(self):
+ """ 6.B.3. TEST CASE, MOVING WITH WRONG COAST WHEN COAST IS NOT NECESSARY
+ If only one coast is possible, but the wrong coast can be specified.
+ France: F Gascony - Spain(sc)
+ If the rules are played very clemently, a move will be attempted to the north coast of Spain.
+ However, since this order is very clear and precise, it is more common that the move fails (see 4.B.3).
+ I prefer that the move fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', 'F GAS')
+ self.set_orders(game, 'FRANCE', 'F GAS - SPA/SC')
+ self.process(game)
+ assert self.check_results(game, 'F GAS', 'void')
+ assert self.owner_name(game, 'F GAS') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+
+ def test_6_b_4(self):
+ """ 6.B.4. TEST CASE, SUPPORT TO UNREACHABLE COAST ALLOWED
+ A fleet can give support to a coast where it can not go.
+ France: F Gascony - Spain(nc)
+ France: F Marseilles Supports F Gascony - Spain(nc)
+ Italy: F Western Mediterranean - Spain(sc)
+ Although the fleet in Marseilles can not go to the north coast it can still
+ support targeting the north coast. So, the support is successful, the move of the fleet
+ in Gasgony succeeds and the move of the Italian fleet fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F GAS', 'F MAR'])
+ self.set_units(game, 'ITALY', 'F WES')
+ self.set_orders(game, 'FRANCE', ['F GAS - SPA/NC', 'F MAR S F GAS - SPA/NC'])
+ self.set_orders(game, 'ITALY', 'F WES - SPA/SC')
+ self.process(game)
+ assert self.check_results(game, 'F WES', 'bounce')
+ assert self.owner_name(game, 'F SPA/NC') == 'FRANCE'
+ assert self.owner_name(game, 'F MAR') == 'FRANCE'
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+
+ def test_6_b_5(self):
+ """ 6.B.5. TEST CASE, SUPPORT FROM UNREACHABLE COAST NOT ALLOWED
+ A fleet can not give support to an area that can not be reached from the current coast of the fleet.
+ France: F Marseilles - Gulf of Lyon
+ France: F Spain(nc) Supports F Marseilles - Gulf of Lyon
+ Italy: F Gulf of Lyon Hold
+ The Gulf of Lyon can not be reached from the North Coast of Spain. Therefore, the support of
+ Spain is invalid and the fleet in the Gulf of Lyon is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F MAR', 'F SPA/NC'])
+ self.set_units(game, 'ITALY', 'F LYO')
+ self.set_orders(game, 'FRANCE', ['F MAR - LYO', 'F SPA/NC S F MAR - LYO'])
+ self.set_orders(game, 'ITALY', 'F LYO H')
+ self.process(game)
+ assert self.check_results(game, 'F SPA/NC', 'void')
+ assert self.check_results(game, 'F MAR', 'bounce')
+ assert self.owner_name(game, 'F MAR') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA/NC') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'ITALY'
+
+ def test_6_b_6(self):
+ """ 6.B.6. TEST CASE, SUPPORT CAN BE CUT WITH OTHER COAST
+ Support can be cut from the other coast.
+ England: F Irish Sea Supports F North Atlantic Ocean - Mid-Atlantic Ocean
+ England: F North Atlantic Ocean - Mid-Atlantic Ocean
+ France: F Spain(nc) Supports F Mid-Atlantic Ocean
+ France: F Mid-Atlantic Ocean Hold
+ Italy: F Gulf of Lyon - Spain(sc)
+ The Italian fleet in the Gulf of Lyon will cut the support in Spain. That means
+ that the French fleet in the Mid Atlantic Ocean will be dislodged by the English fleet
+ in the North Atlantic Ocean.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F IRI', 'F NAO'])
+ self.set_units(game, 'FRANCE', ['F SPA/NC', 'F MAO'])
+ self.set_units(game, 'ITALY', 'F LYO')
+ self.set_orders(game, 'ENGLAND', ['F IRI S F NAO - MAO', 'F NAO - MAO'])
+ self.set_orders(game, 'FRANCE', ['F SPA/NC S F MAO', 'F MAO H'])
+ self.set_orders(game, 'ITALY', 'F LYO - SPA/SC')
+ self.process(game)
+ assert self.check_results(game, 'F SPA/NC', 'cut')
+ assert self.check_results(game, 'F MAO', 'dislodged')
+ assert check_dislodged(game, 'F MAO', 'F NAO')
+ assert self.owner_name(game, 'F IRI') == 'ENGLAND'
+ assert self.owner_name(game, 'F NAO') is None
+ assert self.owner_name(game, 'F MAO') == 'ENGLAND'
+ assert self.owner_name(game, 'F SPA/NC') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'ITALY'
+
+ def test_6_b_7(self):
+ """ 6.B.7. TEST CASE, SUPPORTING WITH UNSPECIFIED COAST
+ Most house rules accept support orders without coast specification.
+ France: F Portugal Supports F Mid-Atlantic Ocean - Spain
+ France: F Mid-Atlantic Ocean - Spain(nc)
+ Italy: F Gulf of Lyon Supports F Western Mediterranean - Spain(sc)
+ Italy: F Western Mediterranean - Spain(sc)
+ See issue 4.B.4. If coasts are not required in support orders, then the support of Portugal is successful.
+ This means that the Italian fleet in the Western Mediterranean bounces. Some adjudicators may not accept a
+ support order without coast (the support will fail or a default coast is taken). In that case the
+ support order of Portugal fails (in case of a default coast the coast will probably the south coast) and
+ the Italian fleet in the Western Mediterranean will successfully move.
+ I prefer that the support succeeds and the Italian fleet in the Western Mediterranean bounces.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F POR', 'F MAO'])
+ self.set_units(game, 'ITALY', ['F LYO', 'F WES'])
+ self.set_orders(game, 'FRANCE', ['F POR S F MAO - SPA', 'F MAO - SPA/NC'])
+ self.set_orders(game, 'ITALY', ['F LYO S F WES - SPA/SC', 'F WES - SPA/SC'])
+ self.process(game)
+ assert self.check_results(game, 'F POR', '')
+ assert self.check_results(game, 'F LYO', '')
+ assert self.check_results(game, 'F MAO', 'bounce')
+ assert self.check_results(game, 'F WES', 'bounce')
+ assert self.owner_name(game, 'F POR') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'ITALY'
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+
+ def test_6_b_8(self):
+ """ 6.B.8. TEST CASE, SUPPORTING WITH UNSPECIFIED COAST WHEN ONLY ONE COAST IS POSSIBLE
+ Some hardliners require a coast in a support order even when only one coast is possible.
+ France: F Portugal Supports F Gascony - Spain
+ France: F Gascony - Spain(nc)
+ Italy: F Gulf of Lyon Supports F Western Mediterranean - Spain(sc)
+ Italy: F Western Mediterranean - Spain(sc)
+ See issue 4.B.4. If coasts are not required in support orders, then the support of Portugal is successful.
+ This means that the Italian fleet in the Western Mediterranean bounces. Some adjudicators may not accept a
+ support order without coast (the support will fail or a default coast is taken). In that case the
+ support order of Portugal fails (in case of a default coast the coast will probably the south coast) and
+ the Italian fleet in the Western Mediterranean will successfully move.
+ I prefer that supporting without coasts should be allowed. So I prefer that the support of Portugal
+ is successful and that the Italian fleet in the Western Mediterranean bounces.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F POR', 'F GAS'])
+ self.set_units(game, 'ITALY', ['F LYO', 'F WES'])
+ self.set_orders(game, 'FRANCE', ['F POR S F GAS - SPA', 'F GAS - SPA/NC'])
+ self.set_orders(game, 'ITALY', ['F LYO S F WES - SPA/SC', 'F WES - SPA/SC'])
+ self.process(game)
+ assert self.check_results(game, 'F POR', '')
+ assert self.check_results(game, 'F LYO', '')
+ assert self.check_results(game, 'F GAS', 'bounce')
+ assert self.check_results(game, 'F WES', 'bounce')
+ assert self.owner_name(game, 'F POR') == 'FRANCE'
+ assert self.owner_name(game, 'F GAS') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'ITALY'
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+
+ def test_6_b_9(self):
+ """ 6.B.9. TEST CASE, SUPPORTING WITH WRONG COAST
+ Coasts can be specified in a support, but the result depends on the house rules.
+ France: F Portugal Supports F Mid-Atlantic Ocean - Spain(nc)
+ France: F Mid-Atlantic Ocean - Spain(sc)
+ Italy: F Gulf of Lyon Supports F Western Mediterranean - Spain(sc)
+ Italy: F Western Mediterranean - Spain(sc)
+ See issue 4.B.4. If it is required that the coast matches, then the support of the French fleet in the
+ Mid-Atlantic Ocean fails and that the Italian fleet in the Western Mediterranean moves successfully. Some
+ adjudicators ignores the coasts in support orders. In that case, the move of the Italian fleet bounces.
+ I prefer that the support fails and that the Italian fleet in the Western Mediterranean moves successfully.
+ """
+ # Order expansion will rewrite F POR S F MAO - SPA/NC -> F POR S F MAO - SPA/SC
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F POR', 'F MAO'])
+ self.set_units(game, 'ITALY', ['F LYO', 'F WES'])
+ self.set_orders(game, 'FRANCE', ['F POR S F MAO - SPA/NC', 'F MAO - SPA/SC'])
+ self.set_orders(game, 'ITALY', ['F LYO S F WES - SPA/SC', 'F WES - SPA/SC'])
+ self.process(game)
+ assert self.check_results(game, 'F POR', '')
+ assert self.check_results(game, 'F MAO', 'bounce')
+ assert self.check_results(game, 'F LYO', '')
+ assert self.check_results(game, 'F WES', 'bounce')
+ assert self.owner_name(game, 'F POR') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F LYO') == 'ITALY'
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+
+ def test_6_b_10(self):
+ """ 6.B.10. TEST CASE, UNIT ORDERED WITH WRONG COAST
+ A player might specify the wrong coast for the ordered unit.
+ France has a fleet on the south coast of Spain and orders:
+ France: F Spain(nc) - Gulf of Lyon
+ If only perfect orders are accepted, then the move will fail, but since the coast for the ordered unit
+ has no purpose, it might also be ignored (see issue 4.B.5).
+ I prefer that a move will be attempted.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', 'F SPA/SC')
+ self.set_orders(game, 'FRANCE', 'F SPA/NC - LYO')
+ self.process(game)
+ assert self.check_results(game, 'F SPA/SC', '')
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F LYO') == 'FRANCE'
+
+ def test_6_b_11(self):
+ """ 6.B.11. TEST CASE, COAST CAN NOT BE ORDERED TO CHANGE
+ The coast can not change by just ordering the other coast.
+ France has a fleet on the north coast of Spain and orders:
+ France: F Spain(sc) - Gulf of Lyon
+ The move fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', 'F SPA/NC')
+ self.set_orders(game, 'FRANCE', 'F SPA/SC - LYO')
+ self.process(game)
+ assert self.check_results(game, 'F SPA/SC', 'void')
+ assert self.owner_name(game, 'F SPA') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA/NC') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F LYO') is None
+
+ def test_6_b_12(self):
+ """ 6.B.12. TEST CASE, ARMY MOVEMENT WITH COASTAL SPECIFICATION
+ For armies the coasts are irrelevant:
+ France: A Gascony - Spain(nc)
+ If only perfect orders are accepted, then the move will fail. But it is also possible that coasts are
+ ignored in this case and a move will be attempted (see issue 4.B.6).
+ I prefer that a move will be attempted.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', 'A GAS')
+ self.set_orders(game, 'FRANCE', 'A GAS - SPA/NC')
+ self.process(game)
+ assert self.check_results(game, 'A GAS', '')
+ assert self.owner_name(game, 'A GAS') is None
+ assert self.owner_name(game, 'A SPA') == 'FRANCE'
+ assert self.owner_name(game, 'A SPA/NC') is None
+ assert self.owner_name(game, 'A SPA/SC') is None
+
+ def test_6_b_13(self):
+ """ 6.B.13. TEST CASE, COASTAL CRAWL NOT ALLOWED
+ If a fleet is leaving a sector from a certain coast while in the opposite direction another fleet
+ is moving to another coast of the sector, it is still a head to head battle. This has been decided in
+ the great revision of the 1961 rules that resulted in the 1971 rules.
+ Turkey: F Bulgaria(sc) - Constantinople
+ Turkey: F Constantinople - Bulgaria(ec)
+ Both moves fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'TURKEY', ['F BUL/SC', 'F CON'])
+ self.set_orders(game, 'TURKEY', ['F BUL/SC - CON', 'F CON - BUL/EC'])
+ self.process(game)
+ assert self.check_results(game, 'F BUL/SC', 'bounce')
+ assert self.check_results(game, 'F CON', 'bounce')
+ assert self.owner_name(game, 'F BUL/SC') == 'TURKEY'
+ assert self.owner_name(game, 'F CON') == 'TURKEY'
+ assert self.owner_name(game, 'F BUL/EC') is None
+
+ def test_6_b_14(self):
+ """ 6.B.14. TEST CASE, BUILDING WITH UNSPECIFIED COAST
+ Coast must be specified in certain build cases:
+ Russia: Build F St Petersburg
+ If no default coast is taken (see issue 4.B.7), the build fails.
+ I do not like default coast, so I prefer that the build fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_centers(game, 'RUSSIA', 'STP')
+ self.move_to_phase(game, 'W1901A')
+ self.set_orders(game, 'RUSSIA', 'F STP B')
+ self.process(game)
+ assert self.check_results(game, 'F STP', 'void', phase='A')
+ assert self.owner_name(game, 'F STP') is None
+ assert self.owner_name(game, 'F STP/SC') is None
+ assert self.owner_name(game, 'F STP/NC') is None
+
+ # 6.C. TEST CASES, CIRCULAR MOVEMENT
+ def test_6_c_1(self):
+ """ 6.C.1. TEST CASE, THREE ARMY CIRCULAR MOVEMENT
+ Three units can change place, even in spring 1901.
+ Turkey: F Ankara - Constantinople
+ Turkey: A Constantinople - Smyrna
+ Turkey: A Smyrna - Ankara
+ All three units will move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'TURKEY', ['F ANK', 'A CON', 'A SMY'])
+ self.set_orders(game, 'TURKEY', ['F ANK - CON', 'A CON - SMY', 'A SMY - ANK'])
+ self.process(game)
+ assert self.check_results(game, 'F ANK', '')
+ assert self.check_results(game, 'A CON', '')
+ assert self.check_results(game, 'A SMY', '')
+ assert self.owner_name(game, 'A ANK') == 'TURKEY'
+ assert self.owner_name(game, 'F CON') == 'TURKEY'
+ assert self.owner_name(game, 'A SMY') == 'TURKEY'
+
+ def test_6_c_2(self):
+ """ 6.C.2. TEST CASE, THREE ARMY CIRCULAR MOVEMENT WITH SUPPORT
+ Three units can change place, even when one gets support.
+ Turkey: F Ankara - Constantinople
+ Turkey: A Constantinople - Smyrna
+ Turkey: A Smyrna - Ankara
+ Turkey: A Bulgaria Supports F Ankara - Constantinople
+ Of course the three units will move, but knowing how programs are written, this can confuse the adjudicator.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'TURKEY', ['F ANK', 'A CON', 'A SMY', 'A BUL'])
+ self.set_orders(game, 'TURKEY', ['F ANK - CON', 'A CON - SMY', 'A SMY - ANK', 'A BUL S F ANK - CON'])
+ self.process(game)
+ assert self.check_results(game, 'F ANK', '')
+ assert self.check_results(game, 'A CON', '')
+ assert self.check_results(game, 'A SMY', '')
+ assert self.check_results(game, 'A BUL', '')
+ assert self.owner_name(game, 'A ANK') == 'TURKEY'
+ assert self.owner_name(game, 'F CON') == 'TURKEY'
+ assert self.owner_name(game, 'A SMY') == 'TURKEY'
+ assert self.owner_name(game, 'A BUL') == 'TURKEY'
+
+ def test_6_c_3(self):
+ """ 6.C.3. TEST CASE, A DISRUPTED THREE ARMY CIRCULAR MOVEMENT
+ When one of the units bounces, the whole circular movement will hold.
+ Turkey: F Ankara - Constantinople
+ Turkey: A Constantinople - Smyrna
+ Turkey: A Smyrna - Ankara
+ Turkey: A Bulgaria - Constantinople
+ Every unit will keep its place.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'TURKEY', ['F ANK', 'A CON', 'A SMY', 'A BUL'])
+ self.set_orders(game, 'TURKEY', ['F ANK - CON', 'A CON - SMY', 'A SMY - ANK', 'A BUL - CON'])
+ self.process(game)
+ assert self.check_results(game, 'F ANK', 'bounce')
+ assert self.check_results(game, 'A CON', 'bounce')
+ assert self.check_results(game, 'A SMY', 'bounce')
+ assert self.check_results(game, 'A BUL', 'bounce')
+ assert self.owner_name(game, 'F ANK') == 'TURKEY'
+ assert self.owner_name(game, 'A CON') == 'TURKEY'
+ assert self.owner_name(game, 'A SMY') == 'TURKEY'
+ assert self.owner_name(game, 'A BUL') == 'TURKEY'
+
+ def test_6_c_4(self):
+ """ 6.C.4. TEST CASE, A CIRCULAR MOVEMENT WITH ATTACKED CONVOY
+ When the circular movement contains an attacked convoy, the circular movement succeeds.
+ The adjudication algorithm should handle attack of convoys before calculating circular movement.
+ Austria: A Trieste - Serbia
+ Austria: A Serbia - Bulgaria
+ Turkey: A Bulgaria - Trieste
+ Turkey: F Aegean Sea Convoys A Bulgaria - Trieste
+ Turkey: F Ionian Sea Convoys A Bulgaria - Trieste
+ Turkey: F Adriatic Sea Convoys A Bulgaria - Trieste
+ Italy: F Naples - Ionian Sea
+ The fleet in the Ionian Sea is attacked but not dislodged. The circular movement succeeds.
+ The Austrian and Turkish armies will advance.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['A TRI', 'A SER'])
+ self.set_units(game, 'TURKEY', ['A BUL', 'F AEG', 'F ION', 'F ADR'])
+ self.set_units(game, 'ITALY', 'F NAP')
+ self.set_orders(game, 'AUSTRIA', ['A TRI - SER', 'A SER - BUL'])
+ self.set_orders(game, 'TURKEY', ['A BUL - TRI', 'F AEG C A BUL - TRI', 'F ION C A BUL - TRI',
+ 'F ADR C A BUL - TRI'])
+ self.set_orders(game, 'ITALY', 'F NAP - ION')
+ self.process(game)
+ assert self.check_results(game, 'A TRI', '')
+ assert self.check_results(game, 'A SER', '')
+ assert self.check_results(game, 'A BUL', '')
+ assert self.check_results(game, 'F AEG', '')
+ assert self.check_results(game, 'F ION', '')
+ assert self.check_results(game, 'F ADR', '')
+ assert self.check_results(game, 'F NAP', 'bounce')
+ assert self.owner_name(game, 'A TRI') == 'TURKEY'
+ assert self.owner_name(game, 'A SER') == 'AUSTRIA'
+ assert self.owner_name(game, 'A BUL') == 'AUSTRIA'
+ assert self.owner_name(game, 'F AEG') == 'TURKEY'
+ assert self.owner_name(game, 'F ION') == 'TURKEY'
+ assert self.owner_name(game, 'F ADR') == 'TURKEY'
+ assert self.owner_name(game, 'F NAP') == 'ITALY'
+
+ def test_6_c_5(self):
+ """ 6.C.5. TEST CASE, A DISRUPTED CIRCULAR MOVEMENT DUE TO DISLODGED CONVOY
+ When the circular movement contains a convoy, the circular movement is disrupted when the convoying
+ fleet is dislodged. The adjudication algorithm should disrupt convoys before calculating circular movement.
+ Austria: A Trieste - Serbia
+ Austria: A Serbia - Bulgaria
+ Turkey: A Bulgaria - Trieste
+ Turkey: F Aegean Sea Convoys A Bulgaria - Trieste
+ Turkey: F Ionian Sea Convoys A Bulgaria - Trieste
+ Turkey: F Adriatic Sea Convoys A Bulgaria - Trieste
+ Italy: F Naples - Ionian Sea
+ Italy: F Tunis Supports F Naples - Ionian Sea
+ Due to the dislodged convoying fleet, all Austrian and Turkish armies will not move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['A TRI', 'A SER'])
+ self.set_units(game, 'TURKEY', ['A BUL', 'F AEG', 'F ION', 'F ADR'])
+ self.set_units(game, 'ITALY', ['F NAP', 'F TUN'])
+ self.set_orders(game, 'AUSTRIA', ['A TRI - SER', 'A SER - BUL'])
+ self.set_orders(game, 'TURKEY', ['A BUL - TRI', 'F AEG C A BUL - TRI', 'F ION C A BUL - TRI',
+ 'F ADR C A BUL - TRI'])
+ self.set_orders(game, 'ITALY', ['F NAP - ION', 'F TUN S F NAP - ION'])
+ self.process(game)
+ assert self.check_results(game, 'A TRI', 'bounce')
+ assert self.check_results(game, 'A SER', 'bounce')
+ assert self.check_results(game, 'A BUL', 'no convoy')
+ assert self.check_results(game, 'F AEG', 'no convoy')
+ assert self.check_results(game, 'F ION', 'dislodged')
+ assert self.check_results(game, 'F ADR', 'no convoy')
+ assert self.check_results(game, 'F NAP', '')
+ assert self.check_results(game, 'F TUN', '')
+ assert check_dislodged(game, 'F ION', 'F NAP')
+ assert self.owner_name(game, 'A TRI') == 'AUSTRIA'
+ assert self.owner_name(game, 'A SER') == 'AUSTRIA'
+ assert self.owner_name(game, 'A BUL') == 'TURKEY'
+ assert self.owner_name(game, 'F AEG') == 'TURKEY'
+ assert self.owner_name(game, 'F ION') == 'ITALY'
+ assert self.owner_name(game, 'F ADR') == 'TURKEY'
+ assert self.owner_name(game, 'F NAP') is None
+ assert self.owner_name(game, 'F TUN') == 'ITALY'
+
+ def test_6_c_6(self):
+ """ 6.C.6. TEST CASE, TWO ARMIES WITH TWO CONVOYS
+ Two armies can swap places even when they are not adjacent.
+ England: F North Sea Convoys A London - Belgium
+ England: A London - Belgium
+ France: F English Channel Convoys A Belgium - London
+ France: A Belgium - London
+ Both convoys should succeed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'FRANCE', ['F ENG', 'A BEL'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - BEL', 'A LON - BEL'])
+ self.set_orders(game, 'FRANCE', ['F ENG C A BEL - LON', 'A BEL - LON'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A BEL', '')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A LON') == 'FRANCE'
+
+ def test_6_c_7(self):
+ """ 6.C.7. TEST CASE, DISRUPTED UNIT SWAP
+ If in a swap one of the unit bounces, then the swap fails.
+ England: F North Sea Convoys A London - Belgium
+ England: A London - Belgium
+ France: F English Channel Convoys A Belgium - London
+ France: A Belgium - London
+ France: A Burgundy - Belgium
+ None of the units will succeed to move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'FRANCE', ['F ENG', 'A BEL', 'A BUR'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - BEL', 'A LON - BEL'])
+ self.set_orders(game, 'FRANCE', ['F ENG C A BEL - LON', 'A BEL - LON', 'A BUR - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A LON', 'bounce')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A BEL', 'bounce')
+ assert self.check_results(game, 'A BUR', 'bounce')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A BEL') == 'FRANCE'
+ assert self.owner_name(game, 'A BUR') == 'FRANCE'
+
+ # 6.D. TEST CASES, SUPPORTS AND DISLODGES
+ def test_6_d_1(self):
+ """ 6.D.1. TEST CASE, SUPPORTED HOLD CAN PREVENT DISLODGEMENT
+ The most simple support to hold order.
+ Austria: F Adriatic Sea Supports A Trieste - Venice
+ Austria: A Trieste - Venice
+ Italy: A Venice Hold
+ Italy: A Tyrolia Supports A Venice
+ The support of Tyrolia prevents that the army in Venice is dislodged. The army in Trieste will not move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F ADR', 'A TRI'])
+ self.set_units(game, 'ITALY', ['A VEN', 'A TYR'])
+ self.set_orders(game, 'AUSTRIA', ['F ADR S A TRI - VEN', 'A TRI - VEN'])
+ self.set_orders(game, 'ITALY', ['A VEN H', 'A TYR S A VEN'])
+ self.process(game)
+ assert self.check_results(game, 'F ADR', '')
+ assert self.check_results(game, 'A TRI', 'bounce')
+ assert self.check_results(game, 'A VEN', '')
+ assert self.check_results(game, 'A TYR', '')
+ assert self.owner_name(game, 'F ADR') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'A TYR') == 'ITALY'
+
+ def test_6_d_2(self):
+ """ 6.D.2. TEST CASE, A MOVE CUTS SUPPORT ON HOLD
+ The most simple support on hold cut.
+ Austria: F Adriatic Sea Supports A Trieste - Venice
+ Austria: A Trieste - Venice
+ Austria: A Vienna - Tyrolia
+ Italy: A Venice Hold
+ Italy: A Tyrolia Supports A Venice
+ The support of Tyrolia is cut by the army in Vienna. That means that the army in Venice is dislodged by the
+ army from Trieste.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F ADR', 'A TRI', 'A VIE'])
+ self.set_units(game, 'ITALY', ['A VEN', 'A TYR'])
+ self.set_orders(game, 'AUSTRIA', ['F ADR S A TRI - VEN', 'A TRI - VEN', 'A VIE - TYR'])
+ self.set_orders(game, 'ITALY', ['A VEN H', 'A TYR S A VEN'])
+ self.process(game)
+ assert self.check_results(game, 'F ADR', '')
+ assert self.check_results(game, 'A TRI', '')
+ assert self.check_results(game, 'A VIE', 'bounce')
+ assert self.check_results(game, 'A VEN', 'dislodged')
+ assert self.check_results(game, 'A TYR', 'cut')
+ assert check_dislodged(game, 'A VEN', 'A TRI')
+ assert self.owner_name(game, 'F ADR') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') is None
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VEN') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TYR') == 'ITALY'
+
+ def test_6_d_3(self):
+ """ 6.D.3. TEST CASE, A MOVE CUTS SUPPORT ON MOVE
+ The most simple support on move cut.
+ Austria: F Adriatic Sea Supports A Trieste - Venice
+ Austria: A Trieste - Venice
+ Italy: A Venice Hold
+ Italy: F Ionian Sea - Adriatic Sea
+ The support of the fleet in the Adriatic Sea is cut. That means that the army in Venice will not be
+ dislodged and the army in Trieste stays in Trieste.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F ADR', 'A TRI'])
+ self.set_units(game, 'ITALY', ['A VEN', 'F ION'])
+ self.set_orders(game, 'AUSTRIA', ['F ADR S A TRI - VEN', 'A TRI - VEN'])
+ self.set_orders(game, 'ITALY', ['A VEN H', 'F ION - ADR'])
+ self.process(game)
+ assert self.check_results(game, 'F ADR', 'cut')
+ assert self.check_results(game, 'A TRI', 'bounce')
+ assert self.check_results(game, 'A VEN', '')
+ assert self.check_results(game, 'F ION', 'bounce')
+ assert self.owner_name(game, 'F ADR') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'F ION') == 'ITALY'
+
+ def test_6_d_4(self):
+ """ 6.D.4. TEST CASE, SUPPORT TO HOLD ON UNIT SUPPORTING A HOLD ALLOWED
+ A unit that is supporting a hold, can receive a hold support.
+ Germany: A Berlin Supports F Kiel
+ Germany: F Kiel Supports A Berlin
+ Russia: F Baltic Sea Supports A Prussia - Berlin
+ Russia: A Prussia - Berlin
+ The Russian move from Prussia to Berlin fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE'])
+ self.set_units(game, 'RUSSIA', ['F BAL', 'A PRU'])
+ self.set_orders(game, 'GERMANY', ['A BER S F KIE', 'F KIE S A BER'])
+ self.set_orders(game, 'RUSSIA', ['F BAL S A PRU - BER', 'A PRU - BER'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', 'cut')
+ assert self.check_results(game, 'F KIE', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'A PRU', 'bounce')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+ assert self.owner_name(game, 'A PRU') == 'RUSSIA'
+
+ def test_6_d_5(self):
+ """ 6.D.5. TEST CASE, SUPPORT TO HOLD ON UNIT SUPPORTING A MOVE ALLOWED
+ A unit that is supporting a move, can receive a hold support.
+ Germany: A Berlin Supports A Munich - Silesia
+ Germany: F Kiel Supports A Berlin
+ Germany: A Munich - Silesia
+ Russia: F Baltic Sea Supports A Prussia - Berlin
+ Russia: A Prussia - Berlin
+ The Russian move from Prussia to Berlin fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE', 'A MUN'])
+ self.set_units(game, 'RUSSIA', ['F BAL', 'A PRU'])
+ self.set_orders(game, 'GERMANY', ['A BER S A MUN - SIL', 'F KIE S A BER', 'A MUN - SIL'])
+ self.set_orders(game, 'RUSSIA', ['F BAL S A PRU - BER', 'A PRU - BER'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', 'cut')
+ assert self.check_results(game, 'F KIE', '')
+ assert self.check_results(game, 'A MUN', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'A PRU', 'bounce')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') is None
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+ assert self.owner_name(game, 'A PRU') == 'RUSSIA'
+ assert self.owner_name(game, 'A SIL') == 'GERMANY'
+
+ def test_6_d_6(self):
+ """ 6.D.6. TEST CASE, SUPPORT TO HOLD ON CONVOYING UNIT ALLOWED
+ A unit that is convoying, can receive a hold support.
+ Germany: A Berlin - Sweden
+ Germany: F Baltic Sea Convoys A Berlin - Sweden
+ Germany: F Prussia Supports F Baltic Sea
+ Russia: F Livonia - Baltic Sea
+ Russia: F Gulf of Bothnia Supports F Livonia - Baltic Sea
+ The Russian move from Livonia to the Baltic Sea fails. The convoy from Berlin to Sweden succeeds.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F BAL', 'F PRU'])
+ self.set_units(game, 'RUSSIA', ['F LVN', 'F BOT'])
+ self.set_orders(game, 'GERMANY', ['A BER - SWE', 'F BAL C A BER - SWE', 'F PRU S F BAL'])
+ self.set_orders(game, 'RUSSIA', ['F LVN - BAL', 'F BOT S F LVN - BAL'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'F PRU', '')
+ assert self.check_results(game, 'F LVN', 'bounce')
+ assert self.check_results(game, 'F BOT', '')
+ assert self.owner_name(game, 'A BER') is None
+ assert self.owner_name(game, 'F BAL') == 'GERMANY'
+ assert self.owner_name(game, 'F PRU') == 'GERMANY'
+ assert self.owner_name(game, 'F LVN') == 'RUSSIA'
+ assert self.owner_name(game, 'F BOT') == 'RUSSIA'
+ assert self.owner_name(game, 'A SWE') == 'GERMANY'
+
+ def test_6_d_7(self):
+ """ 6.D.7. TEST CASE, SUPPORT TO HOLD ON MOVING UNIT NOT ALLOWED
+ A unit that is moving, can not receive a hold support for the situation that the move fails.
+ Germany: F Baltic Sea - Sweden
+ Germany: F Prussia Supports F Baltic Sea
+ Russia: F Livonia - Baltic Sea
+ Russia: F Gulf of Bothnia Supports F Livonia - Baltic Sea
+ Russia: A Finland - Sweden
+ The support of the fleet in Prussia fails. The fleet in Baltic Sea will bounce on the Russian army
+ in Finland and will be dislodged by the Russian fleet from Livonia when it returns to the Baltic Sea.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['F BAL', 'F PRU'])
+ self.set_units(game, 'RUSSIA', ['F LVN', 'F BOT', 'A FIN'])
+ self.set_orders(game, 'GERMANY', ['F BAL - SWE', 'F PRU S F BAL'])
+ self.set_orders(game, 'RUSSIA', ['F LVN - BAL', 'F BOT S F LVN - BAL', 'A FIN - SWE'])
+ self.process(game)
+ assert self.check_results(game, 'F BAL', 'bounce')
+ assert self.check_results(game, 'F BAL', 'dislodged')
+ assert self.check_results(game, 'F PRU', 'void')
+ assert self.check_results(game, 'F LVN', '')
+ assert self.check_results(game, 'F BOT', '')
+ assert self.check_results(game, 'A FIN', 'bounce')
+ assert check_dislodged(game, 'F BAL', 'F LVN')
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+ assert self.owner_name(game, 'F PRU') == 'GERMANY'
+ assert self.owner_name(game, 'F LVN') is None
+ assert self.owner_name(game, 'F BOT') == 'RUSSIA'
+ assert self.owner_name(game, 'A FIN') == 'RUSSIA'
+ assert self.owner_name(game, 'A SWE') is None
+
+ def test_6_d_8(self):
+ """ 6.D.8. TEST CASE, FAILED CONVOY CAN NOT RECEIVE HOLD SUPPORT
+ If a convoy fails because of disruption of the convoy or when the right convoy orders are not given,
+ then the army to be convoyed can not receive support in hold, since it still tried to move.
+ Austria: F Ionian Sea Hold
+ Austria: A Serbia Supports A Albania - Greece
+ Austria: A Albania - Greece
+ Turkey: A Greece - Naples
+ Turkey: A Bulgaria Supports A Greece
+ There was a possible convoy from Greece to Naples, before the orders were made public (via the Ionian Sea).
+ This means that the order of Greece to Naples should never be treated as illegal order and be changed in a
+ hold order able to receive hold support (see also issue VI.A). Therefore, the support in Bulgaria fails and
+ the army in Greece is dislodged by the army in Albania.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F ION', 'A SER', 'A ALB'])
+ self.set_units(game, 'TURKEY', ['A GRE', 'A BUL'])
+ self.set_orders(game, 'AUSTRIA', ['F ION H', 'A SER S A ALB - GRE', 'A ALB - GRE'])
+ self.set_orders(game, 'TURKEY', ['A GRE - NAP', 'A BUL S A GRE'])
+ self.process(game)
+ assert self.check_results(game, 'F ION', '')
+ assert self.check_results(game, 'A SER', '')
+ assert self.check_results(game, 'A ALB', '')
+ assert self.check_results(game, 'A GRE', 'dislodged')
+ assert self.check_results(game, 'A BUL', 'void')
+ assert check_dislodged(game, 'A GRE', 'A ALB')
+ assert self.owner_name(game, 'F ION') == 'AUSTRIA'
+ assert self.owner_name(game, 'A SER') == 'AUSTRIA'
+ assert self.owner_name(game, 'A ALB') is None
+ assert self.owner_name(game, 'A GRE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A BUL') == 'TURKEY'
+
+ def test_6_d_9(self):
+ """ 6.D.9. TEST CASE, SUPPORT TO MOVE ON HOLDING UNIT NOT ALLOWED
+ A unit that is holding can not receive a support in moving.
+ Italy: A Venice - Trieste
+ Italy: A Tyrolia Supports A Venice - Trieste
+ Austria: A Albania Supports A Trieste - Serbia
+ Austria: A Trieste Hold
+ The support of the army in Albania fails and the army in Trieste is dislodged by the army from Venice.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', ['A VEN', 'A TYR'])
+ self.set_units(game, 'AUSTRIA', ['A ALB', 'A TRI'])
+ self.set_orders(game, 'ITALY', ['A VEN - TRI', 'A TYR S A VEN - TRI'])
+ self.set_orders(game, 'AUSTRIA', ['A ALB S A TRI - SER', 'A TRI H'])
+ self.process(game)
+ assert self.check_results(game, 'A VEN', '')
+ assert self.check_results(game, 'A TYR', '')
+ assert self.check_results(game, 'A ALB', 'void')
+ assert self.check_results(game, 'A TRI', 'dislodged')
+ assert check_dislodged(game, 'A TRI', 'A VEN')
+ assert self.owner_name(game, 'A VEN') is None
+ assert self.owner_name(game, 'A TYR') == 'ITALY'
+ assert self.owner_name(game, 'A ALB') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') == 'ITALY'
+
+ def test_6_d_10(self):
+ """ 6.D.10. TEST CASE, SELF DISLODGMENT PROHIBITED
+ A unit may not dislodge a unit of the same great power.
+ Germany: A Berlin Hold
+ Germany: F Kiel - Berlin
+ Germany: A Munich Supports F Kiel - Berlin
+ Move to Berlin fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE', 'A MUN'])
+ self.set_orders(game, 'GERMANY', ['A BER H', 'F KIE - BER', 'A MUN S F KIE - BER'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', '')
+ assert self.check_results(game, 'F KIE', 'bounce')
+ assert self.check_results(game, 'A MUN', 'void')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+
+ def test_6_d_11(self):
+ """ 6.D.11. TEST CASE, NO SELF DISLODGMENT OF RETURNING UNIT
+ Idem.
+ Germany: A Berlin - Prussia
+ Germany: F Kiel - Berlin
+ Germany: A Munich Supports F Kiel - Berlin
+ Russia: A Warsaw - Prussia
+ Army in Berlin bounces, but is not dislodged by own unit.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE', 'A MUN'])
+ self.set_units(game, 'RUSSIA', 'A WAR')
+ self.set_orders(game, 'GERMANY', ['A BER - PRU', 'F KIE - BER', 'A MUN S F KIE - BER'])
+ self.set_orders(game, 'RUSSIA', ['A WAR - PRU'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', 'bounce')
+ assert self.check_results(game, 'F KIE', 'bounce')
+ assert self.check_results(game, 'A MUN', 'void')
+ assert self.check_results(game, 'A WAR', 'bounce')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A WAR') == 'RUSSIA'
+
+ def test_6_d_12(self):
+ """ 6.D.12. TEST CASE, SUPPORTING A FOREIGN UNIT TO DISLODGE OWN UNIT PROHIBITED
+ You may not help another power in dislodging your own unit.
+ Austria: F Trieste Hold
+ Austria: A Vienna Supports A Venice - Trieste
+ Italy: A Venice - Trieste
+ No dislodgment of fleet in Trieste.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F TRI', 'A VIE'])
+ self.set_units(game, 'ITALY', ['A VEN'])
+ self.set_orders(game, 'AUSTRIA', ['F TRI H', 'A VIE S A VEN - TRI'])
+ self.set_orders(game, 'ITALY', 'A VEN - TRI')
+ self.process(game)
+ assert self.check_results(game, 'F TRI', '')
+ assert self.check_results(game, 'A VIE', 'void')
+ assert self.check_results(game, 'A VEN', 'bounce')
+ assert self.owner_name(game, 'F TRI') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+
+ def test_6_d_13(self):
+ """ 6.D.13. TEST CASE, SUPPORTING A FOREIGN UNIT TO DISLODGE A RETURNING OWN UNIT PROHIBITED
+ Idem.
+ Austria: F Trieste - Adriatic Sea
+ Austria: A Vienna Supports A Venice - Trieste
+ Italy: A Venice - Trieste
+ Italy: F Apulia - Adriatic Sea
+ No dislodgment of fleet in Trieste.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F TRI', 'A VIE'])
+ self.set_units(game, 'ITALY', ['A VEN', 'F APU'])
+ self.set_orders(game, 'AUSTRIA', ['F TRI - ADR', 'A VIE S A VEN - TRI'])
+ self.set_orders(game, 'ITALY', ['A VEN - TRI', 'F APU - ADR'])
+ self.process(game)
+ assert self.check_results(game, 'F TRI', 'bounce')
+ assert self.check_results(game, 'A VIE', 'void')
+ assert self.check_results(game, 'A VEN', 'bounce')
+ assert self.check_results(game, 'F APU', 'bounce')
+ assert self.owner_name(game, 'F TRI') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'F APU') == 'ITALY'
+
+ def test_6_d_14(self):
+ """ 6.D.14. TEST CASE, SUPPORTING A FOREIGN UNIT IS NOT ENOUGH TO PREVENT DISLODGEMENT
+ If a foreign unit has enough support to dislodge your unit, you may not prevent that dislodgement by
+ supporting the attack.
+ Austria: F Trieste Hold
+ Austria: A Vienna Supports A Venice - Trieste
+ Italy: A Venice - Trieste
+ Italy: A Tyrolia Supports A Venice - Trieste
+ Italy: F Adriatic Sea Supports A Venice - Trieste
+ The fleet in Trieste is dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F TRI', 'A VIE'])
+ self.set_units(game, 'ITALY', ['A VEN', 'A TYR', 'F ADR'])
+ self.set_orders(game, 'AUSTRIA', ['F TRI H', 'A VIE S A VEN - TRI'])
+ self.set_orders(game, 'ITALY', ['A VEN - TRI', 'A TUR S A VEN - TRI', 'F ADR S A VEN - TRI'])
+ self.process(game)
+ assert self.check_results(game, 'F TRI', 'dislodged')
+ assert self.check_results(game, 'A VIE', 'void')
+ assert self.check_results(game, 'A VEN', '')
+ assert self.check_results(game, 'A TYR', '')
+ assert self.check_results(game, 'F ADR', '')
+ assert check_dislodged(game, 'F TRI', 'A VEN')
+ assert self.owner_name(game, 'A TRI') == 'ITALY'
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VEN') is None
+ assert self.owner_name(game, 'A TYR') == 'ITALY'
+ assert self.owner_name(game, 'F ADR') == 'ITALY'
+
+ def test_6_d_15(self):
+ """ 6.D.15. TEST CASE, DEFENDER CAN NOT CUT SUPPORT FOR ATTACK ON ITSELF
+ A unit that is attacked by a supported unit can not prevent dislodgement by guessing which of the units
+ will do the support.
+ Russia: F Constantinople Supports F Black Sea - Ankara
+ Russia: F Black Sea - Ankara
+ Turkey: F Ankara - Constantinople
+ The support of Constantinople is not cut and the fleet in Ankara is dislodged by the fleet in the Black Sea.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'RUSSIA', ['F CON', 'F BLA'])
+ self.set_units(game, 'TURKEY', ['F ANK'])
+ self.set_orders(game, 'RUSSIA', ['F CON S F BLA - ANK', 'F BLA - ANK'])
+ self.set_orders(game, 'TURKEY', ['F ANK - CON'])
+ self.process(game)
+ assert self.check_results(game, 'F CON', '')
+ assert self.check_results(game, 'F BLA', '')
+ assert self.check_results(game, 'F ANK', 'bounce')
+ assert self.check_results(game, 'F ANK', 'dislodged')
+ assert check_dislodged(game, 'F ANK', 'F BLA')
+ assert self.owner_name(game, 'F CON') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') is None
+ assert self.owner_name(game, 'F ANK') == 'RUSSIA'
+
+ def test_6_d_16(self):
+ """ 6.D.16. TEST CASE, CONVOYING A UNIT DISLODGING A UNIT OF SAME POWER IS ALLOWED
+ It is allowed to convoy a foreign unit that dislodges your own unit is allowed.
+ England: A London Hold
+ England: F North Sea Convoys A Belgium - London
+ France: F English Channel Supports A Belgium - London
+ France: A Belgium - London
+ The English army in London is dislodged by the French army coming from Belgium.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LON', 'F NTH'])
+ self.set_units(game, 'FRANCE', ['F ENG', 'A BEL'])
+ self.set_orders(game, 'ENGLAND', ['A LON H', 'F NTH C A BEL - LON'])
+ self.set_orders(game, 'FRANCE', ['F ENG S A BEL - LON', 'A BEL - LON'])
+ self.process(game)
+ assert self.check_results(game, 'A LON', 'dislodged')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A BEL', '')
+ assert check_dislodged(game, 'A LON', 'A BEL')
+ assert self.owner_name(game, 'A LON') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A BEL') is None
+
+ def test_6_d_17(self):
+ """ 6.D.17. TEST CASE, DISLODGEMENT CUTS SUPPORTS
+ The famous dislodge rule.
+ Russia: F Constantinople Supports F Black Sea - Ankara
+ Russia: F Black Sea - Ankara
+ Turkey: F Ankara - Constantinople
+ Turkey: A Smyrna Supports F Ankara - Constantinople
+ Turkey: A Armenia - Ankara
+ The Russian fleet in Constantinople is dislodged. This cuts the support to from Black Sea to Ankara.
+ Black Sea will bounce with the army from Armenia.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'RUSSIA', ['F CON', 'F BLA'])
+ self.set_units(game, 'TURKEY', ['F ANK', 'A SMY', 'A ARM'])
+ self.set_orders(game, 'RUSSIA', ['F CON S F BLA - ANK', 'F BLA - ANK'])
+ self.set_orders(game, 'TURKEY', ['F ANK - CON', 'A SMY S F ANK - CON', 'A ARM - ANK'])
+ self.process(game)
+ assert self.check_results(game, 'F CON', 'dislodged')
+ assert self.check_results(game, 'F CON', 'cut')
+ assert self.check_results(game, 'F BLA', 'bounce')
+ assert self.check_results(game, 'F ANK', '')
+ assert self.check_results(game, 'A SMY', '')
+ assert self.check_results(game, 'A ARM', 'bounce')
+ assert check_dislodged(game, 'F CON', 'F ANK')
+ assert self.owner_name(game, 'F CON') == 'TURKEY'
+ assert self.owner_name(game, 'F BLA') == 'RUSSIA'
+ assert self.owner_name(game, 'F ANK') is None
+ assert self.owner_name(game, 'A SMY') == 'TURKEY'
+ assert self.owner_name(game, 'A ARM') == 'TURKEY'
+
+ def test_6_d_18(self):
+ """ 6.D.18. TEST CASE, A SURVIVING UNIT WILL SUSTAIN SUPPORT
+ Idem. But now with an additional hold that prevents dislodgement.
+ Russia: F Constantinople Supports F Black Sea - Ankara
+ Russia: F Black Sea - Ankara
+ Russia: A Bulgaria Supports F Constantinople
+ Turkey: F Ankara - Constantinople
+ Turkey: A Smyrna Supports F Ankara - Constantinople
+ Turkey: A Armenia - Ankara
+ The Russian fleet in the Black Sea will dislodge the Turkish fleet in Ankara.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'RUSSIA', ['F CON', 'F BLA', 'A BUL'])
+ self.set_units(game, 'TURKEY', ['F ANK', 'A SMY', 'A ARM'])
+ self.set_orders(game, 'RUSSIA', ['F CON S F BLA - ANK', 'F BLA - ANK', 'A BUL S F CON'])
+ self.set_orders(game, 'TURKEY', ['F ANK - CON', 'A SMY S F ANK - CON', 'A ARM - ANK'])
+ self.process(game)
+ assert self.check_results(game, 'F CON', '')
+ assert self.check_results(game, 'F BLA', '')
+ assert self.check_results(game, 'A BUL', '')
+ assert self.check_results(game, 'F ANK', 'dislodged')
+ assert self.check_results(game, 'A SMY', '')
+ assert self.check_results(game, 'A ARM', 'bounce')
+ assert check_dislodged(game, 'F ANK', 'F BLA')
+ assert self.owner_name(game, 'F CON') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') is None
+ assert self.owner_name(game, 'A BUL') == 'RUSSIA'
+ assert self.owner_name(game, 'F ANK') == 'RUSSIA'
+ assert self.owner_name(game, 'A SMY') == 'TURKEY'
+ assert self.owner_name(game, 'A ARM') == 'TURKEY'
+
+ def test_6_d_19(self):
+ """ 6.D.19. TEST CASE, EVEN WHEN SURVIVING IS IN ALTERNATIVE WAY
+ Now, the dislodgement is prevented because the supports comes from a Russian army:
+ Russia: F Constantinople Supports F Black Sea - Ankara
+ Russia: F Black Sea - Ankara
+ Russia: A Smyrna Supports F Ankara - Constantinople
+ Turkey: F Ankara - Constantinople
+ The Russian fleet in Constantinople is not dislodged, because one of the support is of Russian origin.
+ The support from Black Sea to Ankara will sustain and the fleet in Ankara will be dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'RUSSIA', ['F CON', 'F BLA', 'A SMY'])
+ self.set_units(game, 'TURKEY', ['F ANK'])
+ self.set_orders(game, 'RUSSIA', ['F CON S F BLA - ANK', 'F BLA - ANK', 'A SMY S F ANK - CON'])
+ self.set_orders(game, 'TURKEY', 'F ANK - CON')
+ self.process(game)
+ assert self.check_results(game, 'F CON', '')
+ assert self.check_results(game, 'F BLA', '')
+ assert self.check_results(game, 'A SMY', 'void')
+ assert self.check_results(game, 'F ANK', 'dislodged')
+ assert check_dislodged(game, 'F ANK', 'F BLA')
+ assert self.owner_name(game, 'F CON') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') is None
+ assert self.owner_name(game, 'A SMY') == 'RUSSIA'
+ assert self.owner_name(game, 'F ANK') == 'RUSSIA'
+
+ def test_6_d_20(self):
+ """ 6.D.20. TEST CASE, UNIT CAN NOT CUT SUPPORT OF ITS OWN COUNTRY
+ Although this is not mentioned in all rulebooks, it is generally accepted that when a unit attacks
+ another unit of the same Great Power, it will not cut support.
+ England: F London Supports F North Sea - English Channel
+ England: F North Sea - English Channel
+ England: A Yorkshire - London
+ France: F English Channel Hold
+ The army in York does not cut support. This means that the fleet in the English Channel is dislodged by the
+ fleet in the North Sea.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON', 'F NTH', 'A YOR'])
+ self.set_units(game, 'FRANCE', 'F ENG')
+ self.set_orders(game, 'ENGLAND', ['F LON S F NTH - ENG', 'F NTH - ENG', 'A YOR - LON'])
+ self.set_orders(game, 'FRANCE', 'F ENG H')
+ self.process(game)
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A YOR', 'bounce')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert check_dislodged(game, 'F ENG', 'F NTH')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') is None
+ assert self.owner_name(game, 'A YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+
+ def test_6_d_21(self):
+ """ 6.D.21. TEST CASE, DISLODGING DOES NOT CANCEL A SUPPORT CUT
+ Sometimes there is the question whether a dislodged moving unit does not cut support (similar to the
+ dislodge rule). This is not the case.
+ Austria: F Trieste Hold
+ Italy: A Venice - Trieste
+ Italy: A Tyrolia Supports A Venice - Trieste
+ Germany: A Munich - Tyrolia
+ Russia: A Silesia - Munich
+ Russia: A Berlin Supports A Silesia - Munich
+ Although the German army is dislodged, it still cuts the Italian support. That means that the Austrian
+ Fleet is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F TRI'])
+ self.set_units(game, 'ITALY', ['A VEN', 'A TYR'])
+ self.set_units(game, 'GERMANY', 'A MUN')
+ self.set_units(game, 'RUSSIA', ['A SIL', 'A BER'])
+ self.set_orders(game, 'AUSTRIA', 'F TRI H')
+ self.set_orders(game, 'ITALY', ['A VEN - TRI', 'A TYR S A VEN - TRI'])
+ self.set_orders(game, 'GERMANY', 'A MUN - TYR')
+ self.set_orders(game, 'RUSSIA', ['A SIL - MUN', 'A BER S A SIL - MUN'])
+ self.process(game)
+ assert self.check_results(game, 'F TRI', '')
+ assert self.check_results(game, 'A VEN', 'bounce')
+ assert self.check_results(game, 'A TYR', 'cut')
+ assert self.check_results(game, 'A MUN', 'dislodged')
+ assert self.check_results(game, 'A SIL', '')
+ assert self.check_results(game, 'A BER', '')
+ assert check_dislodged(game, 'A MUN', 'A SIL')
+ assert self.owner_name(game, 'F TRI') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'A TYR') == 'ITALY'
+ assert self.owner_name(game, 'A MUN') == 'RUSSIA'
+ assert self.owner_name(game, 'A SIL') is None
+ assert self.owner_name(game, 'A BER') == 'RUSSIA'
+
+ def test_6_d_22(self):
+ """ 6.D.22. TEST CASE, IMPOSSIBLE FLEET MOVE CAN NOT BE SUPPORTED
+ If a fleet tries moves to a land area it seems pointless to support the fleet, since the move will fail
+ anyway. However, in such case, the support is also invalid for defense purposes.
+ Germany: F Kiel - Munich
+ Germany: A Burgundy Supports F Kiel - Munich
+ Russia: A Munich - Kiel
+ Russia: A Berlin Supports A Munich - Kiel
+ The German move from Kiel to Munich is illegal (fleets can not go to Munich). Therefore, the support from
+ Burgundy fails and the Russian army in Munich will dislodge the fleet in Kiel. Note that the failing of the
+ support is not explicitly mentioned in the rulebooks (the DPTG is more clear about this point). If you take
+ the rulebooks very literally, you might conclude that the fleet in Munich is not dislodged, but this is an
+ incorrect interpretation.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['F KIE', 'A BUR'])
+ self.set_units(game, 'RUSSIA', ['A MUN', 'A BER'])
+ self.set_orders(game, 'GERMANY', ['F KIE - MUN', 'A BUR S F KIE - MUN'])
+ self.set_orders(game, 'RUSSIA', ['A MUN - KIE', 'A BER S A MUN - KIE'])
+ self.process(game)
+ assert self.check_results(game, 'F KIE', 'void')
+ assert self.check_results(game, 'F KIE', 'dislodged')
+ assert self.check_results(game, 'A BUR', 'void')
+ assert self.check_results(game, 'A MUN', '')
+ assert self.check_results(game, 'A BER', '')
+ assert check_dislodged(game, 'F KIE', 'A MUN')
+ assert self.owner_name(game, 'A KIE') == 'RUSSIA'
+ assert self.owner_name(game, 'A BUR') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') is None
+ assert self.owner_name(game, 'A BER') == 'RUSSIA'
+
+ def test_6_d_23(self):
+ """ 6.D.23. TEST CASE, IMPOSSIBLE COAST MOVE CAN NOT BE SUPPORTED
+ Comparable with the previous test case, but now the fleet move is impossible for coastal reasons.
+ Italy: F Gulf of Lyon - Spain(sc)
+ Italy: F Western Mediterranean Supports F Gulf of Lyon - Spain(sc)
+ France: F Spain(nc) - Gulf of Lyon
+ France: F Marseilles Supports F Spain(nc) - Gulf of Lyon
+ The French move from Spain North Coast to Gulf of Lyon is illegal (wrong coast). Therefore, the support
+ from Marseilles fails and the fleet in Spain is dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', ['F LYO', 'F WES'])
+ self.set_units(game, 'FRANCE', ['F SPA/NC', 'F MAR'])
+ self.set_orders(game, 'ITALY', ['F LYO - SPA/SC', 'F WES S F LYO - SPA/SC'])
+ self.set_orders(game, 'FRANCE', ['F SPA/NC - LYO', 'F MAR S F SPA/NC - LYO'])
+ self.process(game)
+ assert self.check_results(game, 'F LYO', '')
+ assert self.check_results(game, 'F WES', '')
+ assert self.check_results(game, 'F SPA/NC', 'void')
+ assert self.check_results(game, 'F SPA/NC', 'dislodged')
+ assert self.check_results(game, 'F MAR', 'void')
+ assert check_dislodged(game, 'F SPA/NC', 'F LYO')
+ assert self.owner_name(game, 'F LYO') is None
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') == 'ITALY'
+ assert self.owner_name(game, 'F MAR') == 'FRANCE'
+
+ def test_6_d_24(self):
+ """ 6.D.24. TEST CASE, IMPOSSIBLE ARMY MOVE CAN NOT BE SUPPORTED
+ Comparable with the previous test case, but now an army tries to move into sea and the support is used in a
+ beleaguered garrison.
+ France: A Marseilles - Gulf of Lyon
+ France: F Spain(sc) Supports A Marseilles - Gulf of Lyon
+ Italy: F Gulf of Lyon Hold
+ Turkey: F Tyrrhenian Sea Supports F Western Mediterranean - Gulf of Lyon
+ Turkey: F Western Mediterranean - Gulf of Lyon
+ The French move from Marseilles to Gulf of Lyon is illegal (an army can not go to sea). Therefore,
+ the support from Spain fails and there is no beleaguered garrison. The fleet in the Gulf of Lyon is
+ dislodged by the Turkish fleet in the Western Mediterranean.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['A MAR', 'F SPA/SC'])
+ self.set_units(game, 'ITALY', ['F LYO'])
+ self.set_units(game, 'TURKEY', ['F TYS', 'F WES'])
+ self.set_orders(game, 'FRANCE', ['A MAR - LYO', 'F SPA/SC S A MAR - LYO'])
+ self.set_orders(game, 'ITALY', ['F LYO H'])
+ self.set_orders(game, 'TURKEY', ['F TYS S F WES - LYO', 'F WES - LYO'])
+ self.process(game)
+ assert self.check_results(game, 'A MAR', 'void')
+ assert self.check_results(game, 'F SPA/SC', 'void')
+ assert self.check_results(game, 'F LYO', 'dislodged')
+ assert self.check_results(game, 'F TYS', '')
+ assert self.check_results(game, 'F WES', '')
+ assert check_dislodged(game, 'F LYO', 'F WES')
+ assert self.owner_name(game, 'A MAR') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA/SC') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'TURKEY'
+ assert self.owner_name(game, 'F TYS') == 'TURKEY'
+ assert self.owner_name(game, 'F WES') is None
+
+ def test_6_d_25(self):
+ """ 6.D.25. TEST CASE, FAILING HOLD SUPPORT CAN BE SUPPORTED
+ If an adjudicator fails on one of the previous three test cases, then the bug should be removed with care.
+ A failing move can not be supported, but a failing hold support, because of some preconditions (unmatching
+ order) can still be supported.
+ Germany: A Berlin Supports A Prussia
+ Germany: F Kiel Supports A Berlin
+ Russia: F Baltic Sea Supports A Prussia - Berlin
+ Russia: A Prussia - Berlin
+ Although the support of Berlin on Prussia fails (because of unmatching orders), the support of Kiel on
+ Berlin is still valid. So, Berlin will not be dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE'])
+ self.set_units(game, 'RUSSIA', ['F BAL', 'A PRU'])
+ self.set_orders(game, 'GERMANY', ['A BER S A PRU', 'F KIE S A BER'])
+ self.set_orders(game, 'RUSSIA', ['F BAL S A PRU - BER', 'A PRU - BER'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', 'void')
+ assert self.check_results(game, 'F KIE', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'A PRU', 'bounce')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+ assert self.owner_name(game, 'A PRU') == 'RUSSIA'
+
+ def test_6_d_26(self):
+ """ 6.D.26. TEST CASE, FAILING MOVE SUPPORT CAN BE SUPPORTED
+ Similar as the previous test case, but now with an unmatched support to move.
+ Germany: A Berlin Supports A Prussia - Silesia
+ Germany: F Kiel Supports A Berlin
+ Russia: F Baltic Sea Supports A Prussia - Berlin
+ Russia: A Prussia - Berlin
+ Again, Berlin will not be dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE'])
+ self.set_units(game, 'RUSSIA', ['F BAL', 'A PRU'])
+ self.set_orders(game, 'GERMANY', ['A BER S A PRU - SIL', 'F KIE S A BER'])
+ self.set_orders(game, 'RUSSIA', ['F BAL S A PRU - BER', 'A PRU - BER'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', 'void')
+ assert self.check_results(game, 'F KIE', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'A PRU', 'bounce')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+ assert self.owner_name(game, 'A PRU') == 'RUSSIA'
+
+ def test_6_d_27(self):
+ """ 6.D.27. TEST CASE, FAILING CONVOY CAN BE SUPPORTED
+ Similar as the previous test case, but now with an unmatched convoy.
+ England: F Sweden - Baltic Sea
+ England: F Denmark Supports F Sweden - Baltic Sea
+ Germany: A Berlin Hold
+ Russia: F Baltic Sea Convoys A Berlin - Livonia
+ Russia: F Prussia Supports F Baltic Sea
+ The convoy order in the Baltic Sea is unmatched and fails. However, the support of Prussia on the Baltic Sea
+ is still valid and the fleet in the Baltic Sea is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F SWE', 'F DEN'])
+ self.set_units(game, 'GERMANY', 'A BER')
+ self.set_units(game, 'RUSSIA', ['F BAL', 'F PRU'])
+ self.set_orders(game, 'ENGLAND', ['F SWE - BAL', 'F DEN S F SWE - BAL'])
+ self.set_orders(game, 'GERMANY', 'A BER H')
+ self.set_orders(game, 'RUSSIA', ['F BAL C A BER - LVN', 'F PRU S F BAL'])
+ self.process(game)
+ assert self.check_results(game, 'F SWE', 'bounce')
+ assert self.check_results(game, 'F DEN', '')
+ assert self.check_results(game, 'A BER', '')
+ assert self.check_results(game, 'F BAL', 'void')
+ assert self.check_results(game, 'F PRU', '')
+ assert self.owner_name(game, 'F SWE') == 'ENGLAND'
+ assert self.owner_name(game, 'F DEN') == 'ENGLAND'
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+ assert self.owner_name(game, 'F PRU') == 'RUSSIA'
+
+ def test_6_d_28(self):
+ """ 6.D.28. TEST CASE, IMPOSSIBLE MOVE AND SUPPORT
+ If a move is impossible then it can be treated as "illegal", which makes a hold support possible.
+ Austria: A Budapest Supports F Rumania
+ Russia: F Rumania - Holland
+ Turkey: F Black Sea - Rumania
+ Turkey: A Bulgaria Supports F Black Sea - Rumania
+ The move of the Russian fleet is impossible. But the question is, whether it is "illegal" (see issue 4.E.1).
+ If the move is "illegal" it must be ignored and that makes the hold support of the army in Budapest valid
+ and the fleet in Rumania will not be dislodged.
+ I prefer that the move is "illegal", which means that the fleet in the Black Sea does not dislodge the
+ supported Russian fleet.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['A BUD'])
+ self.set_units(game, 'RUSSIA', 'F RUM')
+ self.set_units(game, 'TURKEY', ['F BLA', 'A BUL'])
+ self.set_orders(game, 'AUSTRIA', 'A BUD S F RUM')
+ self.set_orders(game, 'RUSSIA', 'F RUM - HOL')
+ self.set_orders(game, 'TURKEY', ['F BLA - RUM', 'A BUL S F BLA - RUM'])
+ self.process(game)
+ assert self.check_results(game, 'A BUD', '')
+ assert self.check_results(game, 'F RUM', 'void')
+ assert self.check_results(game, 'F BLA', 'bounce')
+ assert self.check_results(game, 'A BUL', '')
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+ assert self.owner_name(game, 'F RUM') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') == 'TURKEY'
+ assert self.owner_name(game, 'A BUL') == 'TURKEY'
+
+ def test_6_d_29(self):
+ """ 6.D.29. TEST CASE, MOVE TO IMPOSSIBLE COAST AND SUPPORT
+ Similar to the previous test case, but now the move can be "illegal" because of the wrong coast.
+ Austria: A Budapest Supports F Rumania
+ Russia: F Rumania - Bulgaria(sc)
+ Turkey: F Black Sea - Rumania
+ Turkey: A Bulgaria Supports F Black Sea - Rumania
+ Again the move of the Russian fleet is impossible. However, some people might correct the coast
+ (see issue 4.B.3). If the coast is not corrected, again the question is whether it is "illegal" (see
+ issue 4.E.1). If the move is "illegal" it must be ignored and that makes the hold support of the army in
+ Budapest valid and the fleet in Rumania will not be dislodged.
+ I prefer that unambiguous orders are not changed and that the move is "illegal". That means that the fleet
+ in the Black Sea does not dislodge the supported Russian fleet.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', 'A BUD')
+ self.set_units(game, 'RUSSIA', 'F RUM')
+ self.set_units(game, 'TURKEY', ['F BLA', 'A BUL'])
+ self.set_orders(game, 'AUSTRIA', 'A BUD S F RUM')
+ self.set_orders(game, 'RUSSIA', 'F RUM - BUL/SC')
+ self.set_orders(game, 'TURKEY', ['F BLA - RUM', 'A BUL S F BLA - RUM'])
+ self.process(game)
+ assert self.check_results(game, 'A BUD', '')
+ assert self.check_results(game, 'F RUM', 'void')
+ assert self.check_results(game, 'F BLA', 'bounce')
+ assert self.check_results(game, 'A BUL', '')
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+ assert self.owner_name(game, 'F RUM') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') == 'TURKEY'
+ assert self.owner_name(game, 'A BUL') == 'TURKEY'
+
+ def test_6_d_30(self):
+ """ 6.D.30. TEST CASE, MOVE WITHOUT COAST AND SUPPORT
+ Similar to the previous test case, but now the move can be "illegal" because of missing coast.
+ Italy: F Aegean Sea Supports F Constantinople
+ Russia: F Constantinople - Bulgaria
+ Turkey: F Black Sea - Constantinople
+ Turkey: A Bulgaria Supports F Black Sea - Constantinople
+ Again the order to the Russian fleet is with problems, because it does not specify the coast, while both
+ coasts of Bulgaria are possible. If no default coast is taken (see issue 4.B.1), then also here it must be
+ decided whether the order is "illegal" (see issue 4.E.1). If the move is "illegal" it must be ignored and
+ that makes the hold support of the fleet in the Aegean Sea valid and the Russian fleet will not be
+ dislodged. I don't like default coasts and I prefer that the move is "illegal". That means that the fleet
+ in the Black Sea does not dislodge the supported Russian fleet.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', 'F AEG')
+ self.set_units(game, 'RUSSIA', 'F CON')
+ self.set_units(game, 'TURKEY', ['F BLA', 'A BUL'])
+ self.set_orders(game, 'ITALY', ['F AEG S F CON'])
+ self.set_orders(game, 'RUSSIA', ['F CON - BUL'])
+ self.set_orders(game, 'TURKEY', ['F BLA - CON', 'A BUL S F BLA - CON'])
+ self.process(game)
+ assert self.check_results(game, 'F AEG', '')
+ assert self.check_results(game, 'F CON', 'void')
+ assert self.check_results(game, 'F BLA', 'bounce')
+ assert self.check_results(game, 'A BUL', '')
+ assert self.owner_name(game, 'F AEG') == 'ITALY'
+ assert self.owner_name(game, 'F CON') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') == 'TURKEY'
+ assert self.owner_name(game, 'A BUL') == 'TURKEY'
+
+ def test_6_d_31(self):
+ """ 6.D.31. TEST CASE, A TRICKY IMPOSSIBLE SUPPORT
+ A support order can be impossible for complex reasons.
+ Austria: A Rumania - Armenia
+ Turkey: F Black Sea Supports A Rumania - Armenia
+ Although the army in Rumania can move to Armenia and the fleet in the Black Sea can also go to Armenia,
+ the support is still not possible. The reason is that the only possible convoy is through the Black Sea and
+ a fleet can not convoy and support at the same time.
+ This is relevant for computer programs that show only the possible orders. In the list of possible orders,
+ the support as given to the fleet in the Black Sea, should not be listed. Furthermore, if the fleet in the
+ Black Sea gets a second order, then this may fail, because of double orders (although it can also be ruled
+ differently, see issue 4.D.3). However, when the support order is considered "illegal" (see issue 4.E.1),
+ then this impossible support must be ignored and the second order must be carried out.
+ I prefer that impossible orders are "illegal" and ignored. If there would be a second order for the fleet
+ in the Black Sea, that order should be carried out.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', 'A RUM')
+ self.set_units(game, 'TURKEY', 'F BLA')
+ self.set_orders(game, 'AUSTRIA', ['A RUM - ARM'])
+ self.set_orders(game, 'TURKEY', ['F BLA S A RUM - ARM'])
+ self.process(game)
+ assert self.check_results(game, 'A RUM', 'no convoy')
+ assert self.check_results(game, 'F BLA', 'void')
+ assert self.owner_name(game, 'A RUM') == 'AUSTRIA'
+ assert self.owner_name(game, 'F BLA') == 'TURKEY'
+
+ def test_6_d_32(self):
+ """ 6.D.32. TEST CASE, A MISSING FLEET
+ The previous test cases contained an order that was impossible even when some other pieces on the board
+ where changed. In this test case, the order is impossible, but only for that situation.
+ England: F Edinburgh Supports A Liverpool - Yorkshire
+ England: A Liverpool - Yorkshire
+ France: F London Supports A Yorkshire
+ Germany: A Yorkshire - Holland
+ The German order to Yorkshire can not be executed, because there is no fleet in the North Sea. In other
+ situations (where there is a fleet in the North Sea), the exact same order would be possible. It should be
+ determined whether this is "illegal" (see issue 4.E.1) or not. If it is illegal, then the order should be
+ ignored and the support of the French fleet in London succeeds. This means that the army in Yorkshire is
+ not dislodged.
+ I prefer that impossible orders, even if it is only impossible for the current situation, are "illegal" and
+ ignored. The army in Yorkshire is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F EDI', 'A LVP'])
+ self.set_units(game, 'FRANCE', 'F LON')
+ self.set_units(game, 'GERMANY', 'A YOR')
+ self.set_orders(game, 'ENGLAND', ['F EDI S A LVP - YOR', 'A LVP - YOR'])
+ self.set_orders(game, 'FRANCE', ['F LON S A YOR'])
+ self.set_orders(game, 'GERMANY', ['A YOR - HOL'])
+ self.process(game)
+ assert self.check_results(game, 'F EDI', '')
+ assert self.check_results(game, 'A LVP', 'bounce')
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'A YOR', 'void')
+ assert self.owner_name(game, 'F EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'A LVP') == 'ENGLAND'
+ assert self.owner_name(game, 'F LON') == 'FRANCE'
+ assert self.owner_name(game, 'A YOR') == 'GERMANY'
+
+ def test_6_d_33(self):
+ """ 6.D.33. TEST CASE, UNWANTED SUPPORT ALLOWED
+ A self stand-off can be broken by an unwanted support.
+ Austria: A Serbia - Budapest
+ Austria: A Vienna - Budapest
+ Russia: A Galicia Supports A Serbia - Budapest
+ Turkey: A Bulgaria - Serbia
+ Due to the Russian support, the army in Serbia advances to Budapest. This enables Turkey to capture
+ Serbia with the army in Bulgaria.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['A SER', 'A VIE'])
+ self.set_units(game, 'RUSSIA', 'A GAL')
+ self.set_units(game, 'TURKEY', 'A BUL')
+ self.set_orders(game, 'AUSTRIA', ['A SER - BUD', 'A VIE - BUD'])
+ self.set_orders(game, 'RUSSIA', 'A GAL S A SER - BUD')
+ self.set_orders(game, 'TURKEY', 'A BUL - SER')
+ self.process(game)
+ assert self.check_results(game, 'A SER', '')
+ assert self.check_results(game, 'A VIE', 'bounce')
+ assert self.check_results(game, 'A GAL', '')
+ assert self.check_results(game, 'A BUL', '')
+ assert self.owner_name(game, 'A SER') == 'TURKEY'
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A GAL') == 'RUSSIA'
+ assert self.owner_name(game, 'A BUL') is None
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+
+ def test_6_d_34(self):
+ """ 6.D.34. TEST CASE, SUPPORT TARGETING OWN AREA NOT ALLOWED
+ Support targeting the area where the supporting unit is standing, is illegal.
+ Germany: A Berlin - Prussia
+ Germany: A Silesia Supports A Berlin - Prussia
+ Germany: F Baltic Sea Supports A Berlin - Prussia
+ Italy: A Prussia Supports Livonia - Prussia
+ Russia: A Warsaw Supports A Livonia - Prussia
+ Russia: A Livonia - Prussia
+ Russia and Italy wanted to get rid of the Italian army in Prussia (to build an Italian fleet somewhere
+ else). However, they didn't want a possible German attack on Prussia to succeed. They invented this odd
+ order of Italy. It was intended that the attack of the army in Livonia would have strength three, so it
+ would be capable to prevent the possible German attack to succeed. However, the order of Italy is illegal,
+ because a unit may only support to an area where the unit can go by itself. A unit can't go to the area it
+ is already standing, so the Italian order is illegal and the German move from Berlin succeeds. Even if it
+ would be legal, the German move from Berlin would still succeed, because the support of Prussia is cut by
+ Livonia and Berlin.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'A SIL', 'F BAL'])
+ self.set_units(game, 'ITALY', 'A PRU')
+ self.set_units(game, 'RUSSIA', ['A WAR', 'A LVN'])
+ self.set_orders(game, 'GERMANY', ['A BER - PRU', 'A SIL S A BER - PRU', 'F BAL S A BER - PRU'])
+ self.set_orders(game, 'ITALY', ['A PRU S LVN - PRU'])
+ self.set_orders(game, 'RUSSIA', ['A WAR S A LVN - PRU', 'A LVN - PRU'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', '')
+ assert self.check_results(game, 'A SIL', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'A PRU', 'void')
+ assert self.check_results(game, 'A PRU', 'dislodged')
+ assert self.check_results(game, 'A WAR', '')
+ assert self.check_results(game, 'A LVN', 'bounce')
+ assert check_dislodged(game, 'A PRU', 'A BER')
+ assert self.owner_name(game, 'A BER') is None
+ assert self.owner_name(game, 'A SIL') == 'GERMANY'
+ assert self.owner_name(game, 'F BAL') == 'GERMANY'
+ assert self.owner_name(game, 'A PRU') == 'GERMANY'
+ assert self.owner_name(game, 'A WAR') == 'RUSSIA'
+ assert self.owner_name(game, 'A LVN') == 'RUSSIA'
+
+ # 6.E. TEST CASES, HEAD TO HEAD BATTLES AND BELEAGUERED GARRISON
+ def test_6_e_1(self):
+ """ 6.E.1. TEST CASE, DISLODGED UNIT HAS NO EFFECT ON ATTACKERS AREA
+ An army can follow.
+ Germany: A Berlin - Prussia
+ Germany: F Kiel - Berlin
+ Germany: A Silesia Supports A Berlin - Prussia
+ Russia: A Prussia - Berlin
+ The army in Kiel will move to Berlin.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE', 'A SIL'])
+ self.set_units(game, 'RUSSIA', 'A PRU')
+ self.set_orders(game, 'GERMANY', ['A BER - PRU', 'F KIE - BER', 'A SIL S A BER - PRU'])
+ self.set_orders(game, 'RUSSIA', 'A PRU - BER')
+ self.process(game)
+ assert self.check_results(game, 'A BER', '')
+ assert self.check_results(game, 'F KIE', '')
+ assert self.check_results(game, 'A SIL', '')
+ assert self.check_results(game, 'A PRU', 'dislodged')
+ assert self.check_results(game, 'A PRU', 'bounce')
+ assert check_dislodged(game, 'A PRU', 'A BER')
+ assert self.owner_name(game, 'F BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') is None
+ assert self.owner_name(game, 'A SIL') == 'GERMANY'
+ assert self.owner_name(game, 'A PRU') == 'GERMANY'
+
+ def test_6_e_2(self):
+ """ 6.E.2. TEST CASE, NO SELF DISLODGEMENT IN HEAD TO HEAD BATTLE
+ Self dislodgement is not allowed. This also counts for head to head battles.
+ Germany: A Berlin - Kiel
+ Germany: F Kiel - Berlin
+ Germany: A Munich Supports A Berlin - Kiel
+ No unit will move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE', 'A MUN'])
+ self.set_orders(game, 'GERMANY', ['A BER - KIE', 'F KIE - BER', 'A MUN S A BER - KIE'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', 'bounce')
+ assert self.check_results(game, 'F KIE', 'bounce')
+ assert self.check_results(game, 'A MUN', 'void')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+
+ def test_6_e_3(self):
+ """ 6.E.3. TEST CASE, NO HELP IN DISLODGING OWN UNIT
+ To help a foreign power to dislodge own unit in head to head battle is not possible.
+ Germany: A Berlin - Kiel
+ Germany: A Munich Supports F Kiel - Berlin
+ England: F Kiel - Berlin
+ No unit will move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['A BER', 'A MUN'])
+ self.set_units(game, 'ENGLAND', 'F KIE')
+ self.set_orders(game, 'GERMANY', ['A BER - KIE', 'A MUN S F KIE - BER'])
+ self.set_orders(game, 'ENGLAND', 'F KIE - BER')
+ self.process(game)
+ assert self.check_results(game, 'A BER', 'bounce')
+ assert self.check_results(game, 'A MUN', 'void')
+ assert self.check_results(game, 'F KIE', 'bounce')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'ENGLAND'
+
+ def test_6_e_4(self):
+ """ 6.E.4. TEST CASE, NON-DISLODGED LOSER HAS STILL EFFECT
+ If in an unbalanced head to head battle the loser is not dislodged, it has still effect on the area of
+ the attacker.
+ Germany: F Holland - North Sea
+ Germany: F Helgoland Bight Supports F Holland - North Sea
+ Germany: F Skagerrak Supports F Holland - North Sea
+ France: F North Sea - Holland
+ France: F Belgium Supports F North Sea - Holland
+ England: F Edinburgh Supports F Norwegian Sea - North Sea
+ England: F Yorkshire Supports F Norwegian Sea - North Sea
+ England: F Norwegian Sea - North Sea
+ Austria: A Kiel Supports A Ruhr - Holland
+ Austria: A Ruhr - Holland
+ The French fleet in the North Sea is not dislodged due to the beleaguered garrison. Therefore,
+ the Austrian army in Ruhr will not move to Holland.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['F HOL', 'F HEL', 'F SKA'])
+ self.set_units(game, 'FRANCE', ['F NTH', 'F BEL'])
+ self.set_units(game, 'ENGLAND', ['F EDI', 'F YOR', 'F NWG'])
+ self.set_units(game, 'AUSTRIA', ['A KIE', 'A RUH'])
+ self.set_orders(game, 'GERMANY', ['F HOL - NTH', 'F HEL S F HOL - NTH', 'F SKA S F HOL - NTH'])
+ self.set_orders(game, 'FRANCE', ['F NTH - HOL', 'F BEL S F NTH - HOL'])
+ self.set_orders(game, 'ENGLAND', ['F EDI S F NWG - NTH', 'F YOR S F NWG - NTH', 'F NWG - NTH'])
+ self.set_orders(game, 'AUSTRIA', ['A KIE S A RUH - HOL', 'A RUH - HOL'])
+ self.process(game)
+ assert self.check_results(game, 'F HOL', 'bounce')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NTH', 'bounce')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'F EDI', '')
+ assert self.check_results(game, 'F YOR', '')
+ assert self.check_results(game, 'F NWG', 'bounce')
+ assert self.check_results(game, 'A KIE', '')
+ assert self.check_results(game, 'A RUH', 'bounce')
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+ assert self.owner_name(game, 'F NTH') == 'FRANCE'
+ assert self.owner_name(game, 'F BEL') == 'FRANCE'
+ assert self.owner_name(game, 'F EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F NWG') == 'ENGLAND'
+ assert self.owner_name(game, 'A KIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A RUH') == 'AUSTRIA'
+
+ def test_6_e_5(self):
+ """ 6.E.5. TEST CASE, LOSER DISLODGED BY ANOTHER ARMY HAS STILL EFFECT
+ If in an unbalanced head to head battle the loser is dislodged by a unit not part of the head to head
+ battle, the loser has still effect on the place of the winner of the head to head battle.
+ Germany: F Holland - North Sea
+ Germany: F Helgoland Bight Supports F Holland - North Sea
+ Germany: F Skagerrak Supports F Holland - North Sea
+ France: F North Sea - Holland
+ France: F Belgium Supports F North Sea - Holland
+ England: F Edinburgh Supports F Norwegian Sea - North Sea
+ England: F Yorkshire Supports F Norwegian Sea - North Sea
+ England: F Norwegian Sea - North Sea
+ England: F London Supports F Norwegian Sea - North Sea
+ Austria: A Kiel Supports A Ruhr - Holland
+ Austria: A Ruhr - Holland
+ The French fleet in the North Sea is dislodged but not by the German fleet in Holland. Therefore,
+ the French fleet can still prevent that the Austrian army in Ruhr will move to Holland. So, the Austrian
+ move in Ruhr fails and the German fleet in Holland is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['F HOL', 'F HEL', 'F SKA'])
+ self.set_units(game, 'FRANCE', ['F NTH', 'F BEL'])
+ self.set_units(game, 'ENGLAND', ['F EDI', 'F YOR', 'F NWG', 'F LON'])
+ self.set_units(game, 'AUSTRIA', ['A KIE', 'A RUH'])
+ self.set_orders(game, 'GERMANY', ['F HOL - NTH', 'F HEL S F HOL - NTH', 'F SKA S F HOL - NTH'])
+ self.set_orders(game, 'FRANCE', ['F NTH - HOL', 'F BEL S F NTH - HOL'])
+ self.set_orders(game, 'ENGLAND', ['F EDI S F NWG - NTH', 'F YOR S F NWG - NTH', 'F NWG - NTH',
+ 'F LON S F NWG - NTH'])
+ self.set_orders(game, 'AUSTRIA', ['A KIE S A RUH - HOL', 'A RUH - HOL'])
+ self.process(game)
+ assert self.check_results(game, 'F HOL', 'bounce')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NTH', 'dislodged')
+ assert self.check_results(game, 'F NTH', 'bounce')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'F EDI', '')
+ assert self.check_results(game, 'F YOR', '')
+ assert self.check_results(game, 'F NWG', '')
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'A KIE', '')
+ assert self.check_results(game, 'A RUH', 'bounce')
+ assert check_dislodged(game, 'F NTH', 'F NWG')
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F BEL') == 'FRANCE'
+ assert self.owner_name(game, 'F EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F NWG') is None
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'A KIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A RUH') == 'AUSTRIA'
+
+ def test_6_e_6(self):
+ """ 6.E.6. TEST CASE, NOT DISLODGE BECAUSE OF OWN SUPPORT HAS STILL EFFECT
+ If in an unbalanced head to head battle the loser is not dislodged because the winner had help of a unit
+ of the loser, the loser has still effect on the area of the winner.
+ Germany: F Holland - North Sea
+ Germany: F Helgoland Bight Supports F Holland - North Sea
+ France: F North Sea - Holland
+ France: F Belgium Supports F North Sea - Holland
+ France: F English Channel Supports F Holland - North Sea
+ Austria: A Kiel Supports A Ruhr - Holland
+ Austria: A Ruhr - Holland
+ Although the German force from Holland to North Sea is one larger than the French force from North Sea
+ to Holland,
+ the French fleet in the North Sea is not dislodged, because one of the supports on the German movement is
+ French.
+ Therefore, the Austrian army in Ruhr will not move to Holland.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'GERMANY', ['F HOL', 'F HEL'])
+ self.set_units(game, 'FRANCE', ['F NTH', 'F BEL', 'F ENG'])
+ self.set_units(game, 'AUSTRIA', ['A KIE', 'A RUH'])
+ self.set_orders(game, 'GERMANY', ['F HOL - NTH', 'F HEL S F HOL - NTH'])
+ self.set_orders(game, 'FRANCE', ['F NTH - HOL', 'F BEL S F NTH - HOL', 'F ENG S F HOL - NTH'])
+ self.set_orders(game, 'AUSTRIA', ['A KIE S A RUH - HOL', 'A RUH - HOL'])
+ self.process(game)
+ assert self.check_results(game, 'F HOL', 'bounce')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F NTH', 'bounce')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'F ENG', 'void')
+ assert self.check_results(game, 'A KIE', '')
+ assert self.check_results(game, 'A RUH', 'bounce')
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F NTH') == 'FRANCE'
+ assert self.owner_name(game, 'F BEL') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A KIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A RUH') == 'AUSTRIA'
+
+ def test_6_e_7(self):
+ """ 6.E.7. TEST CASE, NO SELF DISLODGEMENT WITH BELEAGUERED GARRISON
+ An attempt to self dislodgement can be combined with a beleaguered garrison. Such self dislodgment is still
+ not possible.
+ England: F North Sea Hold
+ England: F Yorkshire Supports F Norway - North Sea
+ Germany: F Holland Supports F Helgoland Bight - North Sea
+ Germany: F Helgoland Bight - North Sea
+ Russia: F Skagerrak Supports F Norway - North Sea
+ Russia: F Norway - North Sea
+ Although the Russians beat the German attack (with the support of Yorkshire) and the two Russian fleets
+ are enough to dislodge the fleet in the North Sea, the fleet in the North Sea is not dislodged, since it
+ would not be dislodged if the English fleet in Yorkshire would not give support. According to the DPTG the
+ fleet in the North Sea would be dislodged. The DPTG is incorrect in this case.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'F YOR'])
+ self.set_units(game, 'GERMANY', ['F HOL', 'F HEL'])
+ self.set_units(game, 'RUSSIA', ['F SKA', 'F NWY'])
+ self.set_orders(game, 'ENGLAND', ['F NTH H', 'F YOR S F NWY - NTH'])
+ self.set_orders(game, 'GERMANY', ['F HOL S F HEL - NTH', 'F HEL - NTH'])
+ self.set_orders(game, 'RUSSIA', ['F SKA S F NWY - NTH', 'F NWY - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F YOR', 'void')
+ assert self.check_results(game, 'F HOL', '')
+ assert self.check_results(game, 'F HEL', 'bounce')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NWY', 'bounce')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWY') == 'RUSSIA'
+
+ def test_6_e_8(self):
+ """ 6.E.8. TEST CASE, NO SELF DISLODGEMENT WITH BELEAGUERED GARRISON AND HEAD TO HEAD BATTLE
+ Similar to the previous test case, but now the beleaguered fleet is also engaged in a head to head battle.
+ England: F North Sea - Norway
+ England: F Yorkshire Supports F Norway - North Sea
+ Germany: F Holland Supports F Helgoland Bight - North Sea
+ Germany: F Helgoland Bight - North Sea
+ Russia: F Skagerrak Supports F Norway - North Sea
+ Russia: F Norway - North Sea
+ Again, none of the fleets move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'F YOR'])
+ self.set_units(game, 'GERMANY', ['F HOL', 'F HEL'])
+ self.set_units(game, 'RUSSIA', ['F SKA', 'F NWY'])
+ self.set_orders(game, 'ENGLAND', ['F NTH - NWY', 'F YOR S F NWY - NTH'])
+ self.set_orders(game, 'GERMANY', ['F HOL S F HEL - NTH', 'F HEL - NTH'])
+ self.set_orders(game, 'RUSSIA', ['F SKA S F NWY - NTH', 'F NWY - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'bounce')
+ assert self.check_results(game, 'F YOR', 'void')
+ assert self.check_results(game, 'F HOL', '')
+ assert self.check_results(game, 'F HEL', 'bounce')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NWY', 'bounce')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWY') == 'RUSSIA'
+
+ def test_6_e_9(self):
+ """ 6.E.9. TEST CASE, ALMOST SELF DISLODGEMENT WITH BELEAGUERED GARRISON
+ Similar to the previous test case, but now the beleaguered fleet is moving away.
+ England: F North Sea - Norwegian Sea
+ England: F Yorkshire Supports F Norway - North Sea
+ Germany: F Holland Supports F Helgoland Bight - North Sea
+ Germany: F Helgoland Bight - North Sea
+ Russia: F Skagerrak Supports F Norway - North Sea
+ Russia: F Norway - North Sea
+ Both the fleet in the North Sea and the fleet in Norway move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'F YOR'])
+ self.set_units(game, 'GERMANY', ['F HOL', 'F HEL'])
+ self.set_units(game, 'RUSSIA', ['F SKA', 'F NWY'])
+ self.set_orders(game, 'ENGLAND', ['F NTH - NWG', 'F YOR S F NWY - NTH'])
+ self.set_orders(game, 'GERMANY', ['F HOL S F HEL - NTH', 'F HEL - NTH'])
+ self.set_orders(game, 'RUSSIA', ['F SKA S F NWY - NTH', 'F NWY - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F YOR', '')
+ assert self.check_results(game, 'F HOL', '')
+ assert self.check_results(game, 'F HEL', 'bounce')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NWY', '')
+ assert self.owner_name(game, 'F NTH') == 'RUSSIA'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWY') is None
+ assert self.owner_name(game, 'F NWG') == 'ENGLAND'
+
+ def test_6_e_10(self):
+ """ 6.E.10. TEST CASE, ALMOST CIRCULAR MOVEMENT WITH NO SELF DISLODGEMENT WITH BELEAGUERED GARRISON
+ Similar to the previous test case, but now the beleaguered fleet is in circular movement with the weaker
+ attacker. So, the circular movement fails.
+ England: F North Sea - Denmark
+ England: F Yorkshire Supports F Norway - North Sea
+ Germany: F Holland Supports F Helgoland Bight - North Sea
+ Germany: F Helgoland Bight - North Sea
+ Germany: F Denmark - Helgoland Bight
+ Russia: F Skagerrak Supports F Norway - North Sea
+ Russia: F Norway - North Sea
+ There is no movement of fleets.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'F YOR'])
+ self.set_units(game, 'GERMANY', ['F HOL', 'F HEL', 'F DEN'])
+ self.set_units(game, 'RUSSIA', ['F SKA', 'F NWY'])
+ self.set_orders(game, 'ENGLAND', ['F NTH - DEN', 'F YOR S F NWY - NTH'])
+ self.set_orders(game, 'GERMANY', ['F HOL S F HEL - NTH', 'F HEL - NTH', 'F DEN - HEL'])
+ self.set_orders(game, 'RUSSIA', ['F SKA S F NWY - NTH', 'F NWY - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'bounce')
+ assert self.check_results(game, 'F YOR', 'void')
+ assert self.check_results(game, 'F HOL', '')
+ assert self.check_results(game, 'F HEL', 'bounce')
+ assert self.check_results(game, 'F DEN', 'bounce')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NWY', 'bounce')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F DEN') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWY') == 'RUSSIA'
+
+ def test_6_e_11(self):
+ """ 6.E.11. TEST CASE, NO SELF DISLODGEMENT WITH BELEAGUERED GARRISON, UNIT SWAP WITH ADJACENT CONVOYING AND
+ TWO COASTS
+ Similar to the previous test case, but now the beleaguered fleet is in a unit swap with the stronger
+ attacker. So, the unit swap succeeds. To make the situation more complex, the swap is on an area with
+ two coasts.
+ France: A Spain - Portugal via Convoy
+ France: F Mid-Atlantic Ocean Convoys A Spain - Portugal
+ France: F Gulf of Lyon Supports F Portugal - Spain(nc)
+ Germany: A Marseilles Supports A Gascony - Spain
+ Germany: A Gascony - Spain
+ Italy: F Portugal - Spain(nc)
+ Italy: F Western Mediterranean Supports F Portugal - Spain(nc)
+ The unit swap succeeds. Note that due to the success of the swap, there is no beleaguered garrison anymore.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['A SPA', 'F MAO', 'F LYO'])
+ self.set_units(game, 'GERMANY', ['A MAR', 'A GAS'])
+ self.set_units(game, 'ITALY', ['F POR', 'F WES'])
+ self.set_orders(game, 'FRANCE', ['A SPA - POR VIA', 'F MAO C A SPA - POR', 'F LYO S F POR - SPA/NC'])
+ self.set_orders(game, 'GERMANY', ['A MAR S A GAS - SPA', 'A GAS - SPA'])
+ self.set_orders(game, 'ITALY', ['F POR - SPA/NC', 'F WES S F POR - SPA/NC'])
+ self.process(game)
+ assert self.check_results(game, 'A SPA', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'F LYO', '')
+ assert self.check_results(game, 'A MAR', '')
+ assert self.check_results(game, 'A GAS', 'bounce')
+ assert self.check_results(game, 'F POR', '')
+ assert self.check_results(game, 'F WES', '')
+ assert self.owner_name(game, 'F SPA') == 'ITALY'
+ assert self.owner_name(game, 'F SPA/NC') == 'ITALY'
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'FRANCE'
+ assert self.owner_name(game, 'A MAR') == 'GERMANY'
+ assert self.owner_name(game, 'A GAS') == 'GERMANY'
+ assert self.owner_name(game, 'A POR') == 'FRANCE'
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+
+ def test_6_e_12(self):
+ """ 6.E.12. TEST CASE, SUPPORT ON ATTACK ON OWN UNIT CAN BE USED FOR OTHER MEANS
+ A support on an attack on your own unit has still effect. It can prevent that another army will dislodge
+ the unit.
+ Austria: A Budapest - Rumania
+ Austria: A Serbia Supports A Vienna - Budapest
+ Italy: A Vienna - Budapest
+ Russia: A Galicia - Budapest
+ Russia: A Rumania Supports A Galicia - Budapest
+ The support of Serbia on the Italian army prevents that the Russian army in Galicia will advance.
+ No army will move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['A BUD', 'A SER'])
+ self.set_units(game, 'ITALY', ['A VIE'])
+ self.set_units(game, 'RUSSIA', ['A GAL', 'A RUM'])
+ self.set_orders(game, 'AUSTRIA', ['A BUD - RUM', 'A SER S A VIE - BUD'])
+ self.set_orders(game, 'ITALY', 'A VIE - BUD')
+ self.set_orders(game, 'RUSSIA', ['A GAL - BUD', 'A RUM S A GAL - BUD'])
+ self.process(game)
+ assert self.check_results(game, 'A BUD', 'bounce')
+ assert self.check_results(game, 'A SER', '')
+ assert self.check_results(game, 'A VIE', 'bounce')
+ assert self.check_results(game, 'A GAL', 'bounce')
+ assert self.check_results(game, 'A RUM', '')
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+ assert self.owner_name(game, 'A SER') == 'AUSTRIA'
+ assert self.owner_name(game, 'A VIE') == 'ITALY'
+ assert self.owner_name(game, 'A GAL') == 'RUSSIA'
+ assert self.owner_name(game, 'A RUM') == 'RUSSIA'
+
+ def test_6_e_13(self):
+ """ 6.E.13. TEST CASE, THREE WAY BELEAGUERED GARRISON
+ In a beleaguered garrison from three sides, the adjudicator may not let two attacks fail and then let the
+ third succeed.
+ England: F Edinburgh Supports F Yorkshire - North Sea
+ England: F Yorkshire - North Sea
+ France: F Belgium - North Sea
+ France: F English Channel Supports F Belgium - North Sea
+ Germany: F North Sea Hold
+ Russia: F Norwegian Sea - North Sea
+ Russia: F Norway Supports F Norwegian Sea - North Sea
+ None of the fleets move. The German fleet in the North Sea is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F EDI', 'F YOR'])
+ self.set_units(game, 'FRANCE', ['F BEL', 'F ENG'])
+ self.set_units(game, 'GERMANY', 'F NTH')
+ self.set_units(game, 'RUSSIA', ['F NWG', 'F NWY'])
+ self.set_orders(game, 'ENGLAND', ['F EDI S F YOR - NTH', 'F YOR - NTH'])
+ self.set_orders(game, 'FRANCE', ['F BEL - NTH', 'F ENG S F BEL - NTH'])
+ self.set_orders(game, 'GERMANY', 'F NTH H')
+ self.set_orders(game, 'RUSSIA', ['F NWG - NTH', 'F NWY S F NWG - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F EDI', '')
+ assert self.check_results(game, 'F YOR', 'bounce')
+ assert self.check_results(game, 'F BEL', 'bounce')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F NWG', 'bounce')
+ assert self.check_results(game, 'F NWY', '')
+ assert self.owner_name(game, 'F EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'F BEL') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'F NWG') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWY') == 'RUSSIA'
+
+ def test_6_e_14(self):
+ """ 6.E.14. TEST CASE, ILLEGAL HEAD TO HEAD BATTLE CAN STILL DEFEND
+ If in a head to head battle, one of the units makes an illegal move, than that unit has still the
+ possibility to defend against attacks with strength of one.
+ England: A Liverpool - Edinburgh
+ Russia: F Edinburgh - Liverpool
+ The move of the Russian fleet is illegal, but can still prevent the English army to enter Edinburgh. So,
+ none of the units move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LVP'])
+ self.set_units(game, 'RUSSIA', ['F EDI'])
+ self.set_orders(game, 'ENGLAND', ['A LVP - EDI'])
+ self.set_orders(game, 'RUSSIA', ['F EDI - LVP'])
+ self.process(game)
+ assert self.check_results(game, 'A LVP', 'bounce')
+ assert self.check_results(game, 'F EDI', 'void')
+ assert self.owner_name(game, 'A LVP') == 'ENGLAND'
+ assert self.owner_name(game, 'F EDI') == 'RUSSIA'
+
+ def test_6_e_15(self):
+ """ 6.E.15. TEST CASE, THE FRIENDLY HEAD TO HEAD BATTLE
+ In this case both units in the head to head battle prevent that the other one is dislodged.
+ England: F Holland Supports A Ruhr - Kiel
+ England: A Ruhr - Kiel
+ France: A Kiel - Berlin
+ France: A Munich Supports A Kiel - Berlin
+ France: A Silesia Supports A Kiel - Berlin
+ Germany: A Berlin - Kiel
+ Germany: F Denmark Supports A Berlin - Kiel
+ Germany: F Helgoland Bight Supports A Berlin - Kiel
+ Russia: F Baltic Sea Supports A Prussia - Berlin
+ Russia: A Prussia - Berlin
+ None of the moves succeeds. This case is especially difficult for sequence based adjudicators. They will
+ start adjudicating the head to head battle and continue to adjudicate the attack on one of the units part
+ of the head to head battle. In this self.process, one of the sides of the head to head battle might be
+ cancelled out. This happens in the DPTG. If this is adjudicated according to the DPTG, the unit in Ruhr or
+ in Prussia will advance (depending on the order the units are adjudicated). This is clearly a bug in the
+ DPTG.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F HOL', 'A RUH'])
+ self.set_units(game, 'FRANCE', ['A KIE', 'A MUN', 'A SIL'])
+ self.set_units(game, 'GERMANY', ['A BER', 'F DEN', 'F HEL'])
+ self.set_units(game, 'RUSSIA', ['F BAL', 'A PRU'])
+ self.set_orders(game, 'ENGLAND', ['F HOL S A RUH - KIE', 'A RUH - KIE'])
+ self.set_orders(game, 'FRANCE', ['A KIE - BER', 'A MUN S A KIE - BER', 'A SIL S A KIE - BER'])
+ self.set_orders(game, 'GERMANY', ['A BER - KIE', 'F DEN S A BER - KIE', 'F HEL S A BER - KIE'])
+ self.set_orders(game, 'RUSSIA', ['F BAL S A PRU - BER', 'A PRU - BER'])
+ self.process(game)
+ assert self.check_results(game, 'F HOL', '')
+ assert self.check_results(game, 'A RUH', 'bounce')
+ assert self.check_results(game, 'A KIE', 'bounce')
+ assert self.check_results(game, 'A MUN', '')
+ assert self.check_results(game, 'A SIL', '')
+ assert self.check_results(game, 'A BER', 'bounce')
+ assert self.check_results(game, 'F DEN', '')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'A PRU', 'bounce')
+ assert self.owner_name(game, 'F HOL')
+ assert self.owner_name(game, 'A RUH')
+ assert self.owner_name(game, 'A KIE')
+ assert self.owner_name(game, 'A MUN')
+ assert self.owner_name(game, 'A SIL')
+ assert self.owner_name(game, 'A BER')
+ assert self.owner_name(game, 'F DEN')
+ assert self.owner_name(game, 'F HEL')
+ assert self.owner_name(game, 'F BAL')
+ assert self.owner_name(game, 'A PRU')
+
+ # 6.F. TEST CASES, CONVOYS
+ def test_6_f_1(self):
+ """ 6.F.1. TEST CASE, NO CONVOY IN COASTAL AREAS
+ A fleet in a coastal area may not convoy.
+ Turkey: A Greece - Sevastopol
+ Turkey: F Aegean Sea Convoys A Greece - Sevastopol
+ Turkey: F Constantinople Convoys A Greece - Sevastopol
+ Turkey: F Black Sea Convoys A Greece - Sevastopol
+ The convoy in Constantinople is not possible. So, the army in Greece will not move to Sevastopol.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'TURKEY', ['A GRE', 'F AEG', 'F CON', 'F BLA'])
+ self.set_orders(game, 'TURKEY', ['A GRE - SEV', 'F AEG C A GRE - SEV', 'F CON C A GRE - SEV',
+ 'F BLA C A GRE - SEV'])
+ self.process(game)
+ # Note F CON is void, the other moves then are impossible (i.e. A GRE can't move by convoy to SEV)
+ assert self.check_results(game, 'A GRE', 'void')
+ assert self.check_results(game, 'F AEG', 'void')
+ assert self.check_results(game, 'F CON', 'void')
+ assert self.check_results(game, 'F BLA', 'void')
+ assert self.owner_name(game, 'A GRE') == 'TURKEY'
+ assert self.owner_name(game, 'F AEG') == 'TURKEY'
+ assert self.owner_name(game, 'F CON') == 'TURKEY'
+ assert self.owner_name(game, 'F BLA') == 'TURKEY'
+ assert self.owner_name(game, 'A SEV') is None
+
+ def test_6_f_2(self):
+ """ 6.F.2. TEST CASE, AN ARMY BEING CONVOYED CAN BOUNCE AS NORMAL
+ Armies being convoyed bounce on other units just as armies that are not being convoyed.
+ England: F English Channel Convoys A London - Brest
+ England: A London - Brest
+ France: A Paris - Brest
+ The English army in London bounces on the French army in Paris. Both units do not move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F ENG', 'A LON'])
+ self.set_units(game, 'FRANCE', 'A PAR')
+ self.set_orders(game, 'ENGLAND', ['F ENG C A LON - BRE', 'A LON - BRE'])
+ self.set_orders(game, 'FRANCE', 'A PAR - BRE')
+ self.process(game)
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A LON', 'bounce')
+ assert self.check_results(game, 'A PAR', 'bounce')
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') == 'ENGLAND'
+ assert self.owner_name(game, 'A PAR') == 'FRANCE'
+
+ def test_6_f_3(self):
+ """ 6.F.3. TEST CASE, AN ARMY BEING CONVOYED CAN RECEIVE SUPPORT
+ Armies being convoyed can receive support as in any other move.
+ England: F English Channel Convoys A London - Brest
+ England: A London - Brest
+ England: F Mid-Atlantic Ocean Supports A London - Brest
+ France: A Paris - Brest
+ The army in London receives support and beats the army in Paris. This means that the army London will end
+ in Brest and the French army in Paris stays in Paris.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F ENG', 'A LON', 'F MAO'])
+ self.set_units(game, 'FRANCE', 'A PAR')
+ self.set_orders(game, 'ENGLAND', ['F ENG C A LON - BRE', 'A LON - BRE', 'F MAO S A LON - BRE'])
+ self.set_orders(game, 'FRANCE', 'A PAR - BRE')
+ self.process(game)
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'A PAR', 'bounce')
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A BRE') == 'ENGLAND'
+ assert self.owner_name(game, 'F MAO') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'A PAR') == 'FRANCE'
+
+ def test_6_f_4(self):
+ """ 6.F.4. TEST CASE, AN ATTACKED CONVOY IS NOT DISRUPTED
+ A convoy can only be disrupted by dislodging the fleets. Attacking is not sufficient.
+ England: F North Sea Convoys A London - Holland
+ England: A London - Holland
+ Germany: F Skagerrak - North Sea
+ The army in London will successfully convoy and end in Holland.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'GERMANY', 'F SKA')
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - HOL', 'A LON - HOL'])
+ self.set_orders(game, 'GERMANY', 'F SKA - NTH')
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F SKA', 'bounce')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+ assert self.owner_name(game, 'A HOL') == 'ENGLAND'
+
+ def test_6_f_5(self):
+ """ 6.F.5. TEST CASE, A BELEAGUERED CONVOY IS NOT DISRUPTED
+ Even when a convoy is in a beleaguered garrison it is not disrupted.
+ England: F North Sea Convoys A London - Holland
+ England: A London - Holland
+ France: F English Channel - North Sea
+ France: F Belgium Supports F English Channel - North Sea
+ Germany: F Skagerrak - North Sea
+ Germany: F Denmark Supports F Skagerrak - North Sea
+ The army in London will successfully convoy and end in Holland.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'FRANCE', ['F ENG', 'F BEL'])
+ self.set_units(game, 'GERMANY', ['F SKA', 'F DEN'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - HOL', 'A LON - HOL'])
+ self.set_orders(game, 'FRANCE', ['F ENG - NTH', 'F BEL S F ENG - NTH'])
+ self.set_orders(game, 'GERMANY', ['F SKA - NTH', 'F DEN S F SKA - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F ENG', 'bounce')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'F SKA', 'bounce')
+ assert self.check_results(game, 'F DEN', '')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F BEL') == 'FRANCE'
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+ assert self.owner_name(game, 'F DEN') == 'GERMANY'
+ assert self.owner_name(game, 'A HOL') == 'ENGLAND'
+
+ def test_6_f_6(self):
+ """ 6.F.6. TEST CASE, DISLODGED CONVOY DOES NOT CUT SUPPORT
+ When a fleet of a convoy is dislodged, the convoy is completely cancelled. So, no support is cut.
+ England: F North Sea Convoys A London - Holland
+ England: A London - Holland
+ Germany: A Holland Supports A Belgium
+ Germany: A Belgium Supports A Holland
+ Germany: F Helgoland Bight Supports F Skagerrak - North Sea
+ Germany: F Skagerrak - North Sea
+ France: A Picardy - Belgium
+ France: A Burgundy Supports A Picardy - Belgium
+ The hold order of Holland on Belgium will sustain and Belgium will not be dislodged by the French in
+ Picardy.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'GERMANY', ['A HOL', 'A BEL', 'F HEL', 'F SKA'])
+ self.set_units(game, 'FRANCE', ['A PIC', 'A BUR'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - HOL', 'A LON - HOL'])
+ self.set_orders(game, 'GERMANY', ['A HOL S A BEL', 'A BEL S A HOL', 'F HEL S F SKA - NTH', 'F SKA - NTH'])
+ self.set_orders(game, 'FRANCE', ['A PIC - BEL', 'A BUR S A PIC - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'dislodged')
+ assert self.check_results(game, 'A LON', 'no convoy')
+ assert self.check_results(game, 'A HOL', '')
+ assert self.check_results(game, 'A BEL', 'cut')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'A PIC', 'bounce')
+ assert self.check_results(game, 'A BUR', '')
+ assert check_dislodged(game, 'F NTH', 'F SKA')
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'A LON') == 'ENGLAND'
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+ assert self.owner_name(game, 'A BEL') == 'GERMANY'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') is None
+ assert self.owner_name(game, 'A PIC') == 'FRANCE'
+ assert self.owner_name(game, 'A BUR') == 'FRANCE'
+
+ def test_6_f_7(self):
+ """ 6.F.7. TEST CASE, DISLODGED CONVOY DOES NOT CAUSE CONTESTED AREA
+ When a fleet of a convoy is dislodged, the landing area is not contested, so other units can retreat to
+ that area.
+ England: F North Sea Convoys A London - Holland
+ England: A London - Holland
+ Germany: F Helgoland Bight Supports F Skagerrak - North Sea
+ Germany: F Skagerrak - North Sea
+ The dislodged English fleet can retreat to Holland.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'GERMANY', ['F HEL', 'F SKA'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - HOL', 'A LON - HOL'])
+ self.set_orders(game, 'GERMANY', ['F HEL S F SKA - NTH', 'F SKA - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'dislodged')
+ assert self.check_results(game, 'A LON', 'no convoy')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert check_dislodged(game, 'F NTH', 'F SKA') # ENGLAND
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'A LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') is None
+ assert self.owner_name(game, 'A HOL') is None
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', 'F NTH R HOL')
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '', phase='R')
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'A LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') is None
+ assert self.owner_name(game, 'F HOL') == 'ENGLAND'
+
+ def test_6_f_8(self):
+ """ 6.F.8. TEST CASE, DISLODGED CONVOY DOES NOT CAUSE A BOUNCE
+ When a fleet of a convoy is dislodged, then there will be no bounce in the landing area.
+ England: F North Sea Convoys A London - Holland
+ England: A London - Holland
+ Germany: F Helgoland Bight Supports F Skagerrak - North Sea
+ Germany: F Skagerrak - North Sea
+ Germany: A Belgium - Holland
+ The army in Belgium will not bounce and move to Holland.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'GERMANY', ['F HEL', 'F SKA', 'A BEL'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - HOL', 'A LON - HOL'])
+ self.set_orders(game, 'GERMANY', ['F HEL S F SKA - NTH', 'F SKA - NTH', 'A BEL - HOL'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'dislodged')
+ assert self.check_results(game, 'A LON', 'no convoy')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'A BEL', '')
+ assert check_dislodged(game, 'F NTH', 'F SKA')
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'A LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') is None
+ assert self.owner_name(game, 'A BEL') is None
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+
+ def test_6_f_9(self):
+ """ 6.F.9. TEST CASE, DISLODGE OF MULTI-ROUTE CONVOY
+ When a fleet of a convoy with multiple routes is dislodged, the result depends on the rulebook that is used.
+ England: F English Channel Convoys A London - Belgium
+ England: F North Sea Convoys A London - Belgium
+ England: A London - Belgium
+ France: F Brest Supports F Mid-Atlantic Ocean - English Channel
+ France: F Mid-Atlantic Ocean - English Channel
+ The French fleet in Mid Atlantic Ocean will dislodge the convoying fleet in the English Channel. If the
+ 1971 rules are used (see issue 4.A.1), this will disrupt the convoy and the army will stay in London. When
+ the 1982 or 2000 rulebook is used (which I prefer) the army can still go via the North Sea and the convoy
+ succeeds and the London army will end in Belgium.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F ENG', 'F NTH', 'A LON'])
+ self.set_units(game, 'FRANCE', ['F BRE', 'F MAO'])
+ self.set_orders(game, 'ENGLAND', ['F ENG C A LON - BEL', 'F NTH C A LON - BEL', 'A LON - BEL'])
+ self.set_orders(game, 'FRANCE', ['F BRE S F MAO - ENG', 'F MAO - ENG'])
+ self.process(game)
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F BRE', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert check_dislodged(game, 'F ENG', 'F MAO')
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') is None
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+
+ def test_6_f_10(self):
+ """ 6.F.10. TEST CASE, DISLODGE OF MULTI-ROUTE CONVOY WITH FOREIGN FLEET
+ When the 1971 rulebook is used "unwanted" multi-route convoys are possible.
+ England: F North Sea Convoys A London - Belgium
+ England: A London - Belgium
+ Germany: F English Channel Convoys A London - Belgium
+ France: F Brest Supports F Mid-Atlantic Ocean - English Channel
+ France: F Mid-Atlantic Ocean - English Channel
+ If the 1982 or 2000 rulebook is used (which I prefer), it makes no difference that the convoying fleet in
+ the English Channel is German. It will take the convoy via the North Sea anyway and the army in London will
+ end in Belgium. However, when the 1971 rules are used, the German convoy is "unwanted". According to the
+ DPTG the German fleet should be ignored in the English convoy, since there is a convoy path with only
+ English fleets. That means that the convoy is not disrupted and the English army in London will end in
+ Belgium. See also issue 4.A.1.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON'])
+ self.set_units(game, 'GERMANY', 'F ENG')
+ self.set_units(game, 'FRANCE', ['F BRE', 'F MAO'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - BEL', 'A LON - BEL'])
+ self.set_orders(game, 'GERMANY', ['F ENG C A LON - BEL'])
+ self.set_orders(game, 'FRANCE', ['F BRE S F MAO - ENG', 'F MAO - ENG'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F BRE', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert check_dislodged(game, 'F ENG', 'F MAO')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') is None
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+
+ def test_6_f_11(self):
+ """ 6.F.11. TEST CASE, DISLODGE OF MULTI-ROUTE CONVOY WITH ONLY FOREIGN FLEETS
+ When the 1971 rulebook is used, "unwanted" convoys can not be ignored in all cases.
+ England: A London - Belgium
+ Germany: F English Channel Convoys A London - Belgium
+ Russia: F North Sea Convoys A London - Belgium
+ France: F Brest Supports F Mid-Atlantic Ocean - English Channel
+ France: F Mid-Atlantic Ocean - English Channel
+ If the 1982 or 2000 rulebook is used (which I prefer), it makes no difference that the convoying fleets
+ are not English. It will take the convoy via the North Sea anyway and the army in London will end in
+ Belgium. However, when the 1971 rules are used, the situation is different. Since both the fleet in the
+ English Channel as the fleet in North Sea are not English, it can not be concluded that the German fleet
+ is "unwanted". Therefore, one of the routes of the convoy is disrupted and that means that the complete
+ convoy is disrupted. The army in London will stay in London. See also issue 4.A.1.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LON'])
+ self.set_units(game, 'GERMANY', ['F ENG'])
+ self.set_units(game, 'RUSSIA', ['F NTH'])
+ self.set_units(game, 'FRANCE', ['F BRE', 'F MAO'])
+ self.set_orders(game, 'ENGLAND', 'A LON - BEL')
+ self.set_orders(game, 'GERMANY', 'F ENG C A LON - BEL')
+ self.set_orders(game, 'RUSSIA', 'F NTH C A LON - BEL')
+ self.set_orders(game, 'FRANCE', ['F BRE S F MAO - ENG', 'F MAO - ENG'])
+ self.process(game)
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F BRE', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert check_dislodged(game, 'F ENG', 'F MAO')
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'RUSSIA'
+ assert self.owner_name(game, 'F BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') is None
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+
+ def test_6_f_12(self):
+ """ 6.F.12. TEST CASE, DISLODGED CONVOYING FLEET NOT ON ROUTE
+ When the rule is used that convoys are disrupted when one of the routes is disrupted (see issue 4.A.1),
+ the convoy is not necessarily disrupted when one of the fleets ordered to convoy is dislodged.
+ England: F English Channel Convoys A London - Belgium
+ England: A London - Belgium
+ England: F Irish Sea Convoys A London - Belgium
+ France: F North Atlantic Ocean Supports F Mid-Atlantic Ocean - Irish Sea
+ France: F Mid-Atlantic Ocean - Irish Sea
+ Even when convoys are disrupted when one of the routes is disrupted (see issue 4.A.1), the convoy from
+ London to Belgium will still succeed, since the dislodged fleet in the Irish Sea is not part of any route,
+ although it can be reached from the starting point London.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F ENG', 'A LON', 'F IRI'])
+ self.set_units(game, 'FRANCE', ['F NAO', 'F MAO'])
+ self.set_orders(game, 'ENGLAND', ['F ENG C A LON - BEL', 'A LON - BEL', 'F IRI C A LON - BEL'])
+ self.set_orders(game, 'FRANCE', ['F NAO S F MAO - IRI', 'F MAO - IRI'])
+ self.process(game)
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F IRI', 'dislodged')
+ assert self.check_results(game, 'F NAO', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert check_dislodged(game, 'F IRI', 'F MAO')
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F IRI') == 'FRANCE'
+ assert self.owner_name(game, 'F NAO') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') is None
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+
+ def test_6_f_13(self):
+ """ 6.F.13. TEST CASE, THE UNWANTED ALTERNATIVE
+ This situation is not difficult to adjudicate, but it shows that even if someone wants to convoy, the
+ player might not want an alternative route for the convoy.
+ England: A London - Belgium
+ England: F North Sea Convoys A London - Belgium
+ France: F English Channel Convoys A London - Belgium
+ Germany: F Holland Supports F Denmark - North Sea
+ Germany: F Denmark - North Sea
+ If France and German are allies, England want to keep its army in London, to defend the island. An army
+ in Belgium could easily be destroyed by an alliance of France and Germany. England tries to be friends with
+ Germany, however France and Germany trick England.
+ The convoy of the army in London succeeds and the fleet in Denmark dislodges the fleet in the North Sea.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LON', 'F NTH'])
+ self.set_units(game, 'FRANCE', 'F ENG')
+ self.set_units(game, 'GERMANY', ['F HOL', 'F DEN'])
+ self.set_orders(game, 'ENGLAND', ['A LON - BEL', 'F NTH C A LON - BEL'])
+ self.set_orders(game, 'FRANCE', 'F ENG C A LON - BEL')
+ self.set_orders(game, 'GERMANY', ['F HOL S F DEN - NTH', 'F DEN - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F NTH', 'dislodged')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'F HOL', '')
+ assert self.check_results(game, 'F DEN', '')
+ assert check_dislodged(game, 'F NTH', 'F DEN')
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F DEN') is None
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+
+ def test_6_f_14(self):
+ """ 6.F.14. TEST CASE, SIMPLE CONVOY PARADOX
+ The most common paradox is when the attacked unit supports an attack on one of the convoying fleets.
+ England: F London Supports F Wales - English Channel
+ England: F Wales - English Channel
+ France: A Brest - London
+ France: F English Channel Convoys A Brest - London
+ This situation depends on how paradoxes are handled (see issue (4.A.2). In case of the 'All Hold' rule
+ (fully applied, not just as "backup" rule), both the movement of the English fleet in Wales as the France
+ convoy in Brest are part of the paradox and fail. In all other rules of paradoxical convoys (including the
+ Szykman rule which I prefer), the support of London is not cut. That means that the fleet in the English
+ Channel is dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON', 'F WAL'])
+ self.set_units(game, 'FRANCE', ['A BRE', 'F ENG'])
+ self.set_orders(game, 'ENGLAND', ['F LON S F WAL - ENG', 'F WAL - ENG'])
+ self.set_orders(game, 'FRANCE', ['A BRE - LON', 'F ENG C A BRE - LON'])
+ self.process(game)
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'F WAL', '')
+ assert self.check_results(game, 'A BRE', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert check_dislodged(game, 'F ENG', 'F WAL')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F WAL') is None
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+
+ def test_6_f_15(self):
+ """ 6.F.15. TEST CASE, SIMPLE CONVOY PARADOX WITH ADDITIONAL CONVOY
+ Paradox rules only apply on the paradox core.
+ England: F London Supports F Wales - English Channel
+ England: F Wales - English Channel
+ France: A Brest - London
+ France: F English Channel Convoys A Brest - London
+ Italy: F Irish Sea Convoys A North Africa - Wales
+ Italy: F Mid-Atlantic Ocean Convoys A North Africa - Wales
+ Italy: A North Africa - Wales
+ The Italian convoy is not part of the paradox core and should therefore succeed when the move of the
+ fleet in Wales is successful. This is the case except when the 'All Hold' paradox rule is used (fully
+ applied, not just as "backup" rule, see issue 4.A.2).
+ I prefer the Szykman rule, so I prefer that both the fleet in Wales as the army in North Africa succeed in
+ moving.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON', 'F WAL'])
+ self.set_units(game, 'FRANCE', ['A BRE', 'F ENG'])
+ self.set_units(game, 'ITALY', ['F IRI', 'F MAO', 'A NAF'])
+ self.set_orders(game, 'ENGLAND', ['F LON S F WAL - ENG', 'F WAL - ENG'])
+ self.set_orders(game, 'FRANCE', ['A BRE - LON', 'F ENG C A BRE - LON'])
+ self.set_orders(game, 'ITALY', ['F IRI C A NAF - WAL', 'F MAO C A NAF - WAL', 'A NAF - WAL'])
+ self.process(game)
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'F WAL', '')
+ assert self.check_results(game, 'A BRE', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F IRI', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'A NAF', '')
+ assert check_dislodged(game, 'F ENG', 'F WAL')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'A WAL') == 'ITALY'
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'F IRI') == 'ITALY'
+ assert self.owner_name(game, 'F MAO') == 'ITALY'
+ assert self.owner_name(game, 'A NAF') is None
+
+ def test_6_f_16(self):
+ """ 6.F.16. TEST CASE, PANDIN'S PARADOX
+ In Pandin's paradox, the attacked unit protects the convoying fleet by a beleaguered garrison.
+ England: F London Supports F Wales - English Channel
+ England: F Wales - English Channel
+ France: A Brest - London
+ France: F English Channel Convoys A Brest - London
+ Germany: F North Sea Supports F Belgium - English Channel
+ Germany: F Belgium - English Channel
+ In all the different rules for resolving convoy disruption paradoxes (see issue 4.A.2), the support
+ of London is not cut. That means that the fleet in the English Channel is not dislodged and none of the
+ units succeed to move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON', 'F WAL'])
+ self.set_units(game, 'FRANCE', ['A BRE', 'F ENG'])
+ self.set_units(game, 'GERMANY', ['F NTH', 'F BEL'])
+ self.set_orders(game, 'ENGLAND', ['F LON S F WAL - ENG', 'F WAL - ENG'])
+ self.set_orders(game, 'FRANCE', ['A BRE - LON', 'F ENG C A BRE - LON'])
+ self.set_orders(game, 'GERMANY', ['F NTH S F BEL - ENG', 'F BEL - ENG'])
+ self.process(game)
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'F WAL', 'bounce')
+ assert self.check_results(game, 'A BRE', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'disrupted')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F BEL', 'bounce')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F WAL') == 'ENGLAND'
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'F BEL') == 'GERMANY'
+
+ def test_6_f_17(self):
+ """ 6.F.17. TEST CASE, PANDIN'S EXTENDED PARADOX
+ In Pandin's extended paradox, the attacked unit protects the convoying fleet by a beleaguered garrison and
+ the attacked unit can dislodge the unit that gives the protection.
+ England: F London Supports F Wales - English Channel
+ England: F Wales - English Channel
+ France: A Brest - London
+ France: F English Channel Convoys A Brest - London
+ France: F Yorkshire Supports A Brest - London
+ Germany: F North Sea Supports F Belgium - English Channel
+ Germany: F Belgium - English Channel
+ When the 1971, 1982 or 2000 rule is used (see issue 4.A.2), the support of London is not cut. That means
+ that the fleet in the English Channel is not dislodged. The convoy will succeed and dislodge the fleet in
+ London. You may argue that this violates the dislodge rule, but the common interpretation is that the
+ paradox convoy rules take precedence over the dislodge rule.
+ If the Simon Szykman alternative is used (which I prefer), the convoy fails and the fleet in London and
+ the English Channel are not dislodged. When the 'All Hold' (fully applied, not just as "backup" rule) or
+ the DPTG rule is used, the result is the same as the Simon Szykman alternative. The involved moves (the
+ move of the German fleet in Belgium and the convoying army in Brest) fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F LON', 'F WAL'])
+ self.set_units(game, 'FRANCE', ['A BRE', 'F ENG', 'F YOR'])
+ self.set_units(game, 'GERMANY', ['F NTH', 'F BEL'])
+ self.set_orders(game, 'ENGLAND', ['F LON S F WAL - ENG', 'F WAL - ENG'])
+ self.set_orders(game, 'FRANCE', ['A BRE - LON', 'F ENG C A BRE - LON', 'F YOR S A BRE - LON'])
+ self.set_orders(game, 'GERMANY', ['F NTH S F BEL - ENG', 'F BEL - ENG'])
+ self.process(game)
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'F WAL', 'bounce')
+ assert self.check_results(game, 'A BRE', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'disrupted')
+ assert self.check_results(game, 'F YOR', 'no convoy')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F BEL', 'bounce')
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F WAL') == 'ENGLAND'
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F YOR') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'F BEL') == 'GERMANY'
+
+ def test_6_f_18(self):
+ """ 6.F.18. TEST CASE, BETRAYAL PARADOX
+ The betrayal paradox is comparable to Pandin's paradox, but now the attacked unit direct supports the
+ convoying fleet. Of course, this will only happen when the player of the attacked unit is betrayed.
+ England: F North Sea Convoys A London - Belgium
+ England: A London - Belgium
+ England: F English Channel Supports A London - Belgium
+ France: F Belgium Supports F North Sea
+ Germany: F Helgoland Bight Supports F Skagerrak - North Sea
+ Germany: F Skagerrak - North Sea
+ If the English convoy from London to Belgium is successful, then it cuts the France support necessary to
+ hold the fleet in the North Sea (see issue 4.A.2).
+ The 1971 and 2000 ruling do not give an answer on this.
+ According to the 1982 ruling the French support on the North Sea will not be cut. So, the fleet in the
+ North Sea will not be dislodged by the Germans and the army in London will dislodge the French army in
+ Belgium.
+ If the Szykman rule is followed (which I prefer), the move of the army in London will fail and will not cut
+ support. That means that the fleet in the North Sea will not be dislodged. The 'All Hold' rule has the same
+ result as the Szykman rule, but with a different reason. The move of the army in London and the move of the
+ German fleet in Skagerrak will fail. Since a failing convoy does not result in a consistent resolution,
+ the DPTG gives the same result as the 'All Hold' rule.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A LON', 'F ENG'])
+ self.set_units(game, 'FRANCE', ['F BEL'])
+ self.set_units(game, 'GERMANY', ['F HEL', 'F SKA'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - BEL', 'A LON - BEL', 'F ENG S A LON - BEL'])
+ self.set_orders(game, 'FRANCE', ['F BEL S F NTH'])
+ self.set_orders(game, 'GERMANY', ['F HEL S F SKA - NTH', 'F SKA - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'disrupted')
+ assert self.check_results(game, 'A LON', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'no convoy')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F SKA', 'bounce')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'F BEL') == 'FRANCE'
+ assert self.owner_name(game, 'F HEL') == 'GERMANY'
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+
+ def test_6_f_19(self):
+ """ 6.F.19. TEST CASE, MULTI-ROUTE CONVOY DISRUPTION PARADOX
+ The situation becomes more complex when the convoy has alternative routes.
+ France: A Tunis - Naples
+ France: F Tyrrhenian Sea Convoys A Tunis - Naples
+ France: F Ionian Sea Convoys A Tunis - Naples
+ Italy: F Naples Supports F Rome - Tyrrhenian Sea
+ Italy: F Rome - Tyrrhenian Sea
+ Now, two issues play a role. The ruling about disruption of convoys (issue 4.A.1) and the issue how
+ paradoxes are resolved (issue 4.A.2).
+ If the 1971 rule is used about multi-route convoys (when one of the routes is disrupted, the convoy fails),
+ this test case is just a simple paradox. For the 1971, 1982, 2000 and Szykman paradox rule, the support of
+ the fleet in Naples is not cut and the fleet in Rome dislodges the fleet in the Tyrrhenian Sea. When the
+ 'All Hold' rule is used, both the convoy of the army in Tunis as the move of the fleet in Rome will fail.
+ When the 1982 rule is used about multi-route convoy disruption, then convoys are disrupted when all routes
+ are disrupted (this is the rule I prefer). With this rule, the situation becomes paradoxical. According to
+ the 1971 and 1982 paradox rules, the support given by the fleet in Naples is not cut, that means that the
+ fleet in the Tyrrhenian Sea is dislodged.
+ According to the 2000 ruling the fleet in the Tyrrhenian Sea is not "necessary" for the convoy and the
+ support of Naples is cut and the fleet in the Tyrrhenian Sea is not dislodged.
+ If the Szykman rule is used (which I prefer), the 'All Hold' rule or the DPTG, then there is no paradoxical
+ situation. The support of Naples is cut and the fleet in the Tyrrhenian Sea is not dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['A TUN', 'F TYS', 'F ION'])
+ self.set_units(game, 'ITALY', ['F NAP', 'F ROM'])
+ self.set_orders(game, 'FRANCE', ['A TUN - NAP', 'F TYS C A TUN - NAP', 'F ION C A TUN - NAP'])
+ self.set_orders(game, 'ITALY', ['F NAP S F ROM - TYS', 'F ROM - TYS'])
+ self.process(game)
+ assert self.check_results(game, 'A TUN', 'bounce')
+ assert self.check_results(game, 'F TYS', '')
+ assert self.check_results(game, 'F ION', '')
+ assert self.check_results(game, 'F NAP', 'cut')
+ assert self.check_results(game, 'F ROM', 'bounce')
+ assert self.owner_name(game, 'A TUN') == 'FRANCE'
+ assert self.owner_name(game, 'F TYS') == 'FRANCE'
+ assert self.owner_name(game, 'F ION') == 'FRANCE'
+ assert self.owner_name(game, 'F NAP') == 'ITALY'
+ assert self.owner_name(game, 'F ROM') == 'ITALY'
+
+ def test_6_f_20(self):
+ """ 6.F.20. TEST CASE, UNWANTED MULTI-ROUTE CONVOY PARADOX
+ The 1982 paradox rule allows some creative defense.
+ France: A Tunis - Naples
+ France: F Tyrrhenian Sea Convoys A Tunis - Naples
+ Italy: F Naples Supports F Ionian Sea
+ Italy: F Ionian Sea Convoys A Tunis - Naples
+ Turkey: F Aegean Sea Supports F Eastern Mediterranean - Ionian Sea
+ Turkey: F Eastern Mediterranean - Ionian Sea
+ Again, two issues play a role. The ruling about disruption of multi-route convoys (issue 4.A.1) and the
+ issue how paradoxes are resolved (issue 4.A.2).
+ If the 1971 rule is used about multi-route convoys (when one of the routes is disrupted, the convoy fails),
+ the Italian convoy order in the Ionian Sea is not part of the convoy, because it is a foreign unit
+ (according to the DPTG).
+ That means that the fleet in the Ionian Sea is not a 'convoying' fleet. In all rulings the support of
+ Naples on the Ionian Sea is cut and the fleet in the Ionian Sea is dislodged by the Turkish fleet in the
+ Eastern Mediterranean. When the 1982 rule is used about multi-route convoy disruption, then convoys are
+ disrupted when all routes are disrupted (this is the rule I prefer). With this rule, the situation becomes
+ paradoxical. According to the 1971 and 1982 paradox rules, the support given by the fleet in Naples is not
+ cut, that means that the fleet in the Ionian Sea is not dislodged.
+ According to the 2000 ruling the fleet in the Ionian Sea is not "necessary" and the support of Naples is
+ cut and the fleet in the Ionian Sea is dislodged by the Turkish fleet in the Eastern Mediterranean.
+ If the Szykman rule, the 'All Hold' rule or DPTG is used, then there is no paradoxical situation. The
+ support of Naples is cut and the fleet in the Ionian Sea is dislodged by the Turkish fleet in the Eastern
+ Mediterranean. As you can see, the 1982 rules allows the Italian player to save its fleet in the Ionian Sea
+ with a trick. I do not consider this trick as normal tactical play. I prefer the Szykman rule as one of the
+ rules that does not allow this trick. According to this rule the fleet in the Ionian Sea is dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['A TUN', 'F TYS'])
+ self.set_units(game, 'ITALY', ['F NAP', 'F ION'])
+ self.set_units(game, 'TURKEY', ['F AEG', 'F EAS'])
+ self.set_orders(game, 'FRANCE', ['A TUN - NAP', 'F TYS C A TUN - NAP'])
+ self.set_orders(game, 'ITALY', ['F NAP S F ION', 'F ION C A TUN - NAP'])
+ self.set_orders(game, 'TURKEY', ['F AEG S F EAS - ION', 'F EAS - ION'])
+ self.process(game)
+ assert self.check_results(game, 'A TUN', 'bounce')
+ assert self.check_results(game, 'F TYS', '')
+ assert self.check_results(game, 'F NAP', 'cut')
+ assert self.check_results(game, 'F ION', 'dislodged')
+ assert self.check_results(game, 'F AEG', '')
+ assert self.check_results(game, 'F EAS', '')
+ assert check_dislodged(game, 'F ION', 'F EAS')
+ assert self.owner_name(game, 'A TUN') == 'FRANCE'
+ assert self.owner_name(game, 'F TYS') == 'FRANCE'
+ assert self.owner_name(game, 'F NAP') == 'ITALY'
+ assert self.owner_name(game, 'F ION') == 'TURKEY'
+ assert self.owner_name(game, 'F AEG') == 'TURKEY'
+ assert self.owner_name(game, 'F EAS') is None
+
+ def test_6_f_21(self):
+ """ 6.F.21. TEST CASE, DAD'S ARMY CONVOY
+ The 1982 paradox rule has as side effect that convoying armies do not cut support in some situations that
+ are not paradoxical.
+ Russia: A Edinburgh Supports A Norway - Clyde
+ Russia: F Norwegian Sea Convoys A Norway - Clyde
+ Russia: A Norway - Clyde
+ France: F Irish Sea Supports F Mid-Atlantic Ocean - North Atlantic Ocean
+ France: F Mid-Atlantic Ocean - North Atlantic Ocean
+ England: A Liverpool - Clyde via Convoy
+ England: F North Atlantic Ocean Convoys A Liverpool - Clyde
+ England: F Clyde Supports F North Atlantic Ocean
+ In all rulings, except the 1982 paradox ruling, the support of the fleet in Clyde on the North Atlantic
+ Ocean is cut and the French fleet in the Mid-Atlantic Ocean will dislodge the fleet in the North Atlantic
+ Ocean. This is the preferred way. However, in the 1982 paradox rule (see issue 4.A.2), the support of the
+ fleet in Clyde is not cut. That means that the English fleet in the North Atlantic Ocean is not dislodged.
+ As you can see, the 1982 rule allows England to save its fleet in the North Atlantic Ocean in a very
+ strange way. Just the support of Clyde is insufficient (if there is no convoy, the support is cut). Only
+ the convoy to the area occupied by own unit, can do the trick in this situation. The embarking of troops
+ in the fleet deceives the enemy so much that it works as a magic cloak. The enemy is not able to dislodge
+ the fleet in the North Atlantic Ocean any more. Of course, this will only work in comedies. I prefer the
+ Szykman rule as one of the rules that does not allow this trick. According to this rule (and all other
+ paradox rules), the fleet in the North Atlantic is just dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'RUSSIA', ['A EDI', 'F NWG', 'A NWY'])
+ self.set_units(game, 'FRANCE', ['F IRI', 'F MAO'])
+ self.set_units(game, 'ENGLAND', ['A LVP', 'F NAO', 'F CLY'])
+ self.set_orders(game, 'RUSSIA', ['A EDI S A NWY - CLY', 'F NWG C A NWY - CLY', 'A NWY - CLY'])
+ self.set_orders(game, 'FRANCE', ['F IRI S F MAO - NAO', 'F MAO - NAO'])
+ self.set_orders(game, 'ENGLAND', ['A LVP - CLY VIA', 'F NAO C A LVP - CLY', 'F CLY S F NAO'])
+ self.process(game)
+ assert self.check_results(game, 'A EDI', '')
+ assert self.check_results(game, 'F NWG', '')
+ assert self.check_results(game, 'A NWY', '')
+ assert self.check_results(game, 'F IRI', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'A LVP', 'no convoy')
+ assert self.check_results(game, 'F NAO', 'dislodged')
+ assert self.check_results(game, 'F CLY', 'cut')
+ assert self.check_results(game, 'F CLY', 'dislodged')
+ assert check_dislodged(game, 'F NAO', 'F MAO')
+ assert check_dislodged(game, 'F CLY', 'A NWY')
+ assert self.owner_name(game, 'A EDI') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWG') == 'RUSSIA'
+ assert self.owner_name(game, 'A NWY') is None
+ assert self.owner_name(game, 'F IRI') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') is None
+ assert self.owner_name(game, 'A LVP') == 'ENGLAND'
+ assert self.owner_name(game, 'F NAO') == 'FRANCE'
+ assert self.owner_name(game, 'A CLY') == 'RUSSIA'
+
+ def test_6_f_22(self):
+ """ 6.F.22. TEST CASE, SECOND ORDER PARADOX WITH TWO RESOLUTIONS
+ Two convoys are involved in a second order paradox.
+ England: F Edinburgh - North Sea
+ England: F London Supports F Edinburgh - North Sea
+ France: A Brest - London
+ France: F English Channel Convoys A Brest - London
+ Germany: F Belgium Supports F Picardy - English Channel
+ Germany: F Picardy - English Channel
+ Russia: A Norway - Belgium
+ Russia: F North Sea Convoys A Norway - Belgium
+ Without any paradox rule, there are two consistent resolutions. The supports of the English fleet in London
+ and the German fleet in Picardy are not cut. That means that the French fleet in the English Channel and
+ the Russian fleet in the North Sea are dislodged, which makes it impossible to cut the support. The other
+ resolution is that the supports of the English fleet in London the German fleet in Picardy are cut. In that
+ case the French fleet in the English Channel and the Russian fleet in the North Sea will survive and will
+ not be dislodged. This gives the possibility to cut the support.
+ The 1971 paradox rule and the 2000 rule (see issue 4.A.2) do not have an answer on this.
+ According to the 1982 rule, the supports are not cut which means that the French fleet in the English
+ Channel and the Russian fleet in the North Sea are dislodged.
+ The Szykman (which I prefer), has the same result as the 1982 rule. The supports are not cut, the convoying
+ armies fail to move, the fleet in Picardy dislodges the fleet in English Channel and the fleet in Edinburgh
+ dislodges the fleet in the North Sea.
+ The DPTG rule has in this case the same result as the Szykman rule, because the failing of all convoys is a
+ consistent resolution. So, the armies in Brest and Norway fail to move, while the fleets in Edinburgh and
+ Picardy succeed to move. When the 'All Hold' rule is used, the movement of the armies in Brest and Norway
+ as the fleets in Edinburgh and Picardy will fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F EDI', 'F LON'])
+ self.set_units(game, 'FRANCE', ['A BRE', 'F ENG'])
+ self.set_units(game, 'GERMANY', ['F BEL', 'F PIC'])
+ self.set_units(game, 'RUSSIA', ['A NWY', 'F NTH'])
+ self.set_orders(game, 'ENGLAND', ['F EDI - NTH', 'F LON S F EDI - NTH'])
+ self.set_orders(game, 'FRANCE', ['A BRE - LON', 'F ENG C A BRE - LON'])
+ self.set_orders(game, 'GERMANY', ['F BEL S F PIC - ENG', 'F PIC - ENG'])
+ self.set_orders(game, 'RUSSIA', ['A NWY - BEL', 'F NTH C A NWY - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F EDI', '')
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'A BRE', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'F PIC', '')
+ assert self.check_results(game, 'A NWY', 'no convoy')
+ assert self.check_results(game, 'F NTH', 'dislodged')
+ assert check_dislodged(game, 'F ENG', 'F PIC')
+ assert check_dislodged(game, 'F NTH', 'F EDI')
+ assert self.owner_name(game, 'F EDI') is None
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'GERMANY'
+ assert self.owner_name(game, 'F BEL') == 'GERMANY'
+ assert self.owner_name(game, 'F PIC') is None
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+
+ def test_6_f_23(self):
+ """ 6.F.23. TEST CASE, SECOND ORDER PARADOX WITH TWO EXCLUSIVE CONVOYS
+ In this paradox there are two consistent resolutions, but where the two convoys do not fail or succeed at
+ the same time. This fact is important for the DPTG resolution.
+ England: F Edinburgh - North Sea
+ England: F Yorkshire Supports F Edinburgh - North Sea
+ France: A Brest - London
+ France: F English Channel Convoys A Brest - London
+ Germany: F Belgium Supports F English Channel
+ Germany: F London Supports F North Sea
+ Italy: F Mid-Atlantic Ocean - English Channel
+ Italy: F Irish Sea Supports F Mid-Atlantic Ocean - English Channel
+ Russia: A Norway - Belgium
+ Russia: F North Sea Convoys A Norway - Belgium
+ Without any paradox rule, there are two consistent resolutions. In one resolution, the convoy in the
+ English Channel is dislodged by the fleet in the Mid-Atlantic Ocean, while the convoy in the North Sea
+ succeeds. In the other resolution, it is the other way around. The convoy in the North Sea is dislodged by
+ the fleet in Edinburgh, while the convoy in the English Channel succeeds.
+ The 1971 paradox rule and the 2000 rule (see issue 4.A.2) do not have an answer on this.
+ According to the 1982 rule, the supports are not cut which means that the none of the units move.
+ The Szykman (which I prefer), has the same result as the 1982 rule. The convoying armies fail to move and
+ the supports are not cut. Because of the failure to cut the support, no fleet succeeds to move.
+ When the 'All Hold' rule is used, the movement of the armies and the fleets all fail.
+ Since there is no consistent resolution where all convoys fail, the DPTG rule has the same result as the
+ 'All Hold' rule. That means the movement of all units fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F EDI', 'F YOR'])
+ self.set_units(game, 'FRANCE', ['A BRE', 'F ENG'])
+ self.set_units(game, 'GERMANY', ['F BEL', 'F LON'])
+ self.set_units(game, 'ITALY', ['F MAO', 'F IRI'])
+ self.set_units(game, 'RUSSIA', ['A NWY', 'F NTH'])
+ self.set_orders(game, 'ENGLAND', ['F EDI - NTH', 'F YOR S F EDI - NTH'])
+ self.set_orders(game, 'FRANCE', ['A BRE - LON', 'F ENG C A BRE - LON'])
+ self.set_orders(game, 'GERMANY', ['F BEL S F ENG', 'F LON S F NTH'])
+ self.set_orders(game, 'ITALY', ['F MAO - ENG', 'F IRI S F MAO - ENG'])
+ self.set_orders(game, 'RUSSIA', ['A NWY - BEL', 'F NTH C A NWY - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F EDI', 'bounce')
+ assert self.check_results(game, 'F YOR', '')
+ assert self.check_results(game, 'A BRE', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'disrupted')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'F MAO', 'bounce')
+ assert self.check_results(game, 'F IRI', '')
+ assert self.check_results(game, 'A NWY', 'no convoy')
+ assert self.check_results(game, 'F NTH', 'disrupted')
+ assert self.owner_name(game, 'F EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F BEL') == 'GERMANY'
+ assert self.owner_name(game, 'F LON') == 'GERMANY'
+ assert self.owner_name(game, 'F MAO') == 'ITALY'
+ assert self.owner_name(game, 'F IRI') == 'ITALY'
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'F NTH') == 'RUSSIA'
+
+ def test_6_f_24(self):
+ """ 6.F.24. TEST CASE, SECOND ORDER PARADOX WITH NO RESOLUTION
+ As first order paradoxes, second order paradoxes come in two flavors, with two resolutions or no resolution.
+ England: F Edinburgh - North Sea
+ England: F London Supports F Edinburgh - North Sea
+ England: F Irish Sea - English Channel
+ England: F Mid-Atlantic Ocean Supports F Irish Sea - English Channel
+ France: A Brest - London
+ France: F English Channel Convoys A Brest - London
+ France: F Belgium Supports F English Channel
+ Russia: A Norway - Belgium
+ Russia: F North Sea Convoys A Norway - Belgium
+ When no paradox rule is used, there is no consistent resolution. If the French support in Belgium is cut,
+ the French fleet in the English Channel will be dislodged. That means that the support of London will not
+ be cut and the fleet in Edinburgh will dislodge the Russian fleet in the North Sea. In this way the support
+ in Belgium is not cut! But if the support in Belgium is not cut, the Russian fleet in the North Sea will
+ not be dislodged and the army in Norway can cut the support in Belgium.
+ The 1971 paradox rule and the 2000 rule (see issue 4.A.2) do not have an answer on this. According to the
+ 1982 rule, the supports are not cut which means that the French fleet in the English Channel will survive
+ and but the Russian fleet in the North Sea is dislodged.
+ If the Szykman alternative is used (which I prefer), the supports are not cut and the convoying armies fail
+ to move, which has the same result as the 1982 rule in this case.
+ When the 'All Hold' rule is used, the movement of the armies in Brest and Norway as the fleets in Edinburgh
+ and the Irish Sea will fail. Since there is no consistent resolution where all convoys fail, the DPTG has
+ in this case the same result as the 'All Hold' rule.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F EDI', 'F LON', 'F IRI', 'F MAO'])
+ self.set_units(game, 'FRANCE', ['A BRE', 'F ENG', 'F BEL'])
+ self.set_units(game, 'RUSSIA', ['A NWY', 'F NTH'])
+ self.set_orders(game, 'ENGLAND', ['F EDI - NTH', 'F LON S F EDI - NTH', 'F IRI - ENG', 'F MAO S F IRI - ENG'])
+ self.set_orders(game, 'FRANCE', ['A BRE - LON', 'F ENG C A BRE - LON', 'F BEL S F ENG'])
+ self.set_orders(game, 'RUSSIA', ['A NWY - BEL', 'F NTH C A NWY - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F EDI', '')
+ assert self.check_results(game, 'F LON', '')
+ assert self.check_results(game, 'F IRI', 'bounce')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'A BRE', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'disrupted')
+ assert self.check_results(game, 'F BEL', '')
+ assert self.check_results(game, 'A NWY', 'no convoy')
+ assert self.check_results(game, 'F NTH', 'dislodged')
+ assert check_dislodged(game, 'F NTH', 'F EDI')
+ assert self.owner_name(game, 'F EDI') is None
+ assert self.owner_name(game, 'F LON') == 'ENGLAND'
+ assert self.owner_name(game, 'F IRI') == 'ENGLAND'
+ assert self.owner_name(game, 'F MAO') == 'ENGLAND'
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F BEL') == 'FRANCE'
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+
+ # 6.G. TEST CASES, CONVOYING TO ADJACENT PLACES
+ def test_6_g_1(self):
+ """ 6.G.1. TEST CASE, TWO UNITS CAN SWAP PLACES BY CONVOY
+ The only way to swap two units, is by convoy.
+ England: A Norway - Sweden
+ England: F Skagerrak Convoys A Norway - Sweden
+ Russia: A Sweden - Norway
+ In most interpretation of the rules, the units in Norway and Sweden will be swapped. However, if
+ explicit adjacent convoying is used (see issue 4.A.3), then it is just a head to head battle.
+ I prefer the 2000 rules, so the units are swapped.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A NWY', 'F SKA'])
+ self.set_units(game, 'RUSSIA', ['A SWE'])
+ self.set_orders(game, 'ENGLAND', ['A NWY - SWE', 'F SKA C A NWY - SWE'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'A NWY', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'A SWE', '')
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'F SKA') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'ENGLAND'
+
+ def test_6_g_2(self):
+ """ 6.G.2. TEST CASE, KIDNAPPING AN ARMY
+ Germany promised England to support to dislodge the Russian fleet in Sweden and it promised Russia to
+ support to dislodge the English army in Norway. Instead, the joking German orders a convoy.
+ England: A Norway - Sweden
+ Russia: F Sweden - Norway
+ Germany: F Skagerrak Convoys A Norway - Sweden
+ See issue 4.A.3.
+ When the 1982/2000 rulebook is used (which I prefer), England has no intent to swap and it is just a head
+ to head battle were both units will fail to move. When explicit adjacent convoying is used (DPTG), the
+ English move is not a convoy and again it just a head to head battle were both units will fail to move.
+ In all other interpretations, the army in Norway will be convoyed and swap its place with the fleet in
+ Sweden.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', 'A NWY')
+ self.set_units(game, 'RUSSIA', 'F SWE')
+ self.set_units(game, 'GERMANY', 'F SKA')
+ self.set_orders(game, 'ENGLAND', 'A NWY - SWE')
+ self.set_orders(game, 'RUSSIA', 'F SWE - NWY')
+ self.set_orders(game, 'GERMANY', 'F SKA C A NWY - SWE')
+ self.process(game)
+ assert self.check_results(game, 'A NWY', 'bounce')
+ assert self.check_results(game, 'F SWE', 'bounce')
+ assert self.check_results(game, 'F SKA', 'no convoy')
+ assert self.owner_name(game, 'A NWY') == 'ENGLAND'
+ assert self.owner_name(game, 'F SWE') == 'RUSSIA'
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+
+ def test_6_g_3(self):
+ """ 6.G.3. TEST CASE, KIDNAPPING WITH A DISRUPTED CONVOY
+ When kidnapping of armies is allowed, a move can be sabotaged by a fleet that is almost certainly dislodged.
+ France: F Brest - English Channel
+ France: A Picardy - Belgium
+ France: A Burgundy Supports A Picardy - Belgium
+ France: F Mid-Atlantic Ocean Supports F Brest - English Channel
+ England: F English Channel Convoys A Picardy - Belgium
+ See issue 4.A.3. If a convoy always takes precedence over a land route (choice a), the move from Picardy to
+ Belgium fails. It tries to convoy and the convoy is disrupted.
+ For choice b and c, there is no unit moving in opposite direction for the move of the army in Picardy.
+ For this reason, the move for the army in Picardy is not by convoy and succeeds over land.
+ When the 1982 or 2000 rules are used (choice d), then it is not the "intent" of the French army in Picardy
+ to convoy. The move from Picardy to Belgium is just a successful move over land.
+ When explicit adjacent convoying is used (DPTG, choice e), the order of the French army in Picardy is not
+ a convoy order. So, it just ordered over land, and that move succeeds. This is an excellent example why
+ the convoy route should not automatically have priority over the land route. It would just be annoying for
+ the attacker and this situation is without fun. I prefer the 1982 rule with the 2000 clarification.
+ According to these rules the move from Picardy succeeds.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F BRE', 'A PIC', 'A BUR', 'F MAO'])
+ self.set_units(game, 'ENGLAND', ['F ENG'])
+ self.set_orders(game, 'FRANCE', ['F BRE - ENG', 'A PIC - BEL', 'A BUR S A PIC - BEL', 'F MAO S F BRE - ENG'])
+ self.set_orders(game, 'ENGLAND', ['F ENG C A PIC - BEL'])
+ self.process(game)
+ assert self.check_results(game, 'F BRE', '')
+ assert self.check_results(game, 'A PIC', '')
+ assert self.check_results(game, 'A BUR', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F ENG', 'no convoy')
+ assert check_dislodged(game, 'F ENG', 'F BRE')
+ assert self.owner_name(game, 'F BRE') is None
+ assert self.owner_name(game, 'A PIC') is None
+ assert self.owner_name(game, 'A BUR') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A BEL') == 'FRANCE'
+
+ def test_6_g_4(self):
+ """ 6.G.4. TEST CASE, KIDNAPPING WITH A DISRUPTED CONVOY AND OPPOSITE MOVE
+ In the situation of the previous test case it was rather clear that the army didn't want to take the
+ convoy. But what if there is an army moving in opposite direction?
+ France: F Brest - English Channel
+ France: A Picardy - Belgium
+ France: A Burgundy Supports A Picardy - Belgium
+ France: F Mid-Atlantic Ocean Supports F Brest - English Channel
+ England: F English Channel Convoys A Picardy - Belgium
+ England: A Belgium - Picardy
+ See issue 4.A.3. If a convoy always takes precedence over a land route (choice a), the move from Picardy to
+ Belgium fails. It tries to convoy and the convoy is disrupted.
+ For choice b the convoy is also taken, because there is a unit in Belgium moving in opposite direction.
+ This means that the convoy is disrupted and the move from Picardy to Belgium fails.
+ For choice c the convoy is not taken. Although, the unit in Belgium is moving in opposite direction,
+ the army will not take a disrupted convoy. So, the move from Picardy to Belgium succeeds.
+ When the 1982 or 2000 rules are used (choice d), then it is not the "intent" of the French army in Picardy
+ to convoy. The move from Picardy to Belgium is just a successful move over land.
+ When explicit adjacent convoying is used (DPTG, choice e), the order of the French army in Picardy is not
+ a convoy order. So, it just ordered over land, and that move succeeds.
+ Again an excellent example why the convoy route should not automatically have priority over the land route.
+ It would just be annoying for the attacker and this situation is without fun. I prefer the 1982 rule with
+ the 2000 clarification. According to these rules the move from Picardy succeeds.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F BRE', 'A PIC', 'A BUR', 'F MAO'])
+ self.set_units(game, 'ENGLAND', ['F ENG', 'A BEL'])
+ self.set_orders(game, 'FRANCE', ['F BRE - ENG', 'A PIC - BEL', 'A BUR S A PIC - BEL', 'F MAO S F BRE - ENG'])
+ self.set_orders(game, 'ENGLAND', ['F ENG C A PIC - BEL', 'A BEL - PIC'])
+ self.process(game)
+ assert self.check_results(game, 'F BRE', '')
+ assert self.check_results(game, 'A PIC', '')
+ assert self.check_results(game, 'A BUR', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F ENG', 'no convoy')
+ assert self.check_results(game, 'A BEL', 'dislodged')
+ assert check_dislodged(game, 'F ENG', 'F BRE')
+ assert check_dislodged(game, 'A BEL', 'A PIC')
+ assert self.owner_name(game, 'F BRE') is None
+ assert self.owner_name(game, 'A PIC') is None
+ assert self.owner_name(game, 'A BUR') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A BEL') == 'FRANCE'
+
+ def test_6_g_5(self):
+ """ 6.G.5. TEST CASE, SWAPPING WITH INTENT
+ When one of the convoying fleets is of the same nationality of the convoyed army, the "intent" is to convoy.
+ Italy: A Rome - Apulia
+ Italy: F Tyrrhenian Sea Convoys A Apulia - Rome
+ Turkey: A Apulia - Rome
+ Turkey: F Ionian Sea Convoys A Apulia - Rome
+ See issue 4.A.3. When the 1982/2000 rulebook is used (which I prefer), the convoy depends on the "intent".
+ Since there is an own fleet in the convoy, the intent is to convoy and the armies in Rome and Apulia swap
+ places. For choices a, b and c of the issue there is also a convoy and the same swap takes place.
+ When explicit adjacent convoying is used (DPTG, choice e), then the Turkish army did not receive an order
+ to move by convoy. So, it is just a head to head battle and both the army in Rome and Apulia will not move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ITALY', ['A ROM', 'F TYS'])
+ self.set_units(game, 'TURKEY', ['A APU', 'F ION'])
+ self.set_orders(game, 'ITALY', ['A ROM - APU', 'F TYS C A APU - ROM'])
+ self.set_orders(game, 'TURKEY', ['A APU - ROM', 'F ION C A APU - ROM'])
+ self.process(game)
+ assert self.check_results(game, 'A ROM', '')
+ assert self.check_results(game, 'F TYS', '')
+ assert self.check_results(game, 'A APU', '')
+ assert self.check_results(game, 'F ION', '')
+ assert self.owner_name(game, 'A ROM') == 'TURKEY'
+ assert self.owner_name(game, 'F TYS') == 'ITALY'
+ assert self.owner_name(game, 'A APU') == 'ITALY'
+ assert self.owner_name(game, 'F ION') == 'TURKEY'
+
+ def test_6_g_6(self):
+ """ 6.G.6. TEST CASE, SWAPPING WITH UNINTENDED INTENT
+ The intent is questionable.
+ England: A Liverpool - Edinburgh
+ England: F English Channel Convoys A Liverpool - Edinburgh
+ Germany: A Edinburgh - Liverpool
+ France: F Irish Sea Hold
+ France: F North Sea Hold
+ Russia: F Norwegian Sea Convoys A Liverpool - Edinburgh
+ Russia: F North Atlantic Ocean Convoys A Liverpool - Edinburgh
+ See issue 4.A.3.
+ For choice a, b and c the English army in Liverpool will move by convoy and consequentially the two armies
+ are swapped. For choice d, the 1982/2000 rulebook (which I prefer), the convoy depends on the "intent".
+ England intended to convoy via the French fleets in the Irish Sea and the North Sea. However, the French
+ did not order the convoy. The alternative route with the Russian fleets was unintended. The English fleet
+ in the English Channel (with the convoy order) is not part of this alternative route with the Russian
+ fleets. Since England still "intent" to convoy, the move from Liverpool to Edinburgh should be via convoy
+ and the two armies are swapped. Although, you could argue that this is not really according to the
+ clarification of the 2000 rulebook. When explicit adjacent convoying is used (DPTG, choice e), then the
+ English army did not receive an order to move by convoy. So, it is just a head to head battle and both the
+ army in Edinburgh and Liverpool will not move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LVP', 'F ENG'])
+ self.set_units(game, 'GERMANY', ['A EDI'])
+ self.set_units(game, 'FRANCE', ['F IRI', 'F NTH'])
+ self.set_units(game, 'RUSSIA', ['F NWG', 'F NAO'])
+ self.set_orders(game, 'ENGLAND', ['A LVP - EDI', 'F ENG C A LVP - EDI'])
+ self.set_orders(game, 'GERMANY', ['A EDI - LVP'])
+ self.set_orders(game, 'FRANCE', ['F IRI H', 'F NTH H'])
+ self.set_orders(game, 'RUSSIA', ['F NWG C A LVP - EDI', 'F NAO C A LVP - EDI'])
+ self.process(game)
+ assert self.check_results(game, 'A LVP', '')
+ assert self.check_results(game, 'F ENG', 'no convoy')
+ assert self.check_results(game, 'A EDI', '')
+ assert self.check_results(game, 'F IRI', '')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F NWG', '')
+ assert self.check_results(game, 'F NAO', '')
+ assert self.owner_name(game, 'A LVP') == 'GERMANY'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'F IRI') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'FRANCE'
+ assert self.owner_name(game, 'F NWG') == 'RUSSIA'
+ assert self.owner_name(game, 'F NAO') == 'RUSSIA'
+
+ def test_6_g_7(self):
+ """ 6.G.7. TEST CASE, SWAPPING WITH ILLEGAL INTENT
+ Can the intent made clear with an impossible order?
+ England: F Skagerrak Convoys A Sweden - Norway
+ England: F Norway - Sweden
+ Russia: A Sweden - Norway
+ Russia: F Gulf of Bothnia Convoys A Sweden - Norway
+ See issue 4.A.3 and 4.E.1.
+ If for issue 4.A.3 choice a, b or c has been taken, then the army in Sweden moves by convoy and swaps
+ places with the fleet in Norway.
+ However, if for issue 4.A.3 the 1982/2000 has been chosen (choice d), then the "intent" is important.
+ The question is whether the fleet in the Gulf of Bothnia can express the intent. If the order for this
+ fleet is considered illegal (see issue 4.E.1), then this order must be ignored and there is no intent to
+ swap. In that case none of the units move. If explicit convoying is used (DPTG, choice e of issue 4.A.3)
+ then the army in Sweden will take the land route and none of the units move.
+ I prefer the 1982/2000 rule and that any orders that can't be valid are illegal. So, the order of the fleet
+ in the Gulf of Bothnia is ignored and can not show the intent. There is no convoy, so no unit will move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F SKA', 'F NWY'])
+ self.set_units(game, 'RUSSIA', ['A SWE', 'F BOT'])
+ self.set_orders(game, 'ENGLAND', ['F SKA C A SWE - NWY', 'F NWY - SWE'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY', 'F BOT C A SWE - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'F SKA', 'no convoy')
+ assert self.check_results(game, 'F NWY', 'bounce')
+ assert self.check_results(game, 'A SWE', 'bounce')
+ assert self.check_results(game, 'F BOT', 'void')
+ assert self.owner_name(game, 'F SKA') == 'ENGLAND'
+ assert self.owner_name(game, 'F NWY') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'RUSSIA'
+ assert self.owner_name(game, 'F BOT') == 'RUSSIA'
+
+ def test_6_g_8(self):
+ """ 6.G.8. TEST CASE, EXPLICIT CONVOY THAT ISN'T THERE
+ What to do when a unit is explicitly ordered to move via convoy and the convoy is not there?
+ France: A Belgium - Holland via Convoy
+ England: F North Sea - Helgoland Bight
+ England: A Holland - Kiel
+ The French army in Belgium intended to move convoyed with the English fleet in the North Sea. But the
+ English changed their plans.
+ See issue 4.A.3.
+ If choice a, b or c has been taken, then the 'via Convoy' directive has no meaning and the army in Belgium
+ will move to Holland. If the 1982/2000 rulebook is used (choice d, which I prefer), the "via Convoy" has
+ meaning, but only when there is both a land route and a convoy route. Since there is no convoy the
+ "via Convoy" directive should be ignored. And the move from Belgium to Holland succeeds.
+ If explicit adjacent convoying is used (DPTG, choice e), then the unit can only go by convoy. Since there
+ is no convoy, the move from Belgium to Holland fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['A BEL'])
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A HOL'])
+ self.set_orders(game, 'FRANCE', ['A BEL - HOL VIA'])
+ self.set_orders(game, 'ENGLAND', ['F NTH - HEL', 'A HOL - KIE'])
+ self.process(game)
+ assert self.check_results(game, 'A BEL', '')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A HOL', '')
+ assert self.owner_name(game, 'A BEL') is None
+ assert self.owner_name(game, 'F NTH') is None
+ assert self.owner_name(game, 'A HOL') == 'FRANCE'
+ assert self.owner_name(game, 'F HEL') == 'ENGLAND'
+ assert self.owner_name(game, 'A KIE') == 'ENGLAND'
+
+ def test_6_g_9(self):
+ """ 6.G.9. TEST CASE, SWAPPED OR DISLODGED?
+ The 1982 rulebook says that whether the move is over land or via convoy depends on the "intent" as shown
+ by the totality of the orders written by the player governing the army (see issue 4.A.3). In this test
+ case the English army in Norway will end in all cases in Sweden. But whether it is convoyed or not has
+ effect on the Russian army. In case of convoy the Russian army ends in Norway and in case of a land route
+ the Russian army is dislodged.
+ England: A Norway - Sweden
+ England: F Skagerrak Convoys A Norway - Sweden
+ England: F Finland Supports A Norway - Sweden
+ Russia: A Sweden - Norway
+ See issue 4.A.3.
+ For choice a, b and c the move of the army in Norway is by convoy and the armies in Norway and Sweden are
+ swapped. If the 1982 rulebook is used with the clarification of the 2000 rulebook (choice d, which I
+ prefer), the intent of the English player is to convoy, since it ordered the fleet in Skagerrak to convoy.
+ Therefore, the armies in Norway and Sweden are swapped. When explicit adjacent convoying is used (DTPG,
+ choice e), then the unit in Norway did not receive an order to move by convoy and the land route should be
+ considered. The Russian army in Sweden is dislodged.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A NWY', 'F SKA', 'F FIN'])
+ self.set_units(game, 'RUSSIA', ['A SWE'])
+ self.set_orders(game, 'ENGLAND', ['A NWY - SWE', 'F SKA C A NWY - SWE', 'F FIN S A NWY - SWE'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'A NWY', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F FIN', '')
+ assert self.check_results(game, 'A SWE', '')
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'F SKA') == 'ENGLAND'
+ assert self.owner_name(game, 'F FIN') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'ENGLAND'
+
+ def test_6_g_10(self):
+ """ 6.G.10. TEST CASE, SWAPPED OR AN HEAD TO HEAD BATTLE?
+ Can a dislodged unit have effect on the attackers area, when the attacker moved by convoy?
+ England: A Norway - Sweden via Convoy
+ England: F Denmark Supports A Norway - Sweden
+ England: F Finland Supports A Norway - Sweden
+ Germany: F Skagerrak Convoys A Norway - Sweden
+ Russia: A Sweden - Norway
+ Russia: F Barents Sea Supports A Sweden - Norway
+ France: F Norwegian Sea - Norway
+ France: F North Sea Supports F Norwegian Sea - Norway
+ Since England ordered the army in Norway to move explicitly via convoy and the army in Sweden is moving
+ in opposite direction, only the convoyed route should be considered regardless of the rulebook used. It
+ is clear that the army in Norway will dislodge the Russian army in Sweden. Since the strength of three is
+ in all cases the strongest force. The army in Sweden will not advance to Norway, because it can not beat
+ the force in the Norwegian Sea. It will be dislodged by the army from Norway.
+ The more interesting question is whether French fleet in the Norwegian Sea is bounced by the Russian army
+ from Sweden. This depends on the interpretation of issue 4.A.7. If the rulebook is taken literally
+ (choice a), then a dislodged unit can not bounce a unit in the area where the attacker came from. This
+ would mean that the move of the fleet in the Norwegian Sea succeeds However, if choice b is taken
+ (which I prefer), then a bounce is still possible, when there is no head to head battle. So, the fleet in
+ the Norwegian Sea will fail to move.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A NWY', 'F DEN', 'F FIN'])
+ self.set_units(game, 'GERMANY', ['F SKA'])
+ self.set_units(game, 'RUSSIA', ['A SWE', 'F BAR'])
+ self.set_units(game, 'FRANCE', ['F NWG', 'F NTH'])
+ self.set_orders(game, 'ENGLAND', ['A NWY - SWE VIA', 'F DEN S A NWY - SWE', 'F FIN S A NWY - SWE'])
+ self.set_orders(game, 'GERMANY', ['F SKA C A NWY - SWE'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY', 'F BAR S A SWE - NWY'])
+ self.set_orders(game, 'FRANCE', ['F NWG - NWY', 'F NTH S F NWG - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'A NWY', '')
+ assert self.check_results(game, 'F DEN', '')
+ assert self.check_results(game, 'F FIN', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'A SWE', 'bounce')
+ assert self.check_results(game, 'A SWE', 'dislodged')
+ assert self.check_results(game, 'F BAR', '')
+ assert self.check_results(game, 'F NWG', 'bounce')
+ assert self.check_results(game, 'F NTH', '')
+ assert check_dislodged(game, 'A SWE', 'A NWY')
+ assert self.owner_name(game, 'A NWY') is None
+ assert self.owner_name(game, 'F DEN') == 'ENGLAND'
+ assert self.owner_name(game, 'F FIN') == 'ENGLAND'
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+ assert self.owner_name(game, 'A SWE') == 'ENGLAND'
+ assert self.owner_name(game, 'F BAR') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'FRANCE'
+
+ def test_6_g_11(self):
+ """ 6.G.11. TEST CASE, A CONVOY TO AN ADJACENT PLACE WITH A PARADOX
+ In this case the convoy route is available when the land route is chosen and the convoy route is not
+ available when the convoy route is chosen.
+ England: F Norway Supports F North Sea - Skagerrak
+ England: F North Sea - Skagerrak
+ Russia: A Sweden - Norway
+ Russia: F Skagerrak Convoys A Sweden - Norway
+ Russia: F Barents Sea Supports A Sweden - Norway
+ See issue 4.A.2 and 4.A.3.
+ If for issue 4.A.3, choice b, c or e has been taken, then the move from Sweden to Norway is not a
+ convoy and the English fleet in Norway is dislodged and the fleet in Skagerrak will not be dislodged.
+ If choice a or d (1982/2000 rule) has been taken for issue 4.A.3, then the move from Sweden to Norway
+ must be treated as a convoy. At that moment the situation becomes paradoxical. When the 'All Hold' rule is
+ used, both the army in Sweden as the fleet in the North Sea will not advance. In all other paradox rules
+ the English fleet in the North Sea will dislodge the Russian fleet in Skagerrak and the army in Sweden will
+ not advance.
+ I prefer the 1982 rule with the 2000 rulebook clarification concerning the convoy to adjacent places and
+ I prefer the Szykman rule for paradox resolving. That means that according to these preferences the fleet
+ in the North Sea will dislodge the Russian fleet in Skagerrak and the army in Sweden will not advance.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NWY', 'F NTH'])
+ self.set_units(game, 'RUSSIA', ['A SWE', 'F SKA', 'F BAR'])
+ self.set_orders(game, 'ENGLAND', ['F NWY S F NTH - SKA', 'F NTH - SKA'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY', 'F SKA C A SWE - NWY', 'F BAR S A SWE - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'F NWY', '')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A SWE', 'no convoy')
+ assert self.check_results(game, 'F SKA', 'dislodged')
+ assert self.check_results(game, 'F BAR', 'no convoy')
+ assert check_dislodged(game, 'F SKA', 'F NTH')
+ assert self.owner_name(game, 'F NWY') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') is None
+ assert self.owner_name(game, 'A SWE') == 'RUSSIA'
+ assert self.owner_name(game, 'F SKA') == 'ENGLAND'
+ assert self.owner_name(game, 'F BAR') == 'RUSSIA'
+
+ def test_6_g_12(self):
+ """ 6.G.12. TEST CASE, SWAPPING TWO UNITS WITH TWO CONVOYS
+ Of course, two armies can also swap by when they are both convoyed.
+ England: A Liverpool - Edinburgh via Convoy
+ England: F North Atlantic Ocean Convoys A Liverpool - Edinburgh
+ England: F Norwegian Sea Convoys A Liverpool - Edinburgh
+ Germany: A Edinburgh - Liverpool via Convoy
+ Germany: F North Sea Convoys A Edinburgh - Liverpool
+ Germany: F English Channel Convoys A Edinburgh - Liverpool
+ Germany: F Irish Sea Convoys A Edinburgh - Liverpool
+ The armies in Liverpool and Edinburgh are swapped.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LVP', 'F NAO', 'F NWG'])
+ self.set_units(game, 'GERMANY', ['A EDI', 'F NTH', 'F ENG', 'F IRI'])
+ self.set_orders(game, 'ENGLAND', ['A LVP - EDI VIA', 'F NAO C A LVP - EDI', 'F NWG C A LVP - EDI'])
+ self.set_orders(game, 'GERMANY', ['A EDI - LVP VIA', 'F NTH C A EDI - LVP', 'F ENG C A EDI - LVP',
+ 'F IRI C A EDI - LVP'])
+ self.process(game)
+ assert self.check_results(game, 'A LVP', '')
+ assert self.check_results(game, 'F NAO', '')
+ assert self.check_results(game, 'F NWG', '')
+ assert self.check_results(game, 'A EDI', '')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'F IRI', '')
+ assert self.owner_name(game, 'A LVP') == 'GERMANY'
+ assert self.owner_name(game, 'F NAO') == 'ENGLAND'
+ assert self.owner_name(game, 'F NWG') == 'ENGLAND'
+ assert self.owner_name(game, 'A EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') == 'GERMANY'
+ assert self.owner_name(game, 'F ENG') == 'GERMANY'
+ assert self.owner_name(game, 'F IRI') == 'GERMANY'
+
+ def test_6_g_13(self):
+ """ 6.G.13. TEST CASE, SUPPORT CUT ON ATTACK ON ITSELF VIA CONVOY
+ If a unit is attacked by a supported unit, it is not possible to prevent dislodgement by trying to cut
+ the support. But what, if a move is attempted via a convoy?
+ Austria: F Adriatic Sea Convoys A Trieste - Venice
+ Austria: A Trieste - Venice via Convoy
+ Italy: A Venice Supports F Albania - Trieste
+ Italy: F Albania - Trieste
+ First it should be mentioned that if for issue 4.A.3 choice b or c is taken, then the move from Trieste
+ to Venice is just a move over land, because the army in Venice is not moving in opposite direction. In that
+ case, the support of Venice will not be cut as normal.
+ In any other choice for issue 4.A.3, it should be decided whether the Austrian attack is considered to be
+ coming from Trieste or from the Adriatic Sea. If it comes from Trieste, the support in Venice is not cut
+ and the army in Trieste is dislodged by the fleet in Albania. If the Austrian attack is considered to be
+ coming from the Adriatic Sea, then the support is cut and the army in Trieste will not be dislodged. See
+ also issue 4.A.4. First of all, I prefer the 1982/2000 rules for adjacent convoying. This means that I
+ prefer the move from Trieste uses the convoy. Furthermore, I think that the two Italian units are still
+ stronger than the army in Trieste. Therefore, I prefer that the support in Venice is not cut and that the
+ army in Trieste is dislodged by the fleet in Albania.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F ADR', 'A TRI'])
+ self.set_units(game, 'ITALY', ['A VEN', 'F ALB'])
+ self.set_orders(game, 'AUSTRIA', ['F ADR C A TRI - VEN', 'A TRI - VEN VIA'])
+ self.set_orders(game, 'ITALY', ['A VEN S F ALB - TRI', 'F ALB - TRI'])
+ self.process(game)
+ assert self.check_results(game, 'F ADR', '')
+ assert self.check_results(game, 'A TRI', 'dislodged')
+ assert self.check_results(game, 'A TRI', 'bounce')
+ assert self.check_results(game, 'A VEN', '')
+ assert self.check_results(game, 'F ALB', '')
+ assert check_dislodged(game, 'A TRI', 'F ALB')
+ assert self.owner_name(game, 'F ADR') == 'AUSTRIA'
+ assert self.owner_name(game, 'F TRI') == 'ITALY'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'F ALB') is None
+
+ def test_6_g_14(self):
+ """ 6.G.14. TEST CASE, BOUNCE BY CONVOY TO ADJACENT PLACE
+ Similar to test case 6.G.10, but now the other unit is taking the convoy.
+ England: A Norway - Sweden
+ England: F Denmark Supports A Norway - Sweden
+ England: F Finland Supports A Norway - Sweden
+ France: F Norwegian Sea - Norway
+ France: F North Sea Supports F Norwegian Sea - Norway
+ Germany: F Skagerrak Convoys A Sweden - Norway
+ Russia: A Sweden - Norway via Convoy
+ Russia: F Barents Sea Supports A Sweden - Norway
+ Again the army in Sweden is bounced by the fleet in the Norwegian Sea. The army in Norway will move to
+ Sweden and dislodge the Russian army.
+ The final destination of the fleet in the Norwegian Sea depends on how issue 4.A.7 is resolved. If
+ choice a is taken, then the fleet advances to Norway, but if choice b is taken (which I prefer) the fleet
+ bounces and stays in the Norwegian Sea.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A NWY', 'F DEN', 'F FIN'])
+ self.set_units(game, 'FRANCE', ['F NWG', 'F NTH'])
+ self.set_units(game, 'GERMANY', ['F SKA'])
+ self.set_units(game, 'RUSSIA', ['A SWE', 'F BAR'])
+ self.set_orders(game, 'ENGLAND', ['A NWY - SWE', 'F DEN S A NWY - SWE', 'F FIN S A NWY - SWE'])
+ self.set_orders(game, 'FRANCE', ['F NWG - NWY', 'F NTH S F NWG - NWY'])
+ self.set_orders(game, 'GERMANY', ['F SKA C A SWE - NWY'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY VIA', 'F BAR S A SWE - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'A NWY', '')
+ assert self.check_results(game, 'F DEN', '')
+ assert self.check_results(game, 'F FIN', '')
+ assert self.check_results(game, 'F NWG', 'bounce')
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'A SWE', 'dislodged')
+ assert self.check_results(game, 'A SWE', 'bounce')
+ assert self.check_results(game, 'F BAR', '')
+ assert check_dislodged(game, 'A SWE', 'A NWY')
+ assert self.owner_name(game, 'A NWY') is None
+ assert self.owner_name(game, 'F DEN') == 'ENGLAND'
+ assert self.owner_name(game, 'F FIN') == 'ENGLAND'
+ assert self.owner_name(game, 'F NWG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'FRANCE'
+ assert self.owner_name(game, 'F SKA') == 'GERMANY'
+ assert self.owner_name(game, 'A SWE') == 'ENGLAND'
+ assert self.owner_name(game, 'F BAR') == 'RUSSIA'
+
+ def test_6_g_15(self):
+ """ 6.G.15. TEST CASE, BOUNCE AND DISLODGE WITH DOUBLE CONVOY
+ Similar to test case 6.G.10, but now both units use a convoy and without some support.
+ England: F North Sea Convoys A London - Belgium
+ England: A Holland Supports A London - Belgium
+ England: A Yorkshire - London
+ England: A London - Belgium via Convoy
+ France: F English Channel Convoys A Belgium - London
+ France: A Belgium - London via Convoy
+ The French army in Belgium is bounced by the army from Yorkshire. The army in London move to Belgium,
+ dislodging the unit there.
+ The final destination of the army in the Yorkshire depends on how issue 4.A.7 is resolved. If choice a is
+ taken, then the army advances to London, but if choice b is taken (which I prefer) the army bounces and
+ stays in Yorkshire.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A HOL', 'A YOR', 'A LON'])
+ self.set_units(game, 'FRANCE', ['F ENG', 'A BEL'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - BEL',
+ 'A HOL S A LON - BEL',
+ 'A YOR - LON',
+ 'A LON - BEL VIA'])
+ self.set_orders(game, 'FRANCE', ['F ENG C A BEL - LON', 'A BEL - LON VIA'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A HOL', '')
+ assert self.check_results(game, 'A YOR', 'bounce')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A BEL', 'bounce')
+ assert self.check_results(game, 'A BEL', 'dislodged')
+ assert check_dislodged(game, 'A BEL', 'A LON')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A HOL') == 'ENGLAND'
+ assert self.owner_name(game, 'A YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') is None
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+
+ def test_6_g_16(self):
+ """ 6.G.16. TEST CASE, THE TWO UNIT IN ONE AREA BUG, MOVING BY CONVOY
+ If the adjudicator is not correctly implemented, this may lead to a resolution where two units end up in
+ the same area.
+ England: A Norway - Sweden
+ England: A Denmark Supports A Norway - Sweden
+ England: F Baltic Sea Supports A Norway - Sweden
+ England: F North Sea - Norway
+ Russia: A Sweden - Norway via Convoy
+ Russia: F Skagerrak Convoys A Sweden - Norway
+ Russia: F Norwegian Sea Supports A Sweden - Norway
+ See decision details 5.B.6. If the 'PREVENT STRENGTH' is incorrectly implemented, due to the fact that it
+ does not take into account that the 'PREVENT STRENGTH' is only zero when the unit is engaged in a head to
+ head battle, then this goes wrong in this test case. The 'PREVENT STRENGTH' of Sweden would be zero,
+ because the opposing unit in Norway successfully moves. Since, this strength would be zero, the fleet in
+ the North Sea would move to Norway. However, although the 'PREVENT STRENGTH' is zero, the army in Sweden
+ would also move to Norway. So, the final result would contain two units that successfully moved to Norway.
+ Of course, this is incorrect. Norway will indeed successfully move to Sweden while the army in Sweden ends
+ in Norway, because it is stronger then the fleet in the North Sea. This fleet will stay in the North Sea.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A NWY', 'A DEN', 'F BAL', 'F NTH'])
+ self.set_units(game, 'RUSSIA', ['A SWE', 'F SKA', 'F NWG'])
+ self.set_orders(game, 'ENGLAND', ['A NWY - SWE', 'A DEN S A NWY - SWE', 'F BAL S A NWY - SWE', 'F NTH - NWY'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY VIA', 'F SKA C A SWE - NWY', 'F NWG S A SWE - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'A NWY', '')
+ assert self.check_results(game, 'A DEN', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'F NTH', 'bounce')
+ assert self.check_results(game, 'A SWE', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NWG', '')
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'A DEN') == 'ENGLAND'
+ assert self.owner_name(game, 'F BAL') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'ENGLAND'
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+ assert self.owner_name(game, 'F NWG') == 'RUSSIA'
+
+ def test_6_g_17(self):
+ """ 6.G.17. TEST CASE, THE TWO UNIT IN ONE AREA BUG, MOVING OVER LAND
+ Similar to the previous test case, but now the other unit moves by convoy.
+ England: A Norway - Sweden via Convoy
+ England: A Denmark Supports A Norway - Sweden
+ England: F Baltic Sea Supports A Norway - Sweden
+ England: F Skagerrak Convoys A Norway - Sweden
+ England: F North Sea - Norway
+ Russia: A Sweden - Norway
+ Russia: F Norwegian Sea Supports A Sweden - Norway
+ Sweden and Norway are swapped, while the fleet in the North Sea will bounce.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A NWY', 'A DEN', 'F BAL', 'F SKA', 'F NTH'])
+ self.set_units(game, 'RUSSIA', ['A SWE', 'F NWG'])
+ self.set_orders(game, 'ENGLAND', ['A NWY - SWE VIA',
+ 'A DEN S A NWY - SWE',
+ 'F BAL S A NWY - SWE',
+ 'F SKA C A NWY - SWE',
+ 'F NTH - NWY'])
+ self.set_orders(game, 'RUSSIA', ['A SWE - NWY', 'F NWG S A SWE - NWY'])
+ self.process(game)
+ assert self.check_results(game, 'A NWY', '')
+ assert self.check_results(game, 'A DEN', '')
+ assert self.check_results(game, 'F BAL', '')
+ assert self.check_results(game, 'F SKA', '')
+ assert self.check_results(game, 'F NTH', 'bounce')
+ assert self.check_results(game, 'A SWE', '')
+ assert self.check_results(game, 'F NWG', '')
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'A DEN') == 'ENGLAND'
+ assert self.owner_name(game, 'F BAL') == 'ENGLAND'
+ assert self.owner_name(game, 'F SKA') == 'ENGLAND'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'ENGLAND'
+ assert self.owner_name(game, 'F NWG') == 'RUSSIA'
+
+ def test_6_g_18(self):
+ """ 6.G.18. TEST CASE, THE TWO UNIT IN ONE AREA BUG, WITH DOUBLE CONVOY
+ Similar to the previous test case, but now both units move by convoy.
+ England: F North Sea Convoys A London - Belgium
+ England: A Holland Supports A London - Belgium
+ England: A Yorkshire - London
+ England: A London - Belgium
+ England: A Ruhr Supports A London - Belgium
+ France: F English Channel Convoys A Belgium - London
+ France: A Belgium - London
+ France: A Wales Supports A Belgium - London
+ Belgium and London are swapped, while the army in Yorkshire fails to move to London.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A HOL', 'A YOR', 'A LON', 'A RUH'])
+ self.set_units(game, 'FRANCE', ['F ENG', 'A BEL', 'A WAL'])
+ self.set_orders(game, 'ENGLAND', ['F NTH C A LON - BEL',
+ 'A HOL S A LON - BEL',
+ 'A YOR - LON',
+ 'A LON - BEL',
+ 'A RUH S A LON - BEL'])
+ self.set_orders(game, 'FRANCE', ['F ENG C A BEL - LON', 'A BEL - LON', 'A WAL S A BEL - LON'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A HOL', '')
+ assert self.check_results(game, 'A YOR', 'bounce')
+ assert self.check_results(game, 'A LON', '')
+ assert self.check_results(game, 'A RUH', '')
+ assert self.check_results(game, 'F ENG', '')
+ assert self.check_results(game, 'A BEL', '')
+ assert self.check_results(game, 'A WAL', '')
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A HOL') == 'ENGLAND'
+ assert self.owner_name(game, 'A YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'A LON') == 'FRANCE'
+ assert self.owner_name(game, 'A RUH') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+ assert self.owner_name(game, 'A WAL') == 'FRANCE'
+
+ # 6.H. TEST CASES, RETREATING
+ def test_6_h_1(self):
+ """ 6.H.1. TEST CASE, NO SUPPORTS DURING RETREAT
+ Supports are not allowed in the retreat phase.
+ Austria: F Trieste Hold
+ Austria: A Serbia Hold
+ Turkey: F Greece Hold
+ Italy: A Venice Supports A Tyrolia - Trieste
+ Italy: A Tyrolia - Trieste
+ Italy: F Ionian Sea - Greece
+ Italy: F Aegean Sea Supports F Ionian Sea - Greece
+ The fleet in Trieste and the fleet in Greece are dislodged. If the retreat orders are as follows:
+ Austria: F Trieste - Albania
+ Austria: A Serbia Supports F Trieste - Albania
+ Turkey: F Greece - Albania
+ The Austrian support order is illegal. Both dislodged fleets are disbanded.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['F TRI', 'A SER'])
+ self.set_units(game, 'TURKEY', ['F GRE'])
+ self.set_units(game, 'ITALY', ['A VEN', 'A TYR', 'F ION', 'F AEG'])
+
+ # Movement phase
+ self.set_orders(game, 'AUSTRIA', ['F TRI H', 'A SER H'])
+ self.set_orders(game, 'TURKEY', ['F GRE H'])
+ self.set_orders(game, 'ITALY', ['A VEN S A TYR - TRI', 'A TYR - TRI', 'F ION - GRE', 'F AEG S F ION - GRE'])
+ self.process(game)
+ assert self.check_results(game, 'F TRI', 'dislodged')
+ assert self.check_results(game, 'A SER', '')
+ assert self.check_results(game, 'F GRE', 'dislodged')
+ assert self.check_results(game, 'A VEN', '')
+ assert self.check_results(game, 'A TYR', '')
+ assert self.check_results(game, 'F ION', '')
+ assert self.check_results(game, 'F AEG', '')
+ assert check_dislodged(game, 'F TRI', 'A TYR') # AUSTRIA
+ assert check_dislodged(game, 'F GRE', 'F ION') # TURKEY
+ assert self.owner_name(game, 'A TRI') == 'ITALY'
+ assert self.owner_name(game, 'A SER') == 'AUSTRIA'
+ assert self.owner_name(game, 'F GRE') == 'ITALY'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'A TYR') is None
+ assert self.owner_name(game, 'F ION') is None
+ assert self.owner_name(game, 'F AEG') == 'ITALY'
+
+ # Retreats Phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'AUSTRIA', ['F TRI R ALB', 'A SER S F TRI - ALB'])
+ self.set_orders(game, 'TURKEY', ['F GRE R ALB'])
+ self.process(game)
+ assert self.check_results(game, 'F TRI', 'bounce', phase='R')
+ assert self.check_results(game, 'F TRI', 'disband', phase='R')
+ assert self.check_results(game, 'A SER', 'void', phase='R')
+ assert self.check_results(game, 'F GRE', 'bounce', phase='R')
+ assert self.check_results(game, 'F GRE', 'disband', phase='R')
+ assert not check_dislodged(game, 'F TRI', '') # AUSTRIA
+ assert not check_dislodged(game, 'F GRE', '') # TURKEY
+ assert self.owner_name(game, 'A TRI') == 'ITALY'
+ assert self.owner_name(game, 'A SER') == 'AUSTRIA'
+ assert self.owner_name(game, 'F GRE') == 'ITALY'
+ assert self.owner_name(game, 'A VEN') == 'ITALY'
+ assert self.owner_name(game, 'A TYR') is None
+ assert self.owner_name(game, 'F ION') is None
+ assert self.owner_name(game, 'F AEG') == 'ITALY'
+ assert self.owner_name(game, 'F ALB') is None
+
+ def test_6_h_2(self):
+ """ 6.H.2. TEST CASE, NO SUPPORTS FROM RETREATING UNIT
+ Even a retreating unit can not give support.
+ England: A Liverpool - Edinburgh
+ England: F Yorkshire Supports A Liverpool - Edinburgh
+ England: F Norway Hold
+ Germany: A Kiel Supports A Ruhr - Holland
+ Germany: A Ruhr - Holland
+ Russia: F Edinburgh Hold
+ Russia: A Sweden Supports A Finland - Norway
+ Russia: A Finland - Norway
+ Russia: F Holland Hold
+ The English fleet in Norway and the Russian fleets in Edinburgh and Holland are dislodged. If the
+ following retreat orders are given:
+ England: F Norway - North Sea
+ Russia: F Edinburgh - North Sea
+ Russia: F Holland Supports F Edinburgh - North Sea
+ Although the fleet in Holland may receive an order, it may not support (it is disbanded).
+ The English fleet in Norway and the Russian fleet in Edinburgh bounce and are disbanded.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LVP', 'F YOR', 'F NWY'])
+ self.set_units(game, 'GERMANY', ['A KIE', 'A RUH'])
+ self.set_units(game, 'RUSSIA', ['F EDI', 'A SWE', 'A FIN', 'F HOL'])
+
+ # Movements Phase
+ self.set_orders(game, 'ENGLAND', ['A LVP - EDI', 'F YOR S A LVP - EDI', 'F NWY H'])
+ self.set_orders(game, 'GERMANY', ['A KIE S A RUH - HOL', 'A RUH - HOL'])
+ self.set_orders(game, 'RUSSIA', ['F EDI H', 'A SWE S A FIN - NWY', 'A FIN - NWY', 'F HOL H'])
+ self.process(game)
+ assert self.check_results(game, 'A LVP', '')
+ assert self.check_results(game, 'F YOR', '')
+ assert self.check_results(game, 'F NWY', 'dislodged')
+ assert self.check_results(game, 'A KIE', '')
+ assert self.check_results(game, 'A RUH', '')
+ assert self.check_results(game, 'F EDI', 'dislodged')
+ assert self.check_results(game, 'A SWE', '')
+ assert self.check_results(game, 'A FIN', '')
+ assert self.check_results(game, 'F HOL', 'dislodged')
+ assert check_dislodged(game, 'F NWY', 'A FIN') # ENGLAND
+ assert check_dislodged(game, 'F EDI', 'A LVP') # RUSSIA
+ assert check_dislodged(game, 'F HOL', 'A RUH') # RUSSIA
+ assert self.owner_name(game, 'A LVP') is None
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'A KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+ assert self.owner_name(game, 'A EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'RUSSIA'
+ assert self.owner_name(game, 'A FIN') is None
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', ['F NWY R NTH'])
+ self.set_orders(game, 'RUSSIA', ['F EDI R NTH', 'F HOL S F EDI - NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NWY', 'bounce', phase='R')
+ assert self.check_results(game, 'F NWY', 'disband', phase='R')
+ assert self.check_results(game, 'F EDI', 'bounce', phase='R')
+ assert self.check_results(game, 'F EDI', 'disband', phase='R')
+ assert self.check_results(game, 'F HOL', 'void', phase='R')
+ assert self.check_results(game, 'F EDI', 'disband', phase='R')
+ assert not check_dislodged(game, 'F NWY', '') # ENGLAND
+ assert not check_dislodged(game, 'F EDI', '') # RUSSIA
+ assert not check_dislodged(game, 'F HOL', '') # RUSSIA
+ assert self.owner_name(game, 'A LVP') is None
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'A KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+ assert self.owner_name(game, 'A EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'RUSSIA'
+ assert self.owner_name(game, 'A FIN') is None
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F NTH') is None
+
+ def test_6_h_3(self):
+ """ 6.H.3. TEST CASE, NO CONVOY DURING RETREAT
+ Convoys during retreat are not allowed.
+ England: F North Sea Hold
+ England: A Holland Hold
+ Germany: F Kiel Supports A Ruhr - Holland
+ Germany: A Ruhr - Holland
+ The English army in Holland is dislodged. If England orders the following in retreat:
+ England: A Holland - Yorkshire
+ England: F North Sea Convoys A Holland - Yorkshire
+ The convoy order is illegal. The army in Holland is disbanded.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A HOL'])
+ self.set_units(game, 'GERMANY', ['F KIE', 'A RUH'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['F NTH H', 'A HOL H'])
+ self.set_orders(game, 'GERMANY', ['F KIE S A RUH - HOL', 'A RUH - HOL'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A HOL', 'dislodged')
+ assert self.check_results(game, 'F KIE', '')
+ assert self.check_results(game, 'A RUH', '')
+ assert check_dislodged(game, 'A HOL', 'A RUH') # ENGLAND
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', ['A HOL R YOR', 'F NTH C A HOL - YOR'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'void', phase='R')
+ assert self.check_results(game, 'A HOL', 'void', phase='R')
+ assert self.check_results(game, 'A HOL', 'disband', phase='R')
+ assert not check_dislodged(game, 'A HOL', '') # ENGLAND
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+ assert self.owner_name(game, 'A YOR') is None
+
+ def test_6_h_4(self):
+ """ 6.H.4. TEST CASE, NO OTHER MOVES DURING RETREAT
+ Of course you may not do any other move during a retreat. But look if the adjudicator checks for it.
+ England: F North Sea Hold
+ England: A Holland Hold
+ Germany: F Kiel Supports A Ruhr - Holland
+ Germany: A Ruhr - Holland
+ The English army in Holland is dislodged. If England orders the following in retreat:
+ England: A Holland - Belgium
+ England: F North Sea - Norwegian Sea
+ The fleet in the North Sea is not dislodge, so the move is illegal.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F NTH', 'A HOL'])
+ self.set_units(game, 'GERMANY', ['F KIE', 'A RUH'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['F NTH H', 'A HOL H'])
+ self.set_orders(game, 'GERMANY', ['F KIE S A RUH - HOL', 'A RUH - HOL'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', '')
+ assert self.check_results(game, 'A HOL', 'dislodged')
+ assert self.check_results(game, 'F KIE', '')
+ assert self.check_results(game, 'A RUH', '')
+ assert check_dislodged(game, 'A HOL', 'A RUH') # ENGLAND
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', ['A HOL R BEL', 'F NTH R NWG'])
+ self.process(game)
+ assert self.check_results(game, 'F NTH', 'void', phase='R')
+ assert self.check_results(game, 'A HOL', '', phase='R')
+ assert not check_dislodged(game, 'A HOL', '') # ENGLAND
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+ assert self.owner_name(game, 'A BEL') == 'ENGLAND'
+
+ def test_6_h_5(self):
+ """ 6.H.5. TEST CASE, A UNIT MAY NOT RETREAT TO THE AREA FROM WHICH IT IS ATTACKED
+ Well, that would be of course stupid. Still, the adjudicator must be tested on this.
+ Russia: F Constantinople Supports F Black Sea - Ankara
+ Russia: F Black Sea - Ankara
+ Turkey: F Ankara Hold
+ Fleet in Ankara is dislodged and may not retreat to Black Sea.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'RUSSIA', ['F CON', 'F BLA'])
+ self.set_units(game, 'TURKEY', 'F ANK')
+
+ # Movements phase
+ self.set_orders(game, 'RUSSIA', ['F CON S F BLA - ANK', 'F BLA - ANK'])
+ self.set_orders(game, 'TURKEY', 'F ANK H')
+ self.process(game)
+ assert self.check_results(game, 'F CON', '')
+ assert self.check_results(game, 'F BLA', '')
+ assert self.check_results(game, 'F ANK', 'dislodged')
+ assert check_dislodged(game, 'F ANK', 'F BLA') # TURKEY
+ assert self.owner_name(game, 'F CON') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') is None
+ assert self.owner_name(game, 'F ANK') == 'RUSSIA'
+
+ # Retreats Phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'TURKEY', ['F ANK R BLA'])
+ self.process(game)
+ assert self.check_results(game, 'F ANK', 'void', phase='R')
+ assert self.check_results(game, 'F ANK', 'disband', phase='R')
+ assert not check_dislodged(game, 'F ANK', 'F BLA') # TURKEY
+ assert self.owner_name(game, 'F CON') == 'RUSSIA'
+ assert self.owner_name(game, 'F BLA') is None
+ assert self.owner_name(game, 'F ANK') == 'RUSSIA'
+
+ def test_6_h_6(self):
+ """ 6.H.6. TEST CASE, UNIT MAY NOT RETREAT TO A CONTESTED AREA
+ Stand off prevents retreat to the area.
+ Austria: A Budapest Supports A Trieste - Vienna
+ Austria: A Trieste - Vienna
+ Germany: A Munich - Bohemia
+ Germany: A Silesia - Bohemia
+ Italy: A Vienna Hold
+ The Italian army in Vienna is dislodged. It may not retreat to Bohemia.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['A BUD', 'A TRI'])
+ self.set_units(game, 'GERMANY', ['A MUN', 'A SIL'])
+ self.set_units(game, 'ITALY', ['A VIE'])
+
+ # Movements phase
+ self.set_orders(game, 'AUSTRIA', ['A BUD S A TRI - VIE', 'A TRI - VIE'])
+ self.set_orders(game, 'GERMANY', ['A MUN - BOH', 'A SIL - BOH'])
+ self.set_orders(game, 'ITALY', ['A VIE H'])
+ self.process(game)
+ assert self.check_results(game, 'A BUD', '')
+ assert self.check_results(game, 'A TRI', '')
+ assert self.check_results(game, 'A MUN', 'bounce')
+ assert self.check_results(game, 'A SIL', 'bounce')
+ assert self.check_results(game, 'A VIE', 'dislodged')
+ assert check_dislodged(game, 'A VIE', 'A TRI') # ITALY
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') is None
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A SIL') == 'GERMANY'
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A BOH') is None
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ITALY', ['A VIE R BOH'])
+ self.process(game)
+ assert self.check_results(game, 'A VIE', 'void', phase='R')
+ assert self.check_results(game, 'A VIE', 'disband', phase='R')
+ assert not check_dislodged(game, 'A VIE', '') # ITALY
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') is None
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A SIL') == 'GERMANY'
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A BOH') is None
+
+ def test_6_h_7(self):
+ """ 6.H.7. TEST CASE, MULTIPLE RETREAT TO SAME AREA WILL DISBAND UNITS
+ There can only be one unit in an area.
+ Austria: A Budapest Supports A Trieste - Vienna
+ Austria: A Trieste - Vienna
+ Germany: A Munich Supports A Silesia - Bohemia
+ Germany: A Silesia - Bohemia
+ Italy: A Vienna Hold
+ Italy: A Bohemia Hold
+ If Italy orders the following for retreat:
+ Italy: A Bohemia - Tyrolia
+ Italy: A Vienna - Tyrolia
+ Both armies will be disbanded.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'AUSTRIA', ['A BUD', 'A TRI'])
+ self.set_units(game, 'GERMANY', ['A MUN', 'A SIL'])
+ self.set_units(game, 'ITALY', ['A VIE', 'A BOH'])
+
+ # Movements phase
+ self.set_orders(game, 'AUSTRIA', ['A BUD S A TRI - VIE', 'A TRI - VIE'])
+ self.set_orders(game, 'GERMANY', ['A MUN S A SIL - BOH', 'A SIL - BOH'])
+ self.set_orders(game, 'ITALY', ['A VIE H', 'A BOH H'])
+ self.process(game)
+ assert self.check_results(game, 'A BUD', '')
+ assert self.check_results(game, 'A TRI', '')
+ assert self.check_results(game, 'A MUN', '')
+ assert self.check_results(game, 'A SIL', '')
+ assert self.check_results(game, 'A VIE', 'dislodged')
+ assert self.check_results(game, 'A BOH', 'dislodged')
+ assert check_dislodged(game, 'A VIE', 'A TRI') # ITALY
+ assert check_dislodged(game, 'A BOH', 'A SIL') # ITALY
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') is None
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A SIL') is None
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A BOH') == 'GERMANY'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ITALY', ['A VIE R TYR', 'A BOH R TYR'])
+ self.process(game)
+ assert self.check_results(game, 'A VIE', 'bounce', phase='R')
+ assert self.check_results(game, 'A VIE', 'disband', phase='R')
+ assert self.check_results(game, 'A BOH', 'bounce', phase='R')
+ assert self.check_results(game, 'A BOH', 'disband', phase='R')
+ assert not check_dislodged(game, 'A VIE', '') # ITALY
+ assert not check_dislodged(game, 'A BOH', '') # ITALY
+ assert self.owner_name(game, 'A BUD') == 'AUSTRIA'
+ assert self.owner_name(game, 'A TRI') is None
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A SIL') is None
+ assert self.owner_name(game, 'A VIE') == 'AUSTRIA'
+ assert self.owner_name(game, 'A BOH') == 'GERMANY'
+ assert self.owner_name(game, 'A TYR') is None
+
+ def test_6_h_8(self):
+ """ 6.H.8. TEST CASE, TRIPLE RETREAT TO SAME AREA WILL DISBAND UNITS
+ When three units retreat to the same area, then all three units are disbanded.
+ England: A Liverpool - Edinburgh
+ England: F Yorkshire Supports A Liverpool - Edinburgh
+ England: F Norway Hold
+ Germany: A Kiel Supports A Ruhr - Holland
+ Germany: A Ruhr - Holland
+ Russia: F Edinburgh Hold
+ Russia: A Sweden Supports A Finland - Norway
+ Russia: A Finland - Norway
+ Russia: F Holland Hold
+ The fleets in Norway, Edinburgh and Holland are dislodged. If the following retreat orders are given:
+ England: F Norway - North Sea
+ Russia: F Edinburgh - North Sea
+ Russia: F Holland - North Sea
+ All three units are disbanded.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LVP', 'F YOR', 'F NWY'])
+ self.set_units(game, 'GERMANY', ['A KIE', 'A RUH'])
+ self.set_units(game, 'RUSSIA', ['F EDI', 'A SWE', 'A FIN', 'F HOL'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['A LVP - EDI', 'F YOR S A LVP - EDI', 'F NWY H'])
+ self.set_orders(game, 'GERMANY', ['A KIE S A RUH - HOL', 'A RUH - HOL'])
+ self.set_orders(game, 'RUSSIA', ['F EDI H', 'A SWE S A FIN - NWY', 'A FIN - NWY', 'F HOL H'])
+ self.process(game)
+ assert self.check_results(game, 'A LVP', '')
+ assert self.check_results(game, 'F YOR', '')
+ assert self.check_results(game, 'F NWY', 'dislodged')
+ assert self.check_results(game, 'A KIE', '')
+ assert self.check_results(game, 'A RUH', '')
+ assert self.check_results(game, 'F EDI', 'dislodged')
+ assert self.check_results(game, 'A SWE', '')
+ assert self.check_results(game, 'A FIN', '')
+ assert self.check_results(game, 'F HOL', 'dislodged')
+ assert check_dislodged(game, 'F NWY', 'A FIN') # ENGLAND
+ assert check_dislodged(game, 'F EDI', 'A LVP') # RUSSIA
+ assert check_dislodged(game, 'F HOL', 'A RUH') # RUSSIA
+ assert self.owner_name(game, 'A LVP') is None
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'A KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+ assert self.owner_name(game, 'A EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'RUSSIA'
+ assert self.owner_name(game, 'A FIN') is None
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', ['F NWY R NTH'])
+ self.set_orders(game, 'RUSSIA', ['F EDI R NTH', 'F HOL R NTH'])
+ self.process(game)
+ assert self.check_results(game, 'F NWY', 'bounce', phase='R')
+ assert self.check_results(game, 'F NWY', 'disband', phase='R')
+ assert self.check_results(game, 'F EDI', 'bounce', phase='R')
+ assert self.check_results(game, 'F EDI', 'disband', phase='R')
+ assert self.check_results(game, 'F HOL', 'bounce', phase='R')
+ assert self.check_results(game, 'F HOL', 'disband', phase='R')
+ assert not check_dislodged(game, 'F NWY', '') # ENGLAND
+ assert not check_dislodged(game, 'F EDI', '') # RUSSIA
+ assert not check_dislodged(game, 'F HOL', '') # RUSSIA
+ assert self.owner_name(game, 'A LVP') is None
+ assert self.owner_name(game, 'F YOR') == 'ENGLAND'
+ assert self.owner_name(game, 'A NWY') == 'RUSSIA'
+ assert self.owner_name(game, 'A KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A RUH') is None
+ assert self.owner_name(game, 'A EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'A SWE') == 'RUSSIA'
+ assert self.owner_name(game, 'A FIN') is None
+ assert self.owner_name(game, 'A HOL') == 'GERMANY'
+ assert self.owner_name(game, 'F NTH') is None
+
+ def test_6_h_9(self):
+ """ 6.H.9. TEST CASE, DISLODGED UNIT WILL NOT MAKE ATTACKERS AREA CONTESTED
+ An army can follow.
+ England: F Helgoland Bight - Kiel
+ England: F Denmark Supports F Helgoland Bight - Kiel
+ Germany: A Berlin - Prussia
+ Germany: F Kiel Hold
+ Germany: A Silesia Supports A Berlin - Prussia
+ Russia: A Prussia - Berlin
+ The fleet in Kiel can retreat to Berlin.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F HEL', 'F DEN'])
+ self.set_units(game, 'GERMANY', ['A BER', 'F KIE', 'A SIL'])
+ self.set_units(game, 'RUSSIA', ['A PRU'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['F HEL - KIE', 'F DEN S F HEL - KIE'])
+ self.set_orders(game, 'GERMANY', ['A BER - PRU', 'F KIE H', 'A SIL S A BER - PRU'])
+ self.set_orders(game, 'RUSSIA', ['A PRU - BER'])
+ self.process(game)
+ assert self.check_results(game, 'F HEL', '')
+ assert self.check_results(game, 'F DEN', '')
+ assert self.check_results(game, 'A BER', '')
+ assert self.check_results(game, 'F KIE', 'dislodged')
+ assert self.check_results(game, 'A SIL', '')
+ assert self.check_results(game, 'A PRU', 'dislodged')
+ assert check_dislodged(game, 'F KIE', 'F HEL') # GERMANY
+ assert check_dislodged(game, 'A PRU', 'A BER') # RUSSIA
+ assert self.owner_name(game, 'F HEL') is None
+ assert self.owner_name(game, 'F DEN') == 'ENGLAND'
+ assert self.owner_name(game, 'A BER') is None
+ assert self.owner_name(game, 'F KIE') == 'ENGLAND'
+ assert self.owner_name(game, 'A SIL') == 'GERMANY'
+ assert self.owner_name(game, 'A PRU') == 'GERMANY'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'GERMANY', 'F KIE R BER')
+ self.process(game)
+ assert self.check_results(game, 'F KIE', '', phase='R')
+ assert self.check_results(game, 'A PRU', 'disband', phase='R')
+ assert not check_dislodged(game, 'F KIE', '') # GERMANY
+ assert not check_dislodged(game, 'A PRU', '') # RUSSIA
+ assert self.owner_name(game, 'F HEL') is None
+ assert self.owner_name(game, 'F DEN') == 'ENGLAND'
+ assert self.owner_name(game, 'F BER') == 'GERMANY'
+ assert self.owner_name(game, 'F KIE') == 'ENGLAND'
+ assert self.owner_name(game, 'A SIL') == 'GERMANY'
+ assert self.owner_name(game, 'A PRU') == 'GERMANY'
+
+ def test_6_h_10(self):
+ """ 6.H.10. TEST CASE, NOT RETREATING TO ATTACKER DOES NOT MEAN CONTESTED
+ An army can not retreat to the place of the attacker. The easiest way to program that, is to mark that
+ place as "contested". However, this is not correct. Another army may retreat to that place.
+ England: A Kiel Hold
+ Germany: A Berlin - Kiel
+ Germany: A Munich Supports A Berlin - Kiel
+ Germany: A Prussia Hold
+ Russia: A Warsaw - Prussia
+ Russia: A Silesia Supports A Warsaw - Prussia
+ The armies in Kiel and Prussia are dislodged. The English army in Kiel can not retreat to Berlin, but
+ the army in Prussia can retreat to Berlin. Suppose the following retreat orders are given:
+ England: A Kiel - Berlin
+ Germany: A Prussia - Berlin
+ The English retreat to Berlin is illegal and fails (the unit is disbanded). The German retreat to Berlin is
+ successful and does not bounce on the English unit.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A KIE'])
+ self.set_units(game, 'GERMANY', ['A BER', 'A MUN', 'A PRU'])
+ self.set_units(game, 'RUSSIA', ['A WAR', 'A SIL'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['A KIE H'])
+ self.set_orders(game, 'GERMANY', ['A BER - KIE', 'A MUN S A BER - KIE', 'A PRU H'])
+ self.set_orders(game, 'RUSSIA', ['A WAR - PRU', 'A SIL S A WAR - PRU'])
+ self.process(game)
+ assert self.check_results(game, 'A KIE', 'dislodged')
+ assert self.check_results(game, 'A BER', '')
+ assert self.check_results(game, 'A MUN', '')
+ assert self.check_results(game, 'A PRU', 'dislodged')
+ assert self.check_results(game, 'A WAR', '')
+ assert self.check_results(game, 'A SIL', '')
+ assert check_dislodged(game, 'A KIE', 'A BER') # ENGLAND
+ assert check_dislodged(game, 'A PRU', 'A WAR') # GERMANY
+ assert self.owner_name(game, 'A KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A BER') is None
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A PRU') == 'RUSSIA'
+ assert self.owner_name(game, 'A WAR') is None
+ assert self.owner_name(game, 'A SIL') == 'RUSSIA'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', ['A KIE R BER'])
+ self.set_orders(game, 'GERMANY', ['A PRU R BER'])
+ self.process(game)
+ assert self.check_results(game, 'A KIE', 'void', phase='R')
+ assert self.check_results(game, 'A PRU', '', phase='R')
+ assert not check_dislodged(game, 'A KIE', '') # ENGLAND
+ assert not check_dislodged(game, 'A PRU', '') # GERMANY
+ assert self.owner_name(game, 'A KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A PRU') == 'RUSSIA'
+ assert self.owner_name(game, 'A WAR') is None
+ assert self.owner_name(game, 'A SIL') == 'RUSSIA'
+
+ def test_6_h_11(self):
+ """ 6.H.11. TEST CASE, RETREAT WHEN DISLODGED BY ADJACENT CONVOY
+ If a unit is dislodged by an army via convoy, the question arises whether the dislodged army can retreat
+ to the original place of the convoyed army. This is only relevant in case the convoy was to an adjacent
+ place.
+ France: A Gascony - Marseilles via Convoy
+ France: A Burgundy Supports A Gascony - Marseilles
+ France: F Mid-Atlantic Ocean Convoys A Gascony - Marseilles
+ France: F Western Mediterranean Convoys A Gascony - Marseilles
+ France: F Gulf of Lyon Convoys A Gascony - Marseilles
+ Italy: A Marseilles Hold
+ If for issue 4.A.3 choice b or c has been taken, then the army in Gascony will not move with the use of
+ the convoy, because the army in Marseilles does not move in opposite direction. This immediately means that
+ the army in Marseilles may not move to Gascony when it dislodged by the army there.
+ For all other choices of issue 4.A.3, the army in Gascony takes a convoy and does not pass the border of
+ Gascony with Marseilles (it went a complete different direction). Now, the result depends on which rule
+ is used for retreating (see issue 4.A.5).
+ I prefer the 1982/2000 rule for convoying to adjacent places. This means that the move of Gascony happened
+ by convoy. Furthermore, I prefer that the army in Marseilles may retreat to Gascony.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['A GAS', 'A BUR', 'F MAO', 'F WES', 'F LYO'])
+ self.set_units(game, 'ITALY', ['A MAR'])
+
+ # Movements phase
+ self.set_orders(game, 'FRANCE', ['A GAS - MAR VIA', 'A BUR S A GAS - MAR', 'F MAO C A GAS - MAR',
+ 'F WES C A GAS - MAR', 'F LYO C A GAS - MAR'])
+ self.set_orders(game, 'ITALY', ['A MAR H'])
+ self.process(game)
+ assert self.check_results(game, 'A GAS', '')
+ assert self.check_results(game, 'A BUR', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'F WES', '')
+ assert self.check_results(game, 'F LYO', '')
+ assert self.check_results(game, 'A MAR', 'dislodged')
+ assert check_dislodged(game, 'A MAR', 'A GAS') # ITALY
+ assert self.owner_name(game, 'A GAS') is None
+ assert self.owner_name(game, 'A BUR') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F WES') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'FRANCE'
+ assert self.owner_name(game, 'A MAR') == 'FRANCE'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ITALY', ['A MAR R GAS'])
+ self.process(game)
+ assert self.check_results(game, 'A MAR', '', phase='R')
+ assert not check_dislodged(game, 'A MAR', '') # ITALY
+ assert self.owner_name(game, 'A GAS') == 'ITALY'
+ assert self.owner_name(game, 'A BUR') == 'FRANCE'
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F WES') == 'FRANCE'
+ assert self.owner_name(game, 'F LYO') == 'FRANCE'
+ assert self.owner_name(game, 'A MAR') == 'FRANCE'
+
+ def test_6_h_12(self):
+ """ 6.H.12. TEST CASE, RETREAT WHEN DISLODGED BY ADJACENT CONVOY WHILE TRYING TO DO THE SAME
+ The previous test case can be made more extra ordinary, when both armies tried to move by convoy.
+ England: A Liverpool - Edinburgh via Convoy
+ England: F Irish Sea Convoys A Liverpool - Edinburgh
+ England: F English Channel Convoys A Liverpool - Edinburgh
+ England: F North Sea Convoys A Liverpool - Edinburgh
+ France: F Brest - English Channel
+ France: F Mid-Atlantic Ocean Supports F Brest - English Channel
+ Russia: A Edinburgh - Liverpool via Convoy
+ Russia: F Norwegian Sea Convoys A Edinburgh - Liverpool
+ Russia: F North Atlantic Ocean Convoys A Edinburgh - Liverpool
+ Russia: A Clyde Supports A Edinburgh - Liverpool
+ If for issue 4.A.3 choice c has been taken, then the army in Liverpool will not try to move by convoy,
+ because the convoy is disrupted. This has as consequence that army will just advance to Edinburgh by using
+ the land route. For all other choices of issue 4.A.3, both the army in Liverpool as in Edinburgh will try
+ to move by convoy. The army in Edinburgh will succeed. The army in Liverpool will fail, because of the
+ disrupted convoy. It is dislodged by the army of Edinburgh. Now, the question is whether the army in
+ Liverpool may retreat to Edinburgh. The result depends on which rule is used for retreating (see issue
+ 4.A.5). I prefer the 1982/2000 rule for convoying to adjacent places. This means that the army in Liverpool
+ tries the disrupted convoy. Furthermore, I prefer that the army in Liverpool may retreat to Edinburgh.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A LVP', 'F IRI', 'F ENG', 'F NTH'])
+ self.set_units(game, 'FRANCE', ['F BRE', 'F MAO'])
+ self.set_units(game, 'RUSSIA', ['A EDI', 'F NWG', 'F NAO', 'A CLY'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['A LVP - EDI VIA',
+ 'F IRI C A LVP - EDI',
+ 'F ENG C A LVP - EDI',
+ 'F NTH C A LVP - EDI'])
+ self.set_orders(game, 'FRANCE', ['F BRE - ENG', 'F MAO S F BRE - ENG'])
+ self.set_orders(game, 'RUSSIA', ['A EDI - LVP VIA',
+ 'F NWG C A EDI - LVP',
+ 'F NAO C A EDI - LVP',
+ 'A CLY S A EDI - LVP'])
+ self.process(game)
+ assert self.check_results(game, 'A LVP', 'dislodged')
+ assert self.check_results(game, 'F IRI', 'no convoy')
+ assert self.check_results(game, 'F ENG', 'dislodged')
+ assert self.check_results(game, 'F NTH', 'no convoy')
+ assert self.check_results(game, 'F BRE', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert self.check_results(game, 'A EDI', '')
+ assert self.check_results(game, 'F NWG', '')
+ assert self.check_results(game, 'F NAO', '')
+ assert self.check_results(game, 'A CLY', '')
+ assert check_dislodged(game, 'F ENG', 'F BRE') # ENGLAND
+ assert check_dislodged(game, 'A LVP', 'A EDI') # ENGLAND
+ assert self.owner_name(game, 'A LVP') == 'RUSSIA'
+ assert self.owner_name(game, 'F IRI') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F BRE') is None
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'A EDI') is None
+ assert self.owner_name(game, 'F NWG') == 'RUSSIA'
+ assert self.owner_name(game, 'F NAO') == 'RUSSIA'
+ assert self.owner_name(game, 'A CLY') == 'RUSSIA'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', ['A LVP R EDI', 'F ENG D'])
+ self.process(game)
+ assert self.check_results(game, 'A LVP', '', phase='R')
+ assert self.check_results(game, 'F ENG', 'disband', phase='R')
+ assert not check_dislodged(game, 'A LVP', '') # ENGLAND
+ assert not check_dislodged(game, 'F ENG', '') # ENGLAND
+ assert self.owner_name(game, 'A LVP') == 'RUSSIA'
+ assert self.owner_name(game, 'F IRI') == 'ENGLAND'
+ assert self.owner_name(game, 'F ENG') == 'FRANCE'
+ assert self.owner_name(game, 'F NTH') == 'ENGLAND'
+ assert self.owner_name(game, 'F BRE') is None
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'A EDI') == 'ENGLAND'
+ assert self.owner_name(game, 'F NWG') == 'RUSSIA'
+ assert self.owner_name(game, 'F NAO') == 'RUSSIA'
+ assert self.owner_name(game, 'A CLY') == 'RUSSIA'
+
+ def test_6_h_13(self):
+ """ 6.H.13. TEST CASE, NO RETREAT WITH CONVOY IN MAIN PHASE
+ The places where a unit may retreat to, must be calculated during the main phase. Care should be taken
+ that a convoy ordered in the main phase can not be used in the retreat phase.
+ England: A Picardy Hold
+ England: F English Channel Convoys A Picardy - London
+ France: A Paris - Picardy
+ France: A Brest Supports A Paris - Picardy
+ The dislodged army in Picardy can not retreat to London.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A PIC', 'F ENG'])
+ self.set_units(game, 'FRANCE', ['A PAR', 'A BRE'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['A PIC H', 'F ENG C A PIC - LON'])
+ self.set_orders(game, 'FRANCE', ['A PAR - PIC', 'A BRE S A PAR - PIC'])
+ self.process(game)
+ assert self.check_results(game, 'A PIC', 'dislodged')
+ assert self.check_results(game, 'F ENG', 'void')
+ assert self.check_results(game, 'A PAR', '')
+ assert self.check_results(game, 'A BRE', '')
+ assert check_dislodged(game, 'A PIC', 'A PAR') # ENGLAND
+ assert self.owner_name(game, 'A PIC') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A PAR') is None
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'A LON') is None
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', 'A PIC R LON')
+ self.process(game)
+ assert self.check_results(game, 'A PIC', 'void', phase='R')
+ assert self.check_results(game, 'A PIC', 'disband', phase='R')
+ assert not check_dislodged(game, 'A PIC', '') # ENGLAND
+ assert self.owner_name(game, 'A PIC') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A PAR') is None
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'A LON') is None
+
+ def test_6_h_14(self):
+ """ 6.H.14. TEST CASE, NO RETREAT WITH SUPPORT IN MAIN PHASE
+ Comparable to the previous test case, a support given in the main phase can not be used in the retreat
+ phase.
+ England: A Picardy Hold
+ England: F English Channel Supports A Picardy - Belgium
+ France: A Paris - Picardy
+ France: A Brest Supports A Paris - Picardy
+ France: A Burgundy Hold
+ Germany: A Munich Supports A Marseilles - Burgundy
+ Germany: A Marseilles - Burgundy
+ After the main phase the following retreat orders are given:
+ England: A Picardy - Belgium
+ France: A Burgundy - Belgium
+ Both the army in Picardy and Burgundy are disbanded.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['A PIC', 'F ENG'])
+ self.set_units(game, 'FRANCE', ['A PAR', 'A BRE', 'A BUR'])
+ self.set_units(game, 'GERMANY', ['A MUN', 'A MAR'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['A PIC H', 'F ENG S A PIC - BEL'])
+ self.set_orders(game, 'FRANCE', ['A PAR - PIC', 'A BRE S A PAR - PIC', 'A BUR H'])
+ self.set_orders(game, 'GERMANY', ['A MUN S A MAR - BUR', 'A MAR - BUR'])
+ self.process(game)
+ assert self.check_results(game, 'A PIC', 'dislodged')
+ assert self.check_results(game, 'F ENG', 'void')
+ assert self.check_results(game, 'A PAR', '')
+ assert self.check_results(game, 'A BRE', '')
+ assert self.check_results(game, 'A BUR', 'dislodged')
+ assert self.check_results(game, 'A MUN', '')
+ assert self.check_results(game, 'A MAR', '')
+ assert check_dislodged(game, 'A PIC', 'A PAR') # ENGLAND
+ assert check_dislodged(game, 'A BUR', 'A MAR') # FRANCE
+ assert self.owner_name(game, 'A PIC') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A PAR') is None
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'A BUR') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A MAR') is None
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', ['A PIC R BEL'])
+ self.set_orders(game, 'FRANCE', ['A BUR R BEL'])
+ self.process(game)
+ assert self.check_results(game, 'A PIC', 'bounce', phase='R')
+ assert self.check_results(game, 'A PIC', 'disband', phase='R')
+ assert self.check_results(game, 'A BUR', 'bounce', phase='R')
+ assert self.check_results(game, 'A BUR', 'disband', phase='R')
+ assert not check_dislodged(game, 'A PIC', '') # ENGLAND
+ assert not check_dislodged(game, 'A BUR', '') # FRANCE
+ assert self.owner_name(game, 'A PIC') == 'FRANCE'
+ assert self.owner_name(game, 'F ENG') == 'ENGLAND'
+ assert self.owner_name(game, 'A PAR') is None
+ assert self.owner_name(game, 'A BRE') == 'FRANCE'
+ assert self.owner_name(game, 'A BUR') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') == 'GERMANY'
+ assert self.owner_name(game, 'A MAR') is None
+
+ def test_6_h_15(self):
+ """ 6.H.15. TEST CASE, NO COASTAL CRAWL IN RETREAT
+ You can not go to the other coast from where the attacker came from.
+ England: F Portugal Hold
+ France: F Spain(sc) - Portugal
+ France: F Mid-Atlantic Ocean Supports F Spain(sc) - Portugal
+ The English fleet in Portugal is destroyed and can not retreat to Spain(nc).
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'ENGLAND', ['F POR'])
+ self.set_units(game, 'FRANCE', ['F SPA/SC', 'F MAO'])
+
+ # Movements phase
+ self.set_orders(game, 'ENGLAND', ['F POR H'])
+ self.set_orders(game, 'FRANCE', ['F SPA/SC - POR', 'F MAO S F SPA/SC - POR'])
+ self.process(game)
+ assert self.check_results(game, 'F POR', 'dislodged')
+ assert self.check_results(game, 'F SPA/SC', '')
+ assert self.check_results(game, 'F MAO', '')
+ assert check_dislodged(game, 'F POR', 'F SPA/SC') # ENGLAND
+ assert self.owner_name(game, 'F POR') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'ENGLAND', 'F POR R SPA/NC')
+ self.process(game)
+ assert self.check_results(game, 'F POR', 'void', phase='R')
+ assert self.check_results(game, 'F POR', 'disband', phase='R')
+ assert not check_dislodged(game, 'F POR', '') # ENGLAND
+ assert self.owner_name(game, 'F POR') == 'FRANCE'
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+
+ def test_6_h_16(self):
+ """ 6.H.16. TEST CASE, CONTESTED FOR BOTH COASTS
+ If a coast is contested, the other is not available for retreat.
+ France: F Mid-Atlantic Ocean - Spain(nc)
+ France: F Gascony - Spain(nc)
+ France: F Western Mediterranean Hold
+ Italy: F Tunis Supports F Tyrrhenian Sea - Western Mediterranean
+ Italy: F Tyrrhenian Sea - Western Mediterranean
+ The French fleet in the Western Mediterranean can not retreat to Spain(sc).
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.set_units(game, 'FRANCE', ['F MAO', 'F GAS', 'F WES'])
+ self.set_units(game, 'ITALY', ['F TUN', 'F TYS'])
+
+ # Movements phase
+ self.set_orders(game, 'FRANCE', ['F MAO - SPA/NC', 'F GAS - SPA/NC', 'F WES H'])
+ self.set_orders(game, 'ITALY', ['F TUN S F TYS - WES', 'F TYS - WES'])
+ self.process(game)
+ assert self.check_results(game, 'F MAO', 'bounce')
+ assert self.check_results(game, 'F GAS', 'bounce')
+ assert self.check_results(game, 'F WES', 'dislodged')
+ assert self.check_results(game, 'F TUN', '')
+ assert self.check_results(game, 'F TYS', '')
+ assert check_dislodged(game, 'F WES', 'F TYS') # FRANCE
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F GAS') == 'FRANCE'
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+ assert self.owner_name(game, 'F TUN') == 'ITALY'
+ assert self.owner_name(game, 'F TYS') is None
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+
+ # Retreats phase
+ if game.phase_type == 'R':
+ self.set_orders(game, 'FRANCE', 'F WES R SPA/SC')
+ self.process(game)
+ assert self.check_results(game, 'F WES', 'void', phase='R')
+ assert self.check_results(game, 'F WES', 'disband', phase='R')
+ assert not check_dislodged(game, 'F WES', '') # FRANCE
+ assert self.owner_name(game, 'F MAO') == 'FRANCE'
+ assert self.owner_name(game, 'F GAS') == 'FRANCE'
+ assert self.owner_name(game, 'F WES') == 'ITALY'
+ assert self.owner_name(game, 'F TUN') == 'ITALY'
+ assert self.owner_name(game, 'F TYS') is None
+ assert self.owner_name(game, 'F SPA') is None
+ assert self.owner_name(game, 'F SPA/NC') is None
+ assert self.owner_name(game, 'F SPA/SC') is None
+
+ # 6.I. TEST CASES, BUILDING
+ def test_6_i_1(self):
+ """ 6.I.1. TEST CASE, TOO MANY BUILD ORDERS
+ Check how program reacts when someone orders too many builds.
+ Germany may build one:
+ Germany: Build A Warsaw
+ Germany: Build A Kiel
+ Germany: Build A Munich
+ Program should not build all three, but handle it in an other way. See issue 4.D.4.
+ I prefer that the build orders are just handled one by one until all allowed units are build. According
+ to this preference, the build in Warsaw fails, the build in Kiel succeeds and the build in Munich fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'GERMANY', ['KIE', 'MUN', 'WAR'])
+ self.set_units(game, 'GERMANY', ['F NAO', 'F MAO'])
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'GERMANY', ['A WAR B', 'A KIE B', 'A MUN B'])
+ self.process(game)
+ assert self.check_results(game, 'A WAR', ['void'], phase='A')
+ assert self.check_results(game, 'A KIE', [''], phase='A')
+ assert self.check_results(game, 'A MUN', ['void'], phase='A')
+ assert self.owner_name(game, 'A WAR') is None
+ assert self.owner_name(game, 'A KIE') == 'GERMANY'
+ assert self.owner_name(game, 'A MUN') is None
+
+ def test_6_i_2(self):
+ """ 6.I.2. TEST CASE, FLEETS CAN NOT BE BUILD IN LAND AREAS
+ Physical this is possible, but it is still not allowed.
+ Russia has one build and Moscow is empty.
+ Russia: Build F Moscow
+ See issue 4.C.4. Some game masters will change the order and build an army in Moscow.
+ I prefer that the build fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'MOS')
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'RUSSIA', ['F MOS B'])
+ self.process(game)
+ assert self.check_results(game, 'F MOS', ['void'], phase='A')
+ assert self.owner_name(game, 'F MOS') is None
+
+ def test_6_i_3(self):
+ """ 6.I.3. TEST CASE, SUPPLY CENTER MUST BE EMPTY FOR BUILDING
+ You can't have two units in a sector. So, you can't build when there is a unit in the supply center.
+ Germany may build a unit but has an army in Berlin. Germany orders the following:
+ Germany: Build A Berlin
+ Build fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'GERMANY', ['MUN', 'BER'])
+ self.set_units(game, 'GERMANY', ['A BER'])
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'GERMANY', ['A BER B'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', ['void'], phase='A')
+ assert self.owner_name(game, 'A BER') == 'GERMANY'
+
+ def test_6_i_4(self):
+ """ 6.I.4. TEST CASE, BOTH COASTS MUST BE EMPTY FOR BUILDING
+ If a sector is occupied on one coast, the other coast can not be used for building.
+ Russia may build a unit and has a fleet in St Petersburg(sc). Russia orders the following:
+ Russia: Build A St Petersburg(nc)
+ Build fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', ['STP', 'MOS'])
+ self.set_units(game, 'RUSSIA', ['F STP/SC'])
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'RUSSIA', ['F STP/NC B'])
+ self.process(game)
+ assert self.check_results(game, 'F STP/NC', ['void'], phase='A')
+ assert self.owner_name(game, 'F STP') == 'RUSSIA'
+ assert self.owner_name(game, 'F STP/NC') is None
+ assert self.owner_name(game, 'F STP/SC') == 'RUSSIA'
+
+ def test_6_i_5(self):
+ """ 6.I.5. TEST CASE, BUILDING IN HOME SUPPLY CENTER THAT IS NOT OWNED
+ Building a unit is only allowed when supply center is a home supply center and is owned. If not owned,
+ build fails.
+ Russia captured Berlin in Fall. Left Berlin. Germany can not build in Berlin.
+ Germany: Build A Berlin
+ Build fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'GERMANY', 'MUN')
+ self.set_centers(game, 'RUSSIA', 'BER')
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'GERMANY', ['A BER B'])
+ self.process(game)
+ assert self.check_results(game, 'A BER', ['void'], phase='A')
+ assert self.owner_name(game, 'A BER') is None
+
+ def test_6_i_6(self):
+ """ 6.I.6. TEST CASE, BUILDING IN OWNED SUPPLY CENTER THAT IS NOT A HOME SUPPLY CENTER
+ Building a unit is only allowed when supply center is a home supply center and is owned. If it is not
+ a home supply center, the build fails.
+ Germany owns Warsaw, Warsaw is empty and Germany may build one unit.
+ Germany:
+ Build A Warsaw
+ Build fails.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'GERMANY', ['MUN', 'WAR'])
+ self.set_units(game, 'GERMANY', 'A MUN')
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'GERMANY', ['A WAR B'])
+ self.process(game)
+ assert self.check_results(game, 'A WAR', ['void'], phase='A')
+ assert self.owner_name(game, 'A WAR') is None
+
+ def test_6_i_7(self):
+ """ 6.I.7. TEST CASE, ONLY ONE BUILD IN A HOME SUPPLY CENTER
+ If you may build two units, you can still only build one in a supply center.
+ Russia owns Moscow, Moscow is empty and Russia may build two units.
+ Russia: Build A Moscow
+ Russia: Build A Moscow
+ The second build should fail.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', ['STP', 'MOS'])
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'RUSSIA', ['A MOS B', 'A MOS B'])
+ self.process(game)
+ assert self.check_results(game, 'A MOS', ['void', ''], phase='A')
+ assert self.owner_name(game, 'A MOS') == 'RUSSIA'
+
+ # 6.J. TEST CASES, CIVIL DISORDER AND DISBANDS
+ def test_6_j_1(self):
+ """ 6.J.1. TEST CASE, TOO MANY REMOVE ORDERS
+ Check how program reacts when someone orders too disbands.
+ France has to disband one and has an army in Paris and Picardy.
+ France: Remove F Gulf of Lyon
+ France: Remove A Picardy
+ France: Remove A Paris
+ Program should not disband both Paris and Picardy, but should handle it in a different way. See also
+ issue 4.D.6. I prefer that the disband orders are handled one by one. According to the preference, the
+ removal of the fleet in the Gulf of Lyon fails (no fleet), the removal of the army in Picardy succeeds and
+ the removal of the army in Paris fails (too many disbands).
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'FRANCE', 'PAR')
+ self.set_units(game, 'FRANCE', ['A PIC', 'A PAR'])
+ self.move_to_phase(game, 'W1901A')
+ if game.phase_type == 'A':
+ self.set_orders(game, 'FRANCE', ['F LYO D', 'A PIC D', 'A PAR D'])
+ self.process(game)
+ assert self.check_results(game, 'F LYO', ['void'], phase='A')
+ assert self.check_results(game, 'A PIC', [''], phase='A')
+ assert self.check_results(game, 'A PAR', ['void'], phase='A')
+ assert self.owner_name(game, 'F LYO') is None
+ assert self.owner_name(game, 'A PIC') is None
+ assert self.owner_name(game, 'A PAR') == 'FRANCE'
+
+ def test_6_j_2(self):
+ """ 6.J.2. TEST CASE, REMOVING THE SAME UNIT TWICE
+ If you have to remove two units, you can always try to trick the computer by removing the same unit twice.
+ France has to disband two and has an army in Paris.
+ France: Remove A Paris
+ France: Remove A Paris
+ Program should remove army in Paris and remove another unit by using the civil disorder rules.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'FRANCE', 'PAR')
+ self.set_units(game, 'FRANCE', ['A PIC', 'A PAR', 'F NAO'])
+ self.move_to_phase(game, 'W1901A')
+ self.set_orders(game, 'FRANCE', ['A PAR D', 'A PAR D'])
+ self.process(game)
+ assert self.check_results(game, 'A PAR', ['void', ''], phase='A')
+ assert self.owner_name(game, 'A PAR') is None
+ assert self.owner_name(game, 'A PIC') is None or self.owner_name(game, 'F NAO') is None
+
+ def test_6_j_3(self):
+ """ 6.J.3. TEST CASE, CIVIL DISORDER TWO ARMIES WITH DIFFERENT DISTANCE
+ When a player forgets to disband a unit, the civil disorder rules must be applied. When two armies
+ have different distance from the home supply centers, then the army with the greatest distance has to
+ be removed.
+ Russia has to remove one.
+ Russia has armies in Livonia and Sweden.
+ Russia does not order a disband.
+ The army in Sweden is removed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'SWE')
+ self.set_units(game, 'RUSSIA', ['A LVN', 'A SWE'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'A LVN') == 'RUSSIA'
+ assert self.owner_name(game, 'A SWE') is None
+
+ def test_6_j_4(self):
+ """ 6.J.4. TEST CASE, CIVIL DISORDER TWO ARMIES WITH EQUAL DISTANCE
+ If two armies have equal distance from the home supply centers, then alphabetical order is used.
+ Russia has to remove one.
+ Russia has armies in Livonia and Ukraine.
+ Russia does not order a disband.
+ Both armies have distance one. The Livonia army is removed, because it appears first in alphabetical order.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'STP')
+ self.set_units(game, 'RUSSIA', ['A LIV', 'A UKR'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'A LIV') is None
+ assert self.owner_name(game, 'A UKR') == 'RUSSIA'
+
+ def test_6_j_5(self):
+ """ 6.J.5 TEST CASE, CIVIL DISORDER TWO FLEETS WITH DIFFERENT DISTANCE
+ If two fleets have different distance from the home supply centers, then the fleet with the greatest
+ distance has to be removed. Note that fleets can not go over land.
+ Russia has to remove one.
+ Russia has fleets in Skagerrak and Berlin.
+ Russia does not order a disband.
+ The distance of the fleet in Berlin is three (the fleet can not go to Warsaw), the fleet in Skaggerrak
+ has distance two (via Norway). So, the fleet in Berlin has to be removed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'BER')
+ self.set_units(game, 'RUSSIA', ['F SKA', 'F BER'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+ assert self.owner_name(game, 'F BER') is None
+
+ def test_6_j_6(self):
+ """ 6.J.6. TEST CASE, CIVIL DISORDER TWO FLEETS WITH EQUAL DISTANCE
+ Alphabetical order is used, when two fleets have equal distance to the home supply centers.
+ Russia has to remove one.
+ Russia has fleets in Berlin and Helgoland Bight.
+ Russia does not order a disband.
+ The distances of both fleets to one of the home supply centers is three. The fleet in the Berlin is
+ removed, because it appears first in alphabetical order. This also tests whether fleets can not go over
+ land. If they could go over land, the distance of Berlin would be two (going to Warsaw) and the fleet in
+ the Helgoland Bight would have incorrectly be removed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'BER')
+ self.set_units(game, 'RUSSIA', ['F BER', 'F HEL'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'F BER') is None
+ assert self.owner_name(game, 'F HEL') == 'RUSSIA'
+
+ def test_6_j_7(self):
+ """ 6.J.7. TEST CASE, CIVIL DISORDER TWO FLEETS AND ARMY WITH EQUAL DISTANCE
+ In removal, the fleet has precedence over an army. In this case there are two fleets, to make the test
+ more complex.
+ Russia has to remove one.
+ Russia has an army in Bohemia, a fleet in Skagerrak and a fleet in the North Sea.
+ Russia does not order a disband.
+ The distances of the army and the fleets to one of the home supply centers are two. The fleets take
+ precedence above the army (although the army is alphabetical first). The fleet in the North Sea is
+ alphabetical first, compared to Skagerrak and has to be removed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', ['STP', 'MOS'])
+ self.set_units(game, 'RUSSIA', ['A BOH', 'F SKA', 'F NTH'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'A BOH') == 'RUSSIA'
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+ assert self.owner_name(game, 'F NTH') is None
+
+ def test_6_j_8(self):
+ """ 6.J.8. TEST CASE, CIVIL DISORDER A FLEET WITH SHORTER DISTANCE THEN THE ARMY
+ If the fleet has a shorter distance than the army, the army is removed.
+ Russia has to remove one.
+ Russia has an army in Tyrolia and a fleet in the Baltic Sea.
+ Russia does not order a disband.
+ The distances of the army to Warsaw is three while the distance of the fleet is two. So, the army
+ is removed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'STP')
+ self.set_units(game, 'RUSSIA', ['A TYR', 'F BAL'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'A TYR') is None
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+
+ def test_6_j_9(self):
+ """ 6.J.9. TEST CASE, CIVIL DISORDER MUST BE COUNTED FROM BOTH COASTS
+ Distance must be calculated from both coasts.
+
+ a)
+ Russia has to remove one.
+ Russia has an army in Tyrolia and a fleet in the Baltic Sea.
+ Russia does not order a disband.
+ The distance of the fleet to St Petersburg(nc) is three but to St Petersburg(sc) is two. So, the army
+ in Tyrolia must be removed.
+
+ b)
+ Russia has to remove one.
+ Russia has an army in Tyrolia and a fleet in Skagerrak.
+ Russia does not order a disband.
+ The distance of the fleet to St Petersburg(sc) is three but to St Petersburg(nc) is two. So, the army
+ in Tyrolia must be removed.
+ """
+ # a)
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'STP')
+ self.set_units(game, 'RUSSIA', ['A TYR', 'F BAL'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'A TYR') is None
+ assert self.owner_name(game, 'F BAL') == 'RUSSIA'
+
+ # b)
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'RUSSIA', 'STP')
+ self.set_units(game, 'RUSSIA', ['A TYR', 'F SKA'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'A TYR') is None
+ assert self.owner_name(game, 'F SKA') == 'RUSSIA'
+
+ def test_6_j_10(self):
+ """ 6.J.10. TEST CASE, CIVIL DISORDER COUNTING CONVOYING DISTANCE
+ For armies the distance must be calculated by taking land areas, coastal areas as sea areas.
+ Italy has to remove one.
+ Italy has a fleet in the Ionian Sea and armies in Greece and Silesia.
+ Italy does not order a disband.
+ The distance from Greece to one of the Italian home supply center is three over land. However, using
+ a convoy the distance is one or two (depending how you count, see issue 4.D.8). Anyway, the army in
+ Silesia has to be removed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'ITALY', ['GRE', 'NAP'])
+ self.set_units(game, 'ITALY', ['F ION', 'A GRE', 'A SIL'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'F ION') == 'ITALY'
+ assert self.owner_name(game, 'A GRE') == 'ITALY'
+ assert self.owner_name(game, 'A SIL') is None
+
+ def test_6_j_11(self):
+ """ 6.J.11. TEST CASE, CIVIL DISORDER COUNTING DISTANCE WITHOUT CONVOYING FLEET
+ If there is no convoying fleet the result depends on the interpretation of the rules.
+ Italy has to remove one.
+ Italy has armies in Greece and Silesia.
+ Italy does not order a disband.
+ The distance from Greece to one of the Italian home supply centers is one, two or three (depending how
+ you count, see issue 4.D.8).
+ I prefer that sea areas just add one to the distance. According to this preference, the distance is two
+ and the army in Silesia has to be removed.
+ """
+ game = self.create_game()
+ self.clear_units(game)
+ self.clear_centers(game)
+ self.set_centers(game, 'ITALY', 'GRE')
+ self.set_units(game, 'ITALY', ['A GRE', 'A SIL'])
+ self.move_to_phase(game, 'W1901A')
+ self.process(game)
+ assert self.owner_name(game, 'A GRE') == 'ITALY'
+ assert self.owner_name(game, 'A SIL') is None
+
+def check_dislodged(game, unit, dislodger):
+ """ Checks if a unit has been dislodged """
+ if not game:
+ return False
+ if unit not in game.dislodged:
+ return False
+ return game.dislodged[unit] == ''.join(dislodger.split()[1:])[:3]