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_mintimeleft_handling(self): # check sending stop to bot with low time left tc = TimeControl("3s/0s/0") p = MockEngine(delay=[0, 1.1, 3.1]) game = Game(p, p, tc, min_timeleft=1.1) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) self.assertEqual(p.stopMove, 1) tc = TimeControl("3s/0s/0") p = MockEngine(delay=[2, 2, 0]) game = Game(p, p, tc, min_timeleft=1.5) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 2) self.assertEqual(p.stopMove, 0)
def test_play(self): # check basic endings, goal, immobilization and elimination p = MockEngine() game = Game(p, p) self.assertEqual(game.play(), (0, 'g')) for num, move in enumerate(game.moves): self.assertEqual(move, goal_moves[num]) self.assertEqual(game.result, (0, 'g')) self.assertRaises(RuntimeError, game.play) p = MockEngine(moves=immo_moves) game = Game(p, p) self.assertEqual(game.play(), (1, 'm')) p = MockEngine(moves=elim_moves) game = Game(p, p) self.assertEqual(game.play(), (1, 'e')) # check bot resign ending p = MockEngine(moves=resign_moves) game = Game(p, p) self.assertEqual(game.play(), (0, 'r')) # check illegality of taking opponent steps p = MockEngine(moves=extra_step_moves) game = Game(p, p) self.assertRaises(IllegalMove, game.play) self.assertEqual(p.move, 4) # check illegality of 3 time repetition p = MockEngine(moves=repetition_moves) game = Game(p, p) self.assertRaises(IllegalMove, game.play) self.assertEqual(p.move, 7) # check loose setup enforcement p = MockEngine(moves=handicap_moves) game = Game(p, p) self.assertRaises(IllegalMove, game.play) game = Game(p, p, strict_setup=False) self.assertEqual(game.play(), (1, 'e'))
def test_mintimeleft_handling(self): rt = pyrimaa.game.time # check sending stop to bot with low time left tc = TimeControl("3s/0s/0") p = MockEngine(delay=[0, 1.1, 3.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc, min_timeleft=1.1) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) self.assertEqual(p.stopMove, 1) tc = TimeControl("3s/0s/0") p = MockEngine(delay=[2, 2, 0]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc, min_timeleft=1.5) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 2) self.assertEqual(p.stopMove, 0) pyrimaa.game.time = rt
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 main(args=None): cfg = get_config(args) if cfg.rounds: print("Number of rounds: %d" % (cfg.rounds, )) else: print("Number of rounds not specified, running 1 round.") cfg.rounds = 1 try: tctl_str = cfg.timecontrol if tctl_str.lower() == "none": timecontrol = None else: timecontrol = TimeControl(tctl_str) print("At timecontrol %s" % (tctl_str, )) except NoOptionError: timecontrol = None if cfg.global_options: print("Giving these settings to all bots:") for name, value in cfg.global_options: print(" %s: %s" % (name, value)) print("Playing bots: ", end='') for bot in cfg.bots: print(bot, end=' ') print() # setup to write a bayeselo compatible pgn file write_pgn = False if cfg.pgn is not None: try: pgn_file = open(cfg.pgn, "a+") except IOError: print("Could not open pgn file %s" % (cfg.pgn, )) return 1 print("Writing results to pgn file: %s" % (cfg.pgn, )) write_pgn = True bots = [] for bname in cfg.bots: for bsection in cfg.bot_sections: if bname.lower() == bsection.lower(): bot_options = [] for name, value in cfg.ini.items(bsection): if name.startswith("bot_"): bot_options.append((name[4:], value)) bot = { 'name': bsection, 'options': bot_options, 'gold': 0, 'wins': 0, 'timeouts': 0, 'reasons': dict() } if cfg.ini.has_option(bsection, "timecontrol"): tctl_str = cfg.ini.get(bsection, "timecontrol") if tctl_str.lower() == "none": tc = None else: tc = TimeControl(tctl_str) print("bot %s at timecontrol %s" % (bsection, tctl_str)) bot['timecontrol'] = tc bots.append(bot) break else: print("Did not find a bot section for %s" % (bname)) return 1 start_time = time.time() for round_num in xrange(cfg.rounds): for bot_ix, bot in enumerate(bots[:-1]): for opp in bots[bot_ix + 1:]: if bot['gold'] <= opp['gold']: gbot = bot sbot = opp else: gbot = opp sbot = bot gbot['gold'] += 1 gengine = run_bot(gbot, cfg.ini, cfg.global_options) sengine = run_bot(sbot, cfg.ini, cfg.global_options) tc = [timecontrol, timecontrol] if 'timecontrol' in gbot: tc[0] = gbot['timecontrol'] if 'timecontrol' in sbot: tc[1] = sbot['timecontrol'] game = Game(gengine, sengine, tc, strict_setup=cfg.strict_setup, min_timeleft=cfg.stop_time) wside, reason = game.play() gengine.quit() sengine.quit() winner = [gbot, sbot][wside] loser = [gbot, sbot][wside ^ 1] # Display result of game print("%d%s" % (game.movenumber, "gs"[game.position.color])) print(game.position.board_to_str()) print("%s beat %s because of %s playing side %s" % (winner['name'], loser['name'], reason, "gs"[wside])) # Record game result stats winner['wins'] += 1 if reason == 't': [gbot, sbot][wside ^ 1]['timeouts'] += 1 winner['reasons'][reason] = winner['reasons'].get(reason, 0) + 1 # write game result to pgn file if write_pgn: ply_count = game.movenumber * 2 if game.position.color: ply_count -= 1 else: ply_count -= 2 results = ['1-0', '0-1'] pgn_file.write('[White "%s"]\n' % (gbot['name'], )) pgn_file.write('[Black "%s"]\n' % (sbot['name'], )) if timecontrol: pgn_file.write('[TimeControl "%s"]\n' % (tctl_str, )) pgn_file.write('[PlyCount "%s"]\n' % (ply_count, )) pgn_file.write('[ResultCode "%s"]\n' % (reason, )) pgn_file.write('[Result "%s"]\n' % (results[wside], )) pgn_file.write('\n') for move in game.moves: pgn_file.write('%s\n' % (move, )) pgn_file.write('%s\n\n' % (results[wside])) pgn_file.flush() # give the engines up to 30 more seconds to exit normally for i in range(30): if (not gengine.is_running() and not sengine.is_running()): break time.sleep(1) gengine.cleanup() sengine.cleanup() round_end = time.time() total_time = round_end - start_time print("After round %d and %s:" % (round_num + 1, format_time(total_time))) for bot in bots: print("%s has %d wins and %d timeouts" % (bot['name'], bot['wins'], bot['timeouts'])) for name, value in bot['reasons'].items(): print(" %d by %s" % (value, name)) return 0
def test_timecontrol_handling(self): # check timecontrol enforcement tc = TimeControl("1s/0s/0") p = MockEngine(delay=[0, 0, 1.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check reserve is correctly added when not 100% tc = TimeControl("1s/0s/50") p = MockEngine(delay=[0, 0, 0, 0, 1.2]) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 0) p = MockEngine(delay=[0, 0, 0, 0, 1.6]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check reserve is correctly deducted when reserve addition is not 100% tc = TimeControl("1s/1s/50") p = MockEngine(delay=[0, 0, 1.5, 0, 1.6]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check maximum reserve tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 2.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) # check game time limit tc = TimeControl("1s/1s/100/0/2s") p = MockEngine(delay=[0, 0, 1, 1, 0.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 's')) self.assertEqual(p.stopCount, 1) # check game move limit tc = TimeControl("1s/1s/100/0/33t") p = MockEngine() game = Game(p, p, tc) self.assertEqual(game.play(), (0, 's')) self.assertEqual(p.stopCount, 0) # check maximum move time limit tc = TimeControl("1s/1s/100/0/0/2s") p = MockEngine(delay=[0, 0, 0, 0, 2.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check differing time control for each player tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 2.1, 2.1]) game = Game(p, p, [None, tc]) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) tc1 = TimeControl("2s/0s/100") tc2 = TimeControl("1s/4s/100/6s") p = MockEngine(delay=[0, 0, 0, 0, 0, 5, 0, 0, 7.5]) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 0) p = MockEngine(delay=[0, 0, 0, 0, 5]) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 0, 0, 7.5]) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1)
def test_play(self): # check basic endings, goal, immobilization and elimination p = MockEngine() game = Game(p, p) self.assertEqual(game.play(), (0, "g")) for num, move in enumerate(game.moves): self.assertEqual(move, goal_moves[num]) self.assertEqual(game.result, (0, "g")) self.assertRaises(RuntimeError, game.play) p = MockEngine(moves=immo_moves) game = Game(p, p) self.assertEqual(game.play(), (1, "m")) p = MockEngine(moves=elim_moves) game = Game(p, p) self.assertEqual(game.play(), (1, "e")) # check illegality of taking opponent steps p = MockEngine(moves=extra_step_moves) game = Game(p, p) self.assertRaises(IllegalMove, game.play) self.assertEqual(p.move, 4) # check timecontrol enforcement tc = TimeControl("1s/0s/0") p = MockEngine(delay=[0, 0, 1.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, "t")) tc = TimeControl("1s/0s/50") p = MockEngine(delay=[0, 0, 0, 0, 1.2]) game = Game(p, p, tc) self.assertEqual(game.play(), (0, "g")) p = MockEngine(delay=[0, 0, 0, 0, 1.6]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, "t")) tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 2.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (0, "t")) tc = TimeControl("1s/1s/100/0/2s") p = MockEngine(delay=[0, 0, 1, 1, 0.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, "s")) tc = TimeControl("1s/1s/100/0/33t") p = MockEngine() game = Game(p, p, tc) self.assertEqual(game.play(), (0, "s")) tc = TimeControl("1s/1s/100/0/0/2s") p = MockEngine(delay=[0, 0, 0, 0, 2.1]) game = Game(p, p, tc) self.assertEqual(game.play(), (1, "t")) tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 2.1, 2.1]) game = Game(p, p, [None, tc]) self.assertEqual(game.play(), (0, "t")) tc1 = TimeControl("2s/0s/100") tc2 = TimeControl("1s/4s/100/6s") p = MockEngine(delay=[0, 0, 0, 0, 0, 5, 0, 0, 7.5]) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, "g")) p = MockEngine(delay=[0, 0, 0, 0, 5]) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (1, "t")) p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 0, 0, 7.5]) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, "t")) # check loose setup enforcement p = MockEngine(moves=handicap_moves) game = Game(p, p) self.assertRaises(IllegalMove, game.play) game = Game(p, p, strict_setup=False) self.assertEqual(game.play(), (1, "e"))
def test_timecontrol_handling(self): rt = pyrimaa.game.time # check timecontrol enforcement tc = TimeControl("1s/0s/0") p = MockEngine(delay=[0, 0, 1.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check reserve is correctly added when not 100% tc = TimeControl("1s/0s/50") p = MockEngine(delay=[0, 0, 0, 0, 1.6]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) p = MockEngine(delay=[0, 0, 0, 0, 1.2]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 0) # additionally check that the correct options were sent to the bot expected_options_set = { 'tctotal': [0, 0], 'tcmove': [1, 1], 'tcturns': [0, 0], 'tcreserve': [0, 0], 'tcmax': [0, 0], 'tcpercent': [50, 50], 'tcturntime': [0, 0], 'moveused': [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 'sreserve': [ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20 ], 'greserve': [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19 ], } for option, value in expected_options_set.items(): self.assertIn(option, p.options_set) self.assertEqual(p.options_set[option], value) # check protocol version 0 also gets the correct options tc = TimeControl("1s/0s/50") p = MockEngine(delay=[0, 0, 0, 0, 1.2]) p.protocol_version = 0 pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 0) # additionally check that the correct options were sent to the bot expected_options_set = { 'tctotal': [0, 0], 'tcmove': [1, 1], 'tcturns': [0, 0], 'tcreserve': [0, 0], 'tcmax': [0, 0], 'tcpercent': [50, 50], 'tcturntime': [0, 0], 'moveused': [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 'breserve': [ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20 ], 'wreserve': [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19 ], } for option, value in expected_options_set.items(): self.assertIn(option, p.options_set) self.assertEqual(p.options_set[option], value) # check reserve is correctly deducted when reserve addition is not 100% tc = TimeControl("1s/1s/50") p = MockEngine(delay=[0, 0, 1.5, 0, 1.6]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check maximum reserve tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 2.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) # check game time limit tc = TimeControl("1s/1s/100/0/2s") p = MockEngine(delay=[0, 0, 1, 1, 0.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 's')) self.assertEqual(p.stopCount, 1) # check game move limit tc = TimeControl("1s/1s/100/0/33t") p = MockEngine() pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 's')) self.assertEqual(p.stopCount, 0) # check maximum move time limit tc = TimeControl("1s/1s/100/0/0/2s") p = MockEngine(delay=[0, 0, 0, 0, 2.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check differing time control for each player tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 2.1, 2.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [None, tc]) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) tc1 = TimeControl("2s/0s/100") tc2 = TimeControl("1s/4s/100/6s") p = MockEngine(delay=[0, 0, 0, 0, 0, 5, 0, 0, 7.5]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 0) p = MockEngine(delay=[0, 0, 0, 0, 5]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 0, 0, 7.5]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) pyrimaa.game.time = rt
def main(args=None): try: cfg = get_config(args) except SystemExit as exc: return exc.code if cfg.rounds: print "Number of rounds: ", cfg.rounds else: print "Number of rounds not specified, running 1 round." cfg.rounds = 1 try: tctl_str = cfg.timecontrol if tctl_str.lower() == "none": timecontrol = None else: timecontrol = TimeControl(tctl_str) print "At timecontrol %s" % (tctl_str, ) except NoOptionError: timecontrol = None if cfg.global_options: print "Giving these settings to all bots:" for name, value in cfg.global_options: print "%s: %s" % (name, value) print "Playing bots:", for bot in cfg.bots: print bot, print # setup to write a bayeselo compatible pgn file write_pgn = False if cfg.pgn is not None: try: pgn_file = open(cfg.pgn, "a+") except IOError: print "Could not open pgn file %s" % (cfg.pgn, ) return 1 print "Writing results to pgn file:", cfg.pgn write_pgn = True bots = [] for bname in cfg.bots: for bsection in cfg.bot_sections: if bname.lower() == bsection.lower(): bot_options = [] for name, value in cfg.ini.items(bsection): if name.startswith("bot_"): bot_options.append((name[4:], value)) bot = { 'name': bsection, 'options': bot_options, 'gold': 0, 'wins': 0, 'timeouts': 0, 'reasons': dict() } if cfg.ini.has_option(bsection, "timecontrol"): tctl_str = cfg.ini.get(bsection, "timecontrol") if tctl_str.lower() == "none": tc = None else: tc = TimeControl(tctl_str) print "bot %s at timecontrol %s" % (bsection, tctl_str) bot['timecontrol'] = tc bots.append(bot) break else: print "Did not find a bot section for %s" % (bname) return 1 start_time = time.time() for round_num in xrange(cfg.rounds): for bot_ix, bot in enumerate(bots[:-1]): for opp in bots[bot_ix + 1:]: if bot['gold'] <= opp['gold']: gbot = bot sbot = opp else: gbot = opp sbot = bot gbot['gold'] += 1 gengine = run_bot(gbot, cfg.ini, cfg.global_options) sengine = run_bot(sbot, cfg.ini, cfg.global_options) tc = [timecontrol, timecontrol] if gbot.has_key('timecontrol'): tc[0] = gbot['timecontrol'] if sbot.has_key('timecontrol'): tc[1] = sbot['timecontrol'] game = Game(gengine, sengine, tc, strict_setup=cfg.strict_setup, min_timeleft=cfg.stop_time) wside, reason = game.play() gengine.quit() sengine.quit() winner = [gbot, sbot][wside] loser = [gbot, sbot][wside ^ 1] # Display result of game print "%d%s" % (game.movenumber, "gs" [game.position.color]) print game.position.board_to_str() print "%s beat %s because of %s playing side %s" % ( winner['name'], loser['name'], reason, "gs" [wside] ) # Record game result stats winner['wins'] += 1 if reason == 't': [gbot, sbot][wside ^ 1]['timeouts'] += 1 winner['reasons'][reason] = winner['reasons'].get(reason, 0) + 1 # write game result to pgn file if write_pgn: ply_count = game.movenumber * 2 if game.position.color: ply_count -= 1 else: ply_count -= 2 results = ['1-0', '0-1'] pgn_file.write('[White "%s"]\n' % (gbot['name'], )) pgn_file.write('[Black "%s"]\n' % (sbot['name'], )) if timecontrol: pgn_file.write('[TimeControl "%s"]\n' % (tctl_str, )) pgn_file.write('[PlyCount "%s"]\n' % (ply_count, )) pgn_file.write('[ResultCode "%s"]\n' % (reason, )) pgn_file.write('[Result "%s"]\n' % (results[wside], )) pgn_file.write('\n') for move in game.moves: pgn_file.write('%s\n' % (move, )) pgn_file.write('%s\n\n' % (results[wside])) pgn_file.flush() # give the engines up to 30 more seconds to exit normally for i in range(30): if (not gengine.is_running() and not sengine.is_running()): break time.sleep(1) gengine.cleanup() sengine.cleanup() round_end = time.time() total_time = round_end - start_time print "After round %d and %s:" % (round_num + 1, format_time(total_time)) for bot in bots: print "%s has %d wins and %d timeouts" % (bot['name'], bot['wins'], bot['timeouts']) for name, value in bot['reasons'].items(): print " %d by %s" % (value, name) return 0
def test_timecontrol_handling(self): rt = pyrimaa.game.time # check timecontrol enforcement tc = TimeControl("1s/0s/0") p = MockEngine(delay=[0, 0, 1.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check reserve is correctly added when not 100% tc = TimeControl("1s/0s/50") p = MockEngine(delay=[0, 0, 0, 0, 1.2]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 0) p = MockEngine(delay=[0, 0, 0, 0, 1.6]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check reserve is correctly deducted when reserve addition is not 100% tc = TimeControl("1s/1s/50") p = MockEngine(delay=[0, 0, 1.5, 0, 1.6]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check maximum reserve tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 2.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) # check game time limit tc = TimeControl("1s/1s/100/0/2s") p = MockEngine(delay=[0, 0, 1, 1, 0.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 's')) self.assertEqual(p.stopCount, 1) # check game move limit tc = TimeControl("1s/1s/100/0/33t") p = MockEngine() pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (0, 's')) self.assertEqual(p.stopCount, 0) # check maximum move time limit tc = TimeControl("1s/1s/100/0/0/2s") p = MockEngine(delay=[0, 0, 0, 0, 2.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, tc) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) # check differing time control for each player tc = TimeControl("1s/1s/100/1s") p = MockEngine(delay=[0, 0, 0, 0, 2.1, 2.1]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [None, tc]) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) tc1 = TimeControl("2s/0s/100") tc2 = TimeControl("1s/4s/100/6s") p = MockEngine(delay=[0, 0, 0, 0, 0, 5, 0, 0, 7.5]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, 'g')) self.assertEqual(p.stopCount, 0) p = MockEngine(delay=[0, 0, 0, 0, 5]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (1, 't')) self.assertEqual(p.stopCount, 1) p = MockEngine(delay=[0, 0, 0, 0, 0, 0, 0, 0, 0, 7.5]) pyrimaa.game.time = MockTime(p) game = Game(p, p, [tc1, tc2]) self.assertEqual(game.play(), (0, 't')) self.assertEqual(p.stopCount, 1) pyrimaa.game.time = rt
def main(): config = SafeConfigParser() if not config.read("roundrobin.cfg"): print "Could not read 'roundrobin.cfg'." return 1 bot_configs = set(config.sections()) if "global" not in bot_configs: print "Did not find expected 'global' section in configuration file." return 1 bot_configs.remove('global') rounds = config.getint("global", "rounds") print "Number of rounds: ", rounds try: tctl_str = config.get("global", "timecontrol") if tctl_str.lower() == "none": timecontrol = None else: timecontrol = TimeControl(tctl_str) print "At timecontrol %s" % (tctl_str,) except NoOptionError: timecontrol = None if config.has_option("global", "loglevel"): levelstr = config.get("global", "loglevel").lower() levels = {"info": logging.INFO, "debug": logging.DEBUG, "warn": logging.WARN, "error": logging.ERROR} level = levels.get(levelstr, None) if level: log.setLevel(level) else: print "Attempted to set unrecognized log level" return 1 strict_setup = True if config.has_option("global", "strict_setup"): strict_setup = config.getboolean("global", "strict_setup") if not strict_setup: print "Disabling strict checks on setup moves" global_options = [] for name, value in config.items("global"): if name.startswith("bot_"): global_options.append((name[4:], value)) if global_options: print "Giving these settings to all bots:" for name, value in global_options: print "%s: %s" % (name, value) # setup to write a bayeselo compatible pgn file write_pgn = False if config.has_option("global", "write_pgn"): write_pgn = config.getboolean("global", "write_pgn") if write_pgn: try: pgn_name = config.get("global", "pgn_filename") except NoOptionError: print "Must specify pgn_filename option with write_pgn option." return 1 pgn_file = open(pgn_name, "a+") bots = [] for bname in config.get("global", "bots").split(): for bsection in bot_configs: if bname.lower() == bsection.lower(): bot_options = [] for name, value in config.items(bsection): if name.startswith("bot_"): bot_options.append((name[4:], value)) bot = {'name': bsection, 'options': bot_options, 'gold': 0, 'wins': 0, 'timeouts': 0, 'reasons': dict()} if config.has_option(bsection, "timecontrol"): tctl_str = config.get(bsection, "timecontrol") if tctl_str.lower() == "none": tc = None else: tc = TimeControl(tctl_str) print "bot %s at timecontrol %s" % (bsection, tctl_str) bot['timecontrol'] = tc bots.append(bot) break else: print "Did not find a bot section for %s" % (bname) return 1 start_time = time.time() for round_num in xrange(rounds): for bot_ix, bot in enumerate(bots[:-1]): for opp in bots[bot_ix+1:]: if bot['gold'] <= opp['gold']: gbot = bot sbot = opp else: gbot = opp sbot = bot gbot['gold'] += 1 gengine = run_bot(gbot, config, global_options) sengine = run_bot(sbot, config, global_options) tc = [timecontrol, timecontrol] if gbot.has_key('timecontrol'): tc[0] = gbot['timecontrol'] if sbot.has_key('timecontrol'): tc[1] = sbot['timecontrol'] game = Game(gengine, sengine, tc, strict_setup=strict_setup) wside, reason = game.play() gengine.quit() sengine.quit() winner = [gbot, sbot][wside] loser = [gbot, sbot][wside^1] # Display result of game print "%d%s" % (game.movenumber, "gs"[game.position.color]) print game.position.board_to_str() print "%s beat %s because of %s playing side %s" % ( winner['name'], loser['name'],reason, "gs"[wside]) # Record game result stats winner['wins'] += 1 if reason == 't': [gbot, sbot][wside ^ 1]['timeouts'] += 1 winner['reasons'][reason] = winner['reasons'].get(reason, 0) + 1 # write game result to pgn file if write_pgn: ply_count = game.movenumber * 2 if game.position.color: ply_count -= 1 else: ply_count -= 2 results = ['1-0', '0-1'] pgn_file.write('[White "%s"]\n' % (gbot['name'],)) pgn_file.write('[Black "%s"]\n' % (sbot['name'],)) if timecontrol: pgn_file.write('[TimeControl "%s"]\n' % (tctl_str,)) pgn_file.write('[PlyCount "%s"]\n' % (ply_count,)) pgn_file.write('[ResultCode "%s"]\n' % (reason,)) pgn_file.write('[Result "%s"]\n' % (results[wside],)) pgn_file.write('\n') for move in game.moves: pgn_file.write('%s\n' % (move,)) pgn_file.write('%s\n\n' % (results[wside])) pgn_file.flush() # give the engines up to 30 more seconds to exit normally for i in range(30): if (not gengine.is_running() and not sengine.is_running()): break time.sleep(1) gengine.cleanup() sengine.cleanup() round_end = time.time() total_time = round_end - start_time print "After round %d and %s:" % (round_num+1, format_time(total_time)) for bot in bots: print "%s has %d wins and %d timeouts" % (bot['name'], bot['wins'], bot['timeouts']) for name, value in bot['reasons'].items(): print " %d by %s" % (value, name) return 0