rework directions and add graphviz output for BSP

This commit is contained in:
kleph 2018-07-29 19:07:53 +02:00
parent fb06c08d67
commit 4be382798d

View file

@ -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 self.tilemap[x][y+1] != self.TILE_GROUND:
return False
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 return True
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:
# prevent to carve alongside another hallway def generate_graphviz(self, leaf):
# BUG: backward os already carved, so it never returns true """ generate a dot file for graphviz representation of rooms tree"""
if self.carvable(testx, testy, -1): filename='bsp.dot'
return True 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)
## ##