def __init__(self, go_bot, termination=None, handicap=0, opponent='gnugo', output_sgf="out.sgf", our_color='b'): self.bot = TerminationAgent(go_bot, termination) # <1> self.handicap = handicap self._stopped = False # <2> self.game_state = GameState.new_game(19) self.sgf = SGFWriter(output_sgf) # <3> self.our_color = Player.black if our_color == 'b' else Player.white self.their_color = self.our_color.other cmd = self.opponent_cmd(opponent) # <4> pipe = subprocess.PIPE # Depending on your OS, you may need to set bufsize=0 to prevent # readline() from blocking. # See: https://github.com/maxpumperla/deep_learning_and_the_game_of_go/issues/44 self.gtp_stream = subprocess.Popen( cmd, stdin=pipe, stdout=pipe, # <5> bufsize=0)
def __init__(self, go_bot, termination=None, handicap=0, opponent='gnugo', output_sgf='out.sgf', our_color='b'): self.bot = TerminationAgent(go_bot, termination) self.handicap = handicap self.game_state = GameState.new_game(19) self.sgf = SGFWriter(output_sgf) self.our_color = Player.black if our_color == 'b' else Player.white self.their_color = self.our_color.other cmd = self.opponent_cmd(opponent) pipe = subprocess.PIPE self.gtp_stream = subprocess.Popen(cmd, stdin=pipe, stdout=pipe, bufsize=1, universal_newlines=True) # state self._stopped = False
def __init__(self, go_bot, termination=None, handicap=0, opponent='gnugo', output_sgf="out.sgf", our_color='b'): self.bot = TerminationAgent(go_bot, termination) # <1> self.handicap = handicap self._stopped = False # <2> self.game_state = GameState.new_game(19) self.sgf = SGFWriter(output_sgf) # <3> self.our_color = Player.black if our_color == 'b' else Player.white self.their_color = self.our_color.other cmd = self.opponent_cmd(opponent) # <4> pipe = subprocess.PIPE self.gtp_stream = subprocess.Popen( cmd, stdin=pipe, stdout=pipe # <5> )
def __init__(self, agent, termination=None): self.agent = TerminationAgent(agent, termination) self.game_state = GameState.new_game(19) self._input = sys.stdin self._output = sys.stdout self._stopped = False self.handlers = { 'boardsize': self.handle_boardsize, 'clear_board': self.handle_clear_board, 'fixed_handicap': self.handle_fixed_handicap, 'genmove': self.handle_genmove, 'known_command': self.handle_known_command, 'komi': self.ignore, 'showboard': self.handle_showboard, 'time_settings': self.ignore, 'time_left': self.ignore, 'play': self.handle_play, 'protocol_version': self.handle_protocol_version, 'quit': self.handle_quit, }
class LocalGtpBot: def __init__(self, go_bot, termination=None, handicap=0, opponent='gnugo', output_sgf="out.sgf", our_color='b'): self.bot = TerminationAgent(go_bot, termination) # <1> self.handicap = handicap self._stopped = False # <2> self.game_state = GameState.new_game(19) self.sgf = SGFWriter(output_sgf) # <3> self.our_color = Player.black if our_color == 'b' else Player.white self.their_color = self.our_color.other cmd = self.opponent_cmd(opponent) # <4> pipe = subprocess.PIPE # Depending on your OS, you may need to set bufsize=0 to prevent # readline() from blocking. # See: https://github.com/maxpumperla/deep_learning_and_the_game_of_go/issues/44 self.gtp_stream = subprocess.Popen( cmd, stdin=pipe, stdout=pipe, # <5> bufsize=0) @staticmethod def opponent_cmd(opponent): if opponent == 'gnugo': return ["gnugo", "--mode", "gtp"] elif opponent == 'pachi': return ["pachi"] else: raise ValueError("Unknown bot name {}".format(opponent)) # <1> We initialize a bot from an agent and a termination strategy. # <2> We play until the game is stopped by one of the players. # <3> At the end we write the the game to the provided file in SGF format # <4> Our opponent will either be GNU Go or Pachi. # <5> We read and write GTP commands from the command line. # end::play_local_init[] # tag::play_local_commands[] def send_command(self, cmd): self.gtp_stream.stdin.write(cmd.encode('utf-8')) def get_response(self): succeeded = False result = '' while not succeeded: line = self.gtp_stream.stdout.readline().decode('utf-8') if line[0] == '=': succeeded = True line = line.strip() result = re.sub('^= ?', '', line) return result def command_and_response(self, cmd): self.send_command(cmd) return self.get_response() # end::play_local_commands[] # tag::play_local_run[] def run(self): self.command_and_response("boardsize 19\n") self.set_handicap() self.play() self.sgf.write_sgf() def set_handicap(self): if self.handicap == 0: self.command_and_response("komi 7.5\n") self.sgf.append("KM[7.5]\n") else: stones = self.command_and_response("fixed_handicap {}\n".format( self.handicap)) sgf_handicap = "HA[{}]AB".format(self.handicap) for pos in stones.split(" "): move = gtp_position_to_coords(pos) self.game_state = self.game_state.apply_move(move) sgf_handicap = sgf_handicap + "[" + self.sgf.coordinates( move) + "]" self.sgf.append(sgf_handicap + "\n") # end::play_local_run[] # tag::play_local_play[] def play(self): while not self._stopped: if self.game_state.next_player == self.our_color: self.play_our_move() else: self.play_their_move() print(chr(27) + "[2J") print_board(self.game_state.board) print("Estimated result: ") print(compute_game_result(self.game_state)) # end::play_local_play[] # tag::play_local_our[] def play_our_move(self): move = self.bot.select_move(self.game_state) self.game_state = self.game_state.apply_move(move) our_name = self.our_color.name our_letter = our_name[0].upper() sgf_move = "" if move.is_pass: self.command_and_response("play {} pass\n".format(our_name)) elif move.is_resign: self.command_and_response("play {} resign\n".format(our_name)) else: pos = coords_to_gtp_position(move) self.command_and_response("play {} {}\n".format(our_name, pos)) sgf_move = self.sgf.coordinates(move) self.sgf.append(";{}[{}]\n".format(our_letter, sgf_move)) # end::play_local_our[] # tag::play_local_their[] def play_their_move(self): their_name = self.their_color.name their_letter = their_name[0].upper() pos = self.command_and_response("genmove {}\n".format(their_name)) if pos.lower() == 'resign': self.game_state = self.game_state.apply_move(Move.resign()) self._stopped = True elif pos.lower() == 'pass': self.game_state = self.game_state.apply_move(Move.pass_turn()) self.sgf.append(";{}[]\n".format(their_letter)) if self.game_state.last_move.is_pass: self._stopped = True else: move = gtp_position_to_coords(pos) self.game_state = self.game_state.apply_move(move) self.sgf.append(";{}[{}]\n".format(their_letter, self.sgf.coordinates(move)))
class LocalGtpBot: def __init__(self, go_bot, termination=None, handicap=0, opponent='gnugo', output_sgf="out.sgf", our_color='b'): self.bot = TerminationAgent(go_bot, termination) self.handicap = handicap self._stopped = False self.game_state = GameState.new_game(19) self.sgf = SGFWriter(output_sgf) self.our_color = Player.black if our_color == 'b' else Player.white self.their_color = self.our_color.other cmd = self.opponent_cmd(opponent) pipe = subprocess.PIPE self.gtp_stream = subprocess.Popen(cmd, stdin=pipe, stdout=pipe) @staticmethod def opponent_cmd(opponent): if opponent == 'gnugo': return ["gnugo", "--mode", "gtp"] elif opponent == 'pachi': return ["pachi"] else: raise ValueError("Unknown bot name {}".format(opponent)) def send_command(self, cmd): self.gtp_stream.stdin.write(cmd.encode('utf-8')) def get_response(self): succeeded = False result = '' while not succeeded: line = self.gtp_stream.stdout.readline() if line[0] == '=': succeeded = True line = line.strip() result = re.sub('^= ?', '', line) return result def command_and_response(self, cmd): self.send_command(cmd) return self.get_response() def run(self): self.command_and_response("boardsize 19\n") self.set_handicap() self.play() self.sgf.write_sgf() def set_handicap(self): if self.handicap == 0: self.command_and_response("komi 7.5\n") self.sgf.append("KM[7.5]\n") else: stones = self.command_and_response("fixed_handicap {}\n".format( self.handicap)) sgf_handicap = "HA[{}]AB".format(self.handicap) for pos in stones.split(" "): move = gtp_position_to_coords(pos) self.game_state = self.game_state.apply_move(move) sgf_handicap = sgf_handicap + "[" + self.sgf.coordinates( move) + "]" self.sgf.append(sgf_handicap + "\n") def play(self): while not self._stopped: if self.game_state.next_player == self.our_color: self.play_our_move() else: self.play_their_move() print(chr(27) + "[2J") print_board(self.game_state.board) print("Estimated result: ") print(compute_game_result(self.game_state)) def play_our_move(self): move = self.bot.select_move(self.game_state) self.game_state = self.game_state.apply_move(move) our_name = self.our_color.name our_letter = our_name[0].upper() sgf_move = "" if move.is_pass: self.command_and_response("play {} pass\n".format(our_name)) elif move.is_resign: self.command_and_response("play {} resign\n".format(our_name)) else: pos = coords_to_gtp_position(move) self.command_and_response("play {} {}\n".format(our_name, pos)) sgf_move = self.sgf.coordinates(move) self.sgf.append(";{}[{}]\n".format(our_letter, sgf_move)) def play_their_move(self): their_name = self.their_color.name their_letter = their_name[0].upper() pos = self.command_and_response("genmove {}\n".format(their_name)) if pos.lower() == 'resign': self.game_state = self.game_state.apply_move(Move.resign()) self._stopped = True elif pos.lower() == 'pass': self.game_state = self.game_state.apply_move(Move.pass_turn()) self.sgf.append(";{}[]\n".format(their_letter)) if self.game_state.last_move.is_pass: self._stopped = True else: move = gtp_position_to_coords(pos) self.game_state = self.game_state.apply_move(move) self.sgf.append(";{}[{}]\n".format(their_letter, self.sgf.coordinates(move)))
class LocalGtpBot: def __init__(self, go_bot, termination=None, handicap=0, opponent='gnugo', output_sgf='out.sgf', our_color='b'): self.bot = TerminationAgent(go_bot, termination) self.handicap = handicap self.game_state = GameState.new_game(19) self.sgf = SGFWriter(output_sgf) self.our_color = Player.black if our_color == 'b' else Player.white self.their_color = self.our_color.other cmd = self.opponent_cmd(opponent) pipe = subprocess.PIPE self.gtp_stream = subprocess.Popen(cmd, stdin=pipe, stdout=pipe, bufsize=1, universal_newlines=True) # state self._stopped = False @staticmethod def opponent_cmd(opponent): if opponent == 'gnugo': return [ './../../opponent_engines/gnugo-3.8/gnugo', '--mode', 'gtp' ] elif opponent == 'pachi': return ['../../opponent_engines/Pachi/pachi'] else: raise ValueError('Unknown bot name \'{}\''.format(opponent)) def send_command(self, cmd): self.gtp_stream.stdin.write(cmd) def get_response(self): succeeded = False result = '' while not succeeded: for line in iter(self.gtp_stream.stdout.readline, ""): if line[0] == '=': succeeded = True line = line.strip() result = re.sub('^= ?', '', line) break return result def command_and_response(self, cmd): self.send_command(cmd) return self.get_response() def run(self): self.command_and_response('boardsize 19\n') self.set_handicap() self.play() self.sgf.write_sgf() def set_handicap(self): if self.handicap == 0: self.command_and_response('komi 7.5\n') self.sgf.append('KM[7.5]\n') else: stones = self.command_and_response('fixed_handicap {}\n'.format( self.handicap)) sgf_handicap = "HA[{}]AB".format(self.handicap) for pos in stones.split(' '): move = gtp_position_to_coords(pos) self.game_state = self.game_state.apply_move(move) sgf_handicap += '[' + self.sgf.coordinates(move) + ']' self.sgf.append(sgf_handicap + '\n') def play(self): while not self._stopped: if self.game_state.next_player == self.our_color: self.play_our_move() else: self.play_their_move() print(chr(27) + '[2J') # clears board print_board(self.game_state.board) print('Estimated result: ') print(compute_game_result(self.game_state)) def play_our_move(self): move = self.bot.select_move(self.game_state) self.game_state = self.game_state.apply_move(move) our_name = self.our_color.name our_letter = our_name[0].upper() sgf_move = '' if move.is_pass: self.command_and_response('play {} pass\n'.format(our_name)) elif move.is_resign: self.command_and_response('play {} resign\n'.format(our_name)) else: pos = coords_to_gtp_position(move) self.command_and_response('play {0} {1}\n'.format(our_name, pos)) sgf_move = self.sgf.coordinates(move) self.sgf.append(';{0}[{1}]\n'.format(our_letter, sgf_move)) def play_their_move(self): their_name = self.their_color.name their_letter = their_name[0].upper() pos = self.command_and_response('genmove {}\n'.format(their_name)) if pos.lower() == 'resign': self.game_state = self.game_state.apply_move(Move.resign()) self._stopped = True elif pos.lower() == 'pass': self.game_state = self.game_state.apply_move(Move.pass_turn()) self.sgf.append(';{}[]\n'.format(their_letter)) if self.game_state.last_move.is_pass: self._stopped = True else: move = gtp_position_to_coords(pos) self.game_state = self.game_state.apply_move(move) self.sgf.append(';{0}[{1}]\n'.format(their_letter, self.sgf.coordinates(move)))
class GTPFrontend(object): def __init__(self, agent, termination=None): self.agent = TerminationAgent(agent, termination) self.game_state = GameState.new_game(19) self._input = sys.stdin self._output = sys.stdout self._stopped = False self.handlers = { 'boardsize': self.handle_boardsize, 'clear_board': self.handle_clear_board, 'fixed_handicap': self.handle_fixed_handicap, 'genmove': self.handle_genmove, 'known_command': self.handle_known_command, 'komi': self.ignore, 'showboard': self.handle_showboard, 'time_settings': self.ignore, 'time_left': self.ignore, 'play': self.handle_play, 'protocol_version': self.handle_protocol_version, 'quit': self.handle_quit, } # end::gtp_frontend_init[] # tag::gtp_frontend_run[] def run(self): while not self._stopped: input_line = self._input.readline().strip() cmd = command.parse(input_line) resp = self.process(cmd) self._output.write(response.serialize(cmd, resp)) self._output.flush() def process(self, command): handler = self.handlers.get(command.name, self.handle_unknown) return handler(*command.args) # end::gtp_frontend_run[] # tag::gtp_frontend_commands[] def handle_play(self, color, move): if move.lower() == 'pass': self.game_state = self.game_state.apply_move(Move.pass_turn()) elif move.lower() == 'resign': self.game_state = self.game_state.apply_move(Move.resign()) else: self.game_state = self.game_state.apply_move( gtp_position_to_coords(move)) return response.success() def handle_genmove(self, color): move = self.agent.select_move(self.game_state) self.game_state = self.game_state.apply_move(move) if move.is_pass: return response.success('pass') if move.is_resign: return response.success('resign') return response.success(coords_to_gtp_position(move)) def handle_fixed_handicap(self, nstones): nstones = int(nstones) for stone in HANDICAP_STONES[:nstones]: self.game_state = self.game_state.apply_move( gtp_position_to_coords(stone)) return response.success() # tag::gtp_frontend_commands[] def handle_quit(self): self._stopped = True return response.success() def handle_clear_board(self): self.game_state = GameState.new_game(19) return response.success() def handle_known_command(self, command_name): return response.bool_response(command_name in self.handler.keys()) def handle_boardsize(self, size): if int(size) != 19: return response.error( 'Only 19x19 currently supported, requested {}'.format(size)) return response.success() def handle_showboard(self): print_board(self.game_state.board) return response.success() def handle_time_left(self, color, time, stones): # TODO: Arguments: color color, int time, int stones return response.success() def handle_time_settings(self, main_time, byo_yomi_time, byo_yomi_stones): # TODO: Arguments: int main_time, int byo_yomi_time, int byo_yomi_stones return response.success() def handle_unknown(self, *args): return response.error('Unrecognized command') def ignore(self, *args): return response.success() def handle_protocol_version(self): return response.success('2')