fix(runtime): unstick wander loop + chop radius + explore.far skill
Follow-up to the iteration-1 fixes. Live smoke on play.xmatic.team revealed the bot was spawning into a tree-less plain (no log within 32 blocks of spawn), looping wander→gather→no_target→wander forever inside a 16-block box. - runtime/actions.js: chopNearestTree search radius 32 → 64 (still no trees on this spawn, but a normal biome will be served well by it). wander now has a blind-walk fallback when pathfinder times out (look+forward+jump for 3 s) so the bot at least unsticks from leaves or pillars. Pathfinder timeout reduced 30 s → 15 s. - runtime/skills/explore-far.js: new explore.far skill — walks ~48 blocks in a quadrant (NE/SE/SW/NW, rotating per call) so successive hints actually circle the spawn instead of bouncing in place. Blind walk fallback included. - runtime/reflex.js: when the scheduler is told to wander twice in a row by gather.* recover hints, it now dispatches explore.far instead so the bot actually leaves the patch it's stuck in. Resets the consecutiveWanderHints counter on any success. - runtime/reflex.js (sleep): no longer dispatches when the bot has neither a bed in inventory NOR a known shelter/base location — saved one dispatch + 5-min cooldown per restart at night. - runtime/reflex.js (eat): inventory check + lastEatAt always updated fix the eat-spam loop observed live (every tick fired "eat" → "no food in inventory" → again). - runtime/skills/chop-logs.js: recognise "no log within ..." as no_target so the recover hint switches the bot to wander/explore. npm test 124/124. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+20
-1
@@ -66,12 +66,16 @@ test("defend wins over curriculum when hostile in melee", () => {
|
||||
assert.match(dispatches[0].label, /attack zombie/);
|
||||
});
|
||||
|
||||
test("eat wins over curriculum when food low and bot has food", () => {
|
||||
test("eat wins over curriculum when food low and bot has food in inventory", () => {
|
||||
const { ctx, dispatches } = makeCtx({
|
||||
snapshot: {
|
||||
connected: true,
|
||||
health: 20,
|
||||
food: 10,
|
||||
// 2026-05-26: eat reflex now requires actual food in inventory
|
||||
// to avoid the eat-spam loop that fired every tick on empty
|
||||
// inventory.
|
||||
inventory: { bread: 1 },
|
||||
curriculum: { plan: { skillId: "gather.logs" } },
|
||||
},
|
||||
});
|
||||
@@ -80,6 +84,21 @@ test("eat wins over curriculum when food low and bot has food", () => {
|
||||
assert.equal(dispatches[0].label, "eat");
|
||||
});
|
||||
|
||||
test("eat reflex does NOT dispatch when no food in inventory (no spam)", () => {
|
||||
const { ctx, dispatches } = makeCtx({
|
||||
snapshot: {
|
||||
connected: true,
|
||||
health: 20,
|
||||
food: 10,
|
||||
inventory: { dirt: 1 },
|
||||
curriculum: { plan: { skillId: "gather.logs" } },
|
||||
},
|
||||
});
|
||||
const out = runTick(ctx);
|
||||
// Falls through to curriculum.
|
||||
assert.equal(out.reflex, "curriculum");
|
||||
});
|
||||
|
||||
test("curriculum dispatches suggested skill by id", () => {
|
||||
const { ctx, dispatches } = makeCtx({
|
||||
snapshot: {
|
||||
|
||||
Reference in New Issue
Block a user