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
File without changes
|
@@ -0,0 +1,373 @@
|
|
1
|
+
from items import *
|
2
|
+
from utils import *
|
3
|
+
|
4
|
+
global ValidActions
|
5
|
+
|
6
|
+
ValidActions = [
|
7
|
+
"attack",
|
8
|
+
"defend",
|
9
|
+
"special",
|
10
|
+
]
|
11
|
+
|
12
|
+
class Height:
|
13
|
+
def __init__(self, height_str="0ft 0"):
|
14
|
+
feet, inches = map(float, height_str.split('ft '))
|
15
|
+
if inches >= 12:
|
16
|
+
raise ValueError("Inches must be less than 12.")
|
17
|
+
try:
|
18
|
+
feet = int(feet)
|
19
|
+
except ValueError:
|
20
|
+
pass
|
21
|
+
try:
|
22
|
+
inches = int(inches)
|
23
|
+
except ValueError:
|
24
|
+
pass
|
25
|
+
self.feet = feet
|
26
|
+
self.inches = inches
|
27
|
+
|
28
|
+
def __str__(self):
|
29
|
+
return f"{self.feet}ft {self.inches}"
|
30
|
+
|
31
|
+
|
32
|
+
class base_character:
|
33
|
+
"""
|
34
|
+
Represents a base character in the game, including both players and creatures.
|
35
|
+
"""
|
36
|
+
|
37
|
+
def take_damage(self, damage_taken: int = 5):
|
38
|
+
"""
|
39
|
+
Reduces the character's hit points by the specified amount of damage.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
damage_taken (int): The amount of damage to be subtracted from the character's hit points. Default is 5.
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
None
|
46
|
+
"""
|
47
|
+
string_beginning = "%*MAGENTA*%"
|
48
|
+
if type(self) == creature:
|
49
|
+
string_beginning = "The %*CYAN*%"
|
50
|
+
self.hp = self.hp - damage_taken
|
51
|
+
if self.hp < 0:
|
52
|
+
self.hp = 0
|
53
|
+
type_text(f"{string_beginning}{self.name}%*RESET*% takes {damage_taken} damage and has {self.hp} HP left!")
|
54
|
+
|
55
|
+
|
56
|
+
class creature_type:
|
57
|
+
"""
|
58
|
+
Represents the type of a creature in the game.
|
59
|
+
"""
|
60
|
+
|
61
|
+
def __init__(self, type: str, subtype: str = None) -> None:
|
62
|
+
"""
|
63
|
+
Initializes a creature type with the specified type and optional subtype.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
type (str): The primary type of the creature.
|
67
|
+
subtype (str, optional): The subtype of the creature. Defaults to None.
|
68
|
+
"""
|
69
|
+
self.type = type
|
70
|
+
self.subtype = subtype
|
71
|
+
|
72
|
+
def check_type(self):
|
73
|
+
"""
|
74
|
+
Returns the type and subtype of the creature.
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
tuple: A tuple containing the type and subtype of the creature, or just the type if no subtype is specified.
|
78
|
+
"""
|
79
|
+
if self.subtype:
|
80
|
+
return self.type, self.subtype
|
81
|
+
return self.type
|
82
|
+
|
83
|
+
def __str__(self) -> str:
|
84
|
+
"""
|
85
|
+
Returns a string representation of the creature type.
|
86
|
+
|
87
|
+
Returns:
|
88
|
+
str: A string representation of the creature type.
|
89
|
+
"""
|
90
|
+
if self.subtype:
|
91
|
+
return f"{self.type}, {self.subtype}"
|
92
|
+
return f"{self.type}"
|
93
|
+
|
94
|
+
class creature(base_character):
|
95
|
+
"""
|
96
|
+
A class representing a creature in the game.
|
97
|
+
|
98
|
+
Attributes:
|
99
|
+
name (str): The name of the creature.
|
100
|
+
hp (int): The hit points of the creature.
|
101
|
+
atpw (int): The attack power of the creature.
|
102
|
+
dropped_items (list[str]): A list of items dropped by the creature when defeated.
|
103
|
+
description (str): The description of the creature.
|
104
|
+
flavor_text (str): The flavor text associated with encountering the creature.
|
105
|
+
type (creature_type): The type of the creature.
|
106
|
+
crit_chance (float): The chance of the creature landing a critical hit.
|
107
|
+
"""
|
108
|
+
|
109
|
+
def __init__(self, name: str, hp: int, atpw: int, dropped_items: list[str] = [], description: str = None, flavor_text: str = None, type: creature_type = creature_type('beast'), crit_chance: float = 0.05):
|
110
|
+
"""
|
111
|
+
Initializes a new creature instance.
|
112
|
+
|
113
|
+
Args:
|
114
|
+
name (str): The name of the creature.
|
115
|
+
hp (int): The hit points of the creature.
|
116
|
+
atpw (int): The attack power of the creature.
|
117
|
+
dropped_items (list[str], optional): A list of items dropped by the creature when defeated. Defaults to [].
|
118
|
+
description (str, optional): The description of the creature. Defaults to None.
|
119
|
+
flavor_text (str, optional): The flavor text associated with encountering the creature. Defaults to None.
|
120
|
+
type (creature_type, optional): The type of the creature. Defaults to creature_type('beast').
|
121
|
+
crit_chance (float, optional): The chance of the creature landing a critical hit. Defaults to 0.05.
|
122
|
+
"""
|
123
|
+
self.name = name
|
124
|
+
self.hp = hp
|
125
|
+
self.atpw = atpw
|
126
|
+
self.difficulty = self.hp / 10 + self.atpw
|
127
|
+
self.dropped_items = dropped_items
|
128
|
+
self.xp = rounding(self.difficulty * 2 + len(self.dropped_items))
|
129
|
+
self.description = description if description else f'A %*CYAN*%{self.name}%*RESET'
|
130
|
+
self.flavor_text = flavor_text if flavor_text else f'You see a %*CYAN*%{self.name}%*RESET*%!'
|
131
|
+
self.type = type
|
132
|
+
self.crit_chance = crit_chance
|
133
|
+
|
134
|
+
def type_text_flavor_text(self):
|
135
|
+
"""
|
136
|
+
Prints the flavor text associated with encountering the creature.
|
137
|
+
"""
|
138
|
+
type_text(self.flavor_text)
|
139
|
+
|
140
|
+
def type_text_description(self):
|
141
|
+
"""
|
142
|
+
Prints the description of the creature.
|
143
|
+
"""
|
144
|
+
type_text(self.description)
|
145
|
+
|
146
|
+
class Guard(creature):
|
147
|
+
"""
|
148
|
+
A class representing a guard that patrols in the game.
|
149
|
+
|
150
|
+
Attributes:
|
151
|
+
current_room (str): The current room where the guard is located.
|
152
|
+
patrol_route (list[str]): The list of rooms the guard patrols through.
|
153
|
+
"""
|
154
|
+
|
155
|
+
def __init__(self, name: str, hp: int, atpw: int, dropped_items: list[str] = [], description: str = None, flavor_text: str = None, type: creature_type = creature_type('humanoid'), crit_chance: float = 0.05, current_room: str = None, patrol_route: list[str] = None, patrol_type: str = 'normal'):
|
156
|
+
"""
|
157
|
+
Initializes a new guard instance.
|
158
|
+
|
159
|
+
Args:
|
160
|
+
name (str): The name of the guard.
|
161
|
+
hp (int): The hit points of the guard.
|
162
|
+
atpw (int): The attack power of the guard.
|
163
|
+
dropped_items (list[str], optional): A list of items dropped by the guard when defeated. Defaults to [].
|
164
|
+
description (str, optional): The description of the guard. Defaults to None.
|
165
|
+
flavor_text (str, optional): The flavor text associated with encountering the guard. Defaults to None.
|
166
|
+
type (creature_type, optional): The type of the guard. Defaults to creature_type('humanoid').
|
167
|
+
crit_chance (float, optional): The chance of the guard landing a critical hit. Defaults to 0.05.
|
168
|
+
current_room (str, optional): The current room where the guard is located. Defaults to None.
|
169
|
+
patrol_route (list[str], optional): The list of rooms the guard patrols through. Defaults to None.
|
170
|
+
patrol_type (str): The type of patrol the guard is doing. Defaults to narmol.
|
171
|
+
"""
|
172
|
+
super().__init__(name, hp, atpw, dropped_items, description, flavor_text, type, crit_chance)
|
173
|
+
self.current_room = current_room
|
174
|
+
self.patrol_route = patrol_route or []
|
175
|
+
self.patrol_type = patrol_type
|
176
|
+
|
177
|
+
def move(self, ROOMS):
|
178
|
+
"""
|
179
|
+
Moves the guard depending on his patrol type.
|
180
|
+
"""
|
181
|
+
|
182
|
+
if self.patrol_type == 'normal':
|
183
|
+
if self.patrol_route:
|
184
|
+
current_index = self.patrol_route.index(self.current_room)
|
185
|
+
next_index = (current_index + 1) % len(self.patrol_route)
|
186
|
+
self.current_room = self.patrol_route[next_index]
|
187
|
+
elif self.patrol_type == 'random':
|
188
|
+
rooms = []
|
189
|
+
for direction, room in ROOMS[self.current_room]['directions'].items():
|
190
|
+
rooms.append(room)
|
191
|
+
self.current_room = choice(rooms)
|
192
|
+
|
193
|
+
def check_detection(self, player_room):
|
194
|
+
"""
|
195
|
+
Checks if the guard has detected the player.
|
196
|
+
|
197
|
+
Args:
|
198
|
+
player_room (str): The current room where the player is located.
|
199
|
+
|
200
|
+
Returns:
|
201
|
+
bool: True if the player is detected, False otherwise.
|
202
|
+
"""
|
203
|
+
if self.current_room == player_room:
|
204
|
+
type_text(f"You have been caught by {self.name} in the {self.current_room}!")
|
205
|
+
return True
|
206
|
+
return False
|
207
|
+
|
208
|
+
class base_ability:
|
209
|
+
def __init__(self, name, cooldown_time) -> None:
|
210
|
+
self.ready = True
|
211
|
+
self.name = name
|
212
|
+
self.cooldown_time = cooldown_time
|
213
|
+
self.current_cooldown = 0
|
214
|
+
|
215
|
+
def activate(self, target: creature, damage: int = 5):
|
216
|
+
self.ready = False
|
217
|
+
print(f"Ability {self.name} will be ready after {self.cooldown_time} commands.")
|
218
|
+
|
219
|
+
def Tick(self):
|
220
|
+
self.current_cooldown += 1
|
221
|
+
|
222
|
+
def check_cooldown(self):
|
223
|
+
if self.current_cooldown >= self.cooldown_time:
|
224
|
+
type_text(f"\nAbility {self.name} is ready to use again. ")
|
225
|
+
self.ready = True
|
226
|
+
|
227
|
+
class supercrit_ability(base_ability):
|
228
|
+
def __init__(self) -> None:
|
229
|
+
super().__init__("Super Crit", 5)
|
230
|
+
|
231
|
+
def activate(self, target: base_character, damage: int = 5):
|
232
|
+
target.take_damage(damage*5)
|
233
|
+
super().activate(target, damage)
|
234
|
+
|
235
|
+
class PC(base_character):
|
236
|
+
|
237
|
+
def __init__(
|
238
|
+
self,
|
239
|
+
Name: str,
|
240
|
+
Age: int,
|
241
|
+
Class: str,
|
242
|
+
Level: int,
|
243
|
+
Background: str,
|
244
|
+
Height: Height,
|
245
|
+
Weight: int,
|
246
|
+
Notes: list = [],
|
247
|
+
special_ability: base_ability = supercrit_ability(),
|
248
|
+
NOTES: list = [],
|
249
|
+
xp: int = None,
|
250
|
+
inventory: inv = None,
|
251
|
+
money: int = 0,
|
252
|
+
weapons_atpws: list = [],
|
253
|
+
backstory: str = "",
|
254
|
+
):
|
255
|
+
if not xp:
|
256
|
+
if Level == 1:
|
257
|
+
xp = 0
|
258
|
+
else:
|
259
|
+
xp = Level*25
|
260
|
+
self.name = Name
|
261
|
+
self.Age = Age
|
262
|
+
self.Class = Class
|
263
|
+
self.Level = Level
|
264
|
+
self.Background = Background
|
265
|
+
self.Height = Height
|
266
|
+
self.Weight = Weight
|
267
|
+
self.BackstoryNotes = Notes
|
268
|
+
self.NOTES = NOTES
|
269
|
+
self.maxhp = self.Level * 10
|
270
|
+
self.hp = self.maxhp
|
271
|
+
self.atpw = rounding(self.Level * 1.5 + 3, 1)
|
272
|
+
self.xp = xp
|
273
|
+
self.inventory = inventory if inventory is not None else inv() # Initialize an inv if inventory is None
|
274
|
+
self.money = money
|
275
|
+
self.weapons_atpws = weapons_atpws
|
276
|
+
self.crit_chance = 0.075
|
277
|
+
self.defending = False
|
278
|
+
self.special_ability = special_ability
|
279
|
+
self.backstory = backstory
|
280
|
+
|
281
|
+
def get_change_weapon(self, weapon_atpw: int = 0, weapon_index: int = -1):
|
282
|
+
if weapon_atpw > 0:
|
283
|
+
self.weapons_atpws.append(weapon_atpw)
|
284
|
+
if weapon_index <= 0 or weapon_index > (len(self.weapons_atpws) - 1):
|
285
|
+
self.atpw = self.Level * 2 + 3 + max(self.weapons_atpws)
|
286
|
+
else:
|
287
|
+
self.atpw = self.Level * 2 + 3 + self.weapons_atpws[weapon_index]
|
288
|
+
|
289
|
+
def check_xp(self):
|
290
|
+
self.level = rounding(self.xp/25, 1)
|
291
|
+
|
292
|
+
def add_xp(self, xp_added: int = 5):
|
293
|
+
self.xp += xp_added
|
294
|
+
self.check_xp()
|
295
|
+
|
296
|
+
def inventory_add(self, added: list[item]):
|
297
|
+
try:
|
298
|
+
for item_to_add in added:
|
299
|
+
if isinstance(item_to_add, item):
|
300
|
+
# Add the item to the player's inventory
|
301
|
+
self.inventory.append(item_to_add)
|
302
|
+
|
303
|
+
# Check if the added item is a weapon and update player's weapon if needed
|
304
|
+
if item_to_add.type == 'weapon':
|
305
|
+
self.get_change_weapon(item_to_add.value)
|
306
|
+
else:
|
307
|
+
# Print an error message if the item is not an instance of Item class
|
308
|
+
type_text(f"Error: {item_to_add} is not an instance of Item class")
|
309
|
+
except Exception as e:
|
310
|
+
# Print the full traceback if an exception occurs
|
311
|
+
type_text(("Error:", e))
|
312
|
+
|
313
|
+
def heal(self, value):
|
314
|
+
self.hp = clamp(value, 0, self.maxhp)
|
315
|
+
|
316
|
+
class NPC(PC):
|
317
|
+
def __init__(
|
318
|
+
self,
|
319
|
+
Name: str,
|
320
|
+
Age: int,
|
321
|
+
Class: str,
|
322
|
+
Level: int,
|
323
|
+
Background: str,
|
324
|
+
Height: Height,
|
325
|
+
Weight: int,
|
326
|
+
Notes: list = [],
|
327
|
+
special_ability: base_ability = supercrit_ability(),
|
328
|
+
NOTES: list = [],
|
329
|
+
xp: int = None,
|
330
|
+
inventory: inv = None,
|
331
|
+
money: int = 0,
|
332
|
+
weapons_atpws: list = [],
|
333
|
+
npc_role: str = "generic", # New attribute for NPC role (e.g., merchant, enemy, etc.)
|
334
|
+
aggressive: bool = False # New attribute to determine if NPC is aggressive
|
335
|
+
):
|
336
|
+
super().__init__(
|
337
|
+
Name=Name,
|
338
|
+
Age=Age,
|
339
|
+
Class=Class,
|
340
|
+
Level=Level,
|
341
|
+
Background=Background,
|
342
|
+
Height=Height,
|
343
|
+
Weight=Weight,
|
344
|
+
Notes=Notes,
|
345
|
+
special_ability=special_ability,
|
346
|
+
NOTES=NOTES,
|
347
|
+
xp=xp,
|
348
|
+
inventory=inventory,
|
349
|
+
money=money,
|
350
|
+
weapons_atpws=weapons_atpws
|
351
|
+
)
|
352
|
+
self.npc_role = npc_role
|
353
|
+
self.aggressive = aggressive
|
354
|
+
|
355
|
+
def interact(self):
|
356
|
+
if self.aggressive:
|
357
|
+
return f"{self.name} looks hostile and prepares for a fight!"
|
358
|
+
else:
|
359
|
+
return f"{self.name} has nothing to say to you."
|
360
|
+
|
361
|
+
def npc_info(self):
|
362
|
+
return f"Name: {self.name}, Age: {self.Age}, Class: {self.Class}, Level: {self.Level}, Role: {self.npc_role}, Aggressive: {self.aggressive}"
|
363
|
+
|
364
|
+
class PC_action:
|
365
|
+
def __init__(self, value) -> None:
|
366
|
+
if not value in ValidActions:
|
367
|
+
raise ValueError
|
368
|
+
self.value = value
|
369
|
+
|
370
|
+
def __eq__(self, value: object) -> bool:
|
371
|
+
if isinstance(value, PC_action):
|
372
|
+
return self.value == value.value
|
373
|
+
return self.value == value
|
@@ -0,0 +1,67 @@
|
|
1
|
+
from utils import *
|
2
|
+
|
3
|
+
class item:
|
4
|
+
|
5
|
+
def __init__(self, name: str = '', type: str = 'miscellaneous', value: int = 0):
|
6
|
+
self.name = name
|
7
|
+
self.type = type
|
8
|
+
self.value = value
|
9
|
+
|
10
|
+
def sell(self, seller) -> bool:
|
11
|
+
if self.type.lower() == 'valuable':
|
12
|
+
seller.money += self.value
|
13
|
+
return True
|
14
|
+
else:
|
15
|
+
return False
|
16
|
+
|
17
|
+
def IsUsable(self) -> bool:
|
18
|
+
return self.usable
|
19
|
+
|
20
|
+
class ShopItem:
|
21
|
+
def __init__(self, item: item, price: int):
|
22
|
+
self.item = item
|
23
|
+
self.price = price
|
24
|
+
|
25
|
+
def display(self):
|
26
|
+
return f"{self.item.name} - {self.price} gold: {self.item.effect}"
|
27
|
+
|
28
|
+
def can_buy(self, player) -> bool:
|
29
|
+
return player.money >= self.price
|
30
|
+
|
31
|
+
def buy(self, player) -> bool:
|
32
|
+
if self.can_buy(player):
|
33
|
+
player.money -= self.price
|
34
|
+
player.inventory.append(self.item)
|
35
|
+
return True
|
36
|
+
else:
|
37
|
+
return False
|
38
|
+
|
39
|
+
class inv(list):
|
40
|
+
def __contains__(self, item_name) -> bool:
|
41
|
+
for item_ in self:
|
42
|
+
if item_.name == item_name:
|
43
|
+
return True
|
44
|
+
return False
|
45
|
+
|
46
|
+
def index(self, value, start=0, end=None):
|
47
|
+
if end is None:
|
48
|
+
end = len(self)
|
49
|
+
|
50
|
+
# Custom implementation of index method
|
51
|
+
for i in range(start, end):
|
52
|
+
if isinstance(self[i], item):
|
53
|
+
if self[i].name == value:
|
54
|
+
return i
|
55
|
+
return None
|
56
|
+
|
57
|
+
def remove(self, value):
|
58
|
+
if isinstance(value, item):
|
59
|
+
if value in self:
|
60
|
+
del self[self.index(value.name)]
|
61
|
+
return
|
62
|
+
del self[self.index(value)]
|
63
|
+
|
64
|
+
class container:
|
65
|
+
def __init__(self, contents: list[item], secret: bool = False) -> None:
|
66
|
+
self.contents = contents
|
67
|
+
self.secret = secret
|