### index.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Card Bluff & Shoot - Multiplayer</title>
    <link rel="stylesheet" href="style.css">
    <style>
        /* Basic styling for visibility */
        .selected {
            border: 2px solid blue;
        }
        .player {
            margin: 5px 0;
        }
        .active {
            background-color: #e0ffe0;
        }
        .eliminated {
            text-decoration: line-through;
            color: gray;
        }
        .card {
            display: inline-block;
            width: 50px;
            height: 70px;
            border: 1px solid #000;
            border-radius: 5px;
            margin: 5px;
            text-align: center;
            line-height: 70px;
            font-size: 1.2em;
            cursor: pointer;
        }
        .back {
            background-color: #333;
            color: #333;
        }
        .hearts, .diamonds {
            color: red;
        }
        .spades, .clubs {
            color: black;
        }
        .overlay-content {
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 20px;
            border-radius: 10px;
            text-align: center;
        }
        .overlay-button {
            padding: 10px 20px;
            margin-top: 15px;
            font-size: 1em;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- Waiting Room Section -->
        <div id="waitingRoom" class="section">
            <h3>Room: <span id="roomDisplay">ABC123</span></h3>
            <div id="playersList">
                <h4>Players in room:</h4>
                <!-- List of players will be appended here -->
            </div>
            <button id="startGameBtn" style="display: none;">Start Game</button>
            <button id="resetRoomBtn" style="display: none; margin-top: 10px;">Reset Room</button>
        </div>

        <!-- Game Section -->
        <div id="gameSection" class="game-container" style="display: none;">
            <div class="top-section" id="players"></div>

            <div class="middle-section">
                <div class="game-info">
                    <strong>Core Card:</strong> <span id="coreCard">-</span>
                </div>
                <div class="game-info">
                    <strong>Last Played:</strong> <span id="lastPlayed">None</span>
                </div>
                <!-- Central Card Table -->
                <div class="central-table" id="centralTable"></div>
            </div>

            <div class="bottom-section">
                <div class="player-hand" id="currentHand"></div>
                <div class="actions">
                    <button id="playButton" onclick="playSelectedCards()">Play Selected Cards</button>
                    <button id="callBluffButton" onclick="callBluff()" style="background: #f44336">Call Bluff</button>
                </div>
            </div>

            <!-- Overlay for Bluff Result -->
            <div class="overlay" id="resultOverlay" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; 
                 background: rgba(0,0,0,0.5); align-items: center; justify-content: center;">
                <div class="overlay-content">
                    <h2 id="overlayTitle">Result</h2>
                    <p id="overlayMessage"></p>
                    <button id="overlayButton" class="overlay-button" onclick="handleOverlayAction()">Shoot</button>
                </div>
            </div>
        </div>

        <!-- Game Over Overlay -->
        <div class="shooting-overlay" id="gameOverOverlay" style="display: none;">
            <div class="overlay-content">
                <h2>Game Over!</h2>
                <p id="gameOverText"></p>
                <button onclick="resetToLobby()" class="overlay-button">Return to Lobby</button>
            </div>
        </div>
    </div>

    <script>
        let ws;
        let username;
        const roomId = 'ABC123'; // Predefined room ID
        let isCreator = false;
        let userHand = [];
        let gameState = null;
        let isWaitingForShot = false; // Flag to prevent multiple shots

        // Utility function to generate random username
        function generateRandomUsername() {
            const adjectives = ['Swift', 'Silent', 'Mighty', 'Brave', 'Clever', 'Nimble', 'Fierce', 'Sly', 'Bold', 'Wise'];
            const nouns = ['Lion', 'Tiger', 'Eagle', 'Shark', 'Wolf', 'Panther', 'Dragon', 'Falcon', 'Leopard', 'Cobra'];
            const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
            const noun = nouns[Math.floor(Math.random() * nouns.length)];
            const number = Math.floor(Math.random() * 1000);
            return `${adj}${noun}${number}`;
        }

        // Connect to WebSocket server
        function connectWebSocket() {
            ws = new WebSocket('ws://localhost:3000'); // Ensure this URL matches your server's address and port

            ws.onopen = () => {
                console.log('Connected to server');
                // Assign random username
                username = generateRandomUsername();
                // Send JOIN_ROOM message
                ws.send(JSON.stringify({
                    type: 'JOIN_ROOM',
                    username: username,
                    roomId: roomId
                }));
            };

            ws.onmessage = (event) => {
                const data = JSON.parse(event.data);
                handleWebSocketMessage(data);
            };

            ws.onclose = () => {
                console.log('Disconnected from server');
                alert('Disconnected from server');
                resetToLobby();
            };
        }

        // Handle WebSocket messages
        function handleWebSocketMessage(data) {
            switch(data.type) {
                case 'PLAYER_JOINED':
                    updatePlayersList(data.players, data.creator);
                    break;
                case 'PLAYER_LEFT':
                    updatePlayersList(data.players, null); // Creator remains unchanged
                    break;
                case 'NEW_CREATOR':
                    isCreator = false;
                    alert(`New room creator is: ${data.newCreator}`);
                    updateStartButton(); // Update button visibility
                    break;
                case 'CREATOR':
                    isCreator = data.isCreator;
                    updateStartButton();
                    break;
                case 'GAME_STARTED':
                    gameState = data.gameState;
                    userHand = data.hand || [];
                    startGameUI(data.gameState);
                    break;
                case 'GAME_UPDATE':
                    gameState = data.gameState;
                    if (data.gameState.hand) {
                        userHand = data.gameState.hand;
                    }
                    updateGameUI();
                    break;
                case 'BLUFF_RESULT':
                    handleBluffResult(data);
                    break;
                case 'SHOT_RESULT':
                    handleShotResult(data);
                    break;
                case 'GAME_OVER':
                    showGameOver(data);
                    break;
                case 'RESET':
                    alert(data.message);
                    resetToLobby();
                    break;
                case 'ERROR':
                    alert(data.message);
                    break;
                default:
                    console.log('Unknown message type:', data.type);
            }
        }

        // Update players list in waiting room
        function updatePlayersList(players, creatorUsername) {
            const list = document.getElementById('playersList');
            list.innerHTML = '<h4>Players in room:</h4>';
            players.forEach(player => {
                const div = document.createElement('div');
                div.className = 'player';
                div.textContent = player;
                list.appendChild(div);
            });

            // Determine if the current user is the creator
            if (creatorUsername && creatorUsername === username) {
                isCreator = true;
                updateStartButton();
            }

            // Show start button only to creator and if at least two players
            if (isCreator && players.length >=2 ) {
                document.getElementById('startGameBtn').style.display = 'block';
            } else {
                document.getElementById('startGameBtn').style.display = 'none';
            }

            // Show reset button only to creator
            if (isCreator) {
                document.getElementById('resetRoomBtn').style.display = 'block';
            } else {
                document.getElementById('resetRoomBtn').style.display = 'none';
            }
        }

        // Update start button based on creator status and player count
        function updateStartButton() {
            const players = document.querySelectorAll('#playersList .player');
            if (isCreator && players.length >= 2) {
                document.getElementById('startGameBtn').style.display = 'block';
            } else {
                document.getElementById('startGameBtn').style.display = 'none';
            }

            // Show reset button only to creator
            if (isCreator) {
                document.getElementById('resetRoomBtn').style.display = 'block';
            } else {
                document.getElementById('resetRoomBtn').style.display = 'none';
            }
        }

        // Start Game UI
        function startGameUI(gameStateData) {
            document.getElementById('waitingRoom').style.display = 'none';
            document.getElementById('gameSection').style.display = 'grid';
            renderGame(gameStateData);
        }

        // Update Game UI
        function updateGameUI() {
            if (!gameState) return;
            renderGame(gameState);
        }

        // Render Game UI
        function renderGame(gameState) {
            // Render players
            const playersContainer = document.getElementById('players');
            playersContainer.innerHTML = '';
            gameState.players.forEach(player => {
                const playerEl = document.createElement('div');
                playerEl.className = `player ${player.username === gameState.currentPlayer ? 'active' : ''} ${player.isEliminated ? 'eliminated' : ''}`;
                playerEl.innerHTML = `
                    <strong>${player.username}${player.username === username ? ' (You)' : ''}</strong>
                    <div class="bullets">Bullets: ${player.bulletSlots}/6</div>
                `;
                playersContainer.appendChild(playerEl);
            });

            // Render core card
            const coreCardSpan = document.getElementById('coreCard');
            if (gameState.coreCard && gameState.coreCard !== '-') {
                coreCardSpan.innerHTML = formatCard(gameState.coreCard);
            } else {
                coreCardSpan.textContent = '-';
            }

            // Render last played
            const lastPlayedSpan = document.getElementById('lastPlayed');
            if (gameState.lastPlayedCount > 0) {
                lastPlayedSpan.textContent = `${gameState.lastPlayedCount} card(s) played`;
            } else {
                lastPlayedSpan.textContent = 'None';
            }

            // Render central table
            const centralTable = document.getElementById('centralTable');
            centralTable.innerHTML = '';
            gameState.centralTableCards.forEach(cardObj => {
                const cardEl = document.createElement('div');
                cardEl.className = `card ${cardObj.revealed ? getSuitClass(cardObj.card) : 'back'}`;
                if (cardObj.revealed) {
                    cardEl.innerHTML = formatCard(cardObj.card);
                    cardEl.style.color = getCardColor(cardObj.card);
                } else {
                    cardEl.innerHTML = '🂠';
                }
                centralTable.appendChild(cardEl);
            });

            // Render current player's hand
            const currentPlayerName = gameState.currentPlayer;
            if (currentPlayerName === username && !gameState.isGameOver) {
                const handContainer = document.getElementById('currentHand');
                handContainer.innerHTML = '';
                userHand.forEach((card, index) => {
                    const cardEl = document.createElement('div');
                    cardEl.className = `card ${getSuitClass(card)}`;
                    cardEl.style.color = getCardColor(card);
                    cardEl.dataset.index = index;
                    cardEl.innerHTML = card;
                    cardEl.onclick = () => {
                        cardEl.classList.toggle('selected');
                    };
                    handContainer.appendChild(cardEl);
                });
            } else {
                // Not your turn, show placeholder or information
                const handContainer = document.getElementById('currentHand');
                if (username === currentPlayerName) {
                    handContainer.innerHTML = 'It\'s your turn!';
                } else {
                    const player = gameState.players.find(p => p.username === currentPlayerName);
                    handContainer.innerHTML = `It's ${player.username}'s turn.`;
                }
            }

            // Enable/Disable action buttons based on turn
            if (gameState.currentPlayer === username && !gameState.isGameOver) {
                document.getElementById('playButton').disabled = (userHand.length === 0);
                document.getElementById('callBluffButton').disabled = (gameState.lastPlayedCount === 0);
            } else {
                document.getElementById('playButton').disabled = true;
                document.getElementById('callBluffButton').disabled = true;
            }
        }

        // Format card HTML
        function formatCard(cardStr) {
            const color = getCardColor(cardStr);
            return `<span style="color: ${color};">${cardStr}</span>`;
        }

        // Get card color based on suit
        function getCardColor(cardStr) {
            const suit = cardStr.slice(-1);
            return (suit === '♥' || suit === '♦') ? 'red' : 'black';
        }

        // Get suit class for styling
        function getSuitClass(cardStr) {
            const suit = cardStr.slice(-1);
            return suit === '♠' ? 'spades' :
                   suit === '♣' ? 'clubs' :
                   suit === '♥' ? 'hearts' :
                   'diamonds';
        }

        // Play selected cards
        function playSelectedCards() {
            // Get selected cards
            const selectedCards = Array.from(document.querySelectorAll('.card.selected'));
            if (selectedCards.length === 0) {
                alert('Please select at least one card to play.');
                return;
            }

            const selectedIndices = selectedCards.map(card => parseInt(card.dataset.index));

            // Send PLAY_CARDS message to server
            ws.send(JSON.stringify({
                type: 'PLAY_CARDS',
                selectedIndices: selectedIndices
            }));

            // Remove selected cards from userHand
            selectedIndices.sort((a, b) => b - a); // Remove from higher index to avoid shifting
            selectedIndices.forEach(index => {
                userHand.splice(index, 1);
            });

            // Clear selected classes
            selectedCards.forEach(card => {
                card.classList.remove('selected');
            });
        }

        // Call bluff
        function callBluff() {
            // Send CALL_BLUFF message to server
            ws.send(JSON.stringify({
                type: 'CALL_BLUFF'
            }));
        }

        // Handle Bluff Result
        function handleBluffResult(data) {
            // Reveal the central table cards with appropriate coloring
            const centralTable = document.getElementById('centralTable');
            centralTable.innerHTML = '';
            data.centralTableCards.forEach(cardStr => {
                const cardEl = document.createElement('div');
                const coreCard = data.coreCard;
                const isMatch = isCardMatch(cardStr, coreCard);
                cardEl.className = `card ${getSuitClass(cardStr)}`;
                cardEl.style.color = isMatch ? 'green' : 'red';
                cardEl.innerHTML = cardStr;
                centralTable.appendChild(cardEl);
            });

            // After 2 seconds, show overlay
            setTimeout(() => {
                const overlay = document.getElementById('resultOverlay');
                const overlayTitle = document.getElementById('overlayTitle');
                const overlayMessage = document.getElementById('overlayMessage');
                const overlayButton = document.getElementById('overlayButton');

                // Determine if the current user is the one who lost the bluff
                const lostPlayer = data.player;
                const isUser = lostPlayer === username;

                if (isUser) {
                    overlayTitle.textContent = '⛳ You must Trigger the Gun!';
                    overlayMessage.textContent = 'Click the button below to Pull the Trigger.';
                    overlayButton.style.display = 'inline-block';
                    overlayButton.textContent = 'Shoot';
                } else {
                    overlayTitle.textContent = `${lostPlayer} must Trigger the Gun!`;
                    overlayMessage.textContent = 'Wait for the outcome.';
                    overlayButton.style.display = 'none';
                }

                overlay.style.display = 'flex';
            }, 2000);
        }

        // Determine if two cards match in value
        function isCardMatch(card1, card2) {
            // Compare only the value part (exclude suit)
            const value1 = card1.slice(0, -1);
            const value2 = card2.slice(0, -1);
            return value1 === value2;
        }

        // Handle shooting result
        function handleShotResult(data) {
            const overlay = document.getElementById('resultOverlay');
            const overlayTitle = document.getElementById('overlayTitle');
            const overlayMessage = document.getElementById('overlayMessage');
            const overlayButton = document.getElementById('overlayButton');

            if (data.player === username) {
                if (data.result === 'SHOT') {
                    overlayTitle.textContent = '💀 You have been Shot!';
                    overlayMessage.textContent = 'You have been eliminated.';
                } else if (data.result === 'SURVIVED') {
                    overlayTitle.textContent = '✨ You Survived!';
                    overlayMessage.textContent = 'You can continue playing.';
                }
            } else {
                // For observers or other players
                overlayTitle.textContent = `${data.player} has ${data.result === 'SHOT' ? 'been Shot!' : 'Survived!'}`;
                overlayMessage.textContent = '';
            }

            // Hide the 'Shoot' button if present
            overlayButton.style.display = 'none';

            // After 2 seconds, hide the overlay and reset the game state
            setTimeout(() => {
                overlay.style.display = 'none';
                // Clear the central table
                const centralTable = document.getElementById('centralTable');
                centralTable.innerHTML = '';
                // Update game UI via GAME_UPDATE
                // If game is over, GAME_OVER will handle the UI
            }, 2000);
        }

        // Show game over overlay
        function showGameOver(data) {
            document.getElementById('gameSection').style.display = 'none';
            document.getElementById('gameOverOverlay').style.display = 'flex';
            if (data.winner) {
                document.getElementById('gameOverText').textContent = `Winner: ${data.winner}`;
            } else if (data.message) {
                document.getElementById('gameOverText').textContent = data.message;
            } else {
                document.getElementById('gameOverText').textContent = 'The game has ended.';
            }
        }

        // Reset to lobby
        function resetToLobby() {
            document.getElementById('gameSection').style.display = 'none';
            document.getElementById('gameOverOverlay').style.display = 'none';
            document.getElementById('resultOverlay').style.display = 'none';
            document.getElementById('waitingRoom').style.display = 'block';
            // Reset variables
            // roomId is constant 'ABC123'
            isCreator = false;
            gameState = null;
            userHand = [];
            isWaitingForShot = false;
            // Reload the page to rejoin
            window.location.reload();
        }

        // Handle overlay button (Shoot)
        function handleOverlayAction() {
            if (isWaitingForShot) return; // Prevent multiple shots
            isWaitingForShot = true;
            // Send PULL_TRIGGER message to server
            ws.send(JSON.stringify({
                type: 'PULL_TRIGGER'
            }));
        }

        // Handle start game button
        document.getElementById('startGameBtn').addEventListener('click', () => {
            ws.send(JSON.stringify({
                type: 'START_GAME'
            }));
        });

        // Handle reset room button
        document.getElementById('resetRoomBtn').addEventListener('click', () => {
            if (confirm('Are you sure you want to reset the room? This will end the current game.')) {
                ws.send(JSON.stringify({
                    type: 'RESET_ROOM'
                }));
            }
        });

        // Initialize connection on page load
        window.onload = () => {
            username = generateRandomUsername();
            connectWebSocket();
        };
    </script>
</body>
</html>
```

### server.js

```javascript
// server.js

const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const { v4: uuidv4 } = require('uuid');

// Define Game Classes
class Card {
    constructor(value, suit) {
        this.value = value;
        this.suit = suit; // '♠', '♥', '♦', '♣'
    }

    toString() {
        return `${this.value}${this.suit}`;
    }

    getSuitClass() {
        switch (this.suit) {
            case '♠':
                return 'spades';
            case '♥':
                return 'hearts';
            case '♦':
                return 'diamonds';
            case '♣':
                return 'clubs';
            default:
                return '';
        }
    }

    getColor() {
        return (this.suit === '♥' || this.suit === '♦') ? 'red' : 'black';
    }
}

class Player {
    constructor(id, username, ws) {
        this.id = id;
        this.username = username;
        this.ws = ws;
        this.hand = [];
        this.bulletSlots = 6;
        this.isEliminated = false;
    }
}

class Game {
    constructor(roomId, players) {
        this.roomId = roomId;
        this.players = players; // Array of Player objects
        this.currentPlayerIndex = 0;
        this.coreCard = null;
        this.lastPlayedCards = [];
        this.deck = [];
        this.isGameOver = false;
        this.centralTableCards = [];
        this.shootingPlayer = null; // Player object
        this.initializeDeck();
        this.shuffleDeck();
        this.dealCards();
    }

    initializeDeck() {
        const values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'];
        const suits = ['♠', '♥', '♦', '♣'];
        this.deck = [];
        for (let value of values) {
            for (let suit of suits) {
                this.deck.push(new Card(value, suit));
            }
        }
    }

    shuffleDeck() {
        for (let i = this.deck.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [this.deck[i], this.deck[j]] = [this.deck[j], this.deck[i]];
        }
    }

    dealCards() {
        // Assign a core card
        if (this.deck.length === 0) {
            throw new Error('Deck is empty. Cannot deal cards.');
        }
        this.coreCard = this.deck.shift();

        // Deal 5 cards to each player
        this.players.forEach(player => {
            for (let i = 0; i < 5; i++) {
                if (this.deck.length > 0) {
                    player.hand.push(this.deck.shift());
                }
            }
        });
    }

    getCurrentPlayer() {
        return this.players[this.currentPlayerIndex];
    }

    nextPlayer() {
        if (this.isGameOver) return;
        let attempts = 0;
        do {
            this.currentPlayerIndex = (this.currentPlayerIndex + 1) % this.players.length;
            attempts++;
            if (attempts > this.players.length) break; // Prevent infinite loop
        } while (this.getCurrentPlayer().isEliminated);
    }

    getGameState(requestingPlayerId) {
        return {
            roomId: this.roomId,
            players: this.players.map(player => ({
                id: player.id,
                username: player.username,
                isEliminated: player.isEliminated,
                bulletSlots: player.bulletSlots,
                // Only send hand to the requesting player
                hand: player.id === requestingPlayerId ? player.hand.map(card => card.toString()) : undefined
            })),
            currentPlayer: this.getCurrentPlayer().username,
            coreCard: this.coreCard ? this.coreCard.toString() : '-',
            lastPlayedCount: this.lastPlayedCards.length, // Only send count, not actual cards
            centralTableCards: this.centralTableCards.map(cardObj => ({
                card: cardObj.card.toString(),
                revealed: cardObj.revealed
            })),
            isGameOver: this.isGameOver
        };
    }

    // Assign a new core card for the next round
    assignNewCoreCard() {
        if (this.deck.length === 0) {
            // Reshuffle central table cards back into the deck if needed
            this.deck = this.centralTableCards.map(cardObj => cardObj.card);
            this.shuffleDeck();
            this.centralTableCards = [];
        }
        if (this.deck.length > 0) {
            this.coreCard = this.deck.shift();
        } else {
            // If deck is still empty, set coreCard to null (shouldn't happen with proper deck management)
            this.coreCard = null;
        }
    }
}

// Initialize Express server
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

// Serve static files from 'public' directory
app.use(express.static('public'));

// Define the single room ID
const ROOM_ID = 'ABC123';

// Initialize the room
const room = {
    id: ROOM_ID,
    creator: null, // Will be set to the first player
    players: [], // Array of Player objects
    isStarted: false
};

// Initialize games
let currentGame = null;

// Handle WebSocket connections
wss.on('connection', (ws) => {
    ws.id = uuidv4(); // Assign a unique ID to each connection

    ws.on('message', (message) => {
        let data;
        try {
            data = JSON.parse(message);
        } catch (e) {
            ws.send(JSON.stringify({ type: 'ERROR', message: 'Invalid JSON' }));
            return;
        }

        switch (data.type) {
            case 'JOIN_ROOM':
                handleJoinRoom(ws, data);
                break;
            case 'START_GAME':
                handleStartGame(ws, data);
                break;
            case 'PLAY_CARDS':
                handlePlayCards(ws, data);
                break;
            case 'CALL_BLUFF':
                handleCallBluff(ws, data);
                break;
            case 'PULL_TRIGGER':
                handlePullTrigger(ws, data);
                break;
            case 'RESET_ROOM':
                handleResetRoom(ws, data);
                break;
            default:
                ws.send(JSON.stringify({ type: 'ERROR', message: 'Unknown command' }));
        }
    });

    ws.on('close', () => {
        handleDisconnect(ws);
    });
});

// Handle joining the room
function handleJoinRoom(ws, data) {
    const username = data.username;
    const dataRoomId = data.roomId;

    if (!username) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Username is required to join the room' }));
        return;
    }

    // Validate room ID
    if (dataRoomId !== ROOM_ID) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Room not found' }));
        return;
    }

    if (room.isStarted) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Game already started in this room. Please wait for the next round.' }));
        return;
    }

    if (room.players.length >= 5) { // Assuming max 5 players
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Room is full' }));
        return;
    }

    const playerId = uuidv4();
    const player = new Player(playerId, username, ws);
    room.players.push(player);

    ws.roomId = room.id;
    ws.playerId = playerId;

    // Assign creator if first player
    let isCreator = false;
    if (room.creator === null) {
        room.creator = playerId;
        isCreator = true;
    }

    // Notify all players in the room about the new player and current creator
    broadcastToRoom(room.id, {
        type: 'PLAYER_JOINED',
        players: room.players.map(p => p.username),
        creator: isCreator ? player.username : getPlayerById(room.creator).username
    });

    // If the new player is the creator, send a separate message
    if (isCreator) {
        ws.send(JSON.stringify({ type: 'CREATOR', isCreator: true }));
    }
}

// Handle starting the game
function handleStartGame(ws, data) {
    const roomId = ws.roomId;
    const playerId = ws.playerId;

    if (roomId !== ROOM_ID) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Invalid room' }));
        return;
    }

    if (room.creator !== playerId) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Only the room creator can start the game' }));
        return;
    }

    if (room.isStarted) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Game already started' }));
        return;
    }

    if (room.players.length < 2) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'At least two players are required to start the game' }));
        return;
    }

    try {
        // Initialize game
        currentGame = new Game(roomId, room.players);
        room.isStarted = true;
    } catch (error) {
        ws.send(JSON.stringify({ type: 'ERROR', message: error.message }));
        return;
    }

    // Broadcast game start and initial game state to all players
    room.players.forEach(player => {
        player.ws.send(JSON.stringify({
            type: 'GAME_STARTED',
            gameState: currentGame.getGameState(player.id),
            hand: player.hand.map(card => card.toString())
        }));
    });
}

// Handle playing cards
function handlePlayCards(ws, data) {
    if (!currentGame || currentGame.isGameOver) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Game not found or already over' }));
        return;
    }

    const playerId = ws.playerId;
    const selectedIndices = data.selectedIndices; // Array of indices

    const player = currentGame.players.find(p => p.id === playerId);
    if (!player) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Player not found in the game' }));
        return;
    }

    if (currentGame.getCurrentPlayer().id !== playerId) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Not your turn' }));
        return;
    }

    if (!Array.isArray(selectedIndices) || selectedIndices.length === 0) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'No cards selected' }));
        return;
    }

    // Validate selected indices
    if (selectedIndices.some(index => index < 0 || index >= player.hand.length)) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Invalid card indices' }));
        return;
    }

    // Get selected cards
    const selectedCards = selectedIndices.map(index => player.hand[index]);

    // Remove selected cards from player's hand (reverse sort to remove from higher index to lower)
    selectedIndices.sort((a, b) => b - a);
    selectedIndices.forEach(index => {
        player.hand.splice(index, 1);
    });

    // Update game state's last played cards
    currentGame.lastPlayedCards = selectedCards;

    // **Reset the central table to only hold the latest played cards**
    currentGame.centralTableCards = []; // Clear previous cards

    // Add to central table as face-down
    selectedCards.forEach(card => {
        currentGame.centralTableCards.push({
            card: card,
            revealed: false
        });
    });

    // Broadcast game state to all players
    broadcastGameState(room.id);

    // Move to next player
    currentGame.nextPlayer();

    // Broadcast updated game state after moving the turn
    broadcastGameState(room.id);
}

// Handle calling bluff
function handleCallBluff(ws, data) {
    if (!currentGame || currentGame.isGameOver) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Game not found or already over' }));
        return;
    }

    const playerId = ws.playerId;
    const caller = currentGame.players.find(p => p.id === playerId);
    if (!caller) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Player not found in the game' }));
        return;
    }

    // Cannot call bluff if no one has played yet
    if (currentGame.lastPlayedCards.length === 0) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'No cards have been played yet' }));
        return;
    }

    // Determine if the last played cards are a bluff
    // Assuming in this game, players must play the coreCard value
    const coreCard = currentGame.coreCard;
    if (!coreCard) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Core card is not set' }));
        return;
    }

    const actual = currentGame.lastPlayedCards.every(card => card.value === coreCard.value);

    if (!actual) {
        // Bluff was called, and player who played the last cards was bluffing
        // The previous player loses one bullet slot and might get eliminated

        // Identify the player who played last
        const lastPlayerIndex = (currentGame.currentPlayerIndex - 1 + currentGame.players.length) % currentGame.players.length;
        const lastPlayer = currentGame.players[lastPlayerIndex];

        lastPlayer.bulletSlots -= 1;

        // Check if player is eliminated
        const isEliminated = lastPlayer.bulletSlots <= 0;
        if (isEliminated) {
            lastPlayer.isEliminated = true;
        }

        // Notify all players about the result, including the played cards and core card
        broadcastToRoom(room.id, {
            type: 'BLUFF_RESULT',
            result: 'PLAYER_BLUFFED',
            player: lastPlayer.username,
            bulletSlots: lastPlayer.bulletSlots,
            isEliminated: isEliminated,
            centralTableCards: currentGame.centralTableCards.map(cardObj => cardObj.card.toString()),
            coreCard: coreCard.toString()
        });

        // Clear last played cards and central table cards
        currentGame.lastPlayedCards = [];
        currentGame.centralTableCards = [];

        // Assign a new core card for the next round
        currentGame.assignNewCoreCard();

        // Check if game is over
        const remainingPlayers = currentGame.players.filter(p => !p.isEliminated);
        if (remainingPlayers.length === 1) {
            currentGame.isGameOver = true;
            broadcastToRoom(room.id, {
                type: 'GAME_OVER',
                winner: remainingPlayers[0].username
            });
            currentGame = null;
            room.isStarted = false;
            return;
        }

    } else {
        // Bluff called, but it was not a bluff
        // The caller loses one bullet slot and might get eliminated
        caller.bulletSlots -= 1;

        // Check if caller is eliminated
        const isEliminated = caller.bulletSlots <= 0;
        if (isEliminated) {
            caller.isEliminated = true;
        }

        // Notify all players about the result, including the played cards and core card
        broadcastToRoom(room.id, {
            type: 'BLUFF_RESULT',
            result: 'PLAYER_NOT_BLUFFED',
            player: caller.username,
            bulletSlots: caller.bulletSlots,
            isEliminated: isEliminated,
            centralTableCards: currentGame.centralTableCards.map(cardObj => cardObj.card.toString()),
            coreCard: coreCard.toString()
        });

        // Clear last played cards and central table cards
        currentGame.lastPlayedCards = [];
        currentGame.centralTableCards = [];

        // Assign a new core card for the next round
        currentGame.assignNewCoreCard();

        // Check if game is over
        const remainingPlayers = currentGame.players.filter(p => !p.isEliminated);
        if (remainingPlayers.length === 1) {
            currentGame.isGameOver = true;
            broadcastToRoom(room.id, {
                type: 'GAME_OVER',
                winner: remainingPlayers[0].username
            });
            currentGame = null;
            room.isStarted = false;
            return;
        }
    }

    // Broadcast updated game state
    broadcastGameState(room.id);
}

// Handle pulling trigger
function handlePullTrigger(ws, data) {
    if (!currentGame || currentGame.isGameOver) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Game not found or already over' }));
        return;
    }

    const playerId = ws.playerId;

    if (!currentGame.shootingPlayer) {
        // The shooting player should be the one who lost the bluff
        // Find the shooting player based on who lost the bluff last
        // Assuming the last BLUFF_RESULT specifies who lost
        // Since the server sent BLUFF_RESULT with 'PLAYER_BLUFFED', we can identify who lost

        // Alternatively, maintain a variable to track who lost the last bluff
        // For simplicity, we'll assign shootingPlayer based on the last bluffed player

        // Here, let's assume that after BLUFF_RESULT, the shootingPlayer is set appropriately
        // So, we need to manage this in the server

        // However, since the server processes the outcome and not the client,
        // it's better to link BLUFF_RESULT to triggering shooting overlay on the client side
        // Hence, no need to assign shootingPlayer here, simply process the shooting action
        ws.send(JSON.stringify({ type: 'ERROR', message: 'No shooting action pending' }));
        return;
    }

    const shootingPlayer = currentGame.shootingPlayer;

    // Pull the trigger: determine if the player is shot
    const bulletChance = 1 / shootingPlayer.bulletSlots;
    const shot = Math.random() < bulletChance;

    if (shot) {
        shootingPlayer.bulletSlots -= 1;
        shootingPlayer.isEliminated = true;

        broadcastToRoom(room.id, {
            type: 'SHOT_RESULT',
            result: 'SHOT',
            player: shootingPlayer.username,
            bulletSlots: shootingPlayer.bulletSlots,
            isEliminated: shootingPlayer.isEliminated
        });
    } else {
        shootingPlayer.bulletSlots -= 1;

        broadcastToRoom(room.id, {
            type: 'SHOT_RESULT',
            result: 'SURVIVED',
            player: shootingPlayer.username,
            bulletSlots: shootingPlayer.bulletSlots,
            isEliminated: shootingPlayer.isEliminated
        });
    }

    // Reset shooting player
    currentGame.shootingPlayer = null;

    // Check if game is over
    const remainingPlayers = currentGame.players.filter(p => !p.isEliminated);
    if (remainingPlayers.length === 1) {
        currentGame.isGameOver = true;
        broadcastToRoom(room.id, {
            type: 'GAME_OVER',
            winner: remainingPlayers[0].username
        });
        currentGame = null;
        room.isStarted = false;
        return;
    }

    // Reset for next round
    currentGame.lastPlayedCards = [];
    currentGame.centralTableCards = [];
    currentGame.assignNewCoreCard();

    // Move to next player
    currentGame.nextPlayer();

    // Broadcast updated game state
    broadcastGameState(room.id);
}

// Handle resetting the room
function handleResetRoom(ws, data) {
    const playerId = ws.playerId;
    if (room.creator !== playerId) {
        ws.send(JSON.stringify({ type: 'ERROR', message: 'Only the room creator can reset the room' }));
        return;
    }

    // Reset game state
    if (currentGame && !currentGame.isGameOver) {
        currentGame.isGameOver = true;
        broadcastToRoom(room.id, {
            type: 'GAME_OVER',
            winner: null,
            message: 'Game has been reset by the creator.'
        });
        currentGame = null;
    }

    // Reset room state
    room.isStarted = false;

    // Notify all players to reset
    broadcastToRoom(room.id, {
        type: 'RESET',
        message: 'Room has been reset. You can join again.'
    });

    // Reset all players' states
    room.players.forEach(player => {
        player.hand = [];
        player.bulletSlots = 6;
        player.isEliminated = false;
    });
}

// Handle disconnects
function handleDisconnect(ws) {
    const roomId = ws.roomId;
    const playerId = ws.playerId;

    if (roomId !== ROOM_ID) return;

    const playerIndex = room.players.findIndex(p => p.id === playerId);
    if (playerIndex === -1) return;

    const player = room.players.splice(playerIndex, 1)[0];

    // Notify remaining players
    broadcastToRoom(room.id, {
        type: 'PLAYER_LEFT',
        players: room.players.map(p => p.username)
    });

    // If game is ongoing, mark player as eliminated
    if (currentGame) {
        const gamePlayer = currentGame.players.find(p => p.id === playerId);
        if (gamePlayer) {
            gamePlayer.isEliminated = true;

            // Check for game over
            const remainingPlayers = currentGame.players.filter(p => !p.isEliminated);
            if (remainingPlayers.length === 1) {
                currentGame.isGameOver = true;
                broadcastToRoom(room.id, {
                    type: 'GAME_OVER',
                    winner: remainingPlayers[0].username
                });
                currentGame = null;
                room.isStarted = false;
                return;
            }

            // Broadcast updated game state
            broadcastGameState(room.id);
        }
    }

    // If room is empty, reset creator and game state
    if (room.players.length === 0) {
        room.creator = null;
        room.isStarted = false;
        currentGame = null;
    } else {
        // If creator disconnected, assign a new creator
        if (room.creator === playerId) {
            room.creator = room.players[0].id;
            room.players[0].ws.send(JSON.stringify({
                type: 'NEW_CREATOR',
                newCreator: room.players[0].username
            }));
        }
    }
}

// Broadcast game state to all players in the room
function broadcastGameState(roomId) {
    if (!currentGame) return;

    room.players.forEach(player => {
        player.ws.send(JSON.stringify({
            type: 'GAME_UPDATE',
            gameState: currentGame.getGameState(player.id)
        }));
    });
}

// Broadcast a message to all players in a room
function broadcastToRoom(roomId, message) {
    const targetRoom = roomId === ROOM_ID ? room : null;
    if (!targetRoom) return;

    targetRoom.players.forEach(player => {
        if (player.ws.readyState === WebSocket.OPEN) {
            player.ws.send(JSON.stringify(message));
        }
    });
}

// Helper function to get a player by ID
function getPlayerById(playerId) {
    return room.players.find(p => p.id === playerId);
}

const PORT = process.env.PORT || 3000;

server.listen(PORT, () => {
    console.log(`Server is listening on port ${PORT}`);
});
```

When clicking on shooting, an alert appears "there's no pending shoot" and the game stuck there, and when call bluff the cards on table disappear, when they actually should "flip" but not as animation, but instead just show their faces.