def update_cell(self, entity): prev_x, prev_y = entity.prev_pos prev_tile = self.tiles[xy_to_idx(prev_x, prev_y, self.width)] new_tile = self.tiles[xy_to_idx(entity.x, entity.y, self.width)] prev_tile['entity'] = Ground((prev_x, prev_y)) prev_tile['blocked'] = False new_tile['entity'] = entity new_tile['blocked'] = True
def get_cell_from_abs(self, pos): x, y = pos rel_x = x - self.x + self.map.player.x rel_y = y - self.y + self.map.player.y idx = xy_to_idx(rel_x, rel_y, self.map.width) tile = self.map.tiles[idx] return tile
def get_items(self, entity): idx = xy_to_idx(entity.x, entity.y, self.width) items_to_get = self.tiles[idx]['items'] if items_to_get: entity.add_items(items_to_get) self.tiles[idx]['items'] = [] for item in items_to_get: self.entities['items'].remove(item)
def __init__(self, size_x, size_y, num_rooms, player, controller): # Controller self.controller = controller loading = controller.loading loading.update(0, 'Generating map...') # Map dimensions self.width = size_x self.height = size_y # Holds the vision and pathing logic self.tcod_map = tcod.map.Map(width=size_x, height=size_y) self.tcod_map.transparent[:] = False # Set up the map print('Initializing all cells to walls...') self.tiles = {} for i in range(self.width * self.height): self.tiles[i] = { 'entity': Wall(idx_to_xy(i, size_x)), 'items': [], 'blocked': True } self.rooms = [] self.hallways = [] self.origin = (0, 0) # Origin is set when first room is generated for i in range(num_rooms): print("Generating room: ", i) loading.update((i // num_rooms) // 2) self.rooms.append(self.gen_room()) self.astar = tcod.path.AStar(self.tcod_map.walkable) # Initialize player loading.update(status='Setting player position...') print('Setting player position...') self.player = player self.player.set_pos(self.origin) self.tiles[xy_to_idx(self.player.x, self.player.y, self.width)]['entity'] = self.player self.entities = { 'player': self.player, 'items': [], 'enemies': [], 'blocked': True } loading.update(status='Generating view...') print('Generating initial view...') viewed = np.ndarray((self.width, self.height), dtype=bool) viewed[:] = False self.player.set_view(viewed) loading.update(0.75, status='Populating rooms...') print('Populating rooms with items...') self.populate() self.player.update_fov(self.tcod_map)
def add_room(self): directions = ['N', 'E', 'W', 'S'] direction = None # Create room min_d = ROOM['min_dim'] max_d = ROOM['max_dim'] room = None hallway = None while not self.area_free(room): # Create hallway hallway = None # Keep generating areas until an unoccupied one is found while not self.area_free(hallway): # Select origin room origin = random.choice(self.rooms) # Select a direction direction = random.choice(directions) side = origin.sides[direction] x = random.choice(side['x']) - 1 y = random.choice(side['y']) - 1 hallway_length = random.randrange(HALLWAY['min_length'], HALLWAY['max_length']) hallway_width = HALLWAY['width'] hallway = Room(x, y, hallway_width, hallway_length, direction) # Set direction side = hallway.sides[direction] x = random.choice(side['x']) y = random.choice(side['y']) w = int(random.randrange(min_d, max_d)) h = int(random.randrange(min_d, max_d)) room = Room(x, y, w, h, direction) self.hallways.append(hallway) for i in range(hallway.x, hallway.x2): for j in range(hallway.y, hallway.y2): self.tiles[xy_to_idx(i, j, self.width)] = { 'entity': Ground((i, j)), 'blocked': False, 'items': [] } self.tcod_map.walkable[j, i] = True self.tcod_map.transparent[j, i] = True return room
def enemy_turns(self): for enemy in self.entities['enemies']: if enemy.current_hp > 0: enemy.turn(self) self.update_cell(enemy) else: idx = xy_to_idx(enemy.x, enemy.y, self.width) tile = self.tiles[idx] for item in enemy.inventory: self.entities['items'].append(item) tile['items'].append(item) tile['entity'] = Ground((enemy.x, enemy.y)) tile['blocked'] = False self.entities['enemies'].remove(enemy)
def populate(self): # add items for item in ITEMS.keys(): for i in range( random.randrange(ITEMS[item]['min'], ITEMS[item]['max'])): idx = None while idx is None or self.tiles[idx][ 'entity'].type is not 'ground': rand_x = math.floor(np.random.random() * self.width) rand_y = math.floor(np.random.random() * self.height) idx = xy_to_idx(rand_x, rand_y, self.width) new_item = Item(item, (rand_x, rand_y)) self.tiles[idx]['items'].append(new_item) self.entities['items'].append(new_item) # add enemies num_enemies = random.randrange(ROOM['min_enemies'], ROOM['max_enemies']) enemies = InmateList(num_enemies) for enemy in enemies.inmate_list: idx = None while idx is None or (self.tiles[idx]['blocked'] or self.tiles[idx]['entity'].type is not 'ground'): rand_x = math.floor(np.random.random() * self.width) rand_y = math.floor(np.random.random() * self.height) idx = xy_to_idx(rand_x, rand_y, self.width) new_enemy = Enemy(inmate=enemy) new_enemy.set_pos((rand_x, rand_y)) new_enemy.update_fov(self.tcod_map) self.entities['enemies'].append(new_enemy) self.tiles[idx]['entity'] = new_enemy self.tiles[idx]['blocked'] = True
def area_free(self, room=None): if not room: return False if room.x2 >= self.width or room.x < 0: return False if room.y2 >= self.height or room.y < 0: return False for i in range(room.x, room.x2): for j in range(room.y, room.y2): if self.tiles[xy_to_idx( i, j, self.width)]['entity'].type is not 'wall': return False return True
def check_move(self, move, entity): dest_x, dest_y = move dest_x = entity.x + dest_x dest_y = entity.y + dest_y tile = self.tiles[xy_to_idx(dest_x, dest_y, self.width)] # Check bounds of map if (dest_x >= self.width) or (dest_x < 0): return False elif (dest_y >= self.height) or (dest_y < 0): return False # Check if currently occupied elif tile['blocked']: if tile['entity']: self.controller.attack(entity, tile['entity']) return False # Find walkable path to destination elif self.astar.get_path(entity.y, entity.x, dest_y, dest_x) is None: return False return True
def gen_room(self): # If first room, set it at the center if not self.rooms: min_d = ROOM['min_dim'] max_d = ROOM['max_dim'] w = int(random.randrange(min_d, max_d)) h = int(random.randrange(min_d, max_d)) (x, y) = (self.width // 2, self.height // 2) room = Room(x, y, w, h) self.origin = (room.x + w // 2, room.y + h // 2) else: room = self.add_room() for i in range(room.x, room.x2): for j in range(room.y, room.y2): self.tiles[xy_to_idx(i, j, self.width)] = { 'entity': Ground((i, j)), 'blocked': False, 'items': [] } self.tcod_map.walkable[j, i] = True self.tcod_map.transparent[j, i] = True return room
def draw(self, con): player = self.map.player top_edge = self.top_left_y bot_edge = self.top_left_y + self.view_y left_edge = self.top_left_x right_edge = self.top_left_x + self.view_x half_width = self.view_x // 2 half_height = self.view_y // 2 # The cells to draw tile_x_range = range(player.x - half_width, player.x + half_width) tile_y_range = range(player.y - half_height, player.y + half_height) for y in tile_y_range: if 0 <= y < self.map.height: for x in tile_x_range: if 0 <= x < self.map.width: idx = xy_to_idx(x, y, self.map.width) if player.view_history[y, x]: rel_x = x - player.x rel_y = y - player.y tile = self.map.tiles[idx] item = tile['items'] entity = tile['entity'] if entity.type is 'player': entity.draw(con, self.x, self.y) else: if player.view[y, x]: if entity.type is 'ground' and item: item[0].draw(con, rel_x + self.x, rel_y + self.y) else: entity.draw(con, rel_x + self.x, rel_y + self.y) elif entity.type in ['ground', 'wall']: entity.draw_darker(con, rel_x + self.x, rel_y + self.y) else: tcod.console_put_char_ex( con, rel_x + self.x, rel_y + self.y, '.', fore=COLORS['dark_ground'], back=con.default_bg) # Draw border of map view_edge_symbol = ord('#') for x in range(self.view_x + 1): con.put_char(x + left_edge, top_edge, view_edge_symbol, tcod.BKGND_NONE) con.put_char(x + left_edge, bot_edge, view_edge_symbol, tcod.BKGND_NONE) for y in range(self.view_y): con.put_char(left_edge, y + top_edge, view_edge_symbol, tcod.BKGND_NONE) con.put_char(right_edge, y + top_edge, view_edge_symbol, tcod.BKGND_NONE)