Thursday, July 25, 2013

Fifty-move rule

When you ask an average chess player what the 50 move rule in chess is about he will probably say something like
A game is draw if no capture has been made and no pawn has been moved in the last fifty consecutive moves
I would have said the same and so I implemented it in iCE. But actually this is not correct. If you look the rule up in the FIDE laws they state

The game is drawn, upon a correct claim by the player having the move, if
(a) he writes on his scoresheet, and declares to the arbiter his intention to make a move which shall result in the last 50 moves having been made by each player without the movement of any pawn and without the capture of any piece, or
(b) the last 50 consecutive moves have been made by each player without the movement of any pawn and without the capture of any piece.
Of course it is difficult for a UCI chess engine to write on a scoresheet or even to claim a draw. This is usually done by the GUI automatically. But one important point remains. The game is not automatically a draw after 50 moves, there must exist a side having the right to move.

Why is that important ?

If one side mates the opponent with its 50th move the result is mate and not draw because after a mate there is no side to move that can claim a draw anymore.

Well, how likely is this having any relevance?

It is not as unlikely as one might think. The difference will be suppressed because often games are adjudicated very early by the GUI to save time. But if games are played until the end it will show up sooner or later.

One tester of iCE made me aware of a game where iCE just gave away half a point.

6R1/8/8/8/4K3/4N3/4r2k/8 b - - 96 147
Already 48 moves (96 plies) have been played. The draw is in sight. But what did iCE as Black play?

147.  ..  Kh3??
148. Kf3  Rh2
149. Rh8#

iCE was just assuming that Rh8 will finish the 50 move sequence and draw so he walked into the mate. An analyses shows this clearly. It sees Kh3 as a drawing move.

position fen 6R1/8/8/8/4K3/4N3/4r2k/8 b - - 96 147
analyze depth 8
e2e3 : -32.463  e2e3 e4e3
e2a2 :       0  e2a2 e3f5 a2a1 f5g7
e2e1 :       0  e2e1 g8h8 h2g3 h8g8
h2h3 :       0  h2h3 g8h8 h3g3 h8g8
e2g2 : -32.461  e2g2 g8g2 h2h1 g2c2 h1g1 e4f3 g1h1 c2c1 h1h2 e3g4 h2h3 c1h1
e2f2 :  -1.372  e2f2 e3g4 h2h3 g4f2 h3h2
e2d2 :  -1.346  e2d2 e3f1 h2h3 f1d2 h3h4 e4f4 h4h5 g8g5 h5h4 d2e4
e2c2 :  -1.373  e2c2 e3c2 h2h3 c2d4 h3h4 e4e5 h4h5 d4f5
e2b2 :       0  e2b2 e3f1 h2h3 g8h8
h2h1 :       0  h2h1 g8h8 e2h2 h8h2 h1h2

After knowing there is a problem it was easy to fix. I only had to remove a single character in the source.

inline bool TBoardStateHistory::is50MoveDraw()
    return hmc > 100;    // was hmc >= 100

Now it solves the above position correctly

position fen 6R1/8/8/8/4K3/4N3/4r2k/8 b - - 96 147
analyze depth 6
e2e3 : -32.463  e2e3 e4e3
e2a2 :       0  e2a2 e3f5 h2h3 f5g7
e2e1 :       0  e2e1 g8h8 h2g3 h8f8 e1h1
h2h3 :  -1.345  h2h3 e4f3 h3h4 f3e2 h4h5 e3f5
e2g2 :  -1.401  e2g2 g8g2 h2h1 g2f2 h1g1 f2f1 g1h2 e3d5
e2f2 :  -1.181  e2f2 e3g4 h2g2 g4f2 g2f1 g8h8 f1g1
e2d2 :  -1.378  e2d2 e3f1 h2h3 f1d2 h3h4 d2f3 h4h5 f3e5
e2c2 :  -1.378  e2c2 e3c2 h2h3 c2d4 h3h4 d4f3 h4h5 f3e5
e2b2 :       0  e2b2 e3f1 h2h3 e4f5 h3h4
h2h1 :       0  h2h1 g8h8 e2h2 h8g8 h2g2

It sees now that h2h3 will lose the rook to avoid an instant mate and select a different move.

Thanks to jack who reported the issue.

Saturday, July 13, 2013

Pondering about king positions in pawn hash

iCE 1.0 calculates a hash for the pawn structure and caches it. This is very efficient because different somehow related chess positions share the same pawn structure and evaluation terms related only to the positions of the pawns (e.g. isolated pawns) must not be evaluated again.

I'm now thinking about adding more pawn structure related terms to my evaluation, however terms that only depend on the pawn structure are limited. The king pawn shelter could be a pawn structure related term but it depends also on the king position. The same pawn structure will produce a different results for the shelter depending on the location of the king  (after king side or queen side castling). Only if I add the king position to the hash I can evaluate the pawn shelter. But there is a downside. The amount of hash hits and so the efficiency of the cache will decrease.

In order to visualize the effect I selected a number of positions and recorded the number of hash hits with and without including the king positions in the hash.

Successful hash hits with and without king positions in the hash
So it shows that for typical mid game positions there is an about 4% drop in the hit rate. All the features I'm now able to put into the hash additionally must compensate this 4% drop.

I have to try it out.

Thursday, July 4, 2013

The MSVCP100 mess hits again

I received a message today from someone trying out iCE that the 32 bit version of iCE 1.0 has the dependency on the well known msvcp100.dll. I usually build my executable without that dependency  (it really sucks). But obviously this time in the 32 bit branch I selected the wrong runtime library.

Most of the guys running chess engines have the Microsoft Visual C++ 2010 SP1 Redistributable Package (x86) installed and won't notice. But a few might have not.

I went back to my 1.0 code base and recompiled the 32 bit version and updated my website. So the error should not appear any longer, hopefully.