// additional copyright/license info: //© All Rights Reserved // //Chess.com Cheat/Bot © 2023 by Admin0 // // ==UserScript== // @name Chess.com Bot/Cheat (by Admin0) // @namespace Admin0 // @version 2.2 // @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://greasyfork.org/scripts/445697/code/index.js // @require https://code.jquery.com/jquery-3.6.0.min.js // @run-at document-start // @downloadURL none // ==/UserScript== // SCRIPT // DO NOT CHANGE // const currentVersion = '1'; // Sets the current version function main() { var stockfishObjectURL; var engine = document.engine = {}; var myVars = document.myVars = {}; myVars.autoMovePiece = false; myVars.autoRun = false; myVars.autoMove = false; myVars.autoMatch = false; myVars.delay = 0.1; myVars.customDepth = 11; myVars.hasAutoMatched = false; myVars.gameEnded = false; myVars.isAttemptingAutoMatch = false; // Load saved highlight color or set default myVars.bestMoveHighlightColor = GM_getValue('bestMoveHighlightColor', '#EB6150'); // Default: rgb(235, 97, 80) // Threat Highlighting vars - REMOVED // myVars.enableThreatHighlighting = GM_getValue('enableThreatHighlighting', false); // myVars.threatHighlightColor = GM_getValue('threatHighlightColor', '#FFDB58'); // myVars.lastOpponentMove = null; var myFunctions = document.myFunctions = {}; stop_b = stop_w = 0; s_br = s_br2 = s_wr = s_wr2 = 0; obs = ""; myFunctions.rescan = function(lev) { var ari = $("chess-board") .find(".piece") .map(function() { return this.className; }) .get(); jack = ari.map(f => f.substring(f.indexOf(' ') + 1)); function removeWord(arr, word) { for (var i = 0; i < arr.length; i++) { arr[i] = arr[i].replace(word, ''); } } removeWord(ari, 'square-'); jack = ari.map(f => f.substring(f.indexOf(' ') + 1)); for (var i = 0; i < jack.length; i++) { jack[i] = jack[i].replace('br', 'r') .replace('bn', 'n') .replace('bb', 'b') .replace('bq', 'q') .replace('bk', 'k') .replace('bb', 'b') .replace('bn', 'n') .replace('br', 'r') .replace('bp', 'p') .replace('wp', 'P') .replace('wr', 'R') .replace('wn', 'N') .replace('wb', 'B') .replace('br', 'R') .replace('wn', 'N') .replace('wb', 'B') .replace('wq', 'Q') .replace('wk', 'K') .replace('wb', 'B') } str2 = ""; var count = 0, str = ""; for (var j = 8; j > 0; j--) { for (var i = 1; i < 9; i++) { (str = (jack.find(el => el.includes([i] + [j])))) ? str = str.replace(/[^a-zA-Z]+/g, ''): str = ""; if (str == "") { count++; str = count.toString(); if (!isNaN(str2.charAt(str2.length - 1))) str2 = str2.slice(0, -1); else { count = 1; str = count.toString() } } str2 += str; if (i == 8) { count = 0; str2 += "/"; } } } str2 = str2.slice(0, -1); //str2=str2+" KQkq - 0" color = ""; wk = wq = bk = bq = "0"; const move = $('vertical-move-list') .children(); if (move.length < 2) { stop_b = stop_w = s_br = s_br2 = s_wr = s_wr2 = 0; } if (stop_b != 1) { if (move.find(".black.node:contains('K')") .length) { bk = ""; bq = ""; stop_b = 1; console.log('debug secb'); } } else { bq = ""; bk = ""; } if (stop_b != 1)(bk = (move.find(".black.node:contains('O-O'):not(:contains('O-O-O'))") .length) ? "" : "k") ? (bq = (move.find(".black.node:contains('O-O-O')") .length) ? bk = "" : "q") : bq = ""; if (s_br != 1) { if (move.find(".black.node:contains('R')") .text() .match('[abcd]+')) { bq = ""; s_br = 1 } } else bq = ""; if (s_br2 != 1) { if (move.find(".black.node:contains('R')") .text() .match('[hgf]+')) { bk = ""; s_br2 = 1 } } else bk = ""; if (stop_b == 0) { if (s_br == 0) if (move.find(".white.node:contains('xa8')") .length > 0) { bq = ""; s_br = 1; console.log('debug b castle_r'); } if (s_br2 == 0) if (move.find(".white.node:contains('xh8')") .length > 0) { bk = ""; s_br2 = 1; console.log('debug b castle_l'); } } if (stop_w != 1) { if (move.find(".white.node:contains('K')") .length) { wk = ""; wq = ""; stop_w = 1; console.log('debug secw'); } } else { wq = ""; wk = ""; } if (stop_w != 1)(wk = (move.find(".white.node:contains('O-O'):not(:contains('O-O-O'))") .length) ? "" : "K") ? (wq = (move.find(".white.node:contains('O-O-O')") .length) ? wk = "" : "Q") : wq = ""; if (s_wr != 1) { if (move.find(".white.node:contains('R')") .text() .match('[abcd]+')) { wq = ""; s_wr = 1 } } else wq = ""; if (s_wr2 != 1) { if (move.find(".white.node:contains('R')") .text() .match('[hgf]+')) { wk = ""; s_wr2 = 1 } } else wk = ""; if (stop_w == 0) { if (s_wr == 0) if (move.find(".black.node:contains('xa1')") .length > 0) { wq = ""; s_wr = 1; console.log('debug w castle_l'); } if (s_wr2 == 0) if (move.find(".black.node:contains('xh1')") .length > 0) { wk = ""; s_wr2 = 1; console.log('debug w castle_r'); } } if ($('.coordinates') .children() .first() .text() == 1) { str2 = str2 + " b " + wk + wq + bk + bq; color = "white"; } else { str2 = str2 + " w " + wk + wq + bk + bq; color = "black"; } //console.log(str2); return str2; } myFunctions.color = function(dat){ console.log("[Color Fn Input]:", dat); let bestmoveUCI = dat; if (typeof dat === 'string' && dat.startsWith('bestmove ')) { bestmoveUCI = dat.split(' ')[1]; } console.log("[Color Fn Extracted UCI]:", bestmoveUCI); // Call highlight FIRST myFunctions.highlightMove(bestmoveUCI); // If autoMove is enabled, move the piece after a short delay if(myVars.autoMove == true){ console.log("[Auto Move] Scheduling move in 50ms..."); setTimeout(() => { myFunctions.movePiece(bestmoveUCI.substring(0, 2), bestmoveUCI.substring(2, 4)); }, 50); // 50ms delay - adjust if needed } isThinking = false; } // Simplified movePiece function based on Script 2 myFunctions.movePiece = function(from, to){ const uciMove = from + to; console.log("[Auto Move] Attempting move:", uciMove); if (!board || !board.game) { console.error("[Auto Move] Failed: Board or board.game not initialized!"); return; } try { const legalMoves = board.game.getLegalMoves(); const foundMove = legalMoves.find(move => move.from === from && move.to === to); if (foundMove) { console.log("[Auto Move] Found legal move object:", foundMove); // Determine promotion piece (usually queen 'q') let promotion = undefined; const piece = board.game.getPiece(from); if (piece && piece.type === 'p' && (to[1] === '8' || to[1] === '1')) { promotion = 'q'; // Default promotion to Queen console.log("[Auto Move] Pawn promotion to Queen detected."); } board.game.move({ from: foundMove.from, to: foundMove.to, promotion: promotion, // Add promotion piece if needed animate: false, // Set to false for faster moves, true for visual effect userGenerated: true // Important to mimic user action }); console.log("[Auto Move] Move executed via board.game.move:", uciMove); } else { console.warn("[Auto Move] Failed: No legal move found for UCI:", uciMove, "Available moves:", legalMoves); // Fallback to highlighting if move fails myFunctions.highlightMove(uciMove); } } catch (error) { console.error("[Auto Move] Error during move execution:", error); // Fallback to highlighting on error myFunctions.highlightMove(uciMove); } } function parser(e){ console.log("[Engine Raw]:", e.data); // Log raw engine output if(e.data.includes('bestmove')){ console.log("[Engine Parsed Bestmove Line]:", e.data); myFunctions.color(e.data.split(' ')[1]); isThinking = false; } } myFunctions.reloadChessEngine = function() { console.log(`Reloading the chess engine!`); engine.engine.terminate(); isThinking = false; myFunctions.loadChessEngine(); } myFunctions.loadChessEngine = function() { if(!stockfishObjectURL) { stockfishObjectURL = URL.createObjectURL(new Blob([GM_getResourceText('stockfish.js')], {type: 'application/javascript'})); } console.log(stockfishObjectURL); if(stockfishObjectURL) { engine.engine = new Worker(stockfishObjectURL); engine.engine.onmessage = e => { parser(e); }; engine.engine.onerror = e => { console.log("Worker Error: "+e); }; engine.engine.postMessage('ucinewgame'); } console.log('loaded chess engine'); } var lastValue = 11; myFunctions.runChessEngine = function(depth){ var fen = board.game.getFEN(); console.log(`[Engine Send] Position FEN: ${fen}`); // Log FEN being sent console.log(`[Engine Send] Go Depth: ${depth}`); // Log depth engine.engine.postMessage(`position fen ${fen}`); console.log('updated: ' + `position fen ${fen}`); isThinking = true; engine.engine.postMessage(`go depth ${depth}`); lastValue = depth; } myFunctions.autoRun = function(){ if(board.game.getTurn() == board.game.getPlayingAs()){ myFunctions.runChessEngine(myVars.customDepth); } } document.onkeydown = function(e) { let depthToRun = -1; switch (e.keyCode) { case 81: depthToRun = 1; break; case 87: depthToRun = 2; break; case 69: depthToRun = 3; break; case 82: depthToRun = 4; break; case 84: depthToRun = 5; break; case 89: depthToRun = 6; break; case 85: depthToRun = 7; break; case 73: depthToRun = 8; break; case 79: depthToRun = 9; break; case 80: depthToRun = 10; break; case 65: depthToRun = 11; break; case 83: depthToRun = 12; break; case 68: depthToRun = 13; break; case 70: depthToRun = 14; break; case 71: depthToRun = 15; break; case 72: depthToRun = 16; break; case 74: depthToRun = 17; break; case 75: depthToRun = 18; break; case 76: depthToRun = 19; break; case 90: depthToRun = 20; break; case 88: depthToRun = 21; break; case 67: depthToRun = 22; break; case 86: depthToRun = 23; break; case 66: depthToRun = 24; break; case 78: depthToRun = 25; break; case 77: depthToRun = 26; break; case 187: depthToRun = 100; break; // '+' key } // Handle depth setting via keys Q-M and + if (depthToRun !== -1) { myVars.customDepth = depthToRun; // Update the stored depth if (loaded) { $('#customDepthInput').val(myVars.customDepth); $('#depthText')[0].innerHTML = "Current Depth: " + myVars.customDepth + ""; } myFunctions.runChessEngine(myVars.customDepth); } // Handle UI Toggle via ESC key if (e.keyCode === 27) { // ESC key if (loaded) { const panel = $('#settingsContainer'); if (panel.length > 0) { panel.toggle(); // Toggle visibility console.log("Toggled UI panel visibility."); } } } }; myFunctions.spinner = function() { if (loaded && $('#overlay').length > 0) { $('#overlay').css('display', isThinking ? 'block' : 'none'); } else if (loaded) { console.warn("Spinner overlay #overlay not found."); } } let dynamicStyles = null; function addAnimation(body) { if (!dynamicStyles) { dynamicStyles = document.createElement('style'); dynamicStyles.type = 'text/css'; document.head.appendChild(dynamicStyles); } dynamicStyles.sheet.insertRule(body, dynamicStyles.length); } myFunctions.replaceAd = function(){ // Removed ad replacement logic } var loaded = false; myFunctions.loadEx = function(){ if (loaded) return; // Prevent re-loading try{ console.log("Loading UI panel (Step 1)... "); board = $('chess-board')[0] || $('wc-chess-board')[0]; if (!board) { console.warn("Cannot load UI - board element not found yet."); return; // Don't proceed if board isn't there } myVars.board = board; // --- Inject Styles --- myFunctions.injectStyles(); // --- Create Panel --- // Remove any old panel first (if reloading during testing) $('#settingsContainer').remove(); // Create the main panel div const $panel = $('
').attr('id', 'settingsContainer'); // --- Spinner --- const $spinnerOverlay = $('
').attr('id', 'overlay').hide(); // Start hidden const $spinner = $('
'); // The actual spinner div (styled by CSS) $spinnerOverlay.append($spinner); $panel.append($spinnerOverlay); // --- Depth Section --- $panel.append('

Engine Depth

'); const $depthDiv = $('
'); $depthDiv.append( $('').attr('id', 'depthText').html(`Current: ${myVars.customDepth}`) ); $depthDiv.append('
'); // Line break $depthDiv.append($('