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 "IDABot.h"
#include "Util.h" #include "Util.h"
#include "sc2api/sc2_score.h"
IDABot::IDABot() IDABot::IDABot()
: m_map(*this) : m_map(*this)
...@@ -72,11 +74,21 @@ void IDABot::OnStep() ...@@ -72,11 +74,21 @@ void IDABot::OnStep()
m_unitInfo.onFrame(); m_unitInfo.onFrame();
m_bases.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. // Draw debug interface, and send debug interface to the Sc2 client.
// ----------------------------------------------------------------- // -----------------------------------------------------------------
Debug()->SendDebug(); Debug()->SendDebug();
m_buildingPlacer.drawReservedTiles(); m_buildingPlacer.drawReservedTiles();
}
void IDABot::OnGameEnd()
{
} }
void IDABot::setUnits() void IDABot::setUnits()
...@@ -151,6 +163,10 @@ int IDABot::GetGas() const ...@@ -151,6 +163,10 @@ int IDABot::GetGas() const
Unit IDABot::GetUnit(const CCUnitID & tag) const Unit IDABot::GetUnit(const CCUnitID & tag) const
{ {
if (Observation()->GetUnit(tag) == nullptr) {
return Unit();
}
return Unit(Observation()->GetUnit(tag), *(IDABot *)this); return Unit(Observation()->GetUnit(tag), *(IDABot *)this);
} }
...@@ -199,6 +215,12 @@ BuildingPlacer & IDABot::GetBuildingPlacer() ...@@ -199,6 +215,12 @@ BuildingPlacer & IDABot::GetBuildingPlacer()
return m_buildingPlacer; return m_buildingPlacer;
} }
void IDABot::SendChat(const std::string & message)
{
Actions()->SendChat(message);
}
const TypeData & IDABot::Data(const UnitType & type) const const TypeData & IDABot::Data(const UnitType & type) const
{ {
return m_techTree.getData(type); return m_techTree.getData(type);
...@@ -219,3 +241,176 @@ const TypeData & IDABot::Data(const MetaType & type) const ...@@ -219,3 +241,176 @@ const TypeData & IDABot::Data(const MetaType & type) const
return m_techTree.getData(type); 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 @@ ...@@ -14,6 +14,10 @@
#include "MetaType.h" #include "MetaType.h"
#include "Unit.h" #include "Unit.h"
using sc2::UnitTypeID;
using sc2::Point2D;
using sc2::Point2DI;
class IDABot : public sc2::Agent class IDABot : public sc2::Agent
{ {
MapTools m_map; MapTools m_map;
...@@ -34,6 +38,7 @@ public: ...@@ -34,6 +38,7 @@ public:
void OnGameStart() override; void OnGameStart() override;
void OnStep() override; void OnStep() override;
void OnGameEnd() override;
/* /*
API for students API for students
...@@ -46,6 +51,8 @@ public: ...@@ -46,6 +51,8 @@ public:
CCPosition GetStartLocation() const; CCPosition GetStartLocation() const;
BuildingPlacer & GetBuildingPlacer(); BuildingPlacer & GetBuildingPlacer();
void SendChat(const std::string & message);
int GetCurrentFrame() const; int GetCurrentFrame() const;
int GetMinerals() const; int GetMinerals() const;
int GetCurrentSupply() const; int GetCurrentSupply() const;
...@@ -57,6 +64,43 @@ public: ...@@ -57,6 +64,43 @@ public:
const std::vector<Unit> GetUnits(const UnitType & type, int player = Players::Self) const; const std::vector<Unit> GetUnits(const UnitType & type, int player = Players::Self) const;
const std::vector<CCPosition> & GetStartLocations() 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 // Not needed, just convenience functions
const TypeData & Data(const UnitType & type) const; const TypeData & Data(const UnitType & type) const;
const TypeData & Data(const CCUpgrade & 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 @@ ...@@ -7,6 +7,23 @@
#include <fstream> #include <fstream>
#include <array> #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 size_t LegalActions = 4;
const int actionX[LegalActions] ={1, -1, 0, 0}; const int actionX[LegalActions] ={1, -1, 0, 0};
const int actionY[LegalActions] ={0, 0, 1, -1}; const int actionY[LegalActions] ={0, 0, 1, -1};
...@@ -23,7 +40,8 @@ typedef std::vector<std::vector<float>> vvf; ...@@ -23,7 +40,8 @@ typedef std::vector<std::vector<float>> vvf;
// constructor for MapTools // constructor for MapTools
MapTools::MapTools(IDABot & bot) MapTools::MapTools(IDABot & bot)
: m_bot (bot) : m_bot(bot)
, m_mapName ("")
, m_width (0) , m_width (0)
, m_height (0) , m_height (0)
, m_maxZ (0.0f) , m_maxZ (0.0f)
...@@ -37,6 +55,7 @@ void MapTools::onStart() ...@@ -37,6 +55,7 @@ void MapTools::onStart()
#ifdef SC2API #ifdef SC2API
m_width = m_bot.Observation()->GetGameInfo().width; m_width = m_bot.Observation()->GetGameInfo().width;
m_height = m_bot.Observation()->GetGameInfo().height; m_height = m_bot.Observation()->GetGameInfo().height;
m_mapName= m_bot.Observation()->GetGameInfo().map_name;
#else #else
m_width = BWAPI::Broodwar->mapWidth(); m_width = BWAPI::Broodwar->mapWidth();
m_height = BWAPI::Broodwar->mapHeight(); m_height = BWAPI::Broodwar->mapHeight();
...@@ -261,7 +280,7 @@ bool MapTools::isPowered(int tileX, int tileY) const ...@@ -261,7 +280,7 @@ bool MapTools::isPowered(int tileX, int tileY) const
#endif #endif
} }
float MapTools::terrainHeight(float x, float y) const float MapTools::terrainHeightFromCoord(float x, float y) const
{ {
return m_terrainHeight[(int)x][(int)y]; return m_terrainHeight[(int)x][(int)y];
} }
...@@ -327,7 +346,8 @@ bool MapTools::isValidPosition(const CCPosition & pos) const ...@@ -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 void MapTools::drawLine(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color) const
{ {
#ifdef SC2API #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 #else
BWAPI::Broodwar->drawLineMap(BWAPI::Position(x1, y1), BWAPI::Position(x2, y2), color); BWAPI::Broodwar->drawLineMap(BWAPI::Position(x1, y1), BWAPI::Position(x2, y2), color);
#endif #endif
...@@ -354,6 +374,10 @@ void MapTools::drawTile(int tileX, int tileY, const CCColor & color) const ...@@ -354,6 +374,10 @@ void MapTools::drawTile(int tileX, int tileY, const CCColor & color) const
drawLine(px, py + d, px, py, color); 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 void MapTools::drawBox(CCPositionType x1, CCPositionType y1, CCPositionType x2, CCPositionType y2, const CCColor & color) const
{ {
#ifdef SC2API #ifdef SC2API
...@@ -384,6 +408,15 @@ void MapTools::drawCircle(const CCPosition & pos, CCPositionType radius, const C ...@@ -384,6 +408,15 @@ void MapTools::drawCircle(const CCPosition & pos, CCPositionType radius, const C
#endif #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 void MapTools::drawCircle(CCPositionType x, CCPositionType y, CCPositionType radius, const CCColor & color) const
{ {
#ifdef SC2API #ifdef SC2API
...@@ -512,6 +545,11 @@ int MapTools::height() const ...@@ -512,6 +545,11 @@ int MapTools::height() const
return m_height; return m_height;
} }
std::string MapTools::name() const
{
return m_mapName;
}
const std::vector<CCTilePosition> & MapTools::getClosestTilesTo(const CCTilePosition & pos) const const std::vector<CCTilePosition> & MapTools::getClosestTilesTo(const CCTilePosition & pos) const
{ {
return getDistanceMap(pos).getSortedTiles(); return getDistanceMap(pos).getSortedTiles();
...@@ -541,17 +579,7 @@ CCTilePosition MapTools::getLeastRecentlySeenTile() const ...@@ -541,17 +579,7 @@ CCTilePosition MapTools::getLeastRecentlySeenTile() const
bool MapTools::canWalk(int tileX, int tileY) bool MapTools::canWalk(int tileX, int tileY)
{ {
#ifdef SC2API #ifdef SC2API
auto & info = m_bot.Observation()->GetGameInfo(); return getBit(m_bot.Observation()->GetGameInfo().pathing_grid, tileX, tileY);
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;
#else #else
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
{ {
...@@ -571,17 +599,7 @@ bool MapTools::canWalk(int tileX, int tileY) ...@@ -571,17 +599,7 @@ bool MapTools::canWalk(int tileX, int tileY)
bool MapTools::canBuild(int tileX, int tileY) bool MapTools::canBuild(int tileX, int tileY)
{ {
#ifdef SC2API #ifdef SC2API
auto & info = m_bot.Observation()->GetGameInfo(); return getBit(m_bot.Observation()->GetGameInfo().placement_grid, tileX, tileY);
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;
#else #else
return BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tileX, tileY)); return BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tileX, tileY));
#endif #endif
...@@ -604,4 +622,5 @@ float MapTools::terrainHeight(const CCPosition & point) const ...@@ -604,4 +622,5 @@ float MapTools::terrainHeight(const CCPosition & point) const
#else #else
return 0; return 0;
#endif #endif
} }
\ No newline at end of file
...@@ -8,11 +8,12 @@ class IDABot; ...@@ -8,11 +8,12 @@ class IDABot;
class MapTools class MapTools
{ {
IDABot & m_bot; IDABot & m_bot;
int m_width; std::string m_mapName;
int m_height; int m_width;
float m_maxZ; int m_height;
int m_frame; float m_maxZ;
int m_frame;
// a cache of already computed distance maps, which is mutable since it only acts as a cache // a cache of already computed distance maps, which is mutable since it only acts as a cache
...@@ -42,17 +43,21 @@ public: ...@@ -42,17 +43,21 @@ public:
void onStart(); void onStart();
void onFrame(); void onFrame();
int width() const; int width() const;
int height() 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(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 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(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(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 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(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 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 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; 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 ...@@ -31,18 +31,22 @@ struct TypeData
class TechTree class TechTree
{ {
IDABot & m_bot; sc2::Client & m_client;
std::map<UnitType, TypeData> m_unitTypeData; std::map<UnitType, TypeData> m_unitTypeData;
std::map<CCUpgrade, TypeData> m_upgradeData; std::map<CCUpgrade, TypeData> m_upgradeData;
void initUnitTypeData(); void initUnitTypeData();
void initUpgradeData(); void initUpgradeData();
bool suppressWarnings;
public: public:
TechTree(IDABot & bot); TechTree(sc2::Client & client);
void onStart(); void onStart();
void setSuppressWarnings(bool b);
bool getSuppressWarnings() const;
const TypeData & getData(const UnitType & type) const; const TypeData & getData(const UnitType & type) const;
const TypeData & getData(const CCUpgrade & type) const; const TypeData & getData(const CCUpgrade & type) const;
const TypeData & getData(const MetaType & 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) ...@@ -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.result_type = static_cast<sc2::UNIT_TYPEID>(build_item["unit"]);
description.build_ability = static_cast<sc2::ABILITY_ID>(build_item["ability"]); 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()) if (build_item.find("requires") != build_item.end())
{ {
......
...@@ -18,6 +18,7 @@ struct BuildDescription ...@@ -18,6 +18,7 @@ struct BuildDescription
std::vector<sc2::UNIT_TYPEID> buildings_needed; std::vector<sc2::UNIT_TYPEID> buildings_needed;
std::vector<sc2::UNIT_TYPEID> addons_needed; std::vector<sc2::UNIT_TYPEID> addons_needed;
std::vector<sc2::UPGRADE_ID> upgrades_needed; std::vector<sc2::UPGRADE_ID> upgrades_needed;
int buildTime; // The time in seconds it takes to create the unit
}; };
struct ResearchDescription struct ResearchDescription
...@@ -52,4 +53,4 @@ public: ...@@ -52,4 +53,4 @@ public:
const std::vector<BuildDescription> & BuildDescriptions() const { return build_descriptions; } const std::vector<BuildDescription> & BuildDescriptions() const { return build_descriptions; }
const std::vector<ResearchDescription> & ResearchDescriptions() const { return research_descriptions; } const std::vector<ResearchDescription> & ResearchDescriptions() const { return research_descriptions; }
}; };
\ No newline at end of file
#include "Unit.h" #include "Unit.h"
#include "IDABot.h" #include "IDABot.h"
#include "sc2api/sc2_gametypes.h"
Unit::Unit() Unit::Unit()
: m_bot(nullptr) : m_bot(nullptr)
...@@ -13,7 +14,14 @@ Unit::Unit(const sc2::Unit * unit, IDABot & bot) ...@@ -13,7 +14,14 @@ Unit::Unit(const sc2::Unit * unit, IDABot & bot)
: m_bot(&bot) : m_bot(&bot)
, m_unit(unit) , m_unit(unit)
, m_unitID(unit->tag) , 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 ...@@ -111,7 +119,7 @@ bool Unit::isCompleted() const
bool Unit::isTraining() const bool Unit::isTraining() const
{ {
BOT_ASSERT(isValid(), "Unit is not valid"); 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 bool Unit::isBeingConstructed() const
...@@ -146,6 +154,16 @@ bool Unit::isFlying() const ...@@ -146,6 +154,16 @@ bool Unit::isFlying() const
#endif #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 bool Unit::isAlive() const
{ {
BOT_ASSERT(isValid(), "Unit is not valid"); BOT_ASSERT(isValid(), "Unit is not valid");
...@@ -226,7 +244,7 @@ void Unit::move(const CCPosition & targetPosition) const ...@@ -226,7 +244,7 @@ void Unit::move(const CCPosition & targetPosition) const
{ {
BOT_ASSERT(isValid(), "Unit is not valid"); BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API #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 #else
m_unit->move(targetPosition); m_unit->move(targetPosition);
#endif #endif
...@@ -236,7 +254,7 @@ void Unit::move(const CCTilePosition & targetPosition) const ...@@ -236,7 +254,7 @@ void Unit::move(const CCTilePosition & targetPosition) const
{ {
BOT_ASSERT(isValid(), "Unit is not valid"); BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API #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 #else
m_unit->move(CCPosition(targetPosition)); m_unit->move(CCPosition(targetPosition));
#endif #endif
...@@ -259,13 +277,15 @@ void Unit::repair(const Unit & target) const ...@@ -259,13 +277,15 @@ void Unit::repair(const Unit & target) const
void Unit::build(const UnitType & buildingType, CCTilePosition pos) 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"); BOT_ASSERT(isValid(), "Unit is not valid");
#ifdef SC2API if (m_bot->Map().isConnected(getTilePosition(), pos))
m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos)); {
#else m_bot->Actions()->UnitCommand(m_unit, m_bot->Data(buildingType).buildAbility, Util::GetPosition(pos));
m_unit->build(buildingType.getAPIUnitType(), pos); }
#endif 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 void Unit::buildTarget(const UnitType & buildingType, const Unit & target) const
...@@ -296,4 +316,210 @@ bool Unit::isConstructing(const UnitType & type) const ...@@ -296,4 +316,210 @@ bool Unit::isConstructing(const UnitType & type) const
{ {
sc2::AbilityID buildAbility = m_bot->Data(type).buildAbility; sc2::AbilityID buildAbility = m_bot->Data(type).buildAbility;
return (getUnitPtr()->orders.size() > 0) && (getUnitPtr()->orders[0].ability_id == 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 ...@@ -11,13 +11,15 @@ class Unit
CCUnitID m_unitID; CCUnitID m_unitID;
UnitType m_unitType; UnitType m_unitType;
const sc2::Unit * m_unit; protected:
const sc2::Unit * m_unit;
public: public:
Unit(); Unit();
Unit(const sc2::Unit * unit, IDABot & bot); Unit(const sc2::Unit * unit, IDABot & bot);
Unit(const sc2::Unit * unit);
const sc2::Unit * getUnitPtr() const; const sc2::Unit * getUnitPtr() const;
const sc2::UnitTypeID & getAPIUnitType() const; const sc2::UnitTypeID & getAPIUnitType() const;
...@@ -33,6 +35,7 @@ public: ...@@ -33,6 +35,7 @@ public:
CCHealth getEnergy() const; CCHealth getEnergy() const;
CCPlayer getPlayer() const; CCPlayer getPlayer() const;
CCUnitID getID() const; CCUnitID getID() const;
std::vector< CCBuff > buffs() const;
float getBuildPercentage() const; float getBuildPercentage() const;
int getWeaponCooldown() const; int getWeaponCooldown() const;
bool isCompleted() const; bool isCompleted() const;
...@@ -46,6 +49,31 @@ public: ...@@ -46,6 +49,31 @@ public:
bool isValid() const; bool isValid() const;
bool isTraining() const; bool isTraining() const;
bool isConstructing(const UnitType & type) 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 stop () const;
void attackUnit (const Unit & target) const; void attackUnit (const Unit & target) const;
...@@ -59,4 +87,7 @@ public: ...@@ -59,4 +87,7 @@ public:
void train (const UnitType & buildingType) const; void train (const UnitType & buildingType) const;
void morph (const UnitType & type) const; void morph (const UnitType & type) const;
void research (sc2::UpgradeID upgrade) 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) ...@@ -13,7 +13,7 @@ UnitInfoManager::UnitInfoManager(IDABot & bot)
void UnitInfoManager::onStart() void UnitInfoManager::onStart()
{ {
updateUnitInfo();
} }
void UnitInfoManager::onFrame() void UnitInfoManager::onFrame()
......
This diff is collapsed.
...@@ -2,18 +2,26 @@ ...@@ -2,18 +2,26 @@
#include "Common.h" #include "Common.h"
class IDABot; class IDABot;
class IDAReplayObserver;
class UnitType class UnitType
{ {
mutable IDABot * m_bot; mutable sc2::Client * m_client;
mutable IDABot * m_bot;
mutable IDAReplayObserver * m_observer;
sc2::UnitTypeID m_type; sc2::UnitTypeID m_type;
public: public:
UnitType(); 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; sc2::UnitTypeID getAPIUnitType() const;
bool is(const sc2::UnitTypeID & type) const; bool is(const sc2::UnitTypeID & type) const;
...@@ -22,6 +30,10 @@ public: ...@@ -22,6 +30,10 @@ public:
std::string getName() const; std::string getName() const;
CCRace getRace() const; CCRace getRace() const;
int getMovementSpeed() const;
int getSightRange() const;
sc2::UnitTypeID getRequiredStructure() const;
bool isValid() const; bool isValid() const;
bool isBuilding() const; bool isBuilding() const;
...@@ -37,7 +49,10 @@ public: ...@@ -37,7 +49,10 @@ public:
bool canAttack() const; bool canAttack() const;
bool canMove() const; bool canMove() const;
bool isAddon() const; bool isAddon() const;
bool canAttackGound() const;
bool canAttackAir() const;
CCPositionType getAttackRange() const; CCPositionType getAttackRange() const;
float getAttackDamage() const;
int tileWidth() const; int tileWidth() const;
int tileHeight() const; int tileHeight() const;
int supplyProvided() const; int supplyProvided() const;
...@@ -46,6 +61,9 @@ public: ...@@ -46,6 +61,9 @@ public:
int gasPrice() const; int gasPrice() const;
const std::vector<UnitType> & whatBuilds() 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); 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()