AT Mot — a bilingual (EN/FR) daily word game native to the AT Protocol.
0

Configure Feed

Select the types of activity you want to include in your feed.

at trunk 1.5 kB View raw
1/** 2 * plurals.ts — detect inflected -S forms (plurals, 3rd-person-singular verbs) so 3 * they can be kept out of the daily-answer pool. They remain valid as *guesses*. 4 * 5 * The singular of a 5-letter -S form is shorter than five letters (ROOMS -> ROOM, 6 * BOXES -> BOX), so `isWord` MUST recognise words of every length. The historical 7 * bug here passed a 5-letter-only set, so no 4-letter singular ever matched and 8 * the filter silently did nothing. 9 */ 10 11// Stems that take "-es" rather than a bare "-s": those ending in a sibilant 12// (S, X, Z) or the digraphs CH / SH (BOXES -> BOX, ASHES -> ASH, MATCHES -> MATCH). 13const SIBILANT_STEM = /([SXZ]|[CS]H)$/; 14 15/** 16 * True when `word` looks like a regular -S inflection of a shorter real word. 17 * 18 * @param word Uppercase A–Z candidate. 19 * @param isWord Predicate that recognises real words of ANY length. 20 */ 21export function isInflectedSForm(word: string, isWord: (w: string) => boolean): boolean { 22 if (!word.endsWith('S')) return false; 23 // Regular plural / 3rd-person singular: drop the trailing S (ROOMS -> ROOM). 24 if (isWord(word.slice(0, -1))) return true; 25 // -ES inflection after a sibilant stem (BOXES -> BOX, BUSES -> BUS, ASHES -> ASH). 26 if (word.endsWith('ES')) { 27 const stem = word.slice(0, -2); 28 if (SIBILANT_STEM.test(stem) && isWord(stem)) return true; 29 // Y -> IES inflection (DRIES -> DRY, FLIES -> FLY, SKIES -> SKY). 30 if (word.endsWith('IES') && isWord(word.slice(0, -3) + 'Y')) return true; 31 } 32 return false; 33}