Affinity Chess 1.0 released

Discussion of chess software programming and technical issues.

Moderator: Ras

eligolf
Posts: 114
Joined: Sat Nov 14, 2020 12:49 pm
Full name: Elias Nilsson

Affinity Chess 1.0 released

Post by eligolf »

Hello everyone,

I have just release my first chess engine Affinity Chess on Github. It is written from scratch in C# as a hobby project of mine, some more information about the features included can be found on the Github link posted above. Here is some additional background about the project for those interested:

As a mechanical engineer in my professional life I started programming for fun in Python on my spare time 4-5 years ago. I found it really fun (and frustrating at times...) to create own applications and decide what happens when a user clicks here and there.
As a chess fan (hit me up if you want to play on chess.com sometimes) I have always been fascinated with the brain behind chess engines so I wanted to try and create my own. My first chess engine Endamat Chess was written in Python and it also has its own GUI which was fun creating.

Eventually the limitations of Python/Pygame made me switch platform to Unity. This is where I started learning C# and once again got addicted to programming a chess engine, much because C# is way faster than Python. The project started around new year this year and lots of the code and concepts are inspired and even taken straight from Endamat Chess, translated into C# code. It also has some new features added such as transposition tables, razoring and late move reducitons.

I have no clue about the strenght of version 1.0, but I know it is mediocre given my current level of experience. It has a speed of around 400-800 kNPS on my machine when playing in Arena, uses PeSTO for evaluation and has some pruning features implemented. What limits the depth now seems to be the amount of nodes it spends in Q-search, it always seems to spend around 70% or more of nodes in Q search (q nodes / total nodes).

I am not a programmer, and even less a C# programmer, so the code is probably very inefficient at places. If you would happen to look through some of the code and find something I have done in a stupid way then please let me know, I am always open to learn new things. Also if you have any ideas of logical next steps I am open for input :) Some general things I will look at short term is:

- Limit Q search, not sure how yet though...
- Try to optimize move gen and make/unmake move.
- Implement staged move generation.
- Play around with another evaluation concept to include more features than just PST.

Have fun with it and please let me know if you decide to play around with the engine. Would be cool to see some games vs you :) Also if anyone has a good way of estimate strength I would love to get a rough estimation to know what engines I can play against in own tournaments I set up.

Huge thanks to the community for all the help in the forums, and special thanks to Thomas for some guidance regarding more complex concepts. Author of Cosette and Maksims YouTube series have also been of great help.
User avatar
lithander
Posts: 915
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: Affinity Chess 1.0 released

Post by lithander »

Congrats on the first release!

I ran a few games against Leorik but it was an unfair match:

Code: Select all

Score of Leorik 1.0 vs Affinity Chess: 79 - 2 - 16  [0.897] 97
...      Leorik 1.0 playing White: 40 - 1 - 8  [0.898] 49
...      Leorik 1.0 playing Black: 39 - 1 - 8  [0.896] 48
...      White vs Black: 41 - 40 - 16  [0.505] 97
Elo difference: 375.8 +/- 90.0, LOS: 100.0 %, DrawRatio: 16.5 %
That's a bit surprising because Leorik 1.0 does not have many of the features you have already implemented. Based on your feature list your engine should be much stronger than Leorik! That it's the other way round can't be explained by performance differences alone. I fear you'll have to go on a bug hunt! :wink:

And one thing I noticed is that your engine reports a lot of illegal PVs. Cute Chess validates the PV and reports warnings like this:

Code: Select all

Warning: PV:  Kg2-g1,
Warning: Illegal PV move Kg2-g1, from Affinity Chess (10)
Warning: PV:  Kg2-g1,
Warning: Illegal PV move f4-f5, from Affinity Chess (1)
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
eligolf
Posts: 114
Joined: Sat Nov 14, 2020 12:49 pm
Full name: Elias Nilsson

Re: Affinity Chess 1.0 released

Post by eligolf »

Well you have a nps that is 10 times higher to search more deeply so that could be part of it :) the other features I have is just to reduce nodes searched.

The part about PV seems strange, will have to look into that! What does it mean though? How is a PV move illegal, isnt PV the best move output from engine?
User avatar
lithander
Posts: 915
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: Affinity Chess 1.0 released

Post by lithander »

eligolf wrote: Sat Mar 05, 2022 7:25 am Well you have a nps that is 10 times higher to search more deeply so that could be part of it :) the other features I have is just to reduce nodes searched.
Leorik and Affinity Chess take about 30s to reach depth 12 on the start position. Just by looking at those two you could come to the conclusion that Leoriks speed is compensating for Affinity's better pruning and everything is as it should. But my other engine MinimalChess is as slow as Affinity Chess and only takes 600ms to reach that depth as you can see here:

Code: Select all

MinimalChess 0.6.2
go depth 12
info depth 1 score cp 36 nodes 21 nps 538 time 39 pv d2d4
info depth 2 score cp 0 nodes 98 nps 1781 time 55 pv d2d4 d7d5
info depth 3 score cp 35 nodes 199 nps 3491 time 57 pv d2d4 d7d5 g1f3
info depth 4 score cp 0 nodes 402 nps 6700 time 60 pv d2d4 d7d5 g1f3 g8f6
info depth 5 score cp 33 nodes 834 nps 13672 time 61 pv d2d4 d7d5 g1f3 g8f6 b1c3
info depth 6 score cp 0 nodes 2191 nps 34777 time 63 pv d2d4 d7d5 g1f3 g8f6 b1c3 b8c6
info depth 7 score cp 26 nodes 4001 nps 59716 time 67 pv d2d4 d7d5 g1f3 g8f6 b1c3 b8c6 c1f4
info depth 8 score cp 10 nodes 13103 nps 152360 time 86 pv e2e4 b8c6 g1f3 g8f6 b1c3 e7e5 d2d4 f8d6
info depth 9 score cp 24 nodes 29074 nps 238311 time 122 pv e2e4 g8f6 b1c3 b8c6 d2d4 e7e5 d4e5 c6e5 g1f3
info depth 10 score cp 15 nodes 108278 nps 405535 time 267 pv e2e4 e7e6 b1c3 d7d5 g1f3 b8c6 d2d4 g8f6 c1g5 f8e7
info depth 11 score cp 26 nodes 194066 nps 450269 time 431 pv e2e4 e7e6 b1c3 d7d5 g1f3 b8c6 d2d4 g8f6 e4d5 e6d5 f1d3
info depth 12 score cp 7 nodes 433220 nps 629680 time 688 pv e2e4 e7e5 g1f3 g8f6 b1c3 b8c6 f1d3 f8d6 e1g1 e8g8 c3b5 d6c5
So, with your feature list and taking into account the speed of your engine I think it should be comparable to MinimalChess 0.6.1 but with PST-only tables. And that version of MMC is significantly stronger than Leorik 1.0 and not weaker.
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
User avatar
Ras
Posts: 2696
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Affinity Chess 1.0 released

Post by Ras »

eligolf wrote: Fri Mar 04, 2022 12:53 pm- Limit Q search, not sure how yet though...
Some ideas:
1) Don't search underpromotions in QS. Ideally, don't even generate them.
2) After a "certain" depth within QS (like 5-6 plies), only examine captures on the same square as in the ply before. That prevents searching pointless mutual queen plunder raids.
3) Use delta pruning: if your current capture plus a safety margin (like 2 pawns) doesn't reach alpha even assuming that the opponent cannot capture back, don't examine it. If you score moves by MVV/LVA, you can actually drop the remaining moves because they will be even worse. Pay attention to pawn promotions here because that is a delta of QUEEN-PAWN in itself.
How is a PV move illegal, isnt PV the best move output from engine?
The best move is the first move of the PV - the following PV moves are what the engines thinks the opponent will answer to its best move and how it wants to react to that in turn. If you have illegal moves in the PV, but not the first move itself, then the engine won't actually play illegal moves, but you certainly have a bug there that will reduce the strength of play.
Rasmus Althoff
https://www.ct800.net
eligolf
Posts: 114
Joined: Sat Nov 14, 2020 12:49 pm
Full name: Elias Nilsson

Re: Affinity Chess 1.0 released

Post by eligolf »

I don't like chess engine bugs, they are so hard to find :P Maybe something to do with how I collect PV then.. How did you set up the itnerface so that you can see if PV line is wrong?
Some ideas:
1) Don't search underpromotions in QS. Ideally, don't even generate them.
2) After a "certain" depth within QS (like 5-6 plies), only examine captures on the same square as in the ply before. That prevents searching pointless mutual queen plunder raids.
3) Use delta pruning: if your current capture plus a safety margin (like 2 pawns) doesn't reach alpha even assuming that the opponent cannot capture back, don't examine it. If you score moves by MVV/LVA, you can actually drop the remaining moves because they will be even worse. Pay attention to pawn promotions here because that is a delta of QUEEN-PAWN in itself.
Good ideas! Can I also use TT in Q search? And how do you usually handle checks?
User avatar
Ras
Posts: 2696
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: Affinity Chess 1.0 released

Post by Ras »

eligolf wrote: Sat Mar 05, 2022 6:15 pmHow did you set up the itnerface so that you can see if PV line is wrong?
I'm using c-chess-cli for testing (I'm on Linux), and that reports illegal PVs. In that case, I activate its logging feature to get more information.
Can I also use TT in Q search?
You can try, maybe there's some benefit to it, depending on your engine. E.g. Demolito does it, and I faintly remember an A/B test where it was worth around 20 Elo.
And how do you usually handle checks?
Being in check means you can't stand pat in QS. I generate check evasions (also quiet moves) in QS up to four plies QS depth.
Rasmus Althoff
https://www.ct800.net
eligolf
Posts: 114
Joined: Sat Nov 14, 2020 12:49 pm
Full name: Elias Nilsson

Re: Affinity Chess 1.0 released

Post by eligolf »

I fixed the bug with PV line. Apparently I set PV table entry to 0 after I check for draws or time outs which made an old entry sometimes left in by mistake. Now it is fixed and all good.
lithander wrote: Sat Mar 05, 2022 12:37 am I ran a few games against Leorik but it was an unfair match:
CODE: SELECT ALL

Score of Leorik 1.0 vs Affinity Chess: 79 - 2 - 16 [0.897] 97
... Leorik 1.0 playing White: 40 - 1 - 8 [0.898] 49
... Leorik 1.0 playing Black: 39 - 1 - 8 [0.896] 48
... White vs Black: 41 - 40 - 16 [0.505] 97
Elo difference: 375.8 +/- 90.0, LOS: 100.0 %, DrawRatio: 16.5 %
I played another match with Leorik 1.0 with the following setup:

Code: Select all

cutechess-cli -tournament gauntlet -concurrency 1 -pgnout output_pgn_file.pgn -engine conf=AC1 tc=1+0.1 -engine conf=L1 tc=1+0.1 -draw movenumber=40 movecount=4 score=8 -resign movecount=4 score=500 -each proto=uci -openings file=openings\\openings-16ply-100k.pgn policy=round -repeat -rounds 100 -games 2
Random openings from a dataset and the results from the tests are even more devastating than what you posted earlier.

What I find from the resulting files is that most often the games are pretty equal until late game. Then it sometimes misses a crucial move and gets a -2 or more disadvantage from that. Maybe due to all the prunings I do, maybe due to some bug in the code. I tried playing a fixed depth 8 plies tournament for a few games in Arena with similar results, but I guess that doesn't rule out not point towards a bug. Not sure how to continue from here.

With a 6 ply fixed depth match it beats Leorik like 20-10 but could also just be a fluke. Not sure if it is possible to set up fixed depth matches in cute chess, couldn't find any info of that.
eligolf
Posts: 114
Joined: Sat Nov 14, 2020 12:49 pm
Full name: Elias Nilsson

Re: Affinity Chess 1.0 released

Post by eligolf »

Ras wrote: Sun Mar 06, 2022 11:46 pm
And how do you usually handle checks?
Being in check means you can't stand pat in QS. I generate check evasions (also quiet moves) in QS up to four plies QS depth.
That seems good. I do something similar now with trying all capture moves, and if none of them works I generate quiet ones and try them too. If none of them works and being in check I send back mate score, else draw score.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Affinity Chess 1.0 released

Post by mvanthoor »

lithander wrote: Sat Mar 05, 2022 12:37 am That's a bit surprising because Leorik 1.0 does not have many of the features you have already implemented. Based on your feature list your engine should be much stronger than Leorik! That it's the other way round can't be explained by performance differences alone. I fear you'll have to go on a bug hunt! :wink:
You stole my tagline. I'll be sending out a royalty bill momentarily. It was me who was trying to write an engine as strong as possible with the least amount of features :( But granted, I haven't been doing a lot of engine writing in the last few weeks... months even... :shock: :oops:
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL