BWAPI
|
00001 #pragma once 00002 /* 00003 * TacticalBuildingPlacer.cpp 00004 */ 00005 00006 #include <TacticalBuildingPlacer.h> 00007 #include <BWSAL/BFSBuildingPlacer.h> 00008 #include <BWAPI.h> 00009 00010 #include <algorithm> 00011 00012 00013 TacticalBuildingPlacer::TacticalBuildingPlacer() 00014 { 00015 00016 BWTA::BaseLocation * baseLoc; 00017 BWTA::Region * region; 00018 set<BWTA::Chokepoint *> startLocChokepoints; 00019 set<BWTA::Chokepoint *>::iterator cpi; 00020 pair<BWTA::Region *, vector<EnhancedChokepoint>> regionChokepoints; 00021 00022 // get enhanced chokepoints for start location 00023 baseLoc = BWTA::getStartLocation(BWAPI::Broodwar->self()); 00024 region = baseLoc->getRegion(); 00025 startLocChokepoints = region->getChokepoints(); 00026 00027 // set base region 00028 regionChokepoints.first = region; 00029 00030 // set chokepoints for base region 00031 for (cpi = startLocChokepoints.begin(); cpi != startLocChokepoints.end(); ++cpi) { 00032 EnhancedChokepoint ecPoint(*cpi); 00033 regionChokepoints.second.push_back(ecPoint); 00034 } 00035 00036 // save combo 00037 regionsToChokepoints.push_back(regionChokepoints); 00038 00039 // search for build patterns for base region chokepoints 00040 for (int m = 0; m < (int) regionChokepoints.second.size(); ++m) { 00041 vector<BWAPI::TilePosition> cpBuildLocation; 00042 cpBuildLocation = chokepointBuildPatternSearch(regionChokepoints.second[m], regionChokepoints.first); 00043 // save 00044 chokepointBuildLocations.push_back(cpBuildLocation); 00045 } 00046 } 00047 00048 TacticalBuildingPlacer::~TacticalBuildingPlacer(void) 00049 { 00050 } 00051 00052 // search for optimal build pattern to wall off chokepoint in a region 00053 vector<BWAPI::TilePosition> TacticalBuildingPlacer::chokepointBuildPatternSearch( 00054 EnhancedChokepoint ecpoint, BWTA::Region * region) 00055 { 00056 vector<BWAPI::TilePosition> buildTiles; 00057 //vector<BWAPI::TilePosition> currentBuildTiles; 00058 // side A and B 00059 pair<BWAPI::TilePosition, BWAPI::TilePosition> endTiles; 00060 // main tile to search from 00061 BWAPI::TilePosition baseTile; 00062 BWAPI::TilePosition currentTile; 00063 int buildWidth, buildHeight; 00064 const BWAPI::UnitType & depot = BWAPI::UnitTypes::Terran_Supply_Depot; 00065 vector<EnhancedSide> ecpSides; 00066 vector<EnhancedSide> currentSidesNotCovered; 00067 EnhancedSide * ecpSide; 00068 pair<BWAPI::Position, BWAPI::Position> sideEndPoints; 00069 // pixels 00070 int minLengthNotCovered, currentLengthNotCovered; 00071 // tiles 00072 int minTileGapSideA, minTileGapSideB; 00073 int currentTileGapSideA, currentTileGapSideB; 00074 int ecpNumSides; 00075 EnhancedSide::Orientation orientation; 00076 // to extend buildings to the wall 00077 int xGrowDirEndA, yGrowDirEndA; 00078 int xGrowDirEndB, yGrowDirEndB; 00079 // to search for a better fit in a larger space 00080 int xShiftDir, yShiftDir; 00081 // if the end gaps together equal a building 00082 // same as grow dir 00083 // bump by the gap number 00084 //int xBumpDir, yBumpDir; 00085 bool canBuild; 00086 // quickly tell if wall is far away on growth 00087 bool hitMax; 00088 // make sure 2nd direction isn't really bad either 00089 bool hitMaxReverse; 00090 // count growth 00091 int buildCountSideA, buildCountSideB; 00092 // general purpose 00093 int count; 00094 00095 assert(region); 00096 00097 00098 baseTile = ecpoint.getBuildTile(region); 00099 ecpSides = ecpoint.getBoundingBoxSidesForRegion(region); 00100 buildWidth = depot.tileWidth(); 00101 buildHeight = depot.tileHeight(); 00102 ecpNumSides = (int)ecpSides.size(); 00103 00104 // only handles 2 sides 00105 assert(ecpNumSides && ecpNumSides <= 2); 00106 00107 // if sides, search on longest otherwise 00108 // if the 2 sides are equal in length 00109 // you'll almost always have to search in both directions 00110 // one way will have a lot of space and the other way a little 00111 // -- maybe do gap analysis to pick either side? 00112 // nope, as it turns out, one tile of the side can have gap 0 00113 // and another of gap 40 and checkGap() is set up for the min 00114 // TODO: set up gap check for max 00115 // otherwise hitMax check is in place 00116 if (ecpNumSides > 1) { 00117 int size = ecpSides[0].getTilePositions().size(); 00118 int sizeTemp; 00119 ecpSide = &(ecpSides[0]); 00120 for (int m = 1; m < ecpNumSides; ++m) { 00121 if ((sizeTemp = (int)ecpSides[m].getTilePositions().size()) > size) { 00122 size = sizeTemp; 00123 ecpSide = &(ecpSides[m]); 00124 } 00125 else if (sizeTemp == size) { 00126 // gap analysis for 4 sides of the build area from baseTile 00127 // if left (A) and right have min, then pick horizontal side 00128 // if top (A) and bottom have min, then pick vertical side 00129 // left side 00130 sideEndPoints.first.x() = baseTile.x() * 32; 00131 sideEndPoints.first.y() = baseTile.y() * 32; 00132 sideEndPoints.second.x() = sideEndPoints.first.x(); 00133 sideEndPoints.second.y() = ((baseTile.y() + buildHeight) * 32) - 1; 00134 EnhancedSide left(sideEndPoints, EnhancedSide::left); 00135 minTileGapSideA = left.checkGap(); 00136 // right side 00137 sideEndPoints.first.x() = ((baseTile.x() + buildWidth) * 32) - 1; 00138 sideEndPoints.first.y() = baseTile.y() * 32; 00139 sideEndPoints.second.x() = sideEndPoints.first.x(); 00140 sideEndPoints.second.y() = ((baseTile.y() + buildHeight) * 32) - 1; 00141 EnhancedSide right(sideEndPoints, EnhancedSide::right); 00142 minTileGapSideB = right.checkGap(); 00143 // top side 00144 sideEndPoints.first.x() = baseTile.x() * 32; 00145 sideEndPoints.first.y() = baseTile.y() * 32; 00146 sideEndPoints.second.x() = ((baseTile.x() + buildWidth) * 32) - 1; 00147 sideEndPoints.second.y() = sideEndPoints.first.y(); 00148 EnhancedSide top(sideEndPoints, EnhancedSide::top); 00149 currentTileGapSideA = top.checkGap(); 00150 // bottom side 00151 sideEndPoints.first.x() = baseTile.x() * 32; 00152 sideEndPoints.first.y() = ((baseTile.y() + buildHeight) * 32) - 1; 00153 sideEndPoints.second.x() = ((baseTile.x() + buildWidth) * 32) - 1; 00154 sideEndPoints.second.y() = sideEndPoints.first.y(); 00155 EnhancedSide bottom(sideEndPoints, EnhancedSide::bottom); 00156 currentTileGapSideB = bottom.checkGap(); 00157 // pick horizontal side 00158 if (minTileGapSideA + minTileGapSideB > currentTileGapSideA + currentTileGapSideB) { 00159 if (ecpSides[0].isHorizontal()) { 00160 ecpSide = &(ecpSides[0]); 00161 } 00162 else { 00163 ecpSide = &(ecpSides[1]); 00164 } 00165 } 00166 else { 00167 if (!ecpSides[0].isHorizontal()) { 00168 ecpSide = &(ecpSides[0]); 00169 } 00170 else { 00171 ecpSide = &(ecpSides[1]); 00172 } 00173 } 00174 } 00175 } 00176 } 00177 else { 00178 ecpSide = &(ecpSides[0]); 00179 } 00180 00181 // get direction from orientation 00182 // grow by buildWidth or buildHeight 00183 // shift by one tile 00184 orientation = ecpSide->getOrientation(); 00185 if (orientation == EnhancedSide::left) { 00186 // A is top end 00187 xGrowDirEndA = 0; 00188 yGrowDirEndA = -1; 00189 xGrowDirEndB = 0; 00190 yGrowDirEndB = +1; 00191 xShiftDir = -1; 00192 yShiftDir = 0; 00193 } 00194 else if (orientation == EnhancedSide::top) { 00195 // A is left end 00196 xGrowDirEndA = -1; 00197 yGrowDirEndA = 0; 00198 xGrowDirEndB = +1; 00199 yGrowDirEndB = 0; 00200 xShiftDir = 0; 00201 yShiftDir = -1; 00202 } 00203 else if (orientation == EnhancedSide::right) { 00204 // A is top end 00205 xGrowDirEndA = 0; 00206 yGrowDirEndA = -1; 00207 xGrowDirEndB = 0; 00208 yGrowDirEndB = +1; 00209 xShiftDir = +1; 00210 yShiftDir = 0; 00211 } 00212 else if (orientation == EnhancedSide::bottom) { 00213 // A is left end 00214 xGrowDirEndA = -1; 00215 yGrowDirEndA = 0; 00216 xGrowDirEndB = +1; 00217 yGrowDirEndB = 0; 00218 xShiftDir = 0; 00219 yShiftDir = +1; 00220 } 00221 00222 // search for optimal build pattern which has 00223 // complete coverage and no gap, if that can't 00224 // be achieved, then return best fit 00225 00226 // start with base tile 00227 endTiles.first = endTiles.second = baseTile; 00228 // see if either side builds out too far 00229 hitMax = false; 00230 00231 // try to grow on either end 00232 // set growth limit of 4 on either end 00233 // then check for hit max 00234 00235 // grow end A 00236 currentTile = baseTile; 00237 canBuild = true; 00238 buildCountSideA = 0; 00239 00240 while (canBuild && buildCountSideA < 5) { 00241 currentTile.x() += xGrowDirEndA * buildWidth; 00242 currentTile.y() += yGrowDirEndA * buildHeight; 00243 00244 if (BWAPI::Broodwar->canBuildHere(NULL, currentTile, BWAPI::UnitTypes::Terran_Supply_Depot, false)) { 00245 endTiles.first = currentTile; 00246 buildCountSideA++; 00247 } 00248 else { 00249 canBuild = false; 00250 break; 00251 } 00252 } 00253 00254 // grow end B 00255 currentTile = baseTile; 00256 canBuild = true; 00257 buildCountSideB = 0; 00258 00259 while (canBuild && buildCountSideB < 5) { 00260 currentTile.x() += xGrowDirEndB * buildWidth; 00261 currentTile.y() += yGrowDirEndB * buildHeight; 00262 00263 if (BWAPI::Broodwar->canBuildHere(NULL, currentTile, BWAPI::UnitTypes::Terran_Supply_Depot, false)) { 00264 endTiles.second = currentTile; 00265 buildCountSideB++; 00266 } 00267 else { 00268 canBuild = false; 00269 break; 00270 } 00271 } 00272 00273 // good indication need to search in other direction 00274 // build counts don't usually count the baseTile, 00275 // since they are searching out from it, so >3 is 00276 // really >4 00277 if (buildCountSideA + buildCountSideB > 3) { 00278 hitMax = true; 00279 } 00280 00281 // regrow in other direction if hitMax before analysis 00282 // ie if horizontal, do vertical 00283 if (hitMax) { 00284 // leaving out shift dir, since that is unknown now 00285 if (ecpSide->isHorizontal()) { 00286 xGrowDirEndA = 0; 00287 yGrowDirEndA = -1; 00288 xGrowDirEndB = 0; 00289 yGrowDirEndB = +1; 00290 } 00291 else { 00292 xGrowDirEndA = -1; 00293 yGrowDirEndA = 0; 00294 xGrowDirEndB = +1; 00295 yGrowDirEndB = 0; 00296 } 00297 00298 // start with base tile 00299 endTiles.first = endTiles.second = baseTile; 00300 hitMaxReverse = false; 00301 00302 // now regrow end A 00303 currentTile = baseTile; 00304 canBuild = true; 00305 buildCountSideA = 0; 00306 while (canBuild && buildCountSideA < 5) { 00307 currentTile.x() += xGrowDirEndA * buildWidth; 00308 currentTile.y() += yGrowDirEndA * buildHeight; 00309 if (BWAPI::Broodwar->canBuildHere(NULL, currentTile, BWAPI::UnitTypes::Terran_Supply_Depot, false)) { 00310 endTiles.first = currentTile; 00311 buildCountSideA++; 00312 } 00313 else { 00314 canBuild = false; 00315 break; 00316 } 00317 } 00318 // regrow end B 00319 currentTile = baseTile; 00320 canBuild = true; 00321 buildCountSideB = 0; 00322 while (canBuild && buildCountSideB < 5) { 00323 currentTile.x() += xGrowDirEndB * buildWidth; 00324 currentTile.y() += yGrowDirEndB * buildHeight; 00325 if (BWAPI::Broodwar->canBuildHere(NULL, currentTile, BWAPI::UnitTypes::Terran_Supply_Depot, false)) { 00326 endTiles.second = currentTile; 00327 buildCountSideB++; 00328 } 00329 else { 00330 canBuild = false; 00331 break; 00332 } 00333 } 00334 if (buildCountSideA + buildCountSideB > 3) { 00335 hitMaxReverse = true; 00336 } 00337 } // end hitMax regrow 00338 00339 00340 // check coverage and gap based on side ends 00341 // Note: currently gap tests are only done for 00342 // the side ends (the short ends), not the long ends 00343 // so this won't cover the case where there is still room 00344 // on either side of the side ends, but there isn't a gap on 00345 // the long edge, so the chokepoint is still walled off, 00346 // however this case will still come out as complete coverage 00347 // so coverage is more for the special cases 00348 if ((ecpSide->isHorizontal() && !hitMax) || (!ecpSide->isHorizontal() && hitMax)) { 00349 // ------------- 00350 //A | | | | B 00351 // left to right, top or bottom side doesn't matter 00352 // get from endTiles, far left 00353 sideEndPoints.first.x() = endTiles.first.x() * 32; 00354 sideEndPoints.first.y() = endTiles.first.y() * 32; 00355 // get from endTiles, far right 00356 sideEndPoints.second.x() = ((endTiles.second.x() + buildWidth) * 32) - 1; 00357 sideEndPoints.second.y() = sideEndPoints.first.y(); // same 00358 // check coverage 00359 EnhancedSide coveringSide(sideEndPoints, EnhancedSide::top); 00360 currentSidesNotCovered.clear(); 00361 currentLengthNotCovered = ecpSide->checkCoverage(coveringSide, ¤tSidesNotCovered); 00362 00363 // check side A gap 00364 // first end point is still good from coverage 00365 sideEndPoints.second.x() = sideEndPoints.first.x(); // same 00366 sideEndPoints.second.y() = sideEndPoints.first.y() + (buildHeight * 32) - 1; 00367 EnhancedSide buildSideA(sideEndPoints, EnhancedSide::left); 00368 currentTileGapSideA = buildSideA.checkGap(); 00369 00370 00371 // check side B gap 00372 sideEndPoints.first.x() = ((endTiles.second.x() + buildWidth) * 32) - 1; 00373 // sideEndPoints.first.y() same 00374 sideEndPoints.second.x() = sideEndPoints.first.x(); // same 00375 // sideEndPoints.second.y() same 00376 EnhancedSide buildSideB(sideEndPoints, EnhancedSide::right); 00377 currentTileGapSideB = buildSideB.checkGap(); 00378 } 00379 else if ( (!hitMax) || (ecpSide->isHorizontal() && hitMax) ){ 00380 00381 // A 00382 // --- 00383 // | 00384 // --- 00385 // | 00386 // --- 00387 // | 00388 // --- 00389 // B 00390 // get left side and compare for coverage 00391 // endTile A (first) is top 00392 sideEndPoints.first.x() = endTiles.first.x() * 32; 00393 sideEndPoints.first.y() = endTiles.first.y() * 32; 00394 // get from endTiles, far bottom 00395 sideEndPoints.second.x() = sideEndPoints.first.x(); // same 00396 sideEndPoints.second.y() = ((endTiles.second + buildHeight) * 32) - 1; 00397 // check coverage 00398 EnhancedSide coveringSide(sideEndPoints, EnhancedSide::left); 00399 currentSidesNotCovered.clear(); 00400 currentLengthNotCovered = ecpSide->checkCoverage(coveringSide, ¤tSidesNotCovered); 00401 00402 // check side A gap 00403 // first end point is still good from coverage 00404 sideEndPoints.second.x() = sideEndPoints.first.x() + (buildWidth * 32) - 1; 00405 sideEndPoints.second.y() = sideEndPoints.first.y(); // same 00406 EnhancedSide buildSideA(sideEndPoints, EnhancedSide::top); 00407 currentTileGapSideA = buildSideA.checkGap(); 00408 00409 // check side B gap 00410 // sideEndPoints.first.x() same 00411 sideEndPoints.first.y() = ((endTiles.second + buildHeight) * 32) - 1; 00412 // sideEndPoints.second.x() same 00413 sideEndPoints.second.y() = sideEndPoints.first.y(); // same 00414 EnhancedSide buildSideB(sideEndPoints, EnhancedSide::bottom); 00415 currentTileGapSideB = buildSideB.checkGap(); 00416 } 00417 00418 // save round -- need to do some error checking here 00419 currentTile = endTiles.first; 00420 count = 0; 00421 while (currentTile != endTiles.second) { 00422 buildTiles.push_back(currentTile); 00423 currentTile.x() += xGrowDirEndB * buildWidth; 00424 currentTile.y() += yGrowDirEndB * buildHeight; 00425 count++; 00426 // check for overrun 00427 if (count > 10) { 00428 break; 00429 } 00430 } 00431 buildTiles.push_back(endTiles.second); 00432 00433 // analyze coverage and side gaps 00434 // if both are zero, done! 00435 // make sure size isn't over 4, otherwise this may not be a good solution 00436 if (currentLengthNotCovered < 32 && currentTileGapSideA + currentTileGapSideB == 0) { 00437 if (buildTiles.size() < 5) { 00438 return buildTiles; 00439 } 00440 else { 00441 buildTiles.clear(); 00442 buildTiles.push_back(baseTile); 00443 return buildTiles; 00444 } 00445 } 00446 00447 // if first round set mins to current 00448 minLengthNotCovered = currentLengthNotCovered; 00449 minTileGapSideA = currentTileGapSideA; 00450 minTileGapSideB = currentTileGapSideB; 00451 00452 // check to see if bumping the set by 1 or 2 tiles 00453 // will open up another build position and close the gap 00454 // if horizontal, look for gap total of 3 00455 // if vertical, look for gap total of 2 (1 on either side) 00456 if ((ecpSide->isHorizontal() && minTileGapSideA + minTileGapSideB == buildWidth) || 00457 (!ecpSide->isHorizontal() && minTileGapSideA + minTileGapSideB == buildHeight)) { 00458 // shift left 1 or 2 tiles and try to grow the right side 00459 currentTile.x() = endTiles.first.x() - minTileGapSideA; 00460 if (BWAPI::Broodwar->canBuildHere(NULL, currentTile, BWAPI::UnitTypes::Terran_Supply_Depot, false)) { 00461 endTiles.first = currentTile; 00462 // keep going and grow end B 00463 canBuild = true; 00464 buildCountSideB = 0; 00465 00466 while (canBuild && buildCountSideB < 4) { 00467 currentTile.x() += xGrowDirEndB * buildWidth; 00468 currentTile.y() += yGrowDirEndB * buildHeight; 00469 00470 if (BWAPI::Broodwar->canBuildHere(NULL, currentTile, BWAPI::UnitTypes::Terran_Supply_Depot, false)) { 00471 endTiles.second = currentTile; 00472 buildCountSideB++; 00473 } 00474 else { 00475 canBuild = false; 00476 break; 00477 } 00478 } 00479 } 00480 } 00481 00482 // check for gap improvement after bumping 00483 00484 if (ecpSide->isHorizontal()) { 00485 // check side A gap 00486 sideEndPoints.first.x() = endTiles.first.x() * 32; 00487 sideEndPoints.first.y() = endTiles.first.y() * 32; 00488 sideEndPoints.second.x() = sideEndPoints.first.x(); // same 00489 sideEndPoints.second.y() = sideEndPoints.first.y() + (buildHeight * 32) - 1; 00490 EnhancedSide buildSideA(sideEndPoints, EnhancedSide::left); 00491 currentTileGapSideA = buildSideA.checkGap(); 00492 00493 // check side B gap 00494 sideEndPoints.first.x() = ((endTiles.second.x() + buildWidth) * 32) - 1; 00495 // sideEndPoints.first.y() same 00496 sideEndPoints.second.x() = sideEndPoints.first.x(); // same 00497 // sideEndPoints.second.y() same 00498 EnhancedSide buildSideB(sideEndPoints, EnhancedSide::right); 00499 currentTileGapSideB = buildSideB.checkGap(); 00500 } 00501 else { 00502 // check side A gap 00503 sideEndPoints.first.x() = endTiles.first.x() * 32; 00504 sideEndPoints.first.y() = endTiles.first.y() * 32; 00505 sideEndPoints.second.x() = sideEndPoints.first.x() + (buildWidth * 32) - 1; 00506 sideEndPoints.second.y() = sideEndPoints.first.y(); // same 00507 EnhancedSide buildSideA(sideEndPoints, EnhancedSide::top); 00508 currentTileGapSideA = buildSideA.checkGap(); 00509 00510 // check side B gap 00511 // sideEndPoints.first.x() same 00512 sideEndPoints.first.y() = ((endTiles.second + buildHeight) * 32) - 1; 00513 // sideEndPoints.second.x() same 00514 sideEndPoints.second.y() = sideEndPoints.first.y(); // same 00515 EnhancedSide buildSideB(sideEndPoints, EnhancedSide::bottom); 00516 currentTileGapSideB = buildSideB.checkGap(); 00517 } 00518 00519 if (currentTileGapSideA + currentTileGapSideB < minTileGapSideA + minTileGapSideB) { 00520 00521 // save new round 00522 buildTiles.clear(); 00523 currentTile = endTiles.first; 00524 count = 0; 00525 while (currentTile != endTiles.second) { 00526 buildTiles.push_back(currentTile); 00527 currentTile.x() += xGrowDirEndB * buildWidth; 00528 currentTile.y() += yGrowDirEndB * buildHeight; 00529 count++; 00530 // check for overrun, these tiles will then be thrown out 00531 // in the size check 00532 if (count > 10) { 00533 break; 00534 } 00535 } 00536 buildTiles.push_back(endTiles.second); 00537 00538 00539 00540 // NEED TO DO COVERAGE ANALYSIS AND 00541 // SET LENGTH NOT COVERED AND MIN TILE GAPS 00542 } 00543 00544 // -- get this section working first 00545 00546 // try to shift and then grow again 00547 00548 // compare coverage and gap 00549 00550 // if still not optimal, try opposite direction 00551 00552 // if still not optimal, try staggered pattern 00553 00554 // ensure size isn't to big 00555 if (buildTiles.size() < 5) { 00556 return buildTiles; 00557 } 00558 else { 00559 buildTiles.clear(); 00560 buildTiles.push_back(baseTile); 00561 } 00562 00563 return buildTiles; 00564 } 00565 00566 void TacticalBuildingPlacer::analyze(void) 00567 { 00568 00569 00570 } 00571 00572 void TacticalBuildingPlacer::draw(void) 00573 { 00574 BWTA::Region * region; 00575 vector<EnhancedChokepoint> * chokepoints; 00576 EnhancedUI * eui = new EnhancedUI(); 00577 const BWAPI::UnitType & depot = BWAPI::UnitTypes::Terran_Supply_Depot; 00578 00579 for (int m = 0; m < (int) regionsToChokepoints.size(); ++m) { 00580 00581 region = regionsToChokepoints[m].first; 00582 chokepoints = ®ionsToChokepoints[m].second; 00583 00584 /* draw for enhanced chokepoints */ 00585 for (int x = 0; x < (int) chokepoints->size(); ++x) { 00586 /* draw tiles for the sides and center of chokepoint line */ 00587 chokepoints[0][x].drawTilePositions(); 00588 /* leave out for now, sides can be hard to see with this on */ 00589 //ecPoints[x].drawBoundingBox(); 00590 chokepoints[0][x].drawBoundingBoxSidesForRegion(region, BWAPI::Colors::Red); 00591 chokepoints[0][x].drawBuildableTilesForRegion(region, BWAPI::Colors::White); 00592 //chokepoints[0][x].drawBuildableSupplyDepotForRegion(region, BWAPI::Colors::Cyan); 00593 } 00594 } 00595 00596 // draw for chokepointBuildPatternSearch() return 00597 for (int m = 0; m < (int)chokepointBuildLocations.size(); ++m) { 00598 for (int n = 0; n < (int)chokepointBuildLocations[m].size(); ++n) { 00599 eui->drawBoxAtTilePositionToSize(chokepointBuildLocations[m][n], depot.tileWidth(), 00600 depot.tileHeight(), BWAPI::Colors::Cyan); 00601 } 00602 } 00603 00604 // clean up 00605 delete(eui); 00606 } 00607 00608 // draw reserved tiles 00609 void TacticalBuildingPlacer::update(void) 00610 { 00611 for (int x = 0; x < BWAPI::Broodwar->mapWidth(); x++) 00612 for (int y = 0; y < BWAPI::Broodwar->mapHeight(); y++) 00613 if (BWSAL::ReservedMap::getInstance()->isReserved(x, y)) 00614 BWAPI::Broodwar->drawBoxMap(x*32, y*32, x*32+31, y*32+31, BWAPI::Colors::Red); 00615 } 00616 00617 BWAPI::TilePosition TacticalBuildingPlacer::reserveBuildLocation(BWAPI::UnitType unitType, BWAPI::TilePosition seedLocation, BWAPI::Unit *builder) 00618 { 00619 BWAPI::TilePosition loc; 00620 00621 // Find a default location first 00622 loc = buildingPlacer.findBuildLocation(BWSAL::ReservedMap::getInstance(), unitType, seedLocation, builder); 00623 00624 // special build case for refineries 00625 if (unitType == BWAPI::UnitTypes::Terran_Refinery) { 00626 // hardcode for now, for start location 00627 BWTA::BaseLocation * baseLoc; 00628 baseLoc = BWTA::getStartLocation(BWAPI::Broodwar->self()); 00629 // geysers per base location 00630 set<BWAPI::Unit*> geysers = baseLoc->getGeysers(); 00631 // should only be one ? 00632 for(std::set<BWAPI::Unit*>::const_iterator j=geysers.begin(); j != geysers.end(); ++j) { 00633 loc =(*j)->getTilePosition(); 00634 break; 00635 } 00636 } 00637 // Expansions 00638 else if (unitType == BWAPI::UnitTypes::Terran_Command_Center) 00639 { 00640 double minDist = 9999999; 00641 set<BWTA::BaseLocation*> expansions = BWTA::getBaseLocations(); 00642 for (set<BWTA::BaseLocation*>::iterator it = expansions.begin(); it != expansions.end(); it++) 00643 { 00644 double dist = (*it)->getGroundDistance(BWTA::getStartLocation(BWAPI::Broodwar->self())); 00645 if (dist < minDist && 00646 dist > 200) // Don't rebuild at our start location 00647 { 00648 minDist = dist; 00649 loc = (*it)->getTilePosition(); 00650 } 00651 } 00652 00653 } 00654 BWSAL::ReservedMap::getInstance()->reserveTiles(loc, unitType, unitType.tileWidth(), unitType.tileHeight()); 00655 00656 return loc; 00657 }