@johnmorrisdotca/kumimoji 1.2.1 → 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 +37 -1
- package/CONTRIBUTING.md +81 -44
- package/README.md +478 -327
- 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 +66 -57
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,14 +10,30 @@ 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></p>
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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>
|
|
18
|
+
|
|
19
|
+
<table align="center">
|
|
20
|
+
<tr>
|
|
21
|
+
<td align="center" valign="top">
|
|
22
|
+
<picture>
|
|
23
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/hero-desk-dark.webp">
|
|
24
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/hero-desk-light.webp" alt="The demo on a desk, in English: the page's header with its language chooser and cloth swatches, the choices for tiles, hand and wild tiles, and a green table with a crossword half built from the words SYNDIC, MAUP and PA crossing, one tile left in the hand and the buttons to draw, trade, sort and lift all." width="720">
|
|
25
|
+
</picture>
|
|
26
|
+
<br><em>An English game half way, on a desk: a crossword of SYNDIC and the words that cross it.</em>
|
|
27
|
+
</td>
|
|
28
|
+
<td align="center" valign="top">
|
|
29
|
+
<picture>
|
|
30
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/hero-phone-dark.webp">
|
|
31
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/hero-phone-light.webp" alt="The demo on a phone, in Japanese kana: a green table with a crossword built from kana tiles, and a hand and buttons under it." width="220">
|
|
32
|
+
</picture>
|
|
33
|
+
<br><em>A game in kana on a phone, in the device's light or dark.</em>
|
|
34
|
+
</td>
|
|
35
|
+
</tr>
|
|
36
|
+
</table>
|
|
21
37
|
|
|
22
38
|
A word game engine for the race to build a crossword. Every player lays their
|
|
23
39
|
own tiles as words that cross, draws another when the hand is used and every
|
|
@@ -69,7 +85,7 @@ isFinished(play, judgeWithWords(play.tiles, words)); // → true
|
|
|
69
85
|
|
|
70
86
|
NOW, then SNOW, then SNOWY. And a table to play on, in a page:
|
|
71
87
|
|
|
72
|
-
```js
|
|
88
|
+
```js no-run
|
|
73
89
|
import { mountKumimoji } from "@johnmorrisdotca/kumimoji/ui";
|
|
74
90
|
|
|
75
91
|
mountKumimoji(document.getElementById("table"), { language: "english", hand: 7 });
|
|
@@ -90,8 +106,121 @@ Or with nothing to install, [play a game in the demo](https://johnmorrisdotca.gi
|
|
|
90
106
|
on the や tile, and a list of 163,461 readings.
|
|
91
107
|
- **Learners and teachers** of English or Japanese spelling.
|
|
92
108
|
|
|
109
|
+
## Features
|
|
110
|
+
|
|
111
|
+
- **Dealt from a seed.** `generateKumimoji` lays a crossword first and deals
|
|
112
|
+
its tiles, so every bag can be finished.
|
|
113
|
+
- **English and Japanese.** 144 tiles in each: the English letters, or 45 base
|
|
114
|
+
kana where が plays as か, ゃ as や and を as お. 110,316 English words and
|
|
115
|
+
163,461 Japanese readings, of 2 to 15 tiles.
|
|
116
|
+
- **Wild tiles** that take any letter or kana, and are read as that in every
|
|
117
|
+
word they are part of.
|
|
118
|
+
- **Trades.** A tile you cannot use goes back into the bag for three.
|
|
119
|
+
- **Diagonals**, if chosen: every diagonal run of three or more must be a word
|
|
120
|
+
too.
|
|
121
|
+
- **Three lengths.** A short game, half the set, or all 144 tiles; and two
|
|
122
|
+
English sets at once.
|
|
123
|
+
- **The rules as plain functions.** A game in progress is a value (`TilePlay`):
|
|
124
|
+
`deal`, `placeFromHand`, `moveOnTable`, `liftToHand`, `draw` and `trade` each
|
|
125
|
+
return a new one.
|
|
126
|
+
- **A table of two to eight** sharing one bag, with a last round, resigning,
|
|
127
|
+
joining and leaving, kept as text, and a computer player for any seat.
|
|
128
|
+
- **Help**, if chosen: the words the hand's own tiles spell.
|
|
129
|
+
- **A table to play on.** `mountKumimoji` plays a whole game alone in plain
|
|
130
|
+
DOM, saves it and loads it back; `KumimojiBoard` draws a grid in React.
|
|
131
|
+
- **A tag.** `<kumimoji-table>` is the same game in one element, with no
|
|
132
|
+
framework.
|
|
133
|
+
- **One bag a day.** `kumimojiDailySeed(new Date())` is the same seed for
|
|
134
|
+
everybody, worldwide.
|
|
135
|
+
- **Played from a keyboard.** Arrow keys between squares and tiles, Enter or
|
|
136
|
+
Space to pick up and lay; see [Accessibility](#accessibility).
|
|
137
|
+
- **The table's words in English and Japanese**, and any other language by a
|
|
138
|
+
table of your own. **Themeable**: every colour is a CSS variable.
|
|
139
|
+
|
|
140
|
+
### What's in it
|
|
141
|
+
|
|
142
|
+
Each picture is the table the package draws, taken from [the demo](https://johnmorrisdotca.github.io/kumimoji/) with `pnpm screenshots:readme`, in light and dark. The game is dealt from a seed, and the words are laid by the package's own computer player, so the same pictures come again.
|
|
143
|
+
|
|
144
|
+
<table>
|
|
145
|
+
<tr>
|
|
146
|
+
<td align="center" valign="top" width="50%">
|
|
147
|
+
<picture>
|
|
148
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/english-desk-dark.webp">
|
|
149
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/english-desk-light.webp" alt="An English board on the green table: SYNDIC across with MAUP and PA crossing it, and U hanging under the N, drawn on a grid of empty squares that has no edge." width="400">
|
|
150
|
+
</picture>
|
|
151
|
+
<br><em><strong>English.</strong> 144 tiles, 110,316 words.</em>
|
|
152
|
+
</td>
|
|
153
|
+
<td align="center" valign="top" width="50%">
|
|
154
|
+
<picture>
|
|
155
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/kana-desk-dark.webp">
|
|
156
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/kana-desk-light.webp" alt="A Japanese board of kana tiles on the green table, a crossword of hiragana laid across and down on the grid of empty squares." width="400">
|
|
157
|
+
</picture>
|
|
158
|
+
<br><em><strong>Japanese kana.</strong> 45 base kana tiles, 163,461 readings.</em>
|
|
159
|
+
</td>
|
|
160
|
+
</tr>
|
|
161
|
+
<tr>
|
|
162
|
+
<td align="center" valign="top" width="50%">
|
|
163
|
+
<picture>
|
|
164
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/not-a-word-desk-dark.webp">
|
|
165
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/not-a-word-desk-light.webp" alt="A board with two tiles side by side, N and W, each ringed in red, because the two make the run NW, which is not a word." width="400">
|
|
166
|
+
</picture>
|
|
167
|
+
<br><em><strong>A run that is not a word</strong> is ringed, and named under the table.</em>
|
|
168
|
+
</td>
|
|
169
|
+
<td align="center" valign="top" width="50%">
|
|
170
|
+
<picture>
|
|
171
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/hand-of-eleven-desk-dark.webp">
|
|
172
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/hand-of-eleven-desk-light.webp" alt="A board partly built from a hand of eleven tiles, a larger crossword than a hand of seven makes, on the same green table." width="400">
|
|
173
|
+
</picture>
|
|
174
|
+
<br><em><strong>A hand of eleven.</strong> Hands are 3, 7 or 11.</em>
|
|
175
|
+
</td>
|
|
176
|
+
</tr>
|
|
177
|
+
</table>
|
|
178
|
+
|
|
179
|
+
<p align="center">
|
|
180
|
+
<picture>
|
|
181
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/wild-tiles-desk-dark.webp">
|
|
182
|
+
<img src="https://raw.githubusercontent.com/johnmorrisdotca/kumimoji/main/docs/images/wild-tiles-desk-light.webp" alt="A hand of seven tiles, E, T, U, P, L and L in cream and one gold tile with a black star, a wild tile that is any letter or kana the player gives it." width="500">
|
|
183
|
+
</picture>
|
|
184
|
+
<br><em><strong>A wild tile</strong> is the gold star in the hand: the player gives it a letter before it is laid.</em>
|
|
185
|
+
</p>
|
|
186
|
+
|
|
93
187
|
## Use it in your project
|
|
94
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
|
+
|
|
202
|
+
### Install
|
|
203
|
+
|
|
204
|
+
```sh
|
|
205
|
+
npm install @johnmorrisdotca/kumimoji
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
pnpm add @johnmorrisdotca/kumimoji
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```sh
|
|
213
|
+
yarn add @johnmorrisdotca/kumimoji
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
A page with no bundler loads the table as a tag from a CDN, naming the major version so that a release that changes what you use is one you choose:
|
|
217
|
+
|
|
218
|
+
```html
|
|
219
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@johnmorrisdotca/kumimoji@1/dist/element-define.js"></script>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
On a server or in a script, `import "@johnmorrisdotca/kumimoji/words"` first, so that the word lists are read from the package's files.
|
|
223
|
+
|
|
95
224
|
Kumimoji is five things, each usable without the others: **the rules**, plain
|
|
96
225
|
functions over plain values; **the word lists**, loaded when first needed;
|
|
97
226
|
**a table** you mount into any element; **the same table as a tag**,
|
|
@@ -217,7 +346,7 @@ onBeforeUnmount(() => table?.destroy());
|
|
|
217
346
|
|
|
218
347
|
### 7. Angular
|
|
219
348
|
|
|
220
|
-
```
|
|
349
|
+
```ts no-check
|
|
221
350
|
import { Component, ElementRef, OnDestroy, afterNextRender, provideZonelessChangeDetection, signal, viewChild } from "@angular/core";
|
|
222
351
|
import { bootstrapApplication } from "@angular/platform-browser";
|
|
223
352
|
import { mountKumimoji, type KumimojiTableHandle } from "@johnmorrisdotca/kumimoji/ui";
|
|
@@ -268,156 +397,184 @@ fetches when a game is first dealt.
|
|
|
268
397
|
phone. The rules have no DOM in them and run in Node 22 and later, Deno,
|
|
269
398
|
Bun and web workers.
|
|
270
399
|
|
|
271
|
-
|
|
400
|
+
The cookbook, with the output of each example, is under [Examples](#examples).
|
|
272
401
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
+
|
|
408
|
+
## Examples
|
|
279
409
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
├── index.ts the main entry: the rules, the generator, the computer player and the table's pure helpers
|
|
294
|
-
├── judge.ts judging a grid against its language's word list, run by run
|
|
295
|
-
├── kana.ts Japanese tiles: the 45 base kana, and how every other kana is played as one of them
|
|
296
|
-
├── kumimoji.types.ts the game's types: how much of the set a bag holds, and the rest
|
|
297
|
-
├── party.ts pass and play: two to eight people round one device, one bag, a hand and a table each
|
|
298
|
-
├── party.types.ts what a pass-and-play game was set up as
|
|
299
|
-
├── partyKept.ts a pass-and-play game kept in the browser as one string of JSON
|
|
300
|
-
├── partySeats.ts people and computers joining and leaving a pass-and-play game between turns
|
|
301
|
-
├── partyTurns.ts how a pass-and-play turn ends, and how the game does, and who won
|
|
302
|
-
├── placement.ts where a word can cross a crossword without spoiling it
|
|
303
|
-
├── play.ts a game being played: the bag, the hand and the table, and every move on them
|
|
304
|
-
├── random.ts a seeded random, so one seed deals one game in every browser
|
|
305
|
-
├── react.tsx the "/react" entry: a grid to draw in React
|
|
306
|
-
├── showcase.ts what the rules page shows of the game, worked out from the game's own tables
|
|
307
|
-
├── strings.ts every word Kumimoji shows a person, in English and Japanese
|
|
308
|
-
├── tableView.ts how the table is looked at: which squares are shown, and how big a tile is drawn
|
|
309
|
-
├── tileFace.ts what a tile code shows, without loading a word list
|
|
310
|
-
├── tileFamily.ts which tile of the set a tile is, without loading a word list
|
|
311
|
-
├── tileWords.ts the word list, loaded once when a game opens
|
|
312
|
-
├── tileWordsModule.ts the same lists where there is no browser, imported only by a server or a test
|
|
313
|
-
├── tiles.constants.ts every number the game is played by: tile mixes, hand sizes, lengths of a game
|
|
314
|
-
├── turn.ts turning the table while every tile stays upright
|
|
315
|
-
├── ui.ts the "/ui" entry: Kumimoji played in the browser, in plain DOM
|
|
316
|
-
├── version.ts the version of this package, as package.json has it
|
|
317
|
-
├── wilds.ts a wild tile with no letter read as whatever makes the grid words
|
|
318
|
-
├── words.en.data.ts the English word list
|
|
319
|
-
├── words.ja.data.ts the Japanese word list and tile mix
|
|
320
|
-
├── words.ts the "/words" entry: the word lists, for a place with no browser, such as a server or a test
|
|
321
|
-
└── ui/ the table that draws and plays a game
|
|
322
|
-
├── board.ts how a tile on the table is drawn: sound, in a run that is not a word, or apart
|
|
323
|
-
├── mount.ts the table itself: mounting it on a page, the options it takes, and playing it from a keyboard
|
|
324
|
-
└── style.ts the table's own styles, every colour and size a CSS variable so a page can restyle it
|
|
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.
|
|
411
|
+
|
|
412
|
+
### A page with nothing else
|
|
413
|
+
|
|
414
|
+
Save this as a file and open it. The tag is the whole table: set-up, tiles, hand, clock, saving and loading.
|
|
415
|
+
|
|
416
|
+
```html
|
|
417
|
+
<!doctype html>
|
|
418
|
+
<meta charset="utf-8">
|
|
419
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
420
|
+
<title>A crossword race</title>
|
|
421
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@johnmorrisdotca/kumimoji@1/dist/element-define.js"></script>
|
|
422
|
+
<kumimoji-table language="english" hand="7" seed="daily"></kumimoji-table>
|
|
325
423
|
```
|
|
326
424
|
|
|
327
|
-
|
|
328
|
-
and checks the package as npm packs it, `demo/` is the page published on
|
|
329
|
-
GitHub Pages, and `table/` taps it in real browsers.
|
|
425
|
+
### Listen to the tag
|
|
330
426
|
|
|
331
|
-
|
|
427
|
+
The tag fires `kumimoji-change` after every change, with the game as it would be saved, and `kumimoji-finish` when the last tile is laid and every run is a word:
|
|
332
428
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
sense.
|
|
429
|
+
```html
|
|
430
|
+
<kumimoji-table id="game" language="japanese" hand="7" seed="2026"></kumimoji-table>
|
|
431
|
+
<p id="note"></p>
|
|
432
|
+
<script type="module">
|
|
433
|
+
import "https://cdn.jsdelivr.net/npm/@johnmorrisdotca/kumimoji@1/dist/element-define.js";
|
|
339
434
|
|
|
340
|
-
|
|
435
|
+
const game = document.getElementById("game");
|
|
436
|
+
game.addEventListener("kumimoji-change", (event) => {
|
|
437
|
+
localStorage.setItem("kumimoji", JSON.stringify(event.detail.saved));
|
|
438
|
+
});
|
|
439
|
+
game.addEventListener("kumimoji-finish", (event) => {
|
|
440
|
+
document.getElementById("note").textContent = `Done in ${Math.round(event.detail.elapsedMs / 1000)} seconds.`;
|
|
441
|
+
});
|
|
442
|
+
</script>
|
|
443
|
+
```
|
|
341
444
|
|
|
342
|
-
|
|
343
|
-
puzzles, card games and dice games played at your own pace. *Itsutsu* (五つ) is
|
|
344
|
-
Japanese for "five", after five in a row, the game the site began with. It is
|
|
345
|
-
[the Kumimoji played there](https://itsutsu.com/games/kumimoji): alone, in
|
|
346
|
-
races, round one device and across several.
|
|
445
|
+
### Deal the day's bag
|
|
347
446
|
|
|
348
|
-
|
|
447
|
+
`kumimojiDailySeed(date)` is the UTC date as a number, the same for everybody on earth, and the same number as Tane's `dailySeed`. Everybody who deals from it with the same settings gets the same bag in the same order:
|
|
349
448
|
|
|
350
|
-
|
|
351
|
-
|
|
449
|
+
```ts
|
|
450
|
+
import "@johnmorrisdotca/kumimoji/words";
|
|
451
|
+
import { generateKumimoji, kumimojiDay, kumimojiDailySeed, loadTileWords } from "@johnmorrisdotca/kumimoji";
|
|
352
452
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
453
|
+
await loadTileWords("english");
|
|
454
|
+
const now = new Date("2026-10-06T10:00:00Z");
|
|
455
|
+
kumimojiDay(now); // → "2026-10-06"
|
|
456
|
+
kumimojiDailySeed(now); // → 20261006
|
|
457
|
+
const dealt = generateKumimoji(7, "medium", kumimojiDailySeed(now));
|
|
458
|
+
dealt.givens.length; // → 40
|
|
459
|
+
dealt.givens.slice(0, 10); // → "ltlekac*rm"
|
|
460
|
+
```
|
|
356
461
|
|
|
357
|
-
|
|
462
|
+
The `*` is a wild tile, which takes any letter. The bag is one character a tile, in the order the tiles come out.
|
|
358
463
|
|
|
359
|
-
|
|
360
|
-
Kumimoji is one of twenty-four packages, each made for the same site, each at
|
|
361
|
-
[github.com/johnmorrisdotca](https://github.com/johnmorrisdotca). The code of every one is MIT.
|
|
464
|
+
### Judge a grid
|
|
362
465
|
|
|
363
|
-
|
|
364
|
-
- [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/).
|
|
365
|
-
- [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/).
|
|
366
|
-
- [Toranpu](https://github.com/johnmorrisdotca/toranpu) (トランプ): a deck of playing cards, card games with computer players, and solitaires. [Demo](https://johnmorrisdotca.github.io/toranpu/).
|
|
367
|
-
- [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/).
|
|
368
|
-
- [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/).
|
|
369
|
-
- [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/).
|
|
370
|
-
- [Kumimoji](https://github.com/johnmorrisdotca/kumimoji) (組み文字): a crossword tile race, in English and Japanese kana. [Demo](https://johnmorrisdotca.github.io/kumimoji/).
|
|
371
|
-
- [Tsunagi](https://github.com/johnmorrisdotca/tsunagi) (繋ぎ): a line-joining logic puzzle whose every level has exactly one answer. [Demo](https://johnmorrisdotca.github.io/tsunagi/).
|
|
372
|
-
- [Jarajara](https://github.com/johnmorrisdotca/jarajara) (ジャラジャラ): mahjong tiles drawn as SVG, stacked layouts, and the matching solitaire Awase. [Demo](https://johnmorrisdotca.github.io/jarajara/).
|
|
373
|
-
- [Suido](https://github.com/johnmorrisdotca/suido) (水道): a pipe puzzle: turn the pieces until the water reaches every drain. [Demo](https://johnmorrisdotca.github.io/suido/).
|
|
374
|
-
- [Domino](https://github.com/johnmorrisdotca/domino) (ドミノ): dominoes and Mexican Train. [Demo](https://johnmorrisdotca.github.io/domino/).
|
|
375
|
-
- [Kotoba](https://github.com/johnmorrisdotca/kotoba) (言葉): word lists and word-game rules in English, French, German and Japanese. [Demo](https://johnmorrisdotca.github.io/kotoba/).
|
|
376
|
-
- [Sugoroku](https://github.com/johnmorrisdotca/sugoroku) (双六): backgammon and its variants, with the doubling cube and match play. [Demo](https://johnmorrisdotca.github.io/sugoroku/).
|
|
377
|
-
- [Kazu](https://github.com/johnmorrisdotca/kazu) (数): grid number puzzles: Sudoku and its variants, Futoshiki and Skyscrapers. [Demo](https://johnmorrisdotca.github.io/kazu/).
|
|
378
|
-
- [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/).
|
|
379
|
-
- [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/).
|
|
380
|
-
- [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/).
|
|
381
|
-
- [Bushu](https://github.com/johnmorrisdotca/bushu) (部首): find a kanji by the parts it is made of. [Demo](https://johnmorrisdotca.github.io/bushu/).
|
|
382
|
-
- [Tobiishi](https://github.com/johnmorrisdotca/tobiishi) (飛び石): peg solitaire with nine boards and seeded solvable challenges. [Demo](https://johnmorrisdotca.github.io/tobiishi/).
|
|
383
|
-
- [Jirai](https://github.com/johnmorrisdotca/jirai) (地雷): minesweeper on shaped grids with verified no-guess boards. [Demo](https://johnmorrisdotca.github.io/jirai/).
|
|
384
|
-
- [Gunjin](https://github.com/johnmorrisdotca/gunjin) (軍人): five hidden-rank strategy games with pass-the-device play. [Demo](https://johnmorrisdotca.github.io/gunjin/).
|
|
385
|
-
- [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/).
|
|
386
|
-
- [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/).
|
|
466
|
+
`judgeWithWords(tiles, words)` says what is wrong with a grid: the tiles in runs that are not words, and the tiles standing apart from the crossword. A table draws the first as a red ring and fades the second:
|
|
387
467
|
|
|
388
|
-
|
|
389
|
-
|
|
468
|
+
```ts
|
|
469
|
+
import "@johnmorrisdotca/kumimoji/words";
|
|
470
|
+
import { decodeGrid, judgeWithWords, loadTileWords, squareAt } from "@johnmorrisdotca/kumimoji";
|
|
390
471
|
|
|
391
|
-
|
|
472
|
+
const words = await loadTileWords("english");
|
|
473
|
+
const crossword = decodeGrid("cat/2o/2w")!;
|
|
474
|
+
judgeWithWords(crossword, words).sound; // → true
|
|
475
|
+
|
|
476
|
+
const scattered = new Map(crossword);
|
|
477
|
+
scattered.set(squareAt(4, 4), "x"); // a tile that touches nothing
|
|
478
|
+
const verdict = judgeWithWords(scattered, words);
|
|
479
|
+
verdict.sound; // → false
|
|
480
|
+
[...verdict.apart]; // → ["4,4"]
|
|
481
|
+
```
|
|
392
482
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
483
|
+
### What the computer player would lay
|
|
484
|
+
|
|
485
|
+
`bestLaying(play, words)` finds the word the computer player lays from a hand and a table, with no randomness, so a turn replays exactly after a reload:
|
|
486
|
+
|
|
487
|
+
```ts
|
|
488
|
+
import "@johnmorrisdotca/kumimoji/words";
|
|
489
|
+
import { bestLaying, deal, generateKumimoji, loadTileWords, wordsInHand } from "@johnmorrisdotca/kumimoji";
|
|
490
|
+
|
|
491
|
+
const words = await loadTileWords("english");
|
|
492
|
+
const play = deal(generateKumimoji(7, "hard", 2026).givens, 7);
|
|
493
|
+
play.hand.join(""); // → "xbsnnny"
|
|
494
|
+
bestLaying(play, words)?.word; // → "by"
|
|
495
|
+
wordsInHand(play.hand, words); // → ["by"]
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
`wordsInHand` is the same list a player is offered as help when the game was set up with it.
|
|
499
|
+
|
|
500
|
+
### A computer's turn, step by step
|
|
501
|
+
|
|
502
|
+
`planComputerTurn(game, words)` lists a computer seat's whole turn as steps, in order, for a page to show one at a time; `afterComputerTurn` is the game after all of them:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
import "@johnmorrisdotca/kumimoji/words";
|
|
506
|
+
import { afterComputerTurn, endTurn, generateKumimoji, handCanSpell, judgeWithWords, loadTileWords, nameOf, planComputerTurn, seatPlay, startParty } from "@johnmorrisdotca/kumimoji";
|
|
507
|
+
|
|
508
|
+
const words = await loadTileWords("english");
|
|
509
|
+
const settings = { size: 7, level: "hard", seed: 2026, gameLength: "short", language: "english", doubleSet: false, diagonals: false, hints: false } as const;
|
|
510
|
+
let game = startParty(settings, generateKumimoji(7, "hard", 2026).givens, ["Ann", { name: "Computer", computer: true }]);
|
|
511
|
+
game = endTurn(game, judgeWithWords(seatPlay(game).tiles, words), (hand) => handCanSpell(hand, words)); // Ann passes
|
|
512
|
+
nameOf(game, game.turn); // → "Computer 1"
|
|
513
|
+
|
|
514
|
+
const steps = planComputerTurn(game, words);
|
|
515
|
+
steps.map(({ said }) => (said.kind === "laid" ? `laid ${said.word}` : said.kind)); // → ["laid enamor", "traded", "laid cate", "drew", "done"]
|
|
516
|
+
nameOf(afterComputerTurn(game, words), 0); // → "Ann"
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Points for a finished game
|
|
520
|
+
|
|
521
|
+
A finished game scores 10 a tile, and up to as much again for speed (this one is 770 points at a minute and a half, and 500 at fifteen minutes, when no speed bonus is left). A server that has checked a grid can award the same points the table shows:
|
|
522
|
+
|
|
523
|
+
```ts
|
|
524
|
+
import "@johnmorrisdotca/kumimoji/words";
|
|
525
|
+
import { generateKumimoji, kumimojiPoints, loadTileWords } from "@johnmorrisdotca/kumimoji";
|
|
526
|
+
|
|
527
|
+
await loadTileWords("english");
|
|
528
|
+
const dealt = generateKumimoji(7, "hard", 2026);
|
|
529
|
+
kumimojiPoints(dealt.givens, 90_000); // → 770
|
|
530
|
+
kumimojiPoints(dealt.givens, 900_000); // → 500
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Check a race on a server
|
|
534
|
+
|
|
535
|
+
Players racing a seed are dealt the same bag, so a server that is handed only the seed and a finished grid checks the whole game in time proportional to the grid, with no search:
|
|
536
|
+
|
|
537
|
+
```ts
|
|
538
|
+
import "@johnmorrisdotca/kumimoji/words";
|
|
539
|
+
import { checkKumimoji, generateKumimoji, loadTileWords } from "@johnmorrisdotca/kumimoji";
|
|
540
|
+
|
|
541
|
+
await loadTileWords("english");
|
|
542
|
+
const dealt = generateKumimoji(3, "hard", 44);
|
|
543
|
+
checkKumimoji(3, dealt.givens, "snowy", { level: "hard" }); // → { ok: true }
|
|
544
|
+
checkKumimoji(3, dealt.givens, "snows", { level: "hard" }); // → { ok: false, reason: "the grid does not use exactly the tiles of the bag" }
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Mount the table with options
|
|
548
|
+
|
|
549
|
+
`mountKumimoji` plays a whole game alone in one element, and hands back the game as plain data after each change:
|
|
550
|
+
|
|
551
|
+
```ts no-run
|
|
552
|
+
import { mountKumimoji } from "@johnmorrisdotca/kumimoji/ui";
|
|
553
|
+
|
|
554
|
+
const table = mountKumimoji(document.getElementById("table")!, {
|
|
555
|
+
language: "japanese",
|
|
556
|
+
hand: 11,
|
|
557
|
+
level: "easy", // the most wild tiles
|
|
558
|
+
gameLength: "medium", // half the set
|
|
559
|
+
seed: 2026,
|
|
560
|
+
locale: "ja", // the table's own words
|
|
561
|
+
onFinish: (result) => console.log("done", result),
|
|
562
|
+
});
|
|
563
|
+
await table.newGame({ language: "english", hand: 7 }); // another game, on the same table
|
|
564
|
+
table.destroy();
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### A look of your own
|
|
568
|
+
|
|
569
|
+
Every colour is a CSS variable on `.km-root`, so a stylesheet or the `theme` option can restyle the table:
|
|
570
|
+
|
|
571
|
+
```ts no-run
|
|
572
|
+
import { mountKumimoji } from "@johnmorrisdotca/kumimoji/ui";
|
|
573
|
+
|
|
574
|
+
mountKumimoji(document.getElementById("table")!, {
|
|
575
|
+
theme: { "--km-felt": "#23405a", "--km-tile": "#fffdf7", "--km-wild": "#d4a017", "--km-square": "40px" },
|
|
576
|
+
});
|
|
577
|
+
```
|
|
421
578
|
|
|
422
579
|
## How to play
|
|
423
580
|
|
|
@@ -611,7 +768,7 @@ The JSON, as `kumimojiToJSON` writes it:
|
|
|
611
768
|
{
|
|
612
769
|
"format": 1,
|
|
613
770
|
"game": "kumimoji",
|
|
614
|
-
"generator": "kumimoji 1.
|
|
771
|
+
"generator": "kumimoji 1.3.0",
|
|
615
772
|
"size": 3,
|
|
616
773
|
"level": "hard",
|
|
617
774
|
"seed": 44,
|
|
@@ -707,7 +864,7 @@ turn tiles into words: `glyphOf`, `soundOf`, `wordOf`, `wildFor`, `isWild`,
|
|
|
707
864
|
|
|
708
865
|
## API
|
|
709
866
|
|
|
710
|
-
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.
|
|
711
868
|
|
|
712
869
|
Every function, type and constant has a doc comment, so an editor shows this
|
|
713
870
|
as you type. The entries:
|
|
@@ -721,76 +878,22 @@ as you type. The entries:
|
|
|
721
878
|
| `@johnmorrisdotca/kumimoji/element/define` | Defines `<kumimoji-table>` on the page by being imported; exports nothing |
|
|
722
879
|
| `@johnmorrisdotca/kumimoji/react` | `KumimojiBoard` and `KumimojiTable` |
|
|
723
880
|
|
|
724
|
-
###
|
|
881
|
+
### The calls to learn first
|
|
725
882
|
|
|
726
|
-
|
|
|
883
|
+
| Call | What it does |
|
|
727
884
|
| --- | --- |
|
|
728
885
|
| `generateKumimoji(hand, level, seed, options?)` | A game dealt from a seed: the bag, and one grid that finishes it |
|
|
729
|
-
| `
|
|
730
|
-
| `
|
|
731
|
-
| `
|
|
732
|
-
| `checkKumimoji(size, givens, answer, options?)` |
|
|
733
|
-
| `
|
|
734
|
-
| `
|
|
735
|
-
| `
|
|
736
|
-
| `crossingFit`, `diagonalsRead` | Where a word may be laid crossing a tile, and the diagonal runs a new tile would make, for a generator or a computer player |
|
|
737
|
-
| `seededRandom(seed)`, `shuffled(items, random)` | The seeded random a deal is drawn from |
|
|
738
|
-
|
|
739
|
-
### Tiles and grids
|
|
886
|
+
| `deal(bag, handSize)` and `placeFromHand`, `moveOnTable`, `liftToHand`, `draw`, `trade` | The opening hand, and each move, every one returning a new game |
|
|
887
|
+
| `judgeWithWords(tiles, words)` | What is wrong with a grid, or that it is sound |
|
|
888
|
+
| `isFinished(play, verdict)` | Whether the bag is empty, the hand used and every run a word in one piece |
|
|
889
|
+
| `checkKumimoji(size, givens, answer, options?)` | The one check a server runs on a finished grid |
|
|
890
|
+
| `loadTileWords(language)` | A word list, fetched when first needed |
|
|
891
|
+
| `mountKumimoji(element, options?)` and `<kumimoji-table>` | The table, in one call or one tag |
|
|
892
|
+
| `kumimojiToJSON`, `kumimojiFromJSON` | A game kept, and read back without trusting it |
|
|
740
893
|
|
|
741
|
-
|
|
742
|
-
| --- | --- |
|
|
743
|
-
| `squareAt(row, col)`, `placeOf(square)` | A square's key, and back |
|
|
744
|
-
| `encodeGrid(tiles)`, `decodeGrid(code)`, `boundsOf(tiles)` | A grid as a string, and back; the rows and columns it stands within |
|
|
745
|
-
| `lettersOf(letters)`, `sameLetters(a, b)` | How many of each tile, and whether two tallies match |
|
|
746
|
-
| `tileFace(tile)`, `tileDescription(tile)`, `kanaTileCode(kana, wild?)` | What a tile shows; what a screen reader says; a kana's tile |
|
|
747
|
-
| `tileKana(kana)`, `BASE_KANA`, `CORNER_FORMS`, `formsOfTile(kana)` | The tile a kana is played with, the 45 tiles, and the forms each plays as |
|
|
748
|
-
| `familyKeyOf(language)` | Which tile of the set a code is, without the word list |
|
|
749
|
-
| `loadTileWords`, `tileWords`, `tileWordsReady` | The word list: fetched, handed back, asked after |
|
|
750
|
-
| `unpackTileWords`, `unpackLength`, `tileWordsFrom`, `readTileWordsWith` | How a list is read from its packed data, for the loader |
|
|
751
|
-
| `mixShown(language)`, `lengthRows(hand?)`, `LENGTHS`, `TRY_IT` | A set and the lengths of game as a page shows them |
|
|
894
|
+
### The long tables
|
|
752
895
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
The moves are in [Playing](#playing) above. With them:
|
|
756
|
-
|
|
757
|
-
| Export | What it does |
|
|
758
|
-
| --- | --- |
|
|
759
|
-
| `tilesLeft(play)` | How many tiles are still in the bag |
|
|
760
|
-
| `encodeTileProgress(play)`, `readTileProgress(code)`, `decodeTileProgress(code, bag, language?)` | A game half way as one string; its shape read; and opened again on its own bag |
|
|
761
|
-
| `kumimojiToJSON(saved)`, `kumimojiFromJSON(text)`, `kumimojiExported(saved)` | A game as JSON, and back, or `null` |
|
|
762
|
-
| `kumimojiToText(saved, strings?)`, `gridToText(tiles, language?)`, `kumimojiClock(ms)` | A game, a grid and a time as text |
|
|
763
|
-
| `KUMIMOJI_EXPORT_FORMAT`, `KUMIMOJI_VERSION` | The JSON's format number, and this package's version |
|
|
764
|
-
| `KUMIMOJI_STRINGS`, `kumimojiStrings(locale, own?)`, `kumimojiSay(line, values)` | The table's words in English and Japanese |
|
|
765
|
-
|
|
766
|
-
### A table of players
|
|
767
|
-
|
|
768
|
-
| Export | What it does |
|
|
769
|
-
| --- | --- |
|
|
770
|
-
| `startParty(settings, bag, seats)` | A table dealt: two to eight seats, each a name or `{ name, computer }` |
|
|
771
|
-
| `seatPlay(game)`, `withSeatPlay(game, play)` | The player to move's hand and table as a `TilePlay`, and the game with it put back |
|
|
772
|
-
| `endTurn(game, verdict, handSpells)`, `doneRefused(…)` | End the turn; why Done is refused, if it is |
|
|
773
|
-
| `drawAll(game)`, `mayDrawAll(game, verdict)` | Everyone draws together |
|
|
774
|
-
| `resign(game)`, `mayResign(game)` | Give up the game |
|
|
775
|
-
| `joinParty(game, seat)`, `joinRefused(game)`, `leaveParty(game, at)`, `leaveRefused(game, at)` | Joining and leaving a game under way |
|
|
776
|
-
| `isOver(game)`, `winnersOf(game)`, `goesOut(game, verdict)`, `isLastTurn(game)`, `lastStanding(game)` | How the game stands and ends |
|
|
777
|
-
| `mayTradeThisTurn(game)`, `mustTradeFirst(game, handSpells)`, `laidThisTurn(game)`, `handCanSpell(hand, words)` | What this turn may and must do |
|
|
778
|
-
| `nameOf(game, at)`, `tidyName(name)`, `computerName(players)`, `isComputer(game, at)` | Names, and whether a seat is a computer's |
|
|
779
|
-
| `stillIn(game)`, `nextIn(game, from)`, `partyTilesLeft(game)`, `tilesHeldBy(game, at)`, `tableTally(tiles)` | Who is in, whose turn is next, and the tiles |
|
|
780
|
-
| `partyTilesNeeded`, `partyFits`, `partyLength`, `partyPlayersAsked` | Whether a bag is big enough for a table, for a set-up screen |
|
|
781
|
-
| `passViewStart(game)`, `stepView(game, from, by)` | Whose table a shared screen shows |
|
|
782
|
-
| `encodeParty(game)`, `decodeParty(code, familyKey?)`, `readSettings(value)`, `holdsItsBag(game, familyKey)`, `isPartyFor` | A table kept as text, read back and checked, and matched to the set-up it was dealt for |
|
|
783
|
-
| `afterComputerTurn(game, words)`, `planComputerTurn(game, words)`, `COMPUTER_STEPS_MOST` | A computer seat's turn, whole or step by step |
|
|
784
|
-
| `bestLaying(play, words, rules?)`, `tradeChoice(hand, words)`, `judgeTiles(tiles, words, rules?)` | What the computer would lay, and trade |
|
|
785
|
-
|
|
786
|
-
### Looking at the table
|
|
787
|
-
|
|
788
|
-
A table with no edges is looked at through a view, which the package keeps
|
|
789
|
-
apart from the game: `tableArea`, `fitView`, `fittedMost`, `zoomView`,
|
|
790
|
-
`panView`, `keepInReach`, `overflows`, `squareUnder`, `edgePan` and the
|
|
791
|
-
numbers in `TABLE`. A player may turn the table a quarter at a time with every
|
|
792
|
-
tile kept upright: `nextTurn`, `turnPlace`, `unturnPlace`, `turnArea`,
|
|
793
|
-
`turnView`, `typingWay` and `arrowStep`.
|
|
896
|
+
The tables of every export for dealing and judging, tiles and grids, playing and keeping a game, a table of players and looking at the table are in [docs/API.md](docs/API.md), and every export of every entry point, with its signature and doc comment, is in the [API reference](https://johnmorrisdotca.github.io/kumimoji/api.html). The types the package exports are listed there too.
|
|
794
897
|
|
|
795
898
|
The types are `TilePlay`, `Tiles`, `GridVerdict`, `GridRules`, `Run`,
|
|
796
899
|
`RunLine`, `Bounds`, `Square`, `CrossingFit`, `KumimojiDeal`,
|
|
@@ -803,65 +906,11 @@ The types are `TilePlay`, `Tiles`, `GridVerdict`, `GridRules`, `Run`,
|
|
|
803
906
|
|
|
804
907
|
### The table
|
|
805
908
|
|
|
806
|
-
`mountKumimoji(element, options?)` from `@johnmorrisdotca/kumimoji/ui` deals
|
|
807
|
-
and plays a whole game alone in the element, and returns a handle.
|
|
808
|
-
|
|
809
|
-
| Option | Default | What it does |
|
|
810
|
-
| --- | --- | --- |
|
|
811
|
-
| `language` | `"english"` | The language of the tiles: `"english"` or `"japanese"` |
|
|
812
|
-
| `hand` | `7` | The opening hand: 3, 7 or 11 tiles |
|
|
813
|
-
| `level` | `"medium"` | Wild tiles: `"easy"` the most, `"medium"` some, `"hard"` none |
|
|
814
|
-
| `gameLength` | `"short"` | `"short"`, `"medium"`, or `"full"`, all 144 tiles |
|
|
815
|
-
| `diagonals` | `false` | Every diagonal run of three or more must be a word too |
|
|
816
|
-
| `seed` | a new one each game | The seed the bag is dealt from |
|
|
817
|
-
| `onFinish` | | Called when the last tile is laid and every run is a word, with the time it took |
|
|
818
|
-
| `onChange` | | Called after every change, with the game as it would be saved |
|
|
819
|
-
| `locale` | the page's `lang` | The language of the table's words: `"en"` or `"ja"` |
|
|
820
|
-
| `strings` | | Words of your own, laid over the locale's |
|
|
821
|
-
| `theme` | | CSS variables set on the table itself |
|
|
822
|
-
| `keep` | `true` | Whether the table offers saving and loading |
|
|
823
|
-
|
|
824
|
-
| Handle | What it does |
|
|
825
|
-
| --- | --- |
|
|
826
|
-
| `play()` | The game as it stands, or `null` while it is being dealt |
|
|
827
|
-
| `saved()` | The game as it would be saved, or `null` while it is being dealt |
|
|
828
|
-
| `newGame(options?)` | A new game; any of the first six options may change |
|
|
829
|
-
| `setGame(saved)` | Put a game on the table: one read back by `kumimojiFromJSON` |
|
|
830
|
-
| `setLocale(locale, strings?)` | Change the language of the table's words |
|
|
831
|
-
| `destroy()` | Take the table off the page and stop its clock |
|
|
832
|
-
|
|
833
|
-
To play it: tap a tile in your hand and then a square to lay it; tap a tile on
|
|
834
|
-
the table and then a square to move it, or tap it again to take it back. A
|
|
835
|
-
wild is given its letter before it is laid. To draw a board yourself, the same
|
|
836
|
-
entry has `boardModel(tiles, verdict, glyphOf?)`, which works out the squares
|
|
837
|
-
to draw and how each tile stands, with `BOARD_MARGIN` and `BOARD_LEAST`, and
|
|
838
|
-
`KUMIMOJI_STYLE`, the table's stylesheet as a string.
|
|
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).
|
|
839
910
|
|
|
840
911
|
### The element
|
|
841
912
|
|
|
842
|
-
`<kumimoji-table>` is `mountKumimoji` as a tag: `@johnmorrisdotca/kumimoji/element/define`
|
|
843
|
-
defines it, and `@johnmorrisdotca/kumimoji/element` holds the class alone. Each
|
|
844
|
-
attribute is read again when it changes, and a change to any but `lang` deals a
|
|
845
|
-
new game. A table the rules do not offer (a hand of 5, say) draws nothing.
|
|
846
|
-
|
|
847
|
-
| Attribute | Default | What it does |
|
|
848
|
-
| --- | --- | --- |
|
|
849
|
-
| `language` | `english` | The tiles: `english` or `japanese` kana |
|
|
850
|
-
| `hand` | `7` | The opening hand: 3, 7 or 11 |
|
|
851
|
-
| `level` | `medium` | Wild tiles: `easy` the most, `medium` some, `hard` none |
|
|
852
|
-
| `length` | `short` | `short`, `medium` or `full`, all 144 tiles |
|
|
853
|
-
| `diagonals` | off | `on` to read every diagonal run of three or more too |
|
|
854
|
-
| `seed` | a new one each game | A whole number to deal from, or `daily` for the day's seed |
|
|
855
|
-
| `lang` | the page's | The language of the table's words: `en` or `ja` |
|
|
856
|
-
| `keep` | on | `off` leaves saving and loading out |
|
|
857
|
-
|
|
858
|
-
It fires `kumimoji-change` after every change to the game, with the game as it
|
|
859
|
-
would be saved as `event.detail.saved`, and `kumimoji-finish` when the last
|
|
860
|
-
tile is laid and every run is a word, with the deal, the play and the time it
|
|
861
|
-
took as `event.detail`; both bubble. It has `saved` (the game as it would be
|
|
862
|
-
saved), `table` (the handle `mountKumimoji` returns), `newGame(options?)` and
|
|
863
|
-
`setGame(saved)`. To style it, set the table's variables on `kumimoji-table
|
|
864
|
-
.km-root`: see [Theming](#theming).
|
|
913
|
+
`<kumimoji-table>` is `mountKumimoji` as a tag: `@johnmorrisdotca/kumimoji/element/define` defines it. Its attributes are `language`, `hand`, `level`, `length`, `diagonals`, `seed` (a number, or `daily`), `lang` and `keep`; it fires `kumimoji-change` and `kumimoji-finish`, which bubble. Every attribute, event and property is in [docs/API.md](docs/API.md#the-element).
|
|
865
914
|
|
|
866
915
|
### The React components
|
|
867
916
|
|
|
@@ -886,39 +935,7 @@ export function Board() {
|
|
|
886
935
|
}
|
|
887
936
|
```
|
|
888
937
|
|
|
889
|
-
|
|
890
|
-
| --- | --- |
|
|
891
|
-
| `tiles` | The tiles on the table: `play.tiles` |
|
|
892
|
-
| `verdict` | From `judgeWithWords`: rings the runs that are not words and fades the tiles apart |
|
|
893
|
-
| `glyphOf` | What to print on a tile: `words.glyphOf` for the language played |
|
|
894
|
-
| `onSquare` | Called with a square's key when it is pressed, empty or not |
|
|
895
|
-
| `held` | A square to ring, such as the one holding a tile picked up |
|
|
896
|
-
| `square` | The side of a square in pixels; 36 by default |
|
|
897
|
-
| anything else | Passed to the `<div>` |
|
|
898
|
-
|
|
899
|
-
`KumimojiTable` takes every option of `mountKumimoji` as a prop, and anything
|
|
900
|
-
else for its `<div>`. Options are read when it mounts; give it a new `key` to
|
|
901
|
-
start over with different ones.
|
|
902
|
-
|
|
903
|
-
## Accessibility
|
|
904
|
-
|
|
905
|
-
- **A keyboard plays it.** Every square and every tile in the hand is a button
|
|
906
|
-
with a name. Tab lands on one square of the table and on one tile of the
|
|
907
|
-
hand, the arrow keys move between squares (and Left, Right, Home and End
|
|
908
|
-
between the hand's tiles), Enter or Space picks a tile up and lays it, and
|
|
909
|
-
Escape lets go of a tile you have picked up. The keyboard stays where it was
|
|
910
|
-
after each move, including on the buttons under the table, and the table's
|
|
911
|
-
description says so.
|
|
912
|
-
- **What is happening is said.** The line above the table, with the tiles left
|
|
913
|
-
and the time, and the line saying which runs are not words, are polite live
|
|
914
|
-
regions, and so is the note after saving or loading.
|
|
915
|
-
- **Targets are big enough.** Every button is at least 44 pixels each way,
|
|
916
|
-
which a test holds at a phone's width.
|
|
917
|
-
- **Not by colour alone.** A run that is not a word is ringed and listed in
|
|
918
|
-
words; a tile apart from the crossword is faded and said so.
|
|
919
|
-
- **Motion.** There is none to reduce: the table has no animation.
|
|
920
|
-
- **Not yet.** Letters cannot be typed to lay a tile, and a screen reader hears
|
|
921
|
-
the table as a grid of squares, not as the words they make.
|
|
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).
|
|
922
939
|
|
|
923
940
|
## Theming
|
|
924
941
|
|
|
@@ -945,7 +962,7 @@ on the table itself and so wins in light and dark alike.
|
|
|
945
962
|
|
|
946
963
|
A slate table with ivory tiles, a little smaller:
|
|
947
964
|
|
|
948
|
-
```js
|
|
965
|
+
```js no-run
|
|
949
966
|
import { mountKumimoji } from "@johnmorrisdotca/kumimoji/ui";
|
|
950
967
|
|
|
951
968
|
mountKumimoji(document.getElementById("table"), {
|
|
@@ -956,6 +973,47 @@ mountKumimoji(document.getElementById("table"), {
|
|
|
956
973
|
`KumimojiBoard` draws with colours of its own; style it through its `style`
|
|
957
974
|
and `className`.
|
|
958
975
|
|
|
976
|
+
## Limits
|
|
977
|
+
|
|
978
|
+
| Limit | Value | Constant |
|
|
979
|
+
| --- | --- | --- |
|
|
980
|
+
| Opening hand | 3, 7 or 11 | `KUMIMOJI_HANDS` |
|
|
981
|
+
| A word | 2 to 15 tiles | |
|
|
982
|
+
| A finished grid, either way | 60 squares | `KUMIMOJI_GRID_MOST` |
|
|
983
|
+
| Players at a table | 2 to 8 | `KUMIMOJI_PARTY` |
|
|
984
|
+
| A player's name | 20 characters | `KUMIMOJI_PARTY` |
|
|
985
|
+
| Words one hand is offered as help | 40 | `HELP_WORDS_MOST` |
|
|
986
|
+
| A seed | a whole number from 0 to 4,294,967,295 | |
|
|
987
|
+
| Two sets at once | English only | |
|
|
988
|
+
|
|
989
|
+
## Accessibility
|
|
990
|
+
|
|
991
|
+
- **A keyboard plays it.** Every square and every tile in the hand is a button
|
|
992
|
+
with a name. Tab lands on one square of the table and on one tile of the
|
|
993
|
+
hand, the arrow keys move between squares (and Left, Right, Home and End
|
|
994
|
+
between the hand's tiles), Enter or Space picks a tile up and lays it, and
|
|
995
|
+
Escape lets go of a tile you have picked up. The keyboard stays where it was
|
|
996
|
+
after each move, including on the buttons under the table, and the table's
|
|
997
|
+
description says so.
|
|
998
|
+
- **What is happening is said.** The line above the table, with the tiles left
|
|
999
|
+
and the time, and the line saying which runs are not words, are polite live
|
|
1000
|
+
regions, and so is the note after saving or loading.
|
|
1001
|
+
- **Targets are big enough.** Every button is at least 44 pixels each way,
|
|
1002
|
+
which a test holds at a phone's width.
|
|
1003
|
+
- **Not by colour alone.** A run that is not a word is ringed and listed in
|
|
1004
|
+
words; a tile apart from the crossword is faded and said so.
|
|
1005
|
+
- **Motion.** There is none to reduce: the table has no animation.
|
|
1006
|
+
- **Not yet.** Letters cannot be typed to lay a tile, and a screen reader hears
|
|
1007
|
+
the table as a grid of squares, not as the words they make.
|
|
1008
|
+
|
|
1009
|
+
## Browser support
|
|
1010
|
+
|
|
1011
|
+
Any current browser: Chrome, Edge, Firefox and Safari, on a desk or a phone.
|
|
1012
|
+
It needs ES2020 and dynamic `import()`. The table is tested in Chromium and in
|
|
1013
|
+
WebKit, Safari's engine, at phone size with touch and on a desktop. The rules
|
|
1014
|
+
run in Node 22 and later, Deno, Bun and web workers, and load by `import` and
|
|
1015
|
+
by `require()`.
|
|
1016
|
+
|
|
959
1017
|
## Languages
|
|
960
1018
|
|
|
961
1019
|
Two things here have a language, and they are chosen apart. **The tiles** are
|
|
@@ -981,27 +1039,6 @@ kumimojiStrings("en", { draw: "Robar" }).draw; // → "Robar"
|
|
|
981
1039
|
A new language for the tiles is another matter: it needs a real dictionary of
|
|
982
1040
|
that language, whose licence lets its words be shipped.
|
|
983
1041
|
|
|
984
|
-
## Limits
|
|
985
|
-
|
|
986
|
-
| Limit | Value | Constant |
|
|
987
|
-
| --- | --- | --- |
|
|
988
|
-
| Opening hand | 3, 7 or 11 | `KUMIMOJI_HANDS` |
|
|
989
|
-
| A word | 2 to 15 tiles | |
|
|
990
|
-
| A finished grid, either way | 60 squares | `KUMIMOJI_GRID_MOST` |
|
|
991
|
-
| Players at a table | 2 to 8 | `KUMIMOJI_PARTY` |
|
|
992
|
-
| A player's name | 20 characters | `KUMIMOJI_PARTY` |
|
|
993
|
-
| Words one hand is offered as help | 40 | `HELP_WORDS_MOST` |
|
|
994
|
-
| A seed | a whole number from 0 to 4,294,967,295 | |
|
|
995
|
-
| Two sets at once | English only | |
|
|
996
|
-
|
|
997
|
-
## Browser support
|
|
998
|
-
|
|
999
|
-
Any current browser: Chrome, Edge, Firefox and Safari, on a desk or a phone.
|
|
1000
|
-
It needs ES2020 and dynamic `import()`. The table is tested in Chromium and in
|
|
1001
|
-
WebKit, Safari's engine, at phone size with touch and on a desktop. The rules
|
|
1002
|
-
run in Node 22 and later, Deno, Bun and web workers, and load by `import` and
|
|
1003
|
-
by `require()`.
|
|
1004
|
-
|
|
1005
1042
|
## The command line
|
|
1006
1043
|
|
|
1007
1044
|
There is none, on purpose. Checking a word or seeing a deal is a few lines of
|
|
@@ -1034,24 +1071,138 @@ runs from a static page and costs nothing to host.
|
|
|
1034
1071
|
|
|
1035
1072
|
Ideas and pull requests are welcome.
|
|
1036
1073
|
|
|
1037
|
-
##
|
|
1074
|
+
## Architecture
|
|
1075
|
+
|
|
1076
|
+
The rules are plain functions over plain data with no DOM: a game is a value,
|
|
1077
|
+
every move returns the next one, and the same seed deals the same bag in every
|
|
1078
|
+
browser. Word lists are loaded only when a game opens, and the table is its own
|
|
1079
|
+
entry (`/ui` for plain DOM, `/element` for a tag, `/react` for React), so a page that wants only the
|
|
1080
|
+
rules carries none of it. A computer player is pure too, so its turn replays
|
|
1081
|
+
exactly after a reload.
|
|
1082
|
+
|
|
1083
|
+
The file-by-file tree, with a line on each source file, is in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md): the rules (`grid`, `judge`, `play`, `generate`, `check`), the table of players (`party*`), the computer player (`computer*`), the Japanese tiles (`kana`), the word lists (`words*`), and the three faces (`ui`, `element`, `react`). Tests sit beside the code they test (`*.test.ts`). `scripts/` builds the demo
|
|
1084
|
+
and checks the package as npm packs it, `demo/` is the page published on
|
|
1085
|
+
GitHub Pages, and `table/` taps it in real browsers.
|
|
1086
|
+
|
|
1087
|
+
## The name
|
|
1088
|
+
|
|
1089
|
+
*Kumimoji* (組み文字) is made of *kumi* (組み, from 組む, to put together or
|
|
1090
|
+
assemble) and *moji* (文字, a letter or character): letters put together,
|
|
1091
|
+
which is what a player does with the tiles. Say it in four even beats:
|
|
1092
|
+
ku-mi-mo-ji. In Japanese printing the same word names something else, several
|
|
1093
|
+
characters set together in the space of one; the game borrows only its plain
|
|
1094
|
+
sense.
|
|
1095
|
+
|
|
1096
|
+
## Where it comes from, and where it is used
|
|
1097
|
+
|
|
1098
|
+
Kumimoji was built for [Itsutsu](https://itsutsu.com), a site for board games,
|
|
1099
|
+
puzzles, card games and dice games played at your own pace. *Itsutsu* (五つ) is
|
|
1100
|
+
Japanese for "five", after five in a row, the game the site began with. It is
|
|
1101
|
+
[the Kumimoji played there](https://itsutsu.com/games/kumimoji): alone, in
|
|
1102
|
+
races, round one device and across several.
|
|
1103
|
+
|
|
1104
|
+
### Used by
|
|
1105
|
+
|
|
1106
|
+
- [Itsutsu](https://itsutsu.com), for its game of Kumimoji: its rules, its
|
|
1107
|
+
word lists and its computer player.
|
|
1108
|
+
|
|
1109
|
+
That is the whole list so far. Using Kumimoji in something? Open an
|
|
1110
|
+
[*Add my project*](https://github.com/johnmorrisdotca/kumimoji/issues/new?template=add-my-project.md)
|
|
1111
|
+
issue and we will add you.
|
|
1112
|
+
|
|
1113
|
+
### The family
|
|
1114
|
+
|
|
1115
|
+
<!-- family:start (made by scripts/family-readme.mjs from scripts/family-template.mjs; change those, not this) -->
|
|
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.
|
|
1118
|
+
|
|
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/).
|
|
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/).
|
|
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/).
|
|
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/).
|
|
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/).
|
|
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**
|
|
1038
1135
|
|
|
1039
|
-
|
|
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/).
|
|
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/).
|
|
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/).
|
|
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/).
|
|
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/).
|
|
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
|
+
|
|
1175
|
+
|
|
1176
|
+
**This package is Kumimoji.** The demos of all thirty-two share one header and footer, so each links the rest.
|
|
1177
|
+
<!-- family:end -->
|
|
1178
|
+
|
|
1179
|
+
## Development
|
|
1040
1180
|
|
|
1041
1181
|
```sh
|
|
1042
|
-
pnpm install
|
|
1043
|
-
pnpm check
|
|
1044
|
-
pnpm test:table
|
|
1045
|
-
pnpm
|
|
1046
|
-
pnpm
|
|
1182
|
+
pnpm install --frozen-lockfile
|
|
1183
|
+
pnpm check # lint, types and tests, including the checks on the README's tables and examples
|
|
1184
|
+
pnpm test:table # the demo in real browsers, by taps
|
|
1185
|
+
pnpm test:package # pack it as npm does, install it and import every entry
|
|
1186
|
+
pnpm test:frameworks # the six framework examples, built from the packed tarball and played
|
|
1187
|
+
pnpm test:readme # every TypeScript and JavaScript example in this README, type-checked and run
|
|
1188
|
+
pnpm site # build the demo into ./site
|
|
1189
|
+
pnpm screenshots:readme # retake the README's pictures into docs/images (builds the demo first)
|
|
1047
1190
|
```
|
|
1048
1191
|
|
|
1192
|
+
The pictures are taken on the maintainer's Mac and are retaken only when the look changes; they are in `docs/images` and are not in the package that npm installs.
|
|
1193
|
+
|
|
1194
|
+
## Contributing
|
|
1195
|
+
|
|
1196
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md). In short: run `pnpm check` before you push (see [Development](#development)).
|
|
1197
|
+
|
|
1049
1198
|
Please follow the [code of conduct](./CODE_OF_CONDUCT.md). A way to make a check or a deal run for long, or markup that gets out of the drawing, is for the [security policy](./SECURITY.md), not a public issue.
|
|
1050
1199
|
|
|
1051
1200
|
## Changes
|
|
1052
1201
|
|
|
1053
1202
|
See [CHANGELOG.md](./CHANGELOG.md).
|
|
1054
1203
|
|
|
1204
|
+
The latest release is 1.3.0: the table's standard embed attributes, the shared embed builder, and the documentation site with a checked example for every export.
|
|
1205
|
+
|
|
1055
1206
|
## Licence
|
|
1056
1207
|
|
|
1057
1208
|
The code is [MIT](./LICENSE) © John Morris.
|