]> git.cworth.org Git - lmno-server/commitdiff
anagrams: Have the server auto deal up to 7 tiles to the center
authorCarl Worth <cworth@cworth.org>
Sun, 8 Mar 2026 15:25:49 +0000 (11:25 -0400)
committerCarl Worth <cworth@cworth.org>
Sun, 8 Mar 2026 15:25:49 +0000 (11:25 -0400)
Until there are a few tiles out on the board, it's silly to make the
players press the bag button. Once there are 7 or more it's reasonable
to have the game slow down (no more auto deal) and let players either
find anagrams from what's there, or else grab new tiles from the bag.

anagrams.js

index 868bb81e9d5e5aaa26d4118bbec24f2e74f923b1..ddfe846fba3de9cc5b539afaec7dfe87aab12394 100644 (file)
@@ -7,6 +7,7 @@ const CLAIM_TIMEOUT_MS = 60000;    /* 60 seconds to form a word */
 const CLAIM_WARNING_MS = 15000;    /* show timer for last 15 seconds */
 const VOTE_TIMEOUT_MS = 15000;     /* 15 seconds to vote */
 const REVEAL_COUNTDOWN_MS = 1500;  /* 1.5 seconds to reveal a tile */
+const MIN_CENTER_TILES = 7;       /* auto-deal to maintain this many */
 const MIN_WORD_LENGTH = 4;
 
 class Anagrams extends Game {
@@ -68,17 +69,11 @@ class Anagrams extends Game {
    * Letter management                                 *
    *****************************************************/
 
-  /* Deal a letter from bag to center with a countdown reveal. */
-  handle_deal_letter(request, response) {
-    const session_id = request.session.id;
-    if (!this.state.player_words[session_id]) {
-      response.sendStatus(400);
-      return;
-    }
-
+  /* Deal a single letter from bag to center with a countdown reveal.
+   * Returns true if a letter was dealt, false otherwise. */
+  _deal_one() {
     if (this.state.bag.length === 0 || this._revealing) {
-      response.json({ ok: false });
-      return;
+      return false;
     }
 
     const letter = this.state.bag.pop();
@@ -92,6 +87,7 @@ class Anagrams extends Game {
     this._reveal_timer = setTimeout(() => {
       this._revealing = false;
       this._reveal_timer = null;
+      this._auto_deal();
     }, REVEAL_COUNTDOWN_MS);
 
     this.broadcast_event_object("letter-reveal", {
@@ -104,7 +100,25 @@ class Anagrams extends Game {
       remaining: this.state.bag.length
     });
 
-    response.json({ ok: true });
+    return true;
+  }
+
+  /* Auto-deal if center has fewer than MIN_CENTER_TILES. */
+  _auto_deal() {
+    if (!this.state.started || this.state.finished) return;
+    if (this.state.center.length < MIN_CENTER_TILES) {
+      this._deal_one();
+    }
+  }
+
+  handle_deal_letter(request, response) {
+    const session_id = request.session.id;
+    if (!this.state.player_words[session_id]) {
+      response.sendStatus(400);
+      return;
+    }
+
+    response.json({ ok: this._deal_one() });
   }
 
   /*****************************************************
@@ -512,6 +526,9 @@ class Anagrams extends Game {
     if (this.state.claim_queue.length > 0) {
       this._activate_claimer();
     }
+
+    /* Replenish center if needed. */
+    this._auto_deal();
   }
 
   _compute_score(session_id) {
@@ -649,6 +666,7 @@ class Anagrams extends Game {
     }
 
     this.broadcast_event_object("game-started", {});
+    this._auto_deal();
     response.json({ ok: true });
   }