From 4be382798d71c20dff4dde5782ca09c2b3f88545 Mon Sep 17 00:00:00 2001 From: kleph Date: Sun, 29 Jul 2018 19:07:53 +0200 Subject: [PATCH] rework directions and add graphviz output for BSP --- 03_2_map_tunnel.py | 155 +++++++++++++++++++++------------------------ 1 file changed, 72 insertions(+), 83 deletions(-) diff --git a/03_2_map_tunnel.py b/03_2_map_tunnel.py index 22f59bb..05152d0 100644 --- a/03_2_map_tunnel.py +++ b/03_2_map_tunnel.py @@ -12,6 +12,11 @@ TILE_SIZE_Y = 16 MIN_LEAF_SIZE = 8 +# UP, DOWN, LEFT, RIGHT +DX = [0, 0, -1, 1] +DY = [-1, 1, 0, 0] +BACKWARD = [1, 0, 3, 2] + class Leaf: """ Leaf of the BSP """ @@ -49,16 +54,18 @@ class Leaf: if self.width < MIN_LEAF_SIZE * 2: # leaf is too small return False split_point = random.randint(MIN_LEAF_SIZE, self.width - MIN_LEAF_SIZE) - self.left_leaf = Leaf(self.x, self.y, split_point, self.height, self.id+1) - self.right_leaf = Leaf(self.x + split_point, self.y, self.width - split_point, self.height, self.id+2) + next_id = self.id + 10 + 2 * (self.id % 10) + self.left_leaf = Leaf(self.x, self.y, split_point, self.height, next_id) + self.right_leaf = Leaf(self.x + split_point, self.y, self.width - split_point, self.height, next_id + 1) else: # y if self.height < MIN_LEAF_SIZE * 2: # leaf is too small return False split_point = random.randint(MIN_LEAF_SIZE, self.height - MIN_LEAF_SIZE) - self.left_leaf = Leaf(self.x, self.y, self.width, split_point, self.id+1) - self.right_leaf = Leaf(self.x, self.y + split_point, self.width, self.height - split_point, self.id+2) + next_id = self.id + 10 + 2 * (self.id % 10) + self.left_leaf = Leaf(self.x, self.y, self.width, split_point, next_id) + self.right_leaf = Leaf(self.x, self.y + split_point, self.width, self.height - split_point, next_id + 1) return True @@ -99,8 +106,8 @@ class Room: return cx, cy def is_inside(self, x, y): - if x > self.x and x < self.x + self.width \ - and y > self.y and y < self.y + self.height: + if self.x < x < self.x + self.width \ + and self.y < y < self.y + self.height: return True return False @@ -184,6 +191,8 @@ class Level: # create rooms from partitions self.rooms = self.generate_rooms(self.tree[0], self.tilemap, []) + self.generate_graphviz(self.tree[0]) + self.generate_tunnels() def draw_map(self): @@ -211,31 +220,25 @@ class Level: """ carve tunnels in the space left by the rooms """ #self.carve_tunnel(2, 2) - #self.tilemap[0][0] = self.TILE_ROAD # start some random carvers - # for i in range(0, 5): - # - # randx = random.randint(0, self.sizex) - # randy = random.randint(0, self.sizey) - # while not self.carvable(randx, randy, -1): - # randx = random.randint(0, self.sizex) - # randy = random.randint(0, self.sizey) - # - # self.carve_tunnel(randx, randy) + for i in range(0, 1): - for y in range(2, self.sizey, 1): - for x in range(2, self.sizex, 1): - #if self.tilemap[x][y] == self.TILE_GROUND: - if self.carvable(x, y, -1): - self.carve_tunnel(x, y) + randx = random.randint(0, self.sizex-1) + randy = random.randint(0, self.sizey-1) + while not self.carvable(randx, randy, -1): + randx = random.randint(0, self.sizex-1) + randy = random.randint(0, self.sizey-1) + + self.carve_tunnel(randx, randy) def carve_tunnel(self, startx, starty): """ carve a tunnel from (startx, starty) """ + print("start tunnel at (" + str(startx) + ", " + str(starty) + ")") + # carve self.tilemap[startx][starty] = self.TILE_HALLWAY - print("start tunnel at (" + str(startx) + ", " + str(starty) + ")") # construct direction list dir_list = [0, 1, 2, 3] @@ -243,84 +246,70 @@ class Level: # choose random direction direction = int(random.choice(dir_list)) # print("direction chosen " + str(direction)) - newx = startx - newy = starty - if direction == 0 and newy > 0: # up - newy -= 1 - elif direction == 1 and newy < self.sizey-1: # down - newy += 1 - elif direction == 2 and newx > 0: # left - newx -= 1 - elif direction == 3 and newx < self.sizex-1: # right - newx += 1 + newx = startx + DX[direction] + newy = starty + DY[direction] - print("will dig (" + str(newx) + ", " + str(newy) + ")") if self.carvable(newx, newy, direction): - # if self.carvable(newx, newy, -1): - # carve - self.tilemap[newx][newy] = self.TILE_HALLWAY - # TODO: remove backward while reseting directions list? - print("dig (" + str(newx) + ", " + str(newy) + ")") - dir_list = [0, 1, 2, 3] - startx = newx - starty = newy + self.carve_tunnel(newx, newy) # self.draw_map() - else: - # remove this direction from the list - # print("remove direction " + str(direction)) - dir_list.remove(direction) - # print(dir_list) + + # remove this direction from the list + dir_list.remove(direction) def carvable(self, x, y, d): - testx = x - testy = y + if x < 0 or x > self.sizex - 1: + return False + if y < 0 or y > self.sizey - 1: + return False + + print("trying (" + str(x) + ", " + str(y) + "): " + str(self.tilemap[x][y])) + + if self.tilemap[x][y] != self.TILE_GROUND: + return False # check if in a room for r in self.rooms: if r.is_inside(x, y): return False - if self.tilemap[x][y] == self.TILE_GROUND: - # check all directions - if d == -1: - if x - 1 < 0: - return False - if x + 1 >= self.sizex: - return False - if y - 1 < 0: - return False - if y + 1 >= self.sizey: - return False + # prevent hallway from touching each other + check_dir = [0, 1, 2, 3] + # remove_opposite if we have a direction + if d != -1: + check_dir.remove(BACKWARD[d]) - if self.tilemap[x-1][y] != self.TILE_GROUND: - return False - if self.tilemap[x+1][y] != self.TILE_GROUND: - return False - if self.tilemap[x][y-1] != self.TILE_GROUND: - return False - if self.tilemap[x][y+1] != self.TILE_GROUND: - return False + for dir in check_dir: + testx = x + DX[dir] + testy = y + DY[dir] + print("checking: (" + str(x) + ", " + str(y) + ") dir: " + str(dir)) - return True + if 0 < testx < self.sizex-1: + if 0 < testy < self.sizey-1: + print("tile: " + str(self.tilemap[testx][testy])) + if self.tilemap[testx][testy] == self.TILE_HALLWAY: + return False - # check specific direction - if d == 0 and y - 1 > 0: # up - testy = y - 1 - elif d == 1 and y + 1 < self.sizey-1: # down - testy = y + 1 - elif d == 2 and x - 1 > 0: # left - testx = x - 1 - elif d == 3 and x + 1 < self.sizex-1: # right - testx = x + 1 + return True - # if self.tilemap[testx][testy] == self.TILE_GROUND: - # prevent to carve alongside another hallway - # BUG: backward os already carved, so it never returns true - if self.carvable(testx, testy, -1): - return True + def generate_graphviz(self, leaf): + """ generate a dot file for graphviz representation of rooms tree""" + filename='bsp.dot' + f = open(filename, 'w+t') + f.write("digraph BST {\n") + self.generate_graphviz_sub(leaf, f) + f.write("}") + f.close() - return False + def generate_graphviz_sub(self, leaf, f): + + f.write("\n\tl" + str(leaf.id) + " [label = " + str(leaf.id) + "];\n") + if leaf.left_leaf: + f.write("\tl" + str(leaf.id )+ " -> l" + str(leaf.left_leaf.id) + ";\n") + self.generate_graphviz_sub(leaf.left_leaf, f) + if leaf.right_leaf: + f.write("\tl" + str(leaf.id) + " -> l" + str(leaf.right_leaf.id) + ";\n") + self.generate_graphviz_sub(leaf.right_leaf, f) ##