def test_bsp(): """ commented out statements work in libtcod-cffi """ bsp = libtcodpy.bsp_new_with_size(0, 0, 64, 64) repr(bsp) # test __repr__ on leaf libtcodpy.bsp_resize(bsp, 0, 0, 32, 32) assert bsp != None # test getter/setters bsp.x = bsp.x bsp.y = bsp.y bsp.w = bsp.w bsp.h = bsp.h bsp.position = bsp.position bsp.horizontal = bsp.horizontal bsp.level = bsp.level # cover functions on leaf #self.assertFalse(libtcodpy.bsp_left(bsp)) #self.assertFalse(libtcodpy.bsp_right(bsp)) #self.assertFalse(libtcodpy.bsp_father(bsp)) assert libtcodpy.bsp_is_leaf(bsp) assert libtcodpy.bsp_contains(bsp, 1, 1) #self.assertFalse(libtcodpy.bsp_contains(bsp, -1, -1)) #self.assertEqual(libtcodpy.bsp_find_node(bsp, 1, 1), bsp) #self.assertFalse(libtcodpy.bsp_find_node(bsp, -1, -1)) libtcodpy.bsp_split_once(bsp, False, 4) repr(bsp) # test __repr__ with parent libtcodpy.bsp_split_once(bsp, True, 4) repr(bsp) # cover functions on parent assert libtcodpy.bsp_left(bsp) assert libtcodpy.bsp_right(bsp) #self.assertFalse(libtcodpy.bsp_father(bsp)) assert not libtcodpy.bsp_is_leaf(bsp) #self.assertEqual(libtcodpy.bsp_father(libtcodpy.bsp_left(bsp)), bsp) #self.assertEqual(libtcodpy.bsp_father(libtcodpy.bsp_right(bsp)), bsp) libtcodpy.bsp_split_recursive(bsp, None, 4, 2, 2, 1.0, 1.0) # cover bsp_traverse def traverse(node, user_data): return True libtcodpy.bsp_traverse_pre_order(bsp, traverse) libtcodpy.bsp_traverse_in_order(bsp, traverse) libtcodpy.bsp_traverse_post_order(bsp, traverse) libtcodpy.bsp_traverse_level_order(bsp, traverse) libtcodpy.bsp_traverse_inverted_level_order(bsp, traverse) # test __repr__ on deleted node son = libtcodpy.bsp_left(bsp) libtcodpy.bsp_remove_sons(bsp) repr(son) libtcodpy.bsp_delete(bsp)
def create(self): w = cfg.DNG_MINWIDTH + random.randint(0, cfg.DNG_SIZEVAR) h = cfg.DNG_MINHEIGHT + random.randint(0, cfg.DNG_SIZEVAR) self.width = w self.height = h self.level = [[DungeonTile(j, i) for i in xrange(h)] for j in xrange(w)] self.console = libtcod.console_new(w, h) backColor = libtcod.Color(0, 0, 0) # magic! bsp_depth = 9 bsp_min_room_size = 5 bsp = libtcod.bsp_new_with_size(0, 0, w, h) libtcod.bsp_split_recursive(bsp, 0, bsp_depth, bsp_min_room_size, bsp_min_room_size, 1.5, 1.5) libtcod.bsp_traverse_inverted_level_order(bsp, self.traverseNode) self.findPathable() self.clearUnpathableAreas() # Place entrance e_pos = random.choice(self.pathable) entry = DungeonTileEntity(e_pos[0], e_pos[1]) entry.setChar('>') entry.setColors(libtcod.Color(0, 100, 150), libtcod.Color(40, 40, 0)) self.tile_entity.append(entry) self.entry = entry self.buildBlockedMap()
def bsp_make_map(): global map, objects, stairs, rooms objects = [player] map = [[Tile(True) for y in range(MAP_HEIGHT)] for x in range(MAP_WIDTH)] my_bsp = libtcod.bsp_new_with_size(0,0,MAP_WIDTH, MAP_HEIGHT) libtcod.bsp_split_recursive(my_bsp,0,6,ROOM_MIN_SIZE,ROOM_MIN_SIZE,1.2,1.1) rooms = [] libtcod.bsp_traverse_inverted_level_order(my_bsp,make_room) num_rooms = 0 for room in rooms: (r_x, r_y) = room.center() if num_rooms == 0: player.x = r_x player.y = r_y else: (prev_x, prev_y) = rooms[num_rooms - 1].center() # Draw a coin (random 0 or 1) if libtcod.random_get_int(0,0,1) == 1: # first move horizontally, then vertically create_h_tunnel(prev_x, r_x, prev_y) create_v_tunnel(prev_y, r_y, r_x) else: # first move vertically, then horizontally create_v_tunnel(prev_y, r_y, prev_x) create_h_tunnel(prev_x, r_x, r_y) num_rooms += 1 # Add stairs to last room stairs = Object(r_x, r_y, '<', 'stairs', libtcod.white, always_visible=True) objects.append(stairs) stairs.send_to_back()
def generate_dungeon(): global rooms #fill map with "blocked" tiles g.level_map = [ [ Tile(tile_types.CAVE_WALL) for x in range(MAP_WIDTH) ] for y in range(MAP_HEIGHT) ] # First, we create the root node of the tree. # This node encompasses the whole rectangular region. # bsp_new_with_size(x,y,w,h) my_bsp = libtcod.bsp_new_with_size(0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1) # Once we have the root node, we split it # into smaller non-overlapping nodes. #bsp_split_recursive(node, randomizer, num_recursive_levels, minHSize, # minVSize, maxHRatio, maxVRatio) libtcod.bsp_split_recursive(my_bsp, 0, BSP_RECURSE_LEVEL, ROOM_MIN_SIZE, ROOM_MIN_SIZE, 1.5, 1.5) # Then we change each leaf to a room # and connect each subdivision with tunnels. libtcod.bsp_traverse_inverted_level_order(my_bsp, bsp_leaf_create_room) libtcod.bsp_traverse_level_order(my_bsp, bsp_leaf_create_tunnel) # set player coordinates to the center of this first room return (rooms[0].center()[0], rooms[0].center()[1])
def create(self): w=cfg.DNG_MINWIDTH+random.randint(0,cfg.DNG_SIZEVAR) h=cfg.DNG_MINHEIGHT+random.randint(0,cfg.DNG_SIZEVAR) self.width=w self.height=h self.level=[[DungeonTile(j,i) for i in xrange(h)] for j in xrange(w)] self.console=libtcod.console_new(w,h) backColor=libtcod.Color(0, 0, 0) # magic! bsp_depth=9 bsp_min_room_size=5 bsp = libtcod.bsp_new_with_size(0,0,w,h) libtcod.bsp_split_recursive(bsp, 0, bsp_depth, bsp_min_room_size, bsp_min_room_size, 1.5, 1.5) libtcod.bsp_traverse_inverted_level_order(bsp, self.traverseNode) self.findPathable() self.clearUnpathableAreas() # Place entrance e_pos=random.choice(self.pathable) entry=DungeonTileEntity(e_pos[0],e_pos[1]) entry.setChar('>') entry.setColors(libtcod.Color(0, 100, 150),libtcod.Color(40, 40, 0)) self.tile_entity.append(entry) self.entry=entry self.buildBlockedMap()
def make_map(): global map, leafs, rooms, doors, fov_map map = [[Tile(True) for y in range(MAP_HEIGHT) ] for x in range(MAP_WIDTH) ] leafs = [] rooms = [] doors = [] fov_map = tcod.map_new(MAP_WIDTH, MAP_HEIGHT) bsp = tcod.bsp_new_with_size(2, 2, MAP_WIDTH-3, MAP_HEIGHT-3) tcod.bsp_split_recursive(bsp, 0, 4 , MIN_LEAF_SIZE, MAX_LEAF_SIZE, 1.5, 1.5) tcod.bsp_traverse_inverted_level_order(bsp, bsp_callback) n=0 #create numerated rooms from leafs for object in leafs: make_room(object, n) n += 1 for object in rooms: #dig rooms & corridors dig(object) make_doors(object, object.number) for object in doors: prev = doors[object.number-1] dig_h_tunnel(prev.center_x, object.center_x, prev.center_y) dig_v_tunnel(prev.center_y, object.center_y, object.center_x) for x in range(0, MAP_WIDTH): set_diggable(x,0,False) set_diggable(x,MAP_HEIGHT-1,False) for y in range(0, MAP_HEIGHT): set_diggable(0,y,False) set_diggable(MAP_WIDTH-1,y,False) populate() fov_init()
def split(self, depth, min_size, maxHRatio = 2, maxVRatio = 2): libtcod.bsp_split_recursive(self.bsp, 0, depth, min_size +1, min_size +1, maxHRatio, maxVRatio) bsp_nodes = [] def build_list(node, _): bsp_nodes.append(node) return True libtcod.bsp_traverse_inverted_level_order(self.bsp, build_list) return bsp_nodes
def make_house(): bsp_tree = tcod.bsp_new_with_size(0, 0, HOUSE_WIDTH - 1, HOUSE_HEIGHT - 1) tcod.bsp_split_recursive(bsp_tree, 0, BSP_DEPTH, MIN_ROOM_WIDTH, MIN_ROOM_HEIGHT, MAX_H_RATIO, MAX_V_RATIO) tcod.bsp_traverse_inverted_level_order(bsp_tree, handle_node) house_array[-1][-1] = Tile("wall", True, True) noise = tcod.noise_new(2, HURST, LACNULARITY) for x in xrange(HOUSE_WIDTH): for y in xrange(HOUSE_HEIGHT): if tcod.noise_get_turbulence(noise, [x, y], 32.0, tcod.NOISE_SIMPLEX) > THRESHOLD: house_array[y][x] = Tile("floor", True, True)
def make_bsp(): # map stuff var.map = [[Tile(True) for y in range(var.MAP_HEIGHT)] for x in range(var.MAP_WIDTH)] var.fov_map = lib.map_new(var.MAP_WIDTH, var.MAP_HEIGHT) var.fov_recompute = True # new root node bsp = lib.bsp_new_with_size(0, 0, var.MAP_WIDTH, var.MAP_HEIGHT) # split into nodes lib.bsp_split_recursive(bsp, 0, var.DEPTH, var.MIN_SIZE + 1, var.MIN_SIZE + 1, 1.5, 1.5) # traverse the nodes and create rooms lib.bsp_traverse_inverted_level_order(bsp, traverse_node) # Random room for the stairs stairs_location = random.choice(var.bsp_rooms) var.bsp_rooms.remove(stairs_location) var.stairs = Entity(stairs_location[0], stairs_location[1], '<', 'stairs', 'white', always_visible=True, graphical_char='[0xE0A9]') var.entities.append(var.stairs) send_to_back(var.stairs) # Random room for player start player_room = random.choice(var.bsp_rooms) var.bsp_rooms.remove(player_room) var.player.x = player_room[0] var.player.y = player_room[1] # add monsters and items for room in var.bsp_rooms: new_room = Rect(room[0], room[1], 2, 2) place_objects(new_room) initialize_fov()
def generate_map(self): self._map = self._generate_empty_map() bsp = libtcod.bsp_new_with_size(0, 0, self.map_width, self.map_height) libtcod.bsp_split_recursive(bsp, 0, self.generation_depth, self.min_room_size + 1, self.min_room_size + 1, 1.5, 1.5) libtcod.bsp_traverse_inverted_level_order(bsp, self._traverse_node) stairs_room = random.choice(self._rooms) self._rooms.remove(stairs_room) self.stairs = StairsUp(stairs_room[0], stairs_room[1]) self.objects.append(self.stairs) self.objects.send_to_back(self.stairs) player_room = random.choice(self._rooms) self._rooms.remove(player_room) self.player.x = player_room[0] self.player.y = player_room[1] return self._map
def make_bsp(): global bsp_rooms cfg.objects = [cfg.player] cfg.map = [[Tile(True) for y in range(cfg.MAP_HEIGHT)] for x in range(cfg.MAP_WIDTH)] #Empty global list for storing room coordinates bsp_rooms = [] #New root node bsp = libtcod.bsp_new_with_size(0, 0, cfg.MAP_WIDTH, cfg.MAP_HEIGHT) #Split into nodes libtcod.bsp_split_recursive(bsp, 0, cfg.DEPTH, cfg.MIN_SIZE + 1, cfg.MIN_SIZE + 1, 1.5, 1.5) #Traverse the nodes and create rooms libtcod.bsp_traverse_inverted_level_order(bsp, traverse_node) #Random room for the stairs stairs_location = random.choice(bsp_rooms) bsp_rooms.remove(stairs_location) if cfg.MAKE_STAIRS: cfg.stairs = object.Object(stairs_location[0], stairs_location[1], '>', 'stairs', libtcod.white, always_visible=True) else: cfg.stairs = object.Object(stairs_location[0], stairs_location[1], cfg.FLOOR_CHAR, ' ', cfg.color_light_ground, always_visible=False) cfg.objects.append(cfg.stairs) cfg.stairs.send_to_back() #Random room for player start player_room = random.choice(bsp_rooms) bsp_rooms.remove(player_room) cfg.player.x = player_room[0] cfg.player.y = player_room[1] #Add monsters and items for room in bsp_rooms: new_room = Rect(room[0] - cfg.MIN_SIZE/2, room[1] - cfg.MIN_SIZE/2, cfg.MIN_SIZE, cfg.MIN_SIZE) place_objects(new_room) initialize_fov()
def __init__(self, width, height, seed=54): self.screen_width = width self.screen_height = height self.seed = seed random.seed(seed) self.rnd = libtcod.random_new_from_seed(self.seed) # Load Random Names self.planet_names = [] with open("planet_names", "r") as planet_names_file: self.planet_names = planet_names_file.readlines() random.shuffle(self.planet_names) self.planet_name_index = -1 # Build Galaxy Map self.bsp_depth = 6 self.bsp = libtcod.bsp_new_with_size(0, 0, self.screen_width, self.screen_height) libtcod.bsp_split_recursive(self.bsp, self.rnd, self.bsp_depth, 8, 8, 1.0, 1.0) # Count number of sectors count = [ 0 ] def count_bsp_leaf_nodes(node, userData): if node.level == self.bsp_depth: count[0] += 1 return True libtcod.bsp_traverse_inverted_level_order(self.bsp, count_bsp_leaf_nodes, userData=None) self.sector_count = count[0] # self.sector_count = 2**self.bsp_depth # only if we have a fully populated tree (not guaranteed) self.sectors = [] for i in range(0, self.sector_count): self.new_sector() self.link_sectors() self.current_sector = random.randrange(self.sector_count) # pp("total sectors: {} current sector: {}".format(self.sector_count, self.current_sector)) self.targeted_sector_index = 0 self.selected_blink = 0
def link_sectors(self): self.bsp_nodes = {"index": 0} def get_bsp_nodes(node, userData): self.bsp_nodes["index"] += 1 if node.level not in self.bsp_nodes: self.bsp_nodes[node.level] = [] self.bsp_nodes[node.level].append( {"index": self.bsp_nodes["index"]-1, "x": node.x, "y": node.y, "w": node.w, "h": node.h, "node": node } ) return True libtcod.bsp_traverse_inverted_level_order(self.bsp, get_bsp_nodes, userData=None) # pp(self.bsp_nodes) # Set Sector Galaxy Positions for index, sector in enumerate(self.sectors): node = self.bsp_nodes[self.bsp_depth][index] startx = int(node["x"] + (node["w"]/2.0)) starty = int(node["y"] + (node["h"]/2.0)) sector.galaxy_position_x = startx sector.galaxy_position_y = starty # Link nodes in the bsp tree for i in range(self.bsp_depth): for index in range(0, self.sector_count, 2**(i+1)): # print("current depth: {} starting index: {}".format(i, index)) node1_index = index if i == 0: # we are linking the lowest level nodes node2_index = node1_index + 2**i else: # find the two closest nodes in each subtree node2_index = node1_index + 2**i min_distance = self.screen_width min_node1 = None min_node2 = None tree1_start_index = index tree1_stop_index = index + (2**(i+1))/2 tree2_start_index = tree1_stop_index tree2_stop_index = tree2_start_index + (2**(i+1))/2 # pp([tree1_start_index, tree1_stop_index, tree2_start_index, tree2_stop_index]) for n1 in range(tree1_start_index, tree1_stop_index): for n2 in range(tree2_start_index, tree2_stop_index): if n1 != n2 and n1 < self.sector_count and n2 < self.sector_count: # pp((n1, n2)) node1 = self.bsp_nodes[self.bsp_depth][n1] node2 = self.bsp_nodes[self.bsp_depth][n2] d = math.sqrt((node2["x"] - node1["x"])**2 + (node2["y"] - node1["y"])**2) if d < min_distance: min_distance = d min_node1 = node1["index"] min_node2 = node2["index"] # print("new min: {} indexes: {} {}".format(d, min_node1, min_node2)) node1_index = min_node1 node2_index = min_node2 # print("done min ---") if node2_index < self.sector_count: # print("linked {} -> {}".format(node1_index, node2_index)) if node2_index not in self.sectors[node1_index].neighbors: self.sectors[node1_index].neighbors.append( node2_index ) # Add links in the other direction for index, sector in enumerate(self.sectors): for neighbor in sector.neighbors: if index not in self.sectors[neighbor].neighbors: self.sectors[neighbor].neighbors.append(index) self.one_way_links = [] for index, sector in enumerate(self.sectors): for neighbor in sector.neighbors: if [index, neighbor] not in self.one_way_links and [neighbor, index] not in self.one_way_links: self.one_way_links.append([index, neighbor])