@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/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,37 @@ All notable changes to this project are written down here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.3.1] - 2026-10-31
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Biome replaces ESLint as the formatter and linter, with the family's shared settings in `scripts/biome-family.json`; `pnpm lint` checks formatting too, and `pnpm format` applies it. The code is formatted once to 120 columns. Nothing a user of the package sees has changed.
|
|
14
|
+
- TypeScript targets ES2022, treats an indexed read as possibly missing, and refuses switch fallthrough and unmarked overrides.
|
|
15
|
+
- `pnpm check` also holds every source file to at most 500 lines of code (`scripts/check-size.mjs`; blank lines, comments, tests and data files are not counted).
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- The issue chooser's security link shows again: an unquoted colon had made `.github/ISSUE_TEMPLATE/config.yml` invalid YAML.
|
|
20
|
+
|
|
21
|
+
## [1.3.0] - 2026-10-14
|
|
22
|
+
|
|
23
|
+
The table is a custom element with the family's standard embed attributes and a shared builder, and the package has an English and Japanese documentation site with a checked example for every export. The rules, generation, seeds and saved games are unchanged.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Add the bilingual documentation site, checked public examples, paired guides, local search and machine-readable pages.
|
|
28
|
+
- Add the shared crossword-table builder and validated iframe route with reflected settings and display options. Preserve native saved/table access and gameplay methods; presentation updates now retain play.
|
|
29
|
+
- Add native ready/set, optional initial saved state, control visibility and localized load failures, forwarded by the React wrapper. Preserve event shapes with composed JSON-safe snapshots and add load/error events.
|
|
30
|
+
- Share a package-independent embed builder for option controls, preview adapters, code tabs and shareable links.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Synchronize documentation tooling for repository layouts, generated type references, Node entry points and repository-specific README links.
|
|
35
|
+
- Keep large documentation resource catalogues on the entry index and the active resource beside core navigation, preserving every reference page; render valid default imports in HTML and Markdown.
|
|
36
|
+
- The props table of `KumimojiBoard` moved from the README to `docs/react.md`, so that the README, which now lists the sports packages too, stays under npm's 65,536 characters; the README keeps a summary and a link.
|
|
37
|
+
- Group the package family by kind, alphabetize each group, and include the geography packages and REST in Pieces in the shared footer and README.
|
|
38
|
+
- Update the shared family description for addresses in all seven supported countries, including France and Germany.
|
|
39
|
+
|
|
9
40
|
## [1.2.2] - 2026-10-06
|
|
10
41
|
|
|
11
42
|
Nothing that was exported has changed.
|
|
@@ -157,7 +188,8 @@ The first release.
|
|
|
157
188
|
`@johnmorrisdotca/kumimoji/react`.
|
|
158
189
|
- A static demo for GitHub Pages.
|
|
159
190
|
|
|
160
|
-
[Unreleased]: https://github.com/johnmorrisdotca/kumimoji/compare/v1.
|
|
191
|
+
[Unreleased]: https://github.com/johnmorrisdotca/kumimoji/compare/v1.3.0...HEAD
|
|
192
|
+
[1.3.0]: https://github.com/johnmorrisdotca/kumimoji/compare/v1.2.2...v1.3.0
|
|
161
193
|
[1.2.1]: https://github.com/johnmorrisdotca/kumimoji/compare/v1.2.0...v1.2.1
|
|
162
194
|
[1.1.1]: https://github.com/johnmorrisdotca/kumimoji/compare/v1.1.0...v1.1.1
|
|
163
195
|
[1.1.0]: https://github.com/johnmorrisdotca/kumimoji/releases/tag/v1.1.0
|
package/CONTRIBUTING.md
CHANGED
|
@@ -21,7 +21,8 @@ shape before you spend time on it. Taking part follows the
|
|
|
21
21
|
|
|
22
22
|
```sh
|
|
23
23
|
pnpm install
|
|
24
|
-
pnpm check # lint, types and tests: the same as CI
|
|
24
|
+
pnpm check # format, lint, types, file sizes and tests: the same as CI
|
|
25
|
+
pnpm format # format the code and apply the safe lint fixes
|
|
25
26
|
pnpm test:package # pack it as npm does, install it in an empty project, import every entry
|
|
26
27
|
pnpm site # build the demo into ./site, as GitHub Pages publishes it
|
|
27
28
|
```
|
|
@@ -31,12 +32,18 @@ data scripts) are listed under its own heading below.
|
|
|
31
32
|
|
|
32
33
|
## House rules, shared by every package of the family
|
|
33
34
|
|
|
35
|
+
How the code is written, formatted and checked, and why, is in
|
|
36
|
+
[CODE-STYLE.md](CODE-STYLE.md), the same text in every package.
|
|
37
|
+
|
|
34
38
|
- **No runtime dependencies.** Development dependencies are for tests, builds and
|
|
35
39
|
documentation only.
|
|
36
40
|
- **The core is pure.** Every function in it returns new values and never
|
|
37
41
|
changes what it was given.
|
|
38
42
|
- **Test what you change.** Tests sit beside the code they test. A rule you
|
|
39
43
|
change has a test that would have caught it.
|
|
44
|
+
- **At most 500 lines of code a file** under `src/`, not counting blank lines,
|
|
45
|
+
comments, tests or `*.data.ts` data. A file that reaches it is split by what
|
|
46
|
+
it does, never squeezed.
|
|
40
47
|
- **Words a person reads come in English and Japanese.** If you cannot write the
|
|
41
48
|
Japanese, say so in the pull request and someone will.
|
|
42
49
|
- **Option values and names are kebab case.**
|
|
@@ -48,7 +55,9 @@ data scripts) are listed under its own heading below.
|
|
|
48
55
|
together with the code.
|
|
49
56
|
- **The family's own files are the same in every package**: `demo/family.css`,
|
|
50
57
|
`scripts/family-template.mjs`, `scripts/family-readme.mjs`,
|
|
51
|
-
`scripts/release-notes.mjs`, the files in `scripts/community
|
|
58
|
+
`scripts/release-notes.mjs`, the files in `scripts/community/`,
|
|
59
|
+
`CODE-STYLE.md`, `scripts/biome-family.json`, `scripts/check-size.mjs`,
|
|
60
|
+
`src/embed-attributes.ts` where the package has an element, and
|
|
52
61
|
`family.test.js` (in `src/`, or in `test/`). Do not edit one here. To change
|
|
53
62
|
one, change it in every repository at once, bump `FAMILY_TEMPLATE_VERSION` for
|
|
54
63
|
the template, and record the new hash in `family.test.js`. What is the
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<h1 align="center">Kumimoji <sub>組み文字</sub
|
|
1
|
+
<h1 align="center">Kumimoji <sub>組み文字</sub> — Crossword tile game in English and Japanese</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center"><strong>The crossword tile race: a word game where you build one crossword from a bag of letter tiles.</strong><br>
|
|
4
4
|
In English and in Japanese kana. The rules as pure, seeded TypeScript, two word lists, a computer player, and a table to play on in React, Vue, Svelte, Angular or plain HTML.</p>
|
|
@@ -10,9 +10,11 @@ In English and in Japanese kana. The rules as pure, seeded TypeScript, two word
|
|
|
10
10
|
<a href="./NOTICE.md"><img alt="Japanese word list: CC BY-SA 4.0" src="https://img.shields.io/badge/Japanese%20words-CC%20BY--SA%204.0-b5452c"></a>
|
|
11
11
|
<img alt="No dependencies" src="https://img.shields.io/badge/dependencies-0-2f5d4a">
|
|
12
12
|
<img alt="TypeScript" src="https://img.shields.io/badge/types-TypeScript-3178c6">
|
|
13
|
+
<a href="https://johnmorrisdotca.github.io/kumimoji/docs/api/main/index.html"><img alt="679.1 kB minified and gzipped" src="https://img.shields.io/badge/min%2Bgzip-679.1%20kB-2f5d4a"></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@johnmorrisdotca/kumimoji#provenance"><img alt="Published with npm provenance" src="https://img.shields.io/badge/npm-provenance-2f5d4a"></a>
|
|
13
15
|
</p>
|
|
14
16
|
|
|
15
|
-
<p align="center"><a href="https://johnmorrisdotca.github.io/kumimoji/"><strong>Play a game →</strong></a> · <a href="https://johnmorrisdotca.github.io/kumimoji/api.html">API reference</a> · <a href="docs/API.md">The API in full</a></p>
|
|
17
|
+
<p align="center"><a href="https://johnmorrisdotca.github.io/kumimoji/"><strong>Play a game →</strong></a> · <a href="https://johnmorrisdotca.github.io/kumimoji/docs/">Documentation</a> · <a href="https://johnmorrisdotca.github.io/kumimoji/docs/guides/getting-started.html">Getting started</a> · <a href="https://johnmorrisdotca.github.io/kumimoji/api.html">API reference</a> · <a href="docs/API.md">The API in full</a></p>
|
|
16
18
|
|
|
17
19
|
<table align="center">
|
|
18
20
|
<tr>
|
|
@@ -184,6 +186,19 @@ Each picture is the table the package draws, taken from [the demo](https://johnm
|
|
|
184
186
|
|
|
185
187
|
## Use it in your project
|
|
186
188
|
|
|
189
|
+
### Install under another name
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
npm install word-game@npm:@johnmorrisdotca/kumimoji
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```ts no-check
|
|
196
|
+
import "word-game/words";
|
|
197
|
+
import { loadTileWords, generateKumimoji } from "word-game";
|
|
198
|
+
await loadTileWords("english");
|
|
199
|
+
console.log(generateKumimoji(7,"easy",42).seed);
|
|
200
|
+
```
|
|
201
|
+
|
|
187
202
|
### Install
|
|
188
203
|
|
|
189
204
|
```sh
|
|
@@ -384,6 +399,12 @@ fetches when a game is first dealt.
|
|
|
384
399
|
|
|
385
400
|
The cookbook, with the output of each example, is under [Examples](#examples).
|
|
386
401
|
|
|
402
|
+
### Embed builder and reflected settings
|
|
403
|
+
|
|
404
|
+
[Build a crossword-table embed](https://johnmorrisdotca.github.io/kumimoji/builder.html), preview English letters or Japanese kana and copy element, iframe, module, React 19, Vue, Svelte, Angular, HTML or URL code. It saves no play automatically. The builder/frame defaults `keep` off; the existing element default remains on for compatibility.
|
|
405
|
+
|
|
406
|
+
Every attribute reflects to a property. New `daily` accepts today or an explicit UTC date (the `seed="daily"` alias remains); `controls`, device/light/dark `theme`, `size` (small 320px, medium 480px, large 640px), pixel `width` and spoken `label` are available. `table`, `saved`, `newGame()` and `setGame()` remain. `options` accepts every native table choice, including initial saved state and callbacks. Readiness is available as `table.ready`; `table.set(...)` updates presentation without redealing. Load errors are visible and reported through `onError`/`kumimoji-error`. `defineTable` accepts a custom tag and is server-safe. See [the embed guide](docs/embeds.md).
|
|
407
|
+
|
|
387
408
|
## Examples
|
|
388
409
|
|
|
389
410
|
Every TypeScript and JavaScript block that can run is type-checked against the built package and run by `pnpm test:readme`, so the output after `// →` is what the code prints. The word lists are read from the package's files in Node, so nothing here uses a network.
|
|
@@ -747,7 +768,7 @@ The JSON, as `kumimojiToJSON` writes it:
|
|
|
747
768
|
{
|
|
748
769
|
"format": 1,
|
|
749
770
|
"game": "kumimoji",
|
|
750
|
-
"generator": "kumimoji 1.
|
|
771
|
+
"generator": "kumimoji 1.3.1",
|
|
751
772
|
"size": 3,
|
|
752
773
|
"level": "hard",
|
|
753
774
|
"seed": 44,
|
|
@@ -843,7 +864,7 @@ turn tiles into words: `glyphOf`, `soundOf`, `wordOf`, `wildFor`, `isWild`,
|
|
|
843
864
|
|
|
844
865
|
## API
|
|
845
866
|
|
|
846
|
-
The [
|
|
867
|
+
The [documentation](https://johnmorrisdotca.github.io/kumimoji/docs/) includes bilingual guides, local search, signatures, parameters, return values and checked examples, built from source by `pnpm docs:site`. The [API index](https://johnmorrisdotca.github.io/kumimoji/api.html) preserves export anchors.
|
|
847
868
|
|
|
848
869
|
Every function, type and constant has a doc comment, so an editor shows this
|
|
849
870
|
as you type. The entries:
|
|
@@ -885,7 +906,7 @@ The types are `TilePlay`, `Tiles`, `GridVerdict`, `GridRules`, `Run`,
|
|
|
885
906
|
|
|
886
907
|
### The table
|
|
887
908
|
|
|
888
|
-
`mountKumimoji(element, options?)` from `@johnmorrisdotca/kumimoji/ui` deals and plays a whole game alone in the element and returns a handle (`play()`, `saved()`, `newGame(options?)`, `setGame(saved)`, `setLocale(locale, strings?)`, `destroy()`). Its options are `language`, `hand`, `level`, `gameLength`, `diagonals`, `seed`, `onFinish`, `onChange`, `locale`, `strings`, `theme` and `
|
|
909
|
+
`mountKumimoji(element, options?)` from `@johnmorrisdotca/kumimoji/ui` deals and plays a whole game alone in the element and returns a handle (`play()`, `saved()`, `newGame(options?)`, `setGame(saved)`, `setLocale(locale, strings?)`, `ready`, `set(options)`, `destroy()`). Its options are `language`, `hand`, `level`, `gameLength`, `diagonals`, `seed`, `onFinish`, `onChange`, `locale`, `strings`, `theme`, `keep`, `controls`, `saved` and `onError`; each, with its default, is in [docs/API.md](docs/API.md#the-table).
|
|
889
910
|
|
|
890
911
|
### The element
|
|
891
912
|
|
|
@@ -914,19 +935,7 @@ export function Board() {
|
|
|
914
935
|
}
|
|
915
936
|
```
|
|
916
937
|
|
|
917
|
-
|
|
918
|
-
| --- | --- |
|
|
919
|
-
| `tiles` | The tiles on the table: `play.tiles` |
|
|
920
|
-
| `verdict` | From `judgeWithWords`: rings the runs that are not words and fades the tiles apart |
|
|
921
|
-
| `glyphOf` | What to print on a tile: `words.glyphOf` for the language played |
|
|
922
|
-
| `onSquare` | Called with a square's key when it is pressed, empty or not |
|
|
923
|
-
| `held` | A square to ring, such as the one holding a tile picked up |
|
|
924
|
-
| `square` | The side of a square in pixels; 36 by default |
|
|
925
|
-
| anything else | Passed to the `<div>` |
|
|
926
|
-
|
|
927
|
-
`KumimojiTable` takes every option of `mountKumimoji` as a prop, and anything
|
|
928
|
-
else for its `<div>`. Options are read when it mounts; give it a new `key` to
|
|
929
|
-
start over with different ones.
|
|
938
|
+
The props of `KumimojiBoard` (`tiles`, `verdict`, `glyphOf`, `onSquare`, `held`, `square`, and anything else for its `<div>`) and of `KumimojiTable` are in [docs/react.md](docs/react.md).
|
|
930
939
|
|
|
931
940
|
## Theming
|
|
932
941
|
|
|
@@ -1104,35 +1113,67 @@ issue and we will add you.
|
|
|
1104
1113
|
### The family
|
|
1105
1114
|
|
|
1106
1115
|
<!-- family:start (made by scripts/family-readme.mjs from scripts/family-template.mjs; change those, not this) -->
|
|
1107
|
-
Kumimoji is one of
|
|
1108
|
-
[github.com/johnmorrisdotca](https://github.com/johnmorrisdotca). The code of every one is MIT.
|
|
1116
|
+
Kumimoji is one of thirty-two packages, each made for the same site, each at
|
|
1117
|
+
[github.com/johnmorrisdotca](https://github.com/johnmorrisdotca) or [github.com/spxis](https://github.com/spxis). The code of every one is MIT.
|
|
1109
1118
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
- [
|
|
1113
|
-
- [
|
|
1114
|
-
- [Tane](https://github.com/johnmorrisdotca/tane) (種): seeded random numbers and daily seeds, the same in every browser and on every server. [Demo](https://johnmorrisdotca.github.io/tane/).
|
|
1119
|
+
**Games — board**
|
|
1120
|
+
|
|
1121
|
+
- [Domino](https://github.com/johnmorrisdotca/domino) (ドミノ): dominoes and Mexican Train. [Demo](https://johnmorrisdotca.github.io/domino/).
|
|
1122
|
+
- [Gunjin](https://github.com/johnmorrisdotca/gunjin) (軍人): five hidden-rank strategy games with pass-the-device play. [Demo](https://johnmorrisdotca.github.io/gunjin/).
|
|
1115
1123
|
- [Narabe](https://github.com/johnmorrisdotca/narabe) (並べ): one rules engine for abstract board games, from gomoku and Reversi to Go and checkers. [Demo](https://johnmorrisdotca.github.io/narabe/).
|
|
1124
|
+
- [Sugoroku](https://github.com/johnmorrisdotca/sugoroku) (双六): backgammon and its variants, with the doubling cube and match play. [Demo](https://johnmorrisdotca.github.io/sugoroku/).
|
|
1116
1125
|
- [Tenka](https://github.com/johnmorrisdotca/tenka) (天下): world conquest for two to six, on a map of the real world. [Demo](https://johnmorrisdotca.github.io/tenka/).
|
|
1117
|
-
|
|
1118
|
-
|
|
1126
|
+
|
|
1127
|
+
**Games — cards & tiles**
|
|
1128
|
+
|
|
1129
|
+
- [Hitotsu](https://github.com/johnmorrisdotca/hitotsu) (一つ): a colour-card shedding game for two to eight, with the house rules people play. [Demo](https://johnmorrisdotca.github.io/hitotsu/).
|
|
1119
1130
|
- [Jarajara](https://github.com/johnmorrisdotca/jarajara) (ジャラジャラ): mahjong tiles drawn as SVG, stacked layouts, and the matching solitaire Awase. [Demo](https://johnmorrisdotca.github.io/jarajara/).
|
|
1120
|
-
- [
|
|
1121
|
-
- [
|
|
1122
|
-
|
|
1123
|
-
|
|
1131
|
+
- [Kumimoji](https://github.com/johnmorrisdotca/kumimoji) (組み文字): a crossword tile race, in English and Japanese kana. [Demo](https://johnmorrisdotca.github.io/kumimoji/).
|
|
1132
|
+
- [Toranpu](https://github.com/johnmorrisdotca/toranpu) (トランプ): a deck of playing cards, card games with computer players, and solitaires. [Demo](https://johnmorrisdotca.github.io/toranpu/).
|
|
1133
|
+
|
|
1134
|
+
**Games — puzzles**
|
|
1135
|
+
|
|
1136
|
+
- [Houseki](https://github.com/johnmorrisdotca/houseki) (宝石): gem and stone matching puzzles: falling triplets, stone collapse, colour chains and gem swap. [Demo](https://johnmorrisdotca.github.io/houseki/).
|
|
1137
|
+
- [Jirai](https://github.com/johnmorrisdotca/jirai) (地雷): minesweeper on shaped grids with verified no-guess boards. [Demo](https://johnmorrisdotca.github.io/jirai/).
|
|
1138
|
+
- [Karakuri](https://github.com/johnmorrisdotca/karakuri) (からくり): eight hyper-casual puzzle games, some of them physics: draw a shield, pull pins, cut ropes, slide blocks, pour tubes. [Demo](https://johnmorrisdotca.github.io/karakuri/).
|
|
1124
1139
|
- [Kazu](https://github.com/johnmorrisdotca/kazu) (数): grid number puzzles: Sudoku and its variants, Futoshiki and Skyscrapers. [Demo](https://johnmorrisdotca.github.io/kazu/).
|
|
1140
|
+
- [Kyuubu](https://github.com/johnmorrisdotca/kyuubu) (キューブ): a turning cube for the browser, 2×2 to 7×7, with record solves to replay. [Demo](https://johnmorrisdotca.github.io/kyuubu/).
|
|
1125
1141
|
- [Meikyuu](https://github.com/johnmorrisdotca/meikyuu) (迷宮): mazes on squares, hexagons, triangles and circles, made from a seed and drawn through with a finger or the mouse. [Demo](https://johnmorrisdotca.github.io/meikyuu/).
|
|
1142
|
+
- [Suido](https://github.com/johnmorrisdotca/suido) (水道): a pipe puzzle: turn the pieces until the water reaches every drain. [Demo](https://johnmorrisdotca.github.io/suido/).
|
|
1143
|
+
- [Tobiishi](https://github.com/johnmorrisdotca/tobiishi) (飛び石): peg solitaire with nine boards and seeded solvable challenges. [Demo](https://johnmorrisdotca.github.io/tobiishi/).
|
|
1144
|
+
- [Tsunagi](https://github.com/johnmorrisdotca/tsunagi) (繋ぎ): a line-joining logic puzzle whose every level has exactly one answer. [Demo](https://johnmorrisdotca.github.io/tsunagi/).
|
|
1145
|
+
|
|
1146
|
+
**Games — dice & random**
|
|
1147
|
+
|
|
1148
|
+
- [Korokoro](https://github.com/johnmorrisdotca/korokoro) (コロコロ): dice, with notation, exact odds, real sounds and the dice of many games. [Demo](https://johnmorrisdotca.github.io/korokoro/).
|
|
1149
|
+
- [Tane](https://github.com/johnmorrisdotca/tane) (種): seeded random numbers and daily seeds, the same in every browser and on every server. [Demo](https://johnmorrisdotca.github.io/tane/).
|
|
1150
|
+
|
|
1151
|
+
**Language**
|
|
1152
|
+
|
|
1153
|
+
- [Bushu](https://github.com/johnmorrisdotca/bushu) (部首): find a kanji by the parts it is made of. [Demo](https://johnmorrisdotca.github.io/bushu/).
|
|
1126
1154
|
- [Hikidashi](https://github.com/johnmorrisdotca/hikidashi) (引き出し): a drawer of small Japanese text tools: era dates, kanji numerals, readings and sentence difficulty. [Demo](https://johnmorrisdotca.github.io/hikidashi/).
|
|
1155
|
+
- [Kotoba](https://github.com/johnmorrisdotca/kotoba) (言葉): word lists and word-game rules in English, French, German and Japanese. [Demo](https://johnmorrisdotca.github.io/kotoba/).
|
|
1156
|
+
|
|
1157
|
+
**Geography & data**
|
|
1158
|
+
|
|
1159
|
+
- [address-plus](https://github.com/johnmorrisdotca/address-plus) (アドレスプラス): parse and format addresses in the United States, Canada, Japan, Australia, France, Germany and the United Kingdom. [Demo](https://johnmorrisdotca.github.io/address-plus/).
|
|
1127
1160
|
- [Chizu](https://github.com/johnmorrisdotca/chizu) (地図): maps of the world and of countries' regions, in English and Japanese, with a quiz and callouts. [Demo](https://johnmorrisdotca.github.io/chizu/).
|
|
1128
|
-
- [
|
|
1129
|
-
- [
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
- [
|
|
1161
|
+
- [Hata](https://github.com/johnmorrisdotca/hata) (旗): country and regional flags as SVG, at their true proportions and keyed by ISO code. [Demo](https://johnmorrisdotca.github.io/hata/).
|
|
1162
|
+
- [Kuni](https://github.com/johnmorrisdotca/kuni) (国): countries and their regions, with ISO codes and names in English and Japanese. [Demo](https://johnmorrisdotca.github.io/kuni/).
|
|
1163
|
+
|
|
1164
|
+
**Sports**
|
|
1165
|
+
|
|
1166
|
+
- [Dougu Sports](https://github.com/johnmorrisdotca/dougu-sports) (道具): sports emblems as SVG: trophies, medals, crests, and the ball and gear of every sport, with optional 3D turning. [Demo](https://johnmorrisdotca.github.io/dougu-sports/).
|
|
1167
|
+
- [Kyogijo Stadiums](https://github.com/johnmorrisdotca/kyogijo-stadiums) (競技場): sports fields, rinks, courts and ballparks drawn to scale as SVG, with each team and the score on them. [Demo](https://johnmorrisdotca.github.io/kyogijo-stadiums/).
|
|
1168
|
+
- [Senshu Jerseys](https://github.com/johnmorrisdotca/senshu-jerseys) (選手): sports jerseys, sweaters, kits, caps, helmets and retired-number banners as SVG, front and back, with optional 2.5D turning. [Demo](https://johnmorrisdotca.github.io/senshu-jerseys/).
|
|
1169
|
+
- [Taisen Brackets](https://github.com/johnmorrisdotca/taisen-brackets) (対戦): a sport-agnostic tournament bracket, drawn as SVG, from a list of ties. [Demo](https://johnmorrisdotca.github.io/taisen-brackets/).
|
|
1170
|
+
|
|
1171
|
+
**Developer tools**
|
|
1172
|
+
|
|
1173
|
+
- [REST in Pieces](https://github.com/spxis/rest-in-pieces) (レスト・イン・ピーシーズ): seeded test data and REST APIs for frontend development, with latency and error drills. [Demo](https://spxis.github.io/rest-in-pieces/).
|
|
1174
|
+
|
|
1134
1175
|
|
|
1135
|
-
**This package is Kumimoji.** The demos of all
|
|
1176
|
+
**This package is Kumimoji.** The demos of all thirty-two share one header and footer, so each links the rest.
|
|
1136
1177
|
<!-- family:end -->
|
|
1137
1178
|
|
|
1138
1179
|
## Development
|
|
@@ -1160,7 +1201,7 @@ Please follow the [code of conduct](./CODE_OF_CONDUCT.md). A way to make a check
|
|
|
1160
1201
|
|
|
1161
1202
|
See [CHANGELOG.md](./CHANGELOG.md).
|
|
1162
1203
|
|
|
1163
|
-
The latest release
|
|
1204
|
+
The latest release, 1.3.1, changes nothing a player sees.
|
|
1164
1205
|
|
|
1165
1206
|
## Licence
|
|
1166
1207
|
|
package/dist/check.d.ts
CHANGED
|
@@ -11,9 +11,34 @@ import type { KumimojiCheck, KumimojiLevel, KumimojiOptions } from "./kumimoji.t
|
|
|
11
11
|
* Written out here rather than asked of the play page, which is what made the
|
|
12
12
|
* grid; the list must have been loaded (`loadTileWords`), and a check that
|
|
13
13
|
* cannot read it refuses.
|
|
14
|
+
*
|
|
15
|
+
* @param size - The supported initial hand size.
|
|
16
|
+
* @param givens - The original bag of internal tile codes.
|
|
17
|
+
* @param answer - The encoded completed grid to verify.
|
|
18
|
+
* @param options - Native game, component or presentation options.
|
|
19
|
+
* @returns WHETHER A GRID FINISHES A KUMIMOJI: the one check the server also runs. O(squares) and a lookup a word, nothing searched: the grid uses exactly the tiles of the bag, as many of each, it is all one piece, and every run of two or more across or down is in the list — and, for a game set up with Diagonals, every run of three or more along a diagonal. Which tiles were traded on the way does not matter — a finished game holds the whole bag whatever came out of it when — so the answer is the grid alone.
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { checkKumimoji } from "@johnmorrisdotca/kumimoji";
|
|
23
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
24
|
+
*
|
|
25
|
+
* await loadTileWordsFromModule("english");
|
|
26
|
+
* console.log(checkKumimoji(3,"cat","cat",{level:"hard"}));
|
|
27
|
+
* ```
|
|
14
28
|
*/
|
|
15
29
|
export declare function checkKumimoji(size: number, givens: string, answer: string, options?: KumimojiOptions & {
|
|
16
30
|
level?: KumimojiLevel;
|
|
17
31
|
}): KumimojiCheck;
|
|
18
|
-
/** A finished game's leaderboard points (`KUMIMOJI_SCORE`): ten a tile, and up to as much again for speed.
|
|
32
|
+
/** A finished game's leaderboard points (`KUMIMOJI_SCORE`): ten a tile, and up to as much again for speed.
|
|
33
|
+
*
|
|
34
|
+
* @param givens - The original bag of internal tile codes.
|
|
35
|
+
* @param elapsedMs - The elapsed solve time in milliseconds.
|
|
36
|
+
* @returns A finished game's leaderboard points (`KUMIMOJI_SCORE`): ten a tile, and up to as much again for speed.
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { kumimojiPoints } from "@johnmorrisdotca/kumimoji";
|
|
40
|
+
*
|
|
41
|
+
* console.log(kumimojiPoints("cat",12000));
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
19
44
|
export declare function kumimojiPoints(givens: string, elapsedMs: number): number;
|
package/dist/check.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decodeGrid, lettersOf, sameLetters } from "./grid.js";
|
|
2
2
|
import { judgeWithWords } from "./judge.js";
|
|
3
|
-
import { kumimojiTileCount, kumimojiWildCount,
|
|
3
|
+
import { KUMIMOJI_SCORE, kumimojiTileCount, kumimojiWildCount, TILE_MIX_TOTAL } from "./tiles.constants.js";
|
|
4
4
|
import { tileWords } from "./tileWords.js";
|
|
5
5
|
/**
|
|
6
6
|
* WHETHER A GRID FINISHES A KUMIMOJI: the one check the server also runs.
|
|
@@ -14,6 +14,20 @@ import { tileWords } from "./tileWords.js";
|
|
|
14
14
|
* Written out here rather than asked of the play page, which is what made the
|
|
15
15
|
* grid; the list must have been loaded (`loadTileWords`), and a check that
|
|
16
16
|
* cannot read it refuses.
|
|
17
|
+
*
|
|
18
|
+
* @param size - The supported initial hand size.
|
|
19
|
+
* @param givens - The original bag of internal tile codes.
|
|
20
|
+
* @param answer - The encoded completed grid to verify.
|
|
21
|
+
* @param options - Native game, component or presentation options.
|
|
22
|
+
* @returns WHETHER A GRID FINISHES A KUMIMOJI: the one check the server also runs. O(squares) and a lookup a word, nothing searched: the grid uses exactly the tiles of the bag, as many of each, it is all one piece, and every run of two or more across or down is in the list — and, for a game set up with Diagonals, every run of three or more along a diagonal. Which tiles were traded on the way does not matter — a finished game holds the whole bag whatever came out of it when — so the answer is the grid alone.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { checkKumimoji } from "@johnmorrisdotca/kumimoji";
|
|
26
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
27
|
+
*
|
|
28
|
+
* await loadTileWordsFromModule("english");
|
|
29
|
+
* console.log(checkKumimoji(3,"cat","cat",{level:"hard"}));
|
|
30
|
+
* ```
|
|
17
31
|
*/
|
|
18
32
|
export function checkKumimoji(size, givens, answer, options = {}) {
|
|
19
33
|
const gameLength = options.gameLength ?? "short";
|
|
@@ -48,7 +62,9 @@ export function checkKumimoji(size, givens, answer, options = {}) {
|
|
|
48
62
|
return { ok: false, reason: "the answer is not a grid" };
|
|
49
63
|
const bagIdentities = bag.map(words.familyKey);
|
|
50
64
|
const tileIdentities = [...tiles.values()].map(words.familyKey);
|
|
51
|
-
if (bagIdentities.some((tile) => tile === null) ||
|
|
65
|
+
if (bagIdentities.some((tile) => tile === null) ||
|
|
66
|
+
tileIdentities.some((tile) => tile === null) ||
|
|
67
|
+
!sameLetters(lettersOf(tileIdentities), lettersOf(bagIdentities))) {
|
|
52
68
|
return { ok: false, reason: "the grid does not use exactly the tiles of the bag" };
|
|
53
69
|
}
|
|
54
70
|
const verdict = judgeWithWords(tiles, words, { diagonals: options.diagonals === true });
|
|
@@ -60,7 +76,18 @@ export function checkKumimoji(size, givens, answer, options = {}) {
|
|
|
60
76
|
return { ok: false, reason: "the grid is not finished" };
|
|
61
77
|
return { ok: true };
|
|
62
78
|
}
|
|
63
|
-
/** A finished game's leaderboard points (`KUMIMOJI_SCORE`): ten a tile, and up to as much again for speed.
|
|
79
|
+
/** A finished game's leaderboard points (`KUMIMOJI_SCORE`): ten a tile, and up to as much again for speed.
|
|
80
|
+
*
|
|
81
|
+
* @param givens - The original bag of internal tile codes.
|
|
82
|
+
* @param elapsedMs - The elapsed solve time in milliseconds.
|
|
83
|
+
* @returns A finished game's leaderboard points (`KUMIMOJI_SCORE`): ten a tile, and up to as much again for speed.
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* import { kumimojiPoints } from "@johnmorrisdotca/kumimoji";
|
|
87
|
+
*
|
|
88
|
+
* console.log(kumimojiPoints("cat",12000));
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
64
91
|
export function kumimojiPoints(givens, elapsedMs) {
|
|
65
92
|
const tiles = givens.length;
|
|
66
93
|
const base = KUMIMOJI_SCORE.tile * tiles;
|
package/dist/computer.types.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { PartyGame } from "./party.types.ts";
|
|
2
|
-
/** What a computer did in one step of its turn, for the line over its table.
|
|
2
|
+
/** What a computer did in one step of its turn, for the line over its table.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import type { ComputerSaid } from "@johnmorrisdotca/kumimoji";
|
|
7
|
+
*
|
|
8
|
+
* const value: ComputerSaid = {kind:"drew"};
|
|
9
|
+
* console.log(value);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
3
12
|
export type ComputerSaid = {
|
|
4
13
|
kind: "rebuilt";
|
|
5
14
|
} | {
|
|
@@ -16,7 +25,20 @@ export type ComputerSaid = {
|
|
|
16
25
|
} | {
|
|
17
26
|
kind: "resigned";
|
|
18
27
|
};
|
|
19
|
-
/** One step of a computer's turn: the game after it, and what it did. The last step's game is the one kept.
|
|
28
|
+
/** One step of a computer's turn: the game after it, and what it did. The last step's game is the one kept.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { startParty } from "@johnmorrisdotca/kumimoji";
|
|
33
|
+
* import type { ComputerStep } from "@johnmorrisdotca/kumimoji";
|
|
34
|
+
*
|
|
35
|
+
* const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
|
|
36
|
+
* const bag = "catdogsun";
|
|
37
|
+
* const game = startParty(settings,bag,["Seat 1","Seat 2"]);
|
|
38
|
+
* const value: ComputerStep = {game,said:{kind:"drew"}};
|
|
39
|
+
* console.log(value);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
20
42
|
export type ComputerStep = {
|
|
21
43
|
game: PartyGame;
|
|
22
44
|
said: ComputerSaid;
|
package/dist/computerPlay.d.ts
CHANGED
|
@@ -1,17 +1,60 @@
|
|
|
1
1
|
import { type GridRules, type GridVerdict, type Tiles } from "./grid.ts";
|
|
2
2
|
import { type TilePlay } from "./play.ts";
|
|
3
3
|
import type { TileWords } from "./tileWords.ts";
|
|
4
|
-
/** Whether a grid is sound, read against the loaded word list by the game's rules: the same judgement the desk shows.
|
|
4
|
+
/** Whether a grid is sound, read against the loaded word list by the game's rules: the same judgement the desk shows.
|
|
5
|
+
*
|
|
6
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
7
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
8
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
9
|
+
* @returns Whether a grid is sound, read against the loaded word list by the game's rules: the same judgement the desk shows.
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
13
|
+
* import { judgeTiles } from "@johnmorrisdotca/kumimoji";
|
|
14
|
+
*
|
|
15
|
+
* const words = await loadTileWordsFromModule("english");
|
|
16
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
17
|
+
* console.log(judgeTiles(tiles,words));
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
5
20
|
export declare function judgeTiles(tiles: Tiles, words: TileWords, rules?: GridRules): GridVerdict;
|
|
6
21
|
/**
|
|
7
22
|
* THE COMPUTER'S NEXT WORD: its play after laying the best word its hand can
|
|
8
23
|
* lay on its table, and the word, or null when there is none. The grid after
|
|
9
24
|
* it is judged against the list, by the game's rules (`rules`), and is
|
|
10
25
|
* always sound.
|
|
26
|
+
*
|
|
27
|
+
* @param play - The current immutable solo-game progress.
|
|
28
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
29
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
30
|
+
* @returns THE COMPUTER'S NEXT WORD: its play after laying the best word its hand can lay on its table, and the word, or null when there is none. The grid after it is judged against the list, by the game's rules (`rules`), and is always sound.
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
34
|
+
* import { bestLaying, deal } from "@johnmorrisdotca/kumimoji";
|
|
35
|
+
*
|
|
36
|
+
* const words = await loadTileWordsFromModule("english");
|
|
37
|
+
* const play = deal("catdog",3);
|
|
38
|
+
* console.log(bestLaying(play,words)?.word);
|
|
39
|
+
* ```
|
|
11
40
|
*/
|
|
12
41
|
export declare function bestLaying(play: TilePlay, words: TileWords, rules?: GridRules): {
|
|
13
42
|
play: TilePlay;
|
|
14
43
|
word: string;
|
|
15
44
|
} | null;
|
|
16
|
-
/** The tile a computer trades: its rarest letter in the set, the first of those in its hand; never a wild. Null for a hand of wilds.
|
|
45
|
+
/** The tile a computer trades: its rarest letter in the set, the first of those in its hand; never a wild. Null for a hand of wilds.
|
|
46
|
+
*
|
|
47
|
+
* @param hand - The hand size or tile codes, as declared by the function signature.
|
|
48
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
49
|
+
* @returns The tile a computer trades: its rarest letter in the set, the first of those in its hand; never a wild. null for a hand of wilds.
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
53
|
+
* import { deal, tradeChoice } from "@johnmorrisdotca/kumimoji";
|
|
54
|
+
*
|
|
55
|
+
* const words = await loadTileWordsFromModule("english");
|
|
56
|
+
* const play = deal("catdog",3);
|
|
57
|
+
* console.log(tradeChoice(play.hand,words));
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
17
60
|
export declare function tradeChoice(hand: readonly string[], words: TileWords): number | null;
|
package/dist/computerPlay.js
CHANGED
|
@@ -28,7 +28,22 @@ function plainOf(tile, words) {
|
|
|
28
28
|
const sound = words.soundOf(tile);
|
|
29
29
|
return sound === null ? "" : (words.codeOf(sound) ?? "");
|
|
30
30
|
}
|
|
31
|
-
/** Whether a grid is sound, read against the loaded word list by the game's rules: the same judgement the desk shows.
|
|
31
|
+
/** Whether a grid is sound, read against the loaded word list by the game's rules: the same judgement the desk shows.
|
|
32
|
+
*
|
|
33
|
+
* @param tiles - The map from row,column square names to internal tile codes.
|
|
34
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
35
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
36
|
+
* @returns Whether a grid is sound, read against the loaded word list by the game's rules: the same judgement the desk shows.
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
40
|
+
* import { judgeTiles } from "@johnmorrisdotca/kumimoji";
|
|
41
|
+
*
|
|
42
|
+
* const words = await loadTileWordsFromModule("english");
|
|
43
|
+
* const tiles = new Map([["0,0","c"],["0,1","a"],["0,2","t"]]);
|
|
44
|
+
* console.log(judgeTiles(tiles,words));
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
32
47
|
export function judgeTiles(tiles, words, rules = {}) {
|
|
33
48
|
return judgeWithWords(tiles, words, rules);
|
|
34
49
|
}
|
|
@@ -61,7 +76,7 @@ function lacking(word, hand, most) {
|
|
|
61
76
|
/** How many tiles already down one word may run through: two lets it bridge a gap, as players do. */
|
|
62
77
|
const CROSSED_MOST = 2;
|
|
63
78
|
/** How many placements are tried in one search at most, so a turn's thinking stays a fraction of a second on a phone. */
|
|
64
|
-
const FITS_MOST =
|
|
79
|
+
const FITS_MOST = 20_000;
|
|
65
80
|
/** A laying's worth: tiles used first, rare letters next, wilds spent last. */
|
|
66
81
|
function worth(fresh, wilds, words) {
|
|
67
82
|
let rare = 0;
|
|
@@ -103,7 +118,8 @@ function layings(play, words, rules) {
|
|
|
103
118
|
}
|
|
104
119
|
const bounds = boundsOf(play.tiles);
|
|
105
120
|
const fits = (first, last) => bounds === null ||
|
|
106
|
-
(Math.max(bounds.bottom, last.row) - Math.min(bounds.top, first.row) < KUMIMOJI_GRID_MOST &&
|
|
121
|
+
(Math.max(bounds.bottom, last.row) - Math.min(bounds.top, first.row) < KUMIMOJI_GRID_MOST &&
|
|
122
|
+
Math.max(bounds.right, last.col) - Math.min(bounds.left, first.col) < KUMIMOJI_GRID_MOST);
|
|
107
123
|
const found = [];
|
|
108
124
|
let tried = 0;
|
|
109
125
|
let mostFresh = 0;
|
|
@@ -135,9 +151,15 @@ function layings(play, words, rules) {
|
|
|
135
151
|
if (fit === null)
|
|
136
152
|
continue;
|
|
137
153
|
const step = across ? { row: 0, col: 1 } : { row: 1, col: 0 };
|
|
138
|
-
if (!fits(fit.first, {
|
|
154
|
+
if (!fits(fit.first, {
|
|
155
|
+
row: fit.first.row + (length - 1) * step.row,
|
|
156
|
+
col: fit.first.col + (length - 1) * step.col,
|
|
157
|
+
}))
|
|
139
158
|
continue;
|
|
140
|
-
const fresh = fit.fresh.map((square) => ({
|
|
159
|
+
const fresh = fit.fresh.map((square) => ({
|
|
160
|
+
square: squareAt(square.row, square.col),
|
|
161
|
+
letter: word[square.row - fit.first.row + (square.col - fit.first.col)],
|
|
162
|
+
}));
|
|
141
163
|
const wilds = wildsNeeded(fresh, hand);
|
|
142
164
|
if (wilds !== null)
|
|
143
165
|
keep({ word, fresh, wilds, score: worth(fresh, wilds, words) });
|
|
@@ -173,6 +195,20 @@ const JUDGED_MOST = 12;
|
|
|
173
195
|
* lay on its table, and the word, or null when there is none. The grid after
|
|
174
196
|
* it is judged against the list, by the game's rules (`rules`), and is
|
|
175
197
|
* always sound.
|
|
198
|
+
*
|
|
199
|
+
* @param play - The current immutable solo-game progress.
|
|
200
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
201
|
+
* @param rules - Whether diagonal runs are also judged.
|
|
202
|
+
* @returns THE COMPUTER'S NEXT WORD: its play after laying the best word its hand can lay on its table, and the word, or null when there is none. The grid after it is judged against the list, by the game's rules (`rules`), and is always sound.
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
206
|
+
* import { bestLaying, deal } from "@johnmorrisdotca/kumimoji";
|
|
207
|
+
*
|
|
208
|
+
* const words = await loadTileWordsFromModule("english");
|
|
209
|
+
* const play = deal("catdog",3);
|
|
210
|
+
* console.log(bestLaying(play,words)?.word);
|
|
211
|
+
* ```
|
|
176
212
|
*/
|
|
177
213
|
export function bestLaying(play, words, rules = {}) {
|
|
178
214
|
if (play.hand.length === 0)
|
|
@@ -186,7 +222,21 @@ export function bestLaying(play, words, rules = {}) {
|
|
|
186
222
|
}
|
|
187
223
|
return null;
|
|
188
224
|
}
|
|
189
|
-
/** The tile a computer trades: its rarest letter in the set, the first of those in its hand; never a wild. Null for a hand of wilds.
|
|
225
|
+
/** The tile a computer trades: its rarest letter in the set, the first of those in its hand; never a wild. Null for a hand of wilds.
|
|
226
|
+
*
|
|
227
|
+
* @param hand - The hand size or tile codes, as declared by the function signature.
|
|
228
|
+
* @param words - The loaded native language word list and tile mappings.
|
|
229
|
+
* @returns The tile a computer trades: its rarest letter in the set, the first of those in its hand; never a wild. null for a hand of wilds.
|
|
230
|
+
* @example
|
|
231
|
+
* ```ts
|
|
232
|
+
* import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
|
|
233
|
+
* import { deal, tradeChoice } from "@johnmorrisdotca/kumimoji";
|
|
234
|
+
*
|
|
235
|
+
* const words = await loadTileWordsFromModule("english");
|
|
236
|
+
* const play = deal("catdog",3);
|
|
237
|
+
* console.log(tradeChoice(play.hand,words));
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
190
240
|
export function tradeChoice(hand, words) {
|
|
191
241
|
let chosen = null;
|
|
192
242
|
let fewest = Infinity;
|