def get_map_bounds(self): """ Returns a map with """ left_most = 0 right_most = 0 top_most = 0 bottom_most = 0 for room in self.room_list: if room.position.x < left_most: left_most = room.position.x if room.position.x + room.size_vector.x > right_most: right_most = room.position.x + room.size_vector.x if room.position.y + room.size_vector.y > top_most: top_most = room.position.y + room.size_vector.y if room.position.y < bottom_most: bottom_most = room.position.y width = abs(right_most - left_most) height = abs(top_most - bottom_most) return { 'dimensions': Vector2(width, height), 'position': Vector2(left_most, bottom_most) }
def __init__(self, level, size_vector, doors, biome, items, enemies, position=None, entrance_direction=None, exit_directions=None): self.level = level self.size_vector = Vector2(int(size_vector.x), int(size_vector.y)) self.doors = doors self.biome = biome self.items = items self.enemies = enemies if not position: self.position = None else: self.position = Vector2(int(position.x), int(position.y)) self.entrance_direction = entrance_direction self.exit_directions = exit_directions self.area = size_vector.x * size_vector.y
def room_colision_test(): room_1 = Room.empty(Vector2(15, 5), Vector2(-10, 10)) room_2 = Room.empty(Vector2(15, 5), Vector2(-11, 14)) if not room_1.check_collision(room_2): logger.warning('Room colision not expected!') room_2.position.y = 14 if not room_1.check_collision(room_2): logger.warning('Room collision expected!')
def print_map(self, export_file=None): map_bounds = self.get_map_bounds() ascii_pixel_matrix = [] for y in range(map_bounds['position'].y, map_bounds['dimensions'].y + map_bounds['position'].y): ascii_pixel_row = [''] for x in range( map_bounds['position'].x, map_bounds['dimensions'].x + map_bounds['position'].x): pixel_collider = Room.empty(Vector2(1, 1), Vector2(x, y)) collides = False room_level = 0 for room in self.room_list: if room.check_collision(pixel_collider): collides = True room_level = room.level if collides: if room_level < 10: ascii_pixel_row.append(f'{int(room_level)}') else: ascii_pixel_row.append('#') else: ascii_pixel_row.append(' ') ascii_pixel_matrix.append(ascii_pixel_row) map_string = f'{map_bounds}\n' for room in self.room_list: map_string += f'Room level {room.level} dimensions: {room.size_vector}\n' for row in ascii_pixel_matrix: row_string = '' for pixel in row: row_string += pixel map_string = f'{map_string}\n{row_string}' if export_file: export_file = f'{os.path.dirname(os.path.realpath(__file__))}/Maps/{export_file}' with open(export_file, 'w') as file: file.seek(0) file.write(map_string) return map_string
def map_bounds_test(): room_list = [Room.empty(Vector2(15, 5), Vector2(15, -5)), Room.empty(Vector2(15, 5), Vector2(-10, 12)), Room.empty(Vector2(15, 5), Vector2(-11, 1))] map_bounds = Map(None, None, room_list).get_map_bounds() if list(map_bounds['position']) != [-11, -5]: logger.warning('map position wrong') print(map_bounds) if list(map_bounds['dimensions']) != [41, 22]: logger.warning('map dimentions wrong')
async def generate_map(cls, map_size=None, connectivity=None, biome=None, level=None, level_interval=1, current_map=[], special_rooms=[], special_room_occurance=0.01, client=None, progress_message=None): """ Generates a series of linked rooms :param map_size: number of rooms in the map :param connectivity: how many hallways in the map :param biome: map biome :param level: map starting level, goes up by level_interval for each room :param current_map: The map that this map will build upon :param special_rooms: list of premade rooms :param special_room_occurance: how often premade rooms appear as percent (0, 1) :return: Map instance """ start_time = datetime.datetime.now() if not map_size: map_size = random.randint(5, 30) logger.debug(map_size) if not connectivity: connectivity = random.uniform(0, 1) if not biome: biome = Room.biome_list[random.randint(0, len(Room.biome_list) - 1)] if not level: level = 1 if current_map: room_list = current_map else: room_list = [ Room(items=None, enemies=None, doors={ 'north': True, 'south': False, 'east': False, 'west': False }, position=Vector2.zero(), size_vector=Vector2(random.randint(2, 8), random.randint(2, 8)), biome=biome, level=level, entrance_direction=None, exit_directions=['north']) ] map_size = int(map_size) level = int(level) message_content = progress_message.content progress_message = await client.edit_message( progress_message, message_content + f'\nProgress: []') list_index = 0 while list_index <= map_size - 2: last_room = room_list[list_index] room_succesful = False level += level_interval entrance_direction = GameObject.opposite_direction( last_room.exit_directions[random.randint( 0, len(last_room.exit_directions) - 1)]) room_tries = 0 while room_tries < 100: doors = { 'north': random.randint(0, 1) == 1, 'south': random.randint(0, 1) == 1, 'east': random.randint(0, 1) == 1, 'west': random.randint(0, 1) == 1 } pass # get rid of pycharm formatting bug doors[entrance_direction] = True exit_directions = [] for direction in doors: if direction != entrance_direction and doors[direction]: exit_directions.append(direction) if len(exit_directions) == 0: # room_tries += 1 # logger.debug(f'No exit {room_tries}') continue if random.uniform( 0, 1) < special_room_occurance and len(special_rooms) > 0: room = special_rooms[random.randint( 0, len(special_rooms) - 1)] else: room = Room(items=None, enemies=None, doors=doors, biome=biome, level=level, position=Vector2.zero(), size_vector=Vector2(random.randint(2, 20), random.randint(2, 20)), entrance_direction=entrance_direction, exit_directions=exit_directions) # if room is above last_room if entrance_direction == 'north': room.position.x = random.randint( last_room.position.x - room.size_vector.x + 1, last_room.position.x + last_room.size_vector.x - 1) room.position.y = int(last_room.position.y + last_room.size_vector.y) # if room is below last_room elif entrance_direction == 'south': room.position.x = random.randint( last_room.position.x - room.size_vector.x + 1, last_room.position.x + last_room.size_vector.x - 1) room.position.y = int(last_room.position.y - room.size_vector.y) # if room to the right of last_room elif entrance_direction == 'east': room.position.x = int(last_room.position.x + last_room.size_vector.x) room.position.y = room.position.y = random.randint( last_room.position.y - room.size_vector.y + 1, last_room.position.y + last_room.size_vector.y - 1) # if room to the left of last_room elif entrance_direction == 'west': room.position.x = int(last_room.position.x - room.size_vector.x) room.position.y = random.randint( last_room.position.y - room.size_vector.y + 1, last_room.position.y + last_room.size_vector.y - 1) if room.check_all_collision(room_list): room_tries += 1 # logger.debug(f'room tries: {room_tries}') continue room_list.append(room) logger.info(f'Generated level {level} room') # last_room = room room_tries = 100000 room_succesful = True wip_map = Map(level, biome, room_list) wip_map.print_map(f'{level}.txt') list_index += 1 if not room_succesful: logger.info(f'level {level} room unsuccesful') level -= 1 * level_interval for _ in range(0, 5): if list_index > 0: level -= int(1 * level_interval) list_index -= 1 del (room_list[-1]) progress_string = GameObject.progress_bar( int((len(room_list) / map_size) * 100), map_size) progress_message = await client.edit_message( progress_message, message_content + f'\nProgress: {progress_string}') # for room in room_list: # for other_room in room_list: # # hallway = None # # # if room is underneath or above other_room # if cls.check_horizontal_alignment(room, other_room) and \ # random.uniform(0, 1) < connectivity: # # hallway_pos = Vector2.zero() # hallway_size = Vector2(2, 0) # # # if room is below other_room # if room.position.y - other_room.position.y < 0: # if other_room.position.y - room.position.y < 15 > 2 and \ # room.doors['north'] and other_room.doors['south']: # # hallway_pos.y = room.position.y + room.size_vector.y # hallway_size.y = other_room.position.y - room.position.y + room.size_vector.y # # if hallway_size.y < 2: # continue # else: # continue # # # if room is above other_room # elif room.position.y - other_room.position.y > 0: # if room.position.y - other_room.position.y < 15 > 2 and \ # room.doors['south'] and other_room.doors['north']: # # hallway_pos.y = other_room.position.y + other_room.size_vector.y # hallway_size.y = room.position.y - other_room.position.y + other_room.size_vector.y # # if hallway_size.y < 2: # continue # else: # continue # # hallway_pos.x = ((room.position.x + room.size_vector.x / 2) + # (other_room.position.x + other_room.size_vector.x / 2)) // 2 # # hallway = Room.generate_room(doors={ # 'north': True, # 'south': True, # 'east': False, # 'west': False}, # level=int(level/2), # size_vector=hallway_size, # position=hallway_pos # ) # # if hallway.check_all_collision(room_list): # hallway = None # else: # logger.debug(f'Created vertical hallway between {hallway.position.y} and {hallway.position.y + hallway.size_vector.y}') # # # if room is to the left or right of other_room # if cls.check_vertical_alignment(room, other_room) and \ # random.uniform(0, 1) < connectivity: # # hallway_pos = Vector2.zero() # hallway_size = Vector2(0, 2) # # # if room is to the left of other room # if room.position.x - other_room.position.x < 0: # if other_room.position.x - room.position.x < 15 and \ # room.doors['east'] and other_room.doors['west']: # # hallway_pos.x = room.position.x + room.size_vector.x # hallway_size.x = other_room.position.x - room.position.x + room.size_vector.x # # if hallway_size.x < 2: # continue # else: # continue # # # if room is to the right of other_room # else: # if room.position.x - other_room.position.x < 15 and \ # room.doors['west'] and other_room.doors['east']: # # hallway_pos.x = other_room.position.x + other_room.size_vector.x # hallway_size.x = room.position.x - other_room.position.x + other_room.size_vector.x # # if hallway_size.x < 2: # continue # else: # continue # # hallway_pos.y = ((room.position.y + room.size_vector.y / 2) + # (other_room.position.y + other_room.size_vector.y / 2)) // 2 # # hallway = Room.generate_room(doors={ # 'north': False, # 'south': False, # 'east': True, # 'west': True}, # level=int(level / 2), # size_vector=hallway_size, # position=hallway_pos # ) # # if hallway.check_all_collision(room_list): # hallway = None # else: # logger.debug(f'Created horizontal hallway between {hallway.position.x} and {hallway.position.x + hallway.size_vector.x}') # # if hallway: # room_list.append(hallway) # await asyncio.sleep(0.1) room_list.sort(key=Map.room_level_sort_key) for room in room_list: populated_room = Room.generate_room( room.doors, room.size_vector, room.level, biome=biome, position=room.position, entrance_direction=room.entrance_direction, exit_directions=room.exit_directions) room_list.remove(room) room_list.append(populated_room) generation_time = datetime.datetime.now() - start_time logger.info(f'Map of size {map_size} generated in {generation_time}') return cls(level, biome, room_list)
def generate_room(cls, doors=None, size_vector=None, level=None, enemy_power=None, total_loot=None, biome=None, enemy_distribution=None, loot_distribution=None, position=None, entrance_direction=None, exit_directions=None): if not doors: doors = { 'north': random.randint(0, 1) == 1, 'south': random.randint(0, 1) == 1, 'east': random.randint(0, 1) == 1, 'west': random.randint(0, 1) == 1, } if not size_vector: size_vector = Vector2(0, 0) size_vector.x = random.randint(2, 20) size_vector.y = random.randint(2, 20) if not level: level = GameObject.get_level() * 10 if not enemy_power: enemy_power = (level**2 * GameObject.get_level() * 1) - (random.randint(-5, 13)) if not total_loot: total_loot = GameObject.get_level() * ( (size_vector.x * size_vector.y) / 500) * (level**2 - GameObject.zero_to_range(level**2)) if not biome: biome = cls.biome_list[random.randint(0, len(cls.biome_list) - 1)] if not enemy_distribution: enemy_distribution = random.uniform(0.5, 2) if not loot_distribution: loot_distribution = random.uniform(0.5, 2) level = int(level) enemy_power = int(enemy_power) total_loot = int(total_loot) loot_list = items.Item.generate_loot(level, total_loot, loot_distribution) chest_list = [] for _ in range(0, 3): if random.uniform(0, 1) < 0.1 or len(loot_list) > 5: chest_inventory = [] chest_value = total_loot chest_value = chest_value // 3 while chest_value > 0 and len(loot_list) > 0: loot_item = loot_list[-1] chest_inventory.append(loot_item) chest_value -= loot_item.total_value loot_list.remove(loot_item) chest_list.append(items.Chest(None, chest_inventory)) for chest in chest_list: chest.position = Vector2(random.randint(0, size_vector.x), random.randint(0, size_vector.y)) chest.inventory.sort(key=items.Item.value_sort_key, reverse=True) loot_list.append(chest) for item in loot_list: item.position = Vector2(random.randint(0, size_vector.x), random.randint(0, size_vector.y)) enemy_list = creatures.EnemyHumanoid.generate_enemies( level, enemy_power, enemy_distribution) enemy_list.sort(key=creatures.Creature.power_sort_key, reverse=True) for enemy in enemy_list: enemy.position = Vector2(random.randint(0, size_vector.x), random.randint(0, size_vector.y)) room_instance = cls(level, size_vector, doors, biome, loot_list, enemy_list, position, entrance_direction, exit_directions) return room_instance