@johnmorrisdotca/houseki 0.4.1 → 0.4.2

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 (71) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/README.md +77 -95
  3. package/dist/colour-chains/challenge.d.ts +12 -1
  4. package/dist/colour-chains/challenge.js +12 -1
  5. package/dist/colour-chains/content-types.d.ts +112 -0
  6. package/dist/colour-chains/content.d.ts +140 -3
  7. package/dist/colour-chains/content.js +140 -3
  8. package/dist/colour-chains/engine.d.ts +85 -6
  9. package/dist/colour-chains/engine.js +85 -6
  10. package/dist/colour-chains/input.d.ts +97 -7
  11. package/dist/colour-chains/input.js +97 -7
  12. package/dist/colour-chains/persistence.d.ts +36 -3
  13. package/dist/colour-chains/persistence.js +36 -3
  14. package/dist/colour-chains/types.d.ts +291 -17
  15. package/dist/colour-chains/validation.d.ts +12 -1
  16. package/dist/colour-chains/validation.js +12 -1
  17. package/dist/falling-triplets/content-types.d.ts +69 -0
  18. package/dist/falling-triplets/content.d.ts +60 -3
  19. package/dist/falling-triplets/content.js +60 -3
  20. package/dist/falling-triplets/engine.d.ts +122 -10
  21. package/dist/falling-triplets/engine.js +122 -10
  22. package/dist/falling-triplets/input.d.ts +61 -5
  23. package/dist/falling-triplets/input.js +61 -5
  24. package/dist/falling-triplets/match.d.ts +26 -2
  25. package/dist/falling-triplets/match.js +26 -2
  26. package/dist/falling-triplets/random.d.ts +34 -3
  27. package/dist/falling-triplets/random.js +34 -3
  28. package/dist/falling-triplets/types.d.ts +227 -3
  29. package/dist/gem-swap/content.d.ts +116 -0
  30. package/dist/gem-swap/content.js +72 -0
  31. package/dist/gem-swap/engine.d.ts +124 -9
  32. package/dist/gem-swap/engine.js +124 -9
  33. package/dist/gem-swap/persistence.d.ts +60 -4
  34. package/dist/gem-swap/persistence.js +60 -4
  35. package/dist/gem-swap/types.d.ts +336 -3
  36. package/dist/magnetic-blocks/content-types.d.ts +56 -0
  37. package/dist/magnetic-blocks/content.d.ts +91 -5
  38. package/dist/magnetic-blocks/content.js +91 -5
  39. package/dist/magnetic-blocks/engine.d.ts +63 -5
  40. package/dist/magnetic-blocks/engine.js +63 -5
  41. package/dist/magnetic-blocks/persistence.d.ts +36 -3
  42. package/dist/magnetic-blocks/persistence.js +36 -3
  43. package/dist/magnetic-blocks/physics.d.ts +176 -6
  44. package/dist/magnetic-blocks/physics.js +176 -6
  45. package/dist/magnetic-blocks/types.d.ts +185 -1
  46. package/dist/magnetic-blocks/validation.d.ts +12 -0
  47. package/dist/magnetic-blocks/validation.js +12 -0
  48. package/dist/nature/attraction.d.ts +24 -2
  49. package/dist/nature/attraction.js +24 -2
  50. package/dist/nature/environment.d.ts +200 -7
  51. package/dist/nature/environment.js +88 -7
  52. package/dist/nature/marking.d.ts +13 -1
  53. package/dist/nature/marking.js +13 -1
  54. package/dist/nature/rebound.d.ts +30 -2
  55. package/dist/nature/rebound.js +30 -2
  56. package/dist/nature/state.d.ts +11 -0
  57. package/dist/nature/state.js +11 -0
  58. package/dist/nature/types.d.ts +194 -1
  59. package/dist/nature/validation.d.ts +12 -0
  60. package/dist/nature/validation.js +12 -0
  61. package/dist/stone-collapse/content-types.d.ts +69 -0
  62. package/dist/stone-collapse/content.d.ts +60 -3
  63. package/dist/stone-collapse/content.js +60 -3
  64. package/dist/stone-collapse/engine.d.ts +99 -8
  65. package/dist/stone-collapse/engine.js +99 -8
  66. package/dist/stone-collapse/persistence.d.ts +36 -3
  67. package/dist/stone-collapse/persistence.js +36 -3
  68. package/dist/stone-collapse/types.d.ts +220 -3
  69. package/dist/stone-collapse/validation.d.ts +12 -1
  70. package/dist/stone-collapse/validation.js +12 -1
  71. package/package.json +34 -26
@@ -1,11 +1,68 @@
1
1
  import type { CampaignLevel, CampaignManifest, TutorialDefinition } from './content-types.js';
2
2
  import type { GameState } from './types.js';
3
+ /** The frozen native campaign manifest with its ordering, revisions, checksum and measured levels.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { campaignManifest } from "@johnmorrisdotca/houseki/falling-triplets";
8
+ *
9
+ * console.log(campaignManifest.count);
10
+ * ```
11
+ */
3
12
  export declare const campaignManifest: CampaignManifest;
13
+ /** The frozen ordered native levels; array indices start at zero and display numbers start at one.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { levelManifest } from "@johnmorrisdotca/houseki/falling-triplets";
18
+ *
19
+ * console.log(levelManifest.length);
20
+ * ```
21
+ */
4
22
  export declare const levelManifest: readonly CampaignLevel[];
23
+ /** The frozen native bilingual lessons and their authored teaching steps.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { tutorialManifest } from "@johnmorrisdotca/houseki/falling-triplets";
28
+ *
29
+ * console.log(tutorialManifest.length);
30
+ * ```
31
+ */
5
32
  export declare const tutorialManifest: readonly TutorialDefinition[];
6
- /** Find a level by stable content ID or its current one-based display number. */
33
+ /** Find a level by stable content ID or its current one-based display number.
34
+ *
35
+ * @param id - A stable content id, or the one-based display number when numbers are accepted.
36
+ * @returns Find a level by stable content ID or its current one-based display number. Returns undefined when the id or display number is absent.
37
+ * @example
38
+ * ```ts
39
+ * import { getLevel } from "@johnmorrisdotca/houseki/falling-triplets";
40
+ *
41
+ * console.log(getLevel(1)?.id);
42
+ * ```
43
+ */
7
44
  export declare function getLevel(id: string | number): CampaignLevel | undefined;
8
- /** Construct a fresh validated challenge state for a stable level ID or display number. */
45
+ /** Construct a fresh validated challenge state for a stable level ID or display number.
46
+ *
47
+ * @param id - A stable content id, or the one-based display number when numbers are accepted.
48
+ * @returns Construct a fresh validated challenge state for a stable level ID or display number.
49
+ * @example
50
+ * ```ts
51
+ * import { createLevel } from "@johnmorrisdotca/houseki/falling-triplets";
52
+ *
53
+ * console.log(createLevel(1).phase);
54
+ * ```
55
+ */
9
56
  export declare function createLevel(id: string | number): GameState;
10
- /** Find a lesson by its persistent ID. */
57
+ /** Find a lesson by its persistent ID.
58
+ *
59
+ * @param id - A stable content id, or the one-based display number when numbers are accepted.
60
+ * @returns Find a lesson by its persistent ID. Returns undefined when the id or display number is absent.
61
+ * @example
62
+ * ```ts
63
+ * import { getTutorial, tutorialManifest } from "@johnmorrisdotca/houseki/falling-triplets";
64
+ *
65
+ * console.log(getTutorial(tutorialManifest[0].id)?.id);
66
+ * ```
67
+ */
11
68
  export declare function getTutorial(id: string): TutorialDefinition | undefined;
@@ -8,16 +8,63 @@ function deepFreeze(value) {
8
8
  }
9
9
  return value;
10
10
  }
11
+ /** The frozen native campaign manifest with its ordering, revisions, checksum and measured levels.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { campaignManifest } from "@johnmorrisdotca/houseki/falling-triplets";
16
+ *
17
+ * console.log(campaignManifest.count);
18
+ * ```
19
+ */
11
20
  export const campaignManifest = deepFreeze(contentData.campaign);
21
+ /** The frozen ordered native levels; array indices start at zero and display numbers start at one.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { levelManifest } from "@johnmorrisdotca/houseki/falling-triplets";
26
+ *
27
+ * console.log(levelManifest.length);
28
+ * ```
29
+ */
12
30
  export const levelManifest = campaignManifest.levels;
31
+ /** The frozen native bilingual lessons and their authored teaching steps.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { tutorialManifest } from "@johnmorrisdotca/houseki/falling-triplets";
36
+ *
37
+ * console.log(tutorialManifest.length);
38
+ * ```
39
+ */
13
40
  export const tutorialManifest = deepFreeze(contentData.tutorials);
14
- /** Find a level by stable content ID or its current one-based display number. */
41
+ /** Find a level by stable content ID or its current one-based display number.
42
+ *
43
+ * @param id - A stable content id, or the one-based display number when numbers are accepted.
44
+ * @returns Find a level by stable content ID or its current one-based display number. Returns undefined when the id or display number is absent.
45
+ * @example
46
+ * ```ts
47
+ * import { getLevel } from "@johnmorrisdotca/houseki/falling-triplets";
48
+ *
49
+ * console.log(getLevel(1)?.id);
50
+ * ```
51
+ */
15
52
  export function getLevel(id) {
16
53
  if (typeof id === 'number')
17
54
  return Number.isInteger(id) ? levelManifest.find(level => level.number === id) : undefined;
18
55
  return levelManifest.find(level => level.id === id);
19
56
  }
20
- /** Construct a fresh validated challenge state for a stable level ID or display number. */
57
+ /** Construct a fresh validated challenge state for a stable level ID or display number.
58
+ *
59
+ * @param id - A stable content id, or the one-based display number when numbers are accepted.
60
+ * @returns Construct a fresh validated challenge state for a stable level ID or display number.
61
+ * @example
62
+ * ```ts
63
+ * import { createLevel } from "@johnmorrisdotca/houseki/falling-triplets";
64
+ *
65
+ * console.log(createLevel(1).phase);
66
+ * ```
67
+ */
21
68
  export function createLevel(id) {
22
69
  const level = getLevel(id);
23
70
  if (!level)
@@ -33,7 +80,17 @@ export function createLevel(id) {
33
80
  witness: level.witness
34
81
  });
35
82
  }
36
- /** Find a lesson by its persistent ID. */
83
+ /** Find a lesson by its persistent ID.
84
+ *
85
+ * @param id - A stable content id, or the one-based display number when numbers are accepted.
86
+ * @returns Find a lesson by its persistent ID. Returns undefined when the id or display number is absent.
87
+ * @example
88
+ * ```ts
89
+ * import { getTutorial, tutorialManifest } from "@johnmorrisdotca/houseki/falling-triplets";
90
+ *
91
+ * console.log(getTutorial(tutorialManifest[0].id)?.id);
92
+ * ```
93
+ */
37
94
  export function getTutorial(id) {
38
95
  return tutorialManifest.find(tutorial => tutorial.id === id);
39
96
  }
@@ -1,26 +1,138 @@
1
1
  import type { Action, ChallengeOptions, CreateOptions, GameState, Transition } from './types.js';
2
- /** Returns the exact landing row for the current rigid triplet. */
2
+ /** Returns the exact landing row for the current rigid triplet.
3
+ *
4
+ * @param state - The immutable native state to read or transition; the input is retained.
5
+ * @returns Returns the exact landing row for the current rigid triplet. Returns null when there is no active piece or applicable preview.
6
+ * @example
7
+ * ```ts
8
+ * import { createGame, landingY } from "@johnmorrisdotca/houseki/falling-triplets";
9
+ *
10
+ * const state=createGame({seed:"docs"});
11
+ * console.log(landingY(state));
12
+ * ```
13
+ */
3
14
  export declare function landingY(state: GameState): number | null;
4
- /** Creates a deterministic empty game with an active piece and three-piece preview. */
15
+ /** Creates a deterministic empty game with an active piece and three-piece preview.
16
+ *
17
+ * @param options - Validated native creation, authored challenge, or environment options described by this signature.
18
+ * @returns Creates a deterministic empty game with an active piece and three-piece preview.
19
+ * @example
20
+ * ```ts
21
+ * import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
22
+ *
23
+ * console.log(createGame({seed:"docs"}).phase);
24
+ * ```
25
+ */
5
26
  export declare function createGame(options?: CreateOptions): GameState;
6
- /** Creates a challenge after validating its authored board, finite queue, goal, and witness. */
27
+ /** Creates a challenge after validating its authored board, finite queue, goal, and witness.
28
+ *
29
+ * @param options - Validated native creation, authored challenge, or environment options described by this signature.
30
+ * @returns Creates a challenge after validating its authored board, finite queue, goal, and witness.
31
+ * @example
32
+ * ```ts
33
+ * import { createChallenge } from "@johnmorrisdotca/houseki/falling-triplets";
34
+ *
35
+ * console.log(createChallenge({width:6,height:12,board:Array(72).fill(null),queue:[["red","green","blue"],["blue","red","green"]],goal:{type:"empty"}}).phase);
36
+ * ```
37
+ */
7
38
  export declare function createChallenge(options: ChallengeOptions): GameState;
8
- /** Applies and records one immutable action; rejected actions preserve state identity. */
39
+ /** Applies and records one immutable action; rejected actions preserve state identity.
40
+ *
41
+ * @param state - The immutable native state to read or transition; the input is retained.
42
+ * @param action - One native action for this entry point; inspect accepted and reason on the result.
43
+ * @returns Applies and records one immutable action; rejected actions preserve state identity.
44
+ * @example
45
+ * ```ts
46
+ * import { applyAction, createGame } from "@johnmorrisdotca/houseki/falling-triplets";
47
+ * import type { Action } from "@johnmorrisdotca/houseki/falling-triplets";
48
+ *
49
+ * const state=createGame({seed:"docs"});
50
+ * const action: Action={kind:"left"};
51
+ * console.log(applyAction(state,action).accepted);
52
+ * ```
53
+ */
9
54
  export declare function applyAction(state: GameState, action: Action): Transition;
10
- /** Advances fixed 60 Hz game ticks. Arcade timing is applied to the active piece. */
55
+ /** Advances fixed 60 Hz game ticks. Arcade timing is applied to the active piece.
56
+ *
57
+ * @param state - The immutable native state to read or transition; the input is retained.
58
+ * @param ticks - The nonnegative number of fixed 60 Hz logical ticks to advance.
59
+ * @returns Advances fixed 60 Hz game ticks. Arcade timing is applied to the active piece.
60
+ * @example
61
+ * ```ts
62
+ * import { advanceTicks, createGame } from "@johnmorrisdotca/houseki/falling-triplets";
63
+ *
64
+ * const state=createGame({seed:"docs"});
65
+ * console.log(advanceTicks(state,1).state.phase);
66
+ * ```
67
+ */
11
68
  export declare function advanceTicks(state: GameState, ticks: number): Transition;
12
- /** Lists the core actions currently available to the player. */
69
+ /** Lists the core actions currently available to the player.
70
+ *
71
+ * @param state - The immutable native state to read or transition; the input is retained.
72
+ * @returns Lists the core actions currently available to the player.
73
+ * @example
74
+ * ```ts
75
+ * import { createGame, legalActions } from "@johnmorrisdotca/houseki/falling-triplets";
76
+ *
77
+ * const state=createGame({seed:"docs"});
78
+ * console.log(legalActions(state).length);
79
+ * ```
80
+ */
13
81
  export declare function legalActions(state: GameState): readonly Action[];
14
- /** Returns a plain status summary suitable for UI labels. */
82
+ /** Returns a plain status summary suitable for UI labels.
83
+ *
84
+ * @param state - The immutable native state to read or transition; the input is retained.
85
+ * @returns Returns a plain status summary suitable for UI labels.
86
+ * @example
87
+ * ```ts
88
+ * import { createGame, statusOf } from "@johnmorrisdotca/houseki/falling-triplets";
89
+ *
90
+ * const state=createGame({seed:"docs"});
91
+ * console.log(statusOf(state).phase);
92
+ * ```
93
+ */
15
94
  export declare function statusOf(state: GameState): Readonly<{
16
95
  phase: GameState['phase'];
17
96
  score: number;
18
97
  maxChain: number;
19
98
  reason?: string;
20
99
  }>;
21
- /** Recreates the same authored mode, seed, and challenge configuration from its original setup. */
100
+ /** Recreates the same authored mode, seed, and challenge configuration from its original setup.
101
+ *
102
+ * @param state - The immutable native state to read or transition; the input is retained.
103
+ * @returns Recreates the same authored mode, seed, and challenge configuration from its original setup.
104
+ * @example
105
+ * ```ts
106
+ * import { createGame, restartGame } from "@johnmorrisdotca/houseki/falling-triplets";
107
+ *
108
+ * const state=createGame({seed:"docs"});
109
+ * console.log(restartGame(state).phase);
110
+ * ```
111
+ */
22
112
  export declare function restartGame(state: GameState): GameState;
23
- /** Encodes the authoritative settings, action recording, and derived checkpoint. */
113
+ /** Encodes the authoritative settings, action recording, and derived checkpoint.
114
+ *
115
+ * @param state - The immutable native state to read or transition; the input is retained.
116
+ * @returns Encodes the authoritative settings, action recording, and derived checkpoint.
117
+ * @example
118
+ * ```ts
119
+ * import { createGame, encodeGame } from "@johnmorrisdotca/houseki/falling-triplets";
120
+ *
121
+ * const state=createGame({seed:"docs"});
122
+ * console.log(encodeGame(state).length);
123
+ * ```
124
+ */
24
125
  export declare function encodeGame(state: GameState): string;
25
- /** Replays and validates a bounded save, then verifies its checkpoint against the derived state. */
126
+ /** Replays and validates a bounded save, then verifies its checkpoint against the derived state.
127
+ *
128
+ * @param text - A saved JSON recording from this entry’s encodeGame; malformed or inconsistent saves throw.
129
+ * @returns Replays and validates a bounded save, then verifies its checkpoint against the derived state.
130
+ * @example
131
+ * ```ts
132
+ * import { createGame, decodeGame, encodeGame } from "@johnmorrisdotca/houseki/falling-triplets";
133
+ *
134
+ * const state=createGame({seed:"docs"});
135
+ * console.log(decodeGame(encodeGame(state)).phase);
136
+ * ```
137
+ */
26
138
  export declare function decodeGame(text: string): GameState;
@@ -28,7 +28,18 @@ function activeFromColours(state, colours, y = -3) {
28
28
  function occupied(state, piece, x = piece.x, y = piece.y) {
29
29
  return piece.gems.some((_, i) => { const cy = y + i; return x < 0 || x >= state.settings.width || cy < -HIDDEN || cy >= state.settings.height || state.board[addr(x, cy, state.settings.width)] !== null; });
30
30
  }
31
- /** Returns the exact landing row for the current rigid triplet. */
31
+ /** Returns the exact landing row for the current rigid triplet.
32
+ *
33
+ * @param state - The immutable native state to read or transition; the input is retained.
34
+ * @returns Returns the exact landing row for the current rigid triplet. Returns null when there is no active piece or applicable preview.
35
+ * @example
36
+ * ```ts
37
+ * import { createGame, landingY } from "@johnmorrisdotca/houseki/falling-triplets";
38
+ *
39
+ * const state=createGame({seed:"docs"});
40
+ * console.log(landingY(state));
41
+ * ```
42
+ */
32
43
  export function landingY(state) {
33
44
  if (!state.active)
34
45
  return null;
@@ -48,7 +59,17 @@ function advanceBag(state) {
48
59
  }
49
60
  return [bag, randomState, next];
50
61
  }
51
- /** Creates a deterministic empty game with an active piece and three-piece preview. */
62
+ /** Creates a deterministic empty game with an active piece and three-piece preview.
63
+ *
64
+ * @param options - Validated native creation, authored challenge, or environment options described by this signature.
65
+ * @returns Creates a deterministic empty game with an active piece and three-piece preview.
66
+ * @example
67
+ * ```ts
68
+ * import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
69
+ *
70
+ * console.log(createGame({seed:"docs"}).phase);
71
+ * ```
72
+ */
52
73
  export function createGame(options = {}) {
53
74
  if (options.preset !== undefined && !Object.hasOwn(PRESETS, options.preset))
54
75
  throw new RangeError('Unsupported board preset');
@@ -88,7 +109,17 @@ export function createGame(options = {}) {
88
109
  return state;
89
110
  }
90
111
  const VALID_COLOURS = new Set(['red', 'blue', 'green', 'gold', 'purple', 'teal']);
91
- /** Creates a challenge after validating its authored board, finite queue, goal, and witness. */
112
+ /** Creates a challenge after validating its authored board, finite queue, goal, and witness.
113
+ *
114
+ * @param options - Validated native creation, authored challenge, or environment options described by this signature.
115
+ * @returns Creates a challenge after validating its authored board, finite queue, goal, and witness.
116
+ * @example
117
+ * ```ts
118
+ * import { createChallenge } from "@johnmorrisdotca/houseki/falling-triplets";
119
+ *
120
+ * console.log(createChallenge({width:6,height:12,board:Array(72).fill(null),queue:[["red","green","blue"],["blue","red","green"]],goal:{type:"empty"}}).phase);
121
+ * ```
122
+ */
92
123
  export function createChallenge(options) {
93
124
  const width = options.width ?? 6;
94
125
  const height = options.height ?? 13;
@@ -386,7 +417,21 @@ function applyActionCore(state, action) {
386
417
  }
387
418
  return emptyTransition(state, 'unsupported-action');
388
419
  }
389
- /** Applies and records one immutable action; rejected actions preserve state identity. */
420
+ /** Applies and records one immutable action; rejected actions preserve state identity.
421
+ *
422
+ * @param state - The immutable native state to read or transition; the input is retained.
423
+ * @param action - One native action for this entry point; inspect accepted and reason on the result.
424
+ * @returns Applies and records one immutable action; rejected actions preserve state identity.
425
+ * @example
426
+ * ```ts
427
+ * import { applyAction, createGame } from "@johnmorrisdotca/houseki/falling-triplets";
428
+ * import type { Action } from "@johnmorrisdotca/houseki/falling-triplets";
429
+ *
430
+ * const state=createGame({seed:"docs"});
431
+ * const action: Action={kind:"left"};
432
+ * console.log(applyAction(state,action).accepted);
433
+ * ```
434
+ */
390
435
  export function applyAction(state, action) {
391
436
  const result = applyActionCore(state, action);
392
437
  if (!result.accepted || action.kind === 'tick')
@@ -395,7 +440,19 @@ export function applyAction(state, action) {
395
440
  const ordinal = last?.tick === state.elapsedTicks ? last.ordinal + 1 : 0;
396
441
  return { ...result, state: { ...result.state, recording: [...state.recording, { tick: state.elapsedTicks, ordinal, action }] } };
397
442
  }
398
- /** Advances fixed 60 Hz game ticks. Arcade timing is applied to the active piece. */
443
+ /** Advances fixed 60 Hz game ticks. Arcade timing is applied to the active piece.
444
+ *
445
+ * @param state - The immutable native state to read or transition; the input is retained.
446
+ * @param ticks - The nonnegative number of fixed 60 Hz logical ticks to advance.
447
+ * @returns Advances fixed 60 Hz game ticks. Arcade timing is applied to the active piece.
448
+ * @example
449
+ * ```ts
450
+ * import { advanceTicks, createGame } from "@johnmorrisdotca/houseki/falling-triplets";
451
+ *
452
+ * const state=createGame({seed:"docs"});
453
+ * console.log(advanceTicks(state,1).state.phase);
454
+ * ```
455
+ */
399
456
  export function advanceTicks(state, ticks) {
400
457
  if (!Number.isInteger(ticks) || ticks < 0 || ticks > 3600)
401
458
  throw new RangeError('ticks must be an integer from 0 to 3600');
@@ -437,7 +494,18 @@ export function advanceTicks(state, ticks) {
437
494
  }
438
495
  return { state: current, events, accepted: true };
439
496
  }
440
- /** Lists the core actions currently available to the player. */
497
+ /** Lists the core actions currently available to the player.
498
+ *
499
+ * @param state - The immutable native state to read or transition; the input is retained.
500
+ * @returns Lists the core actions currently available to the player.
501
+ * @example
502
+ * ```ts
503
+ * import { createGame, legalActions } from "@johnmorrisdotca/houseki/falling-triplets";
504
+ *
505
+ * const state=createGame({seed:"docs"});
506
+ * console.log(legalActions(state).length);
507
+ * ```
508
+ */
441
509
  export function legalActions(state) {
442
510
  if (state.phase === 'paused')
443
511
  return [{ kind: 'resume' }];
@@ -461,9 +529,31 @@ export function legalActions(state) {
461
529
  actions.push({ kind: 'pause' });
462
530
  return actions;
463
531
  }
464
- /** Returns a plain status summary suitable for UI labels. */
532
+ /** Returns a plain status summary suitable for UI labels.
533
+ *
534
+ * @param state - The immutable native state to read or transition; the input is retained.
535
+ * @returns Returns a plain status summary suitable for UI labels.
536
+ * @example
537
+ * ```ts
538
+ * import { createGame, statusOf } from "@johnmorrisdotca/houseki/falling-triplets";
539
+ *
540
+ * const state=createGame({seed:"docs"});
541
+ * console.log(statusOf(state).phase);
542
+ * ```
543
+ */
465
544
  export function statusOf(state) { return { phase: state.phase, score: state.score, maxChain: state.maxChain, ...(state.reason ? { reason: state.reason } : {}) }; }
466
- /** Recreates the same authored mode, seed, and challenge configuration from its original setup. */
545
+ /** Recreates the same authored mode, seed, and challenge configuration from its original setup.
546
+ *
547
+ * @param state - The immutable native state to read or transition; the input is retained.
548
+ * @returns Recreates the same authored mode, seed, and challenge configuration from its original setup.
549
+ * @example
550
+ * ```ts
551
+ * import { createGame, restartGame } from "@johnmorrisdotca/houseki/falling-triplets";
552
+ *
553
+ * const state=createGame({seed:"docs"});
554
+ * console.log(restartGame(state).phase);
555
+ * ```
556
+ */
467
557
  export function restartGame(state) {
468
558
  if (state.settings.mode === 'challenge') {
469
559
  const settings = state.settings;
@@ -472,7 +562,18 @@ export function restartGame(state) {
472
562
  }
473
563
  return createGame({ mode: state.settings.mode, seed: state.settings.seed, width: state.settings.width, height: state.settings.height, colourCount: state.settings.colourCount, ...(state.settings.pieceLimit === undefined ? {} : { pieceLimit: state.settings.pieceLimit }) });
474
564
  }
475
- /** Encodes the authoritative settings, action recording, and derived checkpoint. */
565
+ /** Encodes the authoritative settings, action recording, and derived checkpoint.
566
+ *
567
+ * @param state - The immutable native state to read or transition; the input is retained.
568
+ * @returns Encodes the authoritative settings, action recording, and derived checkpoint.
569
+ * @example
570
+ * ```ts
571
+ * import { createGame, encodeGame } from "@johnmorrisdotca/houseki/falling-triplets";
572
+ *
573
+ * const state=createGame({seed:"docs"});
574
+ * console.log(encodeGame(state).length);
575
+ * ```
576
+ */
476
577
  export function encodeGame(state) { return JSON.stringify({ format: 1, game: state.game, rules: state.rules, settings: state.settings, actions: state.recording, elapsedTicks: state.elapsedTicks, checkpoint: state }); }
477
578
  function stable(value) {
478
579
  if (Array.isArray(value))
@@ -481,7 +582,18 @@ function stable(value) {
481
582
  return `{${Object.entries(value).filter(([, item]) => item !== undefined).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${stable(item)}`).join(',')}}`;
482
583
  return JSON.stringify(value) ?? 'null';
483
584
  }
484
- /** Replays and validates a bounded save, then verifies its checkpoint against the derived state. */
585
+ /** Replays and validates a bounded save, then verifies its checkpoint against the derived state.
586
+ *
587
+ * @param text - A saved JSON recording from this entry’s encodeGame; malformed or inconsistent saves throw.
588
+ * @returns Replays and validates a bounded save, then verifies its checkpoint against the derived state.
589
+ * @example
590
+ * ```ts
591
+ * import { createGame, decodeGame, encodeGame } from "@johnmorrisdotca/houseki/falling-triplets";
592
+ *
593
+ * const state=createGame({seed:"docs"});
594
+ * console.log(decodeGame(encodeGame(state)).phase);
595
+ * ```
596
+ */
485
597
  export function decodeGame(text) {
486
598
  if (text.length > 2 * 1024 * 1024)
487
599
  throw new RangeError('Save exceeds 2 MiB');
@@ -5,14 +5,70 @@ export interface InputSchedulerState {
5
5
  readonly held: Readonly<Partial<Record<HoldAction, number>>>;
6
6
  readonly queued: readonly Action[];
7
7
  }
8
- /** Creates an empty fixed-tick input scheduler state. */
8
+ /** Creates an empty fixed-tick input scheduler state.
9
+ *
10
+ * @returns Creates an empty fixed-tick input scheduler state.
11
+ * @example
12
+ * ```ts
13
+ * import { createInputScheduler } from "@johnmorrisdotca/houseki/falling-triplets";
14
+ *
15
+ * console.log(Object.keys(createInputScheduler()));
16
+ * ```
17
+ */
9
18
  export declare function createInputScheduler(): InputSchedulerState;
10
- /** Starts or releases one held action; opposite lateral holds cancel during scheduling. */
19
+ /** Starts or releases one held action; opposite lateral holds cancel during scheduling.
20
+ *
21
+ * @param state - The immutable native state to read or transition; the input is retained.
22
+ * @param action - One native action for this entry point; inspect accepted and reason on the result.
23
+ * @param held - Whether this input is currently held.
24
+ * @returns Starts or releases one held action; opposite lateral holds cancel during scheduling.
25
+ * @example
26
+ * ```ts
27
+ * import { createInputScheduler, setHeldAction } from "@johnmorrisdotca/houseki/falling-triplets";
28
+ *
29
+ * const input=createInputScheduler();
30
+ * console.log(setHeldAction(input,"left",true));
31
+ * ```
32
+ */
11
33
  export declare function setHeldAction(state: InputSchedulerState, action: HoldAction, held: boolean): InputSchedulerState;
12
- /** Queues a one-shot cycle, drop, or pause edge for the next logical tick. */
34
+ /** Queues a one-shot cycle, drop, or pause edge for the next logical tick.
35
+ *
36
+ * @param state - The immutable native state to read or transition; the input is retained.
37
+ * @param action - One native action for this entry point; inspect accepted and reason on the result.
38
+ * @returns Queues a one-shot cycle, drop, or pause edge for the next logical tick.
39
+ * @example
40
+ * ```ts
41
+ * import { createInputScheduler, queueInputEdge } from "@johnmorrisdotca/houseki/falling-triplets";
42
+ *
43
+ * const input=createInputScheduler();
44
+ * console.log(queueInputEdge(input,{kind:"hard-drop"}));
45
+ * ```
46
+ */
13
47
  export declare function queueInputEdge(state: InputSchedulerState, action: Action): InputSchedulerState;
14
- /** Resolves canonical actions in the design's per-tick order. */
48
+ /** Resolves canonical actions in the design's per-tick order.
49
+ *
50
+ * @param state - The immutable native state to read or transition; the input is retained.
51
+ * @returns Resolves canonical actions in the design's per-tick order.
52
+ * @example
53
+ * ```ts
54
+ * import { actionsForTick, createInputScheduler } from "@johnmorrisdotca/houseki/falling-triplets";
55
+ *
56
+ * const input=createInputScheduler();
57
+ * console.log(actionsForTick(input)[0]);
58
+ * ```
59
+ */
15
60
  export declare function actionsForTick(state: InputSchedulerState): readonly [readonly Action[], InputSchedulerState];
16
- /** Releases every held action after blur, pause, or pointer cancellation. */
61
+ /** Releases every held action after blur, pause, or pointer cancellation.
62
+ *
63
+ * @param state - The immutable native state to read or transition; the input is retained.
64
+ * @returns Releases every held action after blur, pause, or pointer cancellation.
65
+ * @example
66
+ * ```ts
67
+ * import { createInputScheduler, releaseAllActions } from "@johnmorrisdotca/houseki/falling-triplets";
68
+ *
69
+ * const input=createInputScheduler();
70
+ * console.log(releaseAllActions(input));
71
+ * ```
72
+ */
17
73
  export declare function releaseAllActions(state: InputSchedulerState): InputSchedulerState;
18
74
  export {};
@@ -1,6 +1,28 @@
1
- /** Creates an empty fixed-tick input scheduler state. */
1
+ /** Creates an empty fixed-tick input scheduler state.
2
+ *
3
+ * @returns Creates an empty fixed-tick input scheduler state.
4
+ * @example
5
+ * ```ts
6
+ * import { createInputScheduler } from "@johnmorrisdotca/houseki/falling-triplets";
7
+ *
8
+ * console.log(Object.keys(createInputScheduler()));
9
+ * ```
10
+ */
2
11
  export function createInputScheduler() { return { held: {}, queued: [] }; }
3
- /** Starts or releases one held action; opposite lateral holds cancel during scheduling. */
12
+ /** Starts or releases one held action; opposite lateral holds cancel during scheduling.
13
+ *
14
+ * @param state - The immutable native state to read or transition; the input is retained.
15
+ * @param action - One native action for this entry point; inspect accepted and reason on the result.
16
+ * @param held - Whether this input is currently held.
17
+ * @returns Starts or releases one held action; opposite lateral holds cancel during scheduling.
18
+ * @example
19
+ * ```ts
20
+ * import { createInputScheduler, setHeldAction } from "@johnmorrisdotca/houseki/falling-triplets";
21
+ *
22
+ * const input=createInputScheduler();
23
+ * console.log(setHeldAction(input,"left",true));
24
+ * ```
25
+ */
4
26
  export function setHeldAction(state, action, held) {
5
27
  const next = { ...state.held };
6
28
  if (held) {
@@ -11,13 +33,36 @@ export function setHeldAction(state, action, held) {
11
33
  delete next[action];
12
34
  return { ...state, held: next };
13
35
  }
14
- /** Queues a one-shot cycle, drop, or pause edge for the next logical tick. */
36
+ /** Queues a one-shot cycle, drop, or pause edge for the next logical tick.
37
+ *
38
+ * @param state - The immutable native state to read or transition; the input is retained.
39
+ * @param action - One native action for this entry point; inspect accepted and reason on the result.
40
+ * @returns Queues a one-shot cycle, drop, or pause edge for the next logical tick.
41
+ * @example
42
+ * ```ts
43
+ * import { createInputScheduler, queueInputEdge } from "@johnmorrisdotca/houseki/falling-triplets";
44
+ *
45
+ * const input=createInputScheduler();
46
+ * console.log(queueInputEdge(input,{kind:"hard-drop"}));
47
+ * ```
48
+ */
15
49
  export function queueInputEdge(state, action) {
16
50
  if (!['cycle-forward', 'cycle-backward', 'hard-drop', 'place', 'pause', 'resume'].includes(action.kind))
17
51
  return state;
18
52
  return { ...state, queued: [...state.queued, action] };
19
53
  }
20
- /** Resolves canonical actions in the design's per-tick order. */
54
+ /** Resolves canonical actions in the design's per-tick order.
55
+ *
56
+ * @param state - The immutable native state to read or transition; the input is retained.
57
+ * @returns Resolves canonical actions in the design's per-tick order.
58
+ * @example
59
+ * ```ts
60
+ * import { actionsForTick, createInputScheduler } from "@johnmorrisdotca/houseki/falling-triplets";
61
+ *
62
+ * const input=createInputScheduler();
63
+ * console.log(actionsForTick(input)[0]);
64
+ * ```
65
+ */
21
66
  export function actionsForTick(state) {
22
67
  const actions = [];
23
68
  const held = { ...state.held };
@@ -37,6 +82,17 @@ export function actionsForTick(state) {
37
82
  held[key] = (held[key] ?? 0) + 1;
38
83
  return [actions, { held, queued: [] }];
39
84
  }
40
- /** Releases every held action after blur, pause, or pointer cancellation. */
85
+ /** Releases every held action after blur, pause, or pointer cancellation.
86
+ *
87
+ * @param state - The immutable native state to read or transition; the input is retained.
88
+ * @returns Releases every held action after blur, pause, or pointer cancellation.
89
+ * @example
90
+ * ```ts
91
+ * import { createInputScheduler, releaseAllActions } from "@johnmorrisdotca/houseki/falling-triplets";
92
+ *
93
+ * const input=createInputScheduler();
94
+ * console.log(releaseAllActions(input));
95
+ * ```
96
+ */
41
97
  // eslint-disable-next-line @typescript-eslint/no-unused-vars -- the public signature takes the state a caller holds, though nothing of it is kept
42
98
  export function releaseAllActions(state) { return { held: {}, queued: [] }; }