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