您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Auto move bot using Stockfish on Chess.com with start/stop UI
当前为
// ==UserScript== // @name Chess.com Stockfish AutoMove Bot with UI // @namespace http://tampermonkey.net/ // @version 0.2 // @description Auto move bot using Stockfish on Chess.com with start/stop UI // @author Nimmmuary123456 // @match https://www.chess.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // Stockfish wasm build URL (you can self-host for reliability) const STOCKFISH_URL = 'https://cdn.jsdelivr.net/gh/niklasf/stockfish.js/stockfish.wasm.js'; let stockfish; let isRunning = false; let analysisRunning = false; // Create UI panel const panel = document.createElement('div'); panel.style.position = 'fixed'; panel.style.top = '10px'; panel.style.right = '10px'; panel.style.backgroundColor = '#222'; panel.style.color = 'white'; panel.style.padding = '10px'; panel.style.borderRadius = '8px'; panel.style.zIndex = 99999; panel.style.fontFamily = 'Arial, sans-serif'; panel.style.width = '200px'; panel.style.boxShadow = '0 0 10px black'; const title = document.createElement('div'); title.textContent = 'Stockfish AutoMove Bot'; title.style.fontWeight = 'bold'; title.style.marginBottom = '8px'; title.style.textAlign = 'center'; panel.appendChild(title); const status = document.createElement('div'); status.textContent = 'Status: Stopped'; status.style.marginBottom = '8px'; panel.appendChild(status); const btnStartStop = document.createElement('button'); btnStartStop.textContent = 'Start'; btnStartStop.style.width = '100%'; btnStartStop.style.padding = '8px'; btnStartStop.style.fontSize = '16px'; btnStartStop.style.cursor = 'pointer'; panel.appendChild(btnStartStop); document.body.appendChild(panel); // Load Stockfish engine as Web Worker function loadStockfish() { return new Promise((resolve, reject) => { stockfish = new Worker(STOCKFISH_URL); stockfish.onmessage = (event) => { const line = event.data; if (line === 'uciok') { resolve(); } }; stockfish.onerror = (e) => { reject(e); }; stockfish.postMessage('uci'); }); } // Send command to stockfish function sendCommand(cmd) { //console.log('Sending to Stockfish:', cmd); stockfish.postMessage(cmd); } // Get FEN from Chess.com board function getFEN() { // Chess.com stores the FEN string in window.__board?.fen() or window.Chessboard try { if (window.__board && typeof window.__board.fen === 'function') { return window.__board.fen(); } // Alternative: read from Chess.com's internal chess object if (window.Chess && window.Chess.fen) { return window.Chess.fen(); } // Or from Chess.com analysis panel - DOM fallback (last move in PGN) // Try to read FEN from page URL or from chessboard data attribute const fenInput = document.querySelector('input#fen-input'); if (fenInput) return fenInput.value; } catch (e) {} return null; } // Find squares on board and simulate clicks to play move function playMove(move) { if (!move || move.length < 4) return; const from = move.slice(0, 2); const to = move.slice(2, 4); // Chess.com board squares have classes like "square-63" but it's complicated; // Let's try to use data-coordinates attributes (Chess.com uses algebraic notation) // The chessboard div uses data-square="e2", etc. const boardSquares = document.querySelectorAll('[data-square]'); let fromEl, toEl; boardSquares.forEach(sq => { if (sq.getAttribute('data-square') === from) fromEl = sq; if (sq.getAttribute('data-square') === to) toEl = sq; }); if (fromEl && toEl) { // Simulate click sequence fromEl.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); fromEl.dispatchEvent(new MouseEvent('mouseup', { bubbles: true })); toEl.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); toEl.dispatchEvent(new MouseEvent('mouseup', { bubbles: true })); console.log(`Moved from ${from} to ${to}`); status.textContent = `Moved: ${move}`; } else { console.log('Could not find squares to move:', from, to); status.textContent = 'Error: Could not find squares'; } } // Analyze position and get best move from Stockfish function analyzePosition(fen) { return new Promise((resolve) => { let bestMove = null; function onMessage(event) { const line = event.data; //console.log('Stockfish:', line); if (line.startsWith('bestmove')) { bestMove = line.split(' ')[1]; stockfish.removeEventListener('message', onMessage); resolve(bestMove); } } stockfish.addEventListener('message', onMessage); sendCommand('ucinewgame'); sendCommand(`position fen ${fen}`); sendCommand('go depth 15'); }); } // Main bot loop async function botLoop() { if (!isRunning) return; if (analysisRunning) return; // prevent overlapping calls analysisRunning = true; const fen = getFEN(); if (!fen) { console.log('FEN not found, retrying...'); status.textContent = 'Waiting for board...'; analysisRunning = false; setTimeout(botLoop, 3000); return; } console.log('Current FEN:', fen); status.textContent = 'Analyzing...'; const bestMove = await analyzePosition(fen); if (bestMove && isRunning) { playMove(bestMove); } analysisRunning = false; if (isRunning) { setTimeout(botLoop, 4000); // wait 4 seconds before next analysis } } // Start the bot async function startBot() { if (isRunning) return; status.textContent = 'Loading Stockfish...'; await loadStockfish(); isRunning = true; status.textContent = 'Running...'; btnStartStop.textContent = 'Stop'; botLoop(); } // Stop the bot function stopBot() { if (!isRunning) return; isRunning = false; status.textContent = 'Stopped'; btnStartStop.textContent = 'Start'; if (stockfish) { stockfish.terminate(); stockfish = null; } } btnStartStop.addEventListener('click', () => { if (isRunning) { stopBot(); } else { startBot(); } }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址