@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.
- package/CHANGELOG.md +33 -1
- package/CONTRIBUTING.md +11 -2
- package/README.md +80 -39
- package/dist/check.d.ts +26 -1
- package/dist/check.js +30 -3
- package/dist/computer.types.d.ts +24 -2
- package/dist/computerPlay.d.ts +45 -2
- package/dist/computerPlay.js +56 -6
- package/dist/computerTurn.d.ts +42 -3
- package/dist/computerTurn.js +47 -5
- package/dist/daily.d.ts +22 -2
- package/dist/daily.js +23 -3
- 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 +359 -77
- 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 +109 -9
- package/dist/generate.d.ts +14 -0
- package/dist/generate.js +32 -5
- package/dist/grid.d.ts +181 -10
- package/dist/grid.js +148 -11
- package/dist/help.d.ts +36 -3
- package/dist/help.js +36 -3
- package/dist/index.d.ts +22 -22
- package/dist/index.js +22 -22
- package/dist/judge.d.ts +14 -0
- package/dist/judge.js +14 -0
- package/dist/kana.d.ts +23 -1
- package/dist/kana.js +62 -7
- package/dist/kumimoji.types.d.ts +70 -5
- package/dist/party.d.ts +268 -14
- package/dist/party.js +296 -19
- package/dist/party.types.d.ts +50 -2
- package/dist/partyKept.d.ts +74 -4
- package/dist/partyKept.js +127 -12
- package/dist/partySeats.d.ts +92 -6
- package/dist/partySeats.js +83 -8
- package/dist/partyTurns.d.ts +171 -5
- package/dist/partyTurns.js +187 -8
- package/dist/placement.d.ts +50 -2
- package/dist/placement.js +35 -2
- package/dist/play.d.ts +247 -15
- package/dist/play.js +251 -18
- package/dist/random.d.ts +34 -3
- package/dist/random.js +23 -2
- package/dist/react.d.ts +42 -4
- package/dist/react.js +54 -7
- package/dist/showcase.d.ts +83 -7
- package/dist/showcase.js +61 -7
- 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 +94 -12
- package/dist/tileWordsModule.d.ts +12 -2
- package/dist/tileWordsModule.js +14 -2
- package/dist/tiles.constants.d.ts +99 -5
- package/dist/tiles.constants.js +171 -13
- package/dist/turn.d.ts +82 -4
- package/dist/turn.js +88 -5
- package/dist/ui/board.d.ts +60 -5
- package/dist/ui/board.js +44 -4
- package/dist/ui/draw.d.ts +62 -0
- package/dist/ui/draw.js +229 -0
- package/dist/ui/mount.d.ts +41 -2
- package/dist/ui/mount.js +190 -265
- package/dist/ui/style.d.ts +6 -1
- package/dist/ui/style.js +6 -0
- package/dist/ui.d.ts +3 -3
- package/dist/ui.js +2 -2
- package/dist/version.d.ts +9 -2
- package/dist/version.js +9 -2
- package/dist/wilds.d.ts +22 -1
- package/dist/wilds.js +25 -3
- package/package.json +68 -61
package/dist/grid.d.ts
CHANGED
|
@@ -11,40 +11,139 @@
|
|
|
11
11
|
* and COW down from its C. Only
|
|
12
12
|
* where the tiles stand beside one another is written, never where on the
|
|
13
13
|
* table they were, so one grid has one spelling however far it was dragged.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import type { Tiles } from "@johnmorrisdotca/kumimoji";
|
|
18
|
+
*
|
|
19
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
20
|
+
* const value: Tiles = tiles;
|
|
21
|
+
* console.log(value);
|
|
22
|
+
* ```
|
|
14
23
|
*/
|
|
15
24
|
export type Tiles = ReadonlyMap<string, string>;
|
|
16
|
-
/** A square's name, "row,col".
|
|
25
|
+
/** A square's name, "row,col".
|
|
26
|
+
*
|
|
27
|
+
* @param row - The integer row coordinate, which may be negative.
|
|
28
|
+
* @param col - The integer column coordinate, which may be negative.
|
|
29
|
+
* @returns A square's name, "row,col".
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { squareAt } from "@johnmorrisdotca/kumimoji";
|
|
33
|
+
*
|
|
34
|
+
* console.log(squareAt(-1,2));
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
17
37
|
export declare function squareAt(row: number, col: number): string;
|
|
18
|
-
/** A square's row and column, from its name.
|
|
38
|
+
/** A square's row and column, from its name.
|
|
39
|
+
*
|
|
40
|
+
* @param square - The row,column square name.
|
|
41
|
+
* @returns A square's row and column, from its name.
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { placeOf } from "@johnmorrisdotca/kumimoji";
|
|
45
|
+
*
|
|
46
|
+
* console.log(placeOf("-1,2"));
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
19
49
|
export declare function placeOf(square: string): {
|
|
20
50
|
row: number;
|
|
21
51
|
col: number;
|
|
22
52
|
};
|
|
23
|
-
/** The rows and columns a grid's tiles stand within.
|
|
53
|
+
/** The rows and columns a grid's tiles stand within.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* import type { Bounds } from "@johnmorrisdotca/kumimoji";
|
|
58
|
+
*
|
|
59
|
+
* const value: Bounds = {top:0,left:0,bottom:0,right:2};
|
|
60
|
+
* console.log(value);
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
24
63
|
export type Bounds = {
|
|
25
64
|
top: number;
|
|
26
65
|
left: number;
|
|
27
66
|
bottom: number;
|
|
28
67
|
right: number;
|
|
29
68
|
};
|
|
30
|
-
/** The rows and columns the tiles stand within, or null for no tiles.
|
|
69
|
+
/** The rows and columns the tiles stand within, or null for no tiles.
|
|
70
|
+
*
|
|
71
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
72
|
+
* @returns The rows and columns the tiles stand within, or null for no tiles.
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { boundsOf } from "@johnmorrisdotca/kumimoji";
|
|
76
|
+
*
|
|
77
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
78
|
+
* console.log(boundsOf(tiles));
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
31
81
|
export declare function boundsOf(tiles: Tiles): Bounds | null;
|
|
32
|
-
/** A grid as a string, drawn from its own top-left tile: `cat/2o/2w`. `decodeGrid` reads it back.
|
|
82
|
+
/** A grid as a string, drawn from its own top-left tile: `cat/2o/2w`. `decodeGrid` reads it back.
|
|
83
|
+
*
|
|
84
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
85
|
+
* @returns A grid as a string, drawn from its own top-left tile: `cat/2o/2w`. `decodeGrid` reads it back.
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* import { encodeGrid } from "@johnmorrisdotca/kumimoji";
|
|
89
|
+
*
|
|
90
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
91
|
+
* console.log(encodeGrid(tiles));
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
33
94
|
export declare function encodeGrid(tiles: Tiles): string;
|
|
34
95
|
/**
|
|
35
96
|
* A grid read back, its first row at row 0, or null for anything that is not
|
|
36
97
|
* one: a stray character, a capital, a grid wider or taller than any grid of
|
|
37
98
|
* fifty tiles can be. An empty string is no tiles.
|
|
99
|
+
*
|
|
100
|
+
* @param code - The encoded grid or progress text.
|
|
101
|
+
* @returns A grid read back, its first row at row 0, or null for anything that is not one: a stray character, a capital, a grid wider or taller than any grid of fifty tiles can be. An empty string is no tiles.
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* import { decodeGrid } from "@johnmorrisdotca/kumimoji";
|
|
105
|
+
*
|
|
106
|
+
* console.log(decodeGrid("cat"));
|
|
107
|
+
* ```
|
|
38
108
|
*/
|
|
39
109
|
export declare function decodeGrid(code: string): Map<string, string> | null;
|
|
40
|
-
/** How many of each letter.
|
|
110
|
+
/** How many of each letter.
|
|
111
|
+
*
|
|
112
|
+
* @param letters - The iterable tile letters to count.
|
|
113
|
+
* @returns How many of each letter.
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* import { lettersOf } from "@johnmorrisdotca/kumimoji";
|
|
117
|
+
*
|
|
118
|
+
* console.log(lettersOf("cat"));
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
41
121
|
export declare function lettersOf(letters: Iterable<string>): Map<string, number>;
|
|
42
|
-
/** Whether two tallies hold the same letters, as many of each.
|
|
122
|
+
/** Whether two tallies hold the same letters, as many of each.
|
|
123
|
+
*
|
|
124
|
+
* @param a - The first letter-count map.
|
|
125
|
+
* @param b - The second letter-count map.
|
|
126
|
+
* @returns Whether two tallies hold the same letters, as many of each.
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* import { lettersOf, sameLetters } from "@johnmorrisdotca/kumimoji";
|
|
130
|
+
*
|
|
131
|
+
* console.log(sameLetters(lettersOf("cat"),lettersOf("act")));
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
43
134
|
export declare function sameLetters(a: Map<string, number>, b: Map<string, number>): boolean;
|
|
44
135
|
/**
|
|
45
136
|
* THE LINES A RUN MAY LIE ALONG, each read top to bottom (and across, left to
|
|
46
137
|
* right): across and down always, and the two diagonals when the game was set
|
|
47
138
|
* up with Diagonals — down to the right, and down to the left.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* import type { RunLine } from "@johnmorrisdotca/kumimoji";
|
|
143
|
+
*
|
|
144
|
+
* const value: RunLine = "across";
|
|
145
|
+
* console.log(value);
|
|
146
|
+
* ```
|
|
48
147
|
*/
|
|
49
148
|
export type RunLine = "across" | "down" | "downRight" | "downLeft";
|
|
50
149
|
/**
|
|
@@ -52,13 +151,37 @@ export type RunLine = "across" | "down" | "downRight" | "downLeft";
|
|
|
52
151
|
* at a corner are what every crossword is full of — the letter above a word
|
|
53
152
|
* and the one beside it — so a pair is free, and only three or more in a
|
|
54
153
|
* line are a diagonal word.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* import { DIAGONAL_RUN_LEAST } from "@johnmorrisdotca/kumimoji";
|
|
158
|
+
* console.log(DIAGONAL_RUN_LEAST);
|
|
159
|
+
* ```
|
|
55
160
|
*/
|
|
56
161
|
export declare const DIAGONAL_RUN_LEAST = 3;
|
|
57
|
-
/** How a grid is read: whether its diagonals are (`KumimojiOptions.diagonals`).
|
|
162
|
+
/** How a grid is read: whether its diagonals are (`KumimojiOptions.diagonals`).
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* import type { GridRules } from "@johnmorrisdotca/kumimoji";
|
|
167
|
+
*
|
|
168
|
+
* const value: GridRules = {diagonals:true};
|
|
169
|
+
* console.log(value);
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
58
172
|
export type GridRules = {
|
|
59
173
|
diagonals?: boolean;
|
|
60
174
|
};
|
|
61
|
-
/** A run of tiles along one line: the word it spells and the squares it stands on, in reading order.
|
|
175
|
+
/** A run of tiles along one line: the word it spells and the squares it stands on, in reading order.
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```ts
|
|
179
|
+
* import type { Run } from "@johnmorrisdotca/kumimoji";
|
|
180
|
+
*
|
|
181
|
+
* const value: Run = {word:"cat",squares:["0,0","0,1","0,2"],line:"across"};
|
|
182
|
+
* console.log(value);
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
62
185
|
export type Run = {
|
|
63
186
|
word: string;
|
|
64
187
|
squares: string[];
|
|
@@ -68,6 +191,17 @@ export type Run = {
|
|
|
68
191
|
* Every run the grid is read by: two or more tiles across, then down, and
|
|
69
192
|
* with Diagonals three or more down to the right, then down to the left. A
|
|
70
193
|
* tile with nothing beside it in a line is no run.
|
|
194
|
+
*
|
|
195
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
196
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
197
|
+
* @returns Every run the grid is read by: two or more tiles across, then down, and with Diagonals three or more down to the right, then down to the left. A tile with nothing beside it in a line is no run.
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* import { runsOf } from "@johnmorrisdotca/kumimoji";
|
|
201
|
+
*
|
|
202
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
203
|
+
* console.log(runsOf(tiles));
|
|
204
|
+
* ```
|
|
71
205
|
*/
|
|
72
206
|
export declare function runsOf(tiles: Tiles, rules?: GridRules): Run[];
|
|
73
207
|
/**
|
|
@@ -76,6 +210,17 @@ export declare function runsOf(tiles: Tiles, rules?: GridRules): Run[];
|
|
|
76
210
|
* other in one of those runs are joined too: a diagonal word holds a
|
|
77
211
|
* crossword together as a word across does. A pair touching at a corner is
|
|
78
212
|
* never a link, because it is never read.
|
|
213
|
+
*
|
|
214
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
215
|
+
* @param links - The runs connecting groups; computed from the grid when omitted.
|
|
216
|
+
* @returns The tiles in groups that touch across or down, largest first. With `links` — the diagonal runs a grid with Diagonals reads — the tiles next to each other in one of those runs are joined too: a diagonal word holds a crossword together as a word across does. A pair touching at a corner is never a link, because it is never read.
|
|
217
|
+
* @example
|
|
218
|
+
* ```ts
|
|
219
|
+
* import { groupsOf } from "@johnmorrisdotca/kumimoji";
|
|
220
|
+
*
|
|
221
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
222
|
+
* console.log(groupsOf(tiles));
|
|
223
|
+
* ```
|
|
79
224
|
*/
|
|
80
225
|
export declare function groupsOf(tiles: Tiles, links?: readonly Run[]): string[][];
|
|
81
226
|
/**
|
|
@@ -85,6 +230,18 @@ export declare function groupsOf(tiles: Tiles, links?: readonly Run[]): string[]
|
|
|
85
230
|
* With Diagonals (`rules`), the diagonal runs of three or more are runs too:
|
|
86
231
|
* each must be a word, a misspelt one is marked as any other is, and each
|
|
87
232
|
* joins its tiles (`groupsOf`).
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```ts
|
|
236
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
237
|
+
* import { judgeWithWords } from "@johnmorrisdotca/kumimoji";
|
|
238
|
+
* import type { GridVerdict } from "@johnmorrisdotca/kumimoji";
|
|
239
|
+
*
|
|
240
|
+
* const words = await loadTileWordsFromModule("english");
|
|
241
|
+
* const verdict = judgeWithWords(new Map([["0,0","c"],["0,1","a"],["0,2","t"]]),words);
|
|
242
|
+
* const value: GridVerdict = verdict;
|
|
243
|
+
* console.log(value);
|
|
244
|
+
* ```
|
|
88
245
|
*/
|
|
89
246
|
export type GridVerdict = {
|
|
90
247
|
sound: boolean;
|
|
@@ -96,5 +253,19 @@ export type GridVerdict = {
|
|
|
96
253
|
/** The runs that are not words, as spelled, for the line under the table. */
|
|
97
254
|
notWords: readonly string[];
|
|
98
255
|
};
|
|
99
|
-
/** A grid judged against any test of a word: `isWord` answers for a run as spelt, and `readable` says how to name one that is not. `judgeWithWords` is this with a language's list.
|
|
256
|
+
/** A grid judged against any test of a word: `isWord` answers for a run as spelt, and `readable` says how to name one that is not. `judgeWithWords` is this with a language's list.
|
|
257
|
+
*
|
|
258
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
259
|
+
* @param isWord - The predicate that accepts a readable word.
|
|
260
|
+
* @param readable - The conversion from tile codes to readable words.
|
|
261
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
262
|
+
* @returns A grid judged against any test of a word: `isWord` answers for a run as spelt, and `readable` says how to name one that is not. `judgeWithWords` is this with a language's list.
|
|
263
|
+
* @example
|
|
264
|
+
* ```ts
|
|
265
|
+
* import { judgeGrid } from "@johnmorrisdotca/kumimoji";
|
|
266
|
+
*
|
|
267
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
268
|
+
* console.log(judgeGrid(tiles,word=>word==="cat"));
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
100
271
|
export declare function judgeGrid(tiles: Tiles, isWord: (word: string) => boolean, readable?: (word: string) => string, rules?: GridRules): GridVerdict;
|
package/dist/grid.js
CHANGED
|
@@ -1,14 +1,46 @@
|
|
|
1
1
|
import { KUMIMOJI_GRID_MOST } from "./tiles.constants.js";
|
|
2
|
-
/** A square's name, "row,col".
|
|
2
|
+
/** A square's name, "row,col".
|
|
3
|
+
*
|
|
4
|
+
* @param row - The integer row coordinate, which may be negative.
|
|
5
|
+
* @param col - The integer column coordinate, which may be negative.
|
|
6
|
+
* @returns A square's name, "row,col".
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { squareAt } from "@johnmorrisdotca/kumimoji";
|
|
10
|
+
*
|
|
11
|
+
* console.log(squareAt(-1,2));
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
3
14
|
export function squareAt(row, col) {
|
|
4
15
|
return `${row},${col}`;
|
|
5
16
|
}
|
|
6
|
-
/** A square's row and column, from its name.
|
|
17
|
+
/** A square's row and column, from its name.
|
|
18
|
+
*
|
|
19
|
+
* @param square - The row,column square name.
|
|
20
|
+
* @returns A square's row and column, from its name.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { placeOf } from "@johnmorrisdotca/kumimoji";
|
|
24
|
+
*
|
|
25
|
+
* console.log(placeOf("-1,2"));
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
7
28
|
export function placeOf(square) {
|
|
8
29
|
const [row, col] = square.split(",").map(Number);
|
|
9
30
|
return { row: row, col: col };
|
|
10
31
|
}
|
|
11
|
-
/** The rows and columns the tiles stand within, or null for no tiles.
|
|
32
|
+
/** The rows and columns the tiles stand within, or null for no tiles.
|
|
33
|
+
*
|
|
34
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
35
|
+
* @returns The rows and columns the tiles stand within, or null for no tiles.
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { boundsOf } from "@johnmorrisdotca/kumimoji";
|
|
39
|
+
*
|
|
40
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
41
|
+
* console.log(boundsOf(tiles));
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
12
44
|
export function boundsOf(tiles) {
|
|
13
45
|
let bounds = null;
|
|
14
46
|
for (const square of tiles.keys()) {
|
|
@@ -16,11 +48,27 @@ export function boundsOf(tiles) {
|
|
|
16
48
|
bounds =
|
|
17
49
|
bounds === null
|
|
18
50
|
? { top: row, left: col, bottom: row, right: col }
|
|
19
|
-
: {
|
|
51
|
+
: {
|
|
52
|
+
top: Math.min(bounds.top, row),
|
|
53
|
+
left: Math.min(bounds.left, col),
|
|
54
|
+
bottom: Math.max(bounds.bottom, row),
|
|
55
|
+
right: Math.max(bounds.right, col),
|
|
56
|
+
};
|
|
20
57
|
}
|
|
21
58
|
return bounds;
|
|
22
59
|
}
|
|
23
|
-
/** A grid as a string, drawn from its own top-left tile: `cat/2o/2w`. `decodeGrid` reads it back.
|
|
60
|
+
/** A grid as a string, drawn from its own top-left tile: `cat/2o/2w`. `decodeGrid` reads it back.
|
|
61
|
+
*
|
|
62
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
63
|
+
* @returns A grid as a string, drawn from its own top-left tile: `cat/2o/2w`. `decodeGrid` reads it back.
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { encodeGrid } from "@johnmorrisdotca/kumimoji";
|
|
67
|
+
*
|
|
68
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
69
|
+
* console.log(encodeGrid(tiles));
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
24
72
|
export function encodeGrid(tiles) {
|
|
25
73
|
const bounds = boundsOf(tiles);
|
|
26
74
|
if (bounds === null)
|
|
@@ -48,6 +96,15 @@ export function encodeGrid(tiles) {
|
|
|
48
96
|
* A grid read back, its first row at row 0, or null for anything that is not
|
|
49
97
|
* one: a stray character, a capital, a grid wider or taller than any grid of
|
|
50
98
|
* fifty tiles can be. An empty string is no tiles.
|
|
99
|
+
*
|
|
100
|
+
* @param code - The encoded grid or progress text.
|
|
101
|
+
* @returns A grid read back, its first row at row 0, or null for anything that is not one: a stray character, a capital, a grid wider or taller than any grid of fifty tiles can be. An empty string is no tiles.
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* import { decodeGrid } from "@johnmorrisdotca/kumimoji";
|
|
105
|
+
*
|
|
106
|
+
* console.log(decodeGrid("cat"));
|
|
107
|
+
* ```
|
|
51
108
|
*/
|
|
52
109
|
export function decodeGrid(code) {
|
|
53
110
|
if (typeof code !== "string")
|
|
@@ -97,7 +154,17 @@ export function decodeGrid(code) {
|
|
|
97
154
|
}
|
|
98
155
|
return tiles;
|
|
99
156
|
}
|
|
100
|
-
/** How many of each letter.
|
|
157
|
+
/** How many of each letter.
|
|
158
|
+
*
|
|
159
|
+
* @param letters - The iterable tile letters to count.
|
|
160
|
+
* @returns How many of each letter.
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* import { lettersOf } from "@johnmorrisdotca/kumimoji";
|
|
164
|
+
*
|
|
165
|
+
* console.log(lettersOf("cat"));
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
101
168
|
export function lettersOf(letters) {
|
|
102
169
|
const counts = new Map();
|
|
103
170
|
for (const letter of letters)
|
|
@@ -105,7 +172,18 @@ export function lettersOf(letters) {
|
|
|
105
172
|
counts.set(letter, (counts.get(letter) ?? 0) + 1);
|
|
106
173
|
return counts;
|
|
107
174
|
}
|
|
108
|
-
/** Whether two tallies hold the same letters, as many of each.
|
|
175
|
+
/** Whether two tallies hold the same letters, as many of each.
|
|
176
|
+
*
|
|
177
|
+
* @param a - The first letter-count map.
|
|
178
|
+
* @param b - The second letter-count map.
|
|
179
|
+
* @returns Whether two tallies hold the same letters, as many of each.
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* import { lettersOf, sameLetters } from "@johnmorrisdotca/kumimoji";
|
|
183
|
+
*
|
|
184
|
+
* console.log(sameLetters(lettersOf("cat"),lettersOf("act")));
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
109
187
|
export function sameLetters(a, b) {
|
|
110
188
|
if (a.size !== b.size)
|
|
111
189
|
return false;
|
|
@@ -115,12 +193,23 @@ export function sameLetters(a, b) {
|
|
|
115
193
|
return true;
|
|
116
194
|
}
|
|
117
195
|
/** One step along each line, as rows and columns. */
|
|
118
|
-
const STEP = {
|
|
196
|
+
const STEP = {
|
|
197
|
+
across: [0, 1],
|
|
198
|
+
down: [1, 0],
|
|
199
|
+
downRight: [1, 1],
|
|
200
|
+
downLeft: [1, -1],
|
|
201
|
+
};
|
|
119
202
|
/**
|
|
120
203
|
* The fewest tiles a diagonal run needs before it is read. Two tiles touching
|
|
121
204
|
* at a corner are what every crossword is full of — the letter above a word
|
|
122
205
|
* and the one beside it — so a pair is free, and only three or more in a
|
|
123
206
|
* line are a diagonal word.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```ts
|
|
210
|
+
* import { DIAGONAL_RUN_LEAST } from "@johnmorrisdotca/kumimoji";
|
|
211
|
+
* console.log(DIAGONAL_RUN_LEAST);
|
|
212
|
+
* ```
|
|
124
213
|
*/
|
|
125
214
|
export const DIAGONAL_RUN_LEAST = 3;
|
|
126
215
|
function runsAlong(tiles, line, least) {
|
|
@@ -147,6 +236,17 @@ function runsAlong(tiles, line, least) {
|
|
|
147
236
|
* Every run the grid is read by: two or more tiles across, then down, and
|
|
148
237
|
* with Diagonals three or more down to the right, then down to the left. A
|
|
149
238
|
* tile with nothing beside it in a line is no run.
|
|
239
|
+
*
|
|
240
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
241
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
242
|
+
* @returns Every run the grid is read by: two or more tiles across, then down, and with Diagonals three or more down to the right, then down to the left. A tile with nothing beside it in a line is no run.
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* import { runsOf } from "@johnmorrisdotca/kumimoji";
|
|
246
|
+
*
|
|
247
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
248
|
+
* console.log(runsOf(tiles));
|
|
249
|
+
* ```
|
|
150
250
|
*/
|
|
151
251
|
export function runsOf(tiles, rules = {}) {
|
|
152
252
|
const runs = [...runsAlong(tiles, "across", 2), ...runsAlong(tiles, "down", 2)];
|
|
@@ -160,6 +260,17 @@ export function runsOf(tiles, rules = {}) {
|
|
|
160
260
|
* other in one of those runs are joined too: a diagonal word holds a
|
|
161
261
|
* crossword together as a word across does. A pair touching at a corner is
|
|
162
262
|
* never a link, because it is never read.
|
|
263
|
+
*
|
|
264
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
265
|
+
* @param links - The runs connecting groups; computed from the grid when omitted.
|
|
266
|
+
* @returns The tiles in groups that touch across or down, largest first. With `links` — the diagonal runs a grid with Diagonals reads — the tiles next to each other in one of those runs are joined too: a diagonal word holds a crossword together as a word across does. A pair touching at a corner is never a link, because it is never read.
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* import { groupsOf } from "@johnmorrisdotca/kumimoji";
|
|
270
|
+
*
|
|
271
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
272
|
+
* console.log(groupsOf(tiles));
|
|
273
|
+
* ```
|
|
163
274
|
*/
|
|
164
275
|
export function groupsOf(tiles, links = []) {
|
|
165
276
|
const joined = new Map();
|
|
@@ -182,7 +293,13 @@ export function groupsOf(tiles, links = []) {
|
|
|
182
293
|
const at = queue.pop();
|
|
183
294
|
group.push(at);
|
|
184
295
|
const { row, col } = placeOf(at);
|
|
185
|
-
for (const near of [
|
|
296
|
+
for (const near of [
|
|
297
|
+
squareAt(row - 1, col),
|
|
298
|
+
squareAt(row + 1, col),
|
|
299
|
+
squareAt(row, col - 1),
|
|
300
|
+
squareAt(row, col + 1),
|
|
301
|
+
...(joined.get(at) ?? []),
|
|
302
|
+
]) {
|
|
186
303
|
if (tiles.has(near) && !seen.has(near)) {
|
|
187
304
|
seen.add(near);
|
|
188
305
|
queue.push(near);
|
|
@@ -193,7 +310,21 @@ export function groupsOf(tiles, links = []) {
|
|
|
193
310
|
}
|
|
194
311
|
return groups.sort((a, b) => b.length - a.length);
|
|
195
312
|
}
|
|
196
|
-
/** A grid judged against any test of a word: `isWord` answers for a run as spelt, and `readable` says how to name one that is not. `judgeWithWords` is this with a language's list.
|
|
313
|
+
/** A grid judged against any test of a word: `isWord` answers for a run as spelt, and `readable` says how to name one that is not. `judgeWithWords` is this with a language's list.
|
|
314
|
+
*
|
|
315
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
316
|
+
* @param isWord - The predicate that accepts a readable word.
|
|
317
|
+
* @param readable - The conversion from tile codes to readable words.
|
|
318
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
319
|
+
* @returns A grid judged against any test of a word: `isWord` answers for a run as spelt, and `readable` says how to name one that is not. `judgeWithWords` is this with a language's list.
|
|
320
|
+
* @example
|
|
321
|
+
* ```ts
|
|
322
|
+
* import { judgeGrid } from "@johnmorrisdotca/kumimoji";
|
|
323
|
+
*
|
|
324
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
325
|
+
* console.log(judgeGrid(tiles,word=>word==="cat"));
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
197
328
|
export function judgeGrid(tiles, isWord, readable = (word) => word, rules = {}) {
|
|
198
329
|
const misspelt = new Set();
|
|
199
330
|
const notWords = [];
|
|
@@ -207,5 +338,11 @@ export function judgeGrid(tiles, isWord, readable = (word) => word, rules = {})
|
|
|
207
338
|
}
|
|
208
339
|
const groups = groupsOf(tiles, runs.filter((run) => run.line === "downRight" || run.line === "downLeft"));
|
|
209
340
|
const apart = new Set(groups.slice(1).flat());
|
|
210
|
-
return {
|
|
341
|
+
return {
|
|
342
|
+
sound: tiles.size >= 2 && groups.length === 1 && notWords.length === 0,
|
|
343
|
+
tiles: tiles.size,
|
|
344
|
+
misspelt,
|
|
345
|
+
apart,
|
|
346
|
+
notWords,
|
|
347
|
+
};
|
|
211
348
|
}
|
package/dist/help.d.ts
CHANGED
|
@@ -12,9 +12,42 @@ import type { TileWords } from "./tileWords.ts";
|
|
|
12
12
|
* Only the hand's own tiles are read — a wild is left for the player to place
|
|
13
13
|
* — and nothing on the table is moved.
|
|
14
14
|
*/
|
|
15
|
-
/** How many words one hand offers before the presses go round again: the longest first.
|
|
15
|
+
/** How many words one hand offers before the presses go round again: the longest first.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { HELP_WORDS_MOST } from "@johnmorrisdotca/kumimoji";
|
|
20
|
+
* console.log(HELP_WORDS_MOST);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
16
23
|
export declare const HELP_WORDS_MOST = 40;
|
|
17
|
-
/** The words the hand's own tiles spell, longest first and then in the list's order; wilds are not used.
|
|
24
|
+
/** The words the hand's own tiles spell, longest first and then in the list's order; wilds are not used.
|
|
25
|
+
*
|
|
26
|
+
* @param hand - The hand size or tile codes, as declared by the function signature.
|
|
27
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
28
|
+
* @returns The words the hand's own tiles spell, longest first and then in the list's order; wilds are not used.
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
32
|
+
* import { wordsInHand } from "@johnmorrisdotca/kumimoji";
|
|
33
|
+
*
|
|
34
|
+
* const words = await loadTileWordsFromModule("english");
|
|
35
|
+
* console.log(wordsInHand(["c","a","t"],words));
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
18
38
|
export declare function wordsInHand(hand: readonly string[], words: TileWords): string[];
|
|
19
|
-
/** The hand with `word`'s tiles first, in its order, and the rest after them as they were.
|
|
39
|
+
/** The hand with `word`'s tiles first, in its order, and the rest after them as they were.
|
|
40
|
+
*
|
|
41
|
+
* @param play - The current immutable solo-game progress.
|
|
42
|
+
* @param word - The encoded word to lay or spell.
|
|
43
|
+
* @returns The hand with `word`'s tiles first, in its order, and the rest after them as they were.
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { deal, handSpelling } from "@johnmorrisdotca/kumimoji";
|
|
47
|
+
*
|
|
48
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
49
|
+
* const play = deal("catdog",3);
|
|
50
|
+
* console.log(handSpelling(play,"cat").tiles);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
20
53
|
export declare function handSpelling(play: TilePlay, word: string): TilePlay;
|
package/dist/help.js
CHANGED
|
@@ -10,9 +10,29 @@
|
|
|
10
10
|
* Only the hand's own tiles are read — a wild is left for the player to place
|
|
11
11
|
* — and nothing on the table is moved.
|
|
12
12
|
*/
|
|
13
|
-
/** How many words one hand offers before the presses go round again: the longest first.
|
|
13
|
+
/** How many words one hand offers before the presses go round again: the longest first.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { HELP_WORDS_MOST } from "@johnmorrisdotca/kumimoji";
|
|
18
|
+
* console.log(HELP_WORDS_MOST);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
14
21
|
export const HELP_WORDS_MOST = 40;
|
|
15
|
-
/** The words the hand's own tiles spell, longest first and then in the list's order; wilds are not used.
|
|
22
|
+
/** The words the hand's own tiles spell, longest first and then in the list's order; wilds are not used.
|
|
23
|
+
*
|
|
24
|
+
* @param hand - The hand size or tile codes, as declared by the function signature.
|
|
25
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
26
|
+
* @returns The words the hand's own tiles spell, longest first and then in the list's order; wilds are not used.
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
30
|
+
* import { wordsInHand } from "@johnmorrisdotca/kumimoji";
|
|
31
|
+
*
|
|
32
|
+
* const words = await loadTileWordsFromModule("english");
|
|
33
|
+
* console.log(wordsInHand(["c","a","t"],words));
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
16
36
|
export function wordsInHand(hand, words) {
|
|
17
37
|
const have = new Map();
|
|
18
38
|
for (const tile of hand)
|
|
@@ -42,7 +62,20 @@ export function wordsInHand(hand, words) {
|
|
|
42
62
|
}
|
|
43
63
|
return found;
|
|
44
64
|
}
|
|
45
|
-
/** The hand with `word`'s tiles first, in its order, and the rest after them as they were.
|
|
65
|
+
/** The hand with `word`'s tiles first, in its order, and the rest after them as they were.
|
|
66
|
+
*
|
|
67
|
+
* @param play - The current immutable solo-game progress.
|
|
68
|
+
* @param word - The encoded word to lay or spell.
|
|
69
|
+
* @returns The hand with `word`'s tiles first, in its order, and the rest after them as they were.
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { deal, handSpelling } 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(handSpelling(play,"cat").tiles);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
46
79
|
export function handSpelling(play, word) {
|
|
47
80
|
const rest = [...play.hand];
|
|
48
81
|
const front = [];
|
package/dist/index.d.ts
CHANGED
|
@@ -16,33 +16,33 @@
|
|
|
16
16
|
* a test through `@johnmorrisdotca/kumimoji/words`, which reads them from
|
|
17
17
|
* disk.
|
|
18
18
|
*/
|
|
19
|
-
export * from "./kumimoji.types.ts";
|
|
20
|
-
export * from "./tiles.constants.ts";
|
|
21
|
-
export * from "./kana.ts";
|
|
22
|
-
export * from "./tileFace.ts";
|
|
23
|
-
export * from "./tileFamily.ts";
|
|
24
|
-
export * from "./tileWords.ts";
|
|
25
|
-
export * from "./grid.ts";
|
|
26
|
-
export * from "./placement.ts";
|
|
27
|
-
export * from "./wilds.ts";
|
|
28
|
-
export * from "./judge.ts";
|
|
29
19
|
export * from "./check.ts";
|
|
30
|
-
export * from "./generate.ts";
|
|
31
|
-
export * from "./play.ts";
|
|
32
|
-
export * from "./help.ts";
|
|
33
|
-
export * from "./turn.ts";
|
|
34
|
-
export * from "./tableView.ts";
|
|
35
|
-
export * from "./showcase.ts";
|
|
36
|
-
export * from "./party.types.ts";
|
|
37
|
-
export * from "./party.ts";
|
|
38
|
-
export * from "./partyTurns.ts";
|
|
39
|
-
export * from "./partySeats.ts";
|
|
40
|
-
export * from "./partyKept.ts";
|
|
41
20
|
export * from "./computer.types.ts";
|
|
42
21
|
export * from "./computerPlay.ts";
|
|
43
22
|
export * from "./computerTurn.ts";
|
|
44
|
-
export * from "./random.ts";
|
|
45
23
|
export * from "./daily.ts";
|
|
46
24
|
export * from "./export.ts";
|
|
25
|
+
export * from "./generate.ts";
|
|
26
|
+
export * from "./grid.ts";
|
|
27
|
+
export * from "./help.ts";
|
|
28
|
+
export * from "./judge.ts";
|
|
29
|
+
export * from "./kana.ts";
|
|
30
|
+
export * from "./kumimoji.types.ts";
|
|
31
|
+
export * from "./party.ts";
|
|
32
|
+
export * from "./party.types.ts";
|
|
33
|
+
export * from "./partyKept.ts";
|
|
34
|
+
export * from "./partySeats.ts";
|
|
35
|
+
export * from "./partyTurns.ts";
|
|
36
|
+
export * from "./placement.ts";
|
|
37
|
+
export * from "./play.ts";
|
|
38
|
+
export * from "./random.ts";
|
|
39
|
+
export * from "./showcase.ts";
|
|
47
40
|
export * from "./strings.ts";
|
|
41
|
+
export * from "./tableView.ts";
|
|
42
|
+
export * from "./tileFace.ts";
|
|
43
|
+
export * from "./tileFamily.ts";
|
|
44
|
+
export * from "./tiles.constants.ts";
|
|
45
|
+
export * from "./tileWords.ts";
|
|
46
|
+
export * from "./turn.ts";
|
|
48
47
|
export { KUMIMOJI_VERSION } from "./version.ts";
|
|
48
|
+
export * from "./wilds.ts";
|