BWAPI
BasicAIModule/source/TacticalBuildingPlacer.cpp
Go to the documentation of this file.
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, &currentSidesNotCovered);
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, &currentSidesNotCovered);
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 = &regionsToChokepoints[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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines