@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
|
@@ -8,20 +8,103 @@ 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/colour-chains";
|
|
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/colour-chains";
|
|
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/colour-chains";
|
|
36
|
+
*
|
|
37
|
+
* console.log(tutorialManifest.length);
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
13
40
|
export const tutorialManifest = deepFreeze(contentData.tutorials);
|
|
41
|
+
/** The ordered native campaign, its generation/grading revisions, checksum and measured levels.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { shizenCampaignManifest } from "@johnmorrisdotca/houseki/colour-chains";
|
|
46
|
+
*
|
|
47
|
+
* console.log(shizenCampaignManifest.count);
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
14
50
|
export const shizenCampaignManifest = deepFreeze((contentData.shizen ?? { ...contentData.campaign, count: 0, levels: [], checksum: '' }));
|
|
51
|
+
/** The frozen ordered native levels; array indices start at zero and display numbers start at one.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { shizenLevelManifest } from "@johnmorrisdotca/houseki/colour-chains";
|
|
56
|
+
*
|
|
57
|
+
* console.log(shizenLevelManifest.length);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
15
60
|
export const shizenLevelManifest = shizenCampaignManifest.levels;
|
|
61
|
+
/** The ordered native campaign, its generation/grading revisions, checksum and measured levels.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import { arashiCampaignManifest } from "@johnmorrisdotca/houseki/colour-chains";
|
|
66
|
+
*
|
|
67
|
+
* console.log(arashiCampaignManifest.count);
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
16
70
|
export const arashiCampaignManifest = deepFreeze((contentData.arashi ?? { ...contentData.campaign, count: 0, levels: [], checksum: '' }));
|
|
71
|
+
/** The frozen ordered native levels; array indices start at zero and display numbers start at one.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { arashiLevelManifest } from "@johnmorrisdotca/houseki/colour-chains";
|
|
76
|
+
*
|
|
77
|
+
* console.log(arashiLevelManifest.length);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
17
80
|
export const arashiLevelManifest = arashiCampaignManifest.levels;
|
|
18
|
-
/** Find a campaign challenge by stable content ID or its current one-based number.
|
|
81
|
+
/** Find a campaign challenge by stable content ID or its current one-based number.
|
|
82
|
+
*
|
|
83
|
+
* @param id - A stable content id, or the one-based display number when numbers are accepted.
|
|
84
|
+
* @returns Find a campaign challenge by stable content ID or its current one-based number. Returns undefined when the id or display number is absent.
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* import { getLevel } from "@johnmorrisdotca/houseki/colour-chains";
|
|
88
|
+
*
|
|
89
|
+
* console.log(getLevel(1)?.id);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
19
92
|
export function getLevel(id) {
|
|
20
93
|
if (typeof id === 'number')
|
|
21
94
|
return Number.isInteger(id) ? levelManifest.find(level => level.number === id) : undefined;
|
|
22
95
|
return levelManifest.find(level => level.id === id);
|
|
23
96
|
}
|
|
24
|
-
/** Create a fresh engine-validated challenge from a stable content ID or display number.
|
|
97
|
+
/** Create a fresh engine-validated challenge from a stable content ID or display number.
|
|
98
|
+
*
|
|
99
|
+
* @param id - A stable content id, or the one-based display number when numbers are accepted.
|
|
100
|
+
* @returns Create a fresh engine-validated challenge from a stable content ID or display number.
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { createLevel } from "@johnmorrisdotca/houseki/colour-chains";
|
|
104
|
+
*
|
|
105
|
+
* console.log(createLevel(1).phase);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
25
108
|
export function createLevel(id) {
|
|
26
109
|
const level = getLevel(id);
|
|
27
110
|
if (!level)
|
|
@@ -31,11 +114,65 @@ export function createLevel(id) {
|
|
|
31
114
|
function createNatureLevel(level) {
|
|
32
115
|
return createChallenge({ id: level.id, seed: level.seed, width: level.width, height: level.height, colourCount: level.colourCount, board: level.board, queue: level.queue, goal: level.goal, witness: level.witness, nature: true, ...(level.weather ? { weather: level.weather } : {}), ...(level.magneticQueue ? { magneticQueue: level.magneticQueue } : {}) });
|
|
33
116
|
}
|
|
117
|
+
/** Find a native Shizen challenge by stable id or one-based display number.
|
|
118
|
+
*
|
|
119
|
+
* @param id - A stable content id, or the one-based display number when numbers are accepted.
|
|
120
|
+
* @returns Find a native Shizen challenge by stable id or one-based display number. Returns undefined when the id or display number is absent.
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* import { getShizenLevel } from "@johnmorrisdotca/houseki/colour-chains";
|
|
124
|
+
*
|
|
125
|
+
* console.log(getShizenLevel(1)?.id);
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
34
128
|
export function getShizenLevel(id) { return typeof id === 'number' ? shizenLevelManifest.find(level => level.number === id) : shizenLevelManifest.find(level => level.id === id); }
|
|
129
|
+
/** Create a validated native Shizen challenge using its stored setup and winning witness.
|
|
130
|
+
*
|
|
131
|
+
* @param id - A stable content id, or the one-based display number when numbers are accepted.
|
|
132
|
+
* @returns Create a validated native Shizen challenge using its stored setup and winning witness.
|
|
133
|
+
* @example
|
|
134
|
+
* ```ts
|
|
135
|
+
* import { createShizenLevel } from "@johnmorrisdotca/houseki/colour-chains";
|
|
136
|
+
*
|
|
137
|
+
* console.log(createShizenLevel(1).phase);
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
35
140
|
export function createShizenLevel(id) { const level = getShizenLevel(id); if (!level)
|
|
36
141
|
throw new RangeError(`Unknown Shizen Colour Chains level: ${String(id)}`); return createNatureLevel(level); }
|
|
142
|
+
/** Find a native Arashi challenge by stable id or one-based display number.
|
|
143
|
+
*
|
|
144
|
+
* @param id - A stable content id, or the one-based display number when numbers are accepted.
|
|
145
|
+
* @returns Find a native Arashi challenge by stable id or one-based display number. Returns undefined when the id or display number is absent.
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* import { getArashiLevel } from "@johnmorrisdotca/houseki/colour-chains";
|
|
149
|
+
*
|
|
150
|
+
* console.log(getArashiLevel(1)?.id);
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
37
153
|
export function getArashiLevel(id) { return typeof id === 'number' ? arashiLevelManifest.find(level => level.number === id) : arashiLevelManifest.find(level => level.id === id); }
|
|
154
|
+
/** Create a validated native Arashi challenge using its stored setup and winning witness.
|
|
155
|
+
*
|
|
156
|
+
* @param id - A stable content id, or the one-based display number when numbers are accepted.
|
|
157
|
+
* @returns Create a validated native Arashi challenge using its stored setup and winning witness.
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { createArashiLevel } from "@johnmorrisdotca/houseki/colour-chains";
|
|
161
|
+
*
|
|
162
|
+
* console.log(createArashiLevel(1).phase);
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
38
165
|
export function createArashiLevel(id) { const level = getArashiLevel(id); if (!level)
|
|
39
166
|
throw new RangeError(`Unknown Arashi Colour Chains level: ${String(id)}`); return createNatureLevel(level); }
|
|
40
|
-
/** Find a persistent interactive lesson by its stable ID.
|
|
167
|
+
/** Find a persistent interactive lesson by its stable ID.
|
|
168
|
+
*
|
|
169
|
+
* @param id - A stable content id, or the one-based display number when numbers are accepted.
|
|
170
|
+
* @returns Find a persistent interactive lesson by its stable ID. Returns undefined when the id or display number is absent.
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* import { getTutorial, tutorialManifest } from "@johnmorrisdotca/houseki/colour-chains";
|
|
174
|
+
*
|
|
175
|
+
* console.log(getTutorial(tutorialManifest[0].id)?.id);
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
41
178
|
export function getTutorial(id) { return tutorialManifest.find(tutorial => tutorial.id === id); }
|
|
@@ -1,12 +1,60 @@
|
|
|
1
1
|
import type { Action, ChainsPowerDropPreview, Colour, CreateOptions, GameState, GameStatus, Gem, Landing, Settings, Transition } from './types.js';
|
|
2
2
|
export { StoneChainsOptionsError } from './validation.js';
|
|
3
|
-
/** Applies one immutable accepted action and records its logical-tick position.
|
|
3
|
+
/** Applies one immutable accepted action and records its logical-tick position.
|
|
4
|
+
*
|
|
5
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
6
|
+
* @param action - One native action for this entry point; inspect accepted and reason on the result.
|
|
7
|
+
* @returns Applies one immutable accepted action and records its logical-tick position.
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { applyAction, createGame } from "@johnmorrisdotca/houseki/colour-chains";
|
|
11
|
+
* import type { Action } from "@johnmorrisdotca/houseki/colour-chains";
|
|
12
|
+
*
|
|
13
|
+
* const state=createGame({seed:"docs"});
|
|
14
|
+
* const action: Action={kind:"left"};
|
|
15
|
+
* console.log(applyAction(state,action).accepted);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
4
18
|
export declare function applyAction(state: GameState, action: Action): Transition;
|
|
5
|
-
/** Advances deterministic 60 Hz simulation and resolution; Relaxed and Challenges do not force a falling clock.
|
|
19
|
+
/** Advances deterministic 60 Hz simulation and resolution; Relaxed and Challenges do not force a falling clock.
|
|
20
|
+
*
|
|
21
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
22
|
+
* @param ticks - The nonnegative number of fixed 60 Hz logical ticks to advance.
|
|
23
|
+
* @returns Advances deterministic 60 Hz simulation and resolution; Relaxed and Challenges do not force a falling clock.
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { advanceTicks, createGame } from "@johnmorrisdotca/houseki/colour-chains";
|
|
27
|
+
*
|
|
28
|
+
* const state=createGame({seed:"docs"});
|
|
29
|
+
* console.log(advanceTicks(state,1).state.phase);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
6
32
|
export declare function advanceTicks(state: GameState, ticks: number): Transition;
|
|
7
|
-
/** Lists only actions accepted by the current game state.
|
|
33
|
+
/** Lists only actions accepted by the current game state.
|
|
34
|
+
*
|
|
35
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
36
|
+
* @returns Lists only actions accepted by the current game state.
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { createGame, legalActions } from "@johnmorrisdotca/houseki/colour-chains";
|
|
40
|
+
*
|
|
41
|
+
* const state=createGame({seed:"docs"});
|
|
42
|
+
* console.log(legalActions(state).length);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
8
45
|
export declare function legalActions(state: GameState): readonly Action[];
|
|
9
|
-
/** Returns the exact independent landing cells for the current rigid pair without consuming random values.
|
|
46
|
+
/** Returns the exact independent landing cells for the current rigid pair without consuming random values.
|
|
47
|
+
*
|
|
48
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
49
|
+
* @returns Returns the exact independent landing cells for the current rigid pair without consuming random values. Returns null when there is no active piece or applicable preview.
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { createGame, landingCells } from "@johnmorrisdotca/houseki/colour-chains";
|
|
53
|
+
*
|
|
54
|
+
* const state=createGame({seed:"docs"});
|
|
55
|
+
* console.log(landingCells(state));
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
10
58
|
export declare function landingCells(state: GameState): Landing | null;
|
|
11
59
|
/**
|
|
12
60
|
* Returns the Shizen hard-drop landing and one-step rebound preview without changing state.
|
|
@@ -15,11 +63,42 @@ export declare function landingCells(state: GameState): Landing | null;
|
|
|
15
63
|
* gap then fall, so `settledCells` is where each stone of the pair comes to rest in the board the hard drop commits,
|
|
16
64
|
* before any clear: draw a ghost from it. Both carry the pair's stable stone ids, and both are checked against
|
|
17
65
|
* `applyAction` with a `hard-drop` over many played boards.
|
|
66
|
+
*
|
|
67
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
68
|
+
* @returns Returns the Shizen hard-drop landing and one-step rebound preview without changing state. Returns null when there is no active piece or applicable preview.
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { createGame, powerDropPreview } from "@johnmorrisdotca/houseki/colour-chains";
|
|
72
|
+
*
|
|
73
|
+
* const state=createGame({seed:"docs"});
|
|
74
|
+
* console.log(powerDropPreview(state));
|
|
75
|
+
* ```
|
|
18
76
|
*/
|
|
19
77
|
export declare function powerDropPreview(state: GameState): ChainsPowerDropPreview | null;
|
|
20
|
-
/** Returns score, mode, chain and completion fields derived from state.
|
|
78
|
+
/** Returns score, mode, chain and completion fields derived from state.
|
|
79
|
+
*
|
|
80
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
81
|
+
* @returns Returns score, mode, chain and completion fields derived from state.
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { createGame, statusOf } from "@johnmorrisdotca/houseki/colour-chains";
|
|
85
|
+
*
|
|
86
|
+
* const state=createGame({seed:"docs"});
|
|
87
|
+
* console.log(statusOf(state).phase);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
21
90
|
export declare function statusOf(state: GameState): GameStatus;
|
|
22
91
|
/** Creates a base challenge state with a previously validated visible board and pair queue. @internal */
|
|
23
92
|
export declare function initialChallengeState(settings: Settings, visibleBoard: readonly (Gem | null)[], queue: readonly (readonly [Colour, Colour])[]): GameState;
|
|
24
|
-
/** Creates a deterministic seeded game with one active pair and three previews.
|
|
93
|
+
/** Creates a deterministic seeded game with one active pair and three previews.
|
|
94
|
+
*
|
|
95
|
+
* @param options - Validated native creation, authored challenge, or environment options described by this signature.
|
|
96
|
+
* @returns Creates a deterministic seeded game with one active pair and three previews.
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { createGame } from "@johnmorrisdotca/houseki/colour-chains";
|
|
100
|
+
*
|
|
101
|
+
* console.log(createGame({seed:"docs"}).phase);
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
25
104
|
export declare function createGame(options?: CreateOptions): GameState;
|
|
@@ -315,7 +315,21 @@ function applyCore(state, action) {
|
|
|
315
315
|
}
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
|
-
/** Applies one immutable accepted action and records its logical-tick position.
|
|
318
|
+
/** Applies one immutable accepted action and records its logical-tick position.
|
|
319
|
+
*
|
|
320
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
321
|
+
* @param action - One native action for this entry point; inspect accepted and reason on the result.
|
|
322
|
+
* @returns Applies one immutable accepted action and records its logical-tick position.
|
|
323
|
+
* @example
|
|
324
|
+
* ```ts
|
|
325
|
+
* import { applyAction, createGame } from "@johnmorrisdotca/houseki/colour-chains";
|
|
326
|
+
* import type { Action } from "@johnmorrisdotca/houseki/colour-chains";
|
|
327
|
+
*
|
|
328
|
+
* const state=createGame({seed:"docs"});
|
|
329
|
+
* const action: Action={kind:"left"};
|
|
330
|
+
* console.log(applyAction(state,action).accepted);
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
319
333
|
export function applyAction(state, action) {
|
|
320
334
|
const result = applyCore(state, action);
|
|
321
335
|
if (!result.accepted)
|
|
@@ -376,7 +390,19 @@ function advanceResolution(state) {
|
|
|
376
390
|
function lockGrounded(state) {
|
|
377
391
|
return lock(state, rigidLanding(state, state.active));
|
|
378
392
|
}
|
|
379
|
-
/** Advances deterministic 60 Hz simulation and resolution; Relaxed and Challenges do not force a falling clock.
|
|
393
|
+
/** Advances deterministic 60 Hz simulation and resolution; Relaxed and Challenges do not force a falling clock.
|
|
394
|
+
*
|
|
395
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
396
|
+
* @param ticks - The nonnegative number of fixed 60 Hz logical ticks to advance.
|
|
397
|
+
* @returns Advances deterministic 60 Hz simulation and resolution; Relaxed and Challenges do not force a falling clock.
|
|
398
|
+
* @example
|
|
399
|
+
* ```ts
|
|
400
|
+
* import { advanceTicks, createGame } from "@johnmorrisdotca/houseki/colour-chains";
|
|
401
|
+
*
|
|
402
|
+
* const state=createGame({seed:"docs"});
|
|
403
|
+
* console.log(advanceTicks(state,1).state.phase);
|
|
404
|
+
* ```
|
|
405
|
+
*/
|
|
380
406
|
export function advanceTicks(state, ticks) {
|
|
381
407
|
if (!Number.isInteger(ticks) || ticks < 0 || ticks > 3600)
|
|
382
408
|
throw new RangeError('ticks must be an integer from 0 to 3600');
|
|
@@ -420,7 +446,18 @@ export function advanceTicks(state, ticks) {
|
|
|
420
446
|
}
|
|
421
447
|
return { state: current, events, accepted: true };
|
|
422
448
|
}
|
|
423
|
-
/** Lists only actions accepted by the current game state.
|
|
449
|
+
/** Lists only actions accepted by the current game state.
|
|
450
|
+
*
|
|
451
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
452
|
+
* @returns Lists only actions accepted by the current game state.
|
|
453
|
+
* @example
|
|
454
|
+
* ```ts
|
|
455
|
+
* import { createGame, legalActions } from "@johnmorrisdotca/houseki/colour-chains";
|
|
456
|
+
*
|
|
457
|
+
* const state=createGame({seed:"docs"});
|
|
458
|
+
* console.log(legalActions(state).length);
|
|
459
|
+
* ```
|
|
460
|
+
*/
|
|
424
461
|
export function legalActions(state) {
|
|
425
462
|
if (state.phase === 'paused')
|
|
426
463
|
return [{ kind: 'resume' }];
|
|
@@ -446,7 +483,18 @@ export function legalActions(state) {
|
|
|
446
483
|
actions.push({ kind: 'pause' });
|
|
447
484
|
return actions;
|
|
448
485
|
}
|
|
449
|
-
/** Returns the exact independent landing cells for the current rigid pair without consuming random values.
|
|
486
|
+
/** Returns the exact independent landing cells for the current rigid pair without consuming random values.
|
|
487
|
+
*
|
|
488
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
489
|
+
* @returns Returns the exact independent landing cells for the current rigid pair without consuming random values. Returns null when there is no active piece or applicable preview.
|
|
490
|
+
* @example
|
|
491
|
+
* ```ts
|
|
492
|
+
* import { createGame, landingCells } from "@johnmorrisdotca/houseki/colour-chains";
|
|
493
|
+
*
|
|
494
|
+
* const state=createGame({seed:"docs"});
|
|
495
|
+
* console.log(landingCells(state));
|
|
496
|
+
* ```
|
|
497
|
+
*/
|
|
450
498
|
export function landingCells(state) {
|
|
451
499
|
if (!state.active)
|
|
452
500
|
return null;
|
|
@@ -464,6 +512,16 @@ export function landingCells(state) {
|
|
|
464
512
|
* gap then fall, so `settledCells` is where each stone of the pair comes to rest in the board the hard drop commits,
|
|
465
513
|
* before any clear: draw a ghost from it. Both carry the pair's stable stone ids, and both are checked against
|
|
466
514
|
* `applyAction` with a `hard-drop` over many played boards.
|
|
515
|
+
*
|
|
516
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
517
|
+
* @returns Returns the Shizen hard-drop landing and one-step rebound preview without changing state. Returns null when there is no active piece or applicable preview.
|
|
518
|
+
* @example
|
|
519
|
+
* ```ts
|
|
520
|
+
* import { createGame, powerDropPreview } from "@johnmorrisdotca/houseki/colour-chains";
|
|
521
|
+
*
|
|
522
|
+
* const state=createGame({seed:"docs"});
|
|
523
|
+
* console.log(powerDropPreview(state));
|
|
524
|
+
* ```
|
|
467
525
|
*/
|
|
468
526
|
export function powerDropPreview(state) {
|
|
469
527
|
if (!state.settings.nature || state.settings.mode === 'relaxed' || !state.active)
|
|
@@ -478,7 +536,18 @@ export function powerDropPreview(state) {
|
|
|
478
536
|
: preview.finalCells;
|
|
479
537
|
return Object.freeze({ ...preview, settledCells: Object.freeze(settledCells) });
|
|
480
538
|
}
|
|
481
|
-
/** Returns score, mode, chain and completion fields derived from state.
|
|
539
|
+
/** Returns score, mode, chain and completion fields derived from state.
|
|
540
|
+
*
|
|
541
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
542
|
+
* @returns Returns score, mode, chain and completion fields derived from state.
|
|
543
|
+
* @example
|
|
544
|
+
* ```ts
|
|
545
|
+
* import { createGame, statusOf } from "@johnmorrisdotca/houseki/colour-chains";
|
|
546
|
+
*
|
|
547
|
+
* const state=createGame({seed:"docs"});
|
|
548
|
+
* console.log(statusOf(state).phase);
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
482
551
|
export function statusOf(state) { return { mode: state.settings.mode, phase: state.phase, score: state.score, maxChain: state.maxChain, allClears: state.allClears, completedPairs: state.completedPairs, assisted: state.assisted, ...(state.reason ? { reason: state.reason } : {}) }; }
|
|
483
552
|
/** Creates a base challenge state with a previously validated visible board and pair queue. @internal */
|
|
484
553
|
export function initialChallengeState(settings, visibleBoard, queue) {
|
|
@@ -491,7 +560,17 @@ export function initialChallengeState(settings, visibleBoard, queue) {
|
|
|
491
560
|
const nextMagnetic = settings.nature ? queue.slice(1, 4).map((_, index) => settings.magneticQueue?.[index + 1] ?? [false, false]) : undefined;
|
|
492
561
|
return { ...base, active, ...(nextMagnetic ? { nextMagnetic: Object.freeze(nextMagnetic) } : {}), nextId: maxId + 3 };
|
|
493
562
|
}
|
|
494
|
-
/** Creates a deterministic seeded game with one active pair and three previews.
|
|
563
|
+
/** Creates a deterministic seeded game with one active pair and three previews.
|
|
564
|
+
*
|
|
565
|
+
* @param options - Validated native creation, authored challenge, or environment options described by this signature.
|
|
566
|
+
* @returns Creates a deterministic seeded game with one active pair and three previews.
|
|
567
|
+
* @example
|
|
568
|
+
* ```ts
|
|
569
|
+
* import { createGame } from "@johnmorrisdotca/houseki/colour-chains";
|
|
570
|
+
*
|
|
571
|
+
* console.log(createGame({seed:"docs"}).phase);
|
|
572
|
+
* ```
|
|
573
|
+
*/
|
|
495
574
|
export function createGame(options = {}) {
|
|
496
575
|
const valid = normalizeOptions(options);
|
|
497
576
|
let state = { game: 'colour-chains', rules: RULES, settings: valid, board: Array(valid.width * (valid.height + HIDDEN)).fill(null), phase: 'falling', active: null, next: [], bag: [], randomState: seedState(`colour-chains|${RULES}|${valid.seed}`), nextId: 1, score: 0, maxChain: 0, allClears: 0, completedPairs: 0, resolutionTick: 0, waves: [], clearCells: [], gravityBoard: null, resolutionHadClear: false, elapsedTicks: 0, assisted: false, witnessIndex: -1, recording: [], ...(valid.weather ? { weatherResolvedPairs: 0 } : {}) };
|
|
@@ -7,18 +7,108 @@ export interface InputSchedulerState {
|
|
|
7
7
|
readonly held: Readonly<Partial<Record<HeldControl, number>>>;
|
|
8
8
|
readonly queued: readonly EdgeAction[];
|
|
9
9
|
}
|
|
10
|
-
/** Creates an empty held-input scheduler.
|
|
10
|
+
/** Creates an empty held-input scheduler.
|
|
11
|
+
*
|
|
12
|
+
* @returns Creates an empty held-input scheduler.
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { createInputScheduler } from "@johnmorrisdotca/houseki/colour-chains";
|
|
16
|
+
*
|
|
17
|
+
* console.log(Object.keys(createInputScheduler()));
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
11
20
|
export declare function createInputScheduler(): InputSchedulerState;
|
|
12
|
-
/** Starts or releases one held control. Repeated press edges do not reset its repeat counter.
|
|
21
|
+
/** Starts or releases one held control. Repeated press edges do not reset its repeat counter.
|
|
22
|
+
*
|
|
23
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
24
|
+
* @param control - The native held-control name.
|
|
25
|
+
* @param pressed - Whether this control is currently pressed.
|
|
26
|
+
* @returns Starts or releases one held control. Repeated press edges do not reset its repeat counter.
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { createInputScheduler, setHeldInput } from "@johnmorrisdotca/houseki/colour-chains";
|
|
30
|
+
*
|
|
31
|
+
* const input=createInputScheduler();
|
|
32
|
+
* console.log(setHeldInput(input,"left",true));
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
13
35
|
export declare function setHeldInput(state: InputSchedulerState, control: HeldControl, pressed: boolean): InputSchedulerState;
|
|
14
|
-
/** Queues a one-shot rotation, drop, Place, pause or resume edge for the next logical tick.
|
|
36
|
+
/** Queues a one-shot rotation, drop, Place, pause or resume 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 rotation, drop, Place, pause or resume edge for the next logical tick.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { createInputScheduler, queueInputEdge } from "@johnmorrisdotca/houseki/colour-chains";
|
|
44
|
+
*
|
|
45
|
+
* const input=createInputScheduler();
|
|
46
|
+
* console.log(queueInputEdge(input,{kind:"hard-drop"}));
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
15
49
|
export declare function queueInputEdge(state: InputSchedulerState, action: EdgeAction): InputSchedulerState;
|
|
16
|
-
/** Releases every held or queued control after focus loss, lock, resolution or pause.
|
|
50
|
+
/** Releases every held or queued control after focus loss, lock, resolution or pause.
|
|
51
|
+
*
|
|
52
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
53
|
+
* @returns Releases every held or queued control after focus loss, lock, resolution or pause.
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { createInputScheduler, releaseAllInput } from "@johnmorrisdotca/houseki/colour-chains";
|
|
57
|
+
*
|
|
58
|
+
* const input=createInputScheduler();
|
|
59
|
+
* console.log(releaseAllInput(input));
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
17
62
|
export declare function releaseAllInput(state: InputSchedulerState): InputSchedulerState;
|
|
18
|
-
/** Resolves this tick's inputs in lateral, rotation, drop, soft-drop, pause order.
|
|
63
|
+
/** Resolves this tick's inputs in lateral, rotation, drop, soft-drop, pause order.
|
|
64
|
+
*
|
|
65
|
+
* @param game - The native game state used to resolve scheduled input.
|
|
66
|
+
* @param input - The held-input scheduler state for this logical tick.
|
|
67
|
+
* @returns Resolves this tick's inputs in lateral, rotation, drop, soft-drop, pause order.
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { actionsForTick, createGame, createInputScheduler } from "@johnmorrisdotca/houseki/colour-chains";
|
|
71
|
+
*
|
|
72
|
+
* const state=createGame({seed:"docs"});
|
|
73
|
+
* const input=createInputScheduler();
|
|
74
|
+
* console.log(actionsForTick(state,input)[0]);
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
19
77
|
export declare function actionsForTick(game: GameState, input: InputSchedulerState): readonly [readonly Action[], InputSchedulerState];
|
|
20
|
-
/** Applies a scheduler batch until the pair locks or the run pauses; accepted actions are recorded by the engine.
|
|
78
|
+
/** Applies a scheduler batch until the pair locks or the run pauses; accepted actions are recorded by the engine.
|
|
79
|
+
*
|
|
80
|
+
* @param game - The native game state used to resolve scheduled input.
|
|
81
|
+
* @param input - The held-input scheduler state for this logical tick.
|
|
82
|
+
* @param actions - Native actions in the scheduler’s canonical order.
|
|
83
|
+
* @param applyAction - The native applyAction function for this game.
|
|
84
|
+
* @returns Applies a scheduler batch until the pair locks or the run pauses; accepted actions are recorded by the engine.
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* import { applyAction, applyScheduledActions, createGame, createInputScheduler } from "@johnmorrisdotca/houseki/colour-chains";
|
|
88
|
+
* import type { Action } from "@johnmorrisdotca/houseki/colour-chains";
|
|
89
|
+
*
|
|
90
|
+
* const state=createGame({seed:"docs"});
|
|
91
|
+
* const action: Action={kind:"left"};
|
|
92
|
+
* const input=createInputScheduler();
|
|
93
|
+
* console.log(applyScheduledActions(state,input,[action],applyAction)[0].phase);
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
21
96
|
export declare function applyScheduledActions(game: GameState, input: InputSchedulerState, actions: readonly Action[], applyAction: (state: GameState, action: Action) => Transition): readonly [GameState, InputSchedulerState, readonly Transition[]];
|
|
22
|
-
/** Applies a complete deterministic held-input and simulation tick, releasing controls on lock or resolution.
|
|
97
|
+
/** Applies a complete deterministic held-input and simulation tick, releasing controls on lock or resolution.
|
|
98
|
+
*
|
|
99
|
+
* @param game - The native game state used to resolve scheduled input.
|
|
100
|
+
* @param input - The held-input scheduler state for this logical tick.
|
|
101
|
+
* @param apply - The native applyAction function for this game.
|
|
102
|
+
* @param tick - The native advanceTicks function for this game.
|
|
103
|
+
* @returns Applies a complete deterministic held-input and simulation tick, releasing controls on lock or resolution.
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* import { advanceTicks, applyAction, createGame, createInputScheduler, processInputTick } from "@johnmorrisdotca/houseki/colour-chains";
|
|
107
|
+
*
|
|
108
|
+
* const state=createGame({seed:"docs"});
|
|
109
|
+
* const input=createInputScheduler();
|
|
110
|
+
* console.log(processInputTick(state,input,applyAction,advanceTicks)[0].phase);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
23
113
|
export declare function processInputTick(game: GameState, input: InputSchedulerState, apply: (state: GameState, action: Action) => Transition, tick: (state: GameState, ticks: number) => Transition): readonly [GameState, InputSchedulerState, readonly Transition[]];
|
|
24
114
|
export {};
|
|
@@ -1,6 +1,28 @@
|
|
|
1
|
-
/** Creates an empty held-input scheduler.
|
|
1
|
+
/** Creates an empty held-input scheduler.
|
|
2
|
+
*
|
|
3
|
+
* @returns Creates an empty held-input scheduler.
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { createInputScheduler } from "@johnmorrisdotca/houseki/colour-chains";
|
|
7
|
+
*
|
|
8
|
+
* console.log(Object.keys(createInputScheduler()));
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
2
11
|
export function createInputScheduler() { return { held: Object.freeze({}), queued: Object.freeze([]) }; }
|
|
3
|
-
/** Starts or releases one held control. Repeated press edges do not reset its repeat counter.
|
|
12
|
+
/** Starts or releases one held control. Repeated press edges do not reset its repeat counter.
|
|
13
|
+
*
|
|
14
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
15
|
+
* @param control - The native held-control name.
|
|
16
|
+
* @param pressed - Whether this control is currently pressed.
|
|
17
|
+
* @returns Starts or releases one held control. Repeated press edges do not reset its repeat counter.
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { createInputScheduler, setHeldInput } from "@johnmorrisdotca/houseki/colour-chains";
|
|
21
|
+
*
|
|
22
|
+
* const input=createInputScheduler();
|
|
23
|
+
* console.log(setHeldInput(input,"left",true));
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
4
26
|
export function setHeldInput(state, control, pressed) {
|
|
5
27
|
const held = { ...state.held };
|
|
6
28
|
if (pressed) {
|
|
@@ -11,12 +33,48 @@ export function setHeldInput(state, control, pressed) {
|
|
|
11
33
|
delete held[control];
|
|
12
34
|
return { ...state, held: Object.freeze(held) };
|
|
13
35
|
}
|
|
14
|
-
/** Queues a one-shot rotation, drop, Place, pause or resume edge for the next logical tick.
|
|
36
|
+
/** Queues a one-shot rotation, drop, Place, pause or resume 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 rotation, drop, Place, pause or resume edge for the next logical tick.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { createInputScheduler, queueInputEdge } from "@johnmorrisdotca/houseki/colour-chains";
|
|
44
|
+
*
|
|
45
|
+
* const input=createInputScheduler();
|
|
46
|
+
* console.log(queueInputEdge(input,{kind:"hard-drop"}));
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
15
49
|
export function queueInputEdge(state, action) { return { ...state, queued: Object.freeze([...state.queued, action]) }; }
|
|
16
|
-
/** Releases every held or queued control after focus loss, lock, resolution or pause.
|
|
50
|
+
/** Releases every held or queued control after focus loss, lock, resolution or pause.
|
|
51
|
+
*
|
|
52
|
+
* @param state - The immutable native state to read or transition; the input is retained.
|
|
53
|
+
* @returns Releases every held or queued control after focus loss, lock, resolution or pause.
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { createInputScheduler, releaseAllInput } from "@johnmorrisdotca/houseki/colour-chains";
|
|
57
|
+
*
|
|
58
|
+
* const input=createInputScheduler();
|
|
59
|
+
* console.log(releaseAllInput(input));
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
17
62
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- the public signature takes the state a caller holds, though nothing of it is kept
|
|
18
63
|
export function releaseAllInput(state) { return createInputScheduler(); }
|
|
19
|
-
/** Resolves this tick's inputs in lateral, rotation, drop, soft-drop, pause order.
|
|
64
|
+
/** Resolves this tick's inputs in lateral, rotation, drop, soft-drop, pause order.
|
|
65
|
+
*
|
|
66
|
+
* @param game - The native game state used to resolve scheduled input.
|
|
67
|
+
* @param input - The held-input scheduler state for this logical tick.
|
|
68
|
+
* @returns Resolves this tick's inputs in lateral, rotation, drop, soft-drop, pause order.
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { actionsForTick, createGame, createInputScheduler } from "@johnmorrisdotca/houseki/colour-chains";
|
|
72
|
+
*
|
|
73
|
+
* const state=createGame({seed:"docs"});
|
|
74
|
+
* const input=createInputScheduler();
|
|
75
|
+
* console.log(actionsForTick(state,input)[0]);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
20
78
|
export function actionsForTick(game, input) {
|
|
21
79
|
if (game.phase === 'paused') {
|
|
22
80
|
const resume = input.queued.filter(action => action.kind === 'resume');
|
|
@@ -45,7 +103,24 @@ export function actionsForTick(game, input) {
|
|
|
45
103
|
held[control] = (held[control] ?? 0) + 1;
|
|
46
104
|
return [actions, { held: Object.freeze(held), queued: Object.freeze([]) }];
|
|
47
105
|
}
|
|
48
|
-
/** Applies a scheduler batch until the pair locks or the run pauses; accepted actions are recorded by the engine.
|
|
106
|
+
/** Applies a scheduler batch until the pair locks or the run pauses; accepted actions are recorded by the engine.
|
|
107
|
+
*
|
|
108
|
+
* @param game - The native game state used to resolve scheduled input.
|
|
109
|
+
* @param input - The held-input scheduler state for this logical tick.
|
|
110
|
+
* @param actions - Native actions in the scheduler’s canonical order.
|
|
111
|
+
* @param applyAction - The native applyAction function for this game.
|
|
112
|
+
* @returns Applies a scheduler batch until the pair locks or the run pauses; accepted actions are recorded by the engine.
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* import { applyAction, applyScheduledActions, createGame, createInputScheduler } from "@johnmorrisdotca/houseki/colour-chains";
|
|
116
|
+
* import type { Action } from "@johnmorrisdotca/houseki/colour-chains";
|
|
117
|
+
*
|
|
118
|
+
* const state=createGame({seed:"docs"});
|
|
119
|
+
* const action: Action={kind:"left"};
|
|
120
|
+
* const input=createInputScheduler();
|
|
121
|
+
* console.log(applyScheduledActions(state,input,[action],applyAction)[0].phase);
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
49
124
|
export function applyScheduledActions(game, input, actions, applyAction) {
|
|
50
125
|
let state = game;
|
|
51
126
|
const transitions = [];
|
|
@@ -64,7 +139,22 @@ export function applyScheduledActions(game, input, actions, applyAction) {
|
|
|
64
139
|
const lockedOrPaused = transitions.some(result => result.events.some(event => event.type === 'pair-locked' || event.type === 'paused')) || state.phase !== 'falling';
|
|
65
140
|
return [state, lockedOrPaused ? createInputScheduler() : input, transitions];
|
|
66
141
|
}
|
|
67
|
-
/** Applies a complete deterministic held-input and simulation tick, releasing controls on lock or resolution.
|
|
142
|
+
/** Applies a complete deterministic held-input and simulation tick, releasing controls on lock or resolution.
|
|
143
|
+
*
|
|
144
|
+
* @param game - The native game state used to resolve scheduled input.
|
|
145
|
+
* @param input - The held-input scheduler state for this logical tick.
|
|
146
|
+
* @param apply - The native applyAction function for this game.
|
|
147
|
+
* @param tick - The native advanceTicks function for this game.
|
|
148
|
+
* @returns Applies a complete deterministic held-input and simulation tick, releasing controls on lock or resolution.
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* import { advanceTicks, applyAction, createGame, createInputScheduler, processInputTick } from "@johnmorrisdotca/houseki/colour-chains";
|
|
152
|
+
*
|
|
153
|
+
* const state=createGame({seed:"docs"});
|
|
154
|
+
* const input=createInputScheduler();
|
|
155
|
+
* console.log(processInputTick(state,input,applyAction,advanceTicks)[0].phase);
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
68
158
|
export function processInputTick(game, input, apply, tick) {
|
|
69
159
|
const [actions, scheduled] = actionsForTick(game, input);
|
|
70
160
|
const [afterInput, retained, transitions] = applyScheduledActions(game, scheduled, actions, apply);
|