# Path: betago/model.py
# class KerasBot(GoModel):
#     '''
#     KerasBot takes top_n predictions of a keras model and tries to apply the best move. If that move is illegal,
#     choose the next best, until the list is exhausted. If no more moves are left to play, continue with random
#     moves until a legal move is found.
#     '''
# 
#     def __init__(self, model, processor, top_n=10):
#         super(KerasBot, self).__init__(model=model, processor=processor)
#         self.top_n = top_n
# 
#     def apply_move(self, color, move):
#         # Apply human move
#         self.go_board.apply_move(color, move)
# 
#     def select_move(self, bot_color):
#         move = get_first_valid_move(self.go_board, bot_color,
#                                     self._move_generator(bot_color))
#         if move is not None:
#             self.go_board.apply_move(bot_color, move)
#         return move
# 
#     def _move_generator(self, bot_color):
#         return chain(
#             # First try the model.
#             self._model_moves(bot_color),
#             # If none of the model moves are valid, fill in a random
#             # dame point. This is probably not a very good move, but
#             # it's better than randomly filling in our own eyes.
#             fill_dame(self.go_board),
#             # Lastly just try any open space.
#             generate_in_random_order(all_empty_points(self.go_board)),
#         )
# 
#     def _model_moves(self, bot_color):
#         # Turn the board into a feature vector.
#         # The (0, 0) is for generating the label, which we ignore.
#         X, label = self.processor.feature_and_label(
#             bot_color, (0, 0), self.go_board, self.num_planes)
#         X = X.reshape((1, X.shape[0], X.shape[1], X.shape[2]))
# 
#         # Generate bot move.
#         pred = np.squeeze(self.model.predict(X))
#         top_n_pred_idx = pred.argsort()[-self.top_n:][::-1]
#         for idx in top_n_pred_idx:
#             prediction = int(idx)
#             pred_row = prediction // 19
#             pred_col = prediction % 19
#             pred_move = (pred_row, pred_col)
#             yield pred_move
# 
# Path: betago/processor.py
# class SevenPlaneProcessor(GoDataProcessor):
#     '''
#     Implementation of a Go data processor, using seven planes of 19x19 values to represent the position of
#     a go board, as explained below.
# 
#     This closely reflects the representation suggested in Clark, Storkey:
#     http://arxiv.org/abs/1412.3409
#     '''
# 
#     def __init__(self, data_directory='data', num_planes=7, consolidate=True, use_generator=False):
#         super(SevenPlaneProcessor, self).__init__(data_directory=data_directory,
#                                                   num_planes=num_planes,
#                                                   consolidate=consolidate,
#                                                   use_generator=use_generator)
# 
#     def feature_and_label(self, color, move, go_board, num_planes):
#         '''
#         Parameters
#         ----------
#         color: color of the next person to move
#         move: move they decided to make
#         go_board: represents the state of the board before they moved
# 
#         Planes we write:
#         0: our stones with 1 liberty
#         1: our stones with 2 liberty
#         2: our stones with 3 or more liberties
#         3: their stones with 1 liberty
#         4: their stones with 2 liberty
#         5: their stones with 3 or more liberties
#         6: simple ko
#         '''
#         row, col = move
#         enemy_color = go_board.other_color(color)
#         label = row * 19 + col
#         move_array = np.zeros((num_planes, go_board.board_size, go_board.board_size))
#         for row in range(0, go_board.board_size):
#             for col in range(0, go_board.board_size):
#                 pos = (row, col)
#                 if go_board.board.get(pos) == color:
#                     if go_board.go_strings[pos].liberties.size() == 1:
#                         move_array[0, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() == 2:
#                         move_array[1, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() >= 3:
#                         move_array[2, row, col] = 1
#                 if go_board.board.get(pos) == enemy_color:
#                     if go_board.go_strings[pos].liberties.size() == 1:
#                         move_array[3, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() == 2:
#                         move_array[4, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() >= 3:
#                         move_array[5, row, col] = 1
#                 if go_board.is_simple_ko(color, pos):
#                     move_array[6, row, col] = 1
#         return move_array, label
# 
# Path: betago/gtp/board.py
# def gtp_position_to_coords(gtp_position):
#     """Convert a GTP board location to a (row, col) tuple.
# 
#     Example:
#     >>> gtp_position_to_coords('A1')
#     (0, 0)
#     """
#     col_str, row_str = gtp_position[0], gtp_position[1:]
#     return (int(row_str) - 1, COLS.find(col_str))
# 
# def coords_to_gtp_position(coords):
#     """Convert (row, col) tuple to GTP board locations.
# 
#     Example:
#     >>> coords_to_gtp_position((0, 0))
#     'A1'
#     """
#     row, col = coords
#     # coords are zero-indexed, GTP is 1-indexed.
#     return COLS[col] + str(row + 1)


import yaml
import subprocess
import re
import argparse
from keras.models import model_from_yaml
from betago.model import KerasBot
from betago.processor import SevenPlaneProcessor
from betago.gtp.board import gtp_position_to_coords, coords_to_gtp_position
from __future__ import print_function


argparser = argparse.ArgumentParser()
argparser.add_argument('handicap', type=int, nargs=1)
argparser.add_argument('output_sgf', nargs='?', default='output.sgf')
args = argparser.parse_args()


# Path: betago/model.py
# class KerasBot(GoModel):
#     '''
#     KerasBot takes top_n predictions of a keras model and tries to apply the best move. If that move is illegal,
#     choose the next best, until the list is exhausted. If no more moves are left to play, continue with random
#     moves until a legal move is found.
#     '''
# 
#     def __init__(self, model, processor, top_n=10):
#         super(KerasBot, self).__init__(model=model, processor=processor)
#         self.top_n = top_n
# 
#     def apply_move(self, color, move):
#         # Apply human move
#         self.go_board.apply_move(color, move)
# 
#     def select_move(self, bot_color):
#         move = get_first_valid_move(self.go_board, bot_color,
#                                     self._move_generator(bot_color))
#         if move is not None:
#             self.go_board.apply_move(bot_color, move)
#         return move
# 
#     def _move_generator(self, bot_color):
#         return chain(
#             # First try the model.
#             self._model_moves(bot_color),
#             # If none of the model moves are valid, fill in a random
#             # dame point. This is probably not a very good move, but
#             # it's better than randomly filling in our own eyes.
#             fill_dame(self.go_board),
#             # Lastly just try any open space.
#             generate_in_random_order(all_empty_points(self.go_board)),
#         )
# 
#     def _model_moves(self, bot_color):
#         # Turn the board into a feature vector.
#         # The (0, 0) is for generating the label, which we ignore.
#         X, label = self.processor.feature_and_label(
#             bot_color, (0, 0), self.go_board, self.num_planes)
#         X = X.reshape((1, X.shape[0], X.shape[1], X.shape[2]))
# 
#         # Generate bot move.
#         pred = np.squeeze(self.model.predict(X))
#         top_n_pred_idx = pred.argsort()[-self.top_n:][::-1]
#         for idx in top_n_pred_idx:
#             prediction = int(idx)
#             pred_row = prediction // 19
#             pred_col = prediction % 19
#             pred_move = (pred_row, pred_col)
#             yield pred_move
# 
# Path: betago/processor.py
# class SevenPlaneProcessor(GoDataProcessor):
#     '''
#     Implementation of a Go data processor, using seven planes of 19x19 values to represent the position of
#     a go board, as explained below.
# 
#     This closely reflects the representation suggested in Clark, Storkey:
#     http://arxiv.org/abs/1412.3409
#     '''
# 
#     def __init__(self, data_directory='data', num_planes=7, consolidate=True, use_generator=False):
#         super(SevenPlaneProcessor, self).__init__(data_directory=data_directory,
#                                                   num_planes=num_planes,
#                                                   consolidate=consolidate,
#                                                   use_generator=use_generator)
# 
#     def feature_and_label(self, color, move, go_board, num_planes):
#         '''
#         Parameters
#         ----------
#         color: color of the next person to move
#         move: move they decided to make
#         go_board: represents the state of the board before they moved
# 
#         Planes we write:
#         0: our stones with 1 liberty
#         1: our stones with 2 liberty
#         2: our stones with 3 or more liberties
#         3: their stones with 1 liberty
#         4: their stones with 2 liberty
#         5: their stones with 3 or more liberties
#         6: simple ko
#         '''
#         row, col = move
#         enemy_color = go_board.other_color(color)
#         label = row * 19 + col
#         move_array = np.zeros((num_planes, go_board.board_size, go_board.board_size))
#         for row in range(0, go_board.board_size):
#             for col in range(0, go_board.board_size):
#                 pos = (row, col)
#                 if go_board.board.get(pos) == color:
#                     if go_board.go_strings[pos].liberties.size() == 1:
#                         move_array[0, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() == 2:
#                         move_array[1, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() >= 3:
#                         move_array[2, row, col] = 1
#                 if go_board.board.get(pos) == enemy_color:
#                     if go_board.go_strings[pos].liberties.size() == 1:
#                         move_array[3, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() == 2:
#                         move_array[4, row, col] = 1
#                     elif go_board.go_strings[pos].liberties.size() >= 3:
#                         move_array[5, row, col] = 1
#                 if go_board.is_simple_ko(color, pos):
#                     move_array[6, row, col] = 1
#         return move_array, label
# 
# Path: betago/gtp/board.py
# def gtp_position_to_coords(gtp_position):
#     """Convert a GTP board location to a (row, col) tuple.
# 
#     Example:
#     >>> gtp_position_to_coords('A1')
#     (0, 0)
#     """
#     col_str, row_str = gtp_position[0], gtp_position[1:]
#     return (int(row_str) - 1, COLS.find(col_str))
# 
# def coords_to_gtp_position(coords):
#     """Convert (row, col) tuple to GTP board locations.
# 
#     Example:
#     >>> coords_to_gtp_position((0, 0))
#     'A1'
#     """
#     row, col = coords
#     # coords are zero-indexed, GTP is 1-indexed.
#     return COLS[col] + str(row + 1)


# Path: examples/play_gnugo.py
import yaml
import subprocess
import re
import argparse
from keras.models import model_from_yaml
from betago.model import KerasBot
from betago.processor import SevenPlaneProcessor
from betago.gtp.board import gtp_position_to_coords, coords_to_gtp_position

from __future__ import print_function


argparser = argparse.ArgumentParser()
argparser.add_argument('handicap', type=int, nargs=1)
argparser.add_argument('output_sgf', nargs='?', default='output.sgf')
args = argparser.parse_args()


processor = SevenPlaneProcessor()