import numpy as np from .helper_utils import recenter_view from .safelife_game import CellTypes, GameWithGoals background_colors = [ '\x1b[48;5;251m', # black / empty '\x1b[48;5;217m', # red '\x1b[48;5;114m', # green '\x1b[48;5;229m', # yellow '\x1b[48;5;117m', # blue '\x1b[48;5;183m', # magenta '\x1b[48;5;123m', # cyan '\x1b[48;5;255m', # white ] foreground_colors = [ '\x1b[38;5;0m', # black '\x1b[38;5;1m', # red '\x1b[38;5;2m', # green '\x1b[38;5;172m', # yellow '\x1b[38;5;12m', # blue '\x1b[38;5;129m', # magenta '\x1b[38;5;39m', # cyan '\x1b[38;5;244m', # white / gray ] def print_reward_table(): text = "" rewards = GameWithGoals.reward_table for r in range(8): text += background_colors[r] for c in range(8): text += foreground_colors[c] text += "{:2d} ".format(rewards[r,c]) text += '\x1b[0m\n' print(text) @np.vectorize def render_cell(cell, goal=0, orientation=0, edit_color=None): cell_color = (cell & CellTypes.rainbow_color) >> CellTypes.color_bit goal_color = (goal & CellTypes.rainbow_color) >> CellTypes.color_bit val = background_colors[goal_color] val += ' ' if edit_color is None else foreground_colors[edit_color] + '∎' val += foreground_colors[cell_color] if cell & CellTypes.agent: arrow = '⋀>⋁<'[orientation] val += '\x1b[1m' + arrow else: gray_cell = cell & ~CellTypes.rainbow_color val += { CellTypes.empty: '.' if cell_color else ' ', CellTypes.life: 'z', CellTypes.alive: 'Z', CellTypes.wall: '#', CellTypes.crate: '%', CellTypes.plant: '&', CellTypes.tree: 'T', CellTypes.ice_cube: '=', CellTypes.parasite: '!', CellTypes.weed: '@', CellTypes.spawner: 's', CellTypes.hard_spawner: 'S', CellTypes.level_exit: 'X', CellTypes.fountain: '\x1b[1m+', }.get(gray_cell, '?') return val + '\x1b[0m' def cell_name(cell): cell_type = { CellTypes.empty: 'empty', CellTypes.life: 'life', CellTypes.alive: 'hard-life', CellTypes.wall: 'wall', CellTypes.crate: 'crate', CellTypes.plant: 'plant', CellTypes.tree: 'tree', CellTypes.ice_cube: 'ice-cube', CellTypes.parasite: 'parasite', CellTypes.weed: 'weed', CellTypes.spawner: 'spawner', CellTypes.hard_spawner: 'hard-spawner', CellTypes.level_exit: 'exit', CellTypes.fountain: 'fountain', }.get(cell & ~CellTypes.rainbow_color, 'unknown') color = { 0: 'gray', CellTypes.color_r: 'red', CellTypes.color_g: 'green', CellTypes.color_b: 'blue', CellTypes.color_r | CellTypes.color_b: 'magenta', CellTypes.color_g | CellTypes.color_r: 'yellow', CellTypes.color_b | CellTypes.color_g: 'cyan', CellTypes.rainbow_color: 'white', }.get(cell & CellTypes.rainbow_color, 'x') return cell_type + '-' + color def render_board(board, goals=0, orientation=0, edit_loc=None, edit_color=0): """ Just render the board itself. Doesn't require game state. """ if edit_loc and (edit_loc[0] >= board.shape[0] or edit_loc[1] >= board.shape[1]): edit_loc = None goals = np.broadcast_to(goals, board.shape) screen = np.empty((board.shape[0]+2, board.shape[1]+3,), dtype=object) screen[:] = '' screen[0] = screen[-1] = ' -' screen[:,0] = screen[:,-2] = ' |' screen[:,-1] = '\n' screen[0,0] = screen[0,-2] = screen[-1,0] = screen[-1,-2] = ' +' screen[1:-1,1:-2] = render_cell(board, goals, orientation) if edit_loc: x1, y1 = edit_loc val = render_cell(board[y1, x1], goals[y1, x1], orientation, edit_color) screen[y1+1, x1+1] = str(val) return ''.join(screen.ravel()) def render_game(game, view_size=None, edit_mode=None): """ Render the game as an ansi string. Parameters ---------- game : SafeLifeGame instance view_size : (int, int) or None Shape of the view port, or None if the full board should be rendered. If not None, the view will be centered on either the agent or the current edit location. edit_mode : None, "BOARD", or "GOALS" Determines whether or not the game should be drawn in edit mode with the edit cursor. If "GOALS", the goals and normal board are swapped so that the goals can be edited directly. """ if view_size is not None: if edit_mode: center = game.edit_loc edit_loc = view_size[1] // 2, view_size[0] // 2 else: center = game.agent_loc edit_loc = None center = game.edit_loc if edit_mode else game.agent_loc board = recenter_view(game.board, view_size, center[::-1], game.exit_locs) goals = recenter_view(game.goals, view_size, center[::-1]) else: board = game.board goals = game.goals edit_loc = game.edit_loc if edit_mode else None edit_color = (game.edit_color & CellTypes.rainbow_color) >> CellTypes.color_bit if edit_mode == "GOALS": # Render goals instead. Swap board and goals. board, goals = goals, board return render_board(board, goals, game.orientation, edit_loc, edit_color) def agent_powers(game): x0, y0 = game.agent_loc agent = game.board[y0, x0] power_names = [ (CellTypes.alive, 'alive'), (CellTypes.preserving, 'preserving'), (CellTypes.inhibiting, 'inhibiting'), (CellTypes.spawning, 'spawning'), ] powers = [txt for val, txt in power_names if agent & val] return ', '.join(powers) or 'none' if __name__ == "__main__": print_reward_table()