No description
Find a file
John McCardle f68a770346 feat(bench): Gauntlet OOM safety guards + The Crucible wall-clock benchmark; closes #353 closes #354
The Gauntlet's auto-ramp had a step ceiling but no memory ceiling. GRID TITAN
ramps grid side S with cost ~ S*S, but renders into a fixed viewport so frame
time can stay under budget while allocation runs away -- observed hard-locking
the desktop mid grid-allocation (all RAM consumed, forced logout).

#353 -- memory safety (defense in depth, weakest failure mode last):
  * tests/benchmarks/gauntlet/safety.py: rss_mb/vmsize_mb probes +
    install_address_space_cap() (RLIMIT_AS backstop; a runaway Grid() then
    aborts THIS process via std::bad_alloc instead of taking the machine down).
  * Trial.predict_bytes(load) + Trial.max_load: a trial refuses a load whose
    predicted footprint exceeds a 512 MB budget BEFORE allocating it. GRID
    TITAN implements both (S*S*~28 B; max_load=4300 ~= 494 MB).
  * RampController: pre-allocation predict/cap check + post-set_load RSS
    watchdog; records stop_reason (budget/hard_cap/max_load/mem_predict/
    mem_rss/max_steps). run_gauntlet.py installs the address-space cap at start.
  * tests/unit/gauntlet_safety_test.py proves the ramp bails on the memory
    guards before over-allocating (synthetic runaway trial records the largest
    load it was asked to build).

#354 -- The Crucible (tests/benchmarks/crucible.py): a headless, deterministic
wall-clock microbenchmark of fixed "comically extreme but tractable" configs
(grid alloc, cell fill, layer writes, turn-manager swarm, FOV, A*, entity
churn). Safe (<512 MB, ~seconds), display-free, cross-version (missing APIs
report "unsupported"). Emits JSON; MCRF_CRUCIBLE_BASELINE diffs two builds.

This is the safe replacement for the windowed-Gauntlet A/B that crashed the
desktop. First result, current master vs the 0.2.8 release artifact (both
headless): grid_alloc -58.9%, grid_fill -25.4%, layer_fill -56.1%,
entity_churn -43.0%, fov_storm -10.3%, step_swarm -6.2%, path_queries -3.2%;
geomean 0.673 (32.7% faster overall), peak RSS ~103 vs ~119 MB. Tracks the
#332 SoA rewrite + #329 entity indexing.

Suite 314/314.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 10:28:13 -04:00
.gitea/workflows Add Gitea Actions CI workflow for automated testing, closes #285 2026-04-10 03:31:31 -04:00
assets asset cleanup 2026-01-08 22:52:34 -05:00
cmake/toolchains mingw toolchain and final fixes for Windows. Closes #162 2026-01-08 21:16:27 -05:00
deps/platform WASM Python integration milestone - game.py runs in browser 2026-01-31 05:15:11 -05:00
docs feat(grid): numpy buffer views for ColorLayer/TileLayer via layer.edit(); closes #335 2026-07-11 02:04:42 -04:00
explanation Add headless-automation.md explanation document 2026-01-14 03:04:48 +00:00
games/unwritten UNWRITTEN: complete short-form RPG at games/unwritten/ 2026-07-03 10:11:12 -04:00
modules Bump libtcod-headless to 79abc66 (FOV overflow fixes); closes #321 2026-06-26 20:57:38 -04:00
sanitizers Re-enable ASan leak detection, add Massif heap profiling target 2026-04-10 01:08:54 -04:00
shade_sprite entity animation version demo 2026-02-27 22:12:17 -05:00
src fix(grid): turn manager invalidates view render cache on entity move; addresses #351 2026-07-11 10:15:36 -04:00
stubs feat(grid): numpy buffer views for ColorLayer/TileLayer via layer.edit(); closes #335 2026-07-11 02:04:42 -04:00
tests feat(bench): Gauntlet OOM safety guards + The Crucible wall-clock benchmark; closes #353 closes #354 2026-07-11 10:28:13 -04:00
tools Regenerate API docs; add threading note to reference intro 2026-07-02 20:23:28 -04:00
wasm_stdlib/lib/python3.14 WASM Python integration milestone - game.py runs in browser 2026-01-31 05:15:11 -05:00
web Migrate docs and links to Forgejo instance (dev.ffwf.net/forgejo) 2026-07-02 19:49:22 -04:00
.gitignore Add tools/audit_pymethoddef.py - MCRF_METHOD/MCRF_PROPERTY compliance auditor 2026-04-18 12:30:25 -04:00
.gitmodules Tiled XML/JSON import support 2026-02-06 21:43:03 -05:00
build.sh Squashed commit of the following: [alpha_streamline_1] 2025-07-05 18:56:02 -04:00
BUILD_FROM_SOURCE.md docs: Add comprehensive build documentation 2025-11-26 11:28:10 -05:00
build_windows.bat hotfix: Windows build attempt 2025-07-09 23:33:09 -04:00
build_windows_cmake.bat Squashed commit of the following: [alpha_presentable] 2025-07-15 21:30:49 -04:00
CLAUDE.md Add profiling build target + native profiler workflow; closes #345 2026-07-10 18:59:39 -04:00
CMakeLists.txt Add profiling build target + native profiler workflow; closes #345 2026-07-10 18:59:39 -04:00
compile_commands.json Squashed commit of the following: [interpreter_mode] 2025-07-05 17:23:09 -04:00
forgejo-mcp.linux.amd64 version bump for forgejo-mcp binary 2025-11-03 10:59:22 -05:00
LICENSE.md Refactor: Python 3.12, build libtcod & SFML from source. Cmake build. Directory cleanup 2024-02-24 22:48:39 -05:00
Makefile Add profiling build target + native profiler workflow; closes #345 2026-07-10 18:59:39 -04:00
mcrf-init.sh Add mcrf-init.sh: game project scaffolding without engine recompilation 2026-02-20 23:17:59 -05:00
pyrightconfig.json Add mcrf-init.sh: game project scaffolding without engine recompilation 2026-02-20 23:17:59 -05:00
README.md Freeze value semantics + record 1.0 compatibility policy 2026-07-02 20:23:11 -04:00
ROADMAP.md ROADMAP: record native profiling rig + perf batch (#345/#331/#342-#344/#348); refresh open-issue index 2026-07-10 23:31:28 -04:00

McRogueFace

Blame my wife for the name

A Python-powered 2D game engine for creating roguelike games, built with C++ and SFML.

  • Core roguelike logic from libtcod: field of view, pathfinding
  • Animate sprites with multiple frames. Smooth transitions for positions, sizes, zoom, and camera
  • Simple GUI element system allows keyboard and mouse input, composition
  • No compilation or installation necessary. The runtime is a full Python environment; "Zip And Ship"

📖 Full Documentation & Tutorials - Quickstart guide, API reference, and cookbook

Quick Start

Download the latest release:

  • Windows: McRogueFace-*-Win.zip
  • Linux: McRogueFace-*-Linux.tar.bz2

Extract and run mcrogueface (or mcrogueface.exe on Windows) to see the demo game.

Your First Game

Create scripts/game.py (or edit the existing one):

import mcrfpy

# Create and activate a scene
scene = mcrfpy.Scene("game")
scene.activate()

# Load a sprite sheet
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)

# Create a tile grid
grid = mcrfpy.Grid(grid_size=(20, 15), texture=texture, pos=(50, 50), size=(640, 480))
grid.zoom = 2.0
scene.children.append(grid)

# Add a player entity
player = mcrfpy.Entity(pos=(10, 7), texture=texture, sprite_index=84)
grid.entities.append(player)

# Handle keyboard input
def on_key(key, state):
    if state != "start":
        return
    x, y = int(player.x), int(player.y)
    if key == "W": y -= 1
    elif key == "S": y += 1
    elif key == "A": x -= 1
    elif key == "D": x += 1
    player.x, player.y = x, y

scene.on_key = on_key

Run mcrogueface and you have a movable character!

Visual Framework

  • Sprite: Single image or sprite from a shared sheet
  • Caption: Text rendering with fonts
  • Frame: Container rectangle for composing UIs
  • Grid: 2D tile array with zoom and camera control
  • Entity: Grid-based game object with sprite and pathfinding
  • Animation: Interpolate any property over time with easing

Building from Source

For most users, pre-built releases are available. If you need to build from source:

Quick Build (with pre-built dependencies)

Download build_deps.tar.gz from the releases page, then:

git clone <repository-url> McRogueFace
cd McRogueFace
tar -xzf /path/to/build_deps.tar.gz
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

Full Build (compiling all dependencies)

git clone --recursive <repository-url> McRogueFace
cd McRogueFace
# See BUILD_FROM_SOURCE.md for complete instructions

BUILD_FROM_SOURCE.md - Complete build guide including:

  • System dependency installation
  • Compiling SFML, Python, and libtcod-headless from source
  • Creating build_deps archives for distribution
  • Troubleshooting common build issues

System Requirements

  • Linux: Debian/Ubuntu tested; other distros should work
  • Windows: Supported (see build guide for details)
  • macOS: Untested

Example: Main Menu with Buttons

import mcrfpy

# Create a scene
scene = mcrfpy.Scene("menu")

# Add a background frame
bg = mcrfpy.Frame(pos=(0, 0), size=(1024, 768),
                  fill_color=mcrfpy.Color(20, 20, 40))
scene.children.append(bg)

# Add a title
title = mcrfpy.Caption(pos=(312, 100), text="My Roguelike",
                       fill_color=mcrfpy.Color(255, 255, 100))
title.font_size = 48
scene.children.append(title)

# Create a button
button = mcrfpy.Frame(pos=(362, 300), size=(300, 80),
                      fill_color=mcrfpy.Color(50, 150, 50))
button_text = mcrfpy.Caption(pos=(90, 25), text="Start Game")
button.children.append(button_text)

def on_click(x, y, btn):
    print("Game starting!")

button.on_click = on_click
scene.children.append(button)

scene.activate()

Documentation

📚 Developer Documentation

For comprehensive documentation about systems, architecture, and development workflows:

Project Wiki

Key wiki pages:

📖 Development Guides

In the repository root:

Note: Running mcrfpy in a Python subinterpreter is unsupported in 1.x; the module declares m_size = -1 and will refuse or misbehave. See #220.

Build Requirements

  • C++17 compiler (GCC 7+ or Clang 5+)
  • CMake 3.14+
  • Python 3.14 (embedded)
  • SFML 2.6
  • Linux or Windows (macOS untested)

See BUILD_FROM_SOURCE.md for detailed compilation instructions.

Project Structure

McRogueFace/
├── assets/        # Sprites, fonts, audio
├── build/         # Build output: this is what you distribute
│   ├── assets/    # (copied from assets/)
│   ├── scripts/   # (copied from src/scripts/)
│   └── lib/       # Python stdlib and extension modules
├── docs/          # Generated HTML, markdown API docs
├── src/           # C++ engine source
│   └── scripts/   # Python game scripts
├── stubs/         # .pyi type stubs for IDE integration
├── tests/         # Automated test suite
└── tools/         # Documentation generation scripts

If you are building McRogueFace to implement game logic or scene configuration in C++, you'll have to compile the project.

If you are writing a game in Python using McRogueFace, you only need to rename and zip/distribute the build directory.

Philosophy

  • C++ every frame, Python every tick: All rendering data is handled in C++. Structure your UI and program animations in Python, and they are rendered without Python. All game logic can be written in Python.
  • No Compiling Required; Zip And Ship: Implement your game objects with Python, zip up McRogueFace with your "game.py" to ship
  • Built-in Roguelike Support: Dungeon generation, pathfinding, and field-of-view via libtcod
  • Hands-Off Testing: PyAutoGUI-inspired event generation framework. All McRogueFace interactions can be performed headlessly via script: for software testing or AI integration
  • Interactive Development: Python REPL integration for live game debugging. Use mcrogueface like a Python interpreter

Contributing

PRs will be considered! Please include explicit mention that your contribution is your own work and released under the MIT license in the pull request.

Issue Tracking

The project uses Forgejo Issues for task tracking and bug reports. Issues are organized with labels:

  • System labels (grid, animation, python-binding, etc.) - identify which codebase area
  • Priority labels (tier1-active, tier2-foundation, tier3-future) - development timeline
  • Type labels (Major Feature, Minor Feature, Bugfix, etc.) - effort and scope

See the Issue Roadmap on the wiki for organized view of all open tasks.

License

This project is licensed under the MIT License - see LICENSE file for details.

Acknowledgments

  • Developed for 7-Day Roguelike 2023, 2024, 2025, 2026 - here's to many more
  • Built with SFML, libtcod, and Python
  • Inspired by David Churchill's COMP4300 game engine lectures