void Squad::gatherTogether() { const Position center(getCenter()); if( center.x() < 0 || center.y() < 0 ) return; AgentSetIter it = agents.begin(); AgentSetIter end = agents.end(); for(; it != end; ++it) { Agent *agent = *it; Unit &unit = agent->getUnit(); if( agent == leader ) unit.stop(); else { const Unit& leaderUnit = leader->getUnit(); // set this so if in attack state and agent gets updated // it doesn't keep going to enemey base and when radius is // low again it's position target will get set to the // leader's again agent->setPositionTarget(leaderUnit.getPosition()); unit.move(leaderUnit.getPosition()); } } }
void Squad::update() { if ((int)agents.size() == 0) return; if (leader == NULL) { leader = *agents.begin(); } // Find a new leader if current one dies if (leader->getUnit().getHitPoints() <= 0) { removeAgent(leader); for (AgentSetIter it = agents.begin(); it != agents.end(); it++) { leader = *it; break; } } // Regather every so often if( getRadius() > 100 && Broodwar->getFrameCount() % 10000 == 0 ) { // gatherTogether(); } else { // Do what the leader is doing AgentSetIter it = agents.begin(); AgentSetIter end = agents.end(); for(; it != end; ++it) { Agent *agent = *it; // command bunker squads to load into bunkers // TODO: check if already loaded if (type == bunker && bunkerTarget != NULL) { agent->getUnit().load(bunkerTarget); } // set non-leaders in squad if( agent != leader ) { // agent->setState(leader->getState()); if (type == attack) { agent->setState(AttackState); } agent->setPositionTarget(leader->getPositionTarget()); agent->setUnitTarget(leader->getUnitTarget()); agent->setUnitTypeTarget(leader->getUnitTypeTarget()); } } } }
int GasManager::getNumWorkersGathering() const { int count = 0; AgentSetConstIter it = agents.begin(); AgentSetConstIter end = agents.end(); for(; it != end;) { Agent *agent = *it; if( agent->getUnit().isGatheringGas() ) { ++count; } } return count; }
void CombatManager::update() { // Get new agents into state addNewAgents(); // TODO : Merge squads // Attack? const int numTroops = numLivingAgents(); //const int threshold = 15; // Update squad leaders for (SquadVectorIter it = attackSquads.begin(); it != attackSquads.end(); it++) { Agent *leader = (*it)->getLeader(); BWAPI::Unit * leaderUnit = &(leader->getUnit()); // Attack with full squad force (adjust to lower) // Otherwise while we are filling up, look mean if ((*it)->getSize() == AttackSquadSize && leader != NULL && numTroops > 50) { leader->setState(AttackState); leader->setPositionTarget(enemyBase); } else if (leader != NULL){ leader->setState(AttackState); // keep position target at base chokepoint } // check for enemy unit targets in range of leader // TODO: set this up for closest weakest enemy //BWAPI::WeaponType wt = leader->getUnitWeaponType(); // TODO: add more weapon types //set<BWAPI::Unit *> unitsInRange = leaderUnit->getUnitsInWeaponRange(wt); // hopefully this covers the back of the squad better (furthest from leader) int killZoneRadius = leaderUnit->getType().seekRange() + (*it)->getRadius(); set<BWAPI::Unit *> unitsInRange = leaderUnit->getUnitsInRadius(killZoneRadius); if ((int)unitsInRange.size() > 0) { int hitPoints = 99999; BWAPI::Unit * enemyTargetInRange = NULL; // get weakest enemy or a medic target for (UnitSetIter unitIt = unitsInRange.begin(); unitIt != unitsInRange.end(); unitIt++) { // check for enemy if ((*unitIt)->getPlayer() != Broodwar->self() && ((*unitIt)->getType().canAttack() || (*unitIt)->getType() == BWAPI::UnitTypes::Terran_Medic || (*unitIt)->getType() == BWAPI::UnitTypes::Terran_Bunker)) { // also check shields int tempHitPoints = (*unitIt)->getHitPoints() + (*unitIt)->getShields(); if (tempHitPoints == 0) continue; if ((*unitIt)->getType() == BWAPI::UnitTypes::Terran_Medic) { enemyTargetInRange = *unitIt; break; } else if (tempHitPoints < hitPoints) { hitPoints = tempHitPoints; enemyTargetInRange = *unitIt; } } } // find a target? if (enemyTargetInRange != NULL) { leader->setState(AttackState); leader->setUnitTarget(enemyTargetInRange); } else { // reset if no targets in range leader->setUnitTarget(NULL); } } } // end squad leader update // Move marines from defense squad to bunker squad if one available if ((int)bunkerAgents.size() > 0 && (int)bunkerSquads.size() > 0 && (int)defendSquads.size() > 0) { while ( bunkerSquads.back()->getSize() < 4 && defendSquads.back()->getSize() > 0) { defendSquads.back()->moveAgent(*(defendSquads.back()->getAgents().begin()), bunkerSquads.back()); } } /* Update attack, defend, and bunker squads */ for (SquadVectorIter it = attackSquads.begin(); it != attackSquads.end(); it++) { (*it)->update(); } for (SquadVectorIter it = defendSquads.begin(); it != defendSquads.end(); it++) { (*it)->update(); } for (SquadVectorIter it = bunkerSquads.begin(); it != bunkerSquads.end(); it++) { (*it)->update(); } // Clean up squads where everyone is dead vector<SquadVectorIter> itersToErase; for(SquadVectorIter it = attackSquads.begin(); it != attackSquads.end(); ++it) { Squad *squad = *it; if( squad->numAlive() == 0 ) { delete squad; itersToErase.push_back(it); } } for(vector<SquadVectorIter>::iterator it = itersToErase.begin(); it != itersToErase.end(); ++it) { attackSquads.erase(*it); } itersToErase.clear(); for(SquadVectorIter it = defendSquads.begin(); it != defendSquads.end(); ++it) { Squad *squad = *it; if( squad->numAlive() == 0 ) { delete squad; itersToErase.push_back(it); } } for(vector<SquadVectorIter>::iterator it = itersToErase.begin(); it != itersToErase.end(); ++it) { defendSquads.erase(*it); } itersToErase.clear(); for(SquadVectorIter it = bunkerSquads.begin(); it != bunkerSquads.end(); ++it) { Squad *squad = *it; if( squad->numAlive() == 0 ) { delete squad; itersToErase.push_back(it); } } for(vector<SquadVectorIter>::iterator it = itersToErase.begin(); it != itersToErase.end(); ++it) { bunkerSquads.erase(*it); } itersToErase.clear(); /* Base class updates Agents */ Manager::update(); }
void CombatManager::addNewAgents() { // If we have any new Agents, they should go in the unassigned set AgentSetIter it = agents.begin(); AgentSetIter end = agents.end(); Squad * squad; for(; it != end; ++it) { Agent *agent = *it; UnitType ut = agent->getUnit().getType(); // if not assigned yet if( assignedAgents.find(agent) == assignedAgents.end() ) { // check for bunkers if (ut == UnitTypes::Terran_Bunker) { bunkerAgents.insert(agent); assignedAgents.insert(agent); continue; } // init to unassigned unassignedAgents.insert(agent); // TODO - this is a hack to make them defend in the right place Position unitPosition = agent->getUnit().getPosition(); Position rallyPoint = MapAdvisor::getPositionOutsideNearestChokepoint(unitPosition); if (rallyPoint != Positions::None) agent->setPositionTarget(rallyPoint); // Assign Agent to a Squad // if there isn't an empty bunker fill up defense squad // with marines at max of 4 (only 1 bunker atm) // these will be reassigned to a bunker squad eventually if ((int)bunkerAgents.size() == 0 && ut == UnitTypes::Terran_Marine && ( (int)defendSquads.size() == 0 || defendSquads.back()->getSize() < 4)) { // if there isn't a defend squad make one if ((int)defendSquads.size() == 0) { defendSquads.push_back(new Squad("defend-squad", defend)); } // set pointer squad = defendSquads.back(); } else if ((int)bunkerAgents.size() == 1 && ut == UnitTypes::Terran_Marine && ((int)bunkerSquads.size() == 0 || bunkerSquads.back()->getSize() < 4)) { // if there isn't a bunker squad make one if ((int)bunkerSquads.size() == 0) { bunkerSquads.push_back(new Squad("bunker-squad", bunker)); // always assigns first bunker as target // TODO: make better bunker agent arrangement bunkerSquads.back()->setBunkerTarget(&(*bunkerAgents.begin())->getUnit()); } // set pointer squad = bunkerSquads.back(); } else { // if there isn't an attack squad make one if ((int)attackSquads.size() == 0 || attackSquads.back()->getSize() == AttackSquadSize) { attackSquads.push_back(new Squad("attack-squad", attack)); } squad = attackSquads.back(); } // TODO: only add the agent if we have (or can create) // a squad that has an unfulfilled requirement for this type of unit, // otherwise leave it in the unassigned set squad->addAgent(*it); // For now this should always be set, giving them the ability // to look for nearby enemy targets (*it)->setState(AttackState); if (squad->getLeader() == NULL) { squad->setLeader(*it); } // change to assigned unassignedAgents.erase(agent); assignedAgents.insert(agent); } } }