diff --git a/.gitmodules b/.gitmodules index 409400680c1c970f60088e7df0ce5464dfa98f19..fe287996fa08fc117d22f686da8778a8bf62c9f7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "lib/s2client-api"] path = lib/s2client-api url = git@github.com:Blizzard/s2client-api.git +[submodule "lib/sc2-gamedata"] + path = lib/sc2-gamedata + url = git@github.com:noorus/sc2-gamedata.git +[submodule "lib/json"] + path = lib/json + url = git@github.com:nlohmann/json.git diff --git a/lib/json b/lib/json new file mode 160000 index 0000000000000000000000000000000000000000..7bfc406ded0434c438dd22139a8baa97f2ffa90e --- /dev/null +++ b/lib/json @@ -0,0 +1 @@ +Subproject commit 7bfc406ded0434c438dd22139a8baa97f2ffa90e diff --git a/lib/sc2-gamedata b/lib/sc2-gamedata new file mode 160000 index 0000000000000000000000000000000000000000..a82b9aeed5be23149e3f79b31793bdc29bab3923 --- /dev/null +++ b/lib/sc2-gamedata @@ -0,0 +1 @@ +Subproject commit a82b9aeed5be23149e3f79b31793bdc29bab3923 diff --git a/python-api-src/CMakeLists.txt b/python-api-src/CMakeLists.txt index 34bace60a22c64f8896fe18ff8f813002f81783e..d2d99321846b3d88be23729a773e9f254cf4b06d 100644 --- a/python-api-src/CMakeLists.txt +++ b/python-api-src/CMakeLists.txt @@ -2,6 +2,7 @@ include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/s2client-api/include ${PROJECT_SOURCE_DIR}/lib/s2client-api/contrib/protobuf/src ${PROJECT_BINARY_DIR}/lib/s2client-api/generated + ${PROJECT_SOURCE_DIR}/lib/json/include ) # All the source files for the bot. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 46ecfe83169f51a2b3965eac0ce556a5e0546dd8..3c540390a0c1d6d73f9486fb28f6c7480e6c4b57 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/s2client-api/include ${PROJECT_SOURCE_DIR}/lib/s2client-api/contrib/protobuf/src ${PROJECT_BINARY_DIR}/lib/s2client-api/generated + ${PROJECT_SOURCE_DIR}/lib/json/include ) link_directories(${PROJECT_BINARY_DIR}/s2client-api/bin) diff --git a/src/IDABot.h b/src/IDABot.h index cab9f2551cf156011d937edb6ab20a8b46668c4d..94c7621dcc55e1b365711dd41dd9efbade8dfecc 100644 --- a/src/IDABot.h +++ b/src/IDABot.h @@ -10,6 +10,7 @@ #include "UnitInfoManager.h" #include "BuildingPlacer.h" #include "TechTree.h" +#include "TechTreeImproved.h" #include "MetaType.h" #include "Unit.h" diff --git a/src/MyAgent.cpp b/src/MyAgent.cpp index 087ca3328b28b3aedfa9fea96b7e6067cfb53e7a..4fd66e698d0d266fce9a4a14bc081d99c44fb812 100644 --- a/src/MyAgent.cpp +++ b/src/MyAgent.cpp @@ -8,6 +8,20 @@ MyAgent::MyAgent() void MyAgent::OnGameStart() { IDABot::OnGameStart(); + + sc2::UnitTypeID wanted_type = sc2::UNIT_TYPEID::TERRAN_GHOST; + sc2::UnitTypeData wanted_data = Observation()->GetUnitTypeData()[wanted_type]; + std::cout << "Looking up: " << wanted_data.name << std::endl; + sc2::UnitTypeData requirement = Observation()->GetUnitTypeData()[wanted_data.tech_requirement]; + std::cout << "Found tech requirement: " << requirement.name << "(" << wanted_data.tech_requirement << ")" << std::endl; + std::cout << std::boolalpha; + std::cout << "Require attached (Is addon?): " << wanted_data.require_attached << std::endl; + + std::cout << "Found ability_id" << wanted_data.ability_id << std::endl; + // TODO: What/who can use this ability?? + + sc2::AbilityData ability_to_create = Observation()->GetAbilityData()[wanted_data.ability_id]; + std::cout << "Button name for ability " << ability_to_create.button_name << std::endl; } void MyAgent::OnStep() diff --git a/src/TechTreeImproved.cpp b/src/TechTreeImproved.cpp new file mode 100644 index 0000000000000000000000000000000000000000..914e2f4689912ca47677f8e5d965a8af1846a2e9 --- /dev/null +++ b/src/TechTreeImproved.cpp @@ -0,0 +1,129 @@ +#include "TechTreeImproved.h" + +using json = nlohmann::json; + +TechTreeImproved::TechTreeImproved() { } + +sc2::UNIT_TYPEID string_to_id(const std::string & str) +{ + return static_cast<sc2::UNIT_TYPEID>(std::stoi(str)); +} + +std::string id_to_string(int id) +{ + return sc2::UnitTypeToName(static_cast<sc2::UNIT_TYPEID>(id)); +} + +void add_requirement(json & requirement, BuildAlternative & alternative) +{ + std::string type = requirement["type"]; + if (type == "and") + { + for (auto & subrequirement : requirement["operands"]) + { + add_requirement(subrequirement, alternative); + } + } + else if (type == "unitCount") + { + if (requirement["state"] == "CompleteOnlyAtUnit") + { + for (auto & unit : requirement["unit"]) + { + //std::cout << "Addon: " << sc2::UnitTypeToName(static_cast<sc2::UNIT_TYPEID>(unit)) << " (" << unit << ")" << std::endl; + alternative.addons_needed.push_back(static_cast<sc2::UNIT_TYPEID>(unit)); + } + } + else if (requirement["state"] == "CompleteOnly") + { + for (auto & unit : requirement["unit"]) + { + //std::cout << "Just building: " << sc2::UnitTypeToName(static_cast<sc2::UNIT_TYPEID>(unit)) << " (" << unit << ")" << std::endl; + alternative.buildings_needed.push_back(static_cast<sc2::UNIT_TYPEID>(unit)); + } + } + else + { + //std::cout << "Unsupported" << std::endl; + //std::cout << requirement << std::endl; + } + } +} + +BuildAlternative parse_build_alternative(json & build_item) +{ + BuildAlternative alternative{ build_item["unit"] }; + + if (build_item.find("requires") != build_item.end()) + { + //std::cout << "Building unit: " << id_to_string(build_item["unit"]) << " requires" << std::endl; + auto & requires = build_item["requires"][0]; + add_requirement(requires, alternative); + } + return alternative; +} + +std::pair<sc2::UNIT_TYPEID, std::vector<BuildAlternative>> parse_unit(json::iterator it) +{ + sc2::UNIT_TYPEID id = string_to_id(it.key()); + std::string name = sc2::UnitTypeToName(id); + std::vector<BuildAlternative> build_alternatives; + + if (it.value().find("builds") != it.value().end()) + { + auto & builds = it.value()["builds"]; + for (auto & build_item : builds) + { + BuildAlternative build_alternative = parse_build_alternative(build_item); + build_alternatives.push_back(build_alternative); + } + } + return { id, build_alternatives }; +} + +void TechTreeImproved::LoadData() { + // TODO: Do not hardcode this. Use the latest json available. + std::ifstream i("techtree.json"); + json j; + i >> j; + + for (auto & race : j) + { + for (json::iterator it = race.begin(); it != race.end(); ++it) + { + auto pair = parse_unit(it); + data[pair.first] = pair.second; + } + } + + std::cout << "Done" << std::endl; +} + +const std::vector<BuildAlternative> & TechTreeImproved::GetBuildAlternatives(sc2::UNIT_TYPEID unit) const +{ + if (data.count(unit) > 0) + { + return data.at(unit); + } + else + { + std::cout << "No information about unit type " << sc2::UnitTypeToName(unit) << " (" << static_cast<int>(unit) << ")" << std::endl; + return {}; + } +} + +std::vector<std::pair<sc2::UNIT_TYPEID, BuildAlternative>> TechTreeImproved::HowToBuild(sc2::UNIT_TYPEID unit_type) +{ + std::vector<std::pair<sc2::UNIT_TYPEID, BuildAlternative>> alternatives; + for (auto & pair : data) + { + for (const BuildAlternative & alternative : pair.second) + { + if (alternative.type == unit_type) + { + alternatives.push_back({ pair.first, alternative }); + } + } + } + return alternatives; +} \ No newline at end of file diff --git a/src/TechTreeImproved.h b/src/TechTreeImproved.h new file mode 100644 index 0000000000000000000000000000000000000000..8288752e0e685882849c0508a6f09fbbf4178145 --- /dev/null +++ b/src/TechTreeImproved.h @@ -0,0 +1,26 @@ +#pragma once + +#include "nlohmann/json.hpp" +#include <string> +#include <vector> +#include <fstream> +#include <iostream> +#include "sc2api/sc2_typeenums.h" + + +struct BuildAlternative +{ + sc2::UNIT_TYPEID type; + std::vector<sc2::UNIT_TYPEID> buildings_needed; + std::vector<sc2::UNIT_TYPEID> addons_needed; +}; + +class TechTreeImproved +{ + std::map<sc2::UNIT_TYPEID, std::vector<BuildAlternative>> data; +public: + TechTreeImproved(); + void LoadData(); + const std::vector<BuildAlternative> & GetBuildAlternatives(sc2::UNIT_TYPEID) const; + std::vector<std::pair<sc2::UNIT_TYPEID, BuildAlternative>> TechTreeImproved::HowToBuild(sc2::UNIT_TYPEID unit); +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ce02c35217f82be5ef10b13f5126ae90966381a6..6e7290100d0998c18395f2ae3b10abf3ea9cd34e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,9 +5,18 @@ #include "sc2utils/sc2_manage_process.h" #include "sc2api/sc2_api.h" +#include "TechTreeImproved.h" int main(int argc, char* argv[]) { + TechTreeImproved tree; + tree.LoadData(); + + std::vector<BuildAlternative> alts = tree.GetBuildAlternatives(sc2::UNIT_TYPEID::TERRAN_BARRACKS); + std::vector<std::pair<sc2::UNIT_TYPEID, BuildAlternative>> alts2 = tree.HowToBuild(sc2::UNIT_TYPEID::TERRAN_GHOST); + + return 0; + sc2::Coordinator coordinator; if (!coordinator.LoadSettings(argc, argv)) {