Chess.com Bot/Cheat (by Wayron)

Chess.com Bot/Cheat that finds the best move!

Pada tanggal 19 Mei 2025. Lihat %(latest_version_link).

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 or Violentmonkey 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 Bot/Cheat (by Wayron)
// @namespace    Admin0
// @version      1.1.0
// @description  Chess.com Bot/Cheat that finds the best move!
// @author       Admin0
// @license      Chess.com Bot/Cheat © 2024 by Admin0, © All Rights Reserved
// @match        https://www.chess.com/play/*
// @match        https://www.chess.com/game/*
// @match        https://www.chess.com/puzzles/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_xmlhttpRequest
// @grant        GM_getResourceText
// @grant        GM_registerMenuCommand
// @resource     stockfish.js        https://cdnjs.cloudflare.com/ajax/libs/stockfish.js/9.0.0/stockfish.js
// @require      https://greatest.deepsurf.us/scripts/445697/code/index.js
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @run-at       document-start
// ==/UserScript==

// CLEAN REWRITE - CHESS.COM THEMED VERSION 3.0

const currentVersion = '3.0';

function main() {
    // Core variables setup
    var stockfishObjectURL;
    var engine = document.engine = {};
    var myVars = document.myVars = {};
    myVars.autoMove = GM_getValue('autoMove', false); // Load saved autoMove
    myVars.suggestMove = GM_getValue('suggestMove', false); // Load saved suggestMove
    myVars.autoMatch = GM_getValue('autoMatch', false); // Load saved autoMatch
    myVars.customDepth = GM_getValue('customDepth', 11); // Load saved depth, default to 11
    myVars.bestMoveHighlightColor = GM_getValue('bestMoveHighlightColor', '#7fa650'); // Chess.com green
    var myFunctions = document.myFunctions = {};
    var lastValue = GM_getValue('customDepth', 11); // Also initialize lastValue with saved/default depth

    // Core chess engine logic from Script3 (the working one)
    myFunctions.color = function(dat) {
        console.log("[Move] Processing:", dat);
        console.log("[Highlight] Attempting highlight on board element:", board ? board.nodeName : 'Board not found!'); // Diagnostic log
        let response = dat;
        let res1 = response.substring(0, 2); // From square
        let res2 = response.substring(2, 4); // To square

        // Execute move if auto-move is enabled
        if (myVars.autoMove === true) {
            myFunctions.movePiece(res1, res2);
        }

        // Reset thinking state
        isThinking = false;

        // Convert chess notation to Chess.com's grid system
        res1 = res1.replace(/^a/, "1")
            .replace(/^b/, "2")
            .replace(/^c/, "3")
            .replace(/^d/, "4")
            .replace(/^e/, "5")
            .replace(/^f/, "6")
            .replace(/^g/, "7")
            .replace(/^h/, "8");
        res2 = res2.replace(/^a/, "1")
            .replace(/^b/, "2")
            .replace(/^c/, "3")
            .replace(/^d/, "4")
            .replace(/^e/, "5")
            .replace(/^f/, "6")
            .replace(/^g/, "7")
            .replace(/^h/, "8");

        // Highlight destination square
        $(board.nodeName)
            .prepend('<div class="highlight square-' + res2 + ' bro" style="background-color: ' + myVars.bestMoveHighlightColor + '; opacity: 0.7;" data-test-element="highlight"></div>')
            .children(':first')
            .delay(1800)
            .queue(function() {
                $(this).remove();
            });

        // Highlight origin square
        $(board.nodeName)
            .prepend('<div class="highlight square-' + res1 + ' bro" style="background-color: ' + myVars.bestMoveHighlightColor + '; opacity: 0.7;" data-test-element="highlight"></div>')
            .children(':first')
            .delay(1800)
            .queue(function() {
                $(this).remove();
            });
    };

    // Move execution function from Script3
    myFunctions.movePiece = function(from, to) {
        console.log("[Move] Executing move from", from, "to", to);
        try {
            // Get legal moves from the game
            let legalMoves = board.game.getLegalMoves();

            // Find our move in legal moves
            for (let each = 0; each < legalMoves.length; each++) {
                if (legalMoves[each].from === from && legalMoves[each].to === to) {
                    let move = legalMoves[each];

                    // Check for promotion (pawn to last rank)
                let promotion = undefined;
                    let piece = board.game.getPiece(from);
                if (piece && piece.type === 'p' && (to[1] === '8' || to[1] === '1')) {
                        promotion = 'q'; // Default promote to queen
                        console.log("[Move] Promoting pawn to queen");
                }

                    // Execute the move
                    board.game.move({
                        from: move.from,
                        to: move.to,
                        promotion: promotion,
                        animate: false,
                        userGenerated: true
                    });
                    console.log("[Move] Executed successfully");
                    return;
                }
            }
            console.warn("[Move] No legal move found:", from, to);
        } catch (error) {
            console.error("[Move] Error executing move:", error);
        }
    };

    // Parser from Script3
    function parser(e) {
        console.log("[Engine] Message:", e.data);
        if (e.data.includes('bestmove')) {
            console.log("[Engine] Found best move:", e.data);
            myFunctions.color(e.data.split(' ')[1]);
            isThinking = false;
        }
    }

    // Engine load function from Script3
    myFunctions.loadChessEngine = function() {
        console.log("[Engine] Loading Stockfish...");
        try {
            if (!stockfishObjectURL) {
            stockfishObjectURL = URL.createObjectURL(new Blob([GM_getResourceText('stockfish.js')], {type: 'application/javascript'}));
        }

            engine.engine = new Worker(stockfishObjectURL);

            engine.engine.onmessage = e => {
                parser(e);
            };

            engine.engine.onerror = e => {
                console.error("[Engine] Error:", e);
                isThinking = false;
            };

            engine.engine.postMessage('ucinewgame');
            console.log("[Engine] Loaded successfully");
        } catch (error) {
            console.error("[Engine] Load failed:", error);
        }
    };

    // Engine reload function
    myFunctions.reloadChessEngine = function() {
        console.log("[Engine] Reloading...");
        try {
            if (engine.engine) {
                engine.engine.terminate();
            }
            isThinking = false;
            stockfishObjectURL = null; // Force recreation
            setTimeout(() => {
                myFunctions.loadChessEngine();
                console.log("[Engine] Reloaded successfully");
            }, 100);
        } catch (error) {
            console.error("[Engine] Reload failed:", error);
        }
    };

    // Run engine at specified depth
    myFunctions.runChessEngine = function(depth) {
        console.log("[Engine] Running at depth", depth);
        let fen = board.game.getFEN();
        console.log("[Engine] Position:", fen);

        engine.engine.postMessage(`position fen ${fen}`);
        isThinking = true;
        engine.engine.postMessage(`go depth ${depth}`);
        lastValue = depth;
    };

    // Auto run function
    myFunctions.autoRun = function(depth) {
        if (board.game.getTurn() == board.game.getPlayingAs()) {
            myFunctions.runChessEngine(depth || myVars.customDepth);
        }
    };

    // Function to handle delayed auto-run
    function other(delay) {
        let endTime = Date.now() + delay;
        let timer = setInterval(() => {
            if (Date.now() >= endTime) {
                myFunctions.autoRun(myVars.customDepth);
                canGo = true;
                clearInterval(timer);
            }
        }, 10);
    }

    // Auto start new game
    myFunctions.startNewGame = function() {
        console.log("[Match] Starting new game...");

        // Find New Game button in different places
        const modalNewGameButton = $('.game-over-modal-content .game-over-buttons-component .cc-button-component:not([aria-label="Rematch"])');
        if (modalNewGameButton.length) {
            modalNewGameButton[0].click();
            console.log("[Match] Clicked New Game from modal");
            myVars.hasAutoMatched = true;
            myVars.gameEnded = false;
            return;
        }

        const newGameButton = $('.game-over-buttons-component .cc-button-component:not([aria-label="Rematch"])');
        if (newGameButton.length) {
            newGameButton[0].click();
            console.log("[Match] Clicked New Game button");
            myVars.hasAutoMatched = true;
            myVars.gameEnded = false;
            return;
        }

        console.log("[Match] No New Game button found");
    };

    // Function to handle spinner visibility
    myFunctions.spinner = function() {
        if (loaded && $('#overlay').length) {
            $('#overlay').css('display', isThinking ? 'block' : 'none');
        }
    };

    // Handle keyboard shortcuts
    document.onkeydown = function(e) {
        const depthKeys = {
            81: 1, 87: 2, 69: 3, 82: 4, 84: 5, 89: 6, 85: 7, 73: 8, 79: 9, 80: 10,
            65: 11, 83: 12, 68: 13, 70: 14, 71: 15, 72: 16, 74: 17, 75: 18, 76: 19,
            90: 20, 88: 21, 67: 22, 86: 23, 66: 24, 78: 25, 77: 26, 187: 100
        };

        if (depthKeys[e.keyCode]) {
            myVars.customDepth = depthKeys[e.keyCode];
            if (loaded) {
                $('#depthValue').text(myVars.customDepth);
            }
            GM_setValue('customDepth', myVars.customDepth); // Save the new depth
            location.reload(); // Reload the page
        }

        // Toggle UI with ESC
        if (e.keyCode === 27 && loaded) {
            $('#chessBot').toggle();
        }
    };

    // UI Creation function - CHESS.COM THEMED
    var loaded = false;
    myFunctions.loadEx = function() {
        if (loaded) return;

        try {
            console.log("[UI] Creating Chess.com themed interface...");
            board = $('chess-board')[0] || $('wc-chess-board')[0];
             if (!board) {
                console.warn("[UI] Board not found yet");
                return;
             }

            myVars.board = board;

            // Create main container with Chess.com styling
            const panel = document.createElement('div');
            panel.id = 'chessBot';
            panel.style = `
    position: fixed;
                right: 20px;
    top: 50%;
    transform: translateY(-50%);
                width: 280px;
                background-color: #312e2b;
                color: #bababa;
                font-family: "Segoe UI", Arial, sans-serif;
    z-index: 9999;
                padding: 15px;
                border-radius: 5px;
                box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
                font-size: 14px;
            `;

            // Create header
            const header = document.createElement('div');
            header.style = `
                display: flex;
                justify-content: space-between;
                align-items: center;
                margin-bottom: 15px;
                border-bottom: 1px solid #464442;
                padding-bottom: 10px;
            `;

            const title = document.createElement('h2');
            title.innerText = 'Chess.com Bot';
            title.style = `
                margin: 0;
                font-size: 18px;
                font-weight: 600;
                color: #bababa;
            `;

            const version = document.createElement('span');
            version.innerText = 'v3.0';
            version.style = `
                font-size: 12px;
                opacity: 0.8;
                color: #bababa;
            `;

            header.appendChild(title);
            header.appendChild(version);
            panel.appendChild(header);

            // Create spinner overlay
            const overlay = document.createElement('div');
            overlay.id = 'overlay';
            overlay.style = `
    position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: rgba(49, 46, 43, 0.85);
    z-index: 10000;
    display: none;
                border-radius: 5px;
            `;

            const spinner = document.createElement('div');
            spinner.style = `
    position: absolute;
                top: 50%;
                left: 50%;
                width: 40px;
                height: 40px;
                margin-top: -20px;
                margin-left: -20px;
                border: 3px solid #bababa;
                border-top-color: #7fa650;
    border-radius: 50%;
                animation: spin 1s infinite linear;
            `;

            const spinStyle = document.createElement('style');
            spinStyle.textContent = `
                @keyframes spin {
                    0% { transform: rotate(0deg); }
                    100% { transform: rotate(360deg); }
                }
            `;

            document.head.appendChild(spinStyle);
            overlay.appendChild(spinner);
            panel.appendChild(overlay);

            // Create content sections
            const createSection = (title) => {
                const section = document.createElement('div');
                section.style = `
                    margin-bottom: 15px;
                `;

                const sectionTitle = document.createElement('h3');
                sectionTitle.innerText = title;
                sectionTitle.style = `
                    margin: 0 0 10px 0;
                    font-size: 16px;
                    color: #bababa;
                    border-bottom: 1px solid #464442;
                    padding-bottom: 5px;
                `;

                section.appendChild(sectionTitle);
                return section;
            };

            // Create depth section
            const depthSection = createSection('Engine Depth');

            const depthDisplay = document.createElement('div');
            depthDisplay.style = `
                display: flex;
                justify-content: space-between;
                align-items: center;
                margin-bottom: 10px;
                background-color: #3a3634;
                padding: 8px 12px;
                border-radius: 4px;
            `;

            const depthLabel = document.createElement('span');
            depthLabel.innerText = 'Current Depth:';

            const depthValue = document.createElement('span');
            depthValue.id = 'depthValue';
            depthValue.innerText = myVars.customDepth;
            depthValue.style = `
                font-weight: bold;
                color: #7fa650;
            `;

            depthDisplay.appendChild(depthLabel);
            depthDisplay.appendChild(depthValue);

            const depthInfo = document.createElement('p');
            depthInfo.innerText = 'Press A-Z keys to change depth (Q=1, W=2, etc.)';
            depthInfo.style = `
                margin: 5px 0;
                font-size: 12px;
                opacity: 0.7;
            `;

            const depthInput = document.createElement('div');
            depthInput.style = `
                display: flex;
                align-items: center;
                margin-top: 10px;
            `;

            const depthInputLabel = document.createElement('label');
            depthInputLabel.innerText = 'Set Depth:';
            depthInputLabel.style = 'margin-right: 10px;';

            const depthInputField = document.createElement('input');
            depthInputField.type = 'number';
            depthInputField.id = 'customDepthInput';
            depthInputField.min = '1';
            depthInputField.max = '100';
            depthInputField.value = myVars.customDepth;
            depthInputField.style = `
                background-color: #3a3634;
                border: 1px solid #464442;
                color: #bababa;
                padding: 5px;
                border-radius: 3px;
                width: 60px;
            `;

            depthInputField.addEventListener('change', function() {
                const value = parseInt(this.value);
                if (!isNaN(value) && value >= 1 && value <= 100) {
                    myVars.customDepth = value;
                    depthValue.innerText = value;
                    GM_setValue('customDepth', myVars.customDepth); // Save the new depth
                    location.reload(); // Reload the page
                } else {
                    this.value = GM_getValue('customDepth', 11); // Reset to saved value if input is invalid
                }
            });

            depthInput.appendChild(depthInputLabel);
            depthInput.appendChild(depthInputField);

            depthSection.appendChild(depthDisplay);
            depthSection.appendChild(depthInfo);
            depthSection.appendChild(depthInput);
            panel.appendChild(depthSection);

            // Create game options section
            const optionsSection = createSection('Game Options');

            const createCheckbox = (id, label) => {
                const container = document.createElement('div');
                container.style = `
                    display: flex;
                    align-items: center;
                    margin-bottom: 10px;
                    cursor: pointer;
                `;

                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.id = id;
                checkbox.style = `
                    margin-right: 10px;
                    cursor: pointer;
                `;

                const checkLabel = document.createElement('label');
                checkLabel.htmlFor = id;
                checkLabel.innerText = label;
                checkLabel.style = 'cursor: pointer;';

                container.appendChild(checkbox);
                container.appendChild(checkLabel);
                return container;
            };

            const autoRunCheck = createCheckbox('suggestMove', 'Enable Suggested Move');
            const autoMoveCheck = createCheckbox('autoMove', 'Enable auto move');
            const autoMatchCheck = createCheckbox('autoMatch', 'Enable auto match');

            optionsSection.appendChild(autoRunCheck);
            optionsSection.appendChild(autoMoveCheck);
            optionsSection.appendChild(autoMatchCheck);
            panel.appendChild(optionsSection);

            // Set initial state from loaded vars
            autoRunCheck.querySelector('input').checked = myVars.suggestMove;
            autoMoveCheck.querySelector('input').checked = myVars.autoMove;
            autoMatchCheck.querySelector('input').checked = myVars.autoMatch;

            // Create delay section
            const delaySection = createSection('Suggestion Delay');

            const createDelayInput = (id, label, defaultValue) => {
                const container = document.createElement('div');
                container.style = `
                    display: flex;
                    align-items: center;
                    margin-bottom: 10px;
                `;

                const inputLabel = document.createElement('label');
                inputLabel.htmlFor = id;
                inputLabel.innerText = label;
                inputLabel.style = `
                    flex: 1;
                `;

                const input = document.createElement('input');
                input.type = 'number';
                input.id = id;
                input.min = '0.1';
                input.step = '0.1';
                input.value = defaultValue;
                input.style = `
                    background-color: #3a3634;
                    border: 1px solid #464442;
                    color: #bababa;
                    padding: 5px;
                    border-radius: 3px;
                    width: 60px;
                `;

                container.appendChild(inputLabel);
                container.appendChild(input);
                return container;
            };

            const minDelayInput = createDelayInput('timeDelayMin', 'Min Delay (s):', '0.1');
            const maxDelayInput = createDelayInput('timeDelayMax', 'Max Delay (s):', '1.0');

            delaySection.appendChild(minDelayInput);
            delaySection.appendChild(maxDelayInput);
            panel.appendChild(delaySection);

            // Create display section
            const displaySection = createSection('Display');

            const colorContainer = document.createElement('div');
            colorContainer.style = `
                display: flex;
                align-items: center;
            `;

            const colorLabel = document.createElement('label');
            colorLabel.htmlFor = 'highlightColorInput';
            colorLabel.innerText = 'Highlight Color:';
            colorLabel.style = 'flex: 1;';

            const colorInput = document.createElement('input');
            colorInput.type = 'color';
            colorInput.id = 'highlightColorInput';
            colorInput.value = myVars.bestMoveHighlightColor;
            colorInput.style = `
                width: 60px;
                height: 30px;
                padding: 0;
                border: none;
                background: none;
            `;

            colorInput.addEventListener('change', function() {
                myVars.bestMoveHighlightColor = this.value;
                GM_setValue('bestMoveHighlightColor', this.value);
            });

            colorContainer.appendChild(colorLabel);
            colorContainer.appendChild(colorInput);
            displaySection.appendChild(colorContainer);
            panel.appendChild(displaySection);

            // Create buttons section
            const actionsSection = createSection('Actions');

            const createButton = (text, onClick, primary = false) => {
                const button = document.createElement('button');
                button.innerText = text;
                button.addEventListener('click', onClick);
                button.style = `
                    background-color: ${primary ? '#7fa650' : '#5d5955'};
                    color: #fff;
                    border: none;
                    padding: 10px;
                    margin-bottom: 10px;
                    border-radius: 3px;
                    width: 100%;
                    cursor: pointer;
                    font-weight: ${primary ? 'bold' : 'normal'};
                    transition: background-color 0.2s;
                `;

                button.addEventListener('mouseover', function() {
                    this.style.backgroundColor = primary ? '#8fb761' : '#6e6a66';
                });

                button.addEventListener('mouseout', function() {
                    this.style.backgroundColor = primary ? '#7fa650' : '#5d5955';
                });

                return button;
            };

            const reloadButton = createButton('Reload Chess Engine', () => myFunctions.reloadChessEngine(), true);
            const issueButton = createButton('Report an Issue', () => {
                window.open('https://greatest.deepsurf.us/en/scripts/534105-chess-com-bot-cheat-by-admin0/feedback', '_blank');
            });

            const updateButton = createButton('Check for Updates', () => {
                window.open('https://greatest.deepsurf.us/en/scripts/534105-chess-com-bot-cheat-by-admin0', '_blank');
            });

            actionsSection.appendChild(reloadButton);
            actionsSection.appendChild(issueButton);
            actionsSection.appendChild(updateButton);
            panel.appendChild(actionsSection);

            // Add drag handle
            const dragHandle = document.createElement('div');
            dragHandle.style = `
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                height: 15px;
                cursor: move;
                background-color: rgba(255, 255, 255, 0.05);
                border-top-left-radius: 5px;
                border-top-right-radius: 5px;
            `;

            // Make panel draggable
            let isDragging = false;
            let offsetX, offsetY;

            dragHandle.addEventListener('mousedown', function(e) {
                isDragging = true;
                offsetX = e.clientX - panel.getBoundingClientRect().left;
                offsetY = e.clientY - panel.getBoundingClientRect().top;
            });

            document.addEventListener('mousemove', function(e) {
                if (isDragging) {
                    panel.style.right = 'auto';
                    panel.style.top = (e.clientY - offsetY) + 'px';
                    panel.style.left = (e.clientX - offsetX) + 'px';
                    panel.style.transform = 'none';
                }
            });

            document.addEventListener('mouseup', function() {
                isDragging = false;
            });

            panel.appendChild(dragHandle);

            // Add footer
            const footer = document.createElement('div');
            footer.style = `
                margin-top: 15px;
                padding-top: 10px;
                border-top: 1px solid #464442;
                font-size: 12px;
                text-align: center;
                opacity: 0.7;
            `;

            footer.innerText = 'Press ESC to toggle interface';
            panel.appendChild(footer);

            // Append panel to body
            document.body.appendChild(panel);

            loaded = true;
            console.log("[UI] Chess.com themed interface created successfully");
        } catch (error) {
            console.error("[UI] Error creating interface:", error);
        }
    };

    // Main interval loop
    const waitForChessBoard = setInterval(() => {
        if (loaded) {
            board = $('chess-board')[0] || $('wc-chess-board')[0];

            // Read checkbox states directly from DOM
            try {
                myVars.suggestMove = document.getElementById('suggestMove').checked;
                myVars.autoMove = document.getElementById('autoMove').checked;
                myVars.autoMatch = document.getElementById('autoMatch').checked;

                // Save the current state
                GM_setValue('suggestMove', myVars.suggestMove);
                GM_setValue('autoMove', myVars.autoMove);
                GM_setValue('autoMatch', myVars.autoMatch);

                // Read delay values
                let minDelay = parseFloat(document.getElementById('timeDelayMin').value) || 0.1;
                let maxDelay = parseFloat(document.getElementById('timeDelayMax').value) || 1.0;
                myVars.delay = Math.random() * (maxDelay - minDelay) + minDelay;
            } catch (e) {
                console.warn("[UI] Error reading UI state:", e);
            }

            // Update spinner
            myVars.isThinking = isThinking;
            myFunctions.spinner();

            // Check for game over
            const gameOverModal = $('.game-over-modal-content');
            if (gameOverModal.length > 0 && !myVars.gameEnded) {
                console.log("[Game] Game over detected");
                myVars.gameEnded = true;
                myVars.hasAutoMatched = false;
            }

            // Check turn
            try {
                if (!myVars.gameEnded && board && board.game) {
                    myTurn = (board.game.getTurn() == board.game.getPlayingAs());
                } else {
                    myTurn = false;
                }
            } catch (e) {
                myTurn = false;
            }

            // Log state (for debugging)
            console.log(`[State] SuggestMove:${myVars.suggestMove} AutoMove:${myVars.autoMove} AutoMatch:${myVars.autoMatch} MyTurn:${myTurn} Thinking:${isThinking} CanGo:${canGo}`);

            // Make sure engine is loaded
            if (!engine.engine) {
                myFunctions.loadChessEngine();
            }

            // Auto Run Logic (Now Suggested Move Logic)
            if (myVars.suggestMove && canGo && !isThinking && myTurn && !myVars.gameEnded) {
                console.log("[Auto] Triggering suggested move analysis...");
                canGo = false;
                const currentDelay = myVars.delay * 1000;
                other(currentDelay);
            }

            // Auto Match Logic
            if (myVars.autoMatch && myVars.gameEnded && !myVars.hasAutoMatched) {
                console.log("[Auto] Triggering auto match...");
                myFunctions.startNewGame();
            }
        } else if ($('chess-board, wc-chess-board').length > 0) {
            // Try to load UI if not loaded yet
            myFunctions.loadEx();
        }
    }, 100);
}

// Global variables
var isThinking = false;
var canGo = true;
var myTurn = false;
var board;

// Start the script
window.addEventListener("load", (event) => {
    console.log("[Script] Chess.com Bot v3.0 starting...");
    main();
});