def gen(rng, dim=(500, 150), num_mountain_ranges=5, num_guaranteed_paths=5, num_lakes=20, num_rivers=20, num_cities=20, num_forests=30, num_deserts=60, terrain_info=default_terrain_info): margin = int(dim[1] / 4) range_dist = int(dim[0] / (num_mountain_ranges + 1)) max_point_offset = int(range_dist / 10) ending_point = clamp_point(dim, (int(range_dist / 2) + rng.randint(-max_point_offset, max_point_offset), rng.randint(margin, dim[1] - margin))) starting_point = clamp_point(dim, (dim[0] - int(range_dist / 2) + rng.randint(-max_point_offset, max_point_offset), rng.randint(margin, dim[1] - margin))) noise = tcod.noise.Noise(2, seed=rng) height = make_base_heightmap(dim, noise) height_pather = tcod.path.AStar(height) mountain_spines = carve_mountains(height, dim, num_mountain_ranges, height_pather, rng) lake_points = carve_lakes(height, dim, num_mountain_ranges, height_pather, rng) height[:] += 1 smooth(height, dim, rng) norm_height = tcod.heightmap_new(*dim) tcod.heightmap_copy(height, norm_height) tcod.heightmap_normalize(norm_height, 0, 1) terrain = tilemap.Tilemap(dim, init=lambda _: things.desert) assign_base_terrain(terrain, norm_height, dim, terrain_info) make_forests(terrain, height, dim, num_forests, height_pather, rng) run_rivers(terrain, height, lake_points, dim, num_rivers, rng, max_x_offset=range_dist) walkability = make_walk_map(terrain, height, dim) walk_pather = tcod.path.AStar(walkability) make_guaranteed_paths(terrain, height, dim, starting_point, ending_point, num_guaranteed_paths, num_mountain_ranges, walk_pather, rng) make_deserts(terrain, height, dim, num_deserts, height_pather, rng) city_points = make_cities(terrain, dim, num_cities, rng, range_dist) make_roads(terrain, height, city_points, dim, walk_pather, rng) return terrain, starting_point, ending_point, city_points, mountain_spines
def generate_global_map(shape: tuple) -> typing.List[typing.List[Tile]]: """Return simple rectangular map with shape shape Precondition: len(shape)==2 """ # create height map global_map = tcod.heightmap_new(shape[0], shape[1]) # voroni tcod.heightmap_add_voronoi(global_map, 2, 2, [0.1, 1.5, 0.6, 1.7, 0.8], rnd=0) # normalize tcod.heightmap_normalize(global_map) # assign TILE to every value of heightmap tile_map = [] for row in global_map: holder = [] for value in row: if value > UPPER_BOUND: holder.append(Tile(True)) elif value > MID_BOUND: holder.append(Tile(True, block_sight=False)) else: holder.append(Tile(False)) tile_map.append(holder) return tile_map
def precipitation(precip_heightmap, temp_heightmap): precip_heightmap[:] += 2 for x in range(WORLD_WIDTH): for y in range(WORLD_HEIGHT): temp = tcod.heightmap_get_value(temp_heightmap, x, y) precipitation = tcod.noise_new(2, tcod.NOISE_DEFAULT_HURST, tcod.NOISE_DEFAULT_LACUNARITY) tcod.heightmap_add_fbm(precip_heightmap, precipitation, 2, 2, 0, 0, 32, 1, 1) tcod.heightmap_normalize(precip_heightmap, 0.0, 1.0) return precip_heightmap, temp_heightmap
def smooth_map(self): # 3x3 kernel for smoothing operations smooth_ks = 9 smooth_dx = [-1, 0, 1, -1, 0, 1, -1, 0, 1] smooth_dy = [-1, -1, -1, 0, 0, 0, 1, 1, 1] smooth_weight = [2, 8, 2, 8, 20, 8, 2, 8, 2] tcod.heightmap_kernel_transform(self._hm, smooth_ks, smooth_dx, smooth_dy, smooth_weight, -1000, 1000) tcod.heightmap_kernel_transform(self._hm2, smooth_ks, smooth_dx, smooth_dy, smooth_weight, -1000, 1000) tcod.heightmap_normalize(self._hm)
def normalize(self, min=0.0, max=1.0): """Normalize heightmap values between <min> and <max>. The heightmap is translated and scaled so that the lowest cell value becomes min and the highest cell value becomes max min < max.""" # max(data)*m+b = max # max-max(data)*m = b # - # min(data)*m+b = min # min(data)*m+max-max(data)*m=min # m*(min(data)-max(data)) = min-max # m = (min-max)/(min(data)-max(data)) tcod.heightmap_normalize(self._data, min, max)
def Percipitaion(preciphm, temphm): tcod.heightmap_add(preciphm, 2) for x in range(WORLD_WIDTH): for y in range(WORLD_HEIGHT): temp = tcod.heightmap_get_value(temphm, x, y) precip = tcod.noise_new(2, tcod.NOISE_DEFAULT_HURST, tcod.NOISE_DEFAULT_LACUNARITY) # tcod.heightmap_add_fbm(preciphm,precip ,2, 2, 0, 0, 32, 1, 1) tcod.heightmap_normalize(preciphm, 0.0, 1.0)
def make_base_heightmap(dim, noise): height = tcod.heightmap_new(*dim) height[:] = 1 tcod.heightmap_add_fbm(height, noise = noise, mulx = 6, muly = 6, addx = 0, addy = 0, octaves = 5, delta = 0, scale = 1 ) tcod.heightmap_normalize(height, 0.1, 1.5) return height
def test_heightmap(): hmap = libtcodpy.heightmap_new(16, 16) repr(hmap) noise = libtcodpy.noise_new(2) # basic operations libtcodpy.heightmap_set_value(hmap, 0, 0, 1) libtcodpy.heightmap_add(hmap, 1) libtcodpy.heightmap_scale(hmap, 1) libtcodpy.heightmap_clear(hmap) libtcodpy.heightmap_clamp(hmap, 0, 0) libtcodpy.heightmap_copy(hmap, hmap) libtcodpy.heightmap_normalize(hmap) libtcodpy.heightmap_lerp_hm(hmap, hmap, hmap, 0) libtcodpy.heightmap_add_hm(hmap, hmap, hmap) libtcodpy.heightmap_multiply_hm(hmap, hmap, hmap) # modifying the heightmap libtcodpy.heightmap_add_hill(hmap, 0, 0, 4, 1) libtcodpy.heightmap_dig_hill(hmap, 0, 0, 4, 1) libtcodpy.heightmap_rain_erosion(hmap, 1, 1, 1) libtcodpy.heightmap_kernel_transform(hmap, 3, [-1, 1, 0], [0, 0, 0], [.33, .33, .33], 0, 1) libtcodpy.heightmap_add_voronoi(hmap, 10, 3, [1,3,5]) libtcodpy.heightmap_add_fbm(hmap, noise, 1, 1, 1, 1, 4, 1, 1) libtcodpy.heightmap_scale_fbm(hmap, noise, 1, 1, 1, 1, 4, 1, 1) libtcodpy.heightmap_dig_bezier(hmap, [0, 16, 16, 0], [0, 0, 16, 16], 1, 1, 1, 1) # read data libtcodpy.heightmap_get_value(hmap, 0, 0) libtcodpy.heightmap_get_interpolated_value(hmap, 0, 0) libtcodpy.heightmap_get_slope(hmap, 0, 0) libtcodpy.heightmap_get_normal(hmap, 0, 0, 0) libtcodpy.heightmap_count_cells(hmap, 0, 0) libtcodpy.heightmap_has_land_on_border(hmap, 0) libtcodpy.heightmap_get_minmax(hmap) libtcodpy.noise_delete(noise) libtcodpy.heightmap_delete(hmap)
def test_heightmap(): hmap = libtcodpy.heightmap_new(16, 16) repr(hmap) noise = libtcodpy.noise_new(2) # basic operations libtcodpy.heightmap_set_value(hmap, 0, 0, 1) libtcodpy.heightmap_add(hmap, 1) libtcodpy.heightmap_scale(hmap, 1) libtcodpy.heightmap_clear(hmap) libtcodpy.heightmap_clamp(hmap, 0, 0) libtcodpy.heightmap_copy(hmap, hmap) libtcodpy.heightmap_normalize(hmap) libtcodpy.heightmap_lerp_hm(hmap, hmap, hmap, 0) libtcodpy.heightmap_add_hm(hmap, hmap, hmap) libtcodpy.heightmap_multiply_hm(hmap, hmap, hmap) # modifying the heightmap libtcodpy.heightmap_add_hill(hmap, 0, 0, 4, 1) libtcodpy.heightmap_dig_hill(hmap, 0, 0, 4, 1) libtcodpy.heightmap_rain_erosion(hmap, 1, 1, 1) libtcodpy.heightmap_kernel_transform(hmap, 3, [-1, 1, 0], [0, 0, 0], [.33, .33, .33], 0, 1) libtcodpy.heightmap_add_voronoi(hmap, 10, 3, [1, 3, 5]) libtcodpy.heightmap_add_fbm(hmap, noise, 1, 1, 1, 1, 4, 1, 1) libtcodpy.heightmap_scale_fbm(hmap, noise, 1, 1, 1, 1, 4, 1, 1) libtcodpy.heightmap_dig_bezier(hmap, [0, 16, 16, 0], [0, 0, 16, 16], 1, 1, 1, 1) # read data libtcodpy.heightmap_get_value(hmap, 0, 0) libtcodpy.heightmap_get_interpolated_value(hmap, 0, 0) libtcodpy.heightmap_get_slope(hmap, 0, 0) libtcodpy.heightmap_get_normal(hmap, 0, 0, 0) libtcodpy.heightmap_count_cells(hmap, 0, 0) libtcodpy.heightmap_has_land_on_border(hmap, 0) libtcodpy.heightmap_get_minmax(hmap) libtcodpy.noise_delete(noise) libtcodpy.heightmap_delete(hmap)
def smooth_precipitations(self): temphm = self._precipitation.copy() hm_data = self._precipitation for i in range(4, 0, -1): for x in range(self.width): minx = max((0, x - 2)) maxx = min((self.width - 1, x + 2)) miny = 0 maxy = 2 psum = np.sum(hm_data[minx:maxx, miny:maxy]) pcount = (maxy - miny) * (maxx - minx) temphm[x, 0] = psum / pcount for y in range(1, self.height): if (y - 2) >= 0: psum -= np.sum(hm_data[minx:maxx, y - 2]) pcount -= (maxx - minx) if (y + 2) < self.height: psum += np.sum(hm_data[minx:maxx, y + 2]) pcount += (maxx - minx) temphm[y, x] = psum / pcount self._precipitation = temphm.copy() tcod.heightmap_normalize(self._precipitation)
def build_base_map(self, hill_cnt=60): self.add_land(hill_cnt, 16 * self.width / 200, 0.7, 0.6) tcod.heightmap_normalize(self._hm) tcod.heightmap_add_fbm(self._hm, noise2d, 2.20 * self.width / 400, 2.2 * self.width / 400, 0, 0, 10, 1.0, 2.05) tcod.heightmap_normalize(self._hm) self._hm2 = self._hm.copy() self.set_land_mass(0.6, SAND_HEIGHT) # Fix land/mountain ratio using x^3 curve above sea level for x in range(self.width): for y in range(self.height): h = self._hm[y, x] if h >= SAND_HEIGHT: coef = (h - SAND_HEIGHT) / (1.0 - SAND_HEIGHT) h = SAND_HEIGHT + coef * coef * coef * (1.0 - SAND_HEIGHT) self._hm[y, x] = h f = [0, 0] for x in range(self.width): f[0] = 6.0 * x / self.width for y in range(self.height): f[1] = 6.0 * y / self.height self._clouds[y, x] = 0.5 * (1.0 + 0.8 * tcod.noise_get_fbm( noise2d, f, 4.0, tcod.NOISE_SIMPLEX))
def MasterWorldGen(): # ------------------------------------------------------- * MASTER GEN * ------------------------------------------------------------- print(" * World Gen START * ") starttime = time.time() # Heightmap hm = tcod.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT) for i in range(250): tcod.heightmap_add_hill( hm, randint(WORLD_WIDTH / 10, WORLD_WIDTH - WORLD_WIDTH / 10), randint(WORLD_HEIGHT / 10, WORLD_HEIGHT - WORLD_HEIGHT / 10), randint(12, 16), randint(6, 10), ) print("- Main Hills -") for i in range(1000): tcod.heightmap_add_hill( hm, randint(WORLD_WIDTH / 10, WORLD_WIDTH - WORLD_WIDTH / 10), randint(WORLD_HEIGHT / 10, WORLD_HEIGHT - WORLD_HEIGHT / 10), randint(2, 4), randint(6, 10), ) print("- Small Hills -") tcod.heightmap_normalize(hm, 0.0, 1.0) noisehm = tcod.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT) noise2d = tcod.noise_new( 2, tcod.NOISE_DEFAULT_HURST, tcod.NOISE_DEFAULT_LACUNARITY ) # tcod.heightmap_add_fbm(noisehm, noise2d,6, 6, 0, 0, 32, 1, 1) tcod.heightmap_normalize(noisehm, 0.0, 1.0) # tcod.heightmap_multiply_hm(hm, noisehm, hm) print("- Apply Simplex -") PoleGen(hm, 0) print("- South Pole -") PoleGen(hm, 1) print("- North Pole -") TectonicGen(hm, 0) TectonicGen(hm, 1) print("- Tectonic Gen -") tcod.heightmap_rain_erosion(hm, WORLD_WIDTH * WORLD_HEIGHT, 0.07, 0, 0) print("- Erosion -") tcod.heightmap_clamp(hm, 0.0, 1.0) # Temperature temp = tcod.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT) Temperature(temp, hm) tcod.heightmap_normalize(temp, 0.0, 1.0) print("- Temperature Calculation -") # Precipitation preciphm = tcod.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT) Percipitaion(preciphm, temp) tcod.heightmap_normalize(preciphm, 0.0, 1.0) print("- Percipitaion Calculation -") # Drainage drainhm = tcod.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT) drain = tcod.noise_new( 2, tcod.NOISE_DEFAULT_HURST, tcod.NOISE_DEFAULT_LACUNARITY ) # tcod.heightmap_add_fbm(drainhm,drain ,2, 2, 0, 0, 32, 1, 1) tcod.heightmap_normalize(drainhm, 0.0, 1.0) print("- Drainage Calculation -") # VOLCANISM - RARE AT SEA FOR NEW ISLANDS (?) RARE AT MOUNTAINS > 0.9 (?) RARE AT TECTONIC BORDERS (?) elapsed_time = time.time() - starttime print(" * World Gen DONE * in: ", elapsed_time, " seconds") # Initialize Tiles with Map values World = [[0 for y in range(WORLD_HEIGHT)] for x in range(WORLD_WIDTH)] for x in range(WORLD_WIDTH): for y in range(WORLD_HEIGHT): World[x][y] = Tile( tcod.heightmap_get_value(hm, x, y), tcod.heightmap_get_value(temp, x, y), tcod.heightmap_get_value(preciphm, x, y), tcod.heightmap_get_value(drainhm, x, y), 0, ) print("- Tiles Initialized -") # Prosperity Prosperity(World) print("- Prosperity Calculation -") # Biome info to Tile for x in range(WORLD_WIDTH): for y in range(WORLD_HEIGHT): if ( World[x][y].precip >= 0.10 and World[x][y].precip < 0.33 and World[x][y].drainage < 0.5 ): World[x][y].biomeID = 3 if randint(1, 2) == 2: World[x][y].biomeID = 16 if World[x][y].precip >= 0.10 and World[x][y].precip > 0.33: World[x][y].biomeID = 2 if World[x][y].precip >= 0.66: World[x][y].biomeID = 1 if ( World[x][y].precip >= 0.33 and World[x][y].precip < 0.66 and World[x][y].drainage >= 0.33 ): World[x][y].biomeID = 15 if randint(1, 5) == 5: World[x][y].biomeID = 5 if ( World[x][y].temp > 0.2 and World[x][y].precip >= 0.66 and World[x][y].drainage > 0.33 ): World[x][y].biomeID = 5 if World[x][y].precip >= 0.75: World[x][y].biomeID = 6 if randint(1, 5) == 5: World[x][y].biomeID = 15 if ( World[x][y].precip >= 0.10 and World[x][y].precip < 0.33 and World[x][y].drainage >= 0.5 ): World[x][y].biomeID = 16 if randint(1, 2) == 2: World[x][y].biomeID = 14 if World[x][y].precip < 0.10: World[x][y].biomeID = 4 if World[x][y].drainage > 0.5: World[x][y].biomeID = 16 if randint(1, 2) == 2: World[x][y].biomeID = 14 if World[x][y].drainage >= 0.66: World[x][y].biomeID = 8 if World[x][y].height <= 0.2: World[x][y].biomeID = 0 if World[x][y].temp <= 0.2 and World[x][y].height > 0.15: World[x][y].biomeID = randint(11, 13) if World[x][y].height > 0.6: World[x][y].biomeID = 9 if World[x][y].height > 0.9: World[x][y].biomeID = 10 print("- BiomeIDs Atributed -") # River Gen for x in range(1): RiverGen(World) print("- River Gen -") # Free Heightmaps tcod.heightmap_delete(hm) tcod.heightmap_delete(temp) tcod.heightmap_delete(noisehm) print(" * Biomes/Rivers Sorted *") return World
def normalize(self, min=0.0, max=1.0): tcod.heightmap_normalize(self._data, min, max) return self