Chess.com Bot/Cheat (by Admin0)

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

Verze ze dne 27. 04. 2025. Zobrazit nejnovější verzi.

  1. // ==UserScript==
  2. // @name Chess.com Bot/Cheat (by Admin0)
  3. // @namespace Admin0
  4. // @version 3.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 = false;
  33. myVars.suggestMove = false;
  34. myVars.autoMatch = false;
  35. myVars.customDepth = 11; // Default depth
  36. myVars.bestMoveHighlightColor = GM_getValue('bestMoveHighlightColor', '#7fa650'); // Chess.com green
  37. var myFunctions = document.myFunctions = {};
  38. var lastValue = 11;
  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. myFunctions.runChessEngine(myVars.customDepth);
  263. }
  264.  
  265. // Toggle UI with ESC
  266. if (e.keyCode === 27 && loaded) {
  267. $('#chessBot').toggle();
  268. }
  269. };
  270.  
  271. // UI Creation function - CHESS.COM THEMED
  272. var loaded = false;
  273. myFunctions.loadEx = function() {
  274. if (loaded) return;
  275.  
  276. try {
  277. console.log("[UI] Creating Chess.com themed interface...");
  278. board = $('chess-board')[0] || $('wc-chess-board')[0];
  279. if (!board) {
  280. console.warn("[UI] Board not found yet");
  281. return;
  282. }
  283.  
  284. myVars.board = board;
  285.  
  286. // Create main container with Chess.com styling
  287. const panel = document.createElement('div');
  288. panel.id = 'chessBot';
  289. panel.style = `
  290. position: fixed;
  291. right: 20px;
  292. top: 50%;
  293. transform: translateY(-50%);
  294. width: 280px;
  295. background-color: #312e2b;
  296. color: #bababa;
  297. font-family: "Segoe UI", Arial, sans-serif;
  298. z-index: 9999;
  299. padding: 15px;
  300. border-radius: 5px;
  301. box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
  302. font-size: 14px;
  303. `;
  304.  
  305. // Create header
  306. const header = document.createElement('div');
  307. header.style = `
  308. display: flex;
  309. justify-content: space-between;
  310. align-items: center;
  311. margin-bottom: 15px;
  312. border-bottom: 1px solid #464442;
  313. padding-bottom: 10px;
  314. `;
  315.  
  316. const title = document.createElement('h2');
  317. title.innerText = 'Chess.com Bot';
  318. title.style = `
  319. margin: 0;
  320. font-size: 18px;
  321. font-weight: 600;
  322. color: #bababa;
  323. `;
  324.  
  325. const version = document.createElement('span');
  326. version.innerText = 'v3.0';
  327. version.style = `
  328. font-size: 12px;
  329. opacity: 0.8;
  330. color: #bababa;
  331. `;
  332.  
  333. header.appendChild(title);
  334. header.appendChild(version);
  335. panel.appendChild(header);
  336.  
  337. // Create spinner overlay
  338. const overlay = document.createElement('div');
  339. overlay.id = 'overlay';
  340. overlay.style = `
  341. position: absolute;
  342. top: 0;
  343. left: 0;
  344. right: 0;
  345. bottom: 0;
  346. background-color: rgba(49, 46, 43, 0.85);
  347. z-index: 10000;
  348. display: none;
  349. border-radius: 5px;
  350. `;
  351.  
  352. const spinner = document.createElement('div');
  353. spinner.style = `
  354. position: absolute;
  355. top: 50%;
  356. left: 50%;
  357. width: 40px;
  358. height: 40px;
  359. margin-top: -20px;
  360. margin-left: -20px;
  361. border: 3px solid #bababa;
  362. border-top-color: #7fa650;
  363. border-radius: 50%;
  364. animation: spin 1s infinite linear;
  365. `;
  366.  
  367. const spinStyle = document.createElement('style');
  368. spinStyle.textContent = `
  369. @keyframes spin {
  370. 0% { transform: rotate(0deg); }
  371. 100% { transform: rotate(360deg); }
  372. }
  373. `;
  374.  
  375. document.head.appendChild(spinStyle);
  376. overlay.appendChild(spinner);
  377. panel.appendChild(overlay);
  378.  
  379. // Create content sections
  380. const createSection = (title) => {
  381. const section = document.createElement('div');
  382. section.style = `
  383. margin-bottom: 15px;
  384. `;
  385.  
  386. const sectionTitle = document.createElement('h3');
  387. sectionTitle.innerText = title;
  388. sectionTitle.style = `
  389. margin: 0 0 10px 0;
  390. font-size: 16px;
  391. color: #bababa;
  392. border-bottom: 1px solid #464442;
  393. padding-bottom: 5px;
  394. `;
  395.  
  396. section.appendChild(sectionTitle);
  397. return section;
  398. };
  399.  
  400. // Create depth section
  401. const depthSection = createSection('Engine Depth');
  402.  
  403. const depthDisplay = document.createElement('div');
  404. depthDisplay.style = `
  405. display: flex;
  406. justify-content: space-between;
  407. align-items: center;
  408. margin-bottom: 10px;
  409. background-color: #3a3634;
  410. padding: 8px 12px;
  411. border-radius: 4px;
  412. `;
  413.  
  414. const depthLabel = document.createElement('span');
  415. depthLabel.innerText = 'Current Depth:';
  416.  
  417. const depthValue = document.createElement('span');
  418. depthValue.id = 'depthValue';
  419. depthValue.innerText = myVars.customDepth;
  420. depthValue.style = `
  421. font-weight: bold;
  422. color: #7fa650;
  423. `;
  424.  
  425. depthDisplay.appendChild(depthLabel);
  426. depthDisplay.appendChild(depthValue);
  427.  
  428. const depthInfo = document.createElement('p');
  429. depthInfo.innerText = 'Press A-Z keys to change depth (Q=1, W=2, etc.)';
  430. depthInfo.style = `
  431. margin: 5px 0;
  432. font-size: 12px;
  433. opacity: 0.7;
  434. `;
  435.  
  436. const depthInput = document.createElement('div');
  437. depthInput.style = `
  438. display: flex;
  439. align-items: center;
  440. margin-top: 10px;
  441. `;
  442.  
  443. const depthInputLabel = document.createElement('label');
  444. depthInputLabel.innerText = 'Set Depth:';
  445. depthInputLabel.style = 'margin-right: 10px;';
  446.  
  447. const depthInputField = document.createElement('input');
  448. depthInputField.type = 'number';
  449. depthInputField.id = 'customDepthInput';
  450. depthInputField.min = '1';
  451. depthInputField.max = '100';
  452. depthInputField.value = myVars.customDepth;
  453. depthInputField.style = `
  454. background-color: #3a3634;
  455. border: 1px solid #464442;
  456. color: #bababa;
  457. padding: 5px;
  458. border-radius: 3px;
  459. width: 60px;
  460. `;
  461.  
  462. depthInputField.addEventListener('change', function() {
  463. const value = parseInt(this.value);
  464. if (!isNaN(value) && value >= 1 && value <= 100) {
  465. myVars.customDepth = value;
  466. depthValue.innerText = value;
  467. } else {
  468. this.value = myVars.customDepth;
  469. }
  470. });
  471.  
  472. depthInput.appendChild(depthInputLabel);
  473. depthInput.appendChild(depthInputField);
  474.  
  475. depthSection.appendChild(depthDisplay);
  476. depthSection.appendChild(depthInfo);
  477. depthSection.appendChild(depthInput);
  478. panel.appendChild(depthSection);
  479.  
  480. // Create game options section
  481. const optionsSection = createSection('Game Options');
  482.  
  483. const createCheckbox = (id, label) => {
  484. const container = document.createElement('div');
  485. container.style = `
  486. display: flex;
  487. align-items: center;
  488. margin-bottom: 10px;
  489. cursor: pointer;
  490. `;
  491.  
  492. const checkbox = document.createElement('input');
  493. checkbox.type = 'checkbox';
  494. checkbox.id = id;
  495. checkbox.style = `
  496. margin-right: 10px;
  497. cursor: pointer;
  498. `;
  499.  
  500. const checkLabel = document.createElement('label');
  501. checkLabel.htmlFor = id;
  502. checkLabel.innerText = label;
  503. checkLabel.style = 'cursor: pointer;';
  504.  
  505. container.appendChild(checkbox);
  506. container.appendChild(checkLabel);
  507. return container;
  508. };
  509.  
  510. const autoRunCheck = createCheckbox('suggestMove', 'Enable Suggested Move');
  511. const autoMoveCheck = createCheckbox('autoMove', 'Enable auto move');
  512. const autoMatchCheck = createCheckbox('autoMatch', 'Enable auto match');
  513.  
  514. optionsSection.appendChild(autoRunCheck);
  515. optionsSection.appendChild(autoMoveCheck);
  516. optionsSection.appendChild(autoMatchCheck);
  517. panel.appendChild(optionsSection);
  518.  
  519. // Create delay section
  520. const delaySection = createSection('Suggestion Delay');
  521.  
  522. const createDelayInput = (id, label, defaultValue) => {
  523. const container = document.createElement('div');
  524. container.style = `
  525. display: flex;
  526. align-items: center;
  527. margin-bottom: 10px;
  528. `;
  529.  
  530. const inputLabel = document.createElement('label');
  531. inputLabel.htmlFor = id;
  532. inputLabel.innerText = label;
  533. inputLabel.style = `
  534. flex: 1;
  535. `;
  536.  
  537. const input = document.createElement('input');
  538. input.type = 'number';
  539. input.id = id;
  540. input.min = '0.1';
  541. input.step = '0.1';
  542. input.value = defaultValue;
  543. input.style = `
  544. background-color: #3a3634;
  545. border: 1px solid #464442;
  546. color: #bababa;
  547. padding: 5px;
  548. border-radius: 3px;
  549. width: 60px;
  550. `;
  551.  
  552. container.appendChild(inputLabel);
  553. container.appendChild(input);
  554. return container;
  555. };
  556.  
  557. const minDelayInput = createDelayInput('timeDelayMin', 'Min Delay (s):', '0.1');
  558. const maxDelayInput = createDelayInput('timeDelayMax', 'Max Delay (s):', '1.0');
  559.  
  560. delaySection.appendChild(minDelayInput);
  561. delaySection.appendChild(maxDelayInput);
  562. panel.appendChild(delaySection);
  563.  
  564. // Create display section
  565. const displaySection = createSection('Display');
  566.  
  567. const colorContainer = document.createElement('div');
  568. colorContainer.style = `
  569. display: flex;
  570. align-items: center;
  571. `;
  572.  
  573. const colorLabel = document.createElement('label');
  574. colorLabel.htmlFor = 'highlightColorInput';
  575. colorLabel.innerText = 'Highlight Color:';
  576. colorLabel.style = 'flex: 1;';
  577.  
  578. const colorInput = document.createElement('input');
  579. colorInput.type = 'color';
  580. colorInput.id = 'highlightColorInput';
  581. colorInput.value = myVars.bestMoveHighlightColor;
  582. colorInput.style = `
  583. width: 60px;
  584. height: 30px;
  585. padding: 0;
  586. border: none;
  587. background: none;
  588. `;
  589.  
  590. colorInput.addEventListener('change', function() {
  591. myVars.bestMoveHighlightColor = this.value;
  592. GM_setValue('bestMoveHighlightColor', this.value);
  593. });
  594.  
  595. colorContainer.appendChild(colorLabel);
  596. colorContainer.appendChild(colorInput);
  597. displaySection.appendChild(colorContainer);
  598. panel.appendChild(displaySection);
  599.  
  600. // Create buttons section
  601. const actionsSection = createSection('Actions');
  602.  
  603. const createButton = (text, onClick, primary = false) => {
  604. const button = document.createElement('button');
  605. button.innerText = text;
  606. button.addEventListener('click', onClick);
  607. button.style = `
  608. background-color: ${primary ? '#7fa650' : '#5d5955'};
  609. color: #fff;
  610. border: none;
  611. padding: 10px;
  612. margin-bottom: 10px;
  613. border-radius: 3px;
  614. width: 100%;
  615. cursor: pointer;
  616. font-weight: ${primary ? 'bold' : 'normal'};
  617. transition: background-color 0.2s;
  618. `;
  619.  
  620. button.addEventListener('mouseover', function() {
  621. this.style.backgroundColor = primary ? '#8fb761' : '#6e6a66';
  622. });
  623.  
  624. button.addEventListener('mouseout', function() {
  625. this.style.backgroundColor = primary ? '#7fa650' : '#5d5955';
  626. });
  627.  
  628. return button;
  629. };
  630.  
  631. const reloadButton = createButton('Reload Chess Engine', () => myFunctions.reloadChessEngine(), true);
  632. const issueButton = createButton('Report an Issue', () => {
  633. window.open('https://greatest.deepsurf.us/en/scripts/534105-chess-com-bot-cheat-by-admin0/feedback', '_blank');
  634. });
  635.  
  636. const updateButton = createButton('Check for Updates', () => {
  637. window.open('https://greatest.deepsurf.us/en/scripts/534105-chess-com-bot-cheat-by-admin0', '_blank');
  638. });
  639.  
  640. actionsSection.appendChild(reloadButton);
  641. actionsSection.appendChild(issueButton);
  642. actionsSection.appendChild(updateButton);
  643. panel.appendChild(actionsSection);
  644.  
  645. // Add drag handle
  646. const dragHandle = document.createElement('div');
  647. dragHandle.style = `
  648. position: absolute;
  649. top: 0;
  650. left: 0;
  651. right: 0;
  652. height: 15px;
  653. cursor: move;
  654. background-color: rgba(255, 255, 255, 0.05);
  655. border-top-left-radius: 5px;
  656. border-top-right-radius: 5px;
  657. `;
  658.  
  659. // Make panel draggable
  660. let isDragging = false;
  661. let offsetX, offsetY;
  662.  
  663. dragHandle.addEventListener('mousedown', function(e) {
  664. isDragging = true;
  665. offsetX = e.clientX - panel.getBoundingClientRect().left;
  666. offsetY = e.clientY - panel.getBoundingClientRect().top;
  667. });
  668.  
  669. document.addEventListener('mousemove', function(e) {
  670. if (isDragging) {
  671. panel.style.right = 'auto';
  672. panel.style.top = (e.clientY - offsetY) + 'px';
  673. panel.style.left = (e.clientX - offsetX) + 'px';
  674. panel.style.transform = 'none';
  675. }
  676. });
  677.  
  678. document.addEventListener('mouseup', function() {
  679. isDragging = false;
  680. });
  681.  
  682. panel.appendChild(dragHandle);
  683.  
  684. // Add footer
  685. const footer = document.createElement('div');
  686. footer.style = `
  687. margin-top: 15px;
  688. padding-top: 10px;
  689. border-top: 1px solid #464442;
  690. font-size: 12px;
  691. text-align: center;
  692. opacity: 0.7;
  693. `;
  694.  
  695. footer.innerText = 'Press ESC to toggle interface';
  696. panel.appendChild(footer);
  697.  
  698. // Append panel to body
  699. document.body.appendChild(panel);
  700.  
  701. loaded = true;
  702. console.log("[UI] Chess.com themed interface created successfully");
  703. } catch (error) {
  704. console.error("[UI] Error creating interface:", error);
  705. }
  706. };
  707.  
  708. // Main interval loop
  709. const waitForChessBoard = setInterval(() => {
  710. if (loaded) {
  711. board = $('chess-board')[0] || $('wc-chess-board')[0];
  712.  
  713. // Read checkbox states directly from DOM
  714. try {
  715. myVars.suggestMove = document.getElementById('suggestMove').checked;
  716. myVars.autoMove = document.getElementById('autoMove').checked;
  717. myVars.autoMatch = document.getElementById('autoMatch').checked;
  718.  
  719. // Read delay values
  720. let minDelay = parseFloat(document.getElementById('timeDelayMin').value) || 0.1;
  721. let maxDelay = parseFloat(document.getElementById('timeDelayMax').value) || 1.0;
  722. myVars.delay = Math.random() * (maxDelay - minDelay) + minDelay;
  723. } catch (e) {
  724. console.warn("[UI] Error reading UI state:", e);
  725. }
  726.  
  727. // Update spinner
  728. myVars.isThinking = isThinking;
  729. myFunctions.spinner();
  730.  
  731. // Check for game over
  732. const gameOverModal = $('.game-over-modal-content');
  733. if (gameOverModal.length > 0 && !myVars.gameEnded) {
  734. console.log("[Game] Game over detected");
  735. myVars.gameEnded = true;
  736. myVars.hasAutoMatched = false;
  737. }
  738.  
  739. // Check turn
  740. try {
  741. if (!myVars.gameEnded && board && board.game) {
  742. myTurn = (board.game.getTurn() == board.game.getPlayingAs());
  743. } else {
  744. myTurn = false;
  745. }
  746. } catch (e) {
  747. myTurn = false;
  748. }
  749.  
  750. // Log state (for debugging)
  751. console.log(`[State] SuggestMove:${myVars.suggestMove} AutoMove:${myVars.autoMove} AutoMatch:${myVars.autoMatch} MyTurn:${myTurn} Thinking:${isThinking} CanGo:${canGo}`);
  752.  
  753. // Make sure engine is loaded
  754. if (!engine.engine) {
  755. myFunctions.loadChessEngine();
  756. }
  757.  
  758. // Auto Run Logic (Now Suggested Move Logic)
  759. if (myVars.suggestMove && canGo && !isThinking && myTurn && !myVars.gameEnded) {
  760. console.log("[Auto] Triggering suggested move analysis...");
  761. canGo = false;
  762. const currentDelay = myVars.delay * 1000;
  763. other(currentDelay);
  764. }
  765.  
  766. // Auto Match Logic
  767. if (myVars.autoMatch && myVars.gameEnded && !myVars.hasAutoMatched) {
  768. console.log("[Auto] Triggering auto match...");
  769. myFunctions.startNewGame();
  770. }
  771. } else if ($('chess-board, wc-chess-board').length > 0) {
  772. // Try to load UI if not loaded yet
  773. myFunctions.loadEx();
  774. }
  775. }, 100);
  776. }
  777.  
  778. // Global variables
  779. var isThinking = false;
  780. var canGo = true;
  781. var myTurn = false;
  782. var board;
  783.  
  784. // Start the script
  785. window.addEventListener("load", (event) => {
  786. console.log("[Script] Chess.com Bot v3.0 starting...");
  787. main();
  788. });