This commit is contained in:
2026-11-05 09:57:11 -05:00
parent d34388bf2c
commit 89e392cc2e
81 changed files with 12410 additions and 1135 deletions
+109
View File
@@ -0,0 +1,109 @@
-- Standalone Lua, no engine. Pass the fixed catalogue path as arg[1].
local target=assert(arg[1],"fauna.lua path required")
local root=target:gsub("[^/\\]+$","")
local L=dofile(root.."lifecycle.lua")
local F=dofile(target)({lifecycle=L},{})
local passed=0
local function test(name,fn)
local ok,err=pcall(fn); assert(ok,name..": "..tostring(err))
passed=passed+1; print("ok "..passed.." - "..name)
end
test("exact stable 23 ID catalogue and strict canonical lookup",function()
local expected="hare deer fox rabbit red_squirrel bank_vole wood_mouse hedgehog badger roe_deer stoat weasel otter robin blackbird blue_tit barn_owl mallard common_frog smooth_newt brown_trout bumblebee earthworm"
local ids={}; for _,r in ipairs(F.list()) do ids[#ids+1]=r.id; assert(F.kind(r.entity)==r.id) end
assert(table.concat(ids," ")==expected and #F.catalog()==23)
for _,v in ipairs({"../fox","fox.b3d","hearth:fox_extra","FOX",string.rep("a",2049)}) do assert(not F.get(v)) end
assert(not F.kind({name=42}) and not F.kind(false))
end)
test("species sources and lifecycle evidence are copied, not invented",function()
for _,r in ipairs(F.list()) do
assert(r.source_url:match("^https://en.wikipedia.org/wiki/"))
assert(r.profile.id==r.id and r.profile.kind=="animal")
if r.id~="deer" then assert(r.latin and #F.source(r.id)>=2) end
end
assert(F.get("deer").latin==false and F.get("deer").profile.confidence=="unverified_identity")
local r=F.get("fox"); r.prey.deer=true; r.bounds.max[2]=999; r.profile.maturity_days={min=1,max=1}
assert(not F.get("fox").prey.deer and F.get("fox").bounds.max[2]<1)
local sourced=F.get("fox").profile.maturity_days
assert(sourced and sourced.min==304 and sourced.max==304,"fox maturity remains the sourced real-day profile")
end)
test("exact authored asset convention, five clips, 24fps and measured bounds",function()
for _,r in ipairs(F.list()) do
assert(r.mesh=="hearth_fauna_"..r.id..".b3d" and r.texture=="hearth_fauna_"..r.id..".png")
assert(r.frames==100 and r.fps==24 and r.eye_height>=.15)
for i,name in ipairs({"idle","locomotion","feed","flight_swim","rest"}) do
assert(r.clips[name][1]==(i-1)*20 and r.clips[name][2]==i*20-1)
end
assert(r.bounds.min[2]==0 and r.bounds.max[2]>0 and r.bounds.min[3]<0)
end
assert(F.get("deer").bounds.max[2]==1.5947 and F.get("fox").bounds.min[3]==-.8624)
assert(F.get("earthworm").speed==20/3600)
end)
test("per-species solar rest schedules and sourced winter dormancy are explicit",function()
for _,r in ipairs(F.list()) do
assert(type(r.sleep)=="table" and type(r.sleep.kind)=="string",r.id)
assert(({day=true,night=true,crepuscular=true,any=true})[r.activity],r.id)
end
assert(F.get("robin").sleep.sleep_below==-6 and F.get("barn_owl").sleep.sleep_above==6)
assert(F.get("deer").sleep.active_between[1]==-8 and F.get("bank_vole").sleep.rest_hours[1]==12)
assert(F.get("hedgehog").winter_dormant and F.get("common_frog").winter_dormant
and F.get("smooth_newt").winter_dormant)
assert(not F.get("hare").winter_dormant)
end)
test("calendar ages are real days, never 60-second maturity or 900-second death",function()
local p=assert(F.phase("bank_vole",100,100+60)); assert(p.phase=="dependent")
p=assert(F.phase("bank_vole",100,100+56*86400)); assert(p.phase=="mature" and p.age_days==56)
p=assert(F.phase("bank_vole",100,100+1000*86400)); assert(not p.death_due)
assert(not F.phase("hare",200,100))
assert(F.phase("earthworm",0,900).phase=="juvenile")
end)
test("only complete source-backed profiles authorize mature seasonal reproduction",function()
local enabled={bank_vole=true,wood_mouse=true,blackbird=true,mallard=true,hare=true,fox=true}
for _,r in ipairs(F.list()) do
local season=r.id=="fox" and "Winter" or "Summer"
assert(F.can_breed(r.id,0,1800000000,"female",season)== (enabled[r.id] or false),r.id)
assert(r.profile.reproduction_enabled==(enabled[r.id] or false))
assert(not F.can_breed(r.id,1800000000-60,1800000000,"female","Summer"))
end
assert(not F.can_breed("missing",0,1800000000,"male"))
assert(F.get("rabbit").profile.gestation_days.min==30)
assert(F.get("wood_mouse").profile.gestation_days.max==26)
assert(F.get("hare").profile.gestation_days.max==42 and F.get("fox").profile.gestation_days.max==53)
assert(not F.can_breed("rabbit",0,1800000000,"female","Spring"))
end)
test("hemisphere-aware seasons not northern months gate both sexes",function()
local south=dofile(target)({lifecycle=L,climate_at=function() return {season="Spring"} end},{})
assert(south.can_breed("wood_mouse",0,1794000000,"male")) -- November southern spring
assert(not south.can_breed("wood_mouse",0,1794000000,"male","Winter"))
assert(not south.can_breed("wood_mouse",0,1794000000,"other","Spring"))
assert(not F.can_breed("wood_mouse",0,1794000000,"female")) -- no climate, fail closed
assert(F.get("mallard").profile.lifespan_days==false)
assert(F.can_breed("mallard",0,1794000000,"female","Spring"))
end)
test("actual UTC breeding windows never turn into reproductive authority",function()
assert(F.breeding_window("roe_deer",7).within_window)
assert(not F.breeding_window("roe_deer",11).within_window)
local fox_july=F.breeding_window("fox",7)
assert(fox_july.known and not fox_july.within_window,
"fox breeding is sourced for winter months, not July")
assert(F.breeding_window("blackbird",3).within_window)
assert(not F.breeding_window("blackbird",1).within_window)
end)
test("food web has concrete registered prey and distinct ecological functions",function()
for _,r in ipairs(F.list()) do for id in pairs(r.prey) do assert(F.get(id),id) end end
assert(F.get("fox").prey.rabbit and F.get("fox").prey.hare)
assert(F.get("stoat").prey.rabbit and F.get("weasel").prey.bank_vole)
assert(F.get("barn_owl").prey.wood_mouse and not F.get("barn_owl").prey.rabbit)
assert(F.get("otter").prey.brown_trout and F.get("badger").prey.earthworm)
assert(F.get("bumblebee").foods.nectar and not F.get("bumblebee").foods.seed)
assert(F.get("earthworm").foods.litter and not next(F.get("brown_trout").prey))
end)
test("unknown starvation is not fabricated; explicit rabbit upper bound is days",function()
for _,r in ipairs(F.list()) do
assert(r.feed_seconds>=300 and r.reserve_seconds>=86400)
if r.id=="rabbit" then assert(r.starvation_days==8 and r.starvation_source:match("#Diet$"))
else assert(r.starvation_days==false) end
end
end)
assert(passed==10)
print("PASS "..passed.." fauna catalogue tests")