Skip to content

Commit

Permalink
Merge pull request #72 from FredNoonienSingh/rewrites
Browse files Browse the repository at this point in the history
added Builds enum
  • Loading branch information
FredNoonienSingh authored Jan 10, 2025
2 parents 7a5707d + 3d6c74e commit c0c59c5
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 24 deletions.
78 changes: 73 additions & 5 deletions bot/HarstemsAunt/build_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ class InstructionType(Enum):
UNIT_PRODUCTION = 1
BUILD_STRUCTURE = 2

class Build(Enum):
CANNON_RUSH = 1
FOUR_GATE = 2


class BuildInstruction:
""" Instruction for the Bot to build a structure, not sure yet how to add upgrades, and multiple instructions at once
and how to take unit production into account, i already got a set of all Structures in .common maybe i just add every instruction
Expand Down Expand Up @@ -46,10 +51,12 @@ def __repr__(self):
if self.instruction_type == InstructionType.UNIT_PRODUCTION:
return f"train {self.type_id}"


class BuildOrder:

def __init__(self, bot:BotAI):
def __init__(self, bot:BotAI, build:Build=Build.FOUR_GATE):
self.bot = bot
self.build = build
self.step = 0
self.buffer = []

Expand All @@ -71,7 +78,9 @@ def instruction_list(self) -> List[BuildInstruction]:
vespene_position_0:Point2 = self.bot.vespene_geyser.closer_than(12, start_pos)[0]
vespene_position_1:Point2 = self.bot.vespene_geyser.closer_than(12, start_pos)[1]

instructions = [
cannon_pylon_0: Point2 = self.bot.enemy_start_locations[0].towards(self.bot.game_info.map_center, 5)

FOUR_GATE = [
BuildInstruction(UnitTypeId.PYLON,wall_pylon_pos),
BuildInstruction(UnitTypeId.GATEWAY,wall_buildings[0]),
BuildInstruction(UnitTypeId.ASSIMILATOR,vespene_position_0),
Expand All @@ -92,8 +101,58 @@ def instruction_list(self) -> List[BuildInstruction]:
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
BuildInstruction(UnitTypeId.STALKER, start_pos),
]

CANNON_RUSH = [
BuildInstruction(UnitTypeId.PYLON,wall_pylon_pos),
BuildInstruction(UnitTypeId.FORGE,wall_buildings[0]),
BuildInstruction(UnitTypeId.PYLON, cannon_pylon_0, 5),
BuildInstruction(UnitTypeId.PHOTONCANNON, cannon_pylon_0, 5),
BuildInstruction(UnitTypeId.PHOTONCANNON, cannon_pylon_0, 5),
BuildInstruction(UnitTypeId.PYLON, cannon_pylon_0, 5),
BuildInstruction(UnitTypeId.PYLON, cannon_pylon_0, 5),
BuildInstruction(UnitTypeId.PHOTONCANNON, cannon_pylon_0, 5),
BuildInstruction(UnitTypeId.PHOTONCANNON, cannon_pylon_0, 5),
BuildInstruction(UnitTypeId.PYLON, cannon_pylon_0, 5),
]
return instructions

match self.build:
case Build.CANNON_RUSH:
return CANNON_RUSH
case Build.FOUR_GATE:
return FOUR_GATE

@property
def constructed_structures(self) -> List[UnitTypeId]:
Expand Down Expand Up @@ -133,10 +192,19 @@ def add_constructed_structure(self, structure:UnitTypeId) -> None:
def get_build_pos(self) -> Union[Point2, Point3, Unit]:
if len(self.instruction_list) > self.step:
return self.instruction_list[self.step].position
return self.bot.start_location.towards(self.bot.game_info.map_center, 4)
last_pylon:Unit = self.bot.structures(UnitTypeId.PYLON).sorted(lambda struct: struct.age)[0]
return last_pylon.position.towards_with_random_angle(self.bot.game_info.map_center)

async def update(self):


if self.build == "cannon":
if self.bot.structures(UnitTypeId.PYLON)\
.filter(lambda struct: struct.distance_to(self.bot.enemy_start_locations[0]) < 12):
self.buffer.append(UnitTypeId.PYLON)
else:
self.buffer.append(UnitTypeId.PHOTONCANNON)
return

#TODO: ADD Conditions under which more Economy gets added to the Build
#TODO: #66 ADD Conditions for advanced Tech -> such as fleet beacon ...
if self.opponent_builds_air and not self.bot.structures(UnitTypeId.STARGATE):
Expand Down
2 changes: 2 additions & 0 deletions bot/HarstemsAunt/builds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

from .build_order import BuildInstruction
43 changes: 24 additions & 19 deletions bot/HarstemsAunt/macro.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from sc2.data import Alert
from sc2.unit import Unit
from sc2.data import Race
from sc2.units import Units
from sc2.bot_ai import BotAI
from sc2.ids.buff_id import BuffId
Expand Down Expand Up @@ -34,18 +33,6 @@ async def build_gateway_units(bot:BotAI,unit_type:UnitTypeId):
warp_in_pos = Utils.get_warp_in_pos(bot)
await warp_in_unit(bot, unit_type, warp_in_pos)

async def build_stargate_units(bot:BotAI, unit_type:UnitTypeId):
if Utils.can_build_unit(bot, unit_type):
for gate in bot.structures(UnitTypeId.STARGATE):
if gate.is_idle:
gate.train(unit_type)

async def build_robo_units(bot:BotAI, unit_type:UnitTypeId):
if Utils.can_build_unit(bot, unit_type):
for robo in bot.structures(UnitTypeId.ROBOTICSFACILITY):
if robo.is_idle:
robo.train(unit_type)

class Macro:

def __init__(self,bot:BotAI) -> None:
Expand Down Expand Up @@ -89,22 +76,40 @@ async def handle_instructions(self) -> None:

async def construct_building(next_step:BuildInstruction):
#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

if self.build_order.step + 1 < len(self.build_order.instruction_list):
following_instruction: BuildInstruction = \
self.build_order.instruction_list[self.build_order.step +1]

if following_instruction == next_step.type_id:
pending_check = False

# Needs to be handled separably because it the special placement requirements
if next_step.type_id == UnitTypeId.ASSIMILATOR:
if Utils.can_build_structure(self.bot, next_step.type_id):
await self.build_gas(next_step.position)
if not pending_check:
await self.build_gas(next_step.position)
else:
if not self.bot.already_pending(next_step.type_id):
await self.build_gas(next_step.position)

# Needs to be handled here because, bot.get_next_expansion() is a coroutine
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()

if Utils.can_build_structure(self.bot, next_step.type_id)and\
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())
if Utils.can_build_structure(self.bot, next_step.type_id):
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())

async def train_unit(next_step:BuildInstruction):
#TODO: ADD WARPPRISM LOGIC, SO REINFORCEMENTS CAN BE WARPED IN CLOSE TO FIGHT
Expand Down

0 comments on commit c0c59c5

Please sign in to comment.