Players¶
The final goal of this project is to be able to create software that can play a specific game. This software is called player and must implement the IPlayer interface.
IPlayer¶
The interface can be found in src/IArena/interfaces/IPlayer module.
This interface is used by an arena to play a specific set of rules.
The only method that must be implemented is play.
It receives an IPosition and must return an IMovement (specific movement depending on the rules playing).
def play(
self,
position: IPosition) -> IMovement:
pass
The constructor of an IPlayer is not defined.
Each implementation could have its own constructor, adding for example a name, the rules of the game, etc.
Rules¶
The rules of each game are available from each IPosition of the game by calling position.get_rules().
Movements¶
Choose the next movement is responsibility of the player. Each game has different movements that require different parameters. Depending on the game, the player must create a movement with the required parameters.
However, in the rules of the game there is a method possible_movements that returns a list of possible movements.
The player can create its own movement or choose one from the list of possible movements.
from IArena.interfaces.IPlayer import IPlayer
from IArena.games.Hanoi import HanoiRules, HanoiMovement, HanoiPosition
class MyPlayer(IPlayer):
def play(
self,
position: HanoiPosition) -> HanoiMovement:
# Create next movement from scratch
movement = IMovement(...)
# Choose one from the list of possible movements
rules = position.get_rules()
possible_movements = rules.possible_movements(position)
movement = possible_movements[...]
# Return the movement
return movement
Arena¶
In order to play a game with an autonomous player, an arena is required. An Arena is a class that implements the loop of the game, or the context in which the game is played. For further information, see the Arena module.
The easiest arena to use is GenericGame that implements a single loop over the game and make each player play in its turn.
If you prefer to see step by step the game playing by the player, use BroadcastGame.
from IArena.arena.GenericGame import GenericGame # or BroadcastGame
from IArena.games.Hanoi import HanoiRules
rules = HanoiRules()
my_player = MyPlayer()
arena = GenericGame(
rules=rules,
players=[my_player]
)
score = arena.play()
Multiplayer games¶
In games with more than 1 player, you would need another player to play against. There are several generic players implemented, please check Random Player.
from IArena.arena.GenericGame import GenericGame # or BroadcastGame
from IArena.games.Coins import CoinsRules, CoinsMovement, CoinsPosition
from IArena.players.players import RandomPlayer
rules = CoinsRules()
my_player = MyPlayer()
other_player = RandomPlayer()
arena = GenericGame(
rules=rules,
players=[my_player, other_player]
)
score = arena.play()
You may want to repeat the game several times to get a better score. For this purpose just use a loop and accumulate the score.
from IArena.arena.GenericGame import GenericGame # or BroadcastGame
from IArena.games.Coins import CoinsRules, CoinsMovement, CoinsPosition
from IArena.players.players import RandomPlayer
rules = CoinsRules()
my_player = MyPlayer()
other_player = RandomPlayer()
score = 0
for _ in range(50):
arena = GenericGame(
rules=rules,
players=[my_player, other_player]
)
score += arena.play()
for _ in range(50):
arena = GenericGame(
rules=rules,
players=[other_player, my_player]
)
score += arena.play()
print(score)
Heuristic Player¶
Other way to create a player is to give a heuristic for a position, rather than a movement.
The already implement player HeuristicPlayer does check every possible future position,
by trying every possible movement in a position,
and calculates the score of the position by the method heuristic.
Then, it decides the movement with the lower heuristic.
from IArena.arena.GenericGame import GenericGame # or BroadcastGame
from IArena.games.Hanoi import HanoiRules, HanoiMovement, HanoiPosition
from IArena.players.HeuristicPlayer import HeuristicPlayer
class MyPlayer(HeuristicPlayer):
def heuristic(self, position: HanoiPosition) -> float:
# Add code to calculate the heuristic of the position
return 0.0
rules = HanoiRules()
my_player = MyPlayer()
arena = GenericGame(
rules=rules,
players=[my_player]
)
Note
Remember that the best movement is the one with the lowest heuristic.
One thing to take into account is that creating an heuristic for a multiplayer game, the heuristic must be calculated as the position given is the one that the opponent will play. Because the positions in which it applies are the next ones, and not the current ones.