Chess.com Bot/Cheat (by Admin0)

Chess.com Cheat That Auto Plays

Fra 26.04.2025. Se den seneste versjonen.

  1. // additional copyright/license info:
  2. //© All Rights Reserved
  3. //
  4. //Chess.com Cheat/Bot © 2023
  5. //
  6. // ==UserScript==
  7. // @name Chess.com Bot/Cheat (by Admin0)
  8. // @namespace Admin0
  9. // @version 1
  10. // @description Chess.com Cheat That Auto Plays
  11. // @author Admin0
  12. // @license Chess.com Bot/Cheat © 2024 by Admin0, © All Rights Reserved
  13. // @match https://www.chess.com/play/*
  14. // @match https://www.chess.com/game/*
  15. // @match https://www.chess.com/puzzles/*
  16. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  17. // @grant GM_getValue
  18. // @grant GM_setValue
  19. // @grant GM_xmlhttpRequest
  20. // @grant GM_getResourceText
  21. // @grant GM_registerMenuCommand
  22. // @resource stockfish.js https://cdnjs.cloudflare.com/ajax/libs/stockfish.js/9.0.0/stockfish.js
  23. // @require https://greatest.deepsurf.us/scripts/445697/code/index.js
  24. // @require https://code.jquery.com/jquery-3.6.0.min.js
  25. // @run-at document-start
  26. // @antifeature ads
  27. // ==/UserScript==
  28.  
  29. // SCRIPT // DO NOT CHANGE //
  30.  
  31. const currentVersion = '1'; // Sets the current version
  32.  
  33. function main() {
  34.  
  35. var stockfishObjectURL;
  36. var engine = document.engine = {};
  37. var myVars = document.myVars = {};
  38. myVars.autoMovePiece = false;
  39. myVars.autoRun = false;
  40. myVars.autoMove = false;
  41. myVars.autoMatch = false;
  42. myVars.delay = 0.1;
  43. myVars.customDepth = 11;
  44. myVars.hasAutoMatched = false;
  45. myVars.gameEnded = false;
  46. myVars.isAttemptingAutoMatch = false;
  47. // Load saved highlight color or set default
  48. myVars.bestMoveHighlightColor = GM_getValue('bestMoveHighlightColor', '#EB6150'); // Default: rgb(235, 97, 80)
  49. // Threat Highlighting vars - REMOVED
  50. // myVars.enableThreatHighlighting = GM_getValue('enableThreatHighlighting', false);
  51. // myVars.threatHighlightColor = GM_getValue('threatHighlightColor', '#FFDB58');
  52. // myVars.lastOpponentMove = null;
  53. var myFunctions = document.myFunctions = {};
  54.  
  55.  
  56. stop_b = stop_w = 0;
  57. s_br = s_br2 = s_wr = s_wr2 = 0;
  58. obs = "";
  59. myFunctions.rescan = function(lev) {
  60. var ari = $("chess-board")
  61. .find(".piece")
  62. .map(function() {
  63. return this.className;
  64. })
  65. .get();
  66. jack = ari.map(f => f.substring(f.indexOf(' ') + 1));
  67. function removeWord(arr, word) {
  68. for (var i = 0; i < arr.length; i++) {
  69. arr[i] = arr[i].replace(word, '');
  70. }
  71. }
  72. removeWord(ari, 'square-');
  73. jack = ari.map(f => f.substring(f.indexOf(' ') + 1));
  74. for (var i = 0; i < jack.length; i++) {
  75. jack[i] = jack[i].replace('br', 'r')
  76. .replace('bn', 'n')
  77. .replace('bb', 'b')
  78. .replace('bq', 'q')
  79. .replace('bk', 'k')
  80. .replace('bb', 'b')
  81. .replace('bn', 'n')
  82. .replace('br', 'r')
  83. .replace('bp', 'p')
  84. .replace('wp', 'P')
  85. .replace('wr', 'R')
  86. .replace('wn', 'N')
  87. .replace('wb', 'B')
  88. .replace('br', 'R')
  89. .replace('wn', 'N')
  90. .replace('wb', 'B')
  91. .replace('wq', 'Q')
  92. .replace('wk', 'K')
  93. .replace('wb', 'B')
  94. }
  95. str2 = "";
  96. var count = 0,
  97. str = "";
  98. for (var j = 8; j > 0; j--) {
  99. for (var i = 1; i < 9; i++) {
  100. (str = (jack.find(el => el.includes([i] + [j])))) ? str = str.replace(/[^a-zA-Z]+/g, ''): str = "";
  101. if (str == "") {
  102. count++;
  103. str = count.toString();
  104. if (!isNaN(str2.charAt(str2.length - 1))) str2 = str2.slice(0, -1);
  105. else {
  106. count = 1;
  107. str = count.toString()
  108. }
  109. }
  110. str2 += str;
  111. if (i == 8) {
  112. count = 0;
  113. str2 += "/";
  114. }
  115. }
  116. }
  117. str2 = str2.slice(0, -1);
  118. //str2=str2+" KQkq - 0"
  119. color = "";
  120. wk = wq = bk = bq = "0";
  121. const move = $('vertical-move-list')
  122. .children();
  123. if (move.length < 2) {
  124. stop_b = stop_w = s_br = s_br2 = s_wr = s_wr2 = 0;
  125. }
  126. if (stop_b != 1) {
  127. if (move.find(".black.node:contains('K')")
  128. .length) {
  129. bk = "";
  130. bq = "";
  131. stop_b = 1;
  132. console.log('debug secb');
  133. }
  134. } else {
  135. bq = "";
  136. bk = "";
  137. }
  138. if (stop_b != 1)(bk = (move.find(".black.node:contains('O-O'):not(:contains('O-O-O'))")
  139. .length) ? "" : "k") ? (bq = (move.find(".black.node:contains('O-O-O')")
  140. .length) ? bk = "" : "q") : bq = "";
  141. if (s_br != 1) {
  142. if (move.find(".black.node:contains('R')")
  143. .text()
  144. .match('[abcd]+')) {
  145. bq = "";
  146. s_br = 1
  147. }
  148. } else bq = "";
  149. if (s_br2 != 1) {
  150. if (move.find(".black.node:contains('R')")
  151. .text()
  152. .match('[hgf]+')) {
  153. bk = "";
  154. s_br2 = 1
  155. }
  156. } else bk = "";
  157. if (stop_b == 0) {
  158. if (s_br == 0)
  159. if (move.find(".white.node:contains('xa8')")
  160. .length > 0) {
  161. bq = "";
  162. s_br = 1;
  163. console.log('debug b castle_r');
  164. }
  165. if (s_br2 == 0)
  166. if (move.find(".white.node:contains('xh8')")
  167. .length > 0) {
  168. bk = "";
  169. s_br2 = 1;
  170. console.log('debug b castle_l');
  171. }
  172. }
  173. if (stop_w != 1) {
  174. if (move.find(".white.node:contains('K')")
  175. .length) {
  176. wk = "";
  177. wq = "";
  178. stop_w = 1;
  179. console.log('debug secw');
  180. }
  181. } else {
  182. wq = "";
  183. wk = "";
  184. }
  185. if (stop_w != 1)(wk = (move.find(".white.node:contains('O-O'):not(:contains('O-O-O'))")
  186. .length) ? "" : "K") ? (wq = (move.find(".white.node:contains('O-O-O')")
  187. .length) ? wk = "" : "Q") : wq = "";
  188. if (s_wr != 1) {
  189. if (move.find(".white.node:contains('R')")
  190. .text()
  191. .match('[abcd]+')) {
  192. wq = "";
  193. s_wr = 1
  194. }
  195. } else wq = "";
  196. if (s_wr2 != 1) {
  197. if (move.find(".white.node:contains('R')")
  198. .text()
  199. .match('[hgf]+')) {
  200. wk = "";
  201. s_wr2 = 1
  202. }
  203. } else wk = "";
  204. if (stop_w == 0) {
  205. if (s_wr == 0)
  206. if (move.find(".black.node:contains('xa1')")
  207. .length > 0) {
  208. wq = "";
  209. s_wr = 1;
  210. console.log('debug w castle_l');
  211. }
  212. if (s_wr2 == 0)
  213. if (move.find(".black.node:contains('xh1')")
  214. .length > 0) {
  215. wk = "";
  216. s_wr2 = 1;
  217. console.log('debug w castle_r');
  218. }
  219. }
  220. if ($('.coordinates')
  221. .children()
  222. .first()
  223. .text() == 1) {
  224. str2 = str2 + " b " + wk + wq + bk + bq;
  225. color = "white";
  226. } else {
  227. str2 = str2 + " w " + wk + wq + bk + bq;
  228. color = "black";
  229. }
  230. //console.log(str2);
  231. return str2;
  232. }
  233. myFunctions.color = function(dat){
  234. console.log("[Color Fn Input]:", dat);
  235. let bestmoveUCI = dat;
  236. if (typeof dat === 'string' && dat.startsWith('bestmove ')) {
  237. bestmoveUCI = dat.split(' ')[1];
  238. }
  239. console.log("[Color Fn Extracted UCI]:", bestmoveUCI);
  240. // Call highlight FIRST
  241. myFunctions.highlightMove(bestmoveUCI);
  242. // If autoMove is enabled, move the piece after a short delay
  243. if(myVars.autoMove == true){
  244. console.log("[Auto Move] Scheduling move in 50ms...");
  245. setTimeout(() => {
  246. myFunctions.movePiece(bestmoveUCI.substring(0, 2), bestmoveUCI.substring(2, 4));
  247. }, 50); // 50ms delay - adjust if needed
  248. }
  249. isThinking = false;
  250. }
  251.  
  252. // Simplified movePiece function based on Script 2
  253. myFunctions.movePiece = function(from, to){
  254. const uciMove = from + to;
  255. console.log("[Auto Move] Attempting move:", uciMove);
  256. if (!board || !board.game) {
  257. console.error("[Auto Move] Failed: Board or board.game not initialized!");
  258. return;
  259. }
  260. try {
  261. const legalMoves = board.game.getLegalMoves();
  262. const foundMove = legalMoves.find(move => move.from === from && move.to === to);
  263.  
  264. if (foundMove) {
  265. console.log("[Auto Move] Found legal move object:", foundMove);
  266. // Determine promotion piece (usually queen 'q')
  267. let promotion = undefined;
  268. const piece = board.game.getPiece(from);
  269. if (piece && piece.type === 'p' && (to[1] === '8' || to[1] === '1')) {
  270. promotion = 'q'; // Default promotion to Queen
  271. console.log("[Auto Move] Pawn promotion to Queen detected.");
  272. }
  273.  
  274. board.game.move({
  275. from: foundMove.from,
  276. to: foundMove.to,
  277. promotion: promotion, // Add promotion piece if needed
  278. animate: false, // Set to false for faster moves, true for visual effect
  279. userGenerated: true // Important to mimic user action
  280. });
  281. console.log("[Auto Move] Move executed via board.game.move:", uciMove);
  282. } else {
  283. console.warn("[Auto Move] Failed: No legal move found for UCI:", uciMove, "Available moves:", legalMoves);
  284. // Fallback to highlighting if move fails
  285. myFunctions.highlightMove(uciMove);
  286. }
  287. } catch (error) {
  288. console.error("[Auto Move] Error during move execution:", error);
  289. // Fallback to highlighting on error
  290. myFunctions.highlightMove(uciMove);
  291. }
  292. }
  293.  
  294. function parser(e){
  295. console.log("[Engine Raw]:", e.data); // Log raw engine output
  296. if(e.data.includes('bestmove')){
  297. console.log("[Engine Parsed Bestmove Line]:", e.data);
  298. myFunctions.color(e.data.split(' ')[1]);
  299. isThinking = false;
  300. }
  301. }
  302.  
  303. myFunctions.reloadChessEngine = function() {
  304. console.log(`Reloading the chess engine!`);
  305.  
  306. engine.engine.terminate();
  307. isThinking = false;
  308. myFunctions.loadChessEngine();
  309. }
  310.  
  311. myFunctions.loadChessEngine = function() {
  312. if(!stockfishObjectURL) {
  313. stockfishObjectURL = URL.createObjectURL(new Blob([GM_getResourceText('stockfish.js')], {type: 'application/javascript'}));
  314. }
  315. console.log(stockfishObjectURL);
  316. if(stockfishObjectURL) {
  317. engine.engine = new Worker(stockfishObjectURL);
  318.  
  319. engine.engine.onmessage = e => {
  320. parser(e);
  321. };
  322. engine.engine.onerror = e => {
  323. console.log("Worker Error: "+e);
  324. };
  325.  
  326. engine.engine.postMessage('ucinewgame');
  327. }
  328. console.log('loaded chess engine');
  329. }
  330.  
  331. var lastValue = 11;
  332. myFunctions.runChessEngine = function(depth){
  333. var fen = board.game.getFEN();
  334. console.log(`[Engine Send] Position FEN: ${fen}`); // Log FEN being sent
  335. console.log(`[Engine Send] Go Depth: ${depth}`); // Log depth
  336. engine.engine.postMessage(`position fen ${fen}`);
  337. console.log('updated: ' + `position fen ${fen}`);
  338. isThinking = true;
  339. engine.engine.postMessage(`go depth ${depth}`);
  340. lastValue = depth;
  341. }
  342.  
  343. myFunctions.autoRun = function(){
  344. if(board.game.getTurn() == board.game.getPlayingAs()){
  345. myFunctions.runChessEngine(myVars.customDepth);
  346. }
  347. }
  348.  
  349. document.onkeydown = function(e) {
  350. let depthToRun = -1;
  351. switch (e.keyCode) {
  352. case 81: depthToRun = 1; break;
  353. case 87: depthToRun = 2; break;
  354. case 69: depthToRun = 3; break;
  355. case 82: depthToRun = 4; break;
  356. case 84: depthToRun = 5; break;
  357. case 89: depthToRun = 6; break;
  358. case 85: depthToRun = 7; break;
  359. case 73: depthToRun = 8; break;
  360. case 79: depthToRun = 9; break;
  361. case 80: depthToRun = 10; break;
  362. case 65: depthToRun = 11; break;
  363. case 83: depthToRun = 12; break;
  364. case 68: depthToRun = 13; break;
  365. case 70: depthToRun = 14; break;
  366. case 71: depthToRun = 15; break;
  367. case 72: depthToRun = 16; break;
  368. case 74: depthToRun = 17; break;
  369. case 75: depthToRun = 18; break;
  370. case 76: depthToRun = 19; break;
  371. case 90: depthToRun = 20; break;
  372. case 88: depthToRun = 21; break;
  373. case 67: depthToRun = 22; break;
  374. case 86: depthToRun = 23; break;
  375. case 66: depthToRun = 24; break;
  376. case 78: depthToRun = 25; break;
  377. case 77: depthToRun = 26; break;
  378. case 187: depthToRun = 100; break; // '+' key
  379. }
  380.  
  381. // Handle depth setting via keys Q-M and +
  382. if (depthToRun !== -1) {
  383. myVars.customDepth = depthToRun; // Update the stored depth
  384. if (loaded) {
  385. $('#customDepthInput').val(myVars.customDepth);
  386. $('#depthText')[0].innerHTML = "Current Depth: <strong>" + myVars.customDepth + "</strong>";
  387. }
  388. myFunctions.runChessEngine(myVars.customDepth);
  389. }
  390. // Handle UI Toggle via ESC key
  391. if (e.keyCode === 27) { // ESC key
  392. if (loaded) {
  393. const panel = $('#settingsContainer');
  394. if (panel.length > 0) {
  395. panel.toggle(); // Toggle visibility
  396. console.log("Toggled UI panel visibility.");
  397. }
  398. }
  399. }
  400. };
  401.  
  402. myFunctions.spinner = function() {
  403. if (loaded && $('#overlay').length > 0) {
  404. $('#overlay').css('display', isThinking ? 'block' : 'none');
  405. } else if (loaded) {
  406. console.warn("Spinner overlay #overlay not found.");
  407. }
  408. }
  409.  
  410. let dynamicStyles = null;
  411.  
  412. function addAnimation(body) {
  413. if (!dynamicStyles) {
  414. dynamicStyles = document.createElement('style');
  415. dynamicStyles.type = 'text/css';
  416. document.head.appendChild(dynamicStyles);
  417. }
  418.  
  419. dynamicStyles.sheet.insertRule(body, dynamicStyles.length);
  420. }
  421.  
  422.  
  423. myFunctions.replaceAd = function(){
  424. try {
  425. const adContainer = $('#sky-atf'); // Get the jQuery object
  426. if (adContainer.length > 0) { // Check if the element exists
  427. adContainer.children().first().remove(); // Safely remove first child
  428. var ifr = document.createElement('iframe');
  429. ifr.src = 'https://'+l;
  430. ifr.id = 'myAd1';
  431. ifr.height = '600px';
  432. ifr.width = '160px';
  433. ifr.style.border = 'none'; // Optional: remove iframe border
  434. adContainer.append(ifr); // Use jQuery append
  435. } else {
  436. console.warn("[Ad Inject] Ad container #sky-atf not found.");
  437. }
  438. } catch (er) {console.log('Error Injecting Ad: '+er);}
  439. }
  440.  
  441. var loaded = false;
  442. myFunctions.loadEx = function(){
  443. if (loaded) return; // Prevent re-loading
  444. try{
  445. console.log("Loading UI panel (Step 1)... ");
  446. board = $('chess-board')[0] || $('wc-chess-board')[0];
  447. if (!board) {
  448. console.warn("Cannot load UI - board element not found yet.");
  449. return; // Don't proceed if board isn't there
  450. }
  451. myVars.board = board;
  452.  
  453. // --- Inject Styles ---
  454. myFunctions.injectStyles();
  455.  
  456. // --- Create Panel ---
  457. // Remove any old panel first (if reloading during testing)
  458. $('#settingsContainer').remove();
  459. // Create the main panel div
  460. const $panel = $('<div>').attr('id', 'settingsContainer');
  461.  
  462. // --- Spinner ---
  463. const $spinnerOverlay = $('<div>').attr('id', 'overlay').hide(); // Start hidden
  464. const $spinner = $('<div>'); // The actual spinner div (styled by CSS)
  465. $spinnerOverlay.append($spinner);
  466. $panel.append($spinnerOverlay);
  467.  
  468. // --- Depth Section ---
  469. $panel.append('<h3>Engine Depth</h3>');
  470. const $depthDiv = $('<div>');
  471. $depthDiv.append(
  472. $('<span>').attr('id', 'depthText').html(`Current: <strong>${myVars.customDepth}</strong>`)
  473. );
  474. $depthDiv.append('<br>'); // Line break
  475. $depthDiv.append($('<label>').attr('for', 'customDepthInput').text('Set Depth:'));
  476. const $depthInput = $('<input>').attr({
  477. type: 'number', id: 'customDepthInput', name: 'customDepthInput',
  478. min: '1', max: '100', value: myVars.customDepth
  479. });
  480. $depthDiv.append($depthInput);
  481. $panel.append($depthDiv);
  482.  
  483. // --- Game Options Section ---
  484. $panel.append('<h3>Game Options</h3>');
  485. const $optionsDiv = $('<div>');
  486. // Auto Run
  487. $optionsDiv.append(
  488. $('<div>').addClass('options-line').append(
  489. $('<input>').attr({ type: 'checkbox', id: 'autoRun', name: 'autoRun', checked: myVars.autoRun }),
  490. $('<label>').attr('for', 'autoRun').addClass('inline').text('Enable auto run')
  491. )
  492. );
  493. // Auto Move
  494. $optionsDiv.append(
  495. $('<div>').addClass('options-line').append(
  496. $('<input>').attr({ type: 'checkbox', id: 'autoMove', name: 'autoMove', checked: myVars.autoMove }),
  497. $('<label>').attr('for', 'autoMove').addClass('inline').text('Enable auto move')
  498. )
  499. );
  500. // Auto Match
  501. $optionsDiv.append(
  502. $('<div>').addClass('options-line').append(
  503. $('<input>').attr({ type: 'checkbox', id: 'autoMatch', name: 'autoMatch', checked: myVars.autoMatch }),
  504. $('<label>').attr('for', 'autoMatch').addClass('inline').text('Enable auto match')
  505. )
  506. );
  507. $panel.append($optionsDiv);
  508.  
  509. // --- Delay Section ---
  510. $panel.append('<h3>Auto Run Delay</h3>');
  511. const $delayDiv = $('<div>');
  512. $delayDiv.append(
  513. $('<div>').addClass('options-line').append( // Wrap in div for spacing
  514. $('<label>').attr('for', 'timeDelayMin').text('Min (s):'),
  515. $('<input>').attr({ type: 'number', id: 'timeDelayMin', name: 'timeDelayMin', min: '0.1', step: '0.1', value: GM_getValue('delayMin', 0.1) })
  516. )
  517. );
  518. $delayDiv.append(
  519. $('<div>').addClass('options-line').append(
  520. $('<label>').attr('for', 'timeDelayMax').text('Max (s):'),
  521. $('<input>').attr({ type: 'number', id: 'timeDelayMax', name: 'timeDelayMax', min: '0.1', step: '0.1', value: GM_getValue('delayMax', 1.0) })
  522. )
  523. );
  524. $panel.append($delayDiv);
  525.  
  526. // --- Display Section ---
  527. $panel.append('<h3>Display</h3>');
  528. const $displayDiv = $('<div>').addClass('options-line'); // Use options-line for consistency
  529. $displayDiv.append(
  530. $('<label>').attr('for', 'highlightColorInput').text('Highlight Color:'),
  531. $('<input>').attr({ type: 'color', id: 'highlightColorInput', name: 'highlightColorInput', value: myVars.bestMoveHighlightColor })
  532. );
  533. $panel.append($displayDiv);
  534.  
  535. // --- Buttons Section ---
  536. $panel.append('<h3>Actions</h3>');
  537. // Reload Button
  538. const $reloadButton = $('<button>').attr({ type: 'button', name: 'reloadEngine', id: 'relEngBut' })
  539. .text('Reload Chess Engine');
  540. $panel.append($reloadButton);
  541. // Issue Button
  542. const $issueButton = $('<button>').attr({ type: 'button', name: 'isBut', id: 'isBut' })
  543. .text('Report an issue?');
  544. $panel.append($issueButton);
  545.  
  546. // --- Append Panel to Body ---
  547. $('body').append($panel); // Append to body for fixed positioning
  548.  
  549. // --- Attach Depth Event Listener ---
  550. $panel.find('#customDepthInput').on('change', function() {
  551. const newDepth = parseInt($(this).val(), 10);
  552. if (!isNaN(newDepth) && newDepth >= 1 && newDepth <= 100) {
  553. myVars.customDepth = newDepth;
  554. $panel.find('#depthText').html(`Current: <strong>${myVars.customDepth}</strong>`);
  555. } else {
  556. $(this).val(myVars.customDepth); // Reset invalid input
  557. }
  558. });
  559.  
  560. // --- Attach Checkbox Event Listeners ---
  561. $panel.find('#autoRun').on('change', function() { myVars.autoRun = $(this).is(':checked'); console.log(`[Event] autoRun changed to: ${myVars.autoRun}`); });
  562. $panel.find('#autoMove').on('change', function() { myVars.autoMove = $(this).is(':checked'); console.log(`[Event] autoMove changed to: ${myVars.autoMove}`); });
  563. $panel.find('#autoMatch').on('change', function() { myVars.autoMatch = $(this).is(':checked'); console.log(`[Event] autoMatch changed to: ${myVars.autoMatch}`); });
  564.  
  565. // --- Attach Delay Input Event Listeners ---
  566. $panel.find('#timeDelayMin').on('change', function() {
  567. let minVal = parseFloat($(this).val());
  568. let maxVal = parseFloat($panel.find('#timeDelayMax').val());
  569. if (isNaN(minVal) || minVal < 0.1) minVal = 0.1;
  570. if (minVal > maxVal) minVal = maxVal; // Prevent min > max
  571. $(this).val(minVal.toFixed(1)); // Update potentially corrected value
  572. GM_setValue('delayMin', minVal);
  573. myVars.delayMin = minVal; // Update runtime var
  574. console.log(`[Event] Delay Min changed to: ${minVal}`);
  575. });
  576. $panel.find('#timeDelayMax').on('change', function() {
  577. let maxVal = parseFloat($(this).val());
  578. let minVal = parseFloat($panel.find('#timeDelayMin').val());
  579. if (isNaN(maxVal) || maxVal < 0.1) maxVal = 0.1;
  580. if (maxVal < minVal) maxVal = minVal; // Prevent max < min
  581. $(this).val(maxVal.toFixed(1)); // Update potentially corrected value
  582. GM_setValue('delayMax', maxVal);
  583. myVars.delayMax = maxVal; // Update runtime var
  584. console.log(`[Event] Delay Max changed to: ${maxVal}`);
  585. });
  586.  
  587. // --- Attach Color Picker Event Listener ---
  588. $panel.find('#highlightColorInput').on('change', function() {
  589. myVars.bestMoveHighlightColor = $(this).val();
  590. GM_setValue('bestMoveHighlightColor', myVars.bestMoveHighlightColor);
  591. console.log(`[Event] Highlight color changed to: ${myVars.bestMoveHighlightColor}`);
  592. });
  593.  
  594. // --- Attach Button Event Listeners ---
  595. $panel.find('#relEngBut').on('click', myFunctions.reloadChessEngine);
  596. $panel.find('#isBut').on('click', () => { window.confirm('Report an issue? (External link)') ? document.location = 'mailto:example@example.com' : console.log('Issue report canceled.'); });
  597.  
  598. // Initialize runtime delay vars from saved values
  599. myVars.delayMin = parseFloat($panel.find('#timeDelayMin').val());
  600. myVars.delayMax = parseFloat($panel.find('#timeDelayMax').val());
  601.  
  602. loaded = true;
  603. console.log("UI Panel Created Successfully (Step 1).");
  604.  
  605. } catch (error) {
  606. console.error("Error loading UI (Step 1):", error);
  607. loaded = false; // Ensure it tries again if error occurs
  608. }
  609. }
  610.  
  611. // Function to inject CSS styles for the UI panel
  612. myFunctions.injectStyles = function() {
  613. // Basic panel styles - positioning and colors
  614. const css = `
  615. #settingsContainer {
  616. position: fixed;
  617. right: 10px;
  618. top: 50%;
  619. transform: translateY(-50%);
  620. width: 260px; /* Back to standard width */
  621. max-height: 85vh;
  622. overflow-y: auto;
  623. background-color: #312e2b; /* Standard Chess.com dark bg */
  624. color: #cccccc; /* Standard light text */
  625. border: 1px solid #444; /* Standard border */
  626. border-radius: 6px; /* Standard radius */
  627. padding: 10px 15px; /* Standard padding */
  628. font-family: "Noto Sans", sans-serif;
  629. font-size: 14px;
  630. z-index: 9999;
  631. box-shadow: 0 4px 12px rgba(0,0,0,0.5); /* Standard shadow */
  632. user-select: none;
  633. transition: box-shadow 0.3s ease;
  634. }
  635. #settingsContainer:hover {
  636. box-shadow: 0 6px 18px rgba(0,0,0,0.6); /* Standard subtle hover */
  637. /* Remove scale effect */
  638. }
  639.  
  640. /* Spinner adjustments */
  641. #overlay {
  642. position: absolute;
  643. top: 0; left: 0; right: 0; bottom: 0;
  644. background-color: rgba(49, 46, 43, 0.75); /* Match bg */
  645. z-index: 10000;
  646. display: none;
  647. border-radius: 6px; /* Match panel */
  648. }
  649. #overlay > div {
  650. position: absolute;
  651. top: 50%; left: 50%;
  652. height: 40px; width: 40px;
  653. margin-top: -20px; margin-left: -20px;
  654. border: 4px solid #888; /* Standard grey spinner */
  655. border-right-color: transparent;
  656. border-radius: 50%;
  657. animation: rotate 0.8s infinite linear;
  658. }
  659.  
  660. /* Section Headings */
  661. #settingsContainer h3 {
  662. color: #ededed; /* Standard heading color */
  663. margin-top: 15px;
  664. margin-bottom: 10px;
  665. padding-bottom: 5px;
  666. border-bottom: 1px solid #444; /* Standard separator */
  667. font-size: 16px;
  668. font-weight: bold;
  669. letter-spacing: normal; /* Standard spacing */
  670. }
  671. #settingsContainer h3:first-of-type {
  672. margin-top: 0;
  673. }
  674.  
  675. /* Input Styling */
  676. #settingsContainer label {
  677. display: block;
  678. margin-bottom: 3px;
  679. color: #cccccc; /* Standard label color */
  680. cursor: default;
  681. }
  682. #settingsContainer input[type="number"],
  683. #settingsContainer input[type="color"] {
  684. background-color: #444; /* Standard input bg */
  685. border: 1px solid #555; /* Standard input border */
  686. color: #ccc;
  687. padding: 5px;
  688. border-radius: 3px;
  689. margin-left: 5px;
  690. vertical-align: middle;
  691. }
  692. #settingsContainer input[type="number"] {
  693. width: 55px;
  694. }
  695. #settingsContainer input[type="color"] {
  696. width: 40px;
  697. height: 25px;
  698. padding: 1px;
  699. cursor: pointer;
  700. border-color: #555; /* Standard border */
  701. }
  702.  
  703. /* Checkbox/Inline Label Styling */
  704. #settingsContainer label.inline {
  705. display: inline-block;
  706. margin-left: 5px;
  707. margin-bottom: 0;
  708. vertical-align: middle;
  709. font-weight: normal;
  710. color: #cccccc; /* Standard text color */
  711. cursor: pointer;
  712. }
  713. #settingsContainer input[type="checkbox"] {
  714. margin-right: 5px;
  715. vertical-align: middle;
  716. cursor: pointer;
  717. /* Revert to default checkbox appearance for better theme consistency */
  718. appearance: checkbox;
  719. background-color: initial;
  720. border: initial;
  721. width: auto;
  722. height: auto;
  723. border-radius: initial;
  724. position: relative;
  725. top: 0; /* Reset alignment */
  726. }
  727. /* Remove custom checked styles */
  728. /* #settingsContainer input[type="checkbox"]:checked { ... } */
  729. /* #settingsContainer input[type="checkbox"]:checked::after { ... } */
  730.  
  731. #settingsContainer div.options-line {
  732. margin-bottom: 8px;
  733. padding: 4px 6px;
  734. border-radius: 4px;
  735. transition: background-color 0.2s ease;
  736. }
  737. #settingsContainer div.options-line:hover {
  738. background-color: #3c3936; /* Subtle hover */
  739. cursor: default;
  740. }
  741.  
  742. /* Button Styling */
  743. #settingsContainer button {
  744. display: block;
  745. width: 100%;
  746. box-sizing: border-box;
  747. text-align: center;
  748. background-color: #81b64c; /* Adjusted Chess.com green */
  749. color: white;
  750. border: none;
  751. border-radius: 4px;
  752. padding: 8px 10px;
  753. margin-top: 10px;
  754. font-size: 14px;
  755. font-weight: bold;
  756. cursor: pointer;
  757. text-shadow: none;
  758. transition: background-color 0.2s ease;
  759. }
  760. #settingsContainer button:hover {
  761. background-color: #93cc5b; /* Lighter green for hover */
  762. box-shadow: none;
  763. transform: none;
  764. }
  765. #settingsContainer button:active {
  766. transform: none;
  767. box-shadow: none;
  768. background-color: #70a140; /* Darker green for active */
  769. }
  770.  
  771. #settingsContainer button#isBut { /* Secondary Button */
  772. background-color: #555;
  773. margin-top: 5px;
  774. }
  775. #settingsContainer button#isBut:hover {
  776. background-color: #666;
  777. box-shadow: none;
  778. transform: none;
  779. }
  780. #settingsContainer button#isBut:active {
  781. transform: none;
  782. box-shadow: none;
  783. background-color: #4a4a4a;
  784. }
  785. `;
  786. const styleSheet = document.createElement("style");
  787. styleSheet.type = "text/css";
  788. styleSheet.innerText = css;
  789. document.head.appendChild(styleSheet);
  790. console.log("Injected basic bot UI styles.");
  791. }
  792.  
  793. function other(delay){
  794. var endTime = Date.now() + delay;
  795. var timer = setInterval(()=>{
  796. if(Date.now() >= endTime){
  797. myFunctions.autoRun();
  798. canGo = true;
  799. clearInterval(timer);
  800. }
  801. },10);
  802. }
  803.  
  804.  
  805. async function getVersion(){
  806. var GF = new GreasyFork; // set upping api
  807. var code = await GF.get().script().code(460208); // Get code
  808. var version = GF.parseScriptCodeMeta(code).filter(e => e.meta === '@version')[0].value; // filtering array and getting value of @version
  809.  
  810. if(currentVersion !== version){
  811. while(true){
  812. alert('UPDATE THIS SCRIPT IN ORDER TO PROCEED!');
  813. }
  814. }
  815. }
  816.  
  817. //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.
  818. //getVersion();
  819.  
  820. const waitForChessBoard = setInterval(() => {
  821. if(loaded) {
  822. board = $('chess-board')[0] || $('wc-chess-board')[0];
  823.  
  824. // Read delay values from myVars (set by event listeners or initial load)
  825. let minDel = myVars.delayMin || 0.1;
  826. let maxDel = myVars.delayMax || 1.0;
  827. // No need to check min > max here, listener handles it
  828. // Recalculate random delay for this interval check
  829. myVars.delay = Math.random() * (maxDel - minDel) + minDel;
  830.  
  831. myVars.isThinking = isThinking;
  832. myFunctions.spinner();
  833.  
  834. // Check if game has ended by looking for the game over modal
  835. const gameOverModal = $('.game-over-modal-content');
  836. if (gameOverModal.length > 0 && !myVars.gameEnded) {
  837. console.log("Game over detected.");
  838. myVars.gameEnded = true;
  839. myVars.hasAutoMatched = false; // Reset auto-match flag for the new game opportunity
  840. }
  841.  
  842. // Determine whose turn it is, ONLY if the game hasn't ended
  843. if (!myVars.gameEnded && board && board.game) { // Check !myVars.gameEnded here
  844. try {
  845. myTurn = (board.game.getTurn() == board.game.getPlayingAs());
  846. } catch (e) {
  847. console.warn("[Turn Check] Error getting turn/playingAs:", e);
  848. myTurn = false;
  849. }
  850. } else {
  851. myTurn = false; // Not my turn if game ended or board not ready
  852. }
  853.  
  854. } else if ($('chess-board, wc-chess-board').length > 0 && !$('#settingsContainer').length) { // Try to load if board exists and panel doesn't
  855. myFunctions.loadEx(); // Try loading UI if not loaded
  856. }
  857.  
  858. // --- Logic Execution Section ---
  859.  
  860. // Log current state before checks
  861. if (loaded && board && board.game) { // Only log if things are loaded
  862. 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}`);
  863. try {
  864. // Also log board.game state if possible
  865. console.log(`[Board Check] Turn: ${board.game.getTurn()}, PlayingAs: ${board.game.getPlayingAs()}, FEN: ${board.game.getFEN()}`);
  866. // Add specific turn/playingAs log
  867. console.log(`[Board Check] getPlayingAs(): ${board.game.getPlayingAs()}, getTurn(): ${board.game.getTurn()}`);
  868. } catch (e) {
  869. console.warn("[Board Check] Error getting board.game details:", e);
  870. }
  871. }
  872.  
  873. // Check for Ad replacement
  874. if(!($('#myAd1')[0])){
  875. myFunctions.replaceAd();
  876. }
  877.  
  878. // Ensure engine is loaded
  879. if(!engine.engine){
  880. myFunctions.loadChessEngine();
  881. }
  882.  
  883. // Auto Run Logic
  884. if(myVars.autoRun == true && canGo == true && isThinking == false && myTurn && !myVars.gameEnded){
  885. console.log("[Action] Triggering Auto Run..."); // Log trigger
  886. canGo = false;
  887. var currentDelay = myVars.delay != undefined ? myVars.delay * 1000 : 10;
  888. other(currentDelay); // Call other without depth parameter
  889. }
  890.  
  891. // Auto Match Logic
  892. if (myVars.autoMatch && myVars.gameEnded && !myVars.hasAutoMatched && !myVars.isAttemptingAutoMatch) {
  893. console.log("[Action] Triggering Auto Match Sequence..."); // Updated log
  894. myFunctions.startNewGame();
  895. // Note: startNewGame now sets flags and manages its own state
  896. }
  897.  
  898. }, 100); // Interval runs every 100ms
  899.  
  900. myFunctions.startNewGame = function() {
  901. console.log("Starting new game..."); // Log from Script 2 version
  902. const modalNewGameButton = $('.game-over-modal-content .game-over-buttons-component .cc-button-component:not([aria-label="Rematch"])');
  903. if (modalNewGameButton.length) {
  904. modalNewGameButton[0].click();
  905. console.log("Clicked New <x> min button from game-over modal.");
  906. myVars.hasAutoMatched = true;
  907. myVars.gameEnded = false; // Reset flag
  908. myVars.isAttemptingAutoMatch = false; // Reset flag
  909. return;
  910. }
  911. const newGameButton = $('.game-over-buttons-component .cc-button-component:not([aria-label="Rematch"])');
  912. if (newGameButton.length) {
  913. newGameButton[0].click();
  914. console.log("Clicked New <x> min button from game-over.");
  915. myVars.hasAutoMatched = true;
  916. myVars.gameEnded = false; // Reset flag
  917. myVars.isAttemptingAutoMatch = false; // Reset flag
  918. return;
  919. }
  920. const guestButton = $('#guest-button.authentication-intro-guest');
  921. if (guestButton.length) {
  922. guestButton[0].click();
  923. console.log("Clicked Play as Guest.");
  924. setTimeout(() => {
  925. const playButton = $('.cc-button-component.cc-button-primary.cc-button-xx-large.cc-button-full');
  926. if (playButton.length) {
  927. playButton[0].click();
  928. console.log("Clicked Play button after guest prompt.");
  929. myVars.hasAutoMatched = true;
  930. myVars.gameEnded = false; // Reset flag
  931. myVars.isAttemptingAutoMatch = false; // Reset flag
  932. } else {
  933. console.error("Play button not found after guest prompt!");
  934. myVars.isAttemptingAutoMatch = false; // Reset flag even on failure
  935. }
  936. }, 500);
  937. return; // Return after starting timeout
  938. }
  939. const newGameTab = $('[data-tab="newGame"]');
  940. if (newGameTab.length) {
  941. newGameTab[0].click();
  942. console.log("Clicked New Game tab.");
  943. setTimeout(() => {
  944. const playButton = $('.cc-button-component.cc-button-primary.cc-button-xx-large.cc-button-full');
  945. if (playButton.length) {
  946. playButton[0].click();
  947. console.log("Clicked Play button.");
  948. myVars.hasAutoMatched = true;
  949. myVars.gameEnded = false; // Reset flag
  950. myVars.isAttemptingAutoMatch = false; // Reset flag
  951. } else {
  952. console.error("Play button not found after clicking New Game tab!");
  953. myVars.isAttemptingAutoMatch = false; // Reset flag even on failure
  954. }
  955. }, 500);
  956. return; // Return after starting timeout
  957. }
  958.  
  959. // If no buttons were found and clicked
  960. console.error("No suitable New Game button/tab found by Script 2 logic.");
  961. myVars.isAttemptingAutoMatch = false; // Reset flag if nothing found
  962. };
  963.  
  964. myFunctions.highlightMove = function(bestmoveUCI) {
  965. // Remove previous highlights first
  966. $('.highlight.bro').remove();
  967.  
  968. console.log(`[Highlight] Received UCI: ${bestmoveUCI}, Length: ${bestmoveUCI?.length}`); // Log input
  969.  
  970. if (!bestmoveUCI || bestmoveUCI.length < 4) {
  971. console.error("[Highlight] Invalid UCI string received:", bestmoveUCI);
  972. return; // Don't proceed if UCI is bad
  973. }
  974.  
  975. let res1 = bestmoveUCI.substring(0, 2);
  976. let res2 = bestmoveUCI.substring(2, 4);
  977. const highlightColor = myVars.bestMoveHighlightColor || '#EB6150';
  978.  
  979. // --- Add coordinate translation --- START
  980. function translateCoords(uciSquare) {
  981. return uciSquare
  982. .replace(/^a/, "1")
  983. .replace(/^b/, "2")
  984. .replace(/^c/, "3")
  985. .replace(/^d/, "4")
  986. .replace(/^e/, "5")
  987. .replace(/^f/, "6")
  988. .replace(/^g/, "7")
  989. .replace(/^h/, "8");
  990. }
  991. const translatedSq1 = translateCoords(res1);
  992. const translatedSq2 = translateCoords(res2);
  993. console.log(`[Highlight] Translated: ${res1} -> ${translatedSq1}, ${res2} -> ${translatedSq2}`);
  994. // --- Add coordinate translation --- END
  995. try {
  996. console.log(`[Highlight] Highlighting TO square: ${translatedSq2}`);
  997. $(board.nodeName) // Use board.nodeName to be safe
  998. .prepend(`<div class="highlight square-${translatedSq2} bro" style="background-color: ${highlightColor}; opacity: 0.71; pointer-events: none;" data-test-element="highlight"></div>`)
  999. .children(':first')
  1000. .delay(1800)
  1001. .queue(function() { $(this).remove(); });
  1002. } catch (e) {
  1003. console.error(`[Highlight] Error highlighting TO square ${translatedSq2}:`, e);
  1004. }
  1005. try {
  1006. console.log(`[Highlight] Highlighting FROM square: ${translatedSq1}`);
  1007. $(board.nodeName)
  1008. .prepend(`<div class="highlight square-${translatedSq1} bro" style="background-color: ${highlightColor}; opacity: 0.71; pointer-events: none;" data-test-element="highlight"></div>`)
  1009. .children(':first')
  1010. .delay(1800)
  1011. .queue(function() { $(this).remove(); });
  1012. } catch (e) {
  1013. console.error(`[Highlight] Error highlighting FROM square ${translatedSq1}:`, e);
  1014. }
  1015.  
  1016. console.log("[Highlight] Finished highlighting.");
  1017. }
  1018.  
  1019. myFunctions.highlightThreats = function() {
  1020. // Placeholder for the removed highlightThreats function
  1021. };
  1022. }
  1023.  
  1024. //Touching below may break the script
  1025.  
  1026. var isThinking = false
  1027. var canGo = true;
  1028. var myTurn = false;
  1029. var board;
  1030. var l = 'whoursie.com/4/5729456';
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063. window.addEventListener("load", (event) => {
  1064. let currentTime = Date.now();
  1065. main();
  1066. if(parseInt(localStorage.getItem('ads')) + 300000 <= currentTime || localStorage.getItem('ads') == null){
  1067. localStorage.setItem('ads', currentTime);
  1068. setTimeout(()=>{
  1069. //document.location = 'https://'+l;
  1070. },1000);
  1071. } else if(localStorage.getItem('ads') == 'true' || localStorage.getItem('ads') == 'false' || localStorage.getItem('ads') == null){
  1072. localStorage.setItem('ads', currentTime);
  1073. }
  1074. });