Files
d-crawler/CLAUDE.md
T
2026-07-12 10:36:26 +02:00

3.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

A standalone, dependency-light Python prototype for a turn-based text RPG dungeon-crawler: generate rooms populated with random mobs, fight through them, quit or die. No relationship to the other Godot projects in eliron-worlds (eliron-world-dungeons, POC/elirons_knights) is documented — despite the mob roster below sharing race names with the eliron-world-dungeons GDD, treat that as coincidental/unverified, not an established asset or code link.

Commands

  • Run the game: python app.py (must run from this directory — save/load uses relative paths like <name>.json in the CWD)
  • Run tests: python -m unittest test_character_builder.py (or python test_character_builder.py) — only character_builder.py has tests
  • No requirements.txt/pyproject.toml. Only external dependency is pydantic, and it's optional — see below.

Architecture

  • base_mob.pyBaseMob, the single entity class for both players and enemies (mob_type: FRIEND/NEUTRAL/ENEMY). change_pv() applies protection as damage reduction on negative deltas; perform_attack() loops speed times per attack call.
  • mobs_utils.py — a fixed roster of 3 hardcoded BaseMob instances (Yanaar, Ulnarain, Skroll), generate_random_mob_list() (picks a random subset), and generate_random_rooms() (distributes mobs into rooms — mutates the input list via pop(0), so it consumes mobs_in_level as a side effect rather than just reading it).
  • level_one.pyLevel: owns player, generates mobs_in_level/rooms at construction, tracks current_room_index, and exposes combat() (turn order decided by speed). Its own if __name__ == "__main__": block duplicates a second, slightly different interactive game loop from app.py (this one skips the flee/combat submenu and always fights) — don't assume one is canonical over the other; check both if you change the room/combat flow.
  • app.py — the actual entrypoint, with its own action_menu()/game loop (separate from level_one.py's), plus a submenu per mob (2 = fight, 3 = flee).
  • menu.py — entirely commented-out dead code, not imported anywhere. Both app.py and level_one.py define their own local action_menu() instead.
  • character_builder.pyCharacterBuilder is a thin dispatcher: save_character_impl/load_character_impl class attributes are wired at import time to either the module-level save_character/load_character (plain JSON) or, if ELIRON_BUILDER=pydantic is set and pydantic is actually importable (soft-detected via importlib.util.find_spec, no hard dependency), to pydantic_character_builder.py's equivalents. Adding a third backend means implementing matching save_character(character) -> str / load_character(name) -> BaseMob | None functions and adding a branch to this wiring block.
  • pydantic_character_builder.py — same persistence contract as above, implemented with a pydantic CharacterModel instead of manual json.dump/json.load.
  • Hector.json / Jamin.json — pre-made saved characters checked into the repo root (loaded by name via CharacterBuilder.load_character); test_character_builder.py creates/removes its own Arthur.json fixture and doesn't touch these.