Chess.com Stockfish UI + Auto-Move

Enhance Chess.com with Stockfish analysis and optional auto-move functionality with a UI to control it.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Chess.com Stockfish UI + Auto-Move
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Enhance Chess.com with Stockfish analysis and optional auto-move functionality with a UI to control it.
// @author       YourName
// @match        *://www.chess.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=chess.com
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // URL for Stockfish WASM (WebAssembly) binary
    const stockfishURL = "https://cdn.jsdelivr.net/gh/nmrugg/stockfish.wasm/stockfish.wasm";

    // Create Stockfish Worker
    let stockfish = new Worker(stockfishURL);
    let isAutoMoveEnabled = false;
    let lastAnalyzedPosition = "";

    // Add a basic user interface (UI)
    const uiContainer = document.createElement("div");
    uiContainer.id = "stockfish-ui";
    uiContainer.style.position = "fixed";
    uiContainer.style.bottom = "20px";
    uiContainer.style.right = "20px";
    uiContainer.style.backgroundColor = "white";
    uiContainer.style.border = "1px solid black";
    uiContainer.style.borderRadius = "8px";
    uiContainer.style.padding = "10px";
    uiContainer.style.zIndex = "9999";
    uiContainer.style.boxShadow = "0 4px 6px rgba(0, 0, 0, 0.1)";
    uiContainer.innerHTML = `
        <h4>Stockfish UI</h4>
        <button id="analyze-btn">Analyze Position</button><br><br>
        <label>
            <input type="checkbox" id="auto-move-toggle">
            Enable Auto-Move
        </label>
        <p id="best-move-display" style="margin-top: 10px;">Best Move: (pending)</p>
    `;
    document.body.appendChild(uiContainer);

    // Get UI elements
    const analyzeButton = document.getElementById("analyze-btn");
    const autoMoveToggle = document.getElementById("auto-move-toggle");
    const bestMoveDisplay = document.getElementById("best-move-display");

    // Setup Stockfish interaction
    stockfish.onmessage = function (event) {
        const message = event.data;

        if (message.startsWith("bestmove")) {
            const move = message.split(" ")[1];
            console.log("Best move:", move);

            // Display the best move in the UI
            bestMoveDisplay.textContent = `Best Move: ${move}`;

            // If auto-move is enabled, execute the move
            if (isAutoMoveEnabled) {
                automove(move);
            }
        }
    };

    // Analyze the current board position
    function analyzePosition() {
        const fen = getFEN();
        if (!fen) {
            alert("Could not detect the board state (FEN). Ensure you're on an active game!");
            return;
        }

        if (fen === lastAnalyzedPosition) {
            console.log("Position has not changed, skipping analysis.");
            return;
        }

        lastAnalyzedPosition = fen;
        console.log(`Analyzing FEN: ${fen}`);

        stockfish.postMessage(`position fen ${fen}`);
        stockfish.postMessage("go depth 20");
    }

    // Fetch the current FEN (board position) from Chess.com
    function getFEN() {
        // Locate the FEN element from the HTML structure
        const fenContainer = document.querySelector('chess-board');
        const fen = fenContainer ? fenContainer.getAttribute('data-fen') : null;
        return fen;
    }

    // Simulate the move on the chessboard in Chess.com
    function automove(move) {
        console.log(`Attempting to auto-move: ${move}`);
        const fromSquare = move.slice(0, 2); // e.g., "e2"
        const toSquare = move.slice(2, 4); // e.g., "e4"

        const fromElement = document.querySelector(`[data-square='${fromSquare}']`);
        const toElement = document.querySelector(`[data-square='${toSquare}']`);

        if (fromElement && toElement) {
            console.log("Executing move:", fromSquare, toSquare);
            fromElement.click(); // Select the piece
            toElement.click(); // Move it to the target square
        } else {
            console.error("Could not find squares for auto-move.");
        }
    }

    // Event listeners for the UI
    analyzeButton.addEventListener("click", () => {
        analyzePosition();
    });

    autoMoveToggle.addEventListener("change", (event) => {
        isAutoMoveEnabled = event.target.checked;
        console.log("Auto-Move Enabled:", isAutoMoveEnabled);
    });

    console.log("Stockfish Auto-Move UI script loaded!");
})();