Files
Kanjin/scene.py
2025-07-13 23:28:56 +12:00

172 lines
7.8 KiB
Python

import sys
# Add the current directory to sys.path to allow imports from sibling files
sys.path.append('.')
from player import Item, Weapon, Armor, rock, dagger, polearm, tornRags, paper, GP1, SP1, CP1
from enum_list import *
class Scene:
"""
Represents a single location or area in the game.
Each scene has a name, a description, and defines its exits to other scenes.
It can also contain items that can be looted from containers/bodies or
items that are simply available to be picked up.
"""
def __init__(self, name, description, exits=None, lootable_items=None, available_items=None):
self.name = name
self.description = description
# Exits are a dictionary mapping direction (str) to Scene objects
self.exits = exits if exits is not None else {}
# Lootable items are typically found within containers or on enemies.
# Format: {"container_name": {item_obj: count, ...}, ...}
self.lootable_items = lootable_items if lootable_items is not None else {}
# Available items are items lying around in the scene.
# Format: {item_obj: count, ...}
self.available_items = available_items if available_items is not None else {}
def __str__(self):
"""Returns the description of the scene."""
return self.description
def add_exit(self, direction, scene):
"""
Adds an exit from this scene to another scene.
:param direction: The direction (e.g., "north", "east") as a string.
:param scene: The Scene object to link to.
"""
self.exits[direction.lower()] = scene
def get_exit(self, direction):
"""
Returns the Scene object for a given direction, or None if no exit exists.
:param direction: The direction to check.
:return: The Scene object or None.
"""
return self.exits.get(direction.lower())
def add_lootable_item(self, container_name, item_obj, count=1):
"""
Adds an item to a lootable container within the scene.
:param container_name: The name of the container (e.g., "chest", "goblin corpse").
:param item_obj: The Item object to add.
:param count: The quantity of the item.
"""
if container_name not in self.lootable_items:
self.lootable_items[container_name] = {}
self.lootable_items[container_name][item_obj] = self.lootable_items[container_name].get(item_obj, 0) + count
def add_available_item(self, item_obj, count=1):
"""
Adds an item that is freely available in the scene.
:param item_obj: The Item object to add.
:param count: The quantity of the item.
"""
self.available_items[item_obj] = self.available_items.get(item_obj, 0) + count
def remove_available_item(self, item_obj, count=1):
"""
Removes a specified count of an available item from the scene.
:param item_obj: The Item object to remove.
:param count: The quantity to remove.
"""
if item_obj in self.available_items:
self.available_items[item_obj] -= count
if self.available_items[item_obj] <= 0:
del self.available_items[item_obj]
def remove_lootable_item(self, container_name, item_obj, count=1):
"""
Removes a specified count of an item from a lootable container in the scene.
:param container_name: The name of the container.
:param item_obj: The Item object to remove.
:param count: The quantity to remove.
"""
if container_name in self.lootable_items and item_obj in self.lootable_items[container_name]:
self.lootable_items[container_name][item_obj] -= count
if self.lootable_items[container_name][item_obj] <= 0:
del self.lootable_items[container_name][item_obj]
if not self.lootable_items[container_name]: # If container is empty, remove it
del self.lootable_items[container_name]
# --- Default Scenes ---
# Scene 0: Tutorial
tutorial = Scene(
name="Tutorial",
description="Welcome to Kanjin Text RPG!\n\n"
"This is a very simple tutorial to show you the basics of issuing commands.\n"
"Important commands you'll want to know can be found by typing 'Help'.\n\n"
"These are the available commands:\n"
"Help - Prints this help message.\n"
"Check inventory | bag | backpack - Lists items you are carrying.\n"
" 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."
)
tutorial.add_available_item(rock, 1)
tutorial.add_available_item(paper, 2)
tutorial.add_lootable_item("suspicious tree trunk", Item("Test Item",
"This is for testing purposes", None,
False, ItemType.Item, False), 1)
# Scene 1: Starting Clearing
starting_clearing = Scene(
name="Starting Clearing",
description="You are in a small clearing, surrounded by tall, ancient trees. "
"A faint, overgrown path leads north, and a darker, narrower trail goes east. "
"Sunlight filters through the canopy, dappling the forest floor. "
"You notice a small, weathered wooden chest near a fallen log."
)
starting_clearing.add_available_item(rock, 3) # Rocks lying on the ground
starting_clearing.add_lootable_item("small wooden chest", GP1, 15)
starting_clearing.add_lootable_item("small wooden chest", SP1, 20)
# Scene 2: Forest Path
forest_path = Scene(
name="Forest Path",
description="The path winds deeper into the whisper-quiet forest. The trees here are "
"ancient and gnarled, their branches intertwining overhead, creating a dense canopy. "
"The air is thick with the scent of pine needles and damp earth. "
"You hear the distant caw of a crow. The clearing is to the south."
)
forest_path.add_available_item(dagger, 1) # A lone dagger dropped on the path
# Scene 3: Dark Cave Entrance
dark_cave_entrance = Scene(
name="Dark Cave Entrance",
description="The narrow trail ends abruptly at the jagged mouth of a dark, foreboding cave. "
"A chilling, damp wind blows from within, carrying the faint smell of mildew and something else... "
"something ancient. The entrance is shrouded in thick vines. "
"The clearing is to the west."
)
dark_cave_entrance.add_available_item(polearm, 1) # A polearm leaning against the cave wall
# Link the scenes together
tutorial.add_exit("tutorial", starting_clearing)
starting_clearing.add_exit("north", forest_path)
starting_clearing.add_exit("east", dark_cave_entrance)
forest_path.add_exit("south", starting_clearing)
dark_cave_entrance.add_exit("west", starting_clearing)
# Global map for easy scene access (optional, could also be managed by an Engine class)
Map = {
"Starting Clearing": starting_clearing,
"Forest Path": forest_path,
"Dark Cave Entrance": dark_cave_entrance,
"Tutorial": tutorial,
}