"""Wall terrain for template: seeded rectangular blocks + focal-only channels.""" from __future__ import annotations import random import proteus.game.scenarios # noqa: F401 (registers scenarios) from proteus.game.engine.difficulty import Difficulty from proteus.game.engine.grid import MotiveGridGame from proteus.game.scenarios.base import get_scenario def _scn(seed=7, diff=Difficulty.MEDIUM): scn = get_scenario("template")() game = MotiveGridGame(scn, random.Random(seed), diff, max_steps=20) return scn, game def test_walls_are_generated_and_deterministic(): a, _ = _scn(seed=7) b, _ = _scn(seed=7) assert a._wall_cells == b._wall_cells assert len(a._wall_cells) > 0 assert a._wall_rects # non-empty def test_walls_clear_spawns_and_border(): scn, _ = _scn(seed=7) w, h = scn.grid_size # spawn footprints must be wall-free (focal 2x2 at (5,30), predator 3x3 at (54,30)) for (sx, sy, sw, sh) in [(5, 30, 2, 2), (54, 30, 3, 3)]: for j in range(sh): for i in range(sw): assert (sx + i, sy + j) not in scn._wall_cells # 1-cell border ring is free for x in range(w): assert (x, 0) not in scn._wall_cells and (x, h - 1) not in scn._wall_cells def test_has_a_focal_only_channel(): """Some 2x2-passable cell is NOT 3x3-passable: a focal-only gap exists.""" scn, _ = _scn(seed=7) w, h = scn.grid_size wc = scn._wall_cells def fp_free(x, y, n): for j in range(n): for i in range(n): cx, cy = x + i, y + j if not (0 <= cx < w and 0 <= cy < h) or (cx, cy) in wc: return False return True found = any( fp_free(x, y, 2) and not fp_free(x, y, 3) for x in range(w) for y in range(h) ) assert found, "expected at least one focal-only (2x2 yes, 3x3 no) anchor" def test_predator_can_reach_focal_region(): """Predator (3x3) BFS from its spawn reaches adjacency of the focal spawn.""" scn, _ = _scn(seed=7) w, h = scn.grid_size wc = scn._wall_cells def fp_free3(x, y): return all( 0 <= x + i < w and 0 <= y + j < h and (x + i, y + j) not in wc for j in range(3) for i in range(3) ) from collections import deque start = (54, 30) seen = {start} q = deque([start]) while q: x, y = q.popleft() for dx, dy in ((0, -1), (0, 1), (-1, 0), (1, 0)): nx, ny = x + dx, y + dy if (nx, ny) not in seen and fp_free3(nx, ny): seen.add((nx, ny)); q.append((nx, ny)) # an anchor whose 3x3 footprint can sit adjacent to the focal spawn (5,30) assert any(abs(ax - 5) <= 6 and abs(ay - 30) <= 6 for (ax, ay) in seen) def test_focal_cannot_move_into_a_wall(): scn, game = _scn(seed=7) focal = game.focal_sprite wx, wy = sorted(scn._wall_cells)[len(scn._wall_cells) // 2] # place focal so moving +1 x makes its 2x2 footprint cover (wx,wy) focal.set_position(wx - 2, wy) # footprint x[wx-2, wx), not yet on wall assert (focal.x, focal.y) == (wx - 2, wy) game.apply_motive_action("right") # would put footprint over (wx,wy) assert focal.x == wx - 2, "move into wall must be reverted by the engine" def test_predator_never_lands_on_a_wall(): scn, game = _scn(seed=7, diff=Difficulty.MEDIUM) for _ in range(60): if game.eliminated or game.survived: break game.apply_motive_action("stay") pred = game.predator_sprite cells = {(pred.x + i, pred.y + j) for j in range(pred.height) for i in range(pred.width)} assert not (cells & scn._wall_cells), "predator footprint entered a wall" def test_legend_includes_wall_symbol(): scn, _ = _scn(seed=7) assert scn.legend().get(3) == "#" def test_render_frame_lists_walls_and_wall_rects_match(): scn, game = _scn(seed=7) frame = scn.render_frame(game) assert "Walls (blocked rectangles" in frame assert scn.wall_rects() == scn._wall_rects assert scn.wall_rects() # non-empty for template