from easyAI import TwoPlayerGame


class Nim(TwoPlayerGame):
    """
    The game starts with 4 piles of 5 pieces. In turn the players
    remove as much pieces as they want, but from one pile only. The
    player that removes the last piece loses.

    Parameters
    ----------

    players
      List of the two players e.g. [HumanPlayer(), HumanPlayer()]

    piles:
      The piles the game starts with. With piles=[2,3,4,4] the
      game will start with 1 pile of 2 pieces, 1 pile of 3 pieces, and 2
      piles of 4 pieces.

    max_removals_per_turn
      Max number of pieces you can remove in a turn. Default is no limit.

    """

    def __init__(self, players=None, max_removals_per_turn=None, piles=(5, 5, 5, 5)):
        """ Default for `piles` is 5 piles of 5 pieces. """
        self.players = players
        self.piles = list(piles)
        self.max_removals_per_turn = max_removals_per_turn
        self.current_player = 1  # player 1 starts.

    def possible_moves(self):
        return [
            "%d,%d" % (i + 1, j)
            for i in range(len(self.piles))
            for j in range(
                1,
                self.piles[i] + 1
                if self.max_removals_per_turn is None
                else min(self.piles[i] + 1, self.max_removals_per_turn),
            )
        ]

    def make_move(self, move):
        move = list(map(int, move.split(",")))
        self.piles[move[0] - 1] -= move[1]

    def unmake_move(self, move):  # optional, speeds up the AI
        move = list(map(int, move.split(",")))
        self.piles[move[0] - 1] += move[1]

    def show(self):
        print(" ".join(map(str, self.piles)))

    def win(self):
        return max(self.piles) == 0

    def is_over(self):
        return self.win()

    def scoring(self):
        return 100 if self.win() else 0

    def ttentry(self):
        return tuple(self.piles)  # optional, speeds up AI


if __name__ == "__main__":
    # IN WHAT FOLLOWS WE SOLVE THE GAME AND START A MATCH AGAINST THE AI

    from easyAI import AI_Player, Human_Player, Negamax, solve_with_iterative_deepening
    from easyAI.AI import TranspositionTable

    # we first solve the game
    w, d, m, tt = solve_with_iterative_deepening(Nim(), range(5, 20), win_score=80)
    w, d, len(tt.d)
    # the previous line prints -1, 16 which shows that if the
    # computer plays second with an AI depth of 16 (or 15) it will
    # always win in 16 (total) moves or less.

    # Now let's play (and lose !) against the AI
    ai = Negamax(16, tt=TranspositionTable())
    game = Nim([Human_Player(), AI_Player(tt)])
    game.play()  # You will always lose this game !
    print("player %d wins" % game.current_player)

    # Note that with the transposition table tt generated by
    # solve_with_iterative_deepening
    # we can setup a perfect AI which doesn't have to think:
    # >>> game = Nim( [ Human_Player(), AI_Player( tt )])
    # >>> game.play() # You will always lose this game too!
