From 32fe2f27f13dec7e4ce09baff7f2db617a49944a Mon Sep 17 00:00:00 2001 From: FredNoonienSingh Date: Fri, 17 Jan 2025 14:43:47 +0100 Subject: [PATCH] fixxed linting errors --- .vscode/settings.json | 9 ++ bot/HarstemsAunt/army_group.py | 93 ++++++--------------- bot/HarstemsAunt/build_order.py | 5 +- bot/HarstemsAunt/macro.py | 11 +-- bot/HarstemsAunt/main.py | 33 ++++---- bot/HarstemsAunt/map_sector.py | 2 +- bot/{ => HarstemsAunt}/production_buffer.py | 27 ++++-- bot/HarstemsAunt/utils.py | 1 - bot/Unit_Classes/Stalkers.py | 10 +-- bot/Unit_Classes/Zealots.py | 12 ++- bot/Unit_Classes/baseClassGround.py | 4 +- 11 files changed, 95 insertions(+), 112 deletions(-) create mode 100644 .vscode/settings.json rename bot/{ => HarstemsAunt}/production_buffer.py (65%) diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3eee361 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "cSpell.words": [ + "Harstems", + "ndarray", + "pathing", + "robofacilities", + "stargates" + ] +} \ No newline at end of file diff --git a/bot/HarstemsAunt/army_group.py b/bot/HarstemsAunt/army_group.py index 1225873..f72a423 100644 --- a/bot/HarstemsAunt/army_group.py +++ b/bot/HarstemsAunt/army_group.py @@ -4,16 +4,18 @@ from typing import Union import numpy as np +# pylint: disable=E0402 from .utils import Utils from .pathing import Pathing -from .common import WORKER_IDS, RUN_BY_SIZE, logger - +from .common import WORKER_IDS +from .production_buffer import ProductionBuffer,ProductionRequest +# pylint: disable=C0411 from sc2.unit import Unit from sc2.units import Units -from sc2.ids.unit_typeid import UnitTypeId from sc2.bot_ai import BotAI from sc2.position import Point2, Point3 +from sc2.ids.unit_typeid import UnitTypeId class GroupStatus(Enum): """Enum representing the State """ @@ -29,10 +31,12 @@ class GroupTypeId(Enum): class ArmyGroup: """Class representing an Army Group """ - def __init__(self, bot:BotAI, unit_list:list,\ - units_in_transit:list,pathing:Pathing,group_type:GroupTypeId=GroupTypeId.ARMY): + def __init__(self, bot:BotAI,name:str, unit_list:list,\ + units_in_transit:list,pathing:Pathing,\ + army_group_id:int=0,group_type:GroupTypeId=GroupTypeId.ARMY): self.bot:BotAI = bot - self.name = "Attack Group Alpha" + self.name = name + self.id = army_group_id self.requested_units:list = [] self.unit_list:list = unit_list self.units_in_transit:list = units_in_transit @@ -124,78 +128,33 @@ def attack_target(self, new_attack_target:Union[Point2,Point3,Unit]): @property def retreat_pos(self) -> Union[Point2,Point3,Unit]: """ position to which the group retreats to """ - return self.bot.start_location + return self.bot.units(UnitTypeId.NEXUS).sort(lambda struct: struct.age) @retreat_pos.setter def retreat_pos(self, new_retreat_pos:Union[Point2,Point3,Unit]): """ sets new attack target """ self.retreat_pos = new_retreat_pos - def request_unit(self) -> UnitTypeId: + def request_units(self) -> None: """ Adds Units based on Logic to the List requested Units Returns: - UnitTypeId: Type of requested Unit + ProductionRequest: None """ - #TODO: THIS SHOULD BE A POLYMORPHIC APPROACH TO AVOID LARGE FUNCTIONS, BUT FOR NOW INNER FUNCTIONS WILL DO - def _runby_request(): - """ reuest unit for Run-By Army group""" - opponent_has_detection:bool = self.bot.macro.build_order.opponent_has_detection - if len(self.unit_list) + len(self.units_in_transit) < RUN_BY_SIZE: - if self.bot.structures.filter(lambda struct: struct.type_id in [UnitTypeId.GATEWAY, UnitTypeId.WARPGATE]): - if self.bot.units(UnitTypeId.DARKSHRINE).ready and not opponent_has_detection: - requested_unit: UnitTypeId = UnitTypeId.DARKTEMPLAR - if not requested_unit in self.requested_units: - self.requested_units.append(requested_unit) - return - requested_unit: UnitTypeId = UnitTypeId.ZEALOT - if not requested_unit in self.requested_units: - self.requested_units.append(requested_unit) - return + buffer:ProductionBuffer = self.bot.macro.production_buffer + + for struct in buffer.gateways: + request:ProductionRequest = \ + ProductionRequest(UnitTypeId.STALKER, self.id, struct.tag) + buffer.add_request(request) + + for struct in buffer.robofacilities: + request:ProductionRequest = \ + ProductionRequest(UnitTypeId.IMMORTAL, self.id, struct.tag) - def _army_request(): - """ request unit for "normal" Army group """ - gate_aliases:list = [UnitTypeId.GATEWAY, UnitTypeId.WARPGATE] - if self.bot.structures.filter(lambda struct: struct.type_id in gate_aliases): - stalkers:int = len(self.units(UnitTypeId.STALKER)) - zealots:int = len(self.units(UnitTypeId.ZEALOT)) +1 - - if self.bot.structures(UnitTypeId.TEMPLARARCHIVE) and len(self.units(UnitTypeId.HIGHTEMPLAR)) < 2: - requested_unit: UnitTypeId = UnitTypeId.HIGHTEMPLAR - if not requested_unit in self.requested_units: - self.requested_units.append(requested_unit) - - if not zealots < stalkers: - requested_unit: UnitTypeId = UnitTypeId.ZEALOT - if not requested_unit in self.requested_units: - self.requested_units.append(requested_unit) - else: - requested_unit: UnitTypeId = UnitTypeId.STALKER - if not requested_unit in self.requested_units: - self.requested_units.append(requested_unit) - - if self.bot.structures(UnitTypeId.ROBOTICSFACILITY): - if not self.has_detection: - requested_unit: UnitTypeId = UnitTypeId.OBSERVER - else: - requested_unit: UnitTypeId = UnitTypeId.IMMORTAL - if not requested_unit in self.requested_units: - self.requested_units.append(requested_unit) - - - if self.bot.structures(UnitTypeId.STARGATE): - if len(self.bot.units.flying) > \ - len(self.bot.enemy_units.filter(lambda unit: unit.is_flying and unit.can_attack)): - requested_unit: UnitTypeId = UnitTypeId.PHOENIX - if not requested_unit in self.requested_units: - self.requested_units.append(requested_unit) - - #match self.GroupTypeId: - #case GroupTypeId.RUN_BY: - # logger.info("not Testing Runbys right now") -# _runby_request() - #case GroupTypeId.ARMY: - _army_request() + for struct in buffer.stargates: + request:ProductionRequest = \ + ProductionRequest(UnitTypeId.PHOENIX, self.id, struct.tag) def remove_unit(self, unit_tag:str) -> bool: """ Removes are unit from ArmyGroup diff --git a/bot/HarstemsAunt/build_order.py b/bot/HarstemsAunt/build_order.py index 21ce0f9..130cb8d 100644 --- a/bot/HarstemsAunt/build_order.py +++ b/bot/HarstemsAunt/build_order.py @@ -13,8 +13,9 @@ from sc2.unit_command import UnitCommand from sc2.ids.unit_typeid import UnitTypeId +# pylint: disable=E0402 from .army_group import ArmyGroup -from .common import ALL_STRUCTURES,INITIAL_TECH,DT_TIMING,logger +from .common import ALL_STRUCTURES,INITIAL_TECH,DT_TIMING class InstructionType(Enum): """Enumeration containing InstructionTypes """ @@ -94,7 +95,7 @@ def __init__(self, bot:BotAI, build:Build=Build.FOUR_GATE): self.build = build self.step = 0 self.buffer = [] - self.army_groups:List[ArmyGroup] = self.bot.army_groups + self.army_groups:List[ArmyGroup] = bot.army_groups @cached_property def enemy_race(self) -> Race: diff --git a/bot/HarstemsAunt/macro.py b/bot/HarstemsAunt/macro.py index 91d6dd0..d9c1d7c 100644 --- a/bot/HarstemsAunt/macro.py +++ b/bot/HarstemsAunt/macro.py @@ -12,8 +12,10 @@ from sc2.ids.upgrade_id import UpgradeId from sc2.ids.unit_typeid import UnitTypeId +# pylint: disable=E0402 from .utils import Utils -from .common import GATEWAY_UNTIS, ROBO_UNITS, STARGATE_UNITS, logger +from .production_buffer import ProductionBuffer +from .common import GATEWAY_UNTIS, ROBO_UNITS, STARGATE_UNITS from .build_order import BuildOrder, BuildInstruction, InstructionType @@ -24,20 +26,20 @@ def __init__(self,bot:BotAI) -> None: self.temp:list = [] self.mined_out_bases: list = [] self.build_order = BuildOrder(self.bot) + self.production_buffer = ProductionBuffer(self.bot) #TODO: #75 Premove workers async def __call__(self): """ makes the class callable, get's executed to every tick in BotClass """ if self.bot.alert: await self.handle_alerts(self.bot.alert) - + await self.chronoboost() self.get_upgrades() - + await self.handle_instructions() await self.build_order.update() - # TODO: Create Check in Build Order Class if not self.build_order.is_performing_initial_build: await self.build_supply() self.build_probes() @@ -150,7 +152,6 @@ async def build_gateway_units(bot:BotAI,unit_type:UnitTypeId): return await build_gateway_units(self.bot,unit_type) - next_step: BuildInstruction = self.build_order.next_instruction() if not next_step and self.build_order.buffer: next_step = self.build_order.get_instruction_from_buffer() diff --git a/bot/HarstemsAunt/main.py b/bot/HarstemsAunt/main.py index c71a2ce..c162279 100644 --- a/bot/HarstemsAunt/main.py +++ b/bot/HarstemsAunt/main.py @@ -14,23 +14,24 @@ from sc2.ids.upgrade_id import UpgradeId from sc2.ids.unit_typeid import UnitTypeId +# pylint: disable=E0401 +#from Unit_Classes.Archon import Archons +from Unit_Classes.Zealots import Zealot +from Unit_Classes.Stalkers import Stalkers +#from Unit_Classes.Immortal import Immortals +from Unit_Classes.observer import Observer +#from Unit_Classes.HighTemplar import HighTemplar +#from Unit_Classes.DarkTemplar import DarkTemplar + from map_analyzer import MapData +# pylint: disable=E0402 from .macro import Macro from .pathing import Pathing +from .army_group import ArmyGroup from .map_sector import MapSector -from .army_group import ArmyGroup, GroupTypeId +from .common import WORKER_IDS,SECTORS,ATTACK_TARGET_IGNORE,logger from .speedmining import get_speedmining_positions,split_workers, micro_worker -from .common import GATEWAY_UNTIS,WORKER_IDS,SECTORS,ATTACK_TARGET_IGNORE,logger - -#TODO: #63 Move UnitClasses into Micro class when ready -from Unit_Classes.Archon import Archons -from Unit_Classes.Zealots import Zealot -from Unit_Classes.Stalkers import Stalkers -from Unit_Classes.Immortal import Immortals -from Unit_Classes.observer import Observer -from Unit_Classes.HighTemplar import HighTemplar -from Unit_Classes.DarkTemplar import DarkTemplar DEBUG = True @@ -43,11 +44,7 @@ class HarstemsAunt(BotAI): # Ground Units zealots: Zealot - archons: Archons stalkers: Stalkers - immortals: Immortals - high_templar: HighTemplar - dark_templar: DarkTemplar # Scouting Units observer : Observer @@ -373,12 +370,12 @@ async def on_end(self,game_result:Result): filename = f"{self.opponent_data_path}/results.csv" if not os.path.exists(filename): - with open(filename, 'w', newline='') as csvfile: + with open(filename, 'w', newline='', encoding='uft-8') as csvfile: csv_writer = csv.writer(csvfile) csv_writer.writerow(data) else: - with open(filename, 'a', newline='') as csvfile: + with open(filename, 'a', newline='', encoding='utf-8') as csvfile: csv_writer = csv.writer(csvfile) csv_writer.writerow(data) - await self.client.leave() \ No newline at end of file + await self.client.leave() diff --git a/bot/HarstemsAunt/map_sector.py b/bot/HarstemsAunt/map_sector.py index 7493bbc..6f94705 100644 --- a/bot/HarstemsAunt/map_sector.py +++ b/bot/HarstemsAunt/map_sector.py @@ -6,7 +6,7 @@ from sc2.unit import Unit from sc2.units import Units from sc2.bot_ai import BotAI -from sc2.game_info import Ramp +#from sc2.game_info import Ramp from sc2.position import Point2, Point3 #TODO: If i decide to keep it, it needs to be rewritten diff --git a/bot/production_buffer.py b/bot/HarstemsAunt/production_buffer.py similarity index 65% rename from bot/production_buffer.py rename to bot/HarstemsAunt/production_buffer.py index fd6ce39..74b89bb 100644 --- a/bot/production_buffer.py +++ b/bot/HarstemsAunt/production_buffer.py @@ -11,7 +11,7 @@ class ProductionRequest: """ Class Representing the a Production Request """ - def __new__(cls, requested_unit:UnitTypeId, army_group_tag: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: @@ -23,14 +23,14 @@ def __new__(cls, requested_unit:UnitTypeId, army_group_tag:int, build_structure_ """ instance = super().__new__(cls) instance.requested_unit = requested_unit - instance.army_group_tag = army_group_tag + instance.army_group = army_group_id instance.build_structure_tag = build_structure_tag return instance - def __init__(self, requested_unit:UnitTypeId, army_group_tag: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_tag + self.army_group_tag:int = army_group_id self.build_structure_tag = build_structure_tag def __repr__(self) -> str: @@ -44,6 +44,7 @@ def handled(self) -> bool: def handled(self, new_status) -> None: self.handled = new_status + class ProductionBuffer: """ Buffer for Production Requests before they are full filled""" @@ -54,15 +55,23 @@ def __init__(self,bot:BotAI) -> None: @property def gateways(self) -> Units: return self.bot.units.filter(lambda struct: struct.type_id \ - in [UnitTypeId.WARPGATE, UnitTypeId.GATEWAY]) + in [UnitTypeId.WARPGATE, UnitTypeId.GATEWAY] and struct.is_idle) @property def stargates(self) -> Units: - return self.bot.units(UnitTypeId.STARGATE) + return self.bot.units(UnitTypeId.STARGATE).idle @property def robofacilities(self) -> Units: - return self.bot.units(UnitTypeId.ROBOTICSFACILITY) + return self.bot.units(UnitTypeId.ROBOTICSFACILITY).idle + + def add_request(self, request:ProductionRequest) -> None: + self.requests.append(request) + + def remove_request(self, request:ProductionRequest): + self.requests.remove(request) - #def add_request(self) -> None: - # self. \ No newline at end of file + def update(self) -> None: + for request in self.requests: + if request.handled: + self.remove_request(request) diff --git a/bot/HarstemsAunt/utils.py b/bot/HarstemsAunt/utils.py index bf84ca2..b104081 100644 --- a/bot/HarstemsAunt/utils.py +++ b/bot/HarstemsAunt/utils.py @@ -6,7 +6,6 @@ from sc2.unit import Unit from sc2.bot_ai import BotAI -from sc2.game_data import GameData from sc2.position import Point2, Point3 from sc2.ids.upgrade_id import UpgradeId from sc2.ids.unit_typeid import UnitTypeId diff --git a/bot/Unit_Classes/Stalkers.py b/bot/Unit_Classes/Stalkers.py index e451c9f..3d82d76 100644 --- a/bot/Unit_Classes/Stalkers.py +++ b/bot/Unit_Classes/Stalkers.py @@ -1,17 +1,17 @@ -from HarstemsAunt.common import logger -from Unit_Classes.baseClassGround import BaseClassGround + + import numpy as np -from sc2.unit import Unit from sc2.units import Units -from sc2.bot_ai import BotAI from sc2.position import Point2 +# pylint: disable=E0402 +# pylint: disable=E0401 from HarstemsAunt.pathing import Pathing from HarstemsAunt.common import ATTACK_TARGET_IGNORE, MIN_SHIELD_AMOUNT,\ ALL_STRUCTURES, PRIO_ATTACK_TARGET, WORKER_IDS - +from Unit_Classes.baseClassGround import BaseClassGround class Stalkers(BaseClassGround): """ Extension of BaseClassGround """ diff --git a/bot/Unit_Classes/Zealots.py b/bot/Unit_Classes/Zealots.py index 0f23a4f..c7f26e4 100644 --- a/bot/Unit_Classes/Zealots.py +++ b/bot/Unit_Classes/Zealots.py @@ -1,4 +1,5 @@ - +"""Unit Class for Zealots""" +# pylint: disable=W0611 from typing import Optional import numpy as np @@ -7,14 +8,21 @@ from sc2.units import Units from sc2.position import Point2 +# pylint: disable=E0401 from Unit_Classes.baseClassGround import BaseClassGround from HarstemsAunt.common import ATTACK_TARGET_IGNORE class Zealot(BaseClassGround): # Overwritten from BaseClassGround - + # pylint: disable=W0640 async def handle_attackers(self, units: Units, attack_target: Point2) -> None: + """ Handles Attackers + + Args: + units (Units): Controlled Units + attack_target (Point2): Point which is supposed to be attacked + """ grid: np.ndarray = self.pathing.ground_grid for unit in units: friendly_units = self.bot.units.filter(lambda u: u.tag != unit.tag) diff --git a/bot/Unit_Classes/baseClassGround.py b/bot/Unit_Classes/baseClassGround.py index a46f4cf..a74a1a2 100644 --- a/bot/Unit_Classes/baseClassGround.py +++ b/bot/Unit_Classes/baseClassGround.py @@ -7,9 +7,9 @@ from sc2.bot_ai import BotAI from sc2.position import Point2 +# pylint: disable=E0401 from HarstemsAunt.pathing import Pathing -from HarstemsAunt.common import ATTACK_TARGET_IGNORE, MIN_SHIELD_AMOUNT,\ - ALL_STRUCTURES, PRIO_ATTACK_TARGET, WORKER_IDS,logger +from HarstemsAunt.common import ATTACK_TARGET_IGNORE,PRIO_ATTACK_TARGET class BaseClassGround: