Answers.Body: <p>One approach is by sending the command <code>go nodes 1000</code>, <code>go nodes 2000 ...</code> to the engine and record the moves and score.</p>
  <p>Here is a sample code to do like that using <a href="https://github.com/niklasf/python-chess" rel="nofollow noreferrer">python chess lib</a> along with other  data and plotting libs.</p>
  <h4>Code</h4>
  <pre><code>&quot;&quot;&quot;
  This script will only work for those uci engines that supports
  &quot;go nodes &lt;value&gt;&quot; command.
  
  Requirements:
      pip install chess
      pip install pandas
      pip install matplotlib
  &quot;&quot;&quot;
  
  import chess
  import chess.engine
  import pandas as pd
  import matplotlib.pyplot as plt
  import matplotlib.ticker as plticker
  
  
  def engine_analysis(efn, fen, nodelimit):
      engine = chess.engine.SimpleEngine.popen_uci(efn)
      try:
          engine.configure({&quot;Hash&quot;: 128})
          engine.configure({&quot;Threads&quot;: 1})
      except Exception as exception:
          pass
      
      board = chess.Board(fen)
      limit = chess.engine.Limit(nodes=nodelimit)
  
      value, sanmove, nodes, timesec = None, None, 0, 0
  
      with engine.analysis(board, limit=limit) as analysis:
          for info in analysis:
              
              pv = info.get('pv')
              score = info.get('score')                
              nodes = info.get('nodes')
              timesec = info.get('time')
              
              if pv is not None:
                  move = pv[0]
                  sanmove = board.san(move)
                  
              if score is not None:
                  value = score.relative.score(mate_score=32000)
  
      engine.quit()
      
      return sanmove, value, nodes, timesec
      
      
  def run_engine():
      # fen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'  # startpos
      fen = 'rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 0 6'  # sicilian
      
      nodes_per_interval = 1000
      num_interval = 30
      
      e1 = {'name': 'Stockfish 14', 'file': 'E:/Chess/Engines/stockfish/sf14/sf14.exe'}
      e2 = {'name': 'Lc0 0.28', 'file': 'E:/Chess/Engines/Lc0/lc0-v0.28.0-windows-gpu-nvidia-cudnn-nodll/lc0.exe'}
      engines = [e1, e2]
      
      dfs = {}
      for eng in engines:
          d = []
          for i in range(num_interval):
              nodelimit = (i+1) * nodes_per_interval
              move, score, actualnodes, timesec = engine_analysis(eng['file'], fen, nodelimit)
              d.append([nodelimit, actualnodes, move, score, timesec])
              
          df = pd.DataFrame(d)
          df.columns = ['nodes', 'actualnodes', 'move', 'scorecp', 'timesec']
          dfs.update({eng['name']: df})
          
      print(f'fen: {fen}')        
      for k, v in dfs.items():
          print(f'{k}:')
          print(f'{v.to_string(index=False)}\n')
  
      # Plot    
      x = dfs[e1['name']]['nodes']
      y1 = dfs[e1['name']]['scorecp']
      y2 = dfs[e2['name']]['scorecp']
      
      _, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(12, 6))
      
      ax1.plot(x, y1)
      ax1.set_title(f&quot;{e1['name']} score at different node levels&quot;)
      ax1.set_ylabel('score cp')
      
      ax2.plot(x, y2)
      ax2.set_title(f&quot;{e2['name']} score at different node levels&quot;)
      ax2.set_xlabel('nodes')
      ax2.set_ylabel('score cp')
      plt.setp(ax2.get_xticklabels(), ha=&quot;right&quot;, rotation=45)
         
      loc = plticker.MultipleLocator(base=nodes_per_interval)  # add ticks in every point
      ax2.xaxis.set_major_locator(loc)
      
      plt.savefig('engine_nodes.png')    
      plt.show()
      
      
  # start
  run_engine()
  </code></pre>
  <h4>Output</h4>
  <pre><code>fen: rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 0 6
  Stockfish 14:
   nodes  actualnodes move  scorecp  timesec
    1000         1002  Be3       64    0.002
    2000         2001  Bg5      -24    0.003
    3000         3005  Nb3       46    0.003
    4000         4010  Bg5       32    0.004
    5000         5004  Bg5        4    0.004
    6000         6003  Nb3       13    0.005
    7000         7040  Bg5       19    0.006
    8000         8013  Be3       41    0.009
    9000         9003  Be2       40    0.007
   10000        10019  Be2       33    0.008
   11000        11003   f3       50    0.009
   12000        12014  Qf3       40    0.010
   13000        13004   a4       27    0.010
   14000        14014   a4       47    0.011
   15000        15006  Be2       32    0.011
   16000        16040  Nb3        6    0.012
   17000        17022  Nb3       37    0.013
   18000        18007  Nb3       52    0.014
   19000        19019   a4       17    0.014
   20000        20040   h3       21    0.020
   21000        21032  Be3       38    0.016
   22000        22011   f3       18    0.016
   23000        23039   f3       38    0.023
   24000        24036   f3       50    0.028
   25000        25019  Bg5       69    0.021
   26000        26021   h3       30    0.019
   27000        27071  Be3       27    0.019
   28000        28072  Nb3       44    0.021
   29000        29032  Be3       64    0.020
   30000        30039  Be2       34    0.022
  
  Lc0 0.28:
   nodes  actualnodes move  scorecp  timesec
    1000         1022   f3       20    0.156
    2000         2012   f3       19    0.180
    3000         2997   f3       20    0.214
    4000         3411   f3       19    0.224
    5000         4211   f3       19    0.249
    6000         5428   f3       19    0.279
    7000         6018   f3       19    0.319
    8000         6449   f3       19    0.339
    9000         6993   f3       20    0.349
   10000         7552   f3       20    0.369
   11000         8039   f3       20    0.392
   12000         8173   f3       20    0.379
   13000         8942   f3       20    0.404
   14000         9583   f3       20    0.417
   15000        10075   f3       20    0.475
   16000        10653   f3       20    0.466
   17000        11045   f3       20    0.474
   18000        11732   f3       20    0.506
   19000        12561   f3       20    0.535
   20000        12763   f3       20    0.543
   21000        13268   f3       20    0.570
   22000        13829   f3       20    0.584
   23000        14323   f3       20    0.602
   24000        14883   f3       20    0.641
   25000        15823   f3       19    0.663
   26000        16810   f3       19    0.693
   27000        25923   f3       18    0.938
   28000        27064   f3       18    1.001
   29000        26266   f3       18    0.976
   30000        29043  Be3       18    1.052
  </code></pre>
  <p><a href="https://i.sstatic.net/BjbJm.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/BjbJm.png" alt="enter image description here" /></a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-12-11T02:37:00.327Z
Answers.LastActivityDate: 2021-12-14T00:21:17.443Z
Answers.LastEditDate: 2021-12-14T00:21:17.443Z
Answers.UserDisplayName: ferdy
Body: <p>I would like to test how Stockfish or other Engines change their moves and evaluations as the number of nodes increases. Is there a way to run Stockfish (or another engine) and force it to output its move preference every 1000 nodes?</p>
  
Tags: <engines><stockfish><websites><chess-ai>
Title: How to compare Stockfish move preference every 1000 nodes
ThreadText: # How to compare Stockfish move preference every 1000 nodes
  
  (Asked by: username_0 on 2021-12-09)
  
  I would like to test how Stockfish or other Engines change their moves and evaluations as the number of nodes increases. Is there a way to run Stockfish (or another engine) and force it to output its move preference every 1000 nodes?
  
  **Tags:** engines, stockfish, websites, chess-ai
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-12-11. Score: 4
  
  One approach is by sending the command `go nodes 1000`, `go nodes 2000 ...` to the engine and record the moves and score.
  
  Here is a sample code to do like that using [python chess lib](https://github.com/niklasf/python-chess) along with other data and plotting libs.
  
  #### Code
  
  ```
  """
  This script will only work for those uci engines that supports
  "go nodes <value>" command.
  
  Requirements:
      pip install chess
      pip install pandas
      pip install matplotlib
  """
  
  import chess
  import chess.engine
  import pandas as pd
  import matplotlib.pyplot as plt
  import matplotlib.ticker as plticker
  
  def engine_analysis(efn, fen, nodelimit):
      engine = chess.engine.SimpleEngine.popen_uci(efn)
      try:
          engine.configure({"Hash": 128})
          engine.configure({"Threads": 1})
      except Exception as exception:
          pass
      
      board = chess.Board(fen)
      limit = chess.engine.Limit(nodes=nodelimit)
  
      value, sanmove, nodes, timesec = None, None, 0, 0
  
      with engine.analysis(board, limit=limit) as analysis:
          for info in analysis:
              
              pv = info.get('pv')
              score = info.get('score')                
              nodes = info.get('nodes')
              timesec = info.get('time')
              
              if pv is not None:
                  move = pv[0]
                  sanmove = board.san(move)
                  
              if score is not None:
                  value = score.relative.score(mate_score=32000)
  
      engine.quit()
      
      return sanmove, value, nodes, timesec
      
      
  def run_engine():
      # fen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'  # startpos
      fen = 'rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 0 6'  # sicilian
      
      nodes_per_interval = 1000
      num_interval = 30
      
      e1 = {'name': 'Stockfish 14', 'file': 'E:/Chess/Engines/stockfish/sf14/sf14.exe'}
      e2 = {'name': 'Lc0 0.28', 'file': 'E:/Chess/Engines/Lc0/lc0-v0.28.0-windows-gpu-nvidia-cudnn-nodll/lc0.exe'}
      engines = [e1, e2]
      
      dfs = {}
      for eng in engines:
          d = []
          for i in range(num_interval):
              nodelimit = (i+1) * nodes_per_interval
              move, score, actualnodes, timesec = engine_analysis(eng['file'], fen, nodelimit)
              d.append([nodelimit, actualnodes, move, score, timesec])
              
          df = pd.DataFrame(d)
          df.columns = ['nodes', 'actualnodes', 'move', 'scorecp', 'timesec']
          dfs.update({eng['name']: df})
          
      print(f'fen: {fen}')        
      for k, v in dfs.items():
          print(f'{k}:')
          print(f'{v.to_string(index=False)}\n')
  
      # Plot    
      x = dfs[e1['name']]['nodes']
      y1 = dfs[e1['name']]['scorecp']
      y2 = dfs[e2['name']]['scorecp']
      
      _, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(12, 6))
      
      ax1.plot(x, y1)
      ax1.set_title(f"{e1['name']} score at different node levels")
      ax1.set_ylabel('score cp')
      
      ax2.plot(x, y2)
      ax2.set_title(f"{e2['name']} score at different node levels")
      ax2.set_xlabel('nodes')
      ax2.set_ylabel('score cp')
      plt.setp(ax2.get_xticklabels(), ha="right", rotation=45)
         
      loc = plticker.MultipleLocator(base=nodes_per_interval)  # add ticks in every point
      ax2.xaxis.set_major_locator(loc)
      
      plt.savefig('engine_nodes.png')    
      plt.show()
      
      
  # start
  run_engine()
  
  ```
  
  #### Output
  
  ```
  fen: rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 0 6
  Stockfish 14:
   nodes  actualnodes move  scorecp  timesec
    1000         1002  Be3       64    0.002
    2000         2001  Bg5      -24    0.003
    3000         3005  Nb3       46    0.003
    4000         4010  Bg5       32    0.004
    5000         5004  Bg5        4    0.004
    6000         6003  Nb3       13    0.005
    7000         7040  Bg5       19    0.006
    8000         8013  Be3       41    0.009
    9000         9003  Be2       40    0.007
   10000        10019  Be2       33    0.008
   11000        11003   f3       50    0.009
   12000        12014  Qf3       40    0.010
   13000        13004   a4       27    0.010
   14000        14014   a4       47    0.011
   15000        15006  Be2       32    0.011
   16000        16040  Nb3        6    0.012
   17000        17022  Nb3       37    0.013
   18000        18007  Nb3       52    0.014
   19000        19019   a4       17    0.014
   20000        20040   h3       21    0.020
   21000        21032  Be3       38    0.016
   22000        22011   f3       18    0.016
   23000        23039   f3       38    0.023
   24000        24036   f3       50    0.028
   25000        25019  Bg5       69    0.021
   26000        26021   h3       30    0.019
   27000        27071  Be3       27    0.019
   28000        28072  Nb3       44    0.021
   29000        29032  Be3       64    0.020
   30000        30039  Be2       34    0.022
  
  Lc0 0.28:
   nodes  actualnodes move  scorecp  timesec
    1000         1022   f3       20    0.156
    2000         2012   f3       19    0.180
    3000         2997   f3       20    0.214
    4000         3411   f3       19    0.224
    5000         4211   f3       19    0.249
    6000         5428   f3       19    0.279
    7000         6018   f3       19    0.319
    8000         6449   f3       19    0.339
    9000         6993   f3       20    0.349
   10000         7552   f3       20    0.369
   11000         8039   f3       20    0.392
   12000         8173   f3       20    0.379
   13000         8942   f3       20    0.404
   14000         9583   f3       20    0.417
   15000        10075   f3       20    0.475
   16000        10653   f3       20    0.466
   17000        11045   f3       20    0.474
   18000        11732   f3       20    0.506
   19000        12561   f3       20    0.535
   20000        12763   f3       20    0.543
   21000        13268   f3       20    0.570
   22000        13829   f3       20    0.584
   23000        14323   f3       20    0.602
   24000        14883   f3       20    0.641
   25000        15823   f3       19    0.663
   26000        16810   f3       19    0.693
   27000        25923   f3       18    0.938
   28000        27064   f3       18    1.001
   29000        26266   f3       18    0.976
   30000        29043  Be3       18    1.052
  
  ```
  
  [![enter image description here](https://i.sstatic.net/BjbJm.png)](https://i.sstatic.net/BjbJm.png)
  
  
  ---
  
  