Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • stebr364/pycommandcenter
  • starcraft-ai-course/pycommandcenter
  • eriah592/pycommandcenter
  • edvbe696/pycommandcenter
  • dawab699/pycommandcenter
  • hanja189/pycommandcenter
  • teoga849/pycommandcenter
  • musab250/pycommandcenter
  • emibr898/pycommandcenter
  • chrgu102/pycommandcenter
  • axega544/pycommandcenter
  • edvth289/pycommandcenter
  • jonbo278/py-command-center-v-2
13 results
Show changes
#include "IDABot.h"
#include "Util.h"
#include "sc2api/sc2_score.h"
IDABot::IDABot()
: m_map(*this)
......@@ -72,11 +74,21 @@ void IDABot::OnStep()
m_unitInfo.onFrame();
m_bases.onFrame();
// suppress warnings while we update the tiles occupied by units
bool old_suppress = m_techTree.getSuppressWarnings();
m_techTree.setSuppressWarnings(true);
m_buildingPlacer.updateReserved(GetAllUnits());
m_techTree.setSuppressWarnings(old_suppress);
// -----------------------------------------------------------------
// Draw debug interface, and send debug interface to the Sc2 client.
// -----------------------------------------------------------------
Debug()->SendDebug();
m_buildingPlacer.drawReservedTiles();
m_buildingPlacer.drawReservedTiles();
}
void IDABot::OnGameEnd()
{
}
void IDABot::setUnits()
......@@ -151,6 +163,10 @@ int IDABot::GetGas() const
Unit IDABot::GetUnit(const CCUnitID & tag) const
{
if (Observation()->GetUnit(tag) == nullptr) {
return Unit();
}
return Unit(Observation()->GetUnit(tag), *(IDABot *)this);
}
......@@ -199,6 +215,12 @@ BuildingPlacer & IDABot::GetBuildingPlacer()
return m_buildingPlacer;
}
void IDABot::SendChat(const std::string & message)
{
Actions()->SendChat(message);
}
const TypeData & IDABot::Data(const UnitType & type) const
{
return m_techTree.getData(type);
......@@ -219,3 +241,176 @@ const TypeData & IDABot::Data(const MetaType & type) const
return m_techTree.getData(type);
}
/*
API extended summer 2020
*/
void IDABot::DebugCreateUnit(UnitTypeID unit_type, const CCPosition& p, uint32_t player_id, uint32_t count)
{
switch (player_id) // playerconstants for the IDAbot is not the same as for the sc2 API
{
case 0:
Debug()->DebugCreateUnit(unit_type, p, 1, count);
break;
case 1:
Debug()->DebugCreateUnit(unit_type, p, 2, count);
break;
case 2:
Debug()->DebugCreateUnit(unit_type, p, 0, count);
break;
case 3:
Debug()->DebugCreateUnit(unit_type, p, 3, count);
default:
break;
}
}
void IDABot::DebugKillUnit(const Unit unit)
{
Debug()->DebugKillUnit(unit.getUnitPtr());
}
void IDABot::DebugShowMap()
{
Debug()->DebugShowMap();
}
void IDABot::DebugFastBuild()
{
Debug()->DebugFastBuild();
}
void IDABot::DebugEnemyControl()
{
Debug()->DebugEnemyControl();
}
void IDABot::DebugIgnoreFood()
{
Debug()->DebugIgnoreFood();
}
void IDABot::DebugIgnoreResourceCost()
{
Debug()->DebugIgnoreResourceCost();
}
void IDABot::DebugGiveAllResources()
{
Debug()->DebugGiveAllResources();
}
void IDABot::DebugGodMode()
{
Debug()->DebugGodMode();
}
void IDABot::DebugIgnoreMineral()
{
Debug()->DebugIgnoreMineral();
}
void IDABot::DebugNoCooldowns()
{
Debug()->DebugIgnoreMineral();
}
void IDABot::DebugGiveAllTech()
{
Debug()->DebugGiveAllTech();
}
void IDABot::DebugGiveAllUpgrades()
{
Debug()->DebugGiveAllUpgrades();
}
void IDABot::DebugSetScore(float score)
{
Debug()->DebugSetScore(score);
}
void IDABot::DebugEndGame(bool victory)
{
Debug()->DebugEndGame(victory);
}
void IDABot::DebugSetEnergy(float value, const Unit unit)
{
Debug()->DebugSetEnergy(value, unit.getUnitPtr());
}
void IDABot::DebugSetLife(float value, const Unit unit)
{
Debug()->DebugSetLife(value, unit.getUnitPtr());
}
void IDABot::DebugSetShields(float value, const Unit unit)
{
Debug()->DebugSetShields(value, unit.getUnitPtr());
}
// There is a bug in the latest SC2 (if using Blizzard API with game >=4.10)
// This a function to get the enemy base instead of using build location manager
// Switched over to other API where this is solved
// Leaving function incase of it breaking
const std::vector<Point2D> IDABot::GetEnemyBaseLocations()
{
return Observation()->GetGameInfo().enemy_start_locations;
}
bool IDABot::HasCreep(Point2D p) const
{
return Observation()->HasCreep(p);
}
void IDABot::CameraMove(Point2DI p)
{
ActionsFeatureLayer()->CameraMove(p);
}
sc2::ABILITY_ID IDABot::abilityForUpgrade(sc2::UpgradeID upgrade_id) const
{
return (sc2::ABILITY_ID)Observation()->GetUpgradeData()[upgrade_id].ability_id;
}
uint32_t IDABot::UpgradeMineralCost(sc2::UpgradeID upgrade_id) const
{
return Observation()->GetUpgradeData()[upgrade_id].mineral_cost;
}
uint32_t IDABot::UpgradeGasCost(sc2::UpgradeID upgrade_id) const
{
return Observation()->GetUpgradeData()[upgrade_id].vespene_cost;
}
float IDABot::UpgradeResearchTime(sc2::UpgradeID upgrade_id) const
{
return Observation()->GetUpgradeData()[upgrade_id].research_time;
}
float IDABot::RadiusEffect(sc2::EffectID effect_id) const
{
return Observation()->GetEffectData()[effect_id].radius;
}
float IDABot::GetScore() const
{
return Observation()->GetScore().score;
}
const sc2::GameResult IDABot::GetPlayerResults() const
{
auto res = Observation()->GetResults();
for(int i = 0; i < res.size(); i++)
{
if (res.at(i).player_id == Observation()->GetPlayerID()) return res.at(i).result;
}
std::cout << "The player can not be found" << std::endl;
return sc2::GameResult::Undecided;
}
bool IDABot::SaveReplay(const std::string& path)
{
return this->Control()->SaveReplay(path);
}
\ No newline at end of file
......@@ -14,6 +14,10 @@
#include "MetaType.h"
#include "Unit.h"
using sc2::UnitTypeID;
using sc2::Point2D;
using sc2::Point2DI;
class IDABot : public sc2::Agent
{
MapTools m_map;
......@@ -34,6 +38,7 @@ public:
void OnGameStart() override;
void OnStep() override;
void OnGameEnd() override;
/*
API for students
......@@ -46,6 +51,8 @@ public:
CCPosition GetStartLocation() const;
BuildingPlacer & GetBuildingPlacer();
void SendChat(const std::string & message);
int GetCurrentFrame() const;
int GetMinerals() const;
int GetCurrentSupply() const;
......@@ -57,6 +64,43 @@ public:
const std::vector<Unit> GetUnits(const UnitType & type, int player = Players::Self) const;
const std::vector<CCPosition> & GetStartLocations() const;
/*
API extended summer 2020
*/
void DebugCreateUnit(UnitTypeID unit_type, const CCPosition& p, uint32_t player_id = 1, uint32_t count = 1);
void DebugKillUnit(const Unit unit);
void DebugShowMap();
void DebugFastBuild();
void DebugEnemyControl();
void DebugIgnoreFood();
void DebugIgnoreResourceCost();
void DebugGiveAllResources();
void DebugGodMode();
void DebugIgnoreMineral();
void DebugNoCooldowns();
void DebugGiveAllTech();
void DebugGiveAllUpgrades();
void DebugSetScore(float score);
void DebugEndGame(bool victory);
void DebugSetEnergy(float value, const Unit unit);
void DebugSetLife(float value, const Unit unit);
void DebugSetShields(float value, const Unit unit);
const std::vector<Point2D> GetEnemyBaseLocations();
bool HasCreep(Point2D p) const;
void CameraMove(Point2DI p);
sc2::ABILITY_ID abilityForUpgrade(sc2::UpgradeID upgrade_id) const;
uint32_t UpgradeMineralCost(sc2::UpgradeID upgrade_id) const;
uint32_t UpgradeGasCost(sc2::UpgradeID upgrade_id) const;
float UpgradeResearchTime(sc2::UpgradeID upgrade_id) const;
float RadiusEffect(sc2::EffectID effect_id) const;
float GetScore() const;
const sc2::GameResult GetPlayerResults() const;
bool SaveReplay(const std::string & path);
// Not needed, just convenience functions
const TypeData & Data(const UnitType & type) const;
const TypeData & Data(const CCUpgrade & type) const;
......
#include "IDAReplayObserver.h"
#include "Util.h"
void IDAReplayObserver::setUnits()
{
m_allUnits.clear();
m_allUnitsID.clear();
for (auto & unit : Observation()->GetUnits())
{
ReplayUnit replayUnit = ReplayUnit(unit, *this);
m_allUnits.push_back(replayUnit);
m_allUnitsID.insert(replayUnit.getID());
}
}
IDAReplayObserver::IDAReplayObserver():
sc2::ReplayObserver(),
m_techTree(*this)
{
}
void IDAReplayObserver::OnGameStart()
{
setUnits();
m_techTree.onStart();
}
void IDAReplayObserver::OnStep()
{
setUnits();
}
void IDAReplayObserver::OnGameEnd()
{
}
void IDAReplayObserver::OnUnitDestroyed(const sc2::Unit* unit)
{
ReplayUnit unitInformation = ReplayUnit(unit, *this);
OnReplayUnitDestroyed(&unitInformation);
}
void IDAReplayObserver::OnReplayUnitDestroyed(const ReplayUnit *)
{
}
void IDAReplayObserver::OnUnitCreated(const sc2::Unit * unit)
{
ReplayUnit unitInformation = ReplayUnit(unit, *this);
OnReplayUnitCreated(&unitInformation);
}
void IDAReplayObserver::OnReplayUnitCreated(const ReplayUnit *)
{
}
void IDAReplayObserver::OnBuildingConstructionComplete(const sc2::Unit *unit)
{
ReplayUnit unitInformation = ReplayUnit(unit, *this);
OnReplayUnitCreated(&unitInformation);
}
ReplayUnit IDAReplayObserver::GetUnit(const CCUnitID tag) const
{
return ReplayUnit(Observation()->GetUnit(tag), *(IDAReplayObserver *)this);
}
bool IDAReplayObserver::UnitExists(const CCUnitID tag) const
{
return m_allUnitsID.find(tag) != m_allUnitsID.end();
}
const std::vector<ReplayUnit>& IDAReplayObserver::GetAllUnits() const
{
return m_allUnits;
}
CCRace IDAReplayObserver::GetPlayerRace(int player)
{
return ReplayControl()->GetReplayInfo().players[player].race;
}
std::string IDAReplayObserver::GetReplayPath()
{
return ReplayControl()->GetReplayInfo().replay_path;
}
sc2::GameResult IDAReplayObserver::GetResultForPlayer(int player)
{
return ReplayControl()->GetReplayInfo().players[player].game_result;
}
const TechTree & IDAReplayObserver::GetTechTree() const
{
return m_techTree;
}
const TypeData & IDAReplayObserver::Data(const UnitType & type) const
{
return m_techTree.getData(type);
}
const TypeData & IDAReplayObserver::Data(const CCUpgrade & type) const
{
return m_techTree.getData(type);
}
const TypeData & IDAReplayObserver::Data(const MetaType & type) const
{
return m_techTree.getData(type);
}
const TypeData & IDAReplayObserver::Data(const Unit & unit) const
{
return m_techTree.getData(unit.getType());
}
#pragma once
#include <deque>
#include <limits>
#include "Common.h"
#include "ReplayUnit.h"
#include "TechTree.h"
class ReplayUnit;
class IDAReplayObserver : public sc2::ReplayObserver
{
void setUnits();
std::vector<ReplayUnit> m_allUnits;
std::set<CCUnitID> m_allUnitsID;
TechTree m_techTree;
public:
IDAReplayObserver();
void OnGameStart() override;
void OnStep() override;
void OnGameEnd() override;
void OnUnitDestroyed(const sc2::Unit*) override;
virtual void OnReplayUnitDestroyed(const ReplayUnit*);
void OnUnitCreated(const sc2::Unit*);
virtual void OnReplayUnitCreated(const ReplayUnit*);
void OnBuildingConstructionComplete(const sc2::Unit*);
ReplayUnit GetUnit(const CCUnitID tag) const;
bool UnitExists(const CCUnitID tag) const;
const std::vector<ReplayUnit> & GetAllUnits() const;
CCRace GetPlayerRace(int player);
std::string GetReplayPath();
sc2::GameResult GetResultForPlayer(int player);
const TechTree & GetTechTree() const;
const TypeData & Data(const UnitType & type) const;
const TypeData & Data(const CCUpgrade & type) const;
const TypeData & Data(const MetaType & type) const;
const TypeData & Data(const Unit & unit) const;
};
......@@ -7,6 +7,23 @@
#include <fstream>
#include <array>
namespace {
bool getBit(const sc2::ImageData& grid, int tileX, int tileY) {
assert(grid.bits_per_pixel == 1);
sc2::Point2DI pointI(tileX, tileY);
if (pointI.x < 0 || pointI.x >= grid.width || pointI.y < 0 || pointI.y >= grid.height)
{
return false;
}
div_t idx = div(pointI.x + pointI.y * grid.width, 8);
return (grid.data[idx.quot] >> (7 - idx.rem)) & 1;
}
} // namespace
const size_t LegalActions = 4;
const int actionX[LegalActions] ={1, -1, 0, 0};
const int actionY[LegalActions] ={0, 0, 1, -1};
......@@ -23,7 +40,8 @@ typedef std::vector<std::vector<float>> vvf;
// constructor for MapTools
MapTools::MapTools(IDABot & bot)
: m_bot (bot)
: m_bot(bot)
, m_mapName ("")
, m_width (0)
, m_height (0)
, m_maxZ (0.0f)
......@@ -37,6 +55,7 @@ void MapTools::onStart()
#ifdef SC2API
m_width = m_bot.Observation()->GetGameInfo().width;
m_height = m_bot.Observation()->GetGameInfo().height;
m_mapName= m_bot.Observation()->GetGameInfo().map_name;
#else
m_width = BWAPI::Broodwar->mapWidth();
m_height = BWAPI::Broodwar->mapHeight();
......@@ -261,7 +280,7 @@ bool MapTools::isPowered(int tileX, int tileY) const
#endif
}
float MapTools::terrainHeight(float x, float y) const
float MapTools::terrainHeightFromCoord(float x, float y) const
{
return m_terrainHeight[(int)x][(int)y];
}
......@@ -327,7 +346,8 @@ bool MapTools::isValidPosition(const CCPosition & pos) const
void MapTools::drawLine(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color) const
{
#ifdef SC2API
m_bot.Debug()->DebugLineOut(sc2::Point3D(x1, y1, terrainHeight(x1, y1) + 0.2f), sc2::Point3D(x2, y2, terrainHeight(x2, y2) + 0.2f), color);
//m_bot.Debug()->DebugLineOut(sc2::Point3D(x1, y1, terrainHeight(x1, y1) + 0.2f), sc2::Point3D(x2, y2, terrainHeight(x2, y2) + 0.2f), color);
m_bot.Debug()->DebugLineOut(sc2::Point3D(x1, y1, m_maxZ), sc2::Point3D(x2, y2, m_maxZ), color); // changed to m_maxZ instead fo terrainHeight since it doesnot work correctly
#else
BWAPI::Broodwar->drawLineMap(BWAPI::Position(x1, y1), BWAPI::Position(x2, y2), color);
#endif
......@@ -354,6 +374,10 @@ void MapTools::drawTile(int tileX, int tileY, const CCColor & color) const
drawLine(px, py + d, px, py, color);
}
void MapTools::drawTile(const CCTilePosition & pos, const CCColor & color) const {
drawTile(pos.x, pos.y, color);
}
void MapTools::drawBox(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color) const
{
#ifdef SC2API
......@@ -384,6 +408,15 @@ void MapTools::drawCircle(const CCPosition & pos, CCPositionType radius, const C
#endif
}
void MapTools::drawResourceSphere(const sc2::Point3D & pos, CCPositionType radius, const CCColor & color) const
{
#ifdef SC2API
m_bot.Debug()->DebugSphereOut(pos, radius, color);
#else
BWAPI::Broodwar->drawCircleMap(pos, radius, color);
#endif
}
void MapTools::drawCircle(CCPositionType x, CCPositionType y, CCPositionType radius, const CCColor & color) const
{
#ifdef SC2API
......@@ -512,6 +545,11 @@ int MapTools::height() const
return m_height;
}
std::string MapTools::name() const
{
return m_mapName;
}
const std::vector<CCTilePosition> & MapTools::getClosestTilesTo(const CCTilePosition & pos) const
{
return getDistanceMap(pos).getSortedTiles();
......@@ -541,17 +579,7 @@ CCTilePosition MapTools::getLeastRecentlySeenTile() const
bool MapTools::canWalk(int tileX, int tileY)
{
#ifdef SC2API
auto & info = m_bot.Observation()->GetGameInfo();
sc2::Point2DI pointI(tileX, tileY);
if (pointI.x < 0 || pointI.x >= info.width || pointI.y < 0 || pointI.y >= info.width)
{
return false;
}
assert(info.pathing_grid.data.size() == info.width * info.height);
unsigned char encodedPlacement = info.pathing_grid.data[pointI.x + ((info.height - 1) - pointI.y) * info.width];
bool decodedPlacement = encodedPlacement == 255 ? false : true;
return decodedPlacement;
return getBit(m_bot.Observation()->GetGameInfo().pathing_grid, tileX, tileY);
#else
for (int i=0; i<4; ++i)
{
......@@ -571,17 +599,7 @@ bool MapTools::canWalk(int tileX, int tileY)
bool MapTools::canBuild(int tileX, int tileY)
{
#ifdef SC2API
auto & info = m_bot.Observation()->GetGameInfo();
sc2::Point2DI pointI(tileX, tileY);
if (pointI.x < 0 || pointI.x >= info.width || pointI.y < 0 || pointI.y >= info.width)
{
return false;
}
assert(info.placement_grid.data.size() == info.width * info.height);
unsigned char encodedPlacement = info.placement_grid.data[pointI.x + ((info.height - 1) - pointI.y) * info.width];
bool decodedPlacement = encodedPlacement == 255 ? true : false;
return decodedPlacement;
return getBit(m_bot.Observation()->GetGameInfo().placement_grid, tileX, tileY);
#else
return BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tileX, tileY));
#endif
......@@ -604,4 +622,5 @@ float MapTools::terrainHeight(const CCPosition & point) const
#else
return 0;
#endif
}
\ No newline at end of file
}
......@@ -8,11 +8,12 @@ class IDABot;
class MapTools
{
IDABot & m_bot;
int m_width;
int m_height;
float m_maxZ;
int m_frame;
IDABot & m_bot;
std::string m_mapName;
int m_width;
int m_height;
float m_maxZ;
int m_frame;
// a cache of already computed distance maps, which is mutable since it only acts as a cache
......@@ -42,17 +43,21 @@ public:
void onStart();
void onFrame();
int width() const;
int height() const;
float terrainHeight(float x, float y) const;
std::string name() const;
float terrainHeightFromCoord(float x, float y) const;
void drawLine(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color = CCColor(255, 255, 255)) const;
void drawLine(const CCPosition & p1, const CCPosition & p2, const CCColor & color = CCColor(255, 255, 255)) const;
void drawTile(int tileX, int tileY, const CCColor & color = CCColor(255, 255, 255)) const;
void drawTile(const CCTilePosition & pos, const CCColor & color) const;
void drawBox(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color = CCColor(255, 255, 255)) const;
void drawBox(const CCPosition & tl, const CCPosition & br, const CCColor & color = CCColor(255, 255, 255)) const;
void drawCircle(CCPositionType x1, CCPositionType x2, CCPositionType radius, const CCColor & color = CCColor(255, 255, 255)) const;
void drawCircle(const CCPosition & pos, CCPositionType radius, const CCColor & color = CCColor(255, 255, 255)) const;
void drawResourceSphere(const sc2::Point3D & pos, CCPositionType radius, const CCColor & color = CCColor(255, 255, 255)) const;
void drawText(const CCPosition & pos, const std::string & str, const CCColor & color = CCColor(255, 255, 255)) const;
void drawTextScreen(float xPerc, float yPerc, const std::string & str, const CCColor & color = CCColor(255, 255, 255)) const;
......
#include "ReplayUnit.h"
ReplayUnit::ReplayUnit(const sc2::Unit * unit, IDAReplayObserver & replayObserver)
: m_replayObserver(&replayObserver), Unit(unit), m_type(unit->unit_type, replayObserver, replayObserver)
{
}
const UnitType & ReplayUnit::getType() const
{
return m_type;
}
bool ReplayUnit::hasTarget() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
if (getUnitPtr()->orders.size() > 0) {
if (getUnitPtr()->orders[0].target_unit_tag != NULL) {
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
// IDAReplayObserver checks if the unit with this tag still exists
if (m_replayObserver->UnitExists(t_id)){
// IDAReplayObserver finds the unit with this tag, and returns true if valid
return m_replayObserver->GetUnit(t_id).isValid();
}
}
}
return false;
}
ReplayUnit ReplayUnit::getTarget() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// if unit has order, check tag of target of first order
if (getUnitPtr()->orders.size() > 0) {
// t_id is set to the unit tag of the target
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
// Checks if the tag is a null tag or the unit have been removed
if (t_id != sc2::NullTag && m_replayObserver->UnitExists(t_id)){
// IDAReplayObserver finds the unit with this tag
return m_replayObserver->GetUnit(t_id);
}
}
return *this;
}
int ReplayUnit::getPlayer() const
{
return m_unit->owner;
}
#pragma once
#include "Unit.h"
#include "IDAReplayObserver.h"
class IDAReplayObserver;
//! A Unit that have a replayobserver insted of an Agent,
class ReplayUnit: public Unit
{
mutable IDAReplayObserver * m_replayObserver;
UnitType m_type;
public:
ReplayUnit(const sc2::Unit * unit, IDAReplayObserver & replayObserver);
const UnitType & getType() const;
bool hasTarget() const;
ReplayUnit getTarget() const;
int getPlayer() const;
};
\ No newline at end of file
This diff is collapsed.
......@@ -31,18 +31,22 @@ struct TypeData
class TechTree
{
IDABot & m_bot;
sc2::Client & m_client;
std::map<UnitType, TypeData> m_unitTypeData;
std::map<CCUpgrade, TypeData> m_upgradeData;
void initUnitTypeData();
void initUpgradeData();
bool suppressWarnings;
public:
TechTree(IDABot & bot);
TechTree(sc2::Client & client);
void onStart();
void setSuppressWarnings(bool b);
bool getSuppressWarnings() const;
const TypeData & getData(const UnitType & type) const;
const TypeData & getData(const CCUpgrade & type) const;
const TypeData & getData(const MetaType & type) const;
......
This diff is collapsed.
......@@ -116,6 +116,7 @@ void parse_build_description(BuildDescription & description, json & build_item)
{
description.result_type = static_cast<sc2::UNIT_TYPEID>(build_item["unit"]);
description.build_ability = static_cast<sc2::ABILITY_ID>(build_item["ability"]);
description.buildTime = static_cast<int>(build_item["time"]); // The time in seconds it takes to create the unit parsed from the json file
if (build_item.find("requires") != build_item.end())
{
......
......@@ -18,6 +18,7 @@ struct BuildDescription
std::vector<sc2::UNIT_TYPEID> buildings_needed;
std::vector<sc2::UNIT_TYPEID> addons_needed;
std::vector<sc2::UPGRADE_ID> upgrades_needed;
int buildTime; // The time in seconds it takes to create the unit
};
struct ResearchDescription
......@@ -52,4 +53,4 @@ public:
const std::vector<BuildDescription> & BuildDescriptions() const { return build_descriptions; }
const std::vector<ResearchDescription> & ResearchDescriptions() const { return research_descriptions; }
};
\ No newline at end of file
};
#include "Unit.h"
#include "IDABot.h"
#include "sc2api/sc2_gametypes.h"
Unit::Unit()
: m_bot(nullptr)
......@@ -13,7 +14,14 @@ Unit::Unit(const sc2::Unit * unit, IDABot & bot)
: m_bot(&bot)
, m_unit(unit)
, m_unitID(unit->tag)
, m_unitType(unit->unit_type, bot)
, m_unitType(unit->unit_type, bot, bot)
{
}
Unit::Unit(const sc2::Unit * unit)
: m_unit(unit)
, m_unitID(unit->tag)
{
}
......@@ -111,7 +119,7 @@ bool Unit::isCompleted() const
bool Unit::isTraining() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->orders.size() > 0;
return m_unit->orders.size() > 0 && m_unitType.isBuilding();
}
bool Unit::isBeingConstructed() const
......@@ -146,6 +154,16 @@ bool Unit::isFlying() const
#endif
}
std::vector<CCBuff> Unit::buffs() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->buffs;
#else
return m_unit->buffs();
#endif
}
bool Unit::isAlive() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
......@@ -226,7 +244,7 @@ void Unit::move(const CCPosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::MOVE, targetPosition);
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_MOVE, targetPosition);
#else
m_unit->move(targetPosition);
#endif
......@@ -236,7 +254,7 @@ void Unit::move(const CCTilePosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::MOVE, CCPosition((float)targetPosition.x, (float)targetPosition.y));
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_MOVE, CCPosition((float)targetPosition.x, (float)targetPosition.y));
#else
m_unit->move(CCPosition(targetPosition));
#endif
......@@ -259,13 +277,15 @@ void Unit::repair(const Unit & target) const
void Unit::build(const UnitType & buildingType, CCTilePosition pos) const
{
BOT_ASSERT(m_bot->Map().isConnected(getTilePosition(), pos), "Error: Build Position is not connected to worker");
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
#else
m_unit->build(buildingType.getAPIUnitType(), pos);
#endif
if (m_bot->Map().isConnected(getTilePosition(), pos))
{
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
}
else
{
printf("Warning! Cannot build at location (%d, %d) and therefore ignoring command.", pos.x, pos.y);
}
}
void Unit::buildTarget(const UnitType & buildingType, const Unit & target) const
......@@ -296,4 +316,210 @@ bool Unit::isConstructing(const UnitType & type) const
{
sc2::AbilityID buildAbility = m_bot->Data(type).buildAbility;
return (getUnitPtr()->orders.size() > 0) && (getUnitPtr()->orders[0].ability_id == buildAbility);
}
\ No newline at end of file
}
void Unit::ability(sc2::AbilityID ability) const
{
m_bot->Actions()->UnitCommand(getUnitPtr(), ability, false);
}
void Unit::ability(sc2::AbilityID ability, const sc2::Point2D& point) const
{
m_bot->Actions()->UnitCommand(getUnitPtr(), ability, point, false);
}
void Unit::ability(sc2::AbilityID ability, const Unit& target) const
{
m_bot->Actions()->UnitCommand(getUnitPtr(), ability, target.getUnitPtr(), false);
}
Unit Unit::getTarget() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// if unit has order, check tag of target of first order
if(getUnitPtr()->orders.size() > 0){
// t_id is set to the unit tag of the target
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
// Make sure the returned tag is not the NullTag
if (t_id == sc2::NullTag) {
return *this;
}
// Make sure the Tag references a valid unit
if (m_bot->Observation()->GetUnit(t_id) == nullptr) {
return *this;
}
// Convert the tag to a Unit object
Unit unit = m_bot->GetUnit(t_id);
if (unit.isValid()) {
return unit;
} else {
return *this;
}
}
return *this;
}
bool Unit::hasTarget() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
if (getUnitPtr()->orders.size() > 0) {
if (getUnitPtr()->orders[0].target_unit_tag != sc2::NullTag) {
CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
if (m_bot->Observation()->GetUnit(t_id) == nullptr) {
return false;
}
Unit unit = m_bot->GetUnit(t_id);
return unit.isValid();
}
}
return false;
}
bool Unit::isBlip() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API
return m_unit->is_blip;
#else
return m_unit->isBlip();
#endif
}
CCHealth Unit::getMaxHitPoints() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->health_max;
}
float Unit::getFacing() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->facing;
}
float Unit::getRadius() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->radius;
}
float Unit::getProgress() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// If unit has order, return progress of first order
if (getUnitPtr()->orders.size() > 0) {
return getUnitPtr()->orders[0].progress;
}
return -1;
}
const std::vector<float> Unit::getAllProgress() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// If unit has order, return progress of first order
std::vector<float> progressions;
if (getUnitPtr()->orders.size() > 0) {
for(int i = 0; i < getUnitPtr()->orders.size(); i++) {
progressions.push_back(getUnitPtr()->orders[i].progress);
}
}
return progressions;
}
sc2::AbilityID Unit::getCurrentAbilityID() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
// If unit has order, return AbilityID of first order
if (getUnitPtr()->orders.size() > 0) {
return getUnitPtr()->orders[0].ability_id;
}
// return invalid AbilityID
return sc2::ABILITY_ID::INVALID;
}
void Unit::holdPosition() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_HOLDPOSITION);
}
void Unit::patrol(const CCPosition & targetPosition) const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::GENERAL_PATROL, targetPosition);
}
void Unit::stopDance() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP_DANCE);
}
/*
// Implementation by Dawid Abucewicz
bool Unit::isCarryingMinerals() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
std::vector<CCBuff> buffs = m_unit->buffs;
for (auto & b : buffs)
{
if (b.to_string() == "271" or b.to_string() == "272")
{
return true;
}
}
return false;
}
*/
int Unit::gasLeftInGeyser() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->vespene_contents;
}
int Unit::mineralsLeftInMineralfield() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->mineral_contents;
}
int Unit::getOwner() const
{
BOT_ASSERT(isValid(), "Unit is not valid");
return m_unit->owner;
}
// Implemented with Blizzard SC2 API
bool Unit::isCarryingGas() const
{
return sc2::IsCarryingVespene(*m_unit);
}
bool Unit::isCarryingMinerals() const
{
return sc2::IsCarryingMinerals(*m_unit);
}
float Unit::maxShields() const
{
return m_unit->shield_max;
}
float Unit::maxEnergy() const
{
return m_unit->energy_max;
}
......@@ -11,13 +11,15 @@ class Unit
CCUnitID m_unitID;
UnitType m_unitType;
const sc2::Unit * m_unit;
protected:
const sc2::Unit * m_unit;
public:
Unit();
Unit(const sc2::Unit * unit, IDABot & bot);
Unit(const sc2::Unit * unit);
const sc2::Unit * getUnitPtr() const;
const sc2::UnitTypeID & getAPIUnitType() const;
......@@ -33,6 +35,7 @@ public:
CCHealth getEnergy() const;
CCPlayer getPlayer() const;
CCUnitID getID() const;
std::vector< CCBuff > buffs() const;
float getBuildPercentage() const;
int getWeaponCooldown() const;
bool isCompleted() const;
......@@ -46,6 +49,31 @@ public:
bool isValid() const;
bool isTraining() const;
bool isConstructing(const UnitType & type) const;
bool isCarryingMinerals() const;
bool isBlip() const;
bool hasTarget() const;
Unit getTarget() const;
CCHealth getMaxHitPoints() const;
float getProgress() const;
const std::vector<float> getAllProgress() const;
sc2::AbilityID getCurrentAbilityID() const;
void holdPosition() const;
void patrol(const CCPosition & targetPosition) const;
void stopDance() const;
float getFacing() const;
float getRadius() const;
/*
API extended summer 2020
*/
int gasLeftInGeyser() const;
int mineralsLeftInMineralfield() const;
int getOwner() const;
bool isCarryingGas() const;
float maxShields() const;
float maxEnergy() const;
void stop () const;
void attackUnit (const Unit & target) const;
......@@ -59,4 +87,7 @@ public:
void train (const UnitType & buildingType) const;
void morph (const UnitType & type) const;
void research (sc2::UpgradeID upgrade) const;
void ability (sc2::AbilityID ability) const;
void ability (sc2::AbilityID ability, const sc2::Point2D & point) const;
void ability (sc2::AbilityID ability, const Unit & target) const;
};
......@@ -13,7 +13,7 @@ UnitInfoManager::UnitInfoManager(IDABot & bot)
void UnitInfoManager::onStart()
{
updateUnitInfo();
}
void UnitInfoManager::onFrame()
......
This diff is collapsed.
......@@ -2,18 +2,26 @@
#include "Common.h"
class IDABot;
class IDAReplayObserver;
class UnitType
{
mutable IDABot * m_bot;
mutable sc2::Client * m_client;
mutable IDABot * m_bot;
mutable IDAReplayObserver * m_observer;
sc2::UnitTypeID m_type;
public:
UnitType();
UnitType(const sc2::UnitTypeID & type, IDABot & bot);
UnitType(const sc2::UnitTypeID & type, sc2::Client & client);
UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDABot & m_bot);
UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDAReplayObserver & observer);
sc2::UnitTypeID getAPIUnitType() const;
bool is(const sc2::UnitTypeID & type) const;
......@@ -22,6 +30,10 @@ public:
std::string getName() const;
CCRace getRace() const;
int getMovementSpeed() const;
int getSightRange() const;
sc2::UnitTypeID getRequiredStructure() const;
bool isValid() const;
bool isBuilding() const;
......@@ -37,7 +49,10 @@ public:
bool canAttack() const;
bool canMove() const;
bool isAddon() const;
bool canAttackGound() const;
bool canAttackAir() const;
CCPositionType getAttackRange() const;
float getAttackDamage() const;
int tileWidth() const;
int tileHeight() const;
int supplyProvided() const;
......@@ -46,6 +61,9 @@ public:
int gasPrice() const;
const std::vector<UnitType> & whatBuilds() const;
std::vector<sc2::UnitTypeID> getEquivalentUnits() const;
bool requiredAttached() const;
float getBuildTime() const;
static UnitType GetUnitTypeFromName(const std::string & name, IDABot & bot);
......
import unittest
import sys
sys.path.append('build/python-api-src')
from commandcenter import UnitTypeID, UNIT_TYPEID
class TestUnitType(unittest.TestCase):
def test_equality(self):
self.assertTrue(UNIT_TYPEID.TERRAN_ARMORY == UNIT_TYPEID.TERRAN_ARMORY)
def test_inequality(self):
self.assertFalse(UNIT_TYPEID.TERRAN_ARMORY != UNIT_TYPEID.TERRAN_ARMORY)
def test_convert_equality(self):
unit_typeid = UNIT_TYPEID.TERRAN_ARMORY
self.assertTrue(unit_typeid == UnitTypeID(unit_typeid))
self.assertTrue(UnitTypeID(unit_typeid) == unit_typeid)
self.assertFalse(UnitTypeID(unit_typeid) != unit_typeid)
if __name__ == '__main__':
unittest.main()