rework directions and add graphviz output for BSP
This commit is contained in:
		
							parent
							
								
									fb06c08d67
								
							
						
					
					
						commit
						4be382798d
					
				
					 1 changed files with 72 additions and 83 deletions
				
			
		| 
						 | 
					@ -12,6 +12,11 @@ TILE_SIZE_Y = 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MIN_LEAF_SIZE = 8
 | 
					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:
 | 
					class Leaf:
 | 
				
			||||||
    """  Leaf of the BSP """
 | 
					    """  Leaf of the BSP """
 | 
				
			||||||
| 
						 | 
					@ -49,16 +54,18 @@ class Leaf:
 | 
				
			||||||
            if self.width < MIN_LEAF_SIZE * 2:  # leaf is too small
 | 
					            if self.width < MIN_LEAF_SIZE * 2:  # leaf is too small
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
            split_point = random.randint(MIN_LEAF_SIZE, self.width - MIN_LEAF_SIZE)
 | 
					            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)
 | 
					            next_id = self.id + 10 + 2 * (self.id % 10)
 | 
				
			||||||
            self.right_leaf = Leaf(self.x + split_point, self.y, self.width - split_point, self.height, self.id+2)
 | 
					            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:
 | 
					        else:
 | 
				
			||||||
            # y
 | 
					            # y
 | 
				
			||||||
            if self.height < MIN_LEAF_SIZE * 2:     # leaf is too small
 | 
					            if self.height < MIN_LEAF_SIZE * 2:     # leaf is too small
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
            split_point = random.randint(MIN_LEAF_SIZE, self.height - MIN_LEAF_SIZE)
 | 
					            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)
 | 
					            next_id = self.id + 10 + 2 * (self.id % 10)
 | 
				
			||||||
            self.right_leaf = Leaf(self.x, self.y + split_point, self.width, self.height - split_point, self.id+2)
 | 
					            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
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,8 +106,8 @@ class Room:
 | 
				
			||||||
        return cx, cy
 | 
					        return cx, cy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def is_inside(self, x, y):
 | 
					    def is_inside(self, x, y):
 | 
				
			||||||
        if x > self.x and x < self.x + self.width \
 | 
					        if self.x < x < self.x + self.width \
 | 
				
			||||||
            and y > self.y  and y < self.y + self.height:
 | 
					            and self.y  < y < self.y + self.height:
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,6 +191,8 @@ class Level:
 | 
				
			||||||
        # create rooms from partitions
 | 
					        # create rooms from partitions
 | 
				
			||||||
        self.rooms = self.generate_rooms(self.tree[0], self.tilemap, [])
 | 
					        self.rooms = self.generate_rooms(self.tree[0], self.tilemap, [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.generate_graphviz(self.tree[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.generate_tunnels()
 | 
					        self.generate_tunnels()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def draw_map(self):
 | 
					    def draw_map(self):
 | 
				
			||||||
| 
						 | 
					@ -211,31 +220,25 @@ class Level:
 | 
				
			||||||
        """ carve tunnels in the space left by the rooms """
 | 
					        """ carve tunnels in the space left by the rooms """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #self.carve_tunnel(2, 2)
 | 
					        #self.carve_tunnel(2, 2)
 | 
				
			||||||
        #self.tilemap[0][0] = self.TILE_ROAD
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # start some random carvers
 | 
					        # start some random carvers
 | 
				
			||||||
        # for i in range(0, 5):
 | 
					        for i in range(0, 1):
 | 
				
			||||||
        #
 | 
					 | 
				
			||||||
        #     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 y in range(2, self.sizey, 1):
 | 
					            randx = random.randint(0, self.sizex-1)
 | 
				
			||||||
           for x in range(2, self.sizex, 1):
 | 
					            randy = random.randint(0, self.sizey-1)
 | 
				
			||||||
               #if self.tilemap[x][y] == self.TILE_GROUND:
 | 
					            while not self.carvable(randx, randy, -1):
 | 
				
			||||||
               if self.carvable(x, y, -1):
 | 
					                randx = random.randint(0, self.sizex-1)
 | 
				
			||||||
                   self.carve_tunnel(x, y)
 | 
					                randy = random.randint(0, self.sizey-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.carve_tunnel(randx, randy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def carve_tunnel(self, startx, starty):
 | 
					    def carve_tunnel(self, startx, starty):
 | 
				
			||||||
        """ carve a tunnel from (startx, starty) """
 | 
					        """ carve a tunnel from (startx, starty) """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print("start tunnel at (" + str(startx) + ", " + str(starty) + ")")
 | 
				
			||||||
 | 
					        # carve
 | 
				
			||||||
        self.tilemap[startx][starty] = self.TILE_HALLWAY
 | 
					        self.tilemap[startx][starty] = self.TILE_HALLWAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print("start tunnel at (" + str(startx) + ", " + str(starty) + ")")
 | 
					 | 
				
			||||||
        # construct direction list
 | 
					        # construct direction list
 | 
				
			||||||
        dir_list = [0, 1, 2, 3]
 | 
					        dir_list = [0, 1, 2, 3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,84 +246,70 @@ class Level:
 | 
				
			||||||
            # choose random direction
 | 
					            # choose random direction
 | 
				
			||||||
            direction = int(random.choice(dir_list))
 | 
					            direction = int(random.choice(dir_list))
 | 
				
			||||||
            # print("direction chosen " + str(direction))
 | 
					            # print("direction chosen " + str(direction))
 | 
				
			||||||
            newx = startx
 | 
					            newx = startx + DX[direction]
 | 
				
			||||||
            newy = starty
 | 
					            newy = starty + DY[direction]
 | 
				
			||||||
            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
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            print("will dig (" + str(newx) + ", " + str(newy) + ")")
 | 
					 | 
				
			||||||
            if self.carvable(newx, newy, direction):
 | 
					            if self.carvable(newx, newy, direction):
 | 
				
			||||||
            # if self.carvable(newx, newy, -1):
 | 
					                self.carve_tunnel(newx, newy)
 | 
				
			||||||
                # 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.draw_map()
 | 
					                # self.draw_map()
 | 
				
			||||||
            else:
 | 
					
 | 
				
			||||||
            # remove this direction from the list
 | 
					            # remove this direction from the list
 | 
				
			||||||
                # print("remove direction " + str(direction))
 | 
					 | 
				
			||||||
            dir_list.remove(direction)
 | 
					            dir_list.remove(direction)
 | 
				
			||||||
                # print(dir_list)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def carvable(self, x, y, d):
 | 
					    def carvable(self, x, y, d):
 | 
				
			||||||
        testx = x
 | 
					        if x < 0 or x > self.sizex - 1:
 | 
				
			||||||
        testy = y
 | 
					            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
 | 
					        # check if in a room
 | 
				
			||||||
        for r in self.rooms:
 | 
					        for r in self.rooms:
 | 
				
			||||||
            if r.is_inside(x, y):
 | 
					            if r.is_inside(x, y):
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.tilemap[x][y] == self.TILE_GROUND:
 | 
					        # prevent hallway from touching each other
 | 
				
			||||||
            # check all directions
 | 
					        check_dir = [0, 1, 2, 3]
 | 
				
			||||||
            if d == -1:
 | 
					        # remove_opposite if we have a direction
 | 
				
			||||||
                if x - 1 < 0:
 | 
					        if d != -1:
 | 
				
			||||||
                    return False
 | 
					            check_dir.remove(BACKWARD[d])
 | 
				
			||||||
                if x + 1 >= self.sizex:
 | 
					 | 
				
			||||||
                    return False
 | 
					 | 
				
			||||||
                if y - 1 < 0:
 | 
					 | 
				
			||||||
                    return False
 | 
					 | 
				
			||||||
                if y + 1 >= self.sizey:
 | 
					 | 
				
			||||||
                    return False
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if self.tilemap[x-1][y] != self.TILE_GROUND:
 | 
					        for dir in check_dir:
 | 
				
			||||||
                    return False
 | 
					            testx = x + DX[dir]
 | 
				
			||||||
                if self.tilemap[x+1][y] != self.TILE_GROUND:
 | 
					            testy = y + DY[dir]
 | 
				
			||||||
                    return False
 | 
					            print("checking: (" + str(x) + ", " + str(y) + ") dir: " + str(dir))
 | 
				
			||||||
                if self.tilemap[x][y-1] != self.TILE_GROUND:
 | 
					
 | 
				
			||||||
                    return False
 | 
					            if 0 < testx < self.sizex-1:
 | 
				
			||||||
                if self.tilemap[x][y+1] != self.TILE_GROUND:
 | 
					                if 0 < testy < self.sizey-1:
 | 
				
			||||||
 | 
					                    print("tile: " + str(self.tilemap[testx][testy]))
 | 
				
			||||||
 | 
					                    if self.tilemap[testx][testy] == self.TILE_HALLWAY:
 | 
				
			||||||
                        return False
 | 
					                        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # 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
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # if self.tilemap[testx][testy] == self.TILE_GROUND:
 | 
					    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()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # prevent to carve alongside another hallway
 | 
					    def generate_graphviz_sub(self, leaf, f):
 | 
				
			||||||
            # BUG: backward os already carved, so it never returns true
 | 
					 | 
				
			||||||
            if self.carvable(testx, testy, -1):
 | 
					 | 
				
			||||||
                return True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return False
 | 
					        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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##
 | 
					##
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue