def load_map(self, map_file): """ Load a previously saved game map. Parameters ---------- map_file: str Address of the `map.json` file for loading the map """ if not os.path.exists(map_file): raise FileNotFoundError('The given map file does not exist') map_dict = json.load(open(map_file, 'r')) assert map_dict['height'] == self.height, \ 'Map heights do not match' assert map_dict['width'] == self.width, \ 'Map widths do not match' assert len(map_dict['agent_locations']) == len(self.agents), \ 'Number of agents in the game do not match' self.game_map = np.asarray( list(map(lambda t: utils.MapTiles(t), map_dict['game_map']))).reshape(self.height, self.width) walls = np.pad((self.game_map == utils.MapTiles.WALL), 1, mode='constant', constant_values=1).astype(np.int32) nw_filters = np.asarray([[0, 0.5, 0], [0.5, 0, 0], [0] * 3]) ne_filters = np.asarray([[0, 0.5, 0], [0, 0, 0.5], [0] * 3]) se_filters = np.asarray([[0] * 3, [0, 0, 0.5], [0, 0.5, 0]]) sw_filters = np.asarray([[0] * 3, [0.5, 0, 0], [0, 0.5, 0]]) self.nwblocks = (signal.correlate2d(walls, nw_filters, mode='valid') >= 1).astype(np.int32) self.neblocks = (signal.correlate2d(walls, ne_filters, mode='valid') >= 1).astype(np.int32) self.seblocks = (signal.correlate2d(walls, se_filters, mode='valid') >= 1).astype(np.int32) self.swblocks = (signal.correlate2d(walls, sw_filters, mode='valid') >= 1).astype(np.int32) for obj in map_dict['objects']: if obj[-1] == 'boss': self.objects[tuple(obj[:2])] = utils.Boss() self.goal_loc = tuple(obj[:2]) elif obj[-1] == 'medkit': self.objects[tuple(obj[:2])] = utils.PowerUp() elif obj[-1] == 'skeleton': self.objects[tuple(obj[:2])] = utils.StaticMonster() else: raise ValueError('Undefined object type') for m in map_dict['dynamic_monsters']: self.dynamic_monsters[(m[0], m[1])] = \ utils.DynamicMonster(m[0], m[1]) self.agent_locations = [ tuple(loc) for loc in map_dict['agent_locations'] ]
def generate_map(self): # TODO: Create a better function for generating the map self.game_map = np.random.choice(list(utils.MapTiles)[1:], (self.height, self.width), p=[0.4, 0.3, 0.2, 0.1]) nonwall_indices = np.where(self.game_map != utils.MapTiles.WALL) # generate objects in the game map object_indices = np.random.choice( len(nonwall_indices[0]), self.num_monsters + self.num_powerups + 1, # extra for the boss replace=False) for cnt, idx in enumerate(object_indices[1:]): i = nonwall_indices[0][idx] j = nonwall_indices[1][idx] if cnt < self.num_powerups: self.objects[(i, j)] = utils.PowerUp() else: self.objects[(i, j)] = utils.StaticMonster() # the boss i = nonwall_indices[0][object_indices[0]] j = nonwall_indices[1][object_indices[0]] self.objects[(i, j)] = utils.Boss() self.goal_loc = (i, j) remaining_indices = [[]] * 2 remaining_indices[0] = [ i for idx, i in enumerate(nonwall_indices[0]) if idx not in object_indices ] remaining_indices[1] = [ j for idx, j in enumerate(nonwall_indices[1]) if idx not in object_indices ] assert len(remaining_indices[0]) >= len(self.agents), \ 'Not enough empty tiles are left' # initial locations for agents for i in range(len(self.agents)): idx = np.random.choice(len(remaining_indices[0])) loc = (remaining_indices[0][idx], remaining_indices[1][idx]) while (loc == self.goal_loc or any(loc == prev_loc for prev_loc in self.agent_locations)): idx = np.random.choice(len(remaining_indices[0])) loc = (remaining_indices[0][idx], remaining_indices[1][idx]) self.agent_locations.append(loc)
def load_map(self, map_file): """ Load a previously saved game map. Parameters ---------- map_file: str Address of the `map.json` file for loading the map """ if not os.path.exists(map_file): raise FileNotFoundError('The given map file does not exist') map_dict = json.load(open(map_file, 'r')) assert map_dict['height'] == self.height, \ 'Map heights do not match' assert map_dict['width'] == self.width, \ 'Map widths do not match' assert len(map_dict['agent_locations']) == len(self.agents), \ 'Number of agents in the game do not match' self.game_map = np.asarray( list(map(lambda t: utils.MapTiles(t), map_dict['game_map']))).reshape(self.height, self.width) for obj in map_dict['objects']: if obj[-1] == 'boss': self.objects[tuple(obj[:2])] = utils.Boss() self.goal_loc = tuple(obj[:2]) elif obj[-1] == 'medkit': self.objects[tuple(obj[:2])] = utils.PowerUp() elif obj[-1] == 'skeleton': self.objects[tuple(obj[:2])] = utils.StaticMonster() else: raise ValueError('Undefined object type') self.agent_locations = [ tuple(loc) for loc in map_dict['agent_locations'] ]
def generate_map(self): # TODO: Create a better function for generating the map self.game_map = np.random.choice(list(utils.MapTiles)[1:], (self.height, self.width), p=[0.4, 0.3, 0.2, 0.1]) walls = np.pad((self.game_map == utils.MapTiles.WALL), 1, mode='constant', constant_values=1).astype(np.int32) nw_filters = np.asarray([[0, 0.5, 0], [0.5, 0, 0], [0] * 3]) ne_filters = np.asarray([[0, 0.5, 0], [0, 0, 0.5], [0] * 3]) se_filters = np.asarray([[0] * 3, [0, 0, 0.5], [0, 0.5, 0]]) sw_filters = np.asarray([[0] * 3, [0.5, 0, 0], [0, 0.5, 0]]) self.nwblocks = (signal.correlate2d(walls, nw_filters, mode='valid') >= 1).astype(np.int32) self.neblocks = (signal.correlate2d(walls, ne_filters, mode='valid') >= 1).astype(np.int32) self.seblocks = (signal.correlate2d(walls, se_filters, mode='valid') >= 1).astype(np.int32) self.swblocks = (signal.correlate2d(walls, sw_filters, mode='valid') >= 1).astype(np.int32) nonwall_indices = np.where(self.game_map != utils.MapTiles.WALL) # generate objects in the game map object_indices = np.random.choice( len(nonwall_indices[0]), self.num_monsters + self.num_powerups + self.num_dynamic_monsters + 1, # extra for the boss replace=False) for cnt, idx in enumerate(object_indices[1:]): i = nonwall_indices[0][idx] j = nonwall_indices[1][idx] if cnt < self.num_powerups: self.objects[(i, j)] = utils.PowerUp() elif cnt < self.num_powerups + self.num_monsters: self.objects[(i, j)] = utils.StaticMonster() else: self.dynamic_monsters[(i, j)] = utils.DynamicMonster(i, j) # the boss i = nonwall_indices[0][object_indices[0]] j = nonwall_indices[1][object_indices[0]] self.objects[(i, j)] = utils.Boss() self.goal_loc = (i, j) remaining_indices = [[]] * 2 remaining_indices[0] = [ i for idx, i in enumerate(nonwall_indices[0]) if idx not in object_indices ] remaining_indices[1] = [ j for idx, j in enumerate(nonwall_indices[1]) if idx not in object_indices ] assert len(remaining_indices[0]) >= len(self.agents), \ 'Not enough empty tiles are left' # initial locations for agents for i in range(len(self.agents)): idx = np.random.choice(len(remaining_indices[0])) loc = (remaining_indices[0][idx], remaining_indices[1][idx]) while (loc == self.goal_loc or any(loc == prev_loc for prev_loc in self.agent_locations)): idx = np.random.choice(len(remaining_indices[0])) loc = (remaining_indices[0][idx], remaining_indices[1][idx]) self.agent_locations.append(loc) for loc in self.agent_locations: wall_sum = self.nwblocks[loc[0], loc[1]] + \ self.neblocks[loc[0], loc[1]] + \ self.seblocks[loc[0], loc[1]] + \ self.swblocks[loc[0], loc[1]] assert wall_sum < 3, 'The map is unsolvable'