neelthee-mansion 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- neelthee_mansion/Mansion_of_Amnesia.py +884 -0
- neelthee_mansion/Quests.py +70 -0
- neelthee_mansion/Rooms.py +1733 -0
- neelthee_mansion/__init__.py +0 -0
- neelthee_mansion/creatures.py +373 -0
- neelthee_mansion/items.py +67 -0
- neelthee_mansion/utils.py +388 -0
- neelthee_mansion-1.0.0.dist-info/METADATA +38 -0
- neelthee_mansion-1.0.0.dist-info/RECORD +12 -0
- neelthee_mansion-1.0.0.dist-info/WHEEL +5 -0
- neelthee_mansion-1.0.0.dist-info/entry_points.txt +2 -0
- neelthee_mansion-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,884 @@
|
|
1
|
+
from Rooms import *
|
2
|
+
from creatures import *
|
3
|
+
from items import *
|
4
|
+
from Quests import *
|
5
|
+
import sys
|
6
|
+
import os
|
7
|
+
|
8
|
+
# Add the path to Utils
|
9
|
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'all_game_utils.py')))
|
10
|
+
from all_game_utils import *
|
11
|
+
|
12
|
+
|
13
|
+
GameState = {
|
14
|
+
'Enemys killed': 0,
|
15
|
+
'collected items': [],
|
16
|
+
}
|
17
|
+
|
18
|
+
|
19
|
+
'''
|
20
|
+
Neel-thee's Mansion of Amnesia
|
21
|
+
'''
|
22
|
+
|
23
|
+
global player, evil_mage, commands, NOTE_NUM, LAST_ROOM, CURRENTROOM, credits, characters, color_coding, quest_manager
|
24
|
+
|
25
|
+
quest_manager = QuestManager()
|
26
|
+
|
27
|
+
color_coding = False
|
28
|
+
|
29
|
+
credits = '''
|
30
|
+
Made by: Alexander.E.F'''
|
31
|
+
|
32
|
+
# start the player in the Hall
|
33
|
+
CURRENTROOM = 'Hall'
|
34
|
+
|
35
|
+
LAST_ROOM = CURRENTROOM
|
36
|
+
|
37
|
+
name = ''
|
38
|
+
age = 0
|
39
|
+
height = Height()
|
40
|
+
weight = 0
|
41
|
+
|
42
|
+
|
43
|
+
charactersList = [
|
44
|
+
{'name': 'Jack', 'age': 19, 'height': Height('6ft 3'), 'weight(LBs)': 213},
|
45
|
+
{'name': 'Darcie-Mae', 'age': 19, 'height': Height('5ft 5'), 'weight(LBs)': 150},
|
46
|
+
{'name': 'John', 'age': 25, 'height': Height('5ft 10'), 'weight(LBs)': 180},
|
47
|
+
{'name': 'Emily', 'age': 22, 'height': Height('5ft 6'), 'weight(LBs)': 135},
|
48
|
+
{'name': 'William', 'age': 30, 'height': Height('6ft 1'), 'weight(LBs)': 200},
|
49
|
+
{'name': 'Samantha', 'age': 28, 'height': Height('5ft 8'), 'weight(LBs)': 155},
|
50
|
+
{'name': 'Mark', 'age': 23, 'height': Height('5ft 11'), 'weight(LBs)': 185},
|
51
|
+
{'name': 'Alex', 'age': 27, 'height': Height('6ft 0'), 'weight(LBs)': 190},
|
52
|
+
{'name': 'Sarah', 'age': 20, 'height': Height('5ft 4'), 'weight(LBs)': 125},
|
53
|
+
{'name': 'Natalie', 'age': 24, 'height': Height('5ft 7'), 'weight(LBs)': 140},
|
54
|
+
{'name': 'Michael', 'age': 32, 'height': Height('6ft 2'), 'weight(LBs)': 200},
|
55
|
+
{'name': 'Liam', 'age': 29, 'height': Height('5ft 10'), 'weight(LBs)': 180},
|
56
|
+
{'name': 'James', 'age': 25, 'height': Height('6ft 1'), 'weight(LBs)': 195},
|
57
|
+
{'name': 'Emma', 'age': 22, 'height': Height('5ft 6'), 'weight(LBs)': 130},
|
58
|
+
{'name': 'Olivia', 'age': 26, 'height': Height('5ft 8'), 'weight(LBs)': 135},
|
59
|
+
{'name': 'Sophia', 'age': 28, 'height': Height('5ft 5'), 'weight(LBs)': 145},
|
60
|
+
{'name': 'Daniel', 'age': 28, 'height': Height('6ft 0'), 'weight(LBs)': 180},
|
61
|
+
{'name': 'Matthew', 'age': 31, 'height': Height('5ft 11'), 'weight(LBs)': 175},
|
62
|
+
{'name': 'Jennifer', 'age': 25, 'height': Height('5ft 6'), 'weight(LBs)': 140},
|
63
|
+
{'name': 'Hannah', 'age': 23, 'height': Height('5ft 4'), 'weight(LBs)': 130},
|
64
|
+
{'name': 'Isabella', 'age': 24, 'height': Height('5ft 4'), 'weight(LBs)': 132},
|
65
|
+
{'name': 'Jake', 'age': 29, 'height': Height('5ft 6'), 'weight(LBs)': 140},
|
66
|
+
{'name': 'Zack', 'age': 21, 'height': Height('5ft 5'), 'weight(LBs)': 125},
|
67
|
+
{'name': 'Lucy', 'age': 27, 'height': Height('5ft 7'), 'weight(LBs)': 135},
|
68
|
+
{'name': 'Mia', 'age': 25, 'height': Height('5ft 3'), 'weight(LBs)': 128},
|
69
|
+
{'name': 'Brandon', 'age': 30, 'height': Height('6ft 1'), 'weight(LBs)': 180},
|
70
|
+
{'name': 'Ethan', 'age': 28, 'height': Height('6ft 0'), 'weight(LBs)': 175},
|
71
|
+
{'name': 'Andrew', 'age': 28, 'height': Height('6ft 0'), 'weight(LBs)': 175},
|
72
|
+
{'name': 'Nathan', 'age': 26, 'height': Height('5ft 10'), 'weight(LBs)': 165},
|
73
|
+
{'name': 'David', 'age': 22, 'height': Height('6ft 2'), 'weight(LBs)': 185},
|
74
|
+
{'name': 'Noah', 'age': 25, 'height': Height('5ft 11'), 'weight(LBs)': 175},
|
75
|
+
{'name': 'Aiden', 'age': 30, 'height': Height('6ft 0'), 'weight(LBs)': 180},
|
76
|
+
{'name': 'Lucas', 'age': 28, 'height': Height('5ft 10'), 'weight(LBs)': 170},
|
77
|
+
{'name': 'Ava', 'age': 22, 'height': Height('5ft 5'), 'weight(LBs)': 130},
|
78
|
+
{'name': 'Lily', 'age': 26, 'height': Height('5ft 6'), 'weight(LBs)': 135},
|
79
|
+
{'name': 'Grace', 'age': 29, 'height': Height('5ft 7'), 'weight(LBs)': 140}
|
80
|
+
]
|
81
|
+
|
82
|
+
|
83
|
+
df = pd.DataFrame(charactersList)
|
84
|
+
|
85
|
+
|
86
|
+
if __name__ == "__main__":
|
87
|
+
# this is the initializer
|
88
|
+
Standord_Player = loop_til_valid_input("Do you want to use a premade character?", "you didn't answer Y or N.", Y_N).value
|
89
|
+
|
90
|
+
if Standord_Player:
|
91
|
+
while True:
|
92
|
+
type_text("Who do you want to play as?", colorTrue=color_coding)
|
93
|
+
print(df)
|
94
|
+
selected_character = loop_til_valid_input(
|
95
|
+
"Who do you want to play as? (please select the number to the left of there stats)",
|
96
|
+
"That wasn't one of the characters. Please choose one.",
|
97
|
+
int
|
98
|
+
)
|
99
|
+
lstIndex = last_index(charactersList)
|
100
|
+
if selected_character <= lstIndex:
|
101
|
+
character_info = charactersList[selected_character]
|
102
|
+
name = character_info['name']
|
103
|
+
age = character_info['age']
|
104
|
+
height = character_info['height']
|
105
|
+
weight = character_info['weight(LBs)']
|
106
|
+
break
|
107
|
+
else:
|
108
|
+
type_text(colorTrue=color_coding)
|
109
|
+
|
110
|
+
type_text("Please enter a codename for your achievements to save under \n>", False, colorTrue=color_coding)
|
111
|
+
codename = input()
|
112
|
+
|
113
|
+
else:
|
114
|
+
type_text("You will now have to enter a name, age, height, and weight. Please enter the height in this format: _ft _. These will be used throughout the game.", colorTrue=color_coding)
|
115
|
+
|
116
|
+
name = loop_til_valid_input("What is your name?", "You didn't enter a string. Please enter a string.", str)
|
117
|
+
age = loop_til_valid_input("What is your age (in whole years)?", "You didn't enter an integer. Please enter an integer.", int)
|
118
|
+
height = loop_til_valid_input("What is your height?", "You didn't enter your height in the correct format. Please enter your height in the correct format.", Height)
|
119
|
+
weight = loop_til_valid_input("What is your weight (in lbs)?", "You didn't enter an integer. Please enter an integer.", int)
|
120
|
+
codename = False
|
121
|
+
|
122
|
+
color_coding = loop_til_valid_input("Do you want color coding (Y/N)?", "you didn't answer Y or N.", Y_N).value
|
123
|
+
|
124
|
+
player = PC(
|
125
|
+
name,
|
126
|
+
age,
|
127
|
+
'Warrior',
|
128
|
+
1,
|
129
|
+
'Soldier',
|
130
|
+
height,
|
131
|
+
weight,
|
132
|
+
[
|
133
|
+
f"You joined the army at {14 if age >= 14 else age}",
|
134
|
+
f"You joined the army to end the war and because you wanted glory",
|
135
|
+
f"You spent your first year of service training and the rest on the front lines, surprisingly you didn't die",
|
136
|
+
f"In your service, you made 3 friends, one of them died",
|
137
|
+
f"You fought your enemies from the tops of the mountains to the vast oceans",
|
138
|
+
f"Your father was never home; he was always off on great adventures until he died when you were {7 if age >= 7 else age}",
|
139
|
+
f"You have no friends back home; you were always very lonely",
|
140
|
+
f"You are an only child. You ran away from home to join the army; your mother misses you terribly",
|
141
|
+
f"She was a baker, and you spent a lot of time helping her bake bread. You never went to school",
|
142
|
+
f"The people you admire the most are Sam and Aragorn from Lord of the Rings, which you read as a child. You have also read the Hunger Games when you were {13 if age >= 13 else age}",
|
143
|
+
f"Your favorite weapon is a bow; however, the scimitar is a close second.",
|
144
|
+
],
|
145
|
+
Background=f"""
|
146
|
+
You were born into a life of solitude as an only child. Your father was always away on grand adventures and passed away when you were just {7 if age >= 7 else age}. Your mother, a dedicated
|
147
|
+
baker, raised you alone. Although she did her best, you spent most of your time helping her in the bakery rather than attending school, which left you feeling quite isolated.
|
148
|
+
|
149
|
+
At the age of {14 if age >= 14 else age}, driven by a desire for glory and a wish to end the war, you left home to join the army. You spent your first year in rigorous training, followed by a
|
150
|
+
harsh life on the front lines. Against all odds, you survived, forging bonds with three close friends—though one of them tragically died in battle. Your journey took you from the heights of
|
151
|
+
mountains to the vast expanses of the ocean, each experience shaping who you are.
|
152
|
+
|
153
|
+
You were deeply influenced by the heroes of your childhood—Sam and Aragorn from %*ITALIC*%Lord of the Rings%*RESET*%, which you read as a child, and the characters from %*ITALIC*%The Hunger
|
154
|
+
Games%*RESET*%, which you read when you were {13 if age >= 13 else age}. These stories inspired you and fueled your dream of heroism. Though your favorite weapon is a bow, you also have a
|
155
|
+
fondness for the scimitar.
|
156
|
+
|
157
|
+
Now, you find yourself in the Mansion of Amnesia, a place that seems to have erased your memories. The details of your past are fragmented, but the echoes of your history drive you forward. You
|
158
|
+
must navigate the mansion and uncover the truth behind your captivity, all while drawing strength from the remnants of your past.
|
159
|
+
"""
|
160
|
+
)
|
161
|
+
|
162
|
+
|
163
|
+
evil_mage = PC(
|
164
|
+
'Neel-thee Contozt',
|
165
|
+
19836,
|
166
|
+
'Mage',
|
167
|
+
29,
|
168
|
+
'Evil prince',
|
169
|
+
Height('5ft 7.375'),
|
170
|
+
222,
|
171
|
+
xp=99180,
|
172
|
+
)
|
173
|
+
|
174
|
+
|
175
|
+
# Function to parse command
|
176
|
+
def parse_command(command_str: str, commands: dict):
|
177
|
+
# Split the command string into parts
|
178
|
+
parts = command_str.split()
|
179
|
+
|
180
|
+
# Check for multi-word commands
|
181
|
+
for cmd in commands.keys():
|
182
|
+
cmd_parts = cmd.split()
|
183
|
+
if len(cmd_parts) > 1 and parts[:len(cmd_parts)] == cmd_parts:
|
184
|
+
action = ' '.join(cmd_parts)
|
185
|
+
targets = parts[len(cmd_parts):]
|
186
|
+
return action, targets
|
187
|
+
|
188
|
+
# Default single word command
|
189
|
+
action = parts[0]
|
190
|
+
targets = parts[1:] if len(parts) > 1 else []
|
191
|
+
return action, targets
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
def showInstructions():
|
196
|
+
# Display the game instructions
|
197
|
+
type_text('''
|
198
|
+
===========================
|
199
|
+
Commands:
|
200
|
+
go [%*GREEN*%direction%*RESET*%/%*GREEN*%teleport%*RESET*%/%*GREEN*%number%*RESET*%] - Move to another location
|
201
|
+
get [%*BLUE*%item%*RESET*%] - Pick up an item from your current location
|
202
|
+
search [the/] [%*RED*%container%*RESET*%] - Search a container in your current location
|
203
|
+
use [%*BLUE*%item%*RESET*%] - Use an item from your inventory
|
204
|
+
put [%*BLUE*%item%*RESET*%] [the/] [%*RED*%container%*RESET*%] - Put an item from your inventory into a container in your current location
|
205
|
+
sleep - Rest for a bit and regain some health
|
206
|
+
look - Look around your current location
|
207
|
+
quit - Quit the game
|
208
|
+
help - Show these instructions
|
209
|
+
hint - Get a random hint for your current location
|
210
|
+
map - Display the map of places you have been to
|
211
|
+
''', colorTrue=color_coding)
|
212
|
+
|
213
|
+
|
214
|
+
def showHint():
|
215
|
+
if 'Hints' in ROOMS[CURRENTROOM]:
|
216
|
+
type_text("You think:", colorTrue=color_coding)
|
217
|
+
hint = choice(ROOMS[CURRENTROOM]['Hints'])
|
218
|
+
type_text(hint, colorTrue=color_coding)
|
219
|
+
else:
|
220
|
+
type_text("You can't think of anything", colorTrue=color_coding)
|
221
|
+
|
222
|
+
def check_direction(var: str, directions: list):
|
223
|
+
for direction in directions:
|
224
|
+
if var == direction:
|
225
|
+
return True
|
226
|
+
return False
|
227
|
+
|
228
|
+
|
229
|
+
def End(text: str, win: bool = True):
|
230
|
+
type_text(text, colorTrue=color_coding)
|
231
|
+
if win:
|
232
|
+
type_text('Do you want to leave the game? Y/N', colorTrue=color_coding)
|
233
|
+
while True:
|
234
|
+
leave = input('>').lower()
|
235
|
+
if leave == 'n':
|
236
|
+
type_text('You decide to continue exploring.', colorTrue=color_coding)
|
237
|
+
break
|
238
|
+
elif leave == 'y':
|
239
|
+
type_text('You escaped the house... %*BOLD*%GAME OVER, YOU WIN!', colorTrue=color_coding)
|
240
|
+
commands["quit"]()
|
241
|
+
else:
|
242
|
+
type_text("Sorry, that wasn't 'y' or 'n'. Please enter 'y' or 'n'.", colorTrue=color_coding)
|
243
|
+
else:
|
244
|
+
type_text('%*BOLD*%GAME OVER, YOU LOSE!', colorTrue=color_coding)
|
245
|
+
commands["quit"]()
|
246
|
+
|
247
|
+
|
248
|
+
NOTE_NUM = 0
|
249
|
+
|
250
|
+
|
251
|
+
def add_note(note, parchment_index=None):
|
252
|
+
player.NOTES.append(note)
|
253
|
+
NOTE_NUM += 1
|
254
|
+
inv_note = 'note ' + str(NOTE_NUM)
|
255
|
+
try:
|
256
|
+
del player.inventory[parchment_index]
|
257
|
+
except IndexError:
|
258
|
+
pass
|
259
|
+
player.inventory_add([item(inv_note)])
|
260
|
+
|
261
|
+
|
262
|
+
def Use_grappling_hook():
|
263
|
+
|
264
|
+
def swing_into_forest():
|
265
|
+
type_text("You throw your grappling-hook, it catches a branch of a nearby tree and hooks back onto itself. \nYou can swing into the forest!", colorTrue=color_coding)
|
266
|
+
if ask_for_consent("Do you want to swing into the forest"):
|
267
|
+
type_text("You swing into the forest", colorTrue=color_coding)
|
268
|
+
Move('Forest Clearing')
|
269
|
+
else:
|
270
|
+
type_text("You flick the rope and it unhooks. You continue exploring the house.", colorTrue=color_coding)
|
271
|
+
|
272
|
+
def climb_into_house():
|
273
|
+
type_text("You throw your grappling-hook, it catches the railing of the nearby house and hooks back onto itself. \nYou can climb into the house!", colorTrue=color_coding)
|
274
|
+
if ask_for_consent("Do you want to climb into the house"):
|
275
|
+
type_text("You climb into the house", colorTrue=color_coding)
|
276
|
+
Move('Balcony')
|
277
|
+
else:
|
278
|
+
type_text("You flick the rope and it unhooks. You continue exploring the forest", colorTrue=color_coding)
|
279
|
+
|
280
|
+
if CURRENTROOM == 'Balcony' and 'grappling-hook' in player.inventory:
|
281
|
+
swing_into_forest()
|
282
|
+
elif CURRENTROOM == 'Forest Clearing' and 'grappling-hook' in player.inventory:
|
283
|
+
climb_into_house()
|
284
|
+
|
285
|
+
|
286
|
+
def Use_quill():
|
287
|
+
|
288
|
+
if all(item in player.inventory for item in ['ink-pot', 'parchment', 'quill']):
|
289
|
+
parchment_index = player.inventory.index('parchment')
|
290
|
+
type_text('What do you want to write', colorTrue=color_coding)
|
291
|
+
write = str(input('>')).strip()
|
292
|
+
|
293
|
+
if write:
|
294
|
+
add_note(write, parchment_index)
|
295
|
+
else:
|
296
|
+
type_text("You can't write nothing", colorTrue=color_coding)
|
297
|
+
else:
|
298
|
+
type_text("You need an ink pot, parchment, and a quill to write.", colorTrue=color_coding)
|
299
|
+
|
300
|
+
|
301
|
+
def Use_note(note_number):
|
302
|
+
"""Reads a specified note from the player's inventory."""
|
303
|
+
note_key = f'note {note_number}'
|
304
|
+
if note_key in player.inventory:
|
305
|
+
note_index = int(note_number) - 1
|
306
|
+
type_text(f'You read:', colorTrue=color_coding)
|
307
|
+
type_text(player.NOTES[note_index], colorTrue=color_coding)
|
308
|
+
else:
|
309
|
+
type_text('You do not have that note', colorTrue=color_coding)
|
310
|
+
|
311
|
+
|
312
|
+
def Use(moveone, movetwo=None):
|
313
|
+
"""Uses an item from the player's inventory."""
|
314
|
+
if moveone in player.inventory:
|
315
|
+
item_obj = player.inventory[player.inventory.index(moveone)]
|
316
|
+
if isinstance(item_obj, item):
|
317
|
+
if item_obj.sell(player):
|
318
|
+
type_text(f"You sell the %*BLUE*%{moveone}%*RESET*%", colorTrue=color_coding)
|
319
|
+
player.inventory.remove(item_obj.name)
|
320
|
+
elif moveone == 'quill':
|
321
|
+
Use_quill()
|
322
|
+
elif moveone == 'grappling-hook':
|
323
|
+
Use_grappling_hook()
|
324
|
+
elif moveone == 'note' and movetwo:
|
325
|
+
Use_note(movetwo)
|
326
|
+
elif moveone == '0':
|
327
|
+
type_text("You can't use nothing", colorTrue=color_coding)
|
328
|
+
else:
|
329
|
+
type_text("You can't use that", colorTrue=color_coding)
|
330
|
+
|
331
|
+
|
332
|
+
def Move(move):
|
333
|
+
global CURRENTROOM, LAST_ROOM
|
334
|
+
|
335
|
+
|
336
|
+
def attempt_charter():
|
337
|
+
if player.money >= 10:
|
338
|
+
player.money -= 10
|
339
|
+
if 'descovered' in ROOMS[newRoom] and not ROOMS[newRoom]['descovered']:
|
340
|
+
ROOMS[newRoom]['descovered'] = True
|
341
|
+
return ROOMS[CURRENTROOM]['directions'][move]
|
342
|
+
else:
|
343
|
+
type_text("You don't have enough money to charter a ship.", colorTrue=color_coding)
|
344
|
+
return CURRENTROOM
|
345
|
+
|
346
|
+
def attempt_move_to_garden():
|
347
|
+
if 'key' in player.inventory:
|
348
|
+
End('You unlock the gate to the garden with the key!')
|
349
|
+
return newRoom
|
350
|
+
else:
|
351
|
+
type_text('The gate is locked.', colorTrue=color_coding)
|
352
|
+
return newRoom
|
353
|
+
|
354
|
+
def move_to_room():
|
355
|
+
global LAST_ROOM
|
356
|
+
LAST_ROOM = CURRENTROOM
|
357
|
+
if move == '0':
|
358
|
+
return attempt_charter()
|
359
|
+
elif newRoom == 'Garden':
|
360
|
+
if 'descovered' in ROOMS[newRoom] and not ROOMS[newRoom]['descovered']:
|
361
|
+
ROOMS[newRoom]['descovered'] = True
|
362
|
+
return attempt_move_to_garden()
|
363
|
+
else:
|
364
|
+
if 'descovered' in ROOMS[newRoom] and not ROOMS[newRoom]['descovered']:
|
365
|
+
ROOMS[newRoom]['descovered'] = True
|
366
|
+
return newRoom
|
367
|
+
|
368
|
+
if move in ROOMS[CURRENTROOM]['directions']:
|
369
|
+
newRoom = ROOMS[CURRENTROOM]['directions'][move]
|
370
|
+
CURRENTROOM = move_to_room()
|
371
|
+
return
|
372
|
+
elif move in ROOMS:
|
373
|
+
newRoom = move
|
374
|
+
if newRoom == 'Garden':
|
375
|
+
CURRENTROOM = attempt_move_to_garden()
|
376
|
+
else:
|
377
|
+
CURRENTROOM = newRoom
|
378
|
+
LAST_ROOM = CURRENTROOM
|
379
|
+
return
|
380
|
+
type_text("You can't go that way!", colorTrue=color_coding)
|
381
|
+
|
382
|
+
|
383
|
+
def start():
|
384
|
+
# type_text a main men, colorTrue=color_codingu
|
385
|
+
type_text(f'\nHello %*MAGENTA*%{player.name}%*RESET*% and welcome to my Role Playing Game. \nI hope you have fun!', colorTrue=color_coding)
|
386
|
+
showInstructions()
|
387
|
+
|
388
|
+
|
389
|
+
def showStatus():
|
390
|
+
|
391
|
+
# Display player's current status
|
392
|
+
text = f'\n---------------------------'
|
393
|
+
|
394
|
+
# Display the current inventory
|
395
|
+
the_inventory = [itemnum.name for itemnum in player.inventory if isinstance(itemnum, item)]
|
396
|
+
text += f'\nInventory: %*BLUE*%{", ".join(the_inventory)}%*RESET*%; Money: {player.money}; XP: {player.xp}; Level: {player.Level}'
|
397
|
+
|
398
|
+
# Display possible directions of travel
|
399
|
+
text = display_directions(text)
|
400
|
+
|
401
|
+
# Display the map if available
|
402
|
+
if 'map' in ROOMS[CURRENTROOM]:
|
403
|
+
text += f'\n\nKey: {"; ".join(KEY)}\n'
|
404
|
+
text += f'\n{ROOMS[CURRENTROOM]["map"]}\n'
|
405
|
+
|
406
|
+
# Display the description of the current room
|
407
|
+
text += ('\n' + str(ROOMS[CURRENTROOM]['info']))
|
408
|
+
|
409
|
+
text += f"\n---------------------------"
|
410
|
+
|
411
|
+
type_text(text, colorTrue=color_coding)
|
412
|
+
|
413
|
+
# Optionally display additional room description
|
414
|
+
if 'description' in ROOMS[CURRENTROOM] and ask_for_consent("Do you want to observe the area"):
|
415
|
+
type_text("The area:", colorTrue=color_coding)
|
416
|
+
type_text(ROOMS[CURRENTROOM]['description'], colorTrue=color_coding)
|
417
|
+
|
418
|
+
|
419
|
+
def display_directions(text):
|
420
|
+
directions = ['north', 'east', 'south', 'west', 'up', 'down', 'teleport']
|
421
|
+
direction_descriptions = {
|
422
|
+
'house': {
|
423
|
+
'north': "There is a door to the",
|
424
|
+
'east': "There is a door to the",
|
425
|
+
'south': "There is a door to the",
|
426
|
+
'west': "There is a door to the",
|
427
|
+
'up': "There is a staircase leading",
|
428
|
+
'down': "There is a staircase leading"
|
429
|
+
},
|
430
|
+
'forest': {
|
431
|
+
'north': "There is a path to the",
|
432
|
+
'east': "There is a path to the",
|
433
|
+
'south': "There is a path to the",
|
434
|
+
'west': "There is a path to the",
|
435
|
+
'up': "There is a ladder going",
|
436
|
+
'down': "There is a holl in the ground leading"
|
437
|
+
}
|
438
|
+
}
|
439
|
+
|
440
|
+
room_type = ROOMS[CURRENTROOM]['room type']
|
441
|
+
if room_type in direction_descriptions:
|
442
|
+
for direction in directions:
|
443
|
+
if direction in ROOMS[CURRENTROOM]['directions']:
|
444
|
+
if direction != 'teleport':
|
445
|
+
text += f'\n{direction_descriptions[room_type][direction]} %*GREEN*%{direction}%*RESET*%.'
|
446
|
+
|
447
|
+
if 'teleport' in ROOMS[CURRENTROOM]['directions']:
|
448
|
+
text += "\nThere is a %*GREEN*%teleport%*RESET*%ation circle on the ground"
|
449
|
+
|
450
|
+
return text
|
451
|
+
|
452
|
+
def battle(player: PC, monster: creature, last_room):
|
453
|
+
"""
|
454
|
+
Simulate a battle between the player and a monster.
|
455
|
+
|
456
|
+
Args:
|
457
|
+
player (PC): The player character.
|
458
|
+
monster (creature): The monster to battle.
|
459
|
+
last_room: The previous room before the battle.
|
460
|
+
|
461
|
+
Returns:
|
462
|
+
The monster if it is still alive, None otherwise.
|
463
|
+
"""
|
464
|
+
while player.hp > 0 and monster.hp > 0:
|
465
|
+
if ask_for_consent("Do you want to run away"):
|
466
|
+
Move(last_room)
|
467
|
+
return monster
|
468
|
+
|
469
|
+
player_turn(player, monster)
|
470
|
+
|
471
|
+
if monster.hp <= 0:
|
472
|
+
handle_victory(player, monster)
|
473
|
+
return None
|
474
|
+
|
475
|
+
monster_turn(player, monster)
|
476
|
+
|
477
|
+
if player.hp <= 0:
|
478
|
+
End(f'The %*CYAN*%{monster.name}%*RESET*% defeats you!', win=False)
|
479
|
+
return monster
|
480
|
+
|
481
|
+
return monster
|
482
|
+
|
483
|
+
def player_turn(player: PC, monster: creature):
|
484
|
+
"""
|
485
|
+
Handle the player's turn during the battle.
|
486
|
+
|
487
|
+
Args:
|
488
|
+
player (PC): The player character.
|
489
|
+
monster (creature): The monster to battle.
|
490
|
+
"""
|
491
|
+
player_action = loop_til_valid_input(
|
492
|
+
"Choose your action: (attack/defend/special): ",
|
493
|
+
"Invalid action. Please enter a valid action.",
|
494
|
+
PC_action
|
495
|
+
).value.lower()
|
496
|
+
|
497
|
+
if player_action == "attack":
|
498
|
+
perform_attack(player, monster)
|
499
|
+
elif player_action == "defend":
|
500
|
+
player.defending = True
|
501
|
+
type_text("You brace yourself for the next attack.", colorTrue=color_coding)
|
502
|
+
elif player_action == "special":
|
503
|
+
use_special_ability(player, monster)
|
504
|
+
|
505
|
+
def monster_turn(player: PC, monster: creature):
|
506
|
+
"""
|
507
|
+
Handle the monster's turn during the battle.
|
508
|
+
|
509
|
+
Args:
|
510
|
+
player (PC): The player character.
|
511
|
+
monster (creature): The monster to battle.
|
512
|
+
"""
|
513
|
+
type_text(f"The %*CYAN*%{monster.name}%*RESET*% attacks!", colorTrue=color_coding)
|
514
|
+
damage = calculate_damage(monster, player)
|
515
|
+
|
516
|
+
player.take_damage(damage)
|
517
|
+
|
518
|
+
def perform_attack(attacker: PC, defender: creature):
|
519
|
+
"""
|
520
|
+
Perform an attack action.
|
521
|
+
|
522
|
+
Args:
|
523
|
+
attacker (PC): The attacking character.
|
524
|
+
defender (creature): The defending monster.
|
525
|
+
"""
|
526
|
+
damage = calculate_damage(attacker, defender)
|
527
|
+
defender.take_damage(damage)
|
528
|
+
|
529
|
+
def handle_victory(player: PC, monster: creature):
|
530
|
+
"""
|
531
|
+
Handle the logic when the player defeats the monster.
|
532
|
+
|
533
|
+
Args:
|
534
|
+
player (PC): The player character.
|
535
|
+
monster (creature): The defeated monster.
|
536
|
+
"""
|
537
|
+
type_text(f"You defeat the %*CYAN*%{monster.name}%*RESET*%!", colorTrue=color_coding)
|
538
|
+
player.inventory_add(monster.dropped_items)
|
539
|
+
|
540
|
+
def calculate_damage(attacker, defender) -> int:
|
541
|
+
"""
|
542
|
+
Calculate the damage inflicted by the attacker on the defender.
|
543
|
+
|
544
|
+
Args:
|
545
|
+
attacker: The attacking character.
|
546
|
+
defender: The defending character.
|
547
|
+
|
548
|
+
Returns:
|
549
|
+
int: The calculated damage.
|
550
|
+
"""
|
551
|
+
damage_min, damage_max = calculate_damage_range(attacker.atpw)
|
552
|
+
damage = randint(damage_min, damage_max)
|
553
|
+
|
554
|
+
if random() < attacker.crit_chance:
|
555
|
+
damage *= 2
|
556
|
+
type_text("Critical hit!", colorTrue=color_coding)
|
557
|
+
|
558
|
+
if hasattr(defender, 'defending') and defender.defending:
|
559
|
+
damage //= 2
|
560
|
+
type_text("The attack is defended, reducing damage.", colorTrue=color_coding)
|
561
|
+
defender.defending = False
|
562
|
+
|
563
|
+
return damage
|
564
|
+
|
565
|
+
def calculate_damage_range(atpw: int) -> tuple[int, int]:
|
566
|
+
"""
|
567
|
+
Calculate the damage range based on attack power.
|
568
|
+
|
569
|
+
Args:
|
570
|
+
atpw (int): Attack power of the combatant.
|
571
|
+
|
572
|
+
Returns:
|
573
|
+
Tuple[int, int]: Minimum and maximum damage range.
|
574
|
+
"""
|
575
|
+
damage_max_range = randint(1, 3)
|
576
|
+
damage_min_range = randint(1, 3)
|
577
|
+
damage_min = max(1, atpw - damage_min_range) # Ensure minimum damage is at least 1
|
578
|
+
damage_max = atpw + damage_max_range
|
579
|
+
return damage_min, damage_max
|
580
|
+
|
581
|
+
def use_special_ability(player: PC, monster: creature):
|
582
|
+
"""
|
583
|
+
Allow the player to use a special ability during combat.
|
584
|
+
|
585
|
+
Args:
|
586
|
+
player (PC): The player character.
|
587
|
+
monster (creature): The monster being fought.
|
588
|
+
"""
|
589
|
+
if player.special_ability.ready:
|
590
|
+
player.special_ability.activate(monster)
|
591
|
+
type_text(f"You use your special ability: {player.special_ability.name}.", colorTrue=color_coding)
|
592
|
+
player.special_ability.ready = False
|
593
|
+
else:
|
594
|
+
type_text("Your special ability is not ready yet.", colorTrue=color_coding)
|
595
|
+
|
596
|
+
|
597
|
+
def command():
|
598
|
+
try:
|
599
|
+
ShouldBreak = False
|
600
|
+
|
601
|
+
while True:
|
602
|
+
showStatus()
|
603
|
+
user_input = get_player_input(False)
|
604
|
+
|
605
|
+
if user_input:
|
606
|
+
commands_list = user_input.split(',')
|
607
|
+
for command_str in commands_list:
|
608
|
+
action, targets = parse_command(command_str.strip(), commands)
|
609
|
+
|
610
|
+
if action in commands:
|
611
|
+
if has_named_arg(commands[action], 'player'):
|
612
|
+
if targets:
|
613
|
+
commands[action](player, *targets)
|
614
|
+
else:
|
615
|
+
commands[action](player)
|
616
|
+
elif targets:
|
617
|
+
commands[action](*targets)
|
618
|
+
else:
|
619
|
+
commands[action]()
|
620
|
+
else:
|
621
|
+
type_text(f"Unknown command '{action}'. Type 'help' for a list of commands.", colorTrue=color_coding)
|
622
|
+
if action in commands:
|
623
|
+
ShouldBreak = True
|
624
|
+
if ShouldBreak:
|
625
|
+
return
|
626
|
+
except KeyError as e:
|
627
|
+
type_text(f"KeyError: {e} - This might be due to an undefined command or incorrect arguments.", colorTrue=color_coding)
|
628
|
+
except ValueError as e:
|
629
|
+
type_text(f"ValueError: {e} - This might be due to incorrect arguments provided.", colorTrue=color_coding)
|
630
|
+
except Exception as e:
|
631
|
+
type_text(f"Unexpected Error: {e}", colorTrue=color_coding)
|
632
|
+
|
633
|
+
def handle_sleep_command(player: PC):
|
634
|
+
type_text("You decide to rest for a while.", colorTrue=color_coding)
|
635
|
+
|
636
|
+
# Simulate some time passing
|
637
|
+
sleep(2) # Example: sleep for 2 seconds
|
638
|
+
|
639
|
+
# Restore player's health or apply any other effects
|
640
|
+
player.heal(3) # Example: heal 5 health points during sleep
|
641
|
+
|
642
|
+
# Optional: Print a message or effect that happens during sleep
|
643
|
+
type_text("You feel refreshed after a good rest.", colorTrue=color_coding)
|
644
|
+
|
645
|
+
def get_player_input(split = True):
|
646
|
+
move = ''
|
647
|
+
while move == '':
|
648
|
+
move = str(input('>')).strip().lower()
|
649
|
+
if split:
|
650
|
+
return move.split()
|
651
|
+
return move
|
652
|
+
|
653
|
+
def handle_go_command(direction):
|
654
|
+
Move(direction)
|
655
|
+
|
656
|
+
def handle_get_command(player: PC, item_name):
|
657
|
+
if "item" in ROOMS[CURRENTROOM] and item_name == ROOMS[CURRENTROOM]['item'].name:
|
658
|
+
player.inventory_add([ROOMS[CURRENTROOM]['item']])
|
659
|
+
del ROOMS[CURRENTROOM]['item']
|
660
|
+
type_text(f'%*BLUE*%{item_name}%*RESET*% got!', colorTrue=color_coding)
|
661
|
+
else:
|
662
|
+
type_text(f"Can't get {item_name}!", colorTrue=color_coding)
|
663
|
+
|
664
|
+
def handle_look_command():
|
665
|
+
return_ = False
|
666
|
+
if 'item' in ROOMS[CURRENTROOM]:
|
667
|
+
type_text(f'The item in the room: %*BLUE*%{ROOMS[CURRENTROOM]["item"].name}%*RESET*%.', colorTrue=color_coding)
|
668
|
+
return_ = True
|
669
|
+
if 'containers' in ROOMS[CURRENTROOM]:
|
670
|
+
type_text(f"The containers here are: %*RED*%{', '.join(ROOMS[CURRENTROOM]['containers'].keys())}%*RESET*%", colorTrue=color_coding)
|
671
|
+
return_ = True
|
672
|
+
if return_:
|
673
|
+
return
|
674
|
+
type_text('There is nothing of interest.', colorTrue=color_coding)
|
675
|
+
|
676
|
+
def handle_use_command(item = None, sub_item = None):
|
677
|
+
Use(item, sub_item)
|
678
|
+
|
679
|
+
def handle_search_command(player, container = None, sub_container = None):
|
680
|
+
if 'containers' in ROOMS[CURRENTROOM]:
|
681
|
+
if container == 'the' and sub_container in ROOMS[CURRENTROOM]['containers'] and not all_same_value(ROOMS[CURRENTROOM]['containers'][sub_container].contents, None):
|
682
|
+
search_container(player, sub_container)
|
683
|
+
elif container in ROOMS[CURRENTROOM]['containers'] and not all_same_value(ROOMS[CURRENTROOM]['containers'][container].contents, None):
|
684
|
+
search_container(player, container)
|
685
|
+
else:
|
686
|
+
type_text(f"You cannot search the {container}", colorTrue=color_coding)
|
687
|
+
|
688
|
+
def search_container(player: PC, container):
|
689
|
+
player.inventory_add(ROOMS[CURRENTROOM]['containers'][container].contents)
|
690
|
+
type_text(f"You search the{' secret' if ROOMS[CURRENTROOM]['containers'][container].secret else ''} %*RED*%{container}%*RESET*% and find a ", newline=False, colorTrue=color_coding)
|
691
|
+
for searchitem in ROOMS[CURRENTROOM]['containers'][container].contents:
|
692
|
+
if searchitem:
|
693
|
+
if isinstance(searchitem, item):
|
694
|
+
end_str = ' and a ' if ROOMS[CURRENTROOM]['containers'][container].contents.index(searchitem) < last_index(ROOMS[CURRENTROOM]['containers'][container].contents) else '\n'
|
695
|
+
type_text(f"%*BLUE*%{searchitem.name}%*RESET*%{end_str}", newline=False, colorTrue=color_coding)
|
696
|
+
ROOMS[CURRENTROOM]['containers'][container].contents = []
|
697
|
+
|
698
|
+
|
699
|
+
def handle_put_command(player: PC, PutItem: item = None, container = None, sub_container = None):
|
700
|
+
if PutItem in player.inventory:
|
701
|
+
if 'containers' in ROOMS[CURRENTROOM]:
|
702
|
+
if container == 'the' and sub_container in ROOMS[CURRENTROOM]['containers']:
|
703
|
+
put_in_container(player, player.inventory[player.inventory.index(PutItem)], sub_container)
|
704
|
+
return
|
705
|
+
elif container in ROOMS[CURRENTROOM]['containers']:
|
706
|
+
put_in_container(player, player.inventory[player.inventory.index(PutItem)], container)
|
707
|
+
return
|
708
|
+
type_text(f"You cannot put the {PutItem.name} in the {container}", colorTrue=color_coding)
|
709
|
+
|
710
|
+
|
711
|
+
def put_in_container(player: PC, PutItem = None, container = None):
|
712
|
+
player.inventory.remove(PutItem.name)
|
713
|
+
if not ROOMS[CURRENTROOM]['containers'][container].contents:
|
714
|
+
ROOMS[CURRENTROOM][container].contents = []
|
715
|
+
if not isinstance(ROOMS[CURRENTROOM][container].contents, list):
|
716
|
+
ROOMS[CURRENTROOM]['containers'][container].contents = [ROOMS[CURRENTROOM]['containers'][container].contents]
|
717
|
+
ROOMS[CURRENTROOM]['containers'][container].contents += [PutItem]
|
718
|
+
type_text(f"You put you're %*BLUE*%{PutItem.name}%*RESET*% into the %*RED*%{container}%*RESET*%", colorTrue=color_coding)
|
719
|
+
|
720
|
+
|
721
|
+
|
722
|
+
def handle_get_quest_command(questnum):
|
723
|
+
if 'quests' in ROOMS[CURRENTROOM]:
|
724
|
+
if questnum in ROOMS[CURRENTROOM]['quests']:
|
725
|
+
quest_manager.add_quest(ROOMS[CURRENTROOM]['quests'][questnum])
|
726
|
+
quest_manager.start_quest(ROOMS[CURRENTROOM]['quests'][questnum])
|
727
|
+
del ROOMS[CURRENTROOM]['quests'][questnum]
|
728
|
+
|
729
|
+
|
730
|
+
def PrintMap():
|
731
|
+
type_text(ShowMap())
|
732
|
+
|
733
|
+
|
734
|
+
# Define handling functions for different types of enemies
|
735
|
+
def handle_hungry_bear(player: PC, enemy: creature):
|
736
|
+
enemy_reacting = True
|
737
|
+
if 'potion' in player.inventory:
|
738
|
+
if ask_for_consent("Do you want to throw your potion at the bear"):
|
739
|
+
enemy_reacting = False
|
740
|
+
del player.inventory[player.inventory.index('potion')]
|
741
|
+
type_text(f'You throw the potion at the bear and it explodes into a puff of magic smoke that stuns the bear!', colorTrue=color_coding)
|
742
|
+
if enemy_reacting:
|
743
|
+
return battle(player, enemy, LAST_ROOM)
|
744
|
+
|
745
|
+
def handle_grumpy_pig(player: PC, enemy: creature):
|
746
|
+
enemy_reacting = True
|
747
|
+
if 'saddle' in player.inventory and 'pig-rod' in player.inventory:
|
748
|
+
if ask_for_consent("Do you want to use your saddle and pig-rod on the pig"):
|
749
|
+
enemy_reacting = False
|
750
|
+
type_text(f'You throw a saddle onto the pig and leap on steering it about with a pig fishing rod!', colorTrue=color_coding)
|
751
|
+
del ROOMS[CURRENTROOM]['creatures stats']
|
752
|
+
del player.inventory[player.inventory.index('saddle')]
|
753
|
+
del player.inventory[player.inventory.index('pig-rod')]
|
754
|
+
player.inventory_add(item['pig-steed'])
|
755
|
+
player.xp += 20
|
756
|
+
if 'torch' in player.inventory:
|
757
|
+
if ask_for_consent("Do you want to use your torch to scare the pig away"):
|
758
|
+
enemy_reacting = False
|
759
|
+
type_text(f'You wave your torch at the pig and it runs away through a tiny open window.', colorTrue=color_coding)
|
760
|
+
del ROOMS[CURRENTROOM]['creatures stats']
|
761
|
+
player.xp += 5
|
762
|
+
if 'ration' in player.inventory:
|
763
|
+
if ask_for_consent("Do you want to throw your ration at the pig"):
|
764
|
+
enemy_reacting = False
|
765
|
+
type_text(f"You quickly throw rations at the pig. It still doesn't look happy though.", colorTrue=color_coding)
|
766
|
+
del player.inventory[player.inventory.index('ration')]
|
767
|
+
player.xp += 15
|
768
|
+
|
769
|
+
if enemy_reacting:
|
770
|
+
return battle(player, enemy, LAST_ROOM)
|
771
|
+
|
772
|
+
def handle_greedy_goblin(player: PC, enemy: creature):
|
773
|
+
enemy_reacting = True
|
774
|
+
if player.money >= 15:
|
775
|
+
if ask_for_consent("Do you want to pay the goblin to not attack you"):
|
776
|
+
enemy_reacting = False
|
777
|
+
type_text(f"You pay the {enemy.name} to not attack you for now, but he says you should run.", colorTrue=color_coding)
|
778
|
+
player.money -= 15
|
779
|
+
enemy.dropped_items[1].value += 15
|
780
|
+
if enemy_reacting:
|
781
|
+
return battle(player, enemy, LAST_ROOM)
|
782
|
+
|
783
|
+
commands = {
|
784
|
+
'go': handle_go_command,
|
785
|
+
'get quest': handle_get_quest_command,
|
786
|
+
'get': handle_get_command,
|
787
|
+
'look': handle_look_command,
|
788
|
+
'use': handle_use_command,
|
789
|
+
'search': handle_search_command,
|
790
|
+
'quit': quit,
|
791
|
+
'help': showInstructions,
|
792
|
+
'hint': showHint,
|
793
|
+
'sleep': handle_sleep_command,
|
794
|
+
'put': handle_put_command,
|
795
|
+
'map': PrintMap,
|
796
|
+
}
|
797
|
+
|
798
|
+
|
799
|
+
def quit():
|
800
|
+
exit()
|
801
|
+
|
802
|
+
guards = [
|
803
|
+
Guard(
|
804
|
+
name="Guard",
|
805
|
+
hp=10,
|
806
|
+
atpw=4,
|
807
|
+
description="A 5ft 8 human guard who looks like he doesn't belong here",
|
808
|
+
flavor_text="A human guard spots you and says: 'You shouldn't be here'",
|
809
|
+
type = creature_type('humanoid', 'human'),
|
810
|
+
current_room="Bedroom",
|
811
|
+
patrol_route=["Bedroom", "Office", "Tower Bottom", "Landing", "Bedroom"],
|
812
|
+
patrol_type='random'
|
813
|
+
),
|
814
|
+
]
|
815
|
+
|
816
|
+
def main():
|
817
|
+
|
818
|
+
# shows the instructions
|
819
|
+
start()
|
820
|
+
|
821
|
+
# loop forever while the player wants to play
|
822
|
+
while True:
|
823
|
+
command()
|
824
|
+
|
825
|
+
# Move guards
|
826
|
+
for guard in guards:
|
827
|
+
if isinstance(guard, Guard):
|
828
|
+
guard.move(ROOMS)
|
829
|
+
|
830
|
+
# Check for detection
|
831
|
+
for guard in guards:
|
832
|
+
if isinstance(guard, Guard):
|
833
|
+
if guard.check_detection(CURRENTROOM):
|
834
|
+
guard.type_text_flavor_text()
|
835
|
+
guards[guards.index(guard)] = battle(player, guard, LAST_ROOM)
|
836
|
+
|
837
|
+
# player loses if they enter a room with a monster, unless they can fight it.
|
838
|
+
if 'creatures stats' in ROOMS[CURRENTROOM]:
|
839
|
+
enemies = ROOMS[CURRENTROOM]['creatures stats']
|
840
|
+
if not isinstance(enemies, list):
|
841
|
+
enemies = [enemies] # Ensure enemies is a list even if there's only one creature
|
842
|
+
|
843
|
+
|
844
|
+
for enemy in enemies:
|
845
|
+
if isinstance(enemy, creature):
|
846
|
+
enemy.type_text_flavor_text()
|
847
|
+
|
848
|
+
if enemy.name == 'hungry bear':
|
849
|
+
enemy_REF = handle_hungry_bear(player, enemy)
|
850
|
+
enemies[enemies.index(enemy)] = enemy_REF
|
851
|
+
elif enemy.name == 'grumpy pig':
|
852
|
+
enemy_REF = handle_grumpy_pig(player, enemy)
|
853
|
+
enemies[enemies.index(enemy)] = enemy_REF
|
854
|
+
elif enemy.name == 'greedy goblin':
|
855
|
+
enemy_REF = handle_greedy_goblin(player, enemy)
|
856
|
+
enemies[enemies.index(enemy)] = enemy_REF
|
857
|
+
else:
|
858
|
+
enemy_REF = battle(player, enemy, LAST_ROOM)
|
859
|
+
enemies[enemies.index(enemy)] = enemy_REF
|
860
|
+
|
861
|
+
if all_same_value(enemies, False):
|
862
|
+
del ROOMS[CURRENTROOM]['creatures stats']
|
863
|
+
else:
|
864
|
+
ROOMS[CURRENTROOM]['creatures stats'] = enemies
|
865
|
+
|
866
|
+
if 'NPCs' in ROOMS[CURRENTROOM]:
|
867
|
+
for npcname, npcstats in ROOMS[CURRENTROOM]['NPCs'].items():
|
868
|
+
if ask_for_consent("Do you want to interact with this NPC") or npcstats.aggressive:
|
869
|
+
npcstats.interact
|
870
|
+
if npcstats.aggressive:
|
871
|
+
ROOMS[CURRENTROOM]['NPCs'][npcname] = battle(player, npcstats)
|
872
|
+
|
873
|
+
player.special_ability.Tick()
|
874
|
+
quest_manager.update_objective(f"Kill {GameState['Enemys killed']} creatures")
|
875
|
+
for ___ in GameState['collected items']:
|
876
|
+
if isinstance(___, item):
|
877
|
+
quest_manager.update_objective(f"Colect {___.name}")
|
878
|
+
|
879
|
+
|
880
|
+
|
881
|
+
|
882
|
+
|
883
|
+
if __name__ == "__main__":
|
884
|
+
main()
|