♟-GabiBot-: Chess Bot And ModMenu!♟ (No Key) - SYNTAX ROBUST V3 (Expanded)

GabiBot is a ModMenu (Key Removed) with Evaluation Bar and PV Display.

À partir de 2025-10-03. Voir la dernière version.

Avant de procéder à l'installation, Greasy Forkattention ce script contient des contre-fonctionnalités, qui sont là pour le bénéfice de l'auteur du script, plutôt que pour le vôtre.

Ce script n'est pleinement fonctionnel qu'une fois que vous vous serez inscrit à quelque chose, comme rejoindre un groupe, vous abonner à une chaîne ou aimer une page.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name          ♟-GabiBot-: Chess Bot And ModMenu!♟ (No Key) - SYNTAX ROBUST V3 (Expanded)
// @namespace     http://tampermonkey.net/
// @version       1.1
// @description   GabiBot is a ModMenu (Key Removed) with Evaluation Bar and PV Display.
// @author        thehackerclient (Modified & Expanded)
// @match         https://www.chess.com/play/computer
// @license       MIT
// @icon          https://www.google.com/s2/favicons?sz=64&domain=chess.com
// @grant         none
// @antifeature   membership
// ==/UserScript==

(async function() {

    // INCREASED DELAY to 5000ms (5 seconds)
    setTimeout(async function(){
        alert("Stockfish Loaded!")
        console.log("GabiBot: Starting GUI creation sequence.");

        async function startStockfish(key){
            var menuWrap = document.createElement("div")
            menuWrap.id="menuWrap"
            var menuWrapStyle = document.createElement("style")

            // *** UPDATED: Added PV Display item ***
            menuWrap.innerHTML = [
                '<div id="topText">',
                '    <a id="modTitle">-GabiBot-</a>',
                '    <a>Ctrl+B To Hide</a>',
                '</div>',
                '<div id="itemsList">',
                '    <div name="enableHack" class="listItem">',
                '        <input class="checkboxMod" type="checkbox">',
                '        <a class="itemDescription">Enable Hack: </a>',
                '        <a class="itemState">Off</a>',
                '    </div>',
                '    <div name="autoMove" class="listItem">',
                '        <input class="checkboxMod" type="checkbox">',
                '        <a class="itemDescription">Auto Move:</a>',
                '        <a class="itemState">Off</a>',
                '    </div>',
                '    <div name="botPower" class="listItem">',
                '        <input min="1" max="15" value="12" class="rangeSlider" type="range">',
                '        <a class="itemDescription">Bot Power:</a>',
                '        <a class="itemState">12</a>',
                '    </div>',
                '    <div name="autoMoveSpeed" class="listItem">',
                '        <input min="1" max="10" value="4" class="rangeSlider" type="range">',
                '        <a class="itemDescription">Auto Move Speed:</a>',
                '        <a class="itemState">3</a>',
                '    </div>',
                '    <div name="updateSpeed" class="listItem">',
                '        <input min="1" max="10" value="8" class="rangeSlider" type="range">',
                '        <a class="itemDescription">Update Speed:</a>',
                '        <a class="itemState">8</a>',
                '    </div>',
                '    <div name="currentEvaluation" class="listItem">',
                '        <a class="itemDescription">Current Evaluation:</a>',
                '        <a class="itemState">-</a>',
                '    </div>',
                '    <div name="bestMove" class="listItem">',
                '        <a class="itemDescription">Best Move:</a>',
                '        <a class="itemState">-</a>',
                '    </div>',
                '    <div name="pvDisplay" class="listItem">',
                '        <a class="itemDescription">PV (Prediction):</a>',
                '        <a class="itemState pv-text-state" title="Principal Variation">-</a>', // Use a custom class for styling PV
                '    </div>',
                '    <div name="information" class="listItem">',
                '        <a class="itemDescription">Information: </a>',
                '        <a class="itemState">GabiHarMotion (1242 Elo)</a>',
                '    </div>',
                '</div>'
            ].join('');

            // *** UPDATED: Added CSS for Evaluation Bar and PV Display ***
            menuWrapStyle.innerHTML = [
                '#menuWrap {',
                '    font-family: monospace;',
                '    border-radius: 1vh;',
                '    z-index: 1000000;',
                '    grid: none;',
                '    display: grid;',
                '    grid-template-columns: 90%;',
                '    grid-template-rows: 15% 85%;',
                '    justify-content: center;',
                '    width: 350px;',
                '    height: 400px;',
                '    position: absolute;',
                '    border: 1px solid rgb(100 100 100);',
                '    background: rgb(16, 16, 16);',
                '    opacity: 0.98;',
                '    user-select: none;',
                '    max-width: 60vw;',
                '    top: 100px;',
                '    left: 100px;',
                '}',
                // New CSS for Principal Variation text to allow long strings
                '.pv-text-state {',
                '    color: white;',
                '    margin-left: 3%;',
                '    max-width: 50%;',
                '    overflow-x: auto;',
                '    white-space: nowrap;',
                '}',
                // New CSS for the Evaluation Bar next to the board
                '#evaluationBarWrap {',
                '    position: absolute;',
                '    height: 100%;',
                '    width: 20px;',
                '    background-color: #333;',
                '    z-index: 999999;',
                '    right: -25px;',
                '    top: 0;',
                '    border-radius: 5px;',
                '    overflow: hidden;',
                '}',
                '#evaluationBar {',
                '    width: 100%;',
                '    position: absolute;',
                '    bottom: 50%;',
                '    transition: height 0.5s ease, bottom 0.5s ease;',
                '}',
                '#evaluationBar.white-advantage {',
                '    background-color: #f7d247;', /* Gold for White */
                '}',
                '#evaluationBar.black-advantage {',
                '    background-color: #3d8bff;', /* Blue for Black */
                '}',
                '#topText {',
                '    width: 40%;',
                '    justify-self: center;',
                '    text-align: center;',
                '}',
                '#modTitle {',
                '    color: white;',
                '    justify-self: center;',
                '    margin-bottom: 5%;',
                '    font-size: 17px;',
                '}',
                '#itemsList{',
                '    overflow-x: hidden;',
                '}',
                '::-webkit-scrollbar {',
                '    width: 8px;',
                '}',
                '::-webkit-scrollbar-thumb {',
                '    background: #888;',
                '    height: 10px;',
                '}',
                '.listItem {',
                '    display: flex;',
                '    align-items: center;',
                '    margin-bottom: 6%;',
                '}',
                '.checkboxMod {',
                '    outline: #acacac 1px solid;',
                '    vertical-align: middle;',
                '    appearance: none;',
                '    border-radius: 30%;',
                '    height: 20px;',
                '    width: 20px;',
                '    top: 30%;',
                '    background: #303030;',
                '    margin-right: 5%;',
                '}',
                '.checkboxMod:checked {',
                '    background-color: #808080;',
                '}',
                '.rangeSlider {',
                '    -webkit-appearance: none;',
                '    width: 45%;',
                '    height: 15px;',
                '    border-radius: 5px;',
                '    background: #b0b0b0;',
                '    outline: none;',
                '    margin-right: 6%;',
                '}',
                '.rangeSlider::-webkit-slider-thumb {',
                '    appearance: none;',
                '    width: 17px;',
                '    height: 17px;',
                '    border-radius: 50%;',
                '    background: #505050;',
                '    cursor: pointer;',
                '}',
                '.itemDescription{',
                '    color: white;',
                '}',
                '.itemState{',
                '    color: white;',
                '    margin-left: 3%;',
                '}'
            ].join('');

            document.body.appendChild(menuWrap)
            document.body.appendChild(menuWrapStyle)

            // *** UPDATED: Added new window variable for PV ***
            window.hackEnabled = 0
            window.botPower = 12
            window.updateSpeed = 8
            window.autoMove = 0
            window.autoMoveSpeed = 4
            window.currentEvaluation = 0
            window.bestMove = ""
            window.principalVariation = "" // New variable

            var itemWrap = document.getElementById("menuWrap")

            function getElementByName(name,selector){return selector.querySelector(`[name="${name}"]`)}
            function getInputElement(element){return element.children[0]}
            function getStateElement(element){return element.children[element.children.length-1]}

            function modFunction(name,type,variable){
                var modElement = getElementByName(name,itemWrap)
                var modState = getStateElement(modElement)
                var modInput = getInputElement(modElement)

                if(type=="text"){
                    // PV is often a long string, so we use the 'title' attribute for hover text
                    if(name === "pvDisplay") modState.title = eval(variable);
                    modState.innerHTML=eval(variable)
                }
                modInput.onmouseup=e=>{
                    if(e.button==0){
                        if(type=="checkbox"){
                            modState.innerHTML=["Off","On"][Number(!modInput.checked)]
                            // Robust eval syntax
                            eval(variable + "=" + !modInput.checked)
                        }
                        if(type=="range"){
                            modState.innerHTML=modInput.value
                            // Robust eval syntax
                            eval(variable + "=" + modInput.value)
                        }
                    }
                }
            }

            modFunction("enableHack","checkbox","window.hackEnabled")
            modFunction("autoMove","checkbox","window.autoMove")

            modFunction("botPower","range","window.botPower")
            modFunction("autoMoveSpeed","range","window.autoMoveSpeed")
            modFunction("updateSpeed","range","window.updateSpeed")

            function updateTexts(){
                modFunction("currentEvaluation","text","window.currentEvaluation");
                modFunction("bestMove","text","window.bestMove");
                modFunction("pvDisplay","text","window.principalVariation"); // New line for PV
                // Robust eval syntax for text
                modFunction("information","text","context.user.username + ' (' + context.user.rating + ' Elo)'");
            }

            // *** NEW FUNCTION: Update Evaluation Bar ***
            function updateEvaluationBar(evaluation, playingAs) {
                const bar = document.getElementById("evaluationBar");
                if (!bar) return;

                let score = 0;
                // Convert mate scores (M-1, M+3) to high numerical values
                if (typeof evaluation === 'string' && evaluation.includes('M')) {
                    let mateScore = parseInt(evaluation.replace('M', ''));
                    score = Math.sign(mateScore) * 1000;
                } else {
                    score = parseFloat(evaluation);
                }

                const maxScore = 8;
                let normalizedScore = Math.max(-maxScore, Math.min(maxScore, score));

                // Scale for visual effect (0-100% height)
                let height = Math.abs(normalizedScore) * (50 / maxScore);

                // If the board is flipped (playing as Black) invert the visual logic
                if (playingAs === 2) {
                    normalizedScore *= -1;
                }

                bar.style.height = `${height}%`;
                // Position: from 50% upwards for White advantage, downwards for Black advantage
                bar.style.bottom = normalizedScore > 0 ? '50%' : `${50 - height}%`;

                // Set class for color
                bar.classList.remove('white-advantage', 'black-advantage');
                if (normalizedScore > 0.5) {
                    bar.classList.add('white-advantage');
                } else if (normalizedScore < -0.5) {
                    bar.classList.add('black-advantage');
                }
            }


            var board = document.querySelector('.board');
            var drawingBoard = document.createElement("canvas");
            var drawingBoardCTX = drawingBoard.getContext("2d");

            // *** NEW HTML FOR EVAL BAR: Check for board and add bar structure ***
            if (!board) {
                console.error("GabiBot Error: Could not find the chess board element (selector: .board). The script may be outdated.");
                return;
            }

            // Add Evaluation Bar Structure
            var evalBarWrap = document.createElement("div");
            evalBarWrap.id = "evaluationBarWrap";
            var evalBar = document.createElement("div");
            evalBar.id = "evaluationBar";
            evalBarWrap.appendChild(evalBar);
            board.appendChild(evalBarWrap);
            // End Eval Bar HTML

            // Set canvas size to match the board
            drawingBoard.width=board.clientWidth;
            drawingBoard.height=board.clientHeight;
            board.appendChild(drawingBoard);

            function clear(){
                drawingBoardCTX.clearRect(0,0,board.clientWidth,board.clientHeight)
            }

            async function executeAction(bestmove){

                // Flip the drawing board if playing as Black
                if(board.game.getPlayingAs()==2){
                    drawingBoard.style.rotate="180deg"
                }else{
                    drawingBoard.style.rotate="0deg"
                }
                clear()

                console.log(bestmove)
                bestmove = bestmove.split(" ")[1] // Format: 'bestmove e2e4' -> 'e2e4'

                var tileSize = (drawingBoard.clientWidth/8)
                var letters = ["a","b","c","d","e","f","g","h"];

                // Calculate coordinates for drawing the move arrow
                var x1 = letters.indexOf(bestmove[0])+1;
                var y1 = 9-Number(bestmove[1]);
                var x2 = letters.indexOf(bestmove[2])+1;
                var y2 = 9-Number(bestmove[3]);

                // Draw the arrow
                drawingBoardCTX.beginPath();
                drawingBoardCTX.moveTo(x1*tileSize-(tileSize/2),y1*tileSize-(tileSize/2));
                drawingBoardCTX.lineTo(x2*tileSize-(tileSize/2),y2*tileSize-(tileSize/2));
                drawingBoardCTX.lineWidth=tileSize/5;
                drawingBoardCTX.strokeStyle="#00ff0050"; // Green with transparency
                drawingBoardCTX.stroke();


                if(window.autoMove){
                    setTimeout(function(){
                        // Find the move object and execute it
                        var legalMoves = game.getLegalMoves()
                        for(var i=0;i<legalMoves.length;i++){
                            if(legalMoves[i].from==bestmove.split("")[0]+bestmove.split("")[1]){
                                if(legalMoves[i].to==bestmove.split("")[2]+bestmove.split("")[3]){
                                    var move = legalMoves[i]
                                    // 'game' object is expected to be available in the global scope of chess.com
                                    game.move({
                                        ...move,
                                        promotion: 'false',
                                        animate: false,
                                        userGenerated: true
                                    });
                                }
                            }
                        }
                    },5000-window.autoMoveSpeed*500) // Speed control: faster if autoMoveSpeed is higher
                }
            }

            var updateBotRunning = false;

            async function updateBot() {
                // Throttle the update rate based on user setting (updateSpeed)
                var updateBotInterval = setTimeout(async function(){

                    updateTexts();
                    var board = document.querySelector('.board');

                    if(!window.hackEnabled) {
                        clear();
                        updateEvaluationBar(0, 1); // Reset bar
                        updateBotRunning = false;
                        clearInterval(updateBotInterval)
                        return;
                    }

                    // Check for board availability again during updates
                    if (!board || !board.game) {
                        console.error("GabiBot Warning: Board or game object is unavailable during update. Retrying...");
                        updateBot(); // Recursively retry after a small delay
                        return;
                    }

                    // *** NEW FEATURE: Game State Awareness ***
                    if (board.game.isGameOver()) {
                        var result = board.game.getGameOverReason();
                        window.currentEvaluation = `GAME OVER: ${result.toUpperCase()}`;
                        window.bestMove = "No moves possible.";
                        window.principalVariation = "Game has ended.";
                        clear(); // Clear the arrow
                        updateEvaluationBar(0, board.game.getPlayingAs()); // Reset bar
                        updateTexts(); // Update the menu
                        // Stop analysis loop until a new game starts
                        updateBotRunning = false;
                        return;
                    }
                    // *** END Game State Awareness ***

                    updateBotRunning = true;


                    // Get FEN from the chess.com game object
                    var FEN = board.game.getFEN();
                    var depth = window.botPower;

                    // Call the Stockfish API
                    // Note: The 'pv' (Principal Variation) should be returned by this API
                    let response = await fetch(`https://stockfish.online/api/s/v2.php?fen=${encodeURIComponent(FEN)}&depth=${depth}`);
                    let data = await response.json();

                    window.bestMove = data.bestmove || "Calculating...";
                    window.currentEvaluation = data.evaluation || "-";
                    // *** NEW FEATURE: Principal Variation (PV) Display ***
                    window.principalVariation = data.pv || "PV not available";

                    var bestmove = data.bestmove;

                    // *** UPDATED: Call Evaluation Bar update ***
                    var playingAs = board.game.getPlayingAs(); // 1 for White, 2 for Black
                    updateEvaluationBar(window.currentEvaluation, playingAs);


                    if (bestmove && bestmove.includes("bestmove")) {
                         executeAction(bestmove);
                    }


                    // Use requestAnimationFrame for smooth GUI updates (if any) and recursive call
                    requestAnimationFrame(()=>{
                        if (updateBotRunning) updateBot();
                    });
                },1100-(window.updateSpeed*100))
            }

            // Re-run the bot logic whenever a change event happens (like a user move)
            document.addEventListener("change", updateBot);

            // Start the bot immediately without a key check
            updateBot();


            var draggingElement = document.getElementById("modTitle")
            dragElement(itemWrap,draggingElement);

            // Function to allow the menu window to be dragged
            function dragElement(elmnt,elmnt2) {
                var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
                elmnt2.onmousedown = dragMouseDown;
                function dragMouseDown(e) {
                    e = e || window.event;
                    e.preventDefault();
                    pos3 = e.clientX;
                    pos4 = e.clientY;
                    document.onmouseup = closeDragElement;
                    document.onmousemove = elementDrag;
                }
                function elementDrag(e) {
                    e = e || window.event;
                    e.preventDefault();
                    pos1 = pos3 - e.clientX;
                    pos2 = pos4 - e.clientY;
                    pos3 = e.clientX;
                    pos4 = e.clientY;
                    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
                    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
                }
                function closeDragElement() {
                    document.onmouseup = null;
                    document.onmousemove = null;
                }
            }

            // Keyboard shortcut for menu visibility
            var menuHidden = 0
            document.addEventListener("keyup",(e)=>{
                if(e.key=="b"&&e.ctrlKey){
                    if(!menuHidden){menuWrap.style.display="none"}
                    else{menuWrap.style.display="grid"}
                    menuHidden^=1
                }
            })
        }

        // Start the bot with a dummy key (key is ignored in this version)
        await startStockfish("key_removed")

    },5000) // Initial 5 second delay to wait for chess.com to load
})();