feat(packages): ludic.compass - bearing marks on a strip: marks gathered once a frame from an open registry of providers (CompassProviders), gated by the viewer's tier, sorted tracked / note / plain and culled to a cap; bearings and distances off the viewer's facing, the tracked mark, a capture that lets a guide hear the providers whatever the tier, the eight points, and the radar's range per tier with blips on a unit disc; the viewer through a port

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 09:35:52 +03:00
parent dc71fc986c
commit 1005a677f2
10 changed files with 453 additions and 0 deletions

View file

@ -0,0 +1,134 @@
# compass_test.ludic - a viewer at (vx, vz) facing yaw with a compass of `tier`, and two providers:
# the places (a camp ahead, a sign west, a far legend) and the objective. The tier gate, the order
# and the cap, bearings and distances, the tracked mark, a capture, the radar's tiers, the points.
import "ludic.compass"
import "ludic.base"
program CompassTest {
numbers float
var vx: float = 0.0
var vz: float = 0.0
var yaw: float = 0.0
var tier: int = 4
var objective: bool = true
function fk_x() -> float { return vx }
function fk_z() -> float { return vz }
function fk_yaw() -> float { return yaw }
function fk_tier() -> int { return tier }
bind CompassWorld { x: fn fk_x, z: fn fk_z, yaw: fn fk_yaw, tier: fn fk_tier }
function places() -> void {
compass_mark(0.0, -100.0, 1, 10, 1, COMPASS_PLAIN, "camp")
compass_mark(-50.0, 0.0, 2, 11, 2, COMPASS_PLAIN, "sign")
compass_mark(0.0, 300.0, 3, 12, 4, COMPASS_PLAIN, "legend")
compass_mark(10.0, 10.0, 4, 13, 1, COMPASS_NOTE, "my mark")
}
function goal() -> void { if objective { compass_mark(80.0, 0.0, 5, 14, 2, COMPASS_TRACKED, "the dock") } }
def CompassProviders places { gather: fn places }
def CompassProviders goal { gather: fn goal }
function fresh() -> void {
compass_config(64)
compass_config_radar([0.0, 0.0, 0.0, 120.0, 260.0], 2)
vx = 0.0
vz = 0.0
yaw = 0.0
tier = 4
objective = true
}
function labels() -> string {
var s = ""
for i in 0 .. compass_count() { s = s + compass_at(i).label + ";" }
return s
}
test "every provider is asked, the tracked mark first, then the player's, then the rest in order" {
fresh()
compass_gather()
expect_eq(compass_count(), 5)
expect(labels() == "the dock;my mark;camp;sign;legend;")
expect_eq(compass_tracked(), 0)
}
test "a mark shows from its tier up, and without a compass nothing is gathered" {
fresh()
tier = 1
compass_gather()
expect(labels() == "my mark;camp;")
expect_eq(compass_tracked(), -1)
tier = 0
compass_gather()
expect_eq(compass_count(), 0)
}
test "past the cap the lowest priorities go" {
fresh()
compass_config(2)
compass_gather()
expect(labels() == "the dock;my mark;")
}
test "a bearing is from the viewer's facing, a distance from where it stands" {
fresh()
compass_gather()
expect_near(compass_bearing(2), 0.0, 0.001)
expect_near(compass_dist(2), 100.0, 0.01)
expect_near(compass_bearing(3), 1.5708, 0.001)
expect_near(compass_bearing(0), -1.5708, 0.001)
yaw = 1.5708
expect_near(compass_bearing(3), 0.0, 0.001)
expect_near(compass_bearing(2), -1.5708, 0.001)
vx = -50.0
vz = 100.0
expect_near(compass_dist(3), 100.0, 0.01)
expect_near(compass_wrap(7.0), 7.0 - 6.2832, 0.001)
expect_near(compass_strip_t(0.5, 1.0), 0.5, 0.001)
}
test "a capture hears every mark whatever the tier and leaves the frame's list alone" {
fresh()
compass_gather()
tier = 1
compass_capture_begin()
expect(compass_capturing())
goal()
places()
let got = compass_capture_end()
expect(not compass_capturing())
expect_eq(len(got), 5)
expect(got[0].label == "the dock")
expect_eq(compass_count(), 5)
}
test "the radar: its range by tier, the blips in it, and where each falls on the disc" {
fresh()
tier = 2
compass_gather()
expect(not compass_radar_on())
expect(not compass_radar_has(0))
tier = 3
compass_gather()
expect(compass_radar_on())
expect_near(compass_radar_range(), 120.0, 0.01)
expect(compass_radar_has(0))
expect(not compass_radar_has(1))
expect(not compass_radar_has(2))
expect(compass_radar_has(3))
expect_near(compass_radar_x(3), -50.0 / 120.0, 0.001)
expect_near(compass_radar_y(3), 0.0, 0.001)
expect_near(compass_radar_x(0), 80.0 / 120.0, 0.001)
tier = 9
expect_near(compass_radar_range(), 260.0, 0.01)
}
test "the eight points go round from the heading 0 toward -x" {
expect_eq(compass_octant(0.0, -10.0), 0)
expect_eq(compass_octant(-10.0, -10.0), 1)
expect_eq(compass_octant(-10.0, 0.0), 2)
expect_eq(compass_octant(0.0, 10.0), 4)
expect_eq(compass_octant(10.0, 0.0), 6)
expect_eq(compass_octant(10.0, -10.0), 7)
expect_eq(compass_octant(1.0, -10.0), 0)
}
}