| 
									
										
										
										
											2025-05-21 14:30:39 +02:00
										 |  |  | from unittest import TestCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from test.bases import WorldTestBase | 
					
						
							| 
									
										
										
										
											2025-07-28 17:01:57 +02:00
										 |  |  | from .. import ShapezWorld | 
					
						
							| 
									
										
										
										
											2025-05-21 14:30:39 +02:00
										 |  |  | from ..data.strings import GOALS, OTHER, ITEMS, LOCATIONS, CATEGORY, OPTIONS, SHAPESANITY | 
					
						
							|  |  |  | from ..options import max_levels_and_upgrades, max_shapesanity | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ShapezTestBase(WorldTestBase): | 
					
						
							|  |  |  |     game = OTHER.game_name | 
					
						
							|  |  |  |     world: ShapezWorld | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_location_count(self): | 
					
						
							|  |  |  |         self.assertTrue(self.world.location_count > 0, | 
					
						
							|  |  |  |                         f"location_count is {self.world.location_count} for some reason.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_logic_lists(self): | 
					
						
							|  |  |  |         logic_buildings = [ITEMS.cutter, ITEMS.rotator, ITEMS.painter, ITEMS.color_mixer, ITEMS.stacker] | 
					
						
							|  |  |  |         for building in logic_buildings: | 
					
						
							|  |  |  |             count = self.world.level_logic.count(building) | 
					
						
							|  |  |  |             self.assertTrue(count == 1, f"{building} was found {count} times in level_logic.") | 
					
						
							|  |  |  |             count = self.world.upgrade_logic.count(building) | 
					
						
							|  |  |  |             self.assertTrue(count == 1, f"{building} was found {count} times in upgrade_logic.") | 
					
						
							|  |  |  |         self.assertTrue(len(self.world.level_logic) == 5, | 
					
						
							|  |  |  |                         f"level_logic contains {len(self.world.level_logic)} entries instead of the expected 5.") | 
					
						
							|  |  |  |         self.assertTrue(len(self.world.upgrade_logic) == 5, | 
					
						
							|  |  |  |                         f"upgrade_logic contains {len(self.world.upgrade_logic)} entries instead of the expected 5.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_random_logic_phase_length(self): | 
					
						
							|  |  |  |         self.assertTrue(len(self.world.random_logic_phase_length) == 5, | 
					
						
							|  |  |  |                         f"random_logic_phase_length contains {len(self.world.random_logic_phase_length)} entries " + | 
					
						
							|  |  |  |                         f"instead of the expected 5.") | 
					
						
							|  |  |  |         self.assertTrue(sum(self.world.random_logic_phase_length) < self.world.maxlevel, | 
					
						
							|  |  |  |                         f"The sum of all random phase lengths is greater than allowed: " + | 
					
						
							|  |  |  |                         str(sum(self.world.random_logic_phase_length))) | 
					
						
							|  |  |  |         for length in self.world.random_logic_phase_length: | 
					
						
							|  |  |  |             self.assertTrue(length in range(self.world.maxlevel), | 
					
						
							|  |  |  |                             f"Found an illegal value in random_logic_phase_length: {length}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_category_random_logic_amounts(self): | 
					
						
							|  |  |  |         self.assertTrue(len(self.world.category_random_logic_amounts) == 4, | 
					
						
							|  |  |  |                         f"Found {len(self.world.category_random_logic_amounts)} instead of 4 keys in " | 
					
						
							|  |  |  |                         f"category_random_logic_amounts.") | 
					
						
							|  |  |  |         self.assertTrue(min(self.world.category_random_logic_amounts.values()) == 0, | 
					
						
							|  |  |  |                         "Found a value less than or no 0 in category_random_logic_amounts.") | 
					
						
							|  |  |  |         self.assertTrue(max(self.world.category_random_logic_amounts.values()) <= 5, | 
					
						
							|  |  |  |                         "Found a value greater than 5 in category_random_logic_amounts.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_maxlevel_and_finaltier(self): | 
					
						
							|  |  |  |         self.assertTrue(self.world.maxlevel in range(25, max_levels_and_upgrades), | 
					
						
							|  |  |  |                         f"Found an illegal value for maxlevel: {self.world.maxlevel}") | 
					
						
							|  |  |  |         self.assertTrue(self.world.finaltier in range(8, max_levels_and_upgrades+1), | 
					
						
							|  |  |  |                         f"Found an illegal value for finaltier: {self.world.finaltier}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_included_locations(self): | 
					
						
							|  |  |  |         self.assertTrue(len(self.world.included_locations) > 0, "Found no locations cached in included_locations.") | 
					
						
							|  |  |  |         self.assertTrue(LOCATIONS.level(1) in self.world.included_locations.keys(), | 
					
						
							|  |  |  |                         "Could not find Level 1 (guraranteed location) cached in included_locations.") | 
					
						
							|  |  |  |         self.assertTrue(LOCATIONS.upgrade(CATEGORY.belt, "II") in self.world.included_locations.keys(), | 
					
						
							|  |  |  |                         "Could not find Belt Upgrade Tier II (guraranteed location) cached in included_locations.") | 
					
						
							|  |  |  |         self.assertTrue(LOCATIONS.shapesanity(1) in self.world.included_locations.keys(), | 
					
						
							|  |  |  |                         "Could not find Shapesanity 1 (guraranteed location) cached in included_locations.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_shapesanity_names(self): | 
					
						
							|  |  |  |         names_length = len(self.world.shapesanity_names) | 
					
						
							|  |  |  |         locations_length = len([0 for loc in self.multiworld.get_locations(self.player) if "Shapesanity" in loc.name]) | 
					
						
							|  |  |  |         self.assertEqual(names_length, locations_length, | 
					
						
							|  |  |  |                          f"The amount of shapesanity names ({names_length}) does not match the amount of included " + | 
					
						
							|  |  |  |                          f"shapesanity locations ({locations_length}).") | 
					
						
							|  |  |  |         self.assertTrue(SHAPESANITY.full(SHAPESANITY.uncolored, SHAPESANITY.circle) in self.world.shapesanity_names, | 
					
						
							|  |  |  |                         "Uncolored Circle is guaranteed but was not found in shapesanity_names.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_efficiency_iii_no_softlock(self): | 
					
						
							|  |  |  |         if self.world.options.goal == GOALS.efficiency_iii: | 
					
						
							|  |  |  |             for item in self.multiworld.itempool: | 
					
						
							|  |  |  |                 self.assertFalse(item.name.endswith("Upgrade Trap"), | 
					
						
							|  |  |  |                                  "Item pool contains an upgrade trap, which could make the efficiency_iii goal " | 
					
						
							|  |  |  |                                  "unreachable if collected.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestGlobalOptionsImport(TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_global_options_import(self): | 
					
						
							|  |  |  |         self.assertTrue(isinstance(max_levels_and_upgrades, int), f"The global option max_levels_and_upgrades is not " + | 
					
						
							|  |  |  |                                                                   f"an integer, but instead a " + | 
					
						
							|  |  |  |                                                                   f"{type(max_levels_and_upgrades)}.") | 
					
						
							|  |  |  |         self.assertTrue(max_levels_and_upgrades >= 27, f"max_levels_and_upgrades must be at least 27, but is " + | 
					
						
							|  |  |  |                                                        f"{max_levels_and_upgrades} instead.") | 
					
						
							|  |  |  |         self.assertTrue(isinstance(max_shapesanity, int), f"The global option max_shapesanity is not an integer, but " + | 
					
						
							|  |  |  |                                                           f"instead a {type(max_levels_and_upgrades)}.") | 
					
						
							|  |  |  |         self.assertTrue(max_shapesanity >= 4, f"max_shapesanity must be at least 4, but is " + | 
					
						
							|  |  |  |                                               f"{max_levels_and_upgrades} instead.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-06-06 00:05:53 +02:00
										 |  |  | # The following unittests are intended to test all code paths of the generator | 
					
						
							| 
									
										
										
										
											2025-05-21 14:30:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestAllRelevantOptions1(ShapezTestBase): | 
					
						
							|  |  |  |     options = { | 
					
						
							|  |  |  |         "goal": GOALS.vanilla, | 
					
						
							|  |  |  |         "randomize_level_requirements": False, | 
					
						
							|  |  |  |         "randomize_upgrade_requirements": False, | 
					
						
							|  |  |  |         "complexity_growth_gradient": "0.1234", | 
					
						
							|  |  |  |         "early_balancer_tunnel_and_trash": "none", | 
					
						
							|  |  |  |         "lock_belt_and_extractor": True, | 
					
						
							|  |  |  |         "include_achievements": True, | 
					
						
							|  |  |  |         "exclude_softlock_achievements": False, | 
					
						
							|  |  |  |         "exclude_long_playtime_achievements": False, | 
					
						
							|  |  |  |         "exclude_progression_unreasonable": True, | 
					
						
							|  |  |  |         "shapesanity_amount": max_shapesanity, | 
					
						
							|  |  |  |         "traps_percentage": "random" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestAllRelevantOptions2(ShapezTestBase): | 
					
						
							|  |  |  |     options = { | 
					
						
							|  |  |  |         "goal": GOALS.mam, | 
					
						
							|  |  |  |         "goal_amount": max_levels_and_upgrades, | 
					
						
							|  |  |  |         "randomize_level_requirements": True, | 
					
						
							|  |  |  |         "randomize_upgrade_requirements": True, | 
					
						
							|  |  |  |         "randomize_level_logic": OPTIONS.logic_random_steps, | 
					
						
							|  |  |  |         "randomize_upgrade_logic": OPTIONS.logic_vanilla_like, | 
					
						
							|  |  |  |         "complexity_growth_gradient": "2", | 
					
						
							|  |  |  |         "early_balancer_tunnel_and_trash": OPTIONS.buildings_5, | 
					
						
							|  |  |  |         "lock_belt_and_extractor": False, | 
					
						
							|  |  |  |         "include_achievements": True, | 
					
						
							|  |  |  |         "exclude_softlock_achievements": False, | 
					
						
							|  |  |  |         "exclude_long_playtime_achievements": False, | 
					
						
							|  |  |  |         "exclude_progression_unreasonable": False, | 
					
						
							|  |  |  |         "shapesanity_amount": 4, | 
					
						
							|  |  |  |         "traps_percentage": 0 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestAllRelevantOptions3(ShapezTestBase): | 
					
						
							|  |  |  |     options = { | 
					
						
							|  |  |  |         "goal": GOALS.even_fasterer, | 
					
						
							|  |  |  |         "goal_amount": max_levels_and_upgrades, | 
					
						
							|  |  |  |         "randomize_level_requirements": True, | 
					
						
							|  |  |  |         "randomize_upgrade_requirements": True, | 
					
						
							|  |  |  |         "randomize_level_logic": f"{OPTIONS.logic_vanilla}_shuffled", | 
					
						
							|  |  |  |         "randomize_upgrade_logic": OPTIONS.logic_linear, | 
					
						
							|  |  |  |         "complexity_growth_gradient": "1e-003", | 
					
						
							|  |  |  |         "early_balancer_tunnel_and_trash": OPTIONS.buildings_3, | 
					
						
							|  |  |  |         "lock_belt_and_extractor": False, | 
					
						
							|  |  |  |         "include_achievements": True, | 
					
						
							|  |  |  |         "exclude_softlock_achievements": True, | 
					
						
							|  |  |  |         "exclude_long_playtime_achievements": True, | 
					
						
							|  |  |  |         "shapesanity_amount": "random", | 
					
						
							|  |  |  |         "traps_percentage": 100, | 
					
						
							|  |  |  |         "include_whacky_upgrades": True, | 
					
						
							|  |  |  |         "split_inventory_draining_trap": True | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestAllRelevantOptions4(ShapezTestBase): | 
					
						
							|  |  |  |     options = { | 
					
						
							|  |  |  |         "goal": GOALS.efficiency_iii, | 
					
						
							|  |  |  |         "randomize_level_requirements": True, | 
					
						
							|  |  |  |         "randomize_upgrade_requirements": True, | 
					
						
							|  |  |  |         "randomize_level_logic": f"{OPTIONS.logic_stretched}_shuffled", | 
					
						
							|  |  |  |         "randomize_upgrade_logic": OPTIONS.logic_category, | 
					
						
							|  |  |  |         "early_balancer_tunnel_and_trash": OPTIONS.sphere_1, | 
					
						
							|  |  |  |         "lock_belt_and_extractor": False, | 
					
						
							|  |  |  |         "include_achievements": True, | 
					
						
							|  |  |  |         "exclude_softlock_achievements": True, | 
					
						
							|  |  |  |         "exclude_long_playtime_achievements": True, | 
					
						
							|  |  |  |         "shapesanity_amount": "random", | 
					
						
							|  |  |  |         "traps_percentage": "random", | 
					
						
							|  |  |  |         "include_whacky_upgrades": True, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestAllRelevantOptions5(ShapezTestBase): | 
					
						
							|  |  |  |     options = { | 
					
						
							|  |  |  |         "goal": GOALS.mam, | 
					
						
							|  |  |  |         "goal_amount": "random-range-27-500", | 
					
						
							|  |  |  |         "randomize_level_requirements": True, | 
					
						
							|  |  |  |         "randomize_upgrade_requirements": True, | 
					
						
							|  |  |  |         "randomize_level_logic": f"{OPTIONS.logic_quick}_shuffled", | 
					
						
							|  |  |  |         "randomize_upgrade_logic": OPTIONS.logic_category_random, | 
					
						
							|  |  |  |         "lock_belt_and_extractor": False, | 
					
						
							|  |  |  |         "include_achievements": True, | 
					
						
							|  |  |  |         "exclude_softlock_achievements": True, | 
					
						
							|  |  |  |         "exclude_long_playtime_achievements": True, | 
					
						
							|  |  |  |         "shapesanity_amount": "random", | 
					
						
							|  |  |  |         "traps_percentage": 100, | 
					
						
							|  |  |  |         "split_inventory_draining_trap": False | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestAllRelevantOptions6(ShapezTestBase): | 
					
						
							|  |  |  |     options = { | 
					
						
							|  |  |  |         "goal": GOALS.mam, | 
					
						
							|  |  |  |         "goal_amount": "random-range-27-500", | 
					
						
							|  |  |  |         "randomize_level_requirements": True, | 
					
						
							|  |  |  |         "randomize_upgrade_requirements": True, | 
					
						
							|  |  |  |         "randomize_level_logic": OPTIONS.logic_hardcore, | 
					
						
							|  |  |  |         "randomize_upgrade_logic": OPTIONS.logic_hardcore, | 
					
						
							|  |  |  |         "lock_belt_and_extractor": False, | 
					
						
							|  |  |  |         "include_achievements": False, | 
					
						
							|  |  |  |         "shapesanity_amount": "random", | 
					
						
							|  |  |  |         "traps_percentage": "random" | 
					
						
							|  |  |  |     } |