-
Notifications
You must be signed in to change notification settings - Fork 0
/
game_world.py
172 lines (140 loc) · 5.6 KB
/
game_world.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
from __future__ import annotations
from typing import TYPE_CHECKING, List
import utils
from engine import Engine
from exceptions import Impossible
import color
from map_gen import procgen
from map_gen.debug_room import create_debug_room
from map_gen.generate_cave import generate_cave
from map_gen.generate_dungeon import generate_dungeon
from map_gen.top_floor import create_top_floor
from map_gen.generate_cathedral import generate_cathedral
if TYPE_CHECKING:
from game_map import GameMap
prefab_maps = {
"debug_room": create_debug_room,
"top_floor": create_top_floor,
}
world_prefabs = {
10: "top_floor",
}
floor_map_generator = {
0: lambda **kwargs: generate_cave(
max_rooms=8, room_min_size=6, room_max_size=10, **kwargs
),
1: lambda **kwargs: generate_cave(
max_rooms=12, room_min_size=8, room_max_size=12, **kwargs
),
4: lambda **kwargs: generate_dungeon(
max_rooms=16, room_min_size=6, room_max_size=10, **kwargs
),
6: lambda **kwargs: generate_cathedral(**kwargs),
# Add more floors and corresponding functions with parameters as needed.
}
class GameWorld:
"""
Holds the settings for the GameMap, and generates new maps when moving down the stairs.
"""
def __init__(
self,
*,
engine: Engine,
map_width: int,
map_height: int,
current_floor: int = 1,
):
self.engine = engine
self.map_width = map_width
self.map_height = map_height
self.current_floor = current_floor
self.floors: List[GameMap] = []
def set_fixed_items(self, items) -> None:
items = list(items)
fixed_items = procgen.get_fixed_items(self.current_floor)
# replace some items with the items in fixed_items if there are any
if len(fixed_items) > 0:
utils.replace_items_in_list(items, 0, fixed_items)
def generate_floor(self) -> None:
"""Generate a new floor, using the corresponding floor generator function."""
if self.engine.debug_mode:
print(f"Generating floor {self.current_floor}")
floor_generator = None
for floor in sorted(floor_map_generator.keys(), reverse=True):
if self.current_floor >= floor:
floor_generator = floor_map_generator[floor]
break
# If no generator is found, default to generate_dungeon
if floor_generator is None:
floor_generator = generate_dungeon
additional_params = {
"map_width": self.map_width,
"map_height": self.map_height,
"engine": self.engine,
}
# Generate the game map using the chosen generator function
game_map = floor_generator(**additional_params)
self.set_fixed_items(game_map.items)
self.floors.append(game_map)
self.engine.game_map = game_map
def load_prefab_map(self, map_name: str) -> None:
params = {
"map_width": self.map_width,
"map_height": self.map_height,
"engine": self.engine,
}
map_generator = prefab_maps[map_name]
if map_generator is None:
raise Impossible(f"Prefab map {map_name} not found!")
game_map = map_generator(**params)
self.floors.append(game_map)
self.engine.game_map = game_map
def load_floor(self, floor: int) -> None:
"""
Loads a specific floor of the game map. Use actual floor numbers, 1 to N.
"""
# Throw an error if the floor does not exist
if floor < 1 or floor > len(self.floors):
raise Impossible("Invalid floor number")
if self.engine.debug_mode:
print(f"Loading floor {floor}")
# Update current loaded floor with the new floor
self.engine.game_map = self.floors[floor - 1]
# Set the pair of stairs to put the player on depending if we're ascending or descending
stairs = (
self.engine.game_map.downstairs_location
if self.current_floor < floor
else self.engine.game_map.upstairs_location
)
self.current_floor = floor
self.engine.player.place(
stairs[0],
stairs[1],
self.engine.game_map,
)
def descend(self) -> None:
self.engine.game_world.load_floor(self.engine.game_world.current_floor - 1)
self.engine.message_log.add_message("You descend the staircase.", color.ascend)
def ascend(self) -> None:
next_floor = self.engine.game_world.current_floor + 1
if len(self.engine.game_world.floors) < next_floor:
# Load a prefab map if there is one
if world_prefabs.get(next_floor):
if self.engine.debug_mode:
print(f"Loading prefab map {world_prefabs[next_floor]}")
self.engine.game_world.load_prefab_map(world_prefabs[next_floor])
self.engine.game_world.current_floor += 1
# Get the downstairs location to place the player
stairs = self.engine.game_map.downstairs_location
self.engine.player.place(
stairs[0],
stairs[1],
self.engine.game_map,
)
else:
# If we're on the last existing floor, and there's no prefab map, we generate a new one.
self.engine.game_world.current_floor += 1
self.engine.game_world.generate_floor()
else:
self.engine.game_world.load_floor(next_floor)
self.engine.message_log.add_message("You ascend the staircase.", color.ascend)