TinyGames · how it works

Quintet

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

The whole game is one hard rule

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.


So the rule is written twice, facing opposite ways

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

What the tests are worth

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.


Five languages, five keyboards

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.

Playing 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.