feat(packages): ludic.aim - what the crosshair is on: a ray through the middle of the screen against upright cylinders widened by a fixed angular forgiveness, the nearest one the ground does not hide, reach floored at three metres, and which thing the use key means (that, nothing and say why, or the nearest); the probe of the ground's own answer against the aim; the camera, the ground and the body through a port

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 09:07:51 +03:00
parent 24a35f1174
commit dc71fc986c
10 changed files with 399 additions and 0 deletions

View file

@ -0,0 +1,101 @@
# aim_test.ludic - a camera 1.5 m up looking down -z over flat ground with a ridge 42 m out: the ray
# against a cylinder, the forgiveness, near before far, the ground hiding a thing, the reach floor,
# which thing the use key means, and the probe agreeing with the ground
import "ludic.aim"
import "ludic.base"
program AimTest {
numbers float
var cx: float = 0.0
var cy: float = 1.5
var cz: float = 0.0
var fy: float = 0.0
function fk_x() -> float { return cx }
function fk_y() -> float { return cy }
function fk_z() -> float { return cz }
function fk_fy() -> float { return fy }
function fk_fz() -> float { return -Math.sqrt(1.0 - fy * fy) }
# a 6 m ridge along z = -42, thirty metres across, the whole width of the view
function fk_ground(x: float, z: float) -> float { return 6.0 * Math.max(0.0, 1.0 - Math.abs(z + 42.0) / 15.0) }
function fk_look(x: float, y: float, z: float) -> void {
cx = x
cy = y
cz = z
}
bind AimView { x: fn fk_x, y: fn fk_y, z: fn fk_z, fy: fn fk_fy, fz: fn fk_fz, ground: fn fk_ground }
function fresh() -> void {
cx = 0.0
cy = 1.5
cz = 0.0
fy = 0.0
aim_begin()
}
test "the ray enters a cylinder in front and misses one to the side or behind" {
fresh()
expect_near(aim_ray_cyl(0.0, 0.0, 2.0, -10.0, 0.5), 9.5, 0.01)
expect(aim_ray_cyl(3.0, 0.0, 2.0, -10.0, 0.5) < 0.0)
expect(aim_ray_cyl(0.0, 0.0, 2.0, 10.0, 0.5) < 0.0)
expect(aim_ray_cyl(0.0, 0.0, 1.0, -10.0, 0.5) < 0.0)
expect_near(aim_ray_cyl(0.0, 0.0, 2.0, 0.0, 0.5), 0.0, 0.001)
}
test "a thin thing far off is still aimable, by an angle and not a metre" {
fresh()
expect(aim_slack_m(20.0) > aim_slack_m(5.0) * 3.9)
expect(aim_offer(1, 7, 0.25, 0.0, 2.0, -20.0, 0.05, 1.5, 30.0))
expect(aim_off_centre() > 0.5)
fresh()
expect(not aim_offer(1, 7, 3.0, 0.0, 2.0, -20.0, 0.05, 1.5, 30.0))
}
test "the nearest thing the ray enters is the pick, whatever order they are offered in" {
fresh()
expect(aim_offer(1, 1, 0.0, 0.0, 2.0, -20.0, 0.5, 1.5, 30.0))
expect(aim_offer(1, 2, 0.0, 0.0, 2.0, -8.0, 0.5, 1.5, 30.0))
expect(not aim_offer(1, 3, 0.0, 0.0, 2.0, -15.0, 0.5, 1.5, 30.0))
expect_eq(aim_id(), 2)
expect_near(aim_dist(), 8.0, 0.01)
expect(not aim_offer(2, 4, 0.0, 0.0, 2.0, -25.0, 0.5, 1.5, 30.0))
expect(not aim_offer(2, 5, 0.0, 0.0, 2.0, -3.0, 0.5, 1.5, 2.0))
}
test "the ground in front hides a thing, and nothing within arm's length is hidden" {
fresh()
expect(not aim_clear_to(0.0, 1.0, -60.0))
expect(aim_clear_to(0.0, 1.0, -30.0))
expect(not aim_offer(1, 1, 0.0, 0.0, 2.0, -60.0, 2.0, 1.5, 80.0))
cy = -5.0
expect(aim_clear_to(0.0, -5.0, -2.0))
}
test "the crosshair decides which, the distance whether: every reach is floored at three metres" {
fresh()
expect_near(aim_reach_of(1.5), AIM_REACH_MIN, 0.001)
expect_near(aim_reach_of(3.4), 3.4, 0.001)
aim_offer(1, 1, 0.0, 0.0, 2.0, -2.6, 0.3, 1.5, 30.0)
expect(aim_in_reach())
expect_eq(aim_use(1), AIM_USE_THIS)
fresh()
aim_offer(1, 1, 0.0, 0.0, 2.0, -6.0, 0.3, 1.5, 30.0)
expect(not aim_in_reach())
expect_eq(aim_use(1), AIM_USE_NOTHING)
expect_eq(aim_use(3), AIM_USE_NEAREST)
fresh()
aim_offer(1, 1, 0.0, 0.0, 3.0, -20.0, 0.3, 1.5, 30.0)
expect_eq(aim_use(1), AIM_USE_NEAREST)
fresh()
aim_offer(2, 9, 0.0, 0.0, 2.0, -2.0, 0.3, AIM_NEVER, 30.0)
expect(not aim_in_reach())
expect_eq(aim_kind(), 2)
}
test "the probe finds the bank and agrees with the ground about every line it hides" {
fresh()
expect(aim_probe_ground(0.0, 0.0, fn fk_look))
expect(aim_probe_seen() > 100)
expect(aim_probe_blocked() > 0)
expect(not (aim_probe_disagree() > aim_probe_seen() / 50))
}
}