How to determine your chess bot's ELO on Lichess
I recently got into chess programming. After creating my first bot, I wanted to estimate its ELO to get an indication of its skills. I personally this process a bit cumbersome. Therefore I wanted to create this guide, so others might have an easier time.
NOTE: As I am using a Mac, some details may be specific to MacOS.
Creating a chess bot
The first step is, naturally, to have a working chess bot. Preferably one that only makes legal moves. If you are only interested in creating the chess bot (and not implementing the chess move generation), I would highly recommend Sebastian Lague's Chess Challenge code. He also has some good videos on chess programming on YouTube.
Making your bot UCI compatible
UCI (Universal Chess Interface) is a chess communication protocol. It lets bots play against each other. This is what we want to do on Lichess, so that it can calculate an ELO for our bot.
If you build your bot using the Chess Challenge code, it won't have UCI support by default. I added it manually, and you can see the changes I made in this commit (this is based on a post on the Chess Challenge Discord). You can probably take inspiration from the changes in the commit even if you built your bot using some other code.
Connect your bot to Lichess
Once you have a chess bot that can play using the UCI protocol, you are ready to connect it to Lichess. You can do this through the lichess-bot code. It handles the complexity of communicating with Lichess bot API. Follow their guide on how to set it up here.
I had some trouble setting this up, so here are some tips:
Start by cloning this repo (even though the tutorial tells you to download it). This will make it easier for you to see what changes you have made.
Once the repo is downloaded, rename the
config.yml.defaultfile toconfig.yml.Create an account on Lichess, and create an OAuth2 token with the right scope, as described in the tutorial.
Upgrade your account to a Bot account as described in the tutorial. You have to copy the
curlcommand on the Lichess API docs site and run it in the terminal with your token from the previous step.
Once you have successfully performed the steps above, it is time to edit the config.yml file. If you built your bot on the Chess Challenge code, you should change your config file to look like this:
token: "<yourTokenHere>" # Lichess OAuth2 Token.
url: "https://lichess.org/" # Lichess base URL.
engine: # Engine settings.
dir: "/.../Chess-Challenge/Chess-Challenge/bin/Debug/net9.0"
name: "Chess-Challenge.dll" # Binary name of the engine to use.
interpreter: "dotnet"
interpreter_options:
- "uci"
- "MyBot"
working_dir: "/.../Chess-Challenge"
protocol: "uci"
A couple things to note here:
I use absolute paths (meaning from root "/") for both "dir" and "working_dir".
I upgraded Chess Challenge project to .NET 9. This is not necessary, but I recommend it as it made the code run faster.
As I am using a Mac, for the binary file, you have to give the path to the
.dllfile. On Windows you would have to give the path to the.exefile.
I also made some changes in other places in the config.yml file:
I commented out the
homemade_optionsoptions.I set
accept_bot: trueunder thechallengesection.I set
challenge_timeout: 1under thematchmakingsection. This allows your bot to challenge other players every minute.
Some modifications are also needed in the lichess-bot/lib/engine_wrapper.py file for the lichess-bot to properly work with your code. I made some changes to how the interpreter options were added to the command executed to run the chess bot binary. The beginning of the file should look like this:
def create_engine(engine_config: Configuration, game: Optional[model.Game] = None) -> EngineWrapper:
cfg = engine_config.engine
engine_path = os.path.abspath(os.path.join(cfg.dir, cfg.name))
engine_type = cfg.protocol
commands = []
if cfg.interpreter:
commands.append(cfg.interpreter)
commands.append(engine_path)
commands.extend(cfg.interpreter_options)
if cfg.engine_options:
for k, v in cfg.engine_options.items():
commands.append(f"--{k}={v}" if v is not None else f"--{k}")
This instructs lichess-bot to run dotnet /.../Chess-Challenge/Chess-Challenge/bin/Debug/net9.0/Chess-Challenge.dll uci MyBot to start your bot. If you start your bot program in UCI mode using another command, you can edit the interpreter and interpreter options in the config.yml file so that the right command gets executed.
Finally, you might have to set execute permission on your chess bot's binary file. On Mac you can do this by running this command chmod +x /.../Chess-Challenge.dll.
NOTE: If you change your bot code and build your project again, you might have to give execute permissions again.
Hopefully, your bot should be able to play on Lichess and get an ELO rating now :) If you have any questions or comments feel free to reach out!