diff --git a/.vscode/settings.json b/.vscode/settings.json index 3a33b7e..68a1ee3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,20 +5,25 @@ "chronoboost", "csvfile", "CYBERNETICSCORE", + "DARKTEMPLAR", "distrubute", + "gameinfo", "hackcheating", "Harstems", + "HIGHTEMPLAR", "linalg", "ndarray", "opponentid", "pathing", "PHOTONCANNON", + "Pointlike", "Premove", "PRIO", "Protoss", "proyimity", "ROBO", "robofacilities", + "ROBOTICSFACILITY", "speedmining", "STARGATE", "stargates", @@ -27,6 +32,7 @@ "unittype", "Utilityclass", "vespene", + "WARPGATE", "warpin", "WARPPRISM", "warprism" diff --git a/bot/HarstemsAunt/common.py b/bot/HarstemsAunt/common.py index daa3092..1d40954 100644 --- a/bot/HarstemsAunt/common.py +++ b/bot/HarstemsAunt/common.py @@ -78,7 +78,7 @@ UnitTypeId.CARRIER } -GATEWAY_UNTIS: Set[UnitTypeId] = { +GATEWAY_UNITS: Set[UnitTypeId] = { UnitTypeId.ZEALOT, UnitTypeId.STALKER, UnitTypeId.SENTRY, diff --git a/bot/HarstemsAunt/debugTools.py b/bot/HarstemsAunt/debugTools.py index c09976c..0ce380d 100644 --- a/bot/HarstemsAunt/debugTools.py +++ b/bot/HarstemsAunt/debugTools.py @@ -1,4 +1,5 @@ """Module containing a Debug Class""" +# pylint: disable=C0103 from typing import Union from math import sin, pi, cos diff --git a/bot/HarstemsAunt/macro.py b/bot/HarstemsAunt/macro.py index d9c1d7c..05e17f6 100644 --- a/bot/HarstemsAunt/macro.py +++ b/bot/HarstemsAunt/macro.py @@ -15,7 +15,7 @@ # pylint: disable=E0402 from .utils import Utils from .production_buffer import ProductionBuffer -from .common import GATEWAY_UNTIS, ROBO_UNITS, STARGATE_UNITS +from .common import GATEWAY_UNITS, ROBO_UNITS, STARGATE_UNITS from .build_order import BuildOrder, BuildInstruction, InstructionType @@ -29,7 +29,7 @@ def __init__(self,bot:BotAI) -> None: self.production_buffer = ProductionBuffer(self.bot) #TODO: #75 Premove workers - async def __call__(self): + async def __call__(self) -> None: """ makes the class callable, get's executed to every tick in BotClass """ if self.bot.alert: await self.handle_alerts(self.bot.alert) @@ -57,7 +57,7 @@ def get_production_structure(self, unit_type: UnitTypeId) -> UnitTypeId: Returns: UnitTypeId: appropriate productions structure """ - if unit_type in GATEWAY_UNTIS: + if unit_type in GATEWAY_UNITS: if not self.bot.structures(UnitTypeId.WARPGATE): return UnitTypeId.GATEWAY return UnitTypeId.WARPGATE @@ -65,6 +65,7 @@ def get_production_structure(self, unit_type: UnitTypeId) -> UnitTypeId: return UnitTypeId.ROBOTICSFACILITY if unit_type in STARGATE_UNITS: return UnitTypeId.STARGATE + return async def handle_instructions(self) -> None: """ gets build Instruction for self.build_order """ @@ -75,7 +76,8 @@ async def construct_building(next_step:BuildInstruction): Args: next_step (BuildInstruction): next instruction """ - #TODO: #70 ADD a check if the next instruction is equal to the current one so that building gets not delayed + #TODO: #70 ADD a check if the next instruction is equal to the + # current one so that building gets not delayed pending_check:bool = False following_instruction: UnitTypeId = None @@ -100,37 +102,40 @@ async def construct_building(next_step:BuildInstruction): if next_step.type_id == UnitTypeId.NEXUS: if Utils.can_build_structure(self.bot, next_step.type_id)and\ not self.bot.already_pending(next_step.type_id): - await self.expand() - + await self.expand() + if Utils.can_build_structure(self.bot, next_step.type_id): - if not pending_check: + if not pending_check: + await self.bot.build(next_step.type_id,near=next_step.position,\ + max_distance=next_step.accuracy,build_worker=self.get_build_worker()) + else: + if not self.bot.already_pending(next_step.type_id): await self.bot.build(next_step.type_id,near=next_step.position,\ max_distance=next_step.accuracy,build_worker=self.get_build_worker()) - else: - if not self.bot.already_pending(next_step.type_id): - await self.bot.build(next_step.type_id,near=next_step.position,\ - max_distance=next_step.accuracy,build_worker=self.get_build_worker()) + # TODO: This should be reworked async def train_unit(next_step:BuildInstruction): """ handles the construction of Units Args: next_step (BuildInstruction): next instruction """ - + async def warp_in_unit(bot: BotAI,unit:UnitTypeId,\ warp_in_position:Union[Point2,Point3,Unit]) -> bool: pos:Point2= warp_in_position.position.to2.random_on_distance(4) - placement = await bot.find_placement(AbilityId.WARPGATETRAIN_STALKER, pos, placement_step=1) + placement = await bot.find_placement(AbilityId.WARPGATETRAIN_STALKER, \ + pos, placement_step=1) for gate in bot.structures(UnitTypeId.WARPGATE).idle: if Utils.can_build_unit(bot, unit): - gate.warp_in(unit, placement) + gate.warp_in(unit, placement) async def build_gateway_units(bot:BotAI,unit_type:UnitTypeId): gate_aliases:list = [UnitTypeId.GATEWAY, UnitTypeId.WARPGATE] if Utils.can_build_unit(bot, unit_type): - for gate in bot.structures.filter(lambda struct: struct.type_id in gate_aliases): + for gate in bot.structures\ + .filter(lambda struct: struct.type_id in gate_aliases): if gate.is_idle and UpgradeId.WARPGATERESEARCH not in bot.researched: gate.train(unit_type) self.build_order.increment_step() @@ -158,10 +163,12 @@ async def build_gateway_units(bot:BotAI,unit_type:UnitTypeId): if not next_step and not self.build_order.buffer: return - if not next_step.type_id == UnitTypeId.ASSIMILATOR and self.build_order.is_performing_initial_build: + if not next_step.type_id == UnitTypeId.ASSIMILATOR \ + and self.build_order.is_performing_initial_build: structure_cost:Cost = self.bot.calculate_cost(next_step.type_id) - if (self.bot.minerals > (structure_cost.minerals*0.65)): - if not Utils.unittype_in_proximity_to_point(self.bot, UnitTypeId.PROBE, next_step.position): + if self.bot.minerals > (structure_cost.minerals*0.65): + if not Utils.unittype_in_proximity_to_point(self.bot,\ + UnitTypeId.PROBE, next_step.position): worker: Unit = self.get_build_worker() worker.move(next_step.position) @@ -173,31 +180,33 @@ async def build_gateway_units(bot:BotAI,unit_type:UnitTypeId): def get_upgrades(self) -> None: """ handles the research of upgrades """ - + attack = [ UpgradeId.PROTOSSGROUNDWEAPONSLEVEL1, UpgradeId.PROTOSSGROUNDWEAPONSLEVEL2, UpgradeId.PROTOSSGROUNDWEAPONSLEVEL3, ] - + amor = [ UpgradeId.PROTOSSGROUNDARMORSLEVEL1, UpgradeId.PROTOSSGROUNDARMORSLEVEL2, UpgradeId.PROTOSSGROUNDARMORSLEVEL3 ] - # THIS IS A INNER FUNCTION DON'T CHANGE THE INDENTATION AGAIN BECAUSE YOU GOT THE MEMORY OF A GOLDFISH - def upgrade(bot:BotAI, Upgrade_structure:UnitTypeId, Upgrade_id:UpgradeId) -> None: - if bot.structures(Upgrade_structure).idle and Utils.can_research_upgrade(bot,Upgrade_id): - bot.research(Upgrade_id) + # THIS IS A INNER FUNCTION DON'T CHANGE THE INDENTATION \ + # AGAIN BECAUSE YOU GOT THE MEMORY OF A GOLDFISH + def upgrade(bot:BotAI, upgrade_structure:UnitTypeId, upgrade_id:UpgradeId) -> None: + if bot.structures(upgrade_structure).idle \ + and Utils.can_research_upgrade(bot,upgrade_id): + bot.research(upgrade_id) for forge in self.bot.structures(UnitTypeId.FORGE): - for upgrades in attack: - if upgrades not in self.bot.researched: - upgrade(self.bot, UnitTypeId.FORGE, upgrades) - for upgrades in amor: - if upgrades not in self.bot.researched: - upgrade(self.bot, UnitTypeId.FORGE, upgrades) + for upgrades in attack: + if upgrades not in self.bot.researched: + upgrade(self.bot, UnitTypeId.FORGE, upgrades) + for upgrades in amor: + if upgrades not in self.bot.researched: + upgrade(self.bot, UnitTypeId.FORGE, upgrades) if self.bot.structures(UnitTypeId.CYBERNETICSCORE): if not UpgradeId.WARPGATERESEARCH in self.bot.researched: @@ -250,9 +259,11 @@ async def build_supply(self) -> None: return if Utils.can_build_structure(self.bot,UnitTypeId.PYLON) and not \ self.bot.already_pending(UnitTypeId.PYLON) and self.bot.supply_left < 8 \ - and len(self.bot.structures(UnitTypeId.NEXUS))>= 2 and self.bot.structures(UnitTypeId.CYBERNETICSCORE): + and len(self.bot.structures(UnitTypeId.NEXUS))>= 2 \ + and self.bot.structures(UnitTypeId.CYBERNETICSCORE): worker:Unit = self.bot.workers.prefer_idle.closest_to(self.build_order.get_build_pos()) - await self.bot.build(UnitTypeId.PYLON, build_worker=worker, near=self.build_order.get_build_pos()) + await self.bot.build(UnitTypeId.PYLON, build_worker=worker, \ + near=self.build_order.get_build_pos()) async def build_gas(self,position:Union[Point2,Point3,Unit]) -> None: """Handles the Building of Gas Structures """ @@ -279,14 +290,16 @@ def check_mined_out(self) -> None: def build_probes(self) -> None: """ Builds workers """ - probe_count:int = len(self.bot.structures(UnitTypeId.NEXUS))*16 + len(self.bot.structures(UnitTypeId.ASSIMILATOR))*3 + probe_count:int = len(self.bot.structures(UnitTypeId.NEXUS))*16 \ + + len(self.bot.structures(UnitTypeId.ASSIMILATOR))*3 if self.bot.structures(UnitTypeId.PYLON): for townhall in self.bot.townhalls.idle: - if Utils.can_build_unit(self.bot, UnitTypeId.PROBE) and len(self.bot.workers) < probe_count: + if Utils.can_build_unit(self.bot, UnitTypeId.PROBE) \ + and len(self.bot.workers) < probe_count: townhall.train(UnitTypeId.PROBE) async def chronoboost(self) -> None: - """ handles Chronoboosting """ + """ handles chronoboosting """ prios:list = [ [ UnitTypeId.ROBOTICSBAY, @@ -312,7 +325,8 @@ async def chronoboost(self) -> None: .sorted(lambda struct: struct.orders[0].progress, reverse=True) for struct in structures: - chrono_nexus = self.bot.structures(UnitTypeId.NEXUS).filter(lambda nexus: nexus.energy > 50) + chrono_nexus = self.bot.structures(UnitTypeId.NEXUS)\ + .filter(lambda nexus: nexus.energy > 50) if chrono_nexus: chrono_nexus[0](AbilityId.EFFECT_CHRONOBOOSTENERGYCOST, struct) @@ -325,4 +339,4 @@ async def expand(self) -> None: # Area is free to build # 2.75 is the radius of a nexus - # if a unit is closer than this a nexus would be build away from the location - await self.bot.build(UnitTypeId.NEXUS, near=location, max_distance=0) \ No newline at end of file + await self.bot.build(UnitTypeId.NEXUS, near=location, max_distance=0) diff --git a/bot/HarstemsAunt/production_buffer.py b/bot/HarstemsAunt/production_buffer.py index 74b89bb..4dc3b03 100644 --- a/bot/HarstemsAunt/production_buffer.py +++ b/bot/HarstemsAunt/production_buffer.py @@ -11,7 +11,10 @@ class ProductionRequest: """ Class Representing the a Production Request """ - def __new__(cls, requested_unit:UnitTypeId,army_group_id:int,build_structure_tag:int) -> ProductionRequest: + def __new__(cls, + requested_unit:UnitTypeId, + army_group_id:int, + build_structure_tag:int) -> ProductionRequest: """ Creates new instance of Production Request Args: @@ -28,7 +31,10 @@ def __new__(cls, requested_unit:UnitTypeId,army_group_id:int,build_structure_tag return instance - def __init__(self, requested_unit:UnitTypeId,army_group_id:int,build_structure_tag:int) -> None: + def __init__(self, + requested_unit:UnitTypeId, + army_group_id:int, + build_structure_tag:int) -> None: self.requested_unit:UnitTypeId = requested_unit self.army_group_tag:int = army_group_id self.build_structure_tag = build_structure_tag @@ -38,6 +44,11 @@ def __repr__(self) -> str: @property def handled(self) -> bool: + """ true if request is done + + Returns: + bool: request handled + """ return False @handled.setter @@ -54,24 +65,50 @@ def __init__(self,bot:BotAI) -> None: @property def gateways(self) -> Units: - return self.bot.units.filter(lambda struct: struct.type_id \ + """ Returns a Units Object containing all idle Warp and Gateways + + Returns: + Units: idle Warp and Gateways + """ + return self.bot.units.filter(lambda struct: struct.type_id \ in [UnitTypeId.WARPGATE, UnitTypeId.GATEWAY] and struct.is_idle) @property def stargates(self) -> Units: + """ Units object containing all idle Stargates + + Returns: + Units: idle stargates + """ return self.bot.units(UnitTypeId.STARGATE).idle @property def robofacilities(self) -> Units: + """ Units object containing all idle robofacilities + + Returns: + Units: all idle robofacilities + """ return self.bot.units(UnitTypeId.ROBOTICSFACILITY).idle def add_request(self, request:ProductionRequest) -> None: + """ adds request to buffer + + Args: + request (ProductionRequest): ProductionRequest + """ self.requests.append(request) def remove_request(self, request:ProductionRequest): + """ removes parsed request from Buffer + + Args: + request (ProductionRequest): Request that is supposed to be removed + """ self.requests.remove(request) def update(self) -> None: + """Updates Buffer""" for request in self.requests: if request.handled: self.remove_request(request)