New chess engine: Rustic

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Rebel, chrisw

User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

New chess engine: Rustic

Post by mvanthoor »

Image

(Upcoming engine: not yet finished)

For some time now, I've been writing my own chess engine from scratch in the Rust programming language. I am now at the point of testing the move generator and make/unmake move functions, before I start writing the search function and a simple evaluation to finish the first version.

It has a website in the making, at the address: https://rustic-chess.org/

As soon as it is able to play games and a base ELO-rating can be determined, it will be released on GitHub under the GPLv3 open source license.

Some move generator output is below. It can now do king, knight, and pawn moves, pawn captures and en-passant; it can also classify moves as such (for later move ordering). Things such as hashing and some auxiliary functionality have been implemented. The two things to be implemented are the bitboards for sliders, and the castling move generation (for which I obviously need the slider bitboards first, as I need to be able to detect rook/bishop/queen attacks on the castling squares). After this is done, the move generator can be tested in Perft, and then only Alpha/Beta and the UCI function need to be done. Then the engine should be finished, as the evaluation will, in the beginning, only use material counting and PST's.

It'll take some time yet, because I'm basically only writing this engine in the weekends. So, why do I post this now? Basically it's another motivation to finish it as soon as I'm able, so I can test where its base ELO is at, and then start to improve it. I hope to chronicle the engine's progress the same way as Eric Madsen is doing with Madchess over at madchess.net, and x_r_a_y with Minic on this site.

Code: Select all

Engine: Rustic 0.1
Author: Marcel Vanthoor

8   . B . . . . . .
7   . . . . k N . .
6   . . n . I . . .
5   . . . . . . . .
4   . I . i I . . .
3   . . . . . . . .
2   . i . . . . i .
1   R . . . K . . N

    A B C D E F G H

en_passant: 20
Move 1: Ke7d6 capture: -, promotion: -, ep: false
Move 2: Ke7e6 capture: Pawn, promotion: -, ep: false
Move 3: Ke7f6 capture: -, promotion: -, ep: false
Move 4: Ke7d7 capture: -, promotion: -, ep: false
Move 5: Ke7f7 capture: Knight, promotion: -, ep: false
Move 6: Ke7d8 capture: -, promotion: -, ep: false
Move 7: Ke7e8 capture: -, promotion: -, ep: false
Move 8: Ke7f8 capture: -, promotion: -, ep: false
Move 9: Nc6b4 capture: Pawn, promotion: -, ep: false
Move 10: Nc6a5 capture: -, promotion: -, ep: false
Move 11: Nc6e5 capture: -, promotion: -, ep: false
Move 12: Nc6a7 capture: -, promotion: -, ep: false
Move 13: Nc6b8 capture: Bishop, promotion: -, ep: false
Move 14: Nc6d8 capture: -, promotion: -, ep: false
Move 15: b2a1 capture: Rook, promotion: Queen, ep: false
Move 16: b2a1 capture: Rook, promotion: Rook, ep: false
Move 17: b2a1 capture: Rook, promotion: Bishop, ep: false
Move 18: b2a1 capture: Rook, promotion: Knight, ep: false
Move 19: b2b1 capture: -, promotion: Queen, ep: false
Move 20: b2b1 capture: -, promotion: Rook, ep: false
Move 21: b2b1 capture: -, promotion: Bishop, ep: false
Move 22: b2b1 capture: -, promotion: Knight, ep: false
Move 23: g2g1 capture: -, promotion: Queen, ep: false
Move 24: g2g1 capture: -, promotion: Rook, ep: false
Move 25: g2g1 capture: -, promotion: Bishop, ep: false
Move 26: g2g1 capture: -, promotion: Knight, ep: false
Move 27: g2h1 capture: Knight, promotion: Queen, ep: false
Move 28: g2h1 capture: Knight, promotion: Rook, ep: false
Move 29: g2h1 capture: Knight, promotion: Bishop, ep: false
Move 30: g2h1 capture: Knight, promotion: Knight, ep: false
Move 31: d4d3 capture: -, promotion: -, ep: false
Move 32: d4e3 capture: -, promotion: -, ep: true
Done.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
supersharp77
Posts: 1242
Joined: Sat Jul 05, 2014 7:54 am
Location: Southwest USA

Re: New chess engine: Rustic

Post by supersharp77 »

mvanthoor wrote: Sun Feb 23, 2020 10:26 pm Image

(Upcoming engine: not yet finished)

For some time now, I've been writing my own chess engine from scratch in the Rust programming language. I am now at the point of testing the move generator and make/unmake move functions, before I start writing the search function and a simple evaluation to finish the first version.

It has a website in the making, at the address: https://rustic-chess.org/

As soon as it is able to play games and a base ELO-rating can be determined, it will be released on GitHub under the GPLv3 open source license.

Some move generator output is below. It can now do king, knight, and pawn moves, pawn captures and en-passant; it can also classify moves as such (for later move ordering). Things such as hashing and some auxiliary functionality have been implemented. The two things to be implemented are the bitboards for sliders, and the castling move generation (for which I obviously need the slider bitboards first, as I need to be able to detect rook/bishop/queen attacks on the castling squares). After this is done, the move generator can be tested in Perft, and then only Alpha/Beta and the UCI function need to be done. Then the engine should be finished, as the evaluation will, in the beginning, only use material counting and PST's.

It'll take some time yet, because I'm basically only writing this engine in the weekends. So, why do I post this now? Basically it's another motivation to finish it as soon as I'm able, so I can test where its base ELO is at, and then start to improve it. I hope to chronicle the engine's progress the same way as Eric Madsen is doing with Madchess over at madchess.net, and x_r_a_y with Minic on this site.
Nice Name.interesting Concept! Well.. My slightly delayed "World Engs Swiss Champs 2020" is due for a restart soon (next month or so) it would be nice to have a 'Rustic' version available for some testing...Congrats on your New Project..
:) :wink: Thx AR
User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

Re: New chess engine: Rustic

Post by xr_a_y »

Great experience to start from the blank page !
Wish you the best.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: New chess engine: Rustic

Post by mvanthoor »

@supersharp77:

Thanks :) Good luck with your own engine. There are a few engines at the start of the development cycle right now:

- Rustic (my engine; not even finished)
- World Engs Swiss Champs 2020 (is that going to be its actual name? Not finished)
- Stash, by mhouppin (Working, original AFAIK)
- seeChess, by bctboi23 (Working, based on VICE, so at least 2000 ELO already)

My main source of information is actually also VICE, by BlueFever software; not the engine or the code, but the explanations of the concepts. I know most of them already, but my knowledge is sketchy because I haven't been doing programming work such as this for a long, long time. BlueFever Software explains them very well.

There isn't a single line of code of Vice in Rustic. It's not even possible in many places, because Vice is a version of a mailbox engine iterating over squares and pieces, where Rustic uses fancy magic bitboards.

Even so, the bitboards are generated using a mailbox helper board to detect edges and make calculating knight jumps easier. This makes the code for generating bitboards straightforward, and very easy to read and understand. It doesn't matter if this method is not not super fast, because it's only used once while starting the engine.

I consider BlueFever Software/Vice my primary teacher. On Rustic's website, I wrote that Rustic will be version 0.1 until I deem it to be strong enough. I think I'm going to call the development version Rustic Alpha, and then just number it 1, 2, 3, etc... as I add new functions. (Instead of 0.1, 0.2, etc...) The Vice engine is in the CCRL 40/15 list at around 2050 ELO. Rustic probably will become version 1.0 after it surpasses Vice comfortably in the rating list; lets say, when as it reaches 2150 ELO.

@xr_a_y

Thanks as well :) I've been following Minic's progress for some time. Congrats on recently hitting 3000 ELO in the CCRL blitz list :)

I've been wanting to do this for a very long time, but never took the time to actually do it. I wrote a very simple mailbox engine as a teenager in the 90's, using books from the library. It played legal moves, and that was it, basically. I had to put in moves on the commandlien. No internet for more information, no UCI, not enough knowledge; but I put writing my own chess engine from scratch on my bucket list.

I could have started this 15 years ago in my university days, writing in C, but always there were always "other" things to do. I like the Rustic language a lot, and writing a chess engine is a good way to actually get a chess engine written from scratch, and learn this language at the same time.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Alayan
Posts: 550
Joined: Tue Nov 19, 2019 8:48 pm
Full name: Alayan Feh

Re: New chess engine: Rustic

Post by Alayan »

mvanthoor wrote: Mon Feb 24, 2020 4:57 pm - World Engs Swiss Champs 2020 (is that going to be its actual name? Not finished)
That's a tournament, obviously. He was thinking of including your engine in it if stable enough.

Good luck on your endeavor with Rustic. My advice would be to focus on all the parts of the engines that are going to be useful for a very long time. Make them clean, make them reliable, make them fast. Better speed in the core parts of the engine will help for the whole life of the engine for playing and more importantly to speed up testing. Then, search is an easy source of massive elo gains. A PSQT eval with maybe basic mobility is more than enough until at least 2500 elo CCRL, and if you write an eval meant to work with a bad search, you'll find out as you improve the search that the eval isn't working very well for a better search.
bctboi23
Posts: 20
Joined: Fri Feb 07, 2020 2:48 am
Location: United States
Full name: Tom R

Re: New chess engine: Rustic

Post by bctboi23 »

As @Alayan says, I would recommend working on the search for a while, and delaying building an advanced evaluation until later. I gained almost 150 elo from the search without much effort, and I could probably gain about 50-100 elo more with tuned values in the search.

P.S. I renamed seeChess to CeeChess cuz there’s already an engine named SEEchess. :D

I wonder if trying to convert to bitboards would help move gen speed a ton, or if my time is better spent writing a SEE function. How fast is your current move generator?
User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

Re: New chess engine: Rustic

Post by xr_a_y »

No evaluation other than pst and very simple passed pawn under 2500 seems a good rule of thumb indeed
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: New chess engine: Rustic

Post by mvanthoor »

Thanks for the advice and encouragement :)

After I've read on Rofchade.nl that it's possible to achieve almost 2800 ELO on CCRL using PST's and a tapered evaluation only, I'd already decided to concentrate on adding (pruning) functionality to the search.
bctboi23 wrote: Mon Feb 24, 2020 5:46 pm I wonder if trying to convert to bitboards would help move gen speed a ton, or if my time is better spent writing a SEE function. How fast is your current move generator?
Ask xr_a_y / Vivien; he actually converted Minic from mailbox to bitboards if I recall correctly, and I also seem to remember that the speedup gained him around 200 ELO. That said, I expect the move generator to be very fast. This is the function that generates king and knight moves:

Code: Select all

fn non_slider(piece: Piece, board: &Board, side: Side, magics: &Magics, list: &mut MoveList) {
    let us = board.bb_pieces[side];
    let mut pieces = board.get_pieces(piece, side);
    while pieces > 0 {
        let from = next(&mut pieces);
        let target = magics.get_non_slider_attacks(piece, from);
        let moves = target & !us;
        add_move(board, piece, side, from, moves, list);
    }
}
This could have been even shorter, but I don't like writing everything inline, as I think it makes code hard(er) to understand. The compiler will optimize this easily, either inlining, collapsing and dropping statements where possible.

This code generates all pawn moves:

Code: Select all

fn pawns(board: &Board, side: Side, magics: &Magics, list: &mut MoveList) {
    let opponent_pieces = board.bb_pieces[side ^ 1];
    let empty = !board.occupancy();
    let direction = if side == WHITE { UP } else { DOWN };
    let fourth = if side == WHITE { BB_RANK_4 } else { BB_RANK_5 };
    let mut pawns = board.get_pieces(PAWN, side);
    while pawns > 0 {
        let from = next(&mut pawns);
        let push = 1u64 << (from as i8 + direction);
        let one_step = push & empty;
        let two_step = one_step.rotate_left((64 + direction) as u32) & empty & fourth;
        let targets = magics.get_pawn_attacks(side, from);
        let captures = targets & opponent_pieces;
        let ep_capture = if let Some(square) = board.en_passant {
            targets & (1u64 << square)
        } else {
            0
        };
        let moves = one_step | two_step | captures | ep_capture;
        add_move(board, PAWN, side, from, moves, list);
    }
}
Same here: the compiler will inline, collapse and drop the let-statements where possible. Inlining it myself to make the function shorter isn't necessary. Rust has zero-cost abstractions, so it strips everything down to the bare minimum wherever possible. (Just like current C and C++ compilers do; rust actually uses LLVM, just like CLANG.)

The add_move() function handles all the things with regard to move classification (quiet, capture, en-passant, promotion, etc), and it'll add four moves when promoting a pawn. The entire move generator is basically only shifting some bits to and fro, not really calculating anything (that has been done in the bitboards already), so if the program is slow, the problem should be somewhere else.

(PS: This will be a pseudo-legal move generator; in_check() will be done when making/unmaking moves.)
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

Re: New chess engine: Rustic

Post by xr_a_y »

Speed up going to BB instead of mailbox very depends on own much / how you are accessing the data.
It is very possible to make a mailbox engine fast.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: New chess engine: Rustic

Post by mvanthoor »

xr_a_y wrote: Mon Feb 24, 2020 7:38 pm Speed up going to BB instead of mailbox very depends on own much / how you are accessing the data.
It is very possible to make a mailbox engine fast.
Of course you can cut down some amount of calculation in a mailbox engine. Piece lists is one (Vice uses this) so you don't have to iterate over the squares to find pieces. You can also count once, and then cache the result of each ray, only updating it if something on that ray changes.

Still, in the end, I think it'll never be as fast as a bitboard engine.

The difficulty with regard to move generation is displaced from the move generator to the bitboard initializer; at least, that is what I'm finding. Now I have to do all the iterations and calculations in the magic bitboard module instead of in the move generator. Obviously that's the entire point; the bitboards (almost) calculate every possible move for every possible piece on every possible square, so you don't have to do it again and again in the move generator.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL