diff --git a/.gitignore b/.gitignore index 0023a727e767c45c3521dc3f0e2ed635bb81f1ff..f5ef6f3289fdb19616e1cb1bc2c5eb8ae7619341 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ build/ .idea -venv +.venv .vs +.vscode +__pycache__ +.DS_Store \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 21e21223478a4d4c9ba32e2300dc847e24e8d86e..8f4ec94ac3372916f7e93546d80a3f43623eea28 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,16 +1,35 @@ -variables: - GIT_SUBMODULE_STRATEGY: recursive +image: gitlab.liu.se:5000/starcraft-ai-course/pycommandcenter -pages: - image: gitlab.liu.se:5000/starcraft-ai-course/pycommandcenter - stage: deploy +stages: + - compile + - deploy + +compile: + variables: + GIT_SUBMODULE_STRATEGY: recursive + stage: compile script: - mkdir build - cd build - cmake .. - - make library - - cd ../docs - - python3 library_import_check.py + - make commandcenter + artifacts: + paths: + - docs + - build + - scripts/generate_pydocs.py + expire_in: 10 minutes + only: + - master + +pages: + variables: + GIT_STRATEGY: none + GIT_CHECKOUT: false + stage: deploy + script: + - cd docs + - python3 -c "import sys, os, conf, commandcenter" - make html - cd .. - mkdir public @@ -20,3 +39,20 @@ pages: - public only: - master + +pack-linux: + variables: + GIT_STRATEGY: none + GIT_CHECKOUT: false + stage: deploy + script: + - cd build/python-api-src + - stubgen -m commandcenter -o . + - cd ../.. + - python3 scripts/generate_pydocs.py + artifacts: + paths: + - build/python-api-src/commandcenter.cpython-312-x86_64-linux-gnu.so + - build/python-api-src/commandcenter.pyi + only: + - master diff --git a/ExtendAPI.md b/CONTRIBUTING.md similarity index 97% rename from ExtendAPI.md rename to CONTRIBUTING.md index 005e30f838b029c9b077a691b68c17f562cb55a9..06dc73d970ea197569e632ade3d44e05ea39c8ad 100644 --- a/ExtendAPI.md +++ b/CONTRIBUTING.md @@ -23,6 +23,6 @@ We can access m_unit in the unit file and with sc2::Function() we can access any Common problems: 1. The return in python is a memory address: - Make sure that it returns a correct type. + Make sure that it returns a correct type. 2. The compiler complains about files I have not even touched: Make sure that the startUp is library and you have release x64. If you just added a new function in pybind, check it. diff --git a/LICENSE b/LICENSE index f56c64d4898209f29cb92e2fad90cdf6865e278b..8af56610cae852cb4c4e94b6e8709c7243e3478d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License - -Copyright (c) 2018 David Bergström +Copyright (c) 2024 Daniel de Leng +Copyright (c) 2018 Jonas Kvarnström, David Bergström Copyright (c) 2017 David Churchill Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/README.md b/README.md index 9452f287648297395c43a22dd6abef31aa0a200c..deb3128042f24822f6f9e46700480db89a805a2a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Key differences: ``` python import os -from library import * +from commandcenter import * class MyAgent(IDABot): @@ -95,15 +95,28 @@ 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: +Navigate to where your commandcenter.pyd/so is located then run: ```terminal -stubgen -m library -o . +stubgen -m commandcenter -o . ``` +NOTE: stubgen might not work on windows unless you have an active python venv. + After creating the .pyi file run the generate_pydocs.py file according to the instructions in that file. # How to use the library with PyCharm -See [separate page](pycharm.md). +Start by downloading the library. Click the latest tag in the [PyCommandCenter repository](https://gitlab.liu.se/starcraft-ai-course/pycommandcenter/-/tags) and find a `.pyd` link at the bottom of the tag page. + +Place the library in your repository. + +Add the library to the Python path in Python by: + +1. File->Settings->Project: (project name)->Project Interpreter. +2. Select the cog in the upper right corner and select "Show All". +3. In the new window that opens, select the icon which shows a few folders connected with lines. +4. In the new window, first press the plus icon, and then select the path of your repository (the path to where you placed the library). +5. Restart PyCharm with "File->Invalidate Caches/Restart->Invalidate and Restart". + # Building the documentation @@ -127,7 +140,7 @@ See [separate page](pycharm.md). # Credits -PyCommandCenter is written and maintained for Linköping University through various contributors over the years. In alphabetical ordering, these include: Sofia Abaied, Dawid Lukasz Abucewicz, Anton Andell, Erik Ahlroth, David Bergström, Edvin Bergström, Emil Brynielsson, Stefan Brynielsson, Ludvig Fors, Hannes Jämtner, Jonas Kvarnström, Daniel de Leng, Fredrik Präntare, Gabriel Tofvesson, David Warnquist, Jonathan Öhrling. Feedback was provided by the teachers and students of TDDD63, TDDE25, and TDDD92. +PyCommandCenter is written and maintained for Linköping University through various contributors over the years. In alphabetical ordering, these include: Sofia Abaied, Dawid Lukasz Abucewicz, Anton Andell, Erik Ahlroth, David Bergström, Edvin Bergström, Jonas Bonnaudet, Emil Brynielsson, Stefan Brynielsson, Ludvig Fors, Hannes Jämtner, Jonas Kvarnström, Daniel de Leng, Fredrik Präntare, Gabriel Tofvesson, David Warnquist, Jonathan Öhrling. Feedback was provided by the teachers and students of TDDD63, TDDE25, and TDDD92. CommandCenter is written by [David Churchill](http://www.cs.mun.ca/~dchurchill/), Assistant Professor of [Computer Science](https://www.cs.mun.ca/) at Memorial University, and organizer of the [AIIDE StarCraft AI Competition](http://www.cs.mun.ca/~dchurchill/starcraftaicomp/). diff --git a/Dockerfile b/docker/Dockerfile similarity index 75% rename from Dockerfile rename to docker/Dockerfile index dd5cba9b752d26bb141aa2e48ef23f7bdb17b9fc..fdc744993d78e470b34a215bb130added73aeeab 100644 --- a/Dockerfile +++ b/docker/Dockerfile @@ -4,6 +4,7 @@ FROM ubuntu:24.04 LABEL org.opencontainers.image.authors="daniel.de.leng@liu.se" RUN apt update && apt install -y build-essential cmake python3-full python3-pybind11 python3-pip python3-sphinx python3-sphinx-design +RUN pip3 install mypy==1.10.0 --break-system-packages # Workaround for python3-mypy having outdated version <1.10.0 ENV HOME=/root WORKDIR /root diff --git a/docs/conf.py b/docs/conf.py index 1f9ada98a57d0fec2e22a7fb476c8a37e2f13e5c..ccb6d3a28e6601340e96a0b2f572540bb333dc87 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,11 +22,11 @@ sys.path.append(os.getcwd()) # -- Project information ----------------------------------------------------- project = 'PyCommandCenter' -copyright = '2018, David Bergström' -author = 'David Bergström' +copyright = '2024 Reasoning and Learning Lab, Linköping University' +author = 'Sofia Abaied, Dawid Lukasz Abucewicz, Anton Andell, Erik Ahlroth, David Bergström, Edvin Bergström, Emil Brynielsson, Stefan Brynielsson, Ludvig Fors, Hannes Jämtner, Jonas Kvarnström, Daniel de Leng, Fredrik Präntare, Gabriel Tofvesson, David Warnquist, Jonathan Öhrling' # The short X.Y version -version = '' +version = '2.0' # The full version, including alpha/beta/rc tags release = '' diff --git a/docs/constants.rst b/docs/constants.rst index 9048549851f509ae456607b509151ae7952d5f0c..2a109b4db428962f01995808c322365cd74c6cd7 100644 --- a/docs/constants.rst +++ b/docs/constants.rst @@ -10,10 +10,10 @@ Player constants The following constants are used when referring to a player: -.. autoclass:: library.PLAYER_SELF -.. autoclass:: library.PLAYER_ENEMY -.. autoclass:: library.PLAYER_NEUTRAL -.. autoclass:: library.PLAYER_ALLY +.. autoclass:: commandcenter.PLAYER_SELF +.. autoclass:: commandcenter.PLAYER_ENEMY +.. autoclass:: commandcenter.PLAYER_NEUTRAL +.. autoclass:: commandcenter.PLAYER_ALLY These are internally represented as integers, but these constants should be used instead to avoid confusion. @@ -21,21 +21,21 @@ used instead to avoid confusion. Difficulty ---------- -.. autoclass:: library.Difficulty +.. autoclass:: commandcenter.Difficulty :members: :undoc-members: AIBuild ------- -.. autoclass:: library.AIBuild +.. autoclass:: commandcenter.AIBuild :members: :undoc-members: Race ---- -.. autoclass:: library.Race +.. autoclass:: commandcenter.Race :members: :undoc-members: diff --git a/docs/coordinates.rst b/docs/coordinates.rst index 9aca00ceb9dc90bd7707e249ba8af178677c80cd..6e46c1546259b6c901df82c728b5421029889f06 100644 --- a/docs/coordinates.rst +++ b/docs/coordinates.rst @@ -2,8 +2,8 @@ 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`. Conversion between the two types is possible by +floats, these are called :class:`commandcenter.Point2DI` and +:class:`commandcenter.Point2D`. Conversion 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 cast into integer values. @@ -16,7 +16,7 @@ Point2DI -------- -.. class:: library.Point2DI +.. class:: commandcenter.Point2DI These points are used for defining the location of tiles, which are used when placing buildings in Starcraft. @@ -28,7 +28,7 @@ Point2DI Point2D ------- -.. class:: library.Point2D +.. class:: commandcenter.Point2D Instances of this class is used to represent the location of Units and support many operations for general purpose calculation. @@ -38,7 +38,7 @@ Example .. code:: python - from library import Point2D, Point2DI + from commandcenter import Point2D, Point2DI # Creating two points @@ -73,7 +73,7 @@ below: .. code:: python from math import sqrt - from library import Point2D + from commandcenter import Point2D p1 = Point2D(3, 4) p2 = Point2D(1, 2) diff --git a/docs/deploy-ida.sh b/docs/deploy-ida.sh deleted file mode 100644 index c9bc4d2aec300a98d2d11297df05434b1cf8356c..0000000000000000000000000000000000000000 --- a/docs/deploy-ida.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -scp -r _build/html/. davbe125@remote-und.ida.liu.se:/wwwpub/davbe125/sc2 diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index c68a47300c4efa3530aec4bfe6a2f6f9428f5800..4114d7a8a700da6125cdc9a4fe4ab13b3ae202e4 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -17,7 +17,7 @@ and more. import os from typing import Optional - from library import * + from commandcenter import * class MyAgent(IDABot): @@ -56,7 +56,7 @@ Now, let us break it down piece by piece to understand it. .. code-block:: python - from library import * + from commandcenter import * This imports everything from the library into your namespace. @@ -74,7 +74,7 @@ Next, we need to define our bot. def on_step(self): IDABot.on_step(self) -A bot which plays Starcraft is defined as a subclass to the class :class:`library.IDABot` which +A bot which plays Starcraft is defined as a subclass to the class :class:`commandcenter.IDABot` which contains some help code in order to make implementing your bit more straightforward. If we look closer at our newly created bot, it has three methods which are all diff --git a/docs/helpers.rst b/docs/helpers.rst index deebc634528d2dffd148ef45e2efc4ef584df2b4..bc0154c181096a73952bc3173831a4773ddc13d8 100644 --- a/docs/helpers.rst +++ b/docs/helpers.rst @@ -2,7 +2,7 @@ Helpers ======= There are several classes related to processing information about the game -state and the input from Starcraft. All these classes are taken more or less +state and the input from StarCraft II. All these classes are taken more or less directly from the original `CommandCenter`_, but we have left all decision-making to the user of the API. @@ -10,17 +10,17 @@ decision-making to the user of the API. Here is a full list of all managers: -* :class:`library.BaseLocationManager` -* :class:`library.TechTree` -* :class:`library.MapTools` -* :class:`library.BuildingPlacer` +* :class:`commandcenter.BaseLocationManager` +* :class:`commandcenter.TechTree` +* :class:`commandcenter.MapTools` +* :class:`commandcenter.BuildingPlacer` The rest of this page contains a brief description of each manager. BaseLocationManager ------------------- -.. class:: library.BaseLocationManager +.. class:: commandcenter.BaseLocationManager .. autoattribute:: base_locations @@ -35,7 +35,7 @@ BaseLocationManager BaseLocation ~~~~~~~~~~~~ -.. class:: library.BaseLocation +.. class:: commandcenter.BaseLocation Closely related to BaseLocationManager. This is the datastructure used by the BaseLocationManager to keep track of all base locations and related @@ -61,16 +61,16 @@ BaseLocation TechTree -------- -.. autoclass:: library.TechTree +.. autoclass:: commandcenter.TechTree This class has some invalid information by default, this can be corrected by placing the file `techtree.json` in the working directory. The `techtree.json` files are available here_, select the lastest version. - A techtree for SC2 version >=4.10 is now available (not fully tested yet), + A techtree for StarCraft II version >=4.10 is now available (not fully tested yet), this can be found under the folder data in this link_. A recent file is included in the `template repository`_. - .. automethod:: get_data(argument) -> library.TypeData + .. automethod:: get_data(argument) -> commandcenter.TypeData .. _link: https://github.com/BurnySc2/sc2-techtree .. _here: https://github.com/noorus/sc2-gamedata @@ -79,7 +79,7 @@ TechTree TypeData ~~~~~~~~ -.. autoclass:: library.TypeData +.. autoclass:: commandcenter.TypeData :members: :undoc-members: @@ -89,7 +89,7 @@ TypeData MapTools -------- -.. autoclass:: library.MapTools +.. autoclass:: commandcenter.MapTools :members: :undoc-members: @@ -97,7 +97,7 @@ MapTools Color ~~~~~ -.. autoclass:: library.Color +.. autoclass:: commandcenter.Color :members: :undoc-members: @@ -106,16 +106,16 @@ Color DistanceMap ~~~~~~~~~~~ -.. autoclass:: library.DistanceMap +.. autoclass:: commandcenter.DistanceMap :members: :undoc-members: BuildingPlacer -------------- -.. autoclass:: library.BuildingPlacer +.. autoclass:: commandcenter.BuildingPlacer :members: :undoc-members: -.. toctree:: \ No newline at end of file +.. toctree:: diff --git a/docs/idabot.rst b/docs/idabot.rst index c0e9e913916619abbcec7faad34b2e2ec83976a1..64d3b3c44d1169b41094e9c3a2cf24429df80e51 100644 --- a/docs/idabot.rst +++ b/docs/idabot.rst @@ -1,7 +1,7 @@ IDABot ====== -.. autoclass:: library.IDABot +.. autoclass:: commandcenter.IDABot See :ref:`this page <gettingstarted>` for how to properly inherit from IDABot. @@ -60,7 +60,7 @@ IDABot Debug ----- -.. class:: library.IDABot +.. class:: commandcenter.IDABot When developing AI-methods or when simply having a problem. The debug-methods are a great tool for speeding up the process. @@ -84,7 +84,7 @@ Debug .. method:: IDABot.debug_set_energy(self, Float, Unit) - Set the amount (Float) of energy to the :class:`library.Unit` + Set the amount (Float) of energy to the :class:`commandcenter.Unit` The maximum depends on the unit maxenergy. Note: This is not in percent of the unit energy. Same goes for life and shields. diff --git a/docs/idareplayobserver.rst b/docs/idareplayobserver.rst index d2379aefe762981f6bd342a26c7c96c4304a485e..d87c77588dab96f96bc4cdfd12312883f72d733d 100644 --- a/docs/idareplayobserver.rst +++ b/docs/idareplayobserver.rst @@ -1,7 +1,7 @@ IDAReplayObserver ================= -.. class:: library.IDAReplayObserver +.. class:: commandcenter.IDAReplayObserver This is a class for following a replay. @@ -35,14 +35,14 @@ IDAReplayObserver Methods: - .. method:: IDAReplayObserver.get_all_units(self) -> List[library.ReplayUnit] + .. method:: IDAReplayObserver.get_all_units(self) -> List[commandcenter.ReplayUnit] - Retrieves a list of all visible units + Retrieves a list of all visible units. - .. method:: IDAReplayObserver.get_player_race(self, player_id) -> library.Race + .. method:: IDAReplayObserver.get_player_race(self, player_id) -> commandcenter.Race - Returns the players race + Returns the player's race. -.. toctree:: \ No newline at end of file +.. toctree:: diff --git a/docs/index.rst b/docs/index.rst index da345dada9ea6d61e89b35860c335efcdd0aef95..e5131d699476c0125bdc861bc311c5d9212e7700 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -19,11 +19,11 @@ Table of contents ----------------- .. toctree:: - :maxdepth: 3 + :maxdepth: 2 gettingstarted - Library<_autosummary/library> - Coordinator<_autosummary/library.Coordinator> + PyCommandCenter<_autosummary/commandcenter> + Coordinator<_autosummary/commandcenter.Coordinator> helpers idabot unit @@ -38,6 +38,6 @@ Table of contents :toctree: _autosummary :hidden: - library - library.Coordinator + commandcenter + commandcenter.Coordinator diff --git a/docs/library_import_check.py b/docs/library_import_check.py index 0744294932734df8d9eef41dd216c5161b81c88a..0ff2cb4fc1d7371fd453f1210f4d9e3a3574d967 100644 --- a/docs/library_import_check.py +++ b/docs/library_import_check.py @@ -1,3 +1,3 @@ import sys,os import conf -import library \ No newline at end of file +import commandcenter \ No newline at end of file diff --git a/docs/replays.rst b/docs/replays.rst index af3307805042078bc4de4903642b827ee6a2e08e..6a8629360b0a00dbd2b6a5a803e7a0a6b0836f73 100644 --- a/docs/replays.rst +++ b/docs/replays.rst @@ -76,7 +76,7 @@ that no action can be preform just observations. .. code-block:: python - from library import * + from commandcenter import * class MyObserver(ReplayObserver): @@ -92,7 +92,7 @@ that no action can be preform just observations. def main(): - coordinator = Coordinator(r"D:/StarCraft II/Versions/Base69232/SC2_x64.exe") + coordinator = Coordinator(r"D:/StarCraft II/Versions/Base<version>/SC2_x64.exe") if coordinator.load_replay_list("D:/Replays/"): observer = MyObserver() coordinator.add_replay_observer(observer) @@ -105,4 +105,4 @@ that no action can be preform just observations. if __name__ == "__main__": main() -.. toctree:: \ No newline at end of file +.. toctree:: diff --git a/docs/replayunit.rst b/docs/replayunit.rst index 97418b8a252d2eb7df43b0ec43c2d9c74aae5902..8955314e459430e94ba391d305185d6cf544635e 100644 --- a/docs/replayunit.rst +++ b/docs/replayunit.rst @@ -1,7 +1,7 @@ ReplayUnit ========== -.. autoclass:: library.ReplayUnit +.. autoclass:: commandcenter.ReplayUnit Properties: diff --git a/docs/types.rst b/docs/types.rst index 33b8748c0e3e8752b2eb29a0a454ebf6e24cff11..eb4839a942cd6e6f11c2a92c5f6297b2df51adf3 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -1,22 +1,18 @@ Types ===== -For a full list of all unit types see the enum :class:`library.UNIT_TYPEID`. -For more information about a certain unit type, the wrapper class -:class:`library.UnitType` can be used. +For a full list of all unit types see the enum :class:`commandcenter.UNIT_TYPEID`. +For more information about a certain unit type, the wrapper class :class:`commandcenter.UnitType` can be used. -For a full list of all abilities and upgrades, see :class:`library.ABILITY_ID` -, :class:`library.UPGRADE_ID` and :class:`library.EFFECT_ID` respectively. Note that these does not have any +For a full list of all abilities and upgrades, see :class:`commandcenter.ABILITY_ID`, :class:`commandcenter.UPGRADE_ID` and :class:`commandcenter.EFFECT_ID` respectively. Note that these does not have any wrapper classes for them. -If any of the ID's doesn't respond with the game. Before contacting the labassistent, check the game version -and the compatibility through Liquipedia. Some ID's might be left after a patch and is not available in -the game anymore. +If any of the ID's doesn't respond with the game. Before contacting the labassistent, check the game version and the compatibility through Liquipedia. Some ID's might be left after a patch and is not available in the game anymore. UnitType -------- -.. autoclass:: library.UnitType +.. autoclass:: commandcenter.UnitType :members: :undoc-members: :special-members: __init__ @@ -24,27 +20,27 @@ UnitType UNIT_TYPEID ----------- -.. dropdown:: UNIT_TYPEID Enum (dropdown because of the size of the enum) +.. dropdown:: UNIT_TYPEID Enum (click to expand) - .. autoclass:: library.UNIT_TYPEID + .. autoclass:: commandcenter.UNIT_TYPEID :members: :undoc-members: ABILITY_ID ---------- -.. dropdown:: ABILITY_ID Enum (dropdown because of the size of the enum) +.. dropdown:: ABILITY_ID Enum (click to expand) - .. autoclass:: library.ABILITY_ID + .. autoclass:: commandcenter.ABILITY_ID :members: :undoc-members: UPGRADE_ID ---------- -.. dropdown:: UPGRADE_ID Enum (dropdown because of the size of the enum) +.. dropdown:: UPGRADE_ID Enum (click to expand) - .. autoclass:: library.UPGRADE_ID + .. autoclass:: commandcenter.UPGRADE_ID :members: :undoc-members: @@ -52,10 +48,10 @@ EFFECT_ID ---------- EffectID is for things like ravager bile, or fungal or even a scan. -.. dropdown:: EFFECT_ID Enum (dropdown because of the size of the enum) +.. dropdown:: EFFECT_ID Enum (click to expand) - .. autoclass:: library.EFFECT_ID + .. autoclass:: commandcenter.EFFECT_ID :members: :undoc-members: -.. toctree:: \ No newline at end of file +.. toctree:: diff --git a/docs/unit.rst b/docs/unit.rst index 26a6c27d6192ccec7c445ec49c58a8055844f64b..4955340408d66bd1da17280615e92194e5290185 100644 --- a/docs/unit.rst +++ b/docs/unit.rst @@ -1,7 +1,7 @@ Unit ==== -.. autoclass:: library.Unit +.. autoclass:: commandcenter.Unit Properties: diff --git a/pycharm.md b/pycharm.md deleted file mode 100644 index 84cef663757f72fd18db6fb7e8b38eb74cd143b0..0000000000000000000000000000000000000000 --- a/pycharm.md +++ /dev/null @@ -1,13 +0,0 @@ -# Installing PyCommandCenter in PyCharm - -Start by downloading the library. Click the latest tag in the [PyCommandCenter repository](https://gitlab.liu.se/starcraft-ai-course/pycommandcenter/-/tags) and find a `.pyd` link at the bottom of the tag page. - -Place the library in your repository. - -Add the library to the Python path in Python by: - -1. File->Settings->Project: (project name)->Project Interpreter. -2. Select the cog in the upper right corner and select "Show All". -3. In the new window that opens, select the icon which shows a few folders connected with lines. -4. In the new window, first press the plus icon, and then select the path of your repository (the path to where you placed the library). -5. Restart PyCharm with "File->Invalidate Caches/Restart->Invalidate and Restart". diff --git a/python-api-src/CMakeLists.txt b/python-api-src/CMakeLists.txt index 16bb62042b6a08f6a5c4da7d377e818d045415f6..04a63413751a67a58dceb908e5b284866cd07269 100644 --- a/python-api-src/CMakeLists.txt +++ b/python-api-src/CMakeLists.txt @@ -17,7 +17,7 @@ link_directories(${PROJECT_BINARY_DIR}/cpp-sc2/bin) add_definitions(-DSC2API) # Create the executable. -pybind11_add_module(library library.cpp library.h ${BOT_SOURCES} ${LIBRARY_SOURCES}) -target_link_libraries(library PRIVATE +pybind11_add_module(commandcenter library.cpp library.h ${BOT_SOURCES} ${LIBRARY_SOURCES}) +target_link_libraries(commandcenter PRIVATE sc2api sc2lib sc2utils sc2protocol libprotobuf ) diff --git a/python-api-src/lib_base_location.cpp b/python-api-src/lib_base_location.cpp index 59b712633f6f5ba968412ca562fcd3ea0aa9f7ee..1cc8c10a0eba875a791f6445037c9cc3abc52dda 100644 --- a/python-api-src/lib_base_location.cpp +++ b/python-api-src/lib_base_location.cpp @@ -5,27 +5,26 @@ namespace py = pybind11; 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), 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("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). Note: also returns the empty mineral fields.") + .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, "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_property_readonly("position", &BaseLocation::getPosition, "The position of the center of the BaseLocation, defined as a :class:`commandcenter.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_), "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 player. See :ref:`playerconstants` for more information") - .def("contains_position", &BaseLocation::containsPosition, "If the baselocation contains the provided :class:`library.Point2D` position") + .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 player. See :ref:`playerconstants` for more information.") + .def("contains_position", &BaseLocation::containsPosition, "If the baselocation contains the provided :class:`commandcenter.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, "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_property_readonly("base_locations", &BaseLocationManager::getBaseLocations, py::return_value_policy::reference, "A list of all :class:`commandcenter.BaseLocation` on the current map.") + .def_property_readonly("starting_base_locations", &BaseLocationManager::getStartingBaseLocations, py::return_value_policy::reference, "A list of all :class:`commandcenter.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, "Returns a list of all :class:`commandcenter.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:`commandcenter.BaseLocation` that provided :ref:`playerconstants` started at.") + .def("get_next_expansion", &BaseLocationManager::getNextExpansion, py::return_value_policy::copy, "player_constant"_a, "Returns the :class:`commandcenter.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. )"; diff --git a/python-api-src/lib_building_placer.cpp b/python-api-src/lib_building_placer.cpp index 0f4155272e6173e8e2d8a993fa55e13ff401f801..83dd6b9fffef2bd1d765ea8f9ded9b17c21b52ce 100644 --- a/python-api-src/lib_building_placer.cpp +++ b/python-api-src/lib_building_placer.cpp @@ -5,16 +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 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("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 add-ons. 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 plan to later construct an add-on. 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 add-ons. So to check add-ons 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 represents 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, "Reserves 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) .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`. + If you want to place a town hall, take a look at attribute `depot_location` of :class:`commandcenter.BaseLocation`. + If you want to place a refinery, take a look at attribute `geysers` of :class:`commandcenter.BaseLocation` and the method build_target of :class:`commandcenter.Unit`. )"; } \ 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 cc3b2be485758ad084e4f4a74aa2bc72ed19a3d3..1734a8d742f5c2a5b96e0fe0ff57bbf5bb750de3 100644 --- a/python-api-src/lib_map_tools.cpp +++ b/python-api-src/lib_map_tools.cpp @@ -18,39 +18,39 @@ void define_map_tools(py::module & m) const CCColor white{ 255, 255, 255 }; 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_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, "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_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 corner 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, "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_valid_tile", py::overload_cast<int, int>(&MapTools::isValidTile, py::const_), "x"_a, "y"_a, "Checks whether the position is valid for the map.") + .def("is_valid_tile", py::overload_cast<const CCTilePosition &>(&MapTools::isValidTile, py::const_), "point_2di"_a, "Checks whether the tile is valid for the map.") + .def("is_valid_position", py::overload_cast<const CCPosition &>(&MapTools::isValidPosition, py::const_), "point_2d"_a, "Checks whether 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, "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("is_explored", py::overload_cast<int, int>(&MapTools::isExplored, py::const_), "x"_a, "y"_a, "Returns whether the coordinates has been explored or not.") + .def("is_explored", py::overload_cast<const CCPosition &>(&MapTools::isExplored, py::const_), "point2d"_a, "Returns whether the coordinate has been explored or not.") + .def("is_explored", py::overload_cast<const CCTilePosition &>(&MapTools::isExplored, py::const_), "point2di"_a, "Returns whether 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 whether the coordinates are connected.") + .def("is_connected", py::overload_cast<const CCTilePosition &, const CCTilePosition &>(&MapTools::isConnected, py::const_), "from"_a, "to"_a, "Returns whether the tiles are connected.") + .def("is_connected", py::overload_cast<const CCPosition &, const CCPosition &>(&MapTools::isConnected, py::const_), "from"_a, "to"_a, "Returns whether the positions are of two connected tiles.") + .def("is_walkable", py::overload_cast<int, int>(&MapTools::isWalkable, py::const_), "x"_a, "y"_a, "Returns whether the coordinates is walkable.") + .def("is_walkable", py::overload_cast<const CCTilePosition &>(&MapTools::isWalkable, py::const_), "point2di"_a, "Returns whether the tile is walkable.") + .def("is_buildable", py::overload_cast<int, int>(&MapTools::isBuildable, py::const_), "x"_a, "y"_a, "Returns whether it is possible to build at the provided coordinate.") + .def("is_buildable", py::overload_cast<const CCTilePosition &>(&MapTools::isBuildable, py::const_), "point2di"_a, "Returns whether it is possible to build on tile.") + .def("is_visible", &MapTools::isVisible, "x"_a, "y"_a, "Returns whether the location identified by the coordinates is visible.") + .def("can_build_type_at_position", &MapTools::canBuildTypeAtPosition, "x"_a, "y"_a, "unit_type"_a, "Returns whether it is possible to build the provided unittype at the location.") + .def("is_depot_buildable_tile", &MapTools::isDepotBuildableTile, "x"_a, "y"_a, "Returns whether it is possbile to 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, "Returns the tile that the most time has passed since it was visible") + .def("get_closest_tiles_to", &MapTools::getClosestTilesTo, "Returns a list of positions, where the first position is the closest and the last is the farthest.", "point2di"_a) + .def("get_least_recently_seen_tile", &MapTools::getLeastRecentlySeenTile, "Returns the tile for which the most time has passed since it was last visible.") .doc() = R"( This class contains two types of methods: diff --git a/python-api-src/lib_replay_unit.cpp b/python-api-src/lib_replay_unit.cpp index 7364163e5ae62362c1f6fea28ecd636ca78df321..cbca06b6a696f5a0a68064fc0973007b3171e427 100644 --- a/python-api-src/lib_replay_unit.cpp +++ b/python-api-src/lib_replay_unit.cpp @@ -5,42 +5,42 @@ namespace py = pybind11; void define_replay_unit(py::module & m) { py::class_<ReplayUnit>(m, "ReplayUnit") - .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, "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("id", &ReplayUnit::getID, "The ID of the unit.") + .def_property_readonly("unit_type", &ReplayUnit::getType, "The :class:`commandcenter.UnitType` of the unit.") + .def_property_readonly("position", &ReplayUnit::getPosition, "The :class:`commandcenter.Point2D` of the unit.") + .def_property_readonly("tile_position", &ReplayUnit::getTilePosition, "The :class:`commandcenter.Point2DI` of the unit.") + .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, "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_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, "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. + A ReplayUnit is a :class:`commandcenter.Unit` with 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 eeb8338dd53a1feaa4cfffd6fc3647682cb2dd34..091ffb7040e7a6f4173e7b9f7de8a3a80bfa7b64 100644 --- a/python-api-src/lib_sc2_typeenums.cpp +++ b/python-api-src/lib_sc2_typeenums.cpp @@ -3382,6 +3382,7 @@ void define_typeenums(py::module & m) .value("PSIDISRUPTOR", sc2::UPGRADE_ID::PSIDISRUPTOR) .value("PSIONICAMPLIFIERS", sc2::UPGRADE_ID::PSIONICAMPLIFIERS) .value("PSISTORMTECH", sc2::UPGRADE_ID::PSISTORMTECH) + .value("CONCUSSIONSHELLS", sc2::UPGRADE_ID::PUNISHERGRENADES) .value("PUNISHERGRENADES", sc2::UPGRADE_ID::PUNISHERGRENADES) .value("RAPIDDEPLOYMENT", sc2::UPGRADE_ID::RAPIDDEPLOYMENT) .value("RAVAGERRANGE", sc2::UPGRADE_ID::RAVAGERRANGE) diff --git a/python-api-src/lib_tech_tree.cpp b/python-api-src/lib_tech_tree.cpp index b982844682e7bbb31159836d5c35411ff247cf8a..9184263ed30c013e625efd7bbe823bf39ef16034 100644 --- a/python-api-src/lib_tech_tree.cpp +++ b/python-api-src/lib_tech_tree.cpp @@ -6,31 +6,31 @@ void define_tech_tree(py::module & m) { py::class_<TypeData>(m, "TypeData") .def_readonly("race", &TypeData::race) - .def_readonly("mineral_cost", &TypeData::mineralCost, "mineral cost of the item") - .def_readonly("gas_cost", &TypeData::gasCost, "gas cost of the item") - .def_readonly("supply_cost", &TypeData::supplyCost, "supply cost of the item") - .def_readonly("build_time", &TypeData::buildTime, "build time of the item in seconds (should be 32 game updates per tick, can someone verify this?)") - .def_readonly("is_unit", &TypeData::isUnit, "is the item a unit") - .def_readonly("is_building", &TypeData::isBuilding, "is the item a building") - .def_readonly("is_worker", &TypeData::isWorker, "is the item a worker") - .def_readonly("is_refinery", &TypeData::isRefinery, "is the item a refinery") - .def_readonly("is_supply_provider", &TypeData::isSupplyProvider, "is the item a supply provider") - .def_readonly("is_resource_depot", &TypeData::isResourceDepot, "is the item a resource depot") - .def_readonly("is_addon", &TypeData::isAddon, "is the item an addon") - .def_readonly("build_ability", &TypeData::buildAbility, "the ability that creates this item") - .def_readonly("warp_ability", &TypeData::warpAbility, "the ability that creates this item via warp-in") - .def_readonly("what_builds", &TypeData::whatBuilds, "any of these units can build the item") - .def_readonly("required_units", &TypeData::requiredUnits, "owning ONE of these is required to make -> List[UnitType]") - .def_readonly("required_upgrades", &TypeData::requiredUpgrades, "having ALL of these is required to make -> List[UPGRADE_ID]") - .def_readonly("required_addons", &TypeData::requiredAddons, "a unit of this type must be present next to the producer -> List[UnitType]") + .def_readonly("mineral_cost", &TypeData::mineralCost, "The mineral cost of the item.") + .def_readonly("gas_cost", &TypeData::gasCost, "The gas cost of the item.") + .def_readonly("supply_cost", &TypeData::supplyCost, "The supply cost of the item.") + .def_readonly("build_time", &TypeData::buildTime, "The build time of the item in seconds (should be 32 game updates per tick).") + .def_readonly("is_unit", &TypeData::isUnit, "Whether the item is a unit.") + .def_readonly("is_building", &TypeData::isBuilding, "Whether the item is a building.") + .def_readonly("is_worker", &TypeData::isWorker, "Whether the item is a worker.") + .def_readonly("is_refinery", &TypeData::isRefinery, "Whether the item is a refinery.") + .def_readonly("is_supply_provider", &TypeData::isSupplyProvider, "Whether the item is a supply provider.") + .def_readonly("is_resource_depot", &TypeData::isResourceDepot, "Whether the item is a resource depot.") + .def_readonly("is_addon", &TypeData::isAddon, "Whether the item is an add-on.") + .def_readonly("build_ability", &TypeData::buildAbility, "The ability that creates this item.") + .def_readonly("warp_ability", &TypeData::warpAbility, "The ability that creates this item via warp-in.") + .def_readonly("what_builds", &TypeData::whatBuilds, "The units that can build the item.") + .def_readonly("required_units", &TypeData::requiredUnits, "Owning ONE of these (List[UnitType]) is required to make the item.") + .def_readonly("required_upgrades", &TypeData::requiredUpgrades, "Having ALL of these (List[UPGRADE_ID]) is required to make the item.") + .def_readonly("required_addons", &TypeData::requiredAddons, "A unit of this type (List[UnitType]) must be present next to the producer.") .doc() = R"( Allows you to get information about a unit type or upgrade. This is a read-only class. )"; 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_), "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) + .def("get_data", py::overload_cast<const CCUpgrade &>(&TechTree::getData, py::const_), "Argument is either an instance of the class :class:`commandcenter.UnitType` or an instance of the class :class:`commandcenter.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 diff --git a/python-api-src/lib_unit.cpp b/python-api-src/lib_unit.cpp index b2b23a5dda386f1a013c9dba4cb85b8e31b9ce87..4fe031c4a52d6931de4e5b779f7f6da7a0d947f0 100644 --- a/python-api-src/lib_unit.cpp +++ b/python-api-src/lib_unit.cpp @@ -5,63 +5,63 @@ namespace py = pybind11; void define_unit(py::module & m) { py::class_<Unit>(m, "Unit") - .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("unit_type", &Unit::getType, "The :class:`commandcenter.UnitType` of the unit.") + .def_property_readonly("position", &Unit::getPosition, "The :class:`commandcenter.Point2D` of the unit.") + .def_property_readonly("tile_position", &Unit::getTilePosition, "The :class:`commandcenter.Point2DI` of the unit.") .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("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_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, "Direction the unit faces in radians (1 radian == 57.296 degrees)") - .def_property_readonly("radius", &Unit::getRadius, "Returns 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("is_idle", &Unit::isIdle, "Whether the unit has any orders.") + .def_property_readonly("is_burrowed", &Unit::isBurrowed, "Whether the unit is burrowed.") + .def_property_readonly("is_valid", &Unit::isValid, "Whether the unit is valid") + .def_property_readonly("is_training", &Unit::isTraining, "Returns True if the unit is a building and is training 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, "Direction the unit faces in radians (1 radian == 57.296 degrees).") + .def_property_readonly("radius", &Unit::getRadius, "Returns 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("owner", &Unit::getOwner, "Which player owns a unit. Note: Not same as player; 'player' originates from IDA implementation whilst 'owner' originates from StarCraft II.") .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("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_), "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("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_), "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) - .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, "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("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:`commandcenter.Point2D` or :class:`commandcenter.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) + .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:`commandcenter.UPGRADE_ID`.", "upgrade_id"_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:`commandcenter.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() + "'>"; }) @@ -71,10 +71,10 @@ void define_unit(py::module & m) 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`. + For all possible types of units see the enum :class:`commandcenter.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 + motivations behind the :class:`commandcenter.UnitType` which aims to to make the list of types more manageable. The UnitType can be accessed by the :any:`Unit.unit_type` property. diff --git a/python-api-src/lib_unittype.cpp b/python-api-src/lib_unittype.cpp index 346ffc5015f085bf1ad6fe8fdb4ff479d1e94d5c..86124e51c1a9d66e5b385988cb6544fe1f360099 100644 --- a/python-api-src/lib_unittype.cpp +++ b/python-api-src/lib_unittype.cpp @@ -9,41 +9,41 @@ void define_unittype(py::module & m) return UnitType(type, bot, bot); })) .def_property_readonly("unit_typeid", [](UnitType & unit_type) { return static_cast<sc2::UNIT_TYPEID>(unit_type.getAPIUnitType()); }) - .def_property_readonly("name", &UnitType::getName, "The name of the unit as a sting.") + .def_property_readonly("name", &UnitType::getName, "The name of the unit as a string.") .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, "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") + .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, "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 morphed.") // 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, "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("is_addon", &UnitType::isAddon, "Is this unit type a add-on.") + .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.") @@ -54,7 +54,7 @@ void define_unittype(py::module & m) .def("__lt__", &UnitType::operator<, py::is_operator()) .def("__eq__", &UnitType::operator==, py::is_operator()) .doc() = R"( - Wrapper for :class:`library.UNIT_TYPEID`. Represents a type of unit in the game. + Wrapper for :class:`commandcenter.UNIT_TYPEID`. Represents a type of unit in the game. NOTE: A lot of functions utilize checks that require the game to be running. Therefore if you get an unexpected segmentation fault, it is likely due to the game not being in a running state. )"; diff --git a/python-api-src/library.cpp b/python-api-src/library.cpp index 22cff691ff11b0832373c5679f3bae36d56e0eaf..2348de060cbcd4ba4de37f4c695e7b5b33809776 100644 --- a/python-api-src/library.cpp +++ b/python-api-src/library.cpp @@ -2,7 +2,7 @@ namespace py = pybind11; -PYBIND11_MODULE(library, m) +PYBIND11_MODULE(commandcenter, m) { m.doc() = "Python API for playing Starcraft II"; @@ -130,48 +130,48 @@ PYBIND11_MODULE(library, m) .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") - .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 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 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 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 through debug mode") - .def("debug_set_score", &IDABot::DebugSetScore, "Set the Players score in game through 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:`commandcenter.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 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 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 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 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 CCposition of the enemy base") - .def("move_camera", &IDABot::CameraMove, "Move the camera to the position", "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, "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("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 CCposition of the enemy base.") + .def("move_camera", &IDABot::CameraMove, "Move the camera to the position.", "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, "An instance of the class :class:`commandcenter.BaseLocationManager`. ") + .def_property_readonly("tech_tree", &IDABot::GetTechTree, "An instance of the class :class:`commandcenter.TechTree`.") + .def_property_readonly("map_tools", &IDABot::Map, "An instance of the class :class:`commandcenter.MapTools`.") + .def_property_readonly("building_placer", &IDABot::GetBuildingPlacer, "An instance of the class :class:`commandcenter.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") - .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.)"; + .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.") + .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 stripped-down version of a bot. It contains all available managers and basic methods.)"; diff --git a/create-visual-studio-solution.bat b/scripts/create-visual-studio-solution-python312.bat similarity index 88% rename from create-visual-studio-solution.bat rename to scripts/create-visual-studio-solution-python312.bat index fca77ee399561b5d5de2625619d23d73a768093d..7e56ecf4942ca68cac71e633f150ca0713a8b6ba 100644 --- a/create-visual-studio-solution.bat +++ b/scripts/create-visual-studio-solution-python312.bat @@ -1,4 +1,4 @@ -mkdir build -cd build +mkdir ..\build +cd ..\build "C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 17 2022" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python312/python.exe" "C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --verbose diff --git a/create-visual-studio-solution-python312.sh b/scripts/create-visual-studio-solution-python312.sh old mode 100644 new mode 100755 similarity index 89% rename from create-visual-studio-solution-python312.sh rename to scripts/create-visual-studio-solution-python312.sh index 6813c78038e134392b21d66693abd54dc90ac4a8..3f925f6c1d81fdbc3fcbd29a2b062e917f3e47a1 --- a/create-visual-studio-solution-python312.sh +++ b/scripts/create-visual-studio-solution-python312.sh @@ -1,6 +1,6 @@ #!/bin/sh -mkdir build -cd build +mkdir ../build +cd ../build "C:\Program Files\CMake\bin\cmake.exe" -G "Visual Studio 17 2022" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python312/python.exe" .. "C:\Program Files\CMake\bin\cmake.exe" --build . --config Release --verbose diff --git a/create-visual-studio-solution-python37.sh b/scripts/create-visual-studio-solution-python37.sh similarity index 82% rename from create-visual-studio-solution-python37.sh rename to scripts/create-visual-studio-solution-python37.sh index 828e5cb115dc98eedaca8ad5cd192d18f12c5382..ad2ac93df78b7165f38924c04e1978a125649ade 100644 --- a/create-visual-studio-solution-python37.sh +++ b/scripts/create-visual-studio-solution-python37.sh @@ -1,5 +1,5 @@ #!/bin/sh -mkdir build37 -cd build37 +mkdir ../build37 +cd ../build37 "C:\Program Files\CMake\bin\cmake" .. -G "Visual Studio 15 Win64" -DPYTHON_EXECUTABLE:FILEPATH="C:/Program Files/Python37/python.exe" diff --git a/create-visual-studio-solution-python38.sh b/scripts/create-visual-studio-solution-python38.sh similarity index 82% rename from create-visual-studio-solution-python38.sh rename to scripts/create-visual-studio-solution-python38.sh index 324f984c01dbc1727bfe0f83f395fc16f6833357..6fda311ddb6176e16045b74f28db54e1eefc4cdd 100644 --- a/create-visual-studio-solution-python38.sh +++ b/scripts/create-visual-studio-solution-python38.sh @@ -1,5 +1,5 @@ #!/bin/sh -mkdir build38 -cd build38 +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/scripts/create-visual-studio-solution-python39.sh similarity index 84% rename from create-visual-studio-solution-python39.sh rename to scripts/create-visual-studio-solution-python39.sh index 1d032bd4fe5e96db107fde946800f0d52ad6a4a2..00d016ffa7949c097942f7289ff7cf34fb41f112 100644 --- a/create-visual-studio-solution-python39.sh +++ b/scripts/create-visual-studio-solution-python39.sh @@ -1,5 +1,5 @@ #!/bin/sh -mkdir build -cd build +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/generate_pydocs.py b/scripts/generate_pydocs.py similarity index 83% rename from generate_pydocs.py rename to scripts/generate_pydocs.py index 2ffb6e7dcadccc7583665e4cd9a737d5d6a6b642..fc7ceb6fd29f3a7acf6517ecc0548d2172075b45 100644 --- a/generate_pydocs.py +++ b/scripts/generate_pydocs.py @@ -13,7 +13,7 @@ import re sys.path.append('build/python-api-src') #Unix sys.path.append('build/python-api-src/Release') #Windows -import library +import commandcenter def update_pyi_with_docstrings(pyi_path): """ @@ -37,17 +37,17 @@ def update_pyi_with_docstrings(pyi_path): new_lines.append(line) if not line.strip().endswith("ID:"): class_name = re.split(r'[\(: ]', line)[1] - docstring = inspect.getdoc(getattr(library, class_name)) + docstring = inspect.getdoc(getattr(commandcenter, class_name)) new_lines.append(f' """{docstring}"""\n') - for func in dir(getattr(library, class_name)): + for func in dir(getattr(commandcenter, class_name)): if func.startswith("__"): continue - func_docs = inspect.getdoc(getattr(getattr(library, class_name), func)) + func_docs = inspect.getdoc(getattr(getattr(commandcenter, class_name), func)) known_def[func] = func_docs else: class_name = re.split(r'[\(: ]', line)[1] - docstring = inspect.getdoc(getattr(library, class_name)) + docstring = inspect.getdoc(getattr(commandcenter, class_name)) docstring = docstring.split("Members:")[0] new_lines.append(f' """{docstring}"""\n') @@ -63,7 +63,7 @@ def update_pyi_with_docstrings(pyi_path): continue else: try: - func_doc = inspect.getdoc(getattr(library, func_name)) + func_doc = inspect.getdoc(getattr(commandcenter, func_name)) if func_name == "create_computer" or func_name == "create_participants": #Special case with indentation new_lines.append(f'\n """{func_doc}"""\n') else: @@ -84,6 +84,6 @@ def update_pyi_with_docstrings(pyi_path): # Path to the generated .pyi file -pyi_file_path = 'build/python-api-src/library.pyi' #Unix -#pyi_file_path = 'build/python-api-src/Release/library.pyi' #Windows +pyi_file_path = 'build/python-api-src/commandcenter.pyi' #Unix +#pyi_file_path = 'build/python-api-src/Release/commandcenter.pyi' #Windows update_pyi_with_docstrings(pyi_file_path) diff --git a/src/UnitType.cpp b/src/UnitType.cpp index 688ccb4c70417bf8fd9a737a3e651de2449d65ba..2757175356868dfbce5b7ef58f77ab4cdf5bf88a 100644 --- a/src/UnitType.cpp +++ b/src/UnitType.cpp @@ -70,13 +70,12 @@ std::string UnitType::getName() const CCRace UnitType::getRace() const { - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed to get race, try with game running!" << std::endl; return CCRace::Random; } - return UTData[m_type].race; + return m_client->Observation()->GetUnitTypeData()[m_type].race; } bool UnitType::isCombatUnit() const @@ -231,13 +230,12 @@ bool UnitType::isWorker() const bool UnitType::canAttackGound() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed canAttackGround, try with game running!" << std::endl; return false; } - auto & weapons = UTData[m_type].weapons; + auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons; if (weapons.empty()) { @@ -262,13 +260,12 @@ bool UnitType::canAttackAir() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed canAttackAir, try with game running!" << std::endl; return false; } - auto & weapons = UTData[m_type].weapons; + auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons; if (weapons.empty()) { @@ -292,13 +289,12 @@ bool UnitType::canAttackAir() const CCPositionType UnitType::getAttackRange() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed getAttackRange, try with game running!" << std::endl; return 0.0f; } - auto & weapons = UTData[m_type].weapons; + auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons; if (weapons.empty()) { @@ -324,13 +320,12 @@ CCPositionType UnitType::getAttackRange() const float UnitType::getAttackDamage() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed getAttackDamage, try with game running!" << std::endl; return 0.0f; } - auto & weapons = UTData[m_type].weapons; + auto & weapons = m_client->Observation()->GetUnitTypeData()[m_type].weapons; if (weapons.empty()) { return 0.0f; @@ -359,20 +354,19 @@ int UnitType::tileWidth() const if (isMineral()) { return 2; } if (isGeyser()) { return 3; } else { - auto UTData = m_client->Observation()->GetAbilityData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetAbilityData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed tileWidth, try with game running!" << std::endl; + return 0; } else if (m_bot != nullptr) { - return (int)(2 * UTData[m_bot->Data(*this).buildAbility].footprint_radius); + return (int)(2 * m_client->Observation()->GetAbilityData()[m_bot->Data(*this).buildAbility].footprint_radius); } else if (m_observer != nullptr) { - return (int)(2 * UTData[m_observer->Data(*this).buildAbility].footprint_radius); + return (int)(2 * m_client->Observation()->GetAbilityData()[m_observer->Data(*this).buildAbility].footprint_radius); } else { @@ -390,20 +384,19 @@ int UnitType::tileHeight() const if (isMineral()) { return 1; } if (isGeyser()) { return 3; } else { - auto UTData = m_client->Observation()->GetAbilityData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetAbilityData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed tileHeight, try with game running!" << std::endl; + return 0; } else if (m_bot != nullptr) { - return (int)(2 * UTData[m_bot->Data(*this).buildAbility].footprint_radius); + return (int)(2 * m_client->Observation()->GetAbilityData()[m_bot->Data(*this).buildAbility].footprint_radius); } else if (m_observer != nullptr) { - return (int)(2 * UTData[m_observer->Data(*this).buildAbility].footprint_radius); + return (int)(2 * m_client->Observation()->GetAbilityData()[m_observer->Data(*this).buildAbility].footprint_radius); } else { @@ -461,14 +454,13 @@ bool UnitType::isBuilding() const int UnitType::supplyProvided() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed supplyProvided, try with game running!" << std::endl; + return 0; } - return (int)UTData[m_type].food_provided; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].food_provided; #else return m_type.supplyProvided(); #endif @@ -477,14 +469,13 @@ int UnitType::supplyProvided() const int UnitType::supplyRequired() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed supplyRequired, try with game running!" << std::endl; + return 0; } - return (int)UTData[m_type].food_required; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].food_required; #else return m_type.supplyRequired(); #endif @@ -493,13 +484,12 @@ int UnitType::supplyRequired() const int UnitType::mineralPrice() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed mineralPrice, try with game running!" << std::endl; + return 0; } - return (int)UTData[m_type].mineral_cost; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].mineral_cost; #else return m_type.mineralPrice(); #endif @@ -508,13 +498,12 @@ int UnitType::mineralPrice() const int UnitType::gasPrice() const { #ifdef SC2API - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed gasPrice, try with game running!" << std::endl; + return 0; } - return (int)UTData[m_type].vespene_cost; + return (int)m_client->Observation()->GetUnitTypeData()[m_type].vespene_cost; #else return m_type.gasPrice(); #endif @@ -606,66 +595,60 @@ bool UnitType::isMorphedBuilding() const int UnitType::getMovementSpeed() const { - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed getMovementSpeed, try with game running!" << std::endl; + return 0; } - return UTData[m_type].movement_speed; + return m_client->Observation()->GetUnitTypeData()[m_type].movement_speed; } int UnitType::getSightRange() const { - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed getSightRange, try with game running!" << std::endl; + return 0; } - return UTData[m_type].sight_range; + return m_client->Observation()->GetUnitTypeData()[m_type].sight_range; } UnitTypeID UnitType::getRequiredStructure() const { - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed getRequiredStructure, try with game running!" << std::endl; return UnitTypeID(); } - return UTData[m_type].tech_requirement; + return m_client->Observation()->GetUnitTypeData()[m_type].tech_requirement; } std::vector<sc2::UnitTypeID> UnitType::getEquivalentUnits() const { - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed getEquivalentUnits, try with game running!" << std::endl; return std::vector<sc2::UnitTypeID>(); } - return UTData[m_type].tech_alias; + return m_client->Observation()->GetUnitTypeData()[m_type].tech_alias; } bool UnitType::requiredAttached() const { - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); + std::cout << "Failed requiredAttached, try with game running!" << std::endl; return false; } - return UTData[m_type].require_attached; + return m_client->Observation()->GetUnitTypeData()[m_type].require_attached; } float UnitType::getBuildTime() const { - auto UTData = m_client->Observation()->GetUnitTypeData(); - if (UTData.empty()) // Check to hopefully avoid segfaults + if (m_client->Observation()->GetUnitTypeData().empty()) // Check to hopefully avoid segfaults { - BOT_ASSERT(false, "Failed, try with game running!"); - return -1; + std::cout << "Failed getBuildTime, try with game running!" << std::endl; + return 0.0f; } - return UTData[m_type].build_time; + return m_client->Observation()->GetUnitTypeData()[m_type].build_time; } \ No newline at end of file diff --git a/tests/unittypeid.py b/tests/unittypeid.py index f3815d9002078987949f31beac2dec8cb93123b3..bc339814215c40dc9f6969aaa8b468e0c28c9c7d 100644 --- a/tests/unittypeid.py +++ b/tests/unittypeid.py @@ -3,7 +3,7 @@ import sys sys.path.append('build/python-api-src') -from library import UnitTypeID, UNIT_TYPEID +from commandcenter import UnitTypeID, UNIT_TYPEID class TestUnitType(unittest.TestCase):