wip(0.S2): migrate - a var nothing writes becomes a let; a state is keyed by its module, directory or program, so every program's plan agrees; paths normalized; program states named SceneDemoState / scene_demo_st; the LSP reads state, mut and entry/handler parameters

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 15:31:34 +03:00
parent 3eda72e8c2
commit 5ffe50ed02
463 changed files with 72045 additions and 67421 deletions

View file

@ -16,224 +16,222 @@ program VehiclesTest {
return -10000.0
}
function fk_blocked(x: float, z: float, r: float) -> bool { return Math.abs(x) < 1.0 + r and Math.abs(z + 60.0) < 1.0 + r }
state VehiclestestState {
swell: float = 0.0
wind: float = 0.0
made: int = 0
gone: int = 0
placed: int = 0
rx: float = 0.0
ry: float = 0.0
rz: float = 0.0
boarded: int = 0
sx: float = 0.0
sz: float = 0.0
}
function fk_swell(vehiclestest_st: VehiclestestState, x: float, z: float, fx: float, fz: float) -> float {
if fx > 0.0 { return vehiclestest_st.swell }
var swell: float = 0.0
function fk_swell(x: float, z: float, fx: float, fz: float) -> float {
if fx > 0.0 { return swell }
return 0.0
}
function fk_wind(vehiclestest_st: VehiclestestState) -> float { return vehiclestest_st.wind }
function fk_made(vehiclestest_st: mut VehiclestestState, v: Vehicle) -> void { vehiclestest_st.made += 1 }
function fk_gone(vehiclestest_st: mut VehiclestestState, v: Vehicle) -> void { vehiclestest_st.gone += 1 }
function fk_placed(vehiclestest_st: mut VehiclestestState, v: Vehicle) -> void { vehiclestest_st.placed += 1 }
var wind: float = 0.0
function fk_wind() -> float { return wind }
var made: int = 0
var gone: int = 0
var placed: int = 0
function fk_made(v: Vehicle) -> void { made += 1 }
function fk_gone(v: Vehicle) -> void { gone += 1 }
function fk_placed(v: Vehicle) -> void { placed += 1 }
# the rider: where it was put, and a safe spot that walks back toward the shore
function fk_board(vehiclestest_st: mut VehiclestestState, x: float, z: float, yaw: float) -> void { vehiclestest_st.boarded += 1 }
function fk_ride(vehiclestest_st: mut VehiclestestState, x: float, y: float, z: float, yaw: float, speed: float) -> void {
vehiclestest_st.rx = x
vehiclestest_st.ry = y
vehiclestest_st.rz = z
var rx: float = 0.0
var ry: float = 0.0
var rz: float = 0.0
var boarded: int = 0
var sx: float = 0.0
var sz: float = 0.0
function fk_board(x: float, z: float, yaw: float) -> void { boarded += 1 }
function fk_ride(x: float, y: float, z: float, yaw: float, speed: float) -> void {
rx = x
ry = y
rz = z
}
function fk_off(vehiclestest_st: mut VehiclestestState, x: float, z: float) -> void {
vehiclestest_st.rx = x
vehiclestest_st.rz = z
vehiclestest_st.ry = fk_ground(x, z)
function fk_off(x: float, z: float) -> void {
rx = x
rz = z
ry = fk_ground(x, z)
}
function fk_safe(vehiclestest_st: mut VehiclestestState, x: float, z: float, from_y: float, max_depth: float) -> bool {
function fk_safe(x: float, z: float, from_y: float, max_depth: float) -> bool {
for s in 0 .. 11 {
let px = x - float(s)
let depth = fk_water(px, z) - fk_ground(px, z)
if not (depth > max_depth) {
vehiclestest_st.sx = px
vehiclestest_st.sz = z
sx = px
sz = z
return true
}
}
return false
}
function fk_sx(vehiclestest_st: VehiclestestState) -> float { return vehiclestest_st.sx }
function fk_sz(vehiclestest_st: VehiclestestState) -> float { return vehiclestest_st.sz }
function fk_sx() -> float { return sx }
function fk_sz() -> float { return sz }
bind VehicleWorld { ground: fn fk_ground, water: fn fk_water, blocked: fn fk_blocked, swell: fn fk_swell, wind: fn fk_wind, made: fn fk_made, gone: fn fk_gone, placed: fn fk_placed }
bind VehicleRider { board: fn fk_board, ride_at: fn fk_ride, step_off: fn fk_off, safe_spot: fn fk_safe, safe_x: fn fk_sx, safe_z: fn fk_sz }
const EAST: float = -1.5707963
function fresh(base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) -> void {
vehicles_reset(base_st, vehicles_st)
vehicles_dock_at(vehicles_st, 10.0, 0.0, EAST)
vehicles_rail_at(vehicles_st, 0.0, 5.0, 0.0)
vehiclestest_st.made = 0
vehiclestest_st.gone = 0
vehiclestest_st.swell = 0.0
vehiclestest_st.wind = 0.0
function fresh() -> void {
vehicles_reset()
vehicles_dock_at(10.0, 0.0, EAST)
vehicles_rail_at(0.0, 5.0, 0.0)
made = 0
gone = 0
swell = 0.0
wind = 0.0
}
function facts(base_st: mut BaseState, vehicles_st: mut VehiclesState) -> []VehicleFact { return q_drain(base_st, vehicle_facts(base_st, vehicles_st)) }
function facts() -> []VehicleFact { return q_drain(vehicle_facts()) }
function count(fs: []VehicleFact, what: int) -> int {
var n = 0
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
return n
}
function ride(base_st: mut BaseState, vehicles_st: mut VehiclesState, ix: float, iz: float, run: bool, secs: float) -> void {
for i in 0 .. int(secs * 60.0) { vehicle_update(base_st, vehicles_st, ix, iz, run, 1.0 / 60.0) }
function ride(ix: float, iz: float, run: bool, secs: float) -> void {
for i in 0 .. int(secs * 60.0) { vehicle_update(ix, iz, run, 1.0 / 60.0) }
}
test "a berth is off the pier head in the water, a bay on the meadow" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
expect_near(vehicle_berth_x(vehicles_st, 0), 17.25, 0.01)
expect_near(vehicle_berth_z(vehicles_st, 0), -3.3, 0.01)
expect_near(vehicle_post_x(vehicles_st, 3), 16.15, 0.01)
expect_near(vehicle_bay_z(vehicles_st, 2), 3.6, 0.01)
test "a berth is off the pier head in the water, a bay on the meadow" {
fresh()
expect_near(vehicle_berth_x(0), 17.25, 0.01)
expect_near(vehicle_berth_z(0), -3.3, 0.01)
expect_near(vehicle_post_x(3), 16.15, 0.01)
expect_near(vehicle_bay_z(2), 3.6, 0.01)
}
test "the first call makes a vehicle, a later one fetches it, and a taken place refuses" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
expect(vehicle_call_for(vehicles_st, 0, VEHICLE_BOAT, 0))
expect_eq(vehiclestest_st.made, 1)
let b = vehicle_find(vehicles_st, VEHICLE_BOAT)
test "the first call makes a vehicle, a later one fetches it, and a taken place refuses" {
fresh()
expect(vehicle_call_for(0, VEHICLE_BOAT, 0))
expect_eq(made, 1)
let b = vehicle_find(VEHICLE_BOAT)
expect(b != null)
expect_near(b.y, 0.02, 0.001)
expect(vehicle_call_for(vehicles_st, 0, VEHICLE_BOAT, 0))
expect_eq(vehiclestest_st.made, 1)
expect(not vehicle_call_for(vehicles_st, 2, VEHICLE_BOAT, 0))
expect(vehicle_call_for(vehicles_st, 2, VEHICLE_BOAT, 1))
expect_eq(vehiclestest_st.made, 2)
expect(vehicle_call_for(vehicles_st, 0, VEHICLE_BOAT, 2))
expect(vehicle_in_place(vehicles_st, VEHICLE_BOAT, 0) == null)
expect_eq(vehicle_free_place(vehicles_st, VEHICLE_BOAT), 0)
expect(vehicle_mine_in_place(vehicles_st, VEHICLE_BOAT))
expect(vehicle_call_for(0, VEHICLE_BOAT, 0))
expect_eq(made, 1)
expect(not vehicle_call_for(2, VEHICLE_BOAT, 0))
expect(vehicle_call_for(2, VEHICLE_BOAT, 1))
expect_eq(made, 2)
expect(vehicle_call_for(0, VEHICLE_BOAT, 2))
expect(vehicle_in_place(VEHICLE_BOAT, 0) == null)
expect_eq(vehicle_free_place(VEHICLE_BOAT), 0)
expect(vehicle_mine_in_place(VEHICLE_BOAT))
}
test "a player leaving takes theirs away; this machine's player never leaves" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
vehicle_call_for(vehicles_st, 3, VEHICLE_HORSE, 1)
vehicles_release(vehicles_st, 0)
expect_eq(len(vehicles_all(vehicles_st)), 2)
vehicles_release(vehicles_st, 3)
expect_eq(len(vehicles_all(vehicles_st)), 1)
expect_eq(vehiclestest_st.gone, 1)
expect(vehicle_in_place(vehicles_st, VEHICLE_HORSE, 1) == null)
test "a player leaving takes theirs away; this machine's player never leaves" {
fresh()
vehicle_call_for(0, VEHICLE_HORSE, 0)
vehicle_call_for(3, VEHICLE_HORSE, 1)
vehicles_release(0)
expect_eq(len(vehicles_all()), 2)
vehicles_release(3)
expect_eq(len(vehicles_all()), 1)
expect_eq(gone, 1)
expect(vehicle_in_place(VEHICLE_HORSE, 1) == null)
}
test "a hungry horse will not go; a fed one is mounted, and only by its owner" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
vehicle_call_for(vehicles_st, 4, VEHICLE_HORSE, 1)
let h = vehicle_find(vehicles_st, VEHICLE_HORSE)
test "a hungry horse will not go; a fed one is mounted, and only by its owner" {
fresh()
vehicle_call_for(0, VEHICLE_HORSE, 0)
vehicle_call_for(4, VEHICLE_HORSE, 1)
let h = vehicle_find(VEHICLE_HORSE)
h.food = 5.0
expect(not vehicle_mount(base_st, vehicles_st, h))
expect_eq(count(facts(base_st, vehicles_st), VEHICLE_HUNGRY), 1)
vehicle_feed(base_st, vehicles_st, h, 50.0)
expect(not vehicle_mount(h))
expect_eq(count(facts(), VEHICLE_HUNGRY), 1)
vehicle_feed(h, 50.0)
expect_near(h.food, 55.0, 0.001)
expect(not vehicle_mount(base_st, vehicles_st, vehicle_of(vehicles_st, 4, VEHICLE_HORSE)))
vehiclestest_st.boarded = 0
expect(vehicle_mount(base_st, vehicles_st, h))
expect_eq(vehiclestest_st.boarded, 1)
expect_eq(vehicle_ride_kind(vehicles_st), VEHICLE_HORSE)
expect(not vehicle_mount(vehicle_of(4, VEHICLE_HORSE)))
boarded = 0
expect(vehicle_mount(h))
expect_eq(boarded, 1)
expect_eq(vehicle_ride_kind(), VEHICLE_HORSE)
expect_eq(h.rider, 0)
expect(vehicle_nearest(vehicles_st, h.x, h.z, 5.0) == null)
expect(vehicle_in_place(vehicles_st, VEHICLE_HORSE, 0) == null)
expect(vehicle_nearest(h.x, h.z, 5.0) == null)
expect(vehicle_in_place(VEHICLE_HORSE, 0) == null)
}
test "a horse walks, gallops on stamina, stops at the water and at a trunk" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
let h = vehicle_find(vehicles_st, VEHICLE_HORSE)
vehicle_mount(base_st, vehicles_st, h)
ride(base_st, vehicles_st, 0.0, 1.0, false, 3.0)
test "a horse walks, gallops on stamina, stops at the water and at a trunk" {
fresh()
vehicle_call_for(0, VEHICLE_HORSE, 0)
let h = vehicle_find(VEHICLE_HORSE)
vehicle_mount(h)
ride(0.0, 1.0, false, 3.0)
expect_near(h.speed, 4.5, 0.05)
expect(count(facts(base_st, vehicles_st), VEHICLE_MOVED) > 100)
ride(base_st, vehicles_st, 0.0, 1.0, true, 3.0)
expect(count(facts(), VEHICLE_MOVED) > 100)
ride(0.0, 1.0, true, 3.0)
expect_near(h.speed, 11.0, 0.1)
expect(h.fuel < 100.0)
expect(h.z < -15.0)
expect_near(vehiclestest_st.rz, h.z, 0.001)
expect_near(vehiclestest_st.ry, 1.35, 0.001)
expect_near(rz, h.z, 0.001)
expect_near(ry, 1.35, 0.001)
# the trunk at z = -60 stops it
ride(base_st, vehicles_st, 0.0, 1.0, true, 6.0)
ride(0.0, 1.0, true, 6.0)
expect(h.z > -60.0 + 1.7)
expect_near(h.speed, 0.0, 0.001)
# and the lake to the east does too
vehicle_drop(vehicles_st)
vehicle_drop()
h.x = 7.0
h.z = 0.0
h.yaw = EAST
vehicle_mount(base_st, vehicles_st, h)
ride(base_st, vehicles_st, 0.0, 1.0, false, 4.0)
vehicle_mount(h)
ride(0.0, 1.0, false, 4.0)
expect(h.x < 9.6)
}
test "a boat rows on water, stops at the shore, loses its stroke to the swell, drifts on the wind" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
vehicle_call_for(vehicles_st, 0, VEHICLE_BOAT, 0)
let b = vehicle_find(vehicles_st, VEHICLE_BOAT)
vehicle_mount(base_st, vehicles_st, b)
ride(base_st, vehicles_st, 0.0, 1.0, false, 2.0)
test "a boat rows on water, stops at the shore, loses its stroke to the swell, drifts on the wind" {
fresh()
vehicle_call_for(0, VEHICLE_BOAT, 0)
let b = vehicle_find(VEHICLE_BOAT)
vehicle_mount(b)
ride(0.0, 1.0, false, 2.0)
let x2 = b.x
expect(x2 > 18.0)
vehiclestest_st.swell = 1.0
ride(base_st, vehicles_st, 0.0, 1.0, false, 1.0)
swell = 1.0
ride(0.0, 1.0, false, 1.0)
expect_near(b.x, x2, 0.2)
expect_eq(count(facts(base_st, vehicles_st), VEHICLE_SWELL), 1)
vehiclestest_st.swell = 0.0
ride(base_st, vehicles_st, 0.0, -1.0, false, 12.0)
expect_eq(count(facts(), VEHICLE_SWELL), 1)
swell = 0.0
ride(0.0, -1.0, false, 12.0)
expect(b.x > 10.3)
vehiclestest_st.wind = 1.0
wind = 1.0
let z0 = b.z
ride(base_st, vehicles_st, 0.0, 0.0, false, 1.0)
ride(0.0, 0.0, false, 1.0)
expect(b.z < z0)
}
test "getting off a boat needs a shore near enough; a horse is left tied where it stands" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
vehicle_call_for(vehicles_st, 0, VEHICLE_BOAT, 0)
let b = vehicle_find(vehicles_st, VEHICLE_BOAT)
vehicle_mount(base_st, vehicles_st, b)
test "getting off a boat needs a shore near enough; a horse is left tied where it stands" {
fresh()
vehicle_call_for(0, VEHICLE_BOAT, 0)
let b = vehicle_find(VEHICLE_BOAT)
vehicle_mount(b)
b.x = 40.0
expect(not vehicle_dismount(base_st, vehicles_st))
expect_eq(count(facts(base_st, vehicles_st), VEHICLE_NO_LANDING), 1)
expect_eq(vehicle_ride_kind(vehicles_st), VEHICLE_BOAT)
expect(not vehicle_dismount())
expect_eq(count(facts(), VEHICLE_NO_LANDING), 1)
expect_eq(vehicle_ride_kind(), VEHICLE_BOAT)
b.x = 12.0
expect(vehicle_dismount(base_st, vehicles_st))
expect_near(vehiclestest_st.rx, 11.0, 0.001)
expect_eq(vehicle_ride_kind(vehicles_st), 0)
expect(vehicle_dismount())
expect_near(rx, 11.0, 0.001)
expect_eq(vehicle_ride_kind(), 0)
expect_eq(b.rider, -1)
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
let h = vehicle_find(vehicles_st, VEHICLE_HORSE)
vehicle_mount(base_st, vehicles_st, h)
vehicle_call_for(0, VEHICLE_HORSE, 0)
let h = vehicle_find(VEHICLE_HORSE)
vehicle_mount(h)
h.x = -5.0
h.z = -5.0
expect(vehicle_dismount(base_st, vehicles_st))
expect(vehicle_dismount())
expect_near(h.home_x, -5.0, 0.001)
expect(vehicle_in_place(vehicles_st, VEHICLE_HORSE, 0) == null)
expect_near(vehiclestest_st.rx, -5.0 + 1.2, 0.001)
expect(vehicle_in_place(VEHICLE_HORSE, 0) == null)
expect_near(rx, -5.0 + 1.2, 0.001)
}
test "this player's own are saved by kind, and a save read before they are made still applies" (base_st: mut BaseState, vehicles_st: mut VehiclesState, vehiclestest_st: mut VehiclestestState) {
fresh(base_st, vehicles_st, vehiclestest_st)
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
vehicle_call_for(vehicles_st, 0, VEHICLE_BOAT, 0)
vehicle_own(vehicle_find(vehicles_st, VEHICLE_HORSE))
vehicle_find(vehicles_st, VEHICLE_HORSE).food = 77.0
let saved = vehicles_save(vehicles_st)
fresh(base_st, vehicles_st, vehiclestest_st)
vehicles_load(vehicles_st, saved, 1)
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
vehicle_call_for(vehicles_st, 0, VEHICLE_BOAT, 0)
expect(vehicle_find(vehicles_st, VEHICLE_HORSE).owned)
expect_near(vehicle_find(vehicles_st, VEHICLE_HORSE).food, 77.0, 0.01)
expect(not vehicle_find(vehicles_st, VEHICLE_BOAT).owned)
test "this player's own are saved by kind, and a save read before they are made still applies" {
fresh()
vehicle_call_for(0, VEHICLE_HORSE, 0)
vehicle_call_for(0, VEHICLE_BOAT, 0)
vehicle_own(vehicle_find(VEHICLE_HORSE))
vehicle_find(VEHICLE_HORSE).food = 77.0
let saved = vehicles_save()
fresh()
vehicles_load(saved, 1)
vehicle_call_for(0, VEHICLE_HORSE, 0)
vehicle_call_for(0, VEHICLE_BOAT, 0)
expect(vehicle_find(VEHICLE_HORSE).owned)
expect_near(vehicle_find(VEHICLE_HORSE).food, 77.0, 0.01)
expect(not vehicle_find(VEHICLE_BOAT).owned)
}
}