1. 23 Jun, 2026 4 commits
    • Mahmoud Aglan's avatar
      test: add chess sync verification test with move+resign proof · 2f9d7d84
      Mahmoud Aglan authored
      Screenshots confirm: moves sync to opponent board, resign shows
      victory screen. Both directions verified via Puppeteer + API.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2f9d7d84
    • Mahmoud Aglan's avatar
      fix: chess moves/resign silently failing — non-existent columns · b3109e7a
      Mahmoud Aglan authored
      The `matches` table has no `last_activity` or `ended_at` columns.
      PostgREST rejects the entire PATCH when ANY column doesn't exist,
      causing every move update and resignation to silently fail.
      
      - Remove `last_activity` from handleGameMove (column doesn't exist)
      - Change `ended_at` to `completed_at` in handleResign, handleDraw,
        handleComplete (correct column name per DB schema)
      
      This was the root cause of zero sync in multiplayer chess.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      b3109e7a
    • Mahmoud Aglan's avatar
      fix: bulletproof matchmaking queue across all games · 1c145579
      Mahmoud Aglan authored
      - Add dequeue handler to backgammon-match.php (was missing)
      - Add 90-second stale entry cleanup to ludo/domino/backgammon queues
      - Add atomic opponent claiming (conditional update) to prevent race conditions
      - Fix client queue.js to route dequeue to correct game endpoint
      - Register unmountQueue for proper cleanup when exiting search screen
      - Remove json_encode on jsonb fields in backgammon (prevent double-encoding)
      
      Fixes: self-matching, ghost queue entries, and race condition where two
      players simultaneously claim the same opponent.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      1c145579
    • Mahmoud Aglan's avatar
      fix: eliminate jsonb double-encoding that broke multiplayer sync · 6517bd2d
      Mahmoud Aglan authored
      The root cause: PHP's json_encode() was used on jsonb fields before
      passing to SupabaseClient->insert/update, which json_encodes the entire
      payload. This double-encoded game_state into a JSON string scalar.
      
      When the match_heartbeat RPC did `jsonb_string || jsonb_object`,
      PostgreSQL created an array instead of merging, corrupting game_state.
      The polling logic then couldn't find move_count or last_move in the
      array, so moves never synced between players.
      
      Fix: pass PHP arrays directly for all jsonb columns (game_state, moves,
      positions, scores, winners, hands, boneyard). The Supabase client
      handles encoding once at the HTTP layer.
      
      Also: when reading game_state back from the DB, handle the case where
      PostgREST returns it as a decoded array/object (not a string) since
      jsonb columns are deserialized automatically.
      
      Affected: chess, ludo, domino — all multiplayer match creation and
      move/state updates.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      6517bd2d
  2. 22 Jun, 2026 1 commit
  3. 21 Jun, 2026 4 commits
  4. 20 Jun, 2026 8 commits
  5. 19 Jun, 2026 17 commits
    • Mahmoud Aglan's avatar
      24810eaf
    • Mahmoud Aglan's avatar
      fix: getPipCount used non-existent VARIANTS.standard key · 1050fd15
      Mahmoud Aglan authored
      The VARIANTS object has keys 'sheshbesh', 'mahbousa', 'thirtyone' but
      getPipCount referenced 'standard' which is undefined, causing
      'Cannot read properties of undefined (reading normPos)' and preventing
      the entire board from rendering.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      1050fd15
    • Mahmoud Aglan's avatar
      fix: redesign backgammon game UI with real player data + polished visuals · c5374e12
      Mahmoud Aglan authored
      - Player cards now use store player data (avatar_url, display_name, level)
      - Opponent shows bot icon or opponent data for multiplayer
      - Active turn highlight on player cards with green glow border
      - Cube value display in match info area
      - Professional dark gradient background with proper hierarchy
      - Controls bar with proper spacing and button styling
      - Doubling offer dialog with backdrop blur and better layout
      - Turn badge repositioned to top-center with pill shape
      - Emote panel centered with backdrop blur
      - All interactive elements have proper touch targets (40px+)
      - Safe area inset for bottom bar
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      c5374e12
    • Mahmoud Aglan's avatar
      fix: backgammon gameplay — working buttons, correct canvas rendering, no DPR bugs · 873b7000
      Mahmoud Aglan authored
      - Remove DPR ctx.scale() that compounded every frame and broke all rendering
      - Use logical pixel dimensions directly (canvas.width = logical size)
      - Fix isSel/isValid closures that caused undefined reference errors in checker glow
      - Simplify game scene: roll button is now a normal element in .bgg-controls (not overlay)
      - Event handlers correctly scale click coords via rect ratio
      - Remove unused getCheckerScreenPos import from move-animator
      - All buttons (roll, double, emote, quit) bind via addEventListener properly
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      873b7000
    • Mahmoud Aglan's avatar
      feat: full backgammon overhaul — 60fps game loop, premium canvas, particles, admin branding · 4cf9baa5
      Mahmoud Aglan authored
      - 60fps requestAnimationFrame game loop with dt-based particle physics
      - 3D checkers with radial gradients, specular highlights, drop shadows
      - Wood-grain board texture with gradient triangles and bevel frame
      - Physics-based dice with bounce damping, spin, and staggered animation
      - Arc-based move animations with easeOutBack overshoot
      - Particle burst on hit (red/orange sparks) and bear-off (green stars)
      - Confetti celebration on match win with canvas animation
      - Full multiplayer sync via match-session + server polling
      - Bot AI with animated moves (arc + SFX per piece)
      - Admin branding: 14 board colors + 7 game settings (durations, particles)
      - CSS tokens for all backgammon board colors (--bg-*)
      - Theme.js maps branding values to CSS vars + window.__EL3AB_THEME
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      4cf9baa5
    • Mahmoud Aglan's avatar
    • Mahmoud Aglan's avatar
      feat: rename backgammon variants to Arabic — شيش بيش، محبوسة، ٣١ · cb1bc9b7
      Mahmoud Aglan authored
      - sheshbesh (شيش بيش): standard backgammon with hitting
      - mahbousa (محبوسة): tapa-style, land on opponent to trap (no hitting)
      - thirtyone (٣١): gul-bara race variant, all pieces start stacked
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      cb1bc9b7
    • Mahmoud Aglan's avatar
      feat: implement full backgammon game — rules engine, bot AI, canvas renderer, multiplayer · 6d2431c7
      Mahmoud Aglan authored
      - Port backgammonjs-master rules to ES modules (standard, gul bara, tapa variants)
      - 3-tier bot AI (easy/medium/hard) with positional evaluation
      - Doubling cube with Crawford rule for match play
      - Canvas board renderer with piece stacking, hit/bear-off animations
      - Room scene with variant/length/difficulty selection
      - Full multiplayer via backgammon-match.php (queue, move, heartbeat, leave)
      - Realtime subscription for backgammon_matches table
      - Emote panel + phrase system (reuses Ludo pattern)
      - 7 new SFX slots in branding admin (dice, move, hit, bear, double, win)
      - Match system (first-to-N, gammon/backgammon scoring multipliers)
      - Wired into engine.js, play table, queue routing, match-session recovery
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      6d2431c7
    • Mahmoud Aglan's avatar
      feat: Ludo full overhaul — multiplayer modes, social, SFX · e4824004
      Mahmoud Aglan authored
      Phase 1 — Room/Mode Picker:
      - New ludo-room scene with menu, setup, and searching views
      - Player count picker (2/3/4 players)
      - Bot/human distribution selector (1 human + N bots, 2 humans + N bots, etc)
      - Bot difficulty picker (easy/medium/hard)
      - Seat preview showing diagonal (2P) or skip-corner (3P) positioning
      - Play table routes Ludo single/multi to the new room
      
      Phase 2 — Social Features:
      - Emote button (😄) in dice area opens full panel
      - 8 emoji reactions + 6 preset Arabic phrases
      - Emotes animate FROM the sender's player panel (speech bubble or floating emoji)
      - Bot emotes on captures use the new bubble system
      - Live mode emote transmission via mp.sendEmote
      - 3-second cooldown between sends
      
      Phase 3 — SFX Completion:
      - sfx_dice_shake: during dice animation roll
      - sfx_boost: rolling a 6 (extra turn excitement)
      - sfx_piece_home: piece reaches center
      - sfx_turn_start: your turn notification in live mode
      - sfx_emote: sending/receiving social actions
      - All new slots added to branding.php admin
      - Synthesized fallbacks in audio.js for each new sound
      
      Phase 4 — Multiplayer & Seat Mapping:
      - rules.createGame accepts seats array for board-slot mapping
      - 2-player = diagonal (Red vs Yellow), 3-player = skip Yellow
      - boardSlot property on each player drives position/color/captures
      - getPiecePosition/getHomeBasePosition use boardSlot not player index
      - Game-over condition: numPlayers-1 finishers (not hardcoded 3)
      - local-multi mode: multiple humans share one device, bots fill rest
      - Turn rotation correctly skips only finished players
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      e4824004
    • Mahmoud Aglan's avatar
      fix: domino tile placement — pip orientation + corner gaps + sizing · 512110c0
      Mahmoud Aglan authored
      - Add flipPips flag: when chain goes LEFT or UP, tile.left/right are
        drawn on the correct screen side (previously always left=left/top)
      - Fix corner turn offset: uses actual tile cross-axis extent instead
        of fixed TILE_H, preventing overlaps/gaps at corners
      - Increase TILE_W from 24→26 for better proportions (less squished)
      - Increase GAP slightly (1→2) so tiles don't visually merge
      - Lower auto-zoom min to 0.3 for large chains
      - Fix invalid hand tiles: use saturate(0.3)+brightness(0.85) instead
        of opacity+brightness that made them look solid dark gray
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      512110c0
    • Mahmoud Aglan's avatar
      feat: domino gameplay UI overhaul + fix animation origin · 38adbafe
      Mahmoud Aglan authored
      - Add fromPlayer param to animatePlacement (top for opponent, bottom for me)
      - Rewrite buildLayout with semantic .dg-* class structure
      - Full CSS for opponent bar, score ribbon, controls, board area
      - Opponent back-tiles visual with removal animations
      - Bot thinking indicator in opponent meta area
      - Remove dead legacy DOM elements
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      38adbafe
    • Mahmoud Aglan's avatar
    • Mahmoud Aglan's avatar
      feat: redesign domino UX — premium hand tiles, smart auto-fit, cohesive screens · 31a8e2dc
      Mahmoud Aglan authored
      Hand tiles (components/hand.js):
      - Proper PIP_POSITIONS matching board tiles (position-based, not flex-wrap)
      - Dynamic sizing: tiles scale to always fit viewport width
      - Fan layout for 5+ tiles (card-like spread with arc lift)
      - Slide-in animation for newly drawn tiles
      - Premium domino look: gradient bg, 3D pips, edge shine, realistic border
      
      Board (canvas/board.js):
      - Smooth animated auto-pan + auto-zoom when chain exceeds viewport
      - Lerp-based transitions (no jarring jumps on new tiles)
      - Vignette overlay for depth
      - Manual pan updates target state for smooth resume
      
      Tile renderer (canvas/tile-renderer.js):
      - Gradient fill (cream to warm), thicker border, top-edge shine
      - 3D pips with specular highlights
      - Better shadow depth and double-tile accent
      
      Drag proxy (components/drag.js):
      - Matches hand tile visual style (position-based pips)
      - Valid/invalid state with colored borders + glow
      - Spring animation on snap/bounce-back
      
      Room screens (scenes/room.js):
      - Unified design language across menu/bot-picker/target-picker/lobby
      - Floating icon animation, consistent card styles
      - Touch-responsive buttons with spring scale
      
      Game layout (scenes/game.js):
      - Polished opponent bar with avatar border glow
      - Score bar with colored indicators
      - Control buttons with active states and pulse animation
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      31a8e2dc
    • Mahmoud Aglan's avatar
      feat: add Ludo pawn sprites, sound effects & 25 emoji slots to branding · 9964877a
      Mahmoud Aglan authored
      - Add 4 Ludo pawn sprite upload slots (red/green/yellow/blue) to admin branding
      - Add 15 sound effect upload slots (mp3/ogg/wav) with audio preview
      - Add 25 missing emoji slots (crown, mute, block, hourglass, etc.)
      - Ludo game.js: draw custom pawn sprites with same bounce/highlight animation
      - Ludo game.js: pawn colors now respect branding ludo_red/green/yellow/blue
      - audio.js: plays custom audio files if uploaded, falls back to synthesized sounds
      - branding.php: support audio MIME types for Supabase storage upload
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      9964877a
    • Mahmoud Aglan's avatar
      feat: replace all system popups with 60fps in-game modals · d84fed77
      Mahmoud Aglan authored
      - Create core/modal.js — GPU-composited confirm/alert system with
        spring animations (scale + opacity on transform layer only)
      - Replace all 7 native confirm() calls across chess resign, ludo exit,
        domino resign, block user, remove friend, remove group member, leave group
      - Each modal has contextual icon, Arabic text, danger styling for destructive actions
      - Add will-change + backface-visibility GPU hints to all interactive elements
      - Add ease-in, ease-in-out timing tokens for complete animation coverage
      - All animations use transform + opacity only (never layout-triggering properties)
        ensuring consistent 60fps on mobile Safari and Chrome
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      d84fed77
    • Mahmoud Aglan's avatar
      feat: cascade 5 global multiplayer systems to all game endpoints · 00bcf1a0
      Mahmoud Aglan authored
      - domino-match.php: add can_player_queue anti-abuse, last_activity tracking,
        server-side turn timeout (30s), universal complete_match rewards,
        heartbeat + leave handlers
      - game.php (chess): add heartbeat + leave handlers, last_activity on moves,
        replace homebrew auto-close with server turn timeout (120s),
        replace inline reward logic with universal complete_match RPC
      - matchmaking.php: add can_player_queue cooldown check before queuing
      - ludo.php (old API): add last_activity on moves, complete_match on end
      - match-session.js: change ping from move-based to heartbeat action,
        handle 'abandoned' status in poll response
      - match-ui.js: add showBotReplacement and showTurnTimedOut overlays
      - engine.js: add domino endpoint mapping for match recovery
      - domino/game.js: add heartbeat (10s interval), handle _turn_timed_out,
        update endMatch to send winners array to universal rewards
      - domino/result.js: remove duplicate complete call for live games,
        use new winners-array format for bot games
      - ludo/result.js: add rewards display (coins, XP, rating change)
      - Move shared supabaseRpc helper to includes/supabase.php
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      00bcf1a0
    • Mahmoud Aglan's avatar
      feat: implement 5 global multiplayer systems (DB + PHP + client) · 2ce274f3
      Mahmoud Aglan authored
      ## System 1: Match Lifecycle Manager
      - DB function `cleanup_stale_matches()` auto-abandons zombie matches
        (waiting >5min, in_progress >30min) across all games
      - Cleaned 109 existing zombies (12 ludo, 36 domino, 61 chess)
      - New `match-cleanup.php` endpoint to trigger periodically
      
      ## System 2: Universal Match Completion + Rewards
      - DB function `complete_match(game_key, match_id, winners, reason)`
        awards coins/XP, updates stats, tracks ratings for ANY game
      - Ludo now calls `action: 'complete'` on game end with ordered winners
      - Uses `reward_config` table (ludo_win_coins=40, 2nd=20, 3rd=10, 4th=5)
      - Tracks `abandon_count` on profiles for anti-abuse
      
      ## System 3: Server-Side Turn Timeout
      - Added `last_activity` column + index on ludo/domino matches
      - DB function `enforce_turn_timeout()` checked on every GET poll
      - After 20s of inactivity: marks turn as timed out
      - After 3 consecutive timeouts: flags for permanent bot replacement
      - Client handles `_turn_timed_out` response from server
      
      ## System 4: Connection State Protocol
      - DB function `match_heartbeat(game_key, match_id, player_id)`
      - Tracks per-player last_ping in game_state.connections
      - Returns other players' status: online/weak/disconnected/abandoned
      - Client sends heartbeat every 10s during live matches
      - Works across chess, ludo, domino
      
      ## System 5: Anti-Abuse + RLS Hardening
      - RLS: ludo/domino UPDATE now requires player to be participant
      - Unique index prevents duplicate queue entries per user
      - DB function `can_player_queue()` enforces 5-min cooldown after
        3+ abandons in 24h (resets daily)
      - `handleLudoLeave` now tracks bot replacement as reversible (30s grace)
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2ce274f3
  6. 17 Jun, 2026 6 commits
    • Mahmoud Aglan's avatar
      fix: escalating six-boost prevents stuck-at-home frustration · 2210bb63
      Mahmoud Aglan authored
      Track rollsWithoutSix per player. Each consecutive failed roll when
      all pieces are home ramps the six probability harder — by roll 3-4
      a human player has ~40-45% chance of six (vs 17% base). No more
      watching bots play while stuck for 6+ turns.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2210bb63
    • Mahmoud Aglan's avatar
      feat: rework Ludo dice for fun tension — human luck + rubber-banding · 929a1434
      Mahmoud Aglan authored
      The dice system now creates satisfying back-and-forth gameplay:
      
      - Human players get a subtle persistent luck edge over bots (slight
        boost to 5s and 6s) — feels lucky without being obvious
      - Rubber-band: whoever is behind gets help catching up; humans get
        an extra comeback boost when far behind the leader
      - Momentum damper: bots that pull too far ahead get cooled down
      - Stuck rescue: all-at-home gets aggressive six boost (stronger for
        humans)
      - Finishing push after 8 min ensures games wrap under 15 min
      - Removed all capture-biased dice logic — captures now happen purely
        by board position, not rigged dice
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      929a1434
    • Mahmoud Aglan's avatar
      fix: reduce capture frequency and add time-decay for fairer Ludo · ee53cfbf
      Mahmoud Aglan authored
      - Halved near-capture dice boost (0.3 → 0.15) and reduced per-die
        capture bonus (0.15 → 0.08)
      - Capture bias decays to zero as game approaches 15 min (captureMul
        factor), making late-game rolls essentially fair/random
      - Removed the multi-capture boost that added +0.2 to all dice 1-5
      - Increased six-boost after 8 min (scales up to +0.8 by 15 min) to
        accelerate finishing and keep games under ~15 minutes
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      ee53cfbf
    • Mahmoud Aglan's avatar
      feat: bigger stacked pawns + 15s turn timer with auto-play · a2876e3e
      Mahmoud Aglan authored
      - Increased stacked pawn scale (2 pawns: 0.82, 3+: 0.7) so they stay
        visible when sharing a cell
      - Added 15-second turn timer bar above the dice area
      - Timer counts down visually (green→yellow→red gradient)
      - If player doesn't roll in time, auto-rolls for them
      - If player doesn't pick a piece in time, bot logic picks the best move
      - Timer works in both single-player and multiplayer modes
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      a2876e3e
    • Mahmoud Aglan's avatar
      revert: restore original flat board and simple pawn visuals · 8c14559d
      Mahmoud Aglan authored
      Remove all 10 fancy visual enhancements (3D gradients, embossed borders,
      glowing safe squares, specular pawns) — back to the clean flat style.
      Keep 60fps render loop, smooth tweens, stacking, and mini dice.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      8c14559d
    • Mahmoud Aglan's avatar
      feat: ludo — 60fps render loop with offscreen board cache + smooth tween animations · 4f6e3507
      Mahmoud Aglan authored
      - Offscreen canvas caches static board (drawn once, reused every frame)
      - Continuous requestAnimationFrame loop renders pieces at 60fps
      - Piece movement uses smooth parabolic arc tweens (no setTimeout stepping)
      - Enter-from-home uses easeOutBounce for natural pop-in feel
      - All drawBoard() calls now just mark board dirty — next frame picks it up
      - Move preview ghosts pulse smoothly using sin wave
      - Ambient corner glow rendered per-frame (lightweight, no cache needed)
      - Render loop auto-stops on game exit/end for zero resource leak
      - Bot step animation also uses smooth tween system
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      4f6e3507