wip(0.S3): the packages migrated by ludic migrate state packages - every package test green
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1e8b5b0523
commit
07505e7ef2
294 changed files with 14996 additions and 14675 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# call.ludic - a player's boat or horse brought to a place: made there the first time, fetched there
|
||||
# after; gone when its player leaves
|
||||
function ve_add(kind: int, x: float, z: float, yaw: float) -> Vehicle {
|
||||
function ve_add(vehicles_st: mut VehiclesState, kind: int, x: float, z: float, yaw: float) -> Vehicle {
|
||||
if kind != VEHICLE_HORSE and kind != VEHICLE_BOAT { return null }
|
||||
let v = new Vehicle
|
||||
v.nid = VehicleWorld.next_id()
|
||||
|
|
@ -14,7 +14,7 @@ function ve_add(kind: int, x: float, z: float, yaw: float) -> Vehicle {
|
|||
v.seat_h = 0.30
|
||||
}
|
||||
ve_put(v, x, z)
|
||||
push(ve_all(), v)
|
||||
push(ve_all(vehicles_st), v)
|
||||
VehicleWorld.made(v)
|
||||
return v
|
||||
}
|
||||
|
|
@ -31,46 +31,46 @@ function ve_put(v: Vehicle, x: float, z: float) -> void {
|
|||
|
||||
# Bring player pid's boat or horse to place k. False when the place is somebody else's, or it is
|
||||
# being ridden. A horse faces the trough: the bay lies on its near side.
|
||||
export function vehicle_call_for(pid: int, kind: int, k: int) -> bool {
|
||||
if not ve_have_dock or k < 0 or k >= VEHICLE_PLACES { return false }
|
||||
let here = vehicle_in_place(kind, k)
|
||||
let v = vehicle_of(pid, kind)
|
||||
export function vehicle_call_for(vehicles_st: mut VehiclesState, pid: int, kind: int, k: int) -> bool {
|
||||
if not vehicles_st.ve_have_dock or k < 0 or k >= VEHICLE_PLACES { return false }
|
||||
let here = vehicle_in_place(vehicles_st, kind, k)
|
||||
let v = vehicle_of(vehicles_st, pid, kind)
|
||||
if here != null { return v != null and here.nid == v.nid }
|
||||
var yaw = ve_dock_yaw
|
||||
if kind == VEHICLE_HORSE { yaw = ve_rail_yaw }
|
||||
var yaw = vehicles_st.ve_dock_yaw
|
||||
if kind == VEHICLE_HORSE { yaw = vehicles_st.ve_rail_yaw }
|
||||
if v == null {
|
||||
let made = ve_add(kind, vehicle_place_x(kind, k), vehicle_place_z(kind, k), yaw)
|
||||
let made = ve_add(vehicles_st, kind, vehicle_place_x(vehicles_st, kind, k), vehicle_place_z(vehicles_st, kind, k), yaw)
|
||||
if made == null { return false }
|
||||
made.owner = pid
|
||||
if pid == 0 { ve_apply_kept(made) }
|
||||
if pid == 0 { ve_apply_kept(vehicles_st, made) }
|
||||
return true
|
||||
}
|
||||
if v.rider >= 0 { return false }
|
||||
ve_put(v, vehicle_place_x(kind, k), vehicle_place_z(kind, k))
|
||||
ve_put(v, vehicle_place_x(vehicles_st, kind, k), vehicle_place_z(vehicles_st, kind, k))
|
||||
v.yaw = yaw
|
||||
VehicleWorld.placed(v)
|
||||
return true
|
||||
}
|
||||
|
||||
# a player left: their boat and horse go with them, and their places are free
|
||||
export function vehicles_release(pid: int) -> void {
|
||||
export function vehicles_release(vehicles_st: mut VehiclesState, pid: int) -> void {
|
||||
if pid == 0 { return }
|
||||
let keep = new []Vehicle
|
||||
let l = ve_all()
|
||||
let l = ve_all(vehicles_st)
|
||||
for i in 0 .. len(l) {
|
||||
if l[i].owner != pid { push(keep, l[i]) } else { VehicleWorld.gone(l[i]) }
|
||||
}
|
||||
ve_list = keep
|
||||
vehicles_st.ve_list = keep
|
||||
}
|
||||
|
||||
# hired or rented for the trip
|
||||
export function vehicle_own(v: Vehicle) -> void { if v != null { v.owned = true } }
|
||||
|
||||
# hay for a horse, up to a full belly
|
||||
export function vehicle_feed(v: Vehicle, amount: float) -> void {
|
||||
export function vehicle_feed(base_st: mut BaseState, vehicles_st: mut VehiclesState, v: Vehicle, amount: float) -> void {
|
||||
if v == null { return }
|
||||
v.food = Math.min(v.food + amount, 100.0)
|
||||
ve_say(VEHICLE_FED, v, amount)
|
||||
ve_say(base_st, vehicles_st, VEHICLE_FED, v, amount)
|
||||
}
|
||||
|
||||
# a horse nobody rides goes where its animal goes, round the home it is tied at (home_x, home_z)
|
||||
|
|
@ -83,22 +83,19 @@ export function vehicle_follow(v: Vehicle, x: float, y: float, z: float, yaw: fl
|
|||
}
|
||||
|
||||
# a saved trip's word on this player's own: hired, and how fed
|
||||
export function vehicle_restore(kind: int, owned: bool, food: float) -> void {
|
||||
export function vehicle_restore(vehicles_st: mut VehiclesState, kind: int, owned: bool, food: float) -> void {
|
||||
if kind == VEHICLE_HORSE {
|
||||
ve_kept_horse = owned
|
||||
ve_kept_food = food
|
||||
} else { ve_kept_boat = owned }
|
||||
let v = vehicle_find(kind)
|
||||
if v != null { ve_apply_kept(v) }
|
||||
vehicles_st.ve_kept_horse = owned
|
||||
vehicles_st.ve_kept_food = food
|
||||
} else { vehicles_st.ve_kept_boat = owned }
|
||||
let v = vehicle_find(vehicles_st, kind)
|
||||
if v != null { ve_apply_kept(vehicles_st, v) }
|
||||
}
|
||||
|
||||
var ve_kept_horse: bool = false
|
||||
var ve_kept_boat: bool = false
|
||||
var ve_kept_food: float = 40.0
|
||||
|
||||
function ve_apply_kept(v: Vehicle) -> void {
|
||||
function ve_apply_kept(vehicles_st: VehiclesState, v: Vehicle) -> void {
|
||||
if v.kind == VEHICLE_HORSE {
|
||||
v.owned = ve_kept_horse
|
||||
v.food = ve_kept_food
|
||||
} else { v.owned = ve_kept_boat }
|
||||
v.owned = vehicles_st.ve_kept_horse
|
||||
v.food = vehicles_st.ve_kept_food
|
||||
} else { v.owned = vehicles_st.ve_kept_boat }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,27 +4,27 @@
|
|||
export const VEHICLE_HAY_MIN: float = 10.0 # a horse with less hay than this will not go
|
||||
|
||||
# this machine's player onto v; false when it is somebody else's, taken, or a hungry horse
|
||||
export function vehicle_mount(v: Vehicle) -> bool {
|
||||
if v == null or v.owner != 0 or v.rider >= 0 or ve_cur != null { return false }
|
||||
export function vehicle_mount(base_st: mut BaseState, vehicles_st: mut VehiclesState, v: Vehicle) -> bool {
|
||||
if v == null or v.owner != 0 or v.rider >= 0 or vehicles_st.ve_cur != null { return false }
|
||||
if v.kind == VEHICLE_HORSE and v.food < VEHICLE_HAY_MIN {
|
||||
ve_say(VEHICLE_HUNGRY, v, v.food)
|
||||
ve_say(base_st, vehicles_st, VEHICLE_HUNGRY, v, v.food)
|
||||
return false
|
||||
}
|
||||
ve_cur = v
|
||||
vehicles_st.ve_cur = v
|
||||
v.rider = 0
|
||||
VehicleRider.board(v.x, v.z, v.yaw)
|
||||
ve_say(VEHICLE_MOUNTED, v, 0.0)
|
||||
ve_say(base_st, vehicles_st, VEHICLE_MOUNTED, v, 0.0)
|
||||
return true
|
||||
}
|
||||
|
||||
# Off, onto the nearest spot a body could stand and walk off: from a boat a wade of up to 1.25 m
|
||||
# within ten metres, from a horse beside its right flank. False (and said) when a boat is too far out.
|
||||
export function vehicle_dismount() -> bool {
|
||||
let v = ve_cur
|
||||
export function vehicle_dismount(base_st: mut BaseState, vehicles_st: mut VehiclesState) -> bool {
|
||||
let v = vehicles_st.ve_cur
|
||||
if v == null { return false }
|
||||
if v.kind == VEHICLE_BOAT {
|
||||
if not VehicleRider.safe_spot(v.x, v.z, VehicleWorld.water(v.x, v.z), 1.25) {
|
||||
ve_say(VEHICLE_NO_LANDING, v, 0.0)
|
||||
ve_say(base_st, vehicles_st, VEHICLE_NO_LANDING, v, 0.0)
|
||||
return false
|
||||
}
|
||||
VehicleRider.step_off(VehicleRider.safe_x(), VehicleRider.safe_z())
|
||||
|
|
@ -37,18 +37,18 @@ export function vehicle_dismount() -> bool {
|
|||
v.home_x = v.x
|
||||
v.home_z = v.z
|
||||
}
|
||||
ve_cur = null
|
||||
vehicles_st.ve_cur = null
|
||||
v.rider = -1
|
||||
v.speed = 0.0
|
||||
ve_say(VEHICLE_DISMOUNTED, v, 0.0)
|
||||
ve_say(base_st, vehicles_st, VEHICLE_DISMOUNTED, v, 0.0)
|
||||
return true
|
||||
}
|
||||
|
||||
# off whatever this player is on, wherever it is (a load, a collapse, a map change)
|
||||
export function vehicle_drop() -> void {
|
||||
if ve_cur != null {
|
||||
ve_cur.rider = -1
|
||||
ve_cur.speed = 0.0
|
||||
export function vehicle_drop(vehicles_st: mut VehiclesState) -> void {
|
||||
if vehicles_st.ve_cur != null {
|
||||
vehicles_st.ve_cur.rider = -1
|
||||
vehicles_st.ve_cur.speed = 0.0
|
||||
}
|
||||
ve_cur = null
|
||||
vehicles_st.ve_cur = null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,51 @@
|
|||
# places.ludic - four berths off the pier head and four bays at the trough. Nobody's boat waits in
|
||||
# one: a player calls theirs into a place that is empty. A place is taken while a boat lies in it or
|
||||
# a horse is tied at it, and frees itself the moment it is rowed or ridden away.
|
||||
export function vehicles_dock_at(x: float, z: float, yaw: float) -> void {
|
||||
ve_dock_x = x
|
||||
ve_dock_z = z
|
||||
ve_dock_yaw = yaw
|
||||
ve_have_dock = true
|
||||
export function vehicles_dock_at(vehicles_st: mut VehiclesState, x: float, z: float, yaw: float) -> void {
|
||||
vehicles_st.ve_dock_x = x
|
||||
vehicles_st.ve_dock_z = z
|
||||
vehicles_st.ve_dock_yaw = yaw
|
||||
vehicles_st.ve_have_dock = true
|
||||
}
|
||||
|
||||
export function vehicles_rail_at(x: float, z: float, yaw: float) -> void {
|
||||
ve_rail_x = x
|
||||
ve_rail_z = z
|
||||
ve_rail_yaw = yaw
|
||||
export function vehicles_rail_at(vehicles_st: mut VehiclesState, x: float, z: float, yaw: float) -> void {
|
||||
vehicles_st.ve_rail_x = x
|
||||
vehicles_st.ve_rail_z = z
|
||||
vehicles_st.ve_rail_yaw = yaw
|
||||
}
|
||||
|
||||
# which way the pier head faces, for the posts a game stands on it
|
||||
export function vehicles_dock_yaw() -> float { return ve_dock_yaw }
|
||||
export function vehicles_dock_yaw(vehicles_st: VehiclesState) -> float { return vehicles_st.ve_dock_yaw }
|
||||
|
||||
function ve_across(k: int) -> float { return -3.3 + float(k) * 2.2 }
|
||||
|
||||
# a berth: 90 cm off the pier head's outer edge, bow out; its post on the deck above it
|
||||
export function vehicle_berth_x(k: int) -> float { return ve_dock_x - Math.sin(ve_dock_yaw) * 7.25 + Math.cos(ve_dock_yaw) * ve_across(k) }
|
||||
export function vehicle_berth_z(k: int) -> float { return ve_dock_z - Math.cos(ve_dock_yaw) * 7.25 - Math.sin(ve_dock_yaw) * ve_across(k) }
|
||||
export function vehicle_post_x(k: int) -> float { return ve_dock_x - Math.sin(ve_dock_yaw) * 6.15 + Math.cos(ve_dock_yaw) * ve_across(k) }
|
||||
export function vehicle_post_z(k: int) -> float { return ve_dock_z - Math.cos(ve_dock_yaw) * 6.15 - Math.sin(ve_dock_yaw) * ve_across(k) }
|
||||
export function vehicle_berth_x(vehicles_st: VehiclesState, k: int) -> float { return vehicles_st.ve_dock_x - Math.sin(vehicles_st.ve_dock_yaw) * 7.25 + Math.cos(vehicles_st.ve_dock_yaw) * ve_across(k) }
|
||||
export function vehicle_berth_z(vehicles_st: VehiclesState, k: int) -> float { return vehicles_st.ve_dock_z - Math.cos(vehicles_st.ve_dock_yaw) * 7.25 - Math.sin(vehicles_st.ve_dock_yaw) * ve_across(k) }
|
||||
export function vehicle_post_x(vehicles_st: VehiclesState, k: int) -> float { return vehicles_st.ve_dock_x - Math.sin(vehicles_st.ve_dock_yaw) * 6.15 + Math.cos(vehicles_st.ve_dock_yaw) * ve_across(k) }
|
||||
export function vehicle_post_z(vehicles_st: VehiclesState, k: int) -> float { return vehicles_st.ve_dock_z - Math.cos(vehicles_st.ve_dock_yaw) * 6.15 - Math.sin(vehicles_st.ve_dock_yaw) * ve_across(k) }
|
||||
|
||||
# a bay: off the trough's long side, a trough's length apart - four horses at a feeding trough
|
||||
# stand shoulder to shoulder along it
|
||||
function ve_bay_across(k: int) -> float { return -1.44 + float(k) * 0.96 }
|
||||
export function vehicle_bay_x(k: int) -> float { return ve_rail_x - Math.sin(ve_rail_yaw) * 1.4 + Math.cos(ve_rail_yaw) * ve_bay_across(k) }
|
||||
export function vehicle_bay_z(k: int) -> float { return ve_rail_z - Math.cos(ve_rail_yaw) * 1.4 - Math.sin(ve_rail_yaw) * ve_bay_across(k) }
|
||||
export function vehicle_bay_x(vehicles_st: VehiclesState, k: int) -> float { return vehicles_st.ve_rail_x - Math.sin(vehicles_st.ve_rail_yaw) * 1.4 + Math.cos(vehicles_st.ve_rail_yaw) * ve_bay_across(k) }
|
||||
export function vehicle_bay_z(vehicles_st: VehiclesState, k: int) -> float { return vehicles_st.ve_rail_z - Math.cos(vehicles_st.ve_rail_yaw) * 1.4 - Math.sin(vehicles_st.ve_rail_yaw) * ve_bay_across(k) }
|
||||
|
||||
export function vehicle_place_x(kind: int, k: int) -> float {
|
||||
if kind == VEHICLE_HORSE { return vehicle_bay_x(k) }
|
||||
return vehicle_berth_x(k)
|
||||
export function vehicle_place_x(vehicles_st: VehiclesState, kind: int, k: int) -> float {
|
||||
if kind == VEHICLE_HORSE { return vehicle_bay_x(vehicles_st, k) }
|
||||
return vehicle_berth_x(vehicles_st, k)
|
||||
}
|
||||
|
||||
export function vehicle_place_z(kind: int, k: int) -> float {
|
||||
if kind == VEHICLE_HORSE { return vehicle_bay_z(k) }
|
||||
return vehicle_berth_z(k)
|
||||
export function vehicle_place_z(vehicles_st: VehiclesState, kind: int, k: int) -> float {
|
||||
if kind == VEHICLE_HORSE { return vehicle_bay_z(vehicles_st, k) }
|
||||
return vehicle_berth_z(vehicles_st, k)
|
||||
}
|
||||
|
||||
# who is in place k: the boat lying in the berth or the horse tied in the bay, or null
|
||||
export function vehicle_in_place(kind: int, k: int) -> Vehicle {
|
||||
let px = vehicle_place_x(kind, k)
|
||||
let pz = vehicle_place_z(kind, k)
|
||||
let l = ve_all()
|
||||
export function vehicle_in_place(vehicles_st: mut VehiclesState, kind: int, k: int) -> Vehicle {
|
||||
let px = vehicle_place_x(vehicles_st, kind, k)
|
||||
let pz = vehicle_place_z(vehicles_st, kind, k)
|
||||
let l = ve_all(vehicles_st)
|
||||
for i in 0 .. len(l) {
|
||||
let v = l[i]
|
||||
if v.kind != kind or v.rider >= 0 { continue }
|
||||
|
|
@ -64,17 +64,17 @@ export function vehicle_in_place(kind: int, k: int) -> Vehicle {
|
|||
}
|
||||
|
||||
# the first free place, or -1
|
||||
export function vehicle_free_place(kind: int) -> int {
|
||||
for k in 0 .. VEHICLE_PLACES { if vehicle_in_place(kind, k) == null { return k } }
|
||||
export function vehicle_free_place(vehicles_st: mut VehiclesState, kind: int) -> int {
|
||||
for k in 0 .. VEHICLE_PLACES { if vehicle_in_place(vehicles_st, kind, k) == null { return k } }
|
||||
return -1
|
||||
}
|
||||
|
||||
# this player's own is lying in one of the places
|
||||
export function vehicle_mine_in_place(kind: int) -> bool {
|
||||
let mine = vehicle_find(kind)
|
||||
export function vehicle_mine_in_place(vehicles_st: mut VehiclesState, kind: int) -> bool {
|
||||
let mine = vehicle_find(vehicles_st, kind)
|
||||
if mine == null { return false }
|
||||
for k in 0 .. VEHICLE_PLACES {
|
||||
let h = vehicle_in_place(kind, k)
|
||||
let h = vehicle_in_place(vehicles_st, kind, k)
|
||||
if h != null and h.nid == mine.nid { return true }
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -23,25 +23,41 @@ export port VehicleRider {
|
|||
safe_z: fn() -> float = fn ve__safe_z
|
||||
}
|
||||
|
||||
var ve_ids: int = 0
|
||||
var ve_sx: float = 0.0
|
||||
var ve_sz: float = 0.0
|
||||
export state VehiclesState {
|
||||
ve_kept_horse: bool = false
|
||||
ve_kept_boat: bool = false
|
||||
ve_kept_food: float = 40.0
|
||||
ve_ids: int = 0
|
||||
ve_sx: float = 0.0
|
||||
ve_sz: float = 0.0
|
||||
ve_list: []Vehicle = null
|
||||
ve_cur: Vehicle = null
|
||||
ve_dock_x: float = 0.0
|
||||
ve_dock_z: float = 0.0
|
||||
ve_dock_yaw: float = 0.0
|
||||
ve_rail_x: float = 0.0
|
||||
ve_rail_z: float = 0.0
|
||||
ve_rail_yaw: float = 0.0
|
||||
ve_have_dock: bool = false
|
||||
ve_swell_said: float = 0.0
|
||||
ve_fact_q: Queue<VehicleFact> = null
|
||||
}
|
||||
function ve__dry(x: float, z: float) -> float { return -10000.0 }
|
||||
function ve__open(x: float, z: float, r: float) -> bool { return false }
|
||||
function ve__calm(x: float, z: float, fx: float, fz: float) -> float { return 0.0 }
|
||||
function ve__zero() -> float { return 0.0 }
|
||||
function ve__next() -> int {
|
||||
ve_ids += 1
|
||||
return ve_ids
|
||||
function ve__next(vehicles_st: mut VehiclesState) -> int {
|
||||
vehicles_st.ve_ids += 1
|
||||
return vehicles_st.ve_ids
|
||||
}
|
||||
function ve__nothing(v: Vehicle) -> void { }
|
||||
function ve__board(x: float, z: float, yaw: float) -> void { }
|
||||
function ve__ride(x: float, y: float, z: float, yaw: float, speed: float) -> void { }
|
||||
function ve__off(x: float, z: float) -> void { }
|
||||
function ve__safe(x: float, z: float, from_y: float, max_depth: float) -> bool {
|
||||
ve_sx = x
|
||||
ve_sz = z
|
||||
function ve__safe(vehicles_st: mut VehiclesState, x: float, z: float, from_y: float, max_depth: float) -> bool {
|
||||
vehicles_st.ve_sx = x
|
||||
vehicles_st.ve_sz = z
|
||||
return true
|
||||
}
|
||||
function ve__safe_x() -> float { return ve_sx }
|
||||
function ve__safe_z() -> float { return ve_sz }
|
||||
function ve__safe_x(vehicles_st: VehiclesState) -> float { return vehicles_st.ve_sx }
|
||||
function ve__safe_z(vehicles_st: VehiclesState) -> float { return vehicles_st.ve_sz }
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ const VE_BOAT_TOP: float = 3.2
|
|||
const VE_BOAT_ACC: float = 1.2
|
||||
const VE_BOAT_TURN: float = 1.1
|
||||
|
||||
export function vehicle_update(ix: float, iz: float, run: bool, dt: float) -> void {
|
||||
let v = ve_cur
|
||||
export function vehicle_update(base_st: mut BaseState, vehicles_st: mut VehiclesState, ix: float, iz: float, run: bool, dt: float) -> void {
|
||||
let v = vehicles_st.ve_cur
|
||||
if v == null { return }
|
||||
var top = VE_BOAT_TOP
|
||||
var acc = VE_BOAT_ACC
|
||||
|
|
@ -21,7 +21,7 @@ export function vehicle_update(ix: float, iz: float, run: bool, dt: float) -> vo
|
|||
if run and v.fuel > 5.0 { top = VE_HORSE_GALLOP }
|
||||
}
|
||||
v.speed = v.speed + Math.clamp(iz * top - v.speed, -acc * dt, acc * dt)
|
||||
if v.kind == VEHICLE_BOAT { ve_swell(v, dt) }
|
||||
if v.kind == VEHICLE_BOAT { ve_swell(base_st, vehicles_st, v, dt) }
|
||||
# Steering follows SIGNED speed: backing up with the stick left swings the nose right
|
||||
if Math.abs(v.speed) > 0.3 {
|
||||
var rate = Math.clamp(Math.abs(v.speed) / 3.0, 0.4, 1.0)
|
||||
|
|
@ -29,14 +29,14 @@ export function vehicle_update(ix: float, iz: float, run: bool, dt: float) -> vo
|
|||
v.yaw = v.yaw - ix * turn * (dt * rate)
|
||||
}
|
||||
let d = v.speed * dt
|
||||
ve_travel(v, v.x - Math.sin(v.yaw) * d, v.z - Math.cos(v.yaw) * d, d)
|
||||
ve_travel(base_st, vehicles_st, v, v.x - Math.sin(v.yaw) * d, v.z - Math.cos(v.yaw) * d, d)
|
||||
if v.kind == VEHICLE_HORSE { ve_stamina(v, d, dt) } else { ve_float(v, d, dt) }
|
||||
VehicleWorld.placed(v)
|
||||
VehicleRider.ride_at(v.x, v.y + v.seat_h, v.z, v.yaw, Math.abs(v.speed))
|
||||
}
|
||||
|
||||
# a boat only where there is water under it; a horse only on dry ground, up a walkable rise, clear
|
||||
function ve_travel(v: Vehicle, nx: float, nz: float, d: float) -> void {
|
||||
function ve_travel(base_st: mut BaseState, vehicles_st: mut VehiclesState, v: Vehicle, nx: float, nz: float, d: float) -> void {
|
||||
let nh = VehicleWorld.ground(nx, nz)
|
||||
var ok = true
|
||||
if v.kind == VEHICLE_BOAT { ok = nh < VehicleWorld.water(nx, nz) - 0.35 } else {
|
||||
|
|
@ -51,12 +51,12 @@ function ve_travel(v: Vehicle, nx: float, nz: float, d: float) -> void {
|
|||
v.x = nx
|
||||
v.z = nz
|
||||
if v.kind != VEHICLE_BOAT { v.y = nh }
|
||||
if Math.abs(d) > 0.0 { ve_say(VEHICLE_MOVED, v, Math.abs(d)) }
|
||||
if Math.abs(d) > 0.0 { ve_say(base_st, vehicles_st, VEHICLE_MOVED, v, Math.abs(d)) }
|
||||
}
|
||||
|
||||
# a boat gets a longer leash than a swimmer and the same current at the end of it: the outward
|
||||
# part of the stroke only, so a boat at the limit can always be put about
|
||||
function ve_swell(v: Vehicle, dt: float) -> void {
|
||||
function ve_swell(base_st: mut BaseState, vehicles_st: mut VehiclesState, v: Vehicle, dt: float) -> void {
|
||||
var fx = -Math.sin(v.yaw)
|
||||
var fz = -Math.cos(v.yaw)
|
||||
if v.speed < 0.0 {
|
||||
|
|
@ -65,11 +65,11 @@ function ve_swell(v: Vehicle, dt: float) -> void {
|
|||
}
|
||||
let take = Math.clamp(VehicleWorld.swell(v.x, v.z, fx, fz), 0.0, 1.0)
|
||||
v.speed = v.speed * (1.0 - take)
|
||||
if take > 0.55 and ve_swell_said < 0.0 {
|
||||
ve_swell_said = 14.0
|
||||
ve_say(VEHICLE_SWELL, v, take)
|
||||
if take > 0.55 and vehicles_st.ve_swell_said < 0.0 {
|
||||
vehicles_st.ve_swell_said = 14.0
|
||||
ve_say(base_st, vehicles_st, VEHICLE_SWELL, v, take)
|
||||
}
|
||||
ve_swell_said = ve_swell_said - dt
|
||||
vehicles_st.ve_swell_said = vehicles_st.ve_swell_said - dt
|
||||
}
|
||||
|
||||
# a gallop spends stamina and a walk gives it back; every metre costs hay
|
||||
|
|
@ -93,8 +93,8 @@ function ve_float(v: Vehicle, d: float, dt: float) -> void {
|
|||
}
|
||||
|
||||
# the boats nobody is in ride the swell where they lie
|
||||
export function vehicles_tick(dt: float) -> void {
|
||||
let l = ve_all()
|
||||
export function vehicles_tick(vehicles_st: mut VehiclesState, dt: float) -> void {
|
||||
let l = ve_all(vehicles_st)
|
||||
for i in 0 .. len(l) {
|
||||
let v = l[i]
|
||||
if v.kind == VEHICLE_BOAT and v.rider < 0 {
|
||||
|
|
|
|||
|
|
@ -1,24 +1,13 @@
|
|||
# state.ludic - every vehicle, the one this machine's player is on, where the places are measured
|
||||
# from, and the facts
|
||||
var ve_list: []Vehicle = null
|
||||
var ve_cur: Vehicle = null
|
||||
var ve_dock_x: float = 0.0
|
||||
var ve_dock_z: float = 0.0
|
||||
var ve_dock_yaw: float = 0.0
|
||||
var ve_rail_x: float = 0.0
|
||||
var ve_rail_z: float = 0.0
|
||||
var ve_rail_yaw: float = 0.0
|
||||
var ve_have_dock: bool = false
|
||||
var ve_swell_said: float = 0.0
|
||||
var ve_fact_q: Queue<VehicleFact> = null
|
||||
const ve_pi: float = 3.14159265
|
||||
|
||||
export function vehicle_facts() -> Queue<VehicleFact> {
|
||||
if ve_fact_q == null { ve_fact_q = queue_new("vehicles.facts") }
|
||||
return ve_fact_q
|
||||
export function vehicle_facts(base_st: mut BaseState, vehicles_st: mut VehiclesState) -> Queue<VehicleFact> {
|
||||
if vehicles_st.ve_fact_q == null { vehicles_st.ve_fact_q = queue_new(base_st, "vehicles.facts") }
|
||||
return vehicles_st.ve_fact_q
|
||||
}
|
||||
|
||||
function ve_say(what: int, v: Vehicle, n: float) -> void {
|
||||
function ve_say(base_st: mut BaseState, vehicles_st: mut VehiclesState, what: int, v: Vehicle, n: float) -> void {
|
||||
let f = new VehicleFact
|
||||
f.what = what
|
||||
f.nid = v.nid
|
||||
|
|
@ -27,40 +16,40 @@ function ve_say(what: int, v: Vehicle, n: float) -> void {
|
|||
f.x = v.x
|
||||
f.z = v.z
|
||||
f.v = n
|
||||
q_push(vehicle_facts(), f)
|
||||
q_push(base_st, vehicle_facts(base_st, vehicles_st), f)
|
||||
}
|
||||
|
||||
function ve_all() -> []Vehicle {
|
||||
if ve_list == null { ve_list = new []Vehicle }
|
||||
return ve_list
|
||||
function ve_all(vehicles_st: mut VehiclesState) -> []Vehicle {
|
||||
if vehicles_st.ve_list == null { vehicles_st.ve_list = new []Vehicle }
|
||||
return vehicles_st.ve_list
|
||||
}
|
||||
|
||||
# every vehicle in the valley, to draw and to aim at (change one only through the verbs)
|
||||
export function vehicles_all() -> []Vehicle { return ve_all() }
|
||||
export function vehicles_all(vehicles_st: mut VehiclesState) -> []Vehicle { return ve_all(vehicles_st) }
|
||||
|
||||
# the kind this machine's player is riding, 0 none
|
||||
export function vehicle_ride_kind() -> int {
|
||||
if ve_cur == null { return 0 }
|
||||
return ve_cur.kind
|
||||
export function vehicle_ride_kind(vehicles_st: VehiclesState) -> int {
|
||||
if vehicles_st.ve_cur == null { return 0 }
|
||||
return vehicles_st.ve_cur.kind
|
||||
}
|
||||
|
||||
export function vehicle_current() -> Vehicle { return ve_cur }
|
||||
export function vehicle_current(vehicles_st: VehiclesState) -> Vehicle { return vehicles_st.ve_cur }
|
||||
|
||||
export function vehicle_of(pid: int, kind: int) -> Vehicle {
|
||||
let l = ve_all()
|
||||
export function vehicle_of(vehicles_st: mut VehiclesState, pid: int, kind: int) -> Vehicle {
|
||||
let l = ve_all(vehicles_st)
|
||||
for i in 0 .. len(l) { if l[i].kind == kind and l[i].owner == pid { return l[i] } }
|
||||
return null
|
||||
}
|
||||
|
||||
# this player's own boat or horse
|
||||
export function vehicle_find(kind: int) -> Vehicle { return vehicle_of(0, kind) }
|
||||
export function vehicle_find(vehicles_st: mut VehiclesState, kind: int) -> Vehicle { return vehicle_of(vehicles_st, 0, kind) }
|
||||
|
||||
# the nearest vehicle nobody is on within `reach` of (x, z); nothing while riding
|
||||
export function vehicle_nearest(x: float, z: float, reach: float) -> Vehicle {
|
||||
if ve_cur != null { return null }
|
||||
export function vehicle_nearest(vehicles_st: mut VehiclesState, x: float, z: float, reach: float) -> Vehicle {
|
||||
if vehicles_st.ve_cur != null { return null }
|
||||
var best: Vehicle = null
|
||||
var bd = reach
|
||||
let l = ve_all()
|
||||
let l = ve_all(vehicles_st)
|
||||
for i in 0 .. len(l) {
|
||||
let v = l[i]
|
||||
if v.rider >= 0 { continue }
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
# system.ludic - vehicles as a system: a reset, and this player's own saved by kind (hired or not,
|
||||
# and the horse's hay); where they lie is not saved - they are called again. The idle boats' bob is
|
||||
# vehicles_tick, which the game calls where the world is run
|
||||
export function vehicles_reset() -> void {
|
||||
ve_list = new []Vehicle
|
||||
ve_cur = null
|
||||
ve_have_dock = false
|
||||
ve_swell_said = 0.0
|
||||
ve_kept_horse = false
|
||||
ve_kept_boat = false
|
||||
ve_kept_food = 40.0
|
||||
q_clear(vehicle_facts())
|
||||
export function vehicles_reset(base_st: mut BaseState, vehicles_st: mut VehiclesState) -> void {
|
||||
vehicles_st.ve_list = new []Vehicle
|
||||
vehicles_st.ve_cur = null
|
||||
vehicles_st.ve_have_dock = false
|
||||
vehicles_st.ve_swell_said = 0.0
|
||||
vehicles_st.ve_kept_horse = false
|
||||
vehicles_st.ve_kept_boat = false
|
||||
vehicles_st.ve_kept_food = 40.0
|
||||
q_clear(base_st, vehicle_facts(base_st, vehicles_st))
|
||||
}
|
||||
|
||||
export function vehicles_save() -> Val {
|
||||
export function vehicles_save(vehicles_st: mut VehiclesState) -> Val {
|
||||
let v = Value.object()
|
||||
let h = vehicle_find(VEHICLE_HORSE)
|
||||
let b = vehicle_find(VEHICLE_BOAT)
|
||||
let h = vehicle_find(vehicles_st, VEHICLE_HORSE)
|
||||
let b = vehicle_find(vehicles_st, VEHICLE_BOAT)
|
||||
if h != null {
|
||||
sv_put_bool(v, "horse_own", h.owned)
|
||||
sv_put_float(v, "horse_food", h.food)
|
||||
|
|
@ -24,10 +24,10 @@ export function vehicles_save() -> Val {
|
|||
return v
|
||||
}
|
||||
|
||||
export function vehicles_load(v: Val, version: int) -> void {
|
||||
vehicle_drop()
|
||||
vehicle_restore(VEHICLE_HORSE, sv_bool(v, "horse_own", false), sv_float(v, "horse_food", 40.0))
|
||||
vehicle_restore(VEHICLE_BOAT, sv_bool(v, "boat_own", false), 0.0)
|
||||
export function vehicles_load(vehicles_st: mut VehiclesState, v: Val, version: int) -> void {
|
||||
vehicle_drop(vehicles_st)
|
||||
vehicle_restore(vehicles_st, VEHICLE_HORSE, sv_bool(v, "horse_own", false), sv_float(v, "horse_food", 40.0))
|
||||
vehicle_restore(vehicles_st, VEHICLE_BOAT, sv_bool(v, "boat_own", false), 0.0)
|
||||
}
|
||||
|
||||
export function vehicles_system() -> System {
|
||||
|
|
|
|||
|
|
@ -16,222 +16,224 @@ 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 }
|
||||
var swell: float = 0.0
|
||||
function fk_swell(x: float, z: float, fx: float, fz: float) -> float {
|
||||
if fx > 0.0 { return swell }
|
||||
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 }
|
||||
return 0.0
|
||||
}
|
||||
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 }
|
||||
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 }
|
||||
|
||||
# the rider: where it was put, and a safe spot that walks back toward the shore
|
||||
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_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
|
||||
}
|
||||
function fk_off(x: float, z: float) -> void {
|
||||
rx = x
|
||||
rz = z
|
||||
ry = fk_ground(x, 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_safe(x: float, z: float, from_y: float, max_depth: float) -> bool {
|
||||
function fk_safe(vehiclestest_st: mut VehiclestestState, 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) {
|
||||
sx = px
|
||||
sz = z
|
||||
vehiclestest_st.sx = px
|
||||
vehiclestest_st.sz = z
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
function fk_sx() -> float { return sx }
|
||||
function fk_sz() -> float { return sz }
|
||||
function fk_sx(vehiclestest_st: VehiclestestState) -> float { return vehiclestest_st.sx }
|
||||
function fk_sz(vehiclestest_st: VehiclestestState) -> float { return vehiclestest_st.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() -> 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 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 facts() -> []VehicleFact { return q_drain(vehicle_facts()) }
|
||||
function facts(base_st: mut BaseState, vehicles_st: mut VehiclesState) -> []VehicleFact { return q_drain(base_st, vehicle_facts(base_st, vehicles_st)) }
|
||||
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(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) }
|
||||
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) }
|
||||
}
|
||||
|
||||
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 "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 "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)
|
||||
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)
|
||||
expect(b != null)
|
||||
expect_near(b.y, 0.02, 0.001)
|
||||
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))
|
||||
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))
|
||||
}
|
||||
|
||||
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 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 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)
|
||||
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)
|
||||
h.food = 5.0
|
||||
expect(not vehicle_mount(h))
|
||||
expect_eq(count(facts(), VEHICLE_HUNGRY), 1)
|
||||
vehicle_feed(h, 50.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_near(h.food, 55.0, 0.001)
|
||||
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(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_eq(h.rider, 0)
|
||||
expect(vehicle_nearest(h.x, h.z, 5.0) == null)
|
||||
expect(vehicle_in_place(VEHICLE_HORSE, 0) == null)
|
||||
expect(vehicle_nearest(vehicles_st, h.x, h.z, 5.0) == null)
|
||||
expect(vehicle_in_place(vehicles_st, VEHICLE_HORSE, 0) == null)
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
expect_near(h.speed, 4.5, 0.05)
|
||||
expect(count(facts(), VEHICLE_MOVED) > 100)
|
||||
ride(0.0, 1.0, true, 3.0)
|
||||
expect(count(facts(base_st, vehicles_st), VEHICLE_MOVED) > 100)
|
||||
ride(base_st, vehicles_st, 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(rz, h.z, 0.001)
|
||||
expect_near(ry, 1.35, 0.001)
|
||||
expect_near(vehiclestest_st.rz, h.z, 0.001)
|
||||
expect_near(vehiclestest_st.ry, 1.35, 0.001)
|
||||
# the trunk at z = -60 stops it
|
||||
ride(0.0, 1.0, true, 6.0)
|
||||
ride(base_st, vehicles_st, 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()
|
||||
vehicle_drop(vehicles_st)
|
||||
h.x = 7.0
|
||||
h.z = 0.0
|
||||
h.yaw = EAST
|
||||
vehicle_mount(h)
|
||||
ride(0.0, 1.0, false, 4.0)
|
||||
vehicle_mount(base_st, vehicles_st, h)
|
||||
ride(base_st, vehicles_st, 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" {
|
||||
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)
|
||||
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)
|
||||
let x2 = b.x
|
||||
expect(x2 > 18.0)
|
||||
swell = 1.0
|
||||
ride(0.0, 1.0, false, 1.0)
|
||||
vehiclestest_st.swell = 1.0
|
||||
ride(base_st, vehicles_st, 0.0, 1.0, false, 1.0)
|
||||
expect_near(b.x, x2, 0.2)
|
||||
expect_eq(count(facts(), VEHICLE_SWELL), 1)
|
||||
swell = 0.0
|
||||
ride(0.0, -1.0, false, 12.0)
|
||||
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(b.x > 10.3)
|
||||
wind = 1.0
|
||||
vehiclestest_st.wind = 1.0
|
||||
let z0 = b.z
|
||||
ride(0.0, 0.0, false, 1.0)
|
||||
ride(base_st, vehicles_st, 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" {
|
||||
fresh()
|
||||
vehicle_call_for(0, VEHICLE_BOAT, 0)
|
||||
let b = vehicle_find(VEHICLE_BOAT)
|
||||
vehicle_mount(b)
|
||||
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)
|
||||
b.x = 40.0
|
||||
expect(not vehicle_dismount())
|
||||
expect_eq(count(facts(), VEHICLE_NO_LANDING), 1)
|
||||
expect_eq(vehicle_ride_kind(), VEHICLE_BOAT)
|
||||
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)
|
||||
b.x = 12.0
|
||||
expect(vehicle_dismount())
|
||||
expect_near(rx, 11.0, 0.001)
|
||||
expect_eq(vehicle_ride_kind(), 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_eq(b.rider, -1)
|
||||
vehicle_call_for(0, VEHICLE_HORSE, 0)
|
||||
let h = vehicle_find(VEHICLE_HORSE)
|
||||
vehicle_mount(h)
|
||||
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
|
||||
let h = vehicle_find(vehicles_st, VEHICLE_HORSE)
|
||||
vehicle_mount(base_st, vehicles_st, h)
|
||||
h.x = -5.0
|
||||
h.z = -5.0
|
||||
expect(vehicle_dismount())
|
||||
expect(vehicle_dismount(base_st, vehicles_st))
|
||||
expect_near(h.home_x, -5.0, 0.001)
|
||||
expect(vehicle_in_place(VEHICLE_HORSE, 0) == null)
|
||||
expect_near(rx, -5.0 + 1.2, 0.001)
|
||||
expect(vehicle_in_place(vehicles_st, VEHICLE_HORSE, 0) == null)
|
||||
expect_near(vehiclestest_st.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" {
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue