61 lines
2.5 KiB
Text
61 lines
2.5 KiB
Text
# probe.ludic - does the aim agree with the ground about what it hides? From (px, pz) and a ring of
|
|
# eight points 250 m round it, at 60, 120 and 200 m on 36 bearings, the answer worked out by walking
|
|
# the ground under each line against aim_clear_to. Lines the ground merely grazes are left out: that
|
|
# is the probe's sampling against the aim's, not a disagreement. Moves the camera (AimView's) through
|
|
# `look`, which the game binds to put its camera at a point.
|
|
var am_seen: int = 0
|
|
var am_blocked: int = 0
|
|
var am_disagree: int = 0
|
|
|
|
export function aim_probe_seen() -> int { return am_seen }
|
|
export function aim_probe_blocked() -> int { return am_blocked }
|
|
export function aim_probe_disagree() -> int { return am_disagree }
|
|
|
|
# true when at least one line is hidden and the aim disagrees with the ground on at most one in fifty
|
|
export function aim_probe_ground(px: float, pz: float, look: fn(float, float, float) -> void) -> bool {
|
|
am_seen = 0
|
|
am_blocked = 0
|
|
am_disagree = 0
|
|
for sp in 0 .. 9 {
|
|
var sx = px
|
|
var sz = pz
|
|
if sp > 0 {
|
|
let sa = float(sp - 1) / 8.0 * 6.2831853
|
|
sx = px + Math.sin(sa) * 250.0
|
|
sz = pz + Math.cos(sa) * 250.0
|
|
}
|
|
if AimView.dry(sx, sz) { am_probe_from(sx, AimView.ground(sx, sz) + 1.6, sz, look) }
|
|
}
|
|
return am_blocked >= 1 and not (am_disagree > am_seen / 50)
|
|
}
|
|
|
|
function am_probe_from(sx: float, sy: float, sz: float, look: fn(float, float, float) -> void) -> void {
|
|
for di in 0 .. 3 {
|
|
var dist = 60.0
|
|
if di == 1 { dist = 120.0 }
|
|
if di == 2 { dist = 200.0 }
|
|
for b in 0 .. 36 {
|
|
let bearing = float(b) / 36.0 * 6.2831853
|
|
let ex = sx + Math.sin(bearing) * dist
|
|
let ez = sz + Math.cos(bearing) * dist
|
|
let ey = AimView.ground(ex, ez) + 0.4
|
|
let truth = am_probe_gap(sx, sy, sz, ex, ey, ez, 0.5, 10000.0)
|
|
if am_probe_gap(sx, sy, sz, ex, ey, ez, -0.5, 0.5) and not truth { continue }
|
|
look(sx, sy, sz)
|
|
am_seen += 1
|
|
let clear = aim_clear_to(ex, ey, ez)
|
|
if not clear { am_blocked += 1 }
|
|
if clear == truth { am_disagree += 1 }
|
|
}
|
|
}
|
|
}
|
|
|
|
# somewhere between the ends (excluded), the ground stands between lo and hi above the line
|
|
function am_probe_gap(sx: float, sy: float, sz: float, ex: float, ey: float, ez: float, lo: float, hi: float) -> bool {
|
|
for k in 2 .. 38 {
|
|
let t = float(k) / 40.0
|
|
let gap = AimView.ground(Math.lerp(sx, ex, t), Math.lerp(sz, ez, t)) - Math.lerp(sy, ey, t)
|
|
if gap > lo and gap < hi { return true }
|
|
}
|
|
return false
|
|
}
|