from __future__ import print_function
import sys
sys.path.append('..')
from Game import Game
from TicTacToeLogic import Board
import numpy as np

"""
Game class implementation for the game of TicTacToe.
Based on the OthelloGame then getGameEnded() was adapted to new rules.

Author: <NAME>, github.com/evg-tyurin
Date: Jan 5, 2018.

Based on the OthelloGame by <NAME>.
"""



class TicTacToeGame(Game):


    INT2STR_MAP = {0: ' ', 1: 'x', -1: 'o'}
    
    def __init__(self, n=Board.SIZE):
        self.n = n

    def getInitBoard(self):
        # return initial board (numpy board)
        b = Board(self.n)
        # print('initial:',np.array(b.pieces))
        return b

    def getBoardSize(self):
        # (a,b) tuple
        return (self.n, self.n)

    def getActionSize(self):
        # return number of actions
        return self.n*self.n + 1

    def getNextState(self, board, player, action):
        # if player takes action on board, return next (board,player)
        # action must be a valid move
        if action == self.n*self.n:
            return (board, -player)
        b = Board(self.n)
        b.pieces = np.copy(board.pieces)
        b.mask_pieces = board.mask_pieces
        move = (int(action/self.n), action%self.n)
        b.execute_move(move, 1)
        return (b, -player)

    def getValidMoves(self, board, player):
        # return a fixed size binary vector
        valids = [0]*self.getActionSize()
        b = Board(self.n)
        b.pieces = np.copy(board.pieces)
        b.mask_pieces = board.mask_pieces
        legalMoves =  b.get_legal_moves()
        #print ('legal moves',legalMoves)
        if len(legalMoves)==0:
            print ('non - legal moves',legalMoves)
            valids[-1]=1
            #print(valids[-1])
            return np.array(valids)
        for x, y in legalMoves:
            valids[self.n*x+y]=1
        return np.array(valids)

    def getGameEnded(self, board, player):
        # return 0 if not ended, 1 if player 1 won, -1 if player 1 lost
        # player = 1
        b = Board(self.n)
        b.pieces = np.copy(board.pieces)
        b.mask_pieces = board.mask_pieces
        if b.is_win(player):
            #print('fdasfad')
            return 1
        # if b.is_win(-player):
        #     return -1
        if b.has_legal_moves():
            return 0
        # draw has a very little value 
        return 1e-4

    def getCanonicalForm(self, board, player):
        # return state if player==1, else return -state if player==-1
        #print(type(board))     
        return board

    def getSymmetries(self, board, pi):
        # mirror, rotational
        assert(len(pi) == self.n**2+1)  # 1 for pass
        pi_board = np.reshape(pi[:-1], (self.n, self.n))
        l = []

        for i in range(1, 5):
            for j in [True, False]:
                newB = np.rot90(board, i)
                newPi = np.rot90(pi_board, i)
                if j:
                    newB = np.fliplr(newB)
                    newPi = np.fliplr(newPi)
                l += [(newB, list(newPi.ravel()) + [pi[-1]])]
        return l

    def stringRepresentation(self, board):
        # 8x8 numpy array (canonical board)
        return board.pieces.tostring()

def display(board):
    #print('this is board', board)
    #print(type(board))
    if Board.SIZE == 3:
        print(
            '\n'
            '\t    0   1   2\n'
            '\t 0  {0} | {1} | {2}\n'
            '\t   ---+---+---\n'
            '\t 1  {3} | {4} | {5}\n'
            '\t   ---+---+---\n'
            '\t 2  {6} | {7} | {8}\n\n'.format(
                *[TicTacToeGame.INT2STR_MAP[x] for x in board.pieces.ravel()]))
    elif Board.SIZE ==4:
        print(
            '\n'
            '\t    0   1   2   3\n'
            '\t 0  {0} | {1} | {2} | {3}\n'
            '\t   ---+---+---+---\n'
            '\t 1  {4} | {5} | {6} | {7}\n'
            '\t   ---+---+---+---\n'
            '\t 2  {8} | {9} | {10} | {11}\n'
            '\t   ---+---+---+---\n'
            '\t 3  {12} | {13} | {14} | {15}\n\n'.format(
                *[TicTacToeGame.INT2STR_MAP[x] for x in board.pieces.ravel()]))
    elif Board.SIZE ==5:
        print(
            '\n'
            '\t    0   1   2   3   4\n'
            '\t 0  {0} | {1} | {2} | {3} | {4}\n'
            '\t   ---+---+---+---+---\n'
            '\t 1  {5} | {6} | {7} | {8} | {9}\n'
            '\t   ---+---+---+---+---\n'
            '\t 2  {10} | {11} | {12} | {13} | {14}\n'
            '\t   ---+---+---+---+---\n'
            '\t 3  {15} | {16} | {17} | {18} | {19}\n'
            '\t   ---+---+---+---+---\n'
            '\t 3  {20} | {21} | {22} | {23} | {24}\n\n'.format(
                *[TicTacToeGame.INT2STR_MAP[x] for x in board.pieces.ravel()]))

    n = board.pieces.shape[0]    

    # print("   ", end="")
    # for y in range(n):
    #     print (y,"", end="")
    # print("")
    # print("  ", end="")
    # for _ in range(n):
    #     print ("-", end="-")
    # print("--")
    # for y in range(n):
    #     print(y, "|",end="")    # print the row #
    #     for x in range(n):
    #         piece = board[y][x]    # get the piece to print
    #         if piece == -1: print("X ",end="")
    #         elif piece == 1: print("O ",end="")
    #         else:
    #             if x==n:
    #                 print("-",end="")
    #             else:
    #                 print("- ",end="")
    #     print("|")

    # print("  ", end="")
    # for _ in range(n):
    #     print ("-", end="-")
    # print("--")

from __future__ import print_function
import sys
sys.path.append('..')
from Game import Game
from TicTacToeLogic import Board
import numpy as np

"""
Game class implementation for the game of TicTacToe.
Based on the OthelloGame then getGameEnded() was adapted to new rules.

Author: <NAME>, github.com/evg-tyurin
Date: Jan 5, 2018.

Based on the OthelloGame by <NAME>.
"""



class TicTacToeGame(Game):


    INT2STR_MAP = {0: ' ', 1: 'x', -1: 'o'}
    
    def __init__(self, n=Board.SIZE):
        self.n = n

    def getInitBoard(self):
        # return initial board (numpy board)
        b = Board(self.n)
        # print('initial:',np.array(b.pieces))
        return b

    def getBoardSize(self):
        # (a,b) tuple
        return (self.n, self.n)

    def getActionSize(self):
        # return number of actions
        return self.n*self.n + 1

    def getNextState(self, board, player, action):
        # if player takes action on board, return next (board,player)
        # action must be a valid move
        if action == self.n*self.n:
            return (board, -player)
        b = Board(self.n)
        b.pieces = np.copy(board.pieces)
        b.mask_pieces = board.mask_pieces
        move = (int(action/self.n), action%self.n)
        b.execute_move(move, 1)
        return (b, -player)

    def getValidMoves(self, board, player):
        # return a fixed size binary vector
        valids = [0]*self.getActionSize()
        b = Board(self.n)
        b.pieces = np.copy(board.pieces)
        b.mask_pieces = board.mask_pieces
        legalMoves =  b.get_legal_moves()
        #print ('legal moves',legalMoves)
        if len(legalMoves)==0:
            print ('non - legal moves',legalMoves)
            valids[-1]=1
            #print(valids[-1])
            return np.array(valids)
        for x, y in legalMoves:
            valids[self.n*x+y]=1
        return np.array(valids)

    def getGameEnded(self, board, player):
        # return 0 if not ended, 1 if player 1 won, -1 if player 1 lost
        # player = 1
        b = Board(self.n)
        b.pieces = np.copy(board.pieces)
        b.mask_pieces = board.mask_pieces
        if b.is_win(player):
            #print('fdasfad')
            return 1
        # if b.is_win(-player):
        #     return -1
        if b.has_legal_moves():
            return 0
        # draw has a very little value 
        return 1e-4

    def getCanonicalForm(self, board, player):
        # return state if player==1, else return -state if player==-1
        #print(type(board))     
        return board

    def getSymmetries(self, board, pi):
        # mirror, rotational
        assert(len(pi) == self.n**2+1)  # 1 for pass
        pi_board = np.reshape(pi[:-1], (self.n, self.n))
        l = []

        for i in range(1, 5):
            for j in [True, False]:
                newB = np.rot90(board, i)
                newPi = np.rot90(pi_board, i)
                if j:
                    newB = np.fliplr(newB)
                    newPi = np.fliplr(newPi)
                l += [(newB, list(newPi.ravel()) + [pi[-1]])]
        return l

    def stringRepresentation(self, board):
        # 8x8 numpy array (canonical board)
        return board.pieces.tostring()

def display(board):
    #print('this is board', board)
    #print(type(board))
    if Board.SIZE == 3:
        print(
            '\n'
            '\t    0   1   2\n'
            '\t 0  {0} | {1} | {2}\n'
            '\t   ---+---+---\n'
            '\t 1  {3} | {4} | {5}\n'
            '\t   ---+---+---\n'
            '\t 2  {6} | {7} | {8}\n\n'.format(
                *[TicTacToeGame.INT2STR_MAP[x] for x in board.pieces.ravel()]))
    elif Board.SIZE ==4:
        print(
            '\n'
            '\t    0   1   2   3\n'
            '\t 0  {0} | {1} | {2} | {3}\n'
            '\t   ---+---+---+---\n'
            '\t 1  {4} | {5} | {6} | {7}\n'
            '\t   ---+---+---+---\n'
            '\t 2  {8} | {9} | {10} | {11}\n'
            '\t   ---+---+---+---\n'
            '\t 3  {12} | {13} | {14} | {15}\n\n'.format(
                *[TicTacToeGame.INT2STR_MAP[x] for x in board.pieces.ravel()]))
    elif Board.SIZE ==5:
        print(
            '\n'
            '\t    0   1   2   3   4\n'
            '\t 0  {0} | {1} | {2} | {3} | {4}\n'
            '\t   ---+---+---+---+---\n'
            '\t 1  {5} | {6} | {7} | {8} | {9}\n'
            '\t   ---+---+---+---+---\n'
            '\t 2  {10} | {11} | {12} | {13} | {14}\n'
            '\t   ---+---+---+---+---\n'
            '\t 3  {15} | {16} | {17} | {18} | {19}\n'
            '\t   ---+---+---+---+---\n'
            '\t 3  {20} | {21} | {22} | {23} | {24}\n\n'.format(
                *[TicTacToeGame.INT2STR_MAP[x] for x in board.pieces.ravel()]))

    n = board.pieces.shape[0]    

    # print("   ", end="")
    # for y in range(n):
    #     print (y,"", end="")
    # print("")
    # print("  ", end="")
    # for _ in range(n):
    #     print ("-", end="-")
    # print("--")
    # for y in range(n):
    #     print(y, "|",end="")    # print the row #
    #     for x in range(n):
    #         piece = board[y][x]    # get the piece to print
    #         if piece == -1: print("X ",end="")
    #         elif piece == 1: print("O ",end="")
    #         else:
    #             if x==n:
    #                 print("-",end="")
    #             else:
    #                 print("- ",end="")
    #     print("|")

    # print("  ", end="")
    # for _ in range(n):
    #     print ("-", end="-")
    # print("--")

Game class implementation for the game of TicTacToe. Based on the OthelloGame then getGameEnded() was adapted to new rules.  Author: <NAME>, github.com/evg-tyurin Date: Jan 5, 2018.  Based on the OthelloGame by <NAME>. # return initial board (numpy board) # print('initial:',np.array(b.pieces)) # (a,b) tuple # return number of actions # if player takes action on board, return next (board,player) # action must be a valid move # return a fixed size binary vector #print ('legal moves',legalMoves) #print(valids[-1]) # return 0 if not ended, 1 if player 1 won, -1 if player 1 lost # player = 1 #print('fdasfad') # if b.is_win(-player): #     return -1 # draw has a very little value # return state if player==1, else return -state if player==-1 #print(type(board)) # mirror, rotational # 1 for pass # 8x8 numpy array (canonical board) #print('this is board', board) #print(type(board)) # print("   ", end="") # for y in range(n): #     print (y,"", end="") # print("") # print("  ", end="") # for _ in range(n): #     print ("-", end="-") # print("--") # for y in range(n): #     print(y, "|",end="")    # print the row # #     for x in range(n): #         piece = board[y][x]    # get the piece to print #         if piece == -1: print("X ",end="") #         elif piece == 1: print("O ",end="") #         else: #             if x==n: #                 print("-",end="") #             else: #                 print("- ",end="") #     print("|") # print("  ", end="") # for _ in range(n): #     print ("-", end="-") # print("--")