TinyGames · how it works
Five letters, six tries, five languages. Every guess comes back marked: green where a letter is in the right place, amber where it is in the word but somewhere else, grey where it is not there at all. Keep solving until you lose one.
Open index.html. No build step, no dependencies, no images — the board is drawn.
quintet/
index.html markup
style.css the frame around the canvas
js/lexicon.js shared: the alphabets, the keyboards, the folding rules
js/guessing.js the marking, the clue reading and the answers
- no pixels, no engine, no DOM
js/quintet.js the playable layer
test-guessing.js node test-guessing.js
Marking a guess sounds like three lines and is not, because of repeated letters. The obvious version asks "is this letter in the answer?" and is wrong in a way nobody notices until a player does.
Answer SPEED, guess EERIE. Three E's guessed; the answer has two. The supply cannot cover three, so one has to come back grey — and which one matters, because a player reads the position. Marking every E amber tells them there are at least three E's in the answer, which is a lie the game told, not a deduction the player got wrong.
The rule that falls out is a supply. Exact matches take their letter out of the answer's pool first; only then do the leftovers claim what remains, in reading order. A single pass, in either direction, gets it wrong.
| direction | used for | |
|---|---|---|
markGuess |
forwards — what does this guess look like against this answer | what the player sees |
fitsClue |
backwards — could this word be the answer, given what was shown | the hint, and the test |
fitsClue never calls markGuess. It is written from the meaning of the marks:
green pins a letter to a place, amber says "at least this many", and grey says the
supply ran out, so "exactly this many". That independence is the point — a shared
mistake would not show up if one simply wrapped the other.
The test holds them to each other in both directions:
Plus a third description of the same rule, written only in the test and deliberately
not how either implementation computes it: for each letter, the number of green-or-amber
marks it gets is min(count in guess, count in answer). That single line pins the
repeated-letter question down completely.
$ node test-guessing.js
57 passed, 0 failed
Five mutants. Four broke something real; the fifth changed nothing on purpose, as a control that the harness does not simply fail on any edit.
| mutation | result |
|---|---|
| the naive "does the answer contain it" rule | caught (5 assertions) |
| amber claimed before green | caught (3) |
fitsClue always agrees |
caught (2) |
| the keyboard keeps the latest mark, not the best | caught (2) |
markGuess wrapped, behaviour unchanged |
passes, as it should |
That fourth one survived the first version of the suite. A key shown green and then grey in a later guess is still green, and the test that was supposed to prove it used a later guess which simply omitted the letter — which proves nothing either way. It needed a later guess that contains the letter and marks it lower. Both cases are in there now, alongside a control computing the naive "last one wins" answer to show the two really do differ.
The alphabets, the keyboard layouts and the accent-folding rules live in
src/shared/lexicon.ts, shared with Hangman and Jumble. Spanish gets ñ as its own
key beside the L; German gets QWERTZ with the umlauts and the eszett; French gets
AZERTY. Guesses are marked on keys, so a French answer spelt with an accent is
still matched by the plain letter a French keyboard would produce.
Answers are curated — a few hundred common five-letter words per language — but guesses are not checked against that list. With a list this size, demanding every guess be one of them would make the game a memory test for one file, and would punish a player working in their second language for knowing a real word that happens not to be in it.
Type, or tap the drawn keyboard. Enter submits, Backspace rubs out, the language
button top right cycles through the five. Escape or P pauses.
The umlauts, the eszett and ñ have no key of their own on a UK keyboard, so the drawn keyboard is the only way to reach them — which is another reason it is drawn rather than assumed.
Advertisement