69 lines
3.3 KiB
Lua
Executable File
69 lines
3.3 KiB
Lua
Executable File
local M = dofile(assert(arg[1], "model.lua path required"))
|
|
local total = 0
|
|
local function test(name, fn)
|
|
local ok, err = pcall(fn)
|
|
assert(ok, name .. ": " .. tostring(err)); total = total + 1
|
|
end
|
|
-- Explicit UTC fixtures; os.time(table) would depend on the machine timezone.
|
|
local june_noon, december_noon = 1782043200, 1797854400
|
|
test("reject malformed locations", function()
|
|
assert(not M.location("bad", 0)); assert(not M.location(91, 0))
|
|
assert(not M.location(0, 181)); assert(not M.location(0 / 0, 0))
|
|
assert(not M.location(math.huge, 0)); assert(M.location(0, 0))
|
|
end)
|
|
test("latitude changes solstice elevation", function()
|
|
local summer = M.solar(june_noon, 45, 0)
|
|
local winter = M.solar(december_noon, 45, 0)
|
|
assert(summer.elevation > winter.elevation + 40)
|
|
assert(summer.temperature > winter.temperature)
|
|
end)
|
|
test("opposite hemispheres reverse seasons", function()
|
|
assert(M.solar(june_noon, 45, 0).season == "Summer")
|
|
assert(M.solar(june_noon, -45, 0).season == "Winter")
|
|
end)
|
|
test("longitude changes solar time", function()
|
|
local a, b = M.solar(june_noon, 0, 0), M.solar(june_noon, 0, 90)
|
|
assert(math.abs((b.hour - a.hour) % 24 - 6) < 0.01)
|
|
end)
|
|
test("polar night and polar day stay finite", function()
|
|
assert(M.solar(june_noon, 90, 0).daylight)
|
|
assert(not M.solar(december_noon, 90, 0).daylight)
|
|
assert(M.solar(june_noon, -90, 0).timeofday >= 0)
|
|
end)
|
|
test("deterministic weather across restarts", function()
|
|
assert(M.weather(june_noon, 30, -70) == M.weather(june_noon, 30, -70))
|
|
end)
|
|
local initial = {food = 80, water = 80, warmth = 80, wet = 20, stamina = 70}
|
|
test("shelter dries while exposed rain wets", function()
|
|
local dry = M.needs(initial, {temperature = 5, shelter = 1, rain = true}, 1)
|
|
local wet = M.needs(initial, {temperature = 5, shelter = 0, rain = true}, 1)
|
|
assert(dry.wet < initial.wet and wet.wet > initial.wet)
|
|
assert(initial.wet == 20) -- no hidden mutation
|
|
end)
|
|
test("rain cloak slows wetting, adds warmth, and a rack accelerates sheltered drying", function()
|
|
local cold = {food = 80, water = 80, warmth = 68, wet = 20, stamina = 70}
|
|
local bare = M.needs(cold, {temperature = 5, shelter = 0, rain = true}, 1)
|
|
local coated = M.needs(cold, {temperature = 5, shelter = 0, rain = true, clothing = true}, 1)
|
|
assert(coated.wet < bare.wet and coated.warmth > bare.warmth)
|
|
local rack = M.needs(initial, {temperature = 5, shelter = 1, rain = true, drying = true}, 1)
|
|
assert(rack.wet < M.needs(initial, {temperature = 5, shelter = 1, rain = true}, 1).wet)
|
|
end)
|
|
test("rest recovers sprint reserve", function()
|
|
local rest = M.needs(initial, {temperature = 20}, 1)
|
|
local run = M.needs(initial, {temperature = 20, sprinting = true}, 1)
|
|
assert(rest.stamina > initial.stamina and run.stamina < initial.stamina)
|
|
end)
|
|
test("large pauses never replay offline starvation", function()
|
|
local state = M.needs(initial, {temperature = -20}, 100000)
|
|
assert(state.food > 79 and state.water > 79)
|
|
end)
|
|
test("negative elapsed does not reverse needs", function()
|
|
local state = M.needs(initial, {temperature = -20}, -1)
|
|
assert(state.food == initial.food)
|
|
end)
|
|
test("fuel expires and is bounded", function()
|
|
assert(M.fuel_remaining(100, 101) == 0)
|
|
assert(M.fuel_remaining(10000000, 0) == 600)
|
|
end)
|
|
print("PASS " .. total .. " model tests")
|