I released my own perft here:hgm wrote: So I am willing to take up the challenge: I claim I can write a capture generator that is both faster and simpler than any bitboard generator could ever be. (And maintainable! ) The question is how to measure it. Perhaps this should be done in a captures-only perft from some positions with many captures. To not contaminate the matter with issues of little relevace for the speed of an engine, we could count pseudo-legal moves. (I.e. assume moving in check is legal, and that King capture terminates the game.) As a requirement the captures should be generated in victim value order, so that staged move generation is possible. (Which would have no advantage at all in perft.)
https://github.com/abulmo/hqperft
It uses a bitboard move generator based on hyperbola quintessence & rank attacks and is largely related to my chess program amoeba. However it is written in C instead of D.
It only produce legal moves (pseudo-legal is a too blurry definition to be implemented without infinite debates).
Here is the help describing its possibilities.
Code: Select all
HQPerft (c) Richard Delorme - 2017
Bitboard move generation based on (H)yperbola (Q)uintessence & rank attacks
hqperft [--fen|-f <fen>] [--depth|-d <depth>] [--hash|-H <size>] [--bulk|-b] [--div] [--capture] [--help|-h]
Enumerate moves.
--help|-h Print this message.
--fen|-f <fen> Test the position indicated in FEN format (default=starting position).
--depth|-d <depth> Test up to this depth (default=6).
--bulk|-b Do fast bulk counting at the last ply.
--hash|-H <size> Use a hashtable with <size> bits entries (default 0, no hashtable).
--capture|-c Generate only captures.
--loop|-l Loop from depth 1 to <depth>.
--div|-r Print a node count for each move.
Code: Select all
$ hqperft -d 7 -b
HQPerft (c) Richard Delorme - 2017
Bitboard move generation based on (H)yperbola (Q)uintessence & range attacks
Perft setting: no hashing; with bulk counting;
a b c d e f g h
8 r n b q k b n r 8
7 p p p p p p p p 7
6 . . . . . . . . 6
5 . . . . . . . . 5
4 . . . . . . . . 4
3 . . . . . . . . 3
2 P P P P P P P P 2
1 R N B Q K B N R 1
a b c d e f g h
w, KQkq
perft 7 : 3195901860 leaves in 12.197 s 262032065 leaves/s
Code: Select all
$ hqperft -d 15 -f 'rnbqkbnr/8/8/pppppppp/PPPPPPPP/8/8/RNBQKBNR w KQkq - 0 1' -c -l -b -H 29
HQPerft (c) Richard Delorme - 2017
Bitboard move generation based on (H)yperbola (Q)uintessence & rank attacks
Perft setting: hashtable size: 12288 Mbytes; with bulk counting; capture only;
a b c d e f g h
8 r n b q k b n r 8
7 . . . . . . . . 7
6 . . . . . . . . 6
5 p p p p p p p p 5
4 P P P P P P P P 4
3 . . . . . . . . 3
2 . . . . . . . . 2
1 R N B Q K B N R 1
a b c d e f g h
w, KQkq
perft 1 : 14 leaves in 0.000 s 19581066 leaves/s
perft 2 : 169 leaves in 0.000 s 48038360 leaves/s
perft 3 : 1709 leaves in 0.000 s 83881431 leaves/s
perft 4 : 14813 leaves in 0.000 s 71124697 leaves/s
perft 5 : 108742 leaves in 0.001 s 93194381 leaves/s
perft 6 : 723016 leaves in 0.006 s 129488522 leaves/s
perft 7 : 4260221 leaves in 0.021 s 203550423 leaves/s
perft 8 : 23933522 leaves in 0.075 s 318096595 leaves/s
perft 9 : 121794742 leaves in 0.229 s 531548794 leaves/s
perft 10 : 600959923 leaves in 0.643 s 935060362 leaves/s
perft 11 : 2712171201 leaves in 1.592 s 1703789119 leaves/s
perft 12 : 11886845933 leaves in 3.723 s 3192437950 leaves/s
perft 13 : 47701666802 leaves in 7.939 s 6008729387 leaves/s
perft 14 : 184019931141 leaves in 15.942 s 11543036668 leaves/s
perft 15 : 646995992152 leaves in 29.824 s 21693571576 leaves/s
total 15 : 894068404100 leaves in 62.775 s 14242533137 leaves/s
Code: Select all
make pgo
- ~30% faster
- more stable: return error messages instead of crashing.
- ~10% simpler: less line of code, less statements, smaller McCabe complexity, etc.
- more complete: can generate only captures, without bulking, etc.
- better coded (less warning from gcc).
On modern CPU, my implementation is both simple and fast. There are faster implementation, though, the fastest I know about (on CPU) having been done by Paul Byrne (gperft).