Weighted random generation, completes Part 12
This commit is contained in:
parent
87bac7a322
commit
1b354b007c
@ -127,8 +127,6 @@ class GameWorld:
|
|||||||
max_rooms: int,
|
max_rooms: int,
|
||||||
room_min_size: int,
|
room_min_size: int,
|
||||||
room_max_size: int,
|
room_max_size: int,
|
||||||
max_monsters_per_room: int,
|
|
||||||
max_items_per_room: int,
|
|
||||||
current_floor: int = 0
|
current_floor: int = 0
|
||||||
):
|
):
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
@ -141,9 +139,6 @@ class GameWorld:
|
|||||||
self.room_min_size = room_min_size
|
self.room_min_size = room_min_size
|
||||||
self.room_max_size = room_max_size
|
self.room_max_size = room_max_size
|
||||||
|
|
||||||
self.max_monsters_per_room = max_monsters_per_room
|
|
||||||
self.max_items_per_room = max_items_per_room
|
|
||||||
|
|
||||||
self.current_floor = current_floor
|
self.current_floor = current_floor
|
||||||
|
|
||||||
def generate_floor(self) -> None:
|
def generate_floor(self) -> None:
|
||||||
@ -157,7 +152,5 @@ class GameWorld:
|
|||||||
room_max_size=self.room_max_size,
|
room_max_size=self.room_max_size,
|
||||||
map_width=self.map_width,
|
map_width=self.map_width,
|
||||||
map_height=self.map_height,
|
map_height=self.map_height,
|
||||||
max_monsters_per_room=self.max_monsters_per_room,
|
|
||||||
max_items_per_room=self.max_items_per_room,
|
|
||||||
engine=self.engine,
|
engine=self.engine,
|
||||||
)
|
)
|
||||||
|
121
procgen.py
121
procgen.py
@ -1,7 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import random
|
import random
|
||||||
from typing import Iterator, List, Tuple, TYPE_CHECKING
|
from typing import Dict, Iterator, List, Tuple, TYPE_CHECKING
|
||||||
|
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
@ -11,6 +11,76 @@ import tile_types
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from engine import Engine
|
from engine import Engine
|
||||||
|
from entity import Entity
|
||||||
|
|
||||||
|
max_items_by_floor = [
|
||||||
|
(1, 1),
|
||||||
|
(4, 2),
|
||||||
|
]
|
||||||
|
|
||||||
|
max_monsters_by_floor = [
|
||||||
|
(1, 2),
|
||||||
|
(4, 3),
|
||||||
|
(6, 5),
|
||||||
|
]
|
||||||
|
|
||||||
|
item_chances: Dict[int, List[Tuple[Entity, int]]] = {
|
||||||
|
0: [(entity_factories.health_potion, 35)],
|
||||||
|
2: [(entity_factories.confusion_scroll, 10)],
|
||||||
|
4: [(entity_factories.lightning_scroll, 25)],
|
||||||
|
6: [(entity_factories.fireball_scroll, 25)],
|
||||||
|
}
|
||||||
|
|
||||||
|
enemy_chances: Dict[int, List[Tuple[Entity, int]]] = {
|
||||||
|
0: [(entity_factories.orc, 80)],
|
||||||
|
3: [(entity_factories.troll, 15)],
|
||||||
|
5: [(entity_factories.troll, 30)],
|
||||||
|
7: [(entity_factories.troll, 60)],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_max_value_for_floor(
|
||||||
|
max_value_by_floor: List[Tuple[int, int]],
|
||||||
|
floor: int
|
||||||
|
) -> int:
|
||||||
|
current_value = 0
|
||||||
|
|
||||||
|
for floor_minimum, value in max_value_by_floor:
|
||||||
|
if floor_minimum > floor:
|
||||||
|
break;
|
||||||
|
else:
|
||||||
|
current_value = value;
|
||||||
|
|
||||||
|
return current_value
|
||||||
|
|
||||||
|
|
||||||
|
def get_entities_at_random(
|
||||||
|
weighted_chances_by_floor: Dict[int, List[Tuple[Entity, int]]],
|
||||||
|
number_of_entities: int,
|
||||||
|
floor: int,
|
||||||
|
) -> List[Entity]:
|
||||||
|
entity_weighted_chances = {}
|
||||||
|
|
||||||
|
for key, values in weighted_chances_by_floor.items():
|
||||||
|
if key > floor:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
for value in values:
|
||||||
|
entity = value[0]
|
||||||
|
weighted_chance = value[1]
|
||||||
|
|
||||||
|
entity_weighted_chances[entity] = weighted_chance
|
||||||
|
|
||||||
|
entities = list(entity_weighted_chances.keys())
|
||||||
|
entity_weighted_chance_values = list(entity_weighted_chances.values())
|
||||||
|
|
||||||
|
chosen_entities = random.choices(
|
||||||
|
entities,
|
||||||
|
weights=entity_weighted_chance_values,
|
||||||
|
k=number_of_entities
|
||||||
|
)
|
||||||
|
|
||||||
|
return chosen_entities
|
||||||
|
|
||||||
|
|
||||||
class RectangularRoom:
|
class RectangularRoom:
|
||||||
@ -45,37 +115,32 @@ class RectangularRoom:
|
|||||||
def place_entities(
|
def place_entities(
|
||||||
room: RectangularRoom,
|
room: RectangularRoom,
|
||||||
dungeon: GameMap,
|
dungeon: GameMap,
|
||||||
maximum_monsters: int,
|
floor_number: int,
|
||||||
maximum_items: int,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
number_of_monsters = random.randint(0, maximum_monsters)
|
number_of_monsters = random.randint(
|
||||||
number_of_items = random.randint(0, maximum_items)
|
0, get_max_value_for_floor(max_monsters_by_floor, floor_number)
|
||||||
|
)
|
||||||
|
number_of_items = random.randint(
|
||||||
|
0, get_max_value_for_floor(max_items_by_floor, floor_number)
|
||||||
|
)
|
||||||
|
|
||||||
for i in range(number_of_monsters):
|
monsters: List[Entity] = get_entities_at_random(
|
||||||
|
enemy_chances,
|
||||||
|
number_of_monsters,
|
||||||
|
floor_number
|
||||||
|
)
|
||||||
|
items: List[Entity] = get_entities_at_random(
|
||||||
|
item_chances,
|
||||||
|
number_of_items,
|
||||||
|
floor_number
|
||||||
|
)
|
||||||
|
|
||||||
|
for entity in monsters + items:
|
||||||
x = random.randint(room.x1 + 1, room.x2 - 1)
|
x = random.randint(room.x1 + 1, room.x2 - 1)
|
||||||
y = random.randint(room.y1 + 1, room.y2 - 1)
|
y = random.randint(room.y1 + 1, room.y2 - 1)
|
||||||
|
|
||||||
if not any(entity.x == x and entity.y == y for entity in dungeon.entities):
|
if not any(entity.x == x and entity.y == y for entity in dungeon.entities):
|
||||||
if random.random() < 0.8:
|
entity.spawn(dungeon, x, y)
|
||||||
entity_factories.orc.spawn(dungeon, x, y)
|
|
||||||
else:
|
|
||||||
entity_factories.troll.spawn(dungeon, x, y)
|
|
||||||
|
|
||||||
for i in range(number_of_items):
|
|
||||||
x = random.randint(room.x1 + 1, room.x2 - 1)
|
|
||||||
y = random.randint(room.y1 + 1, room.y2 - 1)
|
|
||||||
|
|
||||||
if not any(entity.x == x and entity.y == y for entity in dungeon.entities):
|
|
||||||
item_chance = random.random()
|
|
||||||
|
|
||||||
if item_chance < 0.7:
|
|
||||||
entity_factories.health_potion.spawn(dungeon, x, y)
|
|
||||||
elif item_chance < 0.8:
|
|
||||||
entity_factories.fireball_scroll.spawn(dungeon, x, y)
|
|
||||||
elif item_chance < 0.9:
|
|
||||||
entity_factories.confusion_scroll.spawn(dungeon, x, y)
|
|
||||||
else:
|
|
||||||
entity_factories.lightning_scroll.spawn(dungeon, x, y)
|
|
||||||
|
|
||||||
|
|
||||||
def tunnel_between(start: Tuple[int, int], end: Tuple[int, int]) -> Iterator[Tuple[int, int]]:
|
def tunnel_between(start: Tuple[int, int], end: Tuple[int, int]) -> Iterator[Tuple[int, int]]:
|
||||||
@ -103,8 +168,6 @@ def generate_dungeon(
|
|||||||
room_max_size: int,
|
room_max_size: int,
|
||||||
map_width: int,
|
map_width: int,
|
||||||
map_height: int,
|
map_height: int,
|
||||||
max_monsters_per_room: int,
|
|
||||||
max_items_per_room: int,
|
|
||||||
engine: Engine,
|
engine: Engine,
|
||||||
) -> GameMap:
|
) -> GameMap:
|
||||||
"""Generate a new dungeon map."""
|
"""Generate a new dungeon map."""
|
||||||
@ -143,7 +206,7 @@ def generate_dungeon(
|
|||||||
|
|
||||||
center_of_last_room = new_room.center
|
center_of_last_room = new_room.center
|
||||||
|
|
||||||
place_entities(new_room, dungeon, max_monsters_per_room, max_items_per_room)
|
place_entities(new_room, dungeon, engine.game_world.current_floor)
|
||||||
|
|
||||||
dungeon.tiles[center_of_last_room] = tile_types.down_stairs
|
dungeon.tiles[center_of_last_room] = tile_types.down_stairs
|
||||||
dungeon.downstairs_location = center_of_last_room
|
dungeon.downstairs_location = center_of_last_room
|
||||||
|
@ -28,9 +28,6 @@ def new_game() -> Engine:
|
|||||||
room_min_size = 6
|
room_min_size = 6
|
||||||
max_rooms = 30
|
max_rooms = 30
|
||||||
|
|
||||||
max_monsters_per_room = 2
|
|
||||||
max_items_per_room = 2
|
|
||||||
|
|
||||||
player = copy.deepcopy(entity_factories.player)
|
player = copy.deepcopy(entity_factories.player)
|
||||||
|
|
||||||
engine = Engine(player)
|
engine = Engine(player)
|
||||||
@ -42,8 +39,6 @@ def new_game() -> Engine:
|
|||||||
room_max_size=room_max_size,
|
room_max_size=room_max_size,
|
||||||
map_width=map_width,
|
map_width=map_width,
|
||||||
map_height=map_height,
|
map_height=map_height,
|
||||||
max_monsters_per_room=max_monsters_per_room,
|
|
||||||
max_items_per_room=max_items_per_room,
|
|
||||||
)
|
)
|
||||||
engine.game_world.generate_floor()
|
engine.game_world.generate_floor()
|
||||||
engine.update_fov()
|
engine.update_fov()
|
||||||
|
Loading…
Reference in New Issue
Block a user