@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.
- package/CHANGELOG.md +19 -1
- package/README.md +77 -95
- package/dist/colour-chains/challenge.d.ts +12 -1
- package/dist/colour-chains/challenge.js +12 -1
- package/dist/colour-chains/content-types.d.ts +112 -0
- package/dist/colour-chains/content.d.ts +140 -3
- package/dist/colour-chains/content.js +140 -3
- package/dist/colour-chains/engine.d.ts +85 -6
- package/dist/colour-chains/engine.js +85 -6
- package/dist/colour-chains/input.d.ts +97 -7
- package/dist/colour-chains/input.js +97 -7
- package/dist/colour-chains/persistence.d.ts +36 -3
- package/dist/colour-chains/persistence.js +36 -3
- package/dist/colour-chains/types.d.ts +291 -17
- package/dist/colour-chains/validation.d.ts +12 -1
- package/dist/colour-chains/validation.js +12 -1
- package/dist/falling-triplets/content-types.d.ts +69 -0
- package/dist/falling-triplets/content.d.ts +60 -3
- package/dist/falling-triplets/content.js +60 -3
- package/dist/falling-triplets/engine.d.ts +122 -10
- package/dist/falling-triplets/engine.js +122 -10
- package/dist/falling-triplets/input.d.ts +61 -5
- package/dist/falling-triplets/input.js +61 -5
- package/dist/falling-triplets/match.d.ts +26 -2
- package/dist/falling-triplets/match.js +26 -2
- package/dist/falling-triplets/random.d.ts +34 -3
- package/dist/falling-triplets/random.js +34 -3
- package/dist/falling-triplets/types.d.ts +227 -3
- package/dist/gem-swap/content.d.ts +116 -0
- package/dist/gem-swap/content.js +72 -0
- package/dist/gem-swap/engine.d.ts +124 -9
- package/dist/gem-swap/engine.js +124 -9
- package/dist/gem-swap/persistence.d.ts +60 -4
- package/dist/gem-swap/persistence.js +60 -4
- package/dist/gem-swap/types.d.ts +336 -3
- package/dist/magnetic-blocks/content-types.d.ts +56 -0
- package/dist/magnetic-blocks/content.d.ts +91 -5
- package/dist/magnetic-blocks/content.js +91 -5
- package/dist/magnetic-blocks/engine.d.ts +63 -5
- package/dist/magnetic-blocks/engine.js +63 -5
- package/dist/magnetic-blocks/persistence.d.ts +36 -3
- package/dist/magnetic-blocks/persistence.js +36 -3
- package/dist/magnetic-blocks/physics.d.ts +176 -6
- package/dist/magnetic-blocks/physics.js +176 -6
- package/dist/magnetic-blocks/types.d.ts +185 -1
- package/dist/magnetic-blocks/validation.d.ts +12 -0
- package/dist/magnetic-blocks/validation.js +12 -0
- package/dist/nature/attraction.d.ts +24 -2
- package/dist/nature/attraction.js +24 -2
- package/dist/nature/environment.d.ts +200 -7
- package/dist/nature/environment.js +88 -7
- package/dist/nature/marking.d.ts +13 -1
- package/dist/nature/marking.js +13 -1
- package/dist/nature/rebound.d.ts +30 -2
- package/dist/nature/rebound.js +30 -2
- package/dist/nature/state.d.ts +11 -0
- package/dist/nature/state.js +11 -0
- package/dist/nature/types.d.ts +194 -1
- package/dist/nature/validation.d.ts +12 -0
- package/dist/nature/validation.js +12 -0
- package/dist/stone-collapse/content-types.d.ts +69 -0
- package/dist/stone-collapse/content.d.ts +60 -3
- package/dist/stone-collapse/content.js +60 -3
- package/dist/stone-collapse/engine.d.ts +99 -8
- package/dist/stone-collapse/engine.js +99 -8
- package/dist/stone-collapse/persistence.d.ts +36 -3
- package/dist/stone-collapse/persistence.js +36 -3
- package/dist/stone-collapse/types.d.ts +220 -3
- package/dist/stone-collapse/validation.d.ts +12 -1
- package/dist/stone-collapse/validation.js +12 -1
- package/package.json +34 -26
|
@@ -3,7 +3,31 @@ export interface MatchWave {
|
|
|
3
3
|
readonly cells: readonly number[];
|
|
4
4
|
readonly colour: Colour;
|
|
5
5
|
}
|
|
6
|
-
/** Finds the union of every maximal horizontal, vertical, and diagonal run of at least three.
|
|
6
|
+
/** Finds the union of every maximal horizontal, vertical, and diagonal run of at least three.
|
|
7
|
+
*
|
|
8
|
+
* @param board - The row-major native board; null cells are empty or masked.
|
|
9
|
+
* @param width - The native board width in cells.
|
|
10
|
+
* @param height - The native board height in cells.
|
|
11
|
+
* @returns Finds the union of every maximal horizontal, vertical, and diagonal run of at least three.
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { findMatches } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
15
|
+
*
|
|
16
|
+
* console.log(findMatches(Array(72).fill(null),6,12).length);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
7
19
|
export declare function findMatches(board: readonly (Gem | null)[], width: number, height: number): readonly MatchWave[];
|
|
8
|
-
/** Compacts each column downward while preserving the top-to-bottom order of survivors.
|
|
20
|
+
/** Compacts each column downward while preserving the top-to-bottom order of survivors.
|
|
21
|
+
*
|
|
22
|
+
* @param board - The row-major native board; null cells are empty or masked.
|
|
23
|
+
* @param width - The native board width in cells.
|
|
24
|
+
* @param height - The native board height in cells.
|
|
25
|
+
* @returns Compacts each column downward while preserving the top-to-bottom order of survivors. Nested null values denote empty board cells, absent active pieces, unselected tools or outcomes not yet reached; optional undefined fields are absent until applicable.
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { compactBoard } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
29
|
+
*
|
|
30
|
+
* console.log(compactBoard(Array(72).fill(null),6,12).length);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
9
33
|
export declare function compactBoard(board: readonly (Gem | null)[], width: number, height: number): readonly (Gem | null)[];
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
/** Finds the union of every maximal horizontal, vertical, and diagonal run of at least three.
|
|
1
|
+
/** Finds the union of every maximal horizontal, vertical, and diagonal run of at least three.
|
|
2
|
+
*
|
|
3
|
+
* @param board - The row-major native board; null cells are empty or masked.
|
|
4
|
+
* @param width - The native board width in cells.
|
|
5
|
+
* @param height - The native board height in cells.
|
|
6
|
+
* @returns Finds the union of every maximal horizontal, vertical, and diagonal run of at least three.
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { findMatches } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
10
|
+
*
|
|
11
|
+
* console.log(findMatches(Array(72).fill(null),6,12).length);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
2
14
|
export function findMatches(board, width, height) {
|
|
3
15
|
const directions = [[1, 0], [0, 1], [1, 1], [1, -1]];
|
|
4
16
|
const found = new Map();
|
|
@@ -28,7 +40,19 @@ export function findMatches(board, width, height) {
|
|
|
28
40
|
}
|
|
29
41
|
return [...found].map(([colour, cells]) => ({ colour, cells: [...cells].sort((a, b) => a - b) }));
|
|
30
42
|
}
|
|
31
|
-
/** Compacts each column downward while preserving the top-to-bottom order of survivors.
|
|
43
|
+
/** Compacts each column downward while preserving the top-to-bottom order of survivors.
|
|
44
|
+
*
|
|
45
|
+
* @param board - The row-major native board; null cells are empty or masked.
|
|
46
|
+
* @param width - The native board width in cells.
|
|
47
|
+
* @param height - The native board height in cells.
|
|
48
|
+
* @returns Compacts each column downward while preserving the top-to-bottom order of survivors. Nested null values denote empty board cells, absent active pieces, unselected tools or outcomes not yet reached; optional undefined fields are absent until applicable.
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { compactBoard } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
52
|
+
*
|
|
53
|
+
* console.log(compactBoard(Array(72).fill(null),6,12).length);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
32
56
|
export function compactBoard(board, width, height) {
|
|
33
57
|
const result = Array(width * height).fill(null);
|
|
34
58
|
for (let x = 0; x < width; x++) {
|
|
@@ -1,9 +1,40 @@
|
|
|
1
1
|
import type { Colour } from './types.js';
|
|
2
|
-
/** Hashes a string seed with UTF-8 FNV-1a and returns a nonzero uint32 state.
|
|
2
|
+
/** Hashes a string seed with UTF-8 FNV-1a and returns a nonzero uint32 state.
|
|
3
|
+
*
|
|
4
|
+
* @param seed - A string seed hashed into a nonzero deterministic random state.
|
|
5
|
+
* @returns Hashes a string seed with UTF-8 FNV-1a and returns a nonzero uint32 state.
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { seedState } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
9
|
+
*
|
|
10
|
+
* console.log(seedState("docs"));
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
3
13
|
export declare function seedState(seed: string): number;
|
|
4
|
-
/** Advances the reference xorshift32 source.
|
|
14
|
+
/** Advances the reference xorshift32 source.
|
|
15
|
+
*
|
|
16
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
17
|
+
* @returns Advances the reference xorshift32 source.
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { nextUint32, seedState } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
21
|
+
*
|
|
22
|
+
* console.log(nextUint32(seedState("docs")));
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
5
25
|
export declare function nextUint32(state: number): readonly [number, number];
|
|
6
|
-
/** Draws an unbiased integer and updated state using rejection sampling.
|
|
26
|
+
/** Draws an unbiased integer and updated state using rejection sampling.
|
|
27
|
+
*
|
|
28
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
29
|
+
* @param n - The positive upper bound of the integer draw; the result is below this bound.
|
|
30
|
+
* @returns Draws an unbiased integer and updated state using rejection sampling.
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { nextInt, seedState } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
34
|
+
*
|
|
35
|
+
* console.log(nextInt(seedState("docs"),6));
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
7
38
|
export declare function nextInt(state: number, n: number): readonly [number, number];
|
|
8
39
|
/** Creates a shuffled bag with three of each available colour. */
|
|
9
40
|
export declare function drawBag(bag: readonly Colour[], state: number, count: 4 | 5 | 6): readonly [readonly Colour[], number];
|
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
const COLOURS = ['red', 'blue', 'green', 'gold', 'purple', 'teal'];
|
|
2
|
-
/** Hashes a string seed with UTF-8 FNV-1a and returns a nonzero uint32 state.
|
|
2
|
+
/** Hashes a string seed with UTF-8 FNV-1a and returns a nonzero uint32 state.
|
|
3
|
+
*
|
|
4
|
+
* @param seed - A string seed hashed into a nonzero deterministic random state.
|
|
5
|
+
* @returns Hashes a string seed with UTF-8 FNV-1a and returns a nonzero uint32 state.
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { seedState } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
9
|
+
*
|
|
10
|
+
* console.log(seedState("docs"));
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
3
13
|
export function seedState(seed) {
|
|
4
14
|
let hash = 0x811c9dc5;
|
|
5
15
|
for (const byte of new TextEncoder().encode(seed))
|
|
6
16
|
hash = Math.imul(hash ^ byte, 0x01000193) >>> 0;
|
|
7
17
|
return hash || 0x6d2b79f5;
|
|
8
18
|
}
|
|
9
|
-
/** Advances the reference xorshift32 source.
|
|
19
|
+
/** Advances the reference xorshift32 source.
|
|
20
|
+
*
|
|
21
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
22
|
+
* @returns Advances the reference xorshift32 source.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { nextUint32, seedState } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
26
|
+
*
|
|
27
|
+
* console.log(nextUint32(seedState("docs")));
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
10
30
|
export function nextUint32(state) {
|
|
11
31
|
let next = state >>> 0;
|
|
12
32
|
next ^= next << 13;
|
|
@@ -15,7 +35,18 @@ export function nextUint32(state) {
|
|
|
15
35
|
next >>>= 0;
|
|
16
36
|
return [next, next];
|
|
17
37
|
}
|
|
18
|
-
/** Draws an unbiased integer and updated state using rejection sampling.
|
|
38
|
+
/** Draws an unbiased integer and updated state using rejection sampling.
|
|
39
|
+
*
|
|
40
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
41
|
+
* @param n - The positive upper bound of the integer draw; the result is below this bound.
|
|
42
|
+
* @returns Draws an unbiased integer and updated state using rejection sampling.
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { nextInt, seedState } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
46
|
+
*
|
|
47
|
+
* console.log(nextInt(seedState("docs"),6));
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
19
50
|
export function nextInt(state, n) {
|
|
20
51
|
if (!Number.isInteger(n) || n < 1 || n > 0x100000000)
|
|
21
52
|
throw new RangeError('n must be an integer from 1 to 2^32');
|
|
@@ -1,13 +1,65 @@
|
|
|
1
|
-
/** A gem colour ID.
|
|
1
|
+
/** A gem colour ID.
|
|
2
|
+
*
|
|
3
|
+
* @example
|
|
4
|
+
* ```ts
|
|
5
|
+
* import type { Colour } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
6
|
+
*
|
|
7
|
+
* const value: Colour = "red";
|
|
8
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
2
11
|
export type Colour = 'red' | 'blue' | 'green' | 'gold' | 'purple' | 'teal';
|
|
3
|
-
/** A settled or active gem with a stable run-local identity.
|
|
12
|
+
/** A settled or active gem with a stable run-local identity.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import type { Gem } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
17
|
+
*
|
|
18
|
+
* const value: Gem = {id:1,colour:"red"};
|
|
19
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
4
22
|
export interface Gem {
|
|
5
23
|
readonly id: number;
|
|
6
24
|
readonly colour: Colour;
|
|
7
25
|
readonly target?: boolean;
|
|
8
26
|
}
|
|
27
|
+
/** The native game mode; authored challenges have fixed setup and queue rules.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import type { Mode } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
32
|
+
*
|
|
33
|
+
* const value: Mode = "relaxed";
|
|
34
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
9
37
|
export type Mode = 'relaxed' | 'arcade' | 'daily' | 'challenge';
|
|
38
|
+
/** The native falling, resolution, pause and ending phases.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
43
|
+
* import type { Phase } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
44
|
+
*
|
|
45
|
+
* const state=createGame({seed:"docs"});
|
|
46
|
+
* const value: Phase = state.phase;
|
|
47
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
10
50
|
export type Phase = 'falling' | 'clear-mark' | 'clear-remove' | 'gravity' | 'paused' | 'won' | 'lost' | 'finished';
|
|
51
|
+
/** The native falling triplet with stable gem ids, orientation, descent and lock counters.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
56
|
+
* import type { Piece } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
57
|
+
*
|
|
58
|
+
* const state=createGame({seed:"docs"});
|
|
59
|
+
* const value: Piece = state.active!;
|
|
60
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
11
63
|
export interface Piece {
|
|
12
64
|
readonly gems: readonly [Gem, Gem, Gem];
|
|
13
65
|
readonly x: number;
|
|
@@ -19,6 +71,18 @@ export interface Piece {
|
|
|
19
71
|
readonly lockResets: number;
|
|
20
72
|
readonly lockStarted: boolean;
|
|
21
73
|
}
|
|
74
|
+
/** Validated settings fixed at native game creation.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
79
|
+
* import type { Settings } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
80
|
+
*
|
|
81
|
+
* const state=createGame({seed:"docs"});
|
|
82
|
+
* const value: Settings = state.settings;
|
|
83
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
22
86
|
export interface Settings {
|
|
23
87
|
readonly mode: Mode;
|
|
24
88
|
readonly width: number;
|
|
@@ -33,35 +97,129 @@ export interface Settings {
|
|
|
33
97
|
readonly challengeQueue?: readonly Triplet[];
|
|
34
98
|
readonly witness?: readonly ChallengeHint[];
|
|
35
99
|
}
|
|
100
|
+
/** Three ordered gem colours composing one falling triplet.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* import type { Triplet } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
105
|
+
*
|
|
106
|
+
* const value: Triplet = ["red","green","blue"];
|
|
107
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
36
110
|
export type Triplet = readonly [Colour, Colour, Colour];
|
|
111
|
+
/** A Falling Triplets objective requiring the supplied stable target ids to be cleared.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* import type { ChallengeGoalTargets } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
116
|
+
*
|
|
117
|
+
* const value: ChallengeGoalTargets = {type:"targets",targetIds:[1]};
|
|
118
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
37
121
|
export interface ChallengeGoalTargets {
|
|
38
122
|
readonly type: 'targets';
|
|
39
123
|
readonly targetIds: readonly number[];
|
|
40
124
|
}
|
|
125
|
+
/** A Falling Triplets objective requiring at least the supplied chain depth.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* import type { ChallengeGoalChain } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
130
|
+
*
|
|
131
|
+
* const value: ChallengeGoalChain = {type:"chain",minimumChain:2};
|
|
132
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
41
135
|
export interface ChallengeGoalChain {
|
|
42
136
|
readonly type: 'chain';
|
|
43
137
|
readonly minimumChain: number;
|
|
44
138
|
}
|
|
139
|
+
/** A Falling Triplets objective requiring an empty board.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* import type { ChallengeGoalEmpty } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
144
|
+
*
|
|
145
|
+
* const value: ChallengeGoalEmpty = {type:"empty"};
|
|
146
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
45
149
|
export interface ChallengeGoalEmpty {
|
|
46
150
|
readonly type: 'empty';
|
|
47
151
|
}
|
|
152
|
+
/** A native authored challenge objective; its discriminant selects target, chain, empty-board or score requirements.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* import type { ChallengeGoal } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
157
|
+
*
|
|
158
|
+
* const value: ChallengeGoal = {type:"empty"};
|
|
159
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
48
162
|
export type ChallengeGoal = ChallengeGoalTargets | ChallengeGoalChain | ChallengeGoalEmpty;
|
|
163
|
+
/** One witnessed Falling Triplets placement with a column and cycle orientation.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* import type { ChallengeHint } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
168
|
+
*
|
|
169
|
+
* const value: ChallengeHint = {x:0,orientation:0};
|
|
170
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
49
173
|
export interface ChallengeHint {
|
|
50
174
|
readonly x: number;
|
|
51
175
|
readonly orientation: 0 | 1 | 2;
|
|
52
176
|
}
|
|
177
|
+
/** The fixed Falling Triplets challenge settings with the original board and finite triplet queue.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
182
|
+
* import type { ChallengeSettings } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
183
|
+
*
|
|
184
|
+
* const state=createGame({seed:"docs"});
|
|
185
|
+
* const value: ChallengeSettings = {...state.settings,mode:"challenge",goal:"empty",challengeBoard:state.board,challengeQueue:[["red","green","blue"]]};
|
|
186
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
53
189
|
export interface ChallengeSettings extends Settings {
|
|
54
190
|
readonly mode: 'challenge';
|
|
55
191
|
readonly goal: ChallengeGoal['type'];
|
|
56
192
|
readonly challengeBoard: readonly (Gem | null)[];
|
|
57
193
|
readonly challengeQueue: readonly Triplet[];
|
|
58
194
|
}
|
|
195
|
+
/** One simultaneous native match wave, its cleared cells and chain score.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* import type { Wave } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
200
|
+
*
|
|
201
|
+
* const value: Wave = {chain:1,cells:[],points:0,clearedIds:[]};
|
|
202
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
59
205
|
export interface Wave {
|
|
60
206
|
readonly clearedIds: readonly number[];
|
|
61
207
|
readonly cells: readonly number[];
|
|
62
208
|
readonly chain: number;
|
|
63
209
|
readonly points: number;
|
|
64
210
|
}
|
|
211
|
+
/** The immutable authoritative native game state, including its board, random state and recording.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```ts
|
|
215
|
+
* import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
216
|
+
* import type { GameState } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
217
|
+
*
|
|
218
|
+
* const state=createGame({seed:"docs"});
|
|
219
|
+
* const value: GameState = state;
|
|
220
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
65
223
|
export interface GameState {
|
|
66
224
|
readonly game: 'falling-triplets';
|
|
67
225
|
readonly rules: 'triplets-1';
|
|
@@ -92,16 +250,50 @@ export interface GameState {
|
|
|
92
250
|
readonly recording: readonly RecordedAction[];
|
|
93
251
|
readonly reason?: string;
|
|
94
252
|
}
|
|
253
|
+
/** A native player action accepted or rejected according to the current phase and rules.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* import type { Action } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
258
|
+
*
|
|
259
|
+
* const action: Action={kind:"left"};
|
|
260
|
+
* const value: Action = action;
|
|
261
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
95
264
|
export type Action = {
|
|
96
265
|
readonly kind: 'left' | 'right' | 'soft-drop' | 'hard-drop' | 'place' | 'cycle-forward' | 'cycle-backward' | 'pause' | 'resume' | 'hint' | 'tick';
|
|
97
266
|
};
|
|
267
|
+
/** The resulting native state, emitted events and acceptance decision; rejected actions preserve the input.
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* import { applyAction, createGame } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
272
|
+
* import type { Action, Transition } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
273
|
+
*
|
|
274
|
+
* const state=createGame({seed:"docs"});
|
|
275
|
+
* const action: Action={kind:"left"};
|
|
276
|
+
* const value: Transition = applyAction(state,action);
|
|
277
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
98
280
|
export interface Transition {
|
|
99
281
|
readonly state: GameState;
|
|
100
282
|
readonly events: readonly GameEvent[];
|
|
101
283
|
readonly accepted: boolean;
|
|
102
284
|
readonly reason?: string;
|
|
103
285
|
}
|
|
104
|
-
/** One accepted canonical action and its logical tick position.
|
|
286
|
+
/** One accepted canonical action and its logical tick position.
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* import type { Action, RecordedAction } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
291
|
+
*
|
|
292
|
+
* const action: Action={kind:"left"};
|
|
293
|
+
* const value: RecordedAction = {tick:0,ordinal:0,action};
|
|
294
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
105
297
|
export interface RecordedAction {
|
|
106
298
|
readonly tick: number;
|
|
107
299
|
readonly ordinal: number;
|
|
@@ -109,10 +301,30 @@ export interface RecordedAction {
|
|
|
109
301
|
readonly kind: 'tick';
|
|
110
302
|
}>;
|
|
111
303
|
}
|
|
304
|
+
/** An event emitted by one native transition; type selects the event’s additional fields.
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```ts
|
|
308
|
+
* import type { GameEvent } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
309
|
+
*
|
|
310
|
+
* const value: GameEvent = {type:"host-example"};
|
|
311
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
112
314
|
export interface GameEvent {
|
|
113
315
|
readonly type: string;
|
|
114
316
|
readonly [key: string]: unknown;
|
|
115
317
|
}
|
|
318
|
+
/** Creation settings for this native engine; dimensions, mode, seed and optional mechanics are validated together.
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```ts
|
|
322
|
+
* import type { CreateOptions } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
323
|
+
*
|
|
324
|
+
* const value: CreateOptions = {seed:"docs"};
|
|
325
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
116
328
|
export interface CreateOptions {
|
|
117
329
|
readonly mode?: Exclude<Mode, 'challenge'>;
|
|
118
330
|
readonly seed?: string;
|
|
@@ -122,6 +334,18 @@ export interface CreateOptions {
|
|
|
122
334
|
readonly colourCount?: 4 | 5 | 6;
|
|
123
335
|
readonly pieceLimit?: number;
|
|
124
336
|
}
|
|
337
|
+
/** Authored challenge inputs including the starting board, finite goal and supplied witness.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```ts
|
|
341
|
+
* import { createGame } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
342
|
+
* import type { ChallengeOptions } from "@johnmorrisdotca/houseki/falling-triplets";
|
|
343
|
+
*
|
|
344
|
+
* const state=createGame({seed:"docs"});
|
|
345
|
+
* const value: ChallengeOptions = {width:6,height:12,board:state.board,queue:[["red","green","blue"]],goal:{type:"empty"}};
|
|
346
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
125
349
|
export interface ChallengeOptions {
|
|
126
350
|
readonly seed?: string;
|
|
127
351
|
readonly width?: number;
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import type { Action, CreateOptions, ReplayOperation } from './types.js';
|
|
2
|
+
/** The existing campaign’s human-review-pending status; an engine witness is not human review.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import type { GemSwapReviewStatus } from "@johnmorrisdotca/houseki/gem-swap";
|
|
7
|
+
*
|
|
8
|
+
* const value: GemSwapReviewStatus = "human-review-pending";
|
|
9
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
2
12
|
export type GemSwapReviewStatus = 'human-review-pending';
|
|
13
|
+
/** One authored native challenge with its stable id, setup, winning witness, measurements and review status.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { GEM_SWAP_CAMPAIGN } from "@johnmorrisdotca/houseki/gem-swap";
|
|
18
|
+
* import type { GemSwapCampaignLevel } from "@johnmorrisdotca/houseki/gem-swap";
|
|
19
|
+
*
|
|
20
|
+
* const level=GEM_SWAP_CAMPAIGN[0];
|
|
21
|
+
* const value: GemSwapCampaignLevel = level;
|
|
22
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
3
25
|
export interface GemSwapCampaignLevel {
|
|
4
26
|
readonly id: string;
|
|
5
27
|
readonly number: number;
|
|
@@ -23,6 +45,17 @@ export interface GemSwapCampaignLevel {
|
|
|
23
45
|
readonly proofStatus: 'engine-witness-verified';
|
|
24
46
|
readonly reviewStatus: GemSwapReviewStatus;
|
|
25
47
|
}
|
|
48
|
+
/** One bilingual native lesson instruction and the corresponding action or tick step.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import type { GemSwapLessonStep } from "@johnmorrisdotca/houseki/gem-swap";
|
|
53
|
+
* import { GEM_SWAP_LESSONS } from "@johnmorrisdotca/houseki/gem-swap";
|
|
54
|
+
*
|
|
55
|
+
* const value: GemSwapLessonStep = GEM_SWAP_LESSONS[0].steps[0];
|
|
56
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
26
59
|
export type GemSwapLessonStep = {
|
|
27
60
|
readonly kind: 'action';
|
|
28
61
|
readonly id: string;
|
|
@@ -47,6 +80,17 @@ export type GemSwapLessonStep = {
|
|
|
47
80
|
readonly ja: string;
|
|
48
81
|
};
|
|
49
82
|
};
|
|
83
|
+
/** One bilingual native lesson with its authored setup, teaching steps and winning witness.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* import type { GemSwapLesson } from "@johnmorrisdotca/houseki/gem-swap";
|
|
88
|
+
* import { GEM_SWAP_LESSONS } from "@johnmorrisdotca/houseki/gem-swap";
|
|
89
|
+
*
|
|
90
|
+
* const value: GemSwapLesson = GEM_SWAP_LESSONS[0];
|
|
91
|
+
* console.log(value == null ? value : typeof value === "object" ? Object.keys(value).slice(0,6) : value);
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
50
94
|
export interface GemSwapLesson {
|
|
51
95
|
readonly id: string;
|
|
52
96
|
readonly title: {
|
|
@@ -58,9 +102,45 @@ export interface GemSwapLesson {
|
|
|
58
102
|
readonly witness: readonly ReplayOperation[];
|
|
59
103
|
readonly reviewStatus: GemSwapReviewStatus;
|
|
60
104
|
}
|
|
105
|
+
/** The stored Gem Swap campaign generation revision.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* import { GENERATION_REVISION } from "@johnmorrisdotca/houseki/gem-swap";
|
|
110
|
+
*
|
|
111
|
+
* console.log(GENERATION_REVISION);
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
61
114
|
export declare const GENERATION_REVISION = "gem-swap-campaign-1.3.0";
|
|
115
|
+
/** The measurement/normalization revision used to grade Gem Swap challenges.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* import { GRADING_VERSION } from "@johnmorrisdotca/houseki/gem-swap";
|
|
120
|
+
*
|
|
121
|
+
* console.log(GRADING_VERSION);
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
62
124
|
export declare const GRADING_VERSION = "swap-choice-forgiveness-1";
|
|
125
|
+
/** The fixed number of seeded playout samples used in the stored Gem Swap grading.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* import { SAMPLE_BUDGET } from "@johnmorrisdotca/houseki/gem-swap";
|
|
130
|
+
*
|
|
131
|
+
* console.log(SAMPLE_BUDGET);
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
63
134
|
export declare const SAMPLE_BUDGET = 24;
|
|
135
|
+
/** The bounded Gem Swap metric weights used in the recorded grading formula.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* import { GRADING_WEIGHTS } from "@johnmorrisdotca/houseki/gem-swap";
|
|
140
|
+
*
|
|
141
|
+
* console.log(Object.keys(GRADING_WEIGHTS));
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
64
144
|
export declare const GRADING_WEIGHTS: {
|
|
65
145
|
seededPlayoutDifficulty: number;
|
|
66
146
|
choiceDifficulty: number;
|
|
@@ -69,7 +149,43 @@ export declare const GRADING_WEIGHTS: {
|
|
|
69
149
|
witnessLength: number;
|
|
70
150
|
specialCombination: number;
|
|
71
151
|
};
|
|
152
|
+
/** The stored Gem Swap campaign content fingerprint.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* import { CAMPAIGN_CHECKSUM } from "@johnmorrisdotca/houseki/gem-swap";
|
|
157
|
+
*
|
|
158
|
+
* console.log(CAMPAIGN_CHECKSUM);
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
72
161
|
export declare const CAMPAIGN_CHECKSUM = "eb7c54a583db428d596b8fbdab0d63a9ad39ad5b9e39948dc4ccab84ba1196aa";
|
|
162
|
+
/** The number of stored Gem Swap campaign challenges.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* import { CAMPAIGN_COUNT } from "@johnmorrisdotca/houseki/gem-swap";
|
|
167
|
+
*
|
|
168
|
+
* console.log(CAMPAIGN_COUNT);
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
73
171
|
export declare const CAMPAIGN_COUNT = 50;
|
|
172
|
+
/** The frozen measured Gem Swap challenges with stable ids, setups, witnesses and review status.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* import { GEM_SWAP_CAMPAIGN } from "@johnmorrisdotca/houseki/gem-swap";
|
|
177
|
+
*
|
|
178
|
+
* console.log(GEM_SWAP_CAMPAIGN.length);
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
74
181
|
export declare const GEM_SWAP_CAMPAIGN: readonly GemSwapCampaignLevel[];
|
|
182
|
+
/** The frozen bilingual Gem Swap lessons with setup, teaching steps and witnesses.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* import { GEM_SWAP_LESSONS } from "@johnmorrisdotca/houseki/gem-swap";
|
|
187
|
+
*
|
|
188
|
+
* console.log(GEM_SWAP_LESSONS.length);
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
75
191
|
export declare const GEM_SWAP_LESSONS: readonly GemSwapLesson[];
|