Progress on Rustic

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

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

Progress on Rustic

Post by mvanthoor »

Hi :)

As there are a few people who seem to be interested in Rustic, I'm posting a short progress report. The cataract operation went as planned, and recovery also seems to be as planned an on schedule, so I have (slowly) picked up Rustic's development again. In the last few days, I've been able to do the following:

- Code cleanup and reorganization where necessary.
- Create a generic way to plug in communication modules. In time, Rustic will be able to support UCI, XBoard, and its own Console text-based user interface, in modular fashion. The Console text interface already accepts moves, and it runs in its own thread. (UCI and XBoard will as well, obviously.)
- Integrated the CLAP command line parser. Rustic can now do FEN setups and run Perft from the command line without recompiling the program. (Finally.)
- Feature-gated two functions. They won't be in a normal engine build, but they can be included by building with the '--features = "extra" Cargo flag.
* "--wizardry / -w": generates magic numbers for LSB-based magic bit boards. (So people can actually see and study where the magics in magics.rs come from.)
* "--epdtest or -e": runs the full EPD test suite that floats around the net, with many additions posted on Talkchess. This can be used to run 172 perft tests to make sure changes to the move generator are working.
- Because putting the Console text UI into its own thread was quite easy after some jacking around, I decided to also add multi-threading to perft. It works. On an almost 5 year old i7-6700K, running 8 threads (including the logical cores), Rustic now runs perft between 140 and 170 million leaves per second depending on the position.

Code: Select all

$ ./target/release/rustic.exe --fen "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1" --perft 6 --threads 8
Program: Rustic Alpha 1
Author: Marcel Vanthoor <mail@marcelvanthoor.nl>
Description: Chess Engine written in Rust
FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1
Benchmarking perft 1-6 on 8 threads

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

    A B C D E F G H

Zobrist key:        fb86acbc2034870e
Active Color:       White
Castling:           KQkq
En Passant:         -
Half-move clock:    0
Full-move number:   1

Perft 1: 48 (0 ms, inf leaves/sec)
Perft 2: 2039 (0 ms, inf leaves/sec)
Perft 3: 97862 (1 ms, 97862000 leaves/sec)
Perft 4: 4085603 (27 ms, 151318629 leaves/sec)
Perft 5: 193690690 (1135 ms, 170652590 leaves/sec)
Perft 6: 8031647685 (49235 ms, 163128824 leaves/sec)
Total time spent: 50398 ms
Execution speed: 163290684 leaves/second
Next to do in this order:
- Add alpha-beta
- Add quiescence search
- Add PSQT on top of material counting
- Add UCI interface

At that point, Rustic 1 will be done. Then I'll start writing the book with regard to its development, which will be at rustic-chess.org. (It will basically be a "The basics of chess programming" book, using Rust.)

After that, I'll start improving the engine with a transposition table, new search functions such as null move, killers, etc..., multi-threaded search (Lazy SMP), better evaluations... which will hopefully lead to a "More advanced topics of chess programming" book.

I think I'll be busy for the next few... years.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Gabor Szots
Posts: 1362
Joined: Sat Jul 21, 2018 7:43 am
Location: Szentendre, Hungary
Full name: Gabor Szots

Re: Progress on Rustic

Post by Gabor Szots »

Splendid news, Marcel. :D

I can hardly wait for Rustic 1. And the book, too, although I will have to learn some Rust before reading it, I'm not sure I am up to that task. :(

Have you also found the computer of your dreams? I remember you were longing for some 14-core machine.
Gabor Szots
CCRL testing group
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Progress on Rustic

Post by mvanthoor »

Gabor Szots wrote: Thu Sep 17, 2020 3:17 pm Splendid news, Marcel. :D

I can hardly wait for Rustic 1. And the book, too, although I will have to learn some Rust before reading it, I'm not sure I am up to that task. :(
Thanks :) I can't wait to start testing it myself. Almost there.

Please do not expect too much of it in the first few versions. The engine will be weak; I estimate that it'll enter the rating list at around 1450 ELO, just like Stash did some time ago.

The reason is that I want to write that book / tutorial, called "Chess Programming Basics (using the Rust Programming Language)", followed by a somewhat more advanced book / tutorial where I'm going to implement a hash table, search function extensions (LMR, Null move, etc, etc). I wish to be able to chronicle the engine's advancement in strength per added feature.

On Rust: The basics of Rust aren't harder than any other programming language.

If you can write software that doesn't crash (i.e., use pointers correctly) in C, you'll be off to the races with Rust in no-time. If you're used to memory management languages or scripting languages where you can do whatever you want, then... maybe not. The compiler will relentlessly beat you over the head with any and every memory violation you're creating. It's only when you get to the more advanced stuff (Generics, Traits/Interfaces, Generic Traits, and stuff like life-times) that Rust becomes difficult; and I haven't even -touched- on Macro's and Macro's with Generics. But, you don't need most of that for a chess engine. Fortunately. (Really. I'm actually afraid to study some of that stuff.)

So if you understand C, you will be able to understand Rustic.
Have you also found the computer of your dreams? I remember you were longing for some 14-core machine.
No. I don't want an AMD-computer at this time, because I don't trust their BMI2 and PEXT / PDEP implementations. Rustic already uses BMI2, and it will use PEXT bitboards somewhere in the future. The fastest version on AMD would be POPCOUNT, and I can't abide by implementing/using a new feature, and then seeing a speed DROP instead of gain due to poor implementation on the part of the CPU. That would mean that I can't reliably test my own code, and that doesn't cut it.

So in the upcoming new Ryzens AMD will either have to fix BMI2, PEXT and PDEP implementations, or I'll be waiting for Intel.

In case of an Intel, my cue to start looking for a new computer will be when Intel replaces the 2017 vintage X299 chipset. By that time, they'll probably also replace the 109---X CPU's with 119---X versions; or 129---X versions. Whatever, I'm not going to buy a CPU with sub-par intrinsic implementations, nor am I going to buy a CPU that'll sit on a mainboard that's 3 years old at the time of buying it.

I'll wait. Now that I've implemented multi-threading in Perft, I can make changes and test if they still work / don't slow down execution too much about 5 times faster than I could a week ago :) The only reason I'd want a new computer is when I start running tournaments for ELO testing. At some point I'll probably have to look into OpenBench.

edit: I think I'm going to use this thread to post new versions and progress as its made. Shouldn't it have been in the General forum? If so, I'd be happy for a moderator to move it.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Progress on Rustic

Post by maksimKorzh »

mvanthoor wrote: Thu Sep 17, 2020 1:27 am Hi :)

As there are a few people who seem to be interested in Rustic, I'm posting a short progress report. The cataract operation went as planned, and recovery also seems to be as planned an on schedule, so I have (slowly) picked up Rustic's development again. In the last few days, I've been able to do the following:

- Code cleanup and reorganization where necessary.
- Create a generic way to plug in communication modules. In time, Rustic will be able to support UCI, XBoard, and its own Console text-based user interface, in modular fashion. The Console text interface already accepts moves, and it runs in its own thread. (UCI and XBoard will as well, obviously.)
- Integrated the CLAP command line parser. Rustic can now do FEN setups and run Perft from the command line without recompiling the program. (Finally.)
- Feature-gated two functions. They won't be in a normal engine build, but they can be included by building with the '--features = "extra" Cargo flag.
* "--wizardry / -w": generates magic numbers for LSB-based magic bit boards. (So people can actually see and study where the magics in magics.rs come from.)
* "--epdtest or -e": runs the full EPD test suite that floats around the net, with many additions posted on Talkchess. This can be used to run 172 perft tests to make sure changes to the move generator are working.
- Because putting the Console text UI into its own thread was quite easy after some jacking around, I decided to also add multi-threading to perft. It works. On an almost 5 year old i7-6700K, running 8 threads (including the logical cores), Rustic now runs perft between 140 and 170 million leaves per second depending on the position.

Code: Select all

$ ./target/release/rustic.exe --fen "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1" --perft 6 --threads 8
Program: Rustic Alpha 1
Author: Marcel Vanthoor <mail@marcelvanthoor.nl>
Description: Chess Engine written in Rust
FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1
Benchmarking perft 1-6 on 8 threads

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

    A B C D E F G H

Zobrist key:        fb86acbc2034870e
Active Color:       White
Castling:           KQkq
En Passant:         -
Half-move clock:    0
Full-move number:   1

Perft 1: 48 (0 ms, inf leaves/sec)
Perft 2: 2039 (0 ms, inf leaves/sec)
Perft 3: 97862 (1 ms, 97862000 leaves/sec)
Perft 4: 4085603 (27 ms, 151318629 leaves/sec)
Perft 5: 193690690 (1135 ms, 170652590 leaves/sec)
Perft 6: 8031647685 (49235 ms, 163128824 leaves/sec)
Total time spent: 50398 ms
Execution speed: 163290684 leaves/second
Next to do in this order:
- Add alpha-beta
- Add quiescence search
- Add PSQT on top of material counting
- Add UCI interface

At that point, Rustic 1 will be done. Then I'll start writing the book with regard to its development, which will be at rustic-chess.org. (It will basically be a "The basics of chess programming" book, using Rust.)

After that, I'll start improving the engine with a transposition table, new search functions such as null move, killers, etc..., multi-threaded search (Lazy SMP), better evaluations... which will hopefully lead to a "More advanced topics of chess programming" book.

I think I'll be busy for the next few... years.
Cool!
I'm just a bit confused why Rustic 1 would have only alpha beta and no move ordering or improvements?
Or that was assumed implicitly?
Or is that a development philosophy to have weak first version and then improve?
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Progress on Rustic

Post by mvanthoor »

maksimKorzh wrote: Thu Sep 17, 2020 6:13 pm Cool!
I'm just a bit confused why Rustic 1 would have only alpha beta and no move ordering or improvements?
Or that was assumed implicitly?
Or is that a development philosophy to have weak first version and then improve?
Emphasis mine.

Yes, that is the philosophy. I want to write the most basic chess engine possible that still plays somewhat decent chess (*).

By doing it this way, I can measure the impact of every addition I make.

- Basic version with nothing but a/b-search and quiescence search: 1450 ELO
* Move ordering: +100 ELO
* Hash table: +125 ELO
* Null Move: +85 ELO

Obviously I'm just guessing these numbers, but you get the idea. I want to know how much ELO each feature adds. The reason I add move ordering and the hash table first, is that they are among the most important features for gaining speed.

I can run a gauntlet tournament against other engines, and then I'll know where each new version would approximately fall within the CCRL/CEGT lists. Maybe each addition will have its own Rustic version; but if I do that, I don't expect CCRL/CGET to test all of them. That would be waaaaaay too much work.

===

(*) (with "basic", I mean "limited number of features in the engine", not "very basic programming techniques." The feature of the threaded perft function was... uh... an accident. Making the Console input threaded was quite easy after I understood how it's done in Rust, and I got carried away. The threaded perft was implemented before I could stop myself :shock: Maybe I'll take it out for version 1, release that version, put it back in as an extra improvement in version 2. I'm not going to bother with version numbers such as 1.0.7g. It'll just be Rustic 1, Rustic 2, Rustic 3... and if there's a bugfix, maybe Rustic 3.1, 3.2, then 4... just like Firefox and Chrome.)
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Progress on Rustic

Post by maksimKorzh »

mvanthoor wrote: Thu Sep 17, 2020 7:45 pm
maksimKorzh wrote: Thu Sep 17, 2020 6:13 pm Cool!
I'm just a bit confused why Rustic 1 would have only alpha beta and no move ordering or improvements?
Or that was assumed implicitly?
Or is that a development philosophy to have weak first version and then improve?
Emphasis mine.

Yes, that is the philosophy. I want to write the most basic chess engine possible that still plays somewhat decent chess (*).

By doing it this way, I can measure the impact of every addition I make.

- Basic version with nothing but a/b-search and quiescence search: 1450 ELO
* Move ordering: +100 ELO
* Hash table: +125 ELO
* Null Move: +85 ELO

Obviously I'm just guessing these numbers, but you get the idea. I want to know how much ELO each feature adds. The reason I add move ordering and the hash table first, is that they are among the most important features for gaining speed.

I can run a gauntlet tournament against other engines, and then I'll know where each new version would approximately fall within the CCRL/CEGT lists. Maybe each addition will have its own Rustic version; but if I do that, I don't expect CCRL/CGET to test all of them. That would be waaaaaay too much work.

===

(*) (with "basic", I mean "limited number of features in the engine", not "very basic programming techniques." The feature of the threaded perft function was... uh... an accident. Making the Console input threaded was quite easy after I understood how it's done in Rust, and I got carried away. The threaded perft was implemented before I could stop myself :shock: Maybe I'll take it out for version 1, release that version, put it back in as an extra improvement in version 2. I'm not going to bother with version numbers such as 1.0.7g. It'll just be Rustic 1, Rustic 2, Rustic 3... and if there's a bugfix, maybe Rustic 3.1, 3.2, then 4... just like Firefox and Chrome.)
I understand your intent.
The only thing to mention is that adding move ordering increases performance dramatically while transposition table is not a silver bullet. My engine now hits about equal to VICE depth in certain amount of time while doesn't yet have transposition table but it has LMR and PVS and aspiration window in iterative deepening as extra features that VICE does not have. So IMO TT is more important to deal with search instability and make use of for routine tasks like handling 3 fold repetitions. Obviously it improves the performance but not very sighnificant. For example MicroMax by HGM implements TT but due to the lack of move list (hence move ordering in casual understanding) it has limits of it's performance. Even though the state of art IID powered by move generator generating next move first in the way so it would be a best move from previous IID iteration still it is just slower then those engines having move ordering.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Progress on Rustic

Post by mvanthoor »

maksimKorzh wrote: Thu Sep 17, 2020 9:10 pm Obviously it improves the performance but not very sighnificant.
You might change your mind on that later, I think. I've fiddled with a hash table before, also in Perft. (The Perft routine is a perfect thing to test all sorts of stuff.) And I made some mistakes that cost me a great deal of speed, which where kindly pointed out to me by HG Müller, by the way.

The topic:
http://talkchess.com/forum3/viewtopic.p ... 10#p836569

Note that this a very old version of Rustic; only one newer than the first one that could perform perft without mistakes. Its speed is about 28.2 million leaves/sec on my computer on a single thread; the current version runs at 38.5 million leaves/sec on a single thread, and at 170 million nodes on 8 threads (4 of which are on logical cores).

(This version of Rustic could run perft 7 in 78 seconds instead of 82 a few days ago, but threading takes some overhead, and I don't feel the need for implementing a specific "perft in the main thread" option. This is not a perft tool, but a chess engine; therefore I don't implement perft-specific optimizations. That includes bulk-counting.)

From the previously mentioned thread:

Old version of Rustic takes 113 seconds to run perft 7, without hash. (28.2 million leaves/sec)
The same old version takes 28.4 seconds to run perft 7, WITH a 32MB hash (113 million leaves/sec, speedup: 4.00x)

I don't consider a speedup of 4x "insignificant"; the time dropped from 113 seconds to 28.4 seconds, which is a drop of 75% (!).

Expectations for perft if I'd implement a hash table in the current version:

The _current_ version of Rustic takes 82 seconds to run perft 7, without hash (38.6 million leaves/sec)
Assuming a hash would boost this speed a factor 4x, this would result in 154.4 million leaves/sec, or a perft 7 in 20.8 seconds.

I haven't tested it yet, but I'm going to extrapolate anyway, assuming that the 4x speedup will hold when running on 8 threads WITH a hash table. (I assume it doesn't scale perfectly, because the hash table will be shared between the threads, but still...)

Rustic on 8 threads runs perft 7 on the starting position in 21.8 seconds (145 million leaves/sec)
Should the addition of the hash table yield the 4x speed up that would come to 580 million leaves/sec, or perft 7 in 5.5 seconds.

Speed is important to me; if I find anything that will speed up perft (but not be perft-specific), it will speed up the engine. In a chess engine, speed is your currency. With speed (both "brute force" speed and "smart speed" such as search functions and optimizations that will let you see deeper), you can "buy" features in your evaluation function, and replace some of the speed with more knowledge. If the ELO gain from the new knowledge is higher than the ELO loss from the decreased speed, your engine gets stronger.

The results from the other thread for convenience:

Code: Select all

No hash.

Results perft 7:

113.2 seconds for perft 7.
Finds 28.2 million leaf nodes/sec

Benchmarking perft 1-7 from starting position...
Perft 1: 20 (0 ms, inf leaves/sec)
Perft 2: 400 (0 ms, inf leaves/sec)
Perft 3: 8902 (0 ms, inf leaves/sec)
Perft 4: 197281 (7 ms, 28183000 leaves/sec)
Perft 5: 4865609 (174 ms, 27963270 leaves/sec)
Perft 6: 119060324 (4264 ms, 27922214 leaves/sec)
Perft 7: 3195901860 (113215 ms, 28228608 leaves/sec)
Total time spent: 117660 ms
Execution speed: 28217188 leaves/second
Finished.

Code: Select all

32 MB Hash
+/- 600.000 buckets
2 entries per bucket
(1.2 million entries total)

Results perft 7:

28.2 seconds (1/4th of time without hash, 75% speedup)
Finds 111.4 million leaf nodes/sec.

Benchmarking perft 1-7 from starting position...
Perft 1: 20 (0 ms, inf leaves/sec)
Perft 2: 400 (0 ms, inf leaves/sec)
Perft 3: 8902 (0 ms, inf leaves/sec)
Perft 4: 197281 (7 ms, 28183000 leaves/sec)
Perft 5: 4865609 (106 ms, 45901971 leaves/sec)
Perft 6: 119060324 (1457 ms, 81716076 leaves/sec)
Perft 7: 3195901860 (28214 ms, 113273618 leaves/sec)
Total time spent: 29784 ms
Execution speed: 111470400 leaves/second
Finished.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Progress on Rustic

Post by maksimKorzh »

mvanthoor wrote: Thu Sep 17, 2020 11:42 pm
maksimKorzh wrote: Thu Sep 17, 2020 9:10 pm Obviously it improves the performance but not very sighnificant.
You might change your mind on that later, I think. I've fiddled with a hash table before, also in Perft. (The Perft routine is a perfect thing to test all sorts of stuff.) And I made some mistakes that cost me a great deal of speed, which where kindly pointed out to me by HG Müller, by the way.

The topic:
http://talkchess.com/forum3/viewtopic.p ... 10#p836569

Note that this a very old version of Rustic; only one newer than the first one that could perform perft without mistakes. Its speed is about 28.2 million leaves/sec on my computer on a single thread; the current version runs at 38.5 million leaves/sec on a single thread, and at 170 million nodes on 8 threads (4 of which are on logical cores).

(This version of Rustic could run perft 7 in 78 seconds instead of 82 a few days ago, but threading takes some overhead, and I don't feel the need for implementing a specific "perft in the main thread" option. This is not a perft tool, but a chess engine; therefore I don't implement perft-specific optimizations. That includes bulk-counting.)

From the previously mentioned thread:

Old version of Rustic takes 113 seconds to run perft 7, without hash. (28.2 million leaves/sec)
The same old version takes 28.4 seconds to run perft 7, WITH a 32MB hash (113 million leaves/sec, speedup: 4.00x)

I don't consider a speedup of 4x "insignificant"; the time dropped from 113 seconds to 28.4 seconds, which is a drop of 75% (!).

Expectations for perft if I'd implement a hash table in the current version:

The _current_ version of Rustic takes 82 seconds to run perft 7, without hash (38.6 million leaves/sec)
Assuming a hash would boost this speed a factor 4x, this would result in 154.4 million leaves/sec, or a perft 7 in 20.8 seconds.

I haven't tested it yet, but I'm going to extrapolate anyway, assuming that the 4x speedup will hold when running on 8 threads WITH a hash table. (I assume it doesn't scale perfectly, because the hash table will be shared between the threads, but still...)

Rustic on 8 threads runs perft 7 on the starting position in 21.8 seconds (145 million leaves/sec)
Should the addition of the hash table yield the 4x speed up that would come to 580 million leaves/sec, or perft 7 in 5.5 seconds.

Speed is important to me; if I find anything that will speed up perft (but not be perft-specific), it will speed up the engine. In a chess engine, speed is your currency. With speed (both "brute force" speed and "smart speed" such as search functions and optimizations that will let you see deeper), you can "buy" features in your evaluation function, and replace some of the speed with more knowledge. If the ELO gain from the new knowledge is higher than the ELO loss from the decreased speed, your engine gets stronger.

The results from the other thread for convenience:

Code: Select all

No hash.

Results perft 7:

113.2 seconds for perft 7.
Finds 28.2 million leaf nodes/sec

Benchmarking perft 1-7 from starting position...
Perft 1: 20 (0 ms, inf leaves/sec)
Perft 2: 400 (0 ms, inf leaves/sec)
Perft 3: 8902 (0 ms, inf leaves/sec)
Perft 4: 197281 (7 ms, 28183000 leaves/sec)
Perft 5: 4865609 (174 ms, 27963270 leaves/sec)
Perft 6: 119060324 (4264 ms, 27922214 leaves/sec)
Perft 7: 3195901860 (113215 ms, 28228608 leaves/sec)
Total time spent: 117660 ms
Execution speed: 28217188 leaves/second
Finished.

Code: Select all

32 MB Hash
+/- 600.000 buckets
2 entries per bucket
(1.2 million entries total)

Results perft 7:

28.2 seconds (1/4th of time without hash, 75% speedup)
Finds 111.4 million leaf nodes/sec.

Benchmarking perft 1-7 from starting position...
Perft 1: 20 (0 ms, inf leaves/sec)
Perft 2: 400 (0 ms, inf leaves/sec)
Perft 3: 8902 (0 ms, inf leaves/sec)
Perft 4: 197281 (7 ms, 28183000 leaves/sec)
Perft 5: 4865609 (106 ms, 45901971 leaves/sec)
Perft 6: 119060324 (1457 ms, 81716076 leaves/sec)
Perft 7: 3195901860 (28214 ms, 113273618 leaves/sec)
Total time spent: 29784 ms
Execution speed: 111470400 leaves/second
Finished.
Qperft by HGM is the most exciting perft I've ever seen...

I didn't mean to say that TT is not worth it. I just wanted to say that other search optimization techniques are important as well. Btw I've finally implemented Zobrist keys today (for the first time ever!) so TT is about to be implemented hopefully tomorrow. I'm tempted to see the results myself.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Progress on Rustic

Post by mvanthoor »

maksimKorzh wrote: Fri Sep 18, 2020 12:02 am Qperft by HGM is the most exciting perft I've ever seen...
It is, but then, it's a dedicated perft tool and uses every trick in the book to make perft as fast (and configurable) as possible. It also can some perft-only optimizations. I'm not sure I'll ever implement those into my engine.
I didn't mean to say that TT is not worth it. I just wanted to say that other search optimization techniques are important as well. Btw I've finally implemented Zobrist keys today (for the first time ever!) so TT is about to be implemented hopefully tomorrow. I'm tempted to see the results myself.
Very good :) I've looked through your code in the thread about Zobrist hashing and planned to comment on it right about... now. While you seem to grasp the idea fine, it looks like you were missing some of the hashes here and there. That's something you'll just have to test very accurately (hence the checkup() / test_incrementals() debugging function), and after you get it working perfectly, NEVER EVER touch it again if you don't have to. If you change ANYTHING with regard to moving pieces on the board, or in make_move/unmake_move that touches the Zobrist hash in any way, immediately test against the from scratch function. Only make ONE change at a time and then test. If you don't, you'll be in for a lot of pain.

You won't -notice- that your Zobrist-key is wrong, until you start using a hash table... test the hash-table in Perft. There, a non-working zobrist or hash table will get you the wrong results. In-game, a wrong Zobrist or hash may get you an illegal move and make your engine crash, or it gets a legal move and makes the engine suddenly play weirdly.

Keep testing with Perft after every change to the hash and/or move generator so you know everything still works perfectly.

It's even better when you find the very large PERFT test EPD file online and implement to test that. If you want, you can lift it from Rustic:

https://github.com/mvanthoor/rustic/tre ... /src/extra
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Progress on Rustic

Post by mvanthoor »

Today I've mplemented message passing between the main thread (the "engine" itself) and the communication module which runs in its own thread (in thise case, "Console", but can be "Uci" or "Xboard" in the future as well).

The communication module basically catches incoming commands, verifies that they are complete/legal/exist, and then it translates those to the commands the engine understands. For example, let's assume the following commands (for arguments sake: I know the actual commands are different):

- A UCI GUI sends "setup_position <fen-string>"
- An XBoard GUI "create_pos <fen-string>"
- In my own Console, I'd type "fen <fen-string>", the same as the command line parameter --fen

Each of the three communication modules catch the commands, and translate them, in this case to "Command::FEN<fen-string>", which is a variant of the Command enum. Then this command is going to be sent to the engine's thread, and the engine will decide what happens. In this case, it will obviously set up a new position, but depending on the received command, it can also decide to quit all the threads and shut down, start "Go" for the search, change the number of search threads, etc...

As cmopared to other engines it may seem complicated, but in Rust, it's a very logical (and easy!) way of getting this done. In many C engines, such as Vice, everything runs in the main thread (including the search), and the search then peeps into the keyboard buffer to see what commands are incoming. I'm sure it could be done in Rust, but it would definitely require unsafe code, and it is much less extensible than using threading.

For example, Rustic can very easily support ANY protocol I want it to support, just by implementing a new Comm module for the said protocol, and adding the module to the --comm switch (on the command line during program start) as a possible value. Who knows what the future brings? UCI version 3, 4, 5? Some sort of epic engine testing site that uses a specialized version of UCI or a completely new protocol?.

I'm actually thinking to make the evaluation function interchangeable this way, so the engine can have multiple evaluation functions, each with their own style... and maybe one that is tuned with some tuner.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL