22
33import copy
44import random
5- from typing import Iterator , List , Tuple , TYPE_CHECKING
5+ from typing import Dict , Iterator , List , Tuple , TYPE_CHECKING
66
77import tcod
88
1515 import game .game_map
1616
1717
18+ max_items_by_floor = [
19+ (1 , 1 ),
20+ (4 , 2 ),
21+ ]
22+
23+ max_monsters_by_floor = [
24+ (1 , 2 ),
25+ (4 , 3 ),
26+ (6 , 5 ),
27+ ]
28+
29+ item_chances : Dict [int , List [Tuple [game .entity .Entity , int ]]] = {
30+ 0 : [(game .entity_factories .health_potion , 35 )],
31+ 2 : [(game .entity_factories .confusion_scroll , 10 )],
32+ 4 : [(game .entity_factories .lightning_scroll , 25 )],
33+ 6 : [(game .entity_factories .fireball_scroll , 25 )],
34+ }
35+
36+ enemy_chances : Dict [int , List [Tuple [game .entity .Entity , int ]]] = {
37+ 0 : [(game .entity_factories .orc , 80 )],
38+ 3 : [(game .entity_factories .troll , 15 )],
39+ 5 : [(game .entity_factories .troll , 30 )],
40+ 7 : [(game .entity_factories .troll , 60 )],
41+ }
42+
43+
44+ def get_max_value_for_floor (weighted_chances_by_floor : List [Tuple [int , int ]], floor : int ) -> int :
45+ current_value = 0
46+
47+ for floor_minimum , value in weighted_chances_by_floor :
48+ if floor_minimum > floor :
49+ break
50+ else :
51+ current_value = value
52+
53+ return current_value
54+
55+
56+ def get_entities_at_random (
57+ weighted_chances_by_floor : Dict [int , List [Tuple [game .entity .Entity , int ]]],
58+ number_of_entities : int ,
59+ floor : int ,
60+ ) -> List [game .entity .Entity ]:
61+ entity_weighted_chances = {}
62+
63+ for key , values in weighted_chances_by_floor .items ():
64+ if key > floor :
65+ break
66+ else :
67+ for value in values :
68+ entity = value [0 ]
69+ weighted_chance = value [1 ]
70+
71+ entity_weighted_chances [entity ] = weighted_chance
72+
73+ entities = list (entity_weighted_chances .keys ())
74+ entity_weighted_chance_values = list (entity_weighted_chances .values ())
75+
76+ chosen_entities = random .choices (entities , weights = entity_weighted_chance_values , k = number_of_entities )
77+
78+ return chosen_entities
79+
80+
1881class RectangularRoom :
1982 def __init__ (self , x : int , y : int , width : int , height : int ):
2083 self .x1 = x
@@ -60,41 +123,21 @@ def tunnel_between(start: Tuple[int, int], end: Tuple[int, int]) -> Iterator[Tup
60123def place_entities (
61124 room : RectangularRoom ,
62125 dungeon : game .game_map .GameMap ,
63- maximum_monsters : int ,
64- maximum_items : int ,
126+ floor_number : int ,
65127) -> None :
66- number_of_monsters = random .randint (0 , maximum_monsters )
67- number_of_items = random .randint (0 , maximum_items )
128+ number_of_monsters = random .randint (0 , get_max_value_for_floor ( max_monsters_by_floor , floor_number ) )
129+ number_of_items = random .randint (0 , get_max_value_for_floor ( max_items_by_floor , floor_number ) )
68130
69- for _ in range (number_of_monsters ):
70- x = random .randint (room .x1 + 1 , room .x2 - 1 )
71- y = random .randint (room .y1 + 1 , room .y2 - 1 )
131+ monsters : List [game .entity .Entity ] = get_entities_at_random (enemy_chances , number_of_monsters , floor_number )
132+ items : List [game .entity .Entity ] = get_entities_at_random (item_chances , number_of_items , floor_number )
72133
73- if not any (entity .x == x and entity .y == y for entity in dungeon .entities ):
74- if random .random () < 0.8 :
75- monster = copy .deepcopy (game .entity_factories .orc )
76- else :
77- monster = copy .deepcopy (game .entity_factories .troll )
78-
79- monster .place (x , y , dungeon )
80-
81- for _ in range (number_of_items ):
134+ for entity in monsters + items :
82135 x = random .randint (room .x1 + 1 , room .x2 - 1 )
83136 y = random .randint (room .y1 + 1 , room .y2 - 1 )
84137
85138 if not any (entity .x == x and entity .y == y for entity in dungeon .entities ):
86- item_chance = random .random ()
87-
88- if item_chance < 0.7 :
89- item = copy .deepcopy (game .entity_factories .health_potion )
90- elif item_chance < 0.8 :
91- item = copy .deepcopy (game .entity_factories .fireball_scroll )
92- elif item_chance < 0.9 :
93- item = copy .deepcopy (game .entity_factories .confusion_scroll )
94- else :
95- item = copy .deepcopy (game .entity_factories .lightning_scroll )
96-
97- item .place (x , y , dungeon )
139+ entity_copy = copy .deepcopy (entity )
140+ entity_copy .place (x , y , dungeon )
98141
99142
100143def generate_dungeon (
@@ -103,8 +146,7 @@ def generate_dungeon(
103146 room_max_size : int ,
104147 map_width : int ,
105148 map_height : int ,
106- max_monsters_per_room : int ,
107- max_items_per_room : int ,
149+ current_floor : int ,
108150 engine : game .engine .Engine ,
109151) -> game .game_map .GameMap :
110152 """Generate a new dungeon map."""
@@ -139,7 +181,7 @@ def generate_dungeon(
139181 for x , y in tunnel_between (rooms [- 1 ].center , new_room .center ):
140182 dungeon .tiles [x , y ] = game .tiles .floor
141183
142- place_entities (new_room , dungeon , max_monsters_per_room , max_items_per_room )
184+ place_entities (new_room , dungeon , current_floor )
143185
144186 # Finally, append the new room to the list.
145187 rooms .append (new_room )
0 commit comments