fix(runtime/skills): recover from wedged pits with tunnel-out

This commit is contained in:
2026-05-26 12:39:23 +03:00
parent a57625b541
commit 564557450d
5 changed files with 512 additions and 13 deletions
@@ -0,0 +1,71 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { getSkill } from "./index.js";
import { _internal } from "./recovery-tunnel-out.js";
function makePos(x, y, z) {
return {
x, y, z,
offset(dx, dy, dz) { return makePos(x + dx, y + dy, z + dz); },
clone() { return makePos(x, y, z); },
};
}
function makeBlock(name, x, y, z) {
return {
name,
boundingBox: name === "air" ? "empty" : "block",
position: makePos(x, y, z),
};
}
function makeBot(blocks = {}) {
return {
entity: { position: makePos(0, 64, 0) },
blockAt(pos) {
const x = Math.floor(pos.x);
const y = Math.floor(pos.y);
const z = Math.floor(pos.z);
const name = blocks[`${x},${y},${z}`] ?? "stone";
return makeBlock(name, x, y, z);
},
canDigBlock(block) { return block.name !== "bedrock"; },
};
}
test("recovery.tunnel-out is registered", () => {
const skill = getSkill("recovery.tunnel-out");
assert.ok(skill);
assert.equal(skill.preconditions({}).ok, false);
assert.equal(skill.preconditions({ bot: makeBot() }).ok, true);
});
test("tunnel ranking prefers the most-free safe cardinal", () => {
const blocks = {};
// North is already a two-high open tunnel with solid floor.
for (let step = 1; step <= 3; step++) {
blocks[`0,64,${-step}`] = "air";
blocks[`0,65,${-step}`] = "air";
blocks[`0,63,${-step}`] = "dirt";
}
// West is blocked by a player/build-looking block and must be unusable.
blocks["-1,64,0"] = "oak_planks";
const ranked = _internal.rankTunnelDirections(makeBot(blocks), 3);
assert.equal(ranked[0].name, "N");
assert.equal(ranked[0].usable, true);
const west = ranked.find((d) => d.name === "W");
assert.equal(west.usable, false);
assert.deepEqual(west.blockers.map((b) => b.name), ["oak_planks"]);
});
test("safe dig guard allows natural blocks and rejects build/storage blocks", () => {
const bot = makeBot();
assert.equal(_internal.isSafeTunnelDigTarget(bot, makeBlock("dirt", 1, 64, 0)), true);
assert.equal(_internal.isSafeTunnelDigTarget(bot, makeBlock("oak_leaves", 1, 64, 0)), true);
assert.equal(_internal.isSafeTunnelDigTarget(bot, makeBlock("oak_log", 1, 64, 0)), true);
assert.equal(_internal.isSafeTunnelDigTarget(bot, makeBlock("oak_planks", 1, 64, 0)), false);
assert.equal(_internal.isSafeTunnelDigTarget(bot, makeBlock("chest", 1, 64, 0)), false);
assert.equal(_internal.isSafeTunnelDigTarget(bot, makeBlock("bedrock", 1, 64, 0)), false);
});