xref: /csrg-svn/games/chess/move.c (revision 39655)
139654Sbostic /* move generator hes@log-sv.se 890318
239654Sbostic    Modified: 890606 NEWMOVE Levels 1-6 for easier debugging */
339654Sbostic #include "move.h"
439654Sbostic #include "gnuchess.h"
539654Sbostic 
639654Sbostic short distdata[64][64];
739654Sbostic short taxidata[64][64];
839654Sbostic 
Initialize_dist()939654Sbostic void Initialize_dist() {
1039654Sbostic register short a,b,d,di;
1139654Sbostic 
1239654Sbostic   /* init taxi and dist data */
1339654Sbostic   for(a=0;a<64;a++)
1439654Sbostic     for(b=0;b<64;b++) {
1539654Sbostic       d = abs(column[a]-column[b]);
1639654Sbostic       di = abs(row[a]-row[b]);
1739654Sbostic       taxidata[a][b] = d + di;
1839654Sbostic       distdata[a][b] = (d > di ? d : di);
1939654Sbostic     };
2039654Sbostic }
2139654Sbostic 
2239654Sbostic #if (NEWMOVE > 1)
2339654Sbostic struct sqdata posdata[3][8][64][64];
2439654Sbostic 
2539654Sbostic static short direc[8][8] = {
2639654Sbostic     0,  0,  0,  0,  0,  0,  0,  0, /* no_piece = 0 */
2739654Sbostic   -10,-11, -9,  0,  0,  0,  0,  0, /* wpawn    = 1 */
2839654Sbostic   -21,-19,-12, -8, 21, 19, 12,  8, /* knight   = 2 */
2939654Sbostic   -11, -9, 11,  9,  0,  0,  0,  0, /* bishop   = 3 */
3039654Sbostic   -10, -1, 10,  1,  0,  0,  0,  0, /* rook     = 4 */
3139654Sbostic   -11, -9,-10, -1, 11,  9, 10,  1, /* queen    = 5 */
3239654Sbostic   -11, -9,-10, -1, 11,  9, 10,  1, /* king     = 6 */
3339654Sbostic     0,  0,  0,  0,  0,  0,  0,  0};/* no_piece = 7 */
3439654Sbostic 
3539654Sbostic static short dc[3] = {-1,1,0};
3639654Sbostic 
3739654Sbostic static short max_steps [8] = {0,2,1,7,7,7,1,0};
3839654Sbostic 
3939654Sbostic static short unmap[120] = {
4039654Sbostic   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
4139654Sbostic   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
4239654Sbostic   -1, 0, 1, 2, 3, 4, 5, 6, 7,-1,
4339654Sbostic   -1, 8, 9,10,11,12,13,14,15,-1,
4439654Sbostic   -1,16,17,18,19,20,21,22,23,-1,
4539654Sbostic   -1,24,25,26,27,28,29,30,31,-1,
4639654Sbostic   -1,32,33,34,35,36,37,38,39,-1,
4739654Sbostic   -1,40,41,42,43,44,45,46,47,-1,
4839654Sbostic   -1,48,49,50,51,52,53,54,55,-1,
4939654Sbostic   -1,56,57,58,59,60,61,62,63,-1,
5039654Sbostic   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
5139654Sbostic   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
5239654Sbostic 
Initialize_moves()5339654Sbostic void Initialize_moves() {
5439654Sbostic   short c,ptyp,po,p0,d,di,s;
5539654Sbostic   struct sqdata *p;
5639654Sbostic   short dest[8][8];
5739654Sbostic   short steps[8];
5839654Sbostic   short sorted[8];
5939654Sbostic 
6039654Sbostic   /* init posdata */
6139654Sbostic   for(c=0;c<3;c++)
6239654Sbostic     for(ptyp=0;ptyp<8;ptyp++)
6339654Sbostic       for(po=0;po<64;po++)
6439654Sbostic 	for(p0=0;p0<64;p0++) {
6539654Sbostic 	  posdata[c][ptyp][po][p0].nextpos = po;
6639654Sbostic 	  posdata[c][ptyp][po][p0].nextdir = po;
6739654Sbostic 	};
6839654Sbostic   /* dest is a function of dir and step */
6939654Sbostic   for(c=0;c<2;c++)
7039654Sbostic     for(ptyp=1;ptyp<7;ptyp++)
7139654Sbostic       for(po=21;po<99;po++)
7239654Sbostic 	if (unmap[po] >= 0) {
7339654Sbostic           p = posdata[c][ptyp][unmap[po]];
7439654Sbostic 	  for(d=0;d<8;d++) {
7539654Sbostic 	    dest[d][0] = unmap[po];
7639654Sbostic 	    if (dc[c]*direc[ptyp][d] != 0) {
7739654Sbostic 	      p0=po;
7839654Sbostic 	      for(s=0;s<max_steps[ptyp];s++) {
7939654Sbostic 		p0 = p0 + dc[c]*direc[ptyp][d];
8039654Sbostic 		/* break if (off board) or
8139654Sbostic 		   (pawns move two steps from home square) */
8239654Sbostic 		if (unmap[p0] < 0 ||
8339654Sbostic 		    (ptyp == pawn && s>0 && (d>0 || Stboard[unmap[po]] != ptyp)))
8439654Sbostic 		  break;
8539654Sbostic 		else
8639654Sbostic 		  dest[d][s] = unmap[p0];
8739654Sbostic 	      }
8839654Sbostic 	    }
8939654Sbostic 	    else s=0;
9039654Sbostic 	    /* sort dest in number of steps order */
9139654Sbostic 	    steps[d] = s;
9239654Sbostic 	    for(di=d;di>0;di--)
9339654Sbostic 	      if (steps[sorted[di-1]] < s)
9439654Sbostic 		sorted[di] = sorted[di-1];
9539654Sbostic 	      else
9639654Sbostic 		break;
9739654Sbostic 	    sorted[di] = d;
9839654Sbostic 	  }
9939654Sbostic 	  /* update posdata, pawns have two threads (capture and no capture) */
10039654Sbostic 	  p0=unmap[po];
10139654Sbostic 	  if (ptyp == pawn) {
10239654Sbostic 	    for(s=0;s<steps[0];s++) {
10339654Sbostic 	      p[p0].nextpos = dest[0][s];
10439654Sbostic 	      p0 = dest[0][s];
10539654Sbostic 	    }
10639654Sbostic 	    p0=unmap[po];
10739654Sbostic 	    for(d=1;d<3;d++) {
10839654Sbostic 	      p[p0].nextdir = dest[d][0];
10939654Sbostic 	      p0 = dest[d][0];
11039654Sbostic 	    }
11139654Sbostic 	  }
11239654Sbostic 	  else {
11339654Sbostic 	    p[p0].nextdir = dest[sorted[0]][0];
11439654Sbostic 	    for(d=0;d<8;d++)
11539654Sbostic 	      for(s=0;s<steps[sorted[d]];s++) {
11639654Sbostic 		p[p0].nextpos = dest[sorted[d]][s];
11739654Sbostic 		p0 = dest[sorted[d]][s];
11839654Sbostic 		if (d < 7)
11939654Sbostic 		  p[p0].nextdir = dest[sorted[d+1]][0];
12039654Sbostic 		/* else is already initialised */
12139654Sbostic 	      }
12239654Sbostic 	  }
12339654Sbostic #ifdef DEBUG
12439654Sbostic 	  printf("Ptyp:%d Position:%d\n{",ptyp,unmap[po]);
12539654Sbostic 	  for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextpos);
12639654Sbostic 	  printf("%d};\n",p[63].nextpos);
12739654Sbostic 	  for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextdir);
12839654Sbostic 	  printf("%d};\n",p[63].nextdir);
12939654Sbostic #endif DEBUG
13039654Sbostic 	}
13139654Sbostic }
13239654Sbostic #endif
13339654Sbostic 
13439654Sbostic 
13539654Sbostic #if (NEWMOVE > 2)
SqAtakd(sq,side)13639654Sbostic int SqAtakd(sq,side)
13739654Sbostic short sq,side;
13839654Sbostic 
13939654Sbostic /*
14039654Sbostic   See if any piece with color 'side' ataks sq. First check pawns
14139654Sbostic   Then Queen, Bishop, Rook and King and last Knight.
14239654Sbostic */
14339654Sbostic 
14439654Sbostic {
14539654Sbostic   register short u;
14639654Sbostic   register struct sqdata *p;
14739654Sbostic 
14839654Sbostic   p = posdata[1-side][pawn][sq];
14939654Sbostic   u = p[sq].nextdir; /* follow captures thread */
15039654Sbostic   while (u != sq) {
15139654Sbostic     if (board[u] == pawn && color[u] == side) return(true);
15239654Sbostic     u = p[u].nextdir;
15339654Sbostic   }
15439654Sbostic   /* king capture */
15539654Sbostic   if (distance(sq,PieceList[side][0]) == 1) return(true);
15639654Sbostic   /* try a queen bishop capture */
15739654Sbostic   p = posdata[side][bishop][sq];
15839654Sbostic   u = p[sq].nextpos;
15939654Sbostic   while (u != sq) {
16039654Sbostic     if (color[u] == neutral) {
16139654Sbostic       u = p[u].nextpos;
16239654Sbostic     }
16339654Sbostic     else {
16439654Sbostic       if (color[u] == side &&
16539654Sbostic 	  (board[u] == queen || board[u] == bishop))
16639654Sbostic 	return(true);
16739654Sbostic       u = p[u].nextdir;
16839654Sbostic     }
16939654Sbostic   }
17039654Sbostic   /* try a queen rook capture */
17139654Sbostic   p = posdata[side][rook][sq];
17239654Sbostic   u = p[sq].nextpos;
17339654Sbostic   while (u != sq) {
17439654Sbostic     if (color[u] == neutral) {
17539654Sbostic       u = p[u].nextpos;
17639654Sbostic     }
17739654Sbostic     else {
17839654Sbostic       if (color[u] == side &&
17939654Sbostic 	  (board[u] == queen || board[u] == rook))
18039654Sbostic 	return(true);
18139654Sbostic       u = p[u].nextdir;
18239654Sbostic     }
18339654Sbostic   }
18439654Sbostic   /* try a knight capture */
18539654Sbostic   p = posdata[side][knight][sq];
18639654Sbostic   u = p[sq].nextpos;
18739654Sbostic   while (u != sq) {
18839654Sbostic     if (color[u] == neutral) {
18939654Sbostic       u = p[u].nextpos;
19039654Sbostic     }
19139654Sbostic     else {
19239654Sbostic       if (color[u] == side && board[u] == knight) return(true);
19339654Sbostic       u = p[u].nextdir;
19439654Sbostic     }
19539654Sbostic   }
19639654Sbostic   return(false);
19739654Sbostic }
19839654Sbostic #endif
19939654Sbostic 
20039654Sbostic #if (NEWMOVE > 3)
BRscan(sq,s,mob)20139654Sbostic BRscan(sq,s,mob)
20239654Sbostic short sq,*s,*mob;
20339654Sbostic /*
20439654Sbostic    Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
20539654Sbostic    hung[] array if a pin is found.
20639654Sbostic */
20739654Sbostic {
20839654Sbostic   register short u,piece,pin;
20939654Sbostic   register struct sqdata *p;
21039654Sbostic   short *Kf;
21139654Sbostic 
21239654Sbostic   Kf = Kfield[c1];
21339654Sbostic   *mob = 0;
21439654Sbostic   piece = board[sq];
21539654Sbostic   p = posdata[color[sq]][piece][sq];
21639654Sbostic   u = p[sq].nextpos;
21739654Sbostic   pin = -1; /* start new direction */
21839654Sbostic   while (u != sq) {
21939654Sbostic     *s += Kf[u];
22039654Sbostic     if (color[u] == neutral) {
22139654Sbostic       (*mob)++;
22239654Sbostic       if (p[u].nextpos == p[u].nextdir) pin = -1; /* oops new direction */
22339654Sbostic       u = p[u].nextpos;
22439654Sbostic     }
22539654Sbostic     else if (pin < 0) {
22639654Sbostic       if (board[u] == pawn || board[u] == king)
22739654Sbostic 	u = p[u].nextdir;
22839654Sbostic       else {
22939654Sbostic 	if (p[u].nextpos != p[u].nextdir)
23039654Sbostic 	  pin = u; /* not on the edge and on to find a pin */
23139654Sbostic 	u = p[u].nextpos;
23239654Sbostic       }
23339654Sbostic     }
23439654Sbostic     else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
23539654Sbostic       {
23639654Sbostic 	if (color[pin] == c2)
23739654Sbostic 	  {
23839654Sbostic 	    *s += PINVAL;
23939654Sbostic 	    if (atk2[pin] == 0 ||
24039654Sbostic 		atk1[pin] > control[board[pin]]+1)
24139654Sbostic 	      ++hung[c2];
24239654Sbostic 	  }
24339654Sbostic 	else *s += XRAY;
24439654Sbostic 	pin = -1; /* new direction */
24539654Sbostic 	u = p[u].nextdir;
24639654Sbostic       }
24739654Sbostic     else {
24839654Sbostic       pin = -1; /* new direction */
24939654Sbostic       u = p[u].nextdir;
25039654Sbostic     }
25139654Sbostic   }
25239654Sbostic }
25339654Sbostic #endif
25439654Sbostic 
25539654Sbostic #if (NEWMOVE >= 5)
CaptureList(side,xside,ply)25639654Sbostic CaptureList(side,xside,ply)
25739654Sbostic short side,xside,ply;
25839654Sbostic {
25939654Sbostic   register short u,sq;
26039654Sbostic   register struct sqdata *p;
26139654Sbostic   short i,piece,*PL;
26239654Sbostic   struct leaf *node;
26339654Sbostic 
26439654Sbostic   TrPnt[ply+1] = TrPnt[ply];
26539654Sbostic   node = &Tree[TrPnt[ply]];
26639654Sbostic   PL = PieceList[side];
26739654Sbostic   for (i = 0; i <= PieceCnt[side]; i++)
26839654Sbostic     {
26939654Sbostic       sq = PL[i];
27039654Sbostic       piece = board[sq];
27139654Sbostic       p = posdata[side][piece][sq];
27239654Sbostic       if (piece == pawn) {
27339654Sbostic 	u = p[sq].nextdir; /* follow captures thread */
27439654Sbostic 	while (u != sq) {
27539654Sbostic 	  if (color[u] == xside) {
27639654Sbostic             node->f = sq; node->t = u;
27739654Sbostic             node->flags = capture;
27839654Sbostic             if (u < 8 || u > 55)
27939654Sbostic               {
28039654Sbostic                 node->flags |= promote;
28139654Sbostic                 node->score = valueQ;
28239654Sbostic               }
28339654Sbostic 	    else
28439654Sbostic               node->score = value[board[u]] + svalue[board[u]] - piece;
28539654Sbostic             ++node;
28639654Sbostic             ++TrPnt[ply+1];
28739654Sbostic            }
28839654Sbostic 	  u = p[u].nextdir;
28939654Sbostic 	}
29039654Sbostic       }
29139654Sbostic       else {
29239654Sbostic 	u = p[sq].nextpos;
29339654Sbostic 	while (u != sq) {
29439654Sbostic           if (color[u] == neutral)
29539654Sbostic           u = p[u].nextpos;
29639654Sbostic           else {
29739654Sbostic           if (color[u] == xside) {
29839654Sbostic               node->f = sq; node->t = u;
29939654Sbostic               node->flags = capture;
30039654Sbostic               node->score = value[board[u]] + svalue[board[u]] - piece;
30139654Sbostic               ++node;
30239654Sbostic               ++TrPnt[ply+1];
30339654Sbostic              }
30439654Sbostic 	   u = p[u].nextdir;
30539654Sbostic 	 }
30639654Sbostic        }
30739654Sbostic      }
30839654Sbostic    }
30939654Sbostic }
31039654Sbostic #endif
31139654Sbostic 
31239654Sbostic #if (NEWMOVE > 5)
GenMoves(ply,sq,side,xside)31339654Sbostic GenMoves(ply,sq,side,xside)
31439654Sbostic      short ply,sq,side,xside;
315*39655Sbostic 
31639654Sbostic /*
31739654Sbostic   Generate moves for a piece. The moves are taken from the
31839654Sbostic   precalulated array posdata. If the board is free, next move
31939654Sbostic   is choosen from nextpos else from nextdir.
32039654Sbostic */
321*39655Sbostic 
32239654Sbostic {
32339654Sbostic   register short u,piece;
32439654Sbostic   register struct sqdata *p;
325*39655Sbostic 
32639654Sbostic   piece = board[sq];
32739654Sbostic   p = posdata[side][piece][sq];
32839654Sbostic   if (piece == pawn) {
32939654Sbostic     u = p[sq].nextdir; /* follow captures thread */
33039654Sbostic     while (u != sq) {
33139654Sbostic       if (color[u] == xside) LinkMove(ply,sq,u,xside);
33239654Sbostic       u = p[u].nextdir;
33339654Sbostic     }
33439654Sbostic     u = p[sq].nextpos; /* and follow no captures thread */
33539654Sbostic     while (u != sq) {
336*39655Sbostic       if (color[u] == neutral && (u != sq+16 || color[u-8] == neutral)
337*39655Sbostic           && (u != sq-16 || color[u+8] == neutral)) {
338*39655Sbostic         LinkMove(ply,sq,u,xside);
339*39655Sbostic       }
34039654Sbostic       u = p[u].nextpos;
34139654Sbostic     }
342*39655Sbostic   }
34339654Sbostic   else {
34439654Sbostic     u = p[sq].nextpos;
34539654Sbostic     while (u != sq) {
34639654Sbostic       if (color[u] == neutral) {
347*39655Sbostic         LinkMove(ply,sq,u,xside);
348*39655Sbostic         u = p[u].nextpos;
34939654Sbostic       }
35039654Sbostic       else {
351*39655Sbostic         if (color[u] == xside) LinkMove(ply,sq,u,xside);
35239654Sbostic 	u = p[u].nextdir;
35339654Sbostic       }
35439654Sbostic     }
355*39655Sbostic   }
356*39655Sbostic }
35739654Sbostic #endif
358