@kradle/challenges-sdk 0.10.0 → 0.12.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +47 -1
  2. package/LLM_README.md +235 -2333
  3. package/README.md +150 -570
  4. package/dist/index.d.ts +1 -4
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -6
  7. package/dist/index.js.map +1 -1
  8. package/dist/runtime/examples/capture-the-flag.d.ts +33 -0
  9. package/dist/runtime/examples/capture-the-flag.d.ts.map +1 -0
  10. package/dist/runtime/examples/capture-the-flag.js +79 -0
  11. package/dist/runtime/examples/capture-the-flag.js.map +1 -0
  12. package/dist/runtime/examples/climb.d.ts +34 -0
  13. package/dist/runtime/examples/climb.d.ts.map +1 -0
  14. package/dist/runtime/examples/climb.js +54 -0
  15. package/dist/runtime/examples/climb.js.map +1 -0
  16. package/dist/runtime/examples/four-bridges.d.ts +107 -0
  17. package/dist/runtime/examples/four-bridges.d.ts.map +1 -0
  18. package/dist/runtime/examples/four-bridges.js +294 -0
  19. package/dist/runtime/examples/four-bridges.js.map +1 -0
  20. package/dist/runtime/examples/herding.d.ts +59 -0
  21. package/dist/runtime/examples/herding.d.ts.map +1 -0
  22. package/dist/runtime/examples/herding.js +181 -0
  23. package/dist/runtime/examples/herding.js.map +1 -0
  24. package/dist/runtime/examples/skywars.d.ts +116 -0
  25. package/dist/runtime/examples/skywars.d.ts.map +1 -0
  26. package/dist/runtime/examples/skywars.js +253 -0
  27. package/dist/runtime/examples/skywars.js.map +1 -0
  28. package/dist/runtime/sandbox-registry.d.ts +7 -0
  29. package/dist/runtime/sandbox-registry.d.ts.map +1 -0
  30. package/dist/runtime/sandbox-registry.js +16 -0
  31. package/dist/runtime/sandbox-registry.js.map +1 -0
  32. package/dist/runtime/sandbox.d.ts +29 -0
  33. package/dist/runtime/sandbox.d.ts.map +1 -0
  34. package/dist/runtime/sandbox.js +70 -0
  35. package/dist/runtime/sandbox.js.map +1 -0
  36. package/dist/runtime/sdk.d.ts +1038 -0
  37. package/dist/runtime/sdk.d.ts.map +1 -0
  38. package/dist/runtime/sdk.js +1271 -0
  39. package/dist/runtime/sdk.js.map +1 -0
  40. package/dist/runtime/world.d.ts +141 -0
  41. package/dist/runtime/world.d.ts.map +1 -0
  42. package/dist/runtime/world.js +344 -0
  43. package/dist/runtime/world.js.map +1 -0
  44. package/dist/test/harness.d.ts +176 -0
  45. package/dist/test/harness.d.ts.map +1 -0
  46. package/dist/test/harness.js +441 -0
  47. package/dist/test/harness.js.map +1 -0
  48. package/dist/test/helpers.d.ts +7 -0
  49. package/dist/test/helpers.d.ts.map +1 -0
  50. package/dist/test/helpers.js +12 -0
  51. package/dist/test/helpers.js.map +1 -0
  52. package/dist/test/index.d.ts +3 -0
  53. package/dist/test/index.d.ts.map +1 -0
  54. package/dist/test/index.js +20 -0
  55. package/dist/test/index.js.map +1 -0
  56. package/package.json +69 -40
  57. package/dist/actions.d.ts +0 -901
  58. package/dist/actions.d.ts.map +0 -1
  59. package/dist/actions.js +0 -1155
  60. package/dist/actions.js.map +0 -1
  61. package/dist/api_utils.d.ts +0 -25
  62. package/dist/api_utils.d.ts.map +0 -1
  63. package/dist/api_utils.js +0 -48
  64. package/dist/api_utils.js.map +0 -1
  65. package/dist/challenge.d.ts +0 -58
  66. package/dist/challenge.d.ts.map +0 -1
  67. package/dist/challenge.js +0 -582
  68. package/dist/challenge.js.map +0 -1
  69. package/dist/commands.d.ts +0 -57
  70. package/dist/commands.d.ts.map +0 -1
  71. package/dist/commands.js +0 -200
  72. package/dist/commands.js.map +0 -1
  73. package/dist/constants.d.ts +0 -78
  74. package/dist/constants.d.ts.map +0 -1
  75. package/dist/constants.js +0 -109
  76. package/dist/constants.js.map +0 -1
  77. package/dist/testmode.d.ts +0 -3
  78. package/dist/testmode.d.ts.map +0 -1
  79. package/dist/testmode.js +0 -19
  80. package/dist/testmode.js.map +0 -1
  81. package/dist/types.d.ts +0 -195
  82. package/dist/types.d.ts.map +0 -1
  83. package/dist/types.js +0 -38
  84. package/dist/types.js.map +0 -1
  85. package/dist/utils.d.ts +0 -17
  86. package/dist/utils.d.ts.map +0 -1
  87. package/dist/utils.js +0 -22
  88. package/dist/utils.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"world.js","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,176 @@
1
+ import { type Action, type GameMode, type AnyChallenge, type Block, type Box, type Capability, type Duration, type Effect, type EntityType, type Event, type Json, type Marker, type PlayerSample, type Vec3 } from "../runtime/sdk.js";
2
+ /** The state type of a challenge, as `init()` returns it. */
3
+ export type StateOf<Ch extends AnyChallenge> = ReturnType<Ch["init"]>;
4
+ /** JSON with sorted keys, so key order never counts as a difference. */
5
+ export declare const canonical: (v: unknown) => string;
6
+ /**
7
+ * The challenge a test runs against. By default the challenge as imported, in
8
+ * this process: fast, and the rules are the source. When the environment names
9
+ * a built bundle (`KRADLE_CHALLENGE_BUNDLE=<path to kradle-runtime/challenge.js>`,
10
+ * which `kradle challenge test` sets), the bundle is loaded inside the arena's
11
+ * SES sandbox instead: no clock, no random, no timers, and every call gets a
12
+ * fresh compartment. The bundle must be the same challenge as the import.
13
+ * Async because `ses` loads as an ES module: `const c = await sandboxed(source)`.
14
+ */
15
+ export declare function sandboxed<Ch extends AnyChallenge>(challenge: Ch): Promise<Ch>;
16
+ /** A roster entry: the role, or the role with the player's position and sample fields before the first tick. */
17
+ export type RosterEntry = string | ({
18
+ role: string;
19
+ at?: Vec3;
20
+ } & Partial<Omit<PlayerSample, "name" | "participant" | "pos">>);
21
+ export declare class Game<Ch extends AnyChallenge> {
22
+ readonly challenge: Ch;
23
+ state: StateOf<Ch>;
24
+ log: Event[];
25
+ actions: Action[];
26
+ last: Action[];
27
+ /** The harness's tick step, a test setting: server ticks arrive in steps of 4 here (the arena sends every 2 ticks by default). */
28
+ step: number;
29
+ private attempts;
30
+ /** The state this game started from: `init()`, or the checkpoint of `resume`. `replay` starts here. */
31
+ private readonly origin;
32
+ /** Inventory slots the fake players used, per player and item, for this game only. */
33
+ private readonly slots;
34
+ constructor(challenge: Ch, state?: StateOf<Ch>);
35
+ dispatch(event: Event): Action[];
36
+ /** Ticks in steps of `step`, and lands exactly on `serverTick` (the last step is shorter when needed). */
37
+ tickTo(serverTick: number): void;
38
+ tick(n?: number): void;
39
+ /** Advance by a duration: "35s", "2m", or ticks. */
40
+ after(d: Duration | number): void;
41
+ /** Advance until `d` after game start. */
42
+ at(d: Duration | number): void;
43
+ /**
44
+ * run_started, every join, the first tick, and the setup confirmation when the
45
+ * challenge has a setup. A roster entry is a role (`{ alice: "climber" }`), or the
46
+ * role with the player's position and sample fields (`{ alice: { role: "climber",
47
+ * at: { x: 0, y: -60, z: 0 } } }`): the first tick then carries that sample, so
48
+ * `start` and the setup see the position, as they do in the arena. Without `at`
49
+ * the position stays null until the first `moveTo`.
50
+ */
51
+ begin(seed: number, participants: Record<string, RosterEntry>, opts?: {
52
+ params?: Record<string, Json>;
53
+ capabilities?: Capability[];
54
+ setupOk?: boolean;
55
+ locations?: Record<string, Vec3>;
56
+ markers?: Marker[];
57
+ }): this;
58
+ player(name: string): Fake<Ch>;
59
+ custom(name: string, data: Json, player?: string): Action[];
60
+ /** Loads the chunks that cover `box` into the mirror: `block` inside the box, air around it. */
61
+ terrain(box: Box, block: Block, minY?: number, height?: number): Action[];
62
+ /** Blocks changed on the server, by anyone or anything. */
63
+ setBlocks(changes: Array<Vec3 & {
64
+ block: Block;
65
+ by?: string;
66
+ }>): Action[];
67
+ spawnEntity(id: string, type: EntityType, at: Vec3, extra?: Partial<Omit<Extract<Event, {
68
+ type: "entity_spawned";
69
+ }>, "type" | "id" | "entity" | "at">>): Action[];
70
+ /** Entities moved: they arrive with the next tick, so this advances one engine step. */
71
+ moveEntities(moves: Array<{
72
+ id: string;
73
+ pos: Vec3;
74
+ }>): Action[];
75
+ /**
76
+ * One engine tick with several samples at once: participants' positions and
77
+ * fields, and entity moves, all in the same tick, as the engine sends them.
78
+ * A handler that reads another player's position sees this tick for everyone.
79
+ */
80
+ sample(players: Array<{
81
+ name: string;
82
+ } & Partial<Omit<PlayerSample, "name" | "participant">>>, entities?: Array<{
83
+ id: string;
84
+ pos: Vec3;
85
+ }>): Action[];
86
+ removeEntity(id: string, cause?: "died" | "removed", killer?: string): Action[];
87
+ /**
88
+ * The contents of a declared container, as the engine reports them: `items` is the whole
89
+ * content (item to count), laid out one item per slot. `by` names the player who had it open;
90
+ * `initial` marks the first snapshot (no handler fires for it).
91
+ */
92
+ container(at: Vec3, items: Record<string, number>, opts?: {
93
+ by?: string;
94
+ block?: Block;
95
+ initial?: boolean;
96
+ }): Action[];
97
+ /** A game mode change reported by the engine (the `gamemode` event). */
98
+ setGamemode(name: string, gamemode: GameMode): Action[];
99
+ /** A non-participant player's sample (the watcher, a spectator), with the next tick. */
100
+ other(name: string, sample: Omit<PlayerSample, "name" | "participant">): Action[];
101
+ /**
102
+ * The engine's answer to a walk: the last one requested, or the last one for
103
+ * `player` (or with `id`) when several are in flight. A walk that was already
104
+ * answered is skipped.
105
+ */
106
+ walkResult(ok: boolean, detail?: string, which?: {
107
+ player?: string;
108
+ id?: string;
109
+ }): void;
110
+ /** Actions of the last reduction, by type. */
111
+ of<T extends Action["type"]>(type: T): Extract<Action, {
112
+ type: T;
113
+ }>[];
114
+ /** Actions of the whole run, by type. */
115
+ all<T extends Action["type"]>(type: T): Extract<Action, {
116
+ type: T;
117
+ }>[];
118
+ /** Effects of the last reduction, including the ones inside a batch. */
119
+ effects<K extends Effect["kind"]>(kind: K): Extract<Effect, {
120
+ kind: K;
121
+ }>[];
122
+ /** Effects of the whole run, by kind. */
123
+ effectsAll<K extends Effect["kind"]>(kind: K): Extract<Effect, {
124
+ kind: K;
125
+ }>[];
126
+ /** Announcements of the last reduction. `to` omitted = the public ones. */
127
+ announcements(to?: string): string[];
128
+ /** Every announcement of the run, public and private. */
129
+ said(): string[];
130
+ /**
131
+ * The same log through the same reducer instance, from the state this game
132
+ * started with (`init()`, or the checkpoint of `resume`), gives the same final
133
+ * state and the same actions (determinism). It does not prove the absence of
134
+ * hidden module state: that needs a fresh module, which the arena's worker
135
+ * provides. A test calls it; `dispatch` does not.
136
+ */
137
+ replay(): void;
138
+ checkpoint(): string;
139
+ static resume<Ch extends AnyChallenge>(challenge: Ch, json: string): Game<Ch>;
140
+ nextAttempt(): string;
141
+ /** The slot a fake player's item occupies: the one the state shows, else the next free one, for this game only. */
142
+ slotFor(name: string, item: string): number;
143
+ }
144
+ /** A scripted player. Every method dispatches one engine event; the SDK derives the zone edges from moves. */
145
+ export declare class Fake<Ch extends AnyChallenge> {
146
+ private readonly g;
147
+ readonly name: string;
148
+ constructor(g: Game<Ch>, name: string);
149
+ moveTo(to: Partial<Vec3> & {
150
+ y: number;
151
+ }, extrema?: {
152
+ maxY?: number;
153
+ minY?: number;
154
+ }): Action[];
155
+ vote(voteId: string, option: string): {
156
+ accepted: boolean;
157
+ feedback?: string | undefined;
158
+ };
159
+ says(text: string): Action[];
160
+ swings(animation?: "swing" | "swing_off"): Action[];
161
+ hurt(amount: number, cause: string, attacker?: string): Action[];
162
+ dies(cause?: string, killer?: string): Action[];
163
+ respawns(): Action[];
164
+ picksUp(item: `minecraft:${string}`, count?: number, at?: Vec3): Action[];
165
+ /** The player's inventory now holds `count` of `item`: one slot per item name, in this game. */
166
+ has(item: `minecraft:${string}`, count: number): Action[];
167
+ /** Walks into the declared zone (its first corner); the SDK derives the edge. */
168
+ enters(zone: string): Action[];
169
+ /** Walks 100 blocks under the declared zone's first corner. */
170
+ leaves(zone: string): Action[];
171
+ uses(block: `minecraft:${string}`, at: Vec3, item?: `minecraft:${string}`): Action[];
172
+ breaks(block: `minecraft:${string}`, at: Vec3): Action[];
173
+ places(block: `minecraft:${string}`, at: Vec3): Action[];
174
+ private zone;
175
+ }
176
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/test/harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,441 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Fake = exports.Game = exports.canonical = void 0;
4
+ exports.sandboxed = sandboxed;
5
+ // A stand-in arena for tests. It feeds events, collects actions, keeps the event
6
+ // log, and checks on every reduction that the reducer is pure, deterministic, and
7
+ // that the state survives a JSON round trip. No test framework dependency: it
8
+ // throws plain errors, so it runs under node:test, vitest, bun test or jest.
9
+ const node_fs_1 = require("node:fs");
10
+ const sandbox_registry_js_1 = require("../runtime/sandbox-registry.js");
11
+ const sdk_js_1 = require("../runtime/sdk.js");
12
+ /** JSON with sorted keys, so key order never counts as a difference. */
13
+ const canonical = (v) => JSON.stringify(v, (_k, x) => x && typeof x === "object" && !Array.isArray(x) ? Object.fromEntries(Object.entries(x).sort()) : x);
14
+ exports.canonical = canonical;
15
+ function assertEqual(actual, expected, what) {
16
+ if (actual !== expected)
17
+ throw new Error(`${what}\n expected: ${expected}\n actual: ${actual}`);
18
+ }
19
+ /**
20
+ * Under `kradle challenge test` (`KRADLE_CHALLENGE_BUNDLE` set), a Game on the
21
+ * imported source would run the rules outside the sandbox and still count as
22
+ * a pass: refused. A Game on the bundle leaves a line in the file named by
23
+ * `KRADLE_CHALLENGE_EVIDENCE`, the command's proof that the bundle ran.
24
+ */
25
+ function requireBundleUnderTheCommand(challenge) {
26
+ const bundle = process.env.KRADLE_CHALLENGE_BUNDLE;
27
+ if (!bundle)
28
+ return;
29
+ const from = (0, sandbox_registry_js_1.sandboxOrigin)(challenge);
30
+ if (!from) {
31
+ throw new Error("KRADLE_CHALLENGE_BUNDLE is set (kradle challenge test), and this Game runs an imported challenge, not the bundle. Write `const challenge = await sandboxed(source)` and pass that to Game.");
32
+ }
33
+ const evidence = process.env.KRADLE_CHALLENGE_EVIDENCE;
34
+ if (evidence) {
35
+ (0, node_fs_1.appendFileSync)(evidence, `${JSON.stringify({ bundle: from.origin, challenge: challenge.manifest?.name })}\n`);
36
+ }
37
+ }
38
+ /**
39
+ * The challenge a test runs against. By default the challenge as imported, in
40
+ * this process: fast, and the rules are the source. When the environment names
41
+ * a built bundle (`KRADLE_CHALLENGE_BUNDLE=<path to kradle-runtime/challenge.js>`,
42
+ * which `kradle challenge test` sets), the bundle is loaded inside the arena's
43
+ * SES sandbox instead: no clock, no random, no timers, and every call gets a
44
+ * fresh compartment. The bundle must be the same challenge as the import.
45
+ * Async because `ses` loads as an ES module: `const c = await sandboxed(source)`.
46
+ */
47
+ async function sandboxed(challenge) {
48
+ const bundle = process.env.KRADLE_CHALLENGE_BUNDLE;
49
+ if (!bundle)
50
+ return challenge;
51
+ // Lazy: `ses` and the lockdown only enter a process that asked for them.
52
+ const { loadBundleFile } = require("../runtime/sandbox.js");
53
+ const loaded = await loadBundleFile(bundle);
54
+ const want = challenge.manifest?.name;
55
+ const got = loaded.manifest?.name;
56
+ if (want !== got) {
57
+ throw new Error(`KRADLE_CHALLENGE_BUNDLE holds the challenge "${got}", the test imports "${want}"`);
58
+ }
59
+ return loaded;
60
+ }
61
+ class Game {
62
+ challenge;
63
+ state;
64
+ log = [];
65
+ actions = [];
66
+ last = [];
67
+ /** The harness's tick step, a test setting: server ticks arrive in steps of 4 here (the arena sends every 2 ticks by default). */
68
+ step = 4;
69
+ attempts = 0;
70
+ /** The state this game started from: `init()`, or the checkpoint of `resume`. `replay` starts here. */
71
+ origin;
72
+ /** Inventory slots the fake players used, per player and item, for this game only. */
73
+ slots = new Map();
74
+ constructor(challenge, state) {
75
+ this.challenge = challenge;
76
+ requireBundleUnderTheCommand(challenge);
77
+ this.state = (state ?? challenge.init());
78
+ this.origin = JSON.stringify(this.state);
79
+ }
80
+ dispatch(event) {
81
+ const before = JSON.stringify(this.state);
82
+ const a = this.challenge.reduce(this.state, event);
83
+ assertEqual(JSON.stringify(this.state), before, "reduce() mutated its input state");
84
+ this.state = JSON.parse(JSON.stringify(a.state)); // a checkpoint is a JSON string
85
+ this.log.push(event);
86
+ this.last = a.actions;
87
+ this.actions.push(...a.actions);
88
+ return a.actions;
89
+ }
90
+ /** Ticks in steps of `step`, and lands exactly on `serverTick` (the last step is shorter when needed). */
91
+ tickTo(serverTick) {
92
+ for (let t = this.state.tick + this.step; t <= serverTick; t += this.step)
93
+ this.dispatch({ type: "tick", serverTick: t });
94
+ if (this.state.tick < serverTick)
95
+ this.dispatch({ type: "tick", serverTick });
96
+ }
97
+ tick(n = 1) {
98
+ this.tickTo(this.state.tick + n * this.step);
99
+ }
100
+ /** Advance by a duration: "35s", "2m", or ticks. */
101
+ after(d) {
102
+ this.tickTo(this.state.tick + (0, sdk_js_1.toTicks)(d));
103
+ }
104
+ /** Advance until `d` after game start. */
105
+ at(d) {
106
+ this.tickTo(this.state.startTick + (0, sdk_js_1.toTicks)(d));
107
+ }
108
+ /**
109
+ * run_started, every join, the first tick, and the setup confirmation when the
110
+ * challenge has a setup. A roster entry is a role (`{ alice: "climber" }`), or the
111
+ * role with the player's position and sample fields (`{ alice: { role: "climber",
112
+ * at: { x: 0, y: -60, z: 0 } } }`): the first tick then carries that sample, so
113
+ * `start` and the setup see the position, as they do in the arena. Without `at`
114
+ * the position stays null until the first `moveTo`.
115
+ */
116
+ begin(seed, participants, opts = {}) {
117
+ const entries = Object.entries(participants).map(([name, entry]) => [name, typeof entry === "string" ? { role: entry } : entry]);
118
+ this.dispatch({
119
+ type: "run_started",
120
+ seed,
121
+ participants: entries.map(([name, e]) => ({ name, role: e.role })),
122
+ params: opts.params ?? {},
123
+ capabilities: opts.capabilities ?? sdk_js_1.ALL_CAPABILITIES,
124
+ locations: opts.locations,
125
+ markers: opts.markers,
126
+ });
127
+ for (const [name] of entries)
128
+ this.dispatch({ type: "player_joined", name });
129
+ // Every entry that carries a sample field (a position, a game mode, health...) goes into the first tick.
130
+ const samples = entries
131
+ .filter(([, e]) => Object.keys(e).length > 1)
132
+ .map(([name, { role: _role, at, ...rest }]) => ({ name, participant: true, pos: at, ...rest }));
133
+ if (samples.length > 0)
134
+ this.dispatch({ type: "tick", serverTick: this.state.tick + this.step, players: samples });
135
+ else
136
+ this.tick();
137
+ if (this.of("batch").some((b) => b.id === "setup")) {
138
+ const ok = opts.setupOk ?? true;
139
+ this.dispatch({
140
+ type: "effect_result",
141
+ id: "setup",
142
+ ok,
143
+ detail: ok ? undefined : "fill #3 failed: unknown block",
144
+ });
145
+ }
146
+ return this;
147
+ }
148
+ player(name) {
149
+ return new Fake(this, name);
150
+ }
151
+ custom(name, data, player) {
152
+ return this.dispatch({ type: "custom", name, player, data });
153
+ }
154
+ /** Loads the chunks that cover `box` into the mirror: `block` inside the box, air around it. */
155
+ terrain(box, block, minY = -64, height = 384) {
156
+ const { lo, hi } = (0, sdk_js_1.bounds)(box);
157
+ const out = [];
158
+ for (let cx = lo.x >> 4; cx <= hi.x >> 4; cx++) {
159
+ for (let cz = lo.z >> 4; cz <= hi.z >> 4; cz++) {
160
+ const sections = [];
161
+ for (let base = minY; base < minY + height; base += 16) {
162
+ if (base + 15 < lo.y || base > hi.y)
163
+ continue;
164
+ const whole = lo.x <= cx << 4 &&
165
+ hi.x >= (cx << 4) + 15 &&
166
+ lo.z <= cz << 4 &&
167
+ hi.z >= (cz << 4) + 15 &&
168
+ lo.y <= base &&
169
+ hi.y >= base + 15;
170
+ if (whole) {
171
+ sections.push({ y: base, block });
172
+ continue;
173
+ }
174
+ const data = new Array(4096).fill(0);
175
+ for (let y = 0; y < 16; y++)
176
+ for (let z = 0; z < 16; z++)
177
+ for (let x = 0; x < 16; x++) {
178
+ const wx = (cx << 4) + x;
179
+ const wy = base + y;
180
+ const wz = (cz << 4) + z;
181
+ if (wx >= lo.x && wx <= hi.x && wy >= lo.y && wy <= hi.y && wz >= lo.z && wz <= hi.z) {
182
+ data[(y << 8) | (z << 4) | x] = 1;
183
+ }
184
+ }
185
+ sections.push({ y: base, palette: ["minecraft:air", block], data });
186
+ }
187
+ out.push(...this.dispatch({ type: "chunk", x: cx, z: cz, minY, sections }));
188
+ }
189
+ }
190
+ return out;
191
+ }
192
+ /** Blocks changed on the server, by anyone or anything. */
193
+ setBlocks(changes) {
194
+ return this.dispatch({ type: "blocks_changed", changes });
195
+ }
196
+ spawnEntity(id, type, at, extra = {}) {
197
+ return this.dispatch({ type: "entity_spawned", id, entity: type, at, ...extra });
198
+ }
199
+ /** Entities moved: they arrive with the next tick, so this advances one engine step. */
200
+ moveEntities(moves) {
201
+ return this.dispatch({ type: "tick", serverTick: this.state.tick + this.step, entities: moves });
202
+ }
203
+ /**
204
+ * One engine tick with several samples at once: participants' positions and
205
+ * fields, and entity moves, all in the same tick, as the engine sends them.
206
+ * A handler that reads another player's position sees this tick for everyone.
207
+ */
208
+ sample(players, entities) {
209
+ return this.dispatch({
210
+ type: "tick",
211
+ serverTick: this.state.tick + this.step,
212
+ players: players.map((p) => ({ participant: true, ...p })),
213
+ entities,
214
+ });
215
+ }
216
+ removeEntity(id, cause = "removed", killer) {
217
+ return this.dispatch({ type: "entity_removed", id, cause, killer });
218
+ }
219
+ /**
220
+ * The contents of a declared container, as the engine reports them: `items` is the whole
221
+ * content (item to count), laid out one item per slot. `by` names the player who had it open;
222
+ * `initial` marks the first snapshot (no handler fires for it).
223
+ */
224
+ container(at, items, opts = {}) {
225
+ const key = `${Math.floor(at.x)},${Math.floor(at.y)},${Math.floor(at.z)}`;
226
+ const known = Object.keys(this.state.containers?.[key]?.slots ?? {});
227
+ const slots = [];
228
+ let slot = 0;
229
+ for (const [item, count] of Object.entries(items)) {
230
+ if (count > 0)
231
+ slots.push({ slot, item: item, count });
232
+ else
233
+ slots.push({ slot });
234
+ slot++;
235
+ }
236
+ for (const k of known)
237
+ if (Number(k) >= slot)
238
+ slots.push({ slot: Number(k) });
239
+ return this.dispatch({
240
+ type: "container",
241
+ at: { ...at },
242
+ block: opts.block ?? "minecraft:chest",
243
+ slots,
244
+ by: opts.by,
245
+ initial: opts.initial,
246
+ });
247
+ }
248
+ /** A game mode change reported by the engine (the `gamemode` event). */
249
+ setGamemode(name, gamemode) {
250
+ return this.dispatch({ type: "gamemode", name, gamemode });
251
+ }
252
+ /** A non-participant player's sample (the watcher, a spectator), with the next tick. */
253
+ other(name, sample) {
254
+ return this.dispatch({
255
+ type: "tick",
256
+ serverTick: this.state.tick + this.step,
257
+ players: [{ name, participant: false, ...sample }],
258
+ });
259
+ }
260
+ /**
261
+ * The engine's answer to a walk: the last one requested, or the last one for
262
+ * `player` (or with `id`) when several are in flight. A walk that was already
263
+ * answered is skipped.
264
+ */
265
+ walkResult(ok, detail, which = {}) {
266
+ const answered = new Set();
267
+ for (const e of this.log)
268
+ if (e.type === "effect_result")
269
+ answered.add(e.id);
270
+ const walk = [...this.actions]
271
+ .reverse()
272
+ .find((a) => a.type === "walk" &&
273
+ !answered.has(a.id) &&
274
+ (which.id === undefined || a.id === which.id) &&
275
+ (which.player === undefined || a.player === which.player));
276
+ if (!walk)
277
+ throw new Error(`no pending walk${which.player ? ` for ${which.player}` : ""}${which.id ? ` with id ${which.id}` : ""}`);
278
+ this.dispatch({ type: "effect_result", id: walk.id, ok, detail });
279
+ }
280
+ /** Actions of the last reduction, by type. */
281
+ of(type) {
282
+ return this.last.filter((a) => a.type === type);
283
+ }
284
+ /** Actions of the whole run, by type. */
285
+ all(type) {
286
+ return this.actions.filter((a) => a.type === type);
287
+ }
288
+ /** Effects of the last reduction, including the ones inside a batch. */
289
+ effects(kind) {
290
+ return effectsOf(this.last, kind);
291
+ }
292
+ /** Effects of the whole run, by kind. */
293
+ effectsAll(kind) {
294
+ return effectsOf(this.actions, kind);
295
+ }
296
+ /** Announcements of the last reduction. `to` omitted = the public ones. */
297
+ announcements(to) {
298
+ return this.effects("announce")
299
+ .filter((e) => e.to === to)
300
+ .map((e) => e.message);
301
+ }
302
+ /** Every announcement of the run, public and private. */
303
+ said() {
304
+ return this.effectsAll("announce").map((e) => e.message);
305
+ }
306
+ /**
307
+ * The same log through the same reducer instance, from the state this game
308
+ * started with (`init()`, or the checkpoint of `resume`), gives the same final
309
+ * state and the same actions (determinism). It does not prove the absence of
310
+ * hidden module state: that needs a fresh module, which the arena's worker
311
+ * provides. A test calls it; `dispatch` does not.
312
+ */
313
+ replay() {
314
+ let s = JSON.parse(this.origin);
315
+ const actions = [];
316
+ for (const e of this.log) {
317
+ const r = this.challenge.reduce(s, e);
318
+ s = r.state;
319
+ actions.push(...r.actions);
320
+ }
321
+ assertEqual((0, exports.canonical)(s), (0, exports.canonical)(this.state), "replay: final state differs");
322
+ assertEqual((0, exports.canonical)(actions), (0, exports.canonical)(this.actions), "replay: actions differ");
323
+ }
324
+ checkpoint() {
325
+ return JSON.stringify(this.state);
326
+ }
327
+ static resume(challenge, json) {
328
+ return new Game(challenge, JSON.parse(json));
329
+ }
330
+ nextAttempt() {
331
+ return `attempt:${++this.attempts}`;
332
+ }
333
+ /** The slot a fake player's item occupies: the one the state shows, else the next free one, for this game only. */
334
+ slotFor(name, item) {
335
+ const slots = (this.state.players[name]?.slots ?? {});
336
+ const held = Object.entries(slots).find(([, s]) => s?.item === item);
337
+ if (held)
338
+ return Number(held[0]);
339
+ const mine = this.slots.get(name) ?? new Map();
340
+ this.slots.set(name, mine);
341
+ const known = mine.get(item);
342
+ if (known !== undefined)
343
+ return known;
344
+ const used = new Set([...mine.values(), ...Object.keys(slots).map(Number)]);
345
+ let slot = 0;
346
+ while (used.has(slot))
347
+ slot++;
348
+ mine.set(item, slot);
349
+ return slot;
350
+ }
351
+ }
352
+ exports.Game = Game;
353
+ function effectsOf(actions, kind) {
354
+ return actions
355
+ .flatMap((a) => (a.type === "effect" ? [a.effect] : a.type === "batch" ? a.effects : []))
356
+ .filter((e) => e.kind === kind);
357
+ }
358
+ /** A scripted player. Every method dispatches one engine event; the SDK derives the zone edges from moves. */
359
+ class Fake {
360
+ g;
361
+ name;
362
+ constructor(g, name) {
363
+ this.g = g;
364
+ this.name = name;
365
+ }
366
+ moveTo(to, extrema) {
367
+ const prev = this.g.state.players[this.name]?.pos;
368
+ const pos = { x: prev?.x ?? 0, z: prev?.z ?? 0, ...to };
369
+ return this.g.dispatch({
370
+ type: "player_moved",
371
+ name: this.name,
372
+ to: pos,
373
+ maxY: extrema?.maxY ?? pos.y,
374
+ minY: extrema?.minY ?? pos.y,
375
+ });
376
+ }
377
+ vote(voteId, option) {
378
+ const attemptId = this.g.nextAttempt();
379
+ this.g.dispatch({ type: "vote_attempt", attemptId, name: this.name, voteId, option });
380
+ const d = this.g.of("vote_decision").find((x) => x.attemptId === attemptId);
381
+ if (!d)
382
+ throw new Error(`no vote_decision for ${attemptId}`);
383
+ return { accepted: d.accepted, feedback: d.feedback };
384
+ }
385
+ says(text) {
386
+ return this.g.dispatch({ type: "chat", from: this.name, text });
387
+ }
388
+ swings(animation = "swing") {
389
+ return this.g.dispatch({ type: "animation", name: this.name, animation });
390
+ }
391
+ hurt(amount, cause, attacker) {
392
+ return this.g.dispatch({ type: "player_damaged", name: this.name, amount, cause, attacker });
393
+ }
394
+ dies(cause = "fall", killer) {
395
+ return this.g.dispatch({ type: "player_died", name: this.name, cause, killer });
396
+ }
397
+ respawns() {
398
+ return this.g.dispatch({ type: "player_respawned", name: this.name });
399
+ }
400
+ picksUp(item, count = 1, at = { x: 0, y: 0, z: 0 }) {
401
+ return this.g.dispatch({ type: "item_picked_up", name: this.name, item, count, at });
402
+ }
403
+ /** The player's inventory now holds `count` of `item`: one slot per item name, in this game. */
404
+ has(item, count) {
405
+ const slot = this.g.slotFor(this.name, item);
406
+ return this.g.dispatch({
407
+ type: "inventory",
408
+ name: this.name,
409
+ slots: [count > 0 ? { slot, item, count } : { slot }],
410
+ });
411
+ }
412
+ /** Walks into the declared zone (its first corner); the SDK derives the edge. */
413
+ enters(zone) {
414
+ const box = this.zone(zone);
415
+ return this.moveTo({ x: box.from.x + 0.5, y: box.from.y, z: box.from.z + 0.5 });
416
+ }
417
+ /** Walks 100 blocks under the declared zone's first corner. */
418
+ leaves(zone) {
419
+ const box = this.zone(zone);
420
+ return this.moveTo({ x: box.from.x + 0.5, y: box.from.y - 100, z: box.from.z + 0.5 });
421
+ }
422
+ uses(block, at, item) {
423
+ return this.g.dispatch({ type: "block_used", name: this.name, at, block, item });
424
+ }
425
+ breaks(block, at) {
426
+ return this.g.dispatch({ type: "block_broken", name: this.name, at, block });
427
+ }
428
+ places(block, at) {
429
+ return this.g.dispatch({ type: "block_placed", name: this.name, at, block });
430
+ }
431
+ zone(zone) {
432
+ const zones = this.g.challenge.zones;
433
+ const box = zones[zone];
434
+ if (!box) {
435
+ throw new Error(`"${zone}" is not declared in zones (declared: ${Object.keys(zones).join(", ") || "none"})`);
436
+ }
437
+ return box;
438
+ }
439
+ }
440
+ exports.Fake = Fake;
441
+ //# sourceMappingURL=harness.js.map