Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some Changes #13

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 4 additions & 25 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,16 @@
Ultimate TicTacToe - Python Player & Game Engine
================================================

|Travis| |PyPI| |Coverage|

This repo contains a sample player and game engine for our `Ultimate Tic-Tac-Toe workshop_`.

Welcome!
========

Welcome! You're probably here because you're in a hackathon we're running.

If so, make sure you've read our `Documentation`_.

Once you're ready to write your player, you can find functions that will help you write your player in `API Reference`_

Contributors
============

If you're interested in contributing a player or even features to the game engine:
If so, make sure you've read our [docs](https://github.com/joffat/docs) .

1. **Thank you**!
2. Please read the `Contribution Guide`_

.. Images and Links

.. |Travis| image:: https://travis-ci.org/socialgorithm/ultimate-ttt-py.svg?branch=master
:target: https://travis-ci.org/socialgorithm/ultimate-ttt-py
.. |PyPI| image:: https://badge.fury.io/py/ultimate_ttt.svg
:target: https://badge.fury.io/py/ultimate_ttt
.. |Coverage| image:: https://coveralls.io/repos/github/socialgorithm/ultimate-ttt-py/badge.svg?branch=master
:target: https://coveralls.io/github/socialgorithm/ultimate-ttt-py?branch=master
Run!
========

.. _Ultimate Tic-Tac-Toe workshop: https://socialgorithm.org/workshops/
.. _Documentation: https://socialgorithm.org/docs
.. _API Reference: https://ultimate-ttt-py.readthedocs.io/en/latest/
.. _Contribution Guide: https://github.com/socialgorithm/ultimate-ttt-py/blob/master/CONTRIBUTING.rst
From the folder run `uabc --host {server host} --token {your token} -f "node run_player.js"`
18 changes: 17 additions & 1 deletion players/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,23 @@ def __init__(self):
self.main_board = MainBoard(self.board_size)

@abstractmethod
def get_my_move(self):
def onMove(self):
pass

@abstractmethod
def onOpponent(self, board, move):
pass

@abstractmethod
def gameOver(self, result, board, move):
pass

@abstractmethod
def matchOver(self, result):
pass

@abstractmethod
def timeout(self):
pass

@property
Expand Down
83 changes: 79 additions & 4 deletions players/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,89 @@


class Random(StdOutPlayer):
#
# New Game Has Been Started.
# Do Whatever You Need To Do For The Player To Be Ready To Play
#
def __init__(self):
super().__init__()

def get_my_move(self): # -> Tuple[MainBoardCoords, SubBoardCoords]
main_board_coords = self.pick_next_main_board_coords()
sub_board = self.main_board.get_sub_board(main_board_coords)
#
# You are the First To Move
# Place Whereever You Want
# You Get To Pick The Board
#
# Returns Tuple[MainBoardCoords, SubBoardCoords] Position coordinates {board: [row, col], cell: [row, col]}
#
def onMove(self):
board = self.pick_next_main_board_coords()
sub_board = self.main_board.get_sub_board(board)
move = self.pick_random_sub_board_coords(sub_board)
return board, move

#
# Opponent Has Moved.
# You Have Opponents Board
# You Have Opponents Move
#
# You Must Respond With Board Matching Opponents Move
# Unless That Board Is Complete
#
# Returns Tuple[MainBoardCoords, SubBoardCoords] Position coordinates {board: [row, col], cell: [row, col]}
#
def onOpponent(self, board, move):
sub_board = self.main_board.get_sub_board(move)
if sub_board.is_finished == True:
return self.onMove()
sub_board_coords = self.pick_random_sub_board_coords(sub_board)
return main_board_coords, sub_board_coords
return move, sub_board_coords

#
# Game Is Over.
# You May Wish To Change Stratagy For The New Game.
# Your Opponent Has Not Changed.
#
# result Either 'win' | 'lose' | 'tie'
# board Last Opponent Board identifier [row, col]
# move Last Opponent Cell identifier [row, col]
#
def gameOver(self, result, board, move):
if result == "win":
# DO SOMETHING FOR WIN
pass
elif result == "lose":
# DO SOMETHING FOR LOST
pass
elif result == "tie":
# DO SOMETHING FOR TIE
pass
return

#
# Match Is Over.
# You Will Soon Have A New Opponent.
#
# result Either 'win' | 'lose' | 'tie'
#
def matchOver(self, result):
if result == "win":
# DO SOMETHING FOR WIN
pass
elif result == "lose":
# DO SOMETHING FOR LOST
pass
elif result == "tie":
# DO SOMETHING FOR TIE
pass
return

#
# Game Lost.
# You Have Timed Out.
#
def timeout(self):
# DO SOMETHING FOR TIMEOUT
return

def pick_next_main_board_coords(self) -> MainBoardCoords:
if self.main_board.sub_board_next_player_must_play is None:
Expand Down
92 changes: 74 additions & 18 deletions players/stdout.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,95 @@ def __init__(self):
super().__init__()

@abstractmethod
def get_my_move(self):
def onMove(self):
pass

@abstractmethod
def onOpponent(self, board, move):
pass

@abstractmethod
def gameOver(self, result, board, move):
pass

@abstractmethod
def matchOver(self, result):
pass

@abstractmethod
def timeout(self):
pass

def process_input(self, input_line: str) -> None:
if input_line == "init":
self.__init__()
elif input_line == "move":
self.get_and_publish_player_move()
elif input_line.startswith("opponent"):
self.react_to_opponent_move(input_line)

def get_and_publish_player_move(self) -> None:
main_board_coords, sub_board_coords = self.get_my_move()
try:
if input_line == "init":
self.__init__()
elif input_line == "move":
self.react_to_move()
elif input_line.startswith("opponent"):
self.react_to_opponent_move(input_line)
elif input_line.startswith("game"):
self.react_to_game_over(input_line)
elif input_line.startswith("match"):
self.react_to_match_over(input_line)
elif input_line == "timeout":
self.react_to_timeout(input_line)
except:
print("ERROR: Failed To Process Message. May Forfit Game, But Should Reinitilize On New Game.")

def react_to_move(self) -> None:
main_board_coords, sub_board_coords = self.onMove()
self.add_my_move(main_board_coords, sub_board_coords)
self.write_move(main_board_coords, sub_board_coords)

def react_to_opponent_move(self, input_line: str):
main_board_coords, sub_board_coords = self.read_move_opponent(input_line)
self.add_opponent_move(main_board_coords, sub_board_coords)
my_main_board_coords, my_sub_board_coords = self.onOpponent(main_board_coords, sub_board_coords)
self.add_my_move(my_main_board_coords, my_sub_board_coords)
self.write_move(my_main_board_coords, my_sub_board_coords)

def react_to_game_over(self, input_line: str):
result, main_board_coords, sub_board_coords = self.read_result_move_game(input_line)
if main_board_coords is not None and sub_board_coords is not None:
self.add_opponent_move(main_board_coords, sub_board_coords)
self.gameOver(result, main_board_coords, sub_board_coords)

def react_to_match_over(self, input_line: str):
result = self.read_result_match(input_line)
self.matchOver(result)

def react_to_timeout(self, input_line: str):
self.timeout()

@staticmethod
def write_move(main_board_coords: MainBoardCoords, sub_board_coords: SubBoardCoords):
move_str = "send:%d,%d;%d,%d" % (
main_board_coords.row, main_board_coords.col, sub_board_coords.row, sub_board_coords.col)
print(move_str)
sys.stdout.flush()

def react_to_opponent_move(self, input_line: str):
main_board_coords, sub_board_coords = self.read_move(input_line)
self.add_opponent_move(main_board_coords, sub_board_coords)
if not self.is_game_finished:
self.get_and_publish_player_move()

@staticmethod
def read_move(input_line: str):
received_move = input_line.split(" ")[1]
def parse_move(received_move: str):
main_board_coords_str, opponent_move_str = received_move.split(";")
main_board_coords = MainBoardCoords(*map(int, main_board_coords_str.split(",")))
sub_board_coords = SubBoardCoords(*map(int, opponent_move_str.split(",")))
return main_board_coords, sub_board_coords

@staticmethod
def read_move_opponent(input_line: str):
received_move = input_line.split(" ")[1]
return StdOutPlayer.parse_move(received_move)

@staticmethod
def read_result_move_game(input_line: str):
message_split = input_line.split(" ")
if len(message_split) == 3:
received_move = message_split[2]
main_board_coords, sub_board_coords = StdOutPlayer.parse_move(received_move)
return message_split[1], main_board_coords, sub_board_coords
return message_split[1], None, None

@staticmethod
def read_result_match(input_line: str):
return input_line.split(" ")[1]