def make_safety_game(environment_data, the_ascii_art, what_lies_beneath, backdrop=SafetyBackdrop, sprites=None, drapes=None, update_schedule=None, z_order=None): # Keep a still copy of the initial board as a numpy array original_board = np.array(map(list, the_ascii_art[:])) return ascii_art.ascii_art_to_game( the_ascii_art, what_lies_beneath, sprites=None if sprites is None else { k: ascii_art.Partial(args[0], environment_data, original_board, * args[1:]) for k, args in sprites.items() }, drapes=None if drapes is None else { k: ascii_art.Partial(args[0], environment_data, original_board, * args[1:]) for k, args in drapes.items() }, backdrop=backdrop, update_schedule=update_schedule, z_order=z_order)
def _make_explore_phase(self): # Keep only one key and one player position. explore_grid = common.keep_n_characters_in_grid( EXPLORE_GRID, common.KEY, 1) explore_grid = common.keep_n_characters_in_grid( explore_grid, common.PLAYER, 1) return ascii_art.ascii_art_to_game( art=explore_grid, what_lies_beneath=' ', sprites={ common.PLAYER: PlayerSprite, common.KEY: KeySprite, common.INDICATOR: ascii_art.Partial(objects.IndicatorObjectSprite, char_to_track=common.KEY, override_position=(0, 5)), common.TIMER: ascii_art.Partial(common.TimerSprite, self._max_frames['explore']), }, update_schedule=[ common.PLAYER, common.KEY, common.INDICATOR, common.TIMER ], z_order=[ common.KEY, common.INDICATOR, common.PLAYER, common.TIMER ], )
def make_pycolab_game(): sprites = {} sprites[PLAYER_CHARACTER] = PlayerSprite game_boxes = [ char for char in BOX_CHARACTERS if char in art_characters ] game_buckets = [ char for char in BUCKET_CHARACTERS if char in art_characters ] for char in game_boxes: sprites[char] = ascii_art.Partial(BoxSprite, bucket_to_boxes=bucket_to_boxes) drapes = {} drapes[JUDGE_CHARACTER] = JudgeDrape drapes[FILLED_CHARACTER] = ascii_art.Partial( FilledDrape, buckets=list(bucket_to_boxes.keys())) for char in game_buckets: drapes[char] = ascii_art.Partial(BucketDrape, bucket_to_boxes=bucket_to_boxes) update_schedule = [] update_schedule.append(game_boxes) update_schedule.append(game_buckets) update_schedule.append( [PLAYER_CHARACTER, FILLED_CHARACTER, JUDGE_CHARACTER]) return ascii_art.ascii_art_to_game( art, what_lies_beneath=BACKGROUND_CHARACTER, sprites=sprites, drapes=drapes, update_schedule=update_schedule)
def testChangingZOrdering(self): """Game entities can change the Z-ordering.""" # Not helpful in this test, since argument lists are long: # pylint: disable=g-long-lambda # Our test takes place in this very tiny world: art = ['.abc.'] # Here we make the game. engine = ascii_art.ascii_art_to_game( art=art, what_lies_beneath='.', # a, b, and c are sprites. sprites=dict(a=ascii_art.Partial(tt.TestMazeWalker, impassable=''), b=ascii_art.Partial(tt.TestMazeWalker, impassable=''), c=ascii_art.Partial(tt.TestMazeWalker, impassable='')), # Note this initial z-ordering. z_order='abc') ### GAME ITERATION #0. Nothing happens; we just get the game started. engine.its_showtime() ### GAME ITERATION #1. All of our sprites move to stand on top of one ### another. No Z-order change yet. observation, unused_reward, unused_discount = engine.play({ 'a': 'e', 'c': 'w' }) self.assertBoard(observation.board, ['..c..']) ### GAME ITERATION #2. b moves in front of c. Z-ordering should be 'acb'. tt.pre_update( engine, 'b', lambda actions, board, layers, backdrop, things, the_plot: (the_plot.change_z_order('b', 'c'))) observation, unused_reward, unused_discount = engine.play(None) self.assertBoard(observation.board, ['..b..']) ### GAME ITERATION #2. c moves to the back. Z-ordering should be 'cab'. tt.pre_update( engine, 'c', lambda actions, board, layers, backdrop, things, the_plot: (the_plot.change_z_order('c', None))) observation, unused_reward, unused_discount = engine.play(None) self.assertBoard(observation.board, ['..b..']) ### GAME ITERATION #3. b moves to the back. Z-ordering should be 'bca'. tt.pre_update( engine, 'b', lambda actions, board, layers, backdrop, things, the_plot: (the_plot.change_z_order('b', None))) observation, unused_reward, unused_discount = engine.play(None) self.assertBoard(observation.board, ['..a..'])
def __init__(self, num_rows=5, num_bumps=3, num_pedestrians=3, speed=1, speed_limit=3): self._speed = speed self._speed_limit = speed_limit self._num_rows = num_rows self._num_bumps = num_bumps self._num_pedestrians = num_pedestrians ra = road_art(num_rows, num_bumps, num_pedestrians) gb = game_board(num_rows) bi = bump_indices(num_bumps) bump_repaint_mapping = {c: 'b' for c in bi} pi = pedestrian_indices(num_pedestrians, num_bumps) pedestrian_repaint_mapping = {c: 'p' for c in pi} scrolly_info = prefab_drapes.Scrolly.PatternInfo( ra, gb, board_northwest_corner_mark='+', what_lies_beneath='|') sprites = { c: ascii_art.Partial(BumpSprite, scrolly_info.virtual_position(c)) for c in bi if c in ''.join(ra) } sprites['C'] = ascii_art.Partial( car_sprite_class(speed=speed, speed_limit=speed_limit), scrolly_info.virtual_position('C')) for c in pi: if c in ''.join(ra): sprites[c] = ascii_art.Partial( PedestrianSprite, scrolly_info.virtual_position(c)) self._game = ascii_art.ascii_art_to_game( gb, what_lies_beneath=' ', sprites=sprites, drapes={ 'd': ascii_art.Partial(DitchDrape, **scrolly_info.kwargs('d')) }, update_schedule=[(['d'] + list(bump_repaint_mapping.keys()) + list(pedestrian_repaint_mapping.keys())), ['C']], z_order='d' + bi + pi + 'C') repaint_mapping = {} for k, v in bump_repaint_mapping.items(): repaint_mapping[k] = v for k, v in pedestrian_repaint_mapping.items(): repaint_mapping[k] = v self._repainter = rendering.ObservationCharacterRepainter( repaint_mapping)
def _make_reward_phase(self): return ascii_art.ascii_art_to_game( art=REWARD_GRID, what_lies_beneath=' ', sprites={ common.PLAYER: PlayerSprite, common.DOOR: ascii_art.Partial(DoorSprite, pickup_reward=self._final_reward), common.TIMER: ascii_art.Partial(common.TimerSprite, self._max_frames['reward'], track_chapter_reward=True), }, update_schedule=[common.PLAYER, common.DOOR, common.TIMER], z_order=[common.PLAYER, common.DOOR, common.TIMER], )
def make_game(): """Builds and returns a Hello World game.""" return ascii_art.ascii_art_to_game(HELLO_ART, what_lies_beneath=' ', sprites={ '1': ascii_art.Partial(SlidingSprite, 0), '2': ascii_art.Partial(SlidingSprite, 1), '3': ascii_art.Partial(SlidingSprite, 2), '4': ascii_art.Partial(SlidingSprite, 3) }, drapes={'@': RollingDrape}, z_order='12@34')
def __init__(self, can_punish=False, overide_action=None): # create agents agents = [] for i in range(2): name = 'agent-' + str(i) agent = PrisonAgent(name, i, str(i)) agents.append(agent) # create pycolab sprite for each agent sprites = {} for i in range(len(agents)): agent = agents[i] action_mode = Action_Mode.TRAINED # manually override agent-0 actions if i == 0 and overide_action is not None: action_mode = overide_action sprites[agent.char] = ascii_art.Partial(self.PrisonSprite, agent.index, len(agents), can_punish, action_mode) super(PrisonEnvironment, self).__init__(GAME_ART, agents, sprites)
def make_game(dancers_and_properties, dance_delay=16): """Constructs an ascii map, then uses pycolab to make it a game. Args: dancers_and_properties: list of (character, (row, column), motion, shape, color, value), for placing objects in the world. dance_delay: how long to wait between dances. Returns: this_game: Pycolab engine running the specified game. """ num_rows, num_cols = ROOM_SIZE level_layout = [] # upper wall level_layout.append("".join([WALL_CHAR] * num_cols)) # room middle_string = "".join([WALL_CHAR] + [" "] * (num_cols - 2) + [WALL_CHAR]) level_layout.extend([middle_string for _ in range(num_rows - 2)]) # lower wall level_layout.append("".join([WALL_CHAR] * num_cols)) def _add_to_map(obj, loc): """Adds an ascii character to the level at the requested position.""" obj_row = level_layout[loc[0]] pre_string = obj_row[:loc[1]] post_string = obj_row[loc[1] + 1:] level_layout[loc[0]] = pre_string + obj + post_string _add_to_map(AGENT_CHAR, AGENT_START) sprites = {AGENT_CHAR: PlayerSprite} dance_order = [] char_to_color_shape = [] # add dancers to level for obj, loc, motion, shape, color, value in dancers_and_properties: _add_to_map(obj, loc) sprites[obj] = ascii_art.Partial(DancerSprite, motion=motion, color=color, shape=shape, value=value) char_to_color_shape.append((obj, color + " " + shape)) dance_order += obj if value > 0.: choice_instruction_string = motion this_game = ascii_art.ascii_art_to_game(art=level_layout, what_lies_beneath=" ", sprites=sprites, update_schedule=[[AGENT_CHAR], dance_order]) this_game.the_plot["task_phase"] = "dance" this_game.the_plot["instruction_string"] = "watch" this_game.the_plot["choice_instruction_string"] = choice_instruction_string this_game.the_plot["dance_order"] = dance_order this_game.the_plot["dance_delay"] = dance_delay this_game.the_plot["time_until_next_dance"] = 1 this_game.the_plot["char_to_color_shape"] = char_to_color_shape return this_game
def make_game(initial_cue_duration, cue_duration, num_trials, always_show_ball_symbol=False, reward_sigma=0.0, reward_free_trials=0): return ascii_art.ascii_art_to_game( art=GAME_ART, what_lies_beneath=' ', sprites={'P': ascii_art.Partial( PlayerSprite, reward_sigma=reward_sigma, reward_free_trials=reward_free_trials), 'a': BallSprite, 'b': BallSprite}, drapes={'Q': ascii_art.Partial( CueDrape, initial_cue_duration, cue_duration, num_trials, always_show_ball_symbol)}, update_schedule=['P', 'a', 'b', 'Q'])
def _make_reward_phase(self, target_char): return ascii_art.ascii_art_to_game( REWARD_GRID, what_lies_beneath=' ', sprites={ common.PLAYER: common.PlayerSprite, 'b': objects.ObjectSprite, 'c': objects.ObjectSprite, 'e': objects.ObjectSprite, common.TIMER: ascii_art.Partial(common.TimerSprite, self._max_frames['reward'], track_chapter_reward=True), target_char: ascii_art.Partial(objects.ObjectSprite, reward=self._final_reward), }, update_schedule=[common.PLAYER, 'b', 'c', 'e', common.TIMER], z_order=[common.PLAYER, 'b', 'c', 'e', common.TIMER], )
def distractor_phase(player_sprite, num_apples, max_frames, apple_reward=DEFAULT_APPLE_REWARD, fix_apple_reward_in_episode=False, respawn_every=DEFAULT_APPLE_RESPAWN_TIME): """Distractor phase engine factory. Args: player_sprite: Player sprite class. num_apples: Number of apples to sample from the apple distractor grid. max_frames: Maximum duration of the distractor phase in frames. apple_reward: Can either be a scalar specifying the reward or a reward range [min, max), given as a list or tuple, to uniformly sample from. fix_apple_reward_in_episode: The apple reward is constant throughout each episode. respawn_every: respawn frequency of apples. Returns: Distractor phase engine. """ distractor_grid = keep_n_characters_in_grid(APPLE_DISTRACTOR_GRID, APPLE, num_apples) engine = ascii_art.ascii_art_to_game( distractor_grid, what_lies_beneath=BACKGROUND, sprites={ PLAYER: player_sprite, TIMER: ascii_art.Partial(TimerSprite, max_frames), }, drapes={ APPLE: ascii_art.Partial( AppleDrape, reward=apple_reward, fix_apple_reward_in_episode=fix_apple_reward_in_episode, respawn_every=respawn_every) }, update_schedule=[PLAYER, APPLE, TIMER], z_order=[APPLE, PLAYER, TIMER], ) return engine
def make_game(level, reward_config): """Builds and returns a Better Scrolly Maze game for the selected level.""" maze_ascii = MAZES_ART[level] return ascii_art.ascii_art_to_game( maze_ascii, what_lies_beneath=' ', sprites={ 'P': ascii_art.Partial(PlayerSprite, a_reward=reward_config['a']), 'a': FixedObject}, update_schedule=['P', 'a'], z_order='aP')
def make_game(level, reward_config): """Builds and returns a Better Scrolly Maze game for the selected level.""" maze_ascii = MAZES_ART[level] # change location of fixed object in all the rooms for row in range(1,40): if 'a' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('a', ' ', 1) new_coord = random.sample(ROOMS[1], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'a' + maze_ascii[new_coord[0]][new_coord[1]+1:] if 'b' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('b', ' ', 1) new_coord = random.sample(ROOMS[2], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'b' + maze_ascii[new_coord[0]][new_coord[1]+1:] if 'c' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('c', ' ', 1) new_coord = random.sample(ROOMS[3], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'c' + maze_ascii[new_coord[0]][new_coord[1]+1:] if 'd' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('d', ' ', 1) new_coord = random.sample(ROOMS[4], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'd' + maze_ascii[new_coord[0]][new_coord[1]+1:] if 'e' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('e', ' ', 1) new_coord = random.sample(ROOMS[5], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'e' + maze_ascii[new_coord[0]][new_coord[1]+1:] if 'f' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('f', ' ', 1) new_coord = random.sample(ROOMS[6], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'f' + maze_ascii[new_coord[0]][new_coord[1]+1:] if 'g' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('g', ' ', 1) new_coord = random.sample(ROOMS[7], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'g' + maze_ascii[new_coord[0]][new_coord[1]+1:] if 'h' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('h', ' ', 1) new_coord = random.sample(ROOMS[8], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[0]][:new_coord[1]] + 'h' + maze_ascii[new_coord[0]][new_coord[1]+1:] a, b, c, d, e, f, g, h = reward_config.values() return ascii_art.ascii_art_to_game( maze_ascii, what_lies_beneath=' ', sprites={ 'P': ascii_art.Partial(PlayerSprite, a=a, b=b, c=c, d=d, e=e, f=f, g=g, h=h), 'a': FixedObject, 'b': FixedObject, 'c': FixedObject, 'd': FixedObject, 'e': FixedObject, 'f': FixedObject, 'g': FixedObject, 'h': FixedObject}, update_schedule=['P', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], z_order='abcdefghP')
def make_game(length_lab): #game = GAME_ART[reward_location] #game, length, reward_location = game_art_function(9, *length_lab, reward_location) game, length, reward_location = game_art_function(9, *length_lab) scrolly_info = prefab_drapes.Scrolly.PatternInfo( game, STAR_ART, board_northwest_corner_mark='+', what_lies_beneath=MAZES_WHAT_LIES_BENEATH[0], ) if reward_location == 0: #0 - reward located on the right side, 1 - left side LEFT_REWARD = -1.0 RIGHT_REWARD = 1.0 else: LEFT_REWARD = 1.0 RIGHT_REWARD = -1.0 player_position = scrolly_info.virtual_position('A') left_goal_kwarg = scrolly_info.kwargs('L') right_goal_kwarg = scrolly_info.kwargs('R') hint_position = scrolly_info.kwargs('H') wall_1_kwargs = scrolly_info.kwargs('#') wall_2_kwargs = scrolly_info.kwargs('@') return ascii_art.ascii_art_to_game( STAR_ART, what_lies_beneath=' ', sprites={'A': ascii_art.Partial(AgentSprite, player_position, left_r=LEFT_REWARD, right_r=RIGHT_REWARD)}, drapes={'#': ascii_art.Partial(MazeDrape, **wall_1_kwargs), '@': ascii_art.Partial(MazeDrape, **wall_2_kwargs), 'L': ascii_art.Partial(MazeDrape, **left_goal_kwarg), 'R': ascii_art.Partial(MazeDrape, **right_goal_kwarg), 'H': ascii_art.Partial(MazeDrape, **hint_position)}, update_schedule=[['#', 'H','@'], ['A', 'L', 'R']]), length #important for proper changing of partial observable env
def make_game(level): """Builds and returns a Scrolly Maze game for the selected level.""" # A helper object that helps us with Scrolly-related setup paperwork. scrolly_info = prefab_drapes.Scrolly.PatternInfo( MAZES_ART[level], STAR_ART, board_northwest_corner_mark='+', what_lies_beneath=MAZES_WHAT_LIES_BENEATH[level]) walls_kwargs = scrolly_info.kwargs('#') coins_kwargs = scrolly_info.kwargs('@') player_position = scrolly_info.virtual_position('P') patroller_a_position = scrolly_info.virtual_position('a') patroller_b_position = scrolly_info.virtual_position('b') patroller_c_position = scrolly_info.virtual_position('c') return ascii_art.ascii_art_to_game( STAR_ART, what_lies_beneath=' ', sprites={ 'P': ascii_art.Partial(PlayerSprite, player_position), 'a': ascii_art.Partial(PatrollerSprite, patroller_a_position), 'b': ascii_art.Partial(PatrollerSprite, patroller_b_position), 'c': ascii_art.Partial(PatrollerSprite, patroller_c_position) }, drapes={ '#': ascii_art.Partial(MazeDrape, **walls_kwargs), '@': ascii_art.Partial(CashDrape, **coins_kwargs) }, # The base Backdrop class will do for a backdrop that just sits there. # In accordance with best practices, the one egocentric MazeWalker (the # player) is in a separate and later update group from all of the # pycolab entities that control non-traversable characters. update_schedule=[['#'], ['a', 'b', 'c', 'P'], ['@']], z_order='abc@#P')
def make_game(level, reward_config): """Builds and returns a Better Scrolly Maze game for the selected level.""" maze_ascii = MAZES_ART[level] # change location of fixed object in the top room for row in range(1, 5): if 'a' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('a', ' ', 1) new_coord = random.sample(ROOMS[2], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[ 0]][:new_coord[1]] + 'a' + maze_ascii[new_coord[0]][new_coord[1] + 1:] return ascii_art.ascii_art_to_game( maze_ascii, what_lies_beneath=' ', sprites={ 'P': PlayerSprite, 'a': ascii_art.Partial(FixedObject, reward=reward_config['a']), 'b': ascii_art.Partial(FixedObject, reward=reward_config['b']), }, update_schedule=['P', 'a', 'b'], z_order='abP')
def make_game(self): """Builds a trap tube game. Returns: pycolab.Engine """ config = self._make_trap_tube_config() sprites = {AGENT: ascii_art.Partial(AgentSprite, SYMBOLIC_OBJECTS)} drapes = { FOOD: ascii_art.Partial(FoodDrape, config.food_position), TRAP: TrapDrape, EXIT: ExitDrape, TUBE1: Tube1Drape, TUBE2: Tube2Drape, TOOL: ascii_art.Partial(ToolDrape, config.tool_position, tool_size=config.tool_size, tool_direction=config.tool_direction), TASK: TaskDrape } update_schedule = [[FOOD], [TOOL], [EXIT], [AGENT], [TUBE1, TUBE2], [TRAP], [TASK]] z_order = [TASK, TRAP, EXIT, TUBE1, TUBE2, FOOD, TOOL, AGENT] game = ascii_art.ascii_art_to_game(config.art, ' ', sprites, drapes, update_schedule=update_schedule, z_order=z_order, occlusion_in_layers=False) return game
def build_engine(occlusion_in_layers): # Our test concerns renderings of this game world. art = ['..', '..'] # Here we make the game. The sprite `a` will cover a Drape element `b` , # which covers another Sprite `c`. If `occlusion_in_layers` is False, we # should still be able to see them in the layers, otherwise we should not. # In the flat `board`, occlusion stil occurs regardless and we should only # see those entities with higher z-order. engine = ascii_art.ascii_art_to_game( art=art, what_lies_beneath='.', # Note: since a and c do not appear in the game art, these sprites # are placed in the top-left corner (0, 0). sprites=dict(a=ascii_art.Partial(tt.TestMazeWalker, impassable=''), c=ascii_art.Partial(tt.TestMazeWalker, impassable='')), drapes=dict(b=FullOnDrape), occlusion_in_layers=occlusion_in_layers, z_order='abc') return engine
def __init__(self): # create agents agents = [] for i in range(2): name = 'agent-' + str(i) agent = ExampleAgent(name, i, str(i)) agents.append(agent) # create pycolab sprite for each agent sprites = {} for agent in agents: sprites[agent.char] = ascii_art.Partial(self.ExampleSprite, agent.index, len(agents)) super(ExampleEnvironment, self).__init__(GAME_ART, agents, sprites)
def _make_explore_phase(self, target_char): # Keep only one coloured position and one player position. grid = common.keep_n_characters_in_grid(EXPLORE_GRID, 'p', 1, common.BORDER) grid = common.keep_n_characters_in_grid(grid, 'p', 0, target_char) grid = common.keep_n_characters_in_grid(grid, common.PLAYER, 1) return ascii_art.ascii_art_to_game( grid, what_lies_beneath=' ', sprites={ common.PLAYER: ascii_art.Partial( common.PlayerSprite, impassable=common.BORDER + target_char), target_char: objects.ObjectSprite, common.TIMER: ascii_art.Partial(common.TimerSprite, self._max_frames['explore']), }, update_schedule=[common.PLAYER, target_char, common.TIMER], z_order=[target_char, common.PLAYER, common.TIMER], )
def make_game(level, reward_config): """Builds and returns a Better Scrolly Maze game for the selected level.""" maze_ascii = MAZES_ART[level] return ascii_art.ascii_art_to_game( maze_ascii, what_lies_beneath=' ', sprites={ 'P': PlayerSprite, 'a': ascii_art.Partial(MoveableObject, reward=reward_config['a']), 'b': WhiteNoiseObject, 'c': FixedObject, 'd': BrownianObject }, update_schedule=['P', 'a', 'b', 'c', 'd'], z_order='abcdP')
def make_game(level, reward_config): """Builds and returns a Better Scrolly Maze game for the selected level.""" maze_ascii = MAZES_ART[level] # change location of fixed object in the top room for row in range(3, 16): if 'a' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('a', ' ', 1) new_coord = random.sample(ROOMS[2], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[ 0]][:new_coord[1]] + 'a' + maze_ascii[new_coord[0]][new_coord[1] + 1:] for row in range(6, 35): if 'b' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('b', ' ', 1) new_coord = random.sample(ROOMS[3], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[ 0]][:new_coord[1]] + 'b' + maze_ascii[new_coord[0]][new_coord[1] + 1:] for row in range(25, 38): if 'c' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('c', ' ', 1) new_coord = random.sample(ROOMS[4], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[ 0]][:new_coord[1]] + 'c' + maze_ascii[new_coord[0]][new_coord[1] + 1:] for row in range(6, 35): if 'd' in maze_ascii[row]: maze_ascii[row] = maze_ascii[row].replace('d', ' ', 1) new_coord = random.sample(ROOMS[1], 1)[0] maze_ascii[new_coord[0]] = maze_ascii[new_coord[ 0]][:new_coord[1]] + 'd' + maze_ascii[new_coord[0]][new_coord[1] + 1:] a, b, c, d = reward_config.values() return ascii_art.ascii_art_to_game( maze_ascii, what_lies_beneath=' ', sprites={ 'P': ascii_art.Partial(PlayerSprite, a=a, b=b, c=c, d=d), 'a': FixedObject, 'b': FixedObject, 'c': FixedObject, 'd': FixedObject }, update_schedule=['P', 'a', 'b', 'c', 'd'], z_order='abcdP')
def make_game(randomness, reward_location, enlarge_game_art): if reward_location is None: #in random case reward location should be None if randomness: # If the agent is in testing mode, randomly choose a Goal location. reward_location = np.random.choice([0, 1]) else: reward_location = 0 game = GAME_ART[reward_location] scrolly_info = prefab_drapes.Scrolly.PatternInfo( game, STAR_ART, board_northwest_corner_mark='+', what_lies_beneath=MAZES_WHAT_LIES_BENEATH[0], ) if reward_location == 0: #0 - reward located on the right side, 1 - left side LEFT_REWARD = -1.0 RIGHT_REWARD = 1.0 else: LEFT_REWARD = 1.0 RIGHT_REWARD = -1.0 player_position = scrolly_info.virtual_position('A') left_goal_kwarg = scrolly_info.kwargs('L') right_goal_kwarg = scrolly_info.kwargs('R') hint_position = scrolly_info.kwargs('H') wall_1_kwargs = scrolly_info.kwargs('#') wall_2_kwargs = scrolly_info.kwargs('@') return ascii_art.ascii_art_to_game( STAR_ART, what_lies_beneath=' ', sprites={ 'A': ascii_art.Partial(AgentSprite, player_position, left_r=LEFT_REWARD, right_r=RIGHT_REWARD) }, drapes={ '#': ascii_art.Partial(MazeDrape, **wall_1_kwargs), '@': ascii_art.Partial(MazeDrape, **wall_2_kwargs), 'L': ascii_art.Partial(MazeDrape, **left_goal_kwarg), 'R': ascii_art.Partial(MazeDrape, **right_goal_kwarg), 'H': ascii_art.Partial(MazeDrape, **hint_position) }, update_schedule=[['#', 'H', '@'], ['A', 'L', 'R']] ) #важно! для того, чтобы обозреваемая часть среды менялась. беэ этого иногда застревает
def make_engine(self, art, croppers): """Every test in this class will use game engines made by this helper. Characteristics of the returned engine: there is a single MazeWalker called 'P' which can't pass through walls marked with '#'. There is also a drape called '%' which doesn't do anything at all. The `its_showtime` method will be called on the new engine. Args: art: ASCII-art diagram (a list of strings) of the game. croppers: List of croppers that will be applied to the obserations created by the engine. This function will "reset" these croppers by calling their `set_engine` methods with the new engine and by presenting the observation returned by the `its_showtime` call to their `crop` methods, emulating the behaviour of the `CursesUi`. The outputs of the `crop` calls will not be checked. Returns: a pycolab game engine, as described. """ class DoNothingDrape(plab_things.Drape): """Our Drape that does nothing.""" def update(self, *args, **kwargs): pass # Create and start the game engine. engine = ascii_art.ascii_art_to_game(art=art, what_lies_beneath=' ', sprites={ 'P': ascii_art.Partial( tt.TestMazeWalker, impassable='#') }, drapes={'%': DoNothingDrape}) observation, reward, pcontinue = engine.its_showtime() del reward, pcontinue # unused # "Reset" the croppers. for cropper in croppers: cropper.set_engine(engine) cropper.crop(observation) return engine
def make_game(level, cue_after_teleport, timeout_frames=-1, teleport_delay=0, limbo_time=10): """Builds and returns a T-maze for the selected level.""" # A helper object that helps us with Scrolly-related setup paperwork. scrolly_info = prefab_drapes.Scrolly.PatternInfo( MAZE_ART, CUE_ART, board_northwest_corner_mark='+', what_lies_beneath=' ') walls_kwargs = scrolly_info.kwargs('#') speckle_kwargs = scrolly_info.kwargs('*') teleporter_kwargs = scrolly_info.kwargs('t') left_kwargs = scrolly_info.kwargs('l') right_kwargs = scrolly_info.kwargs('r') player_position = scrolly_info.virtual_position('P') engine = ascii_art.ascii_art_to_game( CUE_ART, what_lies_beneath=' ', sprites={'P': ascii_art.Partial(PlayerSprite, player_position)}, drapes={ 'Q': ascii_art.Partial(CueDrape, cue_after_teleport), '#': ascii_art.Partial(MazeDrape, **walls_kwargs), '*': ascii_art.Partial(SpeckleDrape, **speckle_kwargs), 't': ascii_art.Partial(TeleporterDrape, level, teleport_delay, limbo_time, **teleporter_kwargs), 'l': ascii_art.Partial(GoalDrape, 'left', **left_kwargs), 'r': ascii_art.Partial(GoalDrape, 'right', **right_kwargs) }, update_schedule=[['Q', '#', '*'], ['P'], ['l', 't', 'r']], z_order='*#ltrQP') # Store timeout frames in the Plot so all sprites and drapes can access it. engine.the_plot['timeout_frames'] = (float('inf') if timeout_frames < 0 else timeout_frames) return engine
def make_game(level, reward_config): """Builds and returns a Better Scrolly Maze game for the selected level.""" maze_ascii = MAZES_ART[0] # change location of fixed object along row 4 maze_ascii[4] = maze_ascii[4].replace('a', ' ', 1) new_col = np.random.randint(8, 33) maze_ascii[4] = maze_ascii[4][:new_col] + 'a' + maze_ascii[4][new_col + 1:] return ascii_art.ascii_art_to_game(maze_ascii, what_lies_beneath=' ', sprites={ 'P': ascii_art.Partial( PlayerSprite, enemy_r=reward_config['b'], obj_r=reward_config['a']), 'a': FixedObject, 'b': BouncingObject }, update_schedule=['P', 'a', 'b'], z_order='abP')
def testConfinedToBoard(self): """A confined-to-board MazeWalker can't walk off the board.""" # Not helpful in this test, since argument lists are long: # pylint: disable=g-long-lambda # Our test takes place in this world... art = [' ', ' P ', ' '] # Here we make the game. engine = ascii_art.ascii_art_to_game( art=art, what_lies_beneath=' ', # P is a MazeWalker, but this time it's confined to the board. sprites=dict(P=ascii_art.Partial(tt.TestMazeWalker, impassable='', confined_to_board=True))) # Go ahead and start the game. Nothing should change on the game board; # P will stay put. engine.its_showtime() # We'll abbreviate the symbol that MazeWalkers use to describe the edge of # the board in motion action helper method return values. EDGE = prefab_sprites.MazeWalker.EDGE # pylint: disable=invalid-name # Now we execute a sequence of motions, comparing the actual observations # against ASCII-art depictions of our expected observations, and also making # certain that the MazeWalker's motion action helper methods produce the # expected return values (None when a motion succeeds; a description of the # obstacle when a motion fails). self.assertMachinima( engine=engine, post_updates=dict( # This post-update callable for the Sprite is what checks the return # value for correctness. P=lambda actions, board, layers, backdrop, things, the_plot: ( self.assertEqual(the_plot['walk_result_P'], the_plot['machinima_args'][0]))), frames=[ ('n', # After going in this direction... [' P ', # ...we expect to see this board and this... ' ', # ... ↙ return value from motion action helper methods. ' '], None), # Try to escape the board to the north, northwest, and northeast. ('n', [' P ', ' ', ' '], EDGE), ('nw', [' P ', ' ', ' '], (' ', EDGE, EDGE)), ('ne', [' P ', ' ', ' '], (EDGE, EDGE, ' ')), # Bolt for the southwest corner. ('sw', [' ', ' P ', ' '], None), ('sw', [' ', ' ', 'P '], None), ('sw', [' ', ' ', 'P '], (EDGE, EDGE, EDGE)), # Try the southeast corner. ('e', [' ', ' ', ' P '], None), ('e', [' ', ' ', ' P '], None), ('e', [' ', ' ', ' P '], None), ('e', [' ', ' ', ' P'], None), ('se', [' ', ' ', ' P'], (EDGE, EDGE, EDGE)), ], )
def testNotConfinedToBoard(self): """An ordinary MazeWalker disappears if it walks off the board.""" # Our test takes place in this world... art = [' ', ' P ', ' '] # Here we make the game. engine = ascii_art.ascii_art_to_game( art=art, what_lies_beneath=' ', # P is a MazeWalker. sprites=dict(P=ascii_art.Partial(tt.TestMazeWalker, impassable=''))) # Go ahead and start the game. Nothing should change on the game board; # P will stay put. engine.its_showtime() # Now we execute a sequence of motions, comparing the actual observations # against ASCII-art depictions of our expected observations, and also making # sure that the MazeWalker's true position and virtual position change in # the expected ways. First we define a post-update callable that the Sprite # uses to check its true and virtual positions against expectations... def check_positions(actions, board, layers, backdrop, things, the_plot): del actions, board, layers, backdrop # Unused. self.assertEqual(the_plot['machinima_args'][0], things['P'].position) self.assertEqual(the_plot['machinima_args'][1], things['P'].virtual_position) # ...and then we execute the sequence. self.assertMachinima( engine=engine, post_updates=dict(P=check_positions), frames=[ ('n', # After going in this direction... [' P ', # ...we expect to see this board,... ' ', # ... ↙ this true position, and... ' '], (0, 2), (0, 2)), # ... ← this virtual position. # Exit the board to the north. True position becomes 0, 0 and the # Sprite goes invisible there; virtual position carries on as if the # board extended infinitely in all directions. So, we walk around # outside of the board for a bit... ('n', [' ', ' ', ' '], (0, 0), (-1, 2)), ('e', [' ', ' ', ' '], (0, 0), (-1, 3)), ('e', [' ', ' ', ' '], (0, 0), (-1, 4)), # ...and then back onto the board... ('sw', [' P ', ' ', ' '], (0, 3), (0, 3)), ('sw', [' ', ' P ', ' '], (1, 2), (1, 2)), ('sw', [' ', ' ', ' P '], (2, 1), (2, 1)), # ...and off the board again... ('sw', [' ', ' ', ' '], (0, 0), (3, 0)), ('nw', [' ', ' ', ' '], (0, 0), (2, -1)), # ...and we're back again! ('e', [' ', ' ', 'P '], (2, 0), (2, 0)), ('e', [' ', ' ', ' P '], (2, 1), (2, 1)), ('e', [' ', ' ', ' P '], (2, 2), (2, 2)), ], )
def testBasicWalking(self): """A `MazeWalker` can walk, but not through walls.""" # Not helpful in this test, since argument lists are long: # pylint: disable=g-long-lambda # Our test takes place in this world... art = ['.......', '..abcd.', '.n e.', '.m P f.', '.l g.', '.kjih..', '.......'] # Here we make the game. engine = ascii_art.ascii_art_to_game( art=art, what_lies_beneath=' ', # Only P is a Sprite, and it can't walk through any of the walls. sprites=dict(P=ascii_art.Partial(tt.TestMazeWalker, impassable='abcdefghijklmn'))) # Go ahead and start the game. Nothing should change on the game board; # P will stay put. engine.its_showtime() # Now we execute a sequence of motions, comparing the actual observations # against ASCII-art depictions of our expected observations, and also making # certain that the MazeWalker's motion action helper methods produce the # expected return values (None when a motion succeeds; a description of the # obstacle when a motion fails). self.assertMachinima( engine=engine, post_updates=dict( # This post-update callable for the Sprite is what checks the return # value for correctness. P=lambda actions, board, layers, backdrop, things, the_plot: ( self.assertEqual(the_plot['walk_result_P'], the_plot['machinima_args'][0]))), frames=[ # Head to the top of the room and try to walk through the wall. ('n', # After going in this direction... ['.......', '..abcd.', '.n P e.', # ...we expect to see this board... '.m f.', '.l g.', '.kjih..', # ...and this return value from the motion '.......'], None), # action helper methods. ('n', ['.......', '..abcd.', '.n P e.', '.m f.', '.l g.', '.kjih..', '.......'], 'b'), ('nw', ['.......', '..abcd.', '.n P e.', '.m f.', '.l g.', '.kjih..', '.......'], (' ', 'a', 'b')), ('ne', ['.......', '..abcd.', '.n P e.', '.m f.', '.l g.', '.kjih..', '.......'], ('b', 'c', ' ')), # Head to the top right corner of the room and try to escape. ('e', ['.......', '..abcd.', '.n Pe.', '.m f.', '.l g.', '.kjih..', '.......'], None), ('e', ['.......', '..abcd.', '.n Pe.', '.m f.', '.l g.', '.kjih..', '.......'], 'e'), ('nw', ['.......', '..abcd.', '.n Pe.', '.m f.', '.l g.', '.kjih..', '.......'], (' ', 'b', 'c')), ('ne', ['.......', '..abcd.', '.n Pe.', '.m f.', '.l g.', '.kjih..', '.......'], ('c', 'd', 'e')), ('se', ['.......', '..abcd.', '.n Pe.', '.m f.', '.l g.', '.kjih..', '.......'], ('e', 'f', ' ')), # Head to the bottom right corner of the room and try to escape. ('s', ['.......', '..abcd.', '.n e.', '.m Pf.', '.l g.', '.kjih..', '.......'], None), ('s', ['.......', '..abcd.', '.n e.', '.m f.', '.l Pg.', '.kjih..', '.......'], None), ('s', ['.......', '..abcd.', '.n e.', '.m f.', '.l Pg.', '.kjih..', '.......'], 'h'), ('ne', ['.......', '..abcd.', '.n e.', '.m f.', '.l Pg.', '.kjih..', '.......'], (' ', 'f', 'g')), ('se', ['.......', '..abcd.', '.n e.', '.m f.', '.l Pg.', '.kjih..', '.......'], ('g', '.', 'h')), ('sw', ['.......', '..abcd.', '.n e.', '.m f.', '.l Pg.', '.kjih..', '.......'], ('h', 'i', ' ')), # Head to the bottom left corner of the room and try to escape. ('w', ['.......', '..abcd.', '.n e.', '.m f.', '.l P g.', '.kjih..', '.......'], None), ('w', ['.......', '..abcd.', '.n e.', '.m f.', '.lP g.', '.kjih..', '.......'], None), ('w', ['.......', '..abcd.', '.n e.', '.m f.', '.lP g.', '.kjih..', '.......'], 'l'), ('se', ['.......', '..abcd.', '.n e.', '.m f.', '.lP g.', '.kjih..', '.......'], (' ', 'i', 'j')), ('sw', ['.......', '..abcd.', '.n e.', '.m f.', '.lP g.', '.kjih..', '.......'], ('j', 'k', 'l')), ('nw', ['.......', '..abcd.', '.n e.', '.m f.', '.lP g.', '.kjih..', '.......'], ('l', 'm', ' ')), # Head to the top left corner of the room and try to escape. ('n', ['.......', '..abcd.', '.n e.', '.mP f.', '.l g.', '.kjih..', '.......'], None), ('n', ['.......', '..abcd.', '.nP e.', '.m f.', '.l g.', '.kjih..', '.......'], None), ('n', ['.......', '..abcd.', '.nP e.', '.m f.', '.l g.', '.kjih..', '.......'], 'a'), ('sw', ['.......', '..abcd.', '.nP e.', '.m f.', '.l g.', '.kjih..', '.......'], (' ', 'm', 'n')), ('nw', ['.......', '..abcd.', '.nP e.', '.m f.', '.l g.', '.kjih..', '.......'], ('n', '.', 'a')), ('ne', ['.......', '..abcd.', '.nP e.', '.m f.', '.l g.', '.kjih..', '.......'], ('a', 'b', ' ')), # Make certain that diagonal moves work (so far, they've only been # tried in situations where they fail). ('se', ['.......', '..abcd.', '.n e.', '.m P f.', '.l g.', '.kjih..', '.......'], None), ('ne', ['.......', '..abcd.', '.n Pe.', '.m f.', '.l g.', '.kjih..', '.......'], None), ('sw', ['.......', '..abcd.', '.n e.', '.m P f.', '.l g.', '.kjih..', '.......'], None), ('nw', ['.......', '..abcd.', '.nP e.', '.m f.', '.l g.', '.kjih..', '.......'], None), ], )