2026-07-15 00:26:38 -04:00
|
|
|
# mcrf: objects=[BSP,Caption,Color,ColorLayer,Grid,Scene] verified=0.2.8-dev status=ok
|
|
|
|
|
# BSP Quick Reference - create a tree, split, and iterate leaves
|
|
|
|
|
import mcrfpy
|
|
|
|
|
|
|
|
|
|
scene = mcrfpy.Scene("demo")
|
|
|
|
|
mcrfpy.current_scene = scene
|
|
|
|
|
|
|
|
|
|
grid = mcrfpy.Grid(
|
|
|
|
|
grid_size=(80, 50),
|
|
|
|
|
texture=mcrfpy.default_texture,
|
|
|
|
|
pos=(0, 0),
|
|
|
|
|
size=(800, 500),
|
|
|
|
|
)
|
|
|
|
|
scene.children.append(grid)
|
|
|
|
|
|
|
|
|
|
# Create a BSP tree covering a dungeon area
|
|
|
|
|
bsp = mcrfpy.BSP(pos=(0, 0), size=(80, 50))
|
|
|
|
|
|
|
|
|
|
# Split recursively into rooms
|
feat(docs): deterministic snippet screenshots — Phase 1 (STATIC capture)
Generate a byte-stable preview PNG for every docs snippet, as the visual-
regression oracle foundation of #381. A changed image means the snippet's
behaviour changed and wants review.
Pipeline (no C++ change; existing headless build suffices):
- _seed.py: chained as the FIRST --exec so random.seed(42) governs the
snippet's RNG before it draws (snippets draw at import; seeding after is
too late). Shared-interpreter seeding covers all 25 random-module snippets.
- _screenshot.py: chained as the LAST --exec; steps setup frames then
automation.screenshot(). Kept separate from _harness.py so the pass/fail
suite stays fast and untouched.
- tools/generate_snippet_shots.py: orchestrator; runs seed->snippet->shot,
writes gitignored snippet-shots/ (images belong in the doc-site repo,
which pulls them from here). Per-snippet capture params live in a sidecar
OVERRIDES table, not the mcrf: header (which would fight stamp_snippets
and can't hold Phase-3 interaction scripts).
- make snippet-shots target; snippet-shots/ gitignored.
The 4 BSP snippets that needed deterministic pixels (060, 102, 224, 243)
now pass seed=42 — libtcod's global RNG is time(0)-seeded and unreachable
from Python, and seed= also documents reproducible generation for readers.
Validated: 272 captured, 10 skipped (noshot opt-outs), 0 failed; all 272
byte-identical across two full runs (~49s).
Addresses #381.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LTh2ZW7bd3XSd9qK86Z2CE
2026-07-15 20:57:04 -04:00
|
|
|
bsp.split_recursive(depth=4, min_size=(8, 8), seed=42)
|
2026-07-15 00:26:38 -04:00
|
|
|
|
|
|
|
|
# Iterate over leaf nodes (rooms)
|
|
|
|
|
room_layer = mcrfpy.ColorLayer(z_index=1, name="rooms")
|
|
|
|
|
grid.add_layer(room_layer)
|
|
|
|
|
|
|
|
|
|
for leaf in bsp:
|
|
|
|
|
x, y = leaf.pos
|
|
|
|
|
w, h = leaf.size
|
|
|
|
|
room_layer.set((x, y), mcrfpy.Color(200, 150, 100, 150))
|
|
|
|
|
|
|
|
|
|
# Use adjacency graph for corridor placement
|
|
|
|
|
for i, neighbors in enumerate(bsp.adjacency):
|
|
|
|
|
leaf = bsp.get_leaf(i)
|
|
|
|
|
for neighbor_idx in neighbors:
|
|
|
|
|
# leaf and bsp.get_leaf(neighbor_idx) share a wall
|
|
|
|
|
tiles = leaf.adjacent_tiles[neighbor_idx]
|
|
|
|
|
# tiles contains Vector coordinates for corridor placement
|
|
|
|
|
for tile in tiles:
|
|
|
|
|
pass # e.g. carve a corridor tile at (tile.x, tile.y)
|
|
|
|
|
|
|
|
|
|
status = mcrfpy.Caption(text=f"BSP: {len(bsp)} rooms", pos=(10, 10))
|
|
|
|
|
scene.children.append(status)
|