@johnmorrisdotca/kumimoji 1.2.2 → 1.3.1

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