def test_controller_protocol0(self): eng = MockEngine(protocol0) ctl = EngineController(eng) self.assertEqual(ctl.ident["name"], "Mock0") self.assertEqual(ctl.ident["author"], "Janzert") self.assertEqual(ctl.protocol_version, 0) ctl.newgame() pos = board.Position(board.Color.GOLD, 4, board.BASIC_SETUP) ctl.setposition(pos) ctl.cleanup()
def run_bot(bot, config, global_options): cmdline = config.get(bot['name'], "cmdline") if config.has_option(bot['name'], "communication_method"): com_method = config.get(bot['name'], "communication_method").lower() else: com_method = "stdio" if com_method == "stdio": engine = StdioEngine(cmdline, log=log) elif com_method == "socket": engine = SocketEngine(cmdline, log=log) engine = EngineController(engine) for option, value in global_options: engine.setoption(option, value) for name, value in config.items(bot['name']): if name.startswith("bot_"): engine.setoption(name[4:], value) return engine
def main(args): """Main entry for script. Parses the command line. Reads 'gameroom.cfg' for the configuration. Starts the engine and gives it any initial configuration. Joins or creates the specified game. Then finally controls the engine passing it the game information and sending engine responses back to the server. """ try: options = parseargs(args) except ValueError: print "Command not understood '%s'" % (" ".join(args[1:])) print print __doc__ sys.exit(2) config = SafeConfigParser() try: config.readfp(open('gameroom.cfg', 'rU')) except IOError: print "Could not open 'gameroom.cfg'" print "this file must be readable and contain the configuration" print "for connecting to the gameroom." sys.exit(1) aeilog = logging.getLogger("gameroom.aei") if config.has_section("Logging"): logdir = config.get("Logging", "directory") if not os.path.exists(logdir): print "Log directory '%s' not found, attempting to create it." % ( logdir) os.makedirs(logdir) logfilename = "%s-%s.log" % (time.strftime("%Y%m%d-%H%M"), str(os.getpid()), ) logfilename = os.path.join(logdir, logfilename) if config.has_option("Logging", "level"): loglevel = str_loglevel(config.get("Logging", "level")) else: loglevel = logging.WARN logging.basicConfig(level = loglevel, filename = logfilename, datefmt="%Y-%m-%d %H:%M:%S", format="%(asctime)s %(levelname)s:%(name)s:%(message)s", ) if (config.has_option("Logging", "console") and config.getboolean("Logging", "console")): global console console = logging.StreamHandler() if config.has_option("Logging", "console_level"): conlevel = str_loglevel(config.get("Logging", "console_level")) else: conlevel = logging.INFO console.setLevel(conlevel) logging.getLogger('').addHandler(console) if config.has_option("Logging", "net_level"): netlevel = str_loglevel(config.get("Logging", "net_level")) netlog.setLevel(netlevel) if config.has_option("Logging", "engine_level"): enginelevel = str_loglevel(config.get("Logging", "engine_level")) enginelog.setLevel(enginelevel) if config.has_option("Logging", "aei_level"): aeilog.setLevel(str_loglevel(config.get("Logging", "aei_level"))) positionlog.setLevel(logging.ERROR) if (config.has_option("Logging", "log_position") and config.getboolean("Logging", "log_position")): positionlog.setLevel(logging.INFO) run_dir = config.get("global", "run_dir") if not os.path.exists(run_dir): log.warn("Run file directory '%s' not found, attempting to create it." % (run_dir)) os.makedirs(run_dir) bot_count = how_many_bots(run_dir) if bot_count >= config.getint("global", "max_bots"): log.info("Max number of bot limit %d reached, need to wait until some bots finish." % (config.getint("global", "max_bots"))) return bot_section = config.get("global", "default_engine") com_method = config.get(bot_section, "communication_method").lower() enginecmd = config.get(bot_section, "cmdline") gameid_or_opponent = options['against'] unknowns_caught = 0 while True: try: if com_method == "2008cc": engine_ctl = EngineController(SocketEngine(enginecmd, log=aeilog, legacy_mode=True)) elif com_method == "socket": engine_ctl = EngineController(SocketEngine(enginecmd, log=aeilog)) elif com_method == "stdio": engine_ctl = EngineController(StdioEngine(enginecmd, log=aeilog)) else: raise ValueError("Unrecognized communication method, %s" % (com_method)) except OSError, exc: log.error("Could not start the engine; exception thrown: %s", exc) sys.exit(1) try: for option in config.options(bot_section): if option.startswith("bot_"): value = config.get(bot_section, option) engine_ctl.setoption(option[4:], value) log.info("Setting bot option %s = %s", option[4:], value) engine_ctl.isready() bot_username = config.get(bot_section, "username") bot_password = config.get(bot_section, "password") bot_greeting = config.get(bot_section, "greeting") gameroom = GameRoom(config.get("global", "gameroom_url")) gameroom.login(bot_username, bot_password) side = options['side'] if side == "g": side = "w" elif side == "s": side = "b" table = None if gameid_or_opponent == "": log.info("Starting a new game") if side == "": side = 'b' timecontrol = config.get(bot_section, "timecontrol") rated = config.getboolean(bot_section, "rated") log.info("Will play on side %s, using timecontrol %s" % (side, timecontrol)) table = gameroom.newgame(side, timecontrol, rated) else: # look through my games for correct opponent and side games = gameroom.mygames() for game in games: if (gameid_or_opponent == game['player'].lower() or gameid_or_opponent == game['gid']): if (side == "" or side == game['side'] and not already_playing(run_dir, game['gid'], game['side'])): table = Table(gameroom, game) log.info("Found in progress game") break if table == None: games = gameroom.opengames() for game in games: if (gameid_or_opponent == game['player'].lower() or gameid_or_opponent == game['gid']): if (side == "" or side == game['side'] and not already_playing(run_dir, game['gid'], game['side'])): table = Table(gameroom, game) log.info("Found game to join") break if table == None: log.error("Could not find game against %s with side '%s'", gameid_or_opponent, side) engine_ctl.quit() engine_ctl.cleanup() break # Set the game to play in to current game id in case of a restart gameid_or_opponent = table.gid if options['against'] != "": joinmsg = "Joined game gid=%s side=%s; against %s" % (table.gid, table.side, options['against']) else: joinmsg = "Created game gid=%s side=%s; waiting for opponent"\ % (table.gid, table.side) log.info(joinmsg) if console is None: print joinmsg # force the std streams to flush so the bot starter script used # on the arimaa.com server can pick up the join message sys.stdout.flush() sys.stderr.flush() if config.has_option(bot_section, "ponder"): table.ponder = config.getboolean(bot_section, "ponder") if table.ponder: log.info("Set pondering on.") else: log.info("Set pondering off.") else: table.ponder = False if config.has_option("global", "min_move_time"): table.min_move_time = config.getint("global", "min_move_time") log.info("Set minimum move time to %d seconds.", table.min_move_time) else: table.min_move_time = 5 if config.has_option("global", "min_time_left"): table.min_timeleft = config.getint("global", "min_time_left") log.info("Setting emergency stop time to %d seconds" % table.min_timeleft) else: table.min_timeleft = 5 except: shutdown_engine(engine_ctl) raise try: try: log.info("Joining game on %s side", table.side) table.reserveseat() table.sitdown() table.updatestate() engine_ctl.setoption("rated", table.state.get('rated', 1)) try: touch_run_file(run_dir, "%s%s.bot" % (table.gid, table.side)) time.sleep(1) # Give the server a small break. log.info("Starting play") table.playgame(engine_ctl, bot_greeting, options['onemove']) finally: log.info("Leaving game") remove_run_file(run_dir, "%s%s.bot" % (table.gid, table.side)) table.leave() break finally: shutdown_engine(engine_ctl) except (KeyboardInterrupt, SystemExit): raise except EngineCrashException, exc: log.error("Bot engine crashed (%s), restarting.", exc.args[0]) time.sleep(1)
bot_section = config.get("global", "default_engine") if config.has_option(bot_section, "communication_method"): com_method = config.get(bot_section, "communication_method").lower() else: com_method = "stdio" enginecmd = config.get(bot_section, "cmdline") if com_method == "2008cc": eng_com = SocketEngine(enginecmd, legacy_mode=True, log=log) elif com_method == "socket": eng_com = SocketEngine(enginecmd, log=log) elif com_method == "stdio": eng_com = StdioEngine(enginecmd, log=log) else: raise ValueError("Unrecognized communication method: %s" % (com_method,)) eng = EngineController(eng_com) for option in config.options(bot_section): if option.startswith("bot_"): value = config.get(bot_section, option) eng.setoption(option[4:], value) eng.newgame() if have_board: eng.setposition(pos) else: pos = board.Position(board.Color.GOLD, 4, board.BLANK_BOARD) for move in move_list: move = move[3:] pos = pos.do_move_str(move) eng.makemove(move)
bot_section = config.get("global", "default_engine") if config.has_option(bot_section, "communication_method"): com_method = config.get(bot_section, "communication_method").lower() else: com_method = "stdio" enginecmd = config.get(bot_section, "cmdline") if com_method == "2008cc": eng_com = SocketEngine(enginecmd, legacy_mode=True, log=log) elif com_method == "socket": eng_com = SocketEngine(enginecmd, log=log) elif com_method == "stdio": eng_com = StdioEngine(enginecmd, log=log) else: raise ValueError("Unrecognized communication method: %s" % (com_method, )) eng = EngineController(eng_com) for option in config.options(bot_section): if option.startswith("bot_"): value = config.get(bot_section, option) eng.setoption(option[4:], value) eng.newgame() if have_board: eng.setposition(pos) else: pos = board.Position(board.Color.GOLD, 4, board.BLANK_BOARD) for move in move_list: move = move[3:] pos = pos.do_move_str(move) eng.makemove(move)
def test_controller_protocol1(self): eng = MockEngine(protocol1) ctl = EngineController(eng) self.assertEqual(ctl.ident["name"], "Mock") self.assertEqual(ctl.ident["author"], "Janzert") self.assertEqual(ctl.protocol_version, 1) self.assertEqual(ctl.is_running(), True) resp = ctl.get_response() self.assertIsInstance(resp, EngineResponse) self.assertEqual(resp.type, "log") self.assertEqual(resp.message, eng.expected[eng.event - 1][1].lstrip("log ")) ctl.setoption("depth", 4) ctl.newgame() pos = board.Position(board.Color.GOLD, 4, board.BASIC_SETUP) ctl.setposition(pos) ctl.go() ctl.stop() resp = ctl.get_response() self.assertEqual(resp.type, "info") self.assertEqual(resp.message, eng.expected[eng.event - 1][1].lstrip("info ")) resp = ctl.get_response() self.assertEqual(resp.type, "bestmove") self.assertEqual(resp.move, eng.expected[eng.event - 1][1].lstrip("bestmove ")) ctl.makemove("Hb2n Ed2n") ctl.go("ponder") ctl.quit() ctl.cleanup()
def test_controller(self): eng = MockEngine(protocol1) ctl = EngineController(eng) self.assertEqual(ctl.ident["name"], "Mock") self.assertEqual(ctl.ident["author"], "Janzert") self.assertEqual(ctl.protocol_version, 1) self.assertEqual(ctl.is_running(), True) self.assertRaises(socket.timeout, ctl.get_response) resp = ctl.get_response() self.assertIsInstance(resp, EngineResponse) self.assertEqual(resp.type, "log") self.assertEqual(resp.message, eng.expected[eng.event - 1][1].lstrip("log ")) ctl.setoption("depth", 4) ctl.newgame() pos = board.Position(board.Color.GOLD, 4, board.BASIC_SETUP) ctl.setposition(pos) ctl.go() ctl.stop() resp = ctl.get_response() self.assertEqual(resp.type, "info") self.assertEqual(resp.message, eng.expected[eng.event - 1][1].lstrip("info ")) resp = ctl.get_response() self.assertEqual(resp.type, "bestmove") self.assertEqual(resp.move, eng.expected[eng.event - 1][1].lstrip("bestmove ")) ctl.makemove("Hb2n Ed2n") ctl.go("ponder") ctl.quit() ctl.cleanup() # bad response to isready eng = MockEngine(bad_isready_response) ctl = EngineController(eng) ctl.newgame() self.assertRaises(EngineException, ctl.isready) # timeout waiting for aeiok eng = MockEngine(aeiok_timeout) self.assertRaises(EngineException, EngineController, eng) # IOError sending aei eng = MockEngine(aei_send_error) self.assertRaises(EngineException, EngineController, eng)
def test_protocol_versions(self): eng = MockEngine(protocol0) ctl = EngineController(eng) self.assertEqual(ctl.ident["name"], "Mock0") self.assertEqual(ctl.ident["author"], "Janzert") self.assertEqual(ctl.protocol_version, 0) ctl.newgame() pos = board.Position(board.Color.GOLD, 4, board.BASIC_SETUP) ctl.setposition(pos) ctl.cleanup() # bad protocol version eng = MockEngine(bad_protocol) eng.log = MockLog() ctl = EngineController(eng) self.assertIn("Unrecognized protocol version", eng.log.warning) pos = board.Position(board.Color.GOLD, 4, board.BASIC_SETUP) ctl.newgame() ctl.setposition(pos) ctl.go() ctl.stop() ctl.quit()
def main(args): """Main entry for script. Parses the command line. Reads 'gameroom.cfg' for the configuration. Starts the engine and gives it any initial configuration. Joins or creates the specified game. Then finally controls the engine passing it the game information and sending engine responses back to the server. """ try: options = parseargs(args) except ValueError: print "Command not understood '%s'" % (" ".join(args[1:])) print print __doc__ sys.exit(2) config = SafeConfigParser() try: config.readfp(open('gameroom.cfg', 'rU')) except IOError: print "Could not open 'gameroom.cfg'" print "this file must be readable and contain the configuration" print "for connecting to the gameroom." sys.exit(1) aeilog = logging.getLogger("gameroom.aei") if config.has_section("Logging"): logdir = config.get("Logging", "directory") if not os.path.exists(logdir): print "Log directory '%s' not found, attempting to create it." % ( logdir) os.makedirs(logdir) logfilename = "%s-%s.log" % ( time.strftime("%Y%m%d-%H%M"), str(os.getpid()), ) logfilename = os.path.join(logdir, logfilename) if config.has_option("Logging", "level"): loglevel = str_loglevel(config.get("Logging", "level")) else: loglevel = logging.WARN logging.basicConfig( level=loglevel, filename=logfilename, datefmt="%Y-%m-%d %H:%M:%S", format="%(asctime)s %(levelname)s:%(name)s:%(message)s", ) if (config.has_option("Logging", "console") and config.getboolean("Logging", "console")): global console console = logging.StreamHandler() if config.has_option("Logging", "console_level"): conlevel = str_loglevel(config.get("Logging", "console_level")) else: conlevel = logging.INFO console.setLevel(conlevel) logging.getLogger('').addHandler(console) if config.has_option("Logging", "net_level"): netlevel = str_loglevel(config.get("Logging", "net_level")) netlog.setLevel(netlevel) if config.has_option("Logging", "engine_level"): enginelevel = str_loglevel(config.get("Logging", "engine_level")) enginelog.setLevel(enginelevel) if config.has_option("Logging", "aei_level"): aeilog.setLevel(str_loglevel(config.get("Logging", "aei_level"))) positionlog.setLevel(logging.ERROR) if (config.has_option("Logging", "log_position") and config.getboolean("Logging", "log_position")): positionlog.setLevel(logging.INFO) run_dir = config.get("global", "run_dir") if not os.path.exists(run_dir): log.warn( "Run file directory '%s' not found, attempting to create it." % (run_dir)) os.makedirs(run_dir) bot_count = how_many_bots(run_dir) if bot_count >= config.getint("global", "max_bots"): log.info( "Max number of bot limit %d reached, need to wait until some bots finish." % (config.getint("global", "max_bots"))) return bot_section = config.get("global", "default_engine") com_method = config.get(bot_section, "communication_method").lower() enginecmd = config.get(bot_section, "cmdline") gameid_or_opponent = options['against'] unknowns_caught = 0 while True: try: if com_method == "2008cc": engine_ctl = EngineController( SocketEngine(enginecmd, log=aeilog, legacy_mode=True)) elif com_method == "socket": engine_ctl = EngineController( SocketEngine(enginecmd, log=aeilog)) elif com_method == "stdio": engine_ctl = EngineController( StdioEngine(enginecmd, log=aeilog)) else: raise ValueError("Unrecognized communication method, %s" % (com_method)) except OSError, exc: log.error("Could not start the engine; exception thrown: %s", exc) sys.exit(1) try: for option in config.options(bot_section): if option.startswith("bot_"): value = config.get(bot_section, option) engine_ctl.setoption(option[4:], value) log.info("Setting bot option %s = %s", option[4:], value) engine_ctl.isready() bot_username = config.get(bot_section, "username") bot_password = config.get(bot_section, "password") bot_greeting = config.get(bot_section, "greeting") gameroom = GameRoom(config.get("global", "gameroom_url")) gameroom.login(bot_username, bot_password) side = options['side'] if side == "g": side = "w" elif side == "s": side = "b" table = None if gameid_or_opponent == "": log.info("Starting a new game") if side == "": side = 'b' timecontrol = config.get(bot_section, "timecontrol") rated = config.getboolean(bot_section, "rated") log.info("Will play on side %s, using timecontrol %s" % (side, timecontrol)) table = gameroom.newgame(side, timecontrol, rated) else: # look through my games for correct opponent and side games = gameroom.mygames() for game in games: if (gameid_or_opponent == game['player'].lower() or gameid_or_opponent == game['gid']): if (side == "" or side == game['side'] and not already_playing( run_dir, game['gid'], game['side'])): table = Table(gameroom, game) log.info("Found in progress game") break if table == None: games = gameroom.opengames() for game in games: if (gameid_or_opponent == game['player'].lower() or gameid_or_opponent == game['gid']): if (side == "" or side == game['side'] and not already_playing( run_dir, game['gid'], game['side'])): table = Table(gameroom, game) log.info("Found game to join") break if table == None: log.error("Could not find game against %s with side '%s'", gameid_or_opponent, side) engine_ctl.quit() engine_ctl.cleanup() break # Set the game to play in to current game id in case of a restart gameid_or_opponent = table.gid if options['against'] != "": joinmsg = "Joined game gid=%s side=%s; against %s" % ( table.gid, table.side, options['against']) else: joinmsg = "Created game gid=%s side=%s; waiting for opponent"\ % (table.gid, table.side) log.info(joinmsg) if console is None: print joinmsg # force the std streams to flush so the bot starter script used # on the arimaa.com server can pick up the join message sys.stdout.flush() sys.stderr.flush() if config.has_option(bot_section, "ponder"): table.ponder = config.getboolean(bot_section, "ponder") if table.ponder: log.info("Set pondering on.") else: log.info("Set pondering off.") else: table.ponder = False if config.has_option("global", "min_move_time"): table.min_move_time = config.getint("global", "min_move_time") log.info("Set minimum move time to %d seconds.", table.min_move_time) else: table.min_move_time = 5 if config.has_option("global", "min_time_left"): table.min_timeleft = config.getint("global", "min_time_left") log.info("Setting emergency stop time to %d seconds" % table.min_timeleft) else: table.min_timeleft = 5 except: shutdown_engine(engine_ctl) raise try: try: log.info("Joining game on %s side", table.side) table.reserveseat() table.sitdown() table.updatestate() engine_ctl.setoption("rated", table.state.get('rated', 1)) try: touch_run_file(run_dir, "%s%s.bot" % (table.gid, table.side)) time.sleep(1) # Give the server a small break. log.info("Starting play") table.playgame(engine_ctl, bot_greeting, options['onemove']) finally: log.info("Leaving game") remove_run_file(run_dir, "%s%s.bot" % (table.gid, table.side)) table.leave() break finally: shutdown_engine(engine_ctl) except (KeyboardInterrupt, SystemExit): raise except EngineCrashException, exc: log.error("Bot engine crashed (%s), restarting.", exc.args[0]) time.sleep(1)