"""Verify code snippets from Phase D batch 3 wiki updates.""" import mcrfpy import sys passes = 0 fails = 0 def check(name, fn): global passes, fails try: fn() passes += 1 print(f" [OK] {name}") except Exception as e: fails += 1 print(f" [FAIL] {name}: {e}") # =================================================================== print("=== PROCEDURAL GENERATION ===") # =================================================================== def test_pg_bsp_basic(): """BSP dungeon generation pattern""" grid = mcrfpy.Grid(grid_size=(50, 50), pos=(0, 0), size=(400, 400)) # Set cells walkable (carve a room) for x in range(10, 20): for y in range(10, 20): cell = grid.at(x, y) cell.walkable = True cell.transparent = True # Verify assert grid.at(15, 15).walkable == True assert grid.at(0, 0).walkable == False check("PG: BSP basic grid setup", test_pg_bsp_basic) def test_pg_cell_properties(): """Cell property access patterns""" grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(320, 320)) cell = grid.at(5, 5) # Test walkable cell.walkable = True assert cell.walkable == True cell.walkable = False assert cell.walkable == False # Test transparent cell.transparent = True assert cell.transparent == True cell.transparent = False assert cell.transparent == False check("PG: cell properties", test_pg_cell_properties) def test_pg_entity_placement(): """Entity placement in generated rooms""" import random grid = mcrfpy.Grid(grid_size=(30, 30), pos=(0, 0), size=(400, 400)) # Place entities for i in range(5): e = mcrfpy.Entity(grid_pos=(10 + i, 10), sprite_index=i) grid.entities.append(e) assert len(grid.entities) == 5 check("PG: entity placement", test_pg_entity_placement) def test_pg_scene_setup(): """Scene setup for procgen""" scene = mcrfpy.Scene("pg_test") grid = mcrfpy.Grid(grid_size=(50, 50), pos=(0, 0), size=(400, 400)) scene.children.append(grid) player = mcrfpy.Entity(grid_pos=(25, 25), sprite_index=1) grid.entities.append(player) check("PG: scene setup", test_pg_scene_setup) def test_pg_timer_generation(): """Timer-based incremental generation""" step_count = [0] def generate_step(timer, runtime): step_count[0] += 1 if step_count[0] >= 3: timer.stop() t = mcrfpy.Timer("pg_gen", generate_step, 100) # Each step() call can fire at most one timer event for _ in range(5): mcrfpy.step(0.11) assert step_count[0] >= 3, f"Expected >= 3 fires, got {step_count[0]}" t.stop() check("PG: timer generation", test_pg_timer_generation) def test_pg_grid_size(): """Grid size access""" grid = mcrfpy.Grid(grid_size=(40, 30), pos=(0, 0), size=(400, 300)) gs = grid.grid_size assert gs[0] == 40 assert gs[1] == 30 check("PG: grid_size property", test_pg_grid_size) # =================================================================== print("\n=== GRID RENDERING PIPELINE ===") # =================================================================== def test_grp_layer_creation(): """Layer creation with standalone objects""" grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(320, 320), layers=[]) # Create layers as standalone objects bg = mcrfpy.ColorLayer(name="background", z_index=-2) grid.add_layer(bg) # Overlay above entities overlay = mcrfpy.ColorLayer(name="overlay", z_index=1) grid.add_layer(overlay) # Verify layers exist assert grid.layer("background") is not None assert grid.layer("overlay") is not None check("GRP: layer creation", test_grp_layer_creation) def test_grp_layer_operations(): """Layer set/at/fill operations""" grid = mcrfpy.Grid(grid_size=(10, 10), pos=(0, 0), size=(160, 160), layers=[]) cl = mcrfpy.ColorLayer(name="colors", z_index=-1) grid.add_layer(cl) # Fill cl.fill(mcrfpy.Color(0, 0, 0, 255)) # Set individual cell cl.set((5, 5), mcrfpy.Color(255, 0, 0, 255)) # Read back c = cl.at((5, 5)) assert c.r == 255 check("GRP: layer operations", test_grp_layer_operations) def test_grp_tile_layer(): """TileLayer creation""" grid = mcrfpy.Grid(grid_size=(10, 10), pos=(0, 0), size=(160, 160), layers=[]) tl = mcrfpy.TileLayer(name="tiles", z_index=-1) grid.add_layer(tl) assert grid.layer("tiles") is not None check("GRP: TileLayer creation", test_grp_tile_layer) def test_grp_z_index(): """Z-index layer ordering""" grid = mcrfpy.Grid(grid_size=(10, 10), pos=(0, 0), size=(160, 160), layers=[]) l1 = mcrfpy.ColorLayer(name="below", z_index=-2) l2 = mcrfpy.ColorLayer(name="above", z_index=1) grid.add_layer(l1) grid.add_layer(l2) below = grid.layer("below") above = grid.layer("above") assert below.z_index == -2 assert above.z_index == 1 check("GRP: z-index ordering", test_grp_z_index) def test_grp_fog_overlay(): """Fog overlay pattern with layer""" grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(320, 320), layers=[]) fog = mcrfpy.ColorLayer(name="fog", z_index=1) grid.add_layer(fog) fog.fill(mcrfpy.Color(0, 0, 0, 192)) # Make all cells transparent for FOV for x in range(20): for y in range(20): grid.at(x, y).transparent = True grid.at(x, y).walkable = True # Compute FOV and reveal grid.compute_fov((10, 10), radius=8) for x in range(20): for y in range(20): if grid.is_in_fov((x, y)): fog.set((x, y), mcrfpy.Color(0, 0, 0, 0)) # Origin should be revealed c = fog.at((10, 10)) assert c.a == 0 check("GRP: fog overlay", test_grp_fog_overlay) def test_grp_grid_properties(): """Grid rendering properties""" grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(320, 320)) # Check zoom property exists assert hasattr(grid, 'zoom') # Check center properties assert hasattr(grid, 'center') check("GRP: grid properties", test_grp_grid_properties) # =================================================================== print("\n=== GRID TCOD INTEGRATION ===") # =================================================================== def test_tcod_fov(): """FOV computation with tuple args""" grid = mcrfpy.Grid(grid_size=(30, 30), pos=(0, 0), size=(400, 400)) for x in range(30): for y in range(30): grid.at(x, y).transparent = True grid.at(x, y).walkable = True # Add wall grid.at(15, 10).transparent = False grid.at(15, 10).walkable = False # Compute FOV grid.compute_fov((10, 10), radius=10) # Origin should be visible assert grid.is_in_fov((10, 10)) # Behind wall might not be visible # (depends on exact algorithm, just check API works) grid.is_in_fov((20, 10)) # Just verify no crash check("TCOD: FOV computation", test_tcod_fov) def test_tcod_pathfinding(): """A* pathfinding with AStarPath object""" grid = mcrfpy.Grid(grid_size=(30, 30), pos=(0, 0), size=(400, 400)) for x in range(30): for y in range(30): grid.at(x, y).walkable = True # Find path path = grid.find_path((5, 5), (25, 25)) assert path is not None assert len(path) > 0 # Walk the path step = path.walk() assert step is not None # Check properties assert path.origin is not None assert path.destination is not None assert path.remaining >= 0 check("TCOD: A* pathfinding", test_tcod_pathfinding) def test_tcod_dijkstra(): """Dijkstra map with DijkstraMap object""" grid = mcrfpy.Grid(grid_size=(30, 30), pos=(0, 0), size=(400, 400)) for x in range(30): for y in range(30): grid.at(x, y).walkable = True dm = grid.get_dijkstra_map((15, 15)) # Get distance d = dm.distance((0, 0)) assert d > 0 # Get path p = dm.path_from((0, 0)) assert len(p) > 0 # Get next step s = dm.step_from((0, 0)) assert s is not None check("TCOD: Dijkstra map", test_tcod_dijkstra) def test_tcod_perspective(): """Grid perspective assignment""" grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(320, 320)) player = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=0) grid.entities.append(player) # Set perspective grid.perspective = player assert grid.perspective is not None check("TCOD: perspective", test_tcod_perspective) def test_tcod_dynamic_obstacle(): """Dynamic obstacle pattern""" grid = mcrfpy.Grid(grid_size=(20, 20), pos=(0, 0), size=(320, 320)) for x in range(20): for y in range(20): grid.at(x, y).walkable = True # Open door pattern door = grid.at(10, 10) door.walkable = False door.transparent = False # Verify path around door path = grid.find_path((5, 10), (15, 10)) assert path is not None # Should find path around # Open door door.walkable = True door.transparent = True # Path should now go through path2 = grid.find_path((5, 10), (15, 10)) assert path2 is not None # Direct path should be shorter assert len(path2) <= len(path) check("TCOD: dynamic obstacle", test_tcod_dynamic_obstacle) # =================================================================== print("\n=== PERFORMANCE PATTERNS ===") # =================================================================== def test_perf_benchmark_api(): """Check benchmark API exists""" assert hasattr(mcrfpy, 'start_benchmark') or True # May not exist # Just check step works for headless benchmarking dt = mcrfpy.step(0.016) assert dt is not None check("PERF: step-based benchmarking", test_perf_benchmark_api) def test_perf_timer_benchmark(): """Timer-based benchmarking pattern""" frame_times = [] def measure(timer, runtime): frame_times.append(runtime) if len(frame_times) >= 5: timer.stop() t = mcrfpy.Timer("perf_bench", measure, 50) mcrfpy.step(0.3) # Run several frames t.stop() assert len(frame_times) > 0 check("PERF: timer benchmark", test_perf_timer_benchmark) # =================================================================== print("\n=== PYTHON BINDING LAYER PATTERNS ===") # =================================================================== def test_pbl_grid_constructor(): """Modern grid constructor""" grid = mcrfpy.Grid(grid_size=(10, 10), pos=(0, 0), size=(160, 160)) gs = grid.grid_size assert gs[0] == 10 assert gs[1] == 10 check("PBL: Grid constructor", test_pbl_grid_constructor) def test_pbl_entity_constructor(): """Modern entity constructor""" e = mcrfpy.Entity(grid_pos=(5, 5), sprite_index=42) assert e.grid_x == 5 assert e.grid_y == 5 # sprite_index is set assert e.sprite_index == 42 check("PBL: Entity constructor", test_pbl_entity_constructor) def test_pbl_frame_constructor(): """Frame constructor with keywords""" f = mcrfpy.Frame(pos=(100, 200), size=(300, 150)) assert f.x == 100 assert f.y == 200 assert f.w == 300 assert f.h == 150 check("PBL: Frame constructor", test_pbl_frame_constructor) def test_pbl_sprite_constructor(): """Sprite constructor""" s = mcrfpy.Sprite(x=10, y=20, sprite_index=5) assert s.x == 10 assert s.y == 20 check("PBL: Sprite constructor", test_pbl_sprite_constructor) def test_pbl_caption_constructor(): """Caption constructor""" c = mcrfpy.Caption(text="Hello", pos=(50, 60)) assert c.text == "Hello" assert c.x == 50 check("PBL: Caption constructor", test_pbl_caption_constructor) def test_pbl_color(): """Color creation""" c = mcrfpy.Color(255, 128, 0, 200) assert c.r == 255 assert c.g == 128 assert c.b == 0 assert c.a == 200 check("PBL: Color object", test_pbl_color) def test_pbl_scene_api(): """Scene API pattern""" scene = mcrfpy.Scene("pbl_test") f = mcrfpy.Frame(pos=(0, 0), size=(100, 100)) scene.children.append(f) assert len(scene.children) >= 1 check("PBL: Scene API", test_pbl_scene_api) # Check what benchmark API exists def test_check_benchmark_api(): """Check which benchmark methods exist""" has_start = hasattr(mcrfpy, 'start_benchmark') has_end = hasattr(mcrfpy, 'end_benchmark') has_log = hasattr(mcrfpy, 'log_benchmark') print(f" start_benchmark: {has_start}, end_benchmark: {has_end}, log_benchmark: {has_log}") # Also check for sync methods on grid grid = mcrfpy.Grid(grid_size=(10, 10), pos=(0, 0), size=(160, 160)) has_sync = hasattr(grid, 'sync_tcod_map') has_sync_cell = hasattr(grid, 'sync_tcod_cell') print(f" sync_tcod_map: {has_sync}, sync_tcod_cell: {has_sync_cell}") # Check for FOV algorithm constants has_fov_basic = hasattr(mcrfpy, 'FOV_BASIC') print(f" FOV_BASIC constant: {has_fov_basic}") # Check cell.tilesprite cell = grid.at(0, 0) has_tilesprite = hasattr(cell, 'tilesprite') has_sprite_index = hasattr(cell, 'sprite_index') has_tile_index = hasattr(cell, 'tile_index') print(f" cell.tilesprite: {has_tilesprite}, cell.sprite_index: {has_sprite_index}, cell.tile_index: {has_tile_index}") # Check cell color property has_color = hasattr(cell, 'color') has_fill_color = hasattr(cell, 'fill_color') print(f" cell.color: {has_color}, cell.fill_color: {has_fill_color}") # Check entities_in_radius has_eir = hasattr(grid, 'entities_in_radius') print(f" entities_in_radius: {has_eir}") # List all grid cell (GridPoint) attributes cell_attrs = [a for a in dir(cell) if not a.startswith('_')] print(f" GridPoint attrs: {cell_attrs}") check("API: check available methods", test_check_benchmark_api) # =================================================================== print("\n" + "=" * 60) print(f"PHASE D3 VERIFICATION: {passes} passed, {fails} failed") print("=" * 60) if fails: sys.exit(1) else: sys.exit(0)