- // ==UserScript==
- // @name Chess.com Bot/Cheat (by Admin0)
- // @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();
- });