diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0dea84c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,458 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Gitea-First Workflow + +**IMPORTANT**: This project uses Gitea for issue tracking, documentation, and project management. Always consult and update Gitea resources before and during development work. + +**Gitea Instance**: https://gamedev.ffwf.net/gitea/john/McRogueFace + +### Core Principles + +1. **Gitea is the Single Source of Truth** + - Issue tracker contains current tasks, bugs, and feature requests + - Wiki contains living documentation and architecture decisions + - Use Gitea MCP tools to query and update issues programmatically + +2. **Always Check Gitea First** + - Before starting work: Check open issues for related tasks or blockers + - When using `/roadmap` command: Query Gitea for up-to-date issue status + - When researching a feature: Search Gitea wiki and issues before grepping codebase + - When encountering a bug: Check if an issue already exists + +3. **Create Granular Issues** + - Break large features into separate, focused issues + - Each issue should address one specific problem or enhancement + - Tag issues appropriately: `[Bugfix]`, `[Major Feature]`, `[Minor Feature]`, etc. + - Link related issues using dependencies or blocking relationships + +4. **Document as You Go** + - When work on one issue interacts with another system: Add notes to related issues + - When discovering undocumented behavior: Create task to document it + - When documentation misleads you: Create task to correct or expand it + - When implementing a feature: Update the Gitea wiki if appropriate + +5. **Cross-Reference Everything** + - Commit messages should reference issue numbers (e.g., "Fixes #104", "Addresses #125") + - Issue comments should link to commits when work is done + - Wiki pages should reference relevant issues for implementation details + - Issues should link to each other when dependencies exist + +### Workflow Pattern + +``` +┌─────────────────────────────────────────────────────┐ +│ 1. Check Gitea Issues & Wiki │ +│ - Is there an existing issue for this? │ +│ - What's the current status? │ +│ - Are there related issues or blockers? │ +└─────────────────┬───────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 2. Create Issues (if needed) │ +│ - Break work into granular tasks │ +│ - Tag appropriately │ +│ - Link dependencies │ +└─────────────────┬───────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 3. Do the Work │ +│ - Implement/fix/document │ +│ - Write tests first (TDD) │ +│ - Add inline documentation │ +└─────────────────┬───────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 4. Update Gitea │ +│ - Add notes to affected issues │ +│ - Create follow-up issues for discovered work │ +│ - Update wiki if architecture/APIs changed │ +│ - Add documentation correction tasks │ +└─────────────────┬───────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 5. Commit & Reference │ +│ - Commit messages reference issue numbers │ +│ - Close issues or update status │ +│ - Add commit links to issue comments │ +└─────────────────────────────────────────────────────┘ +``` + +### Benefits of Gitea-First Approach + +- **Reduced Context Switching**: Check brief issue descriptions instead of re-reading entire codebase +- **Better Planning**: Issues provide roadmap; avoid duplicate or contradictory work +- **Living Documentation**: Wiki and issues stay current as work progresses +- **Historical Context**: Issue comments capture why decisions were made +- **Efficiency**: MCP tools allow programmatic access to project state + +### MCP Tools Available + +Claude Code has access to Gitea MCP tools for: +- `list_repo_issues` - Query current issues with filtering +- `get_issue` - Get detailed issue information +- `create_issue` - Create new issues programmatically +- `create_issue_comment` - Add comments to issues +- `edit_issue` - Update issue status, title, body +- `add_issue_labels` - Tag issues appropriately +- `add_issue_dependency` / `add_issue_blocking` - Link related issues +- Plus wiki, milestone, and label management tools + +Use these tools liberally to keep the project organized! + +## Build Commands + +```bash +# Build the project (compiles to ./build directory) +make + +# Or use the build script directly +./build.sh + +# Run the game +make run + +# Clean build artifacts +make clean + +# The executable and all assets are in ./build/ +cd build +./mcrogueface +``` + +## Project Architecture + +McRogueFace is a C++ game engine with Python scripting support, designed for creating roguelike games. The architecture consists of: + +### Core Engine (C++) +- **Entry Point**: `src/main.cpp` initializes the game engine +- **Scene System**: `Scene.h/cpp` manages game states +- **Entity System**: `UIEntity.h/cpp` provides game objects +- **Python Integration**: `McRFPy_API.h/cpp` exposes engine functionality to Python +- **UI Components**: `UIFrame`, `UICaption`, `UISprite`, `UIGrid` for rendering + +### Game Logic (Python) +- **Main Script**: `src/scripts/game.py` contains game initialization and scene setup +- **Entity System**: `src/scripts/cos_entities.py` implements game entities (Player, Enemy, Boulder, etc.) +- **Level Generation**: `src/scripts/cos_level.py` uses BSP for procedural dungeon generation +- **Tile System**: `src/scripts/cos_tiles.py` implements Wave Function Collapse for tile placement + +### Key Python API (`mcrfpy` module) +The C++ engine exposes these primary functions to Python: +- Scene Management: `createScene()`, `setScene()`, `sceneUI()` +- Entity Creation: `Entity()` with position and sprite properties +- Grid Management: `Grid()` for tilemap rendering +- Input Handling: `keypressScene()` for keyboard events +- Audio: `createSoundBuffer()`, `playSound()`, `setVolume()` +- Timers: `setTimer()`, `delTimer()` for event scheduling + +## Development Workflow + +### Running the Game +After building, the executable expects: +- `assets/` directory with sprites, fonts, and audio +- `scripts/` directory with Python game files +- Python 3.12 shared libraries in `./lib/` + +### Modifying Game Logic +- Game scripts are in `src/scripts/` +- Main game entry is `game.py` +- Entity behavior in `cos_entities.py` +- Level generation in `cos_level.py` + +### Adding New Features +1. C++ API additions go in `src/McRFPy_API.cpp` +2. Expose to Python using the existing binding pattern +3. Update Python scripts to use new functionality + +## Testing Game Changes + +Currently no automated test suite. Manual testing workflow: +1. Build with `make` +2. Run `make run` or `cd build && ./mcrogueface` +3. Test specific features through gameplay +4. Check console output for Python errors + +### Quick Testing Commands +```bash +# Test basic functionality +make test + +# Run in Python interactive mode +make python + +# Test headless mode +cd build +./mcrogueface --headless -c "import mcrfpy; print('Headless test')" +``` + +## Common Development Tasks + +### Compiling McRogueFace +```bash +# Standard build (to ./build directory) +make + +# Full rebuild +make clean && make + +# Manual CMake build +mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Release +make -j$(nproc) + +# The library path issue: if linking fails, check that libraries are in __lib/ +# CMakeLists.txt expects: link_directories(${CMAKE_SOURCE_DIR}/__lib) +``` + +### Running and Capturing Output +```bash +# Run with timeout and capture output +cd build +timeout 5 ./mcrogueface 2>&1 | tee output.log + +# Run in background and kill after delay +./mcrogueface > output.txt 2>&1 & PID=$!; sleep 3; kill $PID 2>/dev/null + +# Just capture first N lines (useful for crashes) +./mcrogueface 2>&1 | head -50 +``` + +### Debugging with GDB +```bash +# Interactive debugging +gdb ./mcrogueface +(gdb) run +(gdb) bt # backtrace after crash + +# Batch mode debugging (non-interactive) +gdb -batch -ex run -ex where -ex quit ./mcrogueface 2>&1 + +# Get just the backtrace after a crash +gdb -batch -ex "run" -ex "bt" ./mcrogueface 2>&1 | head -50 + +# Debug with specific commands +echo -e "run\nbt 5\nquit\ny" | gdb ./mcrogueface 2>&1 +``` + +### Testing Different Python Scripts +```bash +# The game automatically runs build/scripts/game.py on startup +# To test different behavior: + +# Option 1: Replace game.py temporarily +cd build +cp scripts/my_test_script.py scripts/game.py +./mcrogueface + +# Option 2: Backup original and test +mv scripts/game.py scripts/game.py.bak +cp my_test.py scripts/game.py +./mcrogueface +mv scripts/game.py.bak scripts/game.py + +# Option 3: For quick tests, create minimal game.py +echo 'import mcrfpy; print("Test"); mcrfpy.createScene("test")' > scripts/game.py +``` + +### Understanding Key Macros and Patterns + +#### RET_PY_INSTANCE Macro (UIDrawable.h) +This macro handles converting C++ UI objects to their Python equivalents: +```cpp +RET_PY_INSTANCE(target); +// Expands to a switch on target->derived_type() that: +// 1. Allocates the correct Python object type (Frame, Caption, Sprite, Grid) +// 2. Sets the shared_ptr data member +// 3. Returns the PyObject* +``` + +#### Collection Patterns +- `UICollection` wraps `std::vector>` +- `UIEntityCollection` wraps `std::list>` +- Different containers require different iteration code (vector vs list) + +#### Python Object Creation Patterns +```cpp +// Pattern 1: Using tp_alloc (most common) +auto o = (PyUIFrameObject*)type->tp_alloc(type, 0); +o->data = std::make_shared(); + +// Pattern 2: Getting type from module +auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity"); +auto o = (PyUIEntityObject*)type->tp_alloc(type, 0); + +// Pattern 3: Direct shared_ptr assignment +iterObj->data = self->data; // Shares the C++ object +``` + +### Working Directory Structure +``` +build/ +├── mcrogueface # The executable +├── scripts/ +│ └── game.py # Auto-loaded Python script +├── assets/ # Copied from source during build +└── lib/ # Python libraries (copied from __lib/) +``` + +### Quick Iteration Tips +- Keep a test script ready for quick experiments +- Use `timeout` to auto-kill hanging processes +- The game expects a window manager; use Xvfb for headless testing +- Python errors go to stderr, game output to stdout +- Segfaults usually mean Python type initialization issues + +## Important Notes + +- The project uses SFML for graphics/audio and libtcod for roguelike utilities +- Python scripts are loaded at runtime from the `scripts/` directory +- Asset loading expects specific paths relative to the executable +- The game was created for 7DRL 2025 as "Crypt of Sokoban" +- Iterator implementations require careful handling of C++/Python boundaries + +## Testing Guidelines + +### Test-Driven Development +- **Always write tests first**: Create automation tests in `./tests/` for all bugs and new features +- **Practice TDD**: Write tests that fail to demonstrate the issue, then pass after the fix is applied +- **Close the loop**: Reproduce issue → change code → recompile → verify behavior change + +### Two Types of Tests + +#### 1. Direct Execution Tests (No Game Loop) +For tests that only need class initialization or direct code execution: +```python +# These tests can treat McRogueFace like a Python interpreter +import mcrfpy + +# Test code here +result = mcrfpy.some_function() +assert result == expected_value +print("PASS" if condition else "FAIL") +``` + +#### 2. Game Loop Tests (Timer-Based) +For tests requiring rendering, game state, or elapsed time: +```python +import mcrfpy +from mcrfpy import automation +import sys + +def run_test(runtime): + """Timer callback - runs after game loop starts""" + # Now rendering is active, screenshots will work + automation.screenshot("test_result.png") + + # Run your tests here + automation.click(100, 100) + + # Always exit at the end + print("PASS" if success else "FAIL") + sys.exit(0) + +# Set up the test scene +mcrfpy.createScene("test") +# ... add UI elements ... + +# Schedule test to run after game loop starts +mcrfpy.setTimer("test", run_test, 100) # 0.1 seconds +``` + +### Key Testing Principles +- **Timer callbacks are essential**: Screenshots and UI interactions only work after the render loop starts +- **Use automation API**: Always create and examine screenshots when visual feedback is required +- **Exit properly**: Call `sys.exit()` at the end of timer-based tests to prevent hanging +- **Headless mode**: Use `--exec` flag for automated testing: `./mcrogueface --headless --exec tests/my_test.py` + +### Example Test Pattern +```bash +# Run a test that requires game loop +./build/mcrogueface --headless --exec tests/issue_78_middle_click_test.py + +# The test will: +# 1. Set up the scene during script execution +# 2. Register a timer callback +# 3. Game loop starts +# 4. Timer fires after 100ms +# 5. Test runs with full rendering available +# 6. Test takes screenshots and validates behavior +# 7. Test calls sys.exit() to terminate +``` + +## Development Best Practices + +### Testing and Deployment +- **Keep tests in ./tests, not ./build/tests** - ./build gets shipped, and tests shouldn't be included + +## Documentation Guidelines + +### Inline C++ Documentation Format + +When adding new methods or modifying existing ones in C++ source files, use this documentation format in PyMethodDef arrays: + +```cpp +{"method_name", (PyCFunction)Class::method, METH_VARARGS | METH_KEYWORDS, + "method_name(arg1: type, arg2: type = default) -> return_type\n\n" + "Brief description of what the method does.\n\n" + "Args:\n" + " arg1: Description of first argument\n" + " arg2: Description of second argument (default: value)\n\n" + "Returns:\n" + " Description of return value\n\n" + "Example:\n" + " result = obj.method_name(value1, value2)\n\n" + "Note:\n" + " Any important notes or caveats"}, +``` + +For properties in PyGetSetDef arrays: +```cpp +{"property_name", (getter)getter_func, (setter)setter_func, + "Brief description of the property. " + "Additional details about valid values, side effects, etc.", NULL}, +``` + +### Regenerating Documentation + +After modifying C++ inline documentation: + +1. **Rebuild the project**: `make -j$(nproc)` + +2. **Generate stub files** (for IDE support): + ```bash + ./build/mcrogueface --exec generate_stubs.py + ``` + +3. **Generate dynamic documentation** (recommended): + ```bash + ./build/mcrogueface --exec generate_dynamic_docs.py + ``` + This creates: + - `docs/api_reference_dynamic.html` + - `docs/API_REFERENCE_DYNAMIC.md` + +4. **Update hardcoded documentation** (if still using old system): + - `generate_complete_api_docs.py` - Update method dictionaries + - `generate_complete_markdown_docs.py` - Update method dictionaries + +### Important Notes + +- **McRogueFace as Python interpreter**: Documentation scripts MUST be run using McRogueFace itself, not system Python +- **Use --exec flag**: `./build/mcrogueface --exec script.py` or `--headless --exec` for CI/automation +- **Dynamic is better**: The new `generate_dynamic_docs.py` extracts documentation directly from compiled module +- **Keep docstrings consistent**: Follow the format above for automatic parsing + +### Documentation Pipeline Architecture + +1. **C++ Source** → PyMethodDef/PyGetSetDef arrays with docstrings +2. **Compilation** → Docstrings embedded in compiled module +3. **Introspection** → Scripts use `dir()`, `getattr()`, `__doc__` to extract +4. **Generation** → HTML/Markdown/Stub files created + +The documentation is only as good as the C++ inline docstrings! \ No newline at end of file diff --git a/ROADMAP.md b/ROADMAP.md index 6d38e72..8d02b12 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -201,6 +201,21 @@ For current status and detailed tasks, see the corresponding Gitea issue labels: - **Source Code**: [Gitea Repository](https://gamedev.ffwf.net/gitea/john/McRogueFace) - **Documentation**: See `CLAUDE.md` for build instructions and development guide - **Tutorial**: See `roguelike_tutorial/` for implementation examples +- **Workflow**: See "Gitea-First Workflow" section in `CLAUDE.md` for issue management best practices + +--- + +## 🔄 Development Workflow + +**Gitea is the Single Source of Truth** for this project. Before starting any work: + +1. **Check Gitea Issues** for existing tasks, bugs, or related work +2. **Create granular issues** for new features or problems +3. **Update issues** when work affects other systems +4. **Document discoveries** - if something is undocumented or misleading, create a task to fix it +5. **Cross-reference commits** with issue numbers (e.g., "Fixes #104") + +See the "Gitea-First Workflow" section in `CLAUDE.md` for detailed guidelines on efficient development practices using the Gitea MCP tools. ---