- // 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.1
- // @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==
-
- // 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: <strong>" + myVars.customDepth + "</strong>";
- }
- 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 = $('<div>').attr('id', 'settingsContainer');
-
- // --- Spinner ---
- const $spinnerOverlay = $('<div>').attr('id', 'overlay').hide(); // Start hidden
- const $spinner = $('<div>'); // The actual spinner div (styled by CSS)
- $spinnerOverlay.append($spinner);
- $panel.append($spinnerOverlay);
-
- // --- Depth Section ---
- $panel.append('<h3>Engine Depth</h3>');
- const $depthDiv = $('<div>');
- $depthDiv.append(
- $('<span>').attr('id', 'depthText').html(`Current: <strong>${myVars.customDepth}</strong>`)
- );
- $depthDiv.append('<br>'); // Line break
- $depthDiv.append($('<label>').attr('for', 'customDepthInput').text('Set Depth:'));
- const $depthInput = $('<input>').attr({
- type: 'number', id: 'customDepthInput', name: 'customDepthInput',
- min: '1', max: '100', value: myVars.customDepth
- });
- $depthDiv.append($depthInput);
- $panel.append($depthDiv);
-
- // --- Game Options Section ---
- $panel.append('<h3>Game Options</h3>');
- const $optionsDiv = $('<div>');
- // Auto Run
- $optionsDiv.append(
- $('<div>').addClass('options-line').append(
- $('<input>').attr({ type: 'checkbox', id: 'autoRun', name: 'autoRun', checked: myVars.autoRun }),
- $('<label>').attr('for', 'autoRun').addClass('inline').text('Enable auto run')
- )
- );
- // Auto Move
- $optionsDiv.append(
- $('<div>').addClass('options-line').append(
- $('<input>').attr({ type: 'checkbox', id: 'autoMove', name: 'autoMove', checked: myVars.autoMove }),
- $('<label>').attr('for', 'autoMove').addClass('inline').text('Enable auto move')
- )
- );
- // Auto Match
- $optionsDiv.append(
- $('<div>').addClass('options-line').append(
- $('<input>').attr({ type: 'checkbox', id: 'autoMatch', name: 'autoMatch', checked: myVars.autoMatch }),
- $('<label>').attr('for', 'autoMatch').addClass('inline').text('Enable auto match')
- )
- );
- $panel.append($optionsDiv);
-
- // --- Delay Section ---
- $panel.append('<h3>Auto Run Delay</h3>');
- const $delayDiv = $('<div>');
- $delayDiv.append(
- $('<div>').addClass('options-line').append( // Wrap in div for spacing
- $('<label>').attr('for', 'timeDelayMin').text('Min (s):'),
- $('<input>').attr({ type: 'number', id: 'timeDelayMin', name: 'timeDelayMin', min: '0.1', step: '0.1', value: GM_getValue('delayMin', 0.1) })
- )
- );
- $delayDiv.append(
- $('<div>').addClass('options-line').append(
- $('<label>').attr('for', 'timeDelayMax').text('Max (s):'),
- $('<input>').attr({ type: 'number', id: 'timeDelayMax', name: 'timeDelayMax', min: '0.1', step: '0.1', value: GM_getValue('delayMax', 1.0) })
- )
- );
- $panel.append($delayDiv);
-
- // --- Display Section ---
- $panel.append('<h3>Display</h3>');
- const $displayDiv = $('<div>').addClass('options-line'); // Use options-line for consistency
- $displayDiv.append(
- $('<label>').attr('for', 'highlightColorInput').text('Highlight Color:'),
- $('<input>').attr({ type: 'color', id: 'highlightColorInput', name: 'highlightColorInput', value: myVars.bestMoveHighlightColor })
- );
- $panel.append($displayDiv);
-
- // --- Buttons Section ---
- $panel.append('<h3>Actions</h3>');
- // Reload Button
- const $reloadButton = $('<button>').attr({ type: 'button', name: 'reloadEngine', id: 'relEngBut' })
- .text('Reload Chess Engine');
- $panel.append($reloadButton);
- // Issue Button
- const $issueButton = $('<button>').attr({ type: 'button', name: 'isBut', id: 'isBut' })
- .text('Report an issue?');
- $panel.append($issueButton);
- // Update Button
- const $updateButton = $('<button>').attr({ type: 'button', id: 'updateScriptButton' })
- .text('Check for Updates');
- $panel.append($updateButton);
-
- // --- Append Panel to Body ---
- $('body').append($panel); // Append to body for fixed positioning
-
- // --- Attach Depth Event Listener ---
- $panel.find('#customDepthInput').on('change', function() {
- const newDepth = parseInt($(this).val(), 10);
- if (!isNaN(newDepth) && newDepth >= 1 && newDepth <= 100) {
- myVars.customDepth = newDepth;
- $panel.find('#depthText').html(`Current: <strong>${myVars.customDepth}</strong>`);
- } else {
- $(this).val(myVars.customDepth); // Reset invalid input
- }
- });
-
- // --- Attach Checkbox Event Listeners ---
- $panel.find('#autoRun').on('change', function() { myVars.autoRun = $(this).is(':checked'); console.log(`[Event] autoRun changed to: ${myVars.autoRun}`); });
- $panel.find('#autoMove').on('change', function() { myVars.autoMove = $(this).is(':checked'); console.log(`[Event] autoMove changed to: ${myVars.autoMove}`); });
- $panel.find('#autoMatch').on('change', function() { myVars.autoMatch = $(this).is(':checked'); console.log(`[Event] autoMatch changed to: ${myVars.autoMatch}`); });
-
- // --- Attach Delay Input Event Listeners ---
- $panel.find('#timeDelayMin').on('change', function() {
- let minVal = parseFloat($(this).val());
- let maxVal = parseFloat($panel.find('#timeDelayMax').val());
- if (isNaN(minVal) || minVal < 0.1) minVal = 0.1;
- if (minVal > maxVal) minVal = maxVal; // Prevent min > max
- $(this).val(minVal.toFixed(1)); // Update potentially corrected value
- GM_setValue('delayMin', minVal);
- myVars.delayMin = minVal; // Update runtime var
- console.log(`[Event] Delay Min changed to: ${minVal}`);
- });
- $panel.find('#timeDelayMax').on('change', function() {
- let maxVal = parseFloat($(this).val());
- let minVal = parseFloat($panel.find('#timeDelayMin').val());
- if (isNaN(maxVal) || maxVal < 0.1) maxVal = 0.1;
- if (maxVal < minVal) maxVal = minVal; // Prevent max < min
- $(this).val(maxVal.toFixed(1)); // Update potentially corrected value
- GM_setValue('delayMax', maxVal);
- myVars.delayMax = maxVal; // Update runtime var
- console.log(`[Event] Delay Max changed to: ${maxVal}`);
- });
-
- // --- Attach Color Picker Event Listener ---
- $panel.find('#highlightColorInput').on('change', function() {
- myVars.bestMoveHighlightColor = $(this).val();
- GM_setValue('bestMoveHighlightColor', myVars.bestMoveHighlightColor);
- console.log(`[Event] Highlight color changed to: ${myVars.bestMoveHighlightColor}`);
- });
-
- // --- Attach Button Event Listeners ---
- $panel.find('#relEngBut').on('click', myFunctions.reloadChessEngine);
- $panel.find('#isBut').on('click', () => { window.confirm('Report an issue? (External link)') ? document.location = 'mailto:example@example.com' : console.log('Issue report canceled.'); });
- $panel.find('#updateScriptButton').on('click', () => {
- const scriptPageURL = 'https://greatest.deepsurf.us/en/scripts/534105-chess-com-bot-cheat-by-admin0'; // Your script's page
- window.open(scriptPageURL, '_blank');
- console.log('Opened script page for update check:', scriptPageURL);
- });
-
- // Initialize runtime delay vars from saved values
- myVars.delayMin = parseFloat($panel.find('#timeDelayMin').val());
- myVars.delayMax = parseFloat($panel.find('#timeDelayMax').val());
-
- loaded = true;
- console.log("UI Panel Created Successfully (Step 1).");
-
- } catch (error) {
- console.error("Error loading UI (Step 1):", error);
- loaded = false; // Ensure it tries again if error occurs
- }
- }
-
- // Function to inject CSS styles for the UI panel
- myFunctions.injectStyles = function() {
- // Basic panel styles - positioning and colors
- const css = `
- #settingsContainer {
- position: fixed;
- right: 10px;
- top: 50%;
- transform: translateY(-50%);
- width: 260px; /* Back to standard width */
- max-height: 85vh;
- overflow-y: auto;
- background-color: #312e2b; /* Standard Chess.com dark bg */
- color: #cccccc; /* Standard light text */
- border: 1px solid #444; /* Standard border */
- border-radius: 6px; /* Standard radius */
- padding: 10px 15px; /* Standard padding */
- font-family: "Noto Sans", sans-serif;
- font-size: 14px;
- z-index: 9999;
- box-shadow: 0 4px 12px rgba(0,0,0,0.5); /* Standard shadow */
- user-select: none;
- transition: box-shadow 0.3s ease;
- }
- #settingsContainer:hover {
- box-shadow: 0 6px 18px rgba(0,0,0,0.6); /* Standard subtle hover */
- /* Remove scale effect */
- }
-
- /* Spinner adjustments */
- #overlay {
- position: absolute;
- top: 0; left: 0; right: 0; bottom: 0;
- background-color: rgba(49, 46, 43, 0.75); /* Match bg */
- z-index: 10000;
- display: none;
- border-radius: 6px; /* Match panel */
- }
- #overlay > div {
- position: absolute;
- top: 50%; left: 50%;
- height: 40px; width: 40px;
- margin-top: -20px; margin-left: -20px;
- border: 4px solid #888; /* Standard grey spinner */
- border-right-color: transparent;
- border-radius: 50%;
- animation: rotate 0.8s infinite linear;
- }
-
- /* Section Headings */
- #settingsContainer h3 {
- color: #ededed; /* Standard heading color */
- margin-top: 15px;
- margin-bottom: 10px;
- padding-bottom: 5px;
- border-bottom: 1px solid #444; /* Standard separator */
- font-size: 16px;
- font-weight: bold;
- letter-spacing: normal; /* Standard spacing */
- }
- #settingsContainer h3:first-of-type {
- margin-top: 0;
- }
-
- /* Input Styling */
- #settingsContainer label {
- display: block;
- margin-bottom: 3px;
- color: #cccccc; /* Standard label color */
- cursor: default;
- }
- #settingsContainer input[type="number"],
- #settingsContainer input[type="color"] {
- background-color: #444; /* Standard input bg */
- border: 1px solid #555; /* Standard input border */
- color: #ccc;
- padding: 5px;
- border-radius: 3px;
- margin-left: 5px;
- vertical-align: middle;
- }
- #settingsContainer input[type="number"] {
- width: 55px;
- }
- #settingsContainer input[type="color"] {
- width: 40px;
- height: 25px;
- padding: 1px;
- cursor: pointer;
- border-color: #555; /* Standard border */
- }
-
- /* Checkbox/Inline Label Styling */
- #settingsContainer label.inline {
- display: inline-block;
- margin-left: 5px;
- margin-bottom: 0;
- vertical-align: middle;
- font-weight: normal;
- color: #cccccc; /* Standard text color */
- cursor: pointer;
- }
- #settingsContainer input[type="checkbox"] {
- margin-right: 5px;
- vertical-align: middle;
- cursor: pointer;
- /* Revert to default checkbox appearance for better theme consistency */
- appearance: checkbox;
- background-color: initial;
- border: initial;
- width: auto;
- height: auto;
- border-radius: initial;
- position: relative;
- top: 0; /* Reset alignment */
- }
- /* Remove custom checked styles */
- /* #settingsContainer input[type="checkbox"]:checked { ... } */
- /* #settingsContainer input[type="checkbox"]:checked::after { ... } */
-
- #settingsContainer div.options-line {
- margin-bottom: 8px;
- padding: 4px 6px;
- border-radius: 4px;
- transition: background-color 0.2s ease;
- }
- #settingsContainer div.options-line:hover {
- background-color: #3c3936; /* Subtle hover */
- cursor: default;
- }
-
- /* Button Styling */
- #settingsContainer button {
- display: block;
- width: 100%;
- box-sizing: border-box;
- text-align: center;
- background-color: #81b64c; /* Adjusted Chess.com green */
- color: white;
- border: none;
- border-radius: 4px;
- padding: 8px 10px;
- margin-top: 10px;
- font-size: 14px;
- font-weight: bold;
- cursor: pointer;
- text-shadow: none;
- transition: background-color 0.2s ease;
- }
- #settingsContainer button:hover {
- background-color: #93cc5b; /* Lighter green for hover */
- box-shadow: none;
- transform: none;
- }
- #settingsContainer button:active {
- transform: none;
- box-shadow: none;
- background-color: #70a140; /* Darker green for active */
- }
-
- #settingsContainer button#isBut { /* Secondary Button */
- background-color: #555;
- margin-top: 5px;
- }
- #settingsContainer button#isBut:hover {
- background-color: #666;
- box-shadow: none;
- transform: none;
- }
- #settingsContainer button#isBut:active {
- transform: none;
- box-shadow: none;
- background-color: #4a4a4a;
- }
- `;
- const styleSheet = document.createElement("style");
- styleSheet.type = "text/css";
- styleSheet.innerText = css;
- document.head.appendChild(styleSheet);
- console.log("Injected basic bot UI styles.");
- }
-
- function other(delay){
- var endTime = Date.now() + delay;
- var timer = setInterval(()=>{
- if(Date.now() >= endTime){
- myFunctions.autoRun();
- canGo = true;
- clearInterval(timer);
- }
- },10);
- }
-
-
- async function getVersion(){
- var GF = new GreasyFork; // set upping api
- var code = await GF.get().script().code(460208); // Get code
- var version = GF.parseScriptCodeMeta(code).filter(e => e.meta === '@version')[0].value; // filtering array and getting value of @version
-
- if(currentVersion !== version){
- while(true){
- alert('UPDATE THIS SCRIPT IN ORDER TO PROCEED!');
- }
- }
- }
-
- //Removed due to script being reported. I tried to make it so people can know when bug fixes come out. Clearly people don't like that.
- //getVersion();
-
- const waitForChessBoard = setInterval(() => {
- if(loaded) {
- board = $('chess-board')[0] || $('wc-chess-board')[0];
-
- // Read delay values from myVars (set by event listeners or initial load)
- let minDel = myVars.delayMin || 0.1;
- let maxDel = myVars.delayMax || 1.0;
- // No need to check min > max here, listener handles it
- // Recalculate random delay for this interval check
- myVars.delay = Math.random() * (maxDel - minDel) + minDel;
-
- myVars.isThinking = isThinking;
- myFunctions.spinner();
-
- // Check if game has ended by looking for the game over modal
- const gameOverModal = $('.game-over-modal-content');
- if (gameOverModal.length > 0 && !myVars.gameEnded) {
- console.log("Game over detected.");
- myVars.gameEnded = true;
- myVars.hasAutoMatched = false; // Reset auto-match flag for the new game opportunity
- }
-
- // Determine whose turn it is, ONLY if the game hasn't ended
- if (!myVars.gameEnded && board && board.game) { // Check !myVars.gameEnded here
- try {
- myTurn = (board.game.getTurn() == board.game.getPlayingAs());
- } catch (e) {
- console.warn("[Turn Check] Error getting turn/playingAs:", e);
- myTurn = false;
- }
- } else {
- myTurn = false; // Not my turn if game ended or board not ready
- }
-
- } else if ($('chess-board, wc-chess-board').length > 0 && !$('#settingsContainer').length) { // Try to load if board exists and panel doesn't
- myFunctions.loadEx(); // Try loading UI if not loaded
- }
-
- // --- Logic Execution Section ---
-
- // Log current state before checks
- if (loaded && board && board.game) { // Only log if things are loaded
- console.log(`[State Check] AutoRun:${myVars.autoRun} AutoMove:${myVars.autoMove} AutoMatch:${myVars.autoMatch} MyTurn:${myTurn} GameEnded:${myVars.gameEnded} Thinking:${isThinking} CanGo:${canGo} HasAutoMatched:${myVars.hasAutoMatched}`);
- try {
- // Also log board.game state if possible
- console.log(`[Board Check] Turn: ${board.game.getTurn()}, PlayingAs: ${board.game.getPlayingAs()}, FEN: ${board.game.getFEN()}`);
- // Add specific turn/playingAs log
- console.log(`[Board Check] getPlayingAs(): ${board.game.getPlayingAs()}, getTurn(): ${board.game.getTurn()}`);
- } catch (e) {
- console.warn("[Board Check] Error getting board.game details:", e);
- }
- }
-
- // Auto Run Logic
- if(myVars.autoRun == true && canGo == true && isThinking == false && myTurn && !myVars.gameEnded){
- console.log("[Action] Triggering Auto Run..."); // Log trigger
- canGo = false;
- var currentDelay = myVars.delay != undefined ? myVars.delay * 1000 : 10;
- other(currentDelay); // Call other without depth parameter
- }
-
- // Auto Match Logic
- if (myVars.autoMatch && myVars.gameEnded && !myVars.hasAutoMatched && !myVars.isAttemptingAutoMatch) {
- console.log("[Action] Triggering Auto Match Sequence..."); // Updated log
- myFunctions.startNewGame();
- // Note: startNewGame now sets flags and manages its own state
- }
-
- }, 100); // Interval runs every 100ms
-
- myFunctions.startNewGame = function() {
- console.log("Starting new game..."); // Log from Script 2 version
- 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("Clicked New <x> min button from game-over modal.");
- myVars.hasAutoMatched = true;
- myVars.gameEnded = false; // Reset flag
- myVars.isAttemptingAutoMatch = false; // Reset flag
- return;
- }
- const newGameButton = $('.game-over-buttons-component .cc-button-component:not([aria-label="Rematch"])');
- if (newGameButton.length) {
- newGameButton[0].click();
- console.log("Clicked New <x> min button from game-over.");
- myVars.hasAutoMatched = true;
- myVars.gameEnded = false; // Reset flag
- myVars.isAttemptingAutoMatch = false; // Reset flag
- return;
- }
- const guestButton = $('#guest-button.authentication-intro-guest');
- if (guestButton.length) {
- guestButton[0].click();
- console.log("Clicked Play as Guest.");
- setTimeout(() => {
- const playButton = $('.cc-button-component.cc-button-primary.cc-button-xx-large.cc-button-full');
- if (playButton.length) {
- playButton[0].click();
- console.log("Clicked Play button after guest prompt.");
- myVars.hasAutoMatched = true;
- myVars.gameEnded = false; // Reset flag
- myVars.isAttemptingAutoMatch = false; // Reset flag
- } else {
- console.error("Play button not found after guest prompt!");
- myVars.isAttemptingAutoMatch = false; // Reset flag even on failure
- }
- }, 500);
- return; // Return after starting timeout
- }
- const newGameTab = $('[data-tab="newGame"]');
- if (newGameTab.length) {
- newGameTab[0].click();
- console.log("Clicked New Game tab.");
- setTimeout(() => {
- const playButton = $('.cc-button-component.cc-button-primary.cc-button-xx-large.cc-button-full');
- if (playButton.length) {
- playButton[0].click();
- console.log("Clicked Play button.");
- myVars.hasAutoMatched = true;
- myVars.gameEnded = false; // Reset flag
- myVars.isAttemptingAutoMatch = false; // Reset flag
- } else {
- console.error("Play button not found after clicking New Game tab!");
- myVars.isAttemptingAutoMatch = false; // Reset flag even on failure
- }
- }, 500);
- return; // Return after starting timeout
- }
-
- // If no buttons were found and clicked
- console.error("No suitable New Game button/tab found by Script 2 logic.");
- myVars.isAttemptingAutoMatch = false; // Reset flag if nothing found
- };
-
- myFunctions.highlightMove = function(bestmoveUCI) {
- // Remove previous highlights first
- $('.highlight.bro').remove();
-
- console.log(`[Highlight] Received UCI: ${bestmoveUCI}, Length: ${bestmoveUCI?.length}`); // Log input
-
- if (!bestmoveUCI || bestmoveUCI.length < 4) {
- console.error("[Highlight] Invalid UCI string received:", bestmoveUCI);
- return; // Don't proceed if UCI is bad
- }
-
- let res1 = bestmoveUCI.substring(0, 2);
- let res2 = bestmoveUCI.substring(2, 4);
- const highlightColor = myVars.bestMoveHighlightColor || '#EB6150';
-
- // --- Add coordinate translation --- START
- function translateCoords(uciSquare) {
- return uciSquare
- .replace(/^a/, "1")
- .replace(/^b/, "2")
- .replace(/^c/, "3")
- .replace(/^d/, "4")
- .replace(/^e/, "5")
- .replace(/^f/, "6")
- .replace(/^g/, "7")
- .replace(/^h/, "8");
- }
- const translatedSq1 = translateCoords(res1);
- const translatedSq2 = translateCoords(res2);
- console.log(`[Highlight] Translated: ${res1} -> ${translatedSq1}, ${res2} -> ${translatedSq2}`);
- // --- Add coordinate translation --- END
-
- try {
- console.log(`[Highlight] Highlighting TO square: ${translatedSq2}`);
- $(board.nodeName) // Use board.nodeName to be safe
- .prepend(`<div class="highlight square-${translatedSq2} bro" style="background-color: ${highlightColor}; opacity: 0.71; pointer-events: none;" data-test-element="highlight"></div>`)
- .children(':first')
- .delay(1800)
- .queue(function() { $(this).remove(); });
- } catch (e) {
- console.error(`[Highlight] Error highlighting TO square ${translatedSq2}:`, e);
- }
-
- try {
- console.log(`[Highlight] Highlighting FROM square: ${translatedSq1}`);
- $(board.nodeName)
- .prepend(`<div class="highlight square-${translatedSq1} bro" style="background-color: ${highlightColor}; opacity: 0.71; pointer-events: none;" data-test-element="highlight"></div>`)
- .children(':first')
- .delay(1800)
- .queue(function() { $(this).remove(); });
- } catch (e) {
- console.error(`[Highlight] Error highlighting FROM square ${translatedSq1}:`, e);
- }
-
- console.log("[Highlight] Finished highlighting.");
- }
-
- myFunctions.highlightThreats = function() {
- // Placeholder for the removed highlightThreats function
- };
- }
-
- //Touching below may break the script
-
- var isThinking = false
- var canGo = true;
- var myTurn = false;
- var board;
-
- window.addEventListener("load", (event) => {
- main();
- });