To give you an idea how it looks like:smatovic wrote:Where to get?My move generator i open sourced a year or 10 ago.
--
Srdja
Code: Select all
#define white 0
#define black 1
#define neutral 2
#define no_piece 0 /* 0b0000 */
#define pawn 1 /* 0b0001 */
#define knight 2 /* 0b0010 */
#define bishop 3 /* 0b0011 */
#define rook 4 /* 0b0100 */
#define queen 5 /* 0b0101 */
#define king 6 /* 0b0110 */
#define bpawn 9 /* 0b1001 */
#define bknight 10 /* 0b1010 */
#define bbishop 11 /* 0b1011 */
#define brook 12 /* 0b1100 */
#define bqueen 13 /* 0b1101 */
#define bking 14 /* 0b1110 */
#define QuickLink(FFTT) {genindex->zet = FFTT;genindex++;}
// 'zet' is Dutch for 'move' in English
// the first 2 arrays are exactly like Gnuchess from John Stanback
// not to confuse with the later raped gnuchess when less talented guys
// hopped in to 'care' about gnuchess:
// 'color' has 3 values, 0,1,2 meaning white, black and neutral
// 'board' has piece values 1..6 and empty squares 0
// 'snelbord' also 'quickboard' in other engines i wrote which no longer
// have the 'board' at all nor color, yet realize at cheapskate mobile processors that having all the arrays is faster as every instruction counts
there. Even an AND is yet another instruction.
// it has piece values 1..6 and 9..14
Generating sliders: Queen Rook Bishop
Code: Select all
t = cancapside[side];
psq = &quickpiecelist[side][12]; /* Q R B */
while( (sq=*psq++) != 128 ) {
int SRsq = (sq<<6);
int piece = board[sq]; // same as 'snelbord[sq] & 7'
int *s,*v,*w,u;
s = andscan[0];
v = ipiecepos[piece][sq];
w = iskippos[sq];
u = *v++;
do {
int p1=snelbord[u],sh=w[u];
v += (s[p1]&sh);
if( ((p1-1)>>3) != side ) {
QuickLink(SRsq|u|t[p1]);
}
} while( (u=*v++) != 128 );
}
Code: Select all
psq = quickpiecelist[side]; /* K N */
while( (sq=*psq++) != 128 ) {
int SRsq = (sq<<6);
int piece = board[sq];
int u,*v;
v = ipiecepos[piece][sq];
u = *v++;
do {
int p1 = snelbord[u];
if( ((p1-1)>>3) != side ) {
QuickLink(SRsq|u|t[p1]);
}
} while( (u=*v++) != 128 );
}
Note that things are fall through optimized. I wrote the main generator doing this around 1998, in 2005 there was a small revision how pieces are in different lists. If you don't know what fall through is, please google for it, it's a big step forwards (invented by intel).
Code: Select all
psq = &quickpiecelist[side][26]; /* pawns */
while( (sq=*psq++) != 128 ) {
int SRsq = (sq<<6);
int u,*v,*w;
v = ipiecepos[side][sq];
w = ipawndir[side][sq];
u = *v++;
if( row(u) != 0 && row(u) != 7 ) {
if( color[u] == neutral) {
QuickLink(SRsq|u);
if( (u=*v) != 128 && color[u] == neutral ) { /* indien u == sq dan false */
QuickLink(SRsq|u);
}
}
u = *w++;
if( color[u] == xside ) {
QuickLink(SRsq|u|move_captures);
}
if( (u=*w) != 128 && color[u] == xside ) {
QuickLink(SRsq|u|move_captures);
}
}
else {
if( color[u] == neutral) {
QuickLink(SRsq|u|move_pqueen);
QuickLink(SRsq|u|move_pknight);
QuickLink(SRsq|u|move_prook);
QuickLink(SRsq|u|move_pbishop);
}
u = *w++;
if( color[u] == xside) {/* captures */
QuickLink(SRsq|u|move_captures|move_pqueen);
QuickLink(SRsq|u|move_captures|move_pknight);
QuickLink(SRsq|u|move_captures|move_prook);
QuickLink(SRsq|u|move_captures|move_pbishop);
}
if( (u=*w) != 128 && color[u] == xside) {
QuickLink(SRsq|u|move_captures|move_pqueen);
QuickLink(SRsq|u|move_captures|move_pknight);
QuickLink(SRsq|u|move_captures|move_prook);
QuickLink(SRsq|u|move_captures|move_pbishop);
}
}
}
The difference with the 'old diep' and this 2005 code is that i used to have all pieces in 1 list for each side. This code has QRB separated from KN and separated from the pawns. That single branch there was really EXPENSIVE. No expensive branches in the above code...
Also note the branches to link moves are short so real fast on the CPU's.