For engine developers, i think that it could be usefull if the engines implement a verbose version of divide command, that produce something like this output:
divide 2 verbose
a2a3(a7a6 a7a5 b7b6 b7b5...) N
a2a4(a7a6 a7a5 b7b6 b7b5...) N
...
divide 3 verbose
a2a3(a7a6(a2a4 b2b3 b2b4...)a7a5(a2a4 b2b3 b2b4...)) N
This could help a lot, because you easly find the point where your engine makes the wrong move, when you're debugging the move generator, as i'm doing right now.
Adding the word "verbose" at the end of the command wouldn't impact existing engines, i think.
Perft(5) from starting position is 4,865,609 but in divided form, it includes all Perft(1) = 20 divided perft values.
@Stefano: I think that qperft by Muller already includes some kind of extended divide, I mean, instead of showing all Perft(1) results for Perft(n), it shows all Perft(d) results when specified (with 1 < d < n). For example: a4 a6, a4 a5, ..., Nh3 Nh6 (for d = 2 in the starting position, that is, 400 divided results). They can be written in a Notepad (a log file). qperft source code is online, so everyone can have a look.
perft 6
1 Nb1-a3 4856835: rnbqkbnr/pppppppp/8/8/8/N7/PPPPPPPP/R1BQKBNR b KQkq -
2 Nb1-c3 5708064: rnbqkbnr/pppppppp/8/8/8/2N5/PPPPPPPP/R1BQKBNR b KQkq -
3 Ng1-f3 5723523: rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R b KQkq -
4 Ng1-h3 4877234: rnbqkbnr/pppppppp/8/8/8/7N/PPPPPPPP/RNBQKB1R b KQkq -
5 a2-a3 4463267: rnbqkbnr/pppppppp/8/8/8/P7/1PPPPPPP/RNBQKBNR b KQkq -
6 b2-b3 5310358: rnbqkbnr/pppppppp/8/8/8/1P6/P1PPPPPP/RNBQKBNR b KQkq -
7 c2-c3 5417640: rnbqkbnr/pppppppp/8/8/8/2P5/PP1PPPPP/RNBQKBNR b KQkq -
8 d2-d3 8073082: rnbqkbnr/pppppppp/8/8/8/3P4/PPP1PPPP/RNBQKBNR b KQkq -
9 e2-e3 9726018: rnbqkbnr/pppppppp/8/8/8/4P3/PPPP1PPP/RNBQKBNR b KQkq -
10 f2-f3 4404141: rnbqkbnr/pppppppp/8/8/8/5P2/PPPPP1PP/RNBQKBNR b KQkq -
11 g2-g3 5346260: rnbqkbnr/pppppppp/8/8/8/6P1/PPPPPP1P/RNBQKBNR b KQkq -
12 h2-h3 4463070: rnbqkbnr/pppppppp/8/8/8/7P/PPPPPPP1/RNBQKBNR b KQkq -
13 a2-a4 5363555: rnbqkbnr/pppppppp/8/8/P7/8/1PPPPPPP/RNBQKBNR b KQkq -
14 b2-b4 5293555: rnbqkbnr/pppppppp/8/8/1P6/8/P1PPPPPP/RNBQKBNR b KQkq -
15 c2-c4 5866666: rnbqkbnr/pppppppp/8/8/2P5/8/PP1PPPPP/RNBQKBNR b KQkq -
16 d2-d4 8879566: rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq -
17 e2-e4 9771632: rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq -
18 f2-f4 4890429: rnbqkbnr/pppppppp/8/8/5P2/8/PPPPP1PP/RNBQKBNR b KQkq -
19 g2-g4 5239875: rnbqkbnr/pppppppp/8/8/6P1/8/PPPPPP1P/RNBQKBNR b KQkq -
20 h2-h4 5385554: rnbqkbnr/pppppppp/8/8/7P/8/PPPPPPP1/RNBQKBNR b KQkq -
Time elapsed: 3.39200 seconds
Total leaf nodes: 119060324
35.1M LNPS
You can simply copy/pase the FEN of the wrong branch in both your engine and your reference and do a perft(N-1). Very easy, since you reach the node causing problems with very few steps.
xmas79 wrote:I've found outputting the corresponding FEN a better help in move gen test:
[...]
You can simply copy/pase the FEN of the wrong branch in both your engine and your reference and do a perft(N-1). Very easy, since you reach the node causing problems with very few steps.
Thanks to all for the information, i'll try to convert Muller perft output, to get what i need.
The problem is that my engine have some bug that apperas only if you play from start. If i find that, for sample, perft 8 after e2e4 is bad, sometimes playing e2e4 and comparing the resulting perft 4 gives me a correct count... as if the error disappears. This happens probably because of some bad cleanup of some structure and having a full perft path can help better than a simple divide. Of course i can use other solutions and you're right, because i could generate FEN at some depth and call an external good engine, to compare any single position perft.
stegemma wrote:The problem is that my engine have some bug that apperas only if you play from start. If i find that, for sample, perft 8 after e2e4 is bad, sometimes playing e2e4 and comparing the resulting perft 4 gives me a correct count... as if the error disappears. This happens probably because of some bad cleanup of some structure and having a full perft path can help better than a simple divide. Of course i can use other solutions and you're right, because i could generate FEN at some depth and call an external good engine, to compare any single position perft.
If you do not use hash for perft, then it is not a hash bug. Your description resembles with problems in castling rights and/or en passant captures. If I am not wrong, the first O-O can be played at ply 7 (for example: e4 e5 Nf3 Nc6 Bb5 Nf6 O-O), while the first en passant capture can be played at ply 5 (for example: e4 e6 e5 f5 exf6 e.p.).
I always play out a divergent move and then compare the perft(N-1) numbers.
Note that this is not the same as setting up a position from a FEN: perft calls make/unmake, so if the bug is there it will not show up when setting up a FEN position.
I'd recommend basing the movegen validation on the set of test positions posted here: http://www.talkchess.com/forum/viewtopic.php?t=47318, it captures most problems you run into (this reminds me, I have one it didn't cover).
xmas79 wrote:I've found outputting the corresponding FEN a better help in move gen test:
[...]
You can simply copy/pase the FEN of the wrong branch in both your engine and your reference and do a perft(N-1). Very easy, since you reach the node causing problems with very few steps.
Thanks to all for the information, i'll try to convert Muller perft output, to get what i need.
The problem is that my engine have some bug that apperas only if you play from start. If i find that, for sample, perft 8 after e2e4 is bad, sometimes playing e2e4 and comparing the resulting perft 4 gives me a correct count... as if the error disappears. This happens probably because of some bad cleanup of some structure and having a full perft path can help better than a simple divide. Of course i can use other solutions and you're right, because i could generate FEN at some depth and call an external good engine, to compare any single position perft.
Sorry I don't understand: you do perft 8 (eight) and see e2e4 have wrong node count. Then you play e2e4 on the board and do a perft 4 (four)? This is clearly wrong, so I'm pretty sure I have not understand what you do.
Another useful test is to run the same perft two times in a row: perft 5 followed again by perft 5. This could catch some "board status" bugs at root level. And other common problems I saw were moves that gives checks.
Be also sure that your "board state" is consistent after each make/unmake. E.g. if you use bitboard and 8x8 boards together (as I do) then spend some time to write a function that loops the entire square board and checks if every bit in the "bitboard part" of the board is at its proper value (empty square means empty bit in every BB, a piece on a square means only one bit set in the BB corresponding to the piece on that square and others must be zero etc...), then do the reverse, starting from the BB be sure the other part of the board is consistent, ep flag, castle status, check flag, etc...
Evert wrote:I always play out a divergent move and then compare the perft(N-1) numbers.
Note that this is not the same as setting up a position from a FEN: perft calls make/unmake, so if the bug is there it will not show up when setting up a FEN position.
I'd recommend basing the movegen validation on the set of test positions posted here: http://www.talkchess.com/forum/viewtopic.php?t=47318, it captures most problems you run into (this reminds me, I have one it didn't cover).
Sorry I don't understand. If I do perft 5 and see node count mismatch for a move then something is wrong for that branch. Then I load the FEN, and do a perft 4, and node count is perfect. I already have found the critical node (the root), found the move that goes wrong (see later), and can say the bug is in make/unmake because:
1) the last move preceding the one with wrong counter produced some nasty effect on the status of the current node (bug in unmake)
2) the move with wrong counters is the wrong one (bug in make)