@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.
- package/README.md +47 -57
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -1,69 +1,59 @@
|
|
|
1
1
|
# @table-games-engine/core
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
##
|
|
21
|
+
## Install
|
|
15
22
|
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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
|
-
|
|
25
|
-
if (result.ok) {
|
|
26
|
-
engine.resolveTopFrame();
|
|
27
|
-
}
|
|
39
|
+
## Running the engine
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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.
|
|
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
|
}
|