Skip to content

Commit

Permalink
Fix Issue #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 authored and alkurbatov committed Mar 13, 2021
1 parent edae1f5 commit 3e4a5de
Show file tree
Hide file tree
Showing 14 changed files with 244 additions and 87 deletions.
10 changes: 10 additions & 0 deletions src/Dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,16 @@ void Dispatcher::OnUpgradeCompleted(sc2::UpgradeID id_) {
i->OnUpgradeCompleted(id_);
}

void Dispatcher::OnUnitEnterVision(const sc2::Unit* unit_) {
// gHistory.info() << sc2::UnitTypeToName(unit_->unit_type) <<
// "(" << unit_->tag << ") entered vision" << std::endl;

gHub->OnUnitEnterVision(*unit_);

for (const auto& i : m_plugins)
i->OnUnitEnterVision(unit_, m_builder.get());
}

void Dispatcher::OnError(const std::vector<sc2::ClientError>& client_errors,
const std::vector<std::string>& protocol_errors) {
for (const auto i : client_errors) {
Expand Down
2 changes: 2 additions & 0 deletions src/Dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ struct Dispatcher: sc2::Agent {

void OnUpgradeCompleted(sc2::UpgradeID id_) final;

void OnUnitEnterVision(const sc2::Unit* unit_) final;

void OnError(const std::vector<sc2::ClientError>& client_errors,
const std::vector<std::string>& protocol_errors = {}) final;

Expand Down
118 changes: 87 additions & 31 deletions src/Hub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,9 @@ void Hub::OnUnitCreated(const sc2::Unit& unit_) {
case sc2::UNIT_TYPEID::PROTOSS_NEXUS:
case sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER:
case sc2::UNIT_TYPEID::ZERG_HATCHERY:
for (auto& i : m_expansions) {
if (std::floor(i.town_hall_location.x) != std::floor(unit_.pos.x) ||
std::floor(i.town_hall_location.y) != std::floor(unit_.pos.y))
continue;

i.owner = Owner::SELF;
gHistory.info() << "Capture region: (" <<
unit_.pos.x << ", " << unit_.pos.y <<
")" << std::endl;
return;
}
CaptureExpansion(unit_);
gHistory.info() << "Capture region: (" << unit_.pos.x <<
", " << unit_.pos.y << ")" << std::endl;
return;

default:
Expand All @@ -121,12 +113,28 @@ void Hub::OnUnitDestroyed(const sc2::Unit& unit_) {
case sc2::UNIT_TYPEID::PROTOSS_PROBE:
case sc2::UNIT_TYPEID::TERRAN_SCV:
case sc2::UNIT_TYPEID::ZERG_DRONE: {
if (m_busy_workers.Remove(Worker(unit_))) {
gHistory.info() << "Our busy worker was destroyed" << std::endl;
if (m_free_workers.Remove(Worker(unit_)))
return;

m_busy_workers.Remove(Worker(unit_));
gHistory.info() << "Our busy worker was destroyed" << std::endl;

auto it = std::find_if(m_expansions.begin(), m_expansions.end(),
[unit_](const Expansion& expansion_) {
return expansion_.worker_tag == unit_.tag;
});

if (it == m_expansions.end())
return;

if (it->owner == Owner::CONTESTED) // was enroute to build TownHall
it->RemoveOwner();

if (it->owner == Owner::SELF) { // TownHall still under construction
// NOTE (impulsecloud): decide whether to cancel or send new worker
// may need military escort to clear region
}

m_free_workers.Remove(Worker(unit_));
return;
}

Expand All @@ -152,17 +160,9 @@ void Hub::OnUnitDestroyed(const sc2::Unit& unit_) {
case sc2::UNIT_TYPEID::ZERG_HATCHERY:
case sc2::UNIT_TYPEID::ZERG_HIVE:
case sc2::UNIT_TYPEID::ZERG_LAIR:
for (auto& i : m_expansions) {
if (std::floor(i.town_hall_location.x) != std::floor(unit_.pos.x) ||
std::floor(i.town_hall_location.y) != std::floor(unit_.pos.y))
continue;

i.owner = Owner::NEUTRAL;
gHistory.info() << "Lost region: (" <<
unit_.pos.x << ", " << unit_.pos.y <<
")" << std::endl;
return;
}
RemoveExpansionOwner(unit_);
gHistory.info() << "Lost region: (" << unit_.pos.x
<< ", " << unit_.pos.y << ")" << std::endl;
return;

default:
Expand All @@ -175,7 +175,7 @@ void Hub::OnUnitIdle(const sc2::Unit& unit_) {
case sc2::UNIT_TYPEID::PROTOSS_PROBE:
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 All @@ -196,6 +196,25 @@ void Hub::OnUnitIdle(const sc2::Unit& unit_) {
}
}

void Hub::OnUnitEnterVision(const sc2::Unit& unit_) {
switch (unit_.unit_type.ToType()) {
case sc2::UNIT_TYPEID::PROTOSS_NEXUS:
case sc2::UNIT_TYPEID::TERRAN_COMMANDCENTER:
case sc2::UNIT_TYPEID::TERRAN_ORBITALCOMMAND:
case sc2::UNIT_TYPEID::TERRAN_PLANETARYFORTRESS:
case sc2::UNIT_TYPEID::ZERG_HATCHERY:
case sc2::UNIT_TYPEID::ZERG_HIVE:
case sc2::UNIT_TYPEID::ZERG_LAIR:
EnemyOwnsExpansion(unit_);
gHistory.info() << "Enemy owns region: (" << unit_.pos.x
<< ", " << unit_.pos.y << ")" << std::endl;
return;

default:
return;
}
}

bool Hub::IsOccupied(const sc2::Unit& unit_) const {
return m_captured_geysers.IsCached(Geyser(unit_));
}
Expand Down Expand Up @@ -243,13 +262,13 @@ bool Hub::AssignRefineryConstruction(Order* order_, const sc2::Unit* geyser_) {
return true;
}

bool Hub::AssignBuildTask(Order* order_, const sc2::Point2D& point_) {
sc2::Tag Hub::AssignBuildTask(Order* order_, const sc2::Point2D& point_) {
Worker* worker = GetClosestFreeWorker(point_);
if (!worker)
return false;
return sc2::NullTag;

worker->Build(order_, point_);
return true;
return worker->Tag();
}

void Hub::AssignVespeneHarvester(const sc2::Unit& refinery_) {
Expand Down Expand Up @@ -279,7 +298,7 @@ const Expansions& Hub::GetExpansions() const {
return m_expansions;
}

const sc2::Point3D* Hub::GetNextExpansion() {
Expansion* Hub::GetNextExpansion() {
auto it = std::find_if(m_expansions.begin(), m_expansions.end(),
[](const Expansion& expansion_) {
return expansion_.owner == Owner::NEUTRAL;
Expand All @@ -289,7 +308,44 @@ const sc2::Point3D* Hub::GetNextExpansion() {
return nullptr;

it->owner = Owner::CONTESTED;
return &(it->town_hall_location);
return &(*it);
}

Expansion* Hub::GetExpansionOfTownhall(const sc2::Unit& unit_) {
auto it = std::find_if(m_expansions.begin(), m_expansions.end(),
[unit_](const Expansion& e) {
return std::floor(e.town_hall_location.x) == std::floor(unit_.pos.x) &&
std::floor(e.town_hall_location.y) == std::floor(unit_.pos.y);
});

if (it == m_expansions.end())
return nullptr;

return &(*it);
}

void Hub::CaptureExpansion(const sc2::Unit& unit_) {
auto expansion = GetExpansionOfTownhall(unit_);
if (!expansion)
return;

expansion->SetOwner(unit_, Owner::SELF);
}

void Hub::EnemyOwnsExpansion(const sc2::Unit& unit_) {
auto expansion = GetExpansionOfTownhall(unit_);
if (!expansion)
return;

expansion->SetOwner(unit_, Owner::ENEMY);
}

void Hub::RemoveExpansionOwner(const sc2::Unit& unit_) {
auto expansion = GetExpansionOfTownhall(unit_);
if (!expansion)
return;

expansion->RemoveOwner();
}

std::unique_ptr<Hub> gHub;
16 changes: 14 additions & 2 deletions src/Hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ struct Hub {

void OnUnitIdle(const sc2::Unit& unit_);

void OnUnitEnterVision(const sc2::Unit& unit_);

bool IsOccupied(const sc2::Unit& unit_) const;

bool IsTargetOccupied(const sc2::UnitOrder& order_) const;
Expand All @@ -139,7 +141,7 @@ struct Hub {

bool AssignRefineryConstruction(Order* order_, const sc2::Unit* geyser_);

bool AssignBuildTask(Order* order_, const sc2::Point2D& point_);
sc2::Tag AssignBuildTask(Order* order_, const sc2::Point2D& point_);

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

Expand All @@ -149,9 +151,19 @@ struct Hub {

const Expansions& GetExpansions() const;

const sc2::Point3D* GetNextExpansion();
Expansion* GetNextExpansion();

const Expansion* GetBestMiningExpansionNear(const sc2::Unit* unit_) const;

private:
Expansion* GetExpansionOfTownhall(const sc2::Unit& unit_);

void CaptureExpansion(const sc2::Unit& unit_);

void EnemyOwnsExpansion(const sc2::Unit& unit_);

void RemoveExpansionOwner(const sc2::Unit& unit_);

sc2::Race m_current_race;
Expansions m_expansions;
sc2::UNIT_TYPEID m_current_supply_type;
Expand Down
12 changes: 9 additions & 3 deletions src/blueprints/TownHall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@
#include "core/API.h"

bool TownHall::Build(Order* order_) {
const sc2::Point3D* town_hall_location = gHub->GetNextExpansion();
if (!town_hall_location)
Expansion* next_expand = gHub->GetNextExpansion();
if (!next_expand)
return false;

return gHub->AssignBuildTask(order_, *town_hall_location);
sc2::Tag builder = gHub->AssignBuildTask(order_, next_expand->town_hall_location);
if (!builder)
return false;

next_expand->worker_tag = builder;

return true;
}
8 changes: 4 additions & 4 deletions src/core/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ IsUnit::IsUnit(sc2::UNIT_TYPEID type_): m_type(type_) {
}

bool IsUnit::operator()(const sc2::Unit& unit_) const {
return unit_.unit_type == m_type && unit_.build_progress >= 1.0f;
return unit_.unit_type == m_type && unit_.build_progress >= BUILD_FINISHED;
}

OneOfUnits::OneOfUnits(const std::set<sc2::UNIT_TYPEID>& types_): m_types(types_) {
}

bool OneOfUnits::operator()(const sc2::Unit& unit_) const {
return unit_.build_progress == 1.0f &&
return unit_.build_progress == BUILD_FINISHED &&
m_types.find(unit_.unit_type) != m_types.end();
}

Expand Down Expand Up @@ -103,7 +103,7 @@ bool IsFreeGeyser::operator()(const sc2::Unit& unit_) const {
}

bool IsRefinery::operator()(const sc2::Unit& unit_) const {
if (unit_.build_progress != 1.0f)
if (unit_.build_progress != BUILD_FINISHED)
return false;

return unit_.unit_type == sc2::UNIT_TYPEID::PROTOSS_ASSIMILATOR ||
Expand Down Expand Up @@ -145,7 +145,7 @@ bool IsGasWorker::operator()(const sc2::Unit& unit_) const {

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

bool IsCommandCenter::operator()(const sc2::Unit& unit_) const {
Expand Down
2 changes: 2 additions & 0 deletions src/core/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#include <set>

const float BUILD_FINISHED = 1.0f;

struct IsUnit {
explicit IsUnit(sc2::UNIT_TYPEID type_);

Expand Down
21 changes: 20 additions & 1 deletion src/core/Map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,23 @@ sc2::Point3D Cluster::Center() const {
} // namespace

Expansion::Expansion(const sc2::Point3D& town_hall_location_):
town_hall_location(town_hall_location_), owner(Owner::NEUTRAL) {
town_hall_location(town_hall_location_), owner(Owner::NEUTRAL),
town_hall_tag(sc2::NullTag), worker_tag(sc2::NullTag) {
}

void Expansion::SetOwner(const sc2::Unit& unit_, Owner owner_) {
town_hall_tag = unit_.tag;
owner = owner_;

// Terran worker_tag should remain as it constructs TownHall
if (gAPI->observer().GetCurrentRace() != sc2::Race::Terran)
worker_tag = sc2::NullTag;
}

void Expansion::RemoveOwner() {
owner = Owner::NEUTRAL;
town_hall_tag = sc2::NullTag;
worker_tag = sc2::NullTag;
}

Expansions CalculateExpansionLocations() {
Expand Down Expand Up @@ -152,5 +168,8 @@ Expansions CalculateExpansionLocations() {
start_index += query_size[i.id];
}

// Include start location. TownHall tag will be added during its OnCreated event.
expansions.emplace_back(gAPI->observer().StartingLocation());

return expansions;
}
15 changes: 11 additions & 4 deletions src/core/Map.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,24 @@
#include <vector>

enum Owner {
NEUTRAL = 0,
CONTESTED = 1,
ENEMY = 2,
SELF = 3,
NEUTRAL = 0, // No Townhall at expansion, no workers enroute
CONTESTED = 1, // No Townhall, Enemy may be present, Self Worker enroute
ENEMY = 2, // Enemy TownHall at expansion
SELF = 3, // Self TownHall at expansion, possibly under construction
};

struct Expansion {
explicit Expansion(const sc2::Point3D& town_hall_location_);

void SetOwner(const sc2::Unit& unit_, Owner owner_);

void RemoveOwner();

sc2::Point3D town_hall_location;
Owner owner;
sc2::Tag town_hall_tag; // valid for Owner::SELF or ENEMY
sc2::Tag worker_tag; // valid for Owner::CONTESTED or SELF
// NOTE (impulsecloud): check for dead builder, send new
};

typedef std::vector<Expansion> Expansions;
Expand Down
Loading

0 comments on commit 3e4a5de

Please sign in to comment.