A complete 2000 lines of code engine

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

Moderators: hgm, Rebel, chrisw

User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

A complete 2000 lines of code engine

Post by xr_a_y »

Being a little tired of finding bugs in Weini, I started a week-end project last sunday. The idea was the following : "starting from a blank page, how far can I go in 2 days now I know a little more on chess programming".

An expected side effect was to get a simple engine to experiment with and maybe find some Weini's bug in it.

It is a mailbox negamax (pvs) engine, with classic pruning trick, a double bucket TT and only PST eval.

After 2 days the engine was working in xboard, validated in perft, finds mate in 8 from a collection I often use and was able to always win against me at fast TC (but loses against fairy-max).

Since then I corrected some stuff but the engine is still quite bad, but working :D

Here's the source code : https://github.com/tryingsomestuff/Mini ... r/minic.cc

Some of you probably can easily spot very bad things that makes it so weak.

Maybe, as a 2000 lines c++ code, it may also become an entry point for beginners. I can open the repository for write if some of you want to contribute.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: A complete 2000 lines of code engine

Post by Sven »

The middlegame PST for kings seems to be wrong, it seems to favor moving the king to higher ranks instead of discouraging that.

I do not understand your MvvLvaScores[][] array. First thing is, it has a lot of redundancy by being a 13x13 array while you only need 6x6 (or 7x7). You never have captures of friendly pieces, and White takes Black can be handled with the same data as Black takes White if you use abs(). Next point, MVV/LVA means "most valuable victim/least valuable aggressor" and is usually implemented differently: all moves capturing a piece of type X should be scored higher than all captures of pieces with a lower value than X, and for two captures of the same piece type the move with the lower-valued moving piece should come first. A possible formula would be:

mvvLvaScore(move) = 6 * type_of_captured_piece(move) - type_of_moving_piece(move)

if the piece type is in the range [1 .. 6]. The factor "6" can of course be any number >= 6.

What about the raw speed of this engine? For instance, your move ordering implementation appears to be quite slow since you calculate the ordering scores for each moves within the comparison operator so you calculate it many times for the same move. What about making the ordering score a member of the move and calculating it only once?

There should be a better way (and maybe even one that is more "C++") than always accessing information related to pieces like this throughout the whole code:

Code: Select all

SOME_ARRAY[position.board[square] + PieceShift]
where PieceShift is 6 and board[square] is the piece type in the range { -6 .. +6 }. I could imagine some accessor methods of the position class, for instance:

Code: Select all

unsigned int Position::pieceIndex(Sq s) const { return board[s] + PieceShift; } // returns a number in [0 .. 12]
Piece Position::pieceType(Sq s) const { return std::abs(board[s]); } // returns a number in [0 .. 6]
Color Position::color(Sq s) const { return Colors[pieceIndex(s)]; }
I wonder why you set the hash move as killer move, I can imagine a negative impact on the quality of your move ordering.

I also wonder why you check for "king capture" within the move loop even though you also have an explicit legality check when making a move so that you can never reach a position where the enemy king can be captured. Furthermore, when ignoring that redundancy, the correct score for a position where the king can be captured should be higher than MATE-ply in my opinion since a "mated" position where all pseudo-legal moves lead to capturing the king would already have occurred one ply earlier.

If you would like to know why this engine is so weak I would suggest to disable all pruning code and test that against the original version. Maybe the problem is somewhere within the pruning?
Maybe, as a 2000 lines c++ code, it may also become an entry point for beginners.
Not sure whether a 2-days work is always suitable for that purpose :-) Once you know there are no serious bugs and it has an acceptable strength then go for it, otherwise I suggest first to fix the code before proposing it to beginners.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: A complete 2000 lines of code engine

Post by Sven »

Sven wrote: Sat Oct 20, 2018 2:28 pm The middlegame PST for kings seems to be wrong, it seems to favor moving the king to higher ranks instead of discouraging that.
I may be wrong here, I just saw the PST access is reversed by this code in eval()

Code: Select all

const int s = Signs[p.b[k]+PieceShift];
Square kk = k;
if ( s > 0 ) kk = 63-k;
so PST[x][0] is for H8, not for A1 :-)
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

Re: A complete 2000 lines of code engine

Post by xr_a_y »

Thanks for the comment. I Will simplify mvvlva table and piece type accessor. move score is already backuped.
tpoppins
Posts: 919
Joined: Tue Nov 24, 2015 9:11 pm
Location: upstate

Re: A complete 2000 lines of code engine

Post by tpoppins »

A neat little engine to play with indeed. It lost rather quickly to the 1600-Elo rated Monochrome and obtained a big advantage vs. 1060-rated Soberango, only to go unexpectedly for a threefold repetition.

[pgn][Event "?"] [Site "?"] [Date "2018.10.20"] [Round "?"] [White "Minic 0.1"] [Black "Soberango 0.12.0"] [Result "1/2-1/2"] [ECO "B18"] [GameDuration "00:01:27"] [GameEndTime "2018-10-20T12:49:35.059 Eastern Daylight Time"] [GameStartTime "2018-10-20T12:48:07.098 Eastern Daylight Time"] [Opening "Caro-Kann"] [PlyCount "44"] [TimeControl "40/120"] [Variation "Classical, Flohr Variation"] 1. e4 {book} c6 {book} 2. d4 {book} d5 {book} 3. Nc3 {book} dxe4 {book} 4. Nxe4 {book} Bf5 {book} 5. Ng3 {book} Bg6 {book} 6. Nh3 {book} e6 {book} 7. Nf4 {+0.39/9 2.9s} c5 {0.00/6 2.2s} 8. dxc5 {+1.15/8 2.9s} Qxd1+ {0.00/7 1.8s} 9. Kxd1 {+0.48/11 2.9s} Bxc5 {0.00/7 2.6s} 10. Nxg6 {+0.67/10 2.8s} fxg6 {0.00/6 3.6s} 11. Ne4 {+0.98/11 2.9s} b6 {0.00/6 1.4s} 12. Bc4 {+1.50/9 2.9s} Ke7 {-1.02/6 3.7s} 13. Nxc5 {+2.05/10 2.9s} bxc5 {-1.02/6 3.7s} 14. Re1 {+1.87/11 2.9s} Nf6 {-1.02/6 3.7s} 15. Rxe6+ {+2.10/9 2.9s} Kd7 {-1.03/6 2.3s} 16. Bf4 {+2.61/9 2.9s} Kc8 {-1.03/5 3.8s} 17. Kc1 {+2.71/8 2.9s} Kd7 {-1.03/5 1.6s} 18. c3 {+2.95/8 2.9s} Rc8 {-1.03/5 3.9s} 19. Rd6+ {+2.84/8 2.9s} Ke7 {-1.03/6 1.4s} 20. Re6+ {+2.94/8 2.9s} Kd7 {-1.03/5 4.0s} 21. Rd6+ {+2.84/8 2.9s} Ke7 {-1.03/6 2.7s} 22. Re6+ {+2.80/8 2.9s} Kd7 {0.00/2 0s, Draw by 3-fold repetition} 1/2-1/2 [/pgn]

Here are MinGW builds (32- and 64-bit) of today's code:
minic-01-TP.zip

Note that the execs require -xboard on the command line to enable the Winboard/Xboard mode.
Tirsa Poppins
CCRL
tpoppins
Posts: 919
Joined: Tue Nov 24, 2015 9:11 pm
Location: upstate

Re: A complete 2000 lines of code engine

Post by tpoppins »

Minic can win a KRK endgame. Amazing! I can name at least a dozen engines many hundreds Elo higher that can only draw.

[pgn][Event "?"] [Site "?"] [Date "2018.10.20"] [Round "?"] [White "Minic 0.1 64-bit"] [Black "__Thinker"] [Result "1-0"] [FEN "7R/5K2/8/5k2/8/8/8/8 w - - 0 1"] [GameDuration "00:01:38"] [GameEndTime "2018-10-20T14:47:28.517 Eastern Daylight Time"] [GameStartTime "2018-10-20T14:45:49.816 Eastern Daylight Time"] [PlyCount "47"] [SetUp "1"] [TimeControl "40/120"] 1. Rh3 {+5.58/13 2.8s} Kg4 {9.4s} 2. Rh1 {+5.58/13 2.9s} Kf3 {0.94s} 3. Ke6 {+5.65/12 2.8s} Ke3 {1.4s} 4. Kd5 {+5.65/12 2.8s} Kf3 {0.72s} 5. Ke5 {+5.75/12 2.9s} Kg2 {3.3s} 6. Rc1 {+5.81/13 2.9s} Kf3 {2.1s} 7. Rc3+ {+5.95/12 2.9s} Ke2 {1.9s} 8. Ke4 {+5.89/12 2.8s} Kd2 {1.9s} 9. Rc4 {+5.95/12 2.9s} Ke2 {1.9s} 10. Rc2+ {+5.95/12 2.8s} Kd1 11. Rc6 {+5.95/14 2.9s} Kd2 {3.2s} 12. Rc4 {+5.95/13 2.9s} Ke2 13. Rc1 {+5.95/12 2.9s} Kd2 {3.3s} 14. Rc7 {+5.95/13 2.9s} Ke2 {0.75s} 15. Rc2+ {+5.95/12 2.9s} Kd1 16. Rh2 {+5.95/14 2.9s} Ke1 {1.4s} 17. Ra2 {+5.95/12 2.9s} Kd1 {0.53s} 18. Kd3 {+6.15/13 2.8s} Ke1 19. Re2+ {+5.98/11 2.8s} Kf1 20. Ke3 {+89.90/11 2.9s} Kg1 21. Kf3 {+89.92/11 2.9s} Kf1 22. Re5 {+89.94/17 2.9s} Kg1 23. Rh5 {+89.96/15 2.9s} Kf1 24. Rh1# {+89.98/64 0.001s, White mates} 1-0 [/pgn]
Tirsa Poppins
CCRL
User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

Re: A complete 2000 lines of code engine

Post by xr_a_y »

Well using rofchade PST it can even win against fairy-max sometimes ... Thanks for testing it.
User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

Re: A complete 2000 lines of code engine

Post by xr_a_y »

TC : 20sec/40moves, 12 moves from book

Score of fairymax vs Minic: 54 - 14 - 32 [0.700]
Elo difference: 147.19 +/- 59.21

100 of 100 games finished.
User avatar
xr_a_y
Posts: 1871
Joined: Sat Nov 25, 2017 2:28 pm
Location: France

Re: A complete 2000 lines of code engine

Post by xr_a_y »

Version 0.4 is available and is less stupid than the previous ones ... :lol:
tpoppins
Posts: 919
Joined: Tue Nov 24, 2015 9:11 pm
Location: upstate

Re: A complete 2000 lines of code engine

Post by tpoppins »

And here are Windoze bins for it:

minic-04-TP.zip

But it's 2200+ lines now, you cheat. ;)
Tirsa Poppins
CCRL