Cleaning and docs

This commit is contained in:
Thomas Forgione 2019-03-13 22:26:39 +01:00
parent aae3128737
commit f692e6c8f2
No known key found for this signature in database
GPG Key ID: BFD17A2D71B3B5E7
4 changed files with 104 additions and 24 deletions

View File

@ -2,19 +2,40 @@
from tron.map import Map
from tron.game import Game, PositionPlayer
from tron.player import Player, Direction, ConstantPlayer, KeyboardPlayer
from tron.player import Direction, ConstantPlayer
# This script shows how to create a game with AI, that will run automatically.
# It is made to be fast and not to be used by humans. It especially doesn't
# display and window and doesn't listen to any keystrokes.
def main():
# Prepare the size for the game.
# Those values may be good if you want to play, they might not be so good
# to train your AI. Decreasing them will make the learning faster.
width = 40
height = 40
# Create a game from its size and its players
game = Game(width, height, [
PositionPlayer(1, KeyboardPlayer(Direction.RIGHT), [0, 0]),
# Here we create two players with constant direction.
# It's not very interesting but it's the basis of everything else.
PositionPlayer(1, ConstantPlayer(Direction.RIGHT), [0, 0]),
PositionPlayer(2, ConstantPlayer(Direction.LEFT), [width - 1, height - 1]),
])
# Run the game.
# Since no window is passed as parameter, not only the game will not
# display anything, which avoid doing useless computations, but it will
# also not be limited to a certain framerate, which would be necessary for
# human users.
game.main_loop()
# The game is done, you can get information about it and do what you want.
if game.winner is None:
print("It's a draw!")
else:
print('Player {} wins!'.format(game.winner))
if __name__ == '__main__':
main()

27
play.py
View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3
# Import pygame without printing anything on the terminal
import contextlib
with contextlib.redirect_stdout(None):
import pygame
@ -7,23 +8,43 @@ with contextlib.redirect_stdout(None):
from tron.map import Map
from tron.game import Game, PositionPlayer
from tron.window import Window
from tron.player import Player, Direction, ConstantPlayer, KeyboardPlayer
from tron.player import Direction, KeyboardPlayer, Mode
# This script shows how to create a game with human players and play it interactively.
# It shows how to create the game, to setup interactive controls for users, and
# to run the game while rendering it on a window with a reasonnable framerate.
def main():
# Initialize the game engine
pygame.init()
# Prepare the size for the game.
# Those values may be good if you want to play, they might not be so good
# to train your AI. Decreasing them will make the learning faster.
width = 40
height = 40
# Create a game from its size and its players
game = Game(width, height, [
PositionPlayer(1, KeyboardPlayer(Direction.RIGHT), [0, 0]),
PositionPlayer(2, ConstantPlayer(Direction.LEFT), [width - 1, height - 1]),
# We create two PositionPlayer for each player of the game.
# The first one has the id 1, and will use keyboard interaction, with a
# default direction that will be to the right, and that will use the Z,
# Q, S and D keys.
# The last array defines the initial position of the player.
PositionPlayer(1, KeyboardPlayer(Direction.RIGHT, Mode.ZQSD), [0, 0]),
# We create a second player that will use the arrow keys.
PositionPlayer(2, KeyboardPlayer(Direction.LEFT, Mode.ARROWS), [width - 1, height - 1]),
])
# Create a window for the game so the players can see what they're doing.
window = Window(game, 10)
# Run the game.
game.main_loop(window)
# Once the game is finished, if game.winner is None, it means it's a draw
# Otherwise, game.winner will tell us which player has won the game.
if game.winner is None:
print("It's a draw!")
else:

View File

@ -11,7 +11,7 @@ class Winner(Enum):
PLAYER_ONE = 1
PLAYER_TWO = 2
class Case(Enum):
class Tile(Enum):
"""
The different type of elements that can be in a map.
"""
@ -26,17 +26,17 @@ class Case(Enum):
"""
Converts an element of a map to a nice color.
"""
if self == Case.EMPTY:
if self == Tile.EMPTY:
return (255, 255, 255)
elif self == Case.WALL:
elif self == Tile.WALL:
return (0, 0, 0)
elif self == Case.PLAYER_ONE_BODY:
elif self == Tile.PLAYER_ONE_BODY:
return (128, 0, 0)
elif self == Case.PLAYER_ONE_HEAD:
elif self == Tile.PLAYER_ONE_HEAD:
return (255, 0, 0)
elif self == Case.PLAYER_TWO_BODY:
elif self == Tile.PLAYER_TWO_BODY:
return (0, 128, 0)
elif self == Case.PLAYER_TWO_HEAD:
elif self == Tile.PLAYER_TWO_HEAD:
return (0, 255, 0)
else:
return None
@ -57,18 +57,18 @@ class PositionPlayer:
Returns the body type of the PP depending on its id.
"""
if self.id == 1:
return Case.PLAYER_ONE_BODY
return Tile.PLAYER_ONE_BODY
elif self.id == 2:
return Case.PLAYER_TWO_BODY
return Tile.PLAYER_TWO_BODY
def head(self):
"""
Returns the head type of the PP depending of its id.
"""
if self.id == 1:
return Case.PLAYER_ONE_HEAD
return Tile.PLAYER_ONE_HEAD
elif self.id == 2:
return Case.PLAYER_TWO_HEAD
return Tile.PLAYER_TWO_HEAD
class HistoryElement:
"""
@ -98,7 +98,7 @@ class Game:
"""
self.width = width
self.height = height
mmap = Map(width, height, Case.EMPTY, Case.WALL)
mmap = Map(width, height, Tile.EMPTY, Tile.WALL)
self.history = [HistoryElement(mmap, None, None)]
self.pps = pps
self.winner = None
@ -153,7 +153,7 @@ class Game:
pp.alive = False
# Check collision
elif self.map()[pp.position[0], pp.position[1]] is not Case.EMPTY:
elif self.map()[pp.position[0], pp.position[1]] is not Tile.EMPTY:
pp.alive = False
else:

View File

@ -52,18 +52,56 @@ class Player:
"""
pass
class Mode(Enum):
"""
The different type of interaction for the keyboard controls.
This will allow to play with two humans.
"""
ARROWS = 1
ZQSD = 2
class KeyboardPlayer(Player):
""""
This is the key board interaction.
It uses Z, Q, S and D keys to move the tron.
It uses keys depending on the mode.
"""
def __init__(self, initial_direction):
def __init__(self, initial_direction, mode = Mode.ARROWS):
"""
Creates a keyboard decision with a default direction.
"""
super(KeyboardPlayer, self).__init__()
self.direction = initial_direction
self.mode = mode
def left(self):
"""
Returns the left key of the player depending on the mode.
"""
import pygame
return pygame.K_q if self.mode == Mode.ZQSD else pygame.K_LEFT
def right(self):
"""
Returns the right key of the player depending on the mode.
"""
import pygame
return pygame.K_d if self.mode == Mode.ZQSD else pygame.K_RIGHT
def down(self):
"""
Returns the down key of the player depending on the mode.
"""
import pygame
return pygame.K_s if self.mode == Mode.ZQSD else pygame.K_DOWN
def up(self):
"""
Returns the up key of the player depending on the mode.
"""
import pygame
return pygame.K_z if self.mode == Mode.ZQSD else pygame.K_UP
def manage_event(self, event):
"""
@ -71,13 +109,13 @@ class KeyboardPlayer(Player):
"""
import pygame
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
if event.key == self.left():
self.direction = Direction.LEFT
if event.key == pygame.K_z:
if event.key == self.up():
self.direction = Direction.UP
if event.key == pygame.K_d:
if event.key == self.right():
self.direction = Direction.RIGHT
if event.key == pygame.K_s:
if event.key == self.down():
self.direction = Direction.DOWN
def action(self, game):