feat: bird roosting behavior on trees#82
Merged
biosynthart merged 2 commits intoJun 9, 2026
Merged
Conversation
- Add songbird rendering to visualizer (teardrop body, animated wings, dovetail tail, expanding song rings when IDLE/REPRODUCING) - Introduce male/female sex for ANIMAL/BIRD/INSECT entities: - Only females produce offspring (clutch_size applies per female) - Mate must be opposite sex within sensory range - Offspring get random sex at birth - Auto-assign random sex on init if not provided in world def - Replace hardcoded FLEE_TRIGGER_DISTANCE with entity's sensory_range, so prey flee proportionally to what they can detect - Add songbird omnivore fallback: foraging songbirds hunt butterflies when flowers are scarce or all on cooldown - Increase demo butterfly count from 2 to 4 (2♀ + 2♂) - Fix stale comment about reproductive drive being permanently zero - Update SpawnEntity effect and both spawn handlers to carry sex field - Add tests: male cannot spawn, same-sex mate rejected
- Add roost_affinity trait (list of preferred tree species) to TraitVector/DerivedParams - Birds with roost_affinity seek nearest matching tree when RESTING or IDLE - Movement gate allows resting birds to move toward trees (like pollinators for flowers) - Energy recovery boosted by 50% when within canopy of a preferred roost tree - All behavior driven by data — no engine special-casing by entity type Files changed: traits.py — new roost_affinity field, flows through derive_all() constants.py — ROOST_ENERGY_BONUS_FACTOR, ROOST_PROXIMITY_BUFFER movement_actors.py — _resolve_roosting_target(), _find_nearest_roost_tree() movement_system.py — allow RESTING/IDLE birds with roost_affinity to move flow_actors.py — energy recovery bonus near preferred roost trees species_definitions.json, demo_world.json — wire up songbird → oak affinity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds data-driven roosting behavior for birds. Species with
roost_affinityseek preferred tree species when RESTING or IDLE, and gain an energy recovery bonus while perched within a tree's canopy.Design
Fully driven by trait data — no engine special-casing by entity type:
roost_affinity: list[str]onTraitVector/DerivedParams— species IDs of preferred roost trees (e.g.["oak", "meadow_oak"])Behavior
Files Changed
ecosim/traits.pyroost_affinityfield on TraitVector + DerivedParams, flows through derive_all() and trait_vector_from_dict()ecosim/constants.pyROOST_ENERGY_BONUS_FACTOR = 0.5,ROOST_PROXIMITY_BUFFER = 1.0ecosim/actors/movement_actors.py_resolve_roosting_target()+_find_nearest_roost_tree()— tree-seeking target resolutionecosim/movement_system.pyecosim/actors/flow_actors.pyexamples/species_definitions.json"roost_affinity": ["oak", "meadow_oak"]examples/demo_world.json"roost_affinity": ["meadow_oak"]Testing
All 165 existing tests pass. New trait flows cleanly through TraitVector → derive_all() → DerivedParams pipeline.