Greasy Fork is available in English.

Chess.com Bot/Cheat (by Admin0)

Chess.com Bot/Cheat that finds the best move!

  1. // ==UserScript==
  2. // @name Chess.com Bot/Cheat (by Admin0)
  3. // @namespace Admin0
  4. // @version 1.1.0
  5. // @description Chess.com Bot/Cheat that finds the best move!
  6. // @author Admin0
  7. // @license Chess.com Bot/Cheat © 2024 by Admin0, © All Rights Reserved
  8. // @match https://www.chess.com/play/*
  9. // @match https://www.chess.com/game/*
  10. // @match https://www.chess.com/puzzles/*
  11. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @grant GM_xmlhttpRequest
  15. // @grant GM_getResourceText
  16. // @grant GM_registerMenuCommand
  17. // @resource stockfish.js https://cdnjs.cloudflare.com/ajax/libs/stockfish.js/9.0.0/stockfish.js
  18. // @require https://greatest.deepsurf.us/scripts/445697/code/index.js
  19. // @require https://code.jquery.com/jquery-3.6.0.min.js
  20. // @run-at document-start
  21. // ==/UserScript==
  22.  
  23. // CLEAN REWRITE - CHESS.COM THEMED VERSION 3.0
  24.  
  25. const currentVersion = '3.0';
  26.  
  27. function main() {
  28. // Core variables setup
  29. var stockfishObjectURL;
  30. var engine = document.engine = {};
  31. var myVars = document.myVars = {};
  32. myVars.autoMove = GM_getValue('autoMove', false); // Load saved autoMove
  33. myVars.suggestMove = GM_getValue('suggestMove', false); // Load saved suggestMove
  34. myVars.autoMatch = GM_getValue('autoMatch', false); // Load saved autoMatch
  35. myVars.customDepth = GM_getValue('customDepth', 11); // Load saved depth, default to 11
  36. myVars.bestMoveHighlightColor = GM_getValue('bestMoveHighlightColor', '#7fa650'); // Chess.com green
  37. var myFunctions = document.myFunctions = {};
  38. var lastValue = GM_getValue('customDepth', 11); // Also initialize lastValue with saved/default depth
  39.  
  40. // Core chess engine logic from Script3 (the working one)
  41. myFunctions.color = function(dat) {
  42. console.log("[Move] Processing:", dat);
  43. console.log("[Highlight] Attempting highlight on board element:", board ? board.nodeName : 'Board not found!'); // Diagnostic log
  44. let response = dat;
  45. let res1 = response.substring(0, 2); // From square
  46. let res2 = response.substring(2, 4); // To square
  47.  
  48. // Execute move if auto-move is enabled
  49. if (myVars.autoMove === true) {
  50. myFunctions.movePiece(res1, res2);
  51. }
  52.  
  53. // Reset thinking state
  54. isThinking = false;
  55.  
  56. // Convert chess notation to Chess.com's grid system
  57. res1 = res1.replace(/^a/, "1")
  58. .replace(/^b/, "2")
  59. .replace(/^c/, "3")
  60. .replace(/^d/, "4")
  61. .replace(/^e/, "5")
  62. .replace(/^f/, "6")
  63. .replace(/^g/, "7")
  64. .replace(/^h/, "8");
  65. res2 = res2.replace(/^a/, "1")
  66. .replace(/^b/, "2")
  67. .replace(/^c/, "3")
  68. .replace(/^d/, "4")
  69. .replace(/^e/, "5")
  70. .replace(/^f/, "6")
  71. .replace(/^g/, "7")
  72. .replace(/^h/, "8");
  73.  
  74. // Highlight destination square
  75. $(board.nodeName)
  76. .prepend('<div class="highlight square-' + res2 + ' bro" style="background-color: ' + myVars.bestMoveHighlightColor + '; opacity: 0.7;" data-test-element="highlight"></div>')
  77. .children(':first')
  78. .delay(1800)
  79. .queue(function() {
  80. $(this).remove();
  81. });
  82.  
  83. // Highlight origin square
  84. $(board.nodeName)
  85. .prepend('<div class="highlight square-' + res1 + ' bro" style="background-color: ' + myVars.bestMoveHighlightColor + '; opacity: 0.7;" data-test-element="highlight"></div>')
  86. .children(':first')
  87. .delay(1800)
  88. .queue(function() {
  89. $(this).remove();
  90. });
  91. };
  92.  
  93. // Move execution function from Script3
  94. myFunctions.movePiece = function(from, to) {
  95. console.log("[Move] Executing move from", from, "to", to);
  96. try {
  97. // Get legal moves from the game
  98. let legalMoves = board.game.getLegalMoves();
  99.  
  100. // Find our move in legal moves
  101. for (let each = 0; each < legalMoves.length; each++) {
  102. if (legalMoves[each].from === from && legalMoves[each].to === to) {
  103. let move = legalMoves[each];
  104.  
  105. // Check for promotion (pawn to last rank)
  106. let promotion = undefined;
  107. let piece = board.game.getPiece(from);
  108. if (piece && piece.type === 'p' && (to[1] === '8' || to[1] === '1')) {
  109. promotion = 'q'; // Default promote to queen
  110. console.log("[Move] Promoting pawn to queen");
  111. }
  112.  
  113. // Execute the move
  114. board.game.move({
  115. from: move.from,
  116. to: move.to,
  117. promotion: promotion,
  118. animate: false,
  119. userGenerated: true
  120. });
  121. console.log("[Move] Executed successfully");
  122. return;
  123. }
  124. }
  125. console.warn("[Move] No legal move found:", from, to);
  126. } catch (error) {
  127. console.error("[Move] Error executing move:", error);
  128. }
  129. };
  130.  
  131. // Parser from Script3
  132. function parser(e) {
  133. console.log("[Engine] Message:", e.data);
  134. if (e.data.includes('bestmove')) {
  135. console.log("[Engine] Found best move:", e.data);
  136. myFunctions.color(e.data.split(' ')[1]);
  137. isThinking = false;
  138. }
  139. }
  140.  
  141. // Engine load function from Script3
  142. myFunctions.loadChessEngine = function() {
  143. console.log("[Engine] Loading Stockfish...");
  144. try {
  145. if (!stockfishObjectURL) {
  146. stockfishObjectURL = URL.createObjectURL(new Blob([GM_getResourceText('stockfish.js')], {type: 'application/javascript'}));
  147. }
  148.  
  149. engine.engine = new Worker(stockfishObjectURL);
  150.  
  151. engine.engine.onmessage = e => {
  152. parser(e);
  153. };
  154.  
  155. engine.engine.onerror = e => {
  156. console.error("[Engine] Error:", e);
  157. isThinking = false;
  158. };
  159.  
  160. engine.engine.postMessage('ucinewgame');
  161. console.log("[Engine] Loaded successfully");
  162. } catch (error) {
  163. console.error("[Engine] Load failed:", error);
  164. }
  165. };
  166.  
  167. // Engine reload function
  168. myFunctions.reloadChessEngine = function() {
  169. console.log("[Engine] Reloading...");
  170. try {
  171. if (engine.engine) {
  172. engine.engine.terminate();
  173. }
  174. isThinking = false;
  175. stockfishObjectURL = null; // Force recreation
  176. setTimeout(() => {
  177. myFunctions.loadChessEngine();
  178. console.log("[Engine] Reloaded successfully");
  179. }, 100);
  180. } catch (error) {
  181. console.error("[Engine] Reload failed:", error);
  182. }
  183. };
  184.  
  185. // Run engine at specified depth
  186. myFunctions.runChessEngine = function(depth) {
  187. console.log("[Engine] Running at depth", depth);
  188. let fen = board.game.getFEN();
  189. console.log("[Engine] Position:", fen);
  190.  
  191. engine.engine.postMessage(`position fen ${fen}`);
  192. isThinking = true;
  193. engine.engine.postMessage(`go depth ${depth}`);
  194. lastValue = depth;
  195. };
  196.  
  197. // Auto run function
  198. myFunctions.autoRun = function(depth) {
  199. if (board.game.getTurn() == board.game.getPlayingAs()) {
  200. myFunctions.runChessEngine(depth || myVars.customDepth);
  201. }
  202. };
  203.  
  204. // Function to handle delayed auto-run
  205. function other(delay) {
  206. let endTime = Date.now() + delay;
  207. let timer = setInterval(() => {
  208. if (Date.now() >= endTime) {
  209. myFunctions.autoRun(myVars.customDepth);
  210. canGo = true;
  211. clearInterval(timer);
  212. }
  213. }, 10);
  214. }
  215.  
  216. // Auto start new game
  217. myFunctions.startNewGame = function() {
  218. console.log("[Match] Starting new game...");
  219.  
  220. // Find New Game button in different places
  221. const modalNewGameButton = $('.game-over-modal-content .game-over-buttons-component .cc-button-component:not([aria-label="Rematch"])');
  222. if (modalNewGameButton.length) {
  223. modalNewGameButton[0].click();
  224. console.log("[Match] Clicked New Game from modal");
  225. myVars.hasAutoMatched = true;
  226. myVars.gameEnded = false;
  227. return;
  228. }
  229.  
  230. const newGameButton = $('.game-over-buttons-component .cc-button-component:not([aria-label="Rematch"])');
  231. if (newGameButton.length) {
  232. newGameButton[0].click();
  233. console.log("[Match] Clicked New Game button");
  234. myVars.hasAutoMatched = true;
  235. myVars.gameEnded = false;
  236. return;
  237. }
  238.  
  239. console.log("[Match] No New Game button found");
  240. };
  241.  
  242. // Function to handle spinner visibility
  243. myFunctions.spinner = function() {
  244. if (loaded && $('#overlay').length) {
  245. $('#overlay').css('display', isThinking ? 'block' : 'none');
  246. }
  247. };
  248.  
  249. // Handle keyboard shortcuts
  250. document.onkeydown = function(e) {
  251. const depthKeys = {
  252. 81: 1, 87: 2, 69: 3, 82: 4, 84: 5, 89: 6, 85: 7, 73: 8, 79: 9, 80: 10,
  253. 65: 11, 83: 12, 68: 13, 70: 14, 71: 15, 72: 16, 74: 17, 75: 18, 76: 19,
  254. 90: 20, 88: 21, 67: 22, 86: 23, 66: 24, 78: 25, 77: 26, 187: 100
  255. };
  256.  
  257. if (depthKeys[e.keyCode]) {
  258. myVars.customDepth = depthKeys[e.keyCode];
  259. if (loaded) {
  260. $('#depthValue').text(myVars.customDepth);
  261. }
  262. GM_setValue('customDepth', myVars.customDepth); // Save the new depth
  263. location.reload(); // Reload the page
  264. }
  265.  
  266. // Toggle UI with ESC
  267. if (e.keyCode === 27 && loaded) {
  268. $('#chessBot').toggle();
  269. }
  270. };
  271.  
  272. // UI Creation function - CHESS.COM THEMED
  273. var loaded = false;
  274. myFunctions.loadEx = function() {
  275. if (loaded) return;
  276.  
  277. try {
  278. console.log("[UI] Creating Chess.com themed interface...");
  279. board = $('chess-board')[0] || $('wc-chess-board')[0];
  280. if (!board) {
  281. console.warn("[UI] Board not found yet");
  282. return;
  283. }
  284.  
  285. myVars.board = board;
  286.  
  287. // Create main container with Chess.com styling
  288. const panel = document.createElement('div');
  289. panel.id = 'chessBot';
  290. panel.style = `
  291. position: fixed;
  292. right: 20px;
  293. top: 50%;
  294. transform: translateY(-50%);
  295. width: 280px;
  296. background-color: #312e2b;
  297. color: #bababa;
  298. font-family: "Segoe UI", Arial, sans-serif;
  299. z-index: 9999;
  300. padding: 15px;
  301. border-radius: 5px;
  302. box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
  303. font-size: 14px;
  304. `;
  305.  
  306. // Create header
  307. const header = document.createElement('div');
  308. header.style = `
  309. display: flex;
  310. justify-content: space-between;
  311. align-items: center;
  312. margin-bottom: 15px;
  313. border-bottom: 1px solid #464442;
  314. padding-bottom: 10px;
  315. `;
  316.  
  317. const title = document.createElement('h2');
  318. title.innerText = 'Chess.com Bot';
  319. title.style = `
  320. margin: 0;
  321. font-size: 18px;
  322. font-weight: 600;
  323. color: #bababa;
  324. `;
  325.  
  326. const version = document.createElement('span');
  327. version.innerText = 'v3.0';
  328. version.style = `
  329. font-size: 12px;
  330. opacity: 0.8;
  331. color: #bababa;
  332. `;
  333.  
  334. header.appendChild(title);
  335. header.appendChild(version);
  336. panel.appendChild(header);
  337.  
  338. // Create spinner overlay
  339. const overlay = document.createElement('div');
  340. overlay.id = 'overlay';
  341. overlay.style = `
  342. position: absolute;
  343. top: 0;
  344. left: 0;
  345. right: 0;
  346. bottom: 0;
  347. background-color: rgba(49, 46, 43, 0.85);
  348. z-index: 10000;
  349. display: none;
  350. border-radius: 5px;
  351. `;
  352.  
  353. const spinner = document.createElement('div');
  354. spinner.style = `
  355. position: absolute;
  356. top: 50%;
  357. left: 50%;
  358. width: 40px;
  359. height: 40px;
  360. margin-top: -20px;
  361. margin-left: -20px;
  362. border: 3px solid #bababa;
  363. border-top-color: #7fa650;
  364. border-radius: 50%;
  365. animation: spin 1s infinite linear;
  366. `;
  367.  
  368. const spinStyle = document.createElement('style');
  369. spinStyle.textContent = `
  370. @keyframes spin {
  371. 0% { transform: rotate(0deg); }
  372. 100% { transform: rotate(360deg); }
  373. }
  374. `;
  375.  
  376. document.head.appendChild(spinStyle);
  377. overlay.appendChild(spinner);
  378. panel.appendChild(overlay);
  379.  
  380. // Create content sections
  381. const createSection = (title) => {
  382. const section = document.createElement('div');
  383. section.style = `
  384. margin-bottom: 15px;
  385. `;
  386.  
  387. const sectionTitle = document.createElement('h3');
  388. sectionTitle.innerText = title;
  389. sectionTitle.style = `
  390. margin: 0 0 10px 0;
  391. font-size: 16px;
  392. color: #bababa;
  393. border-bottom: 1px solid #464442;
  394. padding-bottom: 5px;
  395. `;
  396.  
  397. section.appendChild(sectionTitle);
  398. return section;
  399. };
  400.  
  401. // Create depth section
  402. const depthSection = createSection('Engine Depth');
  403.  
  404. const depthDisplay = document.createElement('div');
  405. depthDisplay.style = `
  406. display: flex;
  407. justify-content: space-between;
  408. align-items: center;
  409. margin-bottom: 10px;
  410. background-color: #3a3634;
  411. padding: 8px 12px;
  412. border-radius: 4px;
  413. `;
  414.  
  415. const depthLabel = document.createElement('span');
  416. depthLabel.innerText = 'Current Depth:';
  417.  
  418. const depthValue = document.createElement('span');
  419. depthValue.id = 'depthValue';
  420. depthValue.innerText = myVars.customDepth;
  421. depthValue.style = `
  422. font-weight: bold;
  423. color: #7fa650;
  424. `;
  425.  
  426. depthDisplay.appendChild(depthLabel);
  427. depthDisplay.appendChild(depthValue);
  428.  
  429. const depthInfo = document.createElement('p');
  430. depthInfo.innerText = 'Press A-Z keys to change depth (Q=1, W=2, etc.)';
  431. depthInfo.style = `
  432. margin: 5px 0;
  433. font-size: 12px;
  434. opacity: 0.7;
  435. `;
  436.  
  437. const depthInput = document.createElement('div');
  438. depthInput.style = `
  439. display: flex;
  440. align-items: center;
  441. margin-top: 10px;
  442. `;
  443.  
  444. const depthInputLabel = document.createElement('label');
  445. depthInputLabel.innerText = 'Set Depth:';
  446. depthInputLabel.style = 'margin-right: 10px;';
  447.  
  448. const depthInputField = document.createElement('input');
  449. depthInputField.type = 'number';
  450. depthInputField.id = 'customDepthInput';
  451. depthInputField.min = '1';
  452. depthInputField.max = '100';
  453. depthInputField.value = myVars.customDepth;
  454. depthInputField.style = `
  455. background-color: #3a3634;
  456. border: 1px solid #464442;
  457. color: #bababa;
  458. padding: 5px;
  459. border-radius: 3px;
  460. width: 60px;
  461. `;
  462.  
  463. depthInputField.addEventListener('change', function() {
  464. const value = parseInt(this.value);
  465. if (!isNaN(value) && value >= 1 && value <= 100) {
  466. myVars.customDepth = value;
  467. depthValue.innerText = value;
  468. GM_setValue('customDepth', myVars.customDepth); // Save the new depth
  469. location.reload(); // Reload the page
  470. } else {
  471. this.value = GM_getValue('customDepth', 11); // Reset to saved value if input is invalid
  472. }
  473. });
  474.  
  475. depthInput.appendChild(depthInputLabel);
  476. depthInput.appendChild(depthInputField);
  477.  
  478. depthSection.appendChild(depthDisplay);
  479. depthSection.appendChild(depthInfo);
  480. depthSection.appendChild(depthInput);
  481. panel.appendChild(depthSection);
  482.  
  483. // Create game options section
  484. const optionsSection = createSection('Game Options');
  485.  
  486. const createCheckbox = (id, label) => {
  487. const container = document.createElement('div');
  488. container.style = `
  489. display: flex;
  490. align-items: center;
  491. margin-bottom: 10px;
  492. cursor: pointer;
  493. `;
  494.  
  495. const checkbox = document.createElement('input');
  496. checkbox.type = 'checkbox';
  497. checkbox.id = id;
  498. checkbox.style = `
  499. margin-right: 10px;
  500. cursor: pointer;
  501. `;
  502.  
  503. const checkLabel = document.createElement('label');
  504. checkLabel.htmlFor = id;
  505. checkLabel.innerText = label;
  506. checkLabel.style = 'cursor: pointer;';
  507.  
  508. container.appendChild(checkbox);
  509. container.appendChild(checkLabel);
  510. return container;
  511. };
  512.  
  513. const autoRunCheck = createCheckbox('suggestMove', 'Enable Suggested Move');
  514. const autoMoveCheck = createCheckbox('autoMove', 'Enable auto move');
  515. const autoMatchCheck = createCheckbox('autoMatch', 'Enable auto match');
  516.  
  517. optionsSection.appendChild(autoRunCheck);
  518. optionsSection.appendChild(autoMoveCheck);
  519. optionsSection.appendChild(autoMatchCheck);
  520. panel.appendChild(optionsSection);
  521.  
  522. // Set initial state from loaded vars
  523. autoRunCheck.querySelector('input').checked = myVars.suggestMove;
  524. autoMoveCheck.querySelector('input').checked = myVars.autoMove;
  525. autoMatchCheck.querySelector('input').checked = myVars.autoMatch;
  526.  
  527. // Create delay section
  528. const delaySection = createSection('Suggestion Delay');
  529.  
  530. const createDelayInput = (id, label, defaultValue) => {
  531. const container = document.createElement('div');
  532. container.style = `
  533. display: flex;
  534. align-items: center;
  535. margin-bottom: 10px;
  536. `;
  537.  
  538. const inputLabel = document.createElement('label');
  539. inputLabel.htmlFor = id;
  540. inputLabel.innerText = label;
  541. inputLabel.style = `
  542. flex: 1;
  543. `;
  544.  
  545. const input = document.createElement('input');
  546. input.type = 'number';
  547. input.id = id;
  548. input.min = '0.1';
  549. input.step = '0.1';
  550. input.value = defaultValue;
  551. input.style = `
  552. background-color: #3a3634;
  553. border: 1px solid #464442;
  554. color: #bababa;
  555. padding: 5px;
  556. border-radius: 3px;
  557. width: 60px;
  558. `;
  559.  
  560. container.appendChild(inputLabel);
  561. container.appendChild(input);
  562. return container;
  563. };
  564.  
  565. const minDelayInput = createDelayInput('timeDelayMin', 'Min Delay (s):', '0.1');
  566. const maxDelayInput = createDelayInput('timeDelayMax', 'Max Delay (s):', '1.0');
  567.  
  568. delaySection.appendChild(minDelayInput);
  569. delaySection.appendChild(maxDelayInput);
  570. panel.appendChild(delaySection);
  571.  
  572. // Create display section
  573. const displaySection = createSection('Display');
  574.  
  575. const colorContainer = document.createElement('div');
  576. colorContainer.style = `
  577. display: flex;
  578. align-items: center;
  579. `;
  580.  
  581. const colorLabel = document.createElement('label');
  582. colorLabel.htmlFor = 'highlightColorInput';
  583. colorLabel.innerText = 'Highlight Color:';
  584. colorLabel.style = 'flex: 1;';
  585.  
  586. const colorInput = document.createElement('input');
  587. colorInput.type = 'color';
  588. colorInput.id = 'highlightColorInput';
  589. colorInput.value = myVars.bestMoveHighlightColor;
  590. colorInput.style = `
  591. width: 60px;
  592. height: 30px;
  593. padding: 0;
  594. border: none;
  595. background: none;
  596. `;
  597.  
  598. colorInput.addEventListener('change', function() {
  599. myVars.bestMoveHighlightColor = this.value;
  600. GM_setValue('bestMoveHighlightColor', this.value);
  601. });
  602.  
  603. colorContainer.appendChild(colorLabel);
  604. colorContainer.appendChild(colorInput);
  605. displaySection.appendChild(colorContainer);
  606. panel.appendChild(displaySection);
  607.  
  608. // Create buttons section
  609. const actionsSection = createSection('Actions');
  610.  
  611. const createButton = (text, onClick, primary = false) => {
  612. const button = document.createElement('button');
  613. button.innerText = text;
  614. button.addEventListener('click', onClick);
  615. button.style = `
  616. background-color: ${primary ? '#7fa650' : '#5d5955'};
  617. color: #fff;
  618. border: none;
  619. padding: 10px;
  620. margin-bottom: 10px;
  621. border-radius: 3px;
  622. width: 100%;
  623. cursor: pointer;
  624. font-weight: ${primary ? 'bold' : 'normal'};
  625. transition: background-color 0.2s;
  626. `;
  627.  
  628. button.addEventListener('mouseover', function() {
  629. this.style.backgroundColor = primary ? '#8fb761' : '#6e6a66';
  630. });
  631.  
  632. button.addEventListener('mouseout', function() {
  633. this.style.backgroundColor = primary ? '#7fa650' : '#5d5955';
  634. });
  635.  
  636. return button;
  637. };
  638.  
  639. const reloadButton = createButton('Reload Chess Engine', () => myFunctions.reloadChessEngine(), true);
  640. const issueButton = createButton('Report an Issue', () => {
  641. window.open('https://greatest.deepsurf.us/en/scripts/534105-chess-com-bot-cheat-by-admin0/feedback', '_blank');
  642. });
  643.  
  644. const updateButton = createButton('Check for Updates', () => {
  645. window.open('https://greatest.deepsurf.us/en/scripts/534105-chess-com-bot-cheat-by-admin0', '_blank');
  646. });
  647.  
  648. actionsSection.appendChild(reloadButton);
  649. actionsSection.appendChild(issueButton);
  650. actionsSection.appendChild(updateButton);
  651. panel.appendChild(actionsSection);
  652.  
  653. // Add drag handle
  654. const dragHandle = document.createElement('div');
  655. dragHandle.style = `
  656. position: absolute;
  657. top: 0;
  658. left: 0;
  659. right: 0;
  660. height: 15px;
  661. cursor: move;
  662. background-color: rgba(255, 255, 255, 0.05);
  663. border-top-left-radius: 5px;
  664. border-top-right-radius: 5px;
  665. `;
  666.  
  667. // Make panel draggable
  668. let isDragging = false;
  669. let offsetX, offsetY;
  670.  
  671. dragHandle.addEventListener('mousedown', function(e) {
  672. isDragging = true;
  673. offsetX = e.clientX - panel.getBoundingClientRect().left;
  674. offsetY = e.clientY - panel.getBoundingClientRect().top;
  675. });
  676.  
  677. document.addEventListener('mousemove', function(e) {
  678. if (isDragging) {
  679. panel.style.right = 'auto';
  680. panel.style.top = (e.clientY - offsetY) + 'px';
  681. panel.style.left = (e.clientX - offsetX) + 'px';
  682. panel.style.transform = 'none';
  683. }
  684. });
  685.  
  686. document.addEventListener('mouseup', function() {
  687. isDragging = false;
  688. });
  689.  
  690. panel.appendChild(dragHandle);
  691.  
  692. // Add footer
  693. const footer = document.createElement('div');
  694. footer.style = `
  695. margin-top: 15px;
  696. padding-top: 10px;
  697. border-top: 1px solid #464442;
  698. font-size: 12px;
  699. text-align: center;
  700. opacity: 0.7;
  701. `;
  702.  
  703. footer.innerText = 'Press ESC to toggle interface';
  704. panel.appendChild(footer);
  705.  
  706. // Append panel to body
  707. document.body.appendChild(panel);
  708.  
  709. loaded = true;
  710. console.log("[UI] Chess.com themed interface created successfully");
  711. } catch (error) {
  712. console.error("[UI] Error creating interface:", error);
  713. }
  714. };
  715.  
  716. // Main interval loop
  717. const waitForChessBoard = setInterval(() => {
  718. if (loaded) {
  719. board = $('chess-board')[0] || $('wc-chess-board')[0];
  720.  
  721. // Read checkbox states directly from DOM
  722. try {
  723. myVars.suggestMove = document.getElementById('suggestMove').checked;
  724. myVars.autoMove = document.getElementById('autoMove').checked;
  725. myVars.autoMatch = document.getElementById('autoMatch').checked;
  726.  
  727. // Save the current state
  728. GM_setValue('suggestMove', myVars.suggestMove);
  729. GM_setValue('autoMove', myVars.autoMove);
  730. GM_setValue('autoMatch', myVars.autoMatch);
  731.  
  732. // Read delay values
  733. let minDelay = parseFloat(document.getElementById('timeDelayMin').value) || 0.1;
  734. let maxDelay = parseFloat(document.getElementById('timeDelayMax').value) || 1.0;
  735. myVars.delay = Math.random() * (maxDelay - minDelay) + minDelay;
  736. } catch (e) {
  737. console.warn("[UI] Error reading UI state:", e);
  738. }
  739.  
  740. // Update spinner
  741. myVars.isThinking = isThinking;
  742. myFunctions.spinner();
  743.  
  744. // Check for game over
  745. const gameOverModal = $('.game-over-modal-content');
  746. if (gameOverModal.length > 0 && !myVars.gameEnded) {
  747. console.log("[Game] Game over detected");
  748. myVars.gameEnded = true;
  749. myVars.hasAutoMatched = false;
  750. }
  751.  
  752. // Check turn
  753. try {
  754. if (!myVars.gameEnded && board && board.game) {
  755. myTurn = (board.game.getTurn() == board.game.getPlayingAs());
  756. } else {
  757. myTurn = false;
  758. }
  759. } catch (e) {
  760. myTurn = false;
  761. }
  762.  
  763. // Log state (for debugging)
  764. console.log(`[State] SuggestMove:${myVars.suggestMove} AutoMove:${myVars.autoMove} AutoMatch:${myVars.autoMatch} MyTurn:${myTurn} Thinking:${isThinking} CanGo:${canGo}`);
  765.  
  766. // Make sure engine is loaded
  767. if (!engine.engine) {
  768. myFunctions.loadChessEngine();
  769. }
  770.  
  771. // Auto Run Logic (Now Suggested Move Logic)
  772. if (myVars.suggestMove && canGo && !isThinking && myTurn && !myVars.gameEnded) {
  773. console.log("[Auto] Triggering suggested move analysis...");
  774. canGo = false;
  775. const currentDelay = myVars.delay * 1000;
  776. other(currentDelay);
  777. }
  778.  
  779. // Auto Match Logic
  780. if (myVars.autoMatch && myVars.gameEnded && !myVars.hasAutoMatched) {
  781. console.log("[Auto] Triggering auto match...");
  782. myFunctions.startNewGame();
  783. }
  784. } else if ($('chess-board, wc-chess-board').length > 0) {
  785. // Try to load UI if not loaded yet
  786. myFunctions.loadEx();
  787. }
  788. }, 100);
  789. }
  790.  
  791. // Global variables
  792. var isThinking = false;
  793. var canGo = true;
  794. var myTurn = false;
  795. var board;
  796.  
  797. // Start the script
  798. window.addEventListener("load", (event) => {
  799. console.log("[Script] Chess.com Bot v3.0 starting...");
  800. main();
  801. });