From 42410e25f5c1dab5148085dc777fa2a635ee6ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Bergstr=C3=B6m?= <davbe125@student.liu.se> Date: Wed, 1 Aug 2018 08:43:02 +0200 Subject: [PATCH] Rework TechTree and TechTreeImproved Integrate all information from TechTreeImproved into the existing class TechTree. Thus TechTreeImproved is deprecated and removed from the Python-API. --- python-api-src/library.cpp | 3 ++- src/TechTree.cpp | 44 +++++++++++++++++++++----------------- src/TechTreeImproved.cpp | 43 ++++++++++++++++++++++++++++++++++--- src/TechTreeImproved.h | 9 ++++++-- 4 files changed, 73 insertions(+), 26 deletions(-) diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp index 165d95ca9..73222c244 100644 --- a/python-api-src/library.cpp +++ b/python-api-src/library.cpp @@ -112,12 +112,12 @@ PYBIND11_MODULE(library, m) m.def("create_participants", &sc2::CreateParticipant, "Create participant from bot", "race"_a, "bot"_a); m.def("create_computer", &sc2::CreateComputer, "Create participant from built-in Starcraft computer", "race"_a, "difficulty"_a); + /* py::class_<BuildDescription>(m, "BuildDescription") .def(py::init()) .def_readwrite("producer_type", &BuildDescription::producer_type) .def_readwrite("result_type", &BuildDescription::result_type) .def_readwrite("ability_used", &BuildDescription::ability_used) - .def_readwrite("time", &BuildDescription::time) .def_readwrite("buildings_needed", &BuildDescription::buildings_needed) .def_readwrite("addons_needed", &BuildDescription::addons_needed); @@ -125,4 +125,5 @@ PYBIND11_MODULE(library, m) .def(py::init()) .def("load_data", &TechTreeImproved::LoadData) .def("how_to_build", &TechTreeImproved::HowToBuild); + */ } diff --git a/src/TechTree.cpp b/src/TechTree.cpp index 576ec8804..a358e4d4e 100644 --- a/src/TechTree.cpp +++ b/src/TechTree.cpp @@ -27,35 +27,39 @@ void TechTree::onStart() return; } - for (std::pair<const UnitType, TypeData> & pair : m_unitTypeData) + std::set<sc2::UNIT_TYPEID> updated; + + for (const BuildDescription & description : tree.BuildDescriptions()) { - TypeData & data = pair.second; + if (m_unitTypeData.count(UnitType(description.result_type, m_bot)) == 0) + { + std::cout << "Inserting new information about UNIT_TYPEID: " + << sc2::UnitTypeToName(description.result_type) << " (" + << static_cast<unsigned int>(description.result_type) << ")" + << std::endl; + } - const std::vector<BuildDescription> & howToBuild = tree.HowToBuild(pair.first.getAPIUnitType()); + TypeData & data = m_unitTypeData[UnitType(description.result_type, m_bot)]; - if (howToBuild.empty()) + // If this is the first time we a way to build this type, remove previous data + if (updated.count(description.result_type) == 0) { - continue; + data.whatBuilds.clear(); + data.requiredUnits.clear(); + data.requiredUpgrades.clear(); + updated.insert(description.result_type); } - data.whatBuilds.clear(); - data.requiredUnits.clear(); - // TODO: Support for upgrades, is it possible via JSON? Is the hard coded information correct? - data.requiredUpgrades.clear(); + data.whatBuilds.push_back(UnitType(description.producer_type, m_bot)); - for (const BuildDescription & description : howToBuild) + for (sc2::UNIT_TYPEID unit_typeid : description.buildings_needed) { - data.whatBuilds.push_back(UnitType(description.producer_type, m_bot)); - - for (sc2::UNIT_TYPEID unit_typeid : description.buildings_needed) - { - data.requiredUnits.push_back(UnitType(unit_typeid, m_bot)); - } + data.requiredUnits.push_back(UnitType(unit_typeid, m_bot)); + } - for (sc2::UNIT_TYPEID unit_typeid : description.addons_needed) - { - data.requiredAddons.push_back(UnitType(unit_typeid, m_bot)); - } + for (sc2::UNIT_TYPEID unit_typeid : description.addons_needed) + { + data.requiredAddons.push_back(UnitType(unit_typeid, m_bot)); } } diff --git a/src/TechTreeImproved.cpp b/src/TechTreeImproved.cpp index ab0a36b96..9a20e5535 100644 --- a/src/TechTreeImproved.cpp +++ b/src/TechTreeImproved.cpp @@ -27,7 +27,7 @@ void add_requirement(ResearchDescription & description, json & requirement) } else if (type == "not") { - // Ignore this. This is mostly used for: "We cannot do upgrade X if upgrade X is already running somewhere." + // Ignore this. This is used for: "We cannot do upgrade X if upgrade X is already running somewhere." } else if (type == "unitCount") { @@ -114,7 +114,8 @@ void add_requirement(BuildDescription & description, json & requirement) void parse_build_description(BuildDescription & description, json & build_item) { - description.result_type = build_item["unit"]; + description.result_type = static_cast<sc2::UNIT_TYPEID>(build_item["unit"]); + description.ability_used = static_cast<sc2::ABILITY_ID>(build_item["ability"]); if (build_item.find("requires") != build_item.end()) { @@ -142,7 +143,6 @@ void TechTreeImproved::parse_unit(json::iterator it) { sc2::UNIT_TYPEID producer_id = string_to_id(it.key()); //std::string name = sc2::UnitTypeToName(producer_id); - std::vector<BuildDescription> build_descriptions; if (it.value().find("builds") != it.value().end()) { @@ -163,6 +163,7 @@ void TechTreeImproved::parse_unit(json::iterator it) { result_to_data[description.result_type] = { description }; } + build_descriptions.push_back(description); } } @@ -186,6 +187,42 @@ void TechTreeImproved::parse_unit(json::iterator it) { upgrade_to_data[description.result_type] = { description }; } + research_descriptions.push_back(description); + } + } + + if (it.value().find("morphs") != it.value().end()) + { + for (auto & morph_item : it.value()["morphs"]) + { + BuildDescription description; + description.producer_type = producer_id; + description.ability_used = static_cast<sc2::ABILITY_ID>(morph_item["ability"]); + description.result_type = static_cast<sc2::UNIT_TYPEID>(morph_item["unit"]); + + if (morph_item.find("requires") != morph_item.end()) + { + for (auto & requirement : morph_item["requires"]) + { + std::string type = requirement["type"]; + if (type == "unitCount") + { + for (auto & unit : requirement["unit"]) + { + sc2::UNIT_TYPEID unit_typeid = static_cast<sc2::UNIT_TYPEID>(unit); + description.buildings_needed.push_back(unit_typeid); + } + } + else if (type == "upgradeCount") + { + sc2::UPGRADE_ID upgrade_id = static_cast<sc2::UPGRADE_ID>(requirement["upgrade"]); + description.upgrades_needed.push_back(upgrade_id); + } + } + + } + + build_descriptions.push_back(description); } } } diff --git a/src/TechTreeImproved.h b/src/TechTreeImproved.h index 5e9710a86..55b022701 100644 --- a/src/TechTreeImproved.h +++ b/src/TechTreeImproved.h @@ -12,12 +12,11 @@ struct BuildDescription { sc2::UNIT_TYPEID producer_type; sc2::UNIT_TYPEID result_type; - // TODO: Are these 2 used? sc2::AbilityID ability_used; - float time; std::vector<sc2::UNIT_TYPEID> buildings_needed; std::vector<sc2::UNIT_TYPEID> addons_needed; + std::vector<sc2::UPGRADE_ID> upgrades_needed; }; struct ResearchDescription @@ -35,6 +34,9 @@ class TechTreeImproved std::map<sc2::UNIT_TYPEID, std::vector<BuildDescription>> result_to_data; std::map<sc2::UPGRADE_ID, std::vector<ResearchDescription>> upgrade_to_data; + std::vector<BuildDescription> build_descriptions; + std::vector<ResearchDescription> research_descriptions; + // If there is no BuildDescription for a given type, a reference to tihs list is returned. const std::vector<BuildDescription> empty_build {}; const std::vector<ResearchDescription> empty_research {}; @@ -46,4 +48,7 @@ public: // Given a unit, how can we build it? const std::vector<BuildDescription> & HowToBuild(sc2::UnitTypeID unit) const; const std::vector<ResearchDescription> & HowToResearch(sc2::UpgradeID upgrade) const; + + const std::vector<BuildDescription> & BuildDescriptions() const { return build_descriptions; } + const std::vector<ResearchDescription> & ResearchDescriptions() const { return research_descriptions; } }; \ No newline at end of file -- GitLab