122 lines
3.6 KiB
Markdown
122 lines
3.6 KiB
Markdown
# 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
|
|
|
|
``` python
|
|
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:
|
|
|
|
``` python
|
|
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:
|
|
``` python
|
|
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:
|
|
``` python
|
|
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:
|
|
``` python
|
|
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:
|
|
|
|
``` python
|
|
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
|
|
```
|
|
|
|
<strong>
|
|
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
|
|
</strong>
|
|
|
|
If you wan to modify an np-array without modifying the map, you can use the
|
|
`clone_array` method:
|
|
|
|
``` python
|
|
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
|
|
|
|
``` python
|
|
my_map = Map(5, 5, Tile.EMPTY, Tile.WALL);
|
|
# ...
|
|
my_input = map.state_for_player(1)
|
|
```
|