import { test } from "node:test"; import assert from "node:assert/strict"; import { compile } from "../src/core/loader.js"; import { VerbResolver } from "../src/core/verbs.js"; import { GameWorld } from "../src/core/world.js"; import { readFileSync } from "node:fs"; const example = JSON.parse(readFileSync(new URL("../example/game.json", import.meta.url), "utf8")); function setup() { const c = compile(example); const w = new GameWorld(c); const r = new VerbResolver(c); r.bindWorld(w); return { c, w, r }; } test("exact noun beats tag beats wildcard", () => { const { r } = setup(); const it = r.resolve("look", { kind: "object", id: "post", tags: [] }); assert.equal(it.response, "Sturdy. Smells of rope and regret."); const tagIt = r.resolve("look", { kind: "character", id: "barkeep", tags: ["talker"] }); assert.ok(tagIt.response.includes("rather not be looked at")); }); test("conditions gate matches and fall through to next candidate", () => { const { w, r } = setup(); // give-with-mug: first candidate requires not-gaveMug let it = r.resolve("give", { kind: "character", id: "barkeep", tags: ["talker"] }, "mug"); assert.ok(it.effects.some((e) => e.setFlag === "gaveMug")); w.flags.gaveMug = true; it = r.resolve("give", { kind: "character", id: "barkeep", tags: ["talker"] }, "mug"); assert.equal(it.response, "You already handed it over."); }); test("with-item matching is strict both ways", () => { const { r } = setup(); // give without item: no give-with interaction matches assert.equal(r.resolve("give", { kind: "character", id: "barkeep", tags: [] }, null), null); // give with wrong item: no match assert.equal(r.resolve("give", { kind: "character", id: "barkeep", tags: [] }, "rope"), null); }); test("conditional look on taken mug", () => { const { w, r } = setup(); let it = r.resolve("look", { kind: "object", id: "mug", tags: ["container"] }); assert.ok(it.response.includes("suspicious")); w.give("mug"); it = r.resolve("look", { kind: "object", id: "mug", tags: ["container"] }); assert.ok(it.response.includes("pocket")); }); test("default responses per verb", () => { const { r } = setup(); assert.equal(r.defaultResponse("use", { kind: "object", id: "post" }), "That doesn't seem to work."); assert.equal(r.resolve("nope", { kind: "object", id: "post" }), null); }); test("priority overrides order at equal specificity", () => { const spec = structuredClone(example); spec.interactions.unshift({ verb: "look", noun: "post", response: "HIGH", priority: 100 }); const c = compile(spec); const w = new GameWorld(c); const r = new VerbResolver(c); r.bindWorld(w); const it = r.resolve("look", { kind: "object", id: "post", tags: [] }); assert.equal(it.response, "HIGH"); });