From 1bc4ac6b3b8a6987193fc2549752398e389e09cd Mon Sep 17 00:00:00 2001 From: PartMan Date: Sun, 18 Jan 2026 15:29:21 +0530 Subject: [PATCH 1/4] chore: Start Super Scrabble --- src/ps/games/scrabble/constants.ts | 1 + src/ps/games/scrabble/mods.ts | 41 ++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/ps/games/scrabble/constants.ts b/src/ps/games/scrabble/constants.ts index 364282da..3a2fb594 100644 --- a/src/ps/games/scrabble/constants.ts +++ b/src/ps/games/scrabble/constants.ts @@ -120,4 +120,5 @@ export enum ScrabbleMods { CLABBERS = 'clabbers', POKEMON = 'pokemon', CRAZYMONS = 'crazymons', + SUPER = 'super', } diff --git a/src/ps/games/scrabble/mods.ts b/src/ps/games/scrabble/mods.ts index 6745ecf0..b4acdb71 100644 --- a/src/ps/games/scrabble/mods.ts +++ b/src/ps/games/scrabble/mods.ts @@ -1,11 +1,11 @@ import { DICTIONARY, ScrabbleMods } from '@/ps/games/scrabble/constants'; import type { BaseModEntry } from '@/ps/games/mods'; -import type { LetterMetadata, WordScore } from '@/ps/games/scrabble/types'; +import type { BaseBoard as BaseBoardType, LetterMetadata, WordScore } from '@/ps/games/scrabble/types'; export const ScrabbleModData: Record< ScrabbleMods, - BaseModEntry & { dict: DICTIONARY; points?: LetterMetadata; counts?: LetterMetadata } + BaseModEntry & { dict: DICTIONARY; points?: LetterMetadata; counts?: LetterMetadata; board?: BaseBoardType } > = { [ScrabbleMods.CSW19]: { id: ScrabbleMods.CSW19, @@ -111,6 +111,43 @@ export const ScrabbleModData: Record< dict: DICTIONARY.CSW24, aliases: ['crazy'], }, + [ScrabbleMods.SUPER]: { + id: ScrabbleMods.SUPER, + name: 'Super Scrabble', + desc: 'Super Scrabble, with a super board! See https://en.wikipedia.org/wiki/Super_Scrabble', + dict: DICTIONARY.CSW24, + counts: { + A: 16, + B: 4, + C: 6, + D: 8, + E: 24, + F: 4, + G: 5, + H: 5, + I: 13, + J: 2, + K: 2, + L: 7, + M: 6, + N: 13, + O: 15, + P: 4, + Q: 2, + R: 13, + S: 10, + T: 15, + U: 7, + V: 3, + W: 4, + X: 2, + Y: 4, + Z: 2, + _: 4, + }, + board: [], + aliases: ['superscrabble'], + }, }; export const POKEMON_SCORING: WordScore = [2, 10]; From c49b9331850cd992ffe2cee9d4433e7f889c1ffd Mon Sep 17 00:00:00 2001 From: PartMan Date: Sun, 18 Jan 2026 15:39:39 +0530 Subject: [PATCH 2/4] chore: Add quadruple tile types --- src/ps/games/scrabble/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ps/games/scrabble/types.ts b/src/ps/games/scrabble/types.ts index 7cece132..d5a118a0 100644 --- a/src/ps/games/scrabble/types.ts +++ b/src/ps/games/scrabble/types.ts @@ -11,7 +11,7 @@ export type BoardTile = { type Letter = 'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z'|'_'; export type LetterMetadata = Record; -export type Bonus = '3W' | '2W' | '3L' | '2L' | '2*'; +export type Bonus = '4W' | '3W' | '2W' | '4L' | '3L' | '2L' | '2*'; export type BonusReducer = { apply: (score: number) => number; weight: number }; export type BaseBoard = (Bonus | null)[][]; From 8bfba9a6143921a1877d64d23ef6264e0970fa4c Mon Sep 17 00:00:00 2001 From: PartMan Date: Sun, 18 Jan 2026 15:48:39 +0530 Subject: [PATCH 3/4] chore: Add board --- src/ps/games/scrabble/mods.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/ps/games/scrabble/mods.ts b/src/ps/games/scrabble/mods.ts index b4acdb71..c7c69b4e 100644 --- a/src/ps/games/scrabble/mods.ts +++ b/src/ps/games/scrabble/mods.ts @@ -145,7 +145,29 @@ export const ScrabbleModData: Record< Z: 2, _: 4, }, - board: [], + board: [ + ['4W', null, null, '2L', null, null, null, '3W', null, null, '2L', null, null, '3W', null, null, null, '2L', null, null, '4W'], + [null, '2W', null, null, '3L', null, null, null, '2W', null, null, null, '2W', null, null, null, '3L', null, null, '2W', null], + [null, null, '2W', null, null, '4L', null, null, null, '2W', null, '2W', null, null, null, '4L', null, null, '2W', null, null], + ['2L', null, null, '3W', null, null, '2L', null, null, null, '3W', null, null, null, '2L', null, null, '3W', null, null, '2L'], + [null, '3L', null, null, '2W', null, null, null, '3L', null, null, null, '3L', null, null, null, '2W', null, null, '3L', null], + [null, null, '4L', null, null, '2W', null, null, null, '2L', null, '2L', null, null, null, '2W', null, null, '4L', null, null], + [null, null, null, '2L', null, null, '2W', null, null, null, '2L', null, null, null, '2W', null, null, '2L', null, null, null], + ['3W', null, null, null, null, null, null, '2W', null, null, null, null, null, '2W', null, null, null, null, null, null, '3W'], + [null, '2W', null, null, '3L', null, null, null, '3L', null, null, null, '3L', null, null, null, '3L', null, null, '2W', null], + [null, null, '2W', null, null, '2L', null, null, null, '2L', null, '2L', null, null, null, '2L', null, null, '2W', null, null], + ['2L', null, null, '3W', null, null, '2L', null, null, null, '2*', null, null, null, '2L', null, null, '3W', null, null, '2L'], + [null, null, '2W', null, null, '2L', null, null, null, '2L', null, '2L', null, null, null, '2L', null, null, '2W', null, null], + [null, '2W', null, null, '3L', null, null, null, '3L', null, null, null, '3L', null, null, null, '3L', null, null, '2W', null], + ['3W', null, null, null, null, null, null, '2W', null, null, null, null, null, '2W', null, null, null, null, null, null, '3W'], + [null, null, null, '2L', null, null, '2W', null, null, null, '2L', null, null, null, '2W', null, null, '2L', null, null, null], + [null, null, '4L', null, null, '2W', null, null, null, '2L', null, '2L', null, null, null, '2W', null, null, '4L', null, null], + [null, '3L', null, null, '2W', null, null, null, '3L', null, null, null, '3L', null, null, null, '2W', null, null, '3L', null], + ['2L', null, null, '3W', null, null, '2L', null, null, null, '3W', null, null, null, '2L', null, null, '3W', null, null, '2L'], + [null, null, '2W', null, null, '4L', null, null, null, '2W', null, '2W', null, null, null, '4L', null, null, '2W', null, null], + [null, '2W', null, null, '3L', null, null, null, '2W', null, null, null, '2W', null, null, null, '3L', null, null, '2W', null], + ['4W', null, null, '2L', null, null, null, '3W', null, null, '2L', null, null, '3W', null, null, null, '2L', null, null, '4W'], + ], aliases: ['superscrabble'], }, }; From a382d1d5ff3729f6c75d09d22d03a39480124d92 Mon Sep 17 00:00:00 2001 From: TanPat Date: Sun, 18 Jan 2026 16:30:47 +0530 Subject: [PATCH 4/4] Change board size on start of game based on mod --- src/ps/games/scrabble/index.ts | 4 ++-- src/ps/games/scrabble/render.tsx | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ps/games/scrabble/index.ts b/src/ps/games/scrabble/index.ts index d5b73a15..7263cd79 100644 --- a/src/ps/games/scrabble/index.ts +++ b/src/ps/games/scrabble/index.ts @@ -70,8 +70,8 @@ export class Scrabble extends BaseGame { if (!applyMons.success) throw new Error(applyMons.error); this.room.send(this.$T('GAME.SCRABBLE.AUTO_MOD_APPLIED', { id: this.id, mod: ScrabbleModData[defaultMod].name })); } - this.state.baseBoard = BaseBoard; - this.state.board = createGrid(BaseBoard.length, BaseBoard[0].length, () => null); + this.state.baseBoard = (this.mod ? ScrabbleModData[this.mod].board : null) ?? BaseBoard; + this.state.board = createGrid(this.state.baseBoard.length, this.state.baseBoard[0].length, () => null); this.state.bag = Object.entries((this.mod ? ScrabbleModData[this.mod].counts : null) ?? LETTER_COUNTS) .flatMap(([letter, count]) => letter.repeat(count).split('')) .shuffle(this.prng); diff --git a/src/ps/games/scrabble/render.tsx b/src/ps/games/scrabble/render.tsx index a3c9c35c..48ce7d0d 100644 --- a/src/ps/games/scrabble/render.tsx +++ b/src/ps/games/scrabble/render.tsx @@ -27,8 +27,7 @@ export function renderMove(logEntry: Log, game: Scrabble): [ReactElement, { name {words.length === 1 && !logEntry.ctx.points.bingo ? words[0][0] : words.map(([word, points]) => `${word} (${points})`).list(game.$T)}{' '} - for {pluralize(logEntry.ctx.points.total, 'point', 'points')}! - {logEntry.ctx.points.bingo ? ' BINGO!' : null} + for {pluralize(logEntry.ctx.points.total, 'point', 'points')}!{logEntry.ctx.points.bingo ? ' BINGO!' : null} , opts, ]; @@ -79,6 +78,10 @@ function getBackgroundHex(bonus: Bonus | null): string { return '#e65'; case '3L': return '#49a'; + case '4W': + return '#a12'; + case '4L': + return '#14a'; default: return '#cca'; }