feat(engine): capture-flags modifier descriptor

This commit is contained in:
Joey Yakimowich-Payne 2026-04-18 22:21:07 -06:00
commit ff8b8d9bb0
No known key found for this signature in database

View file

@ -0,0 +1,103 @@
import { describe, it, expect } from "vitest";
import { Session } from "@paratype/rete";
import { MODIFIER_REGISTRY } from "../registry.js";
import { CaptureFlag } from "../../schema.js";
import "./capture-flags.js";
import { CAPTURE_FLAGS_DESCRIPTOR, hasCaptureFlag } from "./capture-flags.js";
describe("capture-flags descriptor — registry", () => {
it("registers in MODIFIER_REGISTRY under key 'capture-flags'", () => {
expect(MODIFIER_REGISTRY.has("capture-flags")).toBe(true);
expect(MODIFIER_REGISTRY.get("capture-flags")).toBe(CAPTURE_FLAGS_DESCRIPTOR);
});
});
describe("capture-flags descriptor — apply()", () => {
it("seeds CaptureFlags fact on piece entity in session", () => {
const session = new Session();
const pieceId = session.nextId();
session.insert(pieceId, "PieceType", "pawn");
CAPTURE_FLAGS_DESCRIPTOR.apply(session, pieceId, CaptureFlag.CANNOT_BE_CAPTURED);
expect(session.contains(pieceId, "CaptureFlags")).toBe(true);
expect(session.get(pieceId, "CaptureFlags")).toBe(CaptureFlag.CANNOT_BE_CAPTURED);
});
});
describe("capture-flags descriptor — describe()", () => {
it("returns 'no flags' for 0", () => {
expect(CAPTURE_FLAGS_DESCRIPTOR.describe(0)).toBe("no flags");
});
it("describes combined CAN_CAPTURE_OWN | CANNOT_BE_CAPTURED flags", () => {
const combined = CaptureFlag.CAN_CAPTURE_OWN | CaptureFlag.CANNOT_BE_CAPTURED;
expect(CAPTURE_FLAGS_DESCRIPTOR.describe(combined)).toBe("can-capture-own, cannot-be-captured");
});
it("describes all three flags", () => {
const allFlags = CaptureFlag.CAN_CAPTURE_OWN | CaptureFlag.CANNOT_BE_CAPTURED | CaptureFlag.EN_PASSANT;
expect(CAPTURE_FLAGS_DESCRIPTOR.describe(allFlags)).toBe(
"can-capture-own, cannot-be-captured, en-passant",
);
});
it("describes a single flag", () => {
expect(CAPTURE_FLAGS_DESCRIPTOR.describe(CaptureFlag.EN_PASSANT)).toBe("en-passant");
});
});
describe("capture-flags descriptor — hasCaptureFlag()", () => {
it("returns true when the flag is set", () => {
const session = new Session();
const pieceId = session.nextId();
CAPTURE_FLAGS_DESCRIPTOR.apply(
session,
pieceId,
CaptureFlag.CAN_CAPTURE_OWN | CaptureFlag.CANNOT_BE_CAPTURED,
);
expect(hasCaptureFlag(session, pieceId, CaptureFlag.CANNOT_BE_CAPTURED)).toBe(true);
expect(hasCaptureFlag(session, pieceId, CaptureFlag.CAN_CAPTURE_OWN)).toBe(true);
});
it("returns false when the flag is not set", () => {
const session = new Session();
const pieceId = session.nextId();
CAPTURE_FLAGS_DESCRIPTOR.apply(session, pieceId, CaptureFlag.CAN_CAPTURE_OWN);
expect(hasCaptureFlag(session, pieceId, CaptureFlag.EN_PASSANT)).toBe(false);
});
it("returns false when CaptureFlags fact is absent", () => {
const session = new Session();
const pieceId = session.nextId();
expect(hasCaptureFlag(session, pieceId, CaptureFlag.CANNOT_BE_CAPTURED)).toBe(false);
});
});
describe("capture-flags descriptor — valueSchema", () => {
const schema = CAPTURE_FLAGS_DESCRIPTOR.valueSchema;
it("accepts 0 (no flags)", () => {
expect(() => schema.parse(0)).not.toThrow();
});
it("accepts MAX_FLAGS (all flags OR'd together = 7)", () => {
const maxFlags = CaptureFlag.CAN_CAPTURE_OWN | CaptureFlag.CANNOT_BE_CAPTURED | CaptureFlag.EN_PASSANT;
expect(() => schema.parse(maxFlags)).not.toThrow();
});
it("rejects -1 (below min)", () => {
expect(() => schema.parse(-1)).toThrow();
});
it("rejects 8 (above MAX_FLAGS = 7)", () => {
expect(() => schema.parse(8)).toThrow();
});
it("rejects non-integer values", () => {
expect(() => schema.parse(1.5)).toThrow();
});
});