Here we cover the very basics to start developing and deploying your bots in the framework. For detailed instructions, please read the readme file:
- readme.md in the source project structure.
- readme.md on the project’s Github page
Start by creating each of your bots in single python files placed inside the “src/bots/test_bots” folder.
The bots that you want to launch when running the game (as well as other basic settings) are specified in the settings.json file.
The folder “src/bots/” includes Skeleton.py, an empty sample bot that you can use as a template.
The baseline bot
The folder “src/bots/test_bots” includes the built-in bot “TestBotBasicSmart.py“, that you can use as baseline rival for your own bots, as well as a source of inspiration and example.
This bot is prepared to work either as Radiant or Dire. NOTE: it’s good practice that you select your heroes (for one or both teams) in a dictionary:
Creating your bot
A bot is written as a Python class that inherits from BaseBot. BaseBot is an abstract base class, and by inheriting from it, you are forced to implement three methods:
|initialize||Called on the first game tick with a list of the hero entities that belong to this bot.|
|actions||Called every game tick, once for each hero on the bot’s team. In this method, the bot developer decides on what action each hero should take in a particular game tick.|
|get_party||Should return a list of the heroes that the bot intends to use.|
BaseBot methods with default implementation which can optionally be overridden:
|before_actions||Called every game tick before actions is called for each hero.|
|after_actions||Called every game tick after actions has been called for each hero.|
Creating bots: class constructor
The constructor should have a single argument: world. The world parameter is an instance of the world object for the particular team that the bot is on. Radiant and Dire do not share world objects because the teams see different things during the course of the game due to fog of war.
Creating bots: game ticks
Game ticks are a fundamental concept in the framework. On each game tick, the game state is updated and each bot controlled hero is allowed to perform a single command. The framework’s tick rate is adjustable and ultimately a question of how often the Lua addon sends updates to the Python server. Do not confuse the framework’s tick rate with Dota 2’s tick rate; they are completely unrelated. The framework’s default tick rate is 0.33 seconds which means that a particular hero can never execute more than three commands per second.
Creating bots: using the same bot on both teams
It might be the case that you want to use the same bot on both teams and do some things differently depending on what team the bot is on. For example, a bot could define two lists of heroes and return a different one in get_party for each team. To support this use-case the world object has a method, get_team(), that returns the bot’s team.
Creating bots: using the API
For a hero do something it needs to be issued a command in the actions method. A hero is given a command by calling a method on the hero object. Simple example:
def actions(self, hero: PlayerHero, game_ticks: int): """This method will run once for each hero during every gametick. This is the starting point for your code commanding the different heroes.""" if game_ticks == 1: hero.move(0, 0)
In the above code, all heroes on this bot’s team will move to position (0, 0) on the first game tick and then do nothing else for the rest of the game (assuming that this is the complete actions method). Commands are not “saved” between game ticks, and it’s legal to not issue a command in a particular game tick. This means that in this case, the heroes will not have any commands to execute on any game tick above 1.
However, keep in mind that a single command could have effects in-game beyond the immediate game tick. E.g., a hero will keep moving to its designated position independently of the game ticks until it reaches its position, a different command is issued that stops it from moving to the position in question, or it’s killed.
The World object is used to provide game state information that the bot writer might need to make appropriate decisions.
|get_team||Returns the team that the hero is on (2 for Radiant and 3 for Dire).|
|get_game_time()||Returns the current game time in seconds to support taking actions that depend on the game clock.|