def __init__(self, gold, silver, timecontrol=None, start_position=None, strict_setup=True, min_timeleft=None): self.engines = (gold, silver) try: self.timecontrol = timecontrol[0] self.side_tc = timecontrol except TypeError: self.timecontrol = timecontrol self.side_tc = [timecontrol, timecontrol] self.reserves = [None, None] if timecontrol: for side, eng in enumerate(self.engines): if not self.side_tc[side]: continue self.reserves[side] = self.side_tc[side].reserve eng.setoption("tcmove", self.side_tc[side].move) eng.setoption("tcreserve", self.side_tc[side].reserve) eng.setoption("tcpercent", self.side_tc[side].percent) eng.setoption("tcmax", self.side_tc[side].max_reserve) eng.setoption("tcturns", self.side_tc[side].turn_limit) eng.setoption("tctotal", self.side_tc[side].time_limit) eng.setoption("tcturntime", self.side_tc[side].max_turntime) for eng in self.engines: eng.newgame() if start_position: eng.setposition(start_position) resps = eng.isready() side = "gs"[self.engines.index(eng)] eng_name = eng.ident["name"] for response in resps: if response.type == "info": log.info("%s (%s) info: %s", eng_name, side, response.message) elif response.type == "log": log.info("%s (%s) log: %s", eng_name, side, response.message) else: log.warn( "Unexpected response while initializing %s (%s) (%s).", eng_name, side, response.type) self.insetup = False self.position = start_position if not start_position: self.insetup = True self.position = Position(Color.GOLD, 4, BLANK_BOARD) self.strict_setup = strict_setup self.min_timeleft = min_timeleft self.movenumber = 1 self.limit_winner = 1 self.moves = [] self.repetition_count = defaultdict(int) self.result = None
def go(self): pos = self.position if self.insetup: setup = Position(Color.GOLD, 4, BASIC_SETUP) setup_moves = setup.to_placing_move() move_str = setup_moves[pos.color][2:] else: steps, result = pos.get_rnd_step_move() move_str = pos.steps_to_str(steps) self.bestmove(move_str)
def test_contruction(self): p = MockEngine() game = Game(p, p) self.assertEqual(game.movenumber, 1) self.assertEqual(game.insetup, True) tc = TimeControl("30s/60s") game = Game(p, p, tc) self.assertEqual(game.timecontrol, tc) pos = Position(Color.GOLD, 4, BASIC_SETUP) game = Game(p, p, tc, pos) self.assertEqual(game.position, pos) self.assertEqual(game.insetup, False)
def test_contruction(self): p = MockEngine() game = Game(p, p) self.assertEqual(game.movenumber, 1) self.assertEqual(game.insetup, True) tc = TimeControl("30s/60s") game = Game(p, p, tc) self.assertEqual(game.timecontrol, tc) pos = Position(Color.GOLD, 4, BASIC_SETUP) game = Game(p, p, tc, pos) self.assertEqual(game.position, pos) self.assertEqual(game.insetup, False) real_log = pyrimaa.game.log mock_log = MockLog() pyrimaa.game.log = mock_log try: info = MockResponse("info") info.message = "Test info message." pl = MockEngine(isready=[info]) game = Game(pl, p) self.assertEqual(game.movenumber, 1) self.assertEqual(game.insetup, True) self.assertEqual(len(mock_log.info_logs), 1) self.assertEqual(len(mock_log.warn_logs), 0) self.assertIn(info.message, mock_log.info_logs[0]) mock_log.reset() log = MockResponse("log") log.message = "Test log message." pl = MockEngine(isready=[log]) game = Game(pl, p) self.assertEqual(game.movenumber, 1) self.assertEqual(game.insetup, True) self.assertEqual(len(mock_log.info_logs), 1) self.assertEqual(len(mock_log.warn_logs), 0) self.assertIn(log.message, mock_log.info_logs[0]) mock_log.reset() invalid = MockResponse("bestmove") invalid.move = " " pl = MockEngine(isready=[invalid]) game = Game(pl, p) self.assertEqual(game.movenumber, 1) self.assertEqual(game.insetup, True) self.assertEqual(len(mock_log.info_logs), 0) self.assertEqual(len(mock_log.warn_logs), 1) mock_log.reset() finally: pyrimaa.game.log = real_log
def go(self): pos = self.position start_time = time.time() if self.insetup: setup = Position(Color.GOLD, 4, BASIC_SETUP) setup_moves = setup.to_placing_move() move_str = setup_moves[pos.color][2:] else: steps, result = pos.get_rnd_step_move() if steps is None: # we are immobilized, return an empty move move_str = "" self.log("Warning: move requested when immobilized.") else: move_str = pos.steps_to_str(steps) if self.move_delay: time.sleep(self.move_delay) move_time = time.time() - start_time self.total_move_time += move_time self.info("time %d" % (int(round(move_time), ))) self.bestmove(move_str)
def newgame(self): self.position = Position(Color.GOLD, 4, BLANK_BOARD) self.insetup = True
def playgame(gold_eng, silver_eng, timecontrol=None, position=None): engines = (gold_eng, silver_eng) if timecontrol: time_incr = timecontrol['move'] reserves = [0, 0] reserves[0] = reserves[1] = timecontrol['reserve'] reserve_per = timecontrol['percent'] / 100.0 reserve_max = timecontrol['max'] max_moves = timecontrol['turns'] max_gametime = timecontrol['total'] max_turn = timecontrol['turntime'] for eng in engines: eng.setoption("tcmove", time_incr) eng.setoption("tcreserve", timecontrol['reserve']) eng.setoption("tcpercent", timecontrol['percent']) eng.setoption("tcmax", reserve_max) eng.setoption("tcturns", max_moves) eng.setoption("tctotal", max_gametime) eng.setoption("tcturntime", max_turn) else: max_gametime = 0 max_moves = 0 for eng in engines: eng.newgame() if position: eng.setposition(position) eng.isready() insetup = False if not position: insetup = True position = Position(Color.GOLD, 4, board.BLANK_BOARD) starttime = time.time() if max_gametime: endtime_limit = starttime + max_gametime position.movenumber = 1 limit_winner = 1 while insetup or not position.is_end_state(): #print "%d%s" % (position.movenumber, "gs"[position.color]) #print position.board_to_str() side = position.color engine = engines[side] if timecontrol: if engine.protocol_version > 0: engine.setoption("greserve", int(reserves[0])) engine.setoption("sreserve", int(reserves[1])) else: engine.setoption("wreserve", int(reserves[0])) engine.setoption("breserve", int(reserves[1])) engine.setoption("tcmoveused", 0) movestart = time.time() engine.setoption("moveused", 0) engine.go() if timecontrol: timeout = movestart + time_incr + reserves[side] if max_turn and starttime + max_turn > timeout: timeout = starttime + max_turn if max_gametime and endtime_limit < timeout: timeout = endtime_limit bstr = position.board_to_str("short") gp = 0 for p in "EMHDCR": gp += bstr.count(p) sp = 0 for p in "emhdcr": sp += bstr.count(p) if gp > sp: limit_winner = 0 elif sp > gp: limit_winner = 1 else: timeout = None resp = None try: while not timeout or time.time() < timeout: if timeout: wait = timeout - time.time() else: wait = None resp = engine.get_response(wait) if resp.type == "bestmove": break if resp.type == "info": log.info("%s info: %s" % ("gs"[side], resp.message)) elif resp.type == "log": log.info("%s log: %s" % ("gs"[side], resp.message)) except socket.timeout: engine.stop() endtime = time.time() if resp and resp.type == "bestmove": if timecontrol: moveend = time.time() if moveend > timeout: return (side ^ 1, "t", position) if not insetup: reserve_incr = ((time_incr - (moveend - movestart)) * reserve_per) reserves[side] += reserve_incr if reserve_max: reserves[side] = min(reserves[side], reserve_max) move = resp.move mn = position.movenumber position = position.do_move_str(move) if position.color == Color.GOLD: mn += 1 position.movenumber = mn log.info("position:\n%s", position.board_to_str()) for eng in engines: eng.makemove(move) if insetup and side == Color.SILVER: insetup = False if max_moves and position.movenumber > max_moves: return (limit_winner, "s", position) elif not max_gametime or endtime < endtime_limit: return (side ^ 1, "t", position) else: # exceeded game time limit return (limit_winner, "s", position) if position.is_goal(): result = (min(position.is_goal(), 0), "g", position) elif position.is_rabbit_loss(): result = (min(position.is_rabbit_loss(), 0), "e", position) else: # immobilization assert len(position.get_steps()) == 0 result = (position.color ^ 1, "m", position) return result