Skip to content

Commit

Permalink
Merge pull request #89 from FredNoonienSingh/82-fix-production-bug
Browse files Browse the repository at this point in the history
fixed more linitng errors
  • Loading branch information
FredNoonienSingh authored Jan 17, 2025
2 parents 2cad669 + 5b92525 commit 81b27cb
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 41 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -27,6 +32,7 @@
"unittype",
"Utilityclass",
"vespene",
"WARPGATE",
"warpin",
"WARPPRISM",
"warprism"
Expand Down
2 changes: 1 addition & 1 deletion bot/HarstemsAunt/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
UnitTypeId.CARRIER
}

GATEWAY_UNTIS: Set[UnitTypeId] = {
GATEWAY_UNITS: Set[UnitTypeId] = {
UnitTypeId.ZEALOT,
UnitTypeId.STALKER,
UnitTypeId.SENTRY,
Expand Down
1 change: 1 addition & 0 deletions bot/HarstemsAunt/debugTools.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Module containing a Debug Class"""
# pylint: disable=C0103
from typing import Union
from math import sin, pi, cos

Expand Down
88 changes: 51 additions & 37 deletions bot/HarstemsAunt/macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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)
Expand Down Expand Up @@ -57,14 +57,15 @@ 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
if unit_type in ROBO_UNITS:
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 """
Expand All @@ -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
Expand All @@ -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()
Expand Down Expand Up @@ -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)

Expand All @@ -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:
Expand Down Expand Up @@ -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 """
Expand All @@ -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,
Expand All @@ -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)

Expand All @@ -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)
await self.bot.build(UnitTypeId.NEXUS, near=location, max_distance=0)
43 changes: 40 additions & 3 deletions bot/HarstemsAunt/production_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)

0 comments on commit 81b27cb

Please sign in to comment.