{"id":29,"date":"2024-11-15T21:00:00","date_gmt":"2024-11-15T21:00:00","guid":{"rendered":"https:\/\/blog.chessboardmagic.com\/?p=29"},"modified":"2025-09-28T21:31:10","modified_gmt":"2025-09-28T21:31:10","slug":"chess-web-programming-part-two-stockfish","status":"publish","type":"post","link":"https:\/\/blog.chessboardmagic.com\/index.php\/2024\/11\/15\/chess-web-programming-part-two-stockfish\/","title":{"rendered":"Chess Web Programming: Part Two: Stockfish"},"content":{"rendered":"\n<p><strong>Integrating Stockfish into our Chess Web Application.<\/strong><\/p>\n\n\n\n<p>In October 2023, I started learning modern web programming, and&nbsp;<strong><a href=\"https:\/\/chessboardmagic.com\/\">Chessboard Magic<\/a><\/strong>&nbsp;became my first major project. What began as a simple practice exercise has grown into something much larger\u2014Chessboard Magic now includes 34 different chess-based applications! Building it has been both a rewarding challenge and a fantastic way to dive into web development, and I\u2019m excited to share this journey with you.<br>In the first part of this series, we set up our development environment and created a basic chess application. We installed React,&nbsp;<em>react-chessboard<\/em>, and&nbsp;<em>chess.js<\/em>, and ended up with a working chessboard that validates moves according to chess rules. This setup provided a solid foundation, and hopefully, you\u2019re feeling more confident about creating interactive chess features in your application. If you missed it, you can read the first part&nbsp;<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-one\/8ZKpwJU8\">here<\/a><\/strong>.<br>In this second part, we\u2019re going to take things up a notch by integrating&nbsp;<strong>Stockfish<\/strong>, a powerful open-source chess engine. With Stockfish, our app won\u2019t just display moves and validate them; it\u2019ll calculate the best moves and even play against you. This integration is a significant step in transforming our chessboard from a simple display to a fully interactive chess tool.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#stockfish\"><\/a>Stockfish<\/h2>\n\n\n\n<p>For those who may not be familiar with it,&nbsp;<strong>Stockfish<\/strong>&nbsp;is one of the most powerful chess engines available today. It\u2019s a highly advanced program designed to analyze chess positions and calculate the best possible moves. Stockfish can evaluate millions of moves per second, making it a favorite among players, developers, and researchers. It\u2019s typically used as a standalone application on desktop computers, where it can be paired with a graphical interface for interactive play or analysis.<br>However, Stockfish is also available in a form that can be used on the web:&nbsp;<strong>WebAssembly<\/strong>&nbsp;(Wasm).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#what-is-webassembly-wasm\"><\/a>What is WebAssembly (Wasm)?<\/h4>\n\n\n\n<p>WebAssembly is a technology that allows code written in languages like C or C++ to run in the browser. Think of it as a bridge between desktop applications and web applications. In the case of Stockfish, WebAssembly enables us to use this powerful chess engine directly in a web application, without needing a server or external desktop program. The code runs right inside the browser, which makes it faster and more efficient.<br>With Stockfish available as a WebAssembly module, we can use it in our chess application to provide real-time analysis, suggest the best moves, or even play a game against the engine\u2014all from within the browser. This approach transforms our chessboard from a simple display into an interactive tool that can provide deep insights and feedback for users, whether they\u2019re analyzing positions or testing their skills against the engine.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#getting-stockfish\"><\/a>Getting Stockfish<\/h2>\n\n\n\n<p>To integrate Stockfish into our web application, we\u2019ll first need to download the necessary files. We\u2019ll be using a version of Stockfish that\u2019s optimized for web use, thanks to WebAssembly. The specific files we need can be found on GitHub.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Download Stockfish Files<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Head over to the GitHub repository at:\u00a0<a href=\"https:\/\/github.com\/nmrugg\/stockfish.js\/tree\/master\/src\">https:\/\/github.com\/nmrugg\/stockfish.js\/tree\/master\/src<\/a>.<\/li>\n\n\n\n<li>Locate the files named\u00a0<code>stockfish-16.1-lite-single.wasm<\/code>\u00a0and\u00a0<code>stockfish-16.1-lite-single.js<\/code>.<\/li>\n\n\n\n<li>Download both files to your computer. These are a lightweight WebAssembly version of Stockfish and a corresponding JavaScript file to interact with it.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Set Up the Files in Your Project<\/strong>:\n<ul class=\"wp-block-list\">\n<li>In your project directory, create a folder named\u00a0<code>public\/js<\/code>. The\u00a0<code>public<\/code>\u00a0folder is typically used to serve static files in web applications, and we\u2019ll keep our Stockfish files here to make them accessible to the app.<\/li>\n\n\n\n<li>Move both\u00a0<code>stockfish-16.1-lite-single.wasm<\/code>\u00a0and\u00a0<code>stockfish-16.1-lite-single.js<\/code>\u00a0into the newly created\u00a0<code>public\/js<\/code>\u00a0folder.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>With these files now in place, we\u2019ll be able to load Stockfish from the browser, allowing us to run it directly in our application. In the next steps, we\u2019ll set up the code to initialize and interact with Stockfish, enabling our app to analyze positions and suggest moves.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#integrating-stockfish\"><\/a>Integrating Stockfish<\/h2>\n\n\n\n<p>Now that we have Stockfish loaded into our project, let\u2019s update the&nbsp;<code>App.js<\/code>&nbsp;file to initialize Stockfish as a Web Worker, calculate the best move after each piece drop, and display this move on the screen.<br>We\u2019ll go through this process step by step, starting with our original code and adding functionality bit by bit.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-1-set-up-state-for-stockfish-and-best-move\"><\/a>Step 1: Set Up State for Stockfish and Best Move<\/h4>\n\n\n\n<p>First, let\u2019s add two new pieces of&nbsp;<strong>state<\/strong>&nbsp;to our app. In React, state is a way to store information that can change over time. When state changes, React automatically updates the part of the screen that depends on it, so our app always shows the latest information.<br>In this case, one state variable will keep track of the Stockfish worker (the tool that helps us run Stockfish in the background), and the other will store the best move that Stockfish suggests.<br>Add these lines right next to the existing&nbsp;<code>useState<\/code>&nbsp;line in&nbsp;<code>App.js<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const &#91;stockfish, setStockfish] = useState(null);\nconst &#91;bestMove, setBestMove] = useState(\"\");<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>stockfish<\/code>\u00a0will store the Stockfish worker instance, allowing us to communicate with it throughout the component.<\/li>\n\n\n\n<li><code>bestMove<\/code>\u00a0will hold the best move calculated by Stockfish, which we\u2019ll display on the screen.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-2-initialize-stockfish-in-useeffect\"><\/a>Step 2: Initialize Stockfish in&nbsp;<code>useEffect<\/code><\/h4>\n\n\n\n<p>Next, we\u2019ll add a&nbsp;<code>useEffect<\/code>&nbsp;function to our code to set up Stockfish as a Web Worker.<br><strong>What is&nbsp;<code>useEffect<\/code>?<\/strong><br><code>useEffect<\/code>&nbsp;is a React function that allows you to run specific code at certain times in your component\u2019s life. Think of it as a way to tell React, \u201cHey, I want to do something special when this part of my app first loads.\u201d Here, we\u2019re using&nbsp;<code>useEffect<\/code>&nbsp;to load Stockfish just once, right when our app starts.<br><strong>What Does \u201cMounting\u201d Mean?<\/strong><br>&#8220;Mounting&#8221; is a term that means adding something to the screen. In React, when a component first appears on the screen, we say it\u2019s &#8220;mounting.&#8221; With&nbsp;<code>useEffect<\/code>, we can control code that only runs when the component first mounts\u2014meaning it only happens when the app loads for the first time. This way, we set up Stockfish once and avoid reloading it every time something else in the app changes.<br>In this&nbsp;<code>useEffect<\/code>, we\u2019ll load Stockfish and connect it as a Web Worker, which allows it to run in the background without slowing down the main app.<br>Add the following&nbsp;<code>useEffect<\/code>&nbsp;code right below the state declarations in your component:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>useEffect(() => {\n  \/\/ Load Stockfish as a Web Worker once when the component mounts\n  const stockfishWorker = new Worker(\"\/js\/stockfish-16.1-lite-single.js\");\n  setStockfish(stockfishWorker);\n\n  \/\/ Listen for messages from Stockfish\n  stockfishWorker.onmessage = (event) => {\n    const message = event.data;\n    if (message.startsWith(\"bestmove\")) {\n      const move = message.split(\" \")&#91;1];\n      setBestMove(move); \/\/ Save the best move to display on the screen\n    }\n  };\n\n  return () => {\n    stockfishWorker.terminate(); \/\/ Clean up the worker when the component unmounts\n  };\n}, &#91;]);<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We load Stockfish as a\u00a0<strong>Web Worker<\/strong>\u00a0and set it to\u00a0<code>stockfishWorker<\/code>. A Web Worker is a JavaScript script that runs in the background, separately from the main web page. This allows the browser to handle complex tasks, like running Stockfish, without slowing down or freezing the main user interface. By using a Web Worker, we can keep Stockfish\u2019s calculations running smoothly without impacting the app\u2019s performance.<\/li>\n\n\n\n<li>The\u00a0<code>onmessage<\/code>\u00a0event listener processes messages received from Stockfish. When Stockfish sends a\u00a0<code>bestmove<\/code>\u00a0message, we capture the best move and update\u00a0<code>bestMove<\/code>.<\/li>\n\n\n\n<li>The\u00a0<code>return<\/code>\u00a0statement with\u00a0<code>stockfishWorker.terminate()<\/code>\u00a0ensures the worker is properly cleaned up when the component unmounts.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-3-modify-ondrop-to-send-positions-to-stockfish\"><\/a>Step 3: Modify&nbsp;<code>onDrop<\/code>&nbsp;to Send Positions to Stockfish<\/h4>\n\n\n\n<p>Now, we\u2019ll modify&nbsp;<code>onDrop<\/code>&nbsp;to send the current game position to Stockfish after each valid move. This will prompt Stockfish to analyze the board and calculate the best move, and we\u2019ll see the results come back in the&nbsp;<code>onmessage<\/code>&nbsp;function we set up earlier.<br>Update&nbsp;<code>onDrop<\/code>&nbsp;to include the following lines:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (stockfish) {\n  stockfish.postMessage(`position fen ${gameCopy.fen()}`);\n  stockfish.postMessage(\"go depth 15\"); \/\/ Set depth for Stockfish analysis\n}<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>After making a valid move, we use\u00a0<code>postMessage<\/code>\u00a0to send the FEN notation of the current board position to Stockfish.<\/li>\n\n\n\n<li>We then send the\u00a0<code>go depth 15<\/code>\u00a0command to start Stockfish\u2019s analysis, specifying a search depth of 15 moves.<\/li>\n<\/ul>\n\n\n\n<p>This modified&nbsp;<code>onDrop<\/code>&nbsp;function will trigger Stockfish\u2019s analysis each time a piece is moved.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-4-display-the-best-move\"><\/a>Step 4: Display the Best Move<\/h4>\n\n\n\n<p>Finally, let\u2019s add a new&nbsp;<code>&lt;div&gt;<\/code>&nbsp;element to display the best move calculated by Stockfish. Update the return statement to include:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div>\n  &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n&lt;\/div><\/code><\/pre>\n\n\n\n<p>This will show the best move on the screen. If Stockfish hasn\u2019t yet calculated a move, it will display \u201cCalculating&#8230;\u201d to indicate that the analysis is still in progress.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#final-appjs-code\"><\/a>Final&nbsp;<code>App.js<\/code>&nbsp;Code<\/h4>\n\n\n\n<p>Here\u2019s the complete code for&nbsp;<code>App.js<\/code>&nbsp;with all changes included:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import React, { useState, useEffect } from \"react\";  \/\/ Import React and hooks for state and effect management\nimport { Chessboard } from \"react-chessboard\";       \/\/ Import the Chessboard component for displaying the board\nimport { Chess } from \"chess.js\";                    \/\/ Import Chess logic from chess.js to handle moves and rules\n\nconst App = () => {\n  \/\/ Initialize game state with a new Chess instance from chess.js\n  const &#91;game, setGame] = useState(new Chess());\n  \/\/ Initialize state for the Stockfish Web Worker instance\n  const &#91;stockfish, setStockfish] = useState(null);\n  \/\/ Initialize state for storing Stockfish's suggested best move\n  const &#91;bestMove, setBestMove] = useState(\"\");\n\n  \/\/ useEffect to set up Stockfish as a Web Worker when the component first loads (mounts)\n  useEffect(() => {\n    \/\/ Create a new Web Worker for Stockfish from the JavaScript file we downloaded\n    const stockfishWorker = new Worker(\"\/js\/stockfish-16.1-lite-single.js\");\n    setStockfish(stockfishWorker); \/\/ Save this worker instance in state for access elsewhere in the component\n\n    \/\/ Listen for messages sent back from Stockfish\n    stockfishWorker.onmessage = (event) => {\n      const message = event.data; \/\/ Capture the message data from Stockfish\n      \/\/ Check if Stockfish has sent a \"bestmove\" response\n      if (message.startsWith(\"bestmove\")) {\n        const move = message.split(\" \")&#91;1]; \/\/ Extract the best move from the message\n        setBestMove(move); \/\/ Save the best move in state to display on the screen\n      }\n    };\n\n    \/\/ Clean up the worker when the component is removed from the screen (unmounted)\n    return () => {\n      stockfishWorker.terminate(); \/\/ Terminates the worker to free up resources\n    };\n  }, &#91;]); \/\/ Empty dependency array means this runs only once when the component mounts\n\n  \/\/ onDrop function is triggered when a piece is moved on the Chessboard\n  const onDrop = (sourceSquare, targetSquare) => {\n    \/\/ Create a copy of the current game state using FEN (Forsyth-Edwards Notation)\n    const gameCopy = new Chess(game.fen());\n\n    try {\n      \/\/ Attempt to make the move on the game copy\n      const move = gameCopy.move({\n        from: sourceSquare,   \/\/ Source square of the piece being moved\n        to: targetSquare,     \/\/ Target square of the move\n        promotion: \"q\",       \/\/ Always promote to a queen for simplicity\n      });\n\n      \/\/ If the move is invalid, return false to prevent it from being applied\n      if (move === null) {\n        return false; \/\/ Invalid move, ignore it\n      }\n\n      \/\/ If the move is valid, update the main game state with the new position\n      setGame(gameCopy);\n\n      \/\/ Send the new position to Stockfish for analysis\n      if (stockfish) {\n        stockfish.postMessage(`position fen ${gameCopy.fen()}`); \/\/ Send the board position in FEN format\n        stockfish.postMessage(\"go depth 15\"); \/\/ Instruct Stockfish to analyze the position up to a depth of 15 moves\n      }\n\n      return true; \/\/ Move was valid and applied, so return true\n    } catch (error) {\n      console.error(error.message); \/\/ Log any errors\n      return false; \/\/ Return false to ignore the move if there was an error\n    }\n  };\n\n  \/\/ Render the component\n  return (\n    &lt;div>\n      &lt;h1>Chess Game with Stockfish&lt;\/h1>\n      &lt;Chessboard\n        position={game.fen()}         \/\/ Set the board position based on the current game state\n        onPieceDrop={onDrop}          \/\/ Attach the onDrop function to handle piece moves\n        boardWidth={500}              \/\/ Set the width of the chessboard to 500 pixels\n      \/>\n      &lt;div>\n        {\/* Display Stockfish's suggested best move or show \"Calculating...\" if no move is available yet *\/}\n        &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n      &lt;\/div>\n    &lt;\/div>\n  );\n};\n\nexport default App; \/\/ Export the App component for use in other parts of the application<\/code><\/pre>\n\n\n\n<p>After applying these changes, we should not see the following:<br><img decoding=\"async\" src=\"https:\/\/image.lichess1.org\/display?fmt=webp&amp;h=0&amp;op=resize&amp;path=hollowleaf:ublogBody:A8rr9ucUa1SY:eLoCOEtT.png&amp;w=800&amp;sig=1291b03fcfaa92ef10da98047afb9350e26457e3\" alt=\"image.png\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#stockfish-evaluations\"><\/a>Stockfish Evaluations<\/h2>\n\n\n\n<p>In addition to finding the best move, Stockfish can provide an&nbsp;<strong>evaluation<\/strong>&nbsp;of the current board position. This evaluation helps us understand which player has the advantage and by how much. Stockfish\u2019s evaluations are typically shown as a numerical score: positive values favor White, and negative values favor Black. In this section, we\u2019ll add code to capture both the best move and evaluation from Stockfish, interpret it based on whose turn it is, and display this information below the chessboard.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-1-add-state-for-evaluation\"><\/a>Step 1: Add State for Evaluation<\/h4>\n\n\n\n<p>First, let\u2019s add a new state variable called&nbsp;<code>evaluation<\/code>&nbsp;to store Stockfish\u2019s assessment of the board position. We\u2019ll display this evaluation beneath the best move on the screen.<br>Add this line to the existing&nbsp;<code>useState<\/code>&nbsp;declarations in&nbsp;<code>App.js<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const &#91;evaluation, setEvaluation] = useState(\"\");<\/code><\/pre>\n\n\n\n<p>This initializes&nbsp;<code>evaluation<\/code>&nbsp;with an empty string, ready to be updated with evaluation data from Stockfish.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-2-create-getevaluation-function-to-parse-best-move-and-evaluation\"><\/a>Step 2: Create&nbsp;<code>getEvaluation<\/code>&nbsp;Function to Parse Best Move and Evaluation<\/h4>\n\n\n\n<p>We\u2019ll create a helper function called&nbsp;<code>getEvaluation<\/code>&nbsp;that handles parsing both the best move and the evaluation from Stockfish\u2019s messages. This function will look for messages with &#8220;bestmove&#8221; to extract the best move and messages containing &#8220;info score&#8221; to calculate the evaluation. By passing the game\u2019s current turn to&nbsp;<code>getEvaluation<\/code>, we\u2019ll ensure that the evaluation score is interpreted correctly (positive for White, negative for Black).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const getEvaluation = (message, turn) => {\n  let result = { bestMove: \"\", evaluation: \"\" }; \/\/ Initialize with default values\n\n  \/\/ Check for \"bestmove\" in the message to get the best move\n  if (message.startsWith(\"bestmove\")) {\n    result.bestMove = message.split(\" \")&#91;1];\n  }\n\n  \/\/ Check for \"info score\" message to get the evaluation\n  if (message.includes(\"info\") &amp;&amp; message.includes(\"score\")) {\n    const scoreParts = message.split(\" \");\n    const scoreIndex = scoreParts.indexOf(\"score\") + 2; \/\/ \"cp\" or \"mate\" is two words after \"score\"\n\n    if (scoreParts&#91;scoreIndex - 1] === \"cp\") {\n      \/\/ Extract centipawn evaluation and adjust based on turn\n      let score = parseInt(scoreParts&#91;scoreIndex], 10);\n      if (turn !== \"b\") {\n        score = -score; \/\/ Invert score if it was Black's turn\n      }\n      result.evaluation = `${score \/ 100}`; \/\/ Convert centipawns to pawns\n\n    } else if (scoreParts&#91;scoreIndex - 1] === \"mate\") {\n      \/\/ Extract mate score if available\n      const mateIn = parseInt(scoreParts&#91;scoreIndex], 10);\n      result.evaluation = `Mate in ${Math.abs(mateIn)}`;\n    }\n  }\n\n  return result;\n};<\/code><\/pre>\n\n\n\n<p>This function:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Initializes\u00a0<code>result<\/code>\u00a0with default empty values for\u00a0<code>bestMove<\/code>\u00a0and\u00a0<code>evaluation<\/code>.<\/li>\n\n\n\n<li>Extracts the best move from any message that starts with &#8220;bestmove.&#8221;<\/li>\n\n\n\n<li>Interprets evaluation scores, converting centipawns to pawns and accounting for whose turn it was.<\/li>\n\n\n\n<li>Returns an object containing both\u00a0<code>bestMove<\/code>\u00a0and\u00a0<code>evaluation<\/code>.<\/li>\n<\/ul>\n\n\n\n<p><strong>Note<\/strong>: If you\u2019re curious to see what messages Stockfish returns, you can add a&nbsp;<code>console.log(message)<\/code>&nbsp;inside the&nbsp;<code>getEvaluation<\/code>&nbsp;function or in the&nbsp;<code>onmessage<\/code>&nbsp;listener. This will print Stockfish\u2019s messages to the&nbsp;<strong>console<\/strong>&nbsp;for debugging.<br>To view the debug messages in&nbsp;<strong>Chrome<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open Chrome\u2019s\u00a0<strong>Developer Tools<\/strong>\u00a0(press\u00a0<code>F12<\/code>\u00a0or right-click on the page and select\u00a0<strong>Inspect<\/strong>).<\/li>\n\n\n\n<li>Go to the\u00a0<strong>Console<\/strong>\u00a0tab.<\/li>\n\n\n\n<li>Reload the page or make moves on the chessboard, and you\u2019ll see Stockfish\u2019s output messages displayed here.<\/li>\n<\/ol>\n\n\n\n<p>Other browsers, like Firefox and Edge, also have similar developer tools that allow you to view debug messages in the Console tab.<br>This can be a helpful way to understand the data Stockfish sends back and explore additional information you may want to display in your app.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-3-update-ondrop-to-use-getevaluation\"><\/a>Step 3: Update&nbsp;<code>onDrop<\/code>&nbsp;to Use&nbsp;<code>getEvaluation<\/code><\/h4>\n\n\n\n<p>Next, we\u2019ll modify&nbsp;<code>onDrop<\/code>&nbsp;to request Stockfish\u2019s evaluation each time a move is made. After sending the board position to Stockfish, we\u2019ll set up a listener for Stockfish\u2019s messages and use&nbsp;<code>getEvaluation<\/code>&nbsp;to parse both the best move and evaluation.<br>Here\u2019s how to update&nbsp;<code>onDrop<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const onDrop = (sourceSquare, targetSquare) => {\n  const gameCopy = new Chess(game.fen());\n\n  try {\n    const move = gameCopy.move({\n      from: sourceSquare,\n      to: targetSquare,\n      promotion: \"q\", \/\/ Always promote to a queen for simplicity\n    });\n\n    if (move === null) {\n      return false; \/\/ Invalid move\n    }\n\n    setGame(gameCopy);\n\n    \/\/ Send the updated position to Stockfish to calculate the best move and evaluation\n    if (stockfish) {\n      stockfish.postMessage(`position fen ${gameCopy.fen()}`);\n      stockfish.postMessage(\"go depth 15\"); \/\/ Set depth for Stockfish analysis\n\n      \/\/ Listen for Stockfish messages and update best move and evaluation\n      stockfish.onmessage = (event) => {\n        const { bestMove, evaluation } = getEvaluation(event.data, game.turn());\n        if (bestMove) setBestMove(bestMove);\n        if (evaluation) setEvaluation(evaluation);\n      };\n    }\n\n    return true; \/\/ Valid move\n  } catch (error) {\n    console.error(error.message);\n    return false; \/\/ Catch any error and return false\n  }\n};<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>After sending the board position to Stockfish, we set up a listener on\u00a0<code>stockfish.onmessage<\/code>\u00a0to handle the response.<\/li>\n\n\n\n<li><code>getEvaluation<\/code>\u00a0parses both the best move and evaluation, and if either is available, we update the\u00a0<code>bestMove<\/code>\u00a0and\u00a0<code>evaluation<\/code>\u00a0state.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-4-simplify-useeffect\"><\/a>Step 4: Simplify&nbsp;<code>useEffect<\/code><\/h4>\n\n\n\n<p>Since we\u2019ve moved the message handling to&nbsp;<code>onDrop<\/code>, we can simplify&nbsp;<code>useEffect<\/code>&nbsp;to just initialize the Stockfish Web Worker.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>useEffect(() =&gt; {\n  \/\/ Load Stockfish as a Web Worker once when the component mounts\n  const stockfishWorker = new Worker(\"\/js\/stockfish-16.1-lite-single.js\");\n  setStockfish(stockfishWorker);\n\n  return () =&gt; {\n    stockfishWorker.terminate(); \/\/ Clean up the worker when the component unmounts\n  };\n}, &#91;]);\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#step-5-update-the-return-statement-to-display-evaluation\"><\/a>Step 5: Update the&nbsp;<code>return<\/code>&nbsp;Statement to Display Evaluation<\/h4>\n\n\n\n<p>Finally, update the&nbsp;<code>return<\/code>&nbsp;statement to display both the best move and evaluation below the chessboard:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>return (\n  &lt;div>\n    &lt;h1>Chess Game with Stockfish&lt;\/h1>\n    &lt;Chessboard\n      position={game.fen()}\n      onPieceDrop={onDrop}\n      boardWidth={500} \/\/ Set the board width to 500px\n    \/>\n    &lt;div>\n      &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n      &lt;h3>Evaluation: {evaluation || \"Evaluating...\"}&lt;\/h3> {\/* Display the evaluation *\/}\n    &lt;\/div>\n  &lt;\/div>\n);<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The best move is displayed with the line\u00a0<code>&lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3><\/code>, showing &#8220;Calculating&#8230;&#8221; until Stockfish provides a suggestion.<\/li>\n\n\n\n<li>The evaluation is displayed with\u00a0<code>&lt;h3>Evaluation: {evaluation || \"Evaluating...\"}&lt;\/h3><\/code>, which will similarly display &#8220;Evaluating&#8230;&#8221; if Stockfish hasn\u2019t yet calculated the position.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#final-appjs-code-1\"><\/a>Final&nbsp;<code>App.js<\/code>&nbsp;Code<\/h4>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#heres-the-complete-updated-code-with-both-best-move-and-evaluation-handled-by-getevaluation-in-ondrop\"><\/a>Here\u2019s the complete updated code with both best move and evaluation handled by&nbsp;<code>getEvaluation<\/code>&nbsp;in&nbsp;<code>onDrop<\/code>:<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>import React, { useState, useEffect } from \"react\";\nimport { Chessboard } from \"react-chessboard\";\nimport { Chess } from \"chess.js\";\n\n\/\/ Function to extract best move and evaluation from Stockfish's message\nconst getEvaluation = (message, turn) => {\n  let result = { bestMove: \"\", evaluation: \"\" }; \/\/ Initialize with default values\n\n  \/\/ Check for \"bestmove\" in the message to get the best move\n  if (message.startsWith(\"bestmove\")) {\n    result.bestMove = message.split(\" \")&#91;1];\n  }\n\n  \/\/ Check for \"info score\" message to get the evaluation\n  if (message.includes(\"info\") &amp;&amp; message.includes(\"score\")) {\n    const scoreParts = message.split(\" \");\n    const scoreIndex = scoreParts.indexOf(\"score\") + 2; \/\/ \"cp\" or \"mate\" is two words after \"score\"\n\n    if (scoreParts&#91;scoreIndex - 1] === \"cp\") {\n      \/\/ Extract centipawn evaluation and adjust based on turn\n      let score = parseInt(scoreParts&#91;scoreIndex], 10);\n      if (turn !== \"b\") {\n        score = -score; \/\/ Invert score if it was Black's turn\n      }\n      result.evaluation = `${score \/ 100}`; \/\/ Convert centipawns to pawns\n\n    } else if (scoreParts&#91;scoreIndex - 1] === \"mate\") {\n      \/\/ Extract mate score if available\n      const mateIn = parseInt(scoreParts&#91;scoreIndex], 10);\n      result.evaluation = `Mate in ${Math.abs(mateIn)}`;\n    }\n  }\n\n  return result;\n};\n\nconst App = () => {\n  const &#91;game, setGame] = useState(new Chess());\n  const &#91;stockfish, setStockfish] = useState(null);\n  const &#91;bestMove, setBestMove] = useState(\"\");\n  const &#91;evaluation, setEvaluation] = useState(\"\"); \/\/ State to store Stockfish's evaluation\n\n  useEffect(() => {\n    \/\/ Load Stockfish as a Web Worker once when the component mounts\n    const stockfishWorker = new Worker(\"\/js\/stockfish-16.1-lite-single.js\");\n    setStockfish(stockfishWorker);\n\n    return () => {\n      stockfishWorker.terminate(); \/\/ Clean up the worker when the component unmounts\n    };\n  }, &#91;]);\n\n  const onDrop = (sourceSquare, targetSquare) => {\n    const gameCopy = new Chess(game.fen());\n\n    try {\n      const move = gameCopy.move({\n        from: sourceSquare,\n        to: targetSquare,\n        promotion: \"q\", \/\/ Always promote to a queen for simplicity\n      });\n\n      if (move === null) {\n        return false; \/\/ Invalid move\n      }\n\n      setGame(gameCopy);\n\n      \/\/ Send the updated position to Stockfish to calculate the best move and evaluation\n      if (stockfish) {\n        stockfish.postMessage(`position fen ${gameCopy.fen()}`);\n        stockfish.postMessage(\"go depth 15\"); \/\/ Set depth for Stockfish analysis\n\n        \/\/ Listen for Stockfish messages and update best move and evaluation\n        stockfish.onmessage = (event) => {\n          const { bestMove, evaluation } = getEvaluation(event.data, game.turn());\n          if (bestMove) setBestMove(bestMove);\n          if (evaluation) setEvaluation(evaluation);\n        };\n      }\n\n      return true; \/\/ Valid move\n    } catch (error) {\n      console.error(error.message);\n      return false; \/\/ Catch any error and return false\n    }\n  };\n\n  return (\n    &lt;div>\n      &lt;h1>Chess Game with Stockfish&lt;\/h1>\n      &lt;Chessboard\n        position={game.fen()}\n        onPieceDrop={onDrop}\n        boardWidth={500} \/\/ Set the board width to 500px\n      \/>\n      &lt;div>\n        &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n        &lt;h3>Evaluation: {evaluation || \"Evaluating...\"}&lt;\/h3>\n      &lt;\/div>\n    &lt;\/div>\n  );\n};\n\nexport default App;<\/code><\/pre>\n\n\n\n<p>Now, if we run our web page, we\u2019ll see the following:<br><img decoding=\"async\" src=\"https:\/\/image.lichess1.org\/display?fmt=webp&amp;h=0&amp;op=resize&amp;path=hollowleaf:ublogBody:VvAWZTx9epbe:iwTFHW7A.png&amp;w=800&amp;sig=13bf5212ea3ca232653617a80c89187867fdc109\" alt=\"image.png\"><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Best Move<\/strong>: After each move, Stockfish will suggest the best move directly below the chessboard.<\/li>\n\n\n\n<li><strong>Evaluation<\/strong>: Stockfish\u2019s evaluation of the current board position will display underneath the best move. A positive evaluation indicates White\u2019s advantage, while a negative evaluation favors Black. If a checkmate is detected, it will display &#8220;Mate in X&#8221; moves.<\/li>\n<\/ul>\n\n\n\n<p>This enhanced functionality transforms our chess application into a dynamic analysis tool, providing real-time feedback on each move and helping players understand the position better.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#summary\"><\/a>Summary<\/h2>\n\n\n\n<p>In this blog, we started with a basic chessboard application built with React,&nbsp;<code>react-chessboard<\/code>, and&nbsp;<code>chess.js<\/code>. Our goal was to enhance the app by integrating Stockfish, a powerful chess engine, to provide real-time analysis.<br>We began by setting up Stockfish as a Web Worker, allowing it to run in the background without affecting the main interface. From there, we implemented functionality to display Stockfish\u2019s&nbsp;<strong>best move<\/strong>&nbsp;suggestion after each player\u2019s move. This alone turned our chessboard into a helpful tool, but we wanted to take it a step further.<br>To add depth to our analysis, we introduced&nbsp;<strong>evaluation scores<\/strong>&nbsp;from Stockfish. These scores reveal the engine\u2019s assessment of the position, giving insight into which side has the advantage and by how much. We parsed both the best move and evaluation using a custom helper function, then displayed these insights beneath the chessboard. Now, each move provides real-time feedback, helping players understand the position and see how each move shifts the game\u2019s balance.<br>In the end, we transformed our simple chess app into an interactive analysis tool, displaying Stockfish\u2019s best moves and evaluations for each position on the board. This feature-rich setup not only assists players in finding optimal moves but also serves as a learning tool for understanding chess positions more deeply.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf#learn-more\"><\/a><strong>Learn more<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/reactjs.org\/\">React<\/a>\u00a0\u2013 A JavaScript library for building user interfaces.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.npmjs.com\/package\/react-chessboard\">react-chessboard<\/a>\u00a0\u2013 A React component for rendering a chessboard.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.npmjs.com\/package\/chess.js\">chess.js<\/a>\u00a0\u2013 A library for handling chess game rules and move validation.<\/li>\n\n\n\n<li><a href=\"https:\/\/stockfishchess.org\/\">Stockfish<\/a>\u00a0\u2013 A powerful open-source chess engine.<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/nmrugg\/stockfish.js\">stockfish.js<\/a>\u00a0\u2013 A JavaScript and WebAssembly version of Stockfish for web applications.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Integrating Stockfish into our Chess Web Application. In October 2023, I started learning modern web programming, and&nbsp;Chessboard Magic&nbsp;became my first major project. What began as a simple practice exercise has grown into something much larger\u2014Chessboard Magic now includes 34 different chess-based applications! Building it has been both a rewarding challenge and a fantastic way to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":30,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-29","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/29","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/comments?post=29"}],"version-history":[{"count":1,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/29\/revisions"}],"predecessor-version":[{"id":31,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/29\/revisions\/31"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/media\/30"}],"wp:attachment":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/media?parent=29"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/categories?post=29"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/tags?post=29"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}