@johnmorrisdotca/kumimoji 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/README.md +80 -39
- package/dist/check.d.ts +26 -1
- package/dist/check.js +26 -1
- package/dist/computer.types.d.ts +24 -2
- package/dist/computerPlay.d.ts +45 -2
- package/dist/computerPlay.js +45 -2
- package/dist/computerTurn.d.ts +42 -3
- package/dist/computerTurn.js +42 -3
- package/dist/daily.d.ts +22 -2
- package/dist/daily.js +22 -2
- package/dist/element-define.d.ts +1 -1
- package/dist/element-define.js +3 -13
- package/dist/element.d.ts +85 -4
- package/dist/element.js +176 -45
- package/dist/embed-day.d.ts +4 -0
- package/dist/embed-day.js +23 -0
- package/dist/export.d.ts +123 -6
- package/dist/export.js +91 -4
- package/dist/generate.d.ts +14 -0
- package/dist/generate.js +14 -0
- package/dist/grid.d.ts +181 -10
- package/dist/grid.js +122 -7
- package/dist/help.d.ts +36 -3
- package/dist/help.js +36 -3
- package/dist/judge.d.ts +14 -0
- package/dist/judge.js +14 -0
- package/dist/kana.d.ts +23 -1
- package/dist/kana.js +23 -1
- package/dist/kumimoji.types.d.ts +70 -5
- package/dist/party.d.ts +268 -14
- package/dist/party.js +268 -14
- package/dist/party.types.d.ts +50 -2
- package/dist/partyKept.d.ts +74 -4
- package/dist/partyKept.js +74 -4
- package/dist/partySeats.d.ts +92 -6
- package/dist/partySeats.js +72 -4
- package/dist/partyTurns.d.ts +171 -5
- package/dist/partyTurns.js +171 -5
- package/dist/placement.d.ts +50 -2
- package/dist/placement.js +30 -0
- package/dist/play.d.ts +247 -15
- package/dist/play.js +237 -15
- package/dist/random.d.ts +34 -3
- package/dist/random.js +23 -2
- package/dist/react.d.ts +42 -4
- package/dist/react.js +22 -5
- package/dist/showcase.d.ts +83 -7
- package/dist/showcase.js +49 -4
- package/dist/strings.d.ts +54 -5
- package/dist/strings.js +34 -3
- package/dist/tableView.d.ts +151 -8
- package/dist/tableView.js +129 -6
- package/dist/tileFace.d.ts +59 -5
- package/dist/tileFace.js +48 -4
- package/dist/tileFamily.d.ts +9 -0
- package/dist/tileFamily.js +9 -0
- package/dist/tileWords.d.ts +93 -6
- package/dist/tileWords.js +83 -6
- package/dist/tileWordsModule.d.ts +11 -1
- package/dist/tileWordsModule.js +11 -1
- package/dist/tiles.constants.d.ts +99 -5
- package/dist/tiles.constants.js +99 -5
- package/dist/turn.d.ts +82 -4
- package/dist/turn.js +82 -4
- package/dist/ui/board.d.ts +60 -5
- package/dist/ui/board.js +28 -2
- package/dist/ui/mount.d.ts +41 -2
- package/dist/ui/mount.js +38 -1
- package/dist/ui/style.d.ts +6 -1
- package/dist/ui/style.js +6 -0
- package/dist/version.d.ts +9 -2
- package/dist/version.js +9 -2
- package/dist/wilds.d.ts +22 -1
- package/dist/wilds.js +22 -1
- package/package.json +64 -56
package/dist/play.d.ts
CHANGED
|
@@ -12,6 +12,16 @@ import { type GridVerdict, type Tiles } from "./grid.ts";
|
|
|
12
12
|
* a game the same for everybody at a seed, trades and all, and lets a kept
|
|
13
13
|
* game be checked: what is held — hand and table — is exactly what was taken,
|
|
14
14
|
* less what was given back.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { deal } from "@johnmorrisdotca/kumimoji";
|
|
19
|
+
* import type { TilePlay } from "@johnmorrisdotca/kumimoji";
|
|
20
|
+
*
|
|
21
|
+
* const play = deal("catdog",3);
|
|
22
|
+
* const value: TilePlay = play;
|
|
23
|
+
* console.log(value);
|
|
24
|
+
* ```
|
|
15
25
|
*/
|
|
16
26
|
export type TilePlay = {
|
|
17
27
|
/** The tiles in the order they come out: the puzzle's givens. */
|
|
@@ -25,39 +35,225 @@ export type TilePlay = {
|
|
|
25
35
|
/** The hand, in the order the player keeps it. */
|
|
26
36
|
hand: readonly string[];
|
|
27
37
|
};
|
|
28
|
-
/** The opening hand: the first `handSize` tiles of the bag, and an empty table.
|
|
38
|
+
/** The opening hand: the first `handSize` tiles of the bag, and an empty table.
|
|
39
|
+
*
|
|
40
|
+
* @param bag - The original bag in draw order.
|
|
41
|
+
* @param handSize - The initial number of tiles to draw.
|
|
42
|
+
* @returns The opening hand: the first `handSize` tiles of the bag, and an empty table.
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { deal } from "@johnmorrisdotca/kumimoji";
|
|
46
|
+
*
|
|
47
|
+
* console.log(deal("catdog",3));
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
29
50
|
export declare function deal(bag: string, handSize: number): TilePlay;
|
|
30
|
-
/** How many tiles are still in the bag.
|
|
51
|
+
/** How many tiles are still in the bag.
|
|
52
|
+
*
|
|
53
|
+
* @param play - The current immutable solo-game progress.
|
|
54
|
+
* @returns How many tiles are still in the bag.
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* import { deal, tilesLeft } from "@johnmorrisdotca/kumimoji";
|
|
58
|
+
*
|
|
59
|
+
* const play = deal("catdog",3);
|
|
60
|
+
* console.log(tilesLeft(play));
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
31
63
|
export declare function tilesLeft(play: TilePlay): number;
|
|
32
|
-
/** A tile from the hand onto an empty square.
|
|
64
|
+
/** A tile from the hand onto an empty square.
|
|
65
|
+
*
|
|
66
|
+
* @param play - The current immutable solo-game progress.
|
|
67
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
68
|
+
* @param square - The row,column square name.
|
|
69
|
+
* @returns A tile from the hand onto an empty square.
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { deal, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
73
|
+
*
|
|
74
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
75
|
+
* const play = deal("catdog",3);
|
|
76
|
+
* console.log(placeFromHand(play,0,"0,0").tiles.size);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
33
79
|
export declare function placeFromHand(play: TilePlay, handAt: number, square: string): TilePlay;
|
|
34
|
-
/** Give a hand tile its chosen reading, without changing which physical tile it is.
|
|
80
|
+
/** Give a hand tile its chosen reading, without changing which physical tile it is.
|
|
81
|
+
*
|
|
82
|
+
* @param play - The current immutable solo-game progress.
|
|
83
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
84
|
+
* @param face - The visible reading to assign to a wild tile.
|
|
85
|
+
* @returns Give a hand tile its chosen reading, without changing which physical tile it is.
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* import { assignHandTile, deal } from "@johnmorrisdotca/kumimoji";
|
|
89
|
+
*
|
|
90
|
+
* console.log(assignHandTile(deal("*atdog",3),0,"c").hand);
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
35
93
|
export declare function assignHandTile(play: TilePlay, handAt: number, face: string): TilePlay;
|
|
36
|
-
/** Give a tile on the table its chosen reading, without changing its square.
|
|
94
|
+
/** Give a tile on the table its chosen reading, without changing its square.
|
|
95
|
+
*
|
|
96
|
+
* @param play - The current immutable solo-game progress.
|
|
97
|
+
* @param square - The row,column square name.
|
|
98
|
+
* @param face - The visible reading to assign to a wild tile.
|
|
99
|
+
* @returns Give a tile on the table its chosen reading, without changing its square.
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* import { assignTableTile, deal, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
103
|
+
*
|
|
104
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
105
|
+
* console.log(assignTableTile(placeFromHand(deal("*atdog",3),0,"0,0"),"0,0","c").tiles);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
37
108
|
export declare function assignTableTile(play: TilePlay, square: string, face: string): TilePlay;
|
|
38
|
-
/** A tile on the table to another square: to an empty one it moves, onto a tile the two change places.
|
|
109
|
+
/** A tile on the table to another square: to an empty one it moves, onto a tile the two change places.
|
|
110
|
+
*
|
|
111
|
+
* @param play - The current immutable solo-game progress.
|
|
112
|
+
* @param from - The source square or seat index.
|
|
113
|
+
* @param to - The destination square.
|
|
114
|
+
* @returns A tile on the table to another square: to an empty one it moves, onto a tile the two change places.
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* import { deal, moveOnTable, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
118
|
+
*
|
|
119
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
120
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
121
|
+
* console.log(moveOnTable(laid,"0,0","1,0").tiles);
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
39
124
|
export declare function moveOnTable(play: TilePlay, from: string, to: string): TilePlay;
|
|
40
|
-
/** A tile from the hand onto a square that holds one: they change places, the table's tile going to the hand where the other was.
|
|
125
|
+
/** A tile from the hand onto a square that holds one: they change places, the table's tile going to the hand where the other was.
|
|
126
|
+
*
|
|
127
|
+
* @param play - The current immutable solo-game progress.
|
|
128
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
129
|
+
* @param square - The row,column square name.
|
|
130
|
+
* @returns A tile from the hand onto a square that holds one: they change places, the table's tile going to the hand where the other was.
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* import { deal, placeFromHand, swapWithHand } from "@johnmorrisdotca/kumimoji";
|
|
134
|
+
*
|
|
135
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
136
|
+
* console.log(swapWithHand(laid,0,"0,0").hand);
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
41
139
|
export declare function swapWithHand(play: TilePlay, handAt: number, square: string): TilePlay;
|
|
42
|
-
/** A tile on the table back to the end of the hand.
|
|
140
|
+
/** A tile on the table back to the end of the hand.
|
|
141
|
+
*
|
|
142
|
+
* @param play - The current immutable solo-game progress.
|
|
143
|
+
* @param square - The row,column square name.
|
|
144
|
+
* @returns A tile on the table back to the end of the hand.
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* import { deal, liftToHand, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
148
|
+
*
|
|
149
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
150
|
+
* console.log(liftToHand(laid,"0,0").hand);
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
43
153
|
export declare function liftToHand(play: TilePlay, square: string): TilePlay;
|
|
44
|
-
/** Every tile on the table back to the hand.
|
|
154
|
+
/** Every tile on the table back to the hand.
|
|
155
|
+
*
|
|
156
|
+
* @param play - The current immutable solo-game progress.
|
|
157
|
+
* @returns Every tile on the table back to the hand.
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { deal, liftAll, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
161
|
+
*
|
|
162
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
163
|
+
* console.log(liftAll(laid).hand);
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
45
166
|
export declare function liftAll(play: TilePlay): TilePlay;
|
|
46
167
|
/**
|
|
47
168
|
* The hand in order (John, 2026-09-28: "it gets sorted for letters
|
|
48
169
|
* alphabetically"): English A to Z, Japanese あいうえお, which is the order
|
|
49
170
|
* of the kana's tile codes, and the wilds last as they came.
|
|
171
|
+
*
|
|
172
|
+
* @param play - The current immutable solo-game progress.
|
|
173
|
+
* @returns The hand in order (John, 2026-09-28: "it gets sorted for letters alphabetically"): English A to Z, Japanese あいうえお, which is the order of the kana's tile codes, and the wilds last as they came.
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* import { deal, sortHand } from "@johnmorrisdotca/kumimoji";
|
|
177
|
+
*
|
|
178
|
+
* const play = deal("catdog",3);
|
|
179
|
+
* console.log(sortHand(play).hand);
|
|
180
|
+
* ```
|
|
50
181
|
*/
|
|
51
182
|
export declare function sortHand(play: TilePlay): TilePlay;
|
|
52
|
-
/** Whether Draw may be pressed: the hand used, the grid sound, and a tile left to draw.
|
|
183
|
+
/** Whether Draw may be pressed: the hand used, the grid sound, and a tile left to draw.
|
|
184
|
+
*
|
|
185
|
+
* @param play - The current immutable solo-game progress.
|
|
186
|
+
* @param verdict - The native word and connectivity verdict for this grid.
|
|
187
|
+
* @returns Whether Draw may be pressed: the hand used, the grid sound, and a tile left to draw.
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
191
|
+
* import { deal, judgeWithWords, mayDraw } from "@johnmorrisdotca/kumimoji";
|
|
192
|
+
*
|
|
193
|
+
* const words = await loadTileWordsFromModule("english");
|
|
194
|
+
* const play = deal("catdog",3);
|
|
195
|
+
* const verdict = judgeWithWords(new Map([["0,0","c"],["0,1","a"],["0,2","t"]]),words);
|
|
196
|
+
* console.log(mayDraw(play,verdict));
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
53
199
|
export declare function mayDraw(play: TilePlay, verdict: GridVerdict): boolean;
|
|
54
|
-
/** The next tile or tiles out of the bag into the hand.
|
|
200
|
+
/** The next tile or tiles out of the bag into the hand.
|
|
201
|
+
*
|
|
202
|
+
* @param play - The current immutable solo-game progress.
|
|
203
|
+
* @param count - The number of tiles to draw.
|
|
204
|
+
* @returns The next tile or tiles out of the bag into the hand.
|
|
205
|
+
* @example
|
|
206
|
+
* ```ts
|
|
207
|
+
* import { deal, draw } from "@johnmorrisdotca/kumimoji";
|
|
208
|
+
*
|
|
209
|
+
* const play = deal("catdog",3);
|
|
210
|
+
* console.log(draw(play,1).hand);
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
55
213
|
export declare function draw(play: TilePlay, count?: number): TilePlay;
|
|
56
|
-
/** Whether a trade may be made: the bag holds as many as a trade takes.
|
|
214
|
+
/** Whether a trade may be made: the bag holds as many as a trade takes.
|
|
215
|
+
*
|
|
216
|
+
* @param play - The current immutable solo-game progress.
|
|
217
|
+
* @returns Whether a trade may be made: the bag holds as many as a trade takes.
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* import { deal, mayTrade } from "@johnmorrisdotca/kumimoji";
|
|
221
|
+
*
|
|
222
|
+
* const play = deal("catdog",3);
|
|
223
|
+
* console.log(mayTrade(play));
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
57
226
|
export declare function mayTrade(play: TilePlay): boolean;
|
|
58
|
-
/** One tile from the hand to the bottom of the bag, and the next three out of it.
|
|
227
|
+
/** One tile from the hand to the bottom of the bag, and the next three out of it.
|
|
228
|
+
*
|
|
229
|
+
* @param play - The current immutable solo-game progress.
|
|
230
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
231
|
+
* @returns One tile from the hand to the bottom of the bag, and the next three out of it.
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* import { deal, trade } from "@johnmorrisdotca/kumimoji";
|
|
235
|
+
*
|
|
236
|
+
* const play = deal("catdog",3);
|
|
237
|
+
* console.log(trade(play,0).hand);
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
59
240
|
export declare function trade(play: TilePlay, handAt: number): TilePlay;
|
|
60
|
-
/** Whether the game is over: the bag empty, the hand used, and the grid sound.
|
|
241
|
+
/** Whether the game is over: the bag empty, the hand used, and the grid sound.
|
|
242
|
+
*
|
|
243
|
+
* @param play - The current immutable solo-game progress.
|
|
244
|
+
* @param verdict - The native word and connectivity verdict for this grid.
|
|
245
|
+
* @returns Whether the game is over: the bag empty, the hand used, and the grid sound.
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
249
|
+
* import { deal, isFinished, judgeWithWords } from "@johnmorrisdotca/kumimoji";
|
|
250
|
+
*
|
|
251
|
+
* const words = await loadTileWordsFromModule("english");
|
|
252
|
+
* const play = deal("catdog",3);
|
|
253
|
+
* const verdict = judgeWithWords(new Map([["0,0","c"],["0,1","a"],["0,2","t"]]),words);
|
|
254
|
+
* console.log(isFinished(play,verdict));
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
61
257
|
export declare function isFinished(play: TilePlay, verdict: GridVerdict): boolean;
|
|
62
258
|
/**
|
|
63
259
|
* A GAME KEPT half way, as one string (`PuzzleRun.progress`): how many tiles
|
|
@@ -65,9 +261,30 @@ export declare function isFinished(play: TilePlay, verdict: GridVerdict): boolea
|
|
|
65
261
|
* (`encodeGrid`), as `12:q:ae:cat/2o/2w`. The bag is the puzzle's own, from
|
|
66
262
|
* its seed, so it is not written again, and where on the table the grid stood
|
|
67
263
|
* is the view's and not kept.
|
|
264
|
+
*
|
|
265
|
+
* @param play - The current immutable solo-game progress.
|
|
266
|
+
* @returns A GAME KEPT half way, as one string (`PuzzleRun.progress`): how many tiles were taken, the tiles traded back, the hand in its order and the grid (`encodeGrid`), as `12:q:ae:cat/2o/2w`. The bag is the puzzle's own, from its seed, so it is not written again, and where on the table the grid stood is the view's and not kept.
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* import { deal, encodeTileProgress } from "@johnmorrisdotca/kumimoji";
|
|
270
|
+
*
|
|
271
|
+
* const play = deal("catdog",3);
|
|
272
|
+
* console.log(encodeTileProgress(play));
|
|
273
|
+
* ```
|
|
68
274
|
*/
|
|
69
275
|
export declare function encodeTileProgress(play: TilePlay): string;
|
|
70
|
-
/** The parts of a kept game, or null for a string that is not one: its shape only, with no bag to check it against.
|
|
276
|
+
/** The parts of a kept game, or null for a string that is not one: its shape only, with no bag to check it against.
|
|
277
|
+
*
|
|
278
|
+
* @param code - The encoded grid or progress text.
|
|
279
|
+
* @returns The parts of a kept game, or null for a string that is not one: its shape only, with no bag to check it against.
|
|
280
|
+
* @example
|
|
281
|
+
* ```ts
|
|
282
|
+
* import { deal, encodeTileProgress, readTileProgress } from "@johnmorrisdotca/kumimoji";
|
|
283
|
+
*
|
|
284
|
+
* const play = deal("catdog",3);
|
|
285
|
+
* console.log(readTileProgress(encodeTileProgress(play)));
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
71
288
|
export declare function readTileProgress(code: string): {
|
|
72
289
|
taken: number;
|
|
73
290
|
returned: string;
|
|
@@ -79,5 +296,20 @@ export declare function readTileProgress(code: string): {
|
|
|
79
296
|
* to it: every tile held — hand and table — must be one taken from the bag
|
|
80
297
|
* and not given back. Null opens the game fresh rather than on a grid that
|
|
81
298
|
* never came out of this bag.
|
|
299
|
+
*
|
|
300
|
+
* @param code - The encoded grid or progress text.
|
|
301
|
+
* @param bag - The original bag in draw order.
|
|
302
|
+
* @param language - The English or Japanese tile language.
|
|
303
|
+
* @returns A kept game opened again on its own bag, or null where it does not belong to it: every tile held — hand and table — must be one taken from the bag and not given back. Null opens the game fresh rather than on a grid that never came out of this bag.
|
|
304
|
+
* @example
|
|
305
|
+
* ```ts
|
|
306
|
+
* import { deal, decodeTileProgress, encodeTileProgress } from "@johnmorrisdotca/kumimoji";
|
|
307
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
308
|
+
*
|
|
309
|
+
* await loadTileWordsFromModule("english");
|
|
310
|
+
* const play = deal("catdog",3);
|
|
311
|
+
* const bag = "catdogsun";
|
|
312
|
+
* console.log(decodeTileProgress(encodeTileProgress(play),play.bag));
|
|
313
|
+
* ```
|
|
82
314
|
*/
|
|
83
315
|
export declare function decodeTileProgress(code: string, bag: string, language?: "english" | "japanese"): TilePlay | null;
|
package/dist/play.js
CHANGED
|
@@ -2,12 +2,34 @@ import { decodeGrid, encodeGrid, lettersOf, sameLetters } from "./grid.js";
|
|
|
2
2
|
import { tileFace } from "./tileFace.js";
|
|
3
3
|
import { KUMIMOJI_DRAW, KUMIMOJI_TRADE } from "./tiles.constants.js";
|
|
4
4
|
import { tileWords } from "./tileWords.js";
|
|
5
|
-
/** The opening hand: the first `handSize` tiles of the bag, and an empty table.
|
|
5
|
+
/** The opening hand: the first `handSize` tiles of the bag, and an empty table.
|
|
6
|
+
*
|
|
7
|
+
* @param bag - The original bag in draw order.
|
|
8
|
+
* @param handSize - The initial number of tiles to draw.
|
|
9
|
+
* @returns The opening hand: the first `handSize` tiles of the bag, and an empty table.
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { deal } from "@johnmorrisdotca/kumimoji";
|
|
13
|
+
*
|
|
14
|
+
* console.log(deal("catdog",3));
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
6
17
|
export function deal(bag, handSize) {
|
|
7
18
|
const taken = Math.min(handSize, bag.length);
|
|
8
19
|
return { bag, returned: "", taken, tiles: new Map(), hand: [...bag.slice(0, taken)] };
|
|
9
20
|
}
|
|
10
|
-
/** How many tiles are still in the bag.
|
|
21
|
+
/** How many tiles are still in the bag.
|
|
22
|
+
*
|
|
23
|
+
* @param play - The current immutable solo-game progress.
|
|
24
|
+
* @returns How many tiles are still in the bag.
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { deal, tilesLeft } from "@johnmorrisdotca/kumimoji";
|
|
28
|
+
*
|
|
29
|
+
* const play = deal("catdog",3);
|
|
30
|
+
* console.log(tilesLeft(play));
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
11
33
|
export function tilesLeft(play) {
|
|
12
34
|
return play.bag.length + play.returned.length - play.taken;
|
|
13
35
|
}
|
|
@@ -16,14 +38,40 @@ function withTiles(play, change) {
|
|
|
16
38
|
change(tiles);
|
|
17
39
|
return tiles;
|
|
18
40
|
}
|
|
19
|
-
/** A tile from the hand onto an empty square.
|
|
41
|
+
/** A tile from the hand onto an empty square.
|
|
42
|
+
*
|
|
43
|
+
* @param play - The current immutable solo-game progress.
|
|
44
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
45
|
+
* @param square - The row,column square name.
|
|
46
|
+
* @returns A tile from the hand onto an empty square.
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { deal, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
50
|
+
*
|
|
51
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
52
|
+
* const play = deal("catdog",3);
|
|
53
|
+
* console.log(placeFromHand(play,0,"0,0").tiles.size);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
20
56
|
export function placeFromHand(play, handAt, square) {
|
|
21
57
|
const letter = play.hand[handAt];
|
|
22
58
|
if (letter === undefined || play.tiles.has(square))
|
|
23
59
|
return play;
|
|
24
60
|
return { ...play, tiles: withTiles(play, (tiles) => tiles.set(square, letter)), hand: play.hand.filter((_, at) => at !== handAt) };
|
|
25
61
|
}
|
|
26
|
-
/** Give a hand tile its chosen reading, without changing which physical tile it is.
|
|
62
|
+
/** Give a hand tile its chosen reading, without changing which physical tile it is.
|
|
63
|
+
*
|
|
64
|
+
* @param play - The current immutable solo-game progress.
|
|
65
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
66
|
+
* @param face - The visible reading to assign to a wild tile.
|
|
67
|
+
* @returns Give a hand tile its chosen reading, without changing which physical tile it is.
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { assignHandTile, deal } from "@johnmorrisdotca/kumimoji";
|
|
71
|
+
*
|
|
72
|
+
* console.log(assignHandTile(deal("*atdog",3),0,"c").hand);
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
27
75
|
export function assignHandTile(play, handAt, face) {
|
|
28
76
|
if (play.hand[handAt] === undefined || face.length !== 1)
|
|
29
77
|
return play;
|
|
@@ -31,13 +79,40 @@ export function assignHandTile(play, handAt, face) {
|
|
|
31
79
|
hand[handAt] = face;
|
|
32
80
|
return { ...play, hand };
|
|
33
81
|
}
|
|
34
|
-
/** Give a tile on the table its chosen reading, without changing its square.
|
|
82
|
+
/** Give a tile on the table its chosen reading, without changing its square.
|
|
83
|
+
*
|
|
84
|
+
* @param play - The current immutable solo-game progress.
|
|
85
|
+
* @param square - The row,column square name.
|
|
86
|
+
* @param face - The visible reading to assign to a wild tile.
|
|
87
|
+
* @returns Give a tile on the table its chosen reading, without changing its square.
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* import { assignTableTile, deal, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
91
|
+
*
|
|
92
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
93
|
+
* console.log(assignTableTile(placeFromHand(deal("*atdog",3),0,"0,0"),"0,0","c").tiles);
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
35
96
|
export function assignTableTile(play, square, face) {
|
|
36
97
|
if (!play.tiles.has(square) || face.length !== 1)
|
|
37
98
|
return play;
|
|
38
99
|
return { ...play, tiles: withTiles(play, (tiles) => tiles.set(square, face)) };
|
|
39
100
|
}
|
|
40
|
-
/** A tile on the table to another square: to an empty one it moves, onto a tile the two change places.
|
|
101
|
+
/** A tile on the table to another square: to an empty one it moves, onto a tile the two change places.
|
|
102
|
+
*
|
|
103
|
+
* @param play - The current immutable solo-game progress.
|
|
104
|
+
* @param from - The source square or seat index.
|
|
105
|
+
* @param to - The destination square.
|
|
106
|
+
* @returns A tile on the table to another square: to an empty one it moves, onto a tile the two change places.
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* import { deal, moveOnTable, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
110
|
+
*
|
|
111
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
112
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
113
|
+
* console.log(moveOnTable(laid,"0,0","1,0").tiles);
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
41
116
|
export function moveOnTable(play, from, to) {
|
|
42
117
|
const moving = play.tiles.get(from);
|
|
43
118
|
if (from === to || moving === undefined)
|
|
@@ -53,7 +128,20 @@ export function moveOnTable(play, from, to) {
|
|
|
53
128
|
}),
|
|
54
129
|
};
|
|
55
130
|
}
|
|
56
|
-
/** A tile from the hand onto a square that holds one: they change places, the table's tile going to the hand where the other was.
|
|
131
|
+
/** A tile from the hand onto a square that holds one: they change places, the table's tile going to the hand where the other was.
|
|
132
|
+
*
|
|
133
|
+
* @param play - The current immutable solo-game progress.
|
|
134
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
135
|
+
* @param square - The row,column square name.
|
|
136
|
+
* @returns A tile from the hand onto a square that holds one: they change places, the table's tile going to the hand where the other was.
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* import { deal, placeFromHand, swapWithHand } from "@johnmorrisdotca/kumimoji";
|
|
140
|
+
*
|
|
141
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
142
|
+
* console.log(swapWithHand(laid,0,"0,0").hand);
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
57
145
|
export function swapWithHand(play, handAt, square) {
|
|
58
146
|
const letter = play.hand[handAt];
|
|
59
147
|
const lifted = play.tiles.get(square);
|
|
@@ -63,14 +151,37 @@ export function swapWithHand(play, handAt, square) {
|
|
|
63
151
|
hand[handAt] = lifted;
|
|
64
152
|
return { ...play, tiles: withTiles(play, (tiles) => tiles.set(square, letter)), hand };
|
|
65
153
|
}
|
|
66
|
-
/** A tile on the table back to the end of the hand.
|
|
154
|
+
/** A tile on the table back to the end of the hand.
|
|
155
|
+
*
|
|
156
|
+
* @param play - The current immutable solo-game progress.
|
|
157
|
+
* @param square - The row,column square name.
|
|
158
|
+
* @returns A tile on the table back to the end of the hand.
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* import { deal, liftToHand, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
162
|
+
*
|
|
163
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
164
|
+
* console.log(liftToHand(laid,"0,0").hand);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
67
167
|
export function liftToHand(play, square) {
|
|
68
168
|
const letter = play.tiles.get(square);
|
|
69
169
|
if (letter === undefined)
|
|
70
170
|
return play;
|
|
71
171
|
return { ...play, tiles: withTiles(play, (tiles) => tiles.delete(square)), hand: [...play.hand, letter] };
|
|
72
172
|
}
|
|
73
|
-
/** Every tile on the table back to the hand.
|
|
173
|
+
/** Every tile on the table back to the hand.
|
|
174
|
+
*
|
|
175
|
+
* @param play - The current immutable solo-game progress.
|
|
176
|
+
* @returns Every tile on the table back to the hand.
|
|
177
|
+
* @example
|
|
178
|
+
* ```ts
|
|
179
|
+
* import { deal, liftAll, placeFromHand } from "@johnmorrisdotca/kumimoji";
|
|
180
|
+
*
|
|
181
|
+
* const laid = placeFromHand(deal("catdog",3),0,"0,0");
|
|
182
|
+
* console.log(liftAll(laid).hand);
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
74
185
|
export function liftAll(play) {
|
|
75
186
|
return { ...play, tiles: new Map(), hand: [...play.hand, ...play.tiles.values()] };
|
|
76
187
|
}
|
|
@@ -78,27 +189,87 @@ export function liftAll(play) {
|
|
|
78
189
|
* The hand in order (John, 2026-09-28: "it gets sorted for letters
|
|
79
190
|
* alphabetically"): English A to Z, Japanese あいうえお, which is the order
|
|
80
191
|
* of the kana's tile codes, and the wilds last as they came.
|
|
192
|
+
*
|
|
193
|
+
* @param play - The current immutable solo-game progress.
|
|
194
|
+
* @returns The hand in order (John, 2026-09-28: "it gets sorted for letters alphabetically"): English A to Z, Japanese あいうえお, which is the order of the kana's tile codes, and the wilds last as they came.
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* import { deal, sortHand } from "@johnmorrisdotca/kumimoji";
|
|
198
|
+
*
|
|
199
|
+
* const play = deal("catdog",3);
|
|
200
|
+
* console.log(sortHand(play).hand);
|
|
201
|
+
* ```
|
|
81
202
|
*/
|
|
82
203
|
export function sortHand(play) {
|
|
83
204
|
const hand = [...play.hand].sort((a, b) => Number(tileFace(a).wild) - Number(tileFace(b).wild) || (tileFace(a).wild ? 0 : a < b ? -1 : a > b ? 1 : 0));
|
|
84
205
|
return { ...play, hand };
|
|
85
206
|
}
|
|
86
|
-
/** Whether Draw may be pressed: the hand used, the grid sound, and a tile left to draw.
|
|
207
|
+
/** Whether Draw may be pressed: the hand used, the grid sound, and a tile left to draw.
|
|
208
|
+
*
|
|
209
|
+
* @param play - The current immutable solo-game progress.
|
|
210
|
+
* @param verdict - The native word and connectivity verdict for this grid.
|
|
211
|
+
* @returns Whether Draw may be pressed: the hand used, the grid sound, and a tile left to draw.
|
|
212
|
+
* @example
|
|
213
|
+
* ```ts
|
|
214
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
215
|
+
* import { deal, judgeWithWords, mayDraw } from "@johnmorrisdotca/kumimoji";
|
|
216
|
+
*
|
|
217
|
+
* const words = await loadTileWordsFromModule("english");
|
|
218
|
+
* const play = deal("catdog",3);
|
|
219
|
+
* const verdict = judgeWithWords(new Map([["0,0","c"],["0,1","a"],["0,2","t"]]),words);
|
|
220
|
+
* console.log(mayDraw(play,verdict));
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
87
223
|
export function mayDraw(play, verdict) {
|
|
88
224
|
return play.hand.length === 0 && verdict.sound && tilesLeft(play) > 0;
|
|
89
225
|
}
|
|
90
|
-
/** The next tile or tiles out of the bag into the hand.
|
|
226
|
+
/** The next tile or tiles out of the bag into the hand.
|
|
227
|
+
*
|
|
228
|
+
* @param play - The current immutable solo-game progress.
|
|
229
|
+
* @param count - The number of tiles to draw.
|
|
230
|
+
* @returns The next tile or tiles out of the bag into the hand.
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* import { deal, draw } from "@johnmorrisdotca/kumimoji";
|
|
234
|
+
*
|
|
235
|
+
* const play = deal("catdog",3);
|
|
236
|
+
* console.log(draw(play,1).hand);
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
91
239
|
export function draw(play, count = KUMIMOJI_DRAW) {
|
|
92
240
|
const coming = (play.bag + play.returned).slice(play.taken, play.taken + count);
|
|
93
241
|
if (coming.length === 0)
|
|
94
242
|
return play;
|
|
95
243
|
return { ...play, taken: play.taken + coming.length, hand: [...play.hand, ...coming] };
|
|
96
244
|
}
|
|
97
|
-
/** Whether a trade may be made: the bag holds as many as a trade takes.
|
|
245
|
+
/** Whether a trade may be made: the bag holds as many as a trade takes.
|
|
246
|
+
*
|
|
247
|
+
* @param play - The current immutable solo-game progress.
|
|
248
|
+
* @returns Whether a trade may be made: the bag holds as many as a trade takes.
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* import { deal, mayTrade } from "@johnmorrisdotca/kumimoji";
|
|
252
|
+
*
|
|
253
|
+
* const play = deal("catdog",3);
|
|
254
|
+
* console.log(mayTrade(play));
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
98
257
|
export function mayTrade(play) {
|
|
99
258
|
return tilesLeft(play) >= KUMIMOJI_TRADE.take;
|
|
100
259
|
}
|
|
101
|
-
/** One tile from the hand to the bottom of the bag, and the next three out of it.
|
|
260
|
+
/** One tile from the hand to the bottom of the bag, and the next three out of it.
|
|
261
|
+
*
|
|
262
|
+
* @param play - The current immutable solo-game progress.
|
|
263
|
+
* @param handAt - The zero-based index of a tile in hand.
|
|
264
|
+
* @returns One tile from the hand to the bottom of the bag, and the next three out of it.
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* import { deal, trade } from "@johnmorrisdotca/kumimoji";
|
|
268
|
+
*
|
|
269
|
+
* const play = deal("catdog",3);
|
|
270
|
+
* console.log(trade(play,0).hand);
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
102
273
|
export function trade(play, handAt) {
|
|
103
274
|
const letter = play.hand[handAt];
|
|
104
275
|
if (letter === undefined || !mayTrade(play))
|
|
@@ -107,7 +278,22 @@ export function trade(play, handAt) {
|
|
|
107
278
|
const coming = (play.bag + returned).slice(play.taken, play.taken + KUMIMOJI_TRADE.take);
|
|
108
279
|
return { ...play, returned, taken: play.taken + coming.length, hand: [...play.hand.filter((_, at) => at !== handAt), ...coming] };
|
|
109
280
|
}
|
|
110
|
-
/** Whether the game is over: the bag empty, the hand used, and the grid sound.
|
|
281
|
+
/** Whether the game is over: the bag empty, the hand used, and the grid sound.
|
|
282
|
+
*
|
|
283
|
+
* @param play - The current immutable solo-game progress.
|
|
284
|
+
* @param verdict - The native word and connectivity verdict for this grid.
|
|
285
|
+
* @returns Whether the game is over: the bag empty, the hand used, and the grid sound.
|
|
286
|
+
* @example
|
|
287
|
+
* ```ts
|
|
288
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
289
|
+
* import { deal, isFinished, judgeWithWords } from "@johnmorrisdotca/kumimoji";
|
|
290
|
+
*
|
|
291
|
+
* const words = await loadTileWordsFromModule("english");
|
|
292
|
+
* const play = deal("catdog",3);
|
|
293
|
+
* const verdict = judgeWithWords(new Map([["0,0","c"],["0,1","a"],["0,2","t"]]),words);
|
|
294
|
+
* console.log(isFinished(play,verdict));
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
111
297
|
export function isFinished(play, verdict) {
|
|
112
298
|
return play.hand.length === 0 && tilesLeft(play) === 0 && verdict.sound;
|
|
113
299
|
}
|
|
@@ -117,11 +303,32 @@ export function isFinished(play, verdict) {
|
|
|
117
303
|
* (`encodeGrid`), as `12:q:ae:cat/2o/2w`. The bag is the puzzle's own, from
|
|
118
304
|
* its seed, so it is not written again, and where on the table the grid stood
|
|
119
305
|
* is the view's and not kept.
|
|
306
|
+
*
|
|
307
|
+
* @param play - The current immutable solo-game progress.
|
|
308
|
+
* @returns A GAME KEPT half way, as one string (`PuzzleRun.progress`): how many tiles were taken, the tiles traded back, the hand in its order and the grid (`encodeGrid`), as `12:q:ae:cat/2o/2w`. The bag is the puzzle's own, from its seed, so it is not written again, and where on the table the grid stood is the view's and not kept.
|
|
309
|
+
* @example
|
|
310
|
+
* ```ts
|
|
311
|
+
* import { deal, encodeTileProgress } from "@johnmorrisdotca/kumimoji";
|
|
312
|
+
*
|
|
313
|
+
* const play = deal("catdog",3);
|
|
314
|
+
* console.log(encodeTileProgress(play));
|
|
315
|
+
* ```
|
|
120
316
|
*/
|
|
121
317
|
export function encodeTileProgress(play) {
|
|
122
318
|
return `${play.taken}:${play.returned}:${play.hand.join("")}:${encodeGrid(play.tiles)}`;
|
|
123
319
|
}
|
|
124
|
-
/** The parts of a kept game, or null for a string that is not one: its shape only, with no bag to check it against.
|
|
320
|
+
/** The parts of a kept game, or null for a string that is not one: its shape only, with no bag to check it against.
|
|
321
|
+
*
|
|
322
|
+
* @param code - The encoded grid or progress text.
|
|
323
|
+
* @returns The parts of a kept game, or null for a string that is not one: its shape only, with no bag to check it against.
|
|
324
|
+
* @example
|
|
325
|
+
* ```ts
|
|
326
|
+
* import { deal, encodeTileProgress, readTileProgress } from "@johnmorrisdotca/kumimoji";
|
|
327
|
+
*
|
|
328
|
+
* const play = deal("catdog",3);
|
|
329
|
+
* console.log(readTileProgress(encodeTileProgress(play)));
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
125
332
|
export function readTileProgress(code) {
|
|
126
333
|
const parts = code.split(":");
|
|
127
334
|
if (parts.length !== 4)
|
|
@@ -139,6 +346,21 @@ export function readTileProgress(code) {
|
|
|
139
346
|
* to it: every tile held — hand and table — must be one taken from the bag
|
|
140
347
|
* and not given back. Null opens the game fresh rather than on a grid that
|
|
141
348
|
* never came out of this bag.
|
|
349
|
+
*
|
|
350
|
+
* @param code - The encoded grid or progress text.
|
|
351
|
+
* @param bag - The original bag in draw order.
|
|
352
|
+
* @param language - The English or Japanese tile language.
|
|
353
|
+
* @returns A kept game opened again on its own bag, or null where it does not belong to it: every tile held — hand and table — must be one taken from the bag and not given back. Null opens the game fresh rather than on a grid that never came out of this bag.
|
|
354
|
+
* @example
|
|
355
|
+
* ```ts
|
|
356
|
+
* import { deal, decodeTileProgress, encodeTileProgress } from "@johnmorrisdotca/kumimoji";
|
|
357
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
358
|
+
*
|
|
359
|
+
* await loadTileWordsFromModule("english");
|
|
360
|
+
* const play = deal("catdog",3);
|
|
361
|
+
* const bag = "catdogsun";
|
|
362
|
+
* console.log(decodeTileProgress(encodeTileProgress(play),play.bag));
|
|
363
|
+
* ```
|
|
142
364
|
*/
|
|
143
365
|
export function decodeTileProgress(code, bag, language = "english") {
|
|
144
366
|
const read = readTileProgress(code);
|