def draw_everything(ai, tile_func): r, c = 23, 94 if sys.stdout.isatty(): try: r, c = map(int, os.popen('stty size', 'r').read().split()) except ValueError: pass r = min(r, ai.game.map_height + 2) lines = [['|'] + [' '] * (c - 2) + ['|'] for _ in range(r - 2)] things = {t: tile_func(t) for t in ai.game.tiles if tile_func(t)} for tile, s in things.items(): y = (tile.y * (r - 2)) // ai.game.map_height x = (tile.x * (c - 2)) // ai.game.map_width + 1 replace_line(lines[y], x, s) print('\033[2J\033[1;1H') # Clear screen, move cursor to 1,1 line = list('+' + '-' * (c - 2) + '+') replace_line( line, 2, background('red') + ai.game.players[0].name + reset() + '--' + background('red') + str(ai.game.players[0].score) + reset()) replace_line( line, c - 5, background('white') + text('black') + str(ai.game.current_turn) + reset()) print(''.join(line)) for line in lines: print(''.join(line)) line = list('+' + '-' * (c - 2) + '+') replace_line( line, 2, background('blue') + ai.game.players[1].name + reset() + '--' + background('blue') + str(ai.game.players[1].score) + reset()) print(''.join(line))
def connect(hostname='localhost', port=3000, print_io=False): _client.hostname = hostname _client.port = int(port) _client._print_io = print_io _client._received_buffer = "" _client._events_stack = [] _client._buffer_size = 1024 _client._timeout_time = 1.0 print( color.text('cyan') + 'Connecting to:', _client.hostname + ':' + str(_client.port) + color.reset()) try: _client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Silly Windows _client.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # so the blocking on recv doesn't hang forever and other system # interrupts (e.g. keyboard) can be handled _client.socket.settimeout(_client._timeout_time) _client.socket.connect((_client.hostname, _client.port)) except socket.error as e: error_code.handle_error( error_code.COULD_NOT_CONNECT, e, 'Could not connect to {}:{}'.format(_client.hostname, _client.port))
def wait_for_events(): if len(_client._events_stack) > 0: return # as we already have events to handle, no need to wait for more try: while True: sent = None try: sent = _client.socket.recv(_client._buffer_size).decode("utf-8") except socket.timeout: pass # timed out so keyboard/system interupts can be handled, hence the while true loop above except socket.error as e: error_code.handle_error(error_code.CANNOT_READ_SOCKET, e, "Error reading socket while waiting for events") if not sent: continue elif _client._print_io: print(color.text("magenta") + "FROM SERVER <-- " + str(sent) + color.reset()) split = (_client._received_buffer + sent).split(EOT_CHAR) _client._received_buffer = split.pop() # the last item will either be "" if the last char was an EOT_CHAR, or a partial data we need to buffer anyways for json_str in reversed(split): try: parsed = json.loads(json_str) except ValueError as e: error_code.handle_error(error_code.MALFORMED_JSON, e, "Could not parse json '" + json_str + "'") _client._events_stack.append(parsed) if len(_client._events_stack) > 0: return except (KeyboardInterrupt, SystemExit): disconnect()
def handle_error(error_code, e=None, message=None): if isinstance(e, SystemExit) or isinstance( e, KeyboardInterrupt ): # we accidentally caught an exit exception, just re-throw it till it gets to the end of the runtime stack sys.exit(e.code) import joueur.client # avoid circular imports (sphinx won't build docs otherwise) joueur.client.disconnect() sys.stderr.write( color.text("red") + "---\nError: {}\n---".format( _by_code[error_code] if error_code in _by_code else "UNKNOWN ERROR {}".format(error_code))) if message: sys.stderr.write("\n{}\n---".format(message)) if e: sys.stderr.write("\n{}\n---\n".format(str(e))) traceback.print_exc() sys.stderr.write("---") sys.stderr.write("\n" + color.reset()) os._exit(error_code)
def connect(server='localhost', port=3000, print_io=False): _client.server = server _client.port = int(port) _client._print_io = print_io _client._received_buffer = "" _client._events_stack = [] _client._buffer_size = 1024 _client._timeout_time = 1.0 print( color.text("cyan") + "Connecting to:", _client.server + ":" + str(_client.port) + color.reset()) try: _client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _client.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # stupid Windows _client.socket.settimeout( _client._timeout_time ) # so the blocking on recv doesn't hang forever and other system interupts (e.g. keyboard) can be handled _client.socket.connect((_client.server, _client.port)) except socket.error as e: error_code.handle_error( error_code.COULD_NOT_CONNECT, e, "Could not connect to " + _client.server + ":" + str(_client.port))
def run(args): split_server = args.server.split(":") args.server = split_server[0] args.port = int((len(split_server) == 2 and split[1])) or args.port joueur.client.connect(args.server, args.port, args.print_io) joueur.client.send("alias", args.game) game_name = joueur.client.wait_for_event("named") module_str = "games." + camel_case_converter(game_name) spec = importlib.util.find_spec(module_str) if spec is None: error_code.handle_error(error_code.GAME_NOT_FOUND, None, "Could not find the module for game '{}'.".format(game_name)) try: module = importlib.import_module(module_str) # should load Game and AI to load based on the game selected in args except ImportError as e: error_code.handle_error(error_code.REFLECTION_FAILED, e, "Could not import game module: '{}'.".format(module_str)) game = module.Game() try: ai = module.AI(game) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "Could not initialize AI class. Probably a syntax error in your AI.") manager = GameManager(game) joueur.client.setup(game, ai, manager) joueur.client.send("play", { 'gameName': game_name, 'password': args.password, 'requestedSession': args.session, 'clientType': "Python", 'playerName': args.name or ai.get_name() or "Python Player", 'playerIndex': args.index, 'gameSettings': args.game_settings }) lobby_data = joueur.client.wait_for_event("lobbied") print(color.text("cyan") + "In lobby for game '" + lobby_data['gameName'] + "' in session '" + lobby_data['gameSession'] + "'." + color.reset()) manager.set_constants(lobby_data['constants']) start_data = joueur.client.wait_for_event("start") print(color.text("green") + "Game is starting." + color.reset()) ai.set_player(game.get_game_object(start_data['playerID'])) try: ai.start() ai.game_updated() except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "AI errored during game initialization") joueur.client.play()
def _auto_handle_over(data): won = _client.ai.player.won reason = _client.ai.player.reason_won if _client.ai.player.won else _client.ai.player.reason_lost print( color.text("green") + "Game is over.", "I Won!" if won else "I Lost :(", "because: " + reason + color.reset()) try: _client.ai.end(won, reason) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), "AI errored during end.") if 'message' in data: print(color.text("cyan") + data['message'] + color.reset()) disconnect() os._exit(0)
def run(args): split_server = args.server.split(":") args.server = split_server[0] args.port = int((len(split_server) == 2 and split[1])) or args.port module_str = "games." + camel_case_converter(args.game) spec = importlib.util.find_spec(module_str) if spec is None: error_code.handle_error(error_code.GAME_NOT_FOUND, None, "Could not find the module for game '{}'.".format(args.game)) try: module = importlib.import_module(module_str) # should load Game and AI to load based on the game selected in args except ImportError as e: error_code.handle_error(error_code.REFLECTION_FAILED, e, "Could not import game module: '{}'.".format(module_str)) game = module.Game() try: ai = module.AI(game) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "Could not initialize AI class. Probably a syntax error in your AI.") manager = GameManager(game) joueur.client.setup(game, ai, manager, args.server, int(args.port), print_io=args.print_io) joueur.client.send("play", { 'gameName': game.name, 'password': args.password, 'requestedSession': args.session, 'clientType': "Python", 'playerName': args.name or ai.get_name() or "Python Player", 'playerIndex': args.index, 'gameSettings': args.game_settings }) lobby_data = joueur.client.wait_for_event("lobbied") print(color.text("cyan") + "In lobby for game '" + lobby_data['gameName'] + "' in session '" + lobby_data['gameSession'] + "'." + color.reset()) manager.set_constants(lobby_data['constants']) start_data = joueur.client.wait_for_event("start") print(color.text("green") + "Game is starting." + color.reset()) ai.set_player(game.get_game_object(start_data['playerID'])) try: ai.start() ai.game_updated() except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "AI errored during game initialization") joueur.client.play()
def _auto_handle_over(data): won = _client.ai.player.won reason = _client.ai.player.reason_won \ if _client.ai.player.won \ else _client.ai.player.reason_lost print('{}Game is Over. {} because {}{}'.format( color.text('green'), 'I Won!' if won else 'I Lost :(', reason, color.reset())) try: _client.ai.end(won, reason) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), 'AI errored during end.') if 'message' in data: message = data['message'].replace('__HOSTNAME__', _client.hostname) print(color.text('cyan') + message + color.reset()) disconnect() os._exit(0)
def general_tile_func(tile): if tile.furnishing: if tile.furnishing.is_piano: return '♬♪♬♪' else: return '┬─┬' elif tile.cowboy: b = background('red' if tile.cowboy.owner.id == '0' else 'blue') r = reset() shortname = {'Sharpshooter': 'S', 'Bartender': 'T', 'Brawler': 'B'} return b + shortname[tile.cowboy.job] + str(tile.cowboy.id) + r elif tile.young_gun: b = background('red' if tile.young_gun.owner.id == '0' else 'blue') r = reset() return b + 'Y-' + str(tile.young_gun.owner.id) + r elif tile.bottle: return ' [] ' elif tile.has_hazard: return 'xxx' elif tile.is_balcony: return '⋅⋅⋅' else: return ''
def _auto_handle_over(data): won = _client.ai.player.won reason = _client.ai.player.reason_won if _client.ai.player.won else _client.ai.player.reason_lost print(color.text("green") + "Game is over.", "I Won!" if won else "I Lost :(", "because: " + reason + color.reset()) try: _client.ai.end(won, reason) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), "AI errored during end.") if 'message' in data: print(color.text("cyan") + data['message'] + color.reset()) disconnect() os._exit(0)
def wait_for_events(): if len(_client._events_stack) > 0: return # as we already have events to handle, no need to wait for more try: while True: sent = None try: sent = _client.socket.recv(_client._buffer_size) \ .decode('utf-8') except socket.timeout: pass # timed out so keyboard/system interrupts can be handled, # hence the while true loop above except socket.error as e: error_code.handle_error( error_code.CANNOT_READ_SOCKET, e, 'Error reading socket while waiting for events') if not sent: continue elif _client._print_io: print( color.text('magenta') + 'FROM SERVER <-- ' + str(sent) + color.reset()) split = (_client._received_buffer + sent).split(EOT_CHAR) # the last item will either be "" if the last char was an EOT_CHAR, # or a partial data we need to buffer anyways _client._received_buffer = split.pop() for json_str in reversed(split): try: parsed = json.loads(json_str) except ValueError as e: error_code.handle_error( error_code.MALFORMED_JSON, e, 'Could not parse json ""'.format(json_str)) _client._events_stack.append(parsed) if len(_client._events_stack) > 0: return except (KeyboardInterrupt, SystemExit): disconnect()
def handle_error(error_code, e=None, message=None): if isinstance(e, SystemExit) or isinstance(e, KeyboardInterrupt): # we accidentally caught an exit exception, just re-throw it till it gets to the end of the runtime stack sys.exit(e.code) import joueur.client # avoid circular imports (sphinx won't build docs otherwise) joueur.client.disconnect() sys.stderr.write(color.text("red") + "---\nError: {}\n---".format(_by_code[error_code] if error_code in _by_code else "UNKNOWN ERROR {}".format(error_code))) if message: sys.stderr.write("\n{}\n---".format(message)) if e: sys.stderr.write("\n{}\n---\n".format(str(e))) traceback.print_exc() sys.stderr.write("---") sys.stderr.write("\n" + color.reset()) os._exit(error_code)
def invalid(self, message): print(color.text("yellow") + "Invalid: " + message + color.reset())
def _send_raw(string): if _client._print_io: print(color.text("magenta") + "TO SERVER --> " + str(string) + color.reset()) _client.socket.send(string)
def connect(server='localhost', port=3000, print_io=False): _client.server = server _client.port = int(port) _client._print_io = print_io _client._received_buffer = "" _client._events_stack = [] _client._buffer_size = 1024 _client._timeout_time = 1.0 print(color.text("cyan") + "Connecting to:", _client.server + ":" + str(_client.port) + color.reset()) try: _client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _client.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # stupid Windows _client.socket.settimeout(_client._timeout_time) # so the blocking on recv doesn't hang forever and other system interupts (e.g. keyboard) can be handled _client.socket.connect((_client.server, _client.port)) except socket.error as e: error_code.handle_error(error_code.COULD_NOT_CONNECT, e, "Could not connect to " + _client.server + ":" + str(_client.port))
def _send_raw(string): if _client._print_io: print( color.text('magenta') + 'TO SERVER --> ' + str(string) + color.reset()) _client.socket.send(string)
def _send_raw(string): if _client._print_io: print( color.text("magenta") + "TO SERVER --> " + str(string) + color.reset()) _client.socket.send(string)
def run(args): split_server = args.server.split(":") args.server = split_server[0] args.port = int((len(split_server) == 2 and split_server[1])) or args.port joueur.client.connect(args.server, args.port, args.print_io) joueur.client.send("alias", args.game) game_name = joueur.client.wait_for_event("named") module_str = "games." + camel_case_converter(game_name) spec = importlib.util.find_spec(module_str) if spec is None: error_code.handle_error( error_code.GAME_NOT_FOUND, None, 'Could not find the module for game "{}".'.format(game_name) ) try: # should load Game and AI to load based on the game selected in args module = importlib.import_module(module_str) except ImportError as e: error_code.handle_error( error_code.REFLECTION_FAILED, e, 'Could not import game module: "{}".'.format(module_str) ) game = module.Game() try: ai = module.AI(game) except: error_code.handle_error( error_code.AI_ERRORED, sys.exc_info()[0], 'Could not initialize the AI class. ' + 'Probably a syntax error in your AI.' ) manager = GameManager(game) joueur.client.setup(game, ai, manager) ai.set_settings(args.ai_settings) joueur.client.send("play", { 'gameName': game_name, 'password': args.password, 'requestedSession': args.session, 'clientType': "Python", 'playerName': args.name or ai.get_name() or "Python Player", 'playerIndex': args.index, 'gameSettings': args.game_settings }) lobby_data = joueur.client.wait_for_event("lobbied") if lobby_data['gameVersion'] != module.game_version: print("""{}WARNING: Game versions do not match. -> Your local game version is: {} -> Game Server's game version is: {} Version mismatch means that unexpected crashes may happen due to differing game structures!{}""".format( color.text('yellow'), str(module.game_version)[:8], str(lobby_data['gameVersion'])[:8], color.reset() ) ) print('{}In Lobby for game "{}" in session "{}".{}'.format( color.text("cyan"), lobby_data['gameName'], lobby_data['gameSession'], color.reset() ) ) manager.set_constants(lobby_data['constants']) start_data = joueur.client.wait_for_event("start") print(color.text("green") + "Game is starting." + color.reset()) ai.set_player(game.get_game_object(start_data['playerID'])) try: ai.start() ai.game_updated() except: error_code.handle_error( error_code.AI_ERRORED, sys.exc_info()[0], 'AI errored during game initialization' ) joueur.client.play()