-
Notifications
You must be signed in to change notification settings - Fork 183
Expand file tree
/
Copy pathwarpgate_push.py
More file actions
147 lines (125 loc) · 6.35 KB
/
warpgate_push.py
File metadata and controls
147 lines (125 loc) · 6.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
from loguru import logger
from sc2 import maps
from sc2.bot_ai import BotAI
from sc2.data import Difficulty, Race
from sc2.ids.ability_id import AbilityId
from sc2.ids.buff_id import BuffId
from sc2.ids.unit_typeid import UnitTypeId
from sc2.ids.upgrade_id import UpgradeId
from sc2.main import run_game
from sc2.player import Bot, Computer
from sc2.unit import Unit
class WarpGateBot(BotAI):
def __init__(self):
# Initialize inherited class
self.proxy_built = False
async def warp_new_units(self, proxy: Unit):
for warpgate in self.structures(UnitTypeId.WARPGATE).ready:
abilities = await self.get_available_abilities([warpgate])
# all the units have the same cooldown anyway so let's just look at ZEALOT
if AbilityId.WARPGATETRAIN_STALKER in abilities[0]:
pos = proxy.position.to2.random_on_distance(4)
placement = await self.find_placement(AbilityId.WARPGATETRAIN_STALKER, pos, placement_step=1)
if placement is None:
# return ActionResult.CantFindPlacementLocation
logger.info("can't place")
return
warpgate.warp_in(UnitTypeId.STALKER, placement)
async def on_step(self, iteration: int):
await self.distribute_workers()
if not self.townhalls.ready:
# Attack with all workers if we don't have any nexuses left, attack-move on enemy spawn (doesn't work on 4 player map) so that probes auto attack on the way
for worker in self.workers:
worker.attack(self.enemy_start_locations[0])
return
nexus = self.townhalls.ready.random
# Build pylon when on low supply
if self.supply_left < 2 and self.already_pending(UnitTypeId.PYLON) == 0:
# Always check if you can afford something before you build it
if self.can_afford(UnitTypeId.PYLON):
await self.build(UnitTypeId.PYLON, near=nexus)
return
if self.workers.amount < self.townhalls.amount * 22 and nexus.is_idle:
if self.can_afford(UnitTypeId.PROBE):
nexus.train(UnitTypeId.PROBE)
elif self.structures(UnitTypeId.PYLON).amount < 5 and self.already_pending(UnitTypeId.PYLON) == 0:
if self.can_afford(UnitTypeId.PYLON):
await self.build(UnitTypeId.PYLON, near=nexus.position.towards(self.game_info.map_center, 5))
proxy = None
if self.structures(UnitTypeId.PYLON).ready:
proxy = self.structures(UnitTypeId.PYLON).closest_to(self.enemy_start_locations[0])
pylon = self.structures(UnitTypeId.PYLON).ready.random
if self.structures(UnitTypeId.GATEWAY).ready:
# If we have no cyber core, build one
if not self.structures(UnitTypeId.CYBERNETICSCORE):
if (
self.can_afford(UnitTypeId.CYBERNETICSCORE)
and self.already_pending(UnitTypeId.CYBERNETICSCORE) == 0
):
await self.build(UnitTypeId.CYBERNETICSCORE, near=pylon)
# Build up to 4 gates
if (
self.can_afford(UnitTypeId.GATEWAY)
and self.structures(UnitTypeId.WARPGATE).amount + self.structures(UnitTypeId.GATEWAY).amount < 4
):
await self.build(UnitTypeId.GATEWAY, near=pylon)
# Build gas
for nexus in self.townhalls.ready:
vgs = self.vespene_geyser.closer_than(15, nexus)
for vg in vgs:
if self.can_afford(UnitTypeId.ASSIMILATOR):
worker = self.select_build_worker(vg.position)
if worker is not None:
if not self.gas_buildings or not self.gas_buildings.closer_than(1, vg):
worker.build_gas(vg)
worker.stop(queue=True)
# Research warp gate if cybercore is completed
if (
self.structures(UnitTypeId.CYBERNETICSCORE).ready
and self.can_afford(AbilityId.RESEARCH_WARPGATE)
and self.already_pending_upgrade(UpgradeId.WARPGATERESEARCH) == 0
):
ccore = self.structures(UnitTypeId.CYBERNETICSCORE).ready.first
ccore.research(UpgradeId.WARPGATERESEARCH)
# Morph to warp gate when research is complete
for gateway in self.structures(UnitTypeId.GATEWAY).ready.idle:
if self.already_pending_upgrade(UpgradeId.WARPGATERESEARCH) == 1:
gateway(AbilityId.MORPH_WARPGATE)
if self.proxy_built and proxy:
await self.warp_new_units(proxy)
# Make stalkers attack either closest enemy unit or enemy spawn location
if self.units(UnitTypeId.STALKER).amount > 3:
for stalker in self.units(UnitTypeId.STALKER).ready.idle:
targets = (self.enemy_units | self.enemy_structures).filter(lambda unit: unit.can_be_attacked)
if targets:
target = targets.closest_to(stalker)
stalker.attack(target)
else:
stalker.attack(self.enemy_start_locations[0])
# Build proxy pylon
if (
self.structures(UnitTypeId.CYBERNETICSCORE).amount >= 1
and not self.proxy_built
and self.can_afford(UnitTypeId.PYLON)
):
p = self.game_info.map_center.towards(self.enemy_start_locations[0], 20)
await self.build(UnitTypeId.PYLON, near=p)
self.proxy_built = True
# Chrono nexus if cybercore is not ready, else chrono cybercore
if not self.structures(UnitTypeId.CYBERNETICSCORE).ready:
if not nexus.has_buff(BuffId.CHRONOBOOSTENERGYCOST) and not nexus.is_idle:
if nexus.energy >= 50:
nexus(AbilityId.EFFECT_CHRONOBOOSTENERGYCOST, nexus)
else:
ccore = self.structures(UnitTypeId.CYBERNETICSCORE).ready.first
if not ccore.has_buff(BuffId.CHRONOBOOSTENERGYCOST) and not ccore.is_idle:
if nexus.energy >= 50:
nexus(AbilityId.EFFECT_CHRONOBOOSTENERGYCOST, ccore)
def main():
run_game(
maps.get("(2)CatalystLE"),
[Bot(Race.Protoss, WarpGateBot()), Computer(Race.Protoss, Difficulty.Easy)],
realtime=False,
)
if __name__ == "__main__":
main()