|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T g
Length: 11181 (0x2bad) Types: TextFile Names: »gen.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/gnu-31mar87/chess/gen.c«
/* This file contains the move-generator for CHESS. Copyright (C) 1986 Free Software Foundation, Inc. This file is part of CHESS. CHESS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the CHESS General Public License for full details. Everyone is granted permission to copy, modify and redistribute CHESS, but only under the conditions described in the CHESS General Public License. A copy of this license is supposed to have been given to you along with CHESS so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include <stdio.h> #include "gnuchess.h" #define pseudolegal(fromval,toval) ((toval == 0) ? NORMAL : ((fromval <= 6 && fromval >= 1 && toval <= 6 && toval >= 1 ? DEFENSE : ((fromval <= 6 && fromval >= 1 && toval < 0) || (fromval < 0 && toval <= 6 && toval >= 1) ? CAPTURE : OFF)))) int attackers[10],defenders[10],natt,ndef; extern int nmoves,gentype; extern struct dirtypes pieces[MAXPC+6]; extern int pcval[MAXPC+1]; extern char *pctype[(MAXPC*2)+1]; #define addmove(bd,_from,_to,moves)\ {\ moves[nmoves].from = _from;\ moves[nmoves].to = _to;\ moves[nmoves].movpiece = bd[_from].piece;\ moves[nmoves].flags = 0;\ moves[nmoves].capcount = 0;\ if (bd[_to].piece != 0) {\ moves[nmoves].flags |= CAPFLAG;\ moves[nmoves].cappiece = bd[_to].piece;\ moves[nmoves].capcount = bd[_to].moved; /* Save move count */\ permflag = moves[nmoves].flags;\ }\ switch(bd[_from].piece) {\ case WK : if (_from == 95) switch(_to) {\ case 97 : moves[nmoves].flags |= KCASFLAG;\ break;\ case 93 : moves[nmoves].flags |= QCASFLAG;\ break;\ }\ break;\ case BK : if (_from == 25) switch(_to) {\ case 27 : moves[nmoves].flags |= KCASFLAG;\ break;\ case 23 : moves[nmoves].flags |= QCASFLAG;\ break;\ }\ break;\ case WP : if (_to < 29) {\ for (ii = WQ; ii >= WN; ii--) {\ moves[nmoves].from = _from;\ moves[nmoves].to = _to;\ moves[nmoves].movpiece = WP;\ moves[nmoves].propiece = ii;\ moves[nmoves].cappiece = bd[_to].piece;\ moves[nmoves].flags = permflag;\ moves[nmoves].flags |= PROMFLAG;\ nmoves = nmoves + 1;\ }\ nmoves = nmoves - 1;\ break;\ }\ case BP : if (_to > 90) {\ for (ii = BQ; ii <= BN; ii++) {\ moves[nmoves].from = _from;\ moves[nmoves].to = _to;\ moves[nmoves].movpiece = BP;\ moves[nmoves].propiece = ii;\ moves[nmoves].cappiece = bd[_to].piece;\ moves[nmoves].flags = permflag;\ moves[nmoves].flags |= PROMFLAG;\ nmoves = nmoves + 1;\ }\ nmoves = nmoves - 1;\ break;\ }\ }\ nmoves = nmoves + 1;\ } /* * Generate creates a move list given the current board configuration. * The move list will contain all pseudo-legal moves for the side on * move. */ int generate(bd,moves) register struct bdtype *bd; register struct mvlist *moves; { register ii, i,j,emptsq,incr,movetype,type; register rank2lo,rank2hi,pwncap1,pwncap2,pwnmov1,pwnmov2,pc,oppcol; register kingloc,krloc,qrloc,ksdest,qsdest,kingtyp,rooktyp; char permflag; nmoves = 0; if (bd[TOMOVE].moved == WHITE) { rank2lo = 80; rank2hi = 89; pwncap1 = -9; pwncap2 = -11; pwnmov1 = -10; pwnmov2 = -20; pc = WP; oppcol = BLACK; kingloc = 95; krloc = 98; qrloc = 91; ksdest = 97; qsdest = 93; kingtyp = WK; rooktyp = WR; } else { rank2lo = 30; rank2hi = 39; pwncap1 = 9; pwncap2 = 11; pwnmov1 = 10; pwnmov2 = 20; pc = BP; oppcol = WHITE; kingloc = 25; krloc = 28; qrloc = 21; ksdest = 27; qsdest = 23; kingtyp = BK; rooktyp = BR; } if (bd[kingloc].piece == kingtyp && bd[krloc].piece == rooktyp && bd[kingloc].moved == 0 && bd[krloc].moved == 0 && bd[kingloc+1].piece == EMP && bd[krloc-1].piece == EMP && !sqattacked(bd,kingloc,oppcol) && !sqattacked(bd,kingloc+1,oppcol) && !sqattacked(bd,krloc-1,oppcol)) { addmove(bd,kingloc,ksdest,moves); } if (bd[kingloc].piece == kingtyp && bd[qrloc].piece == rooktyp && bd[kingloc].moved == 0 && bd[qrloc].moved == 0 && bd[kingloc-1].piece == EMP && bd[qrloc+1].piece == EMP && bd[qrloc+2].piece == EMP && !sqattacked(bd,kingloc,oppcol) && !sqattacked(bd,kingloc-1,oppcol) && !sqattacked(bd,qrloc+1,oppcol) && !sqattacked(bd,qrloc+2,oppcol) && !sqattacked(bd,qrloc+3,oppcol)) { addmove(bd,kingloc,qsdest,moves); } for (i = 21; i <= 98; i++) if (bd[i].piece == pc) { if (COLOR(bd[i+pwncap1].piece) == oppcol) addmove(bd,i,i+pwncap1,moves); if (COLOR(bd[i+pwncap2].piece) == oppcol) addmove(bd,i,i+pwncap2,moves); emptsq = (bd[i+pwnmov1].piece == EMP); if (emptsq) { if (i > rank2lo && i < rank2hi && bd[i+pwnmov2].piece == EMP) addmove(bd,i,i+pwnmov2,moves); addmove(bd,i,i+pwnmov1,moves); } } else if (COLOR(bd[i].piece) == bd[TOMOVE].moved) { type = abs(bd[i].piece); for (j = 0; j < pieces[type].ndirs; j++) { incr = pieces[type].dirs[j]; for (;;) { movetype = pseudolegal(bd[i].piece,bd[i+incr].piece); if (movetype == NORMAL || movetype == CAPTURE) addmove(bd,i,i+incr,moves); if (!pieces[type].slide || movetype != NORMAL) break; incr += pieces[type].dirs[j]; } } } return(nmoves); } /* * sqattacked returned true if the given square on the given board * is attacked by any piece of the given color. */ sqattacked(bd,sq,attackcol) register struct bdtype *bd; { int i, j, incr, pc; /* printf("Is square %d attacked by color %d\n",sq,attackcol); */ if (attackcol == WHITE) { if (bd[sq+9].piece == WP || bd[sq+11].piece == WP) return(TRUE); } else if (attackcol == BLACK) { if (bd[sq-9].piece == BP || bd[sq-11].piece == BP) return(TRUE); } for (i = WN; i <= WK; i++) { pc = (attackcol == WHITE) ? i : -i; for (j = 0; j < pieces[i].ndirs; j++) { incr = pieces[i].dirs[j]; for (;;) { if (bd[sq+incr].piece == pc) return(TRUE); if (!pieces[i].slide || bd[sq+incr].piece != EMP) break; incr += pieces[i].dirs[j]; } } } return(FALSE); } /* * showstatic prints a list of the static exchanges that will * occur on a square during a swapoff of all pieces that attack * a piece on that square. */ showstatic(bd,sq) struct bdtype bd[120]; { printf("staticexchange at "); lin_to_alg(sq,stdout); putchar('\n'); fflush(stdout); printf(" = %d\n",staticexchange(bd,sq)); } #define addatt(val) {attackers[natt++] = val;} #define adddef(val) {defenders[ndef++] = val;} /* * showattacks prints a list of the pieces which attack the given * square on the given board. */ showattacks(bd,sq) struct bdtype bd[120]; { int i, j, incr, pc, gotone,viccol; natt = ndef = 0; viccol = COLOR(bd[sq].piece); for (i = BP+1; i <= WK; i++) { for (j = 0; j < pieces[i].ndirs; j++) { incr = pieces[i].dirs[j]; for (;;) { if (((i == BP+1) && (bd[sq+incr].piece == BP)) || ((abs(bd[sq+incr].piece) == i) && (i != BP+1) && bd[sq+incr].piece != BP)) { if (COLOR(bd[sq+incr].piece) == viccol) adddef(pcval[abs(bd[sq+incr].piece)]) else addatt(pcval[abs(bd[sq+incr].piece)]); #ifdef EXCHDEBUG printf("%s at ",(bd[sq+incr].piece < 0) ? pctype[abs(bd[sq+incr].piece)-1] : pctype[bd[sq+incr].piece+6]); lin_to_alg(sq+incr,stdout); putchar('\n'); #endif } if (!pieces[i].slide || bd[sq+incr].piece != EMP) break; incr += pieces[i].dirs[j]; } } } } /* * staticexchange actually does a full static exchange on the * given square, returning a residue representing how much * material is won or lost. */ staticexchange(bd,sq) struct bdtype bd[120]; { int attindex,defindex,prevresidue,residue,i; showattacks(bd,sq); #ifdef EXCHDEBUG printf("natt = %d, ndef = %d\n",natt,ndef); for (i = 0; i < natt; i++) printf("attackers[%d]=%d\n",i,attackers[i]); for (i = 0; i < ndef; i++) printf("defenders[%d]=%d\n",i,defenders[i]); #endif if (natt == 0) return(0); else if (ndef == 0) return(pcval[abs(bd[sq].piece)]); attindex = -1; defindex = -2; residue = 0; for (i = 1;; i++) { if (++defindex < ndef) { prevresidue = residue; if (i == 1) residue += pcval[abs(bd[sq].piece)]; else residue += defenders[defindex]; if (residue < 0) { #ifdef EXCHDEBUG printf("End Defender = %d, prevresidue = %d, residue = %d\n", i,prevresidue,residue); #endif return(MIN(MAX(prevresidue,0),pcval[abs(bd[sq].piece)])); } #ifdef EXCHDEBUG printf("Defender = %d, prevresidue = %d, residue = %d\n", i,prevresidue,residue); #endif } else break; if (++attindex < natt) { prevresidue = residue; residue -= attackers[attindex]; if (residue > pcval[abs(bd[sq].piece)]) { #ifdef EXCHDEBUG printf("End Attacker = %d, prevresidue = %d, residue = %d\n", i,prevresidue,residue); #endif return(MIN(MAX(prevresidue,0),pcval[abs(bd[sq].piece)])); } #ifdef EXCHDEBUG printf("Attacker = %d, prevresidue = %d, residue = %d\n", i,prevresidue,residue); #endif } else break; } #ifdef EXCHDEBUG printf("End Iter, prevresidue = %d, residue = %d\n", prevresidue,residue); #endif return(MIN(MAX(prevresidue,0),pcval[abs(bd[sq].piece)])); } /* * modmat looks at the material value for both sides on the * given board, and returns a value which, if added to that * material value, represents the actual material value after * static exchanges are taken into account. */ modmat(bd) struct bdtype bd[120]; { int i,movemat,movemat2,curmat2,movedmat,curmat; movemat = movemat2 = curmat2 = movedmat = curmat = 0; for (i = 21; i <= 98; i++) if (bd[i].piece != EMP && bd[i].piece != OFF) { #ifdef EXCHDEBUG printf("sq = "); lin_to_alg(i,stdout); putchar('\n'); #endif if (OPPCOLOR(COLOR(bd[i].piece)) == bd[TOMOVE].moved) { showattacks(bd,i); curmat = staticexchange(bd,i); #ifdef EXCHDEBUG printf("curmat = %d\n",curmat); #endif if (curmat > movedmat) movedmat = curmat; } else if (COLOR(bd[i].piece) == bd[TOMOVE].moved) { showattacks(bd,i); curmat2 = staticexchange(bd,i); #ifdef EXCHDEBUG printf("curmat2 = %d\n",curmat2); #endif if (curmat2 > movemat) { movemat2 = movemat; movemat = curmat2; } else if (curmat2 > movemat2) movemat2 = curmat2; } } #ifdef EXCHDEBUG printf("modmat: movedmat = %d, movemat = %d, movemat2 = %d\n", movedmat,movemat,movemat2); printf("modmat: movedmat - (.75 * movemat2) = %f\n", (float)movedmat - (.75 * (float)movemat2)); #endif return(movedmat - (.75 * movemat2)); }