fuzzyworld

herd / commit

Keep sheep inside the pen once herded in

c4a1cdd14bdfe7355c21f09f38b75fedd4964bee · Pavel Safronov · 2026-05-17 20:42:28 -0700 · parents b90608d0f73e

Keep sheep inside the pen once herded in

Sheep inside the pen now get edge-repulsion on all four walls instead
of the weak center-attraction applied to outside sheep. Peak force is
3× the max flee weight so a spooked sheep still can't escape even with
the dog right at the fence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
 src/ai/Boids.ts | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/ai/Boids.ts b/src/ai/Boids.ts
index ee570ca..b2518d0 100644
--- a/src/ai/Boids.ts
+++ b/src/ai/Boids.ts
@@ -185,8 +185,24 @@ export function updateBoids(
       }
     }
 
-    // ── weak pen attraction ───────────────────────────────────────────────
-    steering = steering.add(pen.center().sub(s.pos).normalize().scale(W_PEN))
+    // ── pen attraction (outside) / retention (inside) ────────────────────
+    if (pen.contains(s.pos)) {
+      // Inside: repel from all four walls so sheep stay put even when spooked.
+      // Peak is 3× max flee force so it dominates regardless of fear level.
+      const PEN_MARGIN = 22 * scale
+      const PEN_PEAK   = 240 * scale
+      const dLeft   = s.pos.x - pen.x
+      const dRight  = (pen.x + pen.w) - s.pos.x
+      const dTop    = s.pos.y - pen.y
+      const dBottom = (pen.y + pen.h) - s.pos.y
+      steering = steering.add(new Vec2(
+        wallPush(dLeft, PEN_MARGIN, PEN_PEAK) - wallPush(dRight, PEN_MARGIN, PEN_PEAK),
+        wallPush(dTop,  PEN_MARGIN, PEN_PEAK) - wallPush(dBottom, PEN_MARGIN, PEN_PEAK),
+      ))
+    } else {
+      // Outside: gentle pull toward pen center to encourage herding.
+      steering = steering.add(pen.center().sub(s.pos).normalize().scale(W_PEN))
+    }
 
     // ── apply ─────────────────────────────────────────────────────────────
     const panicMult = 1 + s.fearLevel * 0.8