From f60ad72d11196112a6b110e7b59feea8973d4e47 Mon Sep 17 00:00:00 2001
From: Emil Brynielsson <emibr898@student.liu.se>
Date: Fri, 6 Aug 2021 12:43:33 +0000
Subject: [PATCH] Bugfixes, added methods and a lot better docs

---
 create-visual-studio-solution-python38.sh |   1 -
 create-visual-studio-solution-python39.sh |   5 +
 docs/coordinates.rst                      |   9 +-
 docs/helpers.rst                          |  54 ++-----
 docs/idabot.rst                           | 168 +++++-----------------
 docs/unit.rst                             |  65 ++-------
 python-api-src/lib_base_location.cpp      |  22 +--
 python-api-src/lib_building_placer.cpp    |   5 +-
 python-api-src/lib_map_tools.cpp          |  46 +++---
 python-api-src/lib_point.cpp              |  21 ++-
 python-api-src/lib_unit.cpp               |  82 +++++------
 python-api-src/lib_unittype.cpp           |  69 ++++-----
 python-api-src/library.cpp                |  44 +++---
 src/BaseLocation.cpp                      |   8 ++
 src/BaseLocation.h                        |   2 +
 src/BaseLocationManager.cpp               |  33 ++++-
 src/BaseLocationManager.h                 |   5 +
 src/BuildingPlacer.cpp                    |  78 +++++++++-
 src/BuildingPlacer.h                      |   4 +
 src/IDABot.cpp                            |  24 +++-
 src/MapTools.cpp                          |  16 ++-
 src/MapTools.h                            |  13 +-
 src/TechTree.cpp                          |   6 +-
 src/TechTree.h                            |   3 +-
 src/Unit.cpp                              |  22 ++-
 src/Unit.h                                |   1 +
 src/UnitType.cpp                          | 109 ++++++++++++--
 src/UnitType.h                            |   3 +
 28 files changed, 527 insertions(+), 391 deletions(-)
 create mode 100644 create-visual-studio-solution-python39.sh

diff --git a/create-visual-studio-solution-python38.sh b/create-visual-studio-solution-python38.sh
index 081c3e8..324f984 100644
--- a/create-visual-studio-solution-python38.sh
+++ b/create-visual-studio-solution-python38.sh
@@ -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"
-
diff --git a/create-visual-studio-solution-python39.sh b/create-visual-studio-solution-python39.sh
new file mode 100644
index 0000000..1d032bd
--- /dev/null
+++ b/create-visual-studio-solution-python39.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+mkdir build
+cd build
+"C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python39/python.exe"
diff --git a/docs/coordinates.rst b/docs/coordinates.rst
index fb74871..a9ef7d4 100644
--- a/docs/coordinates.rst
+++ b/docs/coordinates.rst
@@ -3,7 +3,14 @@ Coordinates
 
 The library uses 2 types of coordinate classes. One for integers and one for 
 floats, these are called :class:`library.Point2DI` and 
-:class:`library.Point2D`.
+:class:`library.Point2D`. Convertion between the two types is possible by 
+sending the other type as argument in the constructor. In the case of 
+Point2D to Point2DI the floating point values will just be casted into 
+integer values.
+
+Both of the types are hashable so they can be used in sets and dictionaries. 
+Note that it is the tuple (x_val, y_val) that will be hashed so don't mix 
+those sets or dictionaries with normal tuples.
 
 Point2DI
 --------
diff --git a/docs/helpers.rst b/docs/helpers.rst
index 68802b4..9f3c4f0 100644
--- a/docs/helpers.rst
+++ b/docs/helpers.rst
@@ -22,20 +22,15 @@ BaseLocationManager
 
 .. class:: library.BaseLocationManager
 
-   .. attribute:: library.BaseLocationManager.base_locations
+   .. autoattribute:: base_locations
 
-      A list of all :class:`library.BaseLocation` on the current map
+   .. autoattribute:: starting_base_locations
 
-   .. attribute:: library.BaseLocationManager.starting_base_locations
+   .. automethod:: get_occupied_base_locations
 
-      A list of all :class:`library.BaseLocation` on the current map which a player
-      started at, indexed by Player constant (see :ref:`playerconstants`).
+   .. automethod:: get_player_starting_base_location
 
-   .. automethod:: library.BaseLocationManager.get_occupied_base_locations
-
-   .. automethod:: library.BaseLocationManager.get_player_starting_base_location
-
-   .. automethod:: library.BaseLocationManager.get_next_expansion
+   .. automethod:: get_next_expansion
 
 BaseLocation
 ~~~~~~~~~~~~
@@ -46,16 +41,9 @@ BaseLocation
    the BaseLocationManager to keep track of all base locations and related
    information.
 
-   .. attribute:: library.BaseLocation.position
-
-      The position of the center of the BaseLocation, defined as a :class:`library.Point2D`.
-
-   .. attribute:: library.BaseLocation.depot_position
+   .. autoattribute:: position
 
-      A suitable position for building a town hall (Command Center, Hatchery or
-      Nexus), defined as a :class:`library.Point2DI`.
-
-   .. autoattribute:: mineral_fields
+   .. autoattribute:: depot_position
 
    .. autoattribute:: minerals
 
@@ -133,32 +121,8 @@ MapTools
    The top three methods below takes in a Point2D, but it's possible to
    send in x and y as floats instead of Point2D.
 
-   .. automethod:: draw_box
-   .. automethod:: draw_circle
-   .. automethod:: draw_resource_sphere
-   .. automethod:: draw_line
-   .. automethod:: draw_text
-   .. automethod:: draw_text_screen
-
-   These are methods which are useful for extracting information about the 
-   game map:
-
-   .. automethod:: can_build_type_at_position
-   .. automethod:: get_closest_tiles_to
-   .. automethod:: get_distance_map
-   .. automethod:: get_ground_distance
-   .. automethod:: get_least_recently_seen_tile
-   .. autoattribute:: height
-   .. autoattribute:: width
-   .. automethod:: is_buildable
-   .. automethod:: is_connected
-   .. automethod:: is_depot_buildable_tile
-   .. automethod:: is_explored
-   .. automethod:: is_powered
-   .. automethod:: is_valid_position
-   .. automethod:: is_valid_tile
-   .. automethod:: is_visible
-   .. automethod:: is_walkable
+   There is also methods which are useful for extracting information about the 
+   game map.
 
 Color
 ~~~~~
diff --git a/docs/idabot.rst b/docs/idabot.rst
index 6a4c6be..8284f45 100644
--- a/docs/idabot.rst
+++ b/docs/idabot.rst
@@ -11,21 +11,10 @@ IDABot
 
    Instances of managers:
 
-   .. attribute:: IDABot.base_location_manager
-
-      An instance of the class :class:`library.BaseLocationManager`
-
-   .. attribute:: IDABot.tech_tree
-
-      An instance of the class :class:`library.TechTree`
-
-   .. attribute:: IDABot.map_tools
-
-      An instance of the class :class:`library.MapTools`
-
-   .. attribute:: IDABot.building_placer
-
-      An instance of the class :class:`library.BuildingPlacer`
+   .. autoattribute:: base_location_manager
+   .. autoattribute:: tech_tree
+   .. autoattribute:: map_tools
+   .. autoattribute:: building_placer
 
    Inherited methods:
 
@@ -43,29 +32,12 @@ IDABot
 
    Methods:
 
-   .. method:: IDABot.get_all_units(self) -> List[library.Unit]
-
-      Retrieves a list of all visible units
-
-   .. method:: IDABot.get_my_units(self) -> List[library.Unit]
-
-      Retrieves a list of all your visible units
-
-   .. method:: IDABot.get_player_race(self) -> library.Race
-
-      Returns the players race, useful if you play Race.Random
-
-   .. method:: IDABot.send_chat(self, message)
-
-      Sends the string 'message' to the game chat
-
-   .. method:: IDABot.has_creep(self, Point2D) -> Boolean
-
-      Returns if the position has a creep
-
-   .. method:: IDABot.move_camera(self, Point2DI)
-
-      Move the camera to the position
+   .. automethod:: get_all_units
+   .. automethod:: get_my_units
+   .. automethod:: get_player_race
+   .. automethod:: send_chat
+   .. automethod:: has_creep
+   .. automethod:: move_camera
 
    .. method:: IDABot.ability_for_upgrade(self, UpgradeID)
 
@@ -76,105 +48,44 @@ IDABot
       the unit of scv has the ability for this. You can then use the
       unit.ability(AbilityID) on the scv for creating the upgrade.
 
-   .. method:: IDABot.upgrade_mineral_cost(self, UpgradeID)
-
-      Mineral cost of researching the upgrade
-
-   .. method:: IDABot.upgrade_gas_cost(self, UpgradeID)
-
-      Vespene/gas cost of researching the upgrade
-
-   .. method:: IDABot.upgrade_research_time(self, UpgradeID)
-
-      Time in GameLoops to research this upgrade
-
-   .. method:: IDABot.effect_radius(self, EffectID)
-
-      Size of the circle the effect impacts
+   .. automethod:: upgrade_mineral_cost
+   .. automethod:: upgrade_gas_cost
+   .. automethod:: upgrade_research_time
+   .. automethod:: effect_radius
 
    Attributes:
 
    .. autoattribute:: minerals
-
    .. autoattribute:: gas
-
    .. autoattribute:: current_supply
-
    .. autoattribute:: max_supply
-
    .. autoattribute:: current_frame
+   .. autoattribute:: start_location
+   ,, autoattribute:: start_locations
 
 Debug
 -----
+.. class:: library.IDABot
 
-When developing AI-methods or when simply having a problem.
-The debug-methods are a great tool for speeding up the process.
-
-   .. method:: IDABot.debug_create_unit(self, UnitTypeID, Point2D, Player Constant, Int)
-
-      This method creates the nr (INT) of units on the position :class:`library.Point2D`, the unit 
-      belongs to the Player Constant
-
-   .. method:: IDABot.debug_kill_unit(self, Unit)
-
-      Kills the :class:`library.Unit`
-
-   .. method:: IDABot.debug_show_map(self)
-
-      Make the entire map visible
-
-   .. method:: IDABot.debug_fast_build(self)
-
-      Set the build time in game to 1
-  
-   .. method:: IDABot.debug_enemy_control(self)
-
-      Gives the player full control over the enemy
-
-   .. method:: IDABot.debug_fast_build(self)
-
-      Set the build time in game to 1
-
-   .. method:: IDABot.debug_ignore_food(self)
-
-      Ignore food in game
-
-   .. method:: IDABot.debug_ignore_resource_cost(self)
-
-      Ignore the resource cost in game. Everything cost 0 resources
-
-   .. method:: IDABot.debug_give_all_resources(self)
-
-      Set the mineral and vespene gas to 5000
-   
-   .. method:: IDABot.debug_god_mode(self)
-
-      Give yourself god mode in the game
-
-   .. method:: IDABot.debug_ignore_mineral(self)
-
-      Ignore the mineral cost in the game
-
-   .. method:: IDABot.debug_no_cooldowns(self)
-
-      Deactivate cooldowns (Basically setting them to 0)
-
-   .. method:: IDABot.debug_give_all_tech(self)
-
-      Give yourself all tech
-
-   .. method:: IDABot.debug_give_all_upgrades(self)
-
-      Give yourself all upgrades
-
-   .. method:: IDABot.debug_set_score(self, Float)
-
-      Set the player score in game
-
-   .. method:: IDABot.debug_end_game(self, Boolean)
-
-      End the game, if the Boolean is True then victory.
-      If False, defeat.
+   When developing AI-methods or when simply having a problem.
+   The debug-methods are a great tool for speeding up the process.
+
+   .. automethod:: debug_create_unit
+   .. automethod:: debug_kill_unit
+   .. automethod:: IDABot.debug_show_map(self)
+   .. automethod:: IDABot.debug_fast_build(self)
+   .. automethod:: debug_enemy_control
+   .. automethod:: debug_fast_build
+   .. automethod:: debug_ignore_food
+   .. automethod:: debug_ignore_resource_cost
+   .. automethod:: debug_give_all_resources
+   .. automethod:: debug_god_mode
+   .. automethod:: debug_ignore_mineral
+   .. automethod:: debug_no_cooldowns
+   .. automethod:: debug_give_all_tech
+   .. automethod:: debug_give_all_upgrades
+   .. automethod:: debug_set_score
+   .. automethod:: debug_end_game
 
    .. method:: IDABot.debug_set_energy(self, Float, Unit)
 
@@ -183,12 +94,9 @@ The debug-methods are a great tool for speeding up the process.
       Note: This is not in percent of the unit energy.
       Same goes for life and shields.
 
-   .. method:: IDABot.debug_set_life(self, Float, Unit)
-
-      Set the amount (Float) of life to the unit
+   .. automethod:: debug_set_life
 
-   .. method:: IDABot.debug_set_shields(self, Float, Unit)
+   .. automethod:: debug_set_shields
 
-      Set the amount (Float) of shield to the unit
 
 .. toctree::
\ No newline at end of file
diff --git a/docs/unit.rst b/docs/unit.rst
index 55a65d7..de4f7b4 100644
--- a/docs/unit.rst
+++ b/docs/unit.rst
@@ -21,96 +21,50 @@ Unit
    Properties:
 
    .. autoattribute:: buffs
-
-      Returns a list of BuffID
-
    .. autoattribute:: build_percentage
    .. autoattribute:: energy
    .. autoattribute:: facing
-
-      Returns the direction the unit is facing
-
+   .. autoattribute:: has_target
    .. autoattribute:: hit_points 
    .. autoattribute:: max_hit_points
-      Returns the max health	
    .. autoattribute:: max_shields
    .. autoattribute:: max_energy
    .. autoattribute:: id 
    .. autoattribute:: is_alive 
    .. autoattribute:: is_blip
-
-      Returns true if unit is a "blip" - a ping on the map
-
    .. autoattribute:: is_being_constructed 
-      
-      Returns build_progress > 0
-
    .. autoattribute:: is_burrowed 
    .. autoattribute:: is_cloaked 
    .. autoattribute:: is_completed 
-
-      Returns build_progress >= 1
-
    .. autoattribute:: is_flying 
    .. autoattribute:: is_idle 
    .. autoattribute:: is_powered 
    .. autoattribute:: is_training 
    .. autoattribute:: is_valid 
-   .. attribute:: Unit.player 
-
-      Returns the constant corresponding to player which this unit belongs to.
-      See :ref:`playerconstants` for more information
-
+   .. autoattribute:: player 
    .. autoattribute:: position 
    .. autoattribute:: current_ability_id
-
    .. autoattribute:: progress
-
-      Returns the progress of currently used ability (-1 if not using ability)
-
+   .. autoattribute:: progression_list
    .. autoattribute:: radius
-
-      Retruns the radius of the unit
-
    .. autoattribute:: shields 
    .. autoattribute:: tile_position 
    .. autoattribute:: unit_type 
    .. autoattribute:: weapon_cooldown 
    .. autoattribute:: is_carrying_minerals
-   
-      Returns if this unit is currently holding minerals
-
    .. autoattribute:: is_carrying_gas
-
-      Returns if this unit is currently holding gas
-
-   .. attribute:: Unit.target
-
-      Returns target if unit has one, otherwise will fail the assertion (make sure not to call this unless certain that the unit has a target!)
-
+   .. autoattribute:: target
    .. autoattribute:: gas_left_in_refinery
-
-      This is used on the geyser.	
-      Returns the amount of gas left in refinery
-
    .. autoattribute:: minerals_left_in_mineralfield
-
-      Returns the amount of minerals left in mineralfield
-
    .. autoattribute:: owner
 
-      Returns the Player ID, the owner of the unit
-
    Methods:
 
    .. automethod:: ability
 
       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:: is_constructing
    .. automethod:: stop
    .. automethod:: attack_unit
    .. automethod:: attack_move
@@ -118,6 +72,7 @@ Unit
 
       Move the unit to the given point, the point being an instance of either 
       :class:`library.Point2D` or :class:`library.Point2DI`.
+
    .. automethod:: right_click
    .. automethod:: repair
    .. automethod:: build
@@ -125,13 +80,9 @@ Unit
    .. automethod:: train
    .. automethod:: research
    .. automethod:: morph
-   .. method:: Unit.has_target
-
-      Returns True if the target has a valid target and False otherwise
-
    .. automethod:: hold_position
+   .. automethod:: patrol
    .. automethod:: stop_dance
 
-      Stop and dance
-
+      
 .. toctree::
\ No newline at end of file
diff --git a/python-api-src/lib_base_location.cpp b/python-api-src/lib_base_location.cpp
index 9f18f8a..3fdda68 100644
--- a/python-api-src/lib_base_location.cpp
+++ b/python-api-src/lib_base_location.cpp
@@ -6,21 +6,21 @@ void define_base_location(py::module & m)
 {
     py::class_<BaseLocation>(m, "BaseLocation")
         .def_property_readonly("geysers", &BaseLocation::getGeysers, "List of geysers at base location (List of units)")
-        .def_property_readonly("minerals", &BaseLocation::getMinerals, "List of mineral fields at base location (List of unit)")
-        .def_property_readonly("mineral_fields", &BaseLocation::getMinerals, "Alias for minerals in order to differentiate from harvested minerals")
+        .def_property_readonly("minerals", &BaseLocation::getMinerals, "List of mineral fields at base location (List of unit), Note: also returns the empty mineralfields")
+        //.def_property_readonly("mineral_fields", &BaseLocation::getMinerals, "Alias for minerals in order to differentiate from harvested minerals") // This just did the same thing as minerals (above) removed to avoid confusion
         .def_property_readonly("is_start_location", &BaseLocation::isStartLocation, "True if the base location is a start location, False otherwise")
-        .def_property_readonly("depot_position", &BaseLocation::getDepotPosition, "Point2DI position suitable for placing a town hall (base structure)")
-        .def_property_readonly("position", &BaseLocation::getPosition)
+        .def_property_readonly("depot_position", &BaseLocation::getDepotPosition, "A suitable position for building a town hall (Command Center, Hatchery or Nexus), defined as a : class :`library.Point2DI`.")
+        .def_property_readonly("position", &BaseLocation::getPosition, "The position of the center of the BaseLocation, defined as a :class:`library.Point2D`.")
         .def("get_ground_distance", py::overload_cast<const CCPosition &>(&BaseLocation::getGroundDistance, py::const_))
         .def("get_ground_distance", py::overload_cast<const CCTilePosition &>(&BaseLocation::getGroundDistance, py::const_))
-        .def("is_occupied_by_player", &BaseLocation::isOccupiedByPlayer, "player constant"_a)
-        .def("is_player_start_location", &BaseLocation::isPlayerStartLocation, "player_constant"_a)
-        .def("contains_position", &BaseLocation::containsPosition);
+        .def("is_occupied_by_player", &BaseLocation::isOccupiedByPlayer, "player constant"_a, "If the baselocation is occupied by the provided player. See :ref:`playerconstants` for more information")
+        .def("is_player_start_location", &BaseLocation::isPlayerStartLocation, "player_constant"_a, "If the baselocation is the start location of the provided palyer. See :ref:`playerconstants` for more information")
+        .def("contains_position", &BaseLocation::containsPosition, "If the baselocation contains the provided :class:`library.Point2D` position");
 
     py::class_<BaseLocationManager>(m, "BaseLocationManager")
-        .def_property_readonly("base_locations", &BaseLocationManager::getBaseLocations, py::return_value_policy::reference)
-        .def_property_readonly("starting_base_locations", &BaseLocationManager::getStartingBaseLocations, py::return_value_policy::reference)
+        .def_property_readonly("base_locations", &BaseLocationManager::getBaseLocations, py::return_value_policy::reference, "A list of all :class:`library.BaseLocation` on the current map")
+        .def_property_readonly("starting_base_locations", &BaseLocationManager::getStartingBaseLocations, py::return_value_policy::reference, "A list of all :class:`library.BaseLocation` on the current map which a player started at, indexed by Player constant(see :ref:`playerconstants`).")
         .def("get_occupied_base_locations", &BaseLocationManager::getOccupiedBaseLocations, py::return_value_policy::reference, "player_constant"_a)
-        .def("get_player_starting_base_location", &BaseLocationManager::getPlayerStartingBaseLocation, py::return_value_policy::copy, "player_constant"_a)
-        .def("get_next_expansion", &BaseLocationManager::getNextExpansion, py::return_value_policy::copy, "player_constant"_a);
+        .def("get_player_starting_base_location", &BaseLocationManager::getPlayerStartingBaseLocation, py::return_value_policy::copy, "player_constant"_a, "Returns the :class:`library.BaseLocation` that provided :ref:`playerconstants` started at.")
+        .def("get_next_expansion", &BaseLocationManager::getNextExpansion, py::return_value_policy::copy, "player_constant"_a, "Returns the :class:`library.BaseLocation` that is closest to the startlocation of provided :ref:`playerconstants` that is possible to expand to.");
 }
\ No newline at end of file
diff --git a/python-api-src/lib_building_placer.cpp b/python-api-src/lib_building_placer.cpp
index f2aed97..56da5e8 100644
--- a/python-api-src/lib_building_placer.cpp
+++ b/python-api-src/lib_building_placer.cpp
@@ -5,8 +5,9 @@ namespace py = pybind11;
 void define_building_placer(py::module & m)
 {
     py::class_<BuildingPlacer>(m, "BuildingPlacer")
-        .def("can_build_here", &BuildingPlacer::canBuildHere, "x"_a, "y"_a, "unit_type"_a)
-        .def("can_build_here_with_spaces", &BuildingPlacer::canBuildHereWithSpace, "Creates a square with the help of x, y, distance_to_building and the size of the unit_type. Good approach if we later gonna make a addon to the building.", "x"_a, "y"_a, "unit_type"_a, "distance_to_building"_a)
+        .def("can_build_here", &BuildingPlacer::canBuildHere, "x"_a, "y"_a, "unit_type"_a, "Returns if the provided unittype it possible to be built at the location. Note: This function uses the width and height of the unittype and this is not correct for addons. So to check addons please use can_build_here_with_size with a hardcoded size instead.")
+		.def("can_build_here_with_size", &BuildingPlacer::canBuildHereWithSize, "x"_a, "y"_a, "width"_a, "height"_a, "Checks if it is possible to build something with the provided width and height at the provided coordinates. Note: False if the it overlaps with a baselocation")
+        .def("can_build_here_with_spaces", &BuildingPlacer::canBuildHereWithSpace, "Creates a square with the help of x, y, distance_to_building and the size of the unit_type. Good approach if we later gonna make a addon to the building. Note: Does not reserve those extra tiles given by distance_to_building for the future! Note: This function uses the width and height of the unittype and this is not correct for addons. So to check addons please use can_build_here_with_size with a hardcoded size instead.", "x"_a, "y"_a, "unit_type"_a, "distance_to_building"_a)
         .def("get_build_location_near", &BuildingPlacer::getBuildLocationNear, "The search_count is how many building we should check (nearby buildings, instead of i < size, we can switch size to search_count). distance_to_building is the distance to the closest building.", "point2di"_a, "unit_type"_a, "distance_to_building"_a = 2, "search_count"_a = 1000)
         .def("reserve_tiles", &BuildingPlacer::reserveTiles, "It's possible to reserve tiles, which makes it impossible to build at the position given by x and y.", "x"_a, "y"_a, "width"_a, "height"_a)
         .def("free_tiles", &BuildingPlacer::freeTiles,"Free the tile (x, y) from reservation", "x"_a, "y"_a, "width"_a, "height"_a);
diff --git a/python-api-src/lib_map_tools.cpp b/python-api-src/lib_map_tools.cpp
index b871070..2f8e344 100644
--- a/python-api-src/lib_map_tools.cpp
+++ b/python-api-src/lib_map_tools.cpp
@@ -16,33 +16,35 @@ void define_map_tools(py::module & m)
     py::class_<MapTools>(m, "MapTools")
         .def_property_readonly("width", &MapTools::width, "The width of the map")
         .def_property_readonly("height", &MapTools::height, "The height of the map")
+		.def_property_readonly("map_name", &MapTools::name, "The name of the map")
         //.def("terrainHeight", &MapTools::terrainHeight, py::const_)
-        .def("draw_line", py::overload_cast<const CCPosition &, const CCPosition &, const CCColor &>(&MapTools::drawLine, py::const_), py::arg("start"), py::arg("stop"), py::arg("color") = sc2::Colors::White)
-        .def("draw_box", py::overload_cast<const CCPosition &, const CCPosition &, const CCColor &>(&MapTools::drawBox, py::const_), py::arg("top_left"), py::arg("bottom_right"), py::arg("color") = sc2::Colors::White)
-        .def("draw_circle", py::overload_cast<const CCPosition &, CCPositionType, const CCColor &>(&MapTools::drawCircle, py::const_), py::arg("center"), py::arg("radius"), py::arg("color") = sc2::Colors::White)
-		.def("draw_resource_sphere", &MapTools::drawResourceSphere, py::arg("center"), py::arg("radius"), py::arg("color") = sc2::Colors::White)
+        .def("draw_line", py::overload_cast<const CCPosition &, const CCPosition &, const CCColor &>(&MapTools::drawLine, py::const_), py::arg("start"), py::arg("stop"), py::arg("color") = sc2::Colors::White, "Draws a line with the given color between to two points.")
+        .def("draw_tile", py::overload_cast<const CCTilePosition &, const CCColor &>(&MapTools::drawTile, py::const_), py::arg("tile"), py::arg("color") = sc2::Colors::White, "Draws an outline with the given color to the given tile.")
+		.def("draw_box", py::overload_cast<const CCPosition &, const CCPosition &, const CCColor &>(&MapTools::drawBox, py::const_), py::arg("top_left"), py::arg("bottom_right"), py::arg("color") = sc2::Colors::White, "Draws a box with the given color from the top left cornor to the botom right")
+        .def("draw_circle", py::overload_cast<const CCPosition &, CCPositionType, const CCColor &>(&MapTools::drawCircle, py::const_), py::arg("center"), py::arg("radius"), py::arg("color") = sc2::Colors::White, "Draws a circle with the given color with the provided point as center and the float as radius")
+		.def("draw_resource_sphere", &MapTools::drawResourceSphere, py::arg("center"), py::arg("radius"), py::arg("color") = sc2::Colors::White, "Draws a 3D sphere with the given color with the provided point as center and the float as radius")
         .def("draw_text", &MapTools::drawText, "position"_a, "text"_a, "color"_a = sc2::Colors::White)
         .def("draw_text_screen", &MapTools::drawTextScreen, "percentage_x"_a, "percentage_y"_a, "text"_a, "color"_a = sc2::Colors::White)
-        .def("is_valid_tile", py::overload_cast<int, int>(&MapTools::isValidTile, py::const_), "x"_a, "y"_a)
-        .def("is_valid_tile", py::overload_cast<const CCTilePosition &>(&MapTools::isValidTile, py::const_), "point_2di"_a)
-        .def("is_valid_position", py::overload_cast<const CCPosition &>(&MapTools::isValidPosition, py::const_), "point_2d"_a)
+        .def("is_valid_tile", py::overload_cast<int, int>(&MapTools::isValidTile, py::const_), "x"_a, "y"_a, "Checks if the position is valid for the map")
+        .def("is_valid_tile", py::overload_cast<const CCTilePosition &>(&MapTools::isValidTile, py::const_), "point_2di"_a, "Checks if the tile is valid for the map")
+        .def("is_valid_position", py::overload_cast<const CCPosition &>(&MapTools::isValidPosition, py::const_), "point_2d"_a, "Checks if the position is valid for the map")
         .def("is_powered", &MapTools::isPowered, "x"_a, "y"_a)
-        .def("is_explored", py::overload_cast<int, int>(&MapTools::isExplored, py::const_), "x"_a, "y"_a)
-        .def("is_explored", py::overload_cast<const CCPosition &>(&MapTools::isExplored, py::const_), "point2d"_a)
-        .def("is_explored", py::overload_cast<const CCTilePosition &>(&MapTools::isExplored, py::const_), "point2di"_a)
-        .def("is_connected", py::overload_cast<int, int, int, int>(&MapTools::isConnected, py::const_), "x1"_a, "y1"_a, "x2"_a, "y2"_a)
-        .def("is_connected", py::overload_cast<const CCTilePosition &, const CCTilePosition &>(&MapTools::isConnected, py::const_), "from"_a, "too"_a)
-        .def("is_connected", py::overload_cast<const CCPosition &, const CCPosition &>(&MapTools::isConnected, py::const_), "from"_a, "too"_a)
-        .def("is_walkable", py::overload_cast<int, int>(&MapTools::isWalkable, py::const_), "x"_a, "y"_a)
-        .def("is_walkable", py::overload_cast<const CCTilePosition &>(&MapTools::isWalkable, py::const_), "point2di"_a)
-        .def("is_buildable", py::overload_cast<int, int>(&MapTools::isBuildable, py::const_), "x"_a, "y"_a)
-        .def("is_buildable", py::overload_cast<const CCTilePosition &>(&MapTools::isBuildable, py::const_), "point2di"_a)
-        .def("is_visible", &MapTools::isVisible, "x"_a, "y"_a)
-        .def("can_build_type_at_position", &MapTools::canBuildTypeAtPosition, "x"_a, "y"_a, "unit_type"_a)
-        .def("is_depot_buildable_tile", &MapTools::isDepotBuildableTile, "x"_a, "y"_a)
-        .def("get_ground_distance", &MapTools::getGroundDistance, "from"_a, "to"_a)
+        .def("is_explored", py::overload_cast<int, int>(&MapTools::isExplored, py::const_), "x"_a, "y"_a, "Returns if the coordinates has been explored or not")
+        .def("is_explored", py::overload_cast<const CCPosition &>(&MapTools::isExplored, py::const_), "point2d"_a, "Returns if the coordinate has been explored or not")
+        .def("is_explored", py::overload_cast<const CCTilePosition &>(&MapTools::isExplored, py::const_), "point2di"_a, "Returns if the tile has been explored or not")
+        .def("is_connected", py::overload_cast<int, int, int, int>(&MapTools::isConnected, py::const_), "x1"_a, "y1"_a, "x2"_a, "y2"_a, "Returns if the coordinates are connected")
+        .def("is_connected", py::overload_cast<const CCTilePosition &, const CCTilePosition &>(&MapTools::isConnected, py::const_), "from"_a, "too"_a, "Returns if the tiles are connected")
+        .def("is_connected", py::overload_cast<const CCPosition &, const CCPosition &>(&MapTools::isConnected, py::const_), "from"_a, "too"_a, "Returns if the positions are of two connected tiles")
+        .def("is_walkable", py::overload_cast<int, int>(&MapTools::isWalkable, py::const_), "x"_a, "y"_a, "Returns if the coordinates is walkable")
+        .def("is_walkable", py::overload_cast<const CCTilePosition &>(&MapTools::isWalkable, py::const_), "point2di"_a, "Returns if the tile is walkable")
+        .def("is_buildable", py::overload_cast<int, int>(&MapTools::isBuildable, py::const_), "x"_a, "y"_a, "Return if it is possible to build at the provided coordinate")
+        .def("is_buildable", py::overload_cast<const CCTilePosition &>(&MapTools::isBuildable, py::const_), "point2di"_a, "Return if it is possible to build on tile")
+        .def("is_visible", &MapTools::isVisible, "x"_a, "y"_a, "Can you see the coordinates")
+        .def("can_build_type_at_position", &MapTools::canBuildTypeAtPosition, "x"_a, "y"_a, "unit_type"_a, "Is it possible to build the provided unittype at the location")
+        .def("is_depot_buildable_tile", &MapTools::isDepotBuildableTile, "x"_a, "y"_a, "Is it possbile do build a depot at the position")
+        .def("get_ground_distance", &MapTools::getGroundDistance, "Returns the ground distance between the two points. Note that this uses a BFS approach and may overshoot a bit. The function will also do the calculations with integers resulting in that sometimes when close to a wall it might return -1 even though a path is available", "from"_a, "to"_a)
         .def("get_distance_map", py::overload_cast<const CCTilePosition &>(&MapTools::getDistanceMap, py::const_), "point2di"_a)
         .def("get_distance_map", py::overload_cast<const CCPosition &>(&MapTools::getDistanceMap, py::const_), "point2d"_a)
         .def("get_closest_tiles_to", &MapTools::getClosestTilesTo, "Returns a list of positions, where the first position is the closest and the last is the furthest", "point2di"_a)
-        .def("get_least_recently_seen_tile", &MapTools::getLeastRecentlySeenTile);
+        .def("get_least_recently_seen_tile", &MapTools::getLeastRecentlySeenTile, "Returns the tile that the most time has passed since it was visible");
 }
\ No newline at end of file
diff --git a/python-api-src/lib_point.cpp b/python-api-src/lib_point.cpp
index 6e46840..be968a3 100644
--- a/python-api-src/lib_point.cpp
+++ b/python-api-src/lib_point.cpp
@@ -9,6 +9,9 @@ void define_point(py::module & m)
     py::class_<sc2::Point2D>(m, "Point2D", py::dynamic_attr())
         .def(py::init<float, float>())
         .def(py::init())
+		.def(py::init([](const sc2::Point2DI & p) {
+			return sc2::Point2D(p.x, p.y);
+		}))
         .def_readwrite("x", &sc2::Point2D::x)
         .def_readwrite("y", &sc2::Point2D::y)
         .def(py::self += py::self)
@@ -16,7 +19,7 @@ void define_point(py::module & m)
         .def(py::self *= float())
         .def(py::self /= float())
         // These does not compile, but it is not a good idea to compare floats with floats anyway
-        //.def(py::self == py::self)
+        .def(py::self == py::self) // compiles now and this one is needed for __hash__. Outdated comment??
         //.def(py::self != py::self)
         .def(py::self + py::self)
         .def(py::self - py::self)
@@ -24,6 +27,14 @@ void define_point(py::module & m)
         .def(float() * py::self)
         .def(py::self / float())
         .def(float() / py::self)
+		.def("__eq__", 
+			[](const sc2::Point2D & p1, const sc2::Point2D & p2) {
+				return (p1.x == p2.x && p1.y == p2.y); 
+			})
+		.def("__hash__",
+			[](const sc2::Point2D & p) {
+				return py::make_tuple(p.x, p.y).attr("__hash__")();
+			})
         .def("__repr__",
             [](const sc2::Point2D & p) {
                 return "<Point2D: (" + std::to_string(p.x) + ", " + std::to_string(p.y) + ")>";
@@ -35,10 +46,18 @@ void define_point(py::module & m)
 
     py::class_<sc2::Point2DI>(m, "Point2DI", py::dynamic_attr())
         .def(py::init<int, int>())
+		.def(py::init())
+		.def(py::init([](const sc2::Point2D & p) {
+			return sc2::Point2DI(p);
+		}))
         .def_readwrite("x", &sc2::Point2DI::x)
         .def_readwrite("y", &sc2::Point2DI::y)
         .def(py::self == py::self)
         .def(py::self != py::self)
+		.def("__hash__",
+			[](const sc2::Point2DI & p) {
+				return py::make_tuple(p.x, p.y).attr("__hash__")();
+		})
         .def("__repr__",
             [](const sc2::Point2DI & p) {
                 return "<Point2DI: (" + std::to_string(p.x) + ", " + std::to_string(p.y) + ")>";
diff --git a/python-api-src/lib_unit.cpp b/python-api-src/lib_unit.cpp
index de09cc5..99a4f56 100644
--- a/python-api-src/lib_unit.cpp
+++ b/python-api-src/lib_unit.cpp
@@ -8,58 +8,60 @@ void define_unit(py::module & m)
         .def_property_readonly("unit_type", &Unit::getType, "The :class:`library.UnitType` of the unit")
         .def_property_readonly("position", &Unit::getPosition, "The :class:`library.Point2D` of the unit")
         .def_property_readonly("tile_position", &Unit::getTilePosition, "The :class:`library.Point2DI` of the unit")
-        .def_property_readonly("hit_points", &Unit::getHitPoints)
-        .def_property_readonly("shields", &Unit::getShields)
-        .def_property_readonly("energy", &Unit::getEnergy)
-        .def_property_readonly("player", &Unit::getPlayer)
-        .def_property_readonly("id", &Unit::getID)
-        .def_property_readonly("build_percentage", &Unit::getBuildPercentage)
-        .def_property_readonly("weapon_cooldown", &Unit::getWeaponCooldown)
-        .def_property_readonly("is_completed", &Unit::isCompleted)
-        .def_property_readonly("is_being_constructed", &Unit::isBeingConstructed)
-        .def_property_readonly("is_cloaked", &Unit::isCloaked)
-        .def_property_readonly("is_flying", &Unit::isFlying)
-        .def_property_readonly("buffs", &Unit::buffs)
-        .def_property_readonly("is_alive", &Unit::isAlive)
-        .def_property_readonly("is_powered", &Unit::isPowered)
-        .def_property_readonly("is_idle", &Unit::isIdle)
-        .def_property_readonly("is_burrowed", &Unit::isBurrowed)
-        .def_property_readonly("is_valid", &Unit::isValid)
-        .def_property_readonly("is_training", &Unit::isTraining)
-        .def_property_readonly("is_blip", &Unit::isBlip)
-        .def_property_readonly("target", &Unit::getTarget)
-        .def_property_readonly("has_target", &Unit::hasTarget)
-        .def_property_readonly("max_hit_points", &Unit::getMaxHitPoints)
-        .def_property_readonly("progress", &Unit::getProgress)
+        .def_property_readonly("hit_points", &Unit::getHitPoints, "Health of the unit.")
+        .def_property_readonly("shields", &Unit::getShields, "Shield of the unit.")
+        .def_property_readonly("energy", &Unit::getEnergy, "Energy of the unit.")
+        .def_property_readonly("player", &Unit::getPlayer, "Returns the constant corresponding to player which this unit belongs to. See :ref:`playerconstants` for more information")
+        .def_property_readonly("id", &Unit::getID, "Returns an int to identify the unit. Note: This value does not stay the same for units you lose vision of, so maybe not best idea to use as a way of keeping track of them.")
+        .def_property_readonly("build_percentage", &Unit::getBuildPercentage, "Gives progress under construction. Range: [0.0, 1.0]. 1.0 == finished.")
+        .def_property_readonly("weapon_cooldown", &Unit::getWeaponCooldown, "Time remaining for a weapon on cooldown.")
+        .def_property_readonly("is_completed", &Unit::isCompleted, "Returns build_progress >= 1")
+        .def_property_readonly("is_being_constructed", &Unit::isBeingConstructed, "Returns (build_progress > 0 and not is_completed)")
+        .def_property_readonly("is_cloaked", &Unit::isCloaked, "If the unit is cloaked")
+        .def_property_readonly("is_flying", &Unit::isFlying, "If the unit is flying.")
+        .def_property_readonly("buffs", &Unit::buffs, "Returns a list buffs on this unit. Only valid for this player's units.")
+        .def_property_readonly("is_alive", &Unit::isAlive, "Whether the unit is alive or not.")
+        .def_property_readonly("is_powered", &Unit::isPowered, "Whether the unit is powered by a pylon.")
+        .def_property_readonly("is_idle", &Unit::isIdle, "Wheter the unit has any orders")
+        .def_property_readonly("is_burrowed", &Unit::isBurrowed, "If the unit is burrowed.")
+        .def_property_readonly("is_valid", &Unit::isValid, "If the unit is valid")
+        .def_property_readonly("is_training", &Unit::isTraining, "Returns True if the unit is a building and is traing another unit.")
+        .def_property_readonly("is_blip", &Unit::isBlip, "Returns true if unit is a 'blip' - a ping on the map")
+        .def_property_readonly("target", &Unit::getTarget, "Returns target unit if one exists, otherwise return itself")
+        .def_property_readonly("has_target", &Unit::hasTarget, "Returns True if the target has a valid target and False otherwise")
+        .def_property_readonly("max_hit_points", &Unit::getMaxHitPoints, "Returns the max health")
+        .def_property_readonly("progress", &Unit::getProgress, "Returns the progress of currently used ability (-1 if not using ability)")
+		.def_property_readonly("progression_list", &Unit::getAllProgress, "Returns a list containing the progression on all the processes in order. Empty list if no process exists")
         .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_property_readonly("is_carrying_gas", &Unit::isCarryingGas)
-		.def_property_readonly("gas_left_in_refinery", &Unit::gasLeftInGeyser)
-		.def_property_readonly("minerals_left_in_mineralfield", &Unit::mineralsLeftInMineralfield)
-		.def_property_readonly("owner", &Unit::getOwner)
-		.def_property_readonly("max_shields", &Unit::maxShields)
-		.def_property_readonly("max_energy", &Unit::maxEnergy)
-        .def("hold_position", &Unit::holdPosition)
-        .def("patrol", py::overload_cast<const CCPosition &>(&Unit::patrol, py::const_))
-        .def("stop_dance", &Unit::stopDance)
-        .def("stop", &Unit::stop)
-        .def("attack_unit", &Unit::attackUnit)
-        .def("attack_move", &Unit::attackMove)
+        .def_property_readonly("facing", &Unit::getFacing, "Direction the unit faces in radians (1 radian == 57.296 degrees)")
+        .def_property_readonly("radius", &Unit::getRadius, "Retruns the radius of the unit")
+        .def_property_readonly("is_carrying_minerals", &Unit::isCarryingMinerals, "Returns if this unit is currently holding minerals")
+		.def_property_readonly("is_carrying_gas", &Unit::isCarryingGas, "Returns if this unit is currently holding gas")
+		.def_property_readonly("gas_left_in_refinery", &Unit::gasLeftInGeyser, "Amount of vespene left in the the refinery.")
+		.def_property_readonly("minerals_left_in_mineralfield", &Unit::mineralsLeftInMineralfield, "Amount of minerals if the unit is a mineral field.")
+		.def_property_readonly("owner", &Unit::getOwner, "Which player owns a unit. Note: Not same as player. Player is from IDA implementation and owner is from sc2")
+		.def_property_readonly("max_shields", &Unit::maxShields, "Max shield of the unit.")
+		.def_property_readonly("max_energy", &Unit::maxEnergy, "Max energy of the unit.")
+
+        .def("hold_position", &Unit::holdPosition, "Unit will hold its position")
+        .def("patrol", py::overload_cast<const CCPosition &>(&Unit::patrol, py::const_), "Unit will patrol back and forth from its current location to the given Point2D")
+        .def("stop_dance", &Unit::stopDance, "Unit will Stop and dance")
+        .def("stop", &Unit::stop, "Unit will stop")
+        .def("attack_unit", &Unit::attackUnit, "Unit will attack the provided unit")
+        .def("attack_move", &Unit::attackMove, "Moves to provided Point2D location. If an enemy is seen on the way it will try to attack it. Will chase after the enemy as long as it is visible.")
         .def("ability", py::overload_cast<sc2::AbilityID>(&Unit::ability, py::const_))
         .def("ability", py::overload_cast<sc2::AbilityID, const CCPosition &>(&Unit::ability, py::const_))
         .def("ability", py::overload_cast<sc2::AbilityID, const Unit &>(&Unit::ability, py::const_))
         .def("move", py::overload_cast<const CCPosition &>(&Unit::move, py::const_))
         .def("move", py::overload_cast<const CCTilePosition &>(&Unit::move, py::const_))
         .def("right_click", &Unit::rightClick, "Same as right-clicking in the game, for example making workers mine minerals")
-        .def("repair", &Unit::repair)
+        .def("repair", &Unit::repair, "Rightclicks on the provided unit in order to repair it")
         .def("build", &Unit::build, "Build unit of type building_type at given position", "building_type"_a, "position"_a)
         .def("build_target", &Unit::buildTarget, "Build building_type on top of target Unit, useful for building refineries", "building_type"_a, "target"_a)
         .def("train", &Unit::train, "Train unit of type", "unit_type"_a)
         .def("morph", &Unit::morph, "Morph into type of unit_type", "unit_type"_a)
         .def("research", &Unit::research, "Research the given :class:`library.UPGRADE_ID`", "upgrade_id"_a)
-        .def("is_constructing", &Unit::isConstructing, "unit_type"_a)
+        .def("is_constructing", &Unit::isConstructing, "unit_type"_a, "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`")
         .def("__hash__", [](const Unit & unit) { return std::hash<const sc2::Unit *>{}(unit.getUnitPtr()); })
         .def(py::self == py::self)
         .def("__repr__", [](const Unit & unit) { return "<Unit of type: '" + unit.getType().getName() + "'>"; });
diff --git a/python-api-src/lib_unittype.cpp b/python-api-src/lib_unittype.cpp
index 723f5e1..c67f74f 100644
--- a/python-api-src/lib_unittype.cpp
+++ b/python-api-src/lib_unittype.cpp
@@ -5,44 +5,49 @@ namespace py = pybind11;
 void define_unittype(py::module & m)
 {
     py::class_<UnitType>(m, "UnitType")
-        .def(py::init<const sc2::UnitTypeID &, IDABot &>())
+		.def(py::init([](const sc2::UnitTypeID & type, IDABot & bot) {
+			return UnitType(type, bot, bot);
+		}))
         .def(py::self == py::self)
         .def_property_readonly("unit_typeid", [](UnitType & unit_type) { return static_cast<sc2::UNIT_TYPEID>(unit_type.getAPIUnitType()); })
-        .def_property_readonly("name", &UnitType::getName)
-        .def_property_readonly("race", &UnitType::getRace)
-        .def_property_readonly("movement_speed", &UnitType::getMovementSpeed)
-        .def_property_readonly("sight_range", &UnitType::getSightRange)
-        .def_property_readonly("required_structure", &UnitType::getRequiredStructure)
-        .def_property_readonly("is_valid", &UnitType::isValid)
-        .def_property_readonly("is_building", &UnitType::isBuilding)
+        .def_property_readonly("name", &UnitType::getName, "The name of the unit as a sting.")
+        .def_property_readonly("race", &UnitType::getRace, "The race the unit belongs to.")
+        .def_property_readonly("movement_speed", &UnitType::getMovementSpeed, "Movement speed of unit type.")
+        .def_property_readonly("sight_range", &UnitType::getSightRange, "Range the unit reveals vision.")
+        .def_property_readonly("required_structure", &UnitType::getRequiredStructure, "Structure required to build this unit. (Or any with the same tech_alias)")
+        .def_property_readonly("is_valid", &UnitType::isValid, "Its a valid unit type")
+        .def_property_readonly("is_building", &UnitType::isBuilding, "Is this unit type a building or not")
         .def_property_readonly("is_combat_unit", &UnitType::isCombatUnit, "The unit is not any of the following: worker, supply provider, building, larva, egg")
-        .def_property_readonly("is_supply_provider", &UnitType::isSupplyProvider)
-        .def_property_readonly("is_resource_depot", &UnitType::isResourceDepot)
-        .def_property_readonly("is_refinery", &UnitType::isRefinery)
-        .def_property_readonly("is_detector", &UnitType::isDetector)
-        .def_property_readonly("is_geyser", &UnitType::isGeyser)
-        .def_property_readonly("is_mineral", &UnitType::isMineral)
-        .def_property_readonly("is_worker", &UnitType::isWorker)
-        .def_property_readonly("is_morphed_building", &UnitType::isMorphedBuilding)
+        .def_property_readonly("is_supply_provider", &UnitType::isSupplyProvider, "The unit provides supply")
+        .def_property_readonly("is_resource_depot", &UnitType::isResourceDepot, "The unit is one of the following: hatchery, lair, hive, commandcenter, orbialtcommand, planetaryfortress, nexus")
+        .def_property_readonly("is_refinery", &UnitType::isRefinery, "The unit is one of the following (depending on race): refinery, assimilator, extractor")
+        .def_property_readonly("is_detector", &UnitType::isDetector, "Is this a unit type which is a detector unit")
+        .def_property_readonly("is_geyser", &UnitType::isGeyser, "Is the unit type a geyser")
+        .def_property_readonly("is_mineral", &UnitType::isMineral, "Is the unit type a mineralfield")
+        .def_property_readonly("is_worker", &UnitType::isWorker, "Is the unit type a unit which is a worker")
+        .def_property_readonly("is_morphed_building", &UnitType::isMorphedBuilding, "Has this building been mophed")
         // Not implemented in CommandCenter
         //.def_property_readonly("can_attack", &UnitType::canAttack)
         //.def_property_readonly("can_Move", &UnitType::canMove)
-        .def_property_readonly("is_addon", &UnitType::isAddon)
-        .def_property_readonly("attack_range", &UnitType::getAttackRange)
-        .def_property_readonly("tile_width", &UnitType::tileWidth)
-        .def_property_readonly("tile_height", &UnitType::tileHeight)
-        .def_property_readonly("supply_provided", &UnitType::supplyProvided)
-        .def_property_readonly("supply_required", &UnitType::supplyRequired)
-        .def_property_readonly("mineral_price", &UnitType::mineralPrice)
-        .def_property_readonly("gas_price", &UnitType::gasPrice)
-        .def_property_readonly("is_overlord", &UnitType::isOverlord)
-        .def_property_readonly("is_larva", &UnitType::isLarva)
-        .def_property_readonly("is_egg", &UnitType::isEgg)
-        .def_property_readonly("is_queen", &UnitType::isQueen)
-        .def_property_readonly("is_tank", &UnitType::isTank)
-		.def_property_readonly("get_equivalent_units", &UnitType::getEquivalentUnits)
-		.def_property_readonly("required_attached", &UnitType::requiredAttached)
-		.def_property_readonly("build_time", &UnitType::getBuildTime)
+        .def_property_readonly("is_addon", &UnitType::isAddon, "Is this unit type a addon")
+		.def_property_readonly("can_attack_ground", &UnitType::canAttackGound, "True if this unit can attack ground units")
+		.def_property_readonly("can_attack_air", &UnitType::canAttackAir, "True if this unit can attack air units")
+        .def_property_readonly("attack_range", &UnitType::getAttackRange, "Returns the attack range of the unit type")
+		.def_property_readonly("attack_damage", &UnitType::getAttackDamage, "Returns the base attack damage of the unit type")
+        .def_property_readonly("tile_width", &UnitType::tileWidth, "Returns the width of the unit type")
+        .def_property_readonly("tile_height", &UnitType::tileHeight, "Returns the height of the unit type")
+        .def_property_readonly("supply_provided", &UnitType::supplyProvided, "Amount of supply provided by the unit type")
+        .def_property_readonly("supply_required", &UnitType::supplyRequired, "Amount of supply required for the unit type")
+        .def_property_readonly("mineral_price", &UnitType::mineralPrice, "Mineral price of the unit type")
+        .def_property_readonly("gas_price", &UnitType::gasPrice, "Gas price of the unit type")
+        .def_property_readonly("is_overlord", &UnitType::isOverlord, "Is this a ZERG_OVERLORD")
+        .def_property_readonly("is_larva", &UnitType::isLarva, "is this a ZERG_LARVA")
+        .def_property_readonly("is_egg", &UnitType::isEgg, "is this a ZERG_EGG")
+        .def_property_readonly("is_queen", &UnitType::isQueen, "is this a ZERG_QUEEN")
+        .def_property_readonly("is_tank", &UnitType::isTank, "is this a TERRAN_SIEGETANK or TERRAN_SIEGETANKSIEGED")
+		.def_property_readonly("get_equivalent_units", &UnitType::getEquivalentUnits, "Units this is equivalent to in terms of satisfying tech requirements.")
+		.def_property_readonly("required_attached", &UnitType::requiredAttached, "Whether tech_requirement is an add-on.")
+		.def_property_readonly("build_time", &UnitType::getBuildTime, "How long the unit takes to build.")
         .def("__hash__", [](const UnitType & unit_type) { return std::hash<CCUnitID>{}(unit_type.getAPIUnitType()); })
         .def(py::self == py::self)
         .def("__repr__", [](const UnitType & unit_type) { return "<UnitType: '" + unit_type.getName() + "'>"; });
diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp
index 1121edc..fdfe49e 100644
--- a/python-api-src/library.cpp
+++ b/python-api-src/library.cpp
@@ -80,42 +80,42 @@ 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)
-		.def("debug_create_unit", &IDABot::DebugCreateUnit, "unit_type"_a, "p"_a, "player_id"_a = 1, "count"_a = 1)
-		.def("debug_kill_unit", &IDABot::DebugKillUnit, "Kill unit from debug mode")
+		.def("send_chat", &IDABot::SendChat, "Sends the string 'message' to the game chat", "message"_a)
+		.def("get_all_units", &IDABot::GetAllUnits, "Returns a list of all visible units, including minerals and geysers")
+		.def("get_my_units", &IDABot::GetMyUnits, "Returns a list of all your units") 
+		.def("get_player_race", &IDABot::GetPlayerRace, "Returns the players race, useful if you play Race.Random")
+		.def("debug_create_unit", &IDABot::DebugCreateUnit, "This method creates the nr (INT) of units on the position :class:`library.Point2D`, the unit belongs to the Player Constant", "unit_type"_a, "p"_a, "player_id"_a = 0, "count"_a = 1)
+		.def("debug_kill_unit", &IDABot::DebugKillUnit, "Kill the unit from debug mode")
 		.def("debug_show_map", &IDABot::DebugShowMap, "Show the entire map through debug mode")
-		.def("debug_fast_build", &IDABot::DebugFastBuild, "Set build time to 1 through debug mode")
+		.def("debug_fast_build", &IDABot::DebugFastBuild, "Set build time in game to 1 through debug mode")
 		.def("debug_enemy_control", &IDABot::DebugEnemyControl, "Control the enemy through debug mode")
-		.def("debug_ignore_food", &IDABot::DebugIgnoreFood, "Ignore the food through debug mode")
-		.def("debug_ignore_resource_cost", &IDABot::DebugIgnoreResourceCost, "Ignore the resource cost through debug mode")
-		.def("debug_give_all_resources", &IDABot::DebugGiveAllResources, "Give all the resources through debug mode")
+		.def("debug_ignore_food", &IDABot::DebugIgnoreFood, "Ignore the food in game through debug mode")
+		.def("debug_ignore_resource_cost", &IDABot::DebugIgnoreResourceCost, "Ignore the resource cost in game, making, everything cost zero resources through debug mode")
+		.def("debug_give_all_resources", &IDABot::DebugGiveAllResources, "Set the mineral and vespene gas to 5000 through debug mode")
 		.def("debug_god_mode", &IDABot::DebugGodMode, "Give the player god mode")
-		.def("debug_ignore_mineral", &IDABot::DebugIgnoreMineral, "Ignore the mineral cost through debug mode")
-		.def("debug_no_cooldowns", &IDABot::DebugNoCooldowns, "Deactive cooldowns through debug mode")
+		.def("debug_ignore_mineral", &IDABot::DebugIgnoreMineral, "Ignore the mineral cost in game through debug mode")
+		.def("debug_no_cooldowns", &IDABot::DebugNoCooldowns, "Deactive cooldowns (Basically setting them to 0) through debug mode")
 		.def("debug_give_all_tech", &IDABot::DebugGiveAllTech, "Give all the tech to the player through debug mode")
-		.def("debug_give_all_upgrades", &IDABot::DebugGiveAllUpgrades, "Give all the upgrades to the player trough debug mode")
-		.def("debug_set_score", &IDABot::DebugSetScore, "Set the Players score through debug mode")
-		.def("debug_end_game", &IDABot::DebugEndGame, "End the game through debug mode")
+		.def("debug_give_all_upgrades", &IDABot::DebugGiveAllUpgrades, "Give all the upgrades to the player through debug mode")
+		.def("debug_set_score", &IDABot::DebugSetScore, "Set the Players score in game through debug mode")
+		.def("debug_end_game", &IDABot::DebugEndGame, "End the game through debug mode. If the Boolean is True then victory. If False, defeat.")
 		.def("debug_set_energy", &IDABot::DebugSetEnergy, "Set the energy on a unit through debug mode")
 		.def("debug_set_life", &IDABot::DebugSetLife, "Set the life on a unit through debug mode")
 		.def("debug_set_shields", &IDABot::DebugSetShields, "Set the shields on a unit through debug mode")
 		.def("get_enemy_base_location", &IDABot::GetEnemyBaseLocations, "Return the CCpostion of the enemy base")
-		.def("move_camera", &IDABot::CameraMove, "Move the camera to p postion", "p"_a)
+		.def("move_camera", &IDABot::CameraMove, "Move the camera to the postion", "p"_a)
 		.def("has_creep", &IDABot::HasCreep, "Returns true if there is creep at position p", "p"_a)
 		.def("ability_for_upgrade", &IDABot::abilityForUpgrade, "Ability that researches this upgrade", "upgrade"_a)
 		.def("upgrade_mineral_cost", &IDABot::UpgradeMineralCost, "Mineral cost of researching the upgrade", "upgrade"_a)
 		.def("upgrade_gas_cost", &IDABot::UpgradeGasCost, "Vespene/gas cost of researching the upgrade", "upgrade"_a)
 		.def("upgrade_research_time", &IDABot::UpgradeResearchTime, "Time in GameLoops to research this upgrade", "upgrade"_a)
 		.def("effect_radius", &IDABot::RadiusEffect, "Size of the circle the effect impacts", "effect"_a)
-		.def_property_readonly("base_location_manager", &IDABot::Bases)
-		.def_property_readonly("tech_tree", &IDABot::GetTechTree)
-		.def_property_readonly("map_tools", &IDABot::Map)
-		.def_property_readonly("building_placer", &IDABot::GetBuildingPlacer)
-		.def_property_readonly("start_location", &IDABot::GetStartLocation, "CCPosition representing the start location")
-		.def_property_readonly("start_locations", &IDABot::GetStartLocations, "CCPosition representing the start locations")
+		.def_property_readonly("base_location_manager", &IDABot::Bases, "An instance of the class :class:`library.BaseLocationManager`")
+		.def_property_readonly("tech_tree", &IDABot::GetTechTree, "An instance of the class :class:`library.TechTree`")
+		.def_property_readonly("map_tools", &IDABot::Map, "An instance of the class :class:`library.MapTools`")
+		.def_property_readonly("building_placer", &IDABot::GetBuildingPlacer, "An instance of the class :class:`library.BuildingPlacer`")
+		.def_property_readonly("start_location", &IDABot::GetStartLocation, "CCPosition representing the start location, note that it is the depot position that is returned.")
+		.def_property_readonly("start_locations", &IDABot::GetStartLocations, "List of CCPositions representing the start locations, note that it is the depot positions and not the center positions")
 		.def_property_readonly("minerals", &IDABot::GetMinerals, "How much minerals we currently have")
 		.def_property_readonly("current_supply", &IDABot::GetCurrentSupply, "How much supply we are currently using")
 		.def_property_readonly("max_supply", &IDABot::GetMaxSupply, "How much supply we can currently use")
diff --git a/src/BaseLocation.cpp b/src/BaseLocation.cpp
index b74c4b8..3175066 100644
--- a/src/BaseLocation.cpp
+++ b/src/BaseLocation.cpp
@@ -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);
diff --git a/src/BaseLocation.h b/src/BaseLocation.h
index 1b22c2a..4378c73 100644
--- a/src/BaseLocation.h
+++ b/src/BaseLocation.h
@@ -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;
 
diff --git a/src/BaseLocationManager.cpp b/src/BaseLocationManager.cpp
index 848c23f..93a89d9 100644
--- a/src/BaseLocationManager.cpp
+++ b/src/BaseLocationManager.cpp
@@ -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; }
@@ -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);
diff --git a/src/BaseLocationManager.h b/src/BaseLocationManager.h
index 8d57be3..1577bba 100644
--- a/src/BaseLocationManager.h
+++ b/src/BaseLocationManager.h
@@ -32,4 +32,9 @@ public:
     
     const BaseLocation * getNextExpansion(int player) const;
 
+private:
+	void updateMinerals(BaseLocation & baseToUpdate);
+	void updateGeysers(BaseLocation & baseToUpdate);
+
+
 };
diff --git a/src/BuildingPlacer.cpp b/src/BuildingPlacer.cpp
index 9638349..8ecf797 100644
--- a/src/BuildingPlacer.cpp
+++ b/src/BuildingPlacer.cpp
@@ -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);
@@ -32,12 +49,12 @@ bool BuildingPlacer::canBuildHere(int bx, int by, const UnitType & type) const
 	int xdelta = (int)std::ceil((width - 1.0) / 2);
 	int ydelta = (int)std::ceil((height - 1.0) / 2);
 
-    // check the reserve map
+    // 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) || m_reserveMap[x][y])
+            if (!m_bot.Map().isValidTile(x, y) || isReserved(x, y) || !m_bot.Map().isWalkable(x, y))
             {
                 return false;
             }
@@ -53,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
 {
@@ -64,6 +134,7 @@ 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);
@@ -97,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;
                 }
@@ -197,6 +268,7 @@ 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();
 
diff --git a/src/BuildingPlacer.h b/src/BuildingPlacer.h
index 791d3d9..e10c228 100644
--- a/src/BuildingPlacer.h
+++ b/src/BuildingPlacer.h
@@ -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
diff --git a/src/IDABot.cpp b/src/IDABot.cpp
index 10c29c1..8a5fbf7 100644
--- a/src/IDABot.cpp
+++ b/src/IDABot.cpp
@@ -72,6 +72,13 @@ void IDABot::OnStep()
 	m_map.onFrame();
 	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.
 	// -----------------------------------------------------------------
@@ -231,7 +238,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) 
diff --git a/src/MapTools.cpp b/src/MapTools.cpp
index 7436317..23d5b21 100644
--- a/src/MapTools.cpp
+++ b/src/MapTools.cpp
@@ -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();
@@ -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
@@ -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();
diff --git a/src/MapTools.h b/src/MapTools.h
index 870052a..b5490ad 100644
--- a/src/MapTools.h
+++ b/src/MapTools.h
@@ -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,11 +46,13 @@ public:
 
     int     width() const;
     int     height() const;
+	std::string name() const;
     float   terrainHeight(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;
diff --git a/src/TechTree.cpp b/src/TechTree.cpp
index d0a94c4..1c7c983 100644
--- a/src/TechTree.cpp
+++ b/src/TechTree.cpp
@@ -101,6 +101,10 @@ void TechTree::setSuppressWarnings(bool b)
 	suppressWarnings = b;
 }
 
+bool TechTree::getSuppressWarnings() const
+{
+	return suppressWarnings;
+}
 
 void TechTree::initUnitTypeData()
 {
@@ -275,7 +279,7 @@ void TechTree::initUpgradeData()
     m_upgradeData[sc2::UPGRADE_ID::PUNISHERGRENADES] =                  { sc2::Race::Terran,  50,  50, 0,  960, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_CONCUSSIVESHELLS, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
     m_upgradeData[sc2::UPGRADE_ID::RAVENCORVIDREACTOR] =                { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENCORVIDREACTOR, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
     m_upgradeData[sc2::UPGRADE_ID::RAVENRECALIBRATEDEXPLOSIVES] =       { sc2::Race::Terran, 150, 150, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_RAVENRECALIBRATEDEXPLOSIVES, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
-    m_upgradeData[sc2::UPGRADE_ID::SHIELDWALL] =                        { sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_COMBATSHIELD, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client) }, {}, {} };
+    m_upgradeData[sc2::UPGRADE_ID::SHIELDWALL] =						{ sc2::Race::Terran, 100, 100, 0, 1760, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_COMBATSHIELD, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_BARRACKSTECHLAB, m_client) }, {}, {} };
     m_upgradeData[sc2::UPGRADE_ID::STIMPACK] =                          { sc2::Race::Terran, 100, 100, 0, 2720, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_STIMPACK, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_SCV, m_client) }, {}, {} };
     m_upgradeData[sc2::UPGRADE_ID::TERRANBUILDINGARMOR] =               { sc2::Race::Terran, 150, 150, 0, 2240, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANSTRUCTUREARMORUPGRADE, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {}, {} };
     m_upgradeData[sc2::UPGRADE_ID::TERRANINFANTRYARMORSLEVEL1] =        { sc2::Race::Terran, 100, 100, 0, 2560, false, false, false, false, false, false, false, sc2::ABILITY_ID::RESEARCH_TERRANINFANTRYARMORLEVEL1, 0, { UnitType(sc2::UNIT_TYPEID::TERRAN_ENGINEERINGBAY, m_client) }, {}, {} };
diff --git a/src/TechTree.h b/src/TechTree.h
index 412aaf4..df75efb 100644
--- a/src/TechTree.h
+++ b/src/TechTree.h
@@ -45,7 +45,8 @@ public:
     void onStart();
 
 	void setSuppressWarnings(bool b);
-
+	bool getSuppressWarnings() const;
+	
     const TypeData & getData(const UnitType & type) const;
     const TypeData & getData(const CCUpgrade & type) const;
     const TypeData & getData(const MetaType & type) const;
diff --git a/src/Unit.cpp b/src/Unit.cpp
index 50b5fa4..130eaa3 100644
--- a/src/Unit.cpp
+++ b/src/Unit.cpp
@@ -118,7 +118,7 @@ bool Unit::isCompleted() const
 bool Unit::isTraining() const
 {
 	BOT_ASSERT(isValid(), "Unit is not valid");
-	return m_unit->orders.size() > 0;
+	return m_unit->orders.size() > 0 && m_unitType.isBuilding();
 }
 
 bool Unit::isBeingConstructed() const
@@ -339,6 +339,12 @@ Unit Unit::getTarget() const
     if(getUnitPtr()->orders.size() > 0){
 		// t_id is set to the unit tag of the target
 		CCUnitID t_id = getUnitPtr()->orders[0].target_unit_tag;
+
+		// if it doesn't have a target. Return itself
+		if (m_bot->GetUnit(t_id) == nullptr) {
+			return *this;
+		}
+
 		// IDABot finds the unit with this tag
 		return m_bot->GetUnit(t_id);
     }
@@ -400,6 +406,20 @@ float Unit::getProgress() const
 	return -1;
 }
 
+const std::vector<float> Unit::getAllProgress() const
+{
+	BOT_ASSERT(isValid(), "Unit is not valid");
+	// If unit has order, return progress of first order
+	std::vector<float> progressions;
+	if (getUnitPtr()->orders.size() > 0) {
+		for(int i = 0; i < getUnitPtr()->orders.size(); i++) {
+			progressions.push_back(getUnitPtr()->orders[i].progress);
+		}
+	}
+
+	return progressions;
+}
+
 sc2::AbilityID Unit::getCurrentAbilityID() const
 {
 	BOT_ASSERT(isValid(), "Unit is not valid");
diff --git a/src/Unit.h b/src/Unit.h
index f68a09b..a33c6ff 100644
--- a/src/Unit.h
+++ b/src/Unit.h
@@ -56,6 +56,7 @@ public:
     Unit getTarget() const;
     CCHealth getMaxHitPoints() const;
     float getProgress() const;
+	const std::vector<float> getAllProgress() const;
     sc2::AbilityID getCurrentAbilityID() const;
     void holdPosition() const;
     void patrol(const CCPosition & targetPosition) const;
diff --git a/src/UnitType.cpp b/src/UnitType.cpp
index 56b113e..f4fcbd4 100644
--- a/src/UnitType.cpp
+++ b/src/UnitType.cpp
@@ -16,7 +16,7 @@ UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client)
 	, m_observer(nullptr)
 
 {
-    
+
 }
 
 UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDABot & bot)
@@ -25,6 +25,7 @@ UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDABot &
 	, m_bot(&bot)
 	, m_observer(nullptr)
 {
+
 }
 
 UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDAReplayObserver & observer)
@@ -34,9 +35,8 @@ UnitType::UnitType(const sc2::UnitTypeID & type, sc2::Client & client, IDAReplay
 	, m_bot(nullptr)
 
 {
-}
-
 
+}
 
 sc2::UnitTypeID UnitType::getAPIUnitType() const
 {
@@ -135,9 +135,12 @@ bool UnitType::isRefinery() const
 #ifdef SC2API
     switch (m_type.ToType()) 
     {
-        case sc2::UNIT_TYPEID::TERRAN_REFINERY      : return true;
-        case sc2::UNIT_TYPEID::PROTOSS_ASSIMILATOR  : return true;
-        case sc2::UNIT_TYPEID::ZERG_EXTRACTOR       : return true;
+        case sc2::UNIT_TYPEID::TERRAN_REFINERY			: return true;
+		case sc2::UNIT_TYPEID::TERRAN_REFINERYRICH		: return true;
+        case sc2::UNIT_TYPEID::PROTOSS_ASSIMILATOR		: return true;
+		case sc2::UNIT_TYPEID::PROTOSS_ASSIMILATORRICH  : return true;
+        case sc2::UNIT_TYPEID::ZERG_EXTRACTOR			: return true;
+		case sc2::UNIT_TYPEID::ZERG_EXTRACTORRICH		: return true;
         default: return false;
     }
 #else
@@ -171,6 +174,10 @@ bool UnitType::isGeyser() const
         case sc2::UNIT_TYPEID::NEUTRAL_VESPENEGEYSER        : return true;
         case sc2::UNIT_TYPEID::NEUTRAL_PROTOSSVESPENEGEYSER : return true;
         case sc2::UNIT_TYPEID::NEUTRAL_SPACEPLATFORMGEYSER  : return true;
+		case sc2::UNIT_TYPEID::NEUTRAL_SHAKURASVESPENEGEYSER: return true;
+		case sc2::UNIT_TYPEID::NEUTRAL_RICHVESPENEGEYSER	: return true;
+		case sc2::UNIT_TYPEID::NEUTRAL_PURIFIERVESPENEGEYSER: return true;
+
         default: return false;
     }
 #else
@@ -183,12 +190,15 @@ bool UnitType::isMineral() const
 #ifdef SC2API
     switch (m_type.ToType()) 
     {
-        case sc2::UNIT_TYPEID::NEUTRAL_MINERALFIELD         : return true;
-        case sc2::UNIT_TYPEID::NEUTRAL_MINERALFIELD750      : return true;
-        case sc2::UNIT_TYPEID::NEUTRAL_RICHMINERALFIELD     : return true;
-        case sc2::UNIT_TYPEID::NEUTRAL_RICHMINERALFIELD750  : return true;
-		case sc2::UNIT_TYPEID::NEUTRAL_LABMINERALFIELD		: return true;
-		case sc2::UNIT_TYPEID::NEUTRAL_LABMINERALFIELD750	: return true;
+        case sc2::UNIT_TYPEID::NEUTRAL_MINERALFIELD				: return true;
+        case sc2::UNIT_TYPEID::NEUTRAL_MINERALFIELD750			: return true;
+        case sc2::UNIT_TYPEID::NEUTRAL_RICHMINERALFIELD			: return true;
+        case sc2::UNIT_TYPEID::NEUTRAL_RICHMINERALFIELD750		: return true;
+		case sc2::UNIT_TYPEID::NEUTRAL_LABMINERALFIELD			: return true;
+		case sc2::UNIT_TYPEID::NEUTRAL_LABMINERALFIELD750		: return true;
+		case sc2::UNIT_TYPEID::NEUTRAL_PURIFIERMINERALFIELD		: return true;
+		case sc2::UNIT_TYPEID::NEUTRAL_PURIFIERMINERALFIELD750	: return true;
+
         default: return false;
     }
 #else
@@ -212,6 +222,54 @@ bool UnitType::isWorker() const
 #endif
 }
 
+bool UnitType::canAttackGound() const 
+{
+#ifdef SC2API
+	auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons;
+
+	if (weapons.empty())
+	{
+		return false;
+	}
+	for (auto & weapon : weapons)
+	{
+		if (weapon.type == sc2::Weapon::TargetType::Ground || weapon.type == sc2::Weapon::TargetType::Any) 
+		{
+			return true;
+		}
+	}
+	return false;
+#else
+	// TODO: this is nothing right now...
+	// just like with the attackRange we should never get in here.
+	return 0.0f;
+#endif
+}
+
+bool UnitType::canAttackAir() const 
+{
+#ifdef SC2API
+	auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons;
+
+	if (weapons.empty())
+	{
+		return false;
+	}
+	for (auto & weapon : weapons)
+	{
+		if (weapon.type == sc2::Weapon::TargetType::Air || weapon.type == sc2::Weapon::TargetType::Any)
+		{
+			return true;
+		}
+	}
+	return false;
+#else
+	// TODO: this is nothing right now...
+	// just like with the attackRange we should never get in here.
+	return 0.0f;
+#endif
+}
+
 CCPositionType UnitType::getAttackRange() const
 {
 #ifdef SC2API
@@ -238,6 +296,33 @@ CCPositionType UnitType::getAttackRange() const
 #endif
 }
 
+float UnitType::getAttackDamage() const
+{
+#ifdef SC2API
+	auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons;
+
+	if (weapons.empty())
+	{
+		return 0.0f;
+	}
+
+	float maxDamage = 0.0f;
+	for (auto & weapon : weapons)
+	{
+		if (weapon.range > maxDamage)
+		{
+			maxDamage = weapon.damage_;
+		}
+	}
+
+	return maxDamage;
+#else
+	// TODO: this is nothing right now...
+	// just like with the attackRange we should never get in here.
+	return 0.0f;
+#endif
+}
+
 int UnitType::tileWidth() const
 {
 #ifdef SC2API
diff --git a/src/UnitType.h b/src/UnitType.h
index 1491bb1..1fe66ae 100644
--- a/src/UnitType.h
+++ b/src/UnitType.h
@@ -49,7 +49,10 @@ public:
     bool canAttack() const;
     bool canMove() const;
     bool isAddon() const;
+	bool canAttackGound() const;
+	bool canAttackAir() const;
     CCPositionType getAttackRange() const;
+	float getAttackDamage() const;
     int tileWidth() const;
     int tileHeight() const;
     int supplyProvided() const;
-- 
GitLab