@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.
Files changed (76) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/README.md +80 -39
  3. package/dist/check.d.ts +26 -1
  4. package/dist/check.js +26 -1
  5. package/dist/computer.types.d.ts +24 -2
  6. package/dist/computerPlay.d.ts +45 -2
  7. package/dist/computerPlay.js +45 -2
  8. package/dist/computerTurn.d.ts +42 -3
  9. package/dist/computerTurn.js +42 -3
  10. package/dist/daily.d.ts +22 -2
  11. package/dist/daily.js +22 -2
  12. package/dist/element-define.d.ts +1 -1
  13. package/dist/element-define.js +3 -13
  14. package/dist/element.d.ts +85 -4
  15. package/dist/element.js +176 -45
  16. package/dist/embed-day.d.ts +4 -0
  17. package/dist/embed-day.js +23 -0
  18. package/dist/export.d.ts +123 -6
  19. package/dist/export.js +91 -4
  20. package/dist/generate.d.ts +14 -0
  21. package/dist/generate.js +14 -0
  22. package/dist/grid.d.ts +181 -10
  23. package/dist/grid.js +122 -7
  24. package/dist/help.d.ts +36 -3
  25. package/dist/help.js +36 -3
  26. package/dist/judge.d.ts +14 -0
  27. package/dist/judge.js +14 -0
  28. package/dist/kana.d.ts +23 -1
  29. package/dist/kana.js +23 -1
  30. package/dist/kumimoji.types.d.ts +70 -5
  31. package/dist/party.d.ts +268 -14
  32. package/dist/party.js +268 -14
  33. package/dist/party.types.d.ts +50 -2
  34. package/dist/partyKept.d.ts +74 -4
  35. package/dist/partyKept.js +74 -4
  36. package/dist/partySeats.d.ts +92 -6
  37. package/dist/partySeats.js +72 -4
  38. package/dist/partyTurns.d.ts +171 -5
  39. package/dist/partyTurns.js +171 -5
  40. package/dist/placement.d.ts +50 -2
  41. package/dist/placement.js +30 -0
  42. package/dist/play.d.ts +247 -15
  43. package/dist/play.js +237 -15
  44. package/dist/random.d.ts +34 -3
  45. package/dist/random.js +23 -2
  46. package/dist/react.d.ts +42 -4
  47. package/dist/react.js +22 -5
  48. package/dist/showcase.d.ts +83 -7
  49. package/dist/showcase.js +49 -4
  50. package/dist/strings.d.ts +54 -5
  51. package/dist/strings.js +34 -3
  52. package/dist/tableView.d.ts +151 -8
  53. package/dist/tableView.js +129 -6
  54. package/dist/tileFace.d.ts +59 -5
  55. package/dist/tileFace.js +48 -4
  56. package/dist/tileFamily.d.ts +9 -0
  57. package/dist/tileFamily.js +9 -0
  58. package/dist/tileWords.d.ts +93 -6
  59. package/dist/tileWords.js +83 -6
  60. package/dist/tileWordsModule.d.ts +11 -1
  61. package/dist/tileWordsModule.js +11 -1
  62. package/dist/tiles.constants.d.ts +99 -5
  63. package/dist/tiles.constants.js +99 -5
  64. package/dist/turn.d.ts +82 -4
  65. package/dist/turn.js +82 -4
  66. package/dist/ui/board.d.ts +60 -5
  67. package/dist/ui/board.js +28 -2
  68. package/dist/ui/mount.d.ts +41 -2
  69. package/dist/ui/mount.js +38 -1
  70. package/dist/ui/style.d.ts +6 -1
  71. package/dist/ui/style.js +6 -0
  72. package/dist/version.d.ts +9 -2
  73. package/dist/version.js +9 -2
  74. package/dist/wilds.d.ts +22 -1
  75. package/dist/wilds.js +22 -1
  76. 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);