-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathBuild_Units.cpp
241 lines (219 loc) · 6.85 KB
/
Build_Units.cpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#include "BasicSc2Bot.h"
using namespace sc2;
void BasicSc2Bot::ManageProduction() {
// Train units and upgrades
TrainMarines();
TrainBattlecruisers();
if (current_gameloop % 10 == 0)
{
TrainSiegeTanks();
}
UpgradeMarines();
UpgradeMechs();
}
void BasicSc2Bot::TrainMarines() {
// Find Barracks to train Marines
const ObservationInterface* obs = Observation();
Units barracks = obs->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_BARRACKS));
Units factories = obs->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_FACTORY));
Units starport = obs->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_STARPORT));
Units reactor = obs->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_BARRACKSREACTOR));
if (barracks.empty() ||
phase == 0) { // Can't train Marines without Barracks
return;
}
// factory is built...gotta swap
if (phase == 1 && !factories.empty()) {
if (factories.front()->build_progress > 0.4) {
return;
}
}
else if (phase == 2 && !starport.empty()) {
if (starport.front()->build_progress > 0.5) {
return;
}
}
// Train Marines from Barracks
if (CanBuild(50) && !barracks.empty()) {
for (const auto& b : barracks) {
if (b->orders.empty() && !reactor.empty() &&
b->add_on_tag == reactor.front()->tag) {
if (CanBuild(550)) {
Actions()->UnitCommand(b, ABILITY_ID::TRAIN_MARINE, true);
Actions()->UnitCommand(b, ABILITY_ID::TRAIN_MARINE, true);
}
}
else if (b->orders.empty()) {
Actions()->UnitCommand(b, ABILITY_ID::TRAIN_MARINE);
}
}
}
}
void BasicSc2Bot::TrainBattlecruisers() {
// Find Starports to build a Battlecruiser
const ObservationInterface* obs = Observation();
Units starports = obs->GetUnits(Unit::Alliance::Self, [](const Unit& unit) {
return unit.unit_type == UNIT_TYPEID::TERRAN_STARPORT && unit.tag;
});
Units fusioncore =
obs->GetUnits(Unit::Alliance::Self, [](const Unit& unit) {
return unit.unit_type == UNIT_TYPEID::TERRAN_FUSIONCORE && unit.tag;
});
if (starports.empty() || fusioncore.empty()) {
return;
}
// Train Battlecruisers from Starports
const Unit* starport = starports.front();
if (starport->add_on_tag != 0) {
if (starport->orders.empty()) {
if (CanBuild(400, 300, 6)) {
Actions()->UnitCommand(starport,
ABILITY_ID::TRAIN_BATTLECRUISER);
}
}
else {
for (const auto& order : starport->orders) {
if (order.ability_id == ABILITY_ID::TRAIN_BATTLECRUISER) {
if (order.progress >= 0.0f) {
first_battlecruiser = true;
}
}
}
}
}
}
void BasicSc2Bot::TrainSiegeTanks() {
// Find Factories to train Siege Tanks
const ObservationInterface* obs = Observation();
Units factories = obs->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_FACTORY));
Units starport = obs->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_STARPORT));
Units fusioncores = obs->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_FUSIONCORE));
// Can't train Siege Tanks without Factories
if (factories.empty()) {
return;
}
const Unit* factory;
if (CanBuild(150, 125, 3)) {
if (phase == 2) {
factory = factories.front();
// Maintain 1 : 4 Ratio of Marines and Siege Tanks
if (factory->add_on_tag != 0 && factory->orders.empty()) {
Actions()->UnitCommand(factory, ABILITY_ID::TRAIN_SIEGETANK);
}
}
else if (phase == 3) {
if (first_battlecruiser) {
std::vector<float> MineralGas =
HowCloseToResourceGoal(400, 300);
/*float avg_resources = (MineralGas[0] + MineralGas[1]) / 2;*/
float m_close = MineralGas[0];
float g_close = MineralGas[1];
float how_close =
!starport.empty()
? HowClosetoFinishCurrentJob(starport.front())
: 0.0f;
factory = factories.front();
if (num_starports && ((0.0f < how_close && how_close < 0.5f))) {
if (factory->add_on_tag != 0 && factory->orders.empty()) {
Actions()->UnitCommand(factory,
ABILITY_ID::TRAIN_SIEGETANK);
}
}
else if (num_starports && m_close > 0.9f && g_close > 0.9f) {
if (factory->add_on_tag != 0 && factory->orders.empty()) {
Actions()->UnitCommand(factory,
ABILITY_ID::TRAIN_SIEGETANK);
}
}
else if (!num_starports || !num_fusioncores) {
if (factory->add_on_tag != 0 && factory->orders.empty()) {
Actions()->UnitCommand(factory,
ABILITY_ID::TRAIN_SIEGETANK);
}
}
}
}
}
}
void BasicSc2Bot::UpgradeMarines() {
// Find Tech Labs and Engineering Bays to upgrade Marines
const ObservationInterface* observation = Observation();
Units techlabs = observation->GetUnits(
Unit::Alliance::Self, IsUnit(UNIT_TYPEID::TERRAN_BARRACKSTECHLAB));
Units engineeringbays = observation->GetUnits(
Unit::Alliance::Self, IsUnit(UNIT_TYPEID::TERRAN_ENGINEERINGBAY));
// Can't upgrade Marines without Engineering Bays
if (engineeringbays.empty()) {
return;
}
// Upgrade from Engineering Bay
for (const auto& upgrade : engineeringbay_upgrade_order) {
// Skip if the upgrade is already completed
if (completed_upgrades.find(upgrade) != completed_upgrades.end()) {
continue;
}
// Get the ability corresponding to the upgrade
ABILITY_ID ability_id = GetAbilityForUpgrade(upgrade);
if (ability_id == ABILITY_ID::INVALID) {
continue;
}
// Upgrade from Tech Lab(Combat Shield)
if (!techlabs.empty()) {
if (completed_upgrades.find(UPGRADE_ID::COMBATSHIELD) ==
completed_upgrades.end()) {
ABILITY_ID upgrade = ABILITY_ID::RESEARCH_COMBATSHIELD;
// Check if the Tech Lab is busy or not
for (const auto& techlab : techlabs) {
if (techlab->orders.empty() && CanBuild(100, 450)) {
Actions()->UnitCommand(techlab, upgrade);
return;
}
}
}
}
// Check if the Engineering Bay is busy or not
for (const auto& engineeringbay : engineeringbays) {
if (engineeringbay->orders.empty() && CanBuild(200, 200)) {
Actions()->UnitCommand(engineeringbay, ability_id);
return;
}
}
}
}
void BasicSc2Bot::UpgradeMechs() {
// Find Armories to upgrade Mechs
const ObservationInterface* observation = Observation();
Units armories = observation->GetUnits(Unit::Alliance::Self,
IsUnit(UNIT_TYPEID::TERRAN_ARMORY));
// Can't upgrade Mechs(Battlecruisers and Tanks) without Armories
// Also, save resources for first Battlecruiser
if (armories.empty() || !first_battlecruiser) {
return;
}
// Upgrade from Armory
for (const auto& upgrade : armory_upgrade_order) {
// Skip if the upgrade is already completed
if (completed_upgrades.find(upgrade) != completed_upgrades.end()) {
continue;
}
// Get the ability corresponding to the upgrade
ABILITY_ID ability_id = GetAbilityForUpgrade(upgrade);
if (ability_id == ABILITY_ID::INVALID) {
continue;
}
// Check if the Armory is busy or not
for (const auto& armory : armories) {
if (armory->orders.empty() && CanBuild(500, 500)) {
Actions()->UnitCommand(armory, ability_id);
return;
}
}
}
}