Hrvoje Horvatic wrote: ↑Sun Mar 03, 2019 8:14 am
(1) This is "classical" table-based move generation, you might check chessprogramming wiki for more information... HGM correctly notices that this approach was implemented in GnuChess (version 5 was bitboard-based, so you have to look for version 4).
there are different ways of organizing data inside tables. I tried a few and it doesn't matter too much speed-wise...
(2) yes, it's fast, somewhat faster than bitboard-based approach, but only for move generation, and not as fast as you might hope... you still need other methods for other problems, like testing whether king is in check, etc.
(3) you initialize table by putting piece on a square on an empty board and enumerate all available squares for that piece... you can use bitboard attacks for that, or any other method... a few years ago Diepeveen posted a code which uses 10x12 board (actually 12x12 board) with guard squares around central 8x8 board, also an ancient trick to detect board edge... there is no problem in using 16x8 board for initialization also...
In general, you can squeeze out a few more cycles, but it's not worth the effort... unless you are looking for a new adventure in coding, in which case I can recommend it wholeheartedly...
Thanks! I just want something simple and very fast for an experiment. About 15/16 years ago I did write a 1600 elo engine named Carnivor that used the GNU chess 4 move generator, much improved though. Here is a snippet.
case BISHOP:
sbns=bns+bol[fs];
sbnd=bnd+bol[fs];
ts=*(sbns+fs);
while(ts<64)
{
switch(wtrgt[brd[ts]])
{
case VACANT:
link(MOVE);
ts=*(sbns+ts);
continue;
case FRIEND:
ts=*(sbnd+ts);
continue;
case ENEMY:
link(CAPTURE);
ts=*(sbnd+ts);
continue;
default:
return FALSE;
}
}
continue;
I also wrote a move generator in assembly in pure jump table style.
wmg: push ebp
push edi
push esi
mov ebp,[ply]
mov eax,[first+ebp*4]
mov [lis+ebp*4],eax
mov edi,[nxt]
jmp [ptmf+edi*4]
wnxtm: mov edi,[nxt+edi*4]
jmp [ptmf+edi*4]
wqm: mov ecx,[ps+edi*4]
mov esi,[qol+ecx*4]
movsx ebx,[qns+esi+ecx]
mov edx,[brd+ebx*4]
jmp [wqmf+edx*4]
wqmrm: mov [tree.fsq+eax*8],cl
mov [tree.tsq+eax*8],bl
mov [tree.typ+eax*8],QMOV
inc eax
movsx ebx,[qns+esi+ebx]
mov edx,[brd+ebx*4]
jmp [wqmf+edx*4]
wqmrc: mov [tree.fsq+eax*8],cl
mov [tree.tsq+eax*8],dl
mov [tree.typ+eax*8],QCAP
inc eax
wqmnd: movsx ebx,[qnd+esi+ebx]
mov edx,[brd+ebx*4]
jmp [wqmf+edx*4]
Stockfish x64 popcount single thread bench 6 as reference on my system.
2,004,571 nodes per second
Carnivor bench 6
41,270,402 nodes per second
Godzilla (in assembly) bench 6
75,604,183 nodes per second
I can get Godzilla to compile using Visual Studio 17 but it crashes after a few milliseconds and I can't find the error or i'd use it. It is way to huge an endeavor to rewrite and I am not happy with the large data of GNU chess 4. So I thought i'd try this modification.