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)) 
     {