Help with Debugging My Chess Engine

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Help with Debugging My Chess Engine

Post by Sven »

universecoder wrote:I found an error on line 316 in chessboard.cpp using gdb
pieceList[move.currPiece].insert(move.to);

Why, I am trying to find out.
In the source version I downloaded about an hour ago this is line 337. Have you changed or deleted a lot since then, or are you not looking at the GitHub version?
universecoder
Posts: 53
Joined: Mon Sep 19, 2016 6:51 am

Re: Help with Debugging My Chess Engine

Post by universecoder »

Ok guys, so finally with help from a lot of places and using gdb, I got to the conclusion that somehow unordered_set was causing the bug! I replaced it with set and it worked!! I wonder what can be the reason for this? There was no actual bug in the code(the hashing was wrong, of course) but the infinite "loop" was somehow caused due to unordered set.
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: Help with Debugging My Chess Engine

Post by AlvaroBegue »

universecoder wrote:Ok guys, so finally with help from a lot of places and using gdb, I got to the conclusion that somehow unordered_set was causing the bug! I replaced it with set and it worked!! I wonder what can be the reason for this? There was no actual bug in the code(the hashing was wrong, of course) but the infinite "loop" was somehow caused due to unordered set.
I am suspicious of your diagnosis. You might have been misusing unordered_set in some way that set tolerates, but chances are you were doing something wrong.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Help with Debugging My Chess Engine

Post by Sven »

To me the code related to en passant in undoMove() does not appear to be correct. It looks almost identical to the corresponding code in playMove() which confuses me.

Also I think that maintaining two ep squares, one per color, is not appropriate (you only get one when setting up a position by FEN). There should be one ep square, and you should store it in playMove() and restore it in undoMove(). In my engine I store castling rights, ep square, and fifty-moves counter in an "Undo" structure which I allocate on the stack close to the call of my makeMove() function. A reference (or pointer) to that "Undo" structure is then passed to both makeMove() (to fill it) and to unmakeMove() (to restore from it). Actually I also store information about the captured piece in "Undo" but that is another topic.
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: Help with Debugging My Chess Engine

Post by matthewlai »

universecoder wrote:Ok guys, so finally with help from a lot of places and using gdb, I got to the conclusion that somehow unordered_set was causing the bug! I replaced it with set and it worked!! I wonder what can be the reason for this? There was no actual bug in the code(the hashing was wrong, of course) but the infinite "loop" was somehow caused due to unordered set.
I don't know what the bug is, but it's highly unlikely that there's a bug in unordered_set.

In my 10+ years of programming in C++ I've only discovered 1 actual bug in a standard library, out of about a dozen instances where I was absolutely convinced it's a bug in the standard library.
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
User avatar
hgm
Posts: 27787
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Help with Debugging My Chess Engine

Post by hgm »

Sven Schüle wrote:1) piece placement related part,
2) castling rights related part,
3) en passant square related part,
4) side to move related part.
Note that it is not really useful, or even counter-productive, to do (2)-(4) incrementally. There are too many conditions that change the castling rights, and 3 and 4 are not permanent contributions to the key, but would have to be undone one turn later anyway.

So the best way is to do the piece-placement part incrementally, and then XOR that with the e.p. part, castling part and stm key to get an actual key for use in the current node. In Fairy-Max I just add (CONST1 + stm)*(CONST2 + epSquare) to the incremental key before using it to probe the hash table. (The only thing Fairy-Max uses the key for.)
universecoder
Posts: 53
Joined: Mon Sep 19, 2016 6:51 am

Re: Help with Debugging My Chess Engine

Post by universecoder »

The undoMove() function seems to be correct and I am restoring the enPassant square. Only the castling rights have not been restored yet. Now that the main bug is solved, I am going to do some rigorous testing as well. I'll inform here once it's done. Also you say that it looks almost the same, look carefully, it reverses the changes and resets the enPassant Square.
universecoder
Posts: 53
Joined: Mon Sep 19, 2016 6:51 am

Re: Help with Debugging My Chess Engine

Post by universecoder »

Ok, I'll try to look into it.
universecoder
Posts: 53
Joined: Mon Sep 19, 2016 6:51 am

Re: Help with Debugging My Chess Engine

Post by universecoder »

As you people suggest, I too don't think it's a problem with unordered_set, rather the problem might be that using it in a wrong way(the same way as a set?). For now, I'll use a set only.
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: Help with Debugging My Chess Engine

Post by AlvaroBegue »

universecoder wrote:As you people suggest, I too don't think it's a problem with unordered_set, rather the problem might be that using it in a wrong way(the same way as a set?). For now, I'll use a set only.
A more instructive thing to do is to try to isolate what you were doing with the unordered_set exactly that triggered the problem. Try to write a minimal program that shows the problem. This will typically be something like 20 or 30 lines of code. If there is a bug in the library, you can use the minimal program in your bug report. Or you can post it here so we can try to reproduce the problem. But chances are by the time you have constructed the minimal program you will have figured out what you were doing wrong.