@livlive/game 0.0.0-stage → 1.0.0
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 +9 -2
- package/index.d.ts +252 -0
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @livlive/game
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The types of the livlive game contract: what a stage's rules may know of the engine — the shapes that cross the box, the functions the
|
|
4
|
+
box calls (`Game<S>`), and `keeper.json`'s declaration (`GameManifest`).
|
|
5
|
+
|
|
6
|
+
A game takes it with `import type` only (`import type { Game } from "@livlive/game";`). The package carries no code: a value import is
|
|
7
|
+
refused when the rules are built.
|
|
8
|
+
|
|
9
|
+
`index.d.ts` is generated from the engine's contract by livlive-backstage's `gen:engine` — never edit it here. The engine reference
|
|
10
|
+
(`../reference/engine.json`) says when each function is called and what goes in and out.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// Generated by livlive-backstage gen:engine from app/src/contracts/game — do not edit.
|
|
2
|
+
/** the contract's version: the engine opens a game only at a version it knows */
|
|
3
|
+
export declare const GAME_PROTOCOL: 1;
|
|
4
|
+
/** a setting's value — a number, a yes/no or words */
|
|
5
|
+
export type SettingValue = number | boolean | string;
|
|
6
|
+
/** ★a setting a game declares★ (spec §4 — owner 2026-11-03 「ステージのページで設定出来るようにしてほしいです。…固定の画面ではダメです。」
|
|
7
|
+
「デフォルト設定という形です。」): what the stage page asks (`words`, the game's own, ≤ 40 characters), its kind and bounds, and the value it
|
|
8
|
+
has until a stage sets one (`default`, within its own bounds). integer: min ≤ default ≤ max on `step` (1 if absent) from min; number: within
|
|
9
|
+
min…max; choice: one of its options' values (two or more); text: at most `max` characters (1–200) */
|
|
10
|
+
export type SettingSpec = {
|
|
11
|
+
words: string;
|
|
12
|
+
} & ({
|
|
13
|
+
type: "integer";
|
|
14
|
+
default: number;
|
|
15
|
+
min: number;
|
|
16
|
+
max: number;
|
|
17
|
+
step?: number;
|
|
18
|
+
} | {
|
|
19
|
+
type: "number";
|
|
20
|
+
default: number;
|
|
21
|
+
min: number;
|
|
22
|
+
max: number;
|
|
23
|
+
} | {
|
|
24
|
+
type: "boolean";
|
|
25
|
+
default: boolean;
|
|
26
|
+
} | {
|
|
27
|
+
type: "choice";
|
|
28
|
+
default: string;
|
|
29
|
+
options: {
|
|
30
|
+
value: string;
|
|
31
|
+
words: string;
|
|
32
|
+
}[];
|
|
33
|
+
} | {
|
|
34
|
+
type: "text";
|
|
35
|
+
default: string;
|
|
36
|
+
max: number;
|
|
37
|
+
});
|
|
38
|
+
/** the stage as a game sees it: its id, its seats and its things with their words, and its settings — every name the game declares with
|
|
39
|
+
the stage's value, the default where the stage set none */
|
|
40
|
+
export type StageView = {
|
|
41
|
+
id: string;
|
|
42
|
+
seats: {
|
|
43
|
+
id: string;
|
|
44
|
+
}[];
|
|
45
|
+
objects: {
|
|
46
|
+
id: string;
|
|
47
|
+
name: string;
|
|
48
|
+
about: string;
|
|
49
|
+
can: string[];
|
|
50
|
+
}[];
|
|
51
|
+
settings: Readonly<Record<string, SettingValue>>;
|
|
52
|
+
};
|
|
53
|
+
/** the show's moment as a game is given it (ms) */
|
|
54
|
+
export type GameTime = {
|
|
55
|
+
t: number;
|
|
56
|
+
tick: number;
|
|
57
|
+
dt: number;
|
|
58
|
+
};
|
|
59
|
+
/** an event the stage declares, asked for at its door this tick, and who asked */
|
|
60
|
+
export type GameTrigger = {
|
|
61
|
+
event: string;
|
|
62
|
+
by?: string;
|
|
63
|
+
};
|
|
64
|
+
/** a hand of hers this tick: a done that says how the things she touched stand now (by thing id) */
|
|
65
|
+
export type GameHand = {
|
|
66
|
+
t: number;
|
|
67
|
+
who: string;
|
|
68
|
+
changed: Record<string, Record<string, unknown>>;
|
|
69
|
+
};
|
|
70
|
+
/** an act of hers that finished well this tick — a game reads the ones it owns (its moves) */
|
|
71
|
+
export type GamePlayed = {
|
|
72
|
+
t: number;
|
|
73
|
+
who: string;
|
|
74
|
+
type: string;
|
|
75
|
+
target: string | null;
|
|
76
|
+
mode: string | null;
|
|
77
|
+
direction: string | null;
|
|
78
|
+
};
|
|
79
|
+
/** what reached the stage since the game was last woken */
|
|
80
|
+
export type GameInput = {
|
|
81
|
+
time: GameTime;
|
|
82
|
+
triggers: readonly GameTrigger[];
|
|
83
|
+
hands: readonly GameHand[];
|
|
84
|
+
acts: readonly GamePlayed[];
|
|
85
|
+
/** the players, in seat order — every performer, or the first `players.max` when keeper.json says how many play (below `players.min` the
|
|
86
|
+
game is not opened at all); `hands`, `acts` and `seats` are theirs alone */ cast: readonly string[];
|
|
87
|
+
/** where each player sits now — a seat id; null standing */ seats: Readonly<Record<string, string | null>>;
|
|
88
|
+
};
|
|
89
|
+
/** what a step came to — the engine's own keepers': what happened, how the room's things stand, its news, its events. A stage's own game answers
|
|
90
|
+
it empty: the box keeps its `state` and reads nothing else of the answer, so a game cannot move the room's things (GAME_CONTRACT's `step`) */
|
|
91
|
+
export type GameOutcome = {
|
|
92
|
+
happenings: readonly unknown[];
|
|
93
|
+
things: Readonly<Record<string, unknown>>;
|
|
94
|
+
news: unknown;
|
|
95
|
+
events: unknown;
|
|
96
|
+
};
|
|
97
|
+
/** an act a character's menu offers, as `check` is asked about it */
|
|
98
|
+
export type CheckAsk = {
|
|
99
|
+
type: string;
|
|
100
|
+
target: string | null;
|
|
101
|
+
mode?: string | null;
|
|
102
|
+
direction?: string | null;
|
|
103
|
+
who?: string;
|
|
104
|
+
};
|
|
105
|
+
/** ★a row a game offers her★ — what it asks, in her words, how long it takes (s); `at` the seats she must sit in for it (absent:
|
|
106
|
+
anywhere); `due` it is hers to do now — her menu then holds only the due rows */
|
|
107
|
+
export type OfferRow = {
|
|
108
|
+
id: string;
|
|
109
|
+
act: {
|
|
110
|
+
type: string;
|
|
111
|
+
target?: string;
|
|
112
|
+
mode?: string;
|
|
113
|
+
};
|
|
114
|
+
words: string;
|
|
115
|
+
s: number;
|
|
116
|
+
at?: readonly string[];
|
|
117
|
+
due?: boolean;
|
|
118
|
+
};
|
|
119
|
+
/** a card a tile may show — its rank (1–5 characters) and suit, or a joker (suit null) */
|
|
120
|
+
export type BoardCard = {
|
|
121
|
+
rank: string;
|
|
122
|
+
suit: "♠" | "♥" | "♦" | "♣" | null;
|
|
123
|
+
};
|
|
124
|
+
/** a board's tile: its words, marked, the card it shows, and the one just moved */
|
|
125
|
+
export type BoardTile = {
|
|
126
|
+
text: string;
|
|
127
|
+
mark?: boolean;
|
|
128
|
+
card?: BoardCard;
|
|
129
|
+
fresh?: boolean;
|
|
130
|
+
};
|
|
131
|
+
/** a row's gauge and its number: `value` (finite, ≥ 0) of `of` (finite, > 0) — any game's own measure: a stack, a score, a life */
|
|
132
|
+
export type BoardMeter = {
|
|
133
|
+
value: number;
|
|
134
|
+
of: number;
|
|
135
|
+
};
|
|
136
|
+
/** a short fact a row shows (a label and a value, ≤ 8 characters each — one code point a character) */
|
|
137
|
+
export type BoardFact = {
|
|
138
|
+
label: string;
|
|
139
|
+
value: string;
|
|
140
|
+
};
|
|
141
|
+
/** the board's middle slot: a label, a big value (≤ 8 characters each) and a line under them (≤ 24) */
|
|
142
|
+
export type BoardCenter = {
|
|
143
|
+
label: string;
|
|
144
|
+
value: string;
|
|
145
|
+
line?: string;
|
|
146
|
+
};
|
|
147
|
+
/** a row's last move, which the board plays once (its `key` new for each move, ≤ 32 characters): push (a bet, a raise), answer (a call, a
|
|
148
|
+
check), fold, draw (cards changed); its words (≤ 8 characters) and what it put (finite, ≥ 0) */
|
|
149
|
+
export type BoardAct = {
|
|
150
|
+
key: string;
|
|
151
|
+
kind: "push" | "answer" | "fold" | "draw";
|
|
152
|
+
words: string;
|
|
153
|
+
amount?: number;
|
|
154
|
+
};
|
|
155
|
+
/** what just happened to the board as a whole, played once a show (its `key` new for each moment, ≤ 32 characters): the cards dealt, the hands
|
|
156
|
+
shown, a round won, the game over — `who` the row it is about (one of the view's rows, or the view is wrong and the game stops). A `win`
|
|
157
|
+
or an `end` with a `who` is a win: the camera goes to that player and back (when they are in the picture) and every character of the cast
|
|
158
|
+
is told of it, the winner as their own win (a winner who is none of the cast is told to nobody); an `end` with none is a draw — no camera,
|
|
159
|
+
no telling. `deal` and `reveal` never move the camera. `end` is the game over: keep it in every later view — a view without it brings the
|
|
160
|
+
table back */
|
|
161
|
+
export type BoardMoment = {
|
|
162
|
+
key: string;
|
|
163
|
+
kind: "deal" | "reveal" | "win" | "end";
|
|
164
|
+
who?: string;
|
|
165
|
+
};
|
|
166
|
+
/** ★what the viewers see of a game★ (the board over the picture): rows of tiles, one row a player (`who`), the one to move marked, a note;
|
|
167
|
+
a row may say one short line under the player's name (`sub`, ≤ 24 characters — any game's own words: a score, a stack, a role), a gauge
|
|
168
|
+
(`meter`) and up to four short facts (`facts`); the view may say its middle slot (`center`) — every one of them optional. Three or four
|
|
169
|
+
rows are drawn as a table seen from above, each player's face in a circle at their side, while the game is on (its view does not
|
|
170
|
+
say `end`) and no win holds the camera: the table is then the whole picture — the room and the bodies are not shown. A win's hold, the
|
|
171
|
+
game's end and any other number of rows draw strips instead, over the room's picture with the bodies in it (livlive's standard look;
|
|
172
|
+
in app delivery — each character a small picture of its own — no board is drawn). The table draws the tiles, the
|
|
173
|
+
middle slot, the names, `sub` and `won` — not `meter`, `facts`, `act` or `danger`, nor a moment's effects (its sound still plays): keep
|
|
174
|
+
what viewers must read in the tiles, `center` or `sub`. `won` draws the row's WIN mark, on a strip and on the table; a row's `won` turning
|
|
175
|
+
true is a win, as a moment is (BoardMoment) — one win a view (the moment's, else the first such row), every won row still marked. The
|
|
176
|
+
table marks by `won` alone: a win told by a moment alone gets the camera and the telling, but no mark there */
|
|
177
|
+
export type BoardView = {
|
|
178
|
+
title: string;
|
|
179
|
+
rows: {
|
|
180
|
+
who: string;
|
|
181
|
+
turn: boolean;
|
|
182
|
+
tiles: BoardTile[];
|
|
183
|
+
sub?: string;
|
|
184
|
+
meter?: BoardMeter;
|
|
185
|
+
facts?: BoardFact[];
|
|
186
|
+
act?: BoardAct;
|
|
187
|
+
danger?: boolean;
|
|
188
|
+
won?: boolean;
|
|
189
|
+
}[];
|
|
190
|
+
note: string;
|
|
191
|
+
center?: BoardCenter;
|
|
192
|
+
moment?: BoardMoment;
|
|
193
|
+
};
|
|
194
|
+
/** when a game asks to be woken by time: once at `at` (the show's ms), or every `every` ms */
|
|
195
|
+
export type Alarm = {
|
|
196
|
+
at: number;
|
|
197
|
+
} | {
|
|
198
|
+
every: number;
|
|
199
|
+
};
|
|
200
|
+
/** how an act a game owns is carried out — `reach`: she walks to the thing and reaches; `here`: where she is — for `ms`; `motion` the
|
|
201
|
+
basic motion it needs */
|
|
202
|
+
export type ActSpec = {
|
|
203
|
+
controller: "reach" | "here";
|
|
204
|
+
ms: number;
|
|
205
|
+
motion: string;
|
|
206
|
+
};
|
|
207
|
+
/** ★how many of a show's performers play a game★ (plan 2026-11-05-four-players-1 Task 4): the fewest and the most, whole numbers,
|
|
208
|
+
1 ≤ min ≤ max ≤ the cast's cap (the engine reference states the number; keeper.json's check holds it) */
|
|
209
|
+
export type GamePlayers = {
|
|
210
|
+
min: number;
|
|
211
|
+
max: number;
|
|
212
|
+
};
|
|
213
|
+
/** keeper.json — what a game declares beside its rules: its id (its questions are named `<id>.<name>`), its version, the acts it owns,
|
|
214
|
+
the questions its `ask` may name, the settings a stage may set and how many play */
|
|
215
|
+
export type GameManifest = {
|
|
216
|
+
id: string;
|
|
217
|
+
version: string;
|
|
218
|
+
acts?: Record<string, ActSpec>;
|
|
219
|
+
questions?: Record<string, {
|
|
220
|
+
instructions: string;
|
|
221
|
+
threshold?: number;
|
|
222
|
+
default?: string;
|
|
223
|
+
}>;
|
|
224
|
+
settings?: Record<string, SettingSpec>;
|
|
225
|
+
/** the keeper protocol it was made for; 1 when absent (a stage made today keeps running — plan 2026-11-04-stage-kit-1 Task 4) */ protocol?: number;
|
|
226
|
+
/** how many play; absent: the game decides in code, and every performer is a player (today's behaviour) */ players?: GamePlayers;
|
|
227
|
+
};
|
|
228
|
+
/** ★the rules' functions, as the box calls them★ — see GAME_CONTRACT for when; `ask` answers a question's short name (keeper.json's) */
|
|
229
|
+
export type Game<S> = {
|
|
230
|
+
reset(stage: StageView, time: GameTime, seed: string): S;
|
|
231
|
+
step(state: S, input: GameInput, stage: StageView): {
|
|
232
|
+
state: S;
|
|
233
|
+
out: GameOutcome;
|
|
234
|
+
};
|
|
235
|
+
check?(type: string, state: S, act: CheckAsk, stage: StageView): string | null;
|
|
236
|
+
alarm?(state: S): Alarm | null;
|
|
237
|
+
offers?(state: S, who: string, stage: StageView): OfferRow[];
|
|
238
|
+
ask?(state: S, who: string, stage: StageView): string | null;
|
|
239
|
+
still?(state: S, who: string, stage: StageView): boolean;
|
|
240
|
+
observe?(state: S, who: string, stage: StageView): string[];
|
|
241
|
+
view?(state: S, stage: StageView): BoardView | null;
|
|
242
|
+
};
|
|
243
|
+
/** ★the contract, in words★ — each function the box calls, when, what goes in and what comes out (the engine reference states it for a
|
|
244
|
+
person's agent; check:world-format holds it to the box's calls). `facts` and `may` are the engine's own keepers' (engineOnly) */
|
|
245
|
+
export declare const GAME_CONTRACT: readonly {
|
|
246
|
+
name: string;
|
|
247
|
+
when: string;
|
|
248
|
+
in: string;
|
|
249
|
+
out: string;
|
|
250
|
+
optional: boolean;
|
|
251
|
+
engineOnly?: true;
|
|
252
|
+
}[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livlive/game",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The livlive game contract's types — import type only",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"exports": { ".": { "types": "./index.d.ts" } },
|
|
8
|
+
"files": ["index.d.ts", "README.md"]
|
|
9
|
+
}
|