Skip to content

Latest commit

 

History

History
102 lines (71 loc) · 4.05 KB

README.md

File metadata and controls

102 lines (71 loc) · 4.05 KB

♔ Chess Engine in Rust ♚

This repo contains the code of a chess engine fully written in Rust, from scratch, and the UI to interact with it. I would like to keep expanding this project to create a Chess annotation software.

This is one of my many personal projects in Rust. And it is my second chess engine (I had done the first in C++)

It features:

  • All the rules of chess written in a very compact format (1 game is represented with 8 bytes)
  • alpha-beta pruning
  • move ordering to favor captures
  • iterative deepening to improve move ordering

Quick Start

The only required dependency is Rust with cargo.

Feel free to try it out and let me know !

git clone <...>
cd chess_rust
cargo run --bin chess --release

The flag --release tells rust to optimize the code (this is absolutely required), and --features fltk specify that you want to compile the UI and to run with the UI.

[Dev] TODO List for myself

List of missing features

  • Chess Rules

    • En Passant, using a stateful representation
    • Non-queen promotions
  • Engine

    • Parallel alpha-beta pruning
    • Engine Server to keep expanding while the other player is thinking
  • UI to become a chess annotation software

    • Allow to resize the window
    • Show the list of move
    • Be able to come back in the list of move
    • Be able to create variations in the list of move

More words about the Engine

  • Tree-search for the best move (min-max algorithm). The resulting computing speed is about 500'000 moves / second.
    • Alpha Beta pruning to do it faster
    • Transposition table to avoid double computation
    • Extra depth for captures move
  • Evaluation function that favors attacking positions
  • An extremely light-weight chess representation
  • UI to play locally on your computer

The whole idea behind this chess engine is that the representation of a chess game is very small: it's only 7 integers !

pub struct ChessGame {
  whites: u64,
  pawns: u64,
  bishops: u64,
  knights: u64,
  rooks: u64,
  queens: u64,
  kings: u64,
  flags: u64
}

This was a design decision, that has benefits and drawbacks.

  • Drawbacks: it's a bit hard to represent moves, captures, ...
  • Benefits: It's super quick to copy a game, therefore the solver can just create massive amounts of games instead of having to work with a single game.

This code contains the following part:

  • The representation of a chess game (position of pieces, rules to determine if moves are valid), under model/game.rs and model/moves.rs. This part is really the most difficult part.
  • The chess engine. Basically, it's a recursive function that explores the tree of possible moves until a given depth. The tree-serach algorithm is a min-max search with alpha-beta prunning. The engine is located under model/engine.rs
  • To play with this engine, I have developed a UI very easy to deploy with FTLK.rs. There is also a WebApp (because i wanted to try yew.rs) in the eventual possibility to host this engine on my website...

Why a chess engine to learn Rust ?

Programming a chess engine is a brilliant exercise for an accomplished developer. I think that chess programming is really the perfect project for testing your own skills.

  • It is easy enough to not take too long: it can be done in a few weeks / months, which is good for self-projects. I often have the problem to start projects too long and I end up tired of them.
  • It is difficult enough to really challenge you. There are some things that are really not trivial. Encoding the rule of chess in a way to allows to have a depth of search good enough is really not easy.

How to optimise the score function ?

  • solver calls game.getAllMoves --> we know the size here.
  • for each move, create a new game
  • for each new game, call the solver : if finished, call game.score()

==> for a given game, game.score() is always called before game.getAllMoves ...

Benchmarking result

The command cargo run without any features will run the benchmarking test.