neelthee-mansion 3.20.21__py3-none-any.whl → 3.21.2__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.
@@ -1,1345 +0,0 @@
1
- from .Rooms import *
2
- from .creatures import *
3
- from .items import *
4
- from .Quests import *
5
- from .all_game_utils import *
6
-
7
-
8
- GameState = {
9
- "Enemies killed": 0,
10
- "collected items": [],
11
- }
12
-
13
-
14
- """
15
- Neel-thee's Mansion of Amnesia
16
- """
17
-
18
- global player, evil_mage, commands, NOTE_NUM, credits, color_coding, quest_manager, revealer, CHARACTERSLIST, BACKGROUNDS
19
-
20
- BACKGROUNDS = {
21
- "Adventurer": ["survival", "climbing"],
22
- "Artist": ["painting", "sculpting"],
23
- "Scholar": ["reading", "research"],
24
- }
25
-
26
- revealer = KeyRevealer()
27
-
28
- quest_manager = QuestManager()
29
-
30
- color_coding = False
31
-
32
- credits = """
33
- Made by: Alexander.E.F
34
- AI assisted the creation"""
35
-
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
- {"name": "Josh", "age": 26, "height": Height("5ft 6"), "weight(LBs)": 135},
81
- {"name": "Luka", "age": 29, "height": Height("5ft 7"), "weight(LBs)": 140},
82
- ]
83
-
84
-
85
- evil_mage = PC(
86
- "Neel-thee Contozt",
87
- 19836,
88
- "Mage",
89
- 29,
90
- "Evil prince",
91
- Height("5ft 7.375"),
92
- 222,
93
- xp=99180,
94
- )
95
-
96
-
97
- # Function to parse command
98
- def parse_command(command_str: str, commands: dict):
99
- global player
100
- # Split the command string into parts
101
- parts = command_str.split()
102
-
103
- # Check for multi-word commands
104
- for cmd in commands.keys():
105
- cmd_parts = cmd.split()
106
- if len(cmd_parts) > 1 and parts[: len(cmd_parts)] == cmd_parts:
107
- action = " ".join(cmd_parts)
108
- targets = parts[len(cmd_parts) :]
109
- return action, targets
110
-
111
- # Default single word command
112
- action = parts[0]
113
- targets = parts[1:] if len(parts) > 1 else []
114
- return action, targets
115
-
116
-
117
- def showInstructions():
118
- global player
119
- # Display the game instructions
120
- type_text(
121
- """
122
- ===========================
123
- Commands:
124
- go [%*GREEN*%direction%*RESET*%/%*GREEN*%teleport%*RESET*%/%*GREEN*%number%*RESET*%] - Move to another location
125
- get [%*BLUE*%item%*RESET*%] - Pick up an item from your current location
126
- search [%*RED*%container%*RESET*%] - Search a container in your current location
127
- use [%*BLUE*%item%*RESET*%] - Use an item from your inventory
128
- put [%*BLUE*%item%*RESET*%] [in] [%*RED*%container%*RESET*%] - Put an item from your inventory into a container in your current location
129
- examine [%*GREEN*%direction%*RESET*%/%*RED*%container%*RESET*%/%*BLUE*%item%*RESET*%] - Find out some info about the object
130
- sleep - Rest for a bit and regain some health
131
- look - Look around your current location
132
- quit - Quit the game
133
- help - Show these instructions
134
- hint - Get a random hint for your current location
135
- map - Display the map of places you have been to
136
- """,
137
- colorTrue=color_coding,
138
- )
139
-
140
-
141
- def showHint():
142
- global player
143
- if "Hints" in ROOMS[player.CURRENTROOM]:
144
- type_text("You think:", colorTrue=color_coding)
145
- hint = choice(ROOMS[player.CURRENTROOM]["Hints"])
146
- type_text(hint, colorTrue=color_coding)
147
- else:
148
- type_text("You can't think of anything", colorTrue=color_coding)
149
-
150
-
151
- def check_direction(var: str, directions: list):
152
- global player
153
- for direction in directions:
154
- if var == direction:
155
- return True
156
- return False
157
-
158
-
159
- def End(text: str, win: bool = True):
160
- global player
161
- type_text(text, colorTrue=color_coding)
162
- if win:
163
- type_text("Do you want to leave the game? Y/N", colorTrue=color_coding)
164
- while True:
165
- leave = input(">").lower()
166
- if leave == "n":
167
- type_text("You decide to continue exploring.", colorTrue=color_coding)
168
- break
169
- elif leave == "y":
170
- type_text(
171
- "You escaped the house... %*BOLD*%GAME OVER, YOU WIN!",
172
- colorTrue=color_coding,
173
- )
174
- commands["quit"]()
175
- else:
176
- type_text(
177
- "Sorry, that wasn't 'y' or 'n'. Please enter 'y' or 'n'.",
178
- colorTrue=color_coding,
179
- )
180
- else:
181
- type_text("%*BOLD*%GAME OVER, YOU LOSE!", colorTrue=color_coding)
182
- commands["quit"]()
183
-
184
-
185
- NOTE_NUM = 0
186
-
187
-
188
- def add_note(note, parchment_index=None):
189
- global player, NOTE_NUM
190
- player.NOTES.append(note)
191
- NOTE_NUM += 1
192
- inv_note = "note " + str(NOTE_NUM)
193
- try:
194
- del player.inventory[parchment_index]
195
- except IndexError:
196
- pass
197
- player.inventory_add([item(inv_note)])
198
-
199
-
200
- def Use_grappling_hook():
201
- global player
202
-
203
- def swing_into_forest():
204
- global player
205
- type_text(
206
- "You throw your grappling-hook, it catches a branch of a nearby tree and hooks back onto itself. \nYou can swing into the forest!",
207
- colorTrue=color_coding,
208
- )
209
- if ask_for_consent("Do you want to swing into the forest"):
210
- type_text("You swing into the forest", colorTrue=color_coding)
211
- Move("Forest Clearing")
212
- else:
213
- type_text(
214
- "You flick the rope and it unhooks. You continue exploring the house.",
215
- colorTrue=color_coding,
216
- )
217
-
218
- def climb_into_house():
219
- global player
220
- type_text(
221
- "You throw your grappling-hook, it catches the railing of the nearby house and hooks back onto itself. \nYou can climb into the house!",
222
- colorTrue=color_coding,
223
- )
224
- if ask_for_consent("Do you want to climb into the house"):
225
- type_text("You climb into the house", colorTrue=color_coding)
226
- Move("Balcony")
227
- else:
228
- type_text(
229
- "You flick the rope and it unhooks. You continue exploring the forest",
230
- colorTrue=color_coding,
231
- )
232
-
233
- if player.CURRENTROOM == "Balcony" and "grappling-hook" in player.inventory:
234
- swing_into_forest()
235
- elif (
236
- player.CURRENTROOM == "Forest Clearing" and "grappling-hook" in player.inventory
237
- ):
238
- climb_into_house()
239
-
240
-
241
- def Use_quill():
242
- global player
243
-
244
- if all(item in player.inventory for item in ["ink-pot", "parchment", "quill"]):
245
- parchment_index = player.inventory.index("parchment")
246
- type_text("What do you want to write", colorTrue=color_coding)
247
- write = str(input(">")).strip()
248
-
249
- if write:
250
- add_note(write, parchment_index)
251
- else:
252
- type_text("You can't write nothing", colorTrue=color_coding)
253
- else:
254
- type_text(
255
- "You need an ink pot, parchment, and a quill to write.",
256
- colorTrue=color_coding,
257
- )
258
-
259
-
260
- def Use_note(note_number):
261
- global player
262
- """Reads a specified note from the player's inventory."""
263
- note_key = f"note {note_number}"
264
- if note_key in player.inventory:
265
- note_index = int(note_number) - 1
266
- type_text(f"You read:", colorTrue=color_coding)
267
- type_text(player.NOTES[note_index], colorTrue=color_coding)
268
- else:
269
- type_text("You do not have that note", colorTrue=color_coding)
270
-
271
-
272
- def Use(*Args):
273
- global player
274
- if isinstance(Args[0], list) or isinstance(Args[0], tuple):
275
- Args = Args[0]
276
- Item = " ".join(Args)
277
- """Uses an item from the player's inventory."""
278
- if Item in player.inventory:
279
- item_obj = player.inventory[player.inventory.index(Item)]
280
- if isinstance(item_obj, item):
281
- if item_obj.sell(player):
282
- type_text(
283
- f"You sell the %*BLUE*%{Item}%*RESET*%", colorTrue=color_coding
284
- )
285
- player.inventory.remove(item_obj.name)
286
- elif Item == "quill":
287
- Use_quill()
288
- elif Item == "grappling-hook":
289
- Use_grappling_hook()
290
- elif len(Item) >= 2 and Item[0] == "note" and Item[1]:
291
- Use_note(Item[1])
292
- elif Item == "0":
293
- type_text("You can't use nothing", colorTrue=color_coding)
294
- else:
295
- type_text("You can't use that", colorTrue=color_coding)
296
-
297
-
298
- def PickKey(locked_obj):
299
- keys = player.inventory.keys()
300
- if not isinstance(keys, list):
301
- keys = [keys]
302
-
303
- if keys:
304
- while True:
305
- type_text(
306
- f"Please pick which key you want to use in the lock. This is what you know about the lock: {locked_obj}. These are your keys:"
307
- )
308
-
309
- # Enumerate keys and display them
310
- for idx, key in enumerate(keys, 1): # Starts numbering at 1
311
- type_text(f"{idx}. {key.name} - {key.CurentRevealStr}")
312
-
313
- # Use loop_til_valid_input to get a valid integer within the correct range
314
- choice = loop_til_valid_input(
315
- input_text="Enter the number of the key you'd like to use: ",
316
- bad_text="That's not a valid choice, please try again.",
317
- Class=int, # Ensuring input is an integer
318
- )
319
-
320
- # Since loop_til_valid_input ensures valid input, just return the selected key
321
- if 1 <= choice <= len(keys):
322
- return keys[choice - 1] # Fetch the key using 0-based index
323
-
324
- return Key(KeyCode=None)
325
-
326
-
327
- def Move(move):
328
- global player
329
-
330
- def attempt_charter():
331
- global player
332
- if player.money >= 10:
333
- player.money -= 10
334
- if "descovered" in ROOMS[newRoom] and not ROOMS[newRoom]["descovered"]:
335
- ROOMS[newRoom]["descovered"] = True
336
- return ROOMS[player.CURRENTROOM]["directions"][move]
337
- else:
338
- type_text(
339
- "You don't have enough money to charter a ship.", colorTrue=color_coding
340
- )
341
- return player.CURRENTROOM
342
-
343
- def attempt_move_to_garden():
344
- global player
345
- key = PickKey(Lock("629.IdnXwnt"))
346
- if key.GetKeyCode() == "629.IdnXwnt":
347
- End("You unlock the gate to the garden with the key!")
348
- return newRoom
349
- type_text("The gate is locked.", colorTrue=color_coding)
350
- return newRoom
351
-
352
- def move_to_room():
353
- global player
354
- player.LASTROOM = player.CURRENTROOM
355
- if "descovered" in ROOMS[newRoom] and not ROOMS[newRoom]["descovered"]:
356
- ROOMS[newRoom]["descovered"] = True
357
- if move == "0":
358
- return attempt_charter()
359
- elif newRoom == "Garden":
360
- return attempt_move_to_garden()
361
- else:
362
- return newRoom
363
-
364
- if move in ROOMS[player.CURRENTROOM]["directions"]:
365
- newRoom = "Hall"
366
- if isinstance(ROOMS[player.CURRENTROOM]["directions"][move], Door):
367
- if isinstance(ROOMS[player.CURRENTROOM]["directions"][move].lock, Lock):
368
- key = PickKey(ROOMS[player.CURRENTROOM]["directions"][move].lock)
369
- ROOMS[player.CURRENTROOM]["directions"][move].Unlock(key, player)
370
- newRoom = ROOMS[player.CURRENTROOM]["directions"][move].GetRoom(
371
- player.CURRENTROOM
372
- )
373
- else:
374
- newRoom = ROOMS[player.CURRENTROOM]["directions"][move]
375
- newRoom = move_to_room()
376
- player.CURRENTROOM = newRoom
377
- return
378
- elif move in ROOMS:
379
- newRoom = move
380
- if newRoom == "Garden":
381
- newRoom = attempt_move_to_garden()
382
- player.LASTROOM = player.CURRENTROOM
383
- player.CURRENTROOM = newRoom
384
- if "random_events" in ROOMS[player.CURRENTROOM]:
385
- for randomEvent in ROOMS[player.CURRENTROOM]["random_events"]:
386
- if isinstance(randomEvent, RandomEvent):
387
- randomEvent.check_and_trigger(player)
388
- return
389
- type_text(f"There is no exit {move}", colorTrue=color_coding)
390
-
391
-
392
- def start():
393
- global player
394
- # shows the main menu
395
- type_text(
396
- f"\nHello %*MAGENTA*%{player.name}%*RESET*% and welcome to my Role Playing Game. \nI hope you have fun!",
397
- colorTrue=color_coding,
398
- )
399
- showInstructions()
400
-
401
-
402
- def showStatus():
403
- global player
404
-
405
- # Display player's current status
406
- text = f"\n---------------------------"
407
-
408
- # Display the current inventory
409
- the_inventory = [
410
- itemnum.name for itemnum in player.inventory if isinstance(itemnum, item)
411
- ]
412
- text += f'\nInventory: %*BLUE*%{", ".join(the_inventory)}%*RESET*%; Money: {player.money}; XP: {player.xp}; Level: {player.Level}'
413
-
414
- # Display possible directions of travel
415
- text = display_directions(text)
416
-
417
- # Display the map if available
418
- if "map" in ROOMS[player.CURRENTROOM]:
419
- text += f'\n\nKey: {"; ".join(KEY)}\n'
420
- text += f'\n{ROOMS[player.CURRENTROOM]["map"]}\n'
421
-
422
- # Display the description of the current room
423
- text += "\n" + str(ROOMS[player.CURRENTROOM]["info"])
424
-
425
- text += f"\n---------------------------"
426
-
427
- type_text(text, colorTrue=color_coding)
428
-
429
- # Optionally display additional room description
430
- if "description" in ROOMS[player.CURRENTROOM] and ask_for_consent(
431
- "Do you want to observe the area"
432
- ):
433
- type_text("The area:", colorTrue=color_coding)
434
- type_text(ROOMS[player.CURRENTROOM]["description"], colorTrue=color_coding)
435
-
436
-
437
- def display_directions(text):
438
- global player
439
- directions = ["north", "east", "south", "west", "up", "down", "teleport"]
440
- direction_descriptions = {
441
- "house": {
442
- "north": "There is a door to the",
443
- "east": "There is a door to the",
444
- "south": "There is a door to the",
445
- "west": "There is a door to the",
446
- "up": "There is a staircase leading",
447
- "down": "There is a staircase leading",
448
- },
449
- "forest": {
450
- "north": "There is a path to the",
451
- "east": "There is a path to the",
452
- "south": "There is a path to the",
453
- "west": "There is a path to the",
454
- "up": "There is a ladder going",
455
- "down": "There is a hole in the ground leading",
456
- },
457
- "cavern": {
458
- "north": "There is a tunel to the",
459
- "east": "There is a tunel to the",
460
- "south": "There is a tunel to the",
461
- "west": "There is a tunel to the",
462
- "up": "There is a shoot with handhold going",
463
- "down": "There is a shoot in the ground going",
464
- },
465
- }
466
-
467
- room_type = ROOMS[player.CURRENTROOM]["room type"]
468
- if room_type in direction_descriptions:
469
- for direction in directions:
470
- if direction in ROOMS[player.CURRENTROOM]["directions"]:
471
- if direction != "teleport":
472
- text += f"\n{direction_descriptions[room_type][direction]} %*GREEN*%{direction}%*RESET*%."
473
-
474
- if "teleport" in ROOMS[player.CURRENTROOM]["directions"]:
475
- text += "\nThere is a %*GREEN*%teleport%*RESET*%ation circle on the ground."
476
-
477
- return text
478
-
479
-
480
- def Examine(*Args):
481
- Name = " ".join(Args)
482
- item_index = player.inventory.index(Name) # Store the result of index in a variable
483
-
484
- if item_index is not None: # Check explicitly if item_index is valid
485
- _ = player.inventory[item_index]
486
- if isinstance(_, item):
487
- type_text("You look at your item and you figure out this about it:")
488
- if not revealer.reveal_key_code(_):
489
- if _.type == "weapon":
490
- type_text(f"This item is a weapon that adds {_.value} damage.")
491
- elif _.type == "readable":
492
- if "reading" in player.Skills:
493
- type_text(f"You read {_.name} and it contains:")
494
- if isinstance(_, Book):
495
- type_text(_.GetContense())
496
- else:
497
- type_text(_.value)
498
- elif Name in ROOMS[player.CURRENTROOM]["directions"]: # Check exits in the room
499
- door = ROOMS[player.CURRENTROOM]["directions"][Name]
500
- if isinstance(door, Door):
501
- if isinstance(door.lock, Lock):
502
- type_text(
503
- (
504
- "The door is locked,"
505
- if door.lock.is_locked
506
- else "The door is not locked,"
507
- ),
508
- "you know this about its key code:",
509
- )
510
- revealer.reveal_key_code(door)
511
- else:
512
- type_text(f"The exit {Name} has no lock.")
513
- else:
514
- type_text(f"There is nothing special about the exit {Name}.")
515
- elif (
516
- Name in ROOMS[player.CURRENTROOM]["containers"]
517
- ): # Check containers in the room
518
- containerins = ROOMS[player.CURRENTROOM]["containers"][Name]
519
- if isinstance(containerins, container):
520
- if isinstance(containerins.lock, Lock):
521
- type_text(
522
- (
523
- "The container is locked,"
524
- if containerins.lock.is_locked
525
- else "The container is not locked,"
526
- ),
527
- "you know this about its key code:",
528
- )
529
- revealer.reveal_key_code(containerins)
530
- else:
531
- type_text(f"The container {Name} has no lock.")
532
- else:
533
- type_text(f"There is no container named {Name} in this room.")
534
- elif "creatures stats" in ROOMS[player.CURRENTROOM]:
535
- for Creature in ROOMS[player.CURRENTROOM]["creatures stats"]:
536
- if isinstance(Creature, creature):
537
- if isinstance(Creature, NPC):
538
- if Creature.name.lower() == Name:
539
- Creature.talk()
540
- return
541
- else:
542
- type_text(f"There is nothing special about the {Name}.")
543
-
544
-
545
- def battle(player: PC, good_guys: list, bad_guys: list, last_room):
546
- """
547
- Simulate a battle between the player (and allies) and monsters.
548
-
549
- Args:
550
- player (PC): The player character.
551
- good_guys (list): The list of allies to help the player.
552
- bad_guys (list): The list of monsters to battle the player.
553
- last_room: The previous room before the battle.
554
-
555
- Returns:
556
- None if all bad guys are defeated, else the remaining bad guys.
557
- """
558
- while player.hp > 0:
559
- if all(monster.hp <= 0 for monster in bad_guys):
560
- handle_victory(player, bad_guys)
561
- return good_guys, None
562
-
563
- if ask_for_consent("Do you want to run away"):
564
- Move(last_room)
565
- return good_guys, bad_guys
566
-
567
- # Player and good guys' turn
568
- for ally in [player] + good_guys:
569
- if all(monster.hp <= 0 for monster in bad_guys):
570
- handle_victory(player, bad_guys)
571
- return good_guys, None
572
-
573
- target = select_target(ally, bad_guys)
574
- player_turn(ally, target)
575
-
576
- # Bad guys' turn
577
- for monster in bad_guys:
578
- if monster.hp > 0:
579
- target = select_target(monster, [player] + good_guys)
580
- monster_turn(target, monster)
581
-
582
- if player.hp <= 0:
583
- End(f"The monsters defeat you!", win=False)
584
- return good_guys, bad_guys
585
-
586
- return good_guys, bad_guys
587
-
588
-
589
- def player_turn(player: PC, monster: creature):
590
- """
591
- Handle a character's turn during the battle.
592
-
593
- Args:
594
- player (PC): The player or ally.
595
- monster (creature): The monster being fought.
596
- """
597
- player_action = loop_til_valid_input(
598
- "Choose your action: (attack/defend/special): ",
599
- "Invalid action. Please enter a valid action.",
600
- PC_action,
601
- ).value.lower()
602
-
603
- if player_action == "attack":
604
- perform_attack(player, monster)
605
- elif player_action == "defend":
606
- player.defending = True
607
- type_text("You brace yourself for the next attack.", colorTrue=color_coding)
608
- elif player_action == "special":
609
- use_special_ability(player, monster)
610
-
611
-
612
- def monster_turn(player: PC, monster: creature):
613
- """
614
- Handle a monster's turn during the battle.
615
-
616
- Args:
617
- player (PC): The player or ally.
618
- monster (creature): The monster attacking.
619
- """
620
- type_text(f"The %*CYAN*%{monster.name}%*RESET*% attacks!", colorTrue=color_coding)
621
- damage = calculate_damage(monster, player)
622
- player.take_damage(damage)
623
-
624
-
625
- def perform_attack(attacker: PC, defender: creature):
626
- """
627
- Perform an attack action.
628
-
629
- Args:
630
- attacker (PC): The attacking character.
631
- defender (creature): The defending monster.
632
- """
633
- damage = calculate_damage(attacker, defender)
634
- defender.take_damage(damage)
635
-
636
-
637
- def handle_victory(player: PC, monsters: list):
638
- """
639
- Handle the logic when the player and allies defeat all monsters.
640
-
641
- Args:
642
- player (PC): The player character.
643
- monsters (list): The list of defeated monsters.
644
- """
645
- type_text("You have defeated all the enemies!", colorTrue=color_coding)
646
- for monster in monsters:
647
- if monster.hp <= 0:
648
- player.inventory_add(monster.dropped_items)
649
-
650
-
651
- def calculate_damage(attacker, defender) -> int:
652
- """
653
- Calculate the damage inflicted by the attacker on the defender.
654
-
655
- Args:
656
- attacker: The attacking character.
657
- defender: The defending character.
658
-
659
- Returns:
660
- int: The calculated damage.
661
- """
662
- damage_min, damage_max = calculate_damage_range(attacker.atpw)
663
- damage = randint(damage_min, damage_max)
664
-
665
- if random() < attacker.crit_chance:
666
- damage *= 2
667
- type_text("Critical hit!", colorTrue=color_coding)
668
-
669
- if hasattr(defender, "defending") and defender.defending:
670
- damage //= 2
671
- type_text("The attack is defended, reducing damage.", colorTrue=color_coding)
672
- defender.defending = False
673
-
674
- return damage
675
-
676
-
677
- def calculate_damage_range(atpw: int) -> tuple[int, int]:
678
- """
679
- Calculate the damage range based on attack power.
680
-
681
- Args:
682
- atpw (int): Attack power of the combatant.
683
-
684
- Returns:
685
- tuple[int, int]: Minimum and maximum damage range.
686
- """
687
- damage_max_range = randint(1, 3)
688
- damage_min_range = randint(1, 3)
689
- damage_min = max(1, atpw - damage_min_range) # Ensure minimum damage is at least 1
690
- damage_max = atpw + damage_max_range
691
- return damage_min, damage_max
692
-
693
-
694
- def use_special_ability(player: PC, monster: creature):
695
- """
696
- Allow the player to use a special ability during combat.
697
-
698
- Args:
699
- player (PC): The player character.
700
- monster (creature): The monster being fought.
701
- """
702
- if player.special_ability.ready:
703
- player.special_ability.activate(monster)
704
- type_text(
705
- f"You use your special ability: {player.special_ability.name}.",
706
- colorTrue=color_coding,
707
- )
708
- player.special_ability.ready = False
709
- else:
710
- type_text("Your special ability is not ready yet.", colorTrue=color_coding)
711
-
712
-
713
- def select_target(chooser, targets: list):
714
- """
715
- Select a target from a list of characters.
716
-
717
- Args:
718
- chooser: The entity (e.g., player or AI) selecting the target.
719
- targets (list): List of characters to select from.
720
-
721
- Returns:
722
- The selected target.
723
- """
724
- if chooser == player:
725
- valid_targets = []
726
- type_text("Who do you want to attack? The options:")
727
- # Enumerate through the targets to get both the index and the enemy.
728
- for index, enemy in enumerate(targets):
729
- if enemy.hp > 0:
730
- type_text(f"{index + 1}: {enemy.name} ({enemy.hp} HP)")
731
- valid_targets.append(index)
732
-
733
- # Prompt the player to select a target
734
- while True:
735
- try:
736
- choice = int(input("Enter the number of the target: ")) - 1
737
- if choice in valid_targets:
738
- return targets[choice]
739
- else:
740
- type_text("Invalid choice. Please select a valid target.")
741
- except ValueError:
742
- type_text("Invalid input. Please enter a number.")
743
- else:
744
- # AI or other logic for non-player chooser
745
- for target in targets:
746
- if target.hp > 0:
747
- return target
748
-
749
-
750
- def command():
751
- global player
752
- # try:
753
- ShouldBreak = False
754
-
755
- while True:
756
- showStatus()
757
- user_input = get_player_input(False)
758
-
759
- if user_input:
760
- commands_list = user_input.split(",")
761
- for command_str in commands_list:
762
- action, targets = parse_command(command_str.strip(), commands)
763
-
764
- if action in commands:
765
- if has_named_arg(commands[action], "player"):
766
- if targets:
767
- commands[action](player, *targets)
768
- else:
769
- commands[action](player)
770
- elif targets:
771
- commands[action](*targets)
772
- else:
773
- commands[action]()
774
- else:
775
- type_text(
776
- f"Unknown command '{action}'. Type 'help' for a list of commands.",
777
- colorTrue=color_coding,
778
- )
779
- if action in commands:
780
- ShouldBreak = True
781
- if ShouldBreak:
782
- return
783
-
784
-
785
- # except KeyError as e:
786
- # type_text(f"KeyError: {e} - This might be due to an undefined command or incorrect arguments.", colorTrue=color_coding)
787
- # except ValueError as e:
788
- # type_text(f"ValueError: {e} - This might be due to incorrect arguments provided.", colorTrue=color_coding)
789
- # except Exception as e:
790
- # type_text(f"Unexpected Error: {e}", colorTrue=color_coding)
791
-
792
-
793
- def handle_sleep_command(player: PC):
794
- type_text("You decide to rest for a while.", colorTrue=color_coding)
795
-
796
- # Simulate some time passing
797
- sleep(2) # Example: sleep for 2 seconds
798
-
799
- # Restore player's health or apply any other effects
800
- player.heal(3) # Example: heal 3 health points during sleep
801
-
802
- # Optional: Print a message or effect that happens during sleep
803
- type_text("You feel refreshed after a good rest.", colorTrue=color_coding)
804
-
805
-
806
- def get_player_input(split=True):
807
- global player
808
- move = ""
809
- while move == "":
810
- move = str(input(">")).strip().lower()
811
- if split:
812
- return move.split()
813
- return move
814
-
815
-
816
- def handle_go_command(direction):
817
- global player
818
- Move(direction)
819
-
820
-
821
- def handle_get_command(player: PC, *Args):
822
- item_name = " ".join(Args)
823
- if "items" in ROOMS[player.CURRENTROOM]:
824
- for ItemName in ROOMS[player.CURRENTROOM]["items"].keys():
825
- if item_name == ItemName:
826
- player.inventory_add([ROOMS[player.CURRENTROOM]["items"][ItemName]])
827
- del ROOMS[player.CURRENTROOM]["items"][ItemName]
828
- type_text(f"%*BLUE*%{item_name}%*RESET*% got!", colorTrue=color_coding)
829
- return
830
- type_text(f"Can't get {item_name}!", colorTrue=color_coding)
831
-
832
-
833
- def handle_look_command():
834
- global player
835
- should_return = False
836
- if "items" in ROOMS[player.CURRENTROOM]:
837
- type_text(
838
- f'The items in the room: %*BLUE*%{", ".join(ROOMS[player.CURRENTROOM]["items"].keys())}%*RESET*%.',
839
- colorTrue=color_coding,
840
- )
841
- should_return = True
842
- if "containers" in ROOMS[player.CURRENTROOM]:
843
- type_text(
844
- f"The containers here are: %*RED*%{', '.join(ROOMS[player.CURRENTROOM]['containers'].keys())}%*RESET*%",
845
- colorTrue=color_coding,
846
- )
847
- should_return = True
848
- if should_return:
849
- return
850
- type_text("There is nothing of interest.", colorTrue=color_coding)
851
-
852
-
853
- def handle_use_command(*Args):
854
- global player
855
- Use(Args)
856
-
857
-
858
- def handle_search_command(player, *Args):
859
- Container = " ".join(Args)
860
- if "containers" in ROOMS[player.CURRENTROOM]:
861
- if Container in ROOMS[player.CURRENTROOM]["containers"] and not all_same_value(
862
- ROOMS[player.CURRENTROOM]["containers"][Container].contents, None
863
- ):
864
- search_container(player, Container)
865
- else:
866
- type_text(f"You cannot search the {Container}", colorTrue=color_coding)
867
-
868
-
869
- def search_container(player: PC, Container):
870
- ContainerName = Container
871
- Container = ROOMS[player.CURRENTROOM]["containers"][Container]
872
- if isinstance(Container, container):
873
- if isinstance(Container.lock, Lock):
874
- key = PickKey(Container.lock)
875
- Container.Unlock(key, player)
876
- type_text(
877
- f"You search the{' secret' if Container.secret else ''} %*RED*%{ContainerName}%*RESET*% and find a ",
878
- newline=False,
879
- colorTrue=color_coding,
880
- )
881
- for searchitem in Container.contents:
882
- if searchitem:
883
- if isinstance(searchitem, item):
884
- end_str = (
885
- " and a "
886
- if Container.contents.index(searchitem)
887
- < last_index(Container.contents)
888
- else "\n"
889
- )
890
- type_text(
891
- f"%*BLUE*%{searchitem.name}%*RESET*%{end_str}",
892
- newline=False,
893
- colorTrue=color_coding,
894
- )
895
- Container.take_contents(player)
896
-
897
-
898
- def handle_put_command(player: PC, *Args):
899
- arguments = " ".join(Args)
900
- Arguments = arguments.split(" in ")
901
-
902
- # Ensure we have exactly two parts
903
- if len(Arguments) < 2:
904
- type_text(
905
- "You need to specify an item and where to put it (e.g., 'put book in drawer').",
906
- colorTrue=color_coding,
907
- )
908
- return
909
-
910
- # Strip whitespace
911
- Arguments = [arg.strip() for arg in Arguments]
912
- item_name = Arguments[0]
913
- container_name = Arguments[1]
914
-
915
- # Check if item is in inventory
916
- if item_name not in [item.name for item in player.inventory]:
917
- type_text(
918
- f"You don't have {item_name} in your inventory.", colorTrue=color_coding
919
- )
920
- return
921
-
922
- # Retrieve item and container
923
- PutItem = player.inventory[
924
- [item.name for item in player.inventory].index(item_name)
925
- ]
926
- if "containers" in ROOMS[player.CURRENTROOM]:
927
- put_in_container(player, PutItem, container_name)
928
- else:
929
- type_text(
930
- f"You cannot put the {PutItem.name} in the {container_name}",
931
- colorTrue=color_coding,
932
- )
933
-
934
-
935
- def put_in_container(player: PC, PutItem=None, container=None):
936
- player.inventory.remove(PutItem.name)
937
- if not ROOMS[player.CURRENTROOM]["containers"][container].contents:
938
- ROOMS[player.CURRENTROOM]["containers"][container].contents = []
939
- if not isinstance(
940
- ROOMS[player.CURRENTROOM]["containers"][container].contents, list
941
- ):
942
- ROOMS[player.CURRENTROOM]["containers"][container].contents = [
943
- ROOMS[player.CURRENTROOM]["containers"][container].contents
944
- ]
945
- ROOMS[player.CURRENTROOM]["containers"][container].contents += [PutItem]
946
- type_text(
947
- f"You put you're %*BLUE*%{PutItem.name}%*RESET*% into the %*RED*%{container}%*RESET*%",
948
- colorTrue=color_coding,
949
- )
950
-
951
-
952
- def handle_get_quest_command(questnum):
953
- global player
954
- if "quests" in ROOMS[player.CURRENTROOM]:
955
- if questnum in ROOMS[player.CURRENTROOM]["quests"]:
956
- quest_manager.add_quest(ROOMS[player.CURRENTROOM]["quests"][questnum])
957
- quest_manager.start_quest(ROOMS[player.CURRENTROOM]["quests"][questnum])
958
- del ROOMS[player.CURRENTROOM]["quests"][questnum]
959
-
960
-
961
- def PrintMap():
962
- global player
963
- type_text(ShowMap())
964
-
965
-
966
- # Define handling functions for different types of enemies
967
- def handle_hungry_bear(player: PC, enemy: creature):
968
- enemy_reacting = True
969
- if "potion" in player.inventory:
970
- if ask_for_consent("Do you want to throw your potion at the bear"):
971
- enemy_reacting = False
972
- del player.inventory[player.inventory.index("potion")]
973
- type_text(
974
- f"You throw the potion at the bear and it explodes into a puff of magic smoke that stuns the bear!",
975
- colorTrue=color_coding,
976
- )
977
- if enemy_reacting:
978
- return [enemy, enemy_reacting]
979
-
980
-
981
- def handle_grumpy_pig(player: PC, enemy: creature):
982
- enemy_reacting = True
983
- if "saddle" in player.inventory and "pig-rod" in player.inventory:
984
- if ask_for_consent("Do you want to use your saddle and pig-rod on the pig"):
985
- enemy_reacting = False
986
- type_text(
987
- f"You throw a saddle onto the pig and leap on steering it about with a pig fishing rod!",
988
- colorTrue=color_coding,
989
- )
990
- del ROOMS[player.CURRENTROOM]["creatures stats"]
991
- del player.inventory[player.inventory.index("saddle")]
992
- del player.inventory[player.inventory.index("pig-rod")]
993
- player.inventory_add(item["pig-steed"])
994
- player.xp += 20
995
- if "torch" in player.inventory:
996
- if ask_for_consent("Do you want to use your torch to scare the pig away"):
997
- enemy_reacting = False
998
- type_text(
999
- f"You wave your torch at the pig and it runs away through a tiny open window.",
1000
- colorTrue=color_coding,
1001
- )
1002
- del ROOMS[player.CURRENTROOM]["creatures stats"][
1003
- ROOMS[player.CURRENTROOM]["creatures stats"].index(enemy)
1004
- ]
1005
- player.xp += 5
1006
- if "rations" in player.inventory:
1007
- if ask_for_consent("Do you want to throw your ration at the pig"):
1008
- enemy_reacting = False
1009
- type_text(
1010
- f"You quickly throw rations at the pig. It still doesn't look happy though.",
1011
- colorTrue=color_coding,
1012
- )
1013
- del player.inventory[player.inventory.index("rations")]
1014
- player.xp += 15
1015
-
1016
- if enemy_reacting:
1017
- return [enemy, enemy_reacting]
1018
-
1019
-
1020
- def handle_greedy_goblin(player: PC, enemy: creature):
1021
- enemy_reacting = True
1022
- if player.money >= 15:
1023
- if ask_for_consent("Do you want to pay the goblin to not attack you"):
1024
- enemy_reacting = False
1025
- type_text(
1026
- f"You pay the {enemy.name} to not attack you for now, but he says you should run.",
1027
- colorTrue=color_coding,
1028
- )
1029
- player.money -= 15
1030
- enemy.dropped_items[1].value += 15
1031
- if enemy_reacting:
1032
- return [enemy, enemy_reacting]
1033
-
1034
-
1035
- commands = {
1036
- "go": handle_go_command,
1037
- "get quest": handle_get_quest_command,
1038
- "get": handle_get_command,
1039
- "look": handle_look_command,
1040
- "use": handle_use_command,
1041
- "search": handle_search_command,
1042
- "quit": quit,
1043
- "help": showInstructions,
1044
- "hint": showHint,
1045
- "sleep": handle_sleep_command,
1046
- "put": handle_put_command,
1047
- "map": PrintMap,
1048
- "examine": Examine,
1049
- }
1050
-
1051
-
1052
- def quit():
1053
- exit()
1054
-
1055
-
1056
- guards = [
1057
- Guard(
1058
- name="Guard",
1059
- hp=10,
1060
- atpw=4,
1061
- description="A 5'8\" human guard who looks like he doesn't belong here.",
1062
- flavor_text="A human guard spots you and says: 'You shouldn't be here.'",
1063
- type=creature_type("humanoid", "human"),
1064
- current_room="Bedroom",
1065
- patrol_route=["Bedroom", "Office", "Tower Bottom", "Landing", "Bedroom"],
1066
- patrol_type="normal",
1067
- ),
1068
- Guard(
1069
- name="Wolf",
1070
- hp=10,
1071
- atpw=4,
1072
- description="A large wolf with blood covering its face.",
1073
- flavor_text="A wolf spots you and growls.",
1074
- type=creature_type("beast", "wolf"),
1075
- current_room="Balcony",
1076
- patrol_type="random",
1077
- frendly_text="The wolf nuzzles you",
1078
- ),
1079
- ]
1080
-
1081
-
1082
- def handle_wolf(player: PC, wolf: Guard):
1083
- enemy_reacting = True
1084
- if "rations" in player.inventory:
1085
- if ask_for_consent("Do you want to give your ration to the wolf"):
1086
- enemy_reacting = False
1087
- type_text(
1088
- "You quickly give your rations to the wolf. It looks happy, walks up to you, and nuzzles you.",
1089
- colorTrue=color_coding,
1090
- )
1091
- player.inventory.remove("rations")
1092
- wolf.patrol_type = "follow"
1093
- wolf.frendly = True
1094
- return wolf
1095
- if enemy_reacting:
1096
- return [wolf, enemy_reacting]
1097
-
1098
-
1099
- def handle_guard_action(guard):
1100
- # Dynamically build the function name
1101
- function_name = f"handle_{guard.name.lower()}"
1102
-
1103
- # Use globals() to retrieve the function by name
1104
- function_to_call = globals().get(function_name)
1105
-
1106
- if function_to_call:
1107
- # Call the found function
1108
- guard = function_to_call(player, guard)
1109
- return [True, guard] # Function was found and called
1110
- else:
1111
- return [False, [guard, True]] # Function was not found
1112
-
1113
-
1114
- def initializer():
1115
- global color_coding, player, CHARACTERSLIST
1116
- df = pd.DataFrame(CHARACTERSLIST)
1117
- Standord_Player = loop_til_valid_input(
1118
- "Do you want to use a premade character?", "you didn't answer Y or N.", Y_N
1119
- ).value
1120
-
1121
- if Standord_Player:
1122
- while True:
1123
- type_text("Who do you want to play as?", colorTrue=False)
1124
- print(df)
1125
- selected_character = loop_til_valid_input(
1126
- "Who do you want to play as? (please select the number to the left of there stats)",
1127
- "That wasn't one of the characters. Please choose one.",
1128
- int,
1129
- )
1130
- lstIndex = last_index(CHARACTERSLIST)
1131
- if selected_character <= lstIndex:
1132
- character_info = CHARACTERSLIST[selected_character]
1133
- name = character_info["name"]
1134
- age = character_info["age"]
1135
- height = character_info["height"]
1136
- weight = character_info["weight(LBs)"]
1137
- break
1138
- else:
1139
- type_text(colorTrue=False)
1140
-
1141
- else:
1142
- type_text(
1143
- "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.",
1144
- colorTrue=False,
1145
- )
1146
-
1147
- name = loop_til_valid_input(
1148
- "What is your name?",
1149
- "You didn't enter a string. Please enter a string.",
1150
- str,
1151
- )
1152
- age = loop_til_valid_input(
1153
- "What is your age (in whole years)?",
1154
- "You didn't enter an integer. Please enter an integer.",
1155
- int,
1156
- )
1157
- height = loop_til_valid_input(
1158
- "What is your height?",
1159
- "You didn't enter your height in the correct format. Please enter your height in the correct format.",
1160
- Height,
1161
- )
1162
- weight = loop_til_valid_input(
1163
- "What is your weight (in lbs)?",
1164
- "You didn't enter an integer. Please enter an integer.",
1165
- int,
1166
- )
1167
-
1168
- color_coding = loop_til_valid_input(
1169
- "Do you want color coding (Y/N)?", "you didn't answer Y or N.", Y_N
1170
- ).value
1171
-
1172
- background_name = []
1173
- background_skills = []
1174
-
1175
- while True:
1176
- type_text("") # Prints an empty line
1177
- type_text("0. Random")
1178
-
1179
- # Display each background with its skills formatted correctly.
1180
- for idx, (background_name, background_skills) in enumerate(BACKGROUNDS.items()):
1181
- formatted_skills = ", ".join(background_skills)
1182
- type_text(f"{idx + 1}. {background_name} - {formatted_skills}")
1183
-
1184
- # Prompt the user to pick a background by number.
1185
- background = loop_til_valid_input(
1186
- "What background do you want? (please select the number to the left of them)",
1187
- "You didn't pick one",
1188
- int,
1189
- )
1190
-
1191
- length = len(BACKGROUNDS)
1192
- if 1 <= background <= length:
1193
- # Get the background name and skills based on user choice.
1194
- background_name = list(BACKGROUNDS.keys())[background - 1]
1195
- background_skills = BACKGROUNDS[background_name]
1196
- break
1197
- elif background == 0:
1198
- # Randomly select a background and get its associated skills.
1199
- background_name = choice(list(BACKGROUNDS.keys()))
1200
- background_skills = BACKGROUNDS[background_name]
1201
- break
1202
- else:
1203
- type_text("You didn't pick one")
1204
-
1205
- # start the player in the Hall and sets up everything else
1206
- player = PC(
1207
- name,
1208
- age,
1209
- background,
1210
- 1,
1211
- "Soldier",
1212
- height,
1213
- weight,
1214
- CURRENTROOM="Hall",
1215
- Skills=background_skills,
1216
- )
1217
-
1218
-
1219
- def main():
1220
- global player, color_coding
1221
-
1222
- # this is the initializer
1223
- initializer()
1224
-
1225
- # shows the instructions
1226
- start()
1227
-
1228
- # loop forever while the player wants to play
1229
- while True:
1230
- command()
1231
-
1232
- if "random_events" in ROOMS[player.CURRENTROOM]:
1233
- for event in ROOMS[player.CURRENTROOM]["random_events"]:
1234
- if isinstance(event, RandomEvent):
1235
- event.check_and_trigger(player)
1236
-
1237
- # Move guards
1238
- for guard in guards:
1239
- if isinstance(guard, Guard):
1240
- guard.move(ROOMS, player)
1241
-
1242
- good_guys = []
1243
- bad_guys = []
1244
-
1245
- # Check for detection
1246
- for guard in guards:
1247
- if isinstance(guard, Guard):
1248
- if guard.hp > 0:
1249
- if guard.check_detection(player.CURRENTROOM):
1250
- guard_handled = handle_guard_action(guard)
1251
- if not isinstance(guard_handled, list):
1252
- guard_handled = [guard_handled]
1253
-
1254
- # Get is_reacting from guard_handled
1255
- is_reacting = (
1256
- guard_handled[1][1]
1257
- if isinstance(guard_handled[1], list)
1258
- else True
1259
- )
1260
-
1261
- # Only update guard if the guard is reacting
1262
- if is_reacting:
1263
- if guard.frendly:
1264
- good_guys.append(guard)
1265
- else:
1266
- bad_guys.append(guard)
1267
-
1268
- if guard_handled[0]:
1269
- guards[guards.index(guard)] = (
1270
- guard_handled[1][0]
1271
- if isinstance(guard_handled[1], list)
1272
- else guard_handled[1]
1273
- )
1274
-
1275
- # Handle creatures in the current room
1276
- if "creatures stats" in ROOMS[player.CURRENTROOM]:
1277
- is_reactings = []
1278
- enemies = ROOMS[player.CURRENTROOM]["creatures stats"]
1279
- if not isinstance(enemies, list):
1280
- enemies = [
1281
- enemies
1282
- ] # Ensure enemies is a list even if there's only one creature
1283
-
1284
- for enemy in enemies:
1285
- if isinstance(enemy, creature):
1286
- if enemy.hp > 0:
1287
- enemy.type_text_flavor_text()
1288
- if ask_for_consent(f"Do you want to examine the {enemy.name}"):
1289
- enemy.type_text_description()
1290
-
1291
- # Handle specific creatures
1292
- if enemy.name == "hungry bear":
1293
- enemy_REF = handle_hungry_bear(player, enemy)
1294
- elif enemy.name == "grumpy pig":
1295
- enemy_REF = handle_grumpy_pig(player, enemy)
1296
- elif enemy.name == "greedy goblin":
1297
- enemy_REF = handle_greedy_goblin(player, enemy)
1298
- else:
1299
- enemy_REF = enemy
1300
-
1301
- if isinstance(enemy_REF, list):
1302
- is_reacting = enemy_REF[1]
1303
- enemy_REF = enemy_REF[0]
1304
- is_reactings.append(is_reacting)
1305
-
1306
- enemies[enemies.index(enemy)] = enemy_REF
1307
-
1308
- # Add to good or bad lists if reacting
1309
- if is_reacting:
1310
- if enemy_REF.frendly:
1311
- good_guys.append(enemy_REF)
1312
- else:
1313
- bad_guys.append(enemy_REF)
1314
-
1315
- if all_same_value(enemies, False):
1316
- del ROOMS[player.CURRENTROOM]["creatures stats"]
1317
- else:
1318
- ROOMS[player.CURRENTROOM]["creatures stats"] = enemies
1319
-
1320
- # Execute battle with separated good and bad guys
1321
- if bad_guys:
1322
- good_guys, bad_guys = battle(player, good_guys, bad_guys, player.LASTROOM)
1323
-
1324
- # Handle NPC interactions
1325
- if "NPCs" in ROOMS[player.CURRENTROOM]:
1326
- for npcname, npcstats in ROOMS[player.CURRENTROOM]["NPCs"].items():
1327
- if (
1328
- ask_for_consent("Do you want to interact with this NPC")
1329
- or npcstats.aggressive
1330
- ):
1331
- npcstats.interact()
1332
- if npcstats.aggressive:
1333
- ROOMS[player.CURRENTROOM]["NPCs"][npcname] = battle(
1334
- player, [], [npcstats], player.LASTROOM
1335
- )[1]
1336
-
1337
- player.special_ability.Tick()
1338
- quest_manager.update_objective(f"Kill {GameState['Enemies killed']} creatures")
1339
- for Item in GameState["collected items"]:
1340
- if isinstance(Item, item):
1341
- quest_manager.update_objective(f"Collect {Item.name}")
1342
-
1343
-
1344
- if __name__ == "__main__":
1345
- main()