# RulesPlugin _(no submodules)_ ## Purpose `RulesPlugin` integrates `@suaveplan/rules` with the game-server engine. It maintains three rule sets — move validation, game start, and game end — and exposes `evaluateMove`, `evaluateGameStart`, and `evaluateGameEnd` so the engine can apply declarative checks without leaking the underlying engine abstraction into game logic. The plugin's role is integration glue: it does not interpret rules itself, it just hands them to the injected `RuleEngine` and records the pass/fail outcomes in a rolling history. Callers compose rule sets at construction time or replace them at runtime via `setMoveRules` / `addMoveRules`. ## Features - Three named rule slots (move / start / end) plus an ad-hoc `evaluate` helper. - Empty rule sets are treated as a "passed" no-op (recorded in history). - Rolling evaluation history with a configurable cap (default 1 000). - Mutable move rule set: append (`addMoveRules`) or replace (`setMoveRules`) at runtime. - Zod-validated `historyCap` option. - Lifecycle-safe: clears rule sets and history on uninstall. ## Usage: Basic ```ts import { RuleEngine } from "@suaveplan/rules"; import { RulesPlugin } from "@suaveplan/game-server/plugins/rules-plugin"; const engine = new RuleEngine(); const plugin = new RulesPlugin({ engine }); await plugin.evaluateMove("p1", { kind: "attack" }, { hp: 10 }); ``` ## Usage: Advanced ```ts import { RuleEngine, type Rule } from "@suaveplan/rules"; import { RulesPlugin } from "@suaveplan/game-server/plugins/rules-plugin"; const engine = new RuleEngine(); const damageCap: Rule = /* ... discriminated rule ... */ ({} as Rule); const plugin = new RulesPlugin({ engine, moveValidationRules: [damageCap], historyCap: 50, clock: () => 1_700_000_000_000, }); plugin.addMoveRules(/* another rule */); const results = await plugin.evaluateMove("p1", { dmg: 5 }, { hp: 10 }); const history = plugin.getHistory(); ``` ## API Reference - `class RulesPlugin extends BasePlugin` - `constructor(options: RulesPluginOptions)` - `evaluateMove(playerId, move, gameState): Promise` - `evaluateGameStart(sessionId): Promise` - `evaluateGameEnd(sessionId): Promise` - `evaluate(rules, context): Promise` - `addMoveRules(...rules): void` - `setMoveRules(rules): void` - `getHistory(): readonly EvaluationHistoryEntry[]` - `clearHistory(): void` ## Implementation Notes - The engine API used here is `evaluateAll(rules, context)`, which returns an array of `EvaluationResult` (one per rule). The plugin records a single history entry per evaluation, with `passed` reflecting the conjunction over the result set. - `evaluate(rules, ctx)` rejects non-object contexts with `GAME_SERVER.INVALID_RULE_CONTEXT` so callers cannot silently pass primitives through to the rule engine. - Empty rule sets short-circuit before hitting the engine — they record a `passed: true, resultCount: 0` history entry so callers still see the checkpoint was reached. - The history is bounded; once the length exceeds `historyCap`, the oldest entries are dropped via `slice(-historyCap)`.