@johnmorrisdotca/kumimoji 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/README.md +80 -39
- package/dist/check.d.ts +26 -1
- package/dist/check.js +26 -1
- package/dist/computer.types.d.ts +24 -2
- package/dist/computerPlay.d.ts +45 -2
- package/dist/computerPlay.js +45 -2
- package/dist/computerTurn.d.ts +42 -3
- package/dist/computerTurn.js +42 -3
- package/dist/daily.d.ts +22 -2
- package/dist/daily.js +22 -2
- package/dist/element-define.d.ts +1 -1
- package/dist/element-define.js +3 -13
- package/dist/element.d.ts +85 -4
- package/dist/element.js +176 -45
- package/dist/embed-day.d.ts +4 -0
- package/dist/embed-day.js +23 -0
- package/dist/export.d.ts +123 -6
- package/dist/export.js +91 -4
- package/dist/generate.d.ts +14 -0
- package/dist/generate.js +14 -0
- package/dist/grid.d.ts +181 -10
- package/dist/grid.js +122 -7
- package/dist/help.d.ts +36 -3
- package/dist/help.js +36 -3
- package/dist/judge.d.ts +14 -0
- package/dist/judge.js +14 -0
- package/dist/kana.d.ts +23 -1
- package/dist/kana.js +23 -1
- package/dist/kumimoji.types.d.ts +70 -5
- package/dist/party.d.ts +268 -14
- package/dist/party.js +268 -14
- package/dist/party.types.d.ts +50 -2
- package/dist/partyKept.d.ts +74 -4
- package/dist/partyKept.js +74 -4
- package/dist/partySeats.d.ts +92 -6
- package/dist/partySeats.js +72 -4
- package/dist/partyTurns.d.ts +171 -5
- package/dist/partyTurns.js +171 -5
- package/dist/placement.d.ts +50 -2
- package/dist/placement.js +30 -0
- package/dist/play.d.ts +247 -15
- package/dist/play.js +237 -15
- package/dist/random.d.ts +34 -3
- package/dist/random.js +23 -2
- package/dist/react.d.ts +42 -4
- package/dist/react.js +22 -5
- package/dist/showcase.d.ts +83 -7
- package/dist/showcase.js +49 -4
- package/dist/strings.d.ts +54 -5
- package/dist/strings.js +34 -3
- package/dist/tableView.d.ts +151 -8
- package/dist/tableView.js +129 -6
- package/dist/tileFace.d.ts +59 -5
- package/dist/tileFace.js +48 -4
- package/dist/tileFamily.d.ts +9 -0
- package/dist/tileFamily.js +9 -0
- package/dist/tileWords.d.ts +93 -6
- package/dist/tileWords.js +83 -6
- package/dist/tileWordsModule.d.ts +11 -1
- package/dist/tileWordsModule.js +11 -1
- package/dist/tiles.constants.d.ts +99 -5
- package/dist/tiles.constants.js +99 -5
- package/dist/turn.d.ts +82 -4
- package/dist/turn.js +82 -4
- package/dist/ui/board.d.ts +60 -5
- package/dist/ui/board.js +28 -2
- package/dist/ui/mount.d.ts +41 -2
- package/dist/ui/mount.js +38 -1
- package/dist/ui/style.d.ts +6 -1
- package/dist/ui/style.js +6 -0
- package/dist/version.d.ts +9 -2
- package/dist/version.js +9 -2
- package/dist/wilds.d.ts +22 -1
- package/dist/wilds.js +22 -1
- package/package.json +64 -56
package/dist/partyTurns.js
CHANGED
|
@@ -8,7 +8,20 @@ import { KUMIMOJI_TRADE } from "./tiles.constants.js";
|
|
|
8
8
|
* solo game's (`play.ts`), and the deal and the draw are `party.ts`'s. Pure:
|
|
9
9
|
* each returns a new game, or the one it was given where the move is refused.
|
|
10
10
|
*/
|
|
11
|
-
/** Whether the game is over.
|
|
11
|
+
/** Whether the game is over.
|
|
12
|
+
*
|
|
13
|
+
* @param game - The current immutable shared-bag party game.
|
|
14
|
+
* @returns Whether the game is over.
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { isOver, startParty } from "@johnmorrisdotca/kumimoji";
|
|
18
|
+
*
|
|
19
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
20
|
+
* const bag = "catdogsun";
|
|
21
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
22
|
+
* console.log(isOver(game));
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
12
25
|
export function isOver(game) {
|
|
13
26
|
return game.ending !== null;
|
|
14
27
|
}
|
|
@@ -16,15 +29,57 @@ export function isOver(game) {
|
|
|
16
29
|
* Whether the player whose turn it is would go out with Done: their hand
|
|
17
30
|
* used, their grid sound, and too few tiles in the bag for everybody still in
|
|
18
31
|
* to draw.
|
|
32
|
+
*
|
|
33
|
+
* @param game - The current immutable shared-bag party game.
|
|
34
|
+
* @param verdict - The native word and connectivity verdict for this grid.
|
|
35
|
+
* @returns Whether the player whose turn it is would go out with Done: their hand used, their grid sound, and too few tiles in the bag for everybody still in to draw.
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
39
|
+
* import { goesOut, judgeWithWords, startParty } from "@johnmorrisdotca/kumimoji";
|
|
40
|
+
*
|
|
41
|
+
* const words = await loadTileWordsFromModule("english");
|
|
42
|
+
* const verdict = judgeWithWords(new Map([["0,0","c"],["0,1","a"],["0,2","t"]]),words);
|
|
43
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
44
|
+
* const bag = "catdogsun";
|
|
45
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
46
|
+
* console.log(goesOut(game,verdict));
|
|
47
|
+
* ```
|
|
19
48
|
*/
|
|
20
49
|
export function goesOut(game, verdict) {
|
|
21
50
|
return !isOver(game) && game.players[game.turn].hand.length === 0 && verdict.sound && partyTilesLeft(game) < stillIn(game).length;
|
|
22
51
|
}
|
|
23
|
-
/** Whether the player whose turn it is has laid a tile on their table this turn: more tiles there than when it began.
|
|
52
|
+
/** Whether the player whose turn it is has laid a tile on their table this turn: more tiles there than when it began.
|
|
53
|
+
*
|
|
54
|
+
* @param game - The current immutable shared-bag party game.
|
|
55
|
+
* @returns Whether the player whose turn it is has laid a tile on their table this turn: more tiles there than when it began.
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { laidThisTurn, startParty } from "@johnmorrisdotca/kumimoji";
|
|
59
|
+
*
|
|
60
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
61
|
+
* const bag = "catdogsun";
|
|
62
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
63
|
+
* console.log(laidThisTurn(game));
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
24
66
|
export function laidThisTurn(game) {
|
|
25
67
|
return game.players[game.turn].tiles.size > [...game.startTable].length;
|
|
26
68
|
}
|
|
27
|
-
/** Whether the player whose turn it is is the only one still in: everybody else has resigned.
|
|
69
|
+
/** Whether the player whose turn it is is the only one still in: everybody else has resigned.
|
|
70
|
+
*
|
|
71
|
+
* @param game - The current immutable shared-bag party game.
|
|
72
|
+
* @returns Whether the player whose turn it is is the only one still in: everybody else has resigned.
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { lastStanding, startParty } from "@johnmorrisdotca/kumimoji";
|
|
76
|
+
*
|
|
77
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
78
|
+
* const bag = "catdogsun";
|
|
79
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
80
|
+
* console.log(lastStanding(game));
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
28
83
|
export function lastStanding(game) {
|
|
29
84
|
return !isOver(game) && game.lastTurns === null && stillIn(game).length === 1;
|
|
30
85
|
}
|
|
@@ -35,6 +90,21 @@ export function lastStanding(game) {
|
|
|
35
90
|
* spell no word, has laid nothing on (or lifted nothing from) their table this
|
|
36
91
|
* turn, and has not traded — unless the bag cannot give three, when there is
|
|
37
92
|
* nothing to trade for. `handSpells` answers for a hand (`handCanSpell`).
|
|
93
|
+
*
|
|
94
|
+
* @param game - The current immutable shared-bag party game.
|
|
95
|
+
* @param handSpells - Whether a hand can form any accepted word.
|
|
96
|
+
* @returns A HAND THAT SPELLS NOTHING MUST BE TRADED. John, 2026-09-28: "If no words can be formed which is possible, they must dump a tile to get 3 more. Easy rule." So Done waits while the player whose turn it is holds tiles that spell no word, has laid nothing on (or lifted nothing from) their table this turn, and has not traded — unless the bag cannot give three, when there is nothing to trade for. `handSpells` answers for a hand (`handCanSpell`).
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
100
|
+
* import { handCanSpell, mustTradeFirst, startParty } from "@johnmorrisdotca/kumimoji";
|
|
101
|
+
*
|
|
102
|
+
* const words = await loadTileWordsFromModule("english");
|
|
103
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
104
|
+
* const bag = "catdogsun";
|
|
105
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
106
|
+
* console.log(mustTradeFirst(game,hand=>handCanSpell(hand,words)));
|
|
107
|
+
* ```
|
|
38
108
|
*/
|
|
39
109
|
export function mustTradeFirst(game, handSpells) {
|
|
40
110
|
if (isOver(game) || game.traded)
|
|
@@ -44,7 +114,20 @@ export function mustTradeFirst(game, handSpells) {
|
|
|
44
114
|
return false;
|
|
45
115
|
return !handSpells(play.hand);
|
|
46
116
|
}
|
|
47
|
-
/** Whether a hand can spell a word from the list: any word of two tiles or more, a wild counting as able to be anything.
|
|
117
|
+
/** Whether a hand can spell a word from the list: any word of two tiles or more, a wild counting as able to be anything.
|
|
118
|
+
*
|
|
119
|
+
* @param hand - The hand size or tile codes, as declared by the function signature.
|
|
120
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
121
|
+
* @returns Whether a hand can spell a word from the list: any word of two tiles or more, a wild counting as able to be anything.
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
125
|
+
* import { handCanSpell } from "@johnmorrisdotca/kumimoji";
|
|
126
|
+
*
|
|
127
|
+
* const words = await loadTileWordsFromModule("english");
|
|
128
|
+
* console.log(handCanSpell(["c","a","t"],words));
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
48
131
|
export function handCanSpell(hand, words) {
|
|
49
132
|
return hand.some(words.isWild) || wordsInHand(hand, words).length > 0;
|
|
50
133
|
}
|
|
@@ -52,6 +135,23 @@ export function handCanSpell(hand, words) {
|
|
|
52
135
|
* Why Done cannot be pressed now, or null when it can: a hand to trade first,
|
|
53
136
|
* or, for the last one standing, no tile laid on a sound grid yet (a hand
|
|
54
137
|
* already used on a sound grid has nothing left to lay, and wins as it is).
|
|
138
|
+
*
|
|
139
|
+
* @param game - The current immutable shared-bag party game.
|
|
140
|
+
* @param verdict - The native word and connectivity verdict for this grid.
|
|
141
|
+
* @param handSpells - Whether a hand can form any accepted word.
|
|
142
|
+
* @returns Why Done cannot be pressed now, or null when it can: a hand to trade first, or, for the last one standing, no tile laid on a sound grid yet (a hand already used on a sound grid has nothing left to lay, and wins as it is).
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
146
|
+
* import { doneRefused, handCanSpell, judgeWithWords, seatPlay, startParty } from "@johnmorrisdotca/kumimoji";
|
|
147
|
+
*
|
|
148
|
+
* const words = await loadTileWordsFromModule("english");
|
|
149
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
150
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
151
|
+
* const bag = "catdogsun";
|
|
152
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
153
|
+
* console.log(doneRefused(game,judgeWithWords(seatPlay(game).tiles,words),hand=>handCanSpell(hand,words)));
|
|
154
|
+
* ```
|
|
55
155
|
*/
|
|
56
156
|
export function doneRefused(game, verdict, handSpells) {
|
|
57
157
|
if (mustTradeFirst(game, handSpells))
|
|
@@ -75,6 +175,23 @@ function passTo(game, turn, rest) {
|
|
|
75
175
|
* The last one standing, everybody else resigned, wins by laying a tile on a
|
|
76
176
|
* sound grid and pressing Done. `verdict` is the grid of the player whose turn
|
|
77
177
|
* it is. Refused, the game given back as it was, while `doneRefused` says so.
|
|
178
|
+
*
|
|
179
|
+
* @param game - The current immutable shared-bag party game.
|
|
180
|
+
* @param verdict - The native word and connectivity verdict for this grid.
|
|
181
|
+
* @param handSpells - Whether a hand can form any accepted word.
|
|
182
|
+
* @returns DONE: the end of a turn, and the device passed on. Before anybody is out, to the next player still in. A player who goes out with it starts the last round: everybody else still in, in order from the next, has one last turn, and any of them who goes out on it shares the win (John, 2026-09-28: "Sharing the win is correct"). After the last of those, the game is over.
|
|
183
|
+
* @example
|
|
184
|
+
* ```ts
|
|
185
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
186
|
+
* import { endTurn, handCanSpell, judgeWithWords, seatPlay, startParty } from "@johnmorrisdotca/kumimoji";
|
|
187
|
+
*
|
|
188
|
+
* const words = await loadTileWordsFromModule("english");
|
|
189
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
190
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
191
|
+
* const bag = "catdogsun";
|
|
192
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
193
|
+
* console.log(endTurn(game,judgeWithWords(seatPlay(game).tiles,words),hand=>handCanSpell(hand,words)).turn);
|
|
194
|
+
* ```
|
|
78
195
|
*/
|
|
79
196
|
export function endTurn(game, verdict, handSpells) {
|
|
80
197
|
if (isOver(game) || doneRefused(game, verdict, handSpells) !== null)
|
|
@@ -108,6 +225,18 @@ function nextLastTurn(game, out, rest = {}) {
|
|
|
108
225
|
* give a trade, so nothing more can be got from it. John, 2026-09-28:
|
|
109
226
|
* "Perhaps we offer a resign button only when there are no remaining tiles
|
|
110
227
|
* they can get from the bag."
|
|
228
|
+
*
|
|
229
|
+
* @param game - The current immutable shared-bag party game.
|
|
230
|
+
* @returns Whether the player whose turn it is may resign: only once the bag cannot give a trade, so nothing more can be got from it. John, 2026-09-28: "Perhaps we offer a resign button only when there are no remaining tiles they can get from the bag."
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* import { mayResign, startParty } from "@johnmorrisdotca/kumimoji";
|
|
234
|
+
*
|
|
235
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
236
|
+
* const bag = "catdogsun";
|
|
237
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
238
|
+
* console.log(mayResign(game));
|
|
239
|
+
* ```
|
|
111
240
|
*/
|
|
112
241
|
export function mayResign(game) {
|
|
113
242
|
return !isOver(game) && partyTilesLeft(game) < KUMIMOJI_TRADE.take;
|
|
@@ -120,6 +249,18 @@ export function mayResign(game) {
|
|
|
120
249
|
* resigned too — it ends tied between everybody who resigned since a player
|
|
121
250
|
* still in last pressed Done. John: "if you resign, as the turns pass, if
|
|
122
251
|
* someone else can't go and has to resign then they are tied."
|
|
252
|
+
*
|
|
253
|
+
* @param game - The current immutable shared-bag party game.
|
|
254
|
+
* @returns RESIGN: the player whose turn it is is out of the game, their table kept for the finish, and their turn passed over from then on. In the last round it is their last turn ended without going out. Otherwise the game goes on with whoever is still in; and when nobody is — the last one standing resigned too — it ends tied between everybody who resigned since a player still in last pressed Done. John: "if you resign, as the turns pass, if someone else can't go and has to resign then they are tied."
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* import { resign, startParty } from "@johnmorrisdotca/kumimoji";
|
|
258
|
+
*
|
|
259
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
260
|
+
* const bag = "catdogsun";
|
|
261
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
262
|
+
* console.log(resign(game));
|
|
263
|
+
* ```
|
|
123
264
|
*/
|
|
124
265
|
export function resign(game) {
|
|
125
266
|
if (!mayResign(game))
|
|
@@ -137,6 +278,18 @@ export function resign(game) {
|
|
|
137
278
|
* The winners of a finished game, by place: everybody who went out; the last
|
|
138
279
|
* one standing; or, tied, the final run of resignations. Empty while it is
|
|
139
280
|
* played.
|
|
281
|
+
*
|
|
282
|
+
* @param game - The current immutable shared-bag party game.
|
|
283
|
+
* @returns The winners of a finished game, by place: everybody who went out; the last one standing; or, tied, the final run of resignations. Empty while it is played.
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* import { startParty, winnersOf } from "@johnmorrisdotca/kumimoji";
|
|
287
|
+
*
|
|
288
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
289
|
+
* const bag = "catdogsun";
|
|
290
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
291
|
+
* console.log(winnersOf(game));
|
|
292
|
+
* ```
|
|
140
293
|
*/
|
|
141
294
|
export function winnersOf(game) {
|
|
142
295
|
if (game.ending === "out")
|
|
@@ -147,7 +300,20 @@ export function winnersOf(game) {
|
|
|
147
300
|
return game.resignRun;
|
|
148
301
|
return [];
|
|
149
302
|
}
|
|
150
|
-
/** Whether the turn now being played is a player's last.
|
|
303
|
+
/** Whether the turn now being played is a player's last.
|
|
304
|
+
*
|
|
305
|
+
* @param game - The current immutable shared-bag party game.
|
|
306
|
+
* @returns Whether the turn now being played is a player's last.
|
|
307
|
+
* @example
|
|
308
|
+
* ```ts
|
|
309
|
+
* import { isLastTurn, startParty } from "@johnmorrisdotca/kumimoji";
|
|
310
|
+
*
|
|
311
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
312
|
+
* const bag = "catdogsun";
|
|
313
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
314
|
+
* console.log(isLastTurn(game));
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
151
317
|
export function isLastTurn(game) {
|
|
152
318
|
return !isOver(game) && game.lastTurns !== null;
|
|
153
319
|
}
|
package/dist/placement.d.ts
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
/** A square by its row and column.
|
|
1
|
+
/** A square by its row and column.
|
|
2
|
+
*
|
|
3
|
+
* @example
|
|
4
|
+
* ```ts
|
|
5
|
+
* import type { Square } from "@johnmorrisdotca/kumimoji";
|
|
6
|
+
*
|
|
7
|
+
* const value: Square = {row:0,col:0};
|
|
8
|
+
* console.log(value);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
2
11
|
export type Square = {
|
|
3
12
|
row: number;
|
|
4
13
|
col: number;
|
|
5
14
|
};
|
|
6
|
-
/** A word's place: its first square, and the squares it lays a new tile on, in the word's order.
|
|
15
|
+
/** A word's place: its first square, and the squares it lays a new tile on, in the word's order.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import type { CrossingFit } from "@johnmorrisdotca/kumimoji";
|
|
20
|
+
*
|
|
21
|
+
* const value: CrossingFit = {first:{row:0,col:0},fresh:[{row:0,col:1},{row:0,col:2}]};
|
|
22
|
+
* console.log(value);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
7
25
|
export type CrossingFit = {
|
|
8
26
|
first: Square;
|
|
9
27
|
fresh: Square[];
|
|
@@ -15,6 +33,21 @@ export type CrossingFit = {
|
|
|
15
33
|
* neighbour at its side, or no new tile at all — and, given `diagonalWord`
|
|
16
34
|
* (a game with Diagonals), a new tile standing in a diagonal run of three or
|
|
17
35
|
* more that `diagonalWord` does not take (`diagonalsRead`).
|
|
36
|
+
*
|
|
37
|
+
* @param letterAt - The tile at a coordinate, or an empty string for no tile.
|
|
38
|
+
* @param inside - Whether a coordinate is within the caller’s working grid.
|
|
39
|
+
* @param word - The encoded word to lay or spell.
|
|
40
|
+
* @param anchor - The existing tile that the word crosses.
|
|
41
|
+
* @param at - The word offset, seat index or date specified by this signature.
|
|
42
|
+
* @param across - Whether to lay or type horizontally rather than vertically.
|
|
43
|
+
* @param diagonalWord - Optional diagonal-word predicate; null disables diagonal checking.
|
|
44
|
+
* @returns Where `word` stands with its letter `at` on the tile at `anchor`, running across or down, or null where it cannot: a square outside what may be used, a tile at either end, a different letter in its way, a new tile with a neighbour at its side, or no new tile at all — and, given `diagonalWord` (a game with Diagonals), a new tile standing in a diagonal run of three or more that `diagonalWord` does not take (`diagonalsRead`).
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { crossingFit } from "@johnmorrisdotca/kumimoji";
|
|
48
|
+
*
|
|
49
|
+
* console.log(crossingFit((r,c)=>r===0&&c===0?"c":"",()=>true,"cat",{row:0,col:0},0,true));
|
|
50
|
+
* ```
|
|
18
51
|
*/
|
|
19
52
|
export declare function crossingFit(letterAt: (row: number, col: number) => string, inside: (row: number, col: number) => boolean, word: string, anchor: Square, at: number, across: boolean, diagonalWord?: ((run: string) => boolean) | null): CrossingFit | null;
|
|
20
53
|
/**
|
|
@@ -23,5 +56,20 @@ export declare function crossingFit(letterAt: (row: number, col: number) => stri
|
|
|
23
56
|
* its new squares. Only a run through a new tile can change, and two new
|
|
24
57
|
* tiles of one word never share a diagonal (they share a row or a column), so
|
|
25
58
|
* each is read on its own. A run of two, a corner touch, is never read.
|
|
59
|
+
*
|
|
60
|
+
* @param letterAt - The tile at a coordinate, or an empty string for no tile.
|
|
61
|
+
* @param inside - Whether a coordinate is within the caller’s working grid.
|
|
62
|
+
* @param word - The encoded word to lay or spell.
|
|
63
|
+
* @param fit - The first coordinate and fresh tile coordinates of the proposed laying.
|
|
64
|
+
* @param isWord - The predicate that accepts a readable word.
|
|
65
|
+
* @returns Whether every diagonal run a laying's new tiles would stand in is taken by `isWord`: each walked from its top end down, with the word's own letters on its new squares. Only a run through a new tile can change, and two new tiles of one word never share a diagonal (they share a row or a column), so each is read on its own. A run of two, a corner touch, is never read.
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
69
|
+
* import { diagonalsRead } from "@johnmorrisdotca/kumimoji";
|
|
70
|
+
*
|
|
71
|
+
* const words = await loadTileWordsFromModule("english");
|
|
72
|
+
* console.log(diagonalsRead(()=>"",()=>true,"cat",{first:{row:0,col:0},fresh:[{row:0,col:0},{row:0,col:1},{row:0,col:2}]},word=>words.allowed.has(word)));
|
|
73
|
+
* ```
|
|
26
74
|
*/
|
|
27
75
|
export declare function diagonalsRead(letterAt: (row: number, col: number) => string, inside: (row: number, col: number) => boolean, word: string, fit: CrossingFit, isWord: (run: string) => boolean): boolean;
|
package/dist/placement.js
CHANGED
|
@@ -28,6 +28,21 @@ import { DIAGONAL_RUN_LEAST } from "./grid.js";
|
|
|
28
28
|
* neighbour at its side, or no new tile at all — and, given `diagonalWord`
|
|
29
29
|
* (a game with Diagonals), a new tile standing in a diagonal run of three or
|
|
30
30
|
* more that `diagonalWord` does not take (`diagonalsRead`).
|
|
31
|
+
*
|
|
32
|
+
* @param letterAt - The tile at a coordinate, or an empty string for no tile.
|
|
33
|
+
* @param inside - Whether a coordinate is within the caller’s working grid.
|
|
34
|
+
* @param word - The encoded word to lay or spell.
|
|
35
|
+
* @param anchor - The existing tile that the word crosses.
|
|
36
|
+
* @param at - The word offset, seat index or date specified by this signature.
|
|
37
|
+
* @param across - Whether to lay or type horizontally rather than vertically.
|
|
38
|
+
* @param diagonalWord - Optional diagonal-word predicate; null disables diagonal checking.
|
|
39
|
+
* @returns Where `word` stands with its letter `at` on the tile at `anchor`, running across or down, or null where it cannot: a square outside what may be used, a tile at either end, a different letter in its way, a new tile with a neighbour at its side, or no new tile at all — and, given `diagonalWord` (a game with Diagonals), a new tile standing in a diagonal run of three or more that `diagonalWord` does not take (`diagonalsRead`).
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { crossingFit } from "@johnmorrisdotca/kumimoji";
|
|
43
|
+
*
|
|
44
|
+
* console.log(crossingFit((r,c)=>r===0&&c===0?"c":"",()=>true,"cat",{row:0,col:0},0,true));
|
|
45
|
+
* ```
|
|
31
46
|
*/
|
|
32
47
|
export function crossingFit(letterAt, inside, word, anchor, at, across, diagonalWord = null) {
|
|
33
48
|
const dr = across ? 0 : 1;
|
|
@@ -67,6 +82,21 @@ export function crossingFit(letterAt, inside, word, anchor, at, across, diagonal
|
|
|
67
82
|
* its new squares. Only a run through a new tile can change, and two new
|
|
68
83
|
* tiles of one word never share a diagonal (they share a row or a column), so
|
|
69
84
|
* each is read on its own. A run of two, a corner touch, is never read.
|
|
85
|
+
*
|
|
86
|
+
* @param letterAt - The tile at a coordinate, or an empty string for no tile.
|
|
87
|
+
* @param inside - Whether a coordinate is within the caller’s working grid.
|
|
88
|
+
* @param word - The encoded word to lay or spell.
|
|
89
|
+
* @param fit - The first coordinate and fresh tile coordinates of the proposed laying.
|
|
90
|
+
* @param isWord - The predicate that accepts a readable word.
|
|
91
|
+
* @returns Whether every diagonal run a laying's new tiles would stand in is taken by `isWord`: each walked from its top end down, with the word's own letters on its new squares. Only a run through a new tile can change, and two new tiles of one word never share a diagonal (they share a row or a column), so each is read on its own. A run of two, a corner touch, is never read.
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
95
|
+
* import { diagonalsRead } from "@johnmorrisdotca/kumimoji";
|
|
96
|
+
*
|
|
97
|
+
* const words = await loadTileWordsFromModule("english");
|
|
98
|
+
* console.log(diagonalsRead(()=>"",()=>true,"cat",{first:{row:0,col:0},fresh:[{row:0,col:0},{row:0,col:1},{row:0,col:2}]},word=>words.allowed.has(word)));
|
|
99
|
+
* ```
|
|
70
100
|
*/
|
|
71
101
|
export function diagonalsRead(letterAt, inside, word, fit, isWord) {
|
|
72
102
|
const freshAt = new Map(fit.fresh.map((square) => [`${square.row},${square.col}`, word[(square.row - fit.first.row) + (square.col - fit.first.col)]]));
|