Add Container class with lock/trap detection, corpse drops, and numbered duplicate corpses

This commit is contained in:
KansaiGaijin
2026-07-07 12:13:43 +12:00
parent db4b5cb543
commit 221cb71410
32 changed files with 938 additions and 160 deletions

View File

@@ -4,8 +4,8 @@ sys.path.append('.')
from player import Player # Only import what's necessary
from enum_list import ItemType, Slots
from race_list import Elf, Dwarf, Human
from job_list import Barbarian, Cleric, Wizard
from race_list import RACES
from class_list import CLASSES
def wait():
@@ -16,8 +16,8 @@ pre_generated_characters = {
"name": "Arion", # Example Name
"gender": "Male",
"age": 25,
"race": Elf,
"job": Wizard, # Based on the High Elf sheet
"race": RACES["Elf"],
"class_": CLASSES["Wizard"], # Based on the High Elf sheet
"alignment": "lawful good",
"description": "A scholarly High Elf skilled in the arcane arts.",
"stats": {
@@ -41,8 +41,8 @@ pre_generated_characters = {
"name": "Brundle", # Example Name
"gender": "Female",
"age": 35,
"race": Human,
"job": Barbarian, # Based on the Human sheet
"race": RACES["Human"],
"class_": CLASSES["Barbarian"], # Based on the Human sheet
"alignment": "chaotic good",
"description": "A robust Human warrior, charging into battle.",
"stats": {
@@ -67,8 +67,8 @@ pre_generated_characters = {
"name": "Drok", # Example Name
"gender": "Other",
"age": 75, # Dwarves live longer
"race": Dwarf,
"job": Cleric, # Based on the Hill Dwarf sheet (Life Domain implied by "healing" focus)
"race": RACES["Dwarf"],
"class_": CLASSES["Cleric"], # Based on the Hill Dwarf sheet (Life Domain implied by "healing" focus)
"alignment": "lawful good",
"description": "A stout Hill Dwarf cleric, a pillar of his community.",
"stats": {
@@ -142,10 +142,10 @@ def startGame():
print("Sorry, I didn't catch that. Please try again.\n")
continue
# --- Race and Job Selection ---
# --- Race and Class Selection ---
race = None
job = None
# Loop until Race and Job are confirmed
class_ = None
# Loop until Race and Class are confirmed
while True:
# Race Selection
selected_race_obj = None
@@ -154,11 +154,11 @@ def startGame():
race_choice = input("Please select a race to learn more about it:\n"
"1) Elf\n2) Dwarf\n3) Human\n >> ").title()
if race_choice in ['Elf', '1']:
selected_race_obj = Elf
selected_race_obj = RACES["Elf"]
elif race_choice in ['Dwarf', '2']:
selected_race_obj = Dwarf
selected_race_obj = RACES["Dwarf"]
elif race_choice in ['Human', '3']:
selected_race_obj = Human
selected_race_obj = RACES["Human"]
else:
print("Sorry I didn't recognise that race. Please select 'Elf', 'Dwarf', or 'Human'.\n")
continue
@@ -177,48 +177,48 @@ def startGame():
print("Sorry, I didn't catch that. Please try again.\n")
continue
# Job Selection
selected_job_obj = None
# Loop for selecting and viewing job
# Class Selection
selected_class_obj = None
# Loop for selecting and viewing class
while True:
job_choice = input("Please select a job to learn more about it:\n"
class_choice = input("Please select a class to learn more about it:\n"
"1) Barbarian\n2) Cleric\n3) Wizard\n >> ").title()
if job_choice in ['Barbarian', '1']:
selected_job_obj = Barbarian
elif job_choice in ['Cleric', '2']:
selected_job_obj = Cleric
elif job_choice in ['Wizard', '3']:
selected_job_obj = Wizard
if class_choice in ['Barbarian', '1']:
selected_class_obj = CLASSES["Barbarian"]
elif class_choice in ['Cleric', '2']:
selected_class_obj = CLASSES["Cleric"]
elif class_choice in ['Wizard', '3']:
selected_class_obj = CLASSES["Wizard"]
else:
print("Sorry I didn't recognise that job. Please select 'Barbarian', 'Cleric', or 'Wizard'.\n")
print("Sorry I didn't recognise that class. Please select 'Barbarian', 'Cleric', or 'Wizard'.\n")
continue
if selected_job_obj:
print(f"\n--- {selected_job_obj.name} ---")
print(selected_job_obj.__repr__())
if selected_class_obj:
print(f"\n--- {selected_class_obj.name} ---")
print(selected_class_obj.__repr__())
print('Would you like to proceed with this job or view another?')
proceed = input('1) Proceed\n2) View another job\n >> ')
print('Would you like to proceed with this class or view another?')
proceed = input('1) Proceed\n2) View another class\n >> ')
if proceed.lower() in ('1', 'proceed'):
job = selected_job_obj # Assign job object
break # Exit job selection loop
elif proceed.lower() in ('2', 'view', 'view another', 'view another job'):
continue # Restart job selection
class_ = selected_class_obj # Assign class object
break # Exit class selection loop
elif proceed.lower() in ('2', 'view', 'view another', 'view another class'):
continue # Restart class selection
else:
print("Sorry, I didn't catch that. Please try again.\n")
continue
# Final confirmation for both Race and Job
# Final confirmation for both Race and Class
while True:
# This safeguard should ideally not be hit if inner loops work correctly
if race is None or job is None:
print("Error: Race or Job not selected. Restarting Race/Job selection.")
break # Break out of this inner loop to restart the outer race/job loop
correct = input(f"\n{name}, you are a {race.name_adjective} {job.name}.\nIs this correct? Y/N\n >> ")
if race is None or class_ is None:
print("Error: Race or Class not selected. Restarting Race/Class selection.")
break # Break out of this inner loop to restart the outer race/class loop
correct = input(f"\n{name}, you are a {race.name_adjective} {class_.name}.\nIs this correct? Y/N\n >> ")
if correct.lower() in ['y', 'yes']:
return name, gender, age, race, job, None# All confirmed, return values
return name, gender, age, race, class_, None# All confirmed, return values
elif correct.lower() in ['n', 'no']:
# If not correct, break this loop to re-enter race/job selection
# If not correct, break this loop to re-enter race/class selection
break
else:
print("Sorry, I didn't catch that. Please try again.\n")
@@ -233,19 +233,19 @@ def startGame():
gender = input("Gender (Male, Female, Other): ")
age = int(input("Age: "))
race_str = input("Race (Elf, Dwarf, Human): ")
job_str = input("Job (Barbarian, Cleric, Wizard): ")
class_str = input("Class (Barbarian, Cleric, Wizard): ")
# Map string inputs to actual Race/Job objects for consistency
race_map = {'elf': Elf, 'dwarf': Dwarf, 'human': Human}
job_map = {'barbarian': Barbarian, 'cleric': Cleric, 'wizard': Wizard}
# Map string inputs to actual Race/Class objects for consistency
race_map = {'elf': RACES["Elf"], 'dwarf': RACES["Dwarf"], 'human': RACES["Human"]}
class_map = {'barbarian': CLASSES["Barbarian"], 'cleric': CLASSES["Cleric"], 'wizard': CLASSES["Wizard"]}
actual_race = race_map.get(race_str.lower())
actual_job = job_map.get(job_str.lower())
actual_class = class_map.get(class_str.lower())
if actual_race and actual_job:
return name, gender, age, actual_race, actual_job, None
if actual_race and actual_class:
return name, gender, age, actual_race, actual_class, None
else:
print("Invalid race or job entered for pre-generated character. Please try again.")
print("Invalid race or class entered for pre-generated character. Please try again.")
start = "1"
continue
return None
@@ -267,7 +267,7 @@ def startGame():
print("Who would you like to to play?")
for key, char_data in pre_generated_characters.items():
print(
f"{key}) {char_data['name']} ({char_data['race'].name_adjective} {char_data['job'].name}, {char_data['alignment']})")
f"{key}) {char_data['name']} ({char_data['race'].name_adjective} {char_data['class_'].name}, {char_data['alignment']})")
print("Type 'back' to return to character creation options.")
char_choice = input(">> ").strip().lower()
@@ -284,7 +284,7 @@ def startGame():
print(f"Gender: {selected_char_data['gender']}")
print(f"Age: {selected_char_data['age']}")
print(f"Race: {selected_char_data['race'].name_adjective}")
print(f"Class: {selected_char_data['job'].name}")
print(f"Class: {selected_char_data['class_'].name}")
print(f"Alignment: {selected_char_data['alignment']}")
print(f"Description: {selected_char_data['description']}")
print(f"Age: {selected_char_data['age']}")
@@ -340,11 +340,11 @@ def startGame():
gender = selected_char_data['gender']
age = selected_char_data['age']
race = selected_char_data['race']
job = selected_char_data['job']
class_ = selected_char_data['class_']
pre_allocated_stats = selected_char_data['stats']
print(f"\nYou have selected: {name}, a {age} year old {race.name_adjective} {job.name}.")
return name, gender, age, race, job, pre_allocated_stats # Exit all loops and function
print(f"\nYou have selected: {name}, a {age} year old {race.name_adjective} {class_.name}.")
return name, gender, age, race, class_, pre_allocated_stats # Exit all loops and function
elif confirm_choice in ("2", "no"):
print("\nReturning to pre-generated character selection.")
@@ -532,7 +532,13 @@ def get_instructions():
"Enter cave | house | room - maybe... TBC\n"
"Scene or Location - Replays the current area's details\n"
"Look around - lists the available items in your scene without displaying the scene description.\n"
"Examine | Open | Loot *object* - Provides details of an item, opens a container, or takes an object.")
"Examine | Open | Loot *object* - Provides details of an item, opens a container, or takes an object.\n"
"Spells | Spellbook - Lists your cantrips, known/preparable spells, prepared spells, and slots.\n"
"Cast *spell name* - Casts a cantrip or prepared spell.\n"
"Prepare | Unprepare *spell name* - Moves a spell in/out of your prepared list.\n"
"Rest - Long rest: restores HP and spell slots.\n"
"Check weight | carry | encumbrance - Shows carrying weight vs capacity.\n"
"Check currency | coins | gold - Shows coinage held and total gp value.")
print(descrip1)
time.sleep(3) # Reduced sleep for faster testing
print(descrip2)
@@ -580,6 +586,24 @@ def parse(input_text):
command = "go"
object1 = " ".join(words[1:])
return command, object1
elif words[0] == "cast":
command = "cast"
object1 = " ".join(words[1:])
return command, object1
elif words[0] == "prepare":
command = "prepare"
object1 = " ".join(words[1:])
return command, object1
elif words[0] == "unprepare":
command = "unprepare"
object1 = " ".join(words[1:])
return command, object1
elif words[0] == "check" and words[1] in ("weight", "carry", "encumbrance"):
command = "weight"
return command, object1
elif words[0] == "check" and words[1] in ("currency", "coins", "gold", "money"):
command = "currency"
return command, object1
# Single-word commands
if words[0] == "help":
@@ -630,6 +654,14 @@ def parse(input_text):
command = "drop" # User needs to specify what to drop
object1 = None
elif words[0] in ("spells", "spellbook"):
command = "spells"
elif words[0] == "rest":
command = "rest"
elif words[0] in ("weight", "carry", "encumbrance"):
command = "weight"
elif words[0] in ("currency", "coins", "gold", "money"):
command = "currency"
elif words[0] == "quit":
command = "quit"
else: