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

Re: Progress on Rustic

Post by mvanthoor »

Thanks again for the explanation. I need to save that somewhere for future reference.

Today, Rustic gained basic time management:

Code: Select all

available = (base_time / moves_to_go) + increment - overhead.
if elapsed >= available { stop }
It doesn't get more basic than this, but for the very first version, it seems to work very well. (I'll have to test more time controls to be certain.)

If "moves_to_go" is not supplied (= all base time for the entire game), Rustic for now assumes the game will be 80 moves long, and it'll calculate "movestogo" accordingly. Many games in my early tests are between 50 and 100 moves with an average of about 75, so I thought 80 would be a good guess for a first time management version.

In the coming week I'll create an engine pool with engines between 1500 - 1800 Elo, as I suspect Rustic to hover around 1650 Elo on CCRL blitz. (It obtains around 50% against "Pulse 1.7.2", which has a rating of 1650. It obtains -70 Elo against ShallowBlue, which has a rating of 1720.)

It still has no features besides MMV-LVA and PSQT's, but it does seem to be very fast compared to other engines in its Elo range. I add one node just before the move loop in alpha/beta and qsearch (so I only add a node when I'm actually going to do some work in the node). Rustic calculates at 4500 kNodes/sec, where other engines I'm testing against hover somewhere between 800 kNodes and 1500 kNodes; they make up for it with much more features and a much better evaluation though.

The only UCI features it's missing now are ones that are minor (such as Send Mate to GUI, and "go mate x", which I've never used), ones that I haven't needed yet (setoption), or never going to implement (go searchmoves and copy protection). I can implement those at any time.

The last big feature it doesn't have yet is CECP (xBoard/WinBoard) support. The UCI-communication module translates incoming UCI-commands from strings to enums/structs, and outgoing responses from enums/structs to strings. Those enums and structs basically constitute a "nicely packaged" internal UCI-protocol so the engine can send commands and responses from one thread to another. The xBoard module will hook into those and translate from and to these structs. Where xBoard can do things that UCI can't, I can extend the engine's internal protocol to support those features.

that will be next (up to the point where the xBoard implementation supports the same features as the UCI one), before I can make a build script that produces all of the executables, and then release the engine as Rustic Alpha 1.

From there on, I can add features and test Elo progression for each feature I add.

Almost there...
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
hgm
Posts: 27811
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Progress on Rustic

Post by hgm »

Well, that is indeed very basic time management. One caveat:

I suppose that moves_to_go here means the UCI movestogo parameter at the start of the game, or that base_time means the actual time on the clock, or the forumaly you present would make no sense. The fundamentally correct thing to say here is time_left / moves_left. If you force all moves to use equal time this will of course be a constant during the game, but once you allow some variation in the thinking time it will not.

You could probably do a lot better by also putting in a statement to break out of the depth interation loop in the root when elapsed > 0.5*available. (As it would be very unlikely you would be able to finish the next iteration in less than twice the time you spent so far, and this would already bing you at a time usage of 1.5*available. Remember that, as long as you have no TT, time spent on aborted iterations will be wasted time.)

You can still keep a cold-turkey abort, but allow some overrun of 'available', since other moves might use only up to half of that. E.g.

Code: Select all

available = (time_left / (moves_left + 2)) + increment - overhead.
if elapsed >= 3*available { stop }
This allows you op to 3 times the nominal time to finish an iteration that took unexpectedly long. (Which usually means the engine sees the move it has so far is no good, and wants to change it.) The extra +2 in the denominator guarantees that you will be able to afford this even in the last move of a TC session.

The factor 0.5 could be adjusted to make the average time spent on a move about equal to 'available'.

And one remark: I expect your nps to take a dramatic hit as soon as you implement a TT. It is a bit pointless to compare the nps of engines with and without a TT. In micro-Max the TT-less versions have about 6 times higher nps as those with TT.
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 »

Progress on Rustic is going well. I've extended the time management to be much less basic, and tweaked some values in the PSQT pawn table. I've rerouted the "--comm xboard" command to start the UCI-interface for now; xBoard will be implemented in one of the following "Alpha" series versions.

Rustic Alpha 1 is basically done.

I've been testing against other engines, and I'm now building a pool of 10-15 engines between 1450 and 1950 Elo to test this version as a baseline. That will be in the coming week. During that time I'll be writing some build-script stuff so I can generate the binaries for Windows and Linux. Later I'll extend the scripts to also generate binaries for the Raspberry Pi 4 and Zero (ARM v7L and v6 if I remember correctly), OSX (which I can't test, because I don't have a Mac, let alone several OSX versions), and Android; but that'll come later.

So in short, in the coming days, I'll be wrapping up everything for a release, and testing the engine to establish a base rating. At this point I don't have enough games. Depending against which engine I test, the rating swings between 1600 and 1825, with 200 Elo error bars... so the engine may fall anywhere between 1400 and close to 2000. I still expect it to fall somewhere between 1600-1700, but we'll see.

After this release, I'll start adding features, and testing each feature one by one to gauge the strength each improvement provides. I'm also going to start writing the tutorial book at http://rustic-chess.org. Fortunately, some of the early features (killer moves, history heuristic, check extension) are relatively easy to implement, but take a long time to test; so during those test runs, I'll be writing the book.

Almost done... just wrapping up, dotting the i's and crossing the t's :) (For Alpha 1, that is... and then I'll see how far I can take this thing.)
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 »

Still crossing some T's and dotting a few i's.

I've decided that I want the XBoard-protocol in there from the start, so I'm now implementing this.

To be able to claim draws, I had to implement a function for insufficient material to mate. The side effect is that the engine, in a KNp-KB endgame doesn't give up its pawn for the bishop. Previously it would, because it would increase material advantage, even though the resulting position is a draw. Now it tries to protect the pawn and not lose it. (Therefore, it should now be able to win games it couldn't before, and thus be a bit stronger. I might take the function out some day and test the difference.)

Because the engine has no evaluation and no TT, and can't see far enough ahead to mate with KR-K; it requires up to 17 moves, and Rustic can't yet see that far. It also doesn't have mobility evaluation yet, to drive the king to the edge. It sometimes sees KQ-K if the mate is 9 moves or less, but if it's 10 or 11 (depending on the position) it may not see it in a Blitz game. This stuff will eventually solve itself, so I'm not going to do anything about it now.

It did play a great game against Dreamer 0.3 (+/- CCRL 1600) where it sacrificed a bishop for 4 pawns, and then proceeded to slowly strangle the opponent, ending with a mate in 5 moves/9 plies, AND a queen... thank you very much.

[pgn][Event "RA1-Dreamer"]
[Date "2020.11.15"]
[Round "1"]
[White "Rustic Alpha 1"]
[Black "Dreamer 0.3"]
[Result "1-0"]
[ECO "E10"]
[GameDuration "00:03:53"]
[GameEndTime "2020-11-15T15:13:05.244 W. Europe Standard Time"]
[GameStartTime "2020-11-15T15:09:11.944 W. Europe Standard Time"]
[Opening "Queen's pawn game"]
[PlyCount "85"]
[TimeControl "120+1"]

1. d4 {book} Nf6 {book} 2. c4 {book} e6 {book} 3. Nf3 {book} d5 {book}
4. Nc3 {book} Bb4 {book} 5. Bg5 {-0.10/7 3.4s} dxc4 {-1.10/8 4.7s}
6. e4 {+0.30/7 3.4s} O-O {-1.32/6 4.6s} 7. Bxc4 {+0.35/7 3.5s} h6 {-1.40/6 4.5s}
8. Bxf6 {+0.45/7 3.5s} Qxf6 {-1.62/7 4.4s} 9. O-O {+0.45/6 3.6s}
Qd8 {-1.56/6 4.2s} 10. Qb3 {+0.65/6 3.7s} Ba5 {-1.62/6 4.1s}
11. Rad1 {+0.65/6 3.7s} Nd7 {-1.62/6 4.0s} 12. Qa3 {+0.85/7 3.3s}
c6 {-1.61/6 3.9s} 13. b4 {+0.70/6 3.9s} Bc7 {-1.68/7 3.8s}
14. Qb3 {+0.65/6 4.0s} b5 {-1.42/7 3.7s} 15. Bxe6 {+1.75/7 4.1s}
fxe6 {-1.36/8 3.6s} 16. Qxe6+ {+1.95/8 4.2s} Kh7 {-1.52/8 3.6s}
17. Qxc6 {+2.15/8 3.6s} Rb8 {-1.40/7 3.5s} 18. Nxb5 {+2.15/7 4.5s}
Bb6 {-1.06/7 3.4s} 19. Nd6 {+2.20/7 4.4s} g6 {-1.06/6 3.3s}
20. b5 {+2.20/6 4.9s} Nf6 {-1.30/6 3.2s} 21. e5 {+2.10/6 5.1s}
Bd7 {-1.55/6 3.2s} 22. Qc1 {+2.05/7 5.3s} Ne8 {-1.64/6 3.1s}
23. Nxe8 {+1.85/8 5.6s} Qxe8 {-1.88/7 3.0s} 24. a4 {+1.25/7 4.6s}
a6 {-1.91/6 2.9s} 25. d5 {+1.30/8 6.1s} axb5 {-2.92/7 2.9s}
26. e6 {+1.50/7 1.6s} Bc8 {-2.92/6 2.8s} 27. axb5 {+1.35/7 1.7s}
Qxb5 {-3.08/6 2.8s} 28. Qc2 {+1.25/6 1.7s} Ba6 {-3.13/6 2.7s}
29. Qe4 {+1.15/6 1.7s} Qe2 {-3.15/6 2.6s} 30. Qh4 {+1.05/7 1.7s}
Bd8 {-3.32/6 2.6s} 31. Qg3 {+1.00/6 1.8s} Ba5 {-3.13/6 2.5s}
32. Ne5 {+0.95/6 1.8s} Qh5 {-2.66/6 2.5s} 33. e7 {+1.15/7 1.8s}
Rfe8 {-2.64/6 2.4s} 34. Nd7 {+1.10/7 1.9s} Rb6 {-0.43/7 2.4s}
35. d6 {+2.80/7 1.9s} Kg7 {+0.31/7 2.3s} 36. Nxb6 {+3.10/7 1.9s}
Bxb6 {+3.01/7 2.3s} 37. Qc3+ {+4.30/6 2.0s} Kh7 {+3.21/7 2.3s}
38. Qb3 {+4.90/7 2.0s} Bxf1 {+5.29/7 2.2s} 39. Qf7+ {+M9/7 2.1s}
Kh8 {+M8/9 0.48s} 40. Qxe8+ {+M7/8 2.1s} Kg7 {+M6/1 0.011s}
41. Qf8+ {+M5/7 2.2s} Kh7 {+M4/1 0.007s} 42. Qf7+ {+M3/7 2.3s}
Kh8 {+M2/3 0.009s} 43. e8=Q# {+M1/7 1.8s, White mates} 1-0[/pgn]

So everything is going well, but (even) more work than anticipated.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
Guenther
Posts: 4610
Joined: Wed Oct 01, 2008 6:33 am
Location: Regensburg, Germany
Full name: Guenther Simon

Re: Progress on Rustic

Post by Guenther »

mvanthoor wrote: Sun Nov 15, 2020 3:33 pm Still crossing some T's and dotting a few i's.

I've decided that I want the XBoard-protocol in there from the start, so I'm now implementing this.

To be able to claim draws, I had to implement a function for insufficient material to mate. The side effect is that the engine, in a KNp-KB endgame doesn't give up its pawn for the bishop. Previously it would, because it would increase material advantage, even though the resulting position is a draw. Now it tries to protect the pawn and not lose it. (Therefore, it should now be able to win games it couldn't before, and thus be a bit stronger. I might take the function out some day and test the difference.)

Because the engine has no evaluation and no TT, and can't see far enough ahead to mate with KR-K; it requires up to 17 moves, and Rustic can't yet see that far. It also doesn't have mobility evaluation yet, to drive the king to the edge. It sometimes sees KQ-K if the mate is 9 moves or less, but if it's 10 or 11 (depending on the position) it may not see it in a Blitz game. This stuff will eventually solve itself, so I'm not going to do anything about it now.

...

So everything is going well, but (even) more work than anticipated.
Marcel, I wanted to give current dev version of Rustic a try and updated my Msys2 installation for being able to compile rust too.
Note that I never compiled for rust before, but your github notes (using msys2) finally encouraged me attempting it.

At first it seems cargo updated and compiled still missing prerequisites flawlessly itself, but while compiling rustic itself
it stumbled upon the same error three times and refused compilation?

Do you have any idea? (I was too lazy to read through all of the long thread given for the issue link)

Code: Select all

   Compiling rustic v0.1.0 (C:\msys64\home\Guenther Simon\rustic)
error[E0658]: `while` is not allowed in a `const fn`
   --> src\board\defs.rs:122:5
    |
122 | /     while i < (NrOf::FILES) {
123 | |         bb_files[i] = BB_FILE_A << i;
124 | |         i += 1;
125 | |     }
    | |_____^
    |
    = note: see issue #52000 <https://github.com/rust-lang/rust/issues/52000> for more information

error[E0658]: `while` is not allowed in a `const fn`
   --> src\board\defs.rs:135:5
    |
135 | /     while i < (NrOf::RANKS as usize) {
136 | |         bb_ranks[i] = BB_RANK_1 << (i * 8);
137 | |         i += 1;
138 | |     }
    | |_____^
    |
    = note: see issue #52000 <https://github.com/rust-lang/rust/issues/52000> for more information

error[E0658]: `while` is not allowed in a `const fn`
   --> src\board\defs.rs:147:5
    |
147 | /     while i < NrOf::SQUARES {
148 | |         bb_squares[i] = 1u64 << i;
149 | |         i += 1;
150 | |     }
    | |_____^
    |
    = note: see issue #52000 <https://github.com/rust-lang/rust/issues/52000> for more information

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0658`.
error: could not compile `rustic`.
Edit:

Code: Select all

$ rustc --explain E0658
An unstable feature was used.
...
If you're using a stable or a beta version of rustc, you won't be able to use
any unstable features. In order to do so, please switch to a nightly version of
rustc (by using rustup).
...
Oops, I don't even know, if I can add unstable/nightly packages to msys2,
or if I should...
https://rwbc-chess.de

trollwatch:
Talkchess nowadays is a joke - it is full of trolls/idiots/people stuck in the pleistocene > 80% of the posts fall into this category...
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 »

Guenther wrote: Mon Nov 16, 2020 12:34 pm ... snip ...
Hi Guenther, thanks for trying.

I think I'm going to see problems like this often:
error[E0658]: `while` is not allowed in a `const fn`
Your installed version of Rust is too old. "while in const functions" is only allowed since Rust 1.46. I'm always on the latest stable version (now at 1.47; will be 1.48 in a few days.)

I only install MSYS2 because it provides Bash and a Linux-like command-line on Windows, and for GCC and CLANG. I *don't* install the Rust version from MSYS2; If you have this installed, just uninstall it, and install the latest Windows-version. The MSYS2 version does work, but it's always behind the curve with regard to the version supplied. It is often several versions older than the newest Windows version. (I should have been clearer. I'll update the instructions this evening.)

When starting MSYS2, you should then be able to type "rustc --version", and get "1.47" (in a few days, 1.48 will be released).

You can find the latest Windows-version here:
https://www.rust-lang.org/

If you want to use the MSVC toolchain, install the C++ Build Tools too; the Rust compiler needs the linker from those tools if you choose the MSVC toolchain. If you use the windows-gnu toolchain, the C++ Build Tools are not required (the Rust compiler will use the GNU linker).

This stuff can be confusing. You can start MSYS2 as:

MSYS (for administrating MSYS2)
MINGW32 (the 32-bit version)
MINGW64 (the 64-bit version) <- I use this (because I like Bash better than CMD or Powershell)

You can also install Rust:
- The Windows version, with MSVC toolchain <- Installed, but only used for profiling on Windows.
- The Windows version, with GNU toolchain <- I use this (toolchain name: stable-x86_64-pc-windows-gnu).
- MSYS-version... either 32-bit or 64-bit <- I don't use the MSYS2 version of Rust (but I do use MSYS2's versions of GCC and CLANG)

There are many combinations. I've marked what I use.

---

After xboard has been implemented, I'll also supply a bunch of binaries for Windows, probably Linux, and, if I can get someone to help me test them, for OSX. (I don't have, nor ever will have, a Mac.)
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
Guenther
Posts: 4610
Joined: Wed Oct 01, 2008 6:33 am
Location: Regensburg, Germany
Full name: Guenther Simon

Re: Progress on Rustic

Post by Guenther »

mvanthoor wrote: Mon Nov 16, 2020 1:44 pm
Guenther wrote: Mon Nov 16, 2020 12:34 pm ... snip ...
Hi Guenther, thanks for trying.

I think I'm going to see problems like this often:
error[E0658]: `while` is not allowed in a `const fn`
Your installed version of Rust is too old. "while in const functions" is only allowed since Rust 1.46. I'm always on the latest stable version (now at 1.47; will be 1.48 in a few days.)

I only install MSYS2 because it provides Bash and a Linux-like command-line on Windows, and for GCC and CLANG. I *don't* install the Rust version from MSYS2; If you have this installed, just uninstall it, and install the latest Windows-version. The MSYS2 version does work, but it's always behind the curve with regard to the version supplied. It is often several versions older than the newest Windows version. (I should have been clearer. I'll update the instructions this evening.)

When starting MSYS2, you should then be able to type "rustc --version", and get "1.47" (in a few days, 1.48 will be released).

...
Thanks Marcel. I see, I have just rust version 1.43 installed, which is still the latest available one at msys2, but it is on the 'outdated' list for msys2-packages too ;-)
This package was made available 2020-04, so I guess they will provide a newer one this year anyway.
If I get imaptient I will use one of the choices you mentioned.

I am already using Msys2 for around 2 years and have it working smoothly for C/C++ compiling with gcc/clang.
(Except when my previous virus scanner suddenly ran amok and killed it irreversibly while compiling! due to false positives - very annoying)
https://rwbc-chess.de

trollwatch:
Talkchess nowadays is a joke - it is full of trolls/idiots/people stuck in the pleistocene > 80% of the posts fall into this category...
User avatar
hgm
Posts: 27811
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Progress on Rustic

Post by hgm »

mvanthoor wrote: Sun Nov 15, 2020 3:33 pmBecause the engine has no evaluation and no TT, and can't see far enough ahead to mate with KR-K; it requires up to 17 moves, and Rustic can't yet see that far. It also doesn't have mobility evaluation yet, to drive the king to the edge. It sometimes sees KQ-K if the mate is 9 moves or less, but if it's 10 or 11 (depending on the position) it may not see it in a Blitz game. This stuff will eventually solve itself, so I'm not going to do anything about it now.
You do have piece-square tables, right? That also counts as 'evaluation'.

My first Chess program (from around 1980, running in 2KB RAM) could only search 3 ply ahead, just enough to see mate-in-1 (as it had to see the King capture to recognize it). And it had no problem at all winning KQ-K. A next version, which searched deep enough to see mate-in-2, had no trouble winning KR-K. Apart from PST the only evaluation needed for it was to give a bonus for the King approaching the last-moved opponent piece.

So you don't really need much depth, as long as your evaluation is not completely counter-productive. Mobility is not really helpful. It doesn't tell you the Kings should approach, for a Rook it is the same everywhere, and for Queens it tries to center them, preventing their use for cornering the bare King.
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 »

Guenther wrote: Mon Nov 16, 2020 2:35 pm Thanks Marcel. I see, I have just rust version 1.43 installed, which is still the latest available one at msys2, but it is on the 'outdated' list for msys2-packages too ;-)
This package was made available 2020-04, so I guess they will provide a newer one this year anyway.
If I get imaptient I will use one of the choices you mentioned.

I am already using Msys2 for around 2 years and have it working smoothly for C/C++ compiling with gcc/clang.
(Except when my previous virus scanner suddenly ran amok and killed it irreversibly while compiling! due to false positives - very annoying)
I've been using MSYS2 almost as long as it exists. (I like it much better than the mess that the different MinGW distributions have created.) Before MSYS2, I used Cygwin for most of my terminal work and compiling C/C++ programs. I like MSYS2 better because it doesn't require cygwin1.dll.

As there isn't a "real" Windows version of either GCC or Clang (as far as I'm aware of), I use the MSYS2 versions to compile C/C++ engines and that has been working great. As opposed to GCC and Clang however, Rust does have a real (official) Windows-version, and so I have this installed. I only use MSYS2 to issue the build command ("cargo build --release"), and because it provides strip ("strip -s ./target/release/rustic.exe") to strip unused debug-symbols from the release version. The build command itself also runs fine from the Windows command line.

The only roadblock for some people compiling on Linux could be that the distribution-provided version of Rust is too old. (And "too old" could even mean "not the very latest stable.") I always install the latest stable version, and if it provides a new feature that makes my code better/shorter/cleaner, I'll immediately use it. ("while in const fn" allowed me to strip some large tables from the code and have them initialized as constants through a function.)
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 »

hgm wrote: Mon Nov 16, 2020 4:25 pm
mvanthoor wrote: Sun Nov 15, 2020 3:33 pmBecause the engine has no evaluation and no TT, and can't see far enough ahead to mate with KR-K; it requires up to 17 moves, and Rustic can't yet see that far. It also doesn't have mobility evaluation yet, to drive the king to the edge. It sometimes sees KQ-K if the mate is 9 moves or less, but if it's 10 or 11 (depending on the position) it may not see it in a Blitz game. This stuff will eventually solve itself, so I'm not going to do anything about it now.
You do have piece-square tables, right? That also counts as 'evaluation'.

My first Chess program (from around 1980, running in 2KB RAM) could only search 3 ply ahead, just enough to see mate-in-1 (as it had to see the King capture to recognize it). And it had no problem at all winning KQ-K. A next version, which searched deep enough to see mate-in-2, had no trouble winning KR-K. Apart from PST the only evaluation needed for it was to give a bonus for the King approaching the last-moved opponent piece.

So you don't really need much depth, as long as your evaluation is not completely counter-productive.
Yes, it does have PSQT's. (And material counting.) It doesn't have anything else.

I wrote a very simplistic mobility check, and it worked; basically, your solution is also a simple mobility check (restriction). I was hesitant to include it because I wanted to avoid adding things into the evaluation. I tried to keep the engine as basic as possible, with the least amount of features... but I had to add qsearch, mvv-lva and check extensions because I couldn't rightfully call the thing a "chess engine" without it. ("Piece pusher that doesn't play illegal moves" would have been a better name.)

Now it seems I do need to add at least a little bit of evaluation.

Feature creep is setting in already.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL