diff --git a/AlphaGo/engine.py b/AlphaGo/engine.py index fef194f..fa8ce0d 100644 --- a/AlphaGo/engine.py +++ b/AlphaGo/engine.py @@ -138,6 +138,7 @@ class GTPEngine(): return self.known_commands, True def cmd_quit(self, args, **kwargs): + self.disconnect = True return None, True def cmd_boardsize(self, args, **kwargs): @@ -180,3 +181,8 @@ class GTPEngine(): return self._vertex_point2string(move), True else: return 'unknown player', False + + +if __name__ == "main": + game = Game() + engine = GTPEngine(game_obj=Game) diff --git a/AlphaGo/go.py b/AlphaGo/go.py index 1ef3e7f..b83d305 100644 --- a/AlphaGo/go.py +++ b/AlphaGo/go.py @@ -15,13 +15,17 @@ import numpy as np # This means that swapping colors is as simple as multiplying array by -1. WHITE, EMPTY, BLACK, FILL, KO, UNKNOWN = range(-1, 5) + class PlayerMove(namedtuple('PlayerMove', ['color', 'move'])): pass + # Represents "group not found" in the LibertyTracker object MISSING_GROUP_ID = -1 + class IllegalMove(Exception): pass + # these are initialized by set_board_size N = None ALL_COORDS = [] @@ -29,6 +33,7 @@ EMPTY_BOARD = None NEIGHBORS = {} DIAGONALS = {} + def set_board_size(n): ''' Hopefully nobody tries to run both 9x9 and 19x19 game instances at once. @@ -39,17 +44,23 @@ def set_board_size(n): N = n ALL_COORDS = [(i, j) for i in range(n) for j in range(n)] EMPTY_BOARD = np.zeros([n, n], dtype=np.int8) + def check_bounds(c): return c[0] % n == c[0] and c[1] % n == c[1] - NEIGHBORS = {(x, y): list(filter(check_bounds, [(x+1, y), (x-1, y), (x, y+1), (x, y-1)])) for x, y in ALL_COORDS} - DIAGONALS = {(x, y): list(filter(check_bounds, [(x+1, y+1), (x+1, y-1), (x-1, y+1), (x-1, y-1)])) for x, y in ALL_COORDS} + NEIGHBORS = {(x, y): list(filter(check_bounds, [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)])) for x, y in + ALL_COORDS} + DIAGONALS = {(x, y): list(filter(check_bounds, [(x + 1, y + 1), (x + 1, y - 1), (x - 1, y + 1), (x - 1, y - 1)])) + for x, y in ALL_COORDS} + def place_stones(board, color, stones): for s in stones: board[s] = color + def find_reached(board, c): + # that can reach from one place color = board[c] chain = set([c]) reached = set() @@ -58,12 +69,13 @@ def find_reached(board, c): current = frontier.pop() chain.add(current) for n in NEIGHBORS[current]: - if board[n] == color and not n in chain: + if board[n] == color and (not n in chain): frontier.append(n) elif board[n] != color: reached.add(n) return chain, reached + def is_koish(board, c): 'Check if c is surrounded on all sides by 1 color, and return that color' if board[c] != EMPTY: return None @@ -73,6 +85,7 @@ def is_koish(board, c): else: return None + def is_eyeish(board, c): 'Check if c is an eye, for the purpose of restricting MC rollouts.' color = is_koish(board, c) @@ -90,17 +103,19 @@ def is_eyeish(board, c): else: return color + class Group(namedtuple('Group', ['id', 'stones', 'liberties', 'color'])): ''' stones: a set of Coordinates belonging to this group liberties: a set of Coordinates that are empty and adjacent to this group. color: color of this group ''' + def __eq__(self, other): return self.stones == other.stones and self.liberties == other.liberties and self.color == other.color -class LibertyTracker(): +class LibertyTracker(object): @staticmethod def from_board(board): board = np.copy(board) @@ -233,8 +248,10 @@ class LibertyTracker(): if group_id != MISSING_GROUP_ID: self._update_liberties(group_id, add={s}) + class Position(): - def __init__(self, board=None, n=0, komi=7.5, caps=(0, 0), lib_tracker=None, ko=None, recent=tuple(), to_play=BLACK): + def __init__(self, board=None, n=0, komi=7.5, caps=(0, 0), lib_tracker=None, ko=None, recent=tuple(), + to_play=BLACK): ''' board: a numpy array n: an int representing moves played so far @@ -276,7 +293,7 @@ class Position(): row = [] for j in range(N): appended = '<' if (self.recent and (i, j) == self.recent[-1].move) else ' ' - row.append(pretty_print_map[board[i,j]] + appended) + row.append(pretty_print_map[board[i, j]] + appended) row.append('\x1b[0m') raw_board_contents.append(''.join(row)) @@ -393,7 +410,7 @@ class Position(): elif O_border and not X_border: territory_color = WHITE else: - territory_color = UNKNOWN # dame, or seki + territory_color = UNKNOWN # dame, or seki place_stones(working_board, territory_color, territory) return np.count_nonzero(working_board == BLACK) - np.count_nonzero(working_board == WHITE) - self.komi @@ -407,4 +424,5 @@ class Position(): else: return 'DRAW' -set_board_size(19) \ No newline at end of file + +set_board_size(19) diff --git a/AlphaGo/self-play.py b/AlphaGo/self-play.py index 4609004..2336e72 100644 --- a/AlphaGo/self-play.py +++ b/AlphaGo/self-play.py @@ -3,7 +3,7 @@ from engine import GTPEngine import re g = Game() - +pattern = "[A-Z]{1}[0-9]{1}" g.show_board() e = GTPEngine(game_obj=g) @@ -15,7 +15,12 @@ while not (black_pass and white_pass): if num % 2 == 0: res = e.run_cmd(str(num) + " genmove BLACK") num += 1 - print(res) + # print(res) + match = re.search(pattern, res) + if match is not None: + print(match.group()) + else: + print("pass") if re.search("pass", res) is not None: black_pass = True else: @@ -23,7 +28,11 @@ while not (black_pass and white_pass): else: res = e.run_cmd(str(num) + " genmove WHITE") num += 1 - print(res) + match = re.search(pattern, res) + if match is not None: + print(match.group()) + else: + print("pass") if re.search("pass", res) is not None: white_pass = True else: diff --git a/AlphaGo/test.py b/AlphaGo/test.py index ceebd83..a95138e 100644 --- a/AlphaGo/test.py +++ b/AlphaGo/test.py @@ -1,11 +1,14 @@ +import sys from game import Game from engine import GTPEngine import utils +game = Game() +engine = GTPEngine(game_obj=game, name='tianshou') +cmd = raw_input - -g = Game() -e = GTPEngine(game_obj = g) - -res = e.run_cmd('8 genmove BLACK') -print(res) +while not engine.disconnect: + command = cmd() + result = engine.run_cmd(command) + sys.stdout.write(result) + sys.stdout.flush()