diff --git a/basebot.py b/basebot.py index 88cb1f9..eb77302 100644 --- a/basebot.py +++ b/basebot.py @@ -1,49 +1,58 @@ -import random -from typing import List +import sys +from typing import Any, Dict, List import sc2 +from loguru import logger from MapAnalyzer import MapData from sc2.position import Point2, Point3 +from game_version import VersionManager + GREEN = Point3((0, 255, 0)) RED = Point3((255, 0, 0)) BLUE = Point3((0, 0, 255)) BLACK = Point3((0, 0, 0)) +LOG_FORMAT = "{time:YY:MM:DD:HH:mm:ss}|" \ + "{level: <8}|{name: ^15}|" \ + "{function: ^15}|" \ + "{line: >4}|" \ + " {level.icon} {message}" + + +class LogFilter: + def __init__(self, module_name: str, level: str = "ERROR") -> None: + self.module_name = module_name + self.level = level + + def __call__(self, record: Dict[str, Any]) -> bool: + # return True + levelno = logger.level(self.level).no + return record["level"].no >= levelno + + class BaseBot(sc2.BotAI): def __init__(self, loglevel=None): super().__init__() self.map_data: MapData = None - self.logger = None + self.version_manager = VersionManager() + self.logger = sc2.main.logger self.loglevel = loglevel - self.home = None + self.log_filter = LogFilter(module_name='picklerick', level=self.loglevel) + self.logger.remove() + self.log_format = LOG_FORMAT + self.logger.add(sys.stderr, format=self.log_format, filter=self.log_filter) + # self.logger.add(f"logs/log1.log", format=self.log_format, filter=self.log_filter) async def on_start(self): + + await self.version_manager.handle_game_version(self.client) if self.loglevel is not None: self.map_data = MapData(self, loglevel=self.loglevel) else: self.map_data = MapData(self, loglevel="DEBUG") - self.logger = self.map_data.logger - - def get_random_point(self, minx, maxx, miny, maxy): - return (random.randint(minx, maxx), random.randint(miny, maxy)) - - def _get_random_influence(self, n, r): - pts = [] - for i in range(n): - pts.append( - (Point2(self.get_random_point(50, 130, 25, 175)), r)) - return pts - - def _plot_influence(self, points): - for tup in points: - p = tup[0] - r = tup[1] - h = self.get_terrain_z_height(p) - pos = Point3((p.x, p.y, h)) - self.client.debug_sphere_out(p=pos, r=r - 1, color=RED) async def on_step(self, iteration: int): pass @@ -63,3 +72,4 @@ def _draw_point_list(self, point_list: List = None, color=None, text=None, box_r self.client.debug_text_world( "\n".join([f"{text}", ]), pos, color=color, size=30, ) + diff --git a/game_version.py b/game_version.py new file mode 100644 index 0000000..a9d12ca --- /dev/null +++ b/game_version.py @@ -0,0 +1,126 @@ +# https://github.com/DrInfy/sharpy-sc2/blob/develop/sharpy/managers/version_manager.py + + +from enum import IntEnum +from typing import Any, Dict, Set + +from sc2 import AbilityId, UnitTypeId +from sc2.client import Client +from sc2.ids.buff_id import BuffId +from sc2.ids.upgrade_id import UpgradeId + + +class GameVersion(IntEnum): + V_5_0_0 = 81009 + V_4_12_0 = 80188 + V_4_11_4 = 78285 + V_4_11_0 = 77379 + V_4_10_0 = 75689 + + +class VersionManager: + def __init__(self): + self.short_version = "0.0.0" + self.full_version = "0.0.0.12345" + self.base_version = 12345 + self.disabled_upgrades: Set[UpgradeId] = set() + self.moved_upgrades: Dict[UpgradeId, UnitTypeId] = {} + self.disabled_abilities: Set[AbilityId] = set() + + async def handle_game_version(self, client: Client): + response = await client.ping() + self.full_version = response.ping.game_version + self.base_version = response.ping.base_build + splits = response.ping.game_version.split(".") + + if len(splits) == 4: + self.short_version = f"{splits[0]}.{splits[1]}.{splits[2]}" + + print(f"Version: {self.full_version}") + self.configure_enums() + self.configure_upgrades() + self.configure_abilities() + + def configure_enums(self): + if self.base_version < GameVersion.V_5_0_0: + self._set_enum_mapping( + UnitTypeId, + { + UnitTypeId.INHIBITORZONESMALL : 1968, + UnitTypeId.INHIBITORZONEMEDIUM : 1969, + UnitTypeId.INHIBITORZONELARGE : 1970, + UnitTypeId.ACCELERATIONZONESMALL : 1971, + UnitTypeId.ACCELERATIONZONEMEDIUM : 1972, + UnitTypeId.ACCELERATIONZONELARGE : 1973, + UnitTypeId.ACCELERATIONZONEFLYINGSMALL : 1974, + UnitTypeId.ACCELERATIONZONEFLYINGMEDIUM: 1975, + UnitTypeId.ACCELERATIONZONEFLYINGLARGE : 1976, + UnitTypeId.INHIBITORZONEFLYINGSMALL : 1977, + UnitTypeId.INHIBITORZONEFLYINGMEDIUM : 1978, + UnitTypeId.INHIBITORZONEFLYINGLARGE : 1979, + UnitTypeId.ASSIMILATORRICH : 1980, + UnitTypeId.EXTRACTORRICH : 1981, + UnitTypeId.REFINERYRICH : 1960, + UnitTypeId.MINERALFIELD450 : 1982, + UnitTypeId.MINERALFIELDOPAQUE : 1983, + UnitTypeId.MINERALFIELDOPAQUE900 : 1984, + }, + ) + self._set_enum_mapping( + AbilityId, + { + AbilityId.BATTERYOVERCHARGE_BATTERYOVERCHARGE : 3801, + AbilityId.AMORPHOUSARMORCLOUD_AMORPHOUSARMORCLOUD: 3803, + }, + ) + self._set_enum_mapping( + BuffId, + { + BuffId.INHIBITORZONETEMPORALFIELD : 292, + BuffId.RESONATINGGLAIVESPHASESHIFT : 293, + BuffId.AMORPHOUSARMORCLOUD : 294, + BuffId.RAVENSHREDDERMISSILEARMORREDUCTIONUISUBTRUCT: 295, + BuffId.BATTERYOVERCHARGE : 296, + }, + ) + + if self.base_version == GameVersion.V_4_10_0: + self._set_enum_mapping( + UnitTypeId, + { + UnitTypeId.ASSIMILATORRICH : 1955, + UnitTypeId.EXTRACTORRICH : 1956, + UnitTypeId.INHIBITORZONESMALL : 1957, + UnitTypeId.INHIBITORZONEMEDIUM: 1958, + UnitTypeId.INHIBITORZONELARGE : 1959, + UnitTypeId.REFINERYRICH : 1960, + UnitTypeId.MINERALFIELD450 : 1961, + }, + ) + if self.base_version < GameVersion.V_4_12_0: + self._set_enum_mapping( + AbilityId, {AbilityId.AMORPHOUSARMORCLOUD_AMORPHOUSARMORCLOUD: 3801}, + ) + + def _set_enum_mapping(self, enum: Any, items: Dict[Any, int]): + for enum_key, value in items.items(): + enum_key._value_ = value + enum._member_map_[enum_key.name] = value + enum._value2member_map_[value] = enum_key + print(f"Setting {enum_key.name} to {enum_key.value}") + + def configure_upgrades(self): + if self.base_version < GameVersion.V_4_11_0: + self.disabled_upgrades.add(UpgradeId.LURKERRANGE) + self.disabled_upgrades.add(UpgradeId.MICROBIALSHROUD) + self.disabled_upgrades.add(UpgradeId.VOIDRAYSPEEDUPGRADE) + self.moved_upgrades[UpgradeId.MEDIVACINCREASESPEEDBOOST] = UnitTypeId.STARPORTTECHLAB + self.moved_upgrades[UpgradeId.LIBERATORAGRANGEUPGRADE] = UnitTypeId.STARPORTTECHLAB + + def configure_abilities(self): + if self.base_version < GameVersion.V_4_12_0: + self.disabled_abilities.add(AbilityId.BATTERYOVERCHARGE_BATTERYOVERCHARGE) + if self.base_version < GameVersion.V_4_11_0: + self.disabled_abilities.add(AbilityId.AMORPHOUSARMORCLOUD_AMORPHOUSARMORCLOUD) + if self.base_version >= GameVersion.V_4_11_0: + self.disabled_abilities.add(AbilityId.INFESTEDTERRANS_INFESTEDTERRANS) diff --git a/main.py b/main.py index b472959..8ab457c 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,7 @@ import sc2 from sc2.player import Bot, Computer -from Raven.picklerick import PickleRick +from picklerick import PickleRick def main(): diff --git a/picklerick.py b/picklerick.py index 6ca2cd6..dc9d1a2 100644 --- a/picklerick.py +++ b/picklerick.py @@ -1,6 +1,7 @@ -from sc2.position import Point3 +import MapAnalyzer +from sc2.position import Point2, Point3 -from Raven.basebot import BaseBot +from basebot import BaseBot GREEN = Point3((0, 255, 0)) RED = Point3((255, 0, 0)) @@ -8,13 +9,53 @@ BLACK = Point3((0, 0, 0)) +class BaseInfo: + def __init__(self, townhalls, bot: BaseBot): + self.townhalls = townhalls + self.bot = bot + self.region = bot.map_data.where_all(self.townhalls[0].position)[0] + + def __repr__(self): + return str(self.region) + ' ' + str(len(self.townhalls)) + + class PickleRick(BaseBot): def __init__(self): super().__init__(loglevel="INFO") + self.bases = [] async def on_start(self): await super().on_start() async def on_step(self, iteration: int): - pass + self.logger.info(f"Minerals : {self.minerals}, Gas : {self.vespene}") + self.logger.info(f"TownHalls : {self.townhalls}") + if len(self.bases) == 0: + self.set_base(townhalls=self.townhalls) + self.logger.info(f"Bases : {self.bases}") + ramp = self.bases[0].region.region_ramps[0] + th = self.bases[0].townhalls[0] + await self.draw_wallof_points(townhall=th, ramp=ramp) + + def set_base(self, townhalls): + base = BaseInfo(townhalls=townhalls, bot=self) + self.bases.append(base) + + async def draw_wallof_points(self, townhall, ramp: MapAnalyzer.MDRamp): + points = ramp.buildables.points + for p in points: + h = self.get_terrain_z_height(p) + th = self.get_terrain_z_height(townhall.position) + if h < th: + continue + pos = Point3((p.x, p.y, h)) + box_r = 0.5 + color = GREEN + p0 = Point3((pos.x - box_r, pos.y - box_r, pos.z + box_r)) + Point2((0.5, 0.5)) + p1 = Point3((pos.x + box_r, pos.y + box_r, pos.z - box_r)) + Point2((0.5, 0.5)) + self.client.debug_box_out(p0, p1, color=color) + + async def walloff(self, townhall, choke: MapAnalyzer.ChokeArea): + if choke.is_ramp: + build_points = choke.buildables.points