Skip to content

Commit

Permalink
Fix Issue alkurbatov#35 "Improve mineral saturation"
Browse files Browse the repository at this point in the history
This will send new/idle workers to a non-saturated townhall. Townhalls will build an extra worker over Ideal and it will go to a new non-saturated townhall upon creation, so each townhall will continually build workers if there are any townhalls that are not yet saturated (until 80 total). After constructing a building, workers will go to an unsaturated townhall instead of the closest/starting one.
  • Loading branch information
ImpulseCloud committed Mar 2, 2021
1 parent 292d4c9 commit a965a95
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 11 deletions.
23 changes: 23 additions & 0 deletions src/Hub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ void Hub::OnUnitIdle(const sc2::Unit& unit_) {
case sc2::UNIT_TYPEID::TERRAN_SCV:
case sc2::UNIT_TYPEID::ZERG_DRONE: {
if (m_free_workers.Swap(Worker(unit_), m_busy_workers))
if (m_busy_workers.Swap(Worker(unit_), m_free_workers))
gHistory.info() << "Our busy worker has finished task" << std::endl;

return;
Expand Down Expand Up @@ -252,6 +253,28 @@ void Hub::AssignVespeneHarvester(const sc2::Unit& refinery_) {
worker->GatherVespene(refinery_);
}

void Hub::DistrubuteMineralWorker(const sc2::Unit* unit_) {
auto patches = gAPI->observer().GetUnits(sc2::IsVisibleMineralPatch(), sc2::Unit::Alliance::Neutral);
auto townhalls = gAPI->observer().GetUnits(IsNonSaturatedTownHall(), sc2::Unit::Alliance::Self);

if (townhalls.Empty()) // no non-Saturated bases, use any finished
townhalls = gAPI->observer().GetUnits(IsBuiltTownHall(), sc2::Unit::Alliance::Self);

const sc2::Unit* townhall_target = townhalls.GetClosestUnit(unit_->pos);

const sc2::Unit* mineral_target;
if (!townhall_target) { // if no TownHalls existing (or landed?)
mineral_target = patches.GetClosestUnit(gAPI->observer().StartingLocation());
} else {
mineral_target = patches.GetClosestUnit(townhall_target->pos);
}

if (!mineral_target)
return;

gAPI->action().Cast(*unit_, sc2::ABILITY_ID::SMART, *mineral_target);
}

bool Hub::AssignLarva(Order* order_) {
if (m_larva.Empty())
return false;
Expand Down
2 changes: 2 additions & 0 deletions src/Hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ struct Hub {

void AssignVespeneHarvester(const sc2::Unit& refinery_);

void DistrubuteMineralWorker(const sc2::Unit* unit_);

bool AssignLarva(Order* order_);

const Cache<GameObject>& GetLarvas() const;
Expand Down
19 changes: 19 additions & 0 deletions src/core/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,25 @@ bool IsGasWorker::operator()(const sc2::Unit& unit_) const {
return false;
}

bool IsTownHall::operator()(const sc2::Unit& unit_) const {
return unit_.unit_type == sc2::UNIT_TYPEID::PROTOSS_NEXUS ||
unit_.unit_type == sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER ||
unit_.unit_type == sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND ||
unit_.unit_type == sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS ||
unit_.unit_type == sc2::UNIT_TYPEID::ZERG_HATCHERY ||
unit_.unit_type == sc2::UNIT_TYPEID::ZERG_HIVE ||
unit_.unit_type == sc2::UNIT_TYPEID::ZERG_LAIR;
}

bool IsBuiltTownHall::operator()(const sc2::Unit& unit_) const {
return IsTownHall()(unit_) && unit_.build_progress == 1.0f;
}

bool IsNonSaturatedTownHall::operator()(const sc2::Unit& unit_) const {
return IsTownHall()(unit_) && unit_.build_progress == 1.0f
&& unit_.assigned_harvesters < unit_.ideal_harvesters;
}

bool IsIdleTownHall::operator()(const sc2::Unit& unit_) const {
return sc2::IsTownHall()(unit_) &&
unit_.orders.empty() && unit_.build_progress == 1.0f;
Expand Down
12 changes: 12 additions & 0 deletions src/core/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ struct IsGasWorker {
bool operator()(const sc2::Unit& unit_) const;
};

struct IsTownHall {
bool operator()(const sc2::Unit& unit_) const;
};

struct IsBuiltTownHall {
bool operator()(const sc2::Unit& unit_) const;
};

struct IsNonSaturatedTownHall {
bool operator()(const sc2::Unit& unit_) const;
};

struct IsIdleTownHall {
bool operator()(const sc2::Unit& unit_) const;
};
Expand Down
15 changes: 4 additions & 11 deletions src/plugins/Miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ const int mule_energy_cost = 50;

void SecureMineralsIncome(Builder* builder_) {
auto town_halls = gAPI->observer().GetUnits(sc2::IsTownHall());
auto numTotalWorkers = gAPI->observer().CountUnitType(gHub->GetCurrentWorkerType());

for (const auto& i : town_halls()) {
if (i->assigned_harvesters >= i->ideal_harvesters)
continue;
if (i->assigned_harvesters >= i->ideal_harvesters + 1 || numTotalWorkers > 80)
continue; // one more than ideal, never more than 80 (pros stop at 77-ish?)

if (!i->orders.empty())
continue;
Expand Down Expand Up @@ -98,19 +99,11 @@ void Miner::OnUnitCreated(const sc2::Unit* unit_, Builder*) {
}

void Miner::OnUnitIdle(const sc2::Unit* unit_, Builder*) {
auto units = gAPI->observer().GetUnits(sc2::IsVisibleMineralPatch(),
sc2::Unit::Alliance::Neutral);

switch (unit_->unit_type.ToType()) {
case sc2::UNIT_TYPEID::PROTOSS_PROBE:
case sc2::UNIT_TYPEID::TERRAN_SCV:
case sc2::UNIT_TYPEID::ZERG_DRONE: {
const sc2::Unit* mineral_target = units.GetClosestUnit(
gAPI->observer().StartingLocation());
if (!mineral_target)
return;

gAPI->action().Cast(*unit_, sc2::ABILITY_ID::SMART, *mineral_target);
gHub->DistrubuteMineralWorker(unit_);
break;
}

Expand Down

0 comments on commit a965a95

Please sign in to comment.