You really should ship an email you know.
But here is the latest revision of gpl.c. An earlier version i shipped to Stallman to include in gnuchess 6 at the time.
I'll post after that what i do since 2005 in diepsnel.c a fast chessprogram getting 2.5 million nps. It's just a small change.
Please note the code below is for 32 bits compiles. It is at x64 FASTER to use 'unsigned int' and 'unsigned char' everywhere instead of 'int' which is signed.
Gerd can explain all this.
Also note the way how the moves are in this code. You also can do things the crafty way there and just
*move++ = ... ;
In Diep a move exists out of 2 integers, which is not as fast obviously as using 1, yet that 2.5 mln nps beancounter (at a K7 2.1Ghz and that's without PGO in fact) is compatible with Diep, which slows it tad down obviously. Also as you see i already assign scores to moves while generating, so then you just pick the highest score and play that move first. It removes at least 1 slow loop for the SEE during search.
This is a search optimized move generator in fact. So it's not meant to be used for stuff like perft obviously.
Code: Select all
/*
Gnu public license here.
See copy of it at FSF (free software foundation)
*/
const int
nunmap[144] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, -1, -1,
-1, -1, 8, 9, 10, 11, 12, 13, 14, 15, -1, -1,
-1, -1, 16, 17, 18, 19, 20, 21, 22, 23, -1, -1,
-1, -1, 24, 25, 26, 27, 28, 29, 30, 31, -1, -1,
-1, -1, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1,
-1, -1, 40, 41, 42, 43, 44, 45, 46, 47, -1, -1,
-1, -1, 48, 49, 50, 51, 52, 53, 54, 55, -1, -1,
-1, -1, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
int
color[64], // having 0 = white, 1 = black, 2 = neutral
board[64], // having 0 = empty, pawn=1,knight=2,bishop=3,rook=4,queen=5,king=6
snelbord[64], // for white same as board[64], for black same as white but with a +8 for each piece
// like whitepawn = 1, blackpawn = 9
gentable[3][64][128], //* 24k loper, toren, dame *
iskippos[64][64], /* l t d */
ipiecepos[7][64][32], /* 0 = witte pion, 1 = zwarte pion, 2 = knight ... 6 = koning */
ipawndir[2][64][4]; /* slagzetten */
void QuickFullMoveList(int side,struct Move *EP) {
/* Generate semi-legal moves in fast manner
*/
int to,xside,*psq,sq,*t;
xside = side^1;
to = EP->zet&63;
if( board[to] == pawn ) { /* for enpassant */
int from = (EP->zet>>6)&63;
if( to-from == 16 || from-to == 16 ) {
int f,*w,u;
f = (to+from)>>1;
w = ipawndir[xside][f];
u = *w++;
if( color[u] == side && board[u] == pawn ) {
genindex->score = 1000;
QuickLink((u<<6)|f|move_captures|move_enpassant);
}
if( (u=*w) != 128 && color[u] == side && board[u] == pawn ) {
genindex->score = 1000;
QuickLink((u<<6)|f|move_captures|move_enpassant);
}
}
}
if( !castld[side] ) {
int u = PieceList[side][0];
if( quickcastle(side,u,u+2) ) {
genindex->score = 0;
QuickLink((u<<6)|(u+2)|move_castles);
}
if( quickcastle(side,u,u-2) ) {
genindex->score = 0;
QuickLink((u<<6)|(u-2)|move_castles);
}
}
t = cancapside[side];
psq = &quickpiecelist[side][12]; /* Q R B */
while( (sq=*psq++) != 128 ) {
int SRsq = (sq<<6);
int piece = board[sq];
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 ) {
genindex->score = pvals[p1];
QuickLink(SRsq|u|t[p1]);
}
} while( (u=*v++) != 128 );
}
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) {
genindex->score = 0;
QuickLink(SRsq|u);
if( (u=*v) != 128 && color[u] == neutral ) { /* indien u == sq dan false */
genindex->score = 0;
QuickLink(SRsq|u);
}
}
u = *w++;
if( color[u] == xside ) { /* ppos bevat geen 100, maar sq. */
genindex->score = pvals[snelbord[u]];
QuickLink(SRsq|u|move_captures);
}
if( (u=*w) != 128 && color[u] == xside ) { /* zelf ben je per definitie side */
genindex->score = pvals[snelbord[u]];
QuickLink(SRsq|u|move_captures);
}
}
else {
if( color[u] == neutral) {
genindex->score = pvals[queen];
QuickLink(SRsq|u|move_pqueen);
genindex->score = 0;
QuickLink(SRsq|u|move_pknight);
genindex->score = 0;
QuickLink(SRsq|u|move_prook);
genindex->score = 0;
QuickLink(SRsq|u|move_pbishop);
}
u = *w++;
if( color[u] == xside) {/* captures */
genindex->score = pvals[queen];
QuickLink(SRsq|u|move_captures|move_pqueen);
genindex->score = 0;
QuickLink(SRsq|u|move_captures|move_pknight);
genindex->score = 0;
QuickLink(SRsq|u|move_captures|move_prook);
genindex->score = 0;
QuickLink(SRsq|u|move_captures|move_pbishop);
}
if( (u=*w) != 128 && color[u] == xside) {
genindex->score = pvals[queen];
QuickLink(SRsq|u|move_captures|move_pqueen);
genindex->score = 0;
QuickLink(SRsq|u|move_captures|move_pknight);
genindex->score = 0;
QuickLink(SRsq|u|move_captures|move_prook);
genindex->score = 0;
QuickLink(SRsq|u|move_captures|move_pbishop);
}
}
}
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 ) {
genindex->score = pvals[p1];
QuickLink(SRsq|u|t[p1]);
}
} while( (u=*v++) != 128 );
}
} /* End QuickFullMoveList() */
void InitGens(void) {
/* vul tabellen voor een 8x8 bord */
int
paardspring[8] = {15,-15,17,-17,6,-6,10,-10},
koningvlucht[8] = {7,-7,9,-9,8,-8,1,-1},
alldirec[3][8] = { /* delta richtingen op een 8x8 bord */
{7,-7,9,-9,0,0,0,0},
{8,-8,1,-1,0,0,0,0},
{7,-7,9,-9,8,-8,1,-1}
},
nsq,sq,flag,i,j,next_sq,rij,piece,np,lijn,m,ms,c,t,old_sq,
skipm[16],
rij8[2] = {7,0},
rij2[2] = {1,6},
slalinks[2] = {7,-9},
slarechts[2] = {9,-7},
veuren[2] = {8,-8},
/* 12x12 bord delta-coordinaten */
numberpiece[3] = {bishop,rook,queen},
numberfields[3] = {4,4,8},
direc[3][10] = { /* richtingen op een 12x12 bord */
{11,-11,13,-13,0,0,0,0,0,0}, /* loper */
{12,-12,1 ,-1 ,0,0,0,0,0,0}, /* toren */
{11,-11,13,-13,12,-12,1 ,-1,0,0} /* dame */
},
vlucht[8] = {11,-11,13,-13,12,-12,1 ,-1}, /* koning */
spring[8] = {23,-23,25,-25,10,-10,14,-14};/* paard */
for( sq = 0 ; sq < 64 ; sq++ )
for( m = 0 ; m < 64 ; m++ )
iskippos[sq][m] = 0;
for( i = 0 ; i < 7 ; i++ ) /* default value */
for( sq = 0 ; sq < 64 ; sq++ )
for( m = 0 ; m < 32 ; m++ )
ipiecepos[i][sq][m] = 128;
/* pionnen */
for( sq = 0 ; sq < 64 ; sq++ ) {
lijn = sq&7;
rij = sq/8;
nsq = 26 + rij*12 + lijn;
for( c = white ; c <= black ; c++ ) { /* pion: wit en zwart */
if( rij == rij8[c] )
ipawndir[c][sq][0] = 128;
else {
m = 0;
if( lijn != 7 ) {
ipawndir[c][sq][m] = (sq+slarechts[c]);
m++;
}
if( lijn != 0 ) {
ipawndir[c][sq][m] = (sq+slalinks[c]);
m++;
}
ipawndir[c][sq][m] = 128;
m = 0;
ipiecepos[c][sq][m] = (sq+veuren[c]);
m++;
if( rij == rij2[c] )
ipiecepos[c][sq][m] = (sq+2*veuren[c]);
}
}
m = 0;
old_sq = sq;
for( i = 0; i < 8; i++ ) {/* paard */
t = nsq+spring[i];
if( nunmap[t] >= 0 ) {
ipiecepos[knight][sq][m] = nunmap[t];
m++;
old_sq = nunmap[t];
}
}
ipiecepos[knight][sq][m] = 128;
m = 0;
old_sq = sq;
for( i = 0; i < 8; i++ ) { /* koning */
t = nsq+vlucht[i];
if( nunmap[t] >= 0 ) {
ipiecepos[king][sq][m] = nunmap[t];
m++;
old_sq = nunmap[t];
}
}
ipiecepos[king][sq][m] = 128;
for( np = 0 ; np < 3 ; np++ ) { /* loper,toren,dame */
piece = numberpiece[np];
m = 0;
ms = 0;
flag = 0;
j = 0;
while( nunmap[nsq+direc[np][j]] == -1 )
j++;
for( i = 0; i < numberfields[np]; i++ ) { /* voor alle richtingen */
int sqdone=0;
t = nsq;
t = t+direc[np][i];
j = i+1;
while( nunmap[nsq+direc[np][j]] == -1 )
j++;
next_sq = nunmap[nsq+direc[np][j]];
while( nunmap[t] != -1 ) {
sqdone++;
ipiecepos[piece][sq][m] = nunmap[t];
m++;
t = t+direc[np][i];
flag = 1;
}
if( sqdone >= 2 && np <= 1 ) {
/* alleen als er bij from-to daarna nog velden af
* te gaan zijn dan is het interessant. Anders 0.
* Dame hoeft niet want toren,loper al gedaan */
int my12sq/*,yesdeze=false*/;
/* begonnen met nsq (12x12) + delta (direc[np][i])
* */
my12sq = nsq+direc[np][i];
do {
/* 8x8 bord opslaan */
sqdone--;
my12sq += direc[np][i];
} while( sqdone >= 2 );
}
if( flag ) {
flag = 0;
skipm[ms] = m;
ms++;
}
}
ipiecepos[piece][sq][m] = 128;
m = 0;
ms = 0;
t = ipiecepos[piece][sq][m];
if( np == 2 ) { /* skippos alleen voor de dame vullen dat is genoeg */
do {
iskippos[sq][t] = (skipm[ms]-m)-1;
m++;
t = ipiecepos[piece][sq][m];
if( m == skipm[ms] )
ms++;
} while( t != 128 );
}
}
}
}