/* creates the unit type specified in the build order item */ void ProductionManager::createUnit(BuildOrderItem<PRIORITY_TYPE> element) { BWAPI::Unit* structure; bool addon = false; //check that we can afford to train the new unit if((Broodwar->self()->minerals() >= element.metaType.mineralPrice()) && (Broodwar->self()->gas() >= element.metaType.gasPrice())) { for(std::map<UnitType, int>::const_iterator i = element.metaType.unitType.requiredUnits().begin(); i != element.metaType.unitType.requiredUnits().end(); i++) { if((*i).first.isAddon() && element.metaType.whatBuilds().canBuildAddon()) { addon = true; } } if(addon) { structure = getBuilding(element.metaType.whatBuilds(), addon); } else { structure = getBuilding(element.metaType.whatBuilds()); } if(structure != NULL && structure->isCompleted()) { structure->train(element.metaType.unitType); } } }
// get the attack priority of a type in relation to a zergling int LurkerManager::getAttackPriority(BWAPI::Unit LurkerUnit, BWAPI::Unit target) { BWAPI::UnitType LurkerType = LurkerUnit->getType(); BWAPI::UnitType targetType = target->getType(); bool isThreat = LurkerType.isFlyer() ? targetType.airWeapon() != BWAPI::WeaponTypes::None : targetType.groundWeapon() != BWAPI::WeaponTypes::None; if (target->getType().isWorker()) { isThreat = false; } if (target->getType() == BWAPI::UnitTypes::Zerg_Larva || target->getType() == BWAPI::UnitTypes::Zerg_Egg) { return 0; } // if the target is building something near our base something is fishy BWAPI::Position ourBasePosition = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()); if (target->getType().isWorker() && (target->isConstructing() || target->isRepairing()) && target->getDistance(ourBasePosition) < 1200) { return 100; } if (target->getType().isBuilding() && (target->isCompleted() || target->isBeingConstructed()) && target->getDistance(ourBasePosition) < 1200) { return 90; } // highest priority is something that can attack us or aid in combat if (targetType == BWAPI::UnitTypes::Terran_Bunker || isThreat) { return 11; } // next priority is worker else if (targetType.isWorker()) { return 11; } // next is special buildings else if (targetType == BWAPI::UnitTypes::Protoss_Pylon) { return 5; } // next is buildings that cost gas else if (targetType.gasPrice() > 0) { return 4; } else if (targetType.mineralPrice() > 0) { return 3; } // then everything else else { return 50; } }
/* starts the upgrade specified in the build order item */ void ProductionManager::startUpgrade(BuildOrderItem<PRIORITY_TYPE> element) { BWAPI::Unit* structure; structure = getBuilding(element.metaType.whatBuilds()); if(structure != NULL && structure->isCompleted()) { structure->upgrade(element.metaType.upgradeType); removeElement(); } else { Broodwar->printf("ProductionManager Error: No structure available to research '%s'", element.metaType.getName().c_str()); } }
bool UnitUtil::IsValidUnit(BWAPI::Unit unit) { if (!unit) { return false; } if (unit->isCompleted() && unit->getHitPoints() > 0 && unit->exists() && unit->getType() != BWAPI::UnitTypes::Unknown && unit->getPosition().x != BWAPI::Positions::Unknown.x && unit->getPosition().y != BWAPI::Positions::Unknown.y) { return true; } else { return false; } }
int InterceptorManager::getPriorityDefault(BWAPI::Unit rangedUnit, BWAPI::Unit target) { BWAPI::UnitType rangedType = rangedUnit->getType(); BWAPI::UnitType targetType = target->getType(); if (target->getType() == BWAPI::UnitTypes::Protoss_Photon_Cannon || target->getType() == BWAPI::UnitTypes::Zerg_Sunken_Colony) { return 8; } if (rangedUnit->getType() == BWAPI::UnitTypes::Zerg_Scourge) { if (target->getType() == BWAPI::UnitTypes::Protoss_Carrier) { return 100; } if (target->getType() == BWAPI::UnitTypes::Protoss_Corsair) { return 90; } } bool isThreat = rangedType.isFlyer() ? targetType.airWeapon() != BWAPI::WeaponTypes::None : targetType.groundWeapon() != BWAPI::WeaponTypes::None; if (target->getType().isWorker()) { isThreat = false; } if (target->getType() == BWAPI::UnitTypes::Zerg_Larva || target->getType() == BWAPI::UnitTypes::Zerg_Egg) { return 0; } if (rangedUnit->isFlying() && target->getType() == BWAPI::UnitTypes::Protoss_Carrier) { return 101; } // if the target is building something near our base something is fishy BWAPI::Position ourBasePosition = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()); if (target->getType().isWorker() && (target->isConstructing() || target->isRepairing()) && target->getDistance(ourBasePosition) < 1200) { return 100; } if (target->getType().isBuilding() && (target->isCompleted() || target->isBeingConstructed()) && target->getDistance(ourBasePosition) < 1200) { return 90; } // highest priority is something that can attack us or aid in combat if (targetType == BWAPI::UnitTypes::Terran_Bunker || isThreat) { return 11; } // next priority is worker else if (targetType.isWorker()) { if (rangedUnit->getType() == BWAPI::UnitTypes::Terran_Vulture) { return 11; } return 11; } // next is special buildings else if (targetType == BWAPI::UnitTypes::Zerg_Spawning_Pool) { return 5; } // next is special buildings else if (targetType == BWAPI::UnitTypes::Protoss_Pylon) { return 5; } // next is buildings that cost gas else if (targetType.gasPrice() > 0) { return 4; } else if (targetType.mineralPrice() > 0) { return 3; } // then everything else else { return 1; } }
void ConstructionManager::update() { std::set<BWAPI::Unit*> myPlayerUnits = SelectAll()(isCompleted)(GetAddon,(BWAPI::Unit*)NULL).not(isCarryingMinerals,isCarryingGas,isGatheringGas); //iterate through all the builder types for(std::map<BWAPI::UnitType,std::set<Building*> >::iterator i=this->buildingsNeedingBuilders.begin();i!=this->buildingsNeedingBuilders.end();i++) { if (!i->second.empty()) //if its empty, we don't really need builders of this type { for(std::set<BWAPI::Unit*>::iterator u = myPlayerUnits.begin(); u != myPlayerUnits.end(); u++) { //if this unit is completed and the right type, and doesn't have an addon, and we aren't already using it if ((*u)->getType()==i->first && this->builders.find(*u)==this->builders.end()) { //bid value depends on distance - we like closer builders better double min_dist=1000000; for(std::set<Building*>::iterator b = i->second.begin(); b != i->second.end(); b++) { double dist = (*u)->getPosition().getDistance((*b)->position); if (dist < min_dist) min_dist = dist; } if (min_dist < 10) min_dist = 10; if (min_dist > 256*32 + 10) min_dist = 256*32 + 10; double bid = 80 - (min_dist - 10)/(256*32)*60; //if this isn't a worker, we don't care about distance if (!(*u)->getType().isWorker()) arbitrator->setBid(this, *u, 80); else arbitrator->setBid(this, *u, bid); } } } } std::list<Building>::iterator i_next; int index=0; //iterate through all the incomplete buildings for(std::list<Building>::iterator i=this->incompleteBuildings.begin();i!=this->incompleteBuildings.end();i=i_next) { index++; i_next=i; i_next++; Building* b = &(*i); if (!b->started && b->buildingUnit!=NULL) //buildingUnit exists, so we've started actual construction { startedCount[b->type]++; b->started=true; } if (b->type.isAddon()) //if the type is an addon { if (b->builderUnit!=NULL) b->buildingUnit=b->builderUnit->getAddon(); //set buildingUnit to the addon (whether the addon exists or not) BWAPI::Unit* u = b->builderUnit; BWAPI::Unit* s = b->buildingUnit; if (s!=NULL && s->isCompleted()) //if the building exists and is completed { startedCount[b->type]--; plannedCount[b->type]--; if (u != NULL) { this->builders.erase(u); arbitrator->removeBid(this,u); } this->placer->freeTiles(b->tilePosition, 4,3); this->placer->freeTiles(b->tilePosition+BWAPI::TilePosition(4,1), 2,2); //If the building is complete, we can forget about it. this->incompleteBuildings.erase(i); } else //building either does not exist, or is incomplete { if (BWAPI::Broodwar->canMake(NULL,b->type)) { if (u == NULL) //if we don't have a builder, ask for one and wait for it to be offered buildingsNeedingBuilders[*b->type.whatBuilds().first].insert(b); else { if (u->getAddon() == NULL) //if the addon does not exist yet { if (u->isLifted()) //if the builder is lifted, find somehwere to land { if (BWAPI::Broodwar->getFrameCount()>b->lastOrderFrame+BWAPI::Broodwar->getLatency()*2) { if (!this->placer->canBuildHereWithSpace(b->tilePosition,b->type)) { this->placer->freeTiles(b->tilePosition, 4,3); this->placer->freeTiles(b->tilePosition+BWAPI::TilePosition(4,1), 2,2); b->tilePosition=placer->getBuildLocationNear(b->tilePosition,*b->type.whatBuilds().first); this->placer->reserveTiles(b->tilePosition, 4,3); this->placer->reserveTiles(b->tilePosition+BWAPI::TilePosition(4,1), 2,2); } u->land(b->tilePosition); b->lastOrderFrame = BWAPI::Broodwar->getFrameCount(); } } else { if (u->isTraining()) //if the builder is training, cancel it - we have control over the builder { u->cancelTrain(); } else { if (u->getTilePosition()!=b->tilePosition) //we may need to lift to find a build site with enough space for an add-on { //b->tilePosition is set in onOffer() u->lift(); b->lastOrderFrame = BWAPI::Broodwar->getFrameCount(); } else //otherwise, we may be in a good spot to make the add-on { //check to see if we can build here bool buildable=true; for(int x=b->tilePosition.x()+4;x<b->tilePosition.x()+6;x++) for(int y=b->tilePosition.y()+1;y<b->tilePosition.y()+3;y++) if (!this->placer->buildable(x,y) || BWAPI::Broodwar->hasCreep(x,y)) buildable=false; if (buildable) //if so, start making the add-on { u->buildAddon(b->type); } else { //otherwise, lift up (once we are lifted we will look for a valid spot to land and build) u->lift(); b->lastOrderFrame = BWAPI::Broodwar->getFrameCount(); } } } } } } } } } else //if the type is a normal building (not an addon) { if (b->tilePosition==BWAPI::TilePositions::None) //if we don't have a build location yet { if ((BWAPI::Broodwar->getFrameCount()+index)%25==0) { //get a build location near the goal position b->tilePosition = this->placer->getBuildLocationNear(b->goalPosition, b->type); if (b->tilePosition!=BWAPI::TilePositions::None) { b->position = BWAPI::Position(b->tilePosition.x()*32 + b->type.tileWidth()*16, b->tilePosition.y()*32 + b->type.tileHeight()*16); this->placer->reserveTiles(b->tilePosition, b->type.tileWidth(), b->type.tileHeight()); } } //if we didn't find a build location yet, or cannot make the building, skip this building for now if (b->tilePosition==BWAPI::TilePositions::None) continue; } //if the builder dies, set it to null if (b->builderUnit!=NULL && !b->builderUnit->exists()) b->builderUnit=NULL; //if the building dies, or isn't the right type, set it to null if (b->buildingUnit!=NULL && (!b->buildingUnit->exists() || b->buildingUnit->getType()!=b->type)) b->buildingUnit=NULL; if (b->buildingUnit == NULL) //if we don't have a building yet, look for it { //look at the units on the tile to see if it exists yet std::set<BWAPI::Unit*> unitsOnTile = BWAPI::Broodwar->unitsOnTile(b->tilePosition.x(), b->tilePosition.y()); for(std::set<BWAPI::Unit*>::iterator t = unitsOnTile.begin(); t != unitsOnTile.end(); t++) if ((*t)->getType() == b->type && !(*t)->isLifted()) { //we found the building b->buildingUnit = *t; break; } //maybe the builder _is_ the building! (Zerg) if (b->buildingUnit == NULL && b->builderUnit!=NULL && b->builderUnit->getType().isBuilding()) { //we found the building b->buildingUnit = b->builderUnit; } } BWAPI::Unit* u = b->builderUnit; BWAPI::Unit* s = b->buildingUnit; if (s != NULL && s->isCompleted()) //if the building is completed, we're done { startedCount[b->type]--; plannedCount[b->type]--; if (u != NULL) { this->builders.erase(u); arbitrator->removeBid(this,u); } this->placer->freeTiles(b->tilePosition, b->type.tileWidth(), b->type.tileHeight()); //If the building is complete, we can forget about it. this->incompleteBuildings.erase(i); } else //otherwise, it doesn't exist or is incomplete { if (s == NULL) //if the building doesn't even exist { if (u == NULL) //ask for a builder if we don't have one yet buildingsNeedingBuilders[*b->type.whatBuilds().first].insert(b); else //if we have a worker { if (!u->isConstructing()) //if the worker isn't constructing { double distance = u->getPosition().getDistance(b->position); if (distance > 100) //if its too far away, tell it to go to the build site u->rightClick(b->position); else //if its close enough, tell it to build if (BWAPI::Broodwar->canBuildHere(u, b->tilePosition, b->type)) //if we can build here, tell the worker to build { if (BWAPI::Broodwar->canMake(u, b->type)) u->build(b->tilePosition, b->type); } else //if we cannot build here, we need to find another build site (reset the tilePosition) { this->placer->freeTiles(b->tilePosition, b->type.tileWidth(), b->type.tileHeight()); b->tilePosition = BWAPI::TilePositions::None; b->position = BWAPI::Positions::None; } } } } else //if the building does exist { if (b->type.getRace() != BWAPI::Races::Terran) //if its not terran, we can forget about the builder (i.e. probe is not needed to finish construction) { if (u != NULL) { this->builders.erase(u); arbitrator->removeBid(this, u); b->builderUnit = NULL; u = b->builderUnit; } } else { //if the buildind is terran, the worker may have been killed if (u == NULL) //looks like the worker was killed, or revoked. In either case we need to ask for another worker to finish our building buildingsNeedingBuilders[*b->type.whatBuilds().first].insert(b); else { //we have a worker, so lets rightClick it on the incomplete building so it can resume construction if (BWAPI::Broodwar->getFrameCount()%(4*BWAPI::Broodwar->getLatency())==0) { if (!u->isConstructing() || !s->isBeingConstructed()) { //right click builder on building u->rightClick(s); //also right click building on builder for good luck! :D s->rightClick(u); } } } } } } } } }