def test_noise(): noise = libtcodpy.noise_new(1) libtcodpy.noise_set_type(noise, libtcodpy.NOISE_SIMPLEX) libtcodpy.noise_get(noise, [0]) libtcodpy.noise_get_fbm(noise, [0], 4) libtcodpy.noise_get_turbulence(noise, [0], 4) libtcodpy.noise_delete(noise)
def draw(self): self.left = left = int((self.size/2) + (self.sector.visible_space_left * self.parallax_speed)) self.top = top = int((self.size/2) + (self.sector.visible_space_top * self.parallax_speed)) self.right = right = left + self.sector.screen_width self.bottom = bottom = top + self.sector.screen_height if self.last_left != left or self.last_top != top: for y in range(0, self.sector.screen_height+2): self.grid[(left-1)%self.size][(top-1+y)%self.size] = None self.grid[(right)%self.size][(top-1+y)%self.size] = None for x in range(0, self.sector.screen_width+2): self.grid[(left-1+x)%self.size][(bottom)%self.size] = None self.grid[(left-1+x)%self.size][(top-1)%self.size] = None self.last_left = left self.last_top = top for y in range(0, self.sector.screen_height): for x in range(0, self.sector.screen_width): if self.grid[(left+x)%self.size][(top+y)%self.size] == None: f = [9999 + self.noise_zoom * (left+x) / (2*self.sector.screen_width), 9999 + self.noise_zoom * (top+y) / (2*self.sector.screen_height)] r = self.get_color_value(libtcod.noise_get_fbm(self.r_noise, f, self.noise_octaves, libtcod.NOISE_SIMPLEX), self.r_factor) g = self.get_color_value(libtcod.noise_get_fbm(self.g_noise, f, self.noise_octaves, libtcod.NOISE_SIMPLEX), self.g_factor) b = self.get_color_value(libtcod.noise_get_fbm(self.b_noise, f, self.noise_octaves, libtcod.NOISE_SIMPLEX), self.b_factor) c = self.exponent_filter( (libtcod.noise_get_fbm(self.c_noise, f, self.noise_octaves, libtcod.NOISE_SIMPLEX) + 1.0) * 255 ) self.grid[(left+x)%self.size][(top+y)%self.size] = [ self.blend_colors( self.blend_multiply(r,c), self.blend_multiply(g,c), self.blend_multiply(b,c), self.sector.background[0], self.sector.background[1], self.sector.background[2], 0.5), None ] f[0] *= 1000.0 f[1] *= 1000.0 star_value = libtcod.noise_get_fbm(self.s_noise, f, self.noise_octaves, libtcod.NOISE_SIMPLEX) if 0.1 < star_value < 0.11: r, g, b = self.grid[(left+x)%self.size][(top+y)%self.size][0] rm = r * random.choice([1, 2, 3, 4, 5]) if r * 5 < 255 else 255 gm = g * random.choice([1, 2, 3, 4, 5]) if g * 5 < 255 else 255 bm = b * random.choice([1, 2, 3, 4, 5]) if b * 5 < 255 else 255 self.grid[(left+x)%self.size][(top+y)%self.size][1] = [rm, gm, bm] # Set the nebula background color r, g, b = self.grid[(left+x)%self.size][(top+y)%self.size][0] self.sector.buffer.set_back(x, self.sector.mirror_y_coordinate(y), r, g, b) # Create a Star if self.grid[(left+x)%self.size][(top+y)%self.size][1]: rm, gm, bm = self.grid[(left+x)%self.size][(top+y)%self.size][1] self.sector.buffer.set_fore(x, self.sector.mirror_y_coordinate(y), rm, gm, bm, ord('.'))
def __init__(self, x, y, world_width, world_height, world_noise, resource_noise): self.x = x self.y = y self.la = ((Decimal(self.y) * 180) / Decimal(world_height)) - 90 self.lo = ((Decimal(self.x) * 360) / Decimal(world_width)) - 180 self.char = '#' self.color = WHITE self.neighbors = {} # Sampling 3d noise to get the shape of the landmasses x, y, z = spherical_to_cartesian(self.la, self.lo, self.LANDMASS_SIZE) self.elevation = libtcod.noise_get_fbm( world_noise, [float(x), float(y), float(z)], self.DETAIL) # Sampling 3d noise to find out where to spawn resource nodes x, y, z = spherical_to_cartesian(self.la, self.lo, self.RESOURCE_DISTRIBUTION) if self.elevation > 0: self.resource_density = libtcod.noise_get( resource_noise, [float(x), float(y), float(z)]) else: self.resource_density = 0 for elev_range, elev_info in self.ELEVATIONS.items(): max_, min_ = elev_range if max_ >= self.elevation > min_: self.color = elev_info['color'] self.char = elev_info['char']
def generate_land(self): for x in range(self.width): for y in range(self.height): f = [self.noise_zoom * x / self.width, self.noise_zoom * y / self.height] value = libtcod.noise_get_fbm(self.world_noise, f, self.noise_octaves, libtcod.NOISE_PERLIN) #Threshold c = ((value + 1.0) / 2.0) col = libtcod.color_lerp(libtcod.dark_green, libtcod.black, c) self.map_list[x][y].land_type = 'grass' c = int((value + 1.0) / 2.0 * 200) c = c - int(self.dist(x,y))/1.5 #This is a beach if c < 28: col = libtcod.lightest_amber self.map_list[x][y].land_type = 'beach' #This is water if c < 20: coef = self.dist(x,y) / 320 col = libtcod.color_lerp(libtcod.azure, libtcod.darkest_azure * (c/2), coef) if c > 5: self.map_list[x][y].land_type = 'shallow_water' else: self.map_list[x][y].land_type = 'deep_water' libtcod.map_set_properties(self.deepsea_map, x, y, False, True) if self.map_list[x][y].land_type == 'grass' or self.map_list[x][y].land_type == 'beach': libtcod.map_set_properties(self.ground_map, x, y, False, True) self.map_list[x][y].color = col libtcod.image_put_pixel(self.world_img, x, y, self.map_list[x][y].color)
def make_map(): global map, objects #the list of objects with just the player objects = [player] player.x = MAP_WIDTH / 2 player.y = MAP_HEIGHT / 2 myrng = libtcod.random_new(123) noise2d = libtcod.noise_new(2,libtcod.NOISE_DEFAULT_HURST, libtcod.NOISE_DEFAULT_LACUNARITY, myrng) libtcod.noise_set_type(noise2d, libtcod.NOISE_PERLIN) #fill map with "normal" tiles map = [[Tile(False, libtcod.light_gray) for y in range(MAP_HEIGHT)] for x in range(MAP_WIDTH)] #add color for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): value = int((libtcod.noise_get_fbm(noise2d,[x/float(MAP_WIDTH),y/float(MAP_HEIGHT)],32) + 1) * 96 ) map[x][y] = Tile(False, libtcod.Color(value,value,value)) r = [libtcod.random_get_int(0, CRATER_MIN_SIZE, (CRATER_MIN_SIZE + (CRATER_MAX_SIZE - CRATER_MIN_SIZE) * (MAX_CRATERS - i)**2/(MAX_CRATERS**2)) ) for i in range(MAX_CRATERS)] r.sort(reverse=True) for i in range(MAX_CRATERS): x = libtcod.random_get_int(0, 0, MAP_WIDTH - 1) y = libtcod.random_get_int(0, 0, MAP_HEIGHT - 1) # r = libtcod.random_get_int(0, CRATER_MIN_SIZE, (CRATER_MIN_SIZE + (CRATER_MAX_SIZE - CRATER_MIN_SIZE) * (MAX_CRATERS - i)/MAX_CRATERS) ) make_crater(x, y, r[i]) spawn_silicon(noise2d)
def spawn_silicon(noise2d): global si max_si_value = 100 si = [[0 for y in range(MAP_HEIGHT)] for x in range(MAP_WIDTH)] for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): si[x][y] = int((libtcod.noise_get_fbm(noise2d,[x/float(MAP_WIDTH),y/float(MAP_HEIGHT)],32) + 1) * 0.5 * max_si_value)
def get_noise_value(x, y, scale=16, type='FBM'): nx, ny = float(x) / scale, float(y) / scale if type == 'DEFAULT': pre_value = libtcod.noise_get(noise_field, (nx, ny) , libtcod.NOISE_PERLIN) elif type == 'FBM': pre_value = libtcod.noise_get_fbm(noise_field, (nx, ny), 8, libtcod.NOISE_DEFAULT) elif type == 'TURB': pre_value = libtcod.noise_get_turbulence(noise_field, (nx, ny), 1, libtcod.NOISE_PERLIN) return pre_value
def get_noise_value(x, y, scale=16, type='FBM'): nx, ny = float(x) / scale, float(y) / scale if type == 'DEFAULT': pre_value = libtcod.noise_get(noise_field, (nx, ny), libtcod.NOISE_PERLIN) elif type == 'FBM': pre_value = libtcod.noise_get_fbm(noise_field, (nx, ny), 8, libtcod.NOISE_DEFAULT) elif type == 'TURB': pre_value = libtcod.noise_get_turbulence(noise_field, (nx, ny), 1, libtcod.NOISE_PERLIN) return pre_value
def spherical_noise(self, noise_dx=0.0, noise_dy=0.0, noise_dz=0.0, noise_octaves=4.0, noise_zoom=1.0, noise_hurst=libtcod.NOISE_DEFAULT_HURST, noise_lacunarity=libtcod.NOISE_DEFAULT_LACUNARITY, width=None, height=None, seed=None): self.rnd = libtcod.random_new_from_seed(self.seed) if seed is None else libtcod.random_new_from_seed(seed) noise = libtcod.noise_new(3, noise_hurst, noise_lacunarity, self.rnd) hm = libtcod.heightmap_new(width, height) noise_dx += 0.01 noise_dy += 0.01 noise_dz += 0.01 pi_times_two = 2 * math.pi pi_div_two = math.pi / 2.0 theta = 0.0 phi = pi_div_two * -1.0 x = 0 y = 0 while phi <= pi_div_two: while theta <= pi_times_two: f = [ noise_zoom * math.cos(phi) * math.cos(theta), noise_zoom * math.cos(phi) * math.sin(theta), noise_zoom * math.sin(phi), ] value = libtcod.noise_get_fbm(noise, f, noise_octaves, libtcod.NOISE_PERLIN) # print((x, y, value)) libtcod.heightmap_set_value(hm, x, y, value) theta += (pi_times_two / width) x += 1 phi += (math.pi / (height-1)) y += 1 x = 0 theta = 0.0 return hm
def get_cylindrical_projection(stars, width=360, height=180): """ Return a tcod console instance of width and height that renders an equirectangular projection of the given list of stars. """ console = tcod.console_new(width, height) for star in stars: azimuthal = int((star.azimuthal * width) / (2 * math.pi)) polar = int((star.polar / math.pi) * height) # Color Work rgb = temperature_to_rgb(random.uniform(4000, 20000)) brightness = 1.0 - star.radial * 0.75 color = tcod.Color(rgb[0], rgb[1], rgb[2]) (h, s, v) = tcod.color_get_hsv(color) tcod.color_set_hsv(color, h, s, brightness) tcod.console_put_char_ex(console, azimuthal, polar, star.sprite, color, tcod.black) # Background Texture noise3d = tcod.noise_new(3) for map_x in range(width): for map_y in range(height): azimuthal = (map_x / (width * 1.0)) * 2.0 * math.pi polar = (map_y / (height * 1.0)) * math.pi x = math.sin(polar) * math.cos(azimuthal) y = math.sin(polar) * math.sin(azimuthal) z = math.cos(polar) blue = int( tcod.noise_get_turbulence(noise3d, [x, y, z], 32.0) * 16.0 + 16.0) green = int(tcod.noise_get(noise3d, [x, y, z]) * 8.0 + 8.0) red = int(tcod.noise_get_fbm(noise3d, [x, y, z], 32.0) * 4.0 + 4.0) background = tcod.Color(red, green, blue) if map_y == height / 2 or map_x == 0 or map_x == width / 2: background = tcod.darkest_yellow tcod.console_set_char_background(console, map_x, map_y, background) tcod.noise_delete(noise3d) return console
def generate(self): self.owner.log.message("Generating map...", debug = True) noise = libtcod.noise_new(2, 0.5, 2.0) heightmap = libtcod.heightmap_new(2*self.width, 2*self.height) maxi = 0 mini = 0 self.tiles = [[ Tile() for y in range(self.height) ] for x in range(self.width) ] self.owner.log.message("-- creating heightmap...", debug = True) for x in range(self.width*2): for y in range(self.height*2): f = [3 * float(x) / (2*self.width), 3 * float(y) / (2*self.height)] value = (libtcod.noise_get_fbm(noise, f, 5, libtcod.NOISE_PERLIN))/2 if value > maxi: maxi = value if value < mini: mini = value libtcod.heightmap_set_value(heightmap, x, y, value) # print "-- erode the map" # libtcod.heightmap_rain_erosion(heightmap, self.width*2*self.height*2*2,0.1,0.2) self.owner.log.message("-- normalize heights...", debug = True) self.heightmap = libtcod.heightmap_new(self.width*2, self.height*2) for x in range(self.width*2): for y in range(self.height*2): value = libtcod.heightmap_get_value(heightmap, x, y) if value < 0: value += 1 mini2 = mini + 1 coeff = (value - mini2)/(1-mini2) libtcod.heightmap_set_value(self.heightmap, x, y, -coeff) else: value = value / maxi libtcod.heightmap_set_value(self.heightmap, x, y, value) self.owner.log.message("-- setting up tiles", debug = True) for x in range(self.width): for y in range(self.height): h = libtcod.heightmap_get_value(self.heightmap, x*2, y*2) if h >= 0.05: self.tiles[x][y].terrain = "land" else: self.tiles[x][y].terrain = "water" # self.owner.log.message("-- creating temperature map", debug = True) # noise2 = libtcod.noise_new(2, 0.5, 2.0) # temp_max = 0 # temp_min = 1 # for x in range(self.width): # for y in range(self.height): # f = [3 * float(x) / (self.width), 3 * float(y) / (self.height)] # value = (libtcod.noise_get_fbm(noise2, f, 5, libtcod.NOISE_PERLIN))/2 # value = (value + 1)/2 # if value < temp_min: # temp_min = value # if value > temp_max: # temp_max = value # self.tiles[x][y].temp = value # temp_max = temp_max - temp_min # height_factor = 0.5 # for x in range(self.width): # for y in range(self.height): # temp = (self.tiles[x][y].temp - temp_min)/temp_max # h = libtcod.heightmap_get_value(self.heightmap, x*2, y*2) # if h > 0: # factor = (-h)*height_factor # temp = temp + factor # temp = min(1, temp) # temp = max(0, temp) # self.tiles[x][y].temp = temp self.owner.log.message("-- creating rainfall map", debug = True) noise3 = libtcod.noise_new(2, 0.5, 2.0) self.rainmap = libtcod.heightmap_new(self.width*2, self.height*2) rain_max = 0 rain_min = 1 for x in range(self.width*2): for y in range(self.height*2): f = [5 * float(x) / (self.width*2), 5 * float(y) / (self.height*2)] value = (libtcod.noise_get_fbm(noise3, f, 5, libtcod.NOISE_PERLIN))/2 value = (value + 1)/2 if value < rain_min: rain_min = value if value > rain_max: rain_max = value self.tiles[x/2][y/2].rain = value libtcod.heightmap_set_value(self.rainmap, x, y, value) rain_max = rain_max - rain_min for x in range(self.width*2): for y in range(self.height*2): libtcod.heightmap_set_value(self.rainmap, x, y, (libtcod.heightmap_get_value(self.rainmap, x, y) - rain_min)/rain_max) self.tiles[x/2][y/2].rain = (self.tiles[x/2][y/2].rain - rain_min)/rain_max self.owner.log.message("Terrain complete", debug = True) self.owner.log.message("Painting terrain", debug = True) deep = libtcod.Color(1, 10, 27) mid = libtcod.Color(38, 50, 60) shallow = libtcod.Color(51, 83, 120) water_idx = [0, 70, 210, 255] water_cols = [deep, deep, mid, shallow] water_colormap = libtcod.color_gen_map(water_cols, water_idx) mountaintop = libtcod.Color(145, 196, 88) grass = libtcod.Color(40, 62, 19) foothill = libtcod.Color(57, 81, 34) sand = libtcod.Color(215, 185, 115) watersedge = libtcod.Color(19, 97, 101) land_idx = [0, 15, 20, 128, 255] land_cols = [watersedge, sand, grass, foothill, mountaintop] land_colormap = libtcod.color_gen_map(land_cols, land_idx) # Apply height-based colours for x in range(self.width*2): for y in range(self.height*2): value = libtcod.heightmap_get_value(self.heightmap, x, y) if value < 0: index = int(-value * 255) libtcod.image_put_pixel(self.image, x, y, water_colormap[index]) else: index = int(value * 255) libtcod.image_put_pixel(self.image, x, y, land_colormap[index]) # Adjust colours for desert-plains-forest for x in range(self.width*2): for y in range(self.height*2): if libtcod.heightmap_get_value(self.heightmap, x, y) > 0: rain = libtcod.heightmap_get_value(self.rainmap, x, y) cur_col = libtcod.image_get_pixel(self.image, x, y) cols = [libtcod.light_sepia, cur_col, cur_col, cur_col * 1.1] col_idx = [0, 100, 165, 255] col_map = libtcod.color_gen_map(cols, col_idx) index = int(rain*255) if index > 165 and libtcod.heightmap_get_value(self.heightmap, x, y) > 0.15: self.tiles[x/2][y/2].biome = "forest" self.tiles[x/2][y/2].char = 'T' self.tiles[x/2][y/2].fg_color = grass * 0.7 libtcod.image_put_pixel(self.image, x, y, col_map[index]) self.owner.log.message("-- apply normal shadows", debug = True) for x in range(self.width*2): for y in range(self.height*2): normal = libtcod.heightmap_get_normal(self.heightmap, x, y, 0) nx = normal[0] ny = normal[1] avg = (nx + ny)/2 if avg > 0: avg = 1 else: avg = avg + 1 avg = min(avg/2 + 0.5, 1) col = libtcod.image_get_pixel(self.image, x, y) * avg libtcod.image_put_pixel(self.image, x, y, col) self.owner.log.message("Placing cities", debug=True) self.owner.entities = [] max_cities = 10 num_cities = 0 for i in range(max_cities): x = libtcod.random_get_int(0, 0, self.width - 1) y = libtcod.random_get_int(0, 0, self.height - 1) if self.tiles[x][y].terrain == "land": city = entity.City(self.owner, x, y, '#', libtcod.Color(libtcod.random_get_int(0, 0, 255), libtcod.random_get_int(0, 0, 255), libtcod.random_get_int(0, 0, 255))) self.owner.entities.append(city) num_cities += 1 self.owner.log.message("-- placed " + str(num_cities) + " cities") self.owner.log.message("Map generated", debug = True) self.generated = True
BSP_RECURSE_LEVEL = 4 ROOM_MAX_SIZE = 10 ROOM_MIN_SIZE = 6 MAX_ROOMS = 20 MAX_ROOM_MONSTERS = 3 MAX_ROOM_ITEMS = 1 # modifier for probability of feature being generated in generate_forest() # 1 is unmodified FOREST_SPARSENESS = 0.5 # create fbm noise map noise2d_gen = libtcod.noise_new(2, 0.5, 2.0) noise_map = [ [ libtcod.noise_get_fbm(noise2d_gen, [i / float(MAP_WIDTH), j / float(MAP_HEIGHT)], 32.0) for i in range(MAP_WIDTH) ] for j in range(MAP_HEIGHT) ] # map of actual fbm noise values class Tile: # a tile of the map and its properties def __init__(self, tile_type): self.blocked = False self.block_sight = None self.type = tile_type # all tiles start unexplored self.explored = False
pi_div_two = math.pi / 2.0 theta = 0.0 phi = pi_div_two * -1.0 x = 0 y = 0 while phi <= pi_div_two: while theta <= pi_times_two: f = [ noise_zoom * math.cos(phi) * math.cos(theta), noise_zoom * math.cos(phi) * math.sin(theta), noise_zoom * math.sin(phi), ] value = 0.0 value = libtcod.noise_get_fbm(noise, f, noise_octaves, libtcod.NOISE_PERLIN) c = int((value + 1.0) / 2.0 * 255) if c < 0: c = 0 elif c > 255: c = 255 col = libtcod.Color(c // 2, c // 2, c) libtcod.image_put_pixel(noise_img,x,y,col) theta += (pi_times_two / SCREEN_WIDTH) x += 1 phi += (math.pi / SCREEN_HEIGHT) y += 1 x = 0 theta = 0.0 # for y in range(SCREEN_HEIGHT):