@table-games-engine/core 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +47 -57
  2. package/package.json +12 -2
package/README.md CHANGED
@@ -1,69 +1,59 @@
1
1
  # @table-games-engine/core
2
2
 
3
- Pure, in-process implementation of the action-stack game engine described in
4
- [`docs/normative/`](../../docs/normative/).
3
+ 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.
5
4
 
6
- ## Run
5
+ Most game authors don't install this directly: it comes with [`@table-games-engine/game-kit`](https://www.npmjs.com/package/@table-games-engine/game-kit), which scaffolds a game that already depends on it. Games import types and helpers from it:
7
6
 
8
- ```bash
9
- npm install
10
- npm test --workspace=@table-games-engine/core
11
- npx tsc -p packages/core --noEmit
7
+ ```ts
8
+ import { ok, reject, resolved, type ActionHandler, type GamePlugin } from '@table-games-engine/core';
9
+
10
+ const fireBolt: ActionHandler = (ctx, frame) => {
11
+ const actor = 'actor' in frame ? frame.actor : frame.controller;
12
+ const target = ctx.getActivePlayers().find((p) => p !== actor);
13
+ if (!target) return reject('rule-violation'); // illegal move: nothing changes
14
+ return resolved([
15
+ { domain: 'player', operation: { type: 'add-resource', playerId: target, resource: 'life', delta: -2 } },
16
+ { domain: 'turn', operation: { type: 'advance' } }, // end the turn
17
+ ]);
18
+ };
12
19
  ```
13
20
 
14
- ## API entry point
21
+ ## Install
15
22
 
16
- ```ts
17
- import {
18
- createEngine,
19
- computePlayerView,
20
- } from '@table-games-engine/core';
23
+ ```sh
24
+ npm install @table-games-engine/core
25
+ ```
26
+
27
+ ESM only.
28
+
29
+ ## What a game provides
30
+
31
+ 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`.
32
+
33
+ Helpers for handlers:
21
34
 
22
- const engine = createEngine(manifest, initialState, handlers);
35
+ - `resolved(mutations, events?)` - a successful result.
36
+ - `reject(reason)` - an illegal move (`'rule-violation'`, `'condition-failed'`, `'targets-illegal'`); state does not change.
37
+ - `ok(value)` - generic `Result` success constructor (`err(error)` is its failure counterpart). `setup` returns `ok({ state })`.
23
38
 
24
- const result = engine.applyAction(playerInput);
25
- if (result.ok) {
26
- engine.resolveTopFrame();
27
- }
39
+ ## Running the engine
28
40
 
29
- const state = engine.getState();
30
- const viewForP1 = computePlayerView(state, manifest, p1Id);
41
+ Use these to run matches yourself (in tests, simulators, servers):
42
+
43
+ ```ts
44
+ import { setupMatch, driveAction, rulesFromPlugin, computePlayerView } from '@table-games-engine/core';
31
45
  ```
32
46
 
33
- See [`__tests__/mini-duel.test.ts`](./__tests__/mini-duel.test.ts) for a full
34
- end-to-end example.
35
-
36
- ## Determinism guarantees
37
-
38
- Same `(initialState, manifest, handlers, inputs[])` always produces the same
39
- final state. The engine never calls `Math.random` or `Date.now`; all
40
- randomness flows through `MatchState.rng` (xorshift32 PRNG). All IDs
41
- (transition, frame, trigger) derive from `state.version` plus caller-supplied
42
- input (clientId, event id) — no hidden module-level state.
43
-
44
- ## Module map
45
-
46
- | File | Purpose |
47
- |---|---|
48
- | `src/types/` | Type definitions (the public API contract) |
49
- | `src/engine/rng.ts` | Seeded xorshift32 PRNG |
50
- | `src/engine/reducer.ts` | Pure `applyMutation` over 8 mutation domains |
51
- | `src/engine/transition.ts` | Compose mutations + bump version + log events |
52
- | `src/engine/stack.ts` | Stack helpers (peek, find, depth) |
53
- | `src/engine/priority.ts` | Priority pass-order operations |
54
- | `src/engine/window.ts` | Compute legal `ActionWindow` from phase + stack |
55
- | `src/engine/context.ts` | `GameEngineContext` — the API game logic sees |
56
- | `src/engine/validate.ts` | Validation pipeline (priority → window → speed) |
57
- | `src/engine/frames.ts` | `StackFrame` builder (deterministic ids) |
58
- | `src/engine/resolve.ts` | Top-of-stack resolver, dispatch to handlers |
59
- | `src/engine/triggers.ts` | Scan triggers, APNAP-order |
60
- | `src/engine/lifecycle.ts` | Advance turn / phase, win check |
61
- | `src/engine/operations.ts` | `createEngine` facade |
62
- | `src/engine/views.ts` | Per-player view filtering |
63
-
64
- ## Status
65
-
66
- M1 — all engine modules implemented and unit-tested. 95 tests across 15 files.
67
-
68
- Out of scope: networking, persistence, client SDK, reference games. See
69
- [`docs/ROADMAP.md`](../../docs/ROADMAP.md).
47
+ - `setupMatch` and `driveAction` start a match from a `GamePlugin` and apply one player input.
48
+ - `createEngine(manifest, initialState, handlers)` is the lower-level facade (`applyAction`, `resolveTopFrame`, `getState`).
49
+ - `computePlayerView(state, manifest, playerId)` returns what one player may see.
50
+ - Randomness: `seedRng`, `nextRandom`, `randomInt`, `randomPick`, `randomShuffle`. Inside handlers use `ctx.random*`.
51
+ - Lower-level building blocks are also exported (`applyMutation`, `applyTransition`, `validateAction`, `resolveTopFrame`, `scanTriggers`, `advanceTurn`, `advancePhase`, `checkWin`, priority helpers).
52
+
53
+ ## Determinism
54
+
55
+ 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).
56
+
57
+ ## Licence
58
+
59
+ Apache-2.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@table-games-engine/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -25,5 +25,15 @@
25
25
  "typescript": "^5.4.0",
26
26
  "vitest": "^2.0.0"
27
27
  },
28
- "license": "Apache-2.0"
28
+ "license": "Apache-2.0",
29
+ "description": "Deterministic turn-based game engine: state, actions, priority, seeded RNG, player views.",
30
+ "keywords": [
31
+ "table-games",
32
+ "turn-based",
33
+ "multiplayer",
34
+ "game-engine",
35
+ "nakama",
36
+ "boardgame"
37
+ ],
38
+ "homepage": "https://www.npmjs.com/package/@table-games-engine/core"
29
39
  }