def _interior_garden(w, h, wall_material, floor_material): M = Map(w, h, fill_cell=C.floor_flagged) garden_part = Map(w // 2, h, fill_cell=C.flora_grass) for y in range(0, h): garden_part[w // 2 - 1, y] = C.floor_flagged() for x in range(1, w // 2 - 1): for y in range(1, 4): garden_part[x, y] = C.floor_flagged() for x in range(2, w // 2): garden_part[x, 2].put(T.water_trough()) for y in range(h - 3, h): garden_part[0, y] = C.flora_tree() garden_part[1, y].put(T.water_trough()) garden_part[2, y] = C.flora_flower() garden_part[w // 2 - 2, 0] = C.flora_flower() garden_part[0, h - 5].put(T.furniture_sofa()) garden_part[1, h - 5].put(T.furniture_table_round()) garden_part[2, h - 6].put(T.urn()) M.meld(garden_part, 0, 0) garden_part2 = deepcopy(garden_part) garden_part2.hmirror() M.meld(garden_part2, w // 2 + w % 2, 0) for x in range(0, w // 2 - 1): M[x, h - 4] = C.floor_flagged() M.scatter(0, 0, w - 1, h - 1, [A.animal_cat()]) return M
def _interior_pantry(w, h, wall_material, floor_material): M = Map(w, h, fill_cell=floor_material) if random.random() < 0.5: for y in range(h): M[2, y] = wall_material() items = [T.tool_wateringcan(), T.tool_pitchfork(), T.tool_fishingrod()] M.scatter(0, 0, w - 1, h, items) else: M[0, 0] = C.stairs_down() M[0, 1].put(T.furniture_box_filled()) return M
def room_default(w, h, wall_type, floor_type): """ Create an empty room with given wall type, floor type. Parameters ---------- w : int Map width h : int Map height wall_type : Cell Wall cell type floor_typr : Cell Floor cell type """ M = Map(w, h, fill_cell=floor_type) # Create walls for x in range(0, w): M[x, 0] = wall_type() M[x, h - 1] = wall_type() for y in range(0, h): M[0, y] = wall_type() M[w - 1, y] = wall_type() return M
def dungeon_bsp_tree(w=30, h=30, optimal_block_size=10): """ Construct the dungeon map using binary space partitioning (BSP) algorithm. Visual ------ Rectangular square-like rooms connected with 1-pixel corridors. These rooms evenly distributed across the map. All corridors are straight. Parameters ---------- w : int Map width h : int Map height optimal_block_size : int Optimal block size. Approximately equals to room size. """ M = Map(w, h, fill_cell=C.wall_dungeon_rough) nodes = {} root = BSPNode('v', 1, 1, w - 1, h - 1) _recursive_split_tree_node(root, optimal_block_size) _load_leafs(root, nodes) _fill_rooms(M, nodes.values()) all_edges = _get_all_edges(nodes.values()) st_edges = _construct_spanning_tree(list(nodes.keys()), all_edges) _create_corridors(M, nodes, st_edges) return M
def _room_cattle_pens(w, h, wall_material, floor_material): M = room_default(w, h, wall_type=C.wall_fence, floor_type=floor_material) M[w - 7, 0] = C.door_close_fence() for i in range(w * h // 3): grass_x = random.randint(1, w - 2) grass_y = random.randint(1, h - 2) M[grass_x, grass_y] = random.choice( [C.flora_grass, C.flora_cane, C.floor_grass])() num_cattles = h // 4 + 1 cowshed = Map(4, 3, fill_cell=floor_material) for y in (1, 2): cowshed[0, y] = C.wall_fence() for y in range(0, 3): cowshed[3, y].put(T.water_trough()) for x in (1, 2): cowshed[x, 2] = wall_material() cowshed[1, 1].put(T.bucket()) cowshed_y = 1 for x in range(num_cattles): copied_cowshed = deepcopy(cowshed) M.meld(copied_cowshed, w - 5, cowshed_y) cowshed_y += 3 cows = [A.animal_cow() for _ in range(num_cattles)] M.scatter(1, 1, w - 5, h - 1, cows) return M
def _room_jailer(w=5, h=5): M = Map(w, h, fill_cell=C.floor_flagged) # Create walls for x in range(0, w): M[x, 0] = C.wall_stone() M[x, h - 1] = C.wall_stone() for y in range(0, h): M[0, y] = C.wall_stone() M[w - 1, y] = C.wall_stone() M[w // 2, 0] = C.door_closed() # Place furniture and items in the room all_coord = [(w // 2, 1)] for item_class in (T.furniture_bed_single, T.furniture_chest, T.furniture_chair, T.furniture_table, T.furniture_torch): while True: x = random.randint(1, w - 2) y = random.randint(1, h - 2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x, y)) break return M
def _room_torture(w=5, h=5): M = Map(w, h, fill_cell=C.floor_flagged) # Create walls for x in range(0, w): M[x, 0] = C.wall_stone() M[x, h - 1] = C.wall_stone() for y in range(0, h): M[0, y] = C.wall_stone() M[w - 1, y] = C.wall_stone() M[w // 2, h - 1] = C.door_closed() M[w // 2 + 1, h - 2] = C.stairs_up() # Place furniture and items in the room M[w // 2, h // 2].put(T.furniture_torture()) all_coord = [(w // 2, h - 2), (w // 2, h // 2), (w // 2 + 1, h - 2)] for item_class in (T.bones, T.bones_skull, T.tool_tongs): while True: x = random.randint(1, w - 2) y = random.randint(1, h - 2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x, y)) break return M
def world_test(w, h): heightmap = [] for y in range(h): line = [] for x in range(w): distance_corners = min([ sqrt(x**2 + y**2), sqrt((w-x)**2 + y**2), sqrt(x**2 + (h-y)**2), sqrt((w-x)**2 + (h-y)**2) ]) distance_edges = min([x*0.7, y*0.7, (w-x)*0.7, (h-y)*0.7]) minus = (w + h) / 3 c = random.randint(-w*0.7, -w*0.6) + distance_corners + distance_edges #print('{:> .1f}'.format(c), '', end='') line.append(c) heightmap.append(line) heightmap = diamond_square_2x(heightmap) heightmap = diamond_square_2x(heightmap, smooth_iteration=2) heightmap = diamond_square_2x(heightmap, smooth_iteration=3) heightmap = diamond_square_2x(heightmap, smooth_iteration=4) M = Map(len(heightmap[0]), len(heightmap), fill_cell=C.overworld_ocean) for y, line in enumerate(M.cells): for x, cell in enumerate(line): M[x, y] = C.overworld_ocean() if heightmap[y][x] < 0 else C.overworld_forest() M = _smooth_map(M) M = _smooth_map(M) return M
def dungeon_grid_simple(w, h, room_size=4, delete_chance=0.33): """Dungeon map generator based on square room grid.""" M = Map(w, h, fill_cell=C.floor_flagged) _create_room_grid(M, room_size=room_size) _create_doors(M, room_size=room_size) _crush_walls(M, room_size=room_size, delete_chance=delete_chance) return M
def _interior_garden(w, h, wall_material, floor_material): M = Map(w, h, fill_cell=C.floor_rocks) for x in range(w): M[x, h-1] = wall_material() M[w//2, h-1] = C.door_closed_wooden() M[w//2-1, h-1] = C.door_closed_wooden() return M
def room_horse_box(w, h, orientation='left'): """ Construct small horse box. """ M = Map(w, h, fill_cell=C.floor_rocks) # Place watertrough and horse food. M[0, 0].put(T.water_trough()) M[w - 1, 0] = C.door_closed() M[0, h - 1].put(T.water_trough()) M[w - 1, h - 1] = C.wall_fence() if h > 2: for y in range(1, h - 1): M[0, y].put(T.water_trough()) M[w - 1, y] = C.wall_fence() # Create horse box with animal or without. stable_with_horse_chance = random.random() all_coord = [] while True: x = random.randint(1, w - 2) y = random.randint(0, h - 1) if (x, y) not in all_coord: M[x, y] = C.flora_grass() all_coord.append((x, y)) break if stable_with_horse_chance > 0.3: while True: x = random.randint(1, w - 2) y = random.randint(0, h - 1) if (x, y) not in all_coord: M[x, y].put(T.farm_mangler()) all_coord.append((x, y)) break while True: x = random.randint(1, w - 2) y = random.randint(0, h - 1) if (x, y) not in all_coord: M[x, y].put(A.animal_horse()) all_coord.append((x, y)) break if orientation == 'right': M.hmirror() return M
def building_stables(w=16, h=16): """ Construct stables with storage and two rows of horse boxes. Constraints: - Map width and map height must be >= 16 and <=23. Parameters ---------- w : int Map width h : int Map height """ # Initial checks. Don't accept too small/big stables if w < 16 or h < 16: raise ValueError('Building is too small: w or h < 16') elif w > 23 or h > 23: raise ValueError('Building is too big: w or h > 25') M = Map(w, h, fill_cell=C.floor_rocks) for x in range(w): for y in range(h): if random.random() > 0.75: M[x, y] = C.flora_grass() # Calculate w and h for storage, horse boxes and stables. horse_box_size_w = w // 2 - 4 horse_box_size_h = 2 stables_size_w = horse_box_size_w * 2 + 3 stables_shift_h = (h - 1) % 3 stables_size_h = h - stables_shift_h storage_size_w = w - stables_size_w + 1 storage_size_h = h * 2 // 3 storage_start_w = w - storage_size_w # Meld stables, storage, add dog. main_stables = room_horse_stables(stables_size_w, stables_size_h, horse_box_size_w, horse_box_size_h) M.meld(main_stables, 0, 0) main_storage = room_storage(storage_size_w, storage_size_h) M.meld(main_storage, storage_start_w, 0) M[w - (w - stables_size_w) // 2, storage_size_h].put(T.well()) dog_place_x = random.randint(stables_size_w, w - 1) dog_place_y = random.randint(storage_size_h + 1, h - 1) M[dog_place_x, dog_place_y].put(A.animal_dog()) if random.choice([True, False]): M.hmirror() return M
def dungeon_cellular_simple(w=30, h=30, start_floor_chance=0.55, smooth_level=3): """ Construct the dungeon map using simple cellular automata. Note that this map can contain disconnected areas. Visual ------ Natural-looking cave-like map. Parameters ---------- w : int Map width h : int Map height start_floor_chance : float Chance of the floor cell in the first map fill smooth_level : int Number of sequential smooth functions """ M = Map(w, h, fill_cell=C.wall_cave) # Randomly fill all-but-border cells by floor with start_floor_chance probability for y, line in enumerate(M.cells[1:-1]): for x, _ in enumerate(line[1:-1]): chance = random.random() if chance <= start_floor_chance: M.cells[y + 1][x + 1] = C.floor_dirt() # Sequentially smooth the map smooth_level times for _ in range(smooth_level): M = _smooth_map(M) return M
def _gen_main(self, xsize, ysize, length, turn_chance=0.4): M = Map(xsize, ysize, fill_symbol='#') worm_x = random.randint(int(xsize * 0.3), int(xsize * 0.6)) worm_y = random.randint(int(ysize * 0.3), int(ysize * 0.6)) move = random.choice([NORTH, SOUTH, EAST, WEST]) for _ in range(length): worm_x, worm_y, move = self._move_worm(M, worm_x, worm_y, move, turn_chance) return M
def _room_outdoor(w, h): M = Map(w, h, fill_cell=C.floor_rocks) for i in range(w*h//3): grass_x = random.randint(0, w-1) grass_y = random.randint(0, h-1) M[grass_x, grass_y] = random.choice([C.flora_grass, C.flora_tree, C.floor_grass])() for x in (1, 8): M[x, 0].put(T.furniture_table()) for x in (0, 2, 7, 9): M[x, 0].put(T.furniture_stool()) if w > 13: M[11, 0].put(T.furniture_table()) M[10, 0].put(T.furniture_stool()) M[12, 0].put(T.furniture_stool()) for y in range(0, h): M[4, y] = C.floor_cobblestone() num_stables = (h - 5) // 2 stables = Map(3, 2, fill_cell=C.void) for x in range(3): stables[x, 0] = C.wall_fence_thin() stables[2, 1] = C.wall_fence_thin() stables[0, 1] = C.door_close_fence() stables[1, 1].put(A.animal_horse()) last_stable_y = h - 1 for i in range(num_stables): stable_x = w - 3 stable_y = 4 + (i * 2) M.meld(stables, stable_x, stable_y) last_stable_y = stable_y for x in range(w-3, w): M[x, last_stable_y + 2] = C.wall_fence_thin() M[2, h-1].put(T.sign_pointer()) M[3, 0].put(T.light_torch()) for y in (h//2-1, h//2): M[0, y].put(T.washtub()) if w > 9: M[0, h//2+1].put(T.washtub()) M[5, 0] = C.flora_flower() return M
def dungeon_drunkard(w, h, length=None, turn_chance=0.4): M = Map(w, h, fill_cell=C.wall_dungeon_smooth) if not length: length = int(w * h / 2) worm_x = random.randint(int(w * 0.3), int(w * 0.6)) worm_y = random.randint(int(h * 0.3), int(h * 0.6)) move = random.choice([NORTH, SOUTH, EAST, WEST]) for _ in range(length): M[worm_x, worm_y] = C.floor_flagged() worm_x, worm_y, move = _move_worm(M, worm_x, worm_y, move, turn_chance) return M
def _room_prison_center(w=5, h=5): M = Map(w, h, fill_cell=C.floor_flagged) if w > 8 and h > 4: jailer_room = _room_jailer(w // 2 + 1, h) M.meld(jailer_room, 0, 0) torture_room = _room_torture(w - w // 2, h) M.meld(torture_room, (w - w // 2) - 1, 0) elif h > 8 and w > 4: jailer_room = _room_jailer(w, h // 2 + 1) M.meld(jailer_room, 0, 0) torture_room = _room_torture(w, h - h // 2) M.meld(torture_room, 0, (h - h // 2) - 1) else: for x in range(0, w): M[x, 0] = C.wall_stone() M[x, h - 1] = C.wall_stone() for y in range(0, h): M[0, y] = C.wall_stone() M[w - 1, y] = C.wall_stone() M[w // 2, 0] = C.door_closed() M[w // 2, h // 2] = C.stairs_up() return M
def world_perlin_noise(w, h, scale=10.0, octaves=6, persistence=0.5, lacunarity=2.0): M = Map(w, h) min_value = None max_value = None startx = random.randint(0, w * 100) starty = random.randint(0, h * 100) for y, line in enumerate(M.cells): for x, cell in enumerate(line): n = noise.pnoise2((startx + x) / scale, (starty + y) / scale, octaves=octaves, persistence=persistence, lacunarity=lacunarity, repeatx=w, repeaty=h, base=2) M[x, y].noise = n if min_value is None: min_value = n if max_value is None: max_value = n if n < min_value: min_value = n if n > max_value: max_value = n delta = (max_value - min_value) / 12 for y, line in enumerate(M.cells): for x, cell in enumerate(line): if M[x, y].noise < min_value + delta: M[x, y] = C.overworld_ocean() elif M[x, y].noise < min_value + 5 * delta: M[x, y] = C.overworld_ocean() elif M[x, y].noise < min_value + 8 * delta: M[x, y] = C.overworld_plains() elif M[x, y].noise < min_value + 10 * delta: M[x, y] = C.overworld_forest() elif M[x, y].noise < min_value + 12 * delta: M[x, y] = C.overworld_mountain() else: M[x, y] = C.overworld_pinnacle() return M
def world_test2(w=400, h=200): M = Map(w, h, fill_cell=C.overworld_ocean) ''' plates = {i: (random.randint(0, w-1), random.randint(0, h-1)) for i in range(30)} for y, line in enumerate(M.cells): for x, cell in enumerate(line): intervals = {i: (plates[i][0] - x) ** 2 + (plates[i][1] - y) ** 2 for i in plates} #print(intervals) M[x, y].plate = min(intervals.items(), key=lambda item: item[1])[0] for y, line in enumerate(M.cells): for x, cell in enumerate(line): M[x, y] = P[M[x, y].plate]() for i in plates: M[plates[i]] = C.void() ''' for y, line in enumerate(M.cells): for x, cell in enumerate(line): distance_corners = min([ sqrt(x**2 + y**2), sqrt((w-x)**2 + y**2), sqrt(x**2 + (h-y)**2), sqrt((w-x)**2 + (h-y)**2) ]) distance_edges = min([x, y, (w-x), (h-y)]) minus = (w + h) / 3 c = random.randint(-w*0.8, -w*0.6) + distance_corners + distance_edges #print('{:> .1f}'.format(c), '', end='') M[x, y] = C.overworld_ocean() if c < 0 else C.overworld_forest() #print() #for y in [0, h-1]: # for x in range(M.w): # M[x, y] = C.overworld_ocean() #for x in [0, w-1]: # for y in range(M.h): # M[x, y] = C.overworld_ocean() #for x in range(w//2-2, w//2+3): # for y in range(h//2-2, h//2+3): # M[x, y] = C.overworld_forest() #for y, line in enumerate(M.cells): # for x, cell in enumerate(line): # if sum(c.cname == 'overworld_forest' for c in M.surrounding(x, y)) >= 7: # M[x, y] = C.overworld_forest() #M = _smooth_map(M) return M
def _room_outdoor(w, h): M = Map(w, h, fill_cell=C.floor_rocks) for i in range(w * h // 3): grass_x = random.randint(1, w - 1) grass_y = random.randint(0, h - 2) M[grass_x, grass_y] = random.choice( [C.flora_grass, C.flora_tree, C.floor_grass])() M[w - 1, 0].put(T.washtub()) for x in range(w): M[x, h - 1] = C.wall_fence_thin() for y in range(h - 1): M[0, y] = C.wall_fence_thin() for y in range(h - 1): M[3, y] = C.floor_rocks() M[3, h - 1] = C.door_close_fence() return M
def _interior_bar(w, h, floor_material): M = Map(w, h, fill_cell=floor_material) M[0, 0].put(T.furniture_table()) M[1, 0].put(T.furniture_stool()) for x in range(w//3, w): for y in (h//3, h//3*2+1): M[x, y].put(T.furniture_longtable()) M.scatter(w//3, h//3-1, w, h//3+2, [T.furniture_stool() for _ in range(w-w//3)], exclude=[(w//3, h//3-1)]) M.scatter(w//3, h//3*2, w, h//3*2+3, [T.furniture_stool() for _ in range(w-w//3)], exclude=[(w//3, h//3*2+2)]) M[0, h-1].put(T.furniture_table()) M[1, h-1].put(T.furniture_stool()) M[w-1, h-1].put(T.light_lantern_oil()) return M
def _interior_vending(w, h, wall_material, floor_material): M = Map(w, h, fill_cell=floor_material) for x in range(w): M[x, 2].put(T.furniture_longtable_showcase()) M[0, 1].put(T.money_pile()) M[w//2, 1].put(T.dining_mug()) for x in range(1, w, 2): M[x, 3].put(T.furniture_stool()) M[1, h-1].put(T.furniture_barrel()) M[2, h-1].put(T.furniture_barrel()) if w > 7: M[w-2, h-1].put(T.furniture_table()) M[w-1, h-1].put(T.furniture_stool()) M[w-3, h-1].put(T.furniture_stool()) if h > 6: for x in range(1, w-2, 3): for y in range(5, h-2, 3): M[x, y].put(T.furniture_table()) M[x+1, y].put(T.furniture_stool()) return M
def building_prison_linear(w=21, h=12, orientation='horizontal'): """ Construct a linear prison building interior. Parameters ---------- w : int Map width h : int Map height """ # Initial checks. Don't accept: # - Too small prisons # - Too wide prisons (for both horizontal and vertical orientations) if w < 11 or h < 11: raise ValueError('Building is too small: w or h < 11') if h > 16 and orientation == 'horizontal': raise ValueError( 'Building is too big: h > 16 and orientation == "horizontal"') if w > 16 and orientation == 'vertical': raise ValueError( 'Building is too big: w > 16 and orientation == "vertical"') if orientation == 'vertical': w, h = h, w M = Map(w, h, fill_cell=C.void) # Randomly choose where torture room and jailer room are. torture_left, jailer_right = None, None torture_left = random.choice([True, False]) if torture_left: jailer_right = True else: jailer_right = False # Create jailer room. We have two situations: jailer room left/right. jailer_y_start = h // 4 jailer_y_end = h // 3 * 2 if jailer_right: # Create walls, floor and door for y in range(jailer_y_start, jailer_y_end + 1): M[w - 1, y] = C.wall_stone() M[w - 5, y] = C.wall_stone() for x in range(w - 5, w): M[x, jailer_y_start] = C.wall_stone() M[x, jailer_y_end] = C.wall_stone() for y in range(jailer_y_start + 1, jailer_y_end): for x in range(w - 4, w - 1): M[x, y] = C.floor_flagged() M[w - 5, h // 2] = C.door_closed() # Place some furniture M[w - 4, jailer_y_start + 1].put(T.furniture_table()) M[w - 3, jailer_y_start + 1].put(T.furniture_table()) M[w - 2, jailer_y_start + 1].put(T.furniture_chair()) M[w - 4, jailer_y_end - 1].put(T.furniture_torch()) M[w - 3, jailer_y_end - 1].put(T.furniture_bed_single()) M[w - 2, jailer_y_end - 1].put(T.furniture_chest()) else: # Create walls, floor and door for y in range(jailer_y_start, jailer_y_end + 1): M[0, y] = C.wall_stone() M[4, y] = C.wall_stone() for x in range(0, 5): M[x, jailer_y_start] = C.wall_stone() M[x, jailer_y_end] = C.wall_stone() for y in range(jailer_y_start + 1, jailer_y_end): for x in range(1, 4): M[x, y] = C.floor_flagged() M[4, h // 2] = C.door_closed() # Place some furniture M[1, jailer_y_start + 1].put(T.furniture_table()) M[2, jailer_y_start + 1].put(T.furniture_table()) M[3, jailer_y_start + 1].put(T.furniture_chair()) M[1, jailer_y_end - 1].put(T.furniture_chest()) M[2, jailer_y_end - 1].put(T.furniture_bed_single()) M[3, jailer_y_end - 1].put(T.furniture_torch()) # Create torture room. We have two situations: torture room left/right. torture_start and torture_end - x-coord. # If torture_end = 0 or 1, there is no place for room (only one or two walls) # So we expand torture room for a one cell's width (+4) if jailer_right: torture_start = 0 torture_end = (w - 1) % 4 if torture_end == 0: torture_end = 4 if torture_end == 1: torture_end = 5 # Create walls, floor and door for x in range(torture_start, torture_end + 1): M[x, 0] = C.wall_stone() M[x, h - 1] = C.wall_stone() for y in range(0, h - 1): M[torture_start, y] = C.wall_stone() M[torture_end, y] = C.wall_stone() for x in range(torture_start + 1, torture_end): for y in range(1, h - 1): M[x, y] = C.floor_flagged() M[torture_end, h // 2] = C.door_closed() # Place some furniture. If torture_end == 2 (just a corridor), then we set only stairs. M[torture_end - 1, h - 2] = C.stairs_up() if torture_end != 2: M[(torture_end - torture_start) // 2, h // 2].put(T.furniture_torture()) all_coord = [(torture_end - 1, h - 2), ((torture_end - torture_start) // 2, h // 2)] for item_class in (T.bones, T.bones_skull, T.tool_tongs): while True: x = random.randint(1, torture_end - 1) y = random.randint(1, h - 2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x, y)) break else: # If torture room is right, we are using the torture room width for calculations. # If torture_width = 7, then we reduce torture room for a one cell's width (-4). torture_width = w % 4 + 4 if torture_width == 7: torture_width = 3 torture_end = w - 1 # Create walls, floor and door for x in range(w - torture_width, torture_end): M[x, 0] = C.wall_stone() M[x, h - 1] = C.wall_stone() for y in range(0, h): M[w - torture_width, y] = C.wall_stone() M[torture_end, y] = C.wall_stone() for x in range(w - torture_width + 1, torture_end): for y in range(1, h - 1): M[x, y] = C.floor_flagged() M[w - torture_width, h // 2] = C.door_closed() # Place some furniture. If torture_width = 3 (just a corridor), then we set only stairs. M[w - 2, h - 2] = C.stairs_up() if torture_width != 3: M[w - 2, h // 2].put(T.furniture_torture()) all_coord = [(w - 1, h - 2), (w - 2, h // 2)] for item_class in (T.bones, T.bones_skull, T.tool_tongs): while True: x = random.randint(w - torture_width + 1, w - 2) y = random.randint(1, h - 2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x, y)) break # Fill corridor with a floor if jailer_right: cor_start = torture_end + 1 cor_end = w - 6 else: cor_start = 5 cor_end = w - torture_width - 1 if h % 2 == 1: for x in range(cor_start, cor_end + 1): M[x, h // 2] = C.floor_flagged() else: for x in range(cor_start, cor_end + 1): M[x, h // 2 - 1] = C.floor_flagged() M[x, h // 2] = C.floor_flagged() # Place prison cells number_of_cells = (cor_end - cor_start + 2) // 4 for cell_index in range(number_of_cells): cell_x = (cor_start - 1) + (cell_index * 4) # Place upper cell M_cell = room_prison_cell(w=5, h=(h - 1) // 2) M.meld(M_cell, cell_x, 0) # Place lower cell M_cell = room_prison_cell(w=5, h=(h - 1) // 2, direction='up') M.meld(M_cell, cell_x, h // 2 + 1) if orientation == 'vertical': M.transpose() return M
def building_house_tworoom(w=12, h=9, wall_material=None, floor_material=None, has_exterior=True, direction='down'): """ Construct house with living room, kitchen and outdoor. Constraints: - Map width and map height must be >= 9 - Map width and map height must be <= 15 - Wall material must be 'block', 'plank', 'brick' or 'stone'. - Floor material must be 'dirt', 'parquet' or 'cobblestone'. Parameters ---------- w : int Map width h : int Map height wall_material : str Wall's material. floor_material : str Floor's material. has_exterior : bool Flag that generates an exterior of the house. direction : str Direction of the house. Can be 'up', 'down', 'left' or 'right'. """ # Initial checks. Don't accept too small/big house if w < 9 or h < 9: raise ValueError('Building is too small: w or h < 9') elif w > 12 or h > 12: raise ValueError('Building is too big: w or h > 15') # Choose materials if not wall_material: wall_material = random.choice( [C.wall_block, C.wall_plank, C.wall_brick, C.wall_stone]) elif wall_material not in (['block', 'plank', 'brick', 'stone']): raise ValueError( 'Wall material should be "block", "plank", "brick" or "stone"') if wall_material == 'block': wall_material = C.wall_block elif wall_material == 'plank': wall_material = C.wall_plank elif wall_material == 'brick': wall_material = C.wall_brick elif wall_material == 'stone': wall_material = C.wall_stone if not floor_material: floor_material = random.choice( [C.floor_dirt, C.floor_parquet, C.floor_cobblestone]) elif floor_material not in (['dirt', 'parquet', 'cobblestone']): raise ValueError( 'Floor material should be "dirt", "parquet" or "cobblestone"') if floor_material == 'dirt': floor_material = C.floor_dirt elif floor_material == 'parquet': floor_material = C.floor_parquet elif floor_material == 'cobblestone': floor_material = C.floor_cobblestone M = Map(w, h, fill_cell=C.void) main_room_h = h // 3 * 2 living_room_w = w // 2 + 1 living_room_h = h - main_room_h + 1 main_room = _room_main(w, main_room_h, wall_material, floor_material) M.meld(main_room, 0, 0) living_room = _room_living(living_room_w, living_room_h, wall_material, floor_material) M.meld(living_room, w - living_room_w, main_room_h - 1) if has_exterior: outdoor = _room_outdoor(w - living_room_w, living_room_h - 1) M.meld(outdoor, 0, main_room_h) if random.choice([True, False]): M.hmirror() if direction == 'up': M.vmirror() elif direction == 'left': M.transpose() elif direction == 'right': M.transpose() M.hmirror() return M
def room_prison_cell(w=5, h=5, direction='down'): if direction == 'left' or direction == 'right': w, h = h, w M = Map(w, h, fill_cell=C.floor_flagged) prison_cell_type = random.choice(['with_prisoner', 'with_bones', 'with_blood', 'with_spider']) # Create walls for x in range(0, w): M[x, 0] = C.wall_stone() M[x, h-1] = C.wall_stone() for y in range(0, h): M[0, y] = C.wall_stone() M[w-1, y] = C.wall_stone() # Create prison bars and door M[1, h-1] = C.wall_bars() M[3, h-1] = C.wall_bars() M[2, h-1] = C.door_closed_bars() # Place some things all_coord = [] if prison_cell_type == 'with_prisoner': for item_class in (T.furniture_napsack, T.bucket, T.furniture_torch): while True: x = random.randint(1, 3) y = random.randint(1, h-2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x,y)) break elif prison_cell_type == 'with_bones': for item_class in (T.bones, T.bones_skull): while True: x = random.randint(1, 3) y = random.randint(1, h-2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x, y)) break elif prison_cell_type == 'with_blood': for item_class in (T.bones_remains, T.effect_blood): while True: x = random.randint(1, 3) y = random.randint(1, h-2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x, y)) break elif prison_cell_type == 'with_spider': for item_class in (T.web, T.web, A.animal_spider): while True: x = random.randint(1, 3) y = random.randint(1, h-2) if (x, y) not in all_coord: M[x, y].put(item_class()) all_coord.append((x, y)) break if direction == 'up': M.vmirror() elif direction == 'left': M.transpose() elif direction == 'right': M.transpose() M.hmirror() return M
def building_medieval_mansion(w=25, h=25, wall_material=None, floor_material=None, direction='down'): """ Construct medieval mansion with living rooms, kitchen, library, treasury, servant's room and outdoor. Constraints: - Map width and map height must be >= 20 - Map width and map height must be <= 30 - Wall material must be 'block', 'plank', 'brick' or 'stone'. - Floor material must be 'dirt', 'parquet' or 'cobblestone'. Parameters ---------- w : int Map width h : int Map height wall_material : str Wall's material. floor_material : str Floor's material. direction : str Direction of the house. Can be 'up', 'down', 'left' or 'right'. """ # Initial checks. Don't accept too small/big house if w < 20 or h < 20: raise ValueError('Building is too small: w or h < 20') elif w > 30 or h > 30: raise ValueError('Building is too big: w or h > 30') # Choose materials if not wall_material: wall_material = random.choice([C.wall_block, C.wall_plank, C.wall_brick, C.wall_stone]) elif wall_material not in (['block', 'plank', 'brick', 'stone']): raise ValueError('Wall material should be "block", "plank", "brick" or "stone"') if wall_material == 'block': wall_material = C.wall_block elif wall_material == 'plank': wall_material = C.wall_plank elif wall_material == 'brick': wall_material = C.wall_brick elif wall_material == 'stone': wall_material = C.wall_stone if not floor_material: floor_material = random.choice([C.floor_dirt, C.floor_parquet, C.floor_cobblestone]) elif floor_material not in (['dirt', 'parquet', 'cobblestone']): raise ValueError('Floor material should be "dirt", "parquet" or "cobblestone"') if floor_material == 'dirt': floor_material = C.floor_dirt elif floor_material == 'parquet': floor_material = C.floor_parquet elif floor_material == 'cobblestone': floor_material = C.floor_cobblestone M = Map(w, h, fill_cell=C.void) default_room_w = w // 4 + 1 default_room_h = h // 4 library_h = h // 2 - 1 second_bedroom_h = h // 4 + 2 treasury = _room_treasury(default_room_w, default_room_h, wall_material, floor_material) M.meld(treasury, 0, 0) bedroom = _room_bedroom(default_room_w, h-second_bedroom_h-default_room_h+2, wall_material, floor_material) M.meld(bedroom, 0, default_room_h-1) second_bedroom = _room_second_bedroom(default_room_w, second_bedroom_h, wall_material, floor_material) M.meld(second_bedroom, 0, h-second_bedroom_h) sacrifice = _room_of_sacrifice(default_room_w, default_room_h, wall_material, floor_material) M.meld(sacrifice, w-default_room_w, 0) kitchen = _room_kitchen(default_room_w, h-default_room_h*2+1, wall_material, floor_material) M.meld(kitchen, w-default_room_w, default_room_h-1) servant = _room_servant(default_room_w, default_room_h+1, wall_material, floor_material) M.meld(servant, w-default_room_w, h-default_room_h-1) library = _room_library(w-default_room_w*2+2, library_h, wall_material, floor_material) M.meld(library, default_room_w-1, 0) garden = _interior_garden(w-default_room_w*2, h-library_h, wall_material, floor_material) M.meld(garden, default_room_w, library_h) if random.choice([True, False]): M.hmirror() if direction == 'up': M.vmirror() elif direction == 'left': M.transpose() elif direction == 'right': M.transpose() M.hmirror() return M
def building_prison_rectangular(w=17, h=17): """ Construct a rectangular prison interior. Parameters ---------- w : int Map width h : int Map height """ # Initial checks. Don't accept too small prisons if w < 17 or h < 17: raise ValueError('Building is too small: w or h < 17') M = Map(w, h, fill_cell=C.void) # Calculate prison cells sizes depends on prison size. cell_shift_w = (w - 1) % 4 if cell_shift_w == 1: left_w = 4 right_w = 5 elif cell_shift_w == 2: left_w = 5 right_w = 5 elif cell_shift_w == 3: left_w = 5 right_w = 6 else: left_w = 4 right_w = 4 cell_shift_h = (h - 1) % 4 if cell_shift_h == 1: top_h = 4 bottom_h = 5 elif cell_shift_h == 2: top_h = 5 bottom_h = 5 elif cell_shift_h == 3: top_h = 5 bottom_h = 6 else: top_h = 4 bottom_h = 4 # Calculate the number of prison cells fits horizontally/vertically num_cell_w = (w - left_w - right_w) // 4 num_cell_h = (h - top_h - bottom_h) // 4 # Place cells for cell_index in range(num_cell_w): cell_x = left_w + (cell_index * 4) # Place upper cell M_cell = room_prison_cell(w=5, h=top_h + 1) M.meld(M_cell, cell_x, 0) # Place lower cell M_cell = room_prison_cell(w=5, h=bottom_h + 1, direction='up') M.meld(M_cell, cell_x, h - bottom_h - 1) for cell_index in range(num_cell_h): cell_y = top_h + (cell_index * 4) # Place left cell M_cell = room_prison_cell(w=left_w + 1, h=5, direction='left') M.meld(M_cell, 0, cell_y) # Place right cell M_cell = room_prison_cell(w=right_w + 1, h=5, direction='right') M.meld(M_cell, w - right_w - 1, cell_y) center_room_w = w - (left_w + 1) - (right_w + 1) - 2 center_room_h = h - (top_h + 1) - (bottom_h + 1) - 2 center_room = _room_prison_center(center_room_w, center_room_h) M.meld(center_room, left_w + 2, top_h + 2) # Construct the corridor for x in range(left_w + 1, w - right_w - 1): M[x, top_h + 1] = C.floor_flagged() M[x, h - bottom_h - 2] = C.floor_flagged() for y in range(top_h + 1, h - bottom_h - 1): M[left_w + 1, y] = C.floor_flagged() M[w - right_w - 2, y] = C.floor_flagged() return M
def building_hunter_robber_house(size=10, material=None, house_type=None): """ Construct the hunter or robber house. Parameters ---------- size : int Square map size. This attribute will be applied for both `w` and `h`. material : string Wall material. Can be "wooden", "stone" or None. If None, a random material will be chosen. house_type : string Type of the house. Can be "hunter" or "robber". If None, a random type will be chosen. """ # Initial check. Don't accept too small/big building if size < 8 or size > 17: raise ValueError( 'Building is too small or too big: size < 8 or size > 17') # Choose materials if not material: material = random.choice(['wooden', 'stone']) if material not in ('wooden', 'stone'): raise ValueError('Material should be "stone" or "wooden"') wall_cell_type = C.wall_stone if material == 'stone' else C.wall_plank floor_cell_type = C.floor_flagged if material == 'stone' else C.floor_plank # Choose between robber house and hunter house if not house_type: house_type = random.choice(['robber', 'hunter']) if house_type not in ('robber', 'hunter'): raise ValueError('Type should be "robber" or "hunter"') M = Map(size, size, fill_cell=floor_cell_type) # Create outward walls for x in range(size): M[x, 0] = wall_cell_type() M[x, size - 1] = wall_cell_type() for y in range(size): M[0, y] = wall_cell_type() M[size - 1, y] = wall_cell_type() # Create door door_random = random.choice([True, False]) door_param = size // 3 * 2 if door_random: M[door_param, size - 1] = C.door_closed() else: M[0, door_param] = C.door_closed() # Place bonfire or hearth in the middle of the room. Place chairs M[size // 2 - 1, size // 2].put(T.furniture_chair()) M[size // 2 + 1, size // 2].put(T.furniture_chair()) if house_type == 'hunter': M[size // 2, size // 2].put(T.furniture_hearth()) else: M[size // 2, size // 2].put(T.bonfire()) # Randomly choose where escape is. Place stairs and wardrobes. escape = random.choice([True, False]) if escape: M[size - 2, 1] = C.stairs_down() if house_type == 'robber': M[size - 3, 1].put(T.furniture_closet()) M[size - 3, 2].put(T.furniture_closet()) M[size - 2, 2].put(T.furniture_closet()) elif house_type == 'hunter': M[size - 2, size - 2].put(T.furniture_closet()) else: M[1, 1] = C.stairs_down() if house_type == 'robber': M[2, 1].put(T.furniture_closet()) M[2, 2].put(T.furniture_closet()) M[1, 2].put(T.furniture_closet()) elif house_type == 'hunter': M[size - 2, size - 2].put(T.furniture_closet()) # Place beds near walls beds_start = 1 if escape else size // 3 + 1 beds_end = size // 2 if escape else size - 1 if escape: for x in range(beds_start, beds_end + 1, 2): M[x, 1].put(T.furniture_bed_single()) else: for x in range(beds_start + 1, beds_end, 2): M[x, 1].put(T.furniture_bed_single()) # Place chests M[size - 2, size // 2 - 1].put(T.furniture_chest()) M[size - 2, size // 2].put(T.furniture_chest()) # Place table with chairs for x in range(size // 5, size // 2): M[x, size - 2].put(T.furniture_longtable()) for x in range(size // 5 + 1, size // 2, 2): M[x, size - 3].put(T.furniture_chair()) return M
def building_housebarn(w=30, h=15, material=None): """ Construct the housebarn (also known as longhouse) building interior. Parameters ---------- w : int Map width h : int Map height material : string Wall material. Can be "wooden", "stone" or None. If None, a random material will be chosen. """ # Initial checks. Don't accept: # - Too small buildings # - Too long/square buildings # - Wall types that are not "stone" or "wooden" if w < 10 or h < 10: raise ValueError('Building is too small: w/h < 10') if not material: material = random.choice(['wooden', 'stone']) if material not in ('wooden', 'stone'): raise ValueError('Material should be "stone" or "wooden"') wall_cell_type = C.wall_stone if material == 'stone' else C.wall_plank is_horizontal = True if w >= h else False if is_horizontal: if w < h * 2 or w > h * 3: raise ValueError('Building is too long or too short.') else: if h < w * 2 or h > w * 3: raise ValueError('Building is too long or too short.') # If parameters are vertial, we firstly construct horizontal building then transpose it. # It allows not to use two additional different subtypes of the building which will simplify the code. if not is_horizontal: w, h = h, w M = Map(w, h, fill_cell=C.floor_flagged) # Create outward walls for x in range(w): M[x, 0] = wall_cell_type() M[x, h - 1] = wall_cell_type() for y in range(h): M[0, y] = wall_cell_type() M[w - 1, y] = wall_cell_type() # Randomly choose where the living part is living_left = random.choice([True, False]) living_wall_x = None barn_wall_x = None # Place central doors/corridor and calculate X-positions for vertical walls if w % 2 == 0: M[w // 2, 0] = C.floor_flagged() M[w // 2 - 1, 0] = C.floor_flagged() M[w // 2, h - 1] = C.floor_flagged() M[w // 2 - 1, h - 1] = C.floor_flagged() living_wall_x = (w // 2 - 3) if living_left else (w // 2 + 2) barn_wall_x = (w // 2 + 2) if living_left else (w // 2 - 3) else: M[w // 2, 0] = C.door_closed_wooden() M[w // 2, h - 1] = C.door_closed_wooden() living_wall_x = (w // 2 - 2) if living_left else (w // 2 + 2) barn_wall_x = (w // 2 + 2) if living_left else (w // 2 - 2) # Place vertical walls for i in range(1, h // 3): M[living_wall_x, i] = wall_cell_type() M[living_wall_x, h - i - 1] = wall_cell_type() for i in range(1, h - 1): M[barn_wall_x, i] = C.wall_fence_thin() M[barn_wall_x, h // 2] = C.door_closed_wooden() # Create living room: # Set initial coordinates lx_start = 1 if living_left else living_wall_x + 1 lx_end = living_wall_x - 1 if living_left else w - 1 beds_dx = int((lx_end - lx_start) % 2 == 0 and not living_left) beds_dy = random.choice([0, 1]) # Place beds near walls or at 1 cell from walls for bed_x in range(lx_start + beds_dx, lx_end, 2): M[bed_x, 1 + beds_dy].put(T.furniture_bed_single()) M[bed_x, h - 2 - beds_dy].put(T.furniture_bed_single()) # Place bonfire in the middle of the room or hearth on the side of the room is_bonfire = random.choice([True, False]) if is_bonfire: M[(lx_start + lx_end) // 2, h // 2].put(T.bonfire()) elif living_left: M[1, h // 2].put(T.furniture_hearth()) else: M[w - 2, h // 2].put(T.furniture_hearth()) # Create barn: # Set initial coordinates bx_start = 1 if not living_left else barn_wall_x + 1 bx_end = barn_wall_x - 1 if not living_left else w - 2 # Fill the barn floor with dirt for x in range(bx_start, bx_end + 1): for y in range(1, h - 1): M[x, y] = C.floor_dirt() is_central_barn = random.choice([True, False]) if is_central_barn: # Central barn: stalls in the center, two waterthroughs on the side for y in range(h // 3, h * 2 // 3): M[bx_start + 2, y] = C.wall_fence_thin() for x in range(bx_start + 3, bx_end - 2, 2): M[x, h // 2] = C.wall_fence_thin() M[x, h // 2 - 1].put(T.farm_mangler()) M[x, h // 2 + 1].put(T.farm_mangler()) for y in range(h // 3, h * 2 // 3): M[x + 1, y] = C.wall_fence_thin() for x in range(bx_start + 1, bx_end): M[x, 1].put(T.water_trough()) M[x, h - 2].put(T.water_trough()) else: # Side barn: stalls on the side, one waterthrough in the center for x in range(bx_start, bx_end - 1, 2): M[x, 1].put(T.farm_mangler()) M[x, h - 2].put(T.farm_mangler()) for y in range(1, h // 3): M[x + 1, y] = C.wall_fence_thin() for y in range(h * 2 // 3, h - 1): M[x + 1, y] = C.wall_fence_thin() for x in range(bx_start + 2, bx_end - 1): M[x, h // 2].put(T.water_trough()) # Transpose the building if it should be vertical if not is_horizontal: M.transpose() return M
def building_kitchengarden(w=17, h=17, wall_material=None, floor_material=None, direction='down'): """ Construct kitchen garden with big storage, garden beds and cattle pens. Constraints: - Map width and map height must be >= 17 - Map width and map height must be <= 22 - Wall material must be 'block', 'plank' or 'stone'. - Floor material must be 'grit' or 'rocks'. Parameters ---------- w : int Map width h : int Map height wall_material : str Wall's material. floor_material : str Floor's material. direction : str Direction of the kitchen garden. Can be 'up', 'down', 'left' or 'right'. """ # Initial checks. Don't accept too small/big kitchen garden if w < 17 or h < 17: raise ValueError('Building is too small: w or h < 17') elif w > 22 or h > 22: raise ValueError('Building is too big: w or h > 22') # Choose materials if not wall_material: wall_material = random.choice( [C.wall_block, C.wall_plank, C.wall_stone]) elif wall_material not in (['block', 'plank', 'stone']): raise ValueError('Wall material should be "block", "plank" or "stone"') if wall_material == 'block': wall_material = C.wall_block elif wall_material == 'plank': wall_material = C.wall_plank elif wall_material == 'stone': wall_material = C.wall_stone if not floor_material: floor_chance = random.random() if floor_chance > 0.3: floor_material = C.floor_rocks else: floor_material = C.floor_grit elif floor_material not in (['grit', 'rocks']): raise ValueError('Floor material should be "grit" or "rocks"') if floor_material == 'grit': floor_material = C.floor_grit elif floor_material == 'rocks': floor_material = C.floor_rocks M = Map(w, h, fill_cell=floor_material) storage_w = w // 3 * 2 storage_h = h // 4 + 1 garden_beds_w = w // 2 for i in range(w * h // 3): grass_x = random.randint(1, w - 1) grass_y = random.randint(0, h - 2) M[grass_x, grass_y] = random.choice( [C.flora_grass, C.flora_tree, C.floor_grass])() garden_beds = _room_garden_beds(garden_beds_w, h - storage_h + 1, wall_material, floor_material) M.meld(garden_beds, 0, storage_h - 1) cattle_pens = _room_cattle_pens(w - garden_beds_w + 1, h - storage_h + 1, wall_material, floor_material) M.meld(cattle_pens, garden_beds_w - 1, storage_h - 1) storage = _room_storage(storage_w, storage_h, wall_material, floor_material, garden_beds_w) M.meld(storage, 0, 0) for x in range(storage_w, w - 1): M[x, storage_h // 2] = floor_material() for y in range(storage_h // 2, storage_h - 1): M[storage_w + 1, y] = floor_material() if random.choice([True, False]): M.hmirror() if direction == 'up': M.vmirror() elif direction == 'left': M.transpose() elif direction == 'right': M.transpose() M.hmirror() return M