1 /* move generator hes@log-sv.se 890318 2 Modified: 890606 NEWMOVE Levels 1-6 for easier debugging */ 3 #include "move.h" 4 #include "gnuchess.h" 5 6 short distdata[64][64]; 7 short taxidata[64][64]; 8 9 void Initialize_dist() { 10 register short a,b,d,di; 11 12 /* init taxi and dist data */ 13 for(a=0;a<64;a++) 14 for(b=0;b<64;b++) { 15 d = abs(column[a]-column[b]); 16 di = abs(row[a]-row[b]); 17 taxidata[a][b] = d + di; 18 distdata[a][b] = (d > di ? d : di); 19 }; 20 } 21 22 #if (NEWMOVE > 1) 23 struct sqdata posdata[3][8][64][64]; 24 25 static short direc[8][8] = { 26 0, 0, 0, 0, 0, 0, 0, 0, /* no_piece = 0 */ 27 -10,-11, -9, 0, 0, 0, 0, 0, /* wpawn = 1 */ 28 -21,-19,-12, -8, 21, 19, 12, 8, /* knight = 2 */ 29 -11, -9, 11, 9, 0, 0, 0, 0, /* bishop = 3 */ 30 -10, -1, 10, 1, 0, 0, 0, 0, /* rook = 4 */ 31 -11, -9,-10, -1, 11, 9, 10, 1, /* queen = 5 */ 32 -11, -9,-10, -1, 11, 9, 10, 1, /* king = 6 */ 33 0, 0, 0, 0, 0, 0, 0, 0};/* no_piece = 7 */ 34 35 static short dc[3] = {-1,1,0}; 36 37 static short max_steps [8] = {0,2,1,7,7,7,1,0}; 38 39 static short unmap[120] = { 40 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 41 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 42 -1, 0, 1, 2, 3, 4, 5, 6, 7,-1, 43 -1, 8, 9,10,11,12,13,14,15,-1, 44 -1,16,17,18,19,20,21,22,23,-1, 45 -1,24,25,26,27,28,29,30,31,-1, 46 -1,32,33,34,35,36,37,38,39,-1, 47 -1,40,41,42,43,44,45,46,47,-1, 48 -1,48,49,50,51,52,53,54,55,-1, 49 -1,56,57,58,59,60,61,62,63,-1, 50 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 51 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 52 53 void Initialize_moves() { 54 short c,ptyp,po,p0,d,di,s; 55 struct sqdata *p; 56 short dest[8][8]; 57 short steps[8]; 58 short sorted[8]; 59 60 /* init posdata */ 61 for(c=0;c<3;c++) 62 for(ptyp=0;ptyp<8;ptyp++) 63 for(po=0;po<64;po++) 64 for(p0=0;p0<64;p0++) { 65 posdata[c][ptyp][po][p0].nextpos = po; 66 posdata[c][ptyp][po][p0].nextdir = po; 67 }; 68 /* dest is a function of dir and step */ 69 for(c=0;c<2;c++) 70 for(ptyp=1;ptyp<7;ptyp++) 71 for(po=21;po<99;po++) 72 if (unmap[po] >= 0) { 73 p = posdata[c][ptyp][unmap[po]]; 74 for(d=0;d<8;d++) { 75 dest[d][0] = unmap[po]; 76 if (dc[c]*direc[ptyp][d] != 0) { 77 p0=po; 78 for(s=0;s<max_steps[ptyp];s++) { 79 p0 = p0 + dc[c]*direc[ptyp][d]; 80 /* break if (off board) or 81 (pawns move two steps from home square) */ 82 if (unmap[p0] < 0 || 83 (ptyp == pawn && s>0 && (d>0 || Stboard[unmap[po]] != ptyp))) 84 break; 85 else 86 dest[d][s] = unmap[p0]; 87 } 88 } 89 else s=0; 90 /* sort dest in number of steps order */ 91 steps[d] = s; 92 for(di=d;di>0;di--) 93 if (steps[sorted[di-1]] < s) 94 sorted[di] = sorted[di-1]; 95 else 96 break; 97 sorted[di] = d; 98 } 99 /* update posdata, pawns have two threads (capture and no capture) */ 100 p0=unmap[po]; 101 if (ptyp == pawn) { 102 for(s=0;s<steps[0];s++) { 103 p[p0].nextpos = dest[0][s]; 104 p0 = dest[0][s]; 105 } 106 p0=unmap[po]; 107 for(d=1;d<3;d++) { 108 p[p0].nextdir = dest[d][0]; 109 p0 = dest[d][0]; 110 } 111 } 112 else { 113 p[p0].nextdir = dest[sorted[0]][0]; 114 for(d=0;d<8;d++) 115 for(s=0;s<steps[sorted[d]];s++) { 116 p[p0].nextpos = dest[sorted[d]][s]; 117 p0 = dest[sorted[d]][s]; 118 if (d < 7) 119 p[p0].nextdir = dest[sorted[d+1]][0]; 120 /* else is already initialised */ 121 } 122 } 123 #ifdef DEBUG 124 printf("Ptyp:%d Position:%d\n{",ptyp,unmap[po]); 125 for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextpos); 126 printf("%d};\n",p[63].nextpos); 127 for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextdir); 128 printf("%d};\n",p[63].nextdir); 129 #endif DEBUG 130 } 131 } 132 #endif 133 134 135 #if (NEWMOVE > 2) 136 int SqAtakd(sq,side) 137 short sq,side; 138 139 /* 140 See if any piece with color 'side' ataks sq. First check pawns 141 Then Queen, Bishop, Rook and King and last Knight. 142 */ 143 144 { 145 register short u; 146 register struct sqdata *p; 147 148 p = posdata[1-side][pawn][sq]; 149 u = p[sq].nextdir; /* follow captures thread */ 150 while (u != sq) { 151 if (board[u] == pawn && color[u] == side) return(true); 152 u = p[u].nextdir; 153 } 154 /* king capture */ 155 if (distance(sq,PieceList[side][0]) == 1) return(true); 156 /* try a queen bishop capture */ 157 p = posdata[side][bishop][sq]; 158 u = p[sq].nextpos; 159 while (u != sq) { 160 if (color[u] == neutral) { 161 u = p[u].nextpos; 162 } 163 else { 164 if (color[u] == side && 165 (board[u] == queen || board[u] == bishop)) 166 return(true); 167 u = p[u].nextdir; 168 } 169 } 170 /* try a queen rook capture */ 171 p = posdata[side][rook][sq]; 172 u = p[sq].nextpos; 173 while (u != sq) { 174 if (color[u] == neutral) { 175 u = p[u].nextpos; 176 } 177 else { 178 if (color[u] == side && 179 (board[u] == queen || board[u] == rook)) 180 return(true); 181 u = p[u].nextdir; 182 } 183 } 184 /* try a knight capture */ 185 p = posdata[side][knight][sq]; 186 u = p[sq].nextpos; 187 while (u != sq) { 188 if (color[u] == neutral) { 189 u = p[u].nextpos; 190 } 191 else { 192 if (color[u] == side && board[u] == knight) return(true); 193 u = p[u].nextdir; 194 } 195 } 196 return(false); 197 } 198 #endif 199 200 #if (NEWMOVE > 3) 201 BRscan(sq,s,mob) 202 short sq,*s,*mob; 203 /* 204 Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the 205 hung[] array if a pin is found. 206 */ 207 { 208 register short u,piece,pin; 209 register struct sqdata *p; 210 short *Kf; 211 212 Kf = Kfield[c1]; 213 *mob = 0; 214 piece = board[sq]; 215 p = posdata[color[sq]][piece][sq]; 216 u = p[sq].nextpos; 217 pin = -1; /* start new direction */ 218 while (u != sq) { 219 *s += Kf[u]; 220 if (color[u] == neutral) { 221 (*mob)++; 222 if (p[u].nextpos == p[u].nextdir) pin = -1; /* oops new direction */ 223 u = p[u].nextpos; 224 } 225 else if (pin < 0) { 226 if (board[u] == pawn || board[u] == king) 227 u = p[u].nextdir; 228 else { 229 if (p[u].nextpos != p[u].nextdir) 230 pin = u; /* not on the edge and on to find a pin */ 231 u = p[u].nextpos; 232 } 233 } 234 else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0)) 235 { 236 if (color[pin] == c2) 237 { 238 *s += PINVAL; 239 if (atk2[pin] == 0 || 240 atk1[pin] > control[board[pin]]+1) 241 ++hung[c2]; 242 } 243 else *s += XRAY; 244 pin = -1; /* new direction */ 245 u = p[u].nextdir; 246 } 247 else { 248 pin = -1; /* new direction */ 249 u = p[u].nextdir; 250 } 251 } 252 } 253 #endif 254 255 #if (NEWMOVE >= 5) 256 CaptureList(side,xside,ply) 257 short side,xside,ply; 258 { 259 register short u,sq; 260 register struct sqdata *p; 261 short i,piece,*PL; 262 struct leaf *node; 263 264 TrPnt[ply+1] = TrPnt[ply]; 265 node = &Tree[TrPnt[ply]]; 266 PL = PieceList[side]; 267 for (i = 0; i <= PieceCnt[side]; i++) 268 { 269 sq = PL[i]; 270 piece = board[sq]; 271 p = posdata[side][piece][sq]; 272 if (piece == pawn) { 273 u = p[sq].nextdir; /* follow captures thread */ 274 while (u != sq) { 275 if (color[u] == xside) { 276 node->f = sq; node->t = u; 277 node->flags = capture; 278 if (u < 8 || u > 55) 279 { 280 node->flags |= promote; 281 node->score = valueQ; 282 } 283 else 284 node->score = value[board[u]] + svalue[board[u]] - piece; 285 ++node; 286 ++TrPnt[ply+1]; 287 } 288 u = p[u].nextdir; 289 } 290 } 291 else { 292 u = p[sq].nextpos; 293 while (u != sq) { 294 if (color[u] == neutral) 295 u = p[u].nextpos; 296 else { 297 if (color[u] == xside) { 298 node->f = sq; node->t = u; 299 node->flags = capture; 300 node->score = value[board[u]] + svalue[board[u]] - piece; 301 ++node; 302 ++TrPnt[ply+1]; 303 } 304 u = p[u].nextdir; 305 } 306 } 307 } 308 } 309 } 310 #endif 311 312 #if (NEWMOVE > 5) 313 GenMoves(ply,sq,side,xside) 314 short ply,sq,side,xside; 315 316 /* 317 Generate moves for a piece. The moves are taken from the 318 precalulated array posdata. If the board is free, next move 319 is choosen from nextpos else from nextdir. 320 */ 321 322 { 323 register short u,piece; 324 register struct sqdata *p; 325 326 piece = board[sq]; 327 p = posdata[side][piece][sq]; 328 if (piece == pawn) { 329 u = p[sq].nextdir; /* follow captures thread */ 330 while (u != sq) { 331 if (color[u] == xside) LinkMove(ply,sq,u,xside); 332 u = p[u].nextdir; 333 } 334 u = p[sq].nextpos; /* and follow no captures thread */ 335 while (u != sq) { 336 if (color[u] == neutral && (u != sq+16 || color[u-8] == neutral) 337 && (u != sq-16 || color[u+8] == neutral)) { 338 LinkMove(ply,sq,u,xside); 339 } 340 u = p[u].nextpos; 341 } 342 } 343 else { 344 u = p[sq].nextpos; 345 while (u != sq) { 346 if (color[u] == neutral) { 347 LinkMove(ply,sq,u,xside); 348 u = p[u].nextpos; 349 } 350 else { 351 if (color[u] == xside) LinkMove(ply,sq,u,xside); 352 u = p[u].nextdir; 353 } 354 } 355 } 356 } 357 #endif 358