In this tutorial, we'll go through the code that powers the random bot and add a couple heuristics to it. This will hopefully help you fully understand Halite and set you on your way to leaderboard domination.
The code in this tutorial can be found at the following links for Python, Java, and C++.
Make sure that you have read Introducing Halite and followed the setup procedures described there.
Now open up the MyBot file in your favorite editor and let's get started!
When writing a halite bot, be sure to stay away from functions like System.out.print
, cout
, print
, etc. Bots use stdout and stdin to communicate with the game environment. You will be ejected from a game of Halite if you print debugging info to stdout. Instead, print to a log file.
Now that you know how the game works, how do the two random starter bots work? How does one code a Halite bot? Here is the source from the main file of our python starter bot:
Let's walk through it line by line.
First we make some imports from the hlt.py helper file that is included in the starter package:
Then we get our ID (each player has a unique identifier that is associated with their pieces) and the initial game map from the environment. We send back the name of our bot. This is used in game replays.
Now we start our game loop:
Each turn, update the current map from the game environment:
Let's create our list of moves by cycling through all the pieces on the map. If a piece is owned by us, let's instruct it to move in a random direction.
Finally, let's send all of our moves to the environment:
And that's random bot!
From the rules outlined in Introducing Halite, we know that when a piece moves, it gains no strength and leaves behind a piece with zero strength. It easily follows from this that moving zero strength pieces is a terrible idea, since:
Let's wrap the movement logic inside a function of its own. This function will take a piece as input and will return the piece's movement.
Now we can improve our bot by making sure that we tell all of our zero strength pieces to remain still.
Our bot still moves its pieces around a lot (only a bit over one out of five turns will a piece stay still). This costs us a lot of strength (since a piece doesn't gain any strength on turns that it moves). To increase our utilization of our production, let's have pieces only move once their strength equals their production times some factor X. We're using 5 as the value of X in this example, but this is arbitrary.
When building a Halite bot, one of our goals should be moving strength out of your territory quickly and with little production loss. Our current bot is terrible at this. Its pieces move randomly around our territory, going nowhere, costing us production, and often losing strength to the strength cap.
To improve this, let's just mandate that our pieces move only north and west. Since the map is wrap-around, we can still capture all of the board with this strategy!
Once our pieces get to our borders, we don't want them to randomly attack just any square (or worse, move back into our territory), as we do now. One problem with this random strategy is that we may attack a map square that has more strength than us. This is unproductive (pun implied) since moving onto the map square costs us a turn of production and we don't actually gain anything. We just diminish the squares strength.
To improve on our current combat, if there is an enemy or map square that is adjacent to one of our pieces with less strength than our piece, let's take it.
That's really up to you! How you improve your bot from here is where you step into the competition.
That said, if you're looking for more ideas or a stronger starting base, nmalaguti wrote a tutorial that walks you through improving your combat, piece management, and expansion.
If you're interested in machine learning, Two Sigma's own Brian van Leeuwen authored an introductory deep learning tutorial.
Good luck!