from MiniGame import *

class TicTacToeException(Exception):
	pass

class TicTacToe(MiniGame):
	def __init__(self):
		self.Reset()
	
	def Reset(self):
		self.board = [[0, 0, 0],[0, 0, 0],[0, 0, 0]]
		# a history of the entire game
		self.moves = []
	
	def Play(self, move):
		"""
		Make a move.
		"""
		player, position = move
		
		# if the game is over send notification, otherwise do the move
		if not self.Notify(self.GetStatus()):
			# see if the same player is trying to move twice
			if len(self.moves):
				oplayer, oposition = self.moves[-1]
				
				if player == oplayer:
					raise TicTacToeException, "Same player tried to play twice"
			
			# check if a particular move is legal
			if not self.LegalMove(move):
				raise TicTacToeException, "That move is not legal"
			else:
				# the move is legal
				
				# make sure the slot isn't filled yet
				self.board[position[0]][position[1]] = player
				
				# add this move to our list of moves
				self.moves += [move]
			
			# send notification if the game is now finished
			self.Notify(self.GetStatus())
	
	def GetMoves(self):
		return self.moves
	
	def GetStatus(self):
		"""
		See if either player has won.
		Return -1 if the game is a draw.
		Return 0 if the game is in progress.
		Return 1 if player 1 has won.
		Return 2 if player 2 has won.
		"""
		status = -1
		
		# make sure there are still slots to play
		if self.IsPlayable():
			status = None
		
		# test the horizontal lineups
		for r in range(3):
			if self.board[r][0] == self.board[r][1] == self.board[r][2] and self.board[r][0] != 0:
				status = self.board[r][0]
			if self.board[0][r] == self.board[1][r] == self.board[2][r] and self.board[0][r] != 0:
				status = self.board[0][r]
		
		# test diagonal lineups
		if self.board[0][0] == self.board[1][1] == self.board[2][2] and self.board[0][0] != 0:
			status = self.board[0][r]
		if self.board[0][2] == self.board[1][1] == self.board[2][0] and self.board[0][0] != 0:
			status = self.board[0][r]
		
		return status
	
	def GetBoard(self):
		"""
		Get the current layout of the board.
		"""
		return self.board
	
	def LegalMove(self, move):
		player, position = move
		return not len([p for p in position if p > 2 or p < 0]) and self.board[position[0]][position[1]] == 0
	
	def IsPlayable(self):
		for x in range(3):
			for y in range(3):
				if self.board[x][y] == 0:
					return True


