Graham Banks 66th Amateur Tournament Division 6

MadChess 2.2 participated in Graham Banks’ 66th Amateur Tournament in Division 6.

66th Amateur D6  2017
                                 1    2    3    4    5    6    7    8    9    0    1    2   
1   Ghost 3.1 64-bit             **** ½0½0 1111 1½½1 ½10½ 1010 1111 0100 ½101 0101 1½11 0½11  27.5/44
2   tomitankChess 1.4 64-bit     ½1½1 **** 1½0½ 0½1½ 0½11 ½011 000½ 1½½1 1½½1 ½01½ ½111 ½½½1  26.5/44
3   Counter 2.0.2 64-bit         0000 0½1½ **** 110½ ½101 ½½1½ 1110 00½½ 101½ ½111 0111 1½11  26.0/44
4   JikChess 0.02 64-bit         0½½0 1½0½ 001½ **** 0½11 101½ ½1½½ ½001 0011 1½11 1001 1010  23.0/44  494.50
5   Dorky 4.5 64-bit             ½01½ 1½00 ½010 1½00 **** 100½ 0½11 1½0½ 1½11 ½½½½ 1½10 0½11  23.0/44  491.25
6   Maverick 1.5 64-bit          0101 ½100 ½½0½ 010½ 011½ **** 1½½0 ½1½0 ½010 010½ ½½11 1½11  22.5/44  472.75
7   Capivara LK 0.09b02g 64-bit  0000 111½ 0001 ½0½½ 1½00 0½½1 **** ½½1½ ½0½1 0½1½ 111½ 1011  22.5/44  466.75
8   Shield 1.3.1 64-bit          1011 0½½0 11½½ ½110 0½1½ ½0½1 ½½0½ **** 0½00 0½½1 0½1½ 1½½½  22.0/44
9   MadChess 2.2 64-bit          ½010 0½½0 010½ 1100 0½00 ½101 ½1½0 1½11 **** 0100 ½½1½ 1½11  21.5/44
10  NanoSzachy 4.1 64-bit        1010 ½10½ ½000 0½00 ½½½½ 101½ 1½0½ 1½½0 1011 **** ½½00 ½½½1  20.0/44
11  Schooner 1.7.0 64-bit        0½00 ½000 1000 0110 0½01 ½½00 000½ 1½0½ ½½0½ ½½11 **** ½0½½  15.0/44
12  Lozza 1.17 64-bit            1½00 ½½½0 0½00 0101 1½00 0½00 0100 0½½½ 0½00 ½½½0 ½1½½ ****  14.5/44

Games

Graham Banks 65th Amateur Tournament Division 6

MadChess 2.2 participated in Graham Banks’ 65th Amateur Tournament in Division 6.

65th Amateur D6  2017
                                 1    2    3    4    5    6    7    8    9    0    1    2    
1   Muse 0.953 64-bit            **** ½100 11½1 0010 0011 ½½1½ 0111 1½10 1½½1 1111 1½11 1011  29.5/44
2   Coiled 0.4 64-bit            ½011 **** ½01½ 0101 001½ 110½ 1101 1½½0 010½ 1½½1 ½½½1 1111  26.5/44
3   Counter 2.0.2 64-bit         00½0 ½10½ **** 111½ ½110 ½011 1½1½ 11½0 11½0 ½101 ½1½½ 1001  26.0/44
4   Ghost 3.1 64-bit             1101 1010 000½ **** 1½11 101½ ½10½ 01½1 0½1½ 0011 111½ 1010  25.5/44
5   Shield 1.3.1 64-bit          1100 110½ ½001 0½00 **** ½011 1001 ½010 0½11 ½110 0110 1½11  23.0/44
6   Capivara LK 0.09b02g 64-bit  ½½0½ 001½ ½100 010½ ½100 **** 0111 11½½ 011½ 1½½½ 1½01 ½100  22.5/44
7   Dorky 4.5 64-bit             1000 0010 0½0½ ½01½ 0110 1000 **** 0111 10½1 1110 1½10 0½11  21.5/44
8   MadChess 2.2 64-bit          0½01 0½½1 00½1 10½0 ½101 00½½ 1000 **** 0101 ½½½0 01½0 1111  20.0/44
9   Maverick 1.5 64-bit          0½½0 101½ 00½1 1½0½ 1½00 100½ 01½0 1010 **** 001½ 1½00 ½½01  18.5/44
10  CyberPagno 3.0 64-bit        0000 0½½0 ½010 1100 ½001 0½½½ 0001 ½½½1 110½ **** 01½1 ½½10  18.0/44
11  Shallow r694 64-bit          0½00 ½½½0 ½0½½ 000½ 1001 0½10 0½01 10½1 0½11 10½0 **** ½00½  16.5/44  358.00
12  Betsabe II 1.75              0100 0000 0110 0101 0½00 ½011 1½00 0000 ½½10 ½½01 ½11½ ****  16.5/44  355.00

Games

MadChess 2.2 Released

I have released version 2.2 of my chess engine. Source code and Windows binaries are available on the Downloads page. MadChess 2.2 is about 50 ELO stronger than version 2.1. It includes the following improvements.

  • Added best move estimation. In principal variations where the cached position does not specify a best move, MadChess will search at reduced depth to obtain a best move. Then it completes the full depth search, searching the best move first. This is called Internal Iterative Deepening (IID) in other engines, though I find the name misleading. It’s recursive but not iterative.
  • Added endgame piece location constants to differentiate the value of pieces in the middlegame and endgame. Evaluation tuning found a significant difference only for rooks.
  • Modified the GetExchangeScore method to use standard 100, 300, 500, 900 piece material values rather than the tuned material values. This forces the engine to consider knights and bishops equal for the purpose of Static Exchange Evaluation (SEE).
  • Tuned evaluation parameters using the technique described by Peter Österlund.
  • Fixed a bug that prevented the evaluation from recognizing drawn endgames.
  • Added a help command that lists custom (non-standard UCI) commands.
  • Added a staticscore custom command that displays evaluation score details by color (white, black) and phase (middlegame, endgame). The scores include differences and totals to clearly indicate strengths and weaknesses of a position for each side.

As I write this post, MadChess is competing in a long time control gauntlet. Presently it’s rated 2574 +/- 69 ELO after 126 games. I’ve seen this show before. I expect its rating to decline as more games are played and the engine “regresses to the mean.” Nonetheless, I expect MadChess 2.2 to be rated > 2500 ELO in rapid chess. So now I can rightfully claim MadChess plays Grandmaster quality chess.

Update 2017 Jul 10: MadChess 2.2 completed the gauntlet tournament. It’s rated 2511 in rapid chess.

MadChess is written in a managed1 programming language, C#, using a mailbox2 board representation. Managed programming languages, such as C# or Java, feature high-level abstractions and trade performance for code clarity. Similarly, array board representations are easier to understand than bitboards- again trading speed for clarity. Despite these trade-offs, it’s possible to write a strong chess engine using a managed programming language and mailbox board representation, as I’ve demonstrate with MadChess.

How strong? I was curious how MadChess compares to other engines of similar technical design. I reviewed the engine list on Ron Murawski’s Computer Chess Wiki, which includes the programming language of each engine. I believe MadChess is the strongest managed, mailbox chess engine. Stronger chess engines have been written in managed languages, but they use bitboards. Lozza is a close 2nd, written- impressively- in Javascript.

Engine Programming Language Board Representation CCRL Rating
Carballo Java Bitboard 2727
NoraGrace C# Bitboard 2619
Cuckoo Chess Java Bitboard 2590
MadChess C# Mailbox 2511
Lozza Javascript Mailbox 2442
Absolute Zero C# Bitboard 2320
Mediocre Java Mailbox 2314
Fischerle Java Bitboard 2297
Dolphin C# Mailbox 2232
Cupcake Java Bitboard 2006
Chess4J Java Bitboard 1965
Deepov Java Bitboard 1844
Ziggy Java Mailbox 1709
SharpChess C# Mailbox 1674
Pulse Java Mailbox 1571
DarkFusch C# Bitboard 1172
jChecs Java Mailbox 1128

Of course this prompts a couple questions.

  • Should I rewrite MadChess using bitboards?
  • Should I rewrite MadChess using a more performance-capable programming language, such as C++?

I will ponder these questions. Regarding changing programming languages, I’m intrigued by the .NET Native and Core RT projects, which aim to compile C# to IL code, statically link .NET Framework IL code, cross-compile the IL code to C++, then use an optimizing C++ compiler to produce a single executable. If this technique can deliver the simplicity of C# with the performance of C++, I’ll have no reason to switch programming languages. I’m cautiously optimistic.


1. So named because memory is automatically managed by the runtime and its garbage collector, not manually managed by the programmer.

2. An array with each index representing a square, index values indicating an empty square or occupying piece. So named because the array representation resembles a mailbox commonly found in apartments.

Graham Banks 64th Amateur Tournament Division 6

MadChess 2.1 participated in Graham Banks’ 64th Amateur Tournament in Division 6.

64th Amateur D6  2017
                           1    2    3    4    5    6    7    8    9    0    1    2    
1   chess22k 1.3 64-bit    **** 11½1 1000 1½11 1100 ½111 11½0 0011 111½ 0101 011½ 0111  29.0/44
2   Gogobello 1.2 64-bit   00½0 **** 01½1 110½ 01½½ 01½½ ½½11 111½ 0111 111½ 1½½½ 1½11  28.5/44
3   Maverick 1.5 64-bit    0111 10½0 **** 0½10 ½1½1 011½ 0½0½ 1011 111½ ½111 1½01 001½  26.5/44
4   Dorky 4.5 64-bit       0½00 001½ 1½01 **** 1110 0½½½ 1110 ½½11 1½11 1½01 11½½ 0½½½  25.5/44
5   Betsabe II 1.66        0011 10½½ ½0½0 0001 **** 0½01 1101 110½ ½101 ½11½ 11½0 ½1½½  23.5/44
6   MadChess 2.1 64-bit    ½000 10½½ 100½ 1½½½ 1½10 **** 001½ 01½0 0010 01½½ ½½1½ 1½10  20.0/44  434.50
7   ECE-X2                 00½1 ½½00 1½1½ 0001 0010 110½ **** 1011 ½½00 0½½½ 1100 1½10  20.0/44  431.75
8   Nemeton 1.5            1100 000½ 0100 ½½00 001½ 10½1 0100 **** 0111 ½½10 1½1½ ½0½½  19.0/44  401.50
9   Lozza 1.17 64-bit      000½ 1000 000½ 0½00 ½010 1101 ½½11 1000 **** 0½10 1011 1½11  19.0/44  383.00
10  Schooner 1.7.0 64-bit  1010 000½ ½000 0½10 ½00½ 10½½ 1½½½ ½½01 1½01 **** ½010 110½  18.5/44
11  TJchess 1.3 64-bit     100½ 0½½½ 0½10 00½½ 00½1 ½½0½ 0011 0½0½ 0100 ½101 **** ½011  17.5/44
12  Bagatur 1.5c 64-bit    1000 0½00 110½ 1½½½ ½0½½ 0½01 0½01 ½1½½ 0½00 001½ ½100 ****  17.0/44

Games

Missed Opportunity in the Endgame

I’ve been playing chess against my engine recently, using a beautiful 23″ wooden board by Drueke, with my notebook PC off to the side.  I set the time control to 25 min + 10 sec / move and give myself an extra 5 minutes per game (more time than MadChess) to make the moves on the board and the PC.  I figure that’s fair- it averages to 5 seconds per move over 60 moves.

Since MadChess plays chess as well as an international master (slightly below a grand master), and I am nowhere near that strong, I handicapped it to play at 1300 ELO.  This is made possible by the UCI_LimitStrength algorithm I implemented in the engine.

25 + 10 is an enjoyable pace. It’s slow enough to think through each move, yet fast enough to complete a game in an hour.  After 48 moves (and numerous missed opportunities as post-game analysis revealed), I reach the following position.  Playing the black pieces, thinking I needed to move my king up the board to support my passed pawn, I played Kc5, a blunder.  Can you find the correct move for black?


Of course! I overlooked the move, thinking it lost material. It does, but only temporarily. The pawn will queen.

I am a better chess programmer than player.  I need to play more games and write less code.  I must say though, what a strange feeling is produced by playing a game against an artificial intelligence I have created, purposefully handicapping it to get an even game, then unleashing its full potential after the game is concluded so it may identify all the moments I erred.  A bit magical and eerie all at once.

The full game, with MadChess’ post-game analysis (at 10 seconds per move), is available by clicking the share icon in the diagram above (the rightmost icon).