From 8e7849e6d33fa4dbbd093c6c13799187ba3398c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Bergstr=C3=B6m?= <davbe125@student.liu.se> Date: Fri, 29 Jun 2018 12:35:07 +0200 Subject: [PATCH] Remove WorkerManager and everything that depends on it --- src/BuildingManager.cpp | 437 -------------------------------------- src/BuildingManager.h | 47 ---- src/IDABot.cpp | 6 - src/IDABot.h | 3 - src/ProductionManager.cpp | 338 ----------------------------- src/ProductionManager.h | 39 ---- src/WorkerManager.cpp | 267 ----------------------- src/WorkerManager.h | 48 ----- 8 files changed, 1185 deletions(-) delete mode 100644 src/BuildingManager.cpp delete mode 100644 src/BuildingManager.h delete mode 100644 src/ProductionManager.cpp delete mode 100644 src/ProductionManager.h delete mode 100644 src/WorkerManager.cpp delete mode 100644 src/WorkerManager.h diff --git a/src/BuildingManager.cpp b/src/BuildingManager.cpp deleted file mode 100644 index db0433e..0000000 --- a/src/BuildingManager.cpp +++ /dev/null @@ -1,437 +0,0 @@ -#include "Common.h" -#include "BuildingManager.h" -#include "IDABot.h" -#include "Util.h" - -BuildingManager::BuildingManager(IDABot & bot) - : m_bot(bot) - , m_buildingPlacer(bot) - , m_debugMode(false) - , m_reservedMinerals(0) - , m_reservedGas(0) -{ - -} - -void BuildingManager::onStart() -{ - m_buildingPlacer.onStart(); -} - -// gets called every frame from GameCommander -void BuildingManager::onFrame() -{ - for (auto unit : m_bot.UnitInfo().getUnits(Players::Self)) - { - // filter out units which aren't buildings under construction - if (m_bot.Data(unit).isBuilding) - { - std::stringstream ss; - ss << unit.getID(); - m_bot.Map().drawText(unit.getPosition(), ss.str()); - } - } - - validateWorkersAndBuildings(); // check to see if assigned workers have died en route or while constructing - assignWorkersToUnassignedBuildings(); // assign workers to the unassigned buildings and label them 'planned' - constructAssignedBuildings(); // for each planned building, if the worker isn't constructing, send the command - checkForStartedConstruction(); // check to see if any buildings have started construction and update data structures - checkForDeadTerranBuilders(); // if we are terran and a building is under construction without a worker, assign a new one - checkForCompletedBuildings(); // check to see if any buildings have completed and update data structures - - drawBuildingInformation(); -} - -bool BuildingManager::isBeingBuilt(UnitType type) -{ - for (auto & b : m_buildings) - { - if (b.type == type) - { - return true; - } - } - - return false; -} - -// STEP 1: DO BOOK KEEPING ON WORKERS WHICH MAY HAVE DIED -void BuildingManager::validateWorkersAndBuildings() -{ - // TODO: if a terran worker dies while constructing and its building - // is under construction, place unit back into buildingsNeedingBuilders - - std::vector<Building> toRemove; - - // find any buildings which have become obsolete - for (auto & b : m_buildings) - { - if (b.status != BuildingStatus::UnderConstruction) - { - continue; - } - - auto buildingUnit = b.buildingUnit; - - // TODO: || !b.buildingUnit->getType().isBuilding() - if (!buildingUnit.isValid()) - { - toRemove.push_back(b); - } - } - - removeBuildings(toRemove); -} - -// STEP 2: ASSIGN WORKERS TO BUILDINGS WITHOUT THEM -void BuildingManager::assignWorkersToUnassignedBuildings() -{ - // for each building that doesn't have a builder, assign one - for (Building & b : m_buildings) - { - if (b.status != BuildingStatus::Unassigned) - { - continue; - } - - BOT_ASSERT(!b.builderUnit.isValid(), "Error: Tried to assign a builder to a building that already had one "); - - if (m_debugMode) { printf("Assigning Worker To: %s", b.type.getName().c_str()); } - - // grab a worker unit from WorkerManager which is closest to this final position - CCTilePosition testLocation = getBuildingLocation(b); - if (!m_bot.Map().isValidTile(testLocation) || (testLocation.x == 0 && testLocation.y == 0)) - { - continue; - } - - b.finalPosition = testLocation; - - // grab the worker unit from WorkerManager which is closest to this final position - Unit builderUnit = m_bot.Workers().getBuilder(b); - b.builderUnit = builderUnit; - if (!b.builderUnit.isValid()) - { - continue; - } - - // reserve this building's space - m_buildingPlacer.reserveTiles((int)b.finalPosition.x, (int)b.finalPosition.y, b.type.tileWidth(), b.type.tileHeight()); - - b.status = BuildingStatus::Assigned; - } -} - -// STEP 3: ISSUE CONSTRUCTION ORDERS TO ASSIGN BUILDINGS AS NEEDED -void BuildingManager::constructAssignedBuildings() -{ - for (auto & b : m_buildings) - { - if (b.status != BuildingStatus::Assigned) - { - continue; - } - - // TODO: not sure if this is the correct way to tell if the building is constructing - //sc2::AbilityID buildAbility = m_bot.Data(b.type).buildAbility; - Unit builderUnit = b.builderUnit; - - bool isConstructing = false; - - // if we're zerg and the builder unit is null, we assume it morphed into the building - if (Util::IsZerg(m_bot.GetPlayerRace(Players::Self))) - { - if (!builderUnit.isValid()) - { - isConstructing = true; - } - } - else - { - BOT_ASSERT(builderUnit.isValid(), "null builder unit"); - - isConstructing = builderUnit.isConstructing(b.type); - } - - // if that worker is not currently constructing - if (!isConstructing) - { - // if we haven't explored the build position, go there - if (!isBuildingPositionExplored(b)) - { - builderUnit.move(b.finalPosition); - } - // if this is not the first time we've sent this guy to build this - // it must be the case that something was in the way of building - else if (b.buildCommandGiven) - { - // TODO: in here is where we would check to see if the builder died on the way - // or if things are taking too long, or the build location is no longer valid - } - else - { - // if it's a refinery, the build command has to be on the geyser unit tag - if (b.type.isRefinery()) - { - // first we find the geyser at the desired location - Unit geyser; - for (auto unit : m_bot.GetAllUnits()) - { - if (unit.getType().isGeyser() && Util::Dist(Util::GetPosition(b.finalPosition), unit.getPosition()) < 3) - { - geyser = unit; - break; - } - } - - if (geyser.isValid()) - { - b.builderUnit.buildTarget(b.type, geyser); - } - else - { - std::cout << "WARNING: NO VALID GEYSER UNIT FOUND TO BUILD ON, SKIPPING REFINERY\n"; - } - } - // if it's not a refinery, we build right on the position - else - { - b.builderUnit.build(b.type, b.finalPosition); - } - - // set the flag to true - b.buildCommandGiven = true; - } - } - } -} - -// STEP 4: UPDATE DATA STRUCTURES FOR BUILDINGS STARTING CONSTRUCTION -void BuildingManager::checkForStartedConstruction() -{ - // for each building unit which is being constructed - for (auto buildingStarted : m_bot.UnitInfo().getUnits(Players::Self)) - { - // filter out units which aren't buildings under construction - if (!buildingStarted.getType().isBuilding() || !buildingStarted.isBeingConstructed()) - { - continue; - } - - // check all our building status objects to see if we have a match and if we do, update it - - for (auto & b : m_buildings) - { - if (b.status != BuildingStatus::Assigned) - { - continue; - } - - // check if the positions match - int dx = b.finalPosition.x - buildingStarted.getTilePosition().x; - int dy = b.finalPosition.y - buildingStarted.getTilePosition().y; - - if (dx*dx + dy*dy < Util::TileToPosition(1.0f)) - { - if (b.buildingUnit.isValid()) - { - std::cout << "Building mis-match somehow\n"; - } - - // the resources should now be spent, so unreserve them - m_reservedMinerals -= buildingStarted.getType().mineralPrice(); - m_reservedGas -= buildingStarted.getType().gasPrice(); - - // flag it as started and set the buildingUnit - b.underConstruction = true; - b.buildingUnit = buildingStarted; - - // if we are zerg, the buildingUnit now becomes nullptr since it's destroyed - if (Util::IsZerg(m_bot.GetPlayerRace(Players::Self))) - { - b.builderUnit = Unit(); - } - else if (Util::IsProtoss(m_bot.GetPlayerRace(Players::Self))) - { - m_bot.Workers().finishedWithWorker(b.builderUnit); - b.builderUnit = Unit(); - } - - // put it in the under construction vector - b.status = BuildingStatus::UnderConstruction; - - // free this space - m_buildingPlacer.freeTiles((int)b.finalPosition.x, (int)b.finalPosition.y, b.type.tileWidth(), b.type.tileHeight()); - - // only one building will match - break; - } - } - } -} - -// STEP 5: IF WE ARE TERRAN, THIS MATTERS, SO: LOL -void BuildingManager::checkForDeadTerranBuilders() {} - -// STEP 6: CHECK FOR COMPLETED BUILDINGS -void BuildingManager::checkForCompletedBuildings() -{ - std::vector<Building> toRemove; - - // for each of our buildings under construction - for (auto & b : m_buildings) - { - if (b.status != BuildingStatus::UnderConstruction) - { - continue; - } - - // if the unit has completed - if (b.buildingUnit.isCompleted()) - { - // if we are terran, give the worker back to worker manager - if (Util::IsTerran(m_bot.GetPlayerRace(Players::Self))) - { - m_bot.Workers().finishedWithWorker(b.builderUnit); - } - - // remove this unit from the under construction vector - toRemove.push_back(b); - } - } - - removeBuildings(toRemove); -} - -// add a new building to be constructed -void BuildingManager::addBuildingTask(const UnitType & type, const CCTilePosition & desiredPosition) -{ - m_reservedMinerals += m_bot.Data(type).mineralCost; - m_reservedGas += m_bot.Data(type).gasCost; - - Building b(type, desiredPosition); - b.status = BuildingStatus::Unassigned; - - m_buildings.push_back(b); -} - -// TODO: may need to iterate over all tiles of the building footprint -bool BuildingManager::isBuildingPositionExplored(const Building & b) const -{ - return m_bot.Map().isExplored(b.finalPosition); -} - - -char BuildingManager::getBuildingWorkerCode(const Building & b) const -{ - return b.builderUnit.isValid() ? 'W' : 'X'; -} - -int BuildingManager::getReservedMinerals() -{ - return m_reservedMinerals; -} - -int BuildingManager::getReservedGas() -{ - return m_reservedGas; -} - -void BuildingManager::drawBuildingInformation() -{ - m_buildingPlacer.drawReservedTiles(); - - std::stringstream ss; - ss << "Building Information " << m_buildings.size() << "\n\n\n"; - - int yspace = 0; - - for (const auto & b : m_buildings) - { - std::stringstream dss; - - if (b.builderUnit.isValid()) - { - dss << "\n\nBuilder: " << b.builderUnit.getID() << "\n"; - } - - if (b.buildingUnit.isValid()) - { - dss << "Building: " << b.buildingUnit.getID() << "\n" << b.buildingUnit.getBuildPercentage(); - m_bot.Map().drawText(b.buildingUnit.getPosition(), dss.str()); - } - - if (b.status == BuildingStatus::Unassigned) - { - ss << "Unassigned " << b.type.getName() << " " << getBuildingWorkerCode(b) << "\n"; - } - else if (b.status == BuildingStatus::Assigned) - { - ss << "Assigned " << b.type.getName() << " " << b.builderUnit.getID() << " " << getBuildingWorkerCode(b) << " (" << b.finalPosition.x << "," << b.finalPosition.y << ")\n"; - - int x1 = b.finalPosition.x; - int y1 = b.finalPosition.y; - int x2 = b.finalPosition.x + b.type.tileWidth(); - int y2 = b.finalPosition.y + b.type.tileHeight(); - - m_bot.Map().drawBox((CCPositionType)x1, (CCPositionType)y1, (CCPositionType)x2, (CCPositionType)y2, CCColor(255, 0, 0)); - //m_bot.Map().drawLine(b.finalPosition, m_bot.GetUnit(b.builderUnitTag)->pos, CCColors::Yellow); - } - else if (b.status == BuildingStatus::UnderConstruction) - { - ss << "Constructing " << b.type.getName() << " " << getBuildingWorkerCode(b) << "\n"; - } - } - - m_bot.Map().drawTextScreen(0.3f, 0.05f, ss.str()); -} - -std::vector<UnitType> BuildingManager::buildingsQueued() const -{ - std::vector<UnitType> buildingsQueued; - - for (const auto & b : m_buildings) - { - if (b.status == BuildingStatus::Unassigned || b.status == BuildingStatus::Assigned) - { - buildingsQueued.push_back(b.type); - } - } - - return buildingsQueued; -} - -CCTilePosition BuildingManager::getBuildingLocation(const Building & b) -{ - size_t numPylons = m_bot.UnitInfo().getUnitTypeCount(Players::Self, Util::GetSupplyProvider(m_bot.GetPlayerRace(Players::Self), m_bot), true); - - // TODO: if requires psi and we have no pylons return 0 - - if (b.type.isRefinery()) - { - return m_buildingPlacer.getRefineryPosition(); - } - - if (b.type.isResourceDepot()) - { - return m_bot.Bases().getNextExpansion(Players::Self)->getDepotPosition(); - } - - // get a position within our region - // TODO: put back in special pylon / cannon spacing - return m_buildingPlacer.getBuildLocationNear(b, 1); -} - -void BuildingManager::removeBuildings(const std::vector<Building> & toRemove) - -{ - for (auto & b : toRemove) - { - const auto & it = std::find(m_buildings.begin(), m_buildings.end(), b); - - if (it != m_buildings.end()) - { - m_buildings.erase(it); - } - } -} \ No newline at end of file diff --git a/src/BuildingManager.h b/src/BuildingManager.h deleted file mode 100644 index 145e3b3..0000000 --- a/src/BuildingManager.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "Common.h" -#include "BuildingPlacer.h" - -class IDABot; - -class BuildingManager -{ - IDABot & m_bot; - - BuildingPlacer m_buildingPlacer; - std::vector<Building> m_buildings; - - bool m_debugMode; - int m_reservedMinerals; // minerals reserved for planned buildings - int m_reservedGas; // gas reserved for planned buildings - - bool isBuildingPositionExplored(const Building & b) const; - void removeBuildings(const std::vector<Building> & toRemove); - - void validateWorkersAndBuildings(); // STEP 1 - void assignWorkersToUnassignedBuildings(); // STEP 2 - void constructAssignedBuildings(); // STEP 3 - void checkForStartedConstruction(); // STEP 4 - void checkForDeadTerranBuilders(); // STEP 5 - void checkForCompletedBuildings(); // STEP 6 - - char getBuildingWorkerCode(const Building & b) const; - -public: - - BuildingManager(IDABot & bot); - - void onStart(); - void onFrame(); - void addBuildingTask(const UnitType & type, const CCTilePosition & desiredPosition); - void drawBuildingInformation(); - CCTilePosition getBuildingLocation(const Building & b); - - int getReservedMinerals(); - int getReservedGas(); - - bool isBeingBuilt(UnitType type); - - std::vector<UnitType> buildingsQueued() const; -}; diff --git a/src/IDABot.cpp b/src/IDABot.cpp index 8b2faf5..6934e31 100644 --- a/src/IDABot.cpp +++ b/src/IDABot.cpp @@ -462,7 +462,6 @@ IDABot::IDABot() : m_map(*this) , m_bases(*this) , m_unitInfo(*this) - , m_workers(*this) , m_techTree(*this) , m_buildingPlacer(*this) { @@ -592,11 +591,6 @@ const TechTree & IDABot::TechTree() const return m_techTree; } -WorkerManager & IDABot::Workers() -{ - return m_workers; -} - int IDABot::GetCurrentSupply() const { return Observation()->GetFoodUsed(); diff --git a/src/IDABot.h b/src/IDABot.h index 519fbe7..1e43153 100644 --- a/src/IDABot.h +++ b/src/IDABot.h @@ -8,7 +8,6 @@ #include "MapTools.h" #include "BaseLocationManager.h" #include "UnitInfoManager.h" -#include "WorkerManager.h" #include "BuildingPlacer.h" #include "TechTree.h" #include "MetaType.h" @@ -19,7 +18,6 @@ class IDABot : public sc2::Agent MapTools m_map; BaseLocationManager m_bases; UnitInfoManager m_unitInfo; - WorkerManager m_workers; TechTree m_techTree; // TODO: This should not be exported for student use BuildingPlacer m_buildingPlacer; @@ -110,7 +108,6 @@ public: API for students */ const TechTree & TechTree() const; - WorkerManager & Workers(); const BaseLocationManager & Bases() const; const MapTools & Map() const; const UnitInfoManager & UnitInfo() const; diff --git a/src/ProductionManager.cpp b/src/ProductionManager.cpp deleted file mode 100644 index 20cbeed..0000000 --- a/src/ProductionManager.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include "ProductionManager.h" -#include "Util.h" -#include "IDABot.h" - -ProductionManager::ProductionManager(IDABot & bot) - : m_bot (bot) - , m_buildingManager (bot) - , m_queue (bot) -{ - -} - -void ProductionManager::setBuildOrder(const BuildOrder & buildOrder) -{ - m_queue.clearAll(); - - for (size_t i(0); i<buildOrder.size(); ++i) - { - m_queue.queueAsLowestPriority(buildOrder[i], true); - } -} - - -void ProductionManager::onStart() -{ - m_buildingManager.onStart(); - //setBuildOrder(m_bot.Strategy().getOpeningBookBuildOrder()); -} - -void ProductionManager::onFrame() -{ - fixBuildOrderDeadlock(); - manageBuildOrderQueue(); - - // TODO: if nothing is currently building, get a new goal from the strategy manager - // TODO: detect if there's a build order deadlock once per second - // TODO: triggers for game things like cloaked units etc - - m_buildingManager.onFrame(); - drawProductionInformation(); -} - -// on unit destroy -void ProductionManager::onUnitDestroy(const Unit & unit) -{ - // TODO: might have to re-do build order if a vital unit died -} - -void ProductionManager::manageBuildOrderQueue() -{ - // if there is nothing in the queue, oh well - if (m_queue.isEmpty()) - { - return; - } - - // the current item to be used - BuildOrderItem & currentItem = m_queue.getHighestPriorityItem(); - - // while there is still something left in the queue - while (!m_queue.isEmpty()) - { - // this is the unit which can produce the currentItem - Unit producer = getProducer(currentItem.type); - - // check to see if we can make it right now - bool canMake = canMakeNow(producer, currentItem.type); - - // TODO: if it's a building and we can't make it yet, predict the worker movement to the location - - // if we can make the current item - if (producer.isValid() && canMake) - { - // create it and remove it from the _queue - create(producer, currentItem); - m_queue.removeCurrentHighestPriorityItem(); - - // don't actually loop around in here - break; - } - // otherwise, if we can skip the current item - else if (m_queue.canSkipItem()) - { - // skip it - m_queue.skipItem(); - - // and get the next one - currentItem = m_queue.getNextHighestPriorityItem(); - } - else - { - // so break out - break; - } - } -} - -void ProductionManager::fixBuildOrderDeadlock() -{ - if (m_queue.isEmpty()) { return; } - BuildOrderItem & currentItem = m_queue.getHighestPriorityItem(); - - // check to see if we have the prerequisites for the topmost item - bool hasRequired = m_bot.Data(currentItem.type).requiredUnits.empty(); - for (auto & required : m_bot.Data(currentItem.type).requiredUnits) - { - if (m_bot.UnitInfo().getUnitTypeCount(Players::Self, required, false) > 0 || m_buildingManager.isBeingBuilt(required)) - { - hasRequired = true; - break; - } - } - - if (!hasRequired) - { - std::cout << currentItem.type.getName() << " needs " << m_bot.Data(currentItem.type).requiredUnits[0].getName() << "\n"; - m_queue.queueAsHighestPriority(MetaType(m_bot.Data(currentItem.type).requiredUnits[0], m_bot), true); - fixBuildOrderDeadlock(); - return; - } - - // build the producer of the unit if we don't have one - bool hasProducer = m_bot.Data(currentItem.type).whatBuilds.empty(); - for (auto & producer : m_bot.Data(currentItem.type).whatBuilds) - { - if (m_bot.UnitInfo().getUnitTypeCount(Players::Self, producer, false) > 0 || m_buildingManager.isBeingBuilt(producer)) - { - hasProducer = true; - break; - } - } - - if (!hasProducer) - { - m_queue.queueAsHighestPriority(MetaType(m_bot.Data(currentItem.type).whatBuilds[0], m_bot), true); - fixBuildOrderDeadlock(); - } - - // build a refinery if we don't have one and the thing costs gas - auto refinery = Util::GetRefinery(m_bot.GetPlayerRace(Players::Self), m_bot); - if (m_bot.Data(currentItem.type).gasCost > 0 && m_bot.UnitInfo().getUnitTypeCount(Players::Self, refinery, false) == 0) - { - m_queue.queueAsHighestPriority(MetaType(refinery, m_bot), true); - } - - // build supply if we need some - auto supplyProvider = Util::GetSupplyProvider(m_bot.GetPlayerRace(Players::Self), m_bot); - if (m_bot.Data(currentItem.type).supplyCost > (m_bot.GetMaxSupply() - m_bot.GetCurrentSupply()) && !m_buildingManager.isBeingBuilt(supplyProvider)) - { - m_queue.queueAsHighestPriority(MetaType(supplyProvider, m_bot), true); - } -} - -Unit ProductionManager::getProducer(const MetaType & type, CCPosition closestTo) -{ - // get all the types of units that cna build this type - auto & producerTypes = m_bot.Data(type).whatBuilds; - - // make a set of all candidate producers - std::vector<Unit> candidateProducers; - for (auto unit : m_bot.UnitInfo().getUnits(Players::Self)) - { - // reasons a unit can not train the desired type - if (std::find(producerTypes.begin(), producerTypes.end(), unit.getType()) == producerTypes.end()) { continue; } - if (!unit.isCompleted()) { continue; } - if (m_bot.Data(unit).isBuilding && unit.isTraining()) { continue; } - if (unit.isFlying()) { continue; } - - // TODO: if unit is not powered continue - // TODO: if the type is an addon, some special cases - // TODO: if the type requires an addon and the producer doesn't have one - - // if we haven't cut it, add it to the set of candidates - candidateProducers.push_back(unit); - } - - return getClosestUnitToPosition(candidateProducers, closestTo); -} - -Unit ProductionManager::getClosestUnitToPosition(const std::vector<Unit> & units, CCPosition closestTo) -{ - if (units.size() == 0) - { - return Unit(); - } - - // if we don't care where the unit is return the first one we have - if (closestTo.x == 0 && closestTo.y == 0) - { - return units[0]; - } - - Unit closestUnit; - double minDist = std::numeric_limits<double>::max(); - - for (auto & unit : units) - { - double distance = Util::Dist(unit, closestTo); - if (!closestUnit.isValid() || distance < minDist) - { - closestUnit = unit; - minDist = distance; - } - } - - return closestUnit; -} - -// this function will check to see if all preconditions are met and then create a unit -void ProductionManager::create(const Unit & producer, BuildOrderItem & item) -{ - if (!producer.isValid()) - { - return; - } - - // if we're dealing with a building - if (item.type.isBuilding()) - { - if (item.type.getUnitType().isMorphedBuilding()) - { - producer.morph(item.type.getUnitType()); - } - else - { - m_buildingManager.addBuildingTask(item.type.getUnitType(), Util::GetTilePosition(m_bot.GetStartLocation())); - } - } - // if we're dealing with a non-building unit - else if (item.type.isUnit()) - { - producer.train(item.type.getUnitType()); - } - else if (item.type.isUpgrade()) - { - // TODO: UPGRADES - //Micro::SmartAbility(producer, m_bot.Data(item.type.getUpgradeID()).buildAbility, m_bot); - } -} - -bool ProductionManager::canMakeNow(const Unit & producer, const MetaType & type) -{ - if (!producer.isValid() || !meetsReservedResources(type)) - { - return false; - } - -#ifdef SC2API - sc2::AvailableAbilities available_abilities = m_bot.Query()->GetAbilitiesForUnit(producer.getUnitPtr()); - - // quick check if the unit can't do anything it certainly can't build the thing we want - if (available_abilities.abilities.empty()) - { - return false; - } - else - { - // check to see if one of the unit's available abilities matches the build ability type - sc2::AbilityID MetaTypeAbility = m_bot.Data(type).buildAbility; - for (const sc2::AvailableAbility & available_ability : available_abilities.abilities) - { - if (available_ability.ability_id == MetaTypeAbility) - { - return true; - } - } - } - - return false; -#else - bool canMake = meetsReservedResources(type); - if (canMake) - { - if (type.isUnit()) - { - canMake = BWAPI::Broodwar->canMake(type.getUnitType().getAPIUnitType(), producer.getUnitPtr()); - } - else if (type.isTech()) - { - canMake = BWAPI::Broodwar->canResearch(type.getTechType(), producer.getUnitPtr()); - } - else if (type.isUpgrade()) - { - canMake = BWAPI::Broodwar->canUpgrade(type.getUpgrade(), producer.getUnitPtr()); - } - else - { - BOT_ASSERT(false, "Unknown type"); - } - } - - return canMake; -#endif -} - -bool ProductionManager::detectBuildOrderDeadlock() -{ - // TODO: detect build order deadlocks here - return false; -} - -int ProductionManager::getFreeMinerals() -{ - return m_bot.GetMinerals() - m_buildingManager.getReservedMinerals(); -} - -int ProductionManager::getFreeGas() -{ - return m_bot.GetGas() - m_buildingManager.getReservedGas(); -} - -// return whether or not we meet resources, including building reserves -bool ProductionManager::meetsReservedResources(const MetaType & type) -{ - // return whether or not we meet the resources - int minerals = m_bot.Data(type).mineralCost; - int gas = m_bot.Data(type).gasCost; - - return (m_bot.Data(type).mineralCost <= getFreeMinerals()) && (m_bot.Data(type).gasCost <= getFreeGas()); -} - -void ProductionManager::drawProductionInformation() -{ - std::stringstream ss; - ss << "Production Information\n\n"; - - for (auto & unit : m_bot.UnitInfo().getUnits(Players::Self)) - { - if (unit.isBeingConstructed()) - { - //ss << sc2::UnitTypeToName(unit.unit_type) << " " << unit.build_progress << "\n"; - } - } - - ss << m_queue.getQueueInformation(); - - m_bot.Map().drawTextScreen(0.01f, 0.01f, ss.str(), CCColor(255, 255, 0)); -} diff --git a/src/ProductionManager.h b/src/ProductionManager.h deleted file mode 100644 index ae46859..0000000 --- a/src/ProductionManager.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "Common.h" -#include "BuildOrder.h" -#include "BuildingManager.h" -#include "BuildOrderQueue.h" - -class IDABot; - -class ProductionManager -{ - IDABot & m_bot; - - BuildingManager m_buildingManager; - BuildOrderQueue m_queue; - - Unit getClosestUnitToPosition(const std::vector<Unit> & units, CCPosition closestTo); - bool meetsReservedResources(const MetaType & type); - bool canMakeNow(const Unit & producer, const MetaType & type); - bool detectBuildOrderDeadlock(); - void setBuildOrder(const BuildOrder & buildOrder); - void create(const Unit & producer, BuildOrderItem & item); - void manageBuildOrderQueue(); - int getFreeMinerals(); - int getFreeGas(); - - void fixBuildOrderDeadlock(); - -public: - - ProductionManager(IDABot & bot); - - void onStart(); - void onFrame(); - void onUnitDestroy(const Unit & unit); - void drawProductionInformation(); - - Unit getProducer(const MetaType & type, CCPosition closestTo = CCPosition(0, 0)); -}; diff --git a/src/WorkerManager.cpp b/src/WorkerManager.cpp deleted file mode 100644 index 89cdaf4..0000000 --- a/src/WorkerManager.cpp +++ /dev/null @@ -1,267 +0,0 @@ -#include "WorkerManager.h" -#include "IDABot.h" -#include "Util.h" -#include "Building.h" - -WorkerManager::WorkerManager(IDABot & bot) - : m_bot (bot) - , m_workerData (bot) -{ - -} - -void WorkerManager::onStart() -{ - -} - -void WorkerManager::onFrame() -{ - m_workerData.updateAllWorkerData(); - - handleGasWorkers(); - handleIdleWorkers(); - - drawResourceDebugInfo(); - drawWorkerInformation(); - - m_workerData.drawDepotDebugInfo(); - - handleRepairWorkers(); -} - -void WorkerManager::setRepairWorker(Unit worker, const Unit & unitToRepair) -{ - m_workerData.setWorkerJob(worker, WorkerJobs::Repair, unitToRepair); -} - -void WorkerManager::stopRepairing(Unit worker) -{ - m_workerData.setWorkerJob(worker, WorkerJobs::Idle); -} - -void WorkerManager::handleGasWorkers() -{ - // for each unit we have - for (auto & unit : m_bot.UnitInfo().getUnits(Players::Self)) - { - // if that unit is a refinery - if (unit.getType().isRefinery() && unit.isCompleted()) - { - // get the number of workers currently assigned to it - int numAssigned = m_workerData.getNumAssignedWorkers(unit); - - // if it's less than we want it to be, fill 'er up - for (int i=0; i<(3-numAssigned); ++i) - { - auto gasWorker = getGasWorker(unit); - if (gasWorker.isValid()) - { - m_workerData.setWorkerJob(gasWorker, WorkerJobs::Gas, unit); - } - } - } - } -} - -void WorkerManager::handleIdleWorkers() -{ - // for each of our workers - for (auto & worker : m_workerData.getWorkers()) - { - if (!worker.isValid()) { continue; } - - bool isIdle = worker.isIdle(); - if (worker.isIdle() && - (m_workerData.getWorkerJob(worker) != WorkerJobs::Build) && - (m_workerData.getWorkerJob(worker) != WorkerJobs::Move) && - (m_workerData.getWorkerJob(worker) != WorkerJobs::Scout)) - { - m_workerData.setWorkerJob(worker, WorkerJobs::Idle); - } - - // if it is idle - if (m_workerData.getWorkerJob(worker) == WorkerJobs::Idle) - { - setMineralWorker(worker); - } - } -} - -void WorkerManager::handleRepairWorkers() -{ - // TODO -} - -Unit WorkerManager::getClosestMineralWorkerTo(const CCPosition & pos) const -{ - Unit closestMineralWorker; - double closestDist = std::numeric_limits<double>::max(); - - // for each of our workers - for (auto & worker : m_workerData.getWorkers()) - { - if (!worker.isValid()) { continue; } - - // if it is a mineral worker - if (m_workerData.getWorkerJob(worker) == WorkerJobs::Minerals) - { - double dist = Util::DistSq(worker.getPosition(), pos); - - if (!closestMineralWorker.isValid() || dist < closestDist) - { - closestMineralWorker = worker; - dist = closestDist; - } - } - } - - return closestMineralWorker; -} - - -// set a worker to mine minerals -void WorkerManager::setMineralWorker(const Unit & unit) -{ - // check if there is a mineral available to send the worker to - auto depot = getClosestDepot(unit); - - // if there is a valid mineral - if (depot.isValid()) - { - // update m_workerData with the new job - m_workerData.setWorkerJob(unit, WorkerJobs::Minerals, depot); - } -} - -Unit WorkerManager::getClosestDepot(Unit worker) const -{ - Unit closestDepot; - double closestDistance = std::numeric_limits<double>::max(); - - for (auto & unit : m_bot.UnitInfo().getUnits(Players::Self)) - { - if (!unit.isValid()) { continue; } - - if (unit.getType().isResourceDepot() && unit.isCompleted()) - { - double distance = Util::Dist(unit, worker); - if (!closestDepot.isValid() || distance < closestDistance) - { - closestDepot = unit; - closestDistance = distance; - } - } - } - - return closestDepot; -} - - -// other managers that need workers call this when they're done with a unit -void WorkerManager::finishedWithWorker(const Unit & unit) -{ - if (m_workerData.getWorkerJob(unit) != WorkerJobs::Scout) - { - m_workerData.setWorkerJob(unit, WorkerJobs::Idle); - } -} - -Unit WorkerManager::getGasWorker(Unit refinery) const -{ - return getClosestMineralWorkerTo(refinery.getPosition()); -} - -void WorkerManager::setBuildingWorker(Unit worker, Building & b) -{ - m_workerData.setWorkerJob(worker, WorkerJobs::Build, b.buildingUnit); -} - -// gets a builder for BuildingManager to use -// if setJobAsBuilder is true (default), it will be flagged as a builder unit -// set 'setJobAsBuilder' to false if we just want to see which worker will build a building -Unit WorkerManager::getBuilder(Building & b, bool setJobAsBuilder) const -{ - Unit builderWorker = getClosestMineralWorkerTo(Util::GetPosition(b.finalPosition)); - - // if the worker exists (one may not have been found in rare cases) - if (builderWorker.isValid() && setJobAsBuilder) - { - m_workerData.setWorkerJob(builderWorker, WorkerJobs::Build, b.builderUnit); - } - - return builderWorker; -} - -// sets a worker as a scout -void WorkerManager::setScoutWorker(Unit workerTag) -{ - m_workerData.setWorkerJob(workerTag, WorkerJobs::Scout); -} - -void WorkerManager::setCombatWorker(Unit workerTag) -{ - m_workerData.setWorkerJob(workerTag, WorkerJobs::Combat); -} - -void WorkerManager::drawResourceDebugInfo() -{ - for (auto & worker : m_workerData.getWorkers()) - { - if (!worker.isValid()) { continue; } - - if (worker.isIdle()) - { - m_bot.Map().drawText(worker.getPosition(), m_workerData.getJobCode(worker)); - } - - auto depot = m_workerData.getWorkerDepot(worker); - if (depot.isValid()) - { - m_bot.Map().drawLine(worker.getPosition(), depot.getPosition()); - } - } -} - -void WorkerManager::drawWorkerInformation() -{ - std::stringstream ss; - ss << "Workers: " << m_workerData.getWorkers().size() << "\n"; - - int yspace = 0; - - for (auto & worker : m_workerData.getWorkers()) - { - ss << m_workerData.getJobCode(worker) << " " << worker.getID() << "\n"; - - m_bot.Map().drawText(worker.getPosition(), m_workerData.getJobCode(worker)); - } - - m_bot.Map().drawTextScreen(0.75f, 0.2f, ss.str()); -} - -bool WorkerManager::isFree(Unit worker) const -{ - return m_workerData.getWorkerJob(worker) == WorkerJobs::Minerals || m_workerData.getWorkerJob(worker) == WorkerJobs::Idle; -} - -bool WorkerManager::isWorkerScout(Unit worker) const -{ - return (m_workerData.getWorkerJob(worker) == WorkerJobs::Scout); -} - -bool WorkerManager::isBuilder(Unit worker) const -{ - return (m_workerData.getWorkerJob(worker) == WorkerJobs::Build); -} - -int WorkerManager::getNumMineralWorkers() -{ - return m_workerData.getWorkerJobCount(WorkerJobs::Minerals); -} - -int WorkerManager::getNumGasWorkers() -{ - return m_workerData.getWorkerJobCount(WorkerJobs::Gas); - -} diff --git a/src/WorkerManager.h b/src/WorkerManager.h deleted file mode 100644 index f254c52..0000000 --- a/src/WorkerManager.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "WorkerData.h" - -class Building; -class IDABot; - -class WorkerManager -{ - IDABot & m_bot; - - mutable WorkerData m_workerData; - Unit m_previousClosestWorker; - - void setMineralWorker(const Unit & unit); - - void handleIdleWorkers(); - void handleGasWorkers(); - void handleRepairWorkers(); - -public: - - WorkerManager(IDABot & bot); - - void onStart(); - void onFrame(); - - void finishedWithWorker(const Unit & unit); - void drawResourceDebugInfo(); - void drawWorkerInformation(); - void setScoutWorker(Unit worker); - void setCombatWorker(Unit worker); - void setBuildingWorker(Unit worker, Building & b); - void setRepairWorker(Unit worker,const Unit & unitToRepair); - void stopRepairing(Unit worker); - - int getNumMineralWorkers(); - int getNumGasWorkers(); - bool isWorkerScout(Unit worker) const; - bool isFree(Unit worker) const; - bool isBuilder(Unit worker) const; - - Unit getBuilder(Building & b,bool setJobAsBuilder = true) const; - Unit getClosestDepot(Unit worker) const; - Unit getGasWorker(Unit refinery) const; - Unit getClosestMineralWorkerTo(const CCPosition & pos) const; -}; - -- GitLab