Chess.com Help Button (Stockfish 3200 ELO)

Adds a Help button to Chess.com to suggest the best move with reasoning using Stockfish 3200 ELO.

  1. // ==UserScript==
  2. // @name Chess.com Help Button (Stockfish 3200 ELO)
  3. // @namespace http://chess.com/
  4. // @version 2.0
  5. // @description Adds a Help button to Chess.com to suggest the best move with reasoning using Stockfish 3200 ELO.
  6. // @author URMAMA
  7. // @match *://www.chess.com/game/live/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. console.log("[Help Button] Script Loaded ✅");
  15.  
  16. function addHelpButton() {
  17. if (document.querySelector("#help-button")) return; // Prevent duplicate buttons
  18.  
  19. let button = document.createElement("button");
  20. button.id = "help-button";
  21. button.innerText = "♟️ Help (3200 ELO)";
  22. button.style.position = "absolute";
  23. button.style.bottom = "20px";
  24. button.style.right = "20px";
  25. button.style.padding = "10px";
  26. button.style.background = "#FF5722";
  27. button.style.color = "#fff";
  28. button.style.border = "none";
  29. button.style.borderRadius = "5px";
  30. button.style.cursor = "pointer";
  31. button.style.fontSize = "14px";
  32. button.style.zIndex = "1000";
  33.  
  34. button.onclick = fetchBestMove;
  35.  
  36. document.body.appendChild(button);
  37. }
  38.  
  39. async function fetchBestMove() {
  40. let fen = getFEN();
  41. if (!fen) {
  42. alert("❌ Error: Could not retrieve game position.");
  43. return;
  44. }
  45.  
  46. console.log(`Fetching best move for FEN: ${fen}`);
  47.  
  48. let response = await fetch(`https://lichess.org/api/cloud-eval?fen=${fen}`);
  49. let data = await response.json();
  50.  
  51. if (data.pvs && data.pvs.length > 0) {
  52. let bestMove = data.pvs[0].moves.split(" ")[0]; // First move suggestion
  53. let depth = data.depth;
  54. let evalScore = data.pvs[0].cp !== undefined ? (data.pvs[0].cp / 100) : "Mate in " + data.pvs[0].mate;
  55. let reasoning = analyzeMove(bestMove, evalScore);
  56. showMove(bestMove, depth, evalScore, reasoning);
  57. } else {
  58. alert("❌ No move suggestion available.");
  59. }
  60. }
  61.  
  62. function getFEN() {
  63. let boardElement = document.querySelector("[data-board]"); // Chess.com stores FEN in attributes
  64. return boardElement ? boardElement.getAttribute("data-board") : null;
  65. }
  66.  
  67. function analyzeMove(move, evalScore) {
  68. if (move.includes("x")) return `Capturing material, improving position (Eval: ${evalScore}).`;
  69. if (move.includes("+")) return `Check move! Putting pressure on the king (Eval: ${evalScore}).`;
  70. if (move.includes("O-O") || move.includes("O-O-O")) return `Castling for king safety (Eval: ${evalScore}).`;
  71. return `Improving piece activity, controlling center (Eval: ${evalScore}).`;
  72. }
  73.  
  74. function showMove(move, depth, evalScore, reasoning) {
  75. let moveBox = document.createElement("div");
  76. moveBox.className = "move-suggestion";
  77. moveBox.style.position = "absolute";
  78. moveBox.style.bottom = "60px";
  79. moveBox.style.right = "20px";
  80. moveBox.style.background = "#4CAF50";
  81. moveBox.style.color = "#fff";
  82. moveBox.style.padding = "10px";
  83. moveBox.style.borderRadius = "5px";
  84. moveBox.style.fontWeight = "bold";
  85. moveBox.style.boxShadow = "0px 4px 8px rgba(0,0,0,0.2)";
  86. moveBox.style.zIndex = "1000";
  87. moveBox.innerText = `✅ Best Move: ${move} (Depth ${depth})\n🔍 Why: ${reasoning}`;
  88.  
  89. document.body.appendChild(moveBox);
  90. setTimeout(() => moveBox.remove(), 5000);
  91. }
  92.  
  93. function watchForChanges() {
  94. let observer = new MutationObserver(() => addHelpButton());
  95. observer.observe(document.body, { childList: true, subtree: true });
  96. console.log("[Help Button] Watching for Chess.com matches...");
  97. }
  98.  
  99. addHelpButton();
  100. watchForChanges();
  101. })();
  102.  
  103.