3.6 KiB
The map module
The map
module contains two important classes:
- the
Tile
class - the
Map
class
The Tile
class
This class contains the different possible values for the tiles of the map. Each value has its own meaning, and the names given are explicit enough.
This class also contains a method named color
which return a 3-uple
containing the red, green and blue channels of the colors of the corresponding
tile. This is espeacially useful for rendering the game on a window.
The Map
class
Map
is one of the most important class of this project. It is made to be easy
to manipulate with things like PyTorch.
It contains an np.array
of two dimensions containing two rows and two columns
more that what specify, because is automatically adds border to your map. This
means that when you run
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL)
it really creates a 7x7 np.array
, in which the interior is filled with
Tile.EMPTY
and the border with Tile.WALL
.
Playing with maps
If you want to modify the map, you can do so by using the getters. Be careful, the getter doesn't take the border into account. You won't be able to modify the border with the getters.
To use the getters, you can do like this:
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL)
# Sets the top left corner of the map to PLAYER_ONE_HEAD
# This does not modify the border, it modifies the inner tile.
my_map[0, 0] = Tile.PLAYER_ONE_HEAD
You can easily clone a map:
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL)
my_second_map = my_map.clone() # Clones the whole map
If you want to clone the array of a map and apply a function to it at the same time, you can do like this:
def my_function(tile):
return tile.value + 1
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL)
my_map.apply(my_function)
If you need, you can use some more parameters and create lambdas, which might give you a clearer code:
def my_function(tile, offset):
return tile.value + offset
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL)
my_map.apply(lambda tile: my_function(tile, 1))
Playing with maps' np-arrays
At any moment, you can get a reference to the np.array
of the map by using
the array
method:
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL)
my_array = my_map.array()
my_array[0][0] = ... # Modifies the top left tile of the border of the map
Be careful: when you get a reference to an np-array, you need to remember:
- the np-array does cantain the border, so the (i, j) tile of the map is the
(i + 1, j + 1) tile of the array
- since you get a reference to the np-array, modifying it will also modify
the map
If you wan to modify an np-array without modifying the map, you can use the
clone_array
method:
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL)
my_array = my_map.clone_array()
# Modifying my_array won't modify my_map
my_array[0][0] = ...
Getting input for your neural network
First of all, it's important to realize that the map does not depend on who is
the player 1. When a player's action
method is called, it is called with the
map as parameter, and also the id so that the player is able to know who he is
on the map.
You can easily convert the map to an input for your neural network by using the
state_for_player
method. It takes the id of the player as a parameter and
returns a numpy array that will have:
- 1 where tiles are empty
- -1 where tiles are walls or bodies of snakes
- 10 for the head of the player with the corresponding id
- -10 for the head of the other player
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL);
# ...
my_input = map.state_for_player(1)