Skip to content

Instantly share code, notes, and snippets.

@cotcotquedec
Created August 12, 2017 12:01
Show Gist options
  • Save cotcotquedec/2afe2ca90eaecb01bb237d7d2f02bf2e to your computer and use it in GitHub Desktop.
Save cotcotquedec/2afe2ca90eaecb01bb237d7d2f02bf2e to your computer and use it in GitHub Desktop.
My SC2 Bot
#include "sc2api/sc2_api.h"
#include <iostream>
using namespace sc2;
class Bot : public Agent {
public:
const ObservationInterface* o;
Units unitsIdle = Units();
bool food_capped = false;
int vespene = 0;
int minerals = 0;
virtual void OnGameStart() final {
std::cout << "Hello, World!" << std::endl;
}
virtual void OnStep() {
o = Observation();
vespene = o->GetVespene();
minerals = o->GetMinerals();
TryBuildSupplyDepot();
TryTrainScv();
TryBuildRefinery();
}
virtual void OnUnitIdle(const Unit& unit) final {
switch (unit.unit_type.ToType()) {
case UNIT_TYPEID::TERRAN_REFINERY: {
TryExploitRefinery(unit);
TryExploitRefinery(unit);
TryExploitRefinery(unit);
TryExploitRefinery(unit);
break;
}
case UNIT_TYPEID::TERRAN_SCV: {
uint64_t mineral_target;
if (FindNearestMineralPatch(unit.pos, mineral_target)) {
Actions()->UnitCommand(unit, ABILITY_ID::SMART, mineral_target);
}
break;
}
default:
unitsIdle.push_back(unit);
}
}
private:
void debug(char* value, int i = 0) {
std::cout << value << " : " << i << std::endl;
}
/* RENVOIE TRUE si la nourriture utilsé eest supererieur au max - 2*/
bool IsFoodCapped() {
bool capped = o->GetFoodUsed() > o->GetFoodCap() - 2;
// si il y a une modifcation de la valeur, on le debug
if (capped != food_capped) {
food_capped = capped;
if (capped) {
debug("FOOD CAPPED", 1);
}
else {
debug("FOOD CAPPED", 0);
}
}
return food_capped;
}
/* Récuperation d'une unité libre */
Unit GetUnitIdleByType(UNIT_TYPEID unit_type = UNIT_TYPEID::TERRAN_SCV) {
for (const auto& unit : unitsIdle) {
if (unit.unit_type == unit_type) {
return unit;
}
}
return Unit();
}
/* TRY REMOVE UNIT OCCUPIED*/
void RemoveUnitIdle(Unit u) {
Units idle = Units();
for (const auto& unit : unitsIdle) {
if (unit.tag != u.tag) {
idle.push_back(unit);
}
}
unitsIdle = idle;
}
/*Renvoiele nombre d'unité que vous avez pour un type*/
int GetUnitTypeCount(UNIT_TYPEID type) {
int count = 0;
Units units = o->GetUnits(Unit::Alliance::Self);
for (const auto& u : units) {
if (u.unit_type == type) {
count++;
}
}
return count;
}
bool TryExploitRefinery(Unit refinery) {
Unit scv = GetScv();
float distance = std::numeric_limits<float>::max();
for (const auto& order : scv.orders) {
if (order.target_unit_tag != refinery.tag) {
debug("EXPLOIT REFINERY", 1);
Actions()->UnitCommand(scv, ABILITY_ID::SMART, refinery.tag);
RemoveUnitIdle(scv);
}
}
return false;
}
bool TryBuildRefinery() {
uint64_t vespene_target;
if (GetUnitTypeCount(UNIT_TYPEID::TERRAN_REFINERY) >= 2) {
return false;
}
// ON verifie que l'mon abien la bonn e quantité de resource
if (minerals < 75) {
return false;
}
// Si on est capé, on ne fait rien
if (IsFoodCapped()) {
return false;
}
if (IsAbilityInProgress(ABILITY_ID::BUILD_REFINERY)) {
return false;
}
// GET SCV
Unit unit = GetScv();
if (unit.unit_type == 0) {
return false;
}
if (FindNearestVespenePatch(unit.pos, vespene_target)) {
Actions()->UnitCommand(unit, ABILITY_ID::BUILD_REFINERY, vespene_target);
debug("BUILD_REFINERY", 1);
RemoveUnitIdle(unit);
}
return false;
}
/* TRAIN A SCV*/
bool TryTrainScv() {
// ON verifie que l'mon abien la bonn e quantité de resource
if (minerals < 50) {
return false;
}
if (GetUnitTypeCount(UNIT_TYPEID::TERRAN_SCV) >= 20) {
return false;
}
// Si on est capé, on ne fait rien
if (IsFoodCapped()) {
return false;
}
// Recuperation d'un CC
Unit unit = GetUnitIdleByType(UNIT_TYPEID::TERRAN_COMMANDCENTER);
if (unit.unit_type == 0) {
return false;
}
// ON envoie la demande
debug("TRAIN SCV", 1);
Actions()->UnitCommand(unit, ABILITY_ID::TRAIN_SCV);
RemoveUnitIdle(unit);
return true;
}
/* Renvoie le SCV le moins occupé*/
Unit GetScv(Tag exclude_tag = NULL) {
// ON cherche si un CSV est libre
Unit unit = GetUnitIdleByType(UNIT_TYPEID::TERRAN_SCV);
if (unit.unit_type == 0) {
Units units = o->GetUnits(Unit::Alliance::Self);
for (const auto& u : units) {
if (u.unit_type == UNIT_TYPEID::TERRAN_SCV) {
for (const auto& order : u.orders) {
if (order.ability_id == ABILITY_ID::HARVEST_GATHER) {
if (order.target_unit_tag != exclude_tag) {
unit = u;
}
}
}
}
}
}
return unit;
}
bool IsAbilityInProgress(ABILITY_ID ability) {
Units units = o->GetUnits(Unit::Alliance::Self);
for (const auto& unit : units) {
for (const auto& order : unit.orders) {
if (order.ability_id == ability) {
return true;
}
}
}
return false;
}
/*Tentative de constreuction d'un depot*/
bool TryBuildSupplyDepot() {
if (minerals < 100) {
return false;
}
// If we are not supply capped, don't build a supply depot.
if (!IsFoodCapped())
return false;
// ON check si un depot n'est pas encours de construction
if (IsAbilityInProgress(ABILITY_ID::BUILD_SUPPLYDEPOT))
return false;
// Recuperation d'un SCV
Unit unit = GetScv();
if (unit.unit_type == 0) {
return false;
}
float rx = GetRandomScalar();
float ry = GetRandomScalar();
// GIVE ORDER
Actions()->UnitCommand(unit,
ABILITY_ID::BUILD_SUPPLYDEPOT,
Point2D(unit.pos.x + rx * 15.0f, unit.pos.y + ry * 15.0f));
RemoveUnitIdle(unit);
debug("BUILD_SUPPLYDEPOT", 1);
return true;
}
/* TORUVE DU MINERAI */
bool FindNearestMineralPatch(const Point2D& start, uint64_t& target) {
Units units = Observation()->GetUnits(Unit::Alliance::Neutral);
float distance = std::numeric_limits<float>::max();
for (const auto& u : units) {
if (u.unit_type == UNIT_TYPEID::NEUTRAL_MINERALFIELD) {
float d = DistanceSquared2D(u.pos, start);
if (d < distance) {
distance = d;
target = u.tag;
}
}
}
if (distance == std::numeric_limits<float>::max()) {
return false;
}
return true;
}
/* TROUVE UN GEYSER VESPENE */
bool FindNearestVespenePatch(const Point2D& start, uint64_t& target) {
Units units = Observation()->GetUnits(Unit::Alliance::Neutral);
float distance = std::numeric_limits<float>::max();
for (const auto& u : units) {
if (u.unit_type == UNIT_TYPEID::NEUTRAL_VESPENEGEYSER) {
float d = DistanceSquared2D(u.pos, start);
if (d < distance) {
distance = d;
target = u.tag;
}
}
}
if (distance == std::numeric_limits<float>::max()) {
return false;
}
return true;
}
};
int main(int argc, char* argv[]) {
Coordinator coordinator;
coordinator.LoadSettings(argc, argv);
Bot bot;
coordinator.SetParticipants({
CreateParticipant(Race::Terran, &bot),
CreateComputer(Race::Zerg)
});
coordinator.LaunchStarcraft();
coordinator.StartGame(sc2::kMapBelShirVestigeLE);
while (coordinator.Update()) {
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment