0

I modified the Goratschin Chess code so that it can run 8 chess engines at the same time, and it works;

however in the code the options management of each single chess engine is missing, so the system reads the default parameters of each exe file related to the chess engines (hash, thread, syzygyPath, evalfile nnue)

Request :

  1. does anyone know how to insert custom parameters (hash, thread, syzygyPath, evalfile nnue) into the following Python code? the starting file that also contains the path and the names of the chess engines is this goratschinLauncher.py :
#!/usr/bin/env python3

# to create an EXE from this file, do:
# pip install pyinstaller
# pyinstaller -wF goratschinLauncher.py
# copy .exe from 'dist' directory in root directory

import argparse
import logging
import sys
import datetime

from goratschinChess import GoratschinChess


# folder and file names for the engines.
engineFolderDefault = "C:/Temp05/ChessCombi2/engines/"
engineFileNames = ["Combi01", "Combi02", "Combi03", "Combi04", "Combi05", "Combi06", "Combi07", "Combi08"]


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='UCI ches engine.')
    parser.add_argument('-log', help='Name of log file.')
    parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output. Changes log level from INFO to DEBUG.')
    parser.add_argument('-e', '--engineFolder', help='Engine folder.')
    parser.add_argument('-m', '--margin', type=int, default=50, help="Margin in centipawns of which the counselor's eval must be better than the boss.")
    args = parser.parse_args()

    print('args :'  + str(args), flush=True)

    # configure logging

    logger = logging.getLogger("goratschinChess")   
    logger.setLevel(logging.DEBUG if args.verbose else logging.INFO) 
    if args.log:
        now = datetime.datetime.now()
        f_handler = logging.FileHandler(args.log + '-' + str(now)[:10] + ".log")
        f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        f_handler.setFormatter(f_format)
        logger.addHandler(f_handler)
    
    enginesDir = args.engineFolder if args.engineFolder else engineFolderDefault
    
    print('engine folder specified: ' + str(enginesDir), flush=True)

    # start the goratschinChess engine
    GoratschinChess(enginesDir, engineFileNames, args.margin).start()

The name of the second file is goratschinChess.py but, since it is too long, I mark the link where it is possible to view it and also the first file: https://github.com/scacchig/Synergy-Chess

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
Marco C.
  • 1
  • 1
  • Please include the relevant parts of your second file here as a [mre]. Your question must be self-contained and not depend on an outside link to make sense, to guard against link-rot. [Ask], the [question checklist](//meta.stackoverflow.com/q/260648/843953) – Pranav Hosangadi May 21 '22 at 15:33

1 Answers1

0

Start each engine and set options to it based on the given options.

goratschinChess.py revisions

Add options param.

def __init__(self, engineLocation, engineNames, margin, options):
    self.engineFolder = engineLocation
    self.engineFileNames = engineNames
    self.score_margin = margin / 100 # given in centipawns, default: 50
    self.options = options

Initialize the engine with the user options. When we receive isready command we will set the options.

def _mainloop():
    ...
    elif userCommand == "isready":
        # Set user options to engines.
        for i, engine in enumerate(self._engines):
            if i >= len(self.options):
                break
            optkeys = list(self.options[i].keys())
            for optname in optkeys:
                engine.stdin.write(f"setoption name {optname} value {self.options[i][optname]}\n")
                engine.stdin.flush()
                print(f"info string {self.engineFileNames[i]}: setoption name {optname} value {self.options[i][optname]}", flush=True)
        self.send_command_to_engines(userCommand)
        emit_and_log("readyok")

Log NNUE info from engine.

def _check_result():
    ...
    elif info.startswith("info string NNUE evaluation "):
        emit(info)

Define options in the launcher.

goratschinLauncher.py revision

    options = {
        0: {"Hash":128, "EvalFile": "nn-6877cd24400e.nnue"},
        1: {"Hash":128, "EvalFile": "nn-d0b74ce1e5eb.nnue"}
    }

    # start the goratschinChess engine
    GoratschinChess(enginesDir, engineFileNames, args.margin, options).start()

Arena log, upon receiving the isready command we set our options.

2022-05-30 19:43:38.593-->1:isready
2022-05-30 19:43:38.909<--1:info string SF_0: setoption name Hash value 128
2022-05-30 19:43:38.912<--1:info string SF_0: setoption name EvalFile value nn-6877cd24400e.nnue
2022-05-30 19:43:38.915<--1:info string SF_1: setoption name Hash value 128
2022-05-30 19:43:38.919<--1:info string SF_1: setoption name EvalFile value nn-d0b74ce1e5eb.nnue
2022-05-30 19:43:38.922<--1:readyok

The engines now use the specified nnue's.

2022-05-30 19:44:03.075<--1:info string NNUE evaluation using nn-6877cd24400e.nnue enabled
2022-05-30 19:44:03.077<--1:info string NNUE evaluation using nn-d0b74ce1e5eb.nnue enabled

Test result

GoratschinLauncher player uses 2 engines.

[Event "Computer chess game"]
[Site "?"]
[Date "2022.05.30"]
[Round "?"]
[White "GoratschinLauncher"]
[Black "SF_0 default"]
[Result "1/2-1/2"]
[ECO "B12"]
[Opening "Caro-Kann"]
[Time "15:27:14"]
[Variation "Advance, 4.Nf3 e6"]
[TimeControl "180+2"]
[Termination "normal"]
[PlyCount "95"]
[WhiteType "program"]
[BlackType "program"]

1. e4 {+0.40/19 12} c6 {-0.37/27 9} 2. d4 {+0.66/17 6} d5 {-0.40/27 5} 3.
e5 {+0.70/18 7} Bf5 {-0.22/24 2} 4. Nf3 {+0.51/16 18} e6 {-0.16/23 2} 5.
Nc3 {+0.21/20 18} c5 {-0.09/22 3} 6. Be3 {+0.35/19 12} c4 {-0.15/23 3} 7.
Ne2 {+0.47/20 5} Nc6 {+0.02/25 3} 8. c3 {+0.37/20 7} b5 {+0.01/26 3} 9. Ng3
{+0.40/18 1} Bg6 {+0.04/27 3} 10. h4 {+0.25/19 9} h6 {+0.36/26 3} 11. a3
{+0.44/17 5} Nge7 {-0.06/30 30} 12. h5 {+0.41/20 2} Bh7 {-0.31/27 7} 13.
Nh4 {+0.54/22 9} Na5 {-0.42/24 3} 14. Qg4 {+0.59/22 2} Nb3 {-0.34/28 8} 15.
Rd1 {+0.64/21 2} Bc2 {-0.25/26 2} 16. Be2 {+0.78/21 2} Qd7 {-0.25/27 3} 17.
Qh3 {+0.78/26 25} Rg8 {-0.53/28 11} 18. O-O {+0.70/24 9} g5 {-0.38/25 4}
19. hxg6 {+0.55/24 4} fxg6 {-0.37/25 4} 20. Rde1 {+0.48/27 8} a5 {-0.53/30
23} 21. f4 {+0.82/21 9} O-O-O {-0.50/26 3} 22. Rf2 {+1.07/19 1} Bd3
{-0.72/26 4} 23. Bxd3 {+2.05/19 2} cxd3 {-0.77/27 3} 24. Nf3 {+0.86/22 19}
a4 {-0.77/27 5} 25. Rd1 {+0.72/25 9} Nf5 {-0.61/28 3} 26. Rxd3 {+0.69/18 5}
Be7 {-0.18/22 3} 27. Nxf5 {+0.49/19 1} gxf5 {0.00/25 3} 28. Qh5 {+0.66/21
7} Qe8 {0.00/31 3} 29. Qxh6 {+1.31/13 0} Rg6 {0.00/35 3} 30. Qh3 {+1.05/17
6} Qf8 {0.00/28 9} 31. Ng5 {+1.17/14 0} Rh6 {0.00/27 2} 32. Qf3 {+1.12/13
0} Qh8 {0.00/29 13} 33. Rf1 {+0.97/18 1} Bxg5 {0.00/31 3} 34. fxg5
{+1.31/14 0} Rh4 {0.00/30 4} 35. Bf4 {+0.80/19 3} Na5 {0.00/30 14} 36. Kf2
{+0.56/18 2} Nc4 {0.00/32 3} 37. Rb1 {+0.70/17 0} Kb7 {0.00/30 6} 38. Rdd1
{+0.91/12 1} Kc6 {0.00/30 3} 39. Rf1 {+0.28/19 3} Rd7 {0.00/31 4} 40. b3
{+0.12/17 1} axb3 {0.00/28 1} 41. Rxb3 {0.00/17 0} Ra7 {0.00/29 1} 42. Rfb1
{+0.12/17 0} Nxa3 {0.00/28 1} 43. Ra1 {+0.08/17 0} Qa8 {0.00/30 1} 44. Kg3
{0.00/22 2} Rg4+ {0.00/25 1} 45. Kh2 {0.00/22 0} Rh4+ {0.00/38 4} 46. Kg3
{0.00/25 3} Rg4+ {0.00/37 1} 47. Kh2 {0.00/27 0} Rh4+ {0.00/40 3} 48. Kg3
{0.00/33 1 3-fold repetition} 1/2-1/2
ferdy
  • 4,396
  • 2
  • 4
  • 16
  • I tried like that def __init __ (self, engineLocation, engineNames, margin, hashmb): self.engineFolder = engineLocation self.engineFileNames = engineNames self.score_margin = margin / 100 # given in centipawns, default: 50 self.hashmb = hashmb – Marco C. May 21 '22 at 17:20
  • Hello and thanks for the reply, i tried your suggestions on a system already tested with 2 chess engines with stockfish 15 original executables with default options, but unfortunately it doesn't work. to fix the problem permanently I should have 8 stockfish 15 exe files each with a different NNUE network and the options Hash, Thread and SyzygyPath instead are configured with the same parameters. anyway thanks again for your reply – Marco C. May 22 '22 at 00:55
  • Indeed the existing `send_command_to_engines()` always send the same options to all engines. I will update my answer with new solution to set options individually. – ferdy May 22 '22 at 01:25
  • Added method 3 to set engine options individually. – ferdy May 22 '22 at 02:04
  • Hello, I installed method 3 with 8 engines and 8 different NNUE networks and the other 3 parameters are the same for everyone, it works perfectly and is also visibly faster because in this way the management of the chess engines is direct, but how can I check if the 8 chess engines are actually using the 8 different NNUE networks ? – Marco C. May 22 '22 at 15:00
  • Hi Ferdi, you are a genius, I had tried empirically but without success, even with Visual Studio! if you want the version of the program with 8 engines (stockfish 15) I can send it by e-mail complete with certified NNUE networks, but in the .bat file you have to change the path indicating the directory where all the files are located and the path where you find the python.exe file, also in the goratschinLauncher.py file you must obviously change the directory where the .exe files are located thanks again for your precious cooperation – Marco C. May 22 '22 at 16:53
  • What do you mean by ` I had tried empirically but without success, even with Visual Studio!`? – ferdy May 23 '22 at 02:25
  • I mean that with Visual Studio I was able to change the options but then I could not create the executable file .exe, in short, in the end I gave up. However now the system is running smoothly on the Arena 3.5.1 GUI, thanks to your availability. within this week I will see what results I will get from the over 100 games I have set; the single chess engine Stockfish 15 nnue versus the 8 chess engines Stockfish 15 nnue with 60 minute games, and if my theory is correct the multiple system should prevail by a few ELO points – Marco C. May 23 '22 at 03:29
  • Are you still interested to verify this: `how can I check if the 8 chess engines are actually using the 8 different NNUE networks ?` If you are I will provide method 4. – ferdy May 23 '22 at 03:40
  • yes, if there is a method to check if the chess engines during the game each use their NNUE network that would be great, in this way we would have the certainty that the system is working at 100%. at this address the system for choosing the Best Move is explained step by step: https://github.com/scacchig/Synergy-Chess if you want I can write about your contribution, and in this case send me the text to this e-mail: marco.marigip@gmail.com – Marco C. May 23 '22 at 06:44
  • Added method 4, after setting the options, we let the engine run at depth 1 to see its output on which nnue it runs. – ferdy May 23 '22 at 22:41
  • Hello Ferdy the system works and with good results, but I still have one last question. The GUI Arena at the first start of the 8 chess engines displays this : engine 7 started as counselor 7 (SFa8) .................. engine 0 started as boss (SFa1) My question : it is possible to have the GUI Arena read the name of each NNUE network that is written in the goratschinLauncher.py en write this : example : engine 7 started as counselor 7 (SFa8) engine 7 (SFa8) nn-cdf1785602d6.nnue ................. engine 0 started as boss (SFa1) engine 0 (SFa1) nn-6877cd24400e.nnue – Marco C. May 27 '22 at 17:17
  • This is the Link Screenshot of the first start of Arena GUI 3.5.1 : https://drive.google.com/file/d/1lb1jEyBRNhzEOM9BF789x5JTkmnRjJq3/view?usp=sharing – Marco C. May 27 '22 at 17:30
  • Regarding last one question, arena has an engine log feature, you can view all the commands sent to the engine and replies from engine. If this is not what you want, send me your py files where there is only two-engine setup. I need to test it in actual. – ferdy May 29 '22 at 00:51
  • Hi Ferdy this is the Google Drive link with the files relating to the system with 2 chess engines ; https://drive.google.com/file/d/1AOnVId8gy_jIRrk35gW__1bHfjo9s5y-/view?usp=sharing it contains 1 goratschinLauncher.py file, 1 goratschinChess.py file, 1 goratschinLauncher.bat file, the 2 executables of the 2 chess engines, the 2 NNUE networks, 1 README.txt Obviously the goratschinLauncher.bat file must be modified with the path of your Python.exe and the path of the directory where you will install the files – Marco C. May 29 '22 at 06:36
  • Thanks I got the files. There are still issues on the options, I will revise both py files to make this work. – ferdy May 29 '22 at 08:27
  • OK, in the README file I have not written that in the goratschinLauncher.py file there is my path where I have inserted all the files and which obviously must be replaced with yours. – Marco C. May 29 '22 at 11:21
  • While testing my revisions to py files, the engine will not run, later I found out the attached 2 nnue files are not compatible with the attached 2 engines. I downloaded 2 new nnue files and it now works. The goratschinchess.py file does not show its output or logs when the engine sent `info string NNUE evaluation ..` This is the reason why we cannot see engine comment that it is using the new NNUE files. I have now enabled this. I will continue testing it, hopefully it will be done in a day or two. – ferdy May 30 '22 at 06:17
  • Well, in the meantime I continue with the tests of the version with 8 chess engines which uses the NNUE networks by default – Marco C. May 30 '22 at 08:54
  • This is the [link](https://drive.google.com/file/d/19zMz4Rf6GSPIsKd9lWz0Qg0E3ixELrC_/view?usp=sharing) to the modified 2 py files. I have tested this in arena and cutechess gui's and it all works. See also the changes posted in the answer. They are just the same. – ferdy May 30 '22 at 12:23
  • Hi Ferdy I tried the version with 2 chess engines you revised and it's OK, but on the 8 CE version it doesn't work. I made the changes in the version with 8 CE (currently working without changes) by assigning each chess engine its own NNUE network by default, in total there are 3 NNUE networks. ------ this is the link of the 2 .py files that I modified ---- https://drive.google.com/file/d/1dVdJjybtk6p3URi0tzE653bYHlPrlVlg/view?usp=sharing – Marco C. Jun 01 '22 at 13:54
  • Use this: `def __init__(self, engineLocation, engineNames, margin, options):` The options was missing in your code. Is this the latest in github? I think I will just check the code there. – ferdy Jun 01 '22 at 14:24
  • I have already corrected my forgetfulness and now it also works with the version of 8 chess engines, but each chess engine only accepts its nnue network by default, therefore, +/- 3/4 nnue networks for 8 different chess engines or different Stockfish Development Versions. Later or tomorrow I update the version on github and Google Drive – Marco C. Jun 01 '22 at 16:39
  • I updated the version with 8 chess engines on Github, and if you want to try it here are all the files, including the executables of the 8 chess engines : https://drive.google.com/file/d/1pKH9MByNX8WMHYZ6XHys6CGT6YAL3EoF/view?usp=sharing – Marco C. Jun 01 '22 at 18:34
  • Hi Ferdi, do you have the Fisherov K or G or J NNUE or Fisherov Chess Monk 1.1 NNUE chess engine? I tried to request a version for personal use through https://chessengines.blogspot.com but they don't respond. – Marco C. Jun 03 '22 at 12:25