Files
last-hearth/docs/fauna.md
T
2026-11-05 09:57:11 -05:00

41 KiB
Executable File

Fauna: evidence, calendar time and integration contract

Reviewed 2026-11-04. Scope includes the catalogue, wildlife runtime, direct in-game interaction panel and focused Lua tests. No engine run or visual-quality acceptance is claimed by this change.

Public interfaces

The catalogue is a factory: dofile(modpath.."/fauna.lua")(hearth,api). It returns VERSION, SECONDS_PER_DAY, list() / catalog() (ordered record arrays), get(id_or_entity), kind(id_or_entity), source(id) (URL array), phase(id,born_at,utc), breeding_window(id,month) and can_breed(id,born_at,utc,sex,season?). Unknown IDs return nil or deny breeding. All catalogue records and lists are defensive copies. Records expose id, entity, common, latin, source_url, wikipedia_url, sources, confidence, profile (unaltered lifecycle evidence), foods, prey, medium, activity, bounds, mesh, texture, clips, fps, frames, eye_height and policy caps.

Main may construct hearth.fauna before wildlife. Otherwise wildlife loads the fixed sibling factory via api.get_modpath("hearth"); no caller-supplied path or saved asset name is accepted. The catalogue uses hearth.lifecycle or loads the fixed sibling lifecycle module. Main should inject lifecycle so seeded cohort ages use its duration() selection consistently. No network request occurs at runtime.

Wildlife returns fauna, species (legacy hare entity), global_cap, player_cap, local_cap, ai_budget, status(). Status includes legacy total, hare, deer, fox, plus a copied counts dictionary containing all 23 IDs, species_count=23, actions, births, meals, grazed, dung, deaths, pollinations, dispersals, detritus, and the three caps. It also exposes a defensive recruitment diagnostics copy: interval=5, scan_nodes=648, attempts, successes, scans, last_reason, and reasons (reason-to-count dictionary). The /ecosystem survey displays all species plus admission attempts, successes and the latest outcome; it remains observation-only. Reasons include waiting, invalid_player, global_cap, no_surface, observer_near, blocked_or_unloaded, habitat_unloaded, no_active_food_match, population_cap, unsafe_body, activation_rejected, admitted, registry_unavailable, region_budget, and region_seeded. status().residents is a fresh diagnostics table containing storage_ok, regions, region_limit=4096, region_size=48, founders_per_region=4, and the persistent individual counter. Counts describe loaded residents, not the entire unloaded population. Diagnostics do not expose mutable journal records.

Field journal and ambient grouping

Right-clicking a live, pointable animal records that species in the observing player's metadata under a versioned, bounded, canonical species-ID list. The species guide marks recorded and not-yet-encountered identities; opening a catalogue-only profile never unlocks an encounter. This is a private per-player field-journal convenience, not a local census, achievement reward, or change to the animal/world state. Invalid saved journal text fails closed and is never overwritten. Active robins, blackbirds, blue tits and mallards also use a small, local cohesion/separation bias when choosing wander direction. It is computed from loaded same-species residents only—there are no persisted flock IDs, unbounded entity scans, or forced spawn groups.

These are original adaptations of ambient grouping and encounter journaling ideas visible in Animalia's public bird behavior, AI, and Libri source. Last Hearth does not include that mod's code, models, textures or audio.

Runtime API integration

The managed package pins the MIT-licensed Creatura 0.2.10 release from ContentDB release 34130; the downloaded archive SHA-256 and upstream commit are recorded in mods/creatura/UPSTREAM.md. Creatura supplies animal-focused pathfinding, boid algorithms and its ABM spawn scheduler. Last Hearth supplies species identities, original meshes/textures, habitat and diet policy, caps, protected/provenance-aware admission, persistent resident IDs, feeding transactions and player interactions. Creatura spawn callbacks do not bypass Last Hearth's on_activate checks. Ambient ABMs are restricted to common species, small groups, natural soil types and fixed per-species caps; no drops, taming, combat or livestock systems are enabled. The bounded Last Hearth recruitment path remains available as a fallback and does not award food when vegetation serves only as an ambient habitat signal.

Engine API: entity/globalstep registration, connected players, loaded-only get_node_or_nil, node definitions, node metadata, protection, add_entity, parse_json / write_json, mod storage (hearth.storage, otherwise api.get_mod_storage()), and normal ObjectRef position, velocity, yaw, acceleration, armor and animation methods. Optional api.now() is an integer UTC epoch test seam; otherwise os.time() is used. Climate uses hearth.climate_at(utc).season; qualitative habitat seasons may be accelerated by climate configuration, but animal ages and activity hours never are.

Direct in-game interaction

Registered animal entities are natively pointable while retaining their existing physical collision envelope. Luanti's normal object picking dispatches right-clicks to hearth.inspect_fauna(clicker, species_id, snapshot); this is not a HUD raycast or a node-placement change. Wildlife verifies that the entity is currently active and that the exact clicker is an online player with a session, then passes a detached snapshot of calendar birth time, modeled reserve, origin, persistence-ID availability and current rest/awake animation observation. The callback is looked up at interaction time so wildlife does not own formspec registration. The interface checks the online player and session again, and escapes/bounds displayed catalogue and snapshot text. Species-guide selection can also open a species-only profile; it is not a local animal census.

The panel reports Latin identity and source URLs, lifecycle phase and real calendar age when available, currently modeled diet and prey, activity/sleep and winter-rest policy, and whether reproduction is enabled for the profile or disabled for incomplete evidence. Food reserve is explicitly labelled as a coarse game policy, not biology. Persistent residency and current animation are observations only; no position is displayed. A direct animal encounter adds one species ID to the observing player's bounded field journal; catalogue browsing does not. Neither action changes animal state, ecology, inventory or terrain. Punching continues to trigger flee movement; immortal armor and the lack of damage/drop handlers prevent combat or item rewards. Collision and crafting/node placement remain unchanged. Native mesh appearance and animation quality were not visually verified in an engine session.

Required succession transaction contract

These are required transactional hooks; the current succession supplies them. Wildlife does not replace or bypass their shared budgets. Missing hooks or anything other than literal boolean true gives no feeding credit and no ecological-success count. Wildlife performs no direct vegetation/node mutation or inventory operation. Main must repeat all loaded/protection/provenance checks inside each transaction. Forage/deposit's entire 3x3 neighbourhood is guarded by wildlife before invocation.

Hook Exact required semantics
habitat(pos) Loaded observation with loaded, grass, cover, canopy, moisture, water, near_water. Unknown/unloaded must fail recruitment.
forage(pos) -> boolean Existing metadata-only natural browse debit, finite and seasonal, not inventory/crop consumption.
deposit(pos) -> boolean Existing bounded metadata-only dung/nutrient receipt. One pending receipt per earned meal; no item or offline queue.
pollinate(pos) -> boolean Atomically debit legitimate nectar from a mature, currently flowering natural plant and apply bounded pollination. Persist shared succ_nectar_ready_at before any callback; all bees compete for the same budget. Reject invalid timestamps. Use an explicit nectar replenishment policy; wildlife's 300-second inter-meal throttle is NOT evidence for floral replenishment. No seed generation.
frugivore(pos, species_id) -> boolean Verify exact botany identity and fruiting season, then atomically debit the same botany_ready_at used by human botany.harvest. Set its existing annual (365.2425 * 86400 seconds) resource deadline before callbacks. Never maintain a parallel animal-only berry budget; reject invalid/future readiness, nonnatural/planted nodes and immature shrubs. No inventory output.
detritivore(pos) -> boolean Consume a finite unit of existing natural litter and transfer only conserved organic/mineral material. Reject empty substrate. Never an infinite soil fertility aura.
granivore(pos, species_id) -> boolean, optional_cache_id Debit an existing finite seasonal seed/nut resource. True grants one meal; optional "hazel" or "oak" grants a second separately debited viable nut, not the eaten seed. No token if the second nut was unavailable.
disperse_seed(pos, species_id) -> boolean Accept one immediately preceding, separately debited cache nut; check loaded natural viable destination and bounded seed metadata. Only squirrel hazel/oak caches invoke this hook. Consume authority once even if the destination fails (lost nut, never duplicated). No persistent token, offline planting, pollinator seed aura, or arbitrary new species.

The cache hook must track immediate granivore authority in succession, rather than trust arbitrary callers. Both source and destination are guarded; successful consumption and successful caching are different counters. Seed-eating mice, voles and birds are not automatically awarded dispersal. Fruit transport/gut passage is not implemented and must not be presented as simulated.

Time, provenance and deliberately unknown biology

Six profiles now enable reproduction: bank vole, wood mouse, blackbird, mallard, European hare and red fox. The sourced hare profile uses 365-day maturity, 42-day gestation, one leveret per litter and a 30-day care lock; its broad reported season is represented as Winter/Spring/Summer. The fox profile uses 304-day maturity, 53-day typical gestation, one pup per litter, and a conservative 300-day postpartum lock; its coarse breeding season is Winter. ADW reports 56-70 days of fox nursing/weaning, but the existing generic dependent-care loop cannot represent paternal provisioning or fox den care, so this species is not a complete family-behavior simulation.

Registration (pending=false for all 23) is independent of evidence completeness. This is not whole-ecosystem true-life certification. The following pages were retrieved on 2026-11-03; ranges are original factual summaries, not bundled article text. Runtime uses conservative upper development and maturity endpoints and the lower sourced litter/clutch count.

Species Maturity Development to birth/hatch Count Sources and limitations
bank vole 42-56 d sex envelope; runtime 56 d for both 17-24 d gestation; runtime 24 d 3-5, runtime 3 ADW gives 17-24 d, 20-25 d weaning, late April-September; Woodland Trust supplies conservative 6/8-week maturity; Wildlife Trusts supplies the chosen 3-5 count. ADW reports a wider 1-10, typically 4-8; these are not silently merged.
wood mouse 65-71 d; runtime 71 d 21-26 d gestation; runtime 26 d 4-8, runtime 4 ADW gives maturity, gestation and 21 d weaning, but 4-7 young; retained 4-8 is from Wildlife Trusts. Wikipedia reports February-October season and 23-27 d gestation, differing from ADW.
blackbird about one year 13-14 d incubation; runtime 14 d 3-4, runtime 3 ADW gives first breeding at one year, 13-day prose/14-day summary and 13-14 d leaving nest. RSPB supplies clutch/nesting window. Fledging is not full independence.
mallard 365 d both sexes 26-28 d incubation; runtime 28 d 9-13, runtime 9 ADW gives these values; Wikipedia gives 50-60 d to flight and spring nesting. Unknown lifespan does not prevent breeding.
European hare 236-365 d; runtime 365 d 30-42 d gestation; runtime 42 d 1-8 leverets, runtime 1 ADW reports maturity at 8 months-1 year, one-month weaning, 30-42 d gestation and 1-8 per litter; winter through midsummer breeding. One-month care lock is a conservative policy.
red fox about 304 d; runtime 304 d 51-53 d typical gestation; runtime 53 d 1-9 in ADW summary, runtime 1 ADW reports 10-month maturity, winter mating in central-range populations, 51-53 d typical gestation and 56-70 d nursing/weaning. Its prose says 1-13 while its summary table says 1-9; the narrower table range is retained. A 300-day postpartum lock approximates its once-yearly seasonal cycle; this is policy.

Breeding requires same-species female and male within two nodes, both mature, safe, recently fed (within twice their feeding throttle), reserve at least 0.7, and loaded food-bearing habitat. Conception spends 0.2 reserve from each parent; each delivered young spends another 0.1 from the mother and starts with 0.1. These are explicit normalized energy policies, not biological calorimetry. Only successful succession transactions earn reserve. There is no feeding-count shortcut to maturity, free fertility command, item reward or player attack.

hearth.climate_at(utc).season (or an explicitly supplied season) determines the hemisphere-aware season gate: Spring/Summer for the four original profiles, Winter/Spring/Summer for hare, and Winter for fox. Northern reference months remain research observations, not a simultaneous northern-month veto on southern spring. These coarse season policies omit some legitimate early-autumn breeding; it is not exact local phenology. Missing climate denies new conception. Calendar age and due times always use real epoch seconds, never climate-speed multipliers.

Pregnancy and incubation use a common persisted deadline field; eggs are a bounded maternal brood state, not mammalian pregnancy or separate nest nodes. Egg laying, nest construction, exact incubation attendance and clutch failure are not simulated. Dependent young rest rather than hunt/browse as adults; nearby loaded mothers transfer 0.05 reserve at the ordinary feeding cadence. This is coarse care accounting, not milk chemistry or a species-specific chick diet. Maternal postpartum locks are 25 d (vole), 21 d (mouse), 42 d (blackbird), 81 d (mallard), 30 d (hare) and 300 d (fox) after the last admitted young. Bird locks deliberately include an extra 21 d beyond the conservative dependency/fledging allowance. They do not claim measured inter-clutch intervals. Assets still use the authored species mesh, not visually distinct baby models.

Seventeen profiles stay reproduction-disabled, including three legacy slots. Blue tit now has BTO 8-10 typical eggs, about 14 d incubation and 18-21 d fledging; first breeding is described as the next spring, not an accepted exact day threshold, and represented caterpillar provisioning is missing. ADW's Cyanistes URL was missing and its older Parus URL contained taxonomy only; neither validates numerical overrides. Common frog adds about 3-year maturity and 14-21 d incubation, but aquatic eggs/tadpoles and their food remain absent. Brown trout needs female mass for its approximately 2000 eggs/kg, a gravel redd and temperature-dependent development. Bumblebee requires queen/worker/ male castes and colony care; a single litter timer would be misleading. Rabbit maturity, squirrel conception season, roe deer/stoat implantation, other mammal profiles, robin/barn owl care, newt larvae and worm cocoons remain incomplete. No missing values are filled with guesses. Lifespan averages never trigger death.

One-time regional founders represent existing wild individuals, not reproduction. Where maturity is sourced, the estimated initial age uses its upper endpoint; born_at=utc-estimated_age_days*86400, origin="established" explicitly labels the estimate. Unknown maturity has no invented age offset and still remains an established individual, not a purported newborn. origin="born" marks actual admitted young with born_at=utc at delivery, including delayed admission after an overdue pregnancy; it never creates an adult-aged catch-up cohort. self.id remains an in-memory scheduling serial. state.resident_id is the separate durable world-local positive integer allocated from mod storage; state.founder_region identifies the founder's geographical cell, or is empty for births and legacy-ID migration. Sex, selection seed, food reserve, birth epoch and reproductive state survive normal unloading and restart. Position is saved by the engine's static-object system, not copied into a second registry.

Feeding throttles (nectar five minutes, predators two hours, other plant food one hour), movement speeds except earthworm, and normalized two-day energy reserves are coarse simulation policies, not sourced metabolic measurements. Unknown starvation durations are false: hunger can accumulate over hours/days but cannot justify an invented death threshold. Rabbit is the sole enabled starvation case: the fetched European rabbit account reports winter survival without food of about 2-8 days; the conservative upper eight-day bound is used, counting only represented loaded hunger (hunger_seconds), never an unloaded absence. This is not a veterinary prediction for an individual. No free food appears because a predator lacks prey. There are no modeled insect-larva, mayfly, beetle, parasite, egg or nestling populations to feed on. Thus adult trout currently have no supported live-prey recruitment resource; saved trout swim and remain otter prey without pretending an unimplemented invertebrate biomass exists.

Persistence and bounds

static_save=true. Static state is version-1 JSON, at most 2048 bytes, with only version, species, born_at, origin, sex, foodreserve, nextfeed, pregnancy_until, last_seen, seed, last_meal, dung_pending, plus conception_at, litter_total, litter_remaining, litter_delivered, nextbreed, last_birth_at, parent_seed, parent_born_at, resident_id, founder_region, hunger_seconds. No deserialize, Lua evaluation, arbitrary asset names or paths. Exact entity/species match, finite numeric types/ranges and coherent nonfuture observation/birth/meal clocks are mandatory. Flat/nonnested input is checked before silent JSON decoding. Pregnancies require an enabled female profile, mature conception, exact sourced maximum development interval, coherent bounded integer litter counts, and a deadline no further ahead than that interval. Overdue deadlines remain valid. The old version-1 empty reproductive state migrates to zero counters; old nonzero pregnancies without the new schema are refused. Next-feed deadlines are bounded to one day ahead; future birth or observation data is rejected, never used for credit. Failed JSON encoding emits an invalid sentinel rather than silently making a fresh cohort next load.

Validated existing residents always restore, even above species/global/local/ player caps, with no connected-player API, or on newly claimed, blocked, foodless, nil/ignore unloaded terrain. Positive native dtime_s is expected for restoration and is accepted. No habitat or collision read may delete a validated existing resident merely because its surroundings changed. Invalid snapshots, unknown fields/species, incoherent clocks or out-of-world coordinates are still rejected, with bounded reason-only warnings (no raw payload logging). Movement and ecological transactions stop safely inside new claims, ambiguous claims, external protection or unknown/unsafe collision terrain. An animal on still-safe but depleted ground can wander and become hungry rather than vanish. There is no teleport/terrain-repair escape for an animal trapped by construction.

Deactivation forgets live counts only, idempotently; it never records a death or removes founder membership. Nothing deletes an existing animal to free admission slots. Dormant mapblock animals stay in the engine save and can return above the new-admission caps. Births and new founders, unlike restores, still require all current safety, habitat and cap checks. There is no 900-second lifetime or walk-away despawn/replenishment path.

Offline calendar ages/deadlines advance from saved epochs, but unloaded AI is frozen, not a whole-world ecological simulation. There are no replayed offline meals, mating cycles, founder admissions or dung/caching queues. An existing overdue brood is reconciled on budgeted AI after a player returns: at most one newborn per attempt, no more than its single stored litter total. Species/global/local/player caps, safe loaded positions, current habitat and maternal energy still apply. Full caps delay the original due time without redating; remaining/delivered counts survive normal save/reload. Failed admission does not spend a child; callback reservations and activation acknowledgement prevent synchronous reentry duplication. Once complete, the brood clears and postpartum lock prevents repeated deliveries. This is normal-save idempotence, not a cross-mapblock crash-atomic transaction or authenticated save format. Server-local static data is not exposed as client/admin fertility input. Schema validation rejects giant/incoherent payloads but cannot authenticate a coherently rewritten world save; operators must protect world files. No such bypass API is added. Energy/hunger work on each safe loaded observation is bounded to 60 seconds; restoration preserves reserve and accumulated hunger, resets the observation clock and clears the pending dung attempt. A successful meal or maternal feeding resets loaded hunger. Legacy snapshots start hunger at zero because their historical loaded/unloaded intervals cannot be reconstructed. Unsafe or player-absent AI turns freeze energy/hunger. No force-loading or emergence.

One-time, geographically bounded founder registry

The separate mod-storage key is wildlife_residents_v1. This does not change the game's world-schema version. Its flat JSON envelope has version=1, counter (last allocated individual ID), and sparse r_<x>_<z> fields. Cell coordinates are floor(world_x/48), floor(world_z/48), including negatives; they do not depend on player, session, Y, current population or visit count. Each region value is a canonical bounded string: attempts/last_attempt_utc/resident_id=species;resident_id=species;.... Both the decoder and encoder enforce the 1,048,576-byte registry ceiling; each region value is at most 256 bytes with at most four founder memberships. The decoder requires exact version, known species, valid bounded cell keys, finite integral clocks/counter/IDs, unique founder IDs and no extra fields. Nested/deep JSON is rejected before parsing; no code evaluation, assets, paths, credentials or client-provided allocation authority are stored.

At most 4096 region records can ever be admitted automatically. Records are never evicted, reset on return, silently truncated or recycled after death. New regions beyond this permanent budget are refused; existing records and saved animals remain intact. Attempts (saturating at one billion) and last UTC are persisted even for a loaded search that has no surface, unavailable food, or unloaded/invalid candidates; these attempts do not fill founder quota. An incomplete cell remains retryable on later valid observations, with no timeout that marks an empty/unloaded area permanently populated. A full cell never fills a dead, eaten, migrated-away or currently unloaded animal's slot. Different eligible species may share its four slots; their IDs and types are retained permanently, not inferred from live counts. This is a one-time founder quota, not a continuously restored carrying-capacity target. Natural births remain independently funded by the existing calendar/food/cap rules and do not spend or refund founder slots.

Membership and monotonic ID allocation are written/read-verified before the new animal is acknowledged. Storage read/write failure, silent dropped writes, invalid JSON/version, duplicate/unknown membership, or any exceeded bound disables all new admissions (including births), without deleting validated existing residents. Missing storage also disables new admissions. A known saved ID above a missing/rolled-back counter fails closed instead of reusing its ID. Legacy snapshots without ID fields receive an ID and empty founder_region when storage is healthy; with failed storage they remain valid residents without an allocated ID, rather than being destroyed. They can migrate on a later restore after operator repair. Never clear this key to make animals reappear: restore world/mod-storage backups together. A process/storage crash after reservation can conservatively spend a founder slot or burn an ID without creating an animal; there is no cross-mapblock crash-atomic population transaction or automatic refill.

New-admission global cap is 64; player-neighbourhood cap 16 within 48 nodes; local cap 12 within 16 nodes. Per-species caps range 2-8. Overlapping player neighbourhoods are all checked for new founders/births only, never movement or restoration. Loaded counts can exceed these limits after restoration; this delays further admissions without erasing any resident. AI and founder searches share 24 actions/second, maximum one second of accrued work; entities are visited in serial round-robin order. Recruitment spends one action every five active seconds, with no credit banked while players are absent. It rotates players and eight search patches, queries one 9x9x8 box through find_nodes_in_area_under_air (648 cells maximum), and checks one round-robin surface candidate per attempt. This is at most 12 queries / 7,776 queried cells per active minute, not a whole-map scan. Habitat, body-envelope and ordinary AI observations are additional bounded work, not included in that terrain-query cell count. No query may emerge unloaded blocks. An integration without this search API reports no_surface, not a guessed Y.

Candidates lie 12-24 horizontal nodes from the selected observer; any observer within eight nodes vetoes admission. Ground/plant surfaces set the body base half a node above actual support, not at the player's Y. Water surfaces retain their own water-cell Y and use the stand above water for succession observations. The fixed vertical search band is player Y minus four through plus three; distant cliffs outside this band wait for a closer observer.

One plant-food observation and one succession habitat observation are shared across cheap rotating catalogue matches. Only currently active, habitat/food-fit, uncapped species receive body-safety/admission checks. There are no 23 separate terrain scans or a forced 11.5-minute wait for the next eligible species. Daylight flowering yarrow can admit a bee, mixed understory a bank vole; nocturnal species remain nocturnal and predators still require represented fruit or actual prey. Qualitative herb seeding seasons are not an implemented food budget: only oak/hazel nuts are recognized as seeds, matching succession's granivore debit. Founder admission does not call can_breed, require a completed reproductive profile, or fabricate an age/maturity threshold for unknown biology.

Unadopted, unmarked, supported worldgen understory is collision-passable without pretending it was already adopted. At a recruitment candidate, at most nine ground-level cells use guarded diversity.bootstrap (when available). The three legacy meadow-grass/fern/wildflower sprites receive only succ_natural metadata under the same loaded, natural-support and provenance checks. This closes the gap between succession's 12-node adoption ring and the wildlife search ring. No botanical birthday/profile, forage ration, inventory item or plant node is created. Unknown placement metadata, named planter markers, claims, ambiguous claims and external protection deny adoption. Botany's presence does not hide legacy grass/fern browse. Every subsequent meal still requires the existing finite succession transaction; merely discovering or adopting a plant grants no nutrition. Existing saved animals activate before the first observer joins, without bootstrap, safe/room rejection or a current-food requirement; unsafe terrain freezes subsequent movement/transactions rather than destroying them.

Founders are initialized only as loaded habitat is explored near an observer; unexplored regions have not yet been instantiated. This unavoidable lazy initialization is not recurring immigration when walking around a seeded region. There is no startup world-wide spawn, force-loading or offline execution. Per-frame safety/velocity checks are bounded per loaded entity and do not count as AI decisions. Restoration may exceed 64 loaded objects; the shared AI action ceiling remains 24/second, but per-frame callbacks/list sorting are not a measured constant CPU bound for an arbitrarily large restored population.

Absent-animal diagnosis and focused regression

Before this correction, a single hardcoded candidate at player Y was tried for one species every 30 seconds. All 23 species therefore took 690 seconds (11.5 minutes) to revisit. Slopes failed body support, and unadopted sprites both blocked clearance and failed food recognition outside succession's adoption ring. With botany loaded, legacy meadow grass/fern also lost the fallback browse path. These were admission/resource blockers, not a missing adult-age privilege: this runtime never gated immigration on known maturity or can_breed. The old danger comparison used squared distance 16 (four nodes); it now uses 64 (eight).

The focused wildlife suite now has 57 named checks. It adds repeated physics steps across AI intervals, approach to reachable food, fine-grained collision sweep, solar activity and dormancy, danger/hunger while resting, winter browse-mode negotiation, and sourced hare/fox reproductive timing.

Movement and art

Every fixed ID uses hearth_fauna_<id>.b3d and hearth_fauna_<id>.png. Five actual ObjectRef animation calls select idle 0-19, locomotion 20-39, feed 40-59, flight/swim 60-79, rest 80-99, at 24 fps with 0.15-second blend. The authored asset has 100 frames. Bounds were obtained from faunaBounds() in the existing art generator (10 model units per node), including long fox tails, squirrel tail height, bird wings and antlers. Eye heights have a 0.15 minimum. Collision is based on those measured bind bounds; safety uses a yaw-independent envelope and animation margin, checking bottom, middle and top, source, destination and a swept path sampled at no more than 0.2 nodes (at most 20 intervals for a four-node segment). No set_pos teleport movement.

Velocity ramps at at most 2 nodes/second squared up to a 1.3 nodes/second ceiling; each command has a 2.5-second lease, exceeding the two-second AI interval. Safety stops may be abrupt. Land, low flight, submerged swimming and moist-land invertebrate corridors differ; amphibians/otters/mallards may inhabit either land or water but shore transitions are deliberately refused until swept bank-ramp traversal is implemented. Flight can move vertically within a three-node natural-ground corridor. Unloaded, claimed, ambiguous, protected, building, unsupported and wrong-medium samples stop movement. This is conservative local movement, not full navigation, arboreal climbing, digging, seasonal migration or fluid dynamics. Gravity is held at zero inside these validated corridors to avoid uncontrolled cliff falls. The earthworm surface speed is the reported 20 metres/hour, not a mammal sprint.

Species activity differs: local solar day/night schedules, twilight activity, winddown/wakeup transitions, short rest windows for flexible activity profiles, and winter dormancy for hedgehogs, frogs and newts. Danger is processed before rest and loaded hunger continues during sleep; dormancy never removes an animal. Resource search checks a fixed 5x5 horizontal area and follows a reachable food candidate rather than requiring it beside the next AI tick. Winter browse accepts only a non-toxic tagged tree/shrub and never implies human edibility. Wildlife passes winter_browse to the shared forage hook, but the current succession implementation does not accept that mode; winter twig/stem debiting is therefore not active until a separately scoped succession change. Ordinary shared browse continues to use its existing seven-day plant cooldown. Also represented are danger flight and hedgehog stillness, alert pauses, nectar visits, fruit feeding, nuts/caching, litter consumption and actual finite prey pursuit. The source accounts describe many additional behaviors; descriptions are not claims that burrows, dreys, antler shedding, caste systems or parenting are coded. Art quality requires separate native-engine animation/visual acceptance.

Research register and implemented nutritional web

Fetched Wikipedia identity/diet accounts (first eight plus earthworm/deer), and Wildlife Trust/RSPB accounts for the remaining rows, on 2026-11-03. All Wikipedia URLs are explicit identity links; generic deer is Cervidae, not a silently chosen Latin binomial. Bank vole retains the lifecycle identity Myodes glareolus (synonym Clethrionomys glareolus on the retrieved Wikipedia page). Prose below is original summary; no source media or article text is bundled.

ID Identity / Wikipedia URL Reviewed nutrition and represented behavior
hare Lepus europaeus Grass/herbs, surface forms, nocturnal escape; represented browse and fox prey.
deer Cervidae, unidentified legacy deer Family-level foliage browsing only; no species timing asserted.
fox Vulpes vulpes Hare/rabbit/vole/mouse/squirrel/worm/frog prey, seasonal berries; mostly nocturnal.
rabbit Oryctolagus cuniculus Grass/leaves; fox and stoat prey; no fictitious warren reproduction.
red_squirrel Sciurus vulgaris Seeds/nuts/fruit; diurnal, canopy-dependent establishment; separately funded oak/hazel cache.
bank_vole Myodes glareolus Leaves/seeds/fruit, needs cover; fox/stoat/weasel/owl prey.
wood_mouse Apodemus sylvaticus Seeds/fruit and nocturnal covered movement; fox/stoat/weasel/owl prey.
hedgehog Erinaceus europaeus Finite earthworm prey, nocturnal/winter rest; badger prey.
badger Meles meles Worms, rodents, hedgehogs, fruit; nocturnal. No adult rabbit edge: account emphasizes kittens.
roe_deer Capreolus capreolus Wildlife Trust: buds/leaves/herbs/grass; delayed implantation not fabricated.
stoat Mustela erminea Wildlife Trust: rabbit and small rodents; day/night hunting.
weasel Mustela nivalis Wildlife Trust: vole/mouse/small birds, low running.
otter Lutra lutra Wildlife Trust: salmonids/frogs/newts; aquatic pursuit.
robin Erithacus rubecula RSPB: earthworms, seeds, fruit; hopping/flight.
blackbird Turdus merula RSPB: earthworms and seasonal fruit; ground feeding.
blue_tit Cyanistes caeruleus RSPB: seeds/nuts/berries; caterpillars are described but absent from simulated food supply.
barn_owl Tyto alba RSPB: finite voles/mice, low hunting flight; no adult-rabbit edge.
mallard Anas platyrhynchos RSPB: seeds/berries/plants; water-associated.
common_frog Rana temporaria Wildlife Trust: invertebrates; only registered earthworms modeled; moist habitat/winter shelter.
smooth_newt Lissotriton vulgaris Wildlife Trust: land worms, nocturnal moist habitat; aquatic prey stages unimplemented.
brown_trout Salmo trutta Wildlife Trust: larvae/small fish/flying insects; no phantom biomass, saved trout are finite otter prey.
bumblebee Bombus terrestris Wildlife Trust: legitimate nectar/pollen at active flowers; shared pollination/nectar transaction, not seed dispersal.
earthworm Lumbricus terrestris Natural dead leaves/mineral soil; moist nocturnal surface motion, finite litter debit. Wild lifespan unknown; captive six-year record is not a death deadline.

Lifecycle's separately attributed numerical references also include ADW rabbit, ADW squirrel, ADW wood mouse and Woodland Trust bank vole. Those evidence values retain field-level confidence; unsupported fields stay unknown.

Focused acceptance

Standalone catalogue and wildlife tests use injected clocks and strict expected named-test totals; no native engine, background game instance or offline event replay is involved. They cover catalogue identity/evidence/copies, real-day age, unknown breeding denial, seasons, JSON hostile payloads and roundtrip, all caps, startup restore before players, all modeled trophic classes, single-use prey, feeding cooldowns, protected source/destination stencils, shared floral/fruit budgets, finite litter/nut authority, velocity bounds/no teleport, runtime animation calls, cliff/water/unloaded refusal, and scheduler work caps.

The wildlife suite now defines 57 named checks, including the movement, activity, dormancy, browse-mode and sourced breeding regressions. These changes were not executed in this pass. No native engine, full-repository test run, real-world save or art files are changed. These tests validate mocked runtime contracts, not native mapblock persistence, rendered young animals, engine crash recovery or biological completeness; native integration remains the main agent's responsibility.