Files
skills/docs/gaming/games/game-server/src/plugins/rules-plugin/rules-plugin.md
2026-05-29 08:20:56 +01:00

3.2 KiB

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

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

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<readonly EvaluationResult[]>
  • evaluateGameStart(sessionId): Promise<readonly EvaluationResult[]>
  • evaluateGameEnd(sessionId): Promise<readonly EvaluationResult[]>
  • evaluate(rules, context): Promise<readonly EvaluationResult[]>
  • 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).