Updated startGame(), fixed bugs, reworded/formatted areas to be consistent.

This commit is contained in:
kansaigaijin
2025-07-13 16:09:24 +12:00
parent 906dde0607
commit 54fef56615

View File

@@ -1,35 +1,27 @@
import time import time
import sys
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 player import *
def wait(): def wait():
input("Press enter to continue...") input("Press enter to continue...")
def startGame(): def startGame():
print("Welcome, stranger.") print("Welcome stranger, to the world of Kanjin!.")
start = input("Would you like to create your own character or use pre-generated stats?" start = input("Would you like to create your own character or use pre-generated stats?"
"\n 1) Create a new character\n 2) Pre-generated\n >> ") "\n 1) Create a new character\n 2) Pre-generated\n >> ")
while True: while True:
if start in ("2", "Pregen"): if start in ("1", "Create"):
print("Please be prepared to enter a name, gender, age, race, and class, from those available in the game."
"\nIf you are unsure what the options are, please go back and create a new character.")
create = input("Do you wish to continue? Y/N\n >> ")
if create in ("y", "yes"):
name = input("Name: ")
gender = input("Gender: ")
age = int(input("Age: ")
race = input("Race: ")
job = input("Job: ")
return name, gender, age, race, job
elif create in ("n", "no"):
start = "1"
elif start in ("1", "Create"):
while True: # Global check to see if Name, Age, and Gender are correct while True: # Global check to see if Name, Age, and Gender are correct
# Name # Name
name = input('What is your name?\n >> ') name = input('What is your name?\n >> ').title()
while len(name) < 2: while len(name) < 2:
name = input('Input name was too short. Try again.\nWhat is your name?\n >> ') name = input('Name must be longer than one character. Try again.\nWhat is your name?\n >> ')
# Gender # Gender
while True: while True:
gender_select = input("What is your gender?\n" gender_select = input("What is your gender?\n"
@@ -45,10 +37,10 @@ def startGame():
gender = "Female" gender = "Female"
elif gender_select in ("3", "other"): elif gender_select in ("3", "other"):
gender = "Other" gender = "Other"
# Age
while True: while True:
# Age
try: try:
age = int(input('How old are you?\n >> ') age = int(input('How old are you?\n >> '))
break break
except ValueError: except ValueError:
print("Sorry I didn't recognise that age. Please type in a whole number.") print("Sorry I didn't recognise that age. Please type in a whole number.")
@@ -68,56 +60,69 @@ def startGame():
continue continue
break break
race = None
job = None
while True: # Global check to see if Race and Job are correct while True: # Global check to see if Race and Job are correct
# Race # Race
selected_race_obj = None
while True: while True:
race = input("Please select a race to learn more about it: Elf, Dwarf, or Human.\n >> ") race_choice = input("Please select a race to learn more about it:\n"
if race not in ("Elf", "Dwarf", "Human", None): "1) Elf\n2) Dwarf\n3) Human\n >> ").title()
race = input("Sorry I didn't recognise that race. Please select 'Elf', 'Dwarf', or 'Human'.\n >> ") if race_choice in ['Elf', '1']:
elif race is None: selected_race_obj = Elf
race = input("Please select a race to learn more about it: Elf, Dwarf, or Human.\n >> ") elif race_choice in ['Dwarf', '2']:
continue selected_race_obj = Dwarf
elif race_choice in ['Human', '3']:
selected_race_obj = Human
else: else:
# Replace these prints with appropriate explanations for the web interface print("Sorry I didn't recognise that race. Please select 'Elf', 'Dwarf', or 'Human'.\n")
if race == "Elf": continue
print("Information about Elves...")
elif race == "Dwarf": if selected_race_obj:
print("Information about Dwarves...") print(f"\n--- {selected_race_obj.name} ---")
elif race == "Human": print(selected_race_obj.__repr__()) # Use the __repr__ to get full description and traits
print("Information about Humans...")
print('Would you like to proceed with this race or view another?') print('Would you like to proceed with this race or view another?')
proceed = input('1) Proceed\n2) View another race\n >> ') proceed = input('1) Proceed\n2) View another race\n >> ')
if proceed in ('1', 'proceed'): if proceed in ('1', 'proceed'):
race = selected_race_obj
break break
elif proceed in ('2', 'view', 'view another', 'view another race'): elif proceed in ('2', 'view', 'view another', 'view another race'):
race = None race = None
continue continue
# Job # Job
selected_job_obj = None
while True: while True:
job = input("Please select a job to learn more about it: Barbarian, Cleric, or Wizard.\n >> ") job_choice = input("Please select a race to learn more about it:\n"
if job not in ("Barbarian", "Cleric", "Wizard", None): "1) Barbarian\n2) Cleric\n3) Wizard\n >> ").title()
job = input("Sorry I didn't recognise that job. Please select 'Barbarian', 'Cleric', or 'Wizard'.\n >> ") if job_choice in ['Barbarian', '1']:
elif job is None: selected_job_obj = Barbarian
job = input("Please select a job to learn more about it: Barbarian, Cleric, or Wizard.\n >> ") elif job_choice in ['Cleric', '2']:
continue selected_job_obj = Cleric
elif job_choice in ['Wizard', '3']:
selected_job_obj = Wizard
else: else:
# Replace these prints with appropriate explanations for the web interface print("Sorry I didn't recognise that job. Please select 'Barbarian', 'Cleric', or 'Wizard'.\n")
if job == "Barbarian": continue
print("Information about Barbarians...")
elif job == "Cleric": if selected_job_obj:
print("Information about Clerics...") print(f"\n--- {selected_job_obj.name} ---")
elif job == "Wizard": print(selected_job_obj.__repr__()) # Use the __repr__ to get full description and traits
print("Information about Wizards...")
print('Would you like to proceed with this job or view another?') print('Would you like to proceed with this job or view another?')
proceed = input('1) Proceed\n2) View another job\n >> ') proceed = input('1) Proceed\n2) View another job\n >> ')
if proceed in ('1', 'proceed'): if proceed in ('1', 'proceed'):
job = selected_job_obj # Store the string name
break break
elif proceed in ('2', 'view', 'view another', 'view another job'): elif proceed in ('2', 'view', 'view another', 'view another job'):
job = None job = None
continue continue
else:
print("Sorry, I didn't catch that. Please try again.\n")
# Final check
while True: while True:
# Final check correct = input(f"{name}, you are a {race.name_adjective} {job.name}.\nIs this correct? Y/N\n >> ")
correct = input(f"{name}, you are a {race} {job}.\nIs this correct? Y/N\n >> ")
if correct in ['y', 'yes']: if correct in ['y', 'yes']:
break break
elif correct in ['n', 'no']: elif correct in ['n', 'no']:
@@ -126,9 +131,31 @@ def startGame():
print("Sorry, I didn't catch that. Please try again.\n") print("Sorry, I didn't catch that. Please try again.\n")
continue continue
return name, gender, age, race, job return name, gender, age, race, job
elif start in ("2", "pre-generated"):
print("Please be prepared to enter a name, gender, age, race, and class, from those available in the game."
"\nIf you are unsure what the options are, please go back and create a new character.")
create = input("Do you wish to continue? Y/N\n >> ").lower()
if create in ("y", "yes"):
name = input("Name: ")
gender = input("Gender: ")
age = int(input("Age: "))
race = input("Race: ")
job = input("Job: ")
return name, gender, age, race, job # Return and exit function
elif create in ("n", "no"):
# If 'n', continue the outer while True loop to re-prompt the initial choice.
continue
else:
print("Invalid input. Please enter Y or N.")
# If invalid, continue the outer while True loop to re-prompt the initial choice.
continue
else:
print("Invalid input. Please select '1' or '2'.")
# Continue the outer while True loop to re-prompt the initial choice.
continue
def query_equip(player: Player):
def query_equip(): """Allows the player to view or change equipped items."""
while True: while True:
print("Do you want to:\n" print("Do you want to:\n"
"1) View your equipped items\n" "1) View your equipped items\n"
@@ -136,15 +163,15 @@ def query_equip():
"3) Return") "3) Return")
response = input(">> ") response = input(">> ")
if response == "1": if response == "1":
current_equipment() player.inventory.current_equipment()
elif response == "2": elif response == "2":
change_equip() change_equip(player)
elif response == "3": elif response == "3":
break break
def change_equip(player: Player):
def change_equip(): """Handles the process of changing equipped items."""
canAddAttunement() player.inventory.update_attunement() # Ensure attunement is up-to-date
while True: while True:
response = input("Which equipment slot would you like to change?\n" response = input("Which equipment slot would you like to change?\n"
"1) Weapon\n" "1) Weapon\n"
@@ -152,139 +179,135 @@ def change_equip():
"3) Other\n" "3) Other\n"
"4) Return\n" "4) Return\n"
">> ").title() ">> ").title()
if response not in ("1", "2", "3", "4", "Weapon", "Armor", "Other", "Return"):
print("Sorry I didn't recognise that. Please try again.\n")
change_equip()
elif response in ("1", "Weapon"): # Weapon
itemlist = ["Return"] # create blank list for items
for item_key, item_value in Inventory.items(): # item, attribute
for key, value in item_value.items(): # attribute, stat
if key == "object" and value == Weapon: # if item = class `Weapon`
itemlist.append(item_key)
if item_key in Equipment.values():
itemlist.remove(item_key)
if len(itemlist) == 1:
print("You have nothing available to equip.\n")
else:
print("What would you like to equip?\n")
for i, name in enumerate(itemlist, start=1):
option = f'{i}) {name}\n'
print(option)
selection = int(input(">> "))
for i, name in enumerate(itemlist, start=1):
if selection == i:
if name == "Return":
break
elif name.itemType == ItemType.Weapon:
if name.attunement: # if item has attunement
if not canAddAttunement(): # check if can add another attuned item
if Equipment["Main Hand"].attunement: # if attune is max, check if swapped weapon is attuned
if name.versatile:
Equipment["Main Hand"] = name
Equipment["Off Hand"] = name
elif name.slot == "Main Hand":
Equipment["Main Hand"] = name
Equipment["Off Hand"] = None
elif name.slot == "Two Handed":
Equipment["Main Hand"] = None
Equipment["Off Hand"] = None
Equipment["Two Handed"] = name
else:
print("\n Cannot equip items: Too many attuned items equipped") # if not attuned, it refuses the equip.
break
else: # If canAddAttunement = True
if name.versatile:
Equipment["Main Hand"] = name
Equipment["Off Hand"] = name
elif name.slot == "Main Hand":
Equipment["Main Hand"] = name
Equipment["Off Hand"] = None
elif name.slot == "Two Handed":
Equipment["Main Hand"] = None
Equipment["Off Hand"] = None
Equipment["Two Handed"] = name
print(f"{current_equipment()}") if response in ("1", "Weapon"):
elif response in ("2", "Armor"): # Armor # Filter weapons from inventory that are not currently equipped in weapon slots
itemlist = ["Return"] # create blank list for items itemlist = [item_obj for item_obj, item_data in player.inventory.items.items()
for item_key, item_value in Inventory.items(): # item, attribute if item_data["object"] == ItemType.Weapon and
for key, value in item_value.items(): # attribute, stat item_obj not in [player.inventory.equipped_items[Slots.MainHand],
if key == "object" and value == Armor: # if item = class `Weapon` player.inventory.equipped_items[Slots.OffHand],
itemlist.append(item_key) # Add item type to list player.inventory.equipped_items[Slots.TwoHanded]]]
if item_key in Equipment.values(): itemlist.append("Return") # Add return option last
itemlist.remove(item_key) # remove from list if currently equipped -
# consider if holding multiple objects if not itemlist or (len(itemlist) == 1 and itemlist[0] == "Return"):
if len(itemlist) == 1: print("You have no unequipped weapons available in your inventory.\n")
print("You have nothing available to equip.\n")
else: else:
print("What would you like to equip?\n") print("What would you like to equip?\n")
for i, name in enumerate(itemlist, start=1): for i, item_obj in enumerate(itemlist, start=1):
option = f'{i}) {name}' if item_obj == "Return":
print(option) print(f'{i}) {item_obj}')
selection = int(input(">> ")) else:
for i, name in enumerate(itemlist, start=1): print(f'{i}) {item_obj.name}')
if selection == i:
if name == "Return": try:
selection = int(input(">> "))
if 1 <= selection <= len(itemlist):
chosen_item = itemlist[selection - 1]
if chosen_item == "Return":
break break
elif name.itemType == Armor: else:
try: # Determine the correct slot based on weapon type
if name.attunment: if chosen_item.slot == Slots.TwoHanded:
print("Not coded attunement yet") # if item has attunement - check availability player.inventory.equip_item(chosen_item, Slots.TwoHanded)
except AttributeError: # if no attunement elif chosen_item.versatile: # For versatile, equip to main hand
if name.slot == Slots.Helm: player.inventory.equip_item(chosen_item, Slots.MainHand)
equip = {"Helm": name} else: # Default to main hand for 1H weapons
Equipment.update(equip) player.inventory.equip_item(chosen_item, Slots.MainHand)
elif name.slot == Slots.Chest: player.inventory.current_equipment()
equip = {"Chest": name} else:
Equipment.update(equip) print("Invalid selection.")
elif name.slot == Slots.Wrists: except ValueError:
equip = {"Wrists": name} print("Invalid input. Please enter a number.")
Equipment.update(equip)
elif name.slot == Slots.Feet: elif response in ("2", "Armor"):
equip = {"Feet": name} itemlist = [item_obj for item_obj, item_data in player.inventory.items.items()
Equipment.update(equip) if item_data["object"] == ItemType.Armor and
print(f"You now have equipped: \n" item_obj not in [player.inventory.equipped_items[Slots.Helm],
f"{current_equipment()}") player.inventory.equipped_items[Slots.Chest],
elif response in ("3", "Other"): # Other player.inventory.equipped_items[Slots.Wrists],
itemlist = ["Return"] # create blank list for items player.inventory.equipped_items[Slots.Feet]]]
for item_key, item_value in Inventory.items(): # item, attribute itemlist.append("Return")
for key, value in item_value.items(): # attribute, stat
if key == "object" and value == Armor: # if item = class `Weapon` if not itemlist or (len(itemlist) == 1 and itemlist[0] == "Return"):
itemlist.append(item_key) # Add item type to list print("You have no unequipped armor available in your inventory.\n")
if item_key in Equipment.values():
itemlist.remove(item_key) # remove from list if currently equipped -
# consider if holding multiple objects
if len(itemlist) == 1:
print("You have nothing available to equip.\n")
else: else:
print("What would you like to equip?\n") print("What would you like to equip?\n")
for i, name in enumerate(itemlist, start=1): for i, item_obj in enumerate(itemlist, start=1):
option = f'{i}) {name}' if item_obj == "Return":
print(option) print(f'{i}) {item_obj}')
selection = int(input(">> ")) else:
for i, name in enumerate(itemlist, start=1): print(f'{i}) {item_obj.name}')
if selection == i:
if name == "Return": try:
selection = int(input(">> "))
if 1 <= selection <= len(itemlist):
chosen_item = itemlist[selection - 1]
if chosen_item == "Return":
break break
elif name.itemType == Armor: else:
try: # Logic for equipping armor based on its intended slot
if name.attunment: if chosen_item.slot == Slots.Helm:
print("Not coded attunement yet") # if item has attunement - check availability player.inventory.equip_item(chosen_item, Slots.Helm)
except AttributeError: # if no attunement elif chosen_item.slot == Slots.Chest:
if name.slot == Slots.Neck: player.inventory.equip_item(chosen_item, Slots.Chest)
equip = {"Neck": name} elif chosen_item.slot == Slots.Wrists:
Equipment.update(equip) player.inventory.equip_item(chosen_item, Slots.Wrists)
elif name.slot == Slots.Cloak: elif chosen_item.slot == Slots.Feet:
equip = {"Cloak": name} player.inventory.equip_item(chosen_item, Slots.Feet)
Equipment.update(equip) else:
elif name.slot == Slots.LeftRing: print(f"This armor ({chosen_item.name}) doesn't seem to fit a standard slot.")
equip = {"Left Ring": name} player.inventory.current_equipment()
Equipment.update(equip) else:
elif name.slot == Slots.RightRing: print("Invalid selection.")
equip = {"Right Ring": name} except ValueError:
Equipment.update(equip) print("Invalid input. Please enter a number.")
print(f"You now have equipped: \n"
f"{current_equipment()}") elif response in ("3", "Other"):
itemlist = [item_obj for item_obj, item_data in player.inventory.items.items()
if item_data["object"] == ItemType.Item and
item_obj not in [player.inventory.equipped_items[Slots.Neck],
player.inventory.equipped_items[Slots.Cloak],
player.inventory.equipped_items[Slots.LeftRing],
player.inventory.equipped_items[Slots.RightRing],
player.inventory.equipped_items[Slots.Other]]]
itemlist.append("Return")
if not itemlist or (len(itemlist) == 1 and itemlist[0] == "Return"):
print("You have no other unequipped items available in your inventory.\n")
else:
print("What would you like to equip?\n")
for i, item_obj in enumerate(itemlist, start=1):
if item_obj == "Return":
print(f'{i}) {item_obj}')
else:
print(f'{i}) {item_obj.name}')
try:
selection = int(input(">> "))
if 1 <= selection <= len(itemlist):
chosen_item = itemlist[selection - 1]
if chosen_item == "Return":
break
else:
# Logic for equipping other items based on their intended slot
if chosen_item.slot == Slots.Neck:
player.inventory.equip_item(chosen_item, Slots.Neck)
elif chosen_item.slot == Slots.Cloak:
player.inventory.equip_item(chosen_item, Slots.Cloak)
elif chosen_item.slot == Slots.LeftRing:
player.inventory.equip_item(chosen_item, Slots.LeftRing)
elif chosen_item.slot == Slots.RightRing:
player.inventory.equip_item(chosen_item, Slots.RightRing)
elif chosen_item.slot == Slots.Other:
player.inventory.equip_item(chosen_item, Slots.Other)
else:
print(f"This item ({chosen_item.name}) doesn't seem to fit a standard 'other' slot.")
player.inventory.current_equipment()
else:
print("Invalid selection.")
except ValueError:
print("Invalid input. Please enter a number.")
elif response in ("4", "Return"): elif response in ("4", "Return"):
break break
else: else:
@@ -299,23 +322,10 @@ def get_instructions():
"To travel to a new area, just type 'Go north' or 'enter cave' etc.\n" "To travel to a new area, just type 'Go north' or 'enter cave' etc.\n"
"To replay the description of the current area, type 'location'.") "To replay the description of the current area, type 'location'.")
print(descrip1) print(descrip1)
time.sleep(5) time.sleep(1) # Reduced sleep for faster testing
print(descrip2) print(descrip2)
def canAddAttunement():
attune = 0
for slot, equipment in Equipment.items():
if isinstance(equipment, Weapon):
if equipment.attunement:
attune += 1
Equipment["Attunement"] = attune
if attune > 3:
return False
else:
return True
def error_message(): def error_message():
print("That command was not recognised. Please try again.") print("That command was not recognised. Please try again.")
@@ -326,95 +336,80 @@ def parse(input_text):
remaining_words_index = None remaining_words_index = None
words = input_text.split() words = input_text.split()
if len(words) > 0: if not words: # Handle empty input
if words[0] == "help": return "error", None
command = "help"
if words[0] == "scene": # Check for multi-word commands first to avoid partial matches
command = "scene" if len(words) >= 2:
if words[0] == "check" and words[1] in ("inventory", "bag", "backpack"):
if words[0] in ("view", "check", "show"):
if words[1] in ("inventory", "bag", "backpack"):
command = "inventory"
elif words[1] in ("equipment", "equip", "items"):
command = "equipment"
elif words[1] == "stats":
command = "stats"
elif words[1] in ("hp", "hitpoints", "health"):
command = "hp"
elif words[1] == "hit" and words[2] == "points":
command = "hp"
if words[0] in ("equip", "equipment"):
command = "equipment"
if words[0] in ("inventory", "bag", "backpack"):
command = "inventory" command = "inventory"
return command, object1
found_examine_words = False elif words[0] == "check" and words[1] in ("equipment", "equip", "items"):
if (words[0] == "examine") and len(words) > 1: command = "equipment"
found_examine_words = True return command, object1
remaining_words_index = 1 elif words[0] == "check" and words[1] == "stats":
command = "stats"
if found_examine_words: return command, object1
remaining_words = "" elif words[0] == "check" and words[1] in ("hp", "hitpoints", "health"):
for i in range(remaining_words_index, len(words)): command = "hp"
remaining_words += words[i] return command, object1
if i < len(words) - 1: elif words[0] == "go":
remaining_words += " " command = "go"
command = "examine" object1 = " ".join(words[1:]) # The rest of the words are the direction
object1 = remaining_words return command, object1
elif words[0] == "pick" and words[1] == "up" and len(words) > 2:
found_take_words = False
if ((words[0] == "take") and len(words) > 1) or \
((words[0] == "pick") and (words[1] == "up") and len(words) > 2):
found_take_words = True
remaining_words_index = 1
if found_take_words:
remaining_words = ""
for i in range(remaining_words_index, len(words)):
remaining_words += words[i]
if i < len(words) - 1:
remaining_words += " "
command = "take" command = "take"
object1 = remaining_words object1 = " ".join(words[2:])
return command, object1
found_loot_words = False # Single-word commands
if (words[0] == "loot") and len(words) > 1: if words[0] == "help":
found_loot_words = True command = "help"
remaining_words_index = 1 elif words[0] == "scene" or words[0] == "location": # Added 'location' as an alias
command = "scene"
if found_loot_words: elif words[0] in ("inventory", "bag", "backpack"):
remaining_words = "" command = "inventory"
for i in range(remaining_words_index, len(words)): elif words[0] in ("equip", "equipment"):
remaining_words += words[i] command = "equipment"
if i < len(words) - 1: elif words[0] == "stats":
remaining_words += " " command = "stats"
elif words[0] in ("hp", "hitpoints", "health"):
command = "hp"
elif words[0] == "examine":
if len(words) > 1:
command = "examine"
object1 = " ".join(words[1:])
else:
command = "examine" # User needs to specify what to examine
object1 = None
elif words[0] == "take":
if len(words) > 1:
command = "take"
object1 = " ".join(words[1:])
else:
command = "take" # User needs to specify what to take
object1 = None
elif words[0] == "loot":
if len(words) > 1:
command = "loot" command = "loot"
object1 = remaining_words object1 = " ".join(words[1:])
else:
found_drop_words = False command = "loot" # User needs to specify what to loot
if (words[0] == "drop") and len(words) > 1: object1 = None
found_drop_words = True elif words[0] == "drop":
remaining_words_index = 1 if len(words) > 1:
if found_drop_words:
remaining_words = ""
for i in range(remaining_words_index, len(words)):
remaining_words += words[i]
if i < len(words) - 1:
remaining_words += " "
command = "drop" command = "drop"
object1 = remaining_words object1 = " ".join(words[1:])
else:
if words[0] not in ("view", "check", "show", "loot", "examine", "take", "equip", "equipment", "inventory", command = "drop" # User needs to specify what to drop
"bag", "backpack", "drop"): object1 = None
command = "error" elif words[0] == "quit":
command = "quit"
else:
command = "error" # Default for unrecognized commands
return command, object1 return command, object1
# def skill_check(skill): # def skill_check(skill):
# """Roll a d20 and add modifier # """Roll a d20 and add modifier
# Return value to compare vs a hardcoded DC""" # Return value to compare vs a hardcoded DC"""
@@ -429,4 +424,4 @@ def parse(input_text):
def calc_weight(): def calc_weight():
pass pass # Placeholder for future weight calculation