Integrates Dear ImGui for an in-game debug console that replaces the
blocking Python REPL. Press ~ (grave/tilde) to toggle the console.
Features:
- Python code execution without blocking the game loop
- Output capture with color coding (yellow=input, red=errors, gray=output)
- Expression results show repr() automatically
- Command history navigation with up/down arrows
- Word wrapping for long output lines
- Auto-scroll that doesn't fight manual scrolling
- mcrfpy.setDevConsole(bool) API to disable for shipping
Technical changes:
- Update imgui submodule to v1.89.9 (stable)
- Update imgui-sfml submodule to 2.6.x branch (SFML 2.x compatible)
- Add ImGui sources to CMakeLists.txt with OpenGL dependency
- Integrate ImGui lifecycle into GameEngine
- Add ImGuiConsole class for console overlay
closes#36, closes#65, closes#75🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update cpython submodule from v3.12.2 to v3.14.0
- Fix test_timer_object.py: Add delTimer call to prevent double-cancel
- Fix test_viewport_scaling.py: Handle headless mode for window resize
Test suite now achieves 100% pass rate (129/129 tests).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Both branches fixed the --exec double-execution bug with complementary approaches:
- origin/master: Added executeStartupScripts() method for cleaner separation
- HEAD: Avoided engine recreation to preserve state
This merge keeps the best of both: executeStartupScripts() called on the
existing engine without recreation.
Also accepts deletion of flaky test_viewport_visual.py from origin/master.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace deprecated Python C API calls with modern PyConfig-based initialization:
- PySys_SetArgvEx() -> PyConfig.argv (deprecated since 3.11)
- Py_InspectFlag -> PyConfig.inspect (deprecated since 3.12)
Fix critical memory safety bugs discovered during migration:
- PyColor::from_arg() and PyVector::from_arg() now return new references
instead of borrowed references, preventing use-after-free when callers
call Py_DECREF on the result
- GameEngine::testTimers() now holds a local shared_ptr copy during
callback execution, preventing use-after-free when timer callbacks
call delTimer() on themselves
Fix double script execution bug with --exec flag:
- Scripts were running twice because GameEngine constructor executed them,
then main.cpp deleted and recreated the engine
- Now reuses existing engine and just sets auto_exit_after_exec flag
Update test syntax to use keyword arguments for Frame/Caption constructors.
Test results: 127/130 passing (97.7%)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Scripts passed to --exec were executing twice because GameEngine
constructor ran scripts, and main.cpp created two GameEngine instances.
- Move exec_scripts from constructor to new executeStartupScripts() method
- Call executeStartupScripts() once after final engine setup in main.cpp
- Remove double-execution workarounds from tests
- Delete duplicate test_viewport_visual.py (flaky due to race condition)
- Fix test constructor syntax and callback signatures
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- BUILD_FROM_SOURCE.md: Complete guide for building from source
- Quick build option using pre-built build_deps archive
- Full build instructions for all dependencies
- libtcod-headless integration (no SDL required)
- Instructions for creating build_deps archives for releases
- Troubleshooting section
- README.md: Add "Building from Source" section
- Quick reference for common build scenarios
- Links to full build guide
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
By default, McRogueFace now exits with code 1 on the first unhandled
exception in timer, click, key, or animation callbacks. This prevents
repeated exception output that wastes resources in AI-driven development.
Changes:
- Add exit_on_exception config flag (default: true)
- Add --continue-after-exceptions CLI flag to preserve old behavior
- Update exception handlers in Timer, PyCallable, and Animation
- Signal game loop via McRFPy_API atomic flags
- Return proper exit code from main()
Before: Timer exceptions repeated 1000+ times until timeout
After: Single traceback, clean exit with code 1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The test was incorrectly using scene_ui.remove(-1) expecting it to
remove the element at index -1. However, Python's list.remove(x)
removes the first occurrence of VALUE x, not by index.
Changed to use `del scene_ui[-1]` which is the correct Python idiom
for removing an element by index.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Breaking change: UICollection.remove() now takes a value (element) instead
of an index, matching Python's list.remove() behavior.
New methods added to both UICollection and EntityCollection:
- pop([index]) -> element: Remove and return element at index (default: last)
- insert(index, element): Insert element at position
Semantic fixes:
- remove(element): Now removes first occurrence of element (was: remove by index)
- All methods now have docstrings documenting behavior
Note on z_index sorting: The collections are sorted by z_index before each
render. Using index-based operations (pop, insert) with non-default z_index
values may produce unexpected results. Use name-based .find() for stable
element access when z_index sorting is in use.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements name-based search for UI elements and entities:
- Exact match returns single element or None
- Wildcard patterns (prefix*, *suffix, *contains*) return list
- Recursive search for nested Frame children (UICollection only)
API:
ui.find("player_frame") # exact match
ui.find("enemy*") # starts with
ui.find("*_button", recursive=True) # recursive search
grid.entities.find("*goblin*") # entity search
Closes#41, closes#40🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix timer restart when switching between animated demo scenes
- Update all demos from 800x600 to 1024x768 resolution
- Add screen_angle_between() for correct arc angles in screen coords
- Fix arc directions by accounting for screen Y inversion
- Reposition labels to avoid text overlaps
- Shift solar system center down to prevent moon orbit overflow
- Reposition ship/target in pathfinding demo to avoid sun clipping
- Scale menu screen to fill 1024x768 with wider buttons
- Regenerate all demo screenshots
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Creates comprehensive visual demonstrations of the geometry module:
Static demos:
- Bresenham algorithms: circle/line rasterization on grid cells
- Angle calculations: line elements showing angles between points,
waypoint viability with angle thresholds, orbit exit headings
- Pathfinding: planets with surfaces and orbit rings, optimal
path using orbital slingshots vs direct path comparison
Animated demos:
- Solar system: planets orbiting star with discrete time steps,
nested moon orbit, position updates every second
- Pathfinding through moving system: ship navigates to target
using orbital intercepts, anticipating planetary motion
Includes 5 screenshot outputs demonstrating each feature.
Run: ./mcrogueface --headless --exec tests/geometry_demo/geometry_main.py
Interactive: ./mcrogueface tests/geometry_demo/geometry_main.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements issue #130 with:
- Basic utilities: distance, angle_between, normalize_angle, lerp, clamp
- Grid algorithms: bresenham_circle, bresenham_line, filled_circle
- OrbitalBody class with recursive positioning (star -> planet -> moon)
- OrbitingShip class for relative ship positioning on orbit rings
- Pathfinding helpers: nearest_orbit_entry, optimal_exit_heading,
is_viable_waypoint, line_of_sight_blocked
- Comprehensive test suite (25+ tests)
Designed for Pinships turn-based space roguelike with:
- Discrete time steps (planets move in whole grid squares)
- Deterministic position projection
- Free orbital movement while in orbit
- Support for nested orbits (moons of moons)
closes#130🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major changes:
- Reorganized tests/ into unit/, integration/, regression/, benchmarks/, demo/
- Deleted 73 failing/outdated tests, kept 126 passing tests (100% pass rate)
- Created demo system with 6 feature screens (Caption, Frame, Primitives, Grid, Animation, Color)
- Updated .gitignore to track tests/ directory
- Updated CLAUDE.md with comprehensive testing guidelines and API quick reference
Demo system features:
- Interactive menu navigation (press 1-6 for demos, ESC to return)
- Headless screenshot generation for CI
- Per-feature demonstration screens with code examples
Testing infrastructure:
- tests/run_tests.py - unified test runner with timeout support
- tests/demo/demo_main.py - interactive/headless demo runner
- All tests are headless-compliant
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Grid now supports a `children` collection for arbitrary UIDrawable elements
(speech bubbles, effects, highlights, path visualization, etc.) that
automatically transform with the grid's camera (pan/zoom).
Key features:
- Children positioned in grid-world pixel coordinates
- Render after entities, before FOV overlay (proper z-ordering)
- Sorted by z_index, culled when outside visible region
- Click detection transforms through grid camera
- Automatically clipped to grid boundaries via RenderTexture
Python API:
grid.children.append(caption) # Speech bubble follows grid camera
grid.children.append(circle) # Highlight indicator
Closes#132🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement new UIDrawable-derived classes for vector graphics:
- UILine: Thick line segments using sf::ConvexShape for proper thickness
- Properties: start, end, color, thickness
- Supports click detection along the line
- UICircle: Filled and outlined circles using sf::CircleShape
- Properties: radius, center, fill_color, outline_color, outline
- Full property system for animations
- UIArc: Arc segments for orbital paths and partial circles
- Properties: center, radius, start_angle, end_angle, color, thickness
- Uses sf::VertexArray with TriangleStrip for smooth rendering
- Supports arbitrary angle spans including negative (reverse) arcs
All primitives integrate with the Python API through mcrfpy module:
- Added to PyObjectsEnum for type identification
- Full getter/setter support for all properties
- Added to UICollection for scene management
- Support for visibility, opacity, z_index, name, and click handling
closes#128, closes#129🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added complete label category breakdown (System, Priority, Type/Scope, Workflow)
- Documented all 22 labels with descriptions and usage guidelines
- Added example label combinations for common scenarios
- Documented MCP tool label application issues (see #131)
- Provided label ID reference for documentation purposes
- Strong recommendation to apply labels manually via web interface
Related to #131🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Closes#127
Previously, `./mcrogueface --headless --exec <script>` would hang
indefinitely after the script completed because the game loop ran
continuously. This required external timeouts and explicit mcrfpy.exit()
calls in every automation script.
This commit adds automatic exit detection for headless+exec mode:
- Added `auto_exit_after_exec` flag to McRogueFaceConfig
- Set flag automatically when both --headless and --exec are present
- Game loop exits when no timers remain (timers.empty())
Benefits:
- Documentation generation scripts work without explicit exit calls
- Testing scripts don't need timeout wrappers
- Clean process termination for automation
- Backward compatible (scripts with mcrfpy.exit() continue working)
Changes:
- src/McRogueFaceConfig.h: Add auto_exit_after_exec flag
- src/main.cpp: Set flag and recreate engine with modified config
- src/GameEngine.cpp: Check timers.empty() in game loop
- ROADMAP.md: Mark Phase 7 as complete (2025-10-30)
- CLAUDE.md: Add instruction about closing issues with commit messages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Converted all module-level functions in McRFPy_API.cpp to use the MCRF_*
documentation macro system:
Audio functions (7):
- createSoundBuffer, loadMusic, setMusicVolume, setSoundVolume
- playSound, getMusicVolume, getSoundVolume
Scene functions (5):
- sceneUI, currentScene, setScene, createScene, keypressScene
Timer functions (2):
- setTimer, delTimer
Utility functions (5):
- exit, setScale, find, findAll, getMetrics
Each function now uses:
- MCRF_SIG for signatures
- MCRF_DESC for descriptions
- MCRF_ARG for parameters
- MCRF_RETURNS for return values
- MCRF_RAISES for exceptions
- MCRF_NOTE for additional details
Phase 4 assessment: PyCallable.cpp and PythonObjectCache.cpp contain only
internal C++ implementation with no Python API to document.
All conversions tested and verified with test_phase3_docs.py.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed module-level docstring in PyModuleDef where double-backslash newlines
(\\n) were appearing as literal "\n" text in help(mcrfpy) output.
Changed from escaped newlines (\\n) to actual newlines (\n) so the C compiler
interprets them correctly.
Before: help(mcrfpy) showed "McRogueFace Python API\\n\\nCore game..."
After: help(mcrfpy) shows proper formatting with line breaks
The issue was in the PyDoc_STR() macro call - it doesn't interpret escape
sequences, so the string literal itself needs to have proper newlines.
Updated documentation guidelines to reflect the new macro-based system:
- Documented MCRF_METHOD and MCRF_PROPERTY usage
- Listed all available macros (MCRF_SIG, MCRF_DESC, MCRF_ARG, etc.)
- Added prose guidelines (concise C++, verbose external docs)
- Updated regeneration workflow (removed references to deleted scripts)
- Emphasized single source of truth and zero-drift architecture
Removed references to obsolete hardcoded documentation scripts that were
deleted in previous commits.
Related: #92 (Inline C++ documentation system)
Fixes critical issue discovered in code review where PyDrawable property
docstrings were being overridden by child classes, making enhanced documentation
invisible to users.
Updated files:
- src/UIBase.h: UIDRAWABLE_GETSETTERS macro (visible, opacity)
- src/UIFrame.cpp: click and z_index properties
- src/UISprite.cpp: click and z_index properties
- src/UICaption.cpp: click and z_index properties
- src/UIGrid.cpp: click and z_index properties
All four UI class hierarchies (Frame, Sprite, Caption, Grid) now expose
consistent, enhanced property documentation to Python users.
Verification:
- tools/test_child_class_docstrings.py: All 16 property tests pass
- All 4 properties (click, z_index, visible, opacity) match across all 4 classes
Related: #92 (Inline C++ documentation system)
All Drawable properties (click, z_index, visible, opacity) now
use MCRF_PROPERTY with enhanced descriptions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Converts get_bounds, move, and resize to MCRF_METHOD.
These are inherited by all UI classes (Frame, Caption, Sprite, Grid).
Updated both PyDrawable.cpp and UIBase.h (UIDRAWABLE_METHODS macro).
All method docstrings now include complete Args, Returns, and Note sections.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes HTML injection vulnerability in generate_dynamic_docs.py where
description text was not HTML-escaped before being inserted into HTML
output. Special characters like <, >, & could be interpreted as HTML.
Changes:
- Modified transform_doc_links() to escape all non-link text when
format='html' or format='web'
- Link text and hrefs are also properly escaped
- Non-HTML formats (markdown, python) remain unchanged
- Added proper handling for descriptions with mixed plain text and links
The fix splits docstrings into link and non-link segments, escapes
non-link segments, and properly escapes content within link patterns.
Tested with comprehensive test suite covering:
- Basic HTML special characters
- Special chars with links
- Special chars in link text
- Multiple links with special chars
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds transform_doc_links() function that converts MCRF_LINK patterns
to appropriate format (HTML links, Markdown links, or plain text).
Addresses issue #97.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Properties x and y now use MCRF_PROPERTY for consistency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
All Vector methods now use MCRF_METHOD macros with complete
documentation including Args, Returns, and Notes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The normalize() method's implementation returns a zero vector when
called on a zero-magnitude vector, rather than raising ValueError as
the documentation claimed. Updated the MCRF_RAISES to MCRF_NOTE to
accurately describe the actual behavior.
Also added test coverage in tools/test_vector_docs.py to verify the
normalize() docstring contains the correct Note section.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Converts magnitude, normalize, and dot methods to MCRF_METHOD macro.
Docstrings now include complete Args/Returns/Raises sections.
Addresses issue #92.
Adds C++ preprocessor macros for consistent API documentation.
Addresses issue #92.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Establish Gitea as the single source of truth for issue tracking,
documentation, and project management to improve development efficiency.
CLAUDE.md changes:
- Add comprehensive "Gitea-First Workflow" section at top of file
- Document 5 core principles for using Gitea effectively
- Provide workflow pattern diagram for development process
- List available Gitea MCP tools for programmatic access
- Explain benefits: reduced context switching, better planning, living docs
ROADMAP.md changes:
- Add "Development Workflow" section referencing Gitea-first approach
- Include 5-step checklist for starting any work
- Link to detailed workflow guidelines in CLAUDE.md
- Emphasize Gitea as single source of truth
Workflow principles:
1. Always check Gitea issues/wiki before starting work
2. Create granular, focused issues for new features/problems
3. Document as you go - update related issues when work affects them
4. If docs mislead, create task to correct/expand them
5. Cross-reference everything - commits, issues, wiki pages
Benefits:
- Avoid re-reading entire codebase by consulting brief issue descriptions
- Reduce duplicate or contradictory work through better planning
- Maintain living documentation that stays current
- Capture historical context and decision rationale
- Improve efficiency using MCP tools for programmatic queries
This establishes best practices for keeping the project organized and
reducing cognitive load during development.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed stale data and duplicate tracking from ROADMAP.md to establish
Gitea as the single source of truth for issue tracking.
Changes:
- Removed outdated urgent priorities from July 2025 (now October)
- Removed extensive checkbox task lists that duplicate Gitea issues
- Removed "Recent Achievements" changelog (use git log instead)
- Removed dated commentary and out-of-sync issue statuses
- Streamlined from 936 lines to 207 lines (~78% reduction)
Kept strategic content:
- Engine philosophy and architecture goals
- Three-layer grid architecture decisions
- Performance optimization patterns
- Development phase summaries with Gitea issue references
- Future vision: Pure Python extension architecture
- Resource links to Gitea issue tracker
The roadmap now focuses on strategic vision and architecture decisions,
while deferring all task tracking, bug reports, and current priorities
to the Gitea issue tracker.
Related: All issue status tracking moved to Gitea
See: https://gamedev.ffwf.net/gitea/john/McRogueFace/issues🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This merge brings in the complete TCOD-style tutorial implementation
for McRogueFace, demonstrating the engine as a viable alternative to
python-tcod for roguelike game development.
Key additions:
- Tutorial parts 0-6 with full documentation
- EntityCollection.remove() API improvement (object-based vs index-based)
- Development tooling scripts (test runner, issue tracking)
- Complete API reference documentation
Tutorial follows "forward-only" philosophy where each step builds
on previous work without requiring refactoring, making it more
accessible for beginners.
This work represents 2+ months of development (July-August 2025)
focused on validating McRogueFace's educational value and TCOD
compatibility.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive HTML API reference documentation covering
all McRogueFace Python API components, methods, and properties.
This documentation was generated from the C++ inline docstrings
and provides complete reference material for engine users.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add utility scripts for development workflow:
- tests/run_all_tests.sh: Test runner script for automated testing
- tools/gitea_issues.py: Issue tracking integration tool
These support the development and testing workflow for McRogueFace.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add Python code for tutorial parts 0-6:
- part_0.py: Initial setup and character rendering
- part_1.py, part_1b.py: Movement systems
- part_2.py variants: Movement with naive, queued, and final implementations
- part_3.py: Dungeon generation with BSP
- part_4.py: Field of view implementation
- part_5.py: Enemy entities and basic interaction
- part_6.py: Combat mechanics
- _generated_part_5.py: Machine-generated draft for reference
These implementations demonstrate McRogueFace capabilities
and serve as foundation for tutorial documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add working tutorial implementations covering:
- Part 0: Basic setup and character display
- Part 1: Movement and grid interaction
- Part 2: Movement variations (naive, queued, final)
- Part 3: Dungeon generation
- Part 4: Field of View
- Part 5: Entities and interactions
- Part 6: Combat system
Each part includes corresponding README with explanations.
Implementation plan document included for parts 6-8.
Tutorial follows "forward-only" philosophy - each step builds
on previous without requiring refactoring.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, EntityCollection.remove() required an integer index, which was
inconsistent with Python's list.remove(item) behavior and the broader
Python ecosystem conventions.
Changes:
- remove() now accepts Entity object directly instead of index
- Searches collection by comparing C++ shared_ptr identity
- Raises ValueError if entity not found in collection
- More Pythonic API matching Python's list.remove() semantics
This aligns with Issue #73 and improves API consistency across the
collection system.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>