CASE STUDY: #P004 25 MIN READ

The Engineering Odyssey of Midnight Poker: Building a Pro-Level Engine

Building "just another poker game" was never the plan. We set out to create Midnight Poker—a rational, high-stakes simulator that challenges human intuition with mathematical precision. This is the raw story of the bugs, the math, and the ultimate triumph.

Monte Carlo (MCTS) Sklansky-Chubukov TypeScript Web Audio Synthesis Glassmorphism UI Pot Odds Logic
Midnight Poker - Table View

The Dream: Beyond Randomness

Most online browser games are built to entertain for three minutes. They use simple logic: "If I have a pair, I bet." But Texas Hold'em is a game of information asymmetry and expected value (EV). To make a game that humans would respect, the AI had to be rational.

We wanted a game where a "Casual" bot plays like a drunk vacationer in Vegas, while a "Pro" bot plays like a sharp-eyed professional in a Macao private room. Achieving this meant building a custom probability engine from the ground up.

Phase 1: The AI Brain Trust

The Monte Carlo Simulation (MCTS)

The core of our PRO difficulty is the Monte Carlo Simulator. When a player bets $500 on the Turn, the AI doesn't just look at its two cards. It pauses and "simulates" 500 different futures.

It randomly assigns cards to its opponents from the remaining deck and deals out the River card. By repeating this process 500 times, the AI arrives at its Equity—the true mathematical probability of winning the pot. It then compares this to the Pot Odds (the risk/reward ratio of the current bet).

// The core simulation loop
public calculateEquity(holeCards: Card[], community: Card[], opponentCount: number): number {
    let wins = 0;
    for (let i = 0; i < 500; i++) {
        const deck = this.getFreshShuffledDeck(holeCards, community);
        const simBoard = [...community];
        // Deal remaining board cards
        while (simBoard.length < 5) simBoard.push(deck.pop()!);
        
        // Check if AI hands wins against N random opponents
        if (this.isWinningHand(holeCards, simBoard, opponentCount, deck)) {
            wins++;
        }
    }
    return wins / 500; // Returns probability (0.0 to 1.0)
}

Sklansky-Chubukov Pre-Flop Logic

Before any cards are even on the table, the AI uses a modified version of the Sklansky-Chubukov ranking system. This isn't just a list of "good hands"; it's a dynamic scoring system that considers Position (the Dealer bonus) and Tightness. A Pro bot won't even look at 7-2 offsuit; it's a mathematical death sentence.

Phase 2: The Trench Wars (Development Post-Mortem)

Every great product is built on the graves of a thousand bugs. During the final 48 hours of development, we hit three "critical path" issues that nearly derailed the launch.

Incident #001: The Negative Stack Paradox
The Problem: When a player went "All-in" with $340 against a $500 bet, the engine was deducting the full $500. This resulted in the player having a -160 stack. In a casino, this would be a riot; in a browser game, it was a logical deadlock.
The Fix: We implemented a clamp mechanism in the processAction method. Now, a bet can never exceed the player's currentStack + currentBet. We also added a "refill" logic where bankrupt bots are automatically topped up to $1000 at the start of a new hand to keep the game flowing.
Incident #002: Header Layout Clipping
The Problem: On narrow screens or when adding the "Home" button, the top-right header buttons (Difficulty, Rules, Sound) would stack vertically, overlapping the Poker table and making the game unplayable.
The Fix: We refactored the .header-actions CSS to use display: flex with a fixed height: 40px and align-items: center. By using a horizontal gap and semi-transparent glassmorphism backgrounds, we ensured all utility buttons remained accessible without ever obstructing the board.
Incident #003: The Iframe Prison
The Problem: When users clicked the "Home" (EXIT) button, the browser would refresh *inside* the iframe/modal, but the main website remained stuck on the game screen. Users felt "trapped."
The Fix: Redirection logic was upgraded from window.location to window.top.location.href. This breaks the iframe context and returns the user to the main site hub. We also implemented a Custom Exit Modal instead of the browser's ugly native `confirm()` to maintain the premium visual style.
"A bug isn't a failure—it's a requirement for a better architecture. We didn't just fix the 'negative stack'; we built a robust state-validation layer."

Phase 3: The "Midnight" Aesthetic

The visual soul of Midnight Poker is built on Nocturnal Elegance. We avoided bright, neon casino lights in favor of deep indigo shadows and high-contrast gold accents.

  • 1. Pure Glassmorphism

    Every UI element uses backdrop-filter: blur(12px). This allows the subtle movements of the poker table to be seen through the action buttons, creating a sense of depth and realism often missing in web games.

  • 2. Performance-First Sound

    We didn't just play MP3 files. We used the Web Audio API to synthesize card "swishes" and terminal-like beep tones. This results in zero latency and a significantly smaller file size for users on mobile connections.

Coda: Building with the Future

The most groundbreaking part of Midnight Poker isn't the code—it's how it was written. This game was developed in a "Pair Programming" session between a human lead and the Antigravity AI Agent (powered by Google Gemini).

Antigravity didn't just write functions; it navigated the file system, suggested UI layouts, and performed "autonomous debugging." When we described the "vibe" of a high-end lounge, the agent translated that intent into 400 lines of highly optimized CSS. This Intent-to-Production workflow reduced the development cycle from weeks to mere days.

5,200+ Lines of Custom TS
0.02ms Logic Latency
48h Total Dev Time
Replayability

READY FOR THE RIVER?

Experience the culmination of our engineering journey. Challenge the Pro AI and see if you have the math to survive the Midnight Table.

PLAY MIDNIGHT POKER