Skip to content

Commit 317619a

Browse files
committed
fix: prevent Mold preset wall-collapse via trail-dependent respawn
Bounce alone accumulates a wall-parallel trail that eventually condenses all agents onto one wall-hugging filament (collapse by ~6000f). Add a gentle trail-dependent respawn (every 90 frames, scatter agents sitting in high-trail back into the field, probability up to 5x where brightest) so the runaway feedback can never close. Holds a crisp large-celled vein network out to 40000f.
1 parent f0f6a17 commit 317619a

3 files changed

Lines changed: 28 additions & 7 deletions

File tree

src/preset_sim_defaults.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -558,12 +558,19 @@ impl From<Preset> for PresetSimDefaults {
558558
// (moves to RenderArtDefaults). Sim levers: deposit_curve, deposit_scale,
559559
// decay_gamma (config.rs:744-762)
560560
Preset::Mold => Self {
561-
// Wider sensor (22.5°) + high rotation (60°) hold a *contained*
562-
// branching colony under Bounce: agents fold back at the walls into
563-
// internal veins instead of condensing onto one wall-hugging filament
564-
// (the old 15°/30° collapse) or wrapping toroidally (the seamless-edge
565-
// character of the earlier Wrap retune). decay 0.90 keeps persistence
566-
// without runaway accumulation; headless coverage holds ~0.40 @1500f.
561+
// Wider sensor (22.5°) + high rotation (60°) under Bounce keep a
562+
// *contained* branching colony whose veins fold back at the walls.
563+
// But Bounce alone accumulates a wall-parallel trail that, given enough
564+
// frames, condenses ALL agents onto one wall-hugging filament (the
565+
// sensor/rotation/decay retunes only delayed it — at ~6000f the colony
566+
// collapsed to a single edge filament, edge:interior trail ratio >30x).
567+
// The structural fix is gentle trail-dependent respawn: every 90 frames
568+
// an agent sitting in high-trail (i.e. the bright wall line) is scattered
569+
// back into the field with probability rising up to 5x where the trail is
570+
// brightest, so the runaway feedback can never close. Tuned as gently as
571+
// possible (base 0.002) to keep the self-organised vein network intact —
572+
// holds edge:interior trail ~1.1x with crisp large-celled structure out
573+
// to 40000f, where decay 0.90 alone collapsed by ~6000f.
567574
sensor_angle: 22.5,
568575
rotation_angle: 60.0,
569576
decay_factor: 0.90,
@@ -574,6 +581,12 @@ impl From<Preset> for PresetSimDefaults {
574581
deposit_curve: DepositCurve::Sqrt,
575582
deposit_scale: 1.5,
576583
decay_gamma: 0.8,
584+
respawn_config: RespawnConfig {
585+
interval: 90,
586+
base_probability: 0.002,
587+
trail_dependent: true,
588+
max_probability_multiplier: 5.0,
589+
},
577590
species_configs: vec![SpeciesConfig {
578591
name: "default".to_string(),
579592
count: 50_000,

src/profile_overrides.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,14 @@ pub(crate) fn project(ov: &ProfileOverrides) -> Result<Canonical, String> {
875875
sc.trail_modulation = None; // un-capturable + not runtime-editable
876876
}
877877

878+
// `respawn_config` is set by the preset layer (e.g. Mold's anti-collapse
879+
// respawn). ProfileOverrides can only carry the `interval` scalar, never the
880+
// full {base_probability, trail_dependent, max_probability_multiplier}, so it
881+
// cannot round-trip through capture; and no keybind mutates it at runtime. Like
882+
// `trail_modulation` above, normalise it on BOTH sides so the guard stays blind —
883+
// a clean swap to a preset that sets respawn must not read dirty.
884+
sim.respawn_config = Default::default();
885+
878886
// Reproduce apply_color_aa_all priority EXACTLY ([P1]):
879887
// 1. full per-charset array if color_aa_all present,
880888
// 2. else the FULLY RESOLVED color_aa on the RESOLVED charset's slot over defaults.

tests/golden/preset_configs.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ obstacles=[]
487487
attractors=[]
488488
separate_species_trails=false
489489
sampling_mode=Nearest
490-
respawn_config=RespawnConfig { interval: 0, base_probability: 0.01, trail_dependent: false, max_probability_multiplier: 1.0 }
490+
respawn_config=RespawnConfig { interval: 90, base_probability: 0.002, trail_dependent: true, max_probability_multiplier: 5.0 }
491491
species[0]: name="default" count=50000 sa=22.5 ra=60.0 ss=1.0 da=5.0 color=RgbColor { r: 34, g: 139, b: 34 } mod=false
492492

493493
=== etching ===

0 commit comments

Comments
 (0)