Implement populate method, so map generation also handles entity spawn
This commit is contained in:
parent
e639ad6255
commit
12e19759aa
@ -1,10 +1,10 @@
|
||||
# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from random import random, randint, shuffle
|
||||
from random import random, randint, shuffle, choice, choices
|
||||
from typing import List, Tuple
|
||||
|
||||
from ..interfaces import Map, Tile
|
||||
from ..interfaces import Map, Tile, Entity
|
||||
|
||||
DEFAULT_PARAMS = {
|
||||
"width": 120,
|
||||
@ -23,6 +23,7 @@ DEFAULT_PARAMS = {
|
||||
"loop_tries" : 40,
|
||||
"loop_max" : 5,
|
||||
"loop_threshold" : 15,
|
||||
"spawn_per_region" : [1, 2],
|
||||
}
|
||||
|
||||
def dist(level, y1, x1, y2, x2):
|
||||
@ -46,6 +47,8 @@ def dist(level, y1, x1, y2, x2):
|
||||
class Generator:
|
||||
def __init__(self, params: dict = None):
|
||||
self.params = params or DEFAULT_PARAMS
|
||||
self.spawn_areas = []
|
||||
self.queued_area = None
|
||||
|
||||
@staticmethod
|
||||
def room_fits(level: List[List[Tile]], y: int, x: int,
|
||||
@ -186,8 +189,8 @@ class Generator:
|
||||
|
||||
return y + length * dy, x + length * dx, dy, dx
|
||||
|
||||
def create_circular_room(self) -> Tuple[List[List[Tile]], int, int,
|
||||
int, int]:
|
||||
def create_circular_room(self, spawnable: bool = True) \
|
||||
-> Tuple[List[List[Tile]], int, int, int, int]:
|
||||
if random() < self.params["large_circular_room"]:
|
||||
r = randint(5, 10)
|
||||
else:
|
||||
@ -214,21 +217,49 @@ class Generator:
|
||||
else:
|
||||
room[-1].append(Tile.EMPTY)
|
||||
|
||||
if spawnable:
|
||||
self.register_spawn_area(room)
|
||||
door_y, door_x, dy, dx = self.attach_door(room, h_sup, w_sup,
|
||||
h_off, w_off)
|
||||
|
||||
return room, door_y, door_x, dy, dx
|
||||
|
||||
def create_random_room(self) -> Tuple[List[list], int, int, int, int]:
|
||||
def create_random_room(self, spawnable: bool = True) \
|
||||
-> Tuple[List[list], int, int, int, int]:
|
||||
return self.create_circular_room()
|
||||
|
||||
def register_spawn_area(self, area:List[List[Tile]]):
|
||||
spawn_positions = []
|
||||
for y, line in enumerate(area):
|
||||
for x, tile in enumerate(line):
|
||||
if tile == Tile.FLOOR:
|
||||
spawn_positions.append([y, x])
|
||||
self.queued_area = spawn_positions
|
||||
|
||||
def update_spawnable(self, y, x):
|
||||
if self.queued_area != None:
|
||||
translated_area = [[y+ry, x+rx] for ry, rx in self.queued_area]
|
||||
self.spawn_areas.append(translated_area)
|
||||
self.queued_area = None
|
||||
|
||||
def populate(self, rv):
|
||||
min_c, max_c = self.params["spawn_per_region"]
|
||||
for region in self.spawn_areas:
|
||||
entity_count = randint(min_c, max_c)
|
||||
for _dummy in range(entity_count):
|
||||
entity = choices(Entity.get_all_entity_classes(),
|
||||
weights=Entity.get_weights(), k=1)[0]()
|
||||
y, x = choice(region)
|
||||
entity.move(y, x)
|
||||
rv.add_entity(entity)
|
||||
|
||||
def run(self) -> Map:
|
||||
height, width = self.params["height"], self.params["width"]
|
||||
level = [width * [Tile.EMPTY] for _ignored in range(height)]
|
||||
|
||||
# the starting room must have no corridor
|
||||
mem, self.params["corridor_chance"] = self.params["corridor_chance"], 0
|
||||
starting_room, _, _, _, _ = self.create_random_room()
|
||||
starting_room, _, _, _, _ = self.create_random_room(spawnable = False)
|
||||
dim_v, dim_h = len(starting_room), len(starting_room[0])
|
||||
pos_y, pos_x = randint(0, height - dim_v - 1),\
|
||||
randint(0, width - dim_h - 1)
|
||||
@ -254,6 +285,7 @@ class Generator:
|
||||
for pos in positions:
|
||||
y, x = pos // width, pos % width
|
||||
if self.room_fits(level, y, x, room, door_y, door_x, dy, dx):
|
||||
self.update_spawnable(y - door_y, x - door_x)
|
||||
self.place_room(level, y, x, room, door_y, door_x)
|
||||
rooms_built += 1
|
||||
break
|
||||
@ -276,4 +308,8 @@ class Generator:
|
||||
y, x = randint(0, height - 1), randint(0, width - 1)
|
||||
level[y][x] = Tile.LADDER
|
||||
|
||||
return Map(width, height, level, sy, sx)
|
||||
# spawn entities
|
||||
rv = Map(width, height, level, sy, sx)
|
||||
self.populate(rv)
|
||||
|
||||
return rv
|
||||
|
Loading…
Reference in New Issue
Block a user