]> git.cworth.org Git - lmno-server/commitdiff
Extract shared tile distribution and bag logic into tiles.js
authorCarl Worth <cworth@cworth.org>
Sun, 8 Mar 2026 00:03:57 +0000 (19:03 -0500)
committerCarl Worth <cworth@cworth.org>
Sun, 8 Mar 2026 00:03:57 +0000 (19:03 -0500)
Letter Rip now imports from the shared module instead of defining
its own tile distribution and make_bag(). This prepares for the
Anagrams game which will reuse the same tile bag (without blanks).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
letterrip.js
templates/letterrip-game.html
tiles.js [new file with mode: 0644]

index e90a165744679de20c1b5b29dfedb96f999bca85..f717aa6d51e86dc2af518162b78a8a5f1fd60e12 100644 (file)
@@ -1,29 +1,7 @@
 const express = require("express");
 const Game = require("./game.js");
 const TWL_WORDS = new Set(require("./twl-words.js"));
-
-/* Tile distribution (98 tiles + 2 blanks = 100).
- * Letter counts: A9 B2 C2 D4 E12 F2 G3 H2 I9 J1 K1 L4 M2
- *                N6 O8 P2 Q1 R6 S4 T6 U4 V2 W2 X1 Y2 Z1
- */
-const TILE_DISTRIBUTION =
-  "AAAAAAAAA" +
-  "BB" + "CC" + "DDDD" +
-  "EEEEEEEEEEEE" +
-  "FF" + "GGG" + "HH" +
-  "IIIIIIIII" +
-  "J" + "K" +
-  "LLLL" + "MM" +
-  "NNNNNN" +
-  "OOOOOOOO" +
-  "PP" + "Q" +
-  "RRRRRR" +
-  "SSSS" +
-  "TTTTTT" +
-  "UUUU" +
-  "VV" + "WW" +
-  "X" + "YY" + "Z" +
-  "__";
+const { make_bag } = require("./tiles.js");
 
 const INITIAL_TILES = 7;
 
@@ -31,7 +9,7 @@ class LetterRip extends Game {
   constructor(id) {
     super(id);
     this.state = {
-      bag: LetterRip.make_bag(),
+      bag: make_bag(),
       player_tiles: {},
       player_boards: {},
       results: null,
@@ -40,16 +18,6 @@ class LetterRip extends Game {
     };
   }
 
-  static make_bag() {
-    const tiles = TILE_DISTRIBUTION.split("");
-    /* Fisher-Yates shuffle */
-    for (let i = tiles.length - 1; i > 0; i--) {
-      const j = Math.floor(Math.random() * (i + 1));
-      [tiles[i], tiles[j]] = [tiles[j], tiles[i]];
-    }
-    return tiles;
-  }
-
   /* Deal count_per_player tiles to each active player.
    * Returns true on success, false if not enough tiles. */
   deal(count_per_player) {
index acd1cb59e75aa36a31fedc204949b7f58b619dfb..21422b51b85db87c4f40771bb98e82a0ec9763dc 100644 (file)
@@ -1,6 +1,7 @@
 {% extends "base.html" %}
 
 {% block head %}
+<link rel="stylesheet" href="/tiles.css" type="text/css" />
 <link rel="stylesheet" href="/letterrip/letterrip.css" type="text/css" />
 
 <script src="/react.js"></script>
diff --git a/tiles.js b/tiles.js
new file mode 100644 (file)
index 0000000..b820596
--- /dev/null
+++ b/tiles.js
@@ -0,0 +1,43 @@
+/* Shared tile distribution and bag logic for letter-based games.
+ *
+ * Standard distribution (98 tiles + 2 blanks = 100):
+ *   A9 B2 C2 D4 E12 F2 G3 H2 I9 J1 K1 L4 M2
+ *   N6 O8 P2 Q1 R6 S4 T6 U4 V2 W2 X1 Y2 Z1  __
+ */
+
+const TILE_DISTRIBUTION =
+  "AAAAAAAAA" +
+  "BB" + "CC" + "DDDD" +
+  "EEEEEEEEEEEE" +
+  "FF" + "GGG" + "HH" +
+  "IIIIIIIII" +
+  "J" + "K" +
+  "LLLL" + "MM" +
+  "NNNNNN" +
+  "OOOOOOOO" +
+  "PP" + "Q" +
+  "RRRRRR" +
+  "SSSS" +
+  "TTTTTT" +
+  "UUUU" +
+  "VV" + "WW" +
+  "X" + "YY" + "Z" +
+  "__";
+
+/* Letters only (no blanks). */
+const TILE_DISTRIBUTION_NO_BLANKS = TILE_DISTRIBUTION.replace(/_/g, "");
+
+/* Create a shuffled bag of tiles. */
+function make_bag(distribution) {
+  const tiles = (distribution || TILE_DISTRIBUTION).split("");
+  /* Fisher-Yates shuffle */
+  for (let i = tiles.length - 1; i > 0; i--) {
+    const j = Math.floor(Math.random() * (i + 1));
+    [tiles[i], tiles[j]] = [tiles[j], tiles[i]];
+  }
+  return tiles;
+}
+
+exports.TILE_DISTRIBUTION = TILE_DISTRIBUTION;
+exports.TILE_DISTRIBUTION_NO_BLANKS = TILE_DISTRIBUTION_NO_BLANKS;
+exports.make_bag = make_bag;