diff --git a/.travis.yml b/.travis.yml index eb836385d..9a3de4398 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ jobs: - docker exec app pip install --upgrade pipenv # Create pipenv virtual environment and install dev packages for testing # Command origins from here: https://stackoverflow.com/a/28037991/10882657 - - docker exec -i app bash -c "cd /root/template && pipenv install --dev" + - docker exec -i app bash -c "cd /root/template && pipenv install --dev --python 3.7" # Run tests - docker exec -i app bash -c "cd /root/template && pipenv run pytest test/" # Shut down and remove container @@ -43,7 +43,7 @@ jobs: - docker run -it -d --name app python:3.8-rc-slim - docker cp . app:/root/template - docker exec app pip install --upgrade pipenv - - docker exec -i app bash -c "cd /root/template && pipenv --python python install --dev" + - docker exec -i app bash -c "cd /root/template && pipenv --python python install --dev --python 3.8" - docker exec -i app bash -c "cd /root/template && pipenv run pytest test/" - docker rm -f app diff --git a/examples/terran/ramp_wall.py b/examples/terran/ramp_wall.py index a8001ea0e..e8c7f6725 100644 --- a/examples/terran/ramp_wall.py +++ b/examples/terran/ramp_wall.py @@ -43,7 +43,6 @@ async def on_step(self, iteration): # Uncomment the following if you want to build 3 supplydepots in the wall instead of a barracks in the middle + 2 depots in the corner # depot_placement_positions = self.main_base_ramp.corner_depots | {self.main_base_ramp.depot_in_middle} - barracks_placement_position = None barracks_placement_position = self.main_base_ramp.barracks_correct_placement # If you prefer to have the barracks in the middle without room for addons, use the following instead # barracks_placement_position = self.main_base_ramp.barracks_in_middle @@ -51,22 +50,29 @@ async def on_step(self, iteration): depots = self.units(SUPPLYDEPOT) | self.units(SUPPLYDEPOTLOWERED) # Draw ramp points - # def terrain_to_z_height(h): - # return round(16 * h / 255, 2) - - # for ramp in self.game_info.map_ramps: - # for p in ramp.points: - # h = self.get_terrain_height(p) - # h2 = terrain_to_z_height(h) - # pos = Point3((p.x, p.y, h2)) - # p0 = Point3((pos.x - 0.25, pos.y - 0.25, pos.z)) - # p1 = Point3((pos.x + 0.25, pos.y + 0.25, pos.z - 0.5)) - # print(f"drawing {p0} to {p1}") - # self._client.debug_box_out(p0, p1, color=Point3((255, 0, 0))) - # - # await self._client.send_debug() - - # Filter locations close to finished supply depots + def terrain_to_z_height(h): + return round(16 * h / 255, 2) + + for ramp in self.game_info.map_ramps: + for p in ramp.points: + h = self.get_terrain_height(p) + h2 = terrain_to_z_height(h) + pos = Point3((p.x, p.y, h2)) + p0 = Point3((pos.x - 0.25, pos.y - 0.25, pos.z)) + p1 = Point3((pos.x + 0.25, pos.y + 0.25, pos.z - 0.5)) + # print(f"Drawing {p0} to {p1}") + color=Point3((255, 0, 0)) + if p in ramp.upper: + color = Point3((0, 255, 0)) + if p in ramp.upper2_for_ramp_wall: + color = Point3((0, 255, 255)) + if p in ramp.lower: + color = Point3((0, 0, 255)) + self._client.debug_box_out(p0, p1, color=color) + + await self._client.send_debug() + + # # Filter locations close to finished supply depots if depots: depot_placement_positions = {d for d in depot_placement_positions if depots.closest_distance_to(d) > 1} @@ -82,7 +88,7 @@ async def on_step(self, iteration): await self.do(w.build(SUPPLYDEPOT, target_depot_location)) # Build barracks - if depots.ready.exists and self.can_afford(BARRACKS) and not self.already_pending(BARRACKS): + if depots.ready and self.can_afford(BARRACKS) and not self.already_pending(BARRACKS): if self.units(BARRACKS).amount + self.already_pending(BARRACKS) > 0: return ws = self.workers.gathering @@ -108,6 +114,7 @@ def main(): "DarknessSanctuaryLE", "ParaSiteLE", # Has 5 upper points at the main ramp "AcolyteLE", # Has 4 upper points at the ramp to the in-base natural and 2 upper points at the small ramp + "HonorgroundsLE", # Has 4 or 9 upper points at the large main base ramp ] ) sc2.run_game( diff --git a/sc2/bot_ai.py b/sc2/bot_ai.py index a9120b9bd..250d4f73d 100644 --- a/sc2/bot_ai.py +++ b/sc2/bot_ai.py @@ -5,8 +5,6 @@ from collections import Counter from typing import Any, Dict, List, Optional, Set, Tuple, Union # mypy type checking -from s2clientprotocol import common_pb2 as common_pb - from .cache import property_cache_forever, property_cache_once_per_frame from .data import ActionResult, Alert, Race, Result, Target, race_gas, race_townhalls, race_worker from .game_data import AbilityData, GameData @@ -126,15 +124,24 @@ def known_enemy_structures(self) -> Units: @property def main_base_ramp(self) -> "Ramp": - """ Returns the Ramp instance of the closest main-ramp to start location. Look in game_info.py for more information """ + """ Returns the Ramp instance of the closest main-ramp to start location. + Look in game_info.py for more information """ if hasattr(self, "cached_main_base_ramp"): return self.cached_main_base_ramp - """ The reason for len(ramp.upper) in {2, 5} is: - ParaSite map has 5 upper points, and most other maps have 2 upper points at the main ramp. The map Acolyte has 4 upper points at the wrong ramp (which is closest to the start position) """ - self.cached_main_base_ramp = min( - (ramp for ramp in self.game_info.map_ramps if len(ramp.upper) in {2, 5}), - key=lambda r: self.start_location.distance_to(r.top_center), - ) + # The reason for len(ramp.upper) in {2, 5} is: + # ParaSite map has 5 upper points, and most other maps have 2 upper points at the main ramp. + # The map Acolyte has 4 upper points at the wrong ramp (which is closest to the start position). + try: + self.cached_main_base_ramp = min( + (ramp for ramp in self.game_info.map_ramps if len(ramp.upper) in {2, 5}), + key=lambda r: self.start_location.distance_to(r.top_center), + ) + except ValueError: + # Hardcoded hotfix for Honorgrounds LE map, as that map has a large main base ramp with inbase natural + self.cached_main_base_ramp = min( + (ramp for ramp in self.game_info.map_ramps if len(ramp.upper) in {4, 9}), + key=lambda r: self.start_location.distance_to(r.top_center), + ) return self.cached_main_base_ramp @property_cache_forever @@ -149,13 +156,9 @@ def expansion_locations(self) -> Dict[Point2, Units]: # Distance we group resources by RESOURCE_SPREAD_THRESHOLD = 8.5 - minerals = self.state.mineral_field geysers = self.state.vespene_geyser - all_resources = minerals | geysers - # Presort resources to get faster clustering - all_resources.sort(key=lambda resource: (resource.position.x, resource.position.y)) # Create a group for every resource - resource_groups = [[resource] for resource in all_resources] + resource_groups = [[resource] for resource in self.state.resources] # Loop the merging process as long as we change something found_something = True while found_something: @@ -177,9 +180,8 @@ def expansion_locations(self) -> Dict[Point2, Units]: offset_range = 7 offsets = [ (x, y) - for x in range(-offset_range, offset_range + 1) - for y in range(-offset_range, offset_range + 1) - if 4 <= math.hypot(x, y) <= 7 + for x, y in itertools.product(range(-offset_range, offset_range + 1), repeat=2) + if math.hypot(x, y) <= 8 ] # Dict we want to return centers = {} @@ -189,20 +191,19 @@ def expansion_locations(self) -> Dict[Point2, Units]: amount = len(resources) # Calculate center, round and add 0.5 because expansion location will have (x.5, y.5) # coordinates because bases have size 5. - center_x = round(sum(resource.position.x for resource in resources) / amount) + 0.5 - center_y = round(sum(resource.position.y for resource in resources) / amount) + 0.5 + center_x = int(sum(resource.position.x for resource in resources) / amount) + 0.5 + center_y = int(sum(resource.position.y for resource in resources) / amount) + 0.5 possible_points = (Point2((offset[0] + center_x, offset[1] + center_y)) for offset in offsets) # Filter out points that are too near possible_points = ( point for point in possible_points # Check if point can be built on - if self._game_info.placement_grid[point.rounded] != 0 + if self._game_info.placement_grid[point.rounded] == 1 # Check if all resources have enough space to point - and all(point.distance_to(resource) >= (7 if resource in geysers else 6) for resource in resources) + and all(point.distance_to(resource) > (7 if resource in geysers else 6) for resource in resources) ) # Choose best fitting point - # TODO can we improve this by calculating the distance only one time? result = min(possible_points, key=lambda point: sum(point.distance_to(resource) for resource in resources)) centers[result] = resources return centers diff --git a/sc2/client.py b/sc2/client.py index 039de3e0f..3c269c1e9 100644 --- a/sc2/client.py +++ b/sc2/client.py @@ -138,6 +138,26 @@ async def get_game_data(self) -> GameData: ) return GameData(result.data) + async def dump_data(self, ability_id=True, unit_type_id=True, upgrade_id=True, buff_id=True, effect_id=True): + """ + Dump the game data files + choose what data to dump in the keywords + this function writes to a text file + call it one time in on_step with: + await self._client.dump_data() + """ + result = await self._execute( + data=sc_pb.RequestData( + ability_id=ability_id, + unit_type_id=unit_type_id, + upgrade_id=upgrade_id, + buff_id=buff_id, + effect_id=effect_id, + ) + ) + with open("data_dump.txt", "a") as file: + file.write(str(result.data)) + async def get_game_info(self) -> GameInfo: result = await self._execute(game_info=sc_pb.RequestGameInfo()) return GameInfo(result.game_info) diff --git a/sc2/game_info.py b/sc2/game_info.py index 6a3285ba5..1dd2a21fb 100644 --- a/sc2/game_info.py +++ b/sc2/game_info.py @@ -92,8 +92,10 @@ def bottom_center(self) -> Point2: return pos @property_immutable_cache - def barracks_in_middle(self) -> Point2: + def barracks_in_middle(self) -> Optional[Point2]: """ Barracks position in the middle of the 2 depots """ + if len(self.upper) not in {2, 5}: + return None if len(self.upper2_for_ramp_wall) == 2: points = self.upper2_for_ramp_wall p1 = points.pop().offset((self.x_offset, self.y_offset)) @@ -105,14 +107,18 @@ def barracks_in_middle(self) -> Point2: raise Exception("Not implemented. Trying to access a ramp that has a wrong amount of upper points.") @property_immutable_cache - def depot_in_middle(self) -> Point2: + def depot_in_middle(self) -> Optional[Point2]: """ Depot in the middle of the 3 depots """ if len(self.upper2_for_ramp_wall) == 2: points = self.upper2_for_ramp_wall - p1 = points.pop().offset((self.x_offset, self.y_offset)) # still an error with pixelmap? + p1 = points.pop().offset((self.x_offset, self.y_offset)) p2 = points.pop().offset((self.x_offset, self.y_offset)) # Offset from top point to depot center is (1.5, 0.5) - intersects = p1.circle_intersection(p2, 2.5 ** 0.5) + try: + intersects = p1.circle_intersection(p2, 2.5 ** 0.5) + except AssertionError: + # Returns None when no placement was found, this is the case on the map Honorgrounds LE with an exceptionally large main base ramp + return None anyLowerPoint = next(iter(self.lower)) return max(intersects, key=lambda p: p.distance_to_point2(anyLowerPoint)) raise Exception("Not implemented. Trying to access a ramp that has a wrong amount of upper points.") @@ -120,12 +126,16 @@ def depot_in_middle(self) -> Point2: @property_mutable_cache def corner_depots(self) -> Set[Point2]: """ Finds the 2 depot positions on the outside """ + if not self.upper2_for_ramp_wall: + return set() if len(self.upper2_for_ramp_wall) == 2: points = self.upper2_for_ramp_wall - p1 = points.pop().offset((self.x_offset, self.y_offset)) # still an error with pixelmap? + p1 = points.pop().offset((self.x_offset, self.y_offset)) p2 = points.pop().offset((self.x_offset, self.y_offset)) center = p1.towards(p2, p1.distance_to_point2(p2) / 2) depotPosition = self.depot_in_middle + if depotPosition is None: + return set() # Offset from middle depot to corner depots is (2, 1) intersects = center.circle_intersection(depotPosition, 5 ** 0.5) return intersects @@ -140,8 +150,10 @@ def barracks_can_fit_addon(self) -> bool: raise Exception("Not implemented. Trying to access a ramp that has a wrong amount of upper points.") @property_immutable_cache - def barracks_correct_placement(self) -> Point2: + def barracks_correct_placement(self) -> Optional[Point2]: """ Corrected placement so that an addon can fit """ + if self.barracks_in_middle is None: + return None if len(self.upper2_for_ramp_wall) == 2: if self.barracks_can_fit_addon: return self.barracks_in_middle diff --git a/sc2/unit.py b/sc2/unit.py index de4559774..213048a5f 100644 --- a/sc2/unit.py +++ b/sc2/unit.py @@ -43,9 +43,7 @@ def __repr__(self) -> str: return f"UnitOrder({self.ability}, {self.target}, {self.progress})" -class PassengerUnit: - """ Is inherited by the Unit class. Everything in here is also available in Unit. """ - +class Unit: def __init__(self, proto_data): self._proto = proto_data self.cache = {} @@ -302,11 +300,6 @@ def energy_percentage(self) -> Union[int, float]: return 0 return self._proto.energy / self._proto.energy_max - -class Unit(PassengerUnit): - - # All type data is in PassengerUnit. - @property_immutable_cache def is_snapshot(self) -> bool: """ Checks if the unit is only available as a snapshot for the bot. @@ -396,6 +389,11 @@ def is_revealed(self) -> bool: """ Checks if the unit is revealed. """ return self._proto.cloak is CloakState.CloakedDetected.value + @property_immutable_cache + def can_be_attacked(self) -> bool: + """ Checks if the unit is revealed or not cloaked and therefore can be attacked """ + return self._proto.cloak in {CloakState.NotCloaked.value, CloakState.CloakedDetected.value} + @property_immutable_cache def buffs(self) -> Set: """ Returns the set of current buffs the unit has. """ @@ -558,7 +556,8 @@ def is_idle(self) -> bool: return not self.orders def is_using_ability(self, abilities: Union[AbilityId, Set[AbilityId]]) -> bool: - """ Check if the unit is using one of the given abilities. """ + """ Check if the unit is using one of the given abilities. + Only works for own units. """ if not self.orders: return False if isinstance(abilities, AbilityId): @@ -567,12 +566,14 @@ def is_using_ability(self, abilities: Union[AbilityId, Set[AbilityId]]) -> bool: @property_immutable_cache def is_moving(self) -> bool: - """ Checks if the unit is moving. """ + """ Checks if the unit is moving. + Only works for own units. """ return self.is_using_ability(AbilityId.MOVE) @property_immutable_cache def is_attacking(self) -> bool: - """ Checks if the unit is attacking. """ + """ Checks if the unit is attacking. + Only works for own units. """ return self.is_using_ability( { AbilityId.ATTACK, @@ -585,27 +586,32 @@ def is_attacking(self) -> bool: @property_immutable_cache def is_patrolling(self) -> bool: - """ Checks if a unit is patrolling. """ + """ Checks if a unit is patrolling. + Only works for own units. """ return self.is_using_ability(AbilityId.PATROL) @property_immutable_cache def is_gathering(self) -> bool: - """ Checks if a unit is on its way to a mineral field or vespene geyser to mine. """ + """ Checks if a unit is on its way to a mineral field or vespene geyser to mine. + Only works for own units. """ return self.is_using_ability(AbilityId.HARVEST_GATHER) @property_immutable_cache def is_returning(self) -> bool: - """ Checks if a unit is returning from mineral field or vespene geyser to deliver resources to townhall. """ + """ Checks if a unit is returning from mineral field or vespene geyser to deliver resources to townhall. + Only works for own units. """ return self.is_using_ability(AbilityId.HARVEST_RETURN) @property_immutable_cache def is_collecting(self) -> bool: - """ Checks if a unit is gathering or returning. """ + """ Checks if a unit is gathering or returning. + Only works for own units. """ return self.is_using_ability({AbilityId.HARVEST_GATHER, AbilityId.HARVEST_RETURN}) @property_immutable_cache def is_constructing_scv(self) -> bool: - """ Checks if the unit is an SCV that is currently building. """ + """ Checks if the unit is an SCV that is currently building. + Only works for own units. """ return self.is_using_ability( { AbilityId.TERRANBUILD_ARMORY, @@ -626,12 +632,14 @@ def is_constructing_scv(self) -> bool: @property_immutable_cache def is_transforming(self) -> bool: - """ Checks if the unit transforming. """ + """ Checks if the unit transforming. + Only works for own units. """ return self.type_id in transforming and self.is_using_ability(transforming[self.type_id]) @property_immutable_cache def is_repairing(self) -> bool: - """ Checks if the unit is an SCV or MULE that is currently repairing. """ + """ Checks if the unit is an SCV or MULE that is currently repairing. + Only works for own units. """ return self.is_using_ability( {AbilityId.EFFECT_REPAIR, AbilityId.EFFECT_REPAIR_MULE, AbilityId.EFFECT_REPAIR_SCV} ) @@ -653,9 +661,9 @@ def add_on_land_position(self) -> Point2: return self.position.offset(Point2((-2.5, 0.5))) @property_mutable_cache - def passengers(self) -> Set["PassengerUnit"]: + def passengers(self) -> Set["Unit"]: """ Returns the units inside a Bunker, CommandCenter, PlanetaryFortress, Medivac, Nydus, Overlord or WarpPrism. """ - return {PassengerUnit(unit) for unit in self._proto.passengers} + return {Unit(unit) for unit in self._proto.passengers} @property_mutable_cache def passengers_tags(self) -> Set[int]: diff --git a/test/generate_pickle_files_bot.py b/test/generate_pickle_files_bot.py index 5352da7cd..e4a22789b 100644 --- a/test/generate_pickle_files_bot.py +++ b/test/generate_pickle_files_bot.py @@ -37,9 +37,6 @@ class ExporterBot(sc2.BotAI): async def on_step(self, iteration): - if iteration == 0: - await self.on_first_iteration() - actions = [] await self.do_actions(actions) @@ -76,27 +73,61 @@ async def on_start_async(self): def main(): maps = [ + "16-BitLE", + "AbiogenesisLE", + "AbyssalReefLE", + "AcidPlantLE", + "AcolyteLE", "Acropolis", "Artana", - "CrystalCavern", - "DigitalFrontier", - "OldSunshine", - "Treachery", - "Triton", + "AscensiontoAiurLE", "AutomatonLE", + "BackwaterLE", + "Bandwidth", + "BattleontheBoardwalkLE", + "BelShirVestigeLE", + "BlackpinkLE", + "BloodBoilLE", "BlueshiftLE", + "CactusValleyLE", + "CatalystLE", "CeruleanFallLE", + "CrystalCavern", + "CyberForestLE", "DarknessSanctuaryLE", + "DefendersLandingLE", + "DigitalFrontier", + "DreamcatcherLE", + "EastwatchLE", + "Ephemeron", + "FractureLE", + "FrostLE", + "HonorgroundsLE", + "InterloperLE", "KairosJunctionLE", + "KingsCoveLE", + "LostandFoundLE", + "MechDepotLE", + "NeonVioletSquareLE", + "NewkirkPrecinctTE", + "NewRepugnancyLE", + "OdysseyLE", + "OldSunshine", + "PaladinoTerminalLE", "ParaSiteLE", "PortAleksanderLE", - "Bandwidth", - "Ephemeron", "PrimusQ9", + "ProximaStationLE", + "RedshiftLE", "Reminiscence", "Sanglune", + "SequencerLE", + # "StasisLE", Commented out because it has uneven number of expansions "TheTimelessVoid", + "Treachery", + "Triton", "Urzagol", + "YearZeroLE", ] for map in maps: @@ -106,7 +137,6 @@ def main(): sc2.maps.get(map), [Bot(Race.Terran, ExporterBot()), Computer(Race.Zerg, Difficulty.Easy)], realtime=False, - save_replay_as="Example.SC2Replay", ) except ProtocolError: # ProtocolError appears after a leave game request diff --git a/test/pickle_data/16-Bit LE.pkl b/test/pickle_data/16-Bit LE.pkl new file mode 100644 index 000000000..7624f90bb Binary files /dev/null and b/test/pickle_data/16-Bit LE.pkl differ diff --git a/test/pickle_data/Abiogenesis LE.pkl b/test/pickle_data/Abiogenesis LE.pkl new file mode 100644 index 000000000..a0d284a0d Binary files /dev/null and b/test/pickle_data/Abiogenesis LE.pkl differ diff --git a/test/pickle_data/Abyssal Reef LE.pkl b/test/pickle_data/Abyssal Reef LE.pkl new file mode 100644 index 000000000..3ae72486b Binary files /dev/null and b/test/pickle_data/Abyssal Reef LE.pkl differ diff --git a/test/pickle_data/Acid Plant LE.pkl b/test/pickle_data/Acid Plant LE.pkl new file mode 100644 index 000000000..6bff5f4bb Binary files /dev/null and b/test/pickle_data/Acid Plant LE.pkl differ diff --git a/test/pickle_data/Acolyte LE.pkl b/test/pickle_data/Acolyte LE.pkl new file mode 100644 index 000000000..ac52af60b Binary files /dev/null and b/test/pickle_data/Acolyte LE.pkl differ diff --git a/test/pickle_data/Ascension to Aiur LE.pkl b/test/pickle_data/Ascension to Aiur LE.pkl new file mode 100644 index 000000000..226fc4217 Binary files /dev/null and b/test/pickle_data/Ascension to Aiur LE.pkl differ diff --git a/test/pickle_data/Automaton LE.pkl b/test/pickle_data/Automaton LE.pkl index 1d0c630ec..51cee9253 100644 Binary files a/test/pickle_data/Automaton LE.pkl and b/test/pickle_data/Automaton LE.pkl differ diff --git a/test/pickle_data/Backwater LE.pkl b/test/pickle_data/Backwater LE.pkl new file mode 100644 index 000000000..5579185d3 Binary files /dev/null and b/test/pickle_data/Backwater LE.pkl differ diff --git a/test/pickle_data/Battle on the Boardwalk LE.pkl b/test/pickle_data/Battle on the Boardwalk LE.pkl new file mode 100644 index 000000000..0aee40115 Binary files /dev/null and b/test/pickle_data/Battle on the Boardwalk LE.pkl differ diff --git a/test/pickle_data/Bel'Shir Vestige LE (Void).pkl b/test/pickle_data/Bel'Shir Vestige LE (Void).pkl new file mode 100644 index 000000000..12d81e576 Binary files /dev/null and b/test/pickle_data/Bel'Shir Vestige LE (Void).pkl differ diff --git a/test/pickle_data/Blackpink LE.pkl b/test/pickle_data/Blackpink LE.pkl new file mode 100644 index 000000000..c400230f0 Binary files /dev/null and b/test/pickle_data/Blackpink LE.pkl differ diff --git a/test/pickle_data/Blood Boil LE.pkl b/test/pickle_data/Blood Boil LE.pkl new file mode 100644 index 000000000..d7cfa0563 Binary files /dev/null and b/test/pickle_data/Blood Boil LE.pkl differ diff --git a/test/pickle_data/Blueshift LE.pkl b/test/pickle_data/Blueshift LE.pkl index ca3ab95de..7e56011fd 100644 Binary files a/test/pickle_data/Blueshift LE.pkl and b/test/pickle_data/Blueshift LE.pkl differ diff --git a/test/pickle_data/Cactus Valley LE (Void).pkl b/test/pickle_data/Cactus Valley LE (Void).pkl new file mode 100644 index 000000000..a69423ce0 Binary files /dev/null and b/test/pickle_data/Cactus Valley LE (Void).pkl differ diff --git a/test/pickle_data/Catalyst LE.pkl b/test/pickle_data/Catalyst LE.pkl new file mode 100644 index 000000000..e9246322b Binary files /dev/null and b/test/pickle_data/Catalyst LE.pkl differ diff --git a/test/pickle_data/Cerulean Fall LE.pkl b/test/pickle_data/Cerulean Fall LE.pkl index 32c4f0a9c..605b12e58 100644 Binary files a/test/pickle_data/Cerulean Fall LE.pkl and b/test/pickle_data/Cerulean Fall LE.pkl differ diff --git a/test/pickle_data/Cyber Forest LE.pkl b/test/pickle_data/Cyber Forest LE.pkl new file mode 100644 index 000000000..ef4bd5887 Binary files /dev/null and b/test/pickle_data/Cyber Forest LE.pkl differ diff --git a/test/pickle_data/Darkness Sanctuary LE.pkl b/test/pickle_data/Darkness Sanctuary LE.pkl index c70590934..3ce9a725d 100644 Binary files a/test/pickle_data/Darkness Sanctuary LE.pkl and b/test/pickle_data/Darkness Sanctuary LE.pkl differ diff --git a/test/pickle_data/Defender's Landing LE.pkl b/test/pickle_data/Defender's Landing LE.pkl new file mode 100644 index 000000000..be8f595e9 Binary files /dev/null and b/test/pickle_data/Defender's Landing LE.pkl differ diff --git a/test/pickle_data/Dreamcatcher LE.pkl b/test/pickle_data/Dreamcatcher LE.pkl new file mode 100644 index 000000000..97d35b3a6 Binary files /dev/null and b/test/pickle_data/Dreamcatcher LE.pkl differ diff --git a/test/pickle_data/Eastwatch LE.pkl b/test/pickle_data/Eastwatch LE.pkl new file mode 100644 index 000000000..9bf46f0a0 Binary files /dev/null and b/test/pickle_data/Eastwatch LE.pkl differ diff --git a/test/pickle_data/Fracture LE.pkl b/test/pickle_data/Fracture LE.pkl new file mode 100644 index 000000000..05bf1a0d6 Binary files /dev/null and b/test/pickle_data/Fracture LE.pkl differ diff --git a/test/pickle_data/Frost LE (Void).pkl b/test/pickle_data/Frost LE (Void).pkl new file mode 100644 index 000000000..57aa4b838 Binary files /dev/null and b/test/pickle_data/Frost LE (Void).pkl differ diff --git a/test/pickle_data/Honorgrounds LE.pkl b/test/pickle_data/Honorgrounds LE.pkl new file mode 100644 index 000000000..465d73195 Binary files /dev/null and b/test/pickle_data/Honorgrounds LE.pkl differ diff --git a/test/pickle_data/Interloper LE.pkl b/test/pickle_data/Interloper LE.pkl new file mode 100644 index 000000000..4640b39fe Binary files /dev/null and b/test/pickle_data/Interloper LE.pkl differ diff --git a/test/pickle_data/Kairos Junction LE.pkl b/test/pickle_data/Kairos Junction LE.pkl index d8931a25a..00f058745 100644 Binary files a/test/pickle_data/Kairos Junction LE.pkl and b/test/pickle_data/Kairos Junction LE.pkl differ diff --git a/test/pickle_data/King's Cove LE.pkl b/test/pickle_data/King's Cove LE.pkl new file mode 100644 index 000000000..a4a2b6605 Binary files /dev/null and b/test/pickle_data/King's Cove LE.pkl differ diff --git a/test/pickle_data/Lost and Found LE.pkl b/test/pickle_data/Lost and Found LE.pkl new file mode 100644 index 000000000..8418e0cb9 Binary files /dev/null and b/test/pickle_data/Lost and Found LE.pkl differ diff --git a/test/pickle_data/Mech Depot LE.pkl b/test/pickle_data/Mech Depot LE.pkl new file mode 100644 index 000000000..7d9e73424 Binary files /dev/null and b/test/pickle_data/Mech Depot LE.pkl differ diff --git a/test/pickle_data/Neon Violet Square LE.pkl b/test/pickle_data/Neon Violet Square LE.pkl new file mode 100644 index 000000000..fa7bf76c5 Binary files /dev/null and b/test/pickle_data/Neon Violet Square LE.pkl differ diff --git a/test/pickle_data/New Repugnancy LE.pkl b/test/pickle_data/New Repugnancy LE.pkl new file mode 100644 index 000000000..bf3d3fa7c Binary files /dev/null and b/test/pickle_data/New Repugnancy LE.pkl differ diff --git a/test/pickle_data/Newkirk Precinct TE (Void).pkl b/test/pickle_data/Newkirk Precinct TE (Void).pkl new file mode 100644 index 000000000..57a090004 Binary files /dev/null and b/test/pickle_data/Newkirk Precinct TE (Void).pkl differ diff --git a/test/pickle_data/Odyssey LE.pkl b/test/pickle_data/Odyssey LE.pkl new file mode 100644 index 000000000..87d5dd934 Binary files /dev/null and b/test/pickle_data/Odyssey LE.pkl differ diff --git a/test/pickle_data/Old Sunshine.pkl b/test/pickle_data/Old Sunshine.pkl index 8adfa5689..0302c679d 100644 Binary files a/test/pickle_data/Old Sunshine.pkl and b/test/pickle_data/Old Sunshine.pkl differ diff --git a/test/pickle_data/Paladino Terminal LE.pkl b/test/pickle_data/Paladino Terminal LE.pkl new file mode 100644 index 000000000..6742dd5ab Binary files /dev/null and b/test/pickle_data/Paladino Terminal LE.pkl differ diff --git a/test/pickle_data/Para Site LE.pkl b/test/pickle_data/Para Site LE.pkl index 46e512cf1..7fadaa475 100644 Binary files a/test/pickle_data/Para Site LE.pkl and b/test/pickle_data/Para Site LE.pkl differ diff --git a/test/pickle_data/Port Aleksander LE.pkl b/test/pickle_data/Port Aleksander LE.pkl index 9321db7c1..b9aacec7d 100644 Binary files a/test/pickle_data/Port Aleksander LE.pkl and b/test/pickle_data/Port Aleksander LE.pkl differ diff --git a/test/pickle_data/Proxima Station LE.pkl b/test/pickle_data/Proxima Station LE.pkl new file mode 100644 index 000000000..ffa3598b7 Binary files /dev/null and b/test/pickle_data/Proxima Station LE.pkl differ diff --git a/test/pickle_data/Redshift LE.pkl b/test/pickle_data/Redshift LE.pkl new file mode 100644 index 000000000..879604150 Binary files /dev/null and b/test/pickle_data/Redshift LE.pkl differ diff --git a/test/pickle_data/STC - Primus Q-9.pkl b/test/pickle_data/STC - Primus Q-9.pkl index 1f0243cbc..9dfb50924 100644 Binary files a/test/pickle_data/STC - Primus Q-9.pkl and b/test/pickle_data/STC - Primus Q-9.pkl differ diff --git a/test/pickle_data/Sanglune.pkl b/test/pickle_data/Sanglune.pkl index f9ade1cdf..2154e342e 100644 Binary files a/test/pickle_data/Sanglune.pkl and b/test/pickle_data/Sanglune.pkl differ diff --git a/test/pickle_data/Sequencer LE.pkl b/test/pickle_data/Sequencer LE.pkl new file mode 100644 index 000000000..944ca0445 Binary files /dev/null and b/test/pickle_data/Sequencer LE.pkl differ diff --git a/test/pickle_data/The Timeless Wild [PLX].pkl b/test/pickle_data/The Timeless Wild [PLX].pkl index 57bb8a025..b63f80946 100644 Binary files a/test/pickle_data/The Timeless Wild [PLX].pkl and b/test/pickle_data/The Timeless Wild [PLX].pkl differ diff --git a/test/pickle_data/Urzagol [PLX].pkl b/test/pickle_data/Urzagol [PLX].pkl index bcb6aa4bc..677f45efa 100644 Binary files a/test/pickle_data/Urzagol [PLX].pkl and b/test/pickle_data/Urzagol [PLX].pkl differ diff --git a/test/pickle_data/Year Zero LE.pkl b/test/pickle_data/Year Zero LE.pkl new file mode 100644 index 000000000..66c066f0d Binary files /dev/null and b/test/pickle_data/Year Zero LE.pkl differ diff --git a/test/pickle_data/[TLMC10] Artana.pkl b/test/pickle_data/[TLMC10] Artana.pkl index 94cda6b89..2d7f60aec 100644 Binary files a/test/pickle_data/[TLMC10] Artana.pkl and b/test/pickle_data/[TLMC10] Artana.pkl differ diff --git a/test/pickle_data/[TLMC10] Digital Frontier.pkl b/test/pickle_data/[TLMC10] Digital Frontier.pkl index fb1d2fef4..881d9503a 100644 Binary files a/test/pickle_data/[TLMC10] Digital Frontier.pkl and b/test/pickle_data/[TLMC10] Digital Frontier.pkl differ diff --git a/test/pickle_data/[TLMC10] Treachery.pkl b/test/pickle_data/[TLMC10] Treachery.pkl index 4551300b2..6ad1e05e1 100644 Binary files a/test/pickle_data/[TLMC10] Treachery.pkl and b/test/pickle_data/[TLMC10] Treachery.pkl differ diff --git a/test/pickle_data/[TLMC11] Crystal Cavern.pkl b/test/pickle_data/[TLMC11] Crystal Cavern.pkl index aaef4b5d3..732e12ecb 100644 Binary files a/test/pickle_data/[TLMC11] Crystal Cavern.pkl and b/test/pickle_data/[TLMC11] Crystal Cavern.pkl differ diff --git a/test/pickle_data/[TLMC11] Reminiscence.pkl b/test/pickle_data/[TLMC11] Reminiscence.pkl index 9181d24b6..a80f7bfdd 100644 Binary files a/test/pickle_data/[TLMC11] Reminiscence.pkl and b/test/pickle_data/[TLMC11] Reminiscence.pkl differ diff --git a/test/pickle_data/[TLMC12] Acropolis.pkl b/test/pickle_data/[TLMC12] Acropolis.pkl index 97fc81def..5a96e44fc 100644 Binary files a/test/pickle_data/[TLMC12] Acropolis.pkl and b/test/pickle_data/[TLMC12] Acropolis.pkl differ diff --git a/test/pickle_data/[TLMC12] Bandwidth.pkl b/test/pickle_data/[TLMC12] Bandwidth.pkl index c9e90ba53..44c671bdd 100644 Binary files a/test/pickle_data/[TLMC12] Bandwidth.pkl and b/test/pickle_data/[TLMC12] Bandwidth.pkl differ diff --git a/test/pickle_data/[TLMC12] Ephemeron.pkl b/test/pickle_data/[TLMC12] Ephemeron.pkl index d4ac4f1e7..c4299b4aa 100644 Binary files a/test/pickle_data/[TLMC12] Ephemeron.pkl and b/test/pickle_data/[TLMC12] Ephemeron.pkl differ diff --git a/test/pickle_data/[TLMC12] Triton.pkl b/test/pickle_data/[TLMC12] Triton.pkl index a3dd448dc..20dc64e11 100644 Binary files a/test/pickle_data/[TLMC12] Triton.pkl and b/test/pickle_data/[TLMC12] Triton.pkl differ diff --git a/test/test_pickled_data.py b/test/test_pickled_data.py index 7f292e81e..9c7e94549 100644 --- a/test/test_pickled_data.py +++ b/test/test_pickled_data.py @@ -112,7 +112,7 @@ def test_bot_ai(self, bot: BotAI): bot._game_info.map_ramps, bot._game_info.vision_blockers = bot._game_info._find_ramps_and_vision_blockers() assert bot.main_base_ramp # Test if any ramp was found # TODO: Cache all expansion positions for a map and check if it is the same - assert len(bot.expansion_locations) >= 12 + assert len(bot.expansion_locations) >= 10 # On N player maps, it is expected that there are N*X bases because of symmetry, at least for 1vs1 maps assert ( len(bot.expansion_locations) % (len(bot.enemy_start_locations) + 1) == 0 @@ -169,15 +169,23 @@ def test_game_info(self, bot: BotAI): # Test if main base ramp works ramp: Ramp = bot.main_base_ramp - assert ramp.barracks_correct_placement - assert ramp.barracks_in_middle - assert ramp.depot_in_middle - assert len(ramp.corner_depots) == 2 + # On the map HonorgroundsLE, the main base is large and it would take a bit of effort to fix, so it returns None or empty set + if len(ramp.upper) in {2, 5}: + assert ramp.barracks_correct_placement + assert ramp.barracks_in_middle + assert ramp.depot_in_middle + assert len(ramp.corner_depots) == 2 + assert ramp.upper2_for_ramp_wall + else: + # On maps it is unable to find valid wall positions (Honorgrounds LE) it should return None + assert ramp.barracks_correct_placement is None + assert ramp.barracks_in_middle is None + assert ramp.depot_in_middle is None + assert ramp.corner_depots == set() assert ramp.top_center assert ramp.bottom_center assert ramp.size assert ramp.points - assert ramp.upper2_for_ramp_wall assert ramp.upper assert ramp.lower @@ -565,10 +573,10 @@ def test_position_pointlike(self, bot: BotAI, x1, y1, x2, y2, x3, y3): dist_furthest_point = pos1._distance_squared(furthest_point) ** 0.5 # Distances between pos1-pos2 and pos1-pos3 might be the same, so the sorting might still be different, that's why I use a set here - assert pos1.closest(points) in {p for p in points2 if pos1.distance_to(p) == dist_closest_point} - assert pos1.distance_to_closest(points) == pos1._distance_squared(closest_point) ** 0.5 - assert pos1.furthest(points) in {p for p in points2 if pos1.distance_to(p) == dist_furthest_point} - assert pos1.distance_to_furthest(points) == pos1._distance_squared(furthest_point) ** 0.5 + assert pos1.closest(points) in {p for p in points2 if abs(pos1.distance_to(p) - dist_closest_point) < epsilon} + assert abs(pos1.distance_to_closest(points) - pos1._distance_squared(closest_point) ** 0.5) < epsilon + assert pos1.furthest(points) in {p for p in points2 if abs(pos1.distance_to(p) - dist_furthest_point) < epsilon} + assert abs(pos1.distance_to_furthest(points) - pos1._distance_squared(furthest_point) ** 0.5) < epsilon assert pos1.offset(pos2) == Point2((pos1.x + pos2.x, pos1.y + pos2.y)) if pos1 != pos2: assert pos1.unit_axes_towards(pos2) != Point2((0, 0))