@table-games-engine/core
v0.1.3
Published
Deterministic turn-based game engine: state, actions, priority, seeded RNG, player views.
Maintainers
Readme
@table-games-engine/core
The deterministic, in-process engine for turn-based table games: state, actions, priority, triggers, seeded randomness and per-player views. Game logic is written against its types.
Most game authors don't install this directly: it comes with @table-games-engine/game-kit, which scaffolds a game that already depends on it. Games import types and helpers from it:
import { ok, reject, resolved, type ActionHandler, type GamePlugin } from '@table-games-engine/core';
const fireBolt: ActionHandler = (ctx, frame) => {
const actor = 'actor' in frame ? frame.actor : frame.controller;
const target = ctx.getActivePlayers().find((p) => p !== actor);
if (!target) return reject('rule-violation'); // illegal move: nothing changes
return resolved([
{ domain: 'player', operation: { type: 'add-resource', playerId: target, resource: 'life', delta: -2 } },
{ domain: 'turn', operation: { type: 'advance' } }, // end the turn
]);
};Install
npm install @table-games-engine/coreESM only.
What a game provides
A GamePlugin has id, version, manifest, requiredMechanics, setup, actionHandlers, winConditionChecker and legalMoves(state, playerId). legalMoves returns every concrete move the player may submit now, and [] when they do not hold priority or the game is over. Handlers must be pure: return mutations, never modify ctx.state.
Helpers for handlers:
resolved(mutations, events?)- a successful result.reject(reason)- an illegal move ('rule-violation','condition-failed','targets-illegal'); state does not change.ok(value)- genericResultsuccess constructor (err(error)is its failure counterpart).setupreturnsok({ state }).
Running the engine
Use these to run matches yourself (in tests, simulators, servers):
import { setupMatch, driveAction, rulesFromPlugin, computePlayerView } from '@table-games-engine/core';setupMatchanddriveActionstart a match from aGamePluginand apply one player input.createEngine(manifest, initialState, handlers)is the lower-level facade (applyAction,resolveTopFrame,getState).computePlayerView(state, manifest, playerId)returns what one player may see.- Randomness:
seedRng,nextRandom,randomInt,randomPick,randomShuffle. Inside handlers usectx.random*. - Lower-level building blocks are also exported (
applyMutation,applyTransition,validateAction,resolveTopFrame,scanTriggers,advanceTurn,advancePhase,checkWin, priority helpers).
Determinism
The same initial state, manifest, handlers and inputs always produce the same final state. The engine never calls Math.random or Date.now; all randomness flows through MatchState.rng (xorshift32).
Licence
Apache-2.0
