feat(grid): map YAML schema, 5-10-5 grid, Dijkstra movement, corner LoS/cover
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""Tests for corner-rule line of effect and cover (los.py).
|
||||
|
||||
Geometry convention: a line is blocked when its relative interior touches a
|
||||
blocking square (interior, border, or vertex); lines that merely start or end
|
||||
on a blocking square's vertex do not count as passing through it.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pf1e_simulator.grid import Grid
|
||||
from pf1e_simulator.los import has_cover, has_line_of_effect
|
||||
from pf1e_simulator.map import MapSpec, TerrainType
|
||||
|
||||
|
||||
def make_grid(rows: list[str]) -> Grid:
|
||||
legend = {
|
||||
"#": TerrainType(type="wall", move_cost=None, blocks_los=True),
|
||||
".": TerrainType(type="floor", move_cost=1),
|
||||
"T": TerrainType(type="rubble", move_cost=2),
|
||||
"C": TerrainType(type="pillar", move_cost=None, cover=True),
|
||||
}
|
||||
spec = MapSpec(name="test", terrain=tuple(rows), legend=legend)
|
||||
return Grid.from_spec(spec)
|
||||
|
||||
|
||||
def test_los_open_field() -> None:
|
||||
grid = make_grid(["...", "...", "..."])
|
||||
assert has_line_of_effect(grid, (0, 0), (2, 2)) is True
|
||||
|
||||
|
||||
def test_los_same_square() -> None:
|
||||
grid = make_grid(["."])
|
||||
assert has_line_of_effect(grid, (0, 0), (0, 0)) is True
|
||||
|
||||
|
||||
def test_los_blocked_by_wall_between() -> None:
|
||||
grid = make_grid([".#.", "..."])
|
||||
assert has_line_of_effect(grid, (0, 0), (0, 2)) is False
|
||||
|
||||
|
||||
def test_los_through_doorway_gap() -> None:
|
||||
grid = make_grid(["##.##", "##.##"])
|
||||
assert has_line_of_effect(grid, (0, 2), (1, 2)) is True
|
||||
|
||||
|
||||
def test_los_pinched_vertex_stays_open() -> None:
|
||||
grid = make_grid([".#.", "#.."])
|
||||
assert has_line_of_effect(grid, (0, 0), (1, 1)) is True
|
||||
|
||||
|
||||
def test_los_blocked_past_wall_line() -> None:
|
||||
grid = make_grid(["...#.", "....."])
|
||||
assert has_line_of_effect(grid, (0, 0), (0, 4)) is False
|
||||
|
||||
|
||||
def test_cover_open_field() -> None:
|
||||
grid = make_grid([".....", "....."])
|
||||
assert has_cover(grid, (0, 0), (0, 4), ranged=True) is False
|
||||
|
||||
|
||||
def test_cover_pillar_between() -> None:
|
||||
grid = make_grid([".....", "..C..", "....."])
|
||||
assert has_cover(grid, (1, 0), (1, 4), ranged=True) is True
|
||||
|
||||
|
||||
def test_no_cover_when_pillar_off_axis() -> None:
|
||||
grid = make_grid(["..C..", "....."])
|
||||
assert has_cover(grid, (1, 0), (1, 4), ranged=True) is False
|
||||
|
||||
|
||||
def test_no_cover_adjacent_with_wall_behind_target() -> None:
|
||||
grid = make_grid(["..#"])
|
||||
assert has_cover(grid, (0, 0), (0, 1), ranged=True) is False
|
||||
|
||||
|
||||
def test_cover_diagonal_past_wall_vertex() -> None:
|
||||
grid = make_grid([".#.", "#.."])
|
||||
assert has_cover(grid, (0, 0), (1, 1), ranged=True) is True
|
||||
|
||||
|
||||
def test_cover_melee_uses_same_corner_rule_in_phase0() -> None:
|
||||
grid = make_grid([".#.", "#.."])
|
||||
assert has_cover(grid, (0, 0), (1, 1), ranged=False) is True
|
||||
open_grid = make_grid(["...", "..."])
|
||||
assert has_cover(open_grid, (0, 0), (1, 1), ranged=False) is False
|
||||
|
||||
|
||||
def test_cover_same_square_is_false() -> None:
|
||||
grid = make_grid(["."])
|
||||
assert has_cover(grid, (0, 0), (0, 0), ranged=True) is False
|
||||
Reference in New Issue
Block a user