4.8 KiB
Pytron
This program is a simple python game, made for implementing your own AIs.
Table of contents
How to download the game
The first step is to clone the repository:
git clone https://gitea.tforgione.fr/tforgione/pytron
Then, ensure you have python3
and pygame
installed. You can test you have
everything by executing the following command:
python3 -c "import pygame"
-
if you get a
python3: command not found
, it means you don't havepython3
, you can install it on ubuntu like so:sudo apt install python3
-
if you get a
ImportError: No module named 'pygame'
, it means you don't havepygame
, you can install it on ubuntu like so:sudo apt install python3-pip sudo pip3 install pygame
How to play the game
There are two runnable scripts in the repository, which are mostly here to be examples:
play.py
which shows how to create a game with a window and play against an AI.headless.py
which shows how to run a game with AIs without watching the interface, and thus, really fast.
How to create your own AI
You need to write a class that derives from snake.player.Player
. You have to
define a constructor, so you can instanciate it, and implement the method
action
which takes as parameter the map of the game, and returns the
direction you want to take.
For example, you can create a file myplayer.py
at the root of this repository
containing the following:
from snake.player import Player, Direction
class MyPlayer(Player):
def __init__(self):
super(MyPlayer, self).__init__()
def action(self, game_map):
# Do stuff
return Direction.DOWN
and you can create an executable file containing the following:
#!/usr/bin/env python3
import contextlib
with contextlib.redirect_stdout(None):
import pygame
from snake.map import Map
from snake.game import Game, PositionPlayer
from snake.window import Window
from snake.player import Player, Direction, ConstantPlayer, KeyboardPlayer
def main():
pygame.init()
width = 40
height = 40
game = Game(width, height, [
PositionPlayer(1, KeyboardPlayer(Direction.RIGHT), [0, 0]),
PositionPlayer(2, ConstantPlayer(Direction.LEFT), [width - 1, height - 1]),
])
window = Window(game, 20)
game.main_loop(window)
if __name__ == '__main__':
main()
and it should work.
About map
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, Case.EMPTY, Case.WALL)
it really creates a 7x7 np.array
, in which the interior is filled with
Case.EMPTY
and the border with Case.WALL
.
Playing with maps
If you want to modify the map, you can do so by using the getters. Be careful, the getter don'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, Case.EMPTY, Case.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] = Case.PLAYER_ONE_HEAD
You can easily clone a map:
my_map = Map(5, 5, Case.EMPTY, Case.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(x):
return x + 1
my_map = Map(5, 5, Case.EMPTY, Case.WALL)
my_map.apply(my_function)
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, Case.EMPTY, Case.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, Case.EMPTY, Case.WALL)
my_array = my_map.clone_array()
# Modifying my_array won't modify my_map
my_array[0][0] = ...