diff --git a/create-visual-studio-solution-python37.sh b/create-visual-studio-solution-python37.sh new file mode 100644 index 0000000000000000000000000000000000000000..828e5cb115dc98eedaca8ad5cd192d18f12c5382 --- /dev/null +++ b/create-visual-studio-solution-python37.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +mkdir build37 +cd build37 +"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python37/python.exe" diff --git a/create-visual-studio-solution-python38.sh b/create-visual-studio-solution-python38.sh new file mode 100644 index 0000000000000000000000000000000000000000..081c3e887218f6621b141865c47dc7dc70aabcdf --- /dev/null +++ b/create-visual-studio-solution-python38.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +mkdir build38 +cd build38 +"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python38/python.exe" + diff --git a/create-visual-studio-solution.sh b/create-visual-studio-solution.sh deleted file mode 100644 index 713b010d401540aaa236db87f8f054f3417cb060..0000000000000000000000000000000000000000 --- a/create-visual-studio-solution.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -mkdir build -cd build -"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" diff --git a/docs/idabot.rst b/docs/idabot.rst index 31864ba8000e44e0002e2c8bcaef839057a34066..2a3b0c0d2f9c1339bb38c7ea32f358afc5f71ae9 100644 --- a/docs/idabot.rst +++ b/docs/idabot.rst @@ -55,6 +55,10 @@ IDABot Returns the players race, useful if you play Race.Random + .. method:: IDABot.send_chat(self, message) + + Sends the string 'message' to the game chat + Attributes: .. autoattribute:: minerals diff --git a/docs/unit.rst b/docs/unit.rst index 88e0f527e1a9467e276dd1f72dff9f5027a73711..d298b02253208bd1905dfdd18e0aabf3010d812f 100644 --- a/docs/unit.rst +++ b/docs/unit.rst @@ -48,7 +48,6 @@ Unit Returns build_progress >= 1 - .. autoattribute:: is_constructing .. autoattribute:: is_flying .. autoattribute:: is_idle .. autoattribute:: is_powered @@ -74,6 +73,9 @@ Unit .. autoattribute:: tile_position .. autoattribute:: unit_type .. autoattribute:: weapon_cooldown + .. autoattribute:: is_carrying_minerals + + Returns if this unit is currently holding minerals .. attribute:: Unit.target @@ -85,6 +87,10 @@ Unit Call an ability directly, different abilities has different targets. Some target the unit itself (no argument), target a point (Point2D as argument) and some target a Unit (instance of Unit as argument). + .. method:: Unit.is_constructing(self, unit_type: library.UnitType) + + Returns true if the unit is currently constructing another unit of type `unit_type`. Note that `unit_type` needs to be an instance of :class:`library.UnitType`. + .. automethod:: stop .. automethod:: attack_unit .. automethod:: attack_move diff --git a/python-api-src/lib_sc2_typeenums.cpp b/python-api-src/lib_sc2_typeenums.cpp index 03ae7992ff11558485830f52ebb7d2aa7c934059..235056ce29cc1711fc5297aa93dd85ab90013fc3 100644 --- a/python-api-src/lib_sc2_typeenums.cpp +++ b/python-api-src/lib_sc2_typeenums.cpp @@ -217,7 +217,8 @@ void define_typeenums(py::module & m) .value("NEUTRAL_UNBUILDABLEPLATESDESTRUCTIBLE", sc2::UNIT_TYPEID::NEUTRAL_UNBUILDABLEPLATESDESTRUCTIBLE) .value("NEUTRAL_UTILITYBOT", sc2::UNIT_TYPEID::NEUTRAL_UTILITYBOT) .value("NEUTRAL_VESPENEGEYSER", sc2::UNIT_TYPEID::NEUTRAL_VESPENEGEYSER) - .value("NEUTRAL_XELNAGATOWER", sc2::UNIT_TYPEID::NEUTRAL_XELNAGATOWER); + .value("NEUTRAL_XELNAGATOWER", sc2::UNIT_TYPEID::NEUTRAL_XELNAGATOWER) + .def("__eq__", [](const sc2::UNIT_TYPEID &value, sc2::UnitTypeID &value2) { return value == value2; }); py::enum_<sc2::ABILITY_ID>(m, "ABILITY_ID") .value("INVALID", sc2::ABILITY_ID::INVALID) diff --git a/python-api-src/lib_tech_tree.cpp b/python-api-src/lib_tech_tree.cpp index ff9b2d54fd36ce2adbb9a9be065fedb4a0242db0..69b4e27752e05c58c45a5f81dc7d7ed22977a7c5 100644 --- a/python-api-src/lib_tech_tree.cpp +++ b/python-api-src/lib_tech_tree.cpp @@ -9,7 +9,7 @@ void define_tech_tree(py::module & m) .def_readonly("mineral_cost", &TypeData::mineralCost, "mineral cost of the item") .def_readonly("gas_cost", &TypeData::gasCost, "gas cost of the item") .def_readonly("supply_cost", &TypeData::supplyCost, "supply cost of the item") - .def_readonly("build_time", &TypeData::buildTime, "build time of the item") + .def_readonly("build_time", &TypeData::buildTime, "build time of the item in seconds (should be 32 game updates per tick, can someone verify this?)") .def_readonly("is_unit", &TypeData::isUnit) .def_readonly("is_building", &TypeData::isBuilding) .def_readonly("is_worker", &TypeData::isWorker) @@ -27,4 +27,4 @@ void define_tech_tree(py::module & m) py::class_<TechTree>(m, "TechTree") .def("get_data", py::overload_cast<const UnitType &>(&TechTree::getData, py::const_)) .def("get_data", py::overload_cast<const CCUpgrade &>(&TechTree::getData, py::const_)); -} \ No newline at end of file +} diff --git a/python-api-src/lib_unit.cpp b/python-api-src/lib_unit.cpp index cb99e65615ae22a661ef9a954f2640f316e1dbb5..83b3166272f4303cabb444eec4da2b6bda75d084 100644 --- a/python-api-src/lib_unit.cpp +++ b/python-api-src/lib_unit.cpp @@ -34,6 +34,7 @@ void define_unit(py::module & m) .def_property_readonly("current_ability_id", &Unit::getCurrentAbilityID, "The AbilityID of currently used ability") .def_property_readonly("facing", &Unit::getFacing) .def_property_readonly("radius", &Unit::getRadius) + .def_property_readonly("is_carrying_minerals", &Unit::isCarryingMinerals) .def("hold_position", &Unit::holdPosition) .def("patrol", py::overload_cast<const CCPosition &>(&Unit::patrol, py::const_)) .def("stop_dance", &Unit::stopDance) diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp index 78e0330481d1cd51be6f418aa221143ef4614a03..b1818c27be7737444af08bed9406b16407132574 100644 --- a/python-api-src/library.cpp +++ b/python-api-src/library.cpp @@ -47,22 +47,17 @@ PYBIND11_MODULE(library, m) m.attr("PLAYER_NEUTRAL") = py::int_((int) Players::Neutral); m.attr("PLAYER_ALLY") = py::int_((int) Players::Ally); - /* - TODO: BuffID is not defined, defined as following by Blizzard: - typedef SC2Type<BUFF_ID> BuffID; - */ py::class_<sc2::BuffID>(m, "BuffID") .def(py::init<sc2::BUFF_ID>()); py::implicitly_convertible<sc2::BUFF_ID, sc2::BuffID>(); - py::class_<sc2::UnitTypeID>(m, "UnitTypeID") - .def(py::init<sc2::UNIT_TYPEID>()); + .def(py::init<sc2::UNIT_TYPEID>()) + .def("__eq__", [](const sc2::UnitTypeID &value, sc2::UNIT_TYPEID &value2) { return value == value2; }); py::implicitly_convertible<sc2::UNIT_TYPEID, sc2::UnitTypeID>(); - py::class_<sc2::UpgradeID>(m, "UpgradeID") .def(py::init<sc2::UPGRADE_ID>()); @@ -82,6 +77,7 @@ PYBIND11_MODULE(library, m) .def(py::init()) .def("on_game_start", &IDABot::OnGameStart) .def("on_step", &IDABot::OnStep) + .def("send_chat", &IDABot::SendChat, "Send a message to the game chat", "message"_a) .def("get_all_units", &IDABot::GetAllUnits, "Returns a list of all units") .def("get_my_units", &IDABot::GetMyUnits, "Returns a list of all units beloning to the player") .def("get_player_race", &IDABot::GetPlayerRace) diff --git a/src/IDABot.cpp b/src/IDABot.cpp index c12fe5ab76ceddd8b69575208806c514718c3265..d0908f789cb42ab5675a0028889085a4918d79bd 100644 --- a/src/IDABot.cpp +++ b/src/IDABot.cpp @@ -199,6 +199,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); diff --git a/src/IDABot.h b/src/IDABot.h index eca954f01a1857bf31747ae128a239b86dc19e88..a1567ac9f75b75b6d5268cb3c4f3e372e8eac23e 100644 --- a/src/IDABot.h +++ b/src/IDABot.h @@ -46,6 +46,8 @@ public: CCPosition GetStartLocation() const; BuildingPlacer & GetBuildingPlacer(); + void SendChat(const std::string & message); + int GetCurrentFrame() const; int GetMinerals() const; int GetCurrentSupply() const; diff --git a/src/TechTree.cpp b/src/TechTree.cpp index fdd3f3f5c8b8ae23c9b374ef6b2ae742ba9597f6..89d511f7a0d7a0fb8fc752c0c009474cab4d50a8 100644 --- a/src/TechTree.cpp +++ b/src/TechTree.cpp @@ -48,6 +48,7 @@ void TechTree::onStart() data.requiredUnits.clear(); data.requiredUpgrades.clear(); updated.insert(description.result_type); + data.buildTime = description.buildTime; // The time in seconds it takes to create the unit data.buildAbility = sc2::ABILITY_ID::INVALID; } @@ -382,4 +383,4 @@ const TypeData & TechTree::getData(const MetaType & type) const BOT_ASSERT(false, "Can't getData this type: %s", type.getName().c_str()); return m_unitTypeData.begin()->second; -} \ No newline at end of file +} diff --git a/src/TechTreeImproved.cpp b/src/TechTreeImproved.cpp index 8b07889aeb8510c3a9eb1a4b6289bf674e521540..7e991fadd4877762531bf4d545a0ad0d870fb8ad 100644 --- a/src/TechTreeImproved.cpp +++ b/src/TechTreeImproved.cpp @@ -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()) { diff --git a/src/TechTreeImproved.h b/src/TechTreeImproved.h index 0948a328c5e9a9216b7a8ff7e3f85eba5ba70dd3..1b650e60d8a4f742f2fcce6803e9a8583863058b 100644 --- a/src/TechTreeImproved.h +++ b/src/TechTreeImproved.h @@ -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 +}; diff --git a/src/Unit.cpp b/src/Unit.cpp index 0bb94a9784e987fff2898534f944bc8018e7b816..9cc165a2b2a1c72aec083346c0a0235f3fc513da 100644 --- a/src/Unit.cpp +++ b/src/Unit.cpp @@ -328,7 +328,6 @@ void Unit::ability(sc2::AbilityID ability, const Unit& target) const Unit Unit::getTarget() const { BOT_ASSERT(isValid(), "Unit is not valid"); - BOT_ASSERT(hasTarget(), "Unit has no target"); // if unit has order, check tag of target of first order if(getUnitPtr()->orders.size() > 0){ @@ -426,3 +425,17 @@ void Unit::stopDance() const BOT_ASSERT(isValid(), "Unit is not valid"); m_bot->Actions()->UnitCommand(m_unit, sc2::ABILITY_ID::STOP_DANCE); } + +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; +} diff --git a/src/Unit.h b/src/Unit.h index 3d5017726eb16b1b6ccc9ede69c6e1b9cc30571d..5a7cef49664e37ee60a197e26a12cbf8065f9854 100644 --- a/src/Unit.h +++ b/src/Unit.h @@ -47,6 +47,7 @@ public: bool isValid() const; bool isTraining() const; bool isConstructing(const UnitType & type) const; + bool isCarryingMinerals() const; bool isBlip() const; bool hasTarget() const; diff --git a/tests/unittypeid.py b/tests/unittypeid.py new file mode 100644 index 0000000000000000000000000000000000000000..f3815d9002078987949f31beac2dec8cb93123b3 --- /dev/null +++ b/tests/unittypeid.py @@ -0,0 +1,25 @@ +import unittest +import sys + +sys.path.append('build/python-api-src') + +from library 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() +