1
0

Weighted random generation, completes Part 12

This commit is contained in:
Timothy Warren 2022-02-08 09:21:19 -05:00
parent 87bac7a322
commit 1b354b007c
3 changed files with 92 additions and 41 deletions

View File

@ -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,
) )

View File

@ -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

View File

@ -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()