From d583b1166d0f7386c0556ae24ce298e10187e283 Mon Sep 17 00:00:00 2001
From: David Warnquist <davwa458@student.liu.se>
Date: Mon, 24 Jun 2024 22:55:02 +0200
Subject: [PATCH] Docs: Big docs update

---
 README.md                              | 11 ++++-
 docs/conf.py                           |  9 +++-
 docs/config.yaml                       | 10 +++++
 docs/constants.rst                     | 13 ++----
 docs/enum_doc.py                       | 15 +++++++
 docs/helpers.rst                       | 39 +---------------
 docs/idabot.rst                        |  4 +-
 docs/replayunit.rst                    | 41 +----------------
 docs/types.rst                         | 35 ++++++++-------
 docs/unit.rst                          | 25 +----------
 generate_pydocs.py                     |  8 ++--
 python-api-src/lib_base_location.cpp   | 16 ++++---
 python-api-src/lib_building_placer.cpp | 14 ++++--
 python-api-src/lib_color.cpp           |  3 ++
 python-api-src/lib_map_tools.cpp       | 26 ++++++++++-
 python-api-src/lib_replay_unit.cpp     | 61 ++++++++++++++------------
 python-api-src/lib_sc2_typeenums.cpp   | 10 ++---
 python-api-src/lib_tech_tree.cpp       | 13 ++++--
 python-api-src/lib_unit.cpp            | 28 +++++++++---
 python-api-src/lib_unittype.cpp        | 11 +++--
 python-api-src/lib_util.cpp            |  3 ++
 python-api-src/library.cpp             | 14 +++---
 requirements.txt                       | 25 +++++++++++
 23 files changed, 237 insertions(+), 197 deletions(-)
 create mode 100644 docs/config.yaml
 create mode 100644 docs/enum_doc.py
 create mode 100644 requirements.txt

diff --git a/README.md b/README.md
index 722feb087..daf328a91 100644
--- a/README.md
+++ b/README.md
@@ -100,7 +100,11 @@ Studio.
    threads)
 
 # Create autocomplete stub
-Make sure you have mypy installed. Navigate to where your library.pyd/so is located then run:
+Make sure you have mypy installed. This can be done with:
+```terminal
+pip3 install -r requirements.txt
+```
+Navigate to where your library.pyd/so is located then run:
 ```terminal
 stubgen -m library -o .
 ```
@@ -115,6 +119,11 @@ See [separate page](pycharm.md).
 1. Build the library binary as described above, the documentation uses the
    binary to automate some parts
 2. Install [Sphinx](http://www.sphinx-doc.org)
+   
+   This can be done with:
+   ```terminal
+   pip3 install -r requirements.txt
+   ```
 3. Go to the `docs` subfolder,
 4. If you are **not** running Visual Studio and building in Release mode you
    have to change row 17 of [conf.py](docs/conf.py) to match the location
diff --git a/docs/conf.py b/docs/conf.py
index 8607f50a4..1f9ada98a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -17,6 +17,8 @@ import sys,os
 sys.path.append(os.path.join(os.getcwd(), "..", "build", "python-api-src", "Release"))
 sys.path.append(os.path.join(os.getcwd(), "..", "build", "python-api-src"))
 
+sys.path.append(os.getcwd())
+
 # -- Project information -----------------------------------------------------
 
 project = 'PyCommandCenter'
@@ -41,7 +43,10 @@ release = ''
 extensions = [
     'sphinx.ext.autodoc',
     'sphinx.ext.githubpages',
-    'sphinx.ext.autosummary'
+    'sphinx.ext.autosummary',
+    'sphinx.ext.napoleon',
+    'sphinx_design',
+    'enum_doc',
 ]
 
 autodoc_docstring_signature=True
@@ -64,7 +69,7 @@ master_doc = 'index'
 #
 # This is also used if you do content translation via gettext catalogs.
 # Usually you set "language" from the command line for these cases.
-language = None
+language = 'en'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
diff --git a/docs/config.yaml b/docs/config.yaml
new file mode 100644
index 000000000..4028d12f7
--- /dev/null
+++ b/docs/config.yaml
@@ -0,0 +1,10 @@
+language: en
+sphinx: true
+extensions:
+  - sphinx_panels
+default_domain: py
+consecutive_numbering: true
+colon_fences: true
+dollar_math: true
+conversions:
+  sphinx_panels.dropdown.DropdownDirective: parse_all
\ No newline at end of file
diff --git a/docs/constants.rst b/docs/constants.rst
index a4e627550..904854985 100644
--- a/docs/constants.rst
+++ b/docs/constants.rst
@@ -35,17 +35,10 @@ AIBuild
 Race
 ----
 
-.. class:: library.Race
-
-   The following three values represent actual races:
-   
-   .. attribute:: Race.Protoss
-   .. attribute:: Race.Terran
-   .. attribute:: Race.Zerg
-
-   The following attribute means a randomly selected race from the three above:
+.. autoclass:: library.Race
+   :members:
+   :undoc-members:
 
-   .. attribute:: Race.Random
 
 
 .. toctree::
\ No newline at end of file
diff --git a/docs/enum_doc.py b/docs/enum_doc.py
new file mode 100644
index 000000000..691ca3432
--- /dev/null
+++ b/docs/enum_doc.py
@@ -0,0 +1,15 @@
+"""
+Self built extension to remove the "Members" section of enums from the autodoc output.
+"""
+
+def setup(app):
+    app.connect('autodoc-process-docstring', filter_autodoc_members)
+
+def filter_autodoc_members(app, what, name, obj, options, lines):
+    new_lines = []
+    for line in lines:
+        if "Members:" in line:
+            break
+        else:
+            new_lines.append(line)
+    lines[:] = new_lines
\ No newline at end of file
diff --git a/docs/helpers.rst b/docs/helpers.rst
index 9f3c4f096..deebc6345 100644
--- a/docs/helpers.rst
+++ b/docs/helpers.rst
@@ -50,9 +50,6 @@ BaseLocation
    .. autoattribute:: geysers
 
    .. automethod:: get_ground_distance
-      
-      This function uses BFS and moves in a vertical and horizontal position. Because of this,
-      the distance might overshoot compared to calculating it with Pythagoras' theorem.
 
    .. automethod:: is_occupied_by_player
 
@@ -64,11 +61,7 @@ BaseLocation
 TechTree
 --------
 
-.. class:: library.TechTree
-
-   This class contains all information about units and what is required to
-   build a certain unit and what builds it. It only has one method, which is
-   used to look-up unit types properties:
+.. autoclass:: library.TechTree
 
    This class has some invalid information by default, this can be corrected by
    placing the file `techtree.json` in the working directory. The
@@ -77,14 +70,7 @@ TechTree
    this can be found under the folder data in this link_.
    A recent file is included in the `template repository`_.
 
-   Instead of using TechTree, it's possible to use the functions in UnitType for
-   structure, etc. In IDABot there is functions for getting data about upgrades.	
-
-   .. method:: get_data(argument) -> library.TypeData
-
-      Argument is either an instance of the class :class:`library.UnitType` or
-      an instance of the class :class:`library.CCUpgrade`, depending on what
-      information is wanted.
+   .. automethod:: get_data(argument) -> library.TypeData
 
 .. _link: https://github.com/BurnySc2/sc2-techtree
 .. _here: https://github.com/noorus/sc2-gamedata
@@ -107,22 +93,6 @@ MapTools
    :members:
    :undoc-members:
 
-   This class contains two types of methods:
-
-   * Methods for drawing information to the screen
-   * Methods for extracting information about the map
-
-   First, let us look at the method concerning drawing information to the 
-   screen. Methods with the suffix ``_screen`` takes percentages of the 
-   screens height and width, i.e. values between 0 and 1. Methods without 
-   this suffix uses the same coordinate system as the game, i.e. world 
-   coordinates.
-
-   The top three methods below takes in a Point2D, but it's possible to
-   send in x and y as floats instead of Point2D.
-
-   There is also methods which are useful for extracting information about the 
-   game map.
 
 Color
 ~~~~~
@@ -147,10 +117,5 @@ BuildingPlacer
    :members:
    :undoc-members:
 
-   This class is useful for placing all buildings, except refineries and town halls (Command Centers, Hacheries and Nexus).
-
-   If you want to place a town hall, take a look at attribute `depot_location` of :class:`library.BaseLocation`.
-
-   If you want to place a refinery, take a look at attribute `geysers` of :class:`library.BaseLocation` and the method build_target of :class:`library.Unit`.
 
 .. toctree::
\ No newline at end of file
diff --git a/docs/idabot.rst b/docs/idabot.rst
index 0cc1c87bf..c0e9e9139 100644
--- a/docs/idabot.rst
+++ b/docs/idabot.rst
@@ -17,9 +17,7 @@ IDABot
 
    .. method:: IDABot.on_game_start(self)
 
-      This method when Starcraft has stared, when you inherit it you have to
-      call the parent's on_game_start method in order to make it work (see
-      :ref:`gettingstarted`).
+       (see :ref:`gettingstarted` for example).
 
    .. method:: IDABot.on_step(self)
 
diff --git a/docs/replayunit.rst b/docs/replayunit.rst
index 7d27a67eb..97418b8a2 100644
--- a/docs/replayunit.rst
+++ b/docs/replayunit.rst
@@ -1,75 +1,38 @@
 ReplayUnit
 ==========
 
-.. class:: library.ReplayUnit
-
-   An instance of the class Unit represents one unit in a replay. A ReplayUnit is a
-   :class:`library.Unit` white some limitations.
-
-   It is possible to use ReplayUnit as keys in a dictionary, which might be helpful
-   for bookkeeping.
+.. autoclass:: library.ReplayUnit
 
    Properties:
 
    .. autoattribute:: buffs
-
-      Returns a list of BuffID
-
    .. autoattribute:: build_percentage
    .. autoattribute:: energy
    .. autoattribute:: facing
-
-      Returns the direction the unit is facing
-
    .. autoattribute:: hit_points
    .. autoattribute:: max_hit_points
    .. 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:: ReplayUnit.player
-
-      Returns the constant corresponding to player which this unit belongs to.
-      See :ref:`playerconstants` for more information.
-
+   .. autoattribute:: ReplayUnit.player
    .. autoattribute:: position
    .. autoattribute:: current_ability_id
-
    .. autoattribute:: progress
-
-      Returns the progress of currently used ability (-1 if not using ability)
-
    .. autoattribute:: radius
-
-      Retruns the radius of the unit
-
    .. autoattribute:: shields
    .. autoattribute:: tile_position
    .. autoattribute:: unit_type
-
-      Returns the :class:`library.UnitType` of the unit
-
    .. autoattribute:: weapon_cooldown
    .. autoattribute:: is_carrying_minerals
 
-      Returns if this unit is currently holding minerals
-
 
 .. toctree::
\ No newline at end of file
diff --git a/docs/types.rst b/docs/types.rst
index 1227e4b87..33b8748c0 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -16,9 +16,6 @@ the game anymore.
 UnitType
 --------
 
-As explained above, this class is a wrapper around the class
-:class:`library.UNIT_TYPEID`.
-
 .. autoclass:: library.UnitType
    :members:
    :undoc-members:
@@ -27,30 +24,38 @@ As explained above, this class is a wrapper around the class
 UNIT_TYPEID
 -----------
 
-.. autoclass:: library.UNIT_TYPEID
-   :members:
-   :undoc-members:
+.. dropdown:: UNIT_TYPEID Enum (dropdown because of the size of the enum)
+
+   .. autoclass:: library.UNIT_TYPEID
+      :members:
+      :undoc-members:
 
 ABILITY_ID
 ----------
 
-.. autoclass:: library.ABILITY_ID 	
-   :members:
-   :undoc-members:
+.. dropdown:: ABILITY_ID Enum (dropdown because of the size of the enum)
+
+   .. autoclass:: library.ABILITY_ID 	
+      :members:
+      :undoc-members:
 
 UPGRADE_ID
 ----------
 
-.. autoclass:: library.UPGRADE_ID 	
-   :members:
-   :undoc-members:
+.. dropdown:: UPGRADE_ID Enum (dropdown because of the size of the enum)
+
+   .. autoclass:: library.UPGRADE_ID 	
+      :members:
+      :undoc-members:
 
 EFFECT_ID
 ----------
 EffectID is for things like ravager bile, or fungal or even a scan.
 
-.. autoclass:: library.EFFECT_ID 	
-   :members:
-   :undoc-members:
+.. dropdown:: EFFECT_ID Enum (dropdown because of the size of the enum)
+
+   .. autoclass:: library.EFFECT_ID 	
+      :members:
+      :undoc-members:
 
 .. toctree::
\ No newline at end of file
diff --git a/docs/unit.rst b/docs/unit.rst
index de4f7b401..26a6c27d6 100644
--- a/docs/unit.rst
+++ b/docs/unit.rst
@@ -1,22 +1,8 @@
 Unit
 ====
 
-.. class:: library.Unit
+.. autoclass:: library.Unit
 
-   An instance of the class Unit represents one unit in the game. The units are 
-   not limited to moveable units, but every entity which is not part of the 
-   background is a unit. For example, the minerals and geysers are units as 
-   well as all buildings.
-
-   For all possible types of units see the enum :class:`library.UNIT_TYPEID`. 
-   Some types of objects are almost the same, for example there are many types 
-   of mineral deposits, but all of them are mineable. This is one of the 
-   motivations behind the :class:`library.UnitType` which aims to to make the 
-   list of types more manageable. The UnitType can be accessed by the 
-   :any:`Unit.unit_type` property.
-
-   It is possible to use Unit as keys in a dictionary, which might be helpful
-   for bookkeeping.
 
    Properties:
 
@@ -61,18 +47,11 @@ 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)
-
    .. automethod:: is_constructing
    .. automethod:: stop
    .. automethod:: attack_unit
    .. automethod:: attack_move
-   .. method:: Unit.move(self, point)
-
-      Move the unit to the given point, the point being an instance of either 
-      :class:`library.Point2D` or :class:`library.Point2DI`.
-
+   .. automethod:: Unit.move(self, point)
    .. automethod:: right_click
    .. automethod:: repair
    .. automethod:: build
diff --git a/generate_pydocs.py b/generate_pydocs.py
index 1c2b01194..ab6bfca8a 100644
--- a/generate_pydocs.py
+++ b/generate_pydocs.py
@@ -12,8 +12,8 @@ import sys
 import inspect
 import re
 
-sys.path.append('build/python-api-src')
-sys.path.append('build/python-api-src/Release')
+sys.path.append('build/python-api-src') #Unix
+sys.path.append('build/python-api-src/Release') #Windows
 import library
 
 def update_pyi_with_docstrings(pyi_path):
@@ -76,6 +76,6 @@ def update_pyi_with_docstrings(pyi_path):
 
 
 # Path to the generated .pyi file
-#pyi_file_path = 'build/python-api-src/library.pyi'
-pyi_file_path = 'build/python-api-src/Release/library.pyi'
+pyi_file_path = 'build/python-api-src/library.pyi' #Unix
+#pyi_file_path = 'build/python-api-src/Release/library.pyi' #Windows
 update_pyi_with_docstrings(pyi_file_path)
diff --git a/python-api-src/lib_base_location.cpp b/python-api-src/lib_base_location.cpp
index 3fdda68bb..59b712633 100644
--- a/python-api-src/lib_base_location.cpp
+++ b/python-api-src/lib_base_location.cpp
@@ -12,15 +12,21 @@ void define_base_location(py::module & m)
         .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("get_ground_distance", py::overload_cast<const CCTilePosition &>(&BaseLocation::getGroundDistance, py::const_), "Returns the ground distance between the provided position and the base location. Note that this uses a BFS approach and may overshoot a bit.")
         .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");
+        .def("is_player_start_location", &BaseLocation::isPlayerStartLocation, "player_constant"_a, "If the baselocation is the start location of the provided player. See :ref:`playerconstants` for more information")
+        .def("contains_position", &BaseLocation::containsPosition, "If the baselocation contains the provided :class:`library.Point2D` position")
+        .doc() = R"(
+        Represents a base location on the map. A base location is a location on the map where a player can build a base. It contains information about the resources available at the location, the position of the location, and other information.
+        )";
 
     py::class_<BaseLocationManager>(m, "BaseLocationManager")
         .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_occupied_base_locations", &BaseLocationManager::getOccupiedBaseLocations, py::return_value_policy::reference, "player_constant"_a, "Returns a list of all :class:`library.BaseLocation` that are occupied by the provided :ref:`playerconstants`.")
         .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.");
+        .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.")
+        .doc() = R"(
+        As the name implies this class helps you manage the base locations on the map. 
+        )";
 }
\ 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 56da5e8ff..0f4155272 100644
--- a/python-api-src/lib_building_placer.cpp
+++ b/python-api-src/lib_building_placer.cpp
@@ -5,10 +5,16 @@ 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, "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("can_build_here", &BuildingPlacer::canBuildHere, "x"_a, "y"_a, "unit_type"_a, "Returns if the provided unit_type it possible to be built at the location. Note: This function uses the width and height of the unit_type 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 base location")
+        .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 unit_type 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);
+        .def("free_tiles", &BuildingPlacer::freeTiles,"Free the tile (x, y) from reservation", "x"_a, "y"_a, "width"_a, "height"_a)
+        .doc() = R"(
+        This class is useful for placing all buildings, except refineries and town halls (Command Centers, Hacheries and Nexus).
+
+        If you want to place a town hall, take a look at attribute `depot_location` of :class:`library.BaseLocation`.
+        If you want to place a refinery, take a look at attribute `geysers` of :class:`library.BaseLocation` and the method build_target of :class:`library.Unit`.
+        )";
 }
\ No newline at end of file
diff --git a/python-api-src/lib_color.cpp b/python-api-src/lib_color.cpp
index 7117b5532..95ab23f1f 100644
--- a/python-api-src/lib_color.cpp
+++ b/python-api-src/lib_color.cpp
@@ -20,4 +20,7 @@ void define_color(py::module & m)
     color.attr("PURPLE") = sc2::Colors::Purple;
     color.attr("BLACK") = sc2::Colors::Black;
     color.attr("GRAY") = sc2::Colors::Gray;
+    color.doc() = R"(
+        Represents a color in RGB format. The color is represented by three integers, each ranging from 0 to 255. The color can be created by providing the red, green and blue values. The class also contains some predefined colors.
+    )";
 }
\ No newline at end of file
diff --git a/python-api-src/lib_map_tools.cpp b/python-api-src/lib_map_tools.cpp
index 2f8e34439..cc3b2be48 100644
--- a/python-api-src/lib_map_tools.cpp
+++ b/python-api-src/lib_map_tools.cpp
@@ -10,7 +10,11 @@ void define_map_tools(py::module & m)
         .def("get_distance", py::overload_cast<const CCPosition &>(&DistanceMap::getDistance, py::const_), "position"_a)
         .def("get_sorted_tiles", &DistanceMap::getSortedTiles)
         .def("get_start_tile", &DistanceMap::getStartTile)
-        .def("draw", &DistanceMap::draw, "bot"_a);
+        .def("draw", &DistanceMap::draw, "bot"_a)
+        .doc() = R"(
+            This class is used to calculate the distance between two points on the map. 
+            The distance is calculated using a BFS algorithm. Keep in mind that it can overshoot the distance a bit. 
+        )";
 
     const CCColor white{ 255, 255, 255 };
     py::class_<MapTools>(m, "MapTools")
@@ -46,5 +50,23 @@ void define_map_tools(py::module & m)
         .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, "Returns the tile that the most time has passed since it was visible");
+        .def("get_least_recently_seen_tile", &MapTools::getLeastRecentlySeenTile, "Returns the tile that the most time has passed since it was visible")
+        .doc() = R"(
+            This class contains two types of methods:
+
+            * Methods for drawing information to the screen
+            * Methods for extracting information about the map
+
+            First, let us look at the method concerning drawing information to the 
+            screen. Methods with the suffix ``_screen`` takes percentages of the 
+            screens height and width, i.e. values between 0 and 1. Methods without 
+            this suffix uses the same coordinate system as the game, i.e. world 
+            coordinates.
+
+            The top three methods below takes in a Point2D, but it's possible to
+            send in x and y as floats instead of Point2D.
+
+            There is also methods which are useful for extracting information about the 
+            game map.
+        )";
 }
\ No newline at end of file
diff --git a/python-api-src/lib_replay_unit.cpp b/python-api-src/lib_replay_unit.cpp
index 6e898aaa6..7364163e5 100644
--- a/python-api-src/lib_replay_unit.cpp
+++ b/python-api-src/lib_replay_unit.cpp
@@ -5,38 +5,43 @@ namespace py = pybind11;
 void define_replay_unit(py::module & m)
 {
 	py::class_<ReplayUnit>(m, "ReplayUnit")
-		.def_property_readonly("id", &ReplayUnit::getID)
-		.def_property_readonly("unit_type", &ReplayUnit::getType, "The :class :`library.UnitType` of the unit")
+		.def_property_readonly("id", &ReplayUnit::getID, "The ID of the unit")
+		.def_property_readonly("unit_type", &ReplayUnit::getType, "The :class:`library.UnitType` of the unit")
 		.def_property_readonly("position", &ReplayUnit::getPosition, "The :class:`library.Point2D` of the unit")
 		.def_property_readonly("tile_position", &ReplayUnit::getTilePosition, "The :class:`library.Point2DI` of the unit")
-		.def_property_readonly("hit_points", &ReplayUnit::getHitPoints)
-		.def_property_readonly("shields", &ReplayUnit::getShields)
-		.def_property_readonly("energy", &ReplayUnit::getEnergy)
-		.def_property_readonly("player", &ReplayUnit::getPlayer)
-		.def_property_readonly("build_percentage", &ReplayUnit::getBuildPercentage)
-		.def_property_readonly("weapon_cooldown", &ReplayUnit::getWeaponCooldown)
-		.def_property_readonly("is_completed", &ReplayUnit::isCompleted)
-		.def_property_readonly("is_being_constructed", &ReplayUnit::isBeingConstructed)
-		.def_property_readonly("is_cloaked", &ReplayUnit::isCloaked)
-		.def_property_readonly("is_flying", &ReplayUnit::isFlying)
-		.def_property_readonly("buffs", &ReplayUnit::buffs)
-		.def_property_readonly("is_alive", &ReplayUnit::isAlive)
-		.def_property_readonly("is_powered", &ReplayUnit::isPowered)
-		.def_property_readonly("is_idle", &ReplayUnit::isIdle)
-		.def_property_readonly("is_burrowed", &ReplayUnit::isBurrowed)
-		.def_property_readonly("is_valid", &ReplayUnit::isValid)
-		.def_property_readonly("is_training", &ReplayUnit::isTraining)
-		.def_property_readonly("is_blip", &ReplayUnit::isBlip)
-		.def_property_readonly("target", &ReplayUnit::getTarget)
-		.def_property_readonly("has_target", &ReplayUnit::hasTarget)
-		.def_property_readonly("max_hit_points", &ReplayUnit::getMaxHitPoints)
-		.def_property_readonly("progress", &ReplayUnit::getProgress)
+		.def_property_readonly("hit_points", &ReplayUnit::getHitPoints, "The hit points of the unit")
+		.def_property_readonly("shields", &ReplayUnit::getShields, "The shields of the unit")
+		.def_property_readonly("energy", &ReplayUnit::getEnergy, "The energy of the unit")
+		.def_property_readonly("player", &ReplayUnit::getPlayer, "Returns the constant corresponding to player which this unit belongs to. See :ref:`playerconstants` for more information.")
+		.def_property_readonly("build_percentage", &ReplayUnit::getBuildPercentage, "The build percentage of the unit")
+		.def_property_readonly("weapon_cooldown", &ReplayUnit::getWeaponCooldown, "The weapon cooldown of the unit")
+		.def_property_readonly("is_completed", &ReplayUnit::isCompleted, "Whether the unit is completed, returns build_progress >= 1")
+		.def_property_readonly("is_being_constructed", &ReplayUnit::isBeingConstructed, "Whether the unit is being constructed, returns build_progress > 0")
+		.def_property_readonly("is_cloaked", &ReplayUnit::isCloaked, "Whether the unit is cloaked")
+		.def_property_readonly("is_flying", &ReplayUnit::isFlying, "Whether the unit is flying")
+		.def_property_readonly("buffs", &ReplayUnit::buffs, "Returns a list of BuffIDs representing the buffs on the unit")
+		.def_property_readonly("is_alive", &ReplayUnit::isAlive, "Whether the unit is alive")
+		.def_property_readonly("is_powered", &ReplayUnit::isPowered, "Whether the unit is powered")
+		.def_property_readonly("is_idle", &ReplayUnit::isIdle, "Whether the unit is idle")
+		.def_property_readonly("is_burrowed", &ReplayUnit::isBurrowed, "Whether the unit is burrowed")
+		.def_property_readonly("is_valid", &ReplayUnit::isValid, "Whether the unit is valid")
+		.def_property_readonly("is_training", &ReplayUnit::isTraining, "Whether the unit is training")
+		.def_property_readonly("is_blip", &ReplayUnit::isBlip, "Whether the unit is a blip ie a ping on the map")
+		.def_property_readonly("target", &ReplayUnit::getTarget, "The target of the unit")
+		.def_property_readonly("has_target", &ReplayUnit::hasTarget, "Whether the unit has a target")
+		.def_property_readonly("max_hit_points", &ReplayUnit::getMaxHitPoints, "The maximum hit points of the unit")
+		.def_property_readonly("progress", &ReplayUnit::getProgress, "Returns the progress of currently used ability (-1 if not using ability)")
 		.def_property_readonly("current_ability_id", &ReplayUnit::getCurrentAbilityID, "The AbilityID of currently used ability")
-		.def_property_readonly("facing", &ReplayUnit::getFacing)
-		.def_property_readonly("radius", &ReplayUnit::getRadius)
-		.def_property_readonly("is_carrying_minerals", &ReplayUnit::isCarryingMinerals)
+		.def_property_readonly("facing", &ReplayUnit::getFacing, "Returns the direction the unit is facing")
+		.def_property_readonly("radius", &ReplayUnit::getRadius, "The radius of the unit")
+		.def_property_readonly("is_carrying_minerals", &ReplayUnit::isCarryingMinerals, "Whether the unit is carrying minerals")
 		.def("__hash__", [](const ReplayUnit & unit) { return std::hash<const sc2::Unit *>{}(unit.getUnitPtr()); })
 		.def(py::self == py::self)
 		.def("__repr__", [](const ReplayUnit & unit) { return "<Unit of type: '" + unit.getType().getName() + "'>"; })
-		;
+		.doc() = R"(
+		The ReplayUnit class is used to represent a unit in a replay of a game. 
+		A ReplayUnit is a :class:`library.Unit` white some limitations.
+   		It provides various properties and methods to access information about the unit, such as its ID, type, position, hit points, energy, and more.
+		It is possible to use ReplayUnit as keys in a dictionary, which might be helpful for bookkeeping.
+		)";
 }
diff --git a/python-api-src/lib_sc2_typeenums.cpp b/python-api-src/lib_sc2_typeenums.cpp
index c18084a17..eeb8338dd 100644
--- a/python-api-src/lib_sc2_typeenums.cpp
+++ b/python-api-src/lib_sc2_typeenums.cpp
@@ -6,7 +6,7 @@ namespace py = pybind11;
 
 void define_typeenums(py::module & m)
 {
-    py::enum_<sc2::UNIT_TYPEID>(m, "UNIT_TYPEID")
+    py::enum_<sc2::UNIT_TYPEID>(m, "UNIT_TYPEID", "Acts as a full list of all unit types in the game. Depending on which game version you're using some of these might not be available.")
 		.value("ABANDONEDBUILDING", sc2::UNIT_TYPEID::ABANDONEDBUILDING)
 		.value("ABERRATIONACGLUESCREENDUMMY", sc2::UNIT_TYPEID::ABERRATIONACGLUESCREENDUMMY)
 		.value("ACCELERATIONZONEFLYINGLARGE", sc2::UNIT_TYPEID::ACCELERATIONZONEFLYINGLARGE)
@@ -2000,7 +2000,7 @@ void define_typeenums(py::module & m)
 		.value("_8SLOTBAG", sc2::UNIT_TYPEID::_8SLOTBAG)
         .def("__eq__", [](const sc2::UNIT_TYPEID &value, sc2::UnitTypeID &value2) { return value == value2; });
 
-    py::enum_<sc2::ABILITY_ID>(m, "ABILITY_ID")
+    py::enum_<sc2::ABILITY_ID>(m, "ABILITY_ID", "Acts as a full list of all abilities in the game. Dependeing on which game version you use, some of these might not work.")
         .value("INVALID", sc2::ABILITY_ID::INVALID)
         .value("ADVANCEDCONSTRUCTION_CANCEL", sc2::ABILITY_ID::ADVANCEDCONSTRUCTION_CANCEL)
         .value("AGGRESSIVEMUTATION", sc2::ABILITY_ID::AGGRESSIVEMUTATION)
@@ -3205,7 +3205,7 @@ void define_typeenums(py::module & m)
 		.value("_330MMBARRAGECANNONS", sc2::ABILITY_ID::_330MMBARRAGECANNONS)
 		.value("_330MMBARRAGECANNONS_CANCEL", sc2::ABILITY_ID::_330MMBARRAGECANNONS_CANCEL);
 
-      py::enum_<sc2::UPGRADE_ID>(m, "UPGRADE_ID")
+      py::enum_<sc2::UPGRADE_ID>(m, "UPGRADE_ID", "Acts as a full list of upgrades available in the game. Depending on which game version you use, some of these upgrades may not be available.")
         .value("ABDOMINALFORTITUDE", sc2::UPGRADE_ID::ABDOMINALFORTITUDE)
         .value("ADEPTKILLBOUNCE", sc2::UPGRADE_ID::ADEPTKILLBOUNCE)
         .value("ADEPTPIERCINGATTACK", sc2::UPGRADE_ID::ADEPTPIERCINGATTACK)
@@ -3508,7 +3508,7 @@ void define_typeenums(py::module & m)
 		.value("ZERGMISSILEWEAPONSLEVEL3", sc2::UPGRADE_ID::ZERGMISSILEWEAPONSLEVEL3)
 		.value("_330MMBARRAGECANNONS", sc2::UPGRADE_ID::_330MMBARRAGECANNONS);
 		
-    py::enum_<sc2::BUFF_ID>(m, "BUFF_ID")
+    py::enum_<sc2::BUFF_ID>(m, "BUFF_ID", "An enumeration of buffs that can affect units.")
 		.value("ACCELERATIONZONEFLYINGTEMPORALFIELD", sc2::BUFF_ID::ACCELERATIONZONEFLYINGTEMPORALFIELD)
 		.value("ACCELERATIONZONETEMPORALFIELD", sc2::BUFF_ID::ACCELERATIONZONETEMPORALFIELD)
 		.value("ADEPTDEATHCHECK", sc2::BUFF_ID::ADEPTDEATHCHECK)
@@ -3804,7 +3804,7 @@ void define_typeenums(py::module & m)
 		.value("_250MMSTRIKECANNONS", sc2::BUFF_ID::_250MMSTRIKECANNONS)
 		.value("_330MMBARRAGECANNONS", sc2::BUFF_ID::_330MMBARRAGECANNONS);
 
-	py::enum_<sc2::EFFECT_ID>(m, "EFFECT_ID")
+	py::enum_<sc2::EFFECT_ID>(m, "EFFECT_ID", "An enumeration of all the effect ids in the game.")
 		.value("BLINDINGCLOUD", sc2::EFFECT_ID::BLINDINGCLOUD)
 		.value("CORROSIVEBILE", sc2::EFFECT_ID::CORROSIVEBILE)
 		.value("GUARDIANSHIELD", sc2::EFFECT_ID::GUARDIANSHIELD)
diff --git a/python-api-src/lib_tech_tree.cpp b/python-api-src/lib_tech_tree.cpp
index 2f388455f..096629189 100644
--- a/python-api-src/lib_tech_tree.cpp
+++ b/python-api-src/lib_tech_tree.cpp
@@ -26,7 +26,14 @@ void define_tech_tree(py::module & m)
 
     py::class_<TechTree>(m, "TechTree")
         .def("get_data", py::overload_cast<const UnitType &>(&TechTree::getData, py::const_))
-        .def("get_data", py::overload_cast<const CCUpgrade &>(&TechTree::getData, py::const_))
-		.def("suppress_warnings", &TechTree::setSuppressWarnings, "Suppress type and uppgrade warnings" ,"b"_a)
-		;
+        .def("get_data", py::overload_cast<const CCUpgrade &>(&TechTree::getData, py::const_), "Argument is either an instance of the class :class:`library.UnitType` or an instance of the class :class:`library.CCUpgrade`, depending on what information is wanted.")
+		.def("suppress_warnings", &TechTree::setSuppressWarnings, "Suppress type and upgrade warnings" ,"b"_a)
+		.doc() = R"(
+            This class contains all information about units and what is required to
+            build a certain unit and what builds it. It only has one method, which is
+            used to look-up unit types properties.
+
+            Instead of using TechTree, it's possible to use the functions in UnitType for
+            structure, etc. In IDABot there is functions for getting data about upgrades.	
+        )";
 }
diff --git a/python-api-src/lib_unit.cpp b/python-api-src/lib_unit.cpp
index e6095a856..b2b23a5dd 100644
--- a/python-api-src/lib_unit.cpp
+++ b/python-api-src/lib_unit.cpp
@@ -12,8 +12,8 @@ void define_unit(py::module & m)
         .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("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)")
@@ -39,7 +39,7 @@ void define_unit(py::module & m)
 		.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("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.")
 
@@ -51,9 +51,9 @@ void define_unit(py::module & m)
         .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("ability", py::overload_cast<sc2::AbilityID, const Unit &>(&Unit::ability, py::const_), "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)")
         .def("move", py::overload_cast<const CCPosition &>(&Unit::move, py::const_))
-        .def("move", py::overload_cast<const CCTilePosition &>(&Unit::move, py::const_))
+        .def("move", py::overload_cast<const CCTilePosition &>(&Unit::move, py::const_), "Move the unit to the given point, the point being an instance of either :class:`library.Point2D` or :class:`library.Point2DI`.")
         .def("right_click", &Unit::rightClick, "Same as right-clicking in the game, for example making workers mine minerals")
         .def("repair", &Unit::repair, "Right-clicks 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)
@@ -64,5 +64,21 @@ void define_unit(py::module & m)
         .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() + "'>"; });
+        .def("__repr__", [](const Unit & unit) { return "<Unit of type: '" + unit.getType().getName() + "'>"; })
+        .doc() = R"(
+            An instance of the class Unit represents one unit in the game. The units are 
+            not limited to moveable units, but every entity which is not part of the 
+            background is a unit. For example, the minerals and geysers are units as 
+            well as all buildings.
+
+            For all possible types of units see the enum :class:`library.UNIT_TYPEID`. 
+            Some types of objects are almost the same, for example there are many types 
+            of mineral deposits, but all of them are mineable. This is one of the 
+            motivations behind the :class:`library.UnitType` which aims to to make the 
+            list of types more manageable. The UnitType can be accessed by the 
+            :any:`Unit.unit_type` property.
+
+            It is possible to use Unit as keys in a dictionary, which might be helpful
+            for bookkeeping.
+        )" ;
 }
diff --git a/python-api-src/lib_unittype.cpp b/python-api-src/lib_unittype.cpp
index c67f74fab..c23529f32 100644
--- a/python-api-src/lib_unittype.cpp
+++ b/python-api-src/lib_unittype.cpp
@@ -17,10 +17,10 @@ void define_unittype(py::module & m)
         .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_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, "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_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")
@@ -50,7 +50,10 @@ void define_unittype(py::module & m)
 		.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() + "'>"; });
+        .def("__repr__", [](const UnitType & unit_type) { return "<UnitType: '" + unit_type.getName() + "'>"; })
+        .doc() = R"(
+            Wrapper for :class:`library.UNIT_TYPEID`. Represents a type of unit in the game.
+        )";
 
         // Not implemented in CommandCenter
         //.def("whatBuilds", &UnitType::whatBuilds);
diff --git a/python-api-src/lib_util.cpp b/python-api-src/lib_util.cpp
index 2c6d6be89..22add6c46 100644
--- a/python-api-src/lib_util.cpp
+++ b/python-api-src/lib_util.cpp
@@ -22,4 +22,7 @@ void define_util(py::module & mod)
     m.def("dist", py::overload_cast<const Unit &, const Unit &>(&Util::Dist));
     m.def("dist", py::overload_cast<const Unit &, const CCPosition &>(&Util::Dist));
     m.def("dist", py::overload_cast<const CCPosition &, const CCPosition &>(&Util::Dist));
+    m.doc() = R"(
+        The util module provides utility functions for the library. 
+    )";
 }
\ No newline at end of file
diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp
index 2a9c5bfa1..22cff691f 100644
--- a/python-api-src/library.cpp
+++ b/python-api-src/library.cpp
@@ -54,7 +54,7 @@ PYBIND11_MODULE(library, m)
 
     py::enum_<sc2::Race>(m, "Race", "The Race enum in the provided code represents the different races in the Starcraft II game. It is used to define the race of a player or a unit. \
 		In Starcraft II, each race has its own unique units, buildings, and abilities. The Race enum allows you to specify the race of a player or a unit, which can be useful for various game-related operations and strategies. \
-		For example, if you want to set the race of a player to Zerg, you can use the Race::Zerg value. Similarly, if you want to check the race of a unit, you can compare its race with the enum values.")
+		For example, if you want to set the race of a player to Terran, you can use the Race.Terran value. Similarly, if you want to check the race of a unit, you can compare its race with the enum values.")
         .value("Terran", sc2::Race::Terran)
         .value("Zerg", sc2::Race::Zerg)
         .value("Protoss", sc2::Race::Protoss)
@@ -124,8 +124,12 @@ PYBIND11_MODULE(library, m)
     // IDABot is a specialization of Agent
 	py::class_<IDABot, PyIDABot, sc2::Agent>(m, "IDABot")
 		.def(py::init())
-		.def("on_game_start", &IDABot::OnGameStart)
-		.def("on_step", &IDABot::OnStep)
+		.def("on_game_start", &IDABot::OnGameStart, R"(The on_game_start function is a method defined in the IDABot class. It is called when a game starts in Starcraft II. 
+		This function is responsible for initializing the bot and performing any necessary setup before the game begins. 
+		This can include setting up initial game state, gathering information about the map and opponents, and making any initial decisions or strategies.)")
+		.def("on_step", &IDABot::OnStep, R"(The on_step function in the IDABot class is a method that is called every game step (or frame) during a Starcraft II match. 
+		This function is crucial for implementing the bot's logic that needs to be executed continuously throughout the game. 
+		It's where the bot evaluates the current game state, makes decisions, and issues commands to units.)")
 		.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") 
@@ -167,9 +171,7 @@ PYBIND11_MODULE(library, m)
 		.def_property_readonly("max_supply", &IDABot::GetMaxSupply, "How much supply we can currently use")
 		.def_property_readonly("gas", &IDABot::GetGas, "How much gas we currently have")
 		.def_property_readonly("current_frame", &IDABot::GetCurrentFrame, "Which frame we are currently on")
-		.doc() = R"(This is a striped down basic version of an bot. It contains all available managers and basic methods.
-
-					)";
+		.doc() = R"(This is a striped down basic version of an bot. It contains all available managers and basic methods.)";
 
 
 
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 000000000..da87b003f
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,25 @@
+alabaster==0.7.16
+Babel==2.15.0
+certifi==2024.6.2
+charset-normalizer==3.3.2
+docutils==0.21.2
+idna==3.7
+imagesize==1.4.1
+Jinja2==3.1.4
+MarkupSafe==2.1.5
+mypy==1.10.0
+mypy-extensions==1.0.0
+packaging==24.1
+Pygments==2.18.0
+requests==2.32.3
+snowballstemmer==2.2.0
+Sphinx==7.3.7
+sphinx_design==0.6.0
+sphinxcontrib-applehelp==1.0.8
+sphinxcontrib-devhelp==1.0.6
+sphinxcontrib-htmlhelp==2.0.5
+sphinxcontrib-jsmath==1.0.1
+sphinxcontrib-qthelp==1.0.7
+sphinxcontrib-serializinghtml==1.1.10
+typing_extensions==4.12.2
+urllib3==2.2.2
-- 
GitLab