summaryrefslogtreecommitdiff
path: root/gnu/games/chess/move.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/games/chess/move.c')
-rw-r--r--gnu/games/chess/move.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/gnu/games/chess/move.c b/gnu/games/chess/move.c
new file mode 100644
index 00000000000..59aea96192d
--- /dev/null
+++ b/gnu/games/chess/move.c
@@ -0,0 +1,361 @@
+#ifndef lint
+static char rcsid[] = "$Id: move.c,v 1.1 1995/10/18 08:41:11 deraadt Exp $";
+#endif /* not lint */
+
+/* move generator hes@log-sv.se 890318
+ Modified: 890606 NEWMOVE Levels 1-6 for easier debugging */
+#include "move.h"
+#include "gnuchess.h"
+
+short distdata[64][64];
+short taxidata[64][64];
+
+void Initialize_dist() {
+register short a,b,d,di;
+
+ /* init taxi and dist data */
+ for(a=0;a<64;a++)
+ for(b=0;b<64;b++) {
+ d = abs(column[a]-column[b]);
+ di = abs(row[a]-row[b]);
+ taxidata[a][b] = d + di;
+ distdata[a][b] = (d > di ? d : di);
+ };
+}
+
+#if (NEWMOVE > 1)
+struct sqdata posdata[3][8][64][64];
+
+static short direc[8][8] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* no_piece = 0 */
+ -10,-11, -9, 0, 0, 0, 0, 0, /* wpawn = 1 */
+ -21,-19,-12, -8, 21, 19, 12, 8, /* knight = 2 */
+ -11, -9, 11, 9, 0, 0, 0, 0, /* bishop = 3 */
+ -10, -1, 10, 1, 0, 0, 0, 0, /* rook = 4 */
+ -11, -9,-10, -1, 11, 9, 10, 1, /* queen = 5 */
+ -11, -9,-10, -1, 11, 9, 10, 1, /* king = 6 */
+ 0, 0, 0, 0, 0, 0, 0, 0};/* no_piece = 7 */
+
+static short dc[3] = {-1,1,0};
+
+static short max_steps [8] = {0,2,1,7,7,7,1,0};
+
+static short unmap[120] = {
+ -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, 8, 9,10,11,12,13,14,15,-1,
+ -1,16,17,18,19,20,21,22,23,-1,
+ -1,24,25,26,27,28,29,30,31,-1,
+ -1,32,33,34,35,36,37,38,39,-1,
+ -1,40,41,42,43,44,45,46,47,-1,
+ -1,48,49,50,51,52,53,54,55,-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};
+
+void Initialize_moves() {
+ short c,ptyp,po,p0,d,di,s;
+ struct sqdata *p;
+ short dest[8][8];
+ short steps[8];
+ short sorted[8];
+
+ /* init posdata */
+ for(c=0;c<3;c++)
+ for(ptyp=0;ptyp<8;ptyp++)
+ for(po=0;po<64;po++)
+ for(p0=0;p0<64;p0++) {
+ posdata[c][ptyp][po][p0].nextpos = po;
+ posdata[c][ptyp][po][p0].nextdir = po;
+ };
+ /* dest is a function of dir and step */
+ for(c=0;c<2;c++)
+ for(ptyp=1;ptyp<7;ptyp++)
+ for(po=21;po<99;po++)
+ if (unmap[po] >= 0) {
+ p = posdata[c][ptyp][unmap[po]];
+ for(d=0;d<8;d++) {
+ dest[d][0] = unmap[po];
+ if (dc[c]*direc[ptyp][d] != 0) {
+ p0=po;
+ for(s=0;s<max_steps[ptyp];s++) {
+ p0 = p0 + dc[c]*direc[ptyp][d];
+ /* break if (off board) or
+ (pawns move two steps from home square) */
+ if (unmap[p0] < 0 ||
+ (ptyp == pawn && s>0 && (d>0 || Stboard[unmap[po]] != ptyp)))
+ break;
+ else
+ dest[d][s] = unmap[p0];
+ }
+ }
+ else s=0;
+ /* sort dest in number of steps order */
+ steps[d] = s;
+ for(di=d;di>0;di--)
+ if (steps[sorted[di-1]] < s)
+ sorted[di] = sorted[di-1];
+ else
+ break;
+ sorted[di] = d;
+ }
+ /* update posdata, pawns have two threads (capture and no capture) */
+ p0=unmap[po];
+ if (ptyp == pawn) {
+ for(s=0;s<steps[0];s++) {
+ p[p0].nextpos = dest[0][s];
+ p0 = dest[0][s];
+ }
+ p0=unmap[po];
+ for(d=1;d<3;d++) {
+ p[p0].nextdir = dest[d][0];
+ p0 = dest[d][0];
+ }
+ }
+ else {
+ p[p0].nextdir = dest[sorted[0]][0];
+ for(d=0;d<8;d++)
+ for(s=0;s<steps[sorted[d]];s++) {
+ p[p0].nextpos = dest[sorted[d]][s];
+ p0 = dest[sorted[d]][s];
+ if (d < 7)
+ p[p0].nextdir = dest[sorted[d+1]][0];
+ /* else is already initialised */
+ }
+ }
+#ifdef DEBUG
+ printf("Ptyp:%d Position:%d\n{",ptyp,unmap[po]);
+ for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextpos);
+ printf("%d};\n",p[63].nextpos);
+ for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextdir);
+ printf("%d};\n",p[63].nextdir);
+#endif DEBUG
+ }
+}
+#endif
+
+
+#if (NEWMOVE > 2)
+int SqAtakd(sq,side)
+short sq,side;
+
+/*
+ See if any piece with color 'side' ataks sq. First check pawns
+ Then Queen, Bishop, Rook and King and last Knight.
+*/
+
+{
+ register short u;
+ register struct sqdata *p;
+
+ p = posdata[1-side][pawn][sq];
+ u = p[sq].nextdir; /* follow captures thread */
+ while (u != sq) {
+ if (board[u] == pawn && color[u] == side) return(true);
+ u = p[u].nextdir;
+ }
+ /* king capture */
+ if (distance(sq,PieceList[side][0]) == 1) return(true);
+ /* try a queen bishop capture */
+ p = posdata[side][bishop][sq];
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == side &&
+ (board[u] == queen || board[u] == bishop))
+ return(true);
+ u = p[u].nextdir;
+ }
+ }
+ /* try a queen rook capture */
+ p = posdata[side][rook][sq];
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == side &&
+ (board[u] == queen || board[u] == rook))
+ return(true);
+ u = p[u].nextdir;
+ }
+ }
+ /* try a knight capture */
+ p = posdata[side][knight][sq];
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == side && board[u] == knight) return(true);
+ u = p[u].nextdir;
+ }
+ }
+ return(false);
+}
+#endif
+
+#if (NEWMOVE > 3)
+BRscan(sq,s,mob)
+short sq,*s,*mob;
+/*
+ Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
+ hung[] array if a pin is found.
+*/
+{
+ register short u,piece,pin;
+ register struct sqdata *p;
+ short *Kf;
+
+ Kf = Kfield[c1];
+ *mob = 0;
+ piece = board[sq];
+ p = posdata[color[sq]][piece][sq];
+ u = p[sq].nextpos;
+ pin = -1; /* start new direction */
+ while (u != sq) {
+ *s += Kf[u];
+ if (color[u] == neutral) {
+ (*mob)++;
+ if (p[u].nextpos == p[u].nextdir) pin = -1; /* oops new direction */
+ u = p[u].nextpos;
+ }
+ else if (pin < 0) {
+ if (board[u] == pawn || board[u] == king)
+ u = p[u].nextdir;
+ else {
+ if (p[u].nextpos != p[u].nextdir)
+ pin = u; /* not on the edge and on to find a pin */
+ u = p[u].nextpos;
+ }
+ }
+ else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
+ {
+ if (color[pin] == c2)
+ {
+ *s += PINVAL;
+ if (atk2[pin] == 0 ||
+ atk1[pin] > control[board[pin]]+1)
+ ++hung[c2];
+ }
+ else *s += XRAY;
+ pin = -1; /* new direction */
+ u = p[u].nextdir;
+ }
+ else {
+ pin = -1; /* new direction */
+ u = p[u].nextdir;
+ }
+ }
+}
+#endif
+
+#if (NEWMOVE >= 5)
+CaptureList(side,xside,ply)
+short side,xside,ply;
+{
+ register short u,sq;
+ register struct sqdata *p;
+ short i,piece,*PL;
+ struct leaf *node;
+
+ TrPnt[ply+1] = TrPnt[ply];
+ node = &Tree[TrPnt[ply]];
+ PL = PieceList[side];
+ for (i = 0; i <= PieceCnt[side]; i++)
+ {
+ sq = PL[i];
+ piece = board[sq];
+ p = posdata[side][piece][sq];
+ if (piece == pawn) {
+ u = p[sq].nextdir; /* follow captures thread */
+ while (u != sq) {
+ if (color[u] == xside) {
+ node->f = sq; node->t = u;
+ node->flags = capture;
+ if (u < 8 || u > 55)
+ {
+ node->flags |= promote;
+ node->score = valueQ;
+ }
+ else
+ node->score = value[board[u]] + svalue[board[u]] - piece;
+ ++node;
+ ++TrPnt[ply+1];
+ }
+ u = p[u].nextdir;
+ }
+ }
+ else {
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral)
+ u = p[u].nextpos;
+ else {
+ if (color[u] == xside) {
+ node->f = sq; node->t = u;
+ node->flags = capture;
+ node->score = value[board[u]] + svalue[board[u]] - piece;
+ ++node;
+ ++TrPnt[ply+1];
+ }
+ u = p[u].nextdir;
+ }
+ }
+ }
+ }
+}
+#endif
+
+#if (NEWMOVE > 5)
+GenMoves(ply,sq,side,xside)
+ short ply,sq,side,xside;
+
+/*
+ Generate moves for a piece. The moves are taken from the
+ precalulated array posdata. If the board is free, next move
+ is choosen from nextpos else from nextdir.
+*/
+
+{
+ register short u,piece;
+ register struct sqdata *p;
+
+ piece = board[sq];
+ p = posdata[side][piece][sq];
+ if (piece == pawn) {
+ u = p[sq].nextdir; /* follow captures thread */
+ while (u != sq) {
+ if (color[u] == xside) LinkMove(ply,sq,u,xside);
+ u = p[u].nextdir;
+ }
+ u = p[sq].nextpos; /* and follow no captures thread */
+ while (u != sq) {
+ if (color[u] == neutral && (u != sq+16 || color[u-8] == neutral)
+ && (u != sq-16 || color[u+8] == neutral)) {
+ LinkMove(ply,sq,u,xside);
+ }
+ u = p[u].nextpos;
+ }
+ }
+ else {
+ u = p[sq].nextpos;
+ while (u != sq) {
+ if (color[u] == neutral) {
+ LinkMove(ply,sq,u,xside);
+ u = p[u].nextpos;
+ }
+ else {
+ if (color[u] == xside) LinkMove(ply,sq,u,xside);
+ u = p[u].nextdir;
+ }
+ }
+ }
+}
+#endif