#3823 Chessboard Football

#3823 Chessboard Football

#3823 Describe tabletop football played with chess pieces on a 6-row by 8-column chess board with each team facing off from either side of the board and "play" in the middle. Determine the proper proportion of pawns.

Based on your description, here is a complete concept for tabletop football played with chess pieces on a $6 \times 8$ board, including the proper proportion of pawns.

This game is a variant of chess that borrows its objective from American football. The goal is not checkmate, but to score a "touchdown" by moving your "ball carrier" piece to the opponent's back rank.

The Game: "Gridiron Chess"

The game is played on a $6 \times 8$ board (6 rows, 8 columns). The 8-column sides are the "sidelines," and the 6-row-deep sides are the "end zones" and "field of play."

  • Team 1 (White): Starts on Row 1.

  • Team 2 (Black): Starts on Row 6.

  • White's End Zone: Row 1

  • Black's End Zone: Row 6

  • Field of Play: Rows 2 through 5.

  • The "Ball": The King is the "Quarterback" and always starts with the ball. The King is the only piece that can score.

Winning the Game

You win by moving your King into any square on the opponent's back rank (Row 6 for White, Row 1 for Black). This is a "touchdown."


Team Composition & Pawn Proportion

The central question is how to arrange the teams. Your $6 \times 8$ board setup leads to two logical interpretations, both of which point to the same conclusion.

Option 1: The "11-on-11" (8-Piece) Setup

This setup models a smaller football team, where each piece represents a player. Each team uses 8 pieces, which fit perfectly on one rank (row).

  • Setup:

    • White's 8 pieces are placed on Row 1.

    • Black's 8 pieces are placed on Row 6.

    • Rows 2-5 are the open "field of play." This represents the "kickoff" position.

  • Proper Team Proportion:

    To mirror a football team (which is roughly half "linemen" and half "skill players"), the most balanced 8-piece team would be:

    • 4 Pawns (The "Line"): These are your blockers. They move as standard pawns (one square forward, capture diagonally) but are primarily used to create a "pocket" for the King or to block defenders.

    • 1 King (The "Quarterback"): The ball-carrier. Moves as a standard King. Must be the piece to enter the end zone.

    • 1 Queen (The "Star Player"): A "running back" or "receiver" who can move quickly to block or clear a path.

    • 2 Rooks (The "Blockers/Tight Ends"): Powerful pieces used to control the "sidelines" (the a- and h-files) and act as lead blockers.

In this setup, the proportion is 4 pawns out of 8 total pieces.

Option 2: The "Line of Scrimmage" (16-Piece) Setup

This setup uses all 16 pieces from a standard chess set to represent a "full team" facing off at a line of scrimmage.

  • Setup:

    • White Team:

      • Row 1: 8 major pieces (King, Queen, Rooks, Bishops, Knights).

      • Row 2: 8 Pawns (The "Offensive/Defensive Line").

    • Black Team:

      • Row 6: 8 major pieces.

      • Row 5: 8 Pawns (The "Offensive/Defensive Line").

    • The "Middle": Rows 3 and 4 are the "neutral zone" at the start of play.

  • Proper Team Proportion:

    In this setup, the roles are even more explicit. The pawns are the "line," and the major pieces are the "skill players" (QB, RBs, Receivers, etc.).

In this setup, the proportion is 8 pawns out of 16 total pieces.


🏈 Final Determination: The Proper Pawn Proportion

In both logical scenarios, the most balanced and thematic team composition for tabletop football is 50% pawns.

  • 4 Pawns in an 8-piece team.

  • 8 Pawns in a 16-piece team.

The pawns perfectly represent the offensive and defensive lines, whose job is to block, tackle (capture), and create openings for the ball-carrier.

Recommended "Gridiron Chess" Rules

Here is a simple ruleset to get you started, using the 8-Piece Setup (Option 1) for a faster, more open-field game.

  1. Setup: Each player arranges their 8 pieces (4 Pawns, 2 Rooks, 1 Queen, 1 King) on their back rank (Row 1 for White, Row 6 for Black).

  2. Objective: Move your King to the opponent's back rank to score a touchdown.

  3. Movement: All pieces move exactly as they do in standard chess.

  4. The "Ball" (The King):

    • Your King is the ball-carrier.

    • If your King is captured, it is a "turnover." The game immediately resets to the starting "kickoff" position, and the capturing player (who now has the "ball") gets the first move.

  5. "Tackles" (Capturing):

    • Capturing is an optional "tackle." You can capture any of a

      player's pieces (Pawns, Rooks, Queen).

    • Captured pieces are removed from the game.

    • You cannot capture the opponent's King. You can only force a turnover by capturing the King.

  6. "Passing" (Optional Rule):

    • Once per game, as its entire move, the King can "pass" the ball.

    • To pass, swap the King's position with any friendly Rook or Queen on the board.

    • This is a high-risk, high-reward play to suddenly reposition your ball-carrier.

Would you like me to elaborate on the "Line of Scrimmage" (16-piece) rules or explore other football-like mechanics, such as "downs" or "field goals"?


Create an HTML, JavaScript, CSS app to play. Support automate computer play, possibly with either standard setups (i.e. plays) or random setups (plays). Provide a speed of play control, a replay button, and a next play button. Keep score.

Here is a complete, single-file HTML/CSS/JavaScript application for "Gridiron Chess."

This app implements the 16-piece "Line of Scrimmage" setup on the $6 \times 8$ board. The goal is to get your King (the "Quarterback") to the opponent's back rank for a touchdown, or to capture the opponent's King for a turnover.

I've included all the features you requested:

  • Automated AI Play: You can select from various AI modes, including "Random" (picks any legal move) and "Standard Plays" (a smarter AI that tries to score, get a turnover, or advance the King).

  • Speed Control: A slider adjusts the AI's move speed.

  • Game Controls: "Next Play" (for after a score/turnover) and "Reset Game" (for a full 0-0 reset).

  • Live Scoreboard: Tracks touchdowns for both teams.

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Gridiron Chess</title>

    <!-- Load Tailwind CSS -->

    <script src="https://cdn.tailwindcss.com"></script>

    <style>

        /* Custom font */

        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');

        body {

            font-family: 'Inter', sans-serif;

            -webkit-font-smoothing: antialiased;

            -moz-osx-font-smoothing: grayscale;

        }

        /* Make piece text unselectable */

        .chess-piece {

            user-select: none;

            cursor: pointer;

            text-shadow: 0 2px 4px rgba(0,0,0,0.2);

        }

        /* Style for the valid move indicator dot */

        .valid-move-dot {

            width: 33.33%;

            height: 33.33%;

            border-radius: 50%;

            background-color: rgba(34, 197, 94, 0.6); /* green-500 with opacity */

        }

        /* Style for a square that can be captured */

        .capture-move-dot {

            width: 90%;

            height: 90%;

            border-radius: 50%;

            border: 4px solid rgba(239, 68, 68, 0.5); /* red-500 with opacity */

            box-sizing: border-box;

        }

        /* Selected piece highlight */

        .selected {

            background-color: rgba(250, 204, 21, 0.7) !important; /* yellow-400 with opacity */

        }

        /* Hide number input arrows */

        input[type=range] {

            -webkit-appearance: none;

            appearance: none;

            background: transparent;

            cursor: pointer;

        }

        input[type=range]::-webkit-slider-runnable-track {

            background: #4a5568; /* gray-700 */

            height: 0.5rem;

            border-radius: 0.5rem;

        }

        input[type=range]::-webkit-slider-thumb {

            -webkit-appearance: none;

            appearance: none;

            margin-top: -4px; /* Center thumb */

            background-color: #2dd4bf; /* cyan-400 */

            height: 1.25rem;

            width: 1.25rem;

            border-radius: 50%;

        }

    </style>

</head>

<body class="bg-gray-900 text-gray-200 flex flex-col min-h-screen">


    <!-- Header with Title and Scoreboard -->

    <header class="bg-gray-800 shadow-lg w-full">

        <div class="container mx-auto flex justify-between items-center p-4">

            <h1 class="text-xl md:text-3xl font-bold text-cyan-400">

                Gridiron Chess

            </h1>

            <div class="flex gap-4 md:gap-6 items-center">

                <div class="text-center">

                    <span class="text-sm md:text-lg font-semibold block text-white">HOME</span>

                    <span id="score-white" class="text-3xl md:text-4xl font-bold block text-white">0</span>

                </div>

                <span class="text-2xl md:text-3xl font-light text-gray-500">-</span>

                <div class="text-center">

                    <span class="text-sm md:text-lg font-semibold block text-gray-400">VISITOR</span>

                    <span id="score-black" class="text-3xl md:text-4xl font-bold block text-gray-400">0</span>

                </div>

            </div>

        </div>

    </header>


    <!-- Main Content -->

    <main class="flex-grow container mx-auto p-4 flex flex-col lg:flex-row gap-6 items-start justify-center">


        <!-- Game Board Area -->

        <div class="w-full lg:w-auto flex-shrink-0">

            <!-- Board: 6 rows, 8 columns. Aspect ratio 4:3 -->

            <div id="board" class="grid grid-cols-8 gap-0 w-full max-w-[640px] mx-auto aspect-[4/3] border-4 border-gray-700 rounded-lg overflow-hidden shadow-2xl bg-gray-700">

                <!-- Squares will be generated by JavaScript -->

            </div>

            <div id="status-message" class="text-center text-lg font-semibold text-yellow-400 mt-4 h-6">

                White's Turn

            </div>

        </div>


        <!-- Controls Area -->

        <div class="w-full lg:max-w-xs bg-gray-800 p-5 rounded-lg shadow-xl">

            <h2 class="text-2xl font-bold mb-4 border-b border-gray-700 pb-2 text-cyan-400">Game Controls</h2>

            

            <!-- Play Buttons -->

            <div class="grid grid-cols-2 gap-3 mb-4">

                <button id="next-play-button" class="bg-green-600 hover:bg-green-500 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all duration-150 hidden">

                    Next Play

                </button>

                <button id="reset-game-button" class="bg-red-600 hover:bg-red-500 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all duration-150 col-span-2">

                    Reset Game

                </button>

            </div>


            <!-- AI Controls -->

            <h3 class="text-xl font-semibold mt-6 mb-3 text-cyan-400">Computer Play</h3>

            

            <label for="ai-mode" class="block text-sm font-medium text-gray-300 mb-1">AI vs. Player</label>

            <select id="ai-mode" class="w-full bg-gray-700 border border-gray-600 text-white rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-cyan-500">

                <option value="none">Player vs. Player</option>

                <option value="black-random">Player (White) vs. AI (Black, Random)</option>

                <option value="black-standard">Player (White) vs. AI (Black, "Plays")</option>

                <option value="white-random">AI (White, Random) vs. Player (Black)</option>

                <option value="white-standard">AI (White, "Plays") vs. Player (Black)</option>

                <option value="ai-vs-ai-random">AI (Random) vs. AI (Random)</option>

                <option value="ai-vs-ai-standard">AI ("Plays") vs. AI ("Plays")</option>

            </select>


            <label for="speed-control" class="block text-sm font-medium text-gray-300 mb-1 mt-4">AI Speed</label>

            <div class="flex items-center gap-2 text-xs">

                <span>Slow</span>

                <input id="speed-control" type="range" min="100" max="2000" value="1500" class="w-full">

                <span>Fast</span>

            </div>

        </div>


    </main>


    <script type="module">

        // --- CONSTANTS ---

        const ROWS = 6;

        const COLS = 8;

        

        // Piece definitions

        const PIECES = {

            wK: '&#9812;', wQ: '&#9813;', wR: '&#9814;', wB: '&#9815;', wN: '&#9816;', wP: '&#9817;',

            bK: '&#9818;', bQ: '&#9819;', bR: '&#9820;', bB: '&#9821;', bN: '&#9822;', bP: '&#9823;'

        };

        

        const PIECE_COLORS = {

            w: 'text-white',

            b: 'text-black'

        };


        // Initial 16-piece "Line of Scrimmage" setup

        const INITIAL_BOARD = [

            // Row 0 (White's Back Rank)

            ['wR', 'wN', 'wB', 'wQ', 'wK', 'wB', 'wN', 'wR'],

            // Row 1 (White's "Line")

            ['wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP'],

            // Row 2 (Neutral Zone)

            [null, null, null, null, null, null, null, null],

            // Row 3 (Neutral Zone)

            [null, null, null, null, null, null, null, null],

            // Row 4 (Black's "Line")

            ['bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP'],

            // Row 5 (Black's Back Rank)

            ['bR', 'bN', 'bB', 'bQ', 'bK', 'bB', 'bN', 'bR']

        ];


        // --- STATE VARIABLES ---

        let boardState = [];

        let currentPlayer = 'w';

        let selectedPiece = null; // { r, c, piece }

        let validMoves = [];

        let score = { w: 0, b: 0 };

        let gameInProgress = true;

        let aiMode = 'none';

        let aiSpeed = 500; // Default speed (2000ms - 1500 value)


        // --- DOM ELEMENTS ---

        const boardEl = document.getElementById('board');

        const statusEl = document.getElementById('status-message');

        const scoreWEl = document.getElementById('score-white');

        const scoreBEl = document.getElementById('score-black');

        const resetGameBtn = document.getElementById('reset-game-button');

        const nextPlayBtn = document.getElementById('next-play-button');

        const aiModeSelect = document.getElementById('ai-mode');

        const speedSlider = document.getElementById('speed-control');


        // --- INITIALIZATION ---

        document.addEventListener('DOMContentLoaded', initGame);


        function initGame() {

            // Add event listeners

            resetGameBtn.addEventListener('click', resetGame);

            nextPlayBtn.addEventListener('click', () => {

                resetBoard();

                nextPlayBtn.classList.add('hidden');

                resetGameBtn.classList.remove('col-span-2');

            });

            aiModeSelect.addEventListener('change', (e) => {

                aiMode = e.target.value;

                triggerAI();

            });

            speedSlider.addEventListener('input', (e) => {

                // Invert slider (high value = fast, low value = slow)

                aiSpeed = 2100 - parseInt(e.target.value, 10);

            });

            

            resetGame();

        }

        

        // --- GAME FLOW FUNCTIONS ---


        /** Resets the entire game, including score */

        function resetGame() {

            score = { w: 0, b: 0 };

            updateScoreDisplay();

            resetBoard();

            nextPlayBtn.classList.add('hidden');

            resetGameBtn.classList.remove('col-span-2');

        }


        /** Resets the board for a new play, keeps score */

        function resetBoard() {

            // Deep copy of the initial board setup

            boardState = INITIAL_BOARD.map(row => [...row]);

            currentPlayer = 'w'; // White always starts

            selectedPiece = null;

            validMoves = [];

            gameInProgress = true;

            updateStatus("White's Turn");

            renderBoard();

            triggerAI(); // Check if AI should make the first move

        }


        /** Renders the board based on boardState */

        function renderBoard() {

            boardEl.innerHTML = '';

            

            for (let r = 0; r < ROWS; r++) {

                for (let c = 0; c < COLS; c++) {

                    const square = document.createElement('div');

                    square.dataset.r = r;

                    square.dataset.c = c;

                    

                    // Set square color

                    const isLight = (r + c) % 2 === 0;

                    square.className = `flex items-center justify-center text-5xl md:text-6xl ${isLight ? 'bg-gray-300' : 'bg-gray-600'}`;

                    

                    const piece = boardState[r][c];

                    if (piece) {

                        square.innerHTML = PIECES[piece];

                        square.classList.add('chess-piece', PIECE_COLORS[piece[0]]);

                    }

                    

                    // Highlight selected piece

                    if (selectedPiece && selectedPiece.r === r && selectedPiece.c === c) {

                        square.classList.add('selected');

                    }

                    

                    // Show valid move indicators

                    const move = validMoves.find(m => m.r === r && m.c === c);

                    if (move) {

                        const dot = document.createElement('div');

                        if (move.isCapture) {

                            dot.className = 'capture-move-dot';

                        } else {

                            dot.className = 'valid-move-dot';

                        }

                        square.appendChild(dot);

                    }

                    

                    square.addEventListener('click', handleSquareClick);

                    boardEl.appendChild(square);

                }

            }

        }


        // --- EVENT HANDLERS ---


        /** Handles clicking on a square */

        function handleSquareClick(e) {

            if (!gameInProgress) return;

            

            // Check if it's an AI's turn

            const isAiTurn = (currentPlayer === 'w' && (aiMode.startsWith('white-') || aiMode.startsWith('ai-vs-ai-'))) ||

                             (currentPlayer === 'b' && (aiMode.startsWith('black-') || aiMode.startsWith('ai-vs-ai-')));

                             

            if (isAiTurn && aiMode !== 'none') return; // Don't allow human clicks on AI turn


            const r = parseInt(e.currentTarget.dataset.r);

            const c = parseInt(e.currentTarget.dataset.c);

            const clickedPiece = boardState[r][c];


            // --- Case 1: A piece is already selected ---

            if (selectedPiece) {

                const isValidMove = validMoves.some(m => m.r === r && m.c === c);

                

                // Try to make a move

                if (isValidMove) {

                    makeMove(selectedPiece.r, selectedPiece.c, r, c);

                    

                    // After move, check game state

                    if (gameInProgress) {

                        swapPlayer();

                        triggerAI();

                    }

                }

                // Deselect or switch piece

                else {

                    // If clicking another friendly piece, switch selection

                    if (clickedPiece && clickedPiece[0] === currentPlayer) {

                        selectPiece(r, c, clickedPiece);

                    } else {

                        // Otherwise, deselect

                        selectedPiece = null;

                        validMoves = [];

                    }

                }

            }

            // --- Case 2: No piece is selected ---

            else if (clickedPiece && clickedPiece[0] === currentPlayer) {

                selectPiece(r, c, clickedPiece);

            }

            

            renderBoard();

        }

        

        /** Selects a piece and calculates its moves */

        function selectPiece(r, c, piece) {

            selectedPiece = { r, c, piece };

            validMoves = getValidMoves(r, c, piece);

        }


        /** Makes a move on the boardState and checks for win/turnover */

        function makeMove(r1, c1, r2, c2) {

            const movingPiece = boardState[r1][c1];

            const targetPiece = boardState[r2][c2];

            

            boardState[r2][c2] = movingPiece;

            boardState[r1][c1] = null;

            

            selectedPiece = null;

            validMoves = [];


            // --- Check for Game End Conditions ---

            

            // 1. Touchdown

            if (movingPiece === 'wK' && r2 === (ROWS - 1)) {

                handleWin('w');

                return;

            }

            if (movingPiece === 'bK' && r2 === 0) {

                handleWin('b');

                return;

            }

            

            // 2. Turnover (King captured)

            if (targetPiece === 'bK') {

                handleTurnover('w'); // White captured Black's King

                return;

            }

            if (targetPiece === 'wK') {

                handleTurnover('b'); // Black captured White's King

                return;

            }

        }

        

        /** Swaps the current player */

        function swapPlayer() {

            currentPlayer = (currentPlayer === 'w' ? 'b' : 'w');

            updateStatus(`${currentPlayer === 'w' ? 'White' : 'Black'}'s Turn`);

        }

        

        /** Handles a win (Touchdown) */

        function handleWin(winner) {

            gameInProgress = false;

            score[winner]++;

            updateScoreDisplay();

            updateStatus(`TOUCHDOWN ${winner === 'w' ? 'WHITE' : 'BLACK'}!`);

            showNextPlayButton();

        }

        

        /** Handles a turnover (King captured) */

        function handleTurnover(newPlayer) {

            gameInProgress = false;

            currentPlayer = newPlayer; // Set possession for next play

            updateStatus(`TURNOVER! ${newPlayer === 'w' ? 'White' : 'Black'}'s Ball!`);

            showNextPlayButton();

        }

        

        function showNextPlayButton() {

            nextPlayBtn.classList.remove('hidden');

            resetGameBtn.classList.add('col-span-2');

        }


        // --- AI LOGIC ---


        /** Checks if AI should make a move and triggers it */

        function triggerAI() {

            if (!gameInProgress) return;

            

            const isAiTurn = (currentPlayer === 'w' && (aiMode.startsWith('white-') || aiMode.startsWith('ai-vs-ai-'))) ||

                             (currentPlayer === 'b' && (aiMode.startsWith('black-') || aiMode.startsWith('ai-vs-ai-')));


            if (isAiTurn) {

                setTimeout(makeAIMove, aiSpeed);

            }

        }


        /** The AI brain decides and makes a move */

        function makeAIMove() {

            if (!gameInProgress) return;


            const allMoves = getAllValidMoves(currentPlayer);

            if (allMoves.length === 0) {

                // No legal moves, treat as a turnover

                handleTurnover(currentPlayer === 'w' ? 'b' : 'w');

                renderBoard();

                return;

            }


            let move;

            const aiType = aiMode.includes('standard') ? 'standard' : 'random';

            

            if (aiType === 'random') {

                move = allMoves[Math.floor(Math.random() * allMoves.length)];

            } else {

                // "Standard Plays" AI

                move = findBestPlay(allMoves, currentPlayer);

            }

            

            makeMove(move.r1, move.c1, move.r2, move.c2);

            renderBoard(); // Render after AI move

            

            if (gameInProgress) {

                swapPlayer();

                triggerAI(); // Check if it's AI vs AI

            }

        }

        

        /** "Standard Plays" AI Logic */

        function findBestPlay(allMoves, player) {

            const king = player + 'K';

            const oppKing = (player === 'w' ? 'b' : 'w') + 'K';

            const oppQueen = (player === 'w' ? 'b' : 'w') + 'Q';

            const oppRook = (player === 'w' ? 'b' : 'w') + 'R';

            const endZone = (player === 'w' ? ROWS - 1 : 0);

            

            let winningMoves = [];

            let turnoverMoves = [];

            let captureQueenMoves = [];

            let captureRookMoves = [];

            let advanceKingMoves = [];

            

            for (const move of allMoves) {

                // 1. Win Now (Touchdown)

                if (move.piece === king && move.r2 === endZone) {

                    winningMoves.push(move);

                }

                // 2. Win Now (Turnover)

                if (move.target === oppKing) {

                    turnoverMoves.push(move);

                }

                // 3. Capture high-value pieces

                if (move.target === oppQueen) {

                    captureQueenMoves.push(move);

                }

                if (move.target === oppRook) {

                    captureRookMoves.push(move);

                }

                // 4. Advance the King

                if (move.piece === king) {

                    const progress = (player === 'w') ? (move.r2 - move.r1) : (move.r1 - move.r2);

                    if (progress > 0) {

                        advanceKingMoves.push(move);

                    }

                }

            }

            

            if (winningMoves.length > 0) return winningMoves[0]; // Best move!

            if (turnoverMoves.length > 0) return turnoverMoves[0]; // Second best!

            if (captureQueenMoves.length > 0) return captureQueenMoves[0];

            if (captureRookMoves.length > 0) return captureRookMoves[0];

            if (advanceKingMoves.length > 0) return advanceKingMoves[Math.floor(Math.random() * advanceKingMoves.length)]; // Pick a random King advance


            // 5. Fallback: random move

            return allMoves[Math.floor(Math.random() * allMoves.length)];

        }


        // --- UI UPDATERS ---

        

        function updateStatus(msg) {

            statusEl.textContent = msg;

        }


        function updateScoreDisplay() {

            scoreWEl.textContent = score.w;

            scoreBEl.textContent = score.b;

        }


        // --- MOVE GENERATION LOGIC ---


        /** Gets all valid moves for a given player */

        function getAllValidMoves(player) {

            let allMoves = [];

            for (let r = 0; r < ROWS; r++) {

                for (let c = 0; c < COLS; c++) {

                    const piece = boardState[r][c];

                    if (piece && piece[0] === player) {

                        const moves = getValidMoves(r, c, piece);

                        for (const move of moves) {

                            allMoves.push({

                                r1: r, c1: c,

                                r2: move.r, c2: move.c,

                                piece: piece,

                                target: boardState[move.r][move.c]

                            });

                        }

                    }

                }

            }

            return allMoves;

        }

        

        /** Gets valid moves for a single piece */

        function getValidMoves(r, c, piece) {

            const player = piece[0];

            const type = piece[1];

            let moves = [];

            

            const addMove = (r, c) => {

                if (r < 0 || r >= ROWS || c < 0 || c >= COLS) return false; // Off board

                const target = boardState[r][c];

                if (target === null) {

                    moves.push({ r, c, isCapture: false });

                    return true; // Can continue sliding

                }

                if (target[0] !== player) {

                    moves.push({ r, c, isCapture: true });

                    return false; // Can capture, but must stop

                }

                return false; // Friendly piece, stop

            };


            switch (type) {

                case 'P': // Pawn

                    const dir = (player === 'w' ? 1 : -1);

                    const rFwd = r + dir;

                    // Move forward

                    if (rFwd >= 0 && rFwd < ROWS && !boardState[rFwd][c]) {

                        moves.push({ r: rFwd, c: c, isCapture: false });

                    }

                    // Capture diagonally

                    for (let dc of [-1, 1]) {

                        const cCap = c + dc;

                        if (rFwd >= 0 && rFwd < ROWS && cCap >= 0 && cCap < COLS) {

                            const target = boardState[rFwd][cCap];

                            if (target && target[0] !== player) {

                                moves.push({ r: rFwd, c: cCap, isCapture: true });

                            }

                        }

                    }

                    // No promotion in this game

                    break;


                case 'R': // Rook

                case 'B': // Bishop

                case 'Q': // Queen

                    let dirs = [];

                    if (type === 'R' || type === 'Q') dirs.push([0, 1], [0, -1], [1, 0], [-1, 0]);

                    if (type === 'B' || type === 'Q') dirs.push([1, 1], [1, -1], [-1, 1], [-1, -1]);

                    

                    for (let [dr, dc] of dirs) {

                        for (let i = 1; ; i++) {

                            if (!addMove(r + i * dr, c + i * dc)) break;

                        }

                    }

                    break;

                    

                case 'N': // Knight

                    const knightMoves = [

                        [2, 1], [2, -1], [-2, 1], [-2, -1],

                        [1, 2], [1, -2], [-1, 2], [-1, -2]

                    ];

                    for (let [dr, dc] of knightMoves) {

                        addMove(r + dr, c + dc);

                    }

                    break;

                    

                case 'K': // King

                    for (let dr = -1; dr <= 1; dr++) {

                        for (let dc = -1; dc <= 1; dc++) {

                            if (dr === 0 && dc === 0) continue;

                            addMove(r + dr, c + dc);

                        }

                    }

                    break;

            }

            return moves;

        }


    </script>

</body>

</html>



From <https://gemini.google.com/app/e98ecf13daaec579>  Google Gemini 2.5 Pro

Comments

Popular posts from this blog

#2892 Example of ChatGPT o1 Prompt

#3105 Federal and State Spending Idiocy