From 5579f5d7913c22b5aa0f5f9c8403ae0fbb44ea59 Mon Sep 17 00:00:00 2001 From: Charles Peyrat Date: Thu, 7 Jan 2021 07:06:08 +0100 Subject: [PATCH] Room now can now generate with a corridor; implemenent door placement finding --- squirrelbattle/mapgeneration/broguelike.py | 79 ++++++++++++++++++---- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/squirrelbattle/mapgeneration/broguelike.py b/squirrelbattle/mapgeneration/broguelike.py index b5ea122..6b394d5 100644 --- a/squirrelbattle/mapgeneration/broguelike.py +++ b/squirrelbattle/mapgeneration/broguelike.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later from enum import auto, Enum -from random import choice, random, randint +from random import choice, random, randint, shuffle from ..interfaces import Map, Tile @@ -12,12 +12,13 @@ DEFAULT_PARAMS = { "height" : 40, "tries" : 600, "max_rooms" : 99, + "max_room_tries" : 15, "cross_room" : 1, - "corridor" : .8, - "min_v_corridor" : - "max_v_corridor" : - "min_h_corridor" : - "max_h_corridor" : + "corridor_chance" : .8, + "min_v_corr" : 2, + "max_v_corr" : 6, + "min_h_corr" : 4, + "max_h_corr" : 12, "large_circular_room" : .10, "circular_holes" : .5, } @@ -27,6 +28,49 @@ class Generator: def __init__(self, params: dict = DEFAULT_PARAMS): self.params = params + def corr_meta_info(self): + if random() < self.params["corridor_chance"]: + h_sup = randint(self.params["min_h_corr"], \ + self.params["max_h_corr"]) if random() < .5 else 0 + w_sup = 0 if h_sup else randint(self.params["min_w_corr"], \ + self.params["max_w_coor"]) + h_off = h_sup if random() < .5 else 0 + w_off = w_sup if random() < .5 else 0 + return h_sup, w_sup, h_off, w_off + return 0, 0, 0, 0 + + def attach_door(self, room, h_sup, w_sup, h_off, w_off): + l = h_sup + w_sup + dy, dx = 0, 0 + if l > 0: + if h_sup: + dy = -1 if h_off else 1 + else: + dx = -1 if w_off else 1 + else: + if random() < .5: + dy = -1 if random() < .5 else 1 + else: + dx = -1 if random() < .5 else 1 + + yxs = [i for i in range(len(room) * len(room[0]))] + shuffle(xys) + for POS in yxs: + y, x = POS // len(room), POS % len(room) + if room[y][x] == Tile.EMPTY: + if room[y-dy][x-dx] == Tile.FLOOR: + build_here = True + for i in range(l): + if room[y+i*dy][x+i*dx] != Tile.EMPTY: + build_here = False + break + if build_here: + for i in range(l): + room[y+i*dy][x+i*dx] == Tile.FLOOR + break + return y+l*dy, x+l*dx + + def create_circular_room(self): if random() < self.params["large_circular_room"]: r = randint(5, 10)**2 @@ -34,18 +78,25 @@ class Generator: r = randint(2, 4)**2 room = [] - height = 2*r+2+self.params["max_h_corridor"] - width = 2*r+2+self.params["max_v_corridor"] + + h_sup, w_sup, h_off, w_off = self.corr_meta_info() + + height = 2*r+2 + width = 2*r+2 make_hole = random() < self.params["circular_holes"] if make_hole: r2 = randint(3, r-3) - for i in range(height): + for i in range(height+h_sup): room.append([]) - d = (i-height//2)**2 - for j in range(width): - if d + (j-width//2)**2 < r**2 and \ - (not(make_hole) or d + (j-width//2)**2 >= r2**2): + d = (i-h_off-height//2)**2 + for j in range(width+w_sup): + if d + (j-w_off-width//2)**2 < r**2 and \ + (not(make_hole) or d + (j-w_off-width//2)**2 >= r2**2): room[-1].append(Tile.FLOOR) else: room[-1].append(Tile.EMPTY) - return room + + door_y, door_x = self.attach_doors(room, h_sup, w_sup, h_off, w_off) + + return room, doory, doorx +