ProtoBot
Loading...
Searching...
No Matches
BuildingPlacer Class Reference

The BuildingPlacer is the way ProtoBot is able to utilize the BWEB blocks generated to place down buildings. This allows for a single class to be able to find places to build and returns information about the placement info if anything goes wrong.

When the BuildingPlacer is first created the Blocks that generated are stored into lists that ProtoBot is able to use based on the building type of a ResourceRequest. This allows the BuildingPlacer to find a suitable generated locations without having to loop through ever single block on the map.
More blocks are added based on the areas the ProtoBot controls. To prevent the risk of ProtoBot building in enemy territory, ProtoBot will only build in the areas that ProtoBot currently 'controls'. When a nexus is created this expands ProtoBot's influence and makes more blocks avalible if any are generated in that location. More...

#include <BuildingPlacer.h>

Public Member Functions

 BuildingPlacer (BuildManager *buildReference)
PlacementInfo getPositionToBuild (BWAPI::UnitType, const BWEM::Base *)
bool alreadyUsingTiles (BWAPI::TilePosition, int, int, bool assimilator)
 Checks if a location to place a building already has another unit ontop of it (will only consider buildings not combat units).
bool checkPower (BWAPI::TilePosition, BWAPI::UnitType)
BWAPI::TilePosition checkBuildingBlocks ()
 Finda an available Block that has no power in the power tile location.
BWAPI::TilePosition checkPowerReserveBlocks ()
 Checks Blocks of size 2x2 (tiles) that can be used in order to place down pylons for supply.
BWAPI::TilePosition findAvailableExpansion ()
 Checks BWEM expansion locations for possible place to construct resource depot.
BWAPI::TilePosition findAvailableGyser (const BWEM::Base *)
 Checks a base to place down an assimlator ontop of a vespene gyser.
BWAPI::TilePosition findAvaliblePlacement (BWAPI::UnitType)
 Standard call for buildings to find a location to be placed other than refineries, resource depots, and supply units.
int numberOfFullPoweredLargePlacements ()
void drawPoweredTiles ()
void onStart ()
 Update Block information to reflect generated BWEB Blocks and reset values to reflect a beggining game state.
void onUnitCreate (BWAPI::Unit)
 Updates BWEM to reflect the current state of StarCraft game.
void onUnitComplete (BWAPI::Unit)
 Updates BWEM to reflect the current state of StarCraft game.
void onUnitDestroy (BWAPI::Unit)
 Updates BWEM to reflect the current state of StarCraft game.
void onUnitMorph (BWAPI::Unit)
 Updates BWEM to reflect the current state of StarCraft game.
void onUnitDiscover (BWAPI::Unit)
 Updates BWEM to reflect the current state of StarCraft game.

Public Attributes

int Powered_LargePlacements = 0
int Powered_MediumPlacements = 0
int Used_LargeBuildingPlacements
int Used_MediumBuildingPlacements
BuildManagerbuildReference

Private Attributes

std::map< BWAPI::TilePosition, BlockDataBlock_Information
std::unordered_set< const BWEM::Area * > AreasOccupied
std::vector< BWEB::Block > ProtoBot_Blocks
std::unordered_map< const BWEM::Area *, std::vector< BWEB::Block > > Area_Blocks
int mapWidth = 0
int mapHeight = 0
int nexusCount = 0
bool debug = false

Detailed Description

The BuildingPlacer is the way ProtoBot is able to utilize the BWEB blocks generated to place down buildings. This allows for a single class to be able to find places to build and returns information about the placement info if anything goes wrong.

When the BuildingPlacer is first created the Blocks that generated are stored into lists that ProtoBot is able to use based on the building type of a ResourceRequest. This allows the BuildingPlacer to find a suitable generated locations without having to loop through ever single block on the map.
More blocks are added based on the areas the ProtoBot controls. To prevent the risk of ProtoBot building in enemy territory, ProtoBot will only build in the areas that ProtoBot currently 'controls'. When a nexus is created this expands ProtoBot's influence and makes more blocks avalible if any are generated in that location.

Definition at line 69 of file BuildingPlacer.h.

Constructor & Destructor Documentation

◆ BuildingPlacer()

BuildingPlacer::BuildingPlacer ( BuildManager * buildReference)

Definition at line 5 of file BuildingPlacer.cpp.

5 : buildReference(buildReference)
6{
7
8}

Member Function Documentation

◆ alreadyUsingTiles()

bool BuildingPlacer::alreadyUsingTiles ( BWAPI::TilePosition position,
int width,
int height,
bool assimilator = false )

Checks if a location to place a building already has another unit ontop of it (will only consider buildings not combat units).

Parameters
Top Left Tile Position to place building
Width
Height
isAssimilator
Returns
TilePosition to build

Definition at line 11 of file BuildingPlacer.cpp.

12{
13 const BWAPI::UnitType typeFound = BWEB::Map::isUsed(position, width, height);
14
15 if (!assimilator)
16 {
17 if (BWAPI::UnitTypes::None != typeFound) return true;
18 }
19 else
20 {
21 if (typeFound.isRefinery())
22 {
23 return true;
24 }
25 }
26
27 return false;
28}

◆ checkBuildingBlocks()

BWAPI::TilePosition BuildingPlacer::checkBuildingBlocks ( )

Finda an available Block that has no power in the power tile location.

Returns
TilePosition to build

Definition at line 54 of file BuildingPlacer.cpp.

55{
56 //Power up blocks that are not power reserve blocks.
57 double distanceToPowerBlock = INT_MAX;
58 BWAPI::TilePosition powerTilePosition = BWAPI::TilePositions::Invalid;
59 double finalDistance;
60
61 for (BWEB::Block block : ProtoBot_Blocks)
62 {
63 BlockData data = Block_Information[block.getTilePosition()];
64
65 if (data.Blocksize != BlockData::SUPPLY && data.Power_State != BlockData::FULLY_POWERED)
66 {
67 //Loop through all power tiles. Blocks can have more than 1 power tile.
68 for (const BWAPI::TilePosition powerPlacements : data.PowerTiles)
69 {
70 if (BWEB::Map::isUsed(powerPlacements) != BWAPI::UnitTypes::None) continue;
71
72 int distance = 0;
73 int distanceToEnemy = 0;
74 theMap.GetPath(BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()), BWAPI::Position(powerPlacements), &distance);
75 if (buildReference->commanderReference->enemy().main.has_value())
76 theMap.GetPath(BWAPI::Position(buildReference->commanderReference->enemy().main.value()), BWAPI::Position(block.getTilePosition()), &distanceToEnemy);
77
78 if (distance == -1) continue;
79
80 if (distanceToEnemy != 0 && buildReference->commanderReference->enemy().main.value())
81 {
82 finalDistance = static_cast<double>(distance) / distanceToEnemy;
83 }
84 else
85 {
86 finalDistance = static_cast<double>(distance);
87 }
88
89 if (finalDistance < distanceToPowerBlock)
90 {
91 distanceToPowerBlock = finalDistance;
92 powerTilePosition = powerPlacements;
93 }
94 }
95 }
96 }
97
98 return powerTilePosition;
99}

◆ checkPower()

bool BuildingPlacer::checkPower ( BWAPI::TilePosition location,
BWAPI::UnitType buildingType )

Definition at line 31 of file BuildingPlacer.cpp.

32{
33 //const int x_location = location.x;
34 //const int y_location = location.y;
35
36 //float tilesPowered = 0.0;
37
38 //for (int row = y_location; row < x_location + buildingType.tileHeight(); row++)
39 //{
40 // for (int column = x_location; column < x_location + buildingType.tileWidth(); column++)
41 // {
42 // if (poweredTiles[row][column] >= 1) tilesPowered++;
43 // }
44 //}
45
46 //const float totalTiles = float(buildingType.tileWidth() * buildingType.tileHeight());
47
49 //if (tilesPowered / totalTiles > .5) return true;
50
51 return false;
52}

◆ checkPowerReserveBlocks()

BWAPI::TilePosition BuildingPlacer::checkPowerReserveBlocks ( )

Checks Blocks of size 2x2 (tiles) that can be used in order to place down pylons for supply.

Returns
TilePosition to build

Definition at line 101 of file BuildingPlacer.cpp.

102{
103 double distanceToPowerBlock = INT_MAX;
104 BWAPI::TilePosition supplyReservePosition = BWAPI::TilePositions::Invalid;
105
106 std::vector<BWEB::Block> blocksToCheck;
107 double finalDistance;
108
109 blocksToCheck = ProtoBot_Blocks;
110 if (nexusCount >= 3)
111 {
112 blocksToCheck = BWEB::Blocks::getBlocks();
113 }
114 else
115 {
116 blocksToCheck = ProtoBot_Blocks;
117 }
118
119 for (BWEB::Block block : blocksToCheck)
120 {
121 BlockData data = Block_Information[block.getTilePosition()];
122
123 if (data.Blocksize == BlockData::SUPPLY && BWEB::Map::isUsed(block.getTilePosition()) == BWAPI::UnitTypes::None)
124 {
125 int distance = 0;
126 int distanceToEnemy = 0;
127 theMap.GetPath(BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()), BWAPI::Position(block.getTilePosition()), &distance);
128
129 if(buildReference->commanderReference->enemy().main.has_value())
130 theMap.GetPath(BWAPI::Position(buildReference->commanderReference->enemy().main.value()), BWAPI::Position(block.getTilePosition()), &distanceToEnemy);
131
132 if (distance == -1) continue;
133
134 if (distanceToEnemy != 0 && buildReference->commanderReference->enemy().main.has_value())
135 {
136 finalDistance = static_cast<double>(distance) / distanceToEnemy;
137 }
138 else
139 {
140 finalDistance = static_cast<double>(distance);
141 }
142
143 if (finalDistance < distanceToPowerBlock)
144 {
145 distanceToPowerBlock = finalDistance;
146 supplyReservePosition = block.getTilePosition();
147 }
148 }
149 }
150
151 return supplyReservePosition;
152}

◆ drawPoweredTiles()

void BuildingPlacer::drawPoweredTiles ( )

Definition at line 298 of file BuildingPlacer.cpp.

299{
300 if (debug == false) return;
301
302 /*for (int row = 0; row < poweredTiles.size(); row++)
303 {
304 for (int column = 0; column < poweredTiles[row].size(); column++)
305 {
306 if (poweredTiles[row][column] >= 1) BWAPI::Broodwar->drawCircleMap((column * 32) + 16, (row * 32) + 16, 5, BWAPI::Colors::Blue, true);
307 }
308 }*/
309
310 std::vector<BWEB::Block> blocksToCheck = {};
311 blocksToCheck = ProtoBot_Blocks;
312
313 /*if (nexusCount >= 3)
314 {
315 blocksToCheck = BWEB::Blocks::getBlocks();
316 }
317 else
318 {
319 blocksToCheck = ProtoBot_Blocks;
320 }*/
321
322 for (BWEB::Block block : blocksToCheck)
323 {
324 block.draw();
325
326 BlockData data = Block_Information[block.getTilePosition()];
327
328 if (data.Blocksize != BlockData::SUPPLY)
329 {
330 for (const BWAPI::TilePosition PowerTilePosition : data.PowerTiles)
331 {
332 BWAPI::Broodwar->drawTextMap(BWAPI::Position((PowerTilePosition.x * 32) + 10, (PowerTilePosition.y * 32) + 16), "Power\nPlacement");
333 }
334 }
335 else
336 {
337 BWAPI::Broodwar->drawTextMap(BWAPI::Position((block.getTilePosition().x * 32) + 16, (block.getTilePosition().y * 32) + 16), "Supply\nReserve");
338 }
339
340 if (data.Power_State == BlockData::FULLY_POWERED)
341 {
342 BWAPI::Broodwar->drawBoxMap(BWAPI::Position(block.getTilePosition()), BWAPI::Position((block.getTilePosition().x + block.width()) * 32 + 1, (block.getTilePosition().y + block.height()) * 32 + 1), BWAPI::Colors::Blue, false);
343 }
344 }
345}

◆ findAvailableExpansion()

BWAPI::TilePosition BuildingPlacer::findAvailableExpansion ( )

Checks BWEM expansion locations for possible place to construct resource depot.

Returns
TilePosition to build

Definition at line 154 of file BuildingPlacer.cpp.

155{
156 const BWAPI::TilePosition ProtoBot_MainBase = BWAPI::Broodwar->self()->getStartLocation();
157 const BWEM::Area* mainArea = theMap.GetArea(ProtoBot_MainBase);
158
159 double distance = INT_MAX;
160 double finalDistance;
161 BWAPI::TilePosition closestDistance = BWAPI::TilePositions::Invalid;
162 const BWAPI::UnitType type = BWAPI::UnitTypes::Protoss_Nexus;
163
164 //This does not cover the case of a building being place on a tile but it should be good enough for now.
165 for (const BWEM::Area& area : theMap.Areas())
166 {
167 for (const BWEM::Base& base : area.Bases())
168 {
169 if (base.Location() == BWAPI::Broodwar->self()->getStartLocation() || alreadyUsingTiles(base.Location(), type.tileWidth(), type.tileHeight())) continue;
170
171 int distanceToNewBase = 0;
172 int distanceToEnemy = 0;
173 const BWEM::CPPath pathToExpansion = theMap.GetPath(BWAPI::Position(ProtoBot_MainBase), BWAPI::Position(base.Location()), &distanceToNewBase);
174
175 if (buildReference->commanderReference->enemy().main.has_value())
176 const BWEM::CPPath pathToEnemy = theMap.GetPath(BWAPI::Position(buildReference->commanderReference->enemy().main.value()), BWAPI::Position(base.Location()), &distanceToEnemy);
177
178 if (distanceToNewBase == -1) continue;
179
180 if (distanceToEnemy != 0 && buildReference->commanderReference->enemy().main.value())
181 {
182 finalDistance = static_cast<double>(distanceToNewBase) / distanceToEnemy;
183 }
184 else
185 {
186 finalDistance = static_cast<double>(distanceToNewBase);
187 }
188
189 if (finalDistance < distance)
190 {
191 distance = finalDistance;
192 closestDistance = base.Location();
193 }
194 }
195 }
196
197 return closestDistance;
198}
bool alreadyUsingTiles(BWAPI::TilePosition, int, int, bool assimilator)
Checks if a location to place a building already has another unit ontop of it (will only consider bui...

◆ findAvailableGyser()

BWAPI::TilePosition BuildingPlacer::findAvailableGyser ( const BWEM::Base * base)

Checks a base to place down an assimlator ontop of a vespene gyser.

Parameters
Base (expansion location)
Returns
TilePosition to build

Definition at line 200 of file BuildingPlacer.cpp.

201{
202 //std::cout << "Checking for open gysers\n";
203 BWAPI::TilePosition availableGyser = BWAPI::TilePositions::Invalid;
204
205 if (base != nullptr)
206 {
207 std::vector<BWEM::Geyser*> gysers = base->Geysers();
208
209 for (const BWEM::Geyser* gyser : gysers)
210 {
211 const BWAPI::Unit unit = gyser->Unit();
212
213 if (unit && unit->getType() == BWAPI::UnitTypes::Resource_Vespene_Geyser &&
214 !alreadyUsingTiles(gyser->TopLeft(), unit->getType().tileWidth(), unit->getType().tileHeight(), true))
215 {
216 return gyser->TopLeft();
217 }
218 }
219 }
220 else
221 {
222 for (const BWEM::Area& area : theMap.Areas())
223 {
224 for (const BWEM::Base& base : area.Bases())
225 {
226 if (base.Geysers().size() == 0) continue;
227
228 //Can change this to use the nexus reference
229
230
231 BWAPI::Unitset units = BWAPI::Broodwar->getUnitsInRectangle(BWAPI::Position(base.Location()),
232 BWAPI::Position(32 * (base.Location().x + (BWAPI::UnitTypes::Protoss_Nexus.tileWidth())), 32 * (base.Location().y + (BWAPI::UnitTypes::Protoss_Nexus.tileHeight()))));
233
234 bool nexusOnLocation = false;
235
236 for (const BWAPI::Unit unit : units)
237 {
238 if (unit->getType() == BWAPI::UnitTypes::Protoss_Nexus && unit->getPlayer() == BWAPI::Broodwar->self())
239 {
240 nexusOnLocation = true;
241 break;
242 }
243 }
244
245 //We do not own the base.
246 if (nexusOnLocation == false) continue;
247
248 std::vector<BWEM::Geyser*> gysers = base.Geysers();
249
250 for (const BWEM::Geyser* gyser : gysers)
251 {
252 const BWAPI::Unit unit = gyser->Unit();
253
254 if (unit && unit->getType() == BWAPI::UnitTypes::Resource_Vespene_Geyser &&
255 !alreadyUsingTiles(gyser->TopLeft(), unit->getType().tileWidth(), unit->getType().tileHeight(), true))
256 {
257 return gyser->TopLeft();
258 }
259 }
260 }
261 }
262 }
263
264 return availableGyser;
265}

◆ findAvaliblePlacement()

BWAPI::TilePosition BuildingPlacer::findAvaliblePlacement ( BWAPI::UnitType type)

Standard call for buildings to find a location to be placed other than refineries, resource depots, and supply units.

Parameters
UnitType (building type to be constructed)
Returns
TilePosition to build

Definition at line 268 of file BuildingPlacer.cpp.

269{
270 int distance = INT_MAX;
271 BWAPI::TilePosition closestDistance = BWAPI::TilePositions::Invalid;
272
273 for (BWEB::Block block : ProtoBot_Blocks)
274 {
275 BlockData& data = Block_Information[block.getTilePosition()];
276
277 if (data.Power_State != BlockData::FULLY_POWERED) continue;
278
279 std::set<BWAPI::TilePosition> placements = block.getPlacements(type);
280
281 for (const BWAPI::TilePosition placement : placements)
282 {
283 const int distanceToPlacement = BWAPI::Broodwar->self()->getStartLocation().getApproxDistance(placement);
284
285 if (BWAPI::Broodwar->canBuildHere(placement, type)
286 && distanceToPlacement < distance
287 && !alreadyUsingTiles(placement, type.tileWidth(), type.tileHeight()))
288 {
289 distance = distanceToPlacement;
290 closestDistance = placement;
291 }
292 }
293 }
294
295 return closestDistance;
296}

◆ getPositionToBuild()

PlacementInfo BuildingPlacer::getPositionToBuild ( BWAPI::UnitType type,
const BWEM::Base * base )

Definition at line 363 of file BuildingPlacer.cpp.

364{
365 PlacementInfo information;
366
367 switch(type)
368 {
369 case BWAPI::UnitTypes::Protoss_Nexus:
370 {
371 const BWAPI::TilePosition pos = findAvailableExpansion();
372
373 if (pos == BWAPI::TilePositions::Invalid)
374 {
375 information.flag = PlacementInfo::NO_EXPANSIONS;
376 }
377 else
378 {
379 information.topLeft = pos;
380 information.flag = PlacementInfo::SUCCESS;
381 information.position = BWAPI::Position(pos);
382 }
383 }
384 break;
385 case BWAPI::UnitTypes::Protoss_Assimilator:
386 {
387 const BWAPI::TilePosition pos = findAvailableGyser(base);
388
389 if (pos == BWAPI::TilePositions::Invalid)
390 {
391 information.flag = PlacementInfo::NO_GYSERS;
392 }
393 else
394 {
395 information.topLeft = pos;
396 information.flag = PlacementInfo::SUCCESS;
397 information.position = BWAPI::Position(pos);
398 }
399 }
400 break;
401 case BWAPI::UnitTypes::Protoss_Pylon:
402 {
403 BWAPI::TilePosition powerTilePosition = checkBuildingBlocks();
404
405 if (powerTilePosition == BWAPI::TilePositions::Invalid)
406 {
407 powerTilePosition = checkPowerReserveBlocks();
408
409 if (powerTilePosition == BWAPI::TilePositions::Invalid)
410 {
411 information.flag = PlacementInfo::NO_BLOCKS;
412 }
413 else
414 {
415 information.topLeft = powerTilePosition;
416 information.position = BWAPI::Position(powerTilePosition);
417 information.flag = PlacementInfo::SUCCESS;
418 }
419 }
420 else
421 {
422 information.topLeft = powerTilePosition;
423 information.position = BWAPI::Position(powerTilePosition);
424 information.flag = PlacementInfo::SUCCESS;
425 }
426 }
427 break;
428 default:
429 {
430 const BWAPI::TilePosition pos = findAvaliblePlacement(type);
431
432 if (pos == BWAPI::TilePositions::Invalid)
433 {
434 information.flag = PlacementInfo::NO_PLACEMENTS;
435
436 }
437 else
438 {
439 information.topLeft = pos;
440 information.flag = PlacementInfo::SUCCESS;
441 information.position = BWAPI::Position(pos);
442 }
443 }
444 break;
445 }
446
447 return information;
448}
BWAPI::TilePosition findAvaliblePlacement(BWAPI::UnitType)
Standard call for buildings to find a location to be placed other than refineries,...
BWAPI::TilePosition findAvailableExpansion()
Checks BWEM expansion locations for possible place to construct resource depot.
BWAPI::TilePosition checkBuildingBlocks()
Finda an available Block that has no power in the power tile location.
BWAPI::TilePosition checkPowerReserveBlocks()
Checks Blocks of size 2x2 (tiles) that can be used in order to place down pylons for supply.
BWAPI::TilePosition findAvailableGyser(const BWEM::Base *)
Checks a base to place down an assimlator ontop of a vespene gyser.

◆ numberOfFullPoweredLargePlacements()

int BuildingPlacer::numberOfFullPoweredLargePlacements ( )

Definition at line 347 of file BuildingPlacer.cpp.

348{
349 int poweredLargePlacements = 0;
350
351 for (BWEB::Block block : ProtoBot_Blocks)
352 {
353 BlockData& data = Block_Information[block.getTilePosition()];
354
355 if (data.Power_State != BlockData::FULLY_POWERED) continue;
356
357 poweredLargePlacements += data.Large_Placements;
358 }
359
360 return poweredLargePlacements;
361}

◆ onStart()

void BuildingPlacer::onStart ( )

Update Block information to reflect generated BWEB Blocks and reset values to reflect a beggining game state.

Definition at line 451 of file BuildingPlacer.cpp.

452{
453 mapWidth = BWAPI::Broodwar->mapWidth();
454 mapHeight = BWAPI::Broodwar->mapHeight();
455
456 //poweredTiles.assign(mapHeight, std::vector<int>(mapWidth, 0));
457 Block_Information.clear();
458 AreasOccupied.clear();
459 ProtoBot_Blocks.clear();
460 Area_Blocks.clear();
461 Powered_LargePlacements = 0;
462 Powered_MediumPlacements = 0;
463
464 //Assign main area since we will always own this area at the start of the game
465 const BWAPI::TilePosition ProtoBot_MainBase = BWAPI::Broodwar->self()->getStartLocation();
466 const BWEM::Area* mainArea = theMap.GetArea(ProtoBot_MainBase);
467 AreasOccupied.insert(mainArea);
468
469 std::vector<BWEB::Block> blocks = BWEB::Blocks::getBlocks();
470 int largePlacements = 0;
471 int mediumPlacements = 0;
472 int smallPlacements = 0;
473 nexusCount = 0;
474
475 for (BWEB::Block block : blocks)
476 {
477 //Store this information for later use and save it.
478 BlockData block_info;
479
480 largePlacements = block.getLargeTiles().size();
481 mediumPlacements = block.getMediumTiles().size();
482 smallPlacements = block.getSmallTiles().size();
483
484 //std::cout << "Large Placements = " << largePlacements << "\n";
485 //std::cout << "Medium Placements = " << mediumPlacements << "\n";
486 //std::cout << "Supply Placements = " << smallPlacements << "\n";
487
488 if (largePlacements >= 2)
489 {
490 block_info.Blocksize = BlockData::LARGE;
491
492 //std::cout << "Adding Large Block\n";
493 std::set<BWAPI::TilePosition> powerTiles = block.getSmallTiles();
494 block_info.PowerTiles = powerTiles;
495 //std::cout << "Block power tiles = " << block_info.PowerTiles.size() << "\n";
496 }
497 else if (mediumPlacements != 0 || largePlacements == 1)
498 {
499 block_info.Blocksize = BlockData::MEDIUM;
500
501 //std::cout << "Adding Medium Block\n";
502 std::set<BWAPI::TilePosition> powerTiles = block.getSmallTiles();
503 block_info.PowerTiles = powerTiles;
504 //std::cout << "Block power tiles = " << block_info.PowerTiles.size() << "\n";
505 }
506 else if (mediumPlacements == 0 && largePlacements == 0 && smallPlacements == 1)
507 {
508 //std::cout << "Adding Supply block\n";
509 block_info.Blocksize = BlockData::SUPPLY;
510 }
511
512 block_info.Large_Placements = largePlacements;
513 block_info.Medium_Placements = mediumPlacements;
514 block_info.Power_Placements = smallPlacements;
515 block_info.Block_AreaLocation = theMap.GetArea(block.getTilePosition());
516
517 //std::cout << "Large Placements " << block_info.Large_Placements << "\n";
518 //std::cout << "Medium Placements " << block_info.Medium_Placements << "\n";
519 //std::cout << "Small/Power Placements " << block_info.Power_Placements << "\n";
520
521 const BWEM::Area* blockArea = theMap.GetNearestArea(block.getTilePosition());
522
523 if (blockArea != nullptr)
524 {
525 Area_Blocks[blockArea].push_back(block);
526 }
527 else
528 {
529 //This should happen but just in case.
530 //std::cout << "Uh Oh couldnt find Area\n";
531 }
532
533 //Might have a bug with corners using this approach but hopefully it will be okay using reserving system
534 Block_Information.emplace(block.getTilePosition(), block_info);
535 }
536
537 ProtoBot_Blocks.insert(ProtoBot_Blocks.end(), Area_Blocks[mainArea].begin(), Area_Blocks[mainArea].end());
538}

◆ onUnitComplete()

void BuildingPlacer::onUnitComplete ( BWAPI::Unit unit)

Updates BWEM to reflect the current state of StarCraft game.

Parameters
Unit

Definition at line 547 of file BuildingPlacer.cpp.

548{
549 if (unit->getType() == BWAPI::UnitTypes::Protoss_Nexus && unit->getPlayer() == BWAPI::Broodwar->self())
550 {
551 nexusCount++;
552
553 const BWEM::Area* expandedArea = theMap.GetArea(unit->getTilePosition());
554
555 //If the area is the same no new blocks should be added
556 if (AreasOccupied.find(expandedArea) != AreasOccupied.end()) return;
557
558 AreasOccupied.insert(expandedArea);
559
560 ProtoBot_Blocks.insert(ProtoBot_Blocks.end(), Area_Blocks[expandedArea].begin(), Area_Blocks[expandedArea].end());
561 }
562 else if (unit->getType() == BWAPI::UnitTypes::Protoss_Pylon && unit->getPlayer() == BWAPI::Broodwar->self())
563 {
564 /*const BWAPI::TilePosition location = unit->getTilePosition();
565 const int mapX_location = location.x;
566 const int mapY_location = location.y;
567
568 //Make looping easier we will think of the area a pylon powers as a square. We will then factor in an offset to then get the proper "circle" shape.
569 const int topLeft_x = mapX_location - 7;
570 const int topLeft_y = mapY_location - 4;
571
572 for (int poweredRow_index = topLeft_y; poweredRow_index < topLeft_y + PYLON_POWER_HEIGHT; poweredRow_index++)
573 {
574 for (int poweredColumn_index = topLeft_x; poweredColumn_index < (topLeft_x + PYLON_POWER_WIDTH); poweredColumn_index++)
575 {
576 if (poweredColumn_index >= mapWidth || poweredColumn_index < 0 || poweredRow_index < 0 || poweredRow_index >= mapHeight) continue;
577
578 poweredTiles[poweredRow_index][poweredColumn_index] += 1;
579 }
580 }*/
581
582 for (BWEB::Block block : ProtoBot_Blocks)
583 {
584 BlockData& data = Block_Information[block.getTilePosition()];
585
586 for (const BWAPI::TilePosition powerTile : data.PowerTiles)
587 {
588 if (unit->getTilePosition() == powerTile)
589 {
590 data.Used_Power_Placements++;
591
592 if (data.Used_Power_Placements == data.PowerTiles.size())
593 {
594 data.Power_State = BlockData::FULLY_POWERED;
595 Powered_LargePlacements += data.Large_Placements;
596 Powered_MediumPlacements += data.Medium_Placements;
597 }
598 else
599 {
600 data.Power_State = BlockData::HALF_POWERED;
601 }
602
603 break;
604 }
605 }
606 }
607 }
608}

◆ onUnitCreate()

void BuildingPlacer::onUnitCreate ( BWAPI::Unit unit)

Updates BWEM to reflect the current state of StarCraft game.

Parameters
Unit

Definition at line 540 of file BuildingPlacer.cpp.

541{
542 if (!unit->getType().isBuilding()) return;
543
544 BWEB::Map::addUsed(unit->getTilePosition(), unit->getType());
545}

◆ onUnitDestroy()

void BuildingPlacer::onUnitDestroy ( BWAPI::Unit unit)

Updates BWEM to reflect the current state of StarCraft game.

Parameters
Unit

Definition at line 610 of file BuildingPlacer.cpp.

611{
612 BWEB::Map::onUnitDestroy(unit);
613
614 if (unit->getType() == BWAPI::UnitTypes::Protoss_Nexus && unit->getPlayer() == BWAPI::Broodwar->self())
615 {
616 if (nexusCount > 0) nexusCount--;
617
618 const BWEM::Area* destroyedNexusArea = theMap.GetArea(unit->getTilePosition());
619
620 //Sanity Check
621 if (AreasOccupied.find(destroyedNexusArea) == AreasOccupied.end()) return;
622
623 AreasOccupied.erase(destroyedNexusArea);
624
625 //Make sure this is working correctly.
626 for (std::vector<BWEB::Block>::iterator it = ProtoBot_Blocks.begin(); it != ProtoBot_Blocks.end();)
627 {
628 const BlockData& data = Block_Information[it->getTilePosition()];
629
630 if (data.Block_AreaLocation == destroyedNexusArea)
631 {
632 it = ProtoBot_Blocks.erase(it);
633 }
634 else
635 {
636 it++;
637 }
638 }
639 }
640 else if (unit->getType() == BWAPI::UnitTypes::Protoss_Pylon && unit->getPlayer() == BWAPI::Broodwar->self())
641 {
642 //std::cout << "Pylon destroyed at location: " << unit->getTilePosition() << "\n";
643
644 /*const BWAPI::TilePosition location = unit->getTilePosition();
645 const int mapX_location = location.x;
646 const int mapY_location = location.y;
647
648 //Make looping easier we will think of the area a pylon powers as a square. We will then factor in an offset to then get the proper "circle" shape.
649 const int topLeft_x = mapX_location - 7;
650 const int topLeft_y = mapY_location - 4;
651
652 for (int poweredRow_index = topLeft_y; poweredRow_index < topLeft_y + PYLON_POWER_HEIGHT; poweredRow_index++)
653 {
654 for (int poweredColumn_index = topLeft_x; poweredColumn_index < (topLeft_x + PYLON_POWER_WIDTH); poweredColumn_index++)
655 {
656 if (poweredColumn_index >= mapWidth || poweredColumn_index < 0 || poweredRow_index < 0 || poweredRow_index >= mapHeight) continue;
657
658 poweredTiles[poweredRow_index][poweredColumn_index] -= 1;
659
660 //Sanity check
661 if (poweredTiles[poweredRow_index][poweredColumn_index] < 0)
662 poweredTiles[poweredRow_index][poweredColumn_index] = 0;
663 }
664 }*/
665
666 for (BWEB::Block block : ProtoBot_Blocks)
667 {
668 BlockData& data = Block_Information[block.getTilePosition()];
669
670 for (const BWAPI::TilePosition powerTile : data.PowerTiles)
671 {
672 if (unit->getTilePosition() == powerTile)
673 {
674 data.Used_Power_Placements--;
675
676 if (data.Used_Power_Placements == data.PowerTiles.size())
677 {
678 data.Power_State = BlockData::FULLY_POWERED;
679 }
680 else if(data.Used_Power_Placements == data.PowerTiles.size() / 2)
681 {
682 data.Power_State = BlockData::HALF_POWERED;
683 }
684 else
685 {
686 data.Power_State = BlockData::NOT_POWERED;
687 if (Powered_LargePlacements - data.Large_Placements > 0)
688 {
689 Powered_LargePlacements -= data.Large_Placements;
690 }
691 else
692 {
693 Powered_LargePlacements = 0;
694 }
695
696 if (Powered_MediumPlacements - data.Medium_Placements > 0)
697 {
698 Powered_MediumPlacements -= data.Medium_Placements;
699 }
700 else
701 {
702 Powered_MediumPlacements = 0;
703 }
704
705 }
706
707 break;
708 }
709 }
710 }
711 }
712}

◆ onUnitDiscover()

void BuildingPlacer::onUnitDiscover ( BWAPI::Unit unit)

Updates BWEM to reflect the current state of StarCraft game.

Parameters
Unit

Definition at line 719 of file BuildingPlacer.cpp.

720{
721 BWEB::Map::onUnitDiscover(unit);
722}

◆ onUnitMorph()

void BuildingPlacer::onUnitMorph ( BWAPI::Unit unit)

Updates BWEM to reflect the current state of StarCraft game.

Parameters
Unit

Definition at line 714 of file BuildingPlacer.cpp.

715{
716 BWEB::Map::onUnitMorph(unit);
717}

Member Data Documentation

◆ Area_Blocks

std::unordered_map<const BWEM::Area*, std::vector<BWEB::Block> > BuildingPlacer::Area_Blocks
private

Definition at line 85 of file BuildingPlacer.h.

◆ AreasOccupied

std::unordered_set<const BWEM::Area *> BuildingPlacer::AreasOccupied
private

Definition at line 78 of file BuildingPlacer.h.

◆ Block_Information

std::map<BWAPI::TilePosition, BlockData> BuildingPlacer::Block_Information
private

Definition at line 75 of file BuildingPlacer.h.

◆ buildReference

BuildManager* BuildingPlacer::buildReference

Definition at line 100 of file BuildingPlacer.h.

◆ debug

bool BuildingPlacer::debug = false
private

Definition at line 93 of file BuildingPlacer.h.

◆ mapHeight

int BuildingPlacer::mapHeight = 0
private

Definition at line 88 of file BuildingPlacer.h.

◆ mapWidth

int BuildingPlacer::mapWidth = 0
private

Definition at line 87 of file BuildingPlacer.h.

◆ nexusCount

int BuildingPlacer::nexusCount = 0
private

Definition at line 91 of file BuildingPlacer.h.

◆ Powered_LargePlacements

int BuildingPlacer::Powered_LargePlacements = 0

Definition at line 96 of file BuildingPlacer.h.

◆ Powered_MediumPlacements

int BuildingPlacer::Powered_MediumPlacements = 0

Definition at line 97 of file BuildingPlacer.h.

◆ ProtoBot_Blocks

std::vector<BWEB::Block> BuildingPlacer::ProtoBot_Blocks
private

Definition at line 81 of file BuildingPlacer.h.

◆ Used_LargeBuildingPlacements

int BuildingPlacer::Used_LargeBuildingPlacements

Definition at line 98 of file BuildingPlacer.h.

◆ Used_MediumBuildingPlacements

int BuildingPlacer::Used_MediumBuildingPlacements

Definition at line 99 of file BuildingPlacer.h.


The documentation for this class was generated from the following files: