Weighted random generation, completes Part 12
This commit is contained in:
parent
87bac7a322
commit
1b354b007c
@ -127,8 +127,6 @@ class GameWorld:
|
||||
max_rooms: int,
|
||||
room_min_size: int,
|
||||
room_max_size: int,
|
||||
max_monsters_per_room: int,
|
||||
max_items_per_room: int,
|
||||
current_floor: int = 0
|
||||
):
|
||||
self.engine = engine
|
||||
@ -141,9 +139,6 @@ class GameWorld:
|
||||
self.room_min_size = room_min_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
|
||||
|
||||
def generate_floor(self) -> None:
|
||||
@ -157,7 +152,5 @@ class GameWorld:
|
||||
room_max_size=self.room_max_size,
|
||||
map_width=self.map_width,
|
||||
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,
|
||||
)
|
||||
|
121
procgen.py
121
procgen.py
@ -1,7 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
from typing import Iterator, List, Tuple, TYPE_CHECKING
|
||||
from typing import Dict, Iterator, List, Tuple, TYPE_CHECKING
|
||||
|
||||
import tcod
|
||||
|
||||
@ -11,6 +11,76 @@ import tile_types
|
||||
|
||||
if TYPE_CHECKING:
|
||||
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:
|
||||
@ -45,37 +115,32 @@ class RectangularRoom:
|
||||
def place_entities(
|
||||
room: RectangularRoom,
|
||||
dungeon: GameMap,
|
||||
maximum_monsters: int,
|
||||
maximum_items: int,
|
||||
floor_number: int,
|
||||
) -> None:
|
||||
number_of_monsters = random.randint(0, maximum_monsters)
|
||||
number_of_items = random.randint(0, maximum_items)
|
||||
number_of_monsters = random.randint(
|
||||
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)
|
||||
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 random.random() < 0.8:
|
||||
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)
|
||||
entity.spawn(dungeon, x, y)
|
||||
|
||||
|
||||
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,
|
||||
map_width: int,
|
||||
map_height: int,
|
||||
max_monsters_per_room: int,
|
||||
max_items_per_room: int,
|
||||
engine: Engine,
|
||||
) -> GameMap:
|
||||
"""Generate a new dungeon map."""
|
||||
@ -143,7 +206,7 @@ def generate_dungeon(
|
||||
|
||||
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.downstairs_location = center_of_last_room
|
||||
|
@ -28,9 +28,6 @@ def new_game() -> Engine:
|
||||
room_min_size = 6
|
||||
max_rooms = 30
|
||||
|
||||
max_monsters_per_room = 2
|
||||
max_items_per_room = 2
|
||||
|
||||
player = copy.deepcopy(entity_factories.player)
|
||||
|
||||
engine = Engine(player)
|
||||
@ -42,8 +39,6 @@ def new_game() -> Engine:
|
||||
room_max_size=room_max_size,
|
||||
map_width=map_width,
|
||||
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.update_fov()
|
||||
|
Loading…
Reference in New Issue
Block a user