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
Showing
with 636 additions and 43 deletions
......@@ -3,6 +3,7 @@
#include <pybind11/pybind11.h>
#include <sc2api/sc2_api.h>
#include "../src/IDABot.h"
#include "../src/IDAReplayObserver.h"
#include <iostream>
#include <pybind11/stl.h> /* Automatic conversion from std::vector to Python lists */
#include <pybind11/operators.h> /* Convenient operator support */
......@@ -21,7 +22,7 @@ public:
}
Coordinator(std::string path) : sc2::Coordinator()
{
{
std::vector<std::string> arguments = { "pycommandcenter", "-e", path };
CustomLoadSettings(arguments);
}
......@@ -59,12 +60,78 @@ public:
OnStep
);
}
void OnGameEnd() override
{
PYBIND11_OVERLOAD_NAME(
void,
IDABot,
"on_game_end",
OnGameEnd
);
}
};
class PyReplayObserver : public IDAReplayObserver
{
public:
using IDAReplayObserver::IDAReplayObserver;
void OnGameStart() override
{
PYBIND11_OVERLOAD_NAME(
void,
IDAReplayObserver,
"on_game_start",
OnGameStart
);
}
void OnStep() override
{
PYBIND11_OVERLOAD_NAME(
void,
IDAReplayObserver,
"on_step",
OnStep
);
}
void OnGameEnd() override
{
PYBIND11_OVERLOAD_NAME(
void,
IDAReplayObserver,
"on_game_end",
OnGameEnd
);
}
void OnReplayUnitDestroyed(const ReplayUnit *unit) override
{
PYBIND11_OVERLOAD_NAME(
void,
IDAReplayObserver,
"on_unit_destroyed",
OnReplayUnitDestroyed,
unit
);
}
void OnReplayUnitCreated(const ReplayUnit *unit) override
{
PYBIND11_OVERLOAD_NAME(
void,
IDAReplayObserver,
"on_unit_created",
OnReplayUnitCreated,
unit
);
}
};
// The functions below are all defined in different .cpp files, in order
// to keep compilation snappy
void define_typeenums(pybind11::module & m);
void define_unit(pybind11::module & m);
void define_replay_unit(pybind11::module & m);
void define_unittype(pybind11::module &m);
void define_util(pybind11::module &m);
void define_point(pybind11::module &m);
......
alabaster==0.7.16
Babel==2.15.0
certifi==2024.6.2
charset-normalizer==3.3.2
docutils==0.21.2
idna==3.7
imagesize==1.4.1
Jinja2==3.1.4
MarkupSafe==2.1.5
mypy==1.10.0
mypy-extensions==1.0.0
packaging==24.1
Pygments==2.18.0
requests==2.32.3
snowballstemmer==2.2.0
Sphinx==7.3.7
sphinx_design==0.6.0
sphinxcontrib-applehelp==1.0.8
sphinxcontrib-devhelp==1.0.6
sphinxcontrib-htmlhelp==2.0.5
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.7
sphinxcontrib-serializinghtml==1.1.10
typing_extensions==4.12.2
urllib3==2.2.2
mkdir build
cd build
"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 17 2022" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python312/python.exe"
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --verbose
#!/bin/sh
mkdir build
cd build
"C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 17 2022" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python312/python.exe" ..
"C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --verbose
......@@ -3,4 +3,3 @@
mkdir build38
cd build38
"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python38/python.exe"
#!/bin/sh
mkdir build
cd build
"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64"
"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python39/python.exe"
"""
This file inserts the docs of each class and method into the pyi file for autocompletetion.
Before running make sure you have created the pyi according to the README.
You might need to change the pyi_path.
Then simply run this file.
After running all the docs should have been inserted.
Now you're done and can enjoy working autocompletion of this library.
"""
import sys
import inspect
import re
sys.path.append('build/python-api-src') #Unix
sys.path.append('build/python-api-src/Release') #Windows
import commandcenter
def update_pyi_with_docstrings(pyi_path):
"""
Update the .pyi file with docstrings from the corresponding library.
Args:
pyi_path (str): The path to the .pyi file.
Returns:
None
"""
with open(pyi_path, 'r') as file:
lines = file.readlines()
new_lines = []
known_def = {} #To keep track of docs to class methods
for i in range(len(lines)):
line = lines[i]
if line.strip().startswith('class '):
new_lines.append(line)
if not line.strip().endswith("ID:"):
class_name = re.split(r'[\(: ]', line)[1]
docstring = inspect.getdoc(getattr(commandcenter, class_name))
new_lines.append(f' """{docstring}"""\n')
for func in dir(getattr(commandcenter, class_name)):
if func.startswith("__"):
continue
func_docs = inspect.getdoc(getattr(getattr(commandcenter, class_name), func))
known_def[func] = func_docs
else:
class_name = re.split(r'[\(: ]', line)[1]
docstring = inspect.getdoc(getattr(commandcenter, class_name))
docstring = docstring.split("Members:")[0]
new_lines.append(f' """{docstring}"""\n')
elif line.strip().startswith('def '):
new_lines.append(line[:-4])
func_name = re.split(r'[\(: ]', line.strip())[1]
if func_name.startswith("__"):
new_lines.append(f' {line[-4:]}')
continue
elif func_name in known_def:
new_lines.append(f'\n """{known_def[func_name]}"""\n')
new_lines.append(f' {line[-4:]}')
continue
else:
try:
func_doc = inspect.getdoc(getattr(commandcenter, func_name))
if func_name == "create_computer" or func_name == "create_participants": #Special case with indentation
new_lines.append(f'\n """{func_doc}"""\n')
else:
new_lines.append(f'\n """{func_doc}"""\n')
new_lines.append(f' {line[-4:]}')
continue
except AttributeError:
new_lines.append(f'\n """not found"""\n')
new_lines.append(f' {line[-4:]}')
continue
else:
new_lines.append(line)
# Write the updated content back to the .pyi file
with open(pyi_path, 'w') as file:
file.writelines(new_lines)
# Path to the generated .pyi file
pyi_file_path = 'build/python-api-src/commandcenter.pyi' #Unix
#pyi_file_path = 'build/python-api-src/Release/commandcenter.pyi' #Windows
update_pyi_with_docstrings(pyi_file_path)
......@@ -131,6 +131,14 @@ void BaseLocation::setPlayerOccupying(CCPlayer player, bool occupying)
}
}
void BaseLocation::setMinerals(std::vector<Unit> & mineralFields) {
m_minerals = mineralFields;
}
void BaseLocation::setGeysers(std::vector<Unit> & geysers) {
m_geysers = geysers;
}
bool BaseLocation::isInResourceBox(int tileX, int tileY) const
{
CCPositionType px = Util::TileToPosition((float)tileX);
......@@ -204,7 +212,7 @@ void BaseLocation::draw()
// Take first mineral for the Z-pos.
sc2::Point3D center_pos = sc2::Point3D(m_centerOfResources.x, m_centerOfResources.y, m_minerals[0].getUnitPtr()->pos.z);
m_bot.Map().drawResourceCircle(center_pos, radius, CCColor(255, 255, 0));
m_bot.Map().drawResourceSphere(center_pos, radius, CCColor(255, 255, 0));
std::stringstream ss;
ss << "BaseLocation: " << m_baseID << "\n";
......@@ -241,12 +249,12 @@ void BaseLocation::draw()
for (auto & mineral : m_minerals)
{
m_bot.Map().drawResourceCircle(mineral.getUnitPtr()->pos, radius, CCColor(0, 128, 128));
m_bot.Map().drawResourceSphere(mineral.getUnitPtr()->pos, radius, CCColor(0, 128, 128));
}
for (auto & geyser : m_geysers)
{
m_bot.Map().drawResourceCircle(geyser.getUnitPtr()->pos, radius, CCColor(0, 255, 0));
m_bot.Map().drawResourceSphere(geyser.getUnitPtr()->pos, radius, CCColor(0, 255, 0));
}
if (m_isStartLocation)
......
......@@ -50,6 +50,8 @@ public:
bool isInResourceBox(int x, int y) const;
void setPlayerOccupying(CCPlayer player, bool occupying);
void setMinerals(std::vector<Unit> & mineralFields);
void setGeysers(std::vector<Unit> & geysers);
const std::vector<CCTilePosition> & getClosestTiles() const;
......
......@@ -138,6 +138,12 @@ void BaseLocationManager::onFrame()
{
drawBaseLocations();
// make sure that mineralfields and geysers are up to date in the different bases
for (BaseLocation & baselocation : m_baseLocationData) {
updateMinerals(baselocation);
updateGeysers(baselocation);
}
// reset the player occupation information for each location
for (auto & baseLocation : m_baseLocationData)
{
......@@ -247,6 +253,32 @@ void BaseLocationManager::onFrame()
}
void BaseLocationManager::updateMinerals(BaseLocation & baseToUpdate) {
std::vector<Unit> newMinerals;
for (Unit oldMineral : baseToUpdate.getMinerals()) {
for (auto & mineral : m_bot.GetAllUnits()) {
if (oldMineral.getPosition() == mineral.getPosition() && mineral.getType().isMineral()) {
newMinerals.push_back(mineral);
break;
}
}
}
baseToUpdate.setMinerals(newMinerals);
}
void BaseLocationManager::updateGeysers(BaseLocation & baseToUpdate) {
std::vector<Unit> newGeysers;
for (Unit oldGeyser : baseToUpdate.getGeysers()) {
for (auto & geyser : m_bot.GetAllUnits()) {
if (oldGeyser.getPosition() == geyser.getPosition() && geyser.getType().isGeyser()) {
newGeysers.push_back(geyser);
break;
}
}
}
baseToUpdate.setGeysers(newGeysers);
}
BaseLocation * BaseLocationManager::getBaseLocation(const CCPosition & pos) const
{
if (!m_bot.Map().isValidPosition(pos)) { return nullptr; }
......@@ -269,7 +301,7 @@ void BaseLocationManager::drawBaseLocations()
const BaseLocation * next_expansion = getNextExpansion(Players::Self);
CCTilePosition nextExpansionPosition = next_expansion->getDepotPosition();
m_bot.Map().drawResourceCircle(sc2::Point3D(Util::GetPosition(nextExpansionPosition).x, Util::GetPosition(nextExpansionPosition).y, next_expansion->getMinerals()[0].getUnitPtr()->pos.z), 1, CCColor(255, 0, 255));
m_bot.Map().drawResourceSphere(sc2::Point3D(Util::GetPosition(nextExpansionPosition).x, Util::GetPosition(nextExpansionPosition).y, next_expansion->getMinerals()[0].getUnitPtr()->pos.z), 1, CCColor(255, 0, 255));
m_bot.Map().drawText(Util::GetPosition(nextExpansionPosition), "Next Expansion Location", CCColor(255, 0, 255));
}
......@@ -293,7 +325,6 @@ const std::set<const BaseLocation *> & BaseLocationManager::getOccupiedBaseLocat
return m_occupiedBaseLocations.at(player);
}
const BaseLocation * BaseLocationManager::getNextExpansion(int player) const
{
const BaseLocation * homeBase = getPlayerStartingBaseLocation(player);
......
......@@ -32,4 +32,9 @@ public:
const BaseLocation * getNextExpansion(int player) const;
private:
void updateMinerals(BaseLocation & baseToUpdate);
void updateGeysers(BaseLocation & baseToUpdate);
};
......@@ -14,6 +14,23 @@ void BuildingPlacer::onStart()
m_reserveMap = std::vector< std::vector<bool> >(m_bot.Map().width(), std::vector<bool>(m_bot.Map().height(), false));
}
void BuildingPlacer::updateReserved(const std::vector<Unit> & units)
{
freeAllTiles();
for (Unit unit : units) {
reserveTiles(unit.getTilePosition().x, unit.getTilePosition().y, unit.getType().tileWidth(), unit.getType().tileHeight());
}
}
void BuildingPlacer::freeAllTiles() {
for (int x = 0; x < m_reserveMap.size(); x++) {
for (int y = 0; y < m_reserveMap[x].size(); y++) {
m_reserveMap[x][y] = false;
}
}
}
bool BuildingPlacer::isInResourceBox(int tileX, int tileY) const
{
return m_bot.Bases().getPlayerStartingBaseLocation(Players::Self)->isInResourceBox(tileX, tileY);
......@@ -27,12 +44,17 @@ bool BuildingPlacer::canBuildHere(int bx, int by, const UnitType & type) const
return false;
}
// check the reserve map
for (int x = bx; x < bx + type.tileWidth(); x++)
int width = type.tileWidth();
int height = type.tileHeight();
int xdelta = (int)std::ceil((width - 1.0) / 2);
int ydelta = (int)std::ceil((height - 1.0) / 2);
// check the reserve map, that it is a valid tile and not a wall
for (int x = bx - xdelta; x < bx + width - xdelta; x++)
{
for (int y = by; y < by + type.tileHeight(); y++)
for (int y = by - ydelta; y < by + height - ydelta; y++)
{
if (!m_bot.Map().isValidTile(x, y) || m_reserveMap[x][y])
if (!m_bot.Map().isValidTile(x, y) || isReserved(x, y) || !m_bot.Map().isWalkable(x, y))
{
return false;
}
......@@ -48,6 +70,59 @@ bool BuildingPlacer::canBuildHere(int bx, int by, const UnitType & type) const
return true;
}
bool BuildingPlacer::canBuildHereWithSize(int bx, int by, int width, int height)
{
if (isInResourceBox(bx, by))
{
return false;
}
int xdelta = (int)std::ceil((width - 1.0) / 2);
int ydelta = (int)std::ceil((height - 1.0) / 2);
// check the reserve map, that it is a valid tile and not a wall
for (int x = bx - xdelta; x < bx + width - xdelta; x++)
{
for (int y = by - ydelta; y < by + height - ydelta; y++)
{
if (!m_bot.Map().isValidTile(x, y) || isReserved(x, y) || !m_bot.Map().isWalkable(x, y))
{
return false;
}
}
}
// Check so it doesn't overlap with a baselocation
// dimensions of the proposed location
int tx1 = bx - xdelta;
int ty1 = by - ydelta;
int tx2 = tx1 + width - xdelta;
int ty2 = ty1 + height - ydelta;
// for each base location
for (const BaseLocation * base : m_bot.Bases().getBaseLocations())
{
// dimensions of the base location
int bx1 = (int)base->getDepotPosition().x;
int by1 = (int)base->getDepotPosition().y;
int bx2 = bx1 + Util::GetTownHall(m_bot.GetPlayerRace(Players::Self), m_bot).tileWidth();
int by2 = by1 + Util::GetTownHall(m_bot.GetPlayerRace(Players::Self), m_bot).tileHeight();
// conditions for non-overlap are easy
bool noOverlap = (tx2 < bx1) || (tx1 > bx2) || (ty2 < by1) || (ty1 > by2);
// If there is overlap, return false
if (!noOverlap)
{
return false;
}
}
// otherwise there is no overlap
return true;
}
//returns true if we can build this type of unit here with the specified amount of space.
bool BuildingPlacer::canBuildHereWithSpace(int bx, int by, const UnitType & type, int buildDist) const
{
......@@ -59,24 +134,33 @@ bool BuildingPlacer::canBuildHereWithSpace(int bx, int by, const UnitType & type
// height and width of the building
int width = type.tileWidth();
int height = type.tileHeight();
int xdelta = (int)std::ceil((width - 1.0) / 2);
int ydelta = (int)std::ceil((height - 1.0) / 2);
// TODO: make sure we leave space for add-ons. These types of units can have addons:
// define the rectangle of the building spot
int startx = bx - buildDist;
int starty = by - buildDist;
int endx = bx + width + buildDist - 1;
int endy = by + height + buildDist - 1;
int startx = bx - buildDist - xdelta;
int starty = by - buildDist - ydelta;
int endx = bx + width + buildDist - xdelta;
int endy = by + height + buildDist - ydelta;
// TODO: recalculate start and end positions for addons
// if this rectangle doesn't fit on the map we can't build here
if (startx < 0 || starty < 0 || endx > m_bot.Map().width() || endx < bx + width - 1 || endy > m_bot.Map().height() - 1)
if (startx < 0 || starty < 0 || endx > m_bot.Map().width() || endx < bx + width - xdelta || endy > m_bot.Map().height() || endy < by + height - ydelta)
{
return false;
}
if (!m_bot.Map().canBuildTypeAtPosition(bx, by, type))
{
return false;
}
// if we can't build here, or space is reserved, or it's in the resource box, we can't build here
for (int x = startx; x < endx; x++)
{
......@@ -84,7 +168,7 @@ bool BuildingPlacer::canBuildHereWithSpace(int bx, int by, const UnitType & type
{
if (!type.isRefinery())
{
if (!buildable(type, x, y) || m_reserveMap[x][y])
if (!buildable(type, x, y) || isReserved(x, y) || !m_bot.Map().isWalkable(x, y)) // added isWalkabale in order to check towards walls
{
return false;
}
......@@ -137,10 +221,14 @@ bool BuildingPlacer::tileOverlapsBaseLocation(int x, int y, UnitType type) const
}
// dimensions of the proposed location
int tx1 = x;
int ty1 = y;
int tx2 = tx1 + type.tileWidth();
int ty2 = ty1 + type.tileHeight();
int xdelta = (int)std::ceil((type.tileWidth() - 1.0) / 2);
int ydelta = (int)std::ceil((type.tileHeight() - 1.0) / 2);
int tx1 = x - xdelta;
int ty1 = y - ydelta;
int tx2 = tx1 + type.tileWidth() - xdelta;
int ty2 = ty1 + type.tileHeight() - ydelta;
// for each base location
for (const BaseLocation * base : m_bot.Bases().getBaseLocations())
......@@ -168,7 +256,7 @@ bool BuildingPlacer::tileOverlapsBaseLocation(int x, int y, UnitType type) const
bool BuildingPlacer::buildable(const UnitType & type, int x, int y) const
{
// TODO: does this take units on the map into account?
if (!m_bot.Map().isValidTile(x, y) || !m_bot.Map().canBuildTypeAtPosition(x, y, type))
if (!m_bot.Map().isValidTile(x, y))
{
return false;
}
......@@ -180,11 +268,16 @@ bool BuildingPlacer::buildable(const UnitType & type, int x, int y) const
void BuildingPlacer::reserveTiles(int bx, int by, int width, int height)
{
// THIS is never called, that's why spacing doesnt work correctly
int rwidth = (int)m_reserveMap.size();
int rheight = (int)m_reserveMap[0].size();
for (int x = bx; x < bx + width && x < rwidth; x++)
int xdelta = (int)std::ceil((width - 1.0) / 2);
int ydelta = (int)std::ceil((height - 1.0) / 2);
for (int x = bx - xdelta; x < bx + width - xdelta && x < rwidth; x++)
{
for (int y = by; y < by + height && y < rheight; y++)
for (int y = by - ydelta; y < by + height - ydelta && y < rheight; y++)
{
m_reserveMap[x][y] = true;
}
......@@ -215,9 +308,12 @@ void BuildingPlacer::freeTiles(int bx, int by, int width, int height)
int rwidth = (int)m_reserveMap.size();
int rheight = (int)m_reserveMap[0].size();
for (int x = bx; x < bx + width && x < rwidth; x++)
int xdelta = (int)std::ceil((width - 1.0) / 2);
int ydelta = (int)std::ceil((height - 1.0) / 2);
for (int x = bx - xdelta; x < bx + width - xdelta && x < rwidth; x++)
{
for (int y = by; y < by + height && y < rheight; y++)
for (int y = by - ydelta; y < by + height - ydelta && y < rheight; y++)
{
m_reserveMap[x][y] = false;
}
......
......@@ -5,6 +5,7 @@
class IDABot;
class BaseLocation;
class UnitType;
class Unit;
class BuildingPlacer
{
......@@ -23,9 +24,12 @@ public:
BuildingPlacer(IDABot & bot);
void onStart();
void updateReserved(const std::vector<Unit> & units);
void freeAllTiles();
// determines whether we can build at a given location
bool canBuildHere(int bx, int by, const UnitType & type) const;
bool canBuildHereWithSize(int bx, int by, int width, int height);
bool canBuildHereWithSpace(int bx, int by, const UnitType & type, int buildDist) const;
// returns a build location near a building's desired location
......
#include "IDABot.h"
#include "Util.h"
#include "sc2api/sc2_score.h"
IDABot::IDABot()
......@@ -73,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()
......@@ -152,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);
}
......@@ -232,7 +247,22 @@ const TypeData & IDABot::Data(const MetaType & type) const
void IDABot::DebugCreateUnit(UnitTypeID unit_type, const CCPosition& p, uint32_t player_id, uint32_t count)
{
Debug()->DebugCreateUnit(unit_type, p, player_id, 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)
......@@ -339,9 +369,9 @@ void IDABot::CameraMove(Point2DI p)
ActionsFeatureLayer()->CameraMove(p);
}
const char* IDABot::abilityForUpgrade(sc2::UpgradeID upgrade_id) const
sc2::ABILITY_ID IDABot::abilityForUpgrade(sc2::UpgradeID upgrade_id) const
{
return sc2::AbilityTypeToName(Observation()->GetUpgradeData()[upgrade_id].ability_id);
return (sc2::ABILITY_ID)Observation()->GetUpgradeData()[upgrade_id].ability_id;
}
uint32_t IDABot::UpgradeMineralCost(sc2::UpgradeID upgrade_id) const
......@@ -362,4 +392,25 @@ float IDABot::UpgradeResearchTime(sc2::UpgradeID upgrade_id) const
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
......@@ -38,6 +38,7 @@ public:
void OnGameStart() override;
void OnStep() override;
void OnGameEnd() override;
/*
API for students
......@@ -87,12 +88,17 @@ public:
const std::vector<Point2D> GetEnemyBaseLocations();
bool HasCreep(Point2D p) const;
void CameraMove(Point2DI p);
const char* abilityForUpgrade(sc2::UpgradeID upgrade_id) const;
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
......
#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;
};
......@@ -40,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)
......@@ -54,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();
......@@ -278,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];
}
......@@ -344,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
......@@ -371,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
......@@ -401,7 +408,7 @@ void MapTools::drawCircle(const CCPosition & pos, CCPositionType radius, const C
#endif
}
void MapTools::drawResourceCircle(const sc2::Point3D & pos, CCPositionType radius, const CCColor & color) const
void MapTools::drawResourceSphere(const sc2::Point3D & pos, CCPositionType radius, const CCColor & color) const
{
#ifdef SC2API
m_bot.Debug()->DebugSphereOut(pos, radius, color);
......@@ -538,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();
......
......@@ -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
......@@ -45,16 +46,18 @@ public:
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 drawResourceCircle(const sc2::Point3D & 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;
......