Fixed bug where selecting take all of leave when looting a chest would register as an invalid command.

This commit is contained in:
kansaigaijin
2025-07-13 22:52:38 +12:00
parent 56806178f3
commit 509fb35a20
2 changed files with 98 additions and 72 deletions

View File

@@ -363,9 +363,18 @@ def get_instructions():
descrip1 = ("There are certain commands that will be available almost anytime you are able to type\n" descrip1 = ("There are certain commands that will be available almost anytime you are able to type\n"
"such as viewing your inventory, checking your equipped items, and also changing them.\n" "such as viewing your inventory, checking your equipped items, and also changing them.\n"
"You can also view your stats including your current and max hp.\n") "You can also view your stats including your current and max hp.\n")
descrip2 = ("Some examples are: 'Check inventory', 'Check equipment', and 'View stats'.\n" descrip2 = ("Help - Prints this help message.\n"
"To travel to a new area, just type 'Go north' or 'Enter cave' etc.\n" "Check inventory | bag | backpack - Lists items you are carrying.\n"
"To replay the description of the current area, type 'Location', or 'Scene'.") " Can also just enter 'inventory | bag | backpack\n"
"Check equipment | equipped | items - Lists items you have equipped\n"
" Can also just enter 'equipment | equipped | items\n"
"Check stats or Check hitpoints | hp | health - Shows your stat block or current health details\n"
" Can also just enter 'stats | health | hitpoints | hp\n"
"Go *direction* - Each scene will give you available directions i.e North\n"
"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.")
print(descrip1) print(descrip1)
time.sleep(3) # Reduced sleep for faster testing time.sleep(3) # Reduced sleep for faster testing
print(descrip2) print(descrip2)
@@ -398,7 +407,7 @@ def parse(input_text):
elif words[0] == "check" and words[1] in ("hp", "hitpoints", "health"): elif words[0] == "check" and words[1] in ("hp", "hitpoints", "health"):
command = "hp" command = "hp"
return command, object1 return command, object1
elif words[0] in ("go", "enter"): elif words[0] in ("go", "enter", "exit"):
command = "go" command = "go"
object1 = " ".join(words[1:]) # The rest of the words are the direction object1 = " ".join(words[1:]) # The rest of the words are the direction
return command, object1 return command, object1
@@ -409,6 +418,10 @@ def parse(input_text):
elif words[0] == "look" and words[1] == "around" and len(words) == 2: elif words[0] == "look" and words[1] == "around" and len(words) == 2:
command = "look_around" command = "look_around"
return command, object1 return command, object1
elif words[0] == "exit" and words[1] == "tutorial" and len(words) == 2:
command = "go"
object1 = " ".join(words[1:])
return command, object1
# Single-word commands # Single-word commands
if words[0] == "help": if words[0] == "help":

133
main.py
View File

@@ -1,11 +1,8 @@
import sys import sys
# Add the current directory to sys.path to allow imports from sibling files # Add the current directory to sys.path to allow imports from sibling files
sys.path.append('.') sys.path.append('.')
# Import classes and functions from your existing files from player import Player
from player import Player, Inventory
from function_list import startGame, parse, error_message, get_instructions from function_list import startGame, parse, error_message, get_instructions
from job_list import Barbarian, Cleric, Wizard
from race_list import Elf, Dwarf, Human
from scene import * from scene import *
@@ -186,72 +183,88 @@ class Engine:
else: else:
print("You don't see any of those lying around to take.") print("You don't see any of those lying around to take.")
def loot_container(self, container_name): def loot_container(self, container_name):
""" """Allows the player to loot items from a specified container."""
Attempts to loot items from a container in the current scene. container_found = False
:param container_name: The name of the container to loot. for current_container_name, items_in_container in list(self.current_scene.lootable_items.items()):
""" if current_container_name.lower() == container_name.lower():
found_container = False container_found = True
container_items = {} if not items_in_container:
for c_name, items_in_c in self.current_scene.lootable_items.items():
if container_name.lower() in c_name.lower():
container_items = items_in_c
found_container = True
break
if found_container:
if not container_items or all(count == 0 for count in container_items.values()):
print(f"The {container_name} is empty.") print(f"The {container_name} is empty.")
return return
print(f"You look inside the {container_name}. You see:") print(f"You look inside the {container_name}. You see:")
loot_options = [] loot_list = list(items_in_container.items()) # List of (item_obj, count) tuples
for i, (item_obj, count) in enumerate(container_items.items()):
if count > 0:
print(f"{i+1}) {item_obj.name} (x{count})")
loot_options.append((item_obj, count))
print(f"{len(loot_options) + 1}) Take all")
print(f"{len(loot_options) + 2}) Leave")
while True: while True:
try: for i, (item_obj, count) in enumerate(loot_list, 1):
choice = input("What would you like to take? (number or 'take all'/'leave')\n>> ").lower() print(f"{i}) {item_obj.name} (x{count})")
if choice == "leave":
print(f"You close the {container_name}.") # Dynamically determine the numbers for "Take all" and "Leave"
break take_all_option = len(loot_list) + 1
elif choice == "take all": leave_option = len(loot_list) + 2
for item_obj, count in loot_options:
print(f"{take_all_option}) Take all")
print(f"{leave_option}) Leave")
choice = input("What would you like to take? (number or 'take all'/'leave')\n>> ").lower().strip()
# --- MODIFIED LOGIC START ---
if choice == "take all" or (choice.isdigit() and int(choice) == take_all_option):
for item_obj, count in list(items_in_container.items()):
self.player.inventory.add_item(item_obj, count) self.player.inventory.add_item(item_obj, count)
self.current_scene.remove_lootable_item(container_name, item_obj, count) print(f"- Took {count} {item_obj.name}")
print(f"You took everything from the {container_name}.") del items_in_container[item_obj]
break
elif choice.isdigit():
index = int(choice) - 1
if 0 <= index < len(loot_options):
item_obj, count = loot_options[index]
self.player.inventory.add_item(item_obj, count)
self.current_scene.remove_lootable_item(container_name, item_obj, count)
print(f"You took the {item_obj.name}.")
# Re-display options if there's still loot
if any(c > 0 for c in container_items.values()):
print(f"Remaining items in {container_name}:")
for i, (item_obj, count) in enumerate(container_items.items()):
if count > 0:
print(f"{i+1}) {item_obj.name} (x{count})")
print(f"{len(loot_options) + 1}) Take all")
print(f"{len(loot_options) + 2}) Leave")
else:
print(f"The {container_name} is now empty.") print(f"The {container_name} is now empty.")
break return
elif choice == "leave" or (choice.isdigit() and int(choice) == leave_option):
print(f"You leave the {container_name} untouched.")
return
else: # Now this 'else' only deals with potential item selections
try:
selection_index = int(choice) - 1
if 0 <= selection_index < len(loot_list):
item_obj, current_count = loot_list[selection_index]
take_count_input = input(
f"How many {item_obj.name} will you take? (enter 'all' or a number)\n>> ").lower().strip()
if take_count_input == "all":
take_count = current_count
else: else:
print("Invalid selection.") try:
else: take_count = int(take_count_input)
print("Invalid input. Please enter a number, 'take all', or 'leave'.")
except ValueError: except ValueError:
print("Invalid input. Please enter a number, 'take all', or 'leave'.") print("Invalid amount. Please enter 'all' or a number.")
continue # Go back to the main loot menu
if take_count > 0 and take_count <= current_count:
self.player.inventory.add_item(item_obj, take_count)
items_in_container[item_obj] -= take_count
print(f"You took {take_count} {item_obj.name}.")
if items_in_container[item_obj] <= 0:
del items_in_container[item_obj]
loot_list = list(items_in_container.items()) # Rebuild loot_list
if not items_in_container:
print(f"The {container_name} is now empty.")
return
elif not loot_list: # This handles if all items were individually taken and loot_list becomes empty
print(f"The {container_name} is now empty.")
return
else: else:
print("You don't see a container like that here to loot.") print("Invalid amount or not enough items.")
else:
print("Invalid selection. Please choose a valid item number, 'take all', or 'leave'.")
except ValueError:
print("Invalid selection. Please enter a number, 'take all', or 'leave'.")
# --- MODIFIED LOGIC END ---
# This return is unreachable if the while True loop has a return path for all conditions
# but it doesn't hurt as a safeguard if logic changes later.
return
if not container_found:
print(f"You don't see a '{container_name}' here to loot.")
# Initialize the game engine # Initialize the game engine
@@ -326,8 +339,8 @@ def main_game_loop():
game_engine.player.drop_item(obj1) game_engine.player.drop_item(obj1)
else: else:
print("What would you like to drop?") print("What would you like to drop?")
elif command.startswith("go "): elif command == "go":
direction = command.split(" ", 1)[1] direction = obj1
game_engine.move_to_scene(direction) game_engine.move_to_scene(direction)
elif command == "quit": elif command == "quit":
print("Thanks for playing!") print("Thanks for playing!")