|
|
1.1 ! root 1: /* ! 2: C source for CHESS ! 3: ! 4: Revision: 4-25-88 ! 5: ! 6: Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. ! 7: Copyright (c) 1988 John Stanback ! 8: ! 9: This file is part of CHESS. ! 10: ! 11: CHESS is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY. No author or distributor ! 13: accepts responsibility to anyone for the consequences of using it ! 14: or for whether it serves any particular purpose or works at all, ! 15: unless he says so in writing. Refer to the CHESS General Public ! 16: License for full details. ! 17: ! 18: Everyone is granted permission to copy, modify and redistribute ! 19: CHESS, but only under the conditions described in the ! 20: CHESS General Public License. A copy of this license is ! 21: supposed to have been given to you along with CHESS so you ! 22: can know your rights and responsibilities. It should be in a ! 23: file named COPYING. Among other things, the copyright notice ! 24: and this notice must be preserved on all copies. ! 25: */ ! 26: ! 27: ! 28: #include <stdio.h> ! 29: #include <ctype.h> ! 30: ! 31: #ifdef MSDOS ! 32: #include <stdlib.h> ! 33: #include <time.h> ! 34: #include <alloc.h> ! 35: #define ttblsz 4096 ! 36: #else ! 37: #include <sys/param.h> ! 38: #include <sys/times.h> ! 39: #define ttblsz 16384 ! 40: #define huge ! 41: #endif MSDOS ! 42: ! 43: #include "move.h" ! 44: ! 45: #define neutral 2 ! 46: #define white 0 ! 47: #define black 1 ! 48: #define no_piece 0 ! 49: #define pawn 1 ! 50: #define knight 2 ! 51: #define bishop 3 ! 52: #define rook 4 ! 53: #define queen 5 ! 54: #define king 6 ! 55: #define valueP 100 ! 56: #define valueN 350 ! 57: #define valueB 355 ! 58: #define valueR 550 ! 59: #define valueQ 1100 ! 60: #define valueK 1200 ! 61: #define ctlP 0x4000 ! 62: #define ctlN 0x2800 ! 63: #define ctlB 0x1800 ! 64: #define ctlR 0x0400 ! 65: #define ctlQ 0x0200 ! 66: #define ctlK 0x0100 ! 67: #define ctlBQ 0x1200 ! 68: #define ctlRQ 0x0600 ! 69: #define ctlNN 0x2000 ! 70: #define pxx " PNBRQK" ! 71: #define qxx " pnbrqk" ! 72: #define rxx "12345678" ! 73: #define cxx "abcdefgh" ! 74: #define check 0x0001 ! 75: #define capture 0x0002 ! 76: #define draw 0x0004 ! 77: #define promote 0x0008 ! 78: #define cstlmask 0x0010 ! 79: #define epmask 0x0020 ! 80: #define exact 0x0040 ! 81: #define pwnthrt 0x0080 ! 82: #define truescore 0x0001 ! 83: #define lowerbound 0x0002 ! 84: #define upperbound 0x0004 ! 85: #define maxdepth 30 ! 86: #define true 1 ! 87: #define false 0 ! 88: #define absv(x) ((x) < 0 ? -(x) : (x)) ! 89: #if (NEWMOVE < 1) ! 90: #define taxicab(a,b) (abs(column[a]-column[b]) + abs(row[a]-row[b])) ! 91: #endif ! 92: struct leaf ! 93: { ! 94: short f,t,score,reply; ! 95: unsigned short flags; ! 96: }; ! 97: struct GameRec ! 98: { ! 99: unsigned short gmove; ! 100: short score,depth,time,piece,color; ! 101: long nodes; ! 102: }; ! 103: struct TimeControlRec ! 104: { ! 105: short moves[2]; ! 106: long clock[2]; ! 107: }; ! 108: struct BookEntry ! 109: { ! 110: struct BookEntry *next; ! 111: unsigned short *mv; ! 112: }; ! 113: struct hashval ! 114: { ! 115: unsigned long bd; ! 116: unsigned short key; ! 117: }; ! 118: struct hashentry ! 119: { ! 120: unsigned long hashbd; ! 121: unsigned short mv,flags; ! 122: short score,depth; ! 123: }; ! 124: ! 125: char mvstr1[5],mvstr2[5]; ! 126: struct leaf Tree[2000],*root; ! 127: short TrPnt[maxdepth],board[64],color[64]; ! 128: short row[64],column[64],locn[8][8],Pindex[64],svalue[64]; ! 129: short PieceList[2][16],PieceCnt[2],atak[2][64],PawnCnt[2][8]; ! 130: short castld[2],kingmoved[2],mtl[2],pmtl[2],emtl[2],hung[2]; ! 131: short c1,c2,*atk1,*atk2,*PC1,*PC2,EnemyKing; ! 132: short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither; ! 133: long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft; ! 134: long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt; ! 135: short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep; ! 136: short wking,bking,FROMsquare,TOsquare,timeout,Zscore,zwndw,xwndw,slk; ! 137: short INCscore; ! 138: short HasPawn[2],HasKnight[2],HasBishop[2],HasRook[2],HasQueen[2]; ! 139: short ChkFlag[maxdepth],CptrFlag[maxdepth],PawnThreat[maxdepth]; ! 140: short Pscore[maxdepth],Tscore[maxdepth],Threat[maxdepth]; ! 141: struct GameRec GameList[240]; ! 142: short GameCnt,Game50,epsquare,lpost,rcptr,contempt; ! 143: short MaxSearchDepth; ! 144: struct BookEntry *Book; ! 145: struct TimeControlRec TimeControl; ! 146: short TCflag,TCmoves,TCminutes,OperatorTime; ! 147: short otherside[3]={1,0,2}; ! 148: short rank7[3]={6,1,0}; ! 149: short map[64]= ! 150: {0,1,2,3,4,5,6,7, ! 151: 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, ! 152: 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, ! 153: 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, ! 154: 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, ! 155: 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, ! 156: 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, ! 157: 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77}; ! 158: short unmap[120]= ! 159: {0,1,2,3,4,5,6,7,-1,-1,-1,-1,-1,-1,-1,-1, ! 160: 8,9,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1, ! 161: 16,17,18,19,20,21,22,23,-1,-1,-1,-1,-1,-1,-1,-1, ! 162: 24,25,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1, ! 163: 32,33,34,35,36,37,38,39,-1,-1,-1,-1,-1,-1,-1,-1, ! 164: 40,41,42,43,44,45,46,47,-1,-1,-1,-1,-1,-1,-1,-1, ! 165: 48,49,50,51,52,53,54,55,-1,-1,-1,-1,-1,-1,-1,-1, ! 166: 56,57,58,59,60,61,62,63}; ! 167: short Dcode[120]= ! 168: {0,1,1,1,1,1,1,1,0,0,0,0,0,0,0x0E,0x0F, ! 169: 0x10,0x11,0x12,0,0,0,0,0,0,0,0,0,0,0,0x0F,0x1F, ! 170: 0x10,0x21,0x11,0,0,0,0,0,0,0,0,0,0,0x0F,0,0, ! 171: 0x10,0,0,0x11,0,0,0,0,0,0,0,0,0x0F,0,0,0, ! 172: 0x10,0,0,0,0x11,0,0,0,0,0,0,0x0F,0,0,0,0, ! 173: 0x10,0,0,0,0,0x11,0,0,0,0,0x0F,0,0,0,0,0, ! 174: 0x10,0,0,0,0,0,0x11,0,0,0x0F,0,0,0,0,0,0, ! 175: 0x10,0,0,0,0,0,0,0x11}; ! 176: short Stboard[64]= ! 177: {rook,knight,bishop,queen,king,bishop,knight,rook, ! 178: pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn, ! 179: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 180: pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn, ! 181: rook,knight,bishop,queen,king,bishop,knight,rook}; ! 182: short Stcolor[64]= ! 183: {white,white,white,white,white,white,white,white, ! 184: white,white,white,white,white,white,white,white, ! 185: 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, ! 186: black,black,black,black,black,black,black,black, ! 187: black,black,black,black,black,black,black,black}; ! 188: short sweep[7]= {false,false,false,true,true,true,false}; ! 189: short Dpwn[3]={4,6,0}; ! 190: short Dstart[7]={6,4,8,4,0,0,0}; ! 191: short Dstop[7]={7,5,15,7,3,7,7}; ! 192: short Dir[16]={1,0x10,-1,-0x10,0x0F,0x11,-0x0F,-0x11, ! 193: 0x0E,-0x0E,0x12,-0x12,0x1F,-0x1F,0x21,-0x21}; ! 194: short Pdir[34]={0,0x38,0,0,0,0,0,0,0,0,0,0,0,0,0x02,0x35, ! 195: 0x38,0x35,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0x02, ! 196: 0,0x02}; ! 197: short pbit[7]={0,0x01,0x02,0x04,0x08,0x10,0x20}; ! 198: unsigned short killr0[maxdepth],killr1[maxdepth],killr2[maxdepth]; ! 199: unsigned short killr3[maxdepth],PrVar[maxdepth]; ! 200: unsigned short PV,hint,Swag0,Swag1,Swag2,Swag3,Swag4; ! 201: unsigned short hashkey; ! 202: unsigned long hashbd; ! 203: struct hashval hashcode[2][7][64]; ! 204: struct hashentry huge *ttable,*ptbl; ! 205: unsigned char history[8192]; ! 206: ! 207: short Mwpawn[64],Mbpawn[64],Mknight[2][64],Mbishop[2][64]; ! 208: short Mking[2][64],Kfield[2][64]; ! 209: short value[7]={0,valueP,valueN,valueB,valueR,valueQ,valueK}; ! 210: short control[7]={0,ctlP,ctlN,ctlB,ctlR,ctlQ,ctlK}; ! 211: short PassedPawn0[8]={0,60,80,120,200,360,600,800}; ! 212: short PassedPawn1[8]={0,30,40,60,100,180,300,800}; ! 213: short PassedPawn2[8]={0,15,25,35,50,90,140,800}; ! 214: short PassedPawn3[8]={0,5,10,15,20,30,140,800}; ! 215: short ISOLANI[8] = {-12,-16,-20,-24,-24,-20,-16,-12}; ! 216: short BACKWARD[8] = {-6,-10,-15,-21,-28,-28,-28,-28}; ! 217: short BMBLTY[14] = {-2,0,2,4,6,8,10,12,13,14,15,16,16,16}; ! 218: short RMBLTY[14] = {0,2,4,6,8,10,11,12,13,14,14,14,14,14}; ! 219: short Kthreat[16] = {0,-8,-20,-36,-52,-68,-80,-80,-80,-80,-80,-80, ! 220: -80,-80,-80,-80}; ! 221: short KNIGHTPOST,KNIGHTSTRONG,BISHOPSTRONG,KATAK,KBNKsq; ! 222: short PEDRNK2B,PWEAKH,PADVNCM,PADVNCI,PAWNSHIELD,PDOUBLED,PBLOK; ! 223: short RHOPN,RHOPNX,KHOPN,KHOPNX,KSFTY; ! 224: short ATAKD,HUNGP,HUNGX,KCASTLD,KMOVD,XRAY,PINVAL; ! 225: short stage,stage2,Zwmtl,Zbmtl,Developed[2],PawnStorm; ! 226: short PawnBonus,BishopBonus,RookBonus; ! 227: short KingOpening[64]= ! 228: { 0, 0, -4,-10,-10, -4, 0, 0, ! 229: -4, -4, -8,-12,-12, -8, -4, -4, ! 230: -12,-16,-20,-20,-20,-20,-16,-12, ! 231: -16,-20,-24,-24,-24,-24,-20,-16, ! 232: -16,-20,-24,-24,-24,-24,-20,-16, ! 233: -12,-16,-20,-20,-20,-20,-16,-12, ! 234: -4, -4, -8,-12,-12, -8, -4, -4, ! 235: 0, 0, -4,-10,-10, -4, 0, 0}; ! 236: short KingEnding[64]= ! 237: { 0, 6,12,18,18,12, 6, 0, ! 238: 6,12,18,24,24,18,12, 6, ! 239: 12,18,24,30,30,24,18,12, ! 240: 18,24,30,36,36,30,24,18, ! 241: 18,24,30,36,36,30,24,18, ! 242: 12,18,24,30,30,24,18,12, ! 243: 6,12,18,24,24,18,12, 6, ! 244: 0, 6,12,18,18,12, 6, 0}; ! 245: short DyingKing[64]= ! 246: { 0, 8,16,24,24,16, 8, 0, ! 247: 8,32,40,48,48,40,32, 8, ! 248: 16,40,56,64,64,56,40,16, ! 249: 24,48,64,72,72,64,48,24, ! 250: 24,48,64,72,72,64,48,24, ! 251: 16,40,56,64,64,56,40,16, ! 252: 8,32,40,48,48,40,32, 8, ! 253: 0, 8,16,24,24,16, 8, 0}; ! 254: short KBNK[64]= ! 255: {99,90,80,70,60,50,40,40, ! 256: 90,80,60,50,40,30,20,40, ! 257: 80,60,40,30,20,10,30,50, ! 258: 70,50,30,10, 0,20,40,60, ! 259: 60,40,20, 0,10,30,50,70, ! 260: 50,30,10,20,30,40,60,80, ! 261: 40,20,30,40,50,60,80,90, ! 262: 40,40,50,60,70,80,90,99}; ! 263: short pknight[64]= ! 264: { 0, 4, 8,10,10, 8, 4, 0, ! 265: 4, 8,16,20,20,16, 8, 4, ! 266: 8,16,24,28,28,24,16, 8, ! 267: 10,20,28,32,32,28,20,10, ! 268: 10,20,28,32,32,28,20,10, ! 269: 8,16,24,28,28,24,16, 8, ! 270: 4, 8,16,20,20,16, 8, 4, ! 271: 0, 4, 8,10,10, 8, 4, 0}; ! 272: short pbishop[64]= ! 273: {14,14,14,14,14,14,14,14, ! 274: 14,22,18,18,18,18,22,14, ! 275: 14,18,22,22,22,22,18,14, ! 276: 14,18,22,22,22,22,18,14, ! 277: 14,18,22,22,22,22,18,14, ! 278: 14,18,22,22,22,22,18,14, ! 279: 14,22,18,18,18,18,22,14, ! 280: 14,14,14,14,14,14,14,14}; ! 281: short PawnAdvance[64]= ! 282: { 0, 0, 0, 0, 0, 0, 0, 0, ! 283: 4, 4, 4, 0, 0, 4, 4, 4, ! 284: 6, 8, 2,10,10, 2, 8, 6, ! 285: 6, 8,12,16,16,12, 8, 6, ! 286: 8,12,16,24,24,16,12, 8, ! 287: 12,16,24,32,32,24,16,12, ! 288: 12,16,24,32,32,24,16,12, ! 289: 0, 0, 0, 0, 0, 0, 0, 0}; ! 290: ! 291: ! 292: main(argc,argv) ! 293: int argc; char *argv[]; ! 294: { ! 295: #ifdef MSDOS ! 296: ttable = (struct hashentry huge *)farmalloc(ttblsz * ! 297: (unsigned long)sizeof(struct hashentry)); ! 298: #else ! 299: ttable = (struct hashentry *)malloc(ttblsz * ! 300: (unsigned long)sizeof(struct hashentry)); ! 301: #endif ! 302: Level = 0; TCflag = false; OperatorTime = 0; ! 303: if (argc == 2) Level = atoi(argv[1]); ! 304: if (argc == 3) ! 305: { ! 306: TCmoves = atoi(argv[1]); TCminutes = atoi(argv[2]); TCflag = true; ! 307: } ! 308: Initialize(); ! 309: NewGame(); ! 310: #if (NEWMOVE > 0) ! 311: Initialize_dist(); ! 312: #if (NEWMOVE > 1) ! 313: Initialize_moves(); ! 314: #endif ! 315: #endif ! 316: while (!(quit)) ! 317: { ! 318: if (bothsides && !mate) SelectMove(opponent,1); else InputCommand(); ! 319: if (!(quit || mate || force)) SelectMove(computer,1); ! 320: } ! 321: ExitChess(); ! 322: } ! 323: ! 324: ! 325: ! 326: /* ............ INTERFACE ROUTINES ........................... */ ! 327: ! 328: int VerifyMove(s,iop,mv) ! 329: char s[]; ! 330: short iop; ! 331: unsigned short *mv; ! 332: ! 333: /* ! 334: Compare the string 's' to the list of legal moves available for the ! 335: opponent. If a match is found, make the move on the board. ! 336: */ ! 337: ! 338: { ! 339: static short pnt,tempb,tempc,tempsf,tempst,cnt; ! 340: static struct leaf xnode; ! 341: struct leaf *node; ! 342: ! 343: *mv = 0; ! 344: if (iop == 2) ! 345: { ! 346: UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); ! 347: return(false); ! 348: } ! 349: cnt = 0; ! 350: MoveList(opponent,2); ! 351: pnt = TrPnt[2]; ! 352: while (pnt < TrPnt[3]) ! 353: { ! 354: node = &Tree[pnt++]; ! 355: algbr(node->f,node->t,(short) node->flags & cstlmask); ! 356: if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0) ! 357: { ! 358: cnt++; xnode = *node; ! 359: } ! 360: } ! 361: if (cnt == 1) ! 362: { ! 363: MakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); ! 364: if (SqAtakd(PieceList[opponent][0],computer)) ! 365: { ! 366: UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); ! 367: ShowMessage("Illegal Move!!"); ! 368: return(false); ! 369: } ! 370: else ! 371: { ! 372: if (iop == 1) return(true); ! 373: if (xnode.flags & epmask) UpdateDisplay(0,0,1,0); ! 374: else UpdateDisplay(xnode.f,xnode.t,0,xnode.flags & cstlmask); ! 375: if (xnode.flags & cstlmask) Game50 = GameCnt; ! 376: else if (board[xnode.t] == pawn || (xnode.flags & capture)) ! 377: Game50 = GameCnt; ! 378: GameList[GameCnt].depth = GameList[GameCnt].score = 0; ! 379: GameList[GameCnt].nodes = 0; ! 380: ElapsedTime(1); ! 381: GameList[GameCnt].time = (short)et; ! 382: TimeControl.clock[opponent] -= et; ! 383: --TimeControl.moves[opponent]; ! 384: *mv = (xnode.f << 8) + xnode.t; ! 385: algbr(xnode.f,xnode.t,false); ! 386: return(true); ! 387: } ! 388: } ! 389: if (cnt > 1) ShowMessage("Ambiguous Move!"); ! 390: return(false); ! 391: } ! 392: ! 393: ! 394: NewGame() ! 395: ! 396: /* ! 397: Reset the board and other variables to start a new game. ! 398: */ ! 399: ! 400: { ! 401: short l,r,c,p; ! 402: ! 403: mate = quit = reverse = bothsides = post = false; ! 404: hashflag = force = PawnStorm = false; ! 405: beep = rcptr = easy = true; ! 406: lpost = NodeCnt = epsquare = et0 = 0; ! 407: dither = 0; ! 408: Awindow = 90; ! 409: Bwindow = 90; ! 410: xwndw = 90; ! 411: MaxSearchDepth = 29; ! 412: contempt = 0; ! 413: GameCnt = -1; Game50 = 0; ! 414: Zwmtl = Zbmtl = 0; ! 415: Developed[white] = Developed[black] = false; ! 416: castld[white] = castld[black] = false; ! 417: kingmoved[white] = kingmoved[black] = 0; ! 418: PawnThreat[0] = CptrFlag[0] = Threat[0] = false; ! 419: Pscore[0] = 12000; Tscore[0] = 12000; ! 420: opponent = white; computer = black; ! 421: for (r = 0; r < 8; r++) ! 422: for (c = 0; c < 8; c++) ! 423: { ! 424: l = 8*r+c; locn[r][c] = l; ! 425: row[l] = r; column[l] = c; ! 426: board[l] = Stboard[l]; color[l] = Stcolor[l]; ! 427: } ! 428: for (c = white; c <= black; c++) ! 429: for (p = pawn; p <= king; p++) ! 430: for (l = 0; l < 64; l++) ! 431: { ! 432: hashcode[c][p][l].key = (unsigned short)rand(); ! 433: hashcode[c][p][l].bd = ((unsigned long)rand() << 16) + ! 434: (unsigned long)rand(); ! 435: } ! 436: ClrScreen(); ! 437: if (TCflag) SetTimeControl(); ! 438: else if (Level == 0) SelectLevel(); ! 439: UpdateDisplay(0,0,1,0); ! 440: InitializeStats(); ! 441: time0 = time((long *)0); ! 442: ElapsedTime(1); ! 443: GetOpenings(); ! 444: } ! 445: ! 446: ! 447: algbr(f,t,iscastle) ! 448: short f,t,iscastle; ! 449: { ! 450: mvstr1[0] = cxx[column[f]]; mvstr1[1] = rxx[row[f]]; ! 451: mvstr1[2] = cxx[column[t]]; mvstr1[3] = rxx[row[t]]; ! 452: mvstr2[0] = qxx[board[f]]; ! 453: mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3]; ! 454: mvstr1[4] = '\0'; mvstr2[3] = '\0'; ! 455: if (iscastle) ! 456: if (t > f) strcpy(mvstr2,"o-o"); ! 457: else strcpy(mvstr2,"o-o-o"); ! 458: } ! 459: ! 460: ! 461: /* ............ MOVE GENERATION & SEARCH ROUTINES .............. */ ! 462: ! 463: SelectMove(side,iop) ! 464: short side,iop; ! 465: ! 466: /* ! 467: Select a move by calling function search() at progressively deeper ! 468: ply until time is up or a mate or draw is reached. An alpha-beta ! 469: window of -90 to +90 points is set around the score returned from the ! 470: previous iteration. If Sdepth != 0 then the program has correctly ! 471: predicted the opponents move and the search will start at a depth of ! 472: Sdepth+1 rather than a depth of 1. ! 473: */ ! 474: ! 475: { ! 476: static short i,alpha,beta,score,tempb,tempc,tempsf,tempst,xside,rpt; ! 477: ! 478: timeout = false; ! 479: xside = otherside[side]; ! 480: if (iop != 2) player = side; ! 481: if (TCflag) ! 482: { ! 483: if (((TimeControl.moves[side] + 3) - OperatorTime) != 0) ! 484: ResponseTime = (TimeControl.clock[side]) / ! 485: (TimeControl.moves[side] + 3) - ! 486: OperatorTime; ! 487: else ResponseTime = 0; ! 488: ResponseTime += (ResponseTime*TimeControl.moves[side])/(2*TCmoves+1); ! 489: } ! 490: else ResponseTime = Level; ! 491: if (iop == 2) ResponseTime = 999; ! 492: if (Sdepth > 0 && root->score > Zscore-zwndw) ResponseTime -= ft; ! 493: else if (ResponseTime < 1) ResponseTime = 1; ! 494: ExtraTime = 0; ! 495: ExaminePosition(); ! 496: ScorePosition(side,&score); ! 497: ShowSidetomove(); ! 498: ! 499: if (Sdepth == 0) ! 500: { ! 501: ZeroTTable(); ! 502: SearchStartStuff(side); ! 503: for (i = 0; i < 8192; i++) history[i] = 0; ! 504: FROMsquare = TOsquare = -1; ! 505: PV = 0; ! 506: if (iop != 2) hint = 0; ! 507: for (i = 0; i < maxdepth; i++) ! 508: PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0; ! 509: alpha = score-90; beta = score+90; ! 510: rpt = 0; ! 511: TrPnt[1] = 0; root = &Tree[0]; ! 512: MoveList(side,1); ! 513: for (i = TrPnt[1]; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1); ! 514: if (Book != NULL) OpeningBook(); ! 515: if (Book != NULL) timeout = true; ! 516: NodeCnt = ETnodes = EvalNodes = HashCnt = 0; ! 517: Zscore = 0; zwndw = 20; ! 518: } ! 519: ! 520: while (!timeout && Sdepth < MaxSearchDepth) ! 521: { ! 522: Sdepth++; ! 523: ShowDepth(' '); ! 524: score = search(side,1,Sdepth,alpha,beta,PrVar,&rpt); ! 525: for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i]; ! 526: if (score < alpha) ! 527: { ! 528: ShowDepth('-'); ! 529: ExtraTime = 10*ResponseTime; ! 530: ZeroTTable(); ! 531: score = search(side,1,Sdepth,-9000,beta,PrVar,&rpt); ! 532: } ! 533: if (score > beta && !(root->flags & exact)) ! 534: { ! 535: ShowDepth('+'); ! 536: ExtraTime = 0; ! 537: ZeroTTable(); ! 538: score = search(side,1,Sdepth,alpha,9000,PrVar,&rpt); ! 539: } ! 540: score = root->score; ! 541: if (!timeout) ! 542: for (i = TrPnt[1]+1; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1); ! 543: ShowResults(score,PrVar,'.'); ! 544: for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i]; ! 545: if (score > Zscore-zwndw && score > Tree[1].score+250) ExtraTime = 0; ! 546: else if (score > Zscore-3*zwndw) ExtraTime = ResponseTime; ! 547: else ExtraTime = 3*ResponseTime; ! 548: if (root->flags & exact) timeout = true; ! 549: if (Tree[1].score < -9000) timeout = true; ! 550: if (4*et > 2*ResponseTime + ExtraTime) timeout = true; ! 551: if (!timeout) ! 552: { ! 553: Tscore[0] = score; ! 554: if (Zscore == 0) Zscore = score; ! 555: else Zscore = (Zscore+score)/2; ! 556: } ! 557: zwndw = 20+abs(Zscore/12); ! 558: beta = score + Bwindow; ! 559: if (Zscore < score) alpha = Zscore - Awindow - zwndw; ! 560: else alpha = score - Awindow - zwndw; ! 561: } ! 562: ! 563: score = root->score; ! 564: if (rpt >= 2 || score < -12000) root->flags |= draw; ! 565: if (iop == 2) return(0); ! 566: if (Book == NULL) hint = PrVar[2]; ! 567: ElapsedTime(1); ! 568: ! 569: if (score > -9999 && rpt <= 2) ! 570: { ! 571: MakeMove(side,root,&tempb,&tempc,&tempsf,&tempst); ! 572: algbr(root->f,root->t,(short) root->flags & cstlmask); ! 573: } ! 574: else mvstr1[0] = '\0'; ! 575: OutputMove(); ! 576: if (score == -9999 || score == 9998) mate = true; ! 577: if (mate) hint = 0; ! 578: if (root->flags & cstlmask) Game50 = GameCnt; ! 579: else if (board[root->t] == pawn || (root->flags & capture)) ! 580: Game50 = GameCnt; ! 581: GameList[GameCnt].score = score; ! 582: GameList[GameCnt].nodes = NodeCnt; ! 583: GameList[GameCnt].time = (short)et; ! 584: GameList[GameCnt].depth = Sdepth; ! 585: if (TCflag) ! 586: { ! 587: TimeControl.clock[side] -= (et + OperatorTime); ! 588: if (--TimeControl.moves[side] == 0) SetTimeControl(); ! 589: } ! 590: if ((root->flags & draw) && bothsides) quit = true; ! 591: if (GameCnt > 238) quit = true; ! 592: player = xside; ! 593: Sdepth = 0; ! 594: fflush(stdin); ! 595: return(0); ! 596: } ! 597: ! 598: ! 599: OpeningBook() ! 600: ! 601: /* ! 602: Go thru each of the opening lines of play and check for a match with ! 603: the current game listing. If a match occurs, generate a random number. ! 604: If this number is the largest generated so far then the next move in ! 605: this line becomes the current "candidate". After all lines are ! 606: checked, the candidate move is put at the top of the Tree[] array and ! 607: will be played by the program. Note that the program does not handle ! 608: book transpositions. ! 609: */ ! 610: ! 611: { ! 612: short j,pnt; ! 613: unsigned short m,*mp; ! 614: unsigned r,r0; ! 615: struct BookEntry *p; ! 616: ! 617: srand((unsigned)time0); ! 618: r0 = m = 0; ! 619: p = Book; ! 620: while (p != NULL) ! 621: { ! 622: mp = p->mv; ! 623: for (j = 0; j <= GameCnt; j++) ! 624: if (GameList[j].gmove != *(mp++)) break; ! 625: if (j > GameCnt) ! 626: if ((r=rand()) > r0) ! 627: { ! 628: r0 = r; m = *mp; ! 629: hint = *(++mp); ! 630: } ! 631: p = p->next; ! 632: } ! 633: ! 634: for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++) ! 635: if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0; ! 636: pick(TrPnt[1],TrPnt[2]-1); ! 637: if (Tree[TrPnt[1]].score < 0) Book = NULL; ! 638: } ! 639: ! 640: ! 641: #define UpdateSearchStatus\ ! 642: {\ ! 643: if (post) ShowCurrentMove(pnt,node->f,node->t);\ ! 644: if (pnt > TrPnt[1])\ ! 645: {\ ! 646: d = best-Zscore; e = best-node->score;\ ! 647: if (best < alpha) ExtraTime = 10*ResponseTime;\ ! 648: else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\ ! 649: else if (d > -zwndw) ExtraTime = 0;\ ! 650: else if (d > -3*zwndw) ExtraTime = ResponseTime;\ ! 651: else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\ ! 652: else ExtraTime = 5*ResponseTime;\ ! 653: }\ ! 654: } ! 655: ! 656: int search(side,ply,depth,alpha,beta,bstline,rpt) ! 657: short side,ply,depth,alpha,beta,*rpt; ! 658: unsigned short bstline[]; ! 659: ! 660: /* ! 661: Perform an alpha-beta search to determine the score for the current ! 662: board position. If depth <= 0 only capturing moves, pawn promotions ! 663: and responses to check are generated and searched, otherwise all ! 664: moves are processed. The search depth is modified for check evasions, ! 665: certain re-captures and threats. Extensions may continue for up to 11 ! 666: ply beyond the nominal search depth. ! 667: */ ! 668: ! 669: #define prune (cf && score+node->score < alpha) ! 670: #define ReCapture (rcptr && score > alpha && score < beta &&\ ! 671: ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2]) ! 672: #define MateThreat (ply < Sdepth+4 && ply > 4 &&\ ! 673: ChkFlag[ply-2] && ChkFlag[ply-4] &&\ ! 674: ChkFlag[ply-2] != ChkFlag[ply-4]) ! 675: ! 676: { ! 677: register short j,pnt; ! 678: short best,tempb,tempc,tempsf,tempst; ! 679: short xside,pbst,d,e,cf,score,rcnt; ! 680: unsigned short mv,nxtline[maxdepth]; ! 681: struct leaf *node,tmp; ! 682: ! 683: NodeCnt++; ! 684: xside = otherside[side]; ! 685: if (depth < 0) depth = 0; ! 686: ! 687: if (ply <= Sdepth+3) repetition(rpt); else *rpt = 0; ! 688: if (*rpt >= 2) return(0); ! 689: ! 690: score = evaluate(side,xside,ply,alpha,beta); ! 691: if (score > 9000) ! 692: { ! 693: bstline[ply] = 0; ! 694: return(score); ! 695: } ! 696: ! 697: if (depth > 0) ! 698: { ! 699: if (InChk || PawnThreat[ply-1] || ReCapture) ++depth; ! 700: } ! 701: else ! 702: { ! 703: if (score >= alpha && ! 704: (InChk || PawnThreat[ply-1] || Threat[ply-1])) ++depth; ! 705: else if (score <= beta && MateThreat) ++depth; ! 706: } ! 707: ! 708: if (depth > 0 && hashflag && ply > 1) ! 709: { ! 710: ProbeTTable(side,depth,&alpha,&beta,&score); ! 711: bstline[ply] = PV; ! 712: bstline[ply+1] = 0; ! 713: if (beta == -20000) return(score); ! 714: if (alpha > beta) return(alpha); ! 715: } ! 716: ! 717: if (Sdepth == 1) d = 7; else d = 11; ! 718: if (ply > Sdepth+d || (depth < 1 && score > beta)) return(score); ! 719: ! 720: if (ply > 1) ! 721: if (depth > 0) MoveList(side,ply); ! 722: else CaptureList(side,xside,ply); ! 723: ! 724: if (TrPnt[ply] == TrPnt[ply+1]) return(score); ! 725: ! 726: cf = (depth < 1 && ply > Sdepth+1 && !ChkFlag[ply-2] && !slk); ! 727: ! 728: if (depth > 0) best = -12000; else best = score; ! 729: if (best > alpha) alpha = best; ! 730: ! 731: for (pnt = pbst = TrPnt[ply]; ! 732: pnt < TrPnt[ply+1] && best <= beta; ! 733: pnt++) ! 734: { ! 735: if (ply > 1) pick(pnt,TrPnt[ply+1]-1); ! 736: node = &Tree[pnt]; ! 737: mv = (node->f << 8) + node->t; ! 738: nxtline[ply+1] = 0; ! 739: ! 740: if (prune) break; ! 741: if (ply == 1) UpdateSearchStatus; ! 742: ! 743: if (!(node->flags & exact)) ! 744: { ! 745: MakeMove(side,node,&tempb,&tempc,&tempsf,&tempst); ! 746: CptrFlag[ply] = (node->flags & capture); ! 747: PawnThreat[ply] = (node->flags & pwnthrt); ! 748: Tscore[ply] = node->score; ! 749: PV = node->reply; ! 750: node->score = -search(xside,ply+1,depth-1,-beta,-alpha, ! 751: nxtline,&rcnt); ! 752: if (abs(node->score) > 9000) node->flags |= exact; ! 753: else if (rcnt == 1) node->score /= 2; ! 754: if (rcnt >= 2 || GameCnt-Game50 > 99 || ! 755: (node->score == 9999-ply && !ChkFlag[ply])) ! 756: { ! 757: node->flags |= draw; node->flags |= exact; ! 758: if (side == computer) node->score = contempt; ! 759: else node->score = -contempt; ! 760: } ! 761: node->reply = nxtline[ply+1]; ! 762: UnmakeMove(side,node,&tempb,&tempc,&tempsf,&tempst); ! 763: } ! 764: if (node->score > best && !timeout) ! 765: { ! 766: if (depth > 0) ! 767: if (node->score > alpha && !(node->flags & exact)) ! 768: node->score += depth; ! 769: best = node->score; pbst = pnt; ! 770: if (best > alpha) alpha = best; ! 771: for (j = ply+1; nxtline[j] > 0; j++) bstline[j] = nxtline[j]; ! 772: bstline[j] = 0; ! 773: bstline[ply] = mv; ! 774: if (ply == 1) ! 775: { ! 776: if (best == alpha) ! 777: { ! 778: tmp = Tree[pnt]; ! 779: for (j = pnt-1; j >= 0; j--) Tree[j+1] = Tree[j]; ! 780: Tree[0] = tmp; ! 781: pbst = 0; ! 782: } ! 783: if (Sdepth > 2) ! 784: if (best > beta) ShowResults(best,bstline,'+'); ! 785: else if (best < alpha) ShowResults(best,bstline,'-'); ! 786: else ShowResults(best,bstline,'&'); ! 787: } ! 788: } ! 789: if (NodeCnt > ETnodes) ElapsedTime(0); ! 790: if (timeout) return(-Tscore[ply-1]); ! 791: } ! 792: ! 793: node = &Tree[pbst]; ! 794: mv = (node->f<<8) + node->t; ! 795: if (hashflag && ply <= Sdepth && *rpt == 0 && best == alpha) ! 796: PutInTTable(side,best,depth,alpha,beta,mv); ! 797: if (depth > 0) ! 798: { ! 799: j = (node->f<<6) + node->t; if (side == black) j |= 0x1000; ! 800: if (history[j] < 150) history[j] += 2*depth; ! 801: if (node->t != (GameList[GameCnt].gmove & 0xFF)) ! 802: if (best <= beta) killr3[ply] = mv; ! 803: else if (mv != killr1[ply]) ! 804: { ! 805: killr2[ply] = killr1[ply]; ! 806: killr1[ply] = mv; ! 807: } ! 808: if (best > 9000) killr0[ply] = mv; else killr0[ply] = 0; ! 809: } ! 810: return(best); ! 811: } ! 812: ! 813: ! 814: evaluate(side,xside,ply,alpha,beta) ! 815: short side,xside,ply,alpha,beta; ! 816: ! 817: /* ! 818: Compute an estimate of the score by adding the positional score from ! 819: the previous ply to the material difference. If this score falls ! 820: inside a window which is 180 points wider than the alpha-beta window ! 821: (or within a 50 point window during quiescence search) call ! 822: ScorePosition() to determine a score, otherwise return the estimated ! 823: score. If one side has only a king and the other either has no pawns ! 824: or no pieces then the function ScoreLoneKing() is called. ! 825: */ ! 826: ! 827: { ! 828: short s,evflag; ! 829: ! 830: hung[white] = hung[black] = 0; ! 831: slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) || ! 832: (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0))); ! 833: s = -Pscore[ply-1] + mtl[side] - mtl[xside]; ! 834: s -= INCscore; ! 835: ! 836: if (slk) evflag = false; ! 837: else evflag = ! 838: (ply == 1 || ply < Sdepth || ! 839: ((ply == Sdepth+1 || ply == Sdepth+2) && ! 840: (s > alpha-xwndw && s < beta+xwndw)) || ! 841: (ply > Sdepth+2 && s >= alpha-25 && s <= beta+25)); ! 842: ! 843: if (evflag) ! 844: { ! 845: EvalNodes++; ! 846: ataks(side,atak[side]); ! 847: if (atak[side][PieceList[xside][0]] > 0) return(10001-ply); ! 848: ataks(xside,atak[xside]); ! 849: InChk = (atak[xside][PieceList[side][0]] > 0); ! 850: ScorePosition(side,&s); ! 851: } ! 852: else ! 853: { ! 854: if (SqAtakd(PieceList[xside][0],side)) return(10001-ply); ! 855: InChk = SqAtakd(PieceList[side][0],xside); ! 856: if (slk) ScoreLoneKing(side,&s); ! 857: } ! 858: ! 859: Pscore[ply] = s - mtl[side] + mtl[xside]; ! 860: if (InChk) ChkFlag[ply-1] = Pindex[TOsquare]; ! 861: else ChkFlag[ply-1] = 0; ! 862: Threat[ply-1] = (hung[side] > 1 && ply == Sdepth+1); ! 863: return(s); ! 864: } ! 865: ! 866: ! 867: ProbeTTable(side,depth,alpha,beta,score) ! 868: short side,depth,*alpha,*beta,*score; ! 869: ! 870: /* ! 871: Look for the current board position in the transposition table. ! 872: */ ! 873: ! 874: { ! 875: short hindx; ! 876: if (side == white) hashkey |= 1; else hashkey &= 0xFFFE; ! 877: hindx = (hashkey & (ttblsz-1)); ! 878: ptbl = (ttable + hindx); ! 879: if (ptbl->depth >= depth && ptbl->hashbd == hashbd) ! 880: { ! 881: HashCnt++; ! 882: PV = ptbl->mv; ! 883: if (ptbl->flags & truescore) ! 884: { ! 885: *score = ptbl->score; ! 886: *beta = -20000; ! 887: return(true); ! 888: } ! 889: /* ! 890: else if (ptbl->flags & upperbound) ! 891: { ! 892: if (ptbl->score < *beta) *beta = ptbl->score+1; ! 893: } ! 894: */ ! 895: else if (ptbl->flags & lowerbound) ! 896: { ! 897: if (ptbl->score > *alpha) *alpha = ptbl->score-1; ! 898: } ! 899: } ! 900: return(false); ! 901: } ! 902: ! 903: ! 904: PutInTTable(side,score,depth,alpha,beta,mv) ! 905: short side,score,depth,alpha,beta; ! 906: unsigned short mv; ! 907: ! 908: /* ! 909: Store the current board position in the transposition table. ! 910: */ ! 911: ! 912: { ! 913: short hindx; ! 914: if (side == white) hashkey |= 1; else hashkey &= 0xFFFE; ! 915: hindx = (hashkey & (ttblsz-1)); ! 916: ptbl = (ttable + hindx); ! 917: ptbl->hashbd = hashbd; ! 918: ptbl->depth = depth; ! 919: ptbl->score = score; ! 920: ptbl->mv = mv; ! 921: ptbl->flags = 0; ! 922: if (score < alpha) ptbl->flags |= upperbound; ! 923: else if (score > beta) ptbl->flags |= lowerbound; ! 924: else ptbl->flags |= truescore; ! 925: } ! 926: ! 927: ! 928: ZeroTTable() ! 929: { ! 930: int i; ! 931: if (hashflag) ! 932: for (i = 0; i < ttblsz; i++) ! 933: { ! 934: ptbl = (ttable + i); ! 935: ptbl->depth = 0; ! 936: } ! 937: } ! 938: ! 939: ! 940: MoveList(side,ply) ! 941: short side,ply; ! 942: ! 943: /* ! 944: Fill the array Tree[] with all available moves for side to play. Array ! 945: TrPnt[ply] contains the index into Tree[] of the first move at a ply. ! 946: */ ! 947: ! 948: { ! 949: register short i; ! 950: short xside,f; ! 951: ! 952: xside = otherside[side]; ! 953: if (PV == 0) Swag0 = killr0[ply]; else Swag0 = PV; ! 954: Swag1 = killr1[ply]; Swag2 = killr2[ply]; ! 955: Swag3 = killr3[ply]; Swag4 = 0; ! 956: if (ply > 2) Swag4 = killr1[ply-2]; ! 957: TrPnt[ply+1] = TrPnt[ply]; ! 958: Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1; ! 959: for (i = PieceCnt[side]; i >= 0; i--) ! 960: GenMoves(ply,PieceList[side][i],side,xside); ! 961: if (kingmoved[side] == 0 && !castld[side]) ! 962: { ! 963: f = PieceList[side][0]; ! 964: if (castle(side,f,f+2,0)) ! 965: { ! 966: LinkMove(ply,f,f+2,xside); ! 967: Tree[TrPnt[ply+1]-1].flags |= cstlmask; ! 968: } ! 969: if (castle(side,f,f-2,0)) ! 970: { ! 971: LinkMove(ply,f,f-2,xside); ! 972: Tree[TrPnt[ply+1]-1].flags |= cstlmask; ! 973: } ! 974: } ! 975: } ! 976: ! 977: #if (NEWMOVE < 11) ! 978: GenMoves(ply,sq,side,xside) ! 979: short ply,sq,side,xside; ! 980: ! 981: /* ! 982: Generate moves for a piece. The from square is mapped onto a special ! 983: board and offsets (taken from array Dir[]) are added to the mapped ! 984: location. The newly generated square is tested to see if it falls off ! 985: the board by ANDing the square with 88 HEX. Legal moves are linked ! 986: into the tree. ! 987: */ ! 988: ! 989: { ! 990: register short m,u,d; ! 991: short i,m0,piece; ! 992: ! 993: piece = board[sq]; m0 = map[sq]; ! 994: if (sweep[piece]) ! 995: for (i = Dstart[piece]; i <= Dstop[piece]; i++) ! 996: { ! 997: d = Dir[i]; m = m0+d; ! 998: while (!(m & 0x88)) ! 999: { ! 1000: u = unmap[m]; ! 1001: if (color[u] == neutral) ! 1002: { ! 1003: LinkMove(ply,sq,u,xside); ! 1004: m += d; ! 1005: } ! 1006: else if (color[u] == xside) ! 1007: { ! 1008: LinkMove(ply,sq,u,xside); ! 1009: break; ! 1010: } ! 1011: else break; ! 1012: } ! 1013: } ! 1014: else if (piece == pawn) ! 1015: { ! 1016: if (side == white && color[sq+8] == neutral) ! 1017: { ! 1018: LinkMove(ply,sq,sq+8,xside); ! 1019: if (row[sq] == 1) ! 1020: if (color[sq+16] == neutral) ! 1021: LinkMove(ply,sq,sq+16,xside); ! 1022: } ! 1023: else if (side == black && color[sq-8] == neutral) ! 1024: { ! 1025: LinkMove(ply,sq,sq-8,xside); ! 1026: if (row[sq] == 6) ! 1027: if (color[sq-16] == neutral) ! 1028: LinkMove(ply,sq,sq-16,xside); ! 1029: } ! 1030: for (i = Dstart[piece]; i <= Dstop[piece]; i++) ! 1031: if (!((m = m0+Dir[i]) & 0x88)) ! 1032: { ! 1033: u = unmap[m]; ! 1034: if (color[u] == xside || u == epsquare) ! 1035: LinkMove(ply,sq,u,xside); ! 1036: } ! 1037: } ! 1038: else ! 1039: { ! 1040: for (i = Dstart[piece]; i <= Dstop[piece]; i++) ! 1041: if (!((m = m0+Dir[i]) & 0x88)) ! 1042: { ! 1043: u = unmap[m]; ! 1044: if (color[u] != side) LinkMove(ply,sq,u,xside); ! 1045: } ! 1046: } ! 1047: } ! 1048: #endif ! 1049: ! 1050: LinkMove(ply,f,t,xside) ! 1051: short ply,f,t,xside; ! 1052: ! 1053: /* ! 1054: Add a move to the tree. Assign a bonus to order the moves ! 1055: as follows: ! 1056: 1. Principle variation ! 1057: 2. Capture of last moved piece ! 1058: 3. Other captures (major pieces first) ! 1059: 4. Killer moves ! 1060: 5. "history" killers ! 1061: */ ! 1062: ! 1063: { ! 1064: register short s,z; ! 1065: unsigned short mv; ! 1066: struct leaf *node; ! 1067: ! 1068: node = &Tree[TrPnt[ply+1]]; ! 1069: ++TrPnt[ply+1]; ! 1070: node->flags = node->reply = 0; ! 1071: node->f = f; node->t = t; ! 1072: mv = (f<<8) + t; ! 1073: s = 0; ! 1074: if (mv == Swag0) s = 2000; ! 1075: else if (mv == Swag1) s = 60; ! 1076: else if (mv == Swag2) s = 50; ! 1077: else if (mv == Swag3) s = 40; ! 1078: else if (mv == Swag4) s = 30; ! 1079: if (color[t] != neutral) ! 1080: { ! 1081: node->flags |= capture; ! 1082: if (t == TOsquare) s += 500; ! 1083: s += value[board[t]] - board[f]; ! 1084: } ! 1085: if (board[f] == pawn) ! 1086: if (row[t] == 0 || row[t] == 7) ! 1087: { ! 1088: node->flags |= promote; ! 1089: s += 800; ! 1090: } ! 1091: else if (row[t] == 1 || row[t] == 6) ! 1092: { ! 1093: node->flags |= pwnthrt; ! 1094: s += 600; ! 1095: } ! 1096: else if (t == epsquare) node->flags |= epmask; ! 1097: z = (f<<6) + t; if (xside == white) z |= 0x1000; ! 1098: s += history[z]; ! 1099: node->score = s - 20000; ! 1100: } ! 1101: ! 1102: #if (NEWMOVE < 10) ! 1103: CaptureList(side,xside,ply) ! 1104: short side,xside,ply; ! 1105: ! 1106: /* ! 1107: Generate captures and Pawn promotions only. ! 1108: */ ! 1109: ! 1110: #define LinkCapture\ ! 1111: {\ ! 1112: node->f = sq; node->t = u;\ ! 1113: node->reply = 0;\ ! 1114: node->flags = capture;\ ! 1115: node->score = value[board[u]] + svalue[board[u]] - piece;\ ! 1116: if (piece == pawn && (u < 8 || u > 55))\ ! 1117: {\ ! 1118: node->flags |= promote;\ ! 1119: node->score = valueQ;\ ! 1120: }\ ! 1121: ++node;\ ! 1122: ++TrPnt[ply+1];\ ! 1123: } ! 1124: ! 1125: { ! 1126: register short m,u; ! 1127: short d,sq,i,j,j1,j2,m0,r7,d0,piece,*PL; ! 1128: struct leaf *node; ! 1129: ! 1130: TrPnt[ply+1] = TrPnt[ply]; ! 1131: node = &Tree[TrPnt[ply]]; ! 1132: Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1; ! 1133: if (side == white) ! 1134: { ! 1135: r7 = 6; d0 = 8; ! 1136: } ! 1137: else ! 1138: { ! 1139: r7 = 1; d0 = -8; ! 1140: } ! 1141: PL = PieceList[side]; ! 1142: for (i = 0; i <= PieceCnt[side]; i++) ! 1143: { ! 1144: sq = PL[i]; ! 1145: m0 = map[sq]; piece = board[sq]; ! 1146: j1 = Dstart[piece]; j2 = Dstop[piece]; ! 1147: if (sweep[piece]) ! 1148: for (j = j1; j <= j2; j++) ! 1149: { ! 1150: d = Dir[j]; m = m0+d; ! 1151: while (!(m & 0x88)) ! 1152: { ! 1153: u = unmap[m]; ! 1154: if (color[u] == neutral) m += d; ! 1155: else ! 1156: { ! 1157: if (color[u] == xside) LinkCapture; ! 1158: break; ! 1159: } ! 1160: } ! 1161: } ! 1162: else ! 1163: { ! 1164: for (j = j1; j <= j2; j++) ! 1165: if (!((m = m0+Dir[j]) & 0x88)) ! 1166: { ! 1167: u = unmap[m]; ! 1168: if (color[u] == xside) LinkCapture; ! 1169: } ! 1170: if (piece == pawn && row[sq] == r7) ! 1171: { ! 1172: u = sq+d0; ! 1173: if (color[u] == neutral) LinkCapture; ! 1174: } ! 1175: } ! 1176: } ! 1177: } ! 1178: #endif ! 1179: ! 1180: int castle(side,kf,kt,iop) ! 1181: short side,kf,kt,iop; ! 1182: ! 1183: /* ! 1184: Make or Unmake a castling move. ! 1185: */ ! 1186: ! 1187: { ! 1188: short rf,rt,d,t0,xside; ! 1189: ! 1190: xside = otherside[side]; ! 1191: if (kt > kf) ! 1192: { ! 1193: rf = kf+3; rt = kt-1; d = 1; ! 1194: } ! 1195: else ! 1196: { ! 1197: rf = kf-4; rt = kt+1; d = -1; ! 1198: } ! 1199: if (iop == 0) ! 1200: { ! 1201: if (board[kf] != king || board[rf] != rook || color[rf] != side) ! 1202: return(false); ! 1203: if (color[kt] != neutral || color[rt] != neutral) return(false); ! 1204: if (d == -1 && color[kt+d] != neutral) return(false); ! 1205: if (SqAtakd(kf,xside)) return(false); ! 1206: if (SqAtakd(kt,xside)) return(false); ! 1207: if (SqAtakd(kf+d,xside)) return(false); ! 1208: } ! 1209: else ! 1210: { ! 1211: if (iop == 1) castld[side] = true; else castld[side] = false; ! 1212: if (iop == 2) ! 1213: { ! 1214: t0 = kt; kt = kf; kf = t0; ! 1215: t0 = rt; rt = rf; rf = t0; ! 1216: } ! 1217: board[kt] = king; color[kt] = side; Pindex[kt] = 0; ! 1218: board[kf] = no_piece; color[kf] = neutral; ! 1219: board[rt] = rook; color[rt] = side; Pindex[rt] = Pindex[rf]; ! 1220: board[rf] = no_piece; color[rf] = neutral; ! 1221: PieceList[side][Pindex[kt]] = kt; ! 1222: PieceList[side][Pindex[rt]] = rt; ! 1223: if (hashflag) ! 1224: { ! 1225: UpdateHashbd(side,king,kf,kt); ! 1226: UpdateHashbd(side,rook,rf,rt); ! 1227: } ! 1228: } ! 1229: return(true); ! 1230: } ! 1231: ! 1232: ! 1233: EnPassant(xside,f,t,iop) ! 1234: short xside,f,t,iop; ! 1235: ! 1236: /* ! 1237: Make or unmake an en passant move. ! 1238: */ ! 1239: ! 1240: { ! 1241: short l; ! 1242: if (t > f) l = t-8; else l = t+8; ! 1243: if (iop == 1) ! 1244: { ! 1245: board[l] = no_piece; color[l] = neutral; ! 1246: } ! 1247: else ! 1248: { ! 1249: board[l] = pawn; color[l] = xside; ! 1250: } ! 1251: InitializeStats(); ! 1252: } ! 1253: ! 1254: ! 1255: MakeMove(side,node,tempb,tempc,tempsf,tempst) ! 1256: short side,*tempc,*tempb,*tempsf,*tempst; ! 1257: struct leaf *node; ! 1258: ! 1259: /* ! 1260: Update Arrays board[], color[], and Pindex[] to reflect the new board ! 1261: position obtained after making the move pointed to by node. Also ! 1262: update miscellaneous stuff that changes when a move is made. ! 1263: */ ! 1264: ! 1265: { ! 1266: register short f,t; ! 1267: short xside,ct,cf; ! 1268: ! 1269: xside = otherside[side]; ! 1270: f = node->f; t = node->t; epsquare = -1; ! 1271: FROMsquare = f; TOsquare = t; ! 1272: INCscore = 0; ! 1273: GameList[++GameCnt].gmove = (f<<8) + t; ! 1274: if (node->flags & cstlmask) ! 1275: { ! 1276: GameList[GameCnt].piece = no_piece; ! 1277: GameList[GameCnt].color = side; ! 1278: castle(side,f,t,1); ! 1279: } ! 1280: else ! 1281: { ! 1282: *tempc = color[t]; *tempb = board[t]; ! 1283: *tempsf = svalue[f]; *tempst = svalue[t]; ! 1284: GameList[GameCnt].piece = *tempb; ! 1285: GameList[GameCnt].color = *tempc; ! 1286: if (*tempc != neutral) ! 1287: { ! 1288: UpdatePieceList(*tempc,t,1); ! 1289: if (*tempb == pawn) --PawnCnt[*tempc][column[t]]; ! 1290: if (board[f] == pawn) ! 1291: { ! 1292: --PawnCnt[side][column[f]]; ! 1293: ++PawnCnt[side][column[t]]; ! 1294: cf = column[f]; ct = column[t]; ! 1295: if (PawnCnt[side][ct] > 1+PawnCnt[side][cf]) ! 1296: INCscore -= 15; ! 1297: else if (PawnCnt[side][ct] < 1+PawnCnt[side][cf]) ! 1298: INCscore += 15; ! 1299: else if (ct == 0 || ct == 7 || PawnCnt[side][ct+ct-cf] == 0) ! 1300: INCscore -= 15; ! 1301: } ! 1302: mtl[xside] -= value[*tempb]; ! 1303: if (*tempb == pawn) pmtl[xside] -= valueP; ! 1304: if (hashflag) UpdateHashbd(xside,*tempb,-1,t); ! 1305: INCscore += *tempst; ! 1306: } ! 1307: color[t] = color[f]; board[t] = board[f]; svalue[t] = svalue[f]; ! 1308: Pindex[t] = Pindex[f]; PieceList[side][Pindex[t]] = t; ! 1309: color[f] = neutral; board[f] = no_piece; ! 1310: if (board[t] == pawn) ! 1311: if (t-f == 16) epsquare = f+8; ! 1312: else if (f-t == 16) epsquare = f-8; ! 1313: if (node->flags & promote) ! 1314: { ! 1315: board[t] = queen; ! 1316: --PawnCnt[side][column[t]]; ! 1317: mtl[side] += valueQ - valueP; ! 1318: pmtl[side] -= valueP; ! 1319: HasQueen[side] = true; ! 1320: if (hashflag) ! 1321: { ! 1322: UpdateHashbd(side,pawn,f,-1); ! 1323: UpdateHashbd(side,queen,f,-1); ! 1324: } ! 1325: INCscore -= *tempsf; ! 1326: } ! 1327: if (board[t] == king) ++kingmoved[side]; ! 1328: if (node->flags & epmask) EnPassant(xside,f,t,1); ! 1329: else if (hashflag) UpdateHashbd(side,board[t],f,t); ! 1330: } ! 1331: } ! 1332: ! 1333: ! 1334: UnmakeMove(side,node,tempb,tempc,tempsf,tempst) ! 1335: short side,*tempc,*tempb,*tempsf,*tempst; ! 1336: struct leaf *node; ! 1337: ! 1338: /* ! 1339: Take back a move. ! 1340: */ ! 1341: ! 1342: { ! 1343: register short f,t; ! 1344: short xside; ! 1345: ! 1346: xside = otherside[side]; ! 1347: f = node->f; t = node->t; epsquare = -1; ! 1348: GameCnt--; ! 1349: if (node->flags & cstlmask) castle(side,f,t,2); ! 1350: else ! 1351: { ! 1352: color[f] = color[t]; board[f] = board[t]; svalue[f] = *tempsf; ! 1353: Pindex[f] = Pindex[t]; PieceList[side][Pindex[f]] = f; ! 1354: color[t] = *tempc; board[t] = *tempb; svalue[t] = *tempst; ! 1355: if (node->flags & promote) ! 1356: { ! 1357: board[f] = pawn; ! 1358: ++PawnCnt[side][column[t]]; ! 1359: mtl[side] += valueP - valueQ; ! 1360: pmtl[side] += valueP; ! 1361: if (hashflag) ! 1362: { ! 1363: UpdateHashbd(side,queen,-1,t); ! 1364: UpdateHashbd(side,pawn,-1,t); ! 1365: } ! 1366: } ! 1367: if (*tempc != neutral) ! 1368: { ! 1369: UpdatePieceList(*tempc,t,2); ! 1370: if (*tempb == pawn) ++PawnCnt[*tempc][column[t]]; ! 1371: if (board[f] == pawn) ! 1372: { ! 1373: --PawnCnt[side][column[t]]; ! 1374: ++PawnCnt[side][column[f]]; ! 1375: } ! 1376: mtl[xside] += value[*tempb]; ! 1377: if (*tempb == pawn) pmtl[xside] += valueP; ! 1378: if (hashflag) UpdateHashbd(xside,*tempb,-1,t); ! 1379: } ! 1380: if (board[f] == king) --kingmoved[side]; ! 1381: if (node->flags & epmask) EnPassant(xside,f,t,2); ! 1382: else if (hashflag) UpdateHashbd(side,board[f],f,t); ! 1383: } ! 1384: } ! 1385: ! 1386: ! 1387: UpdateHashbd(side,piece,f,t) ! 1388: short side,piece,f,t; ! 1389: ! 1390: /* ! 1391: hashbd contains a 32 bit "signature" of the board position. hashkey ! 1392: contains a 16 bit code used to address the hash table. When a move is ! 1393: made, XOR'ing the hashcode of moved piece on the from and to squares ! 1394: with the hashbd and hashkey values keeps things current. ! 1395: */ ! 1396: ! 1397: { ! 1398: if (f >= 0) ! 1399: { ! 1400: hashbd ^= hashcode[side][piece][f].bd; ! 1401: hashkey ^= hashcode[side][piece][f].key; ! 1402: } ! 1403: if (t >= 0) ! 1404: { ! 1405: hashbd ^= hashcode[side][piece][t].bd; ! 1406: hashkey ^= hashcode[side][piece][t].key; ! 1407: } ! 1408: } ! 1409: ! 1410: ! 1411: UpdatePieceList(side,sq,iop) ! 1412: short side,sq,iop; ! 1413: ! 1414: /* ! 1415: Update the PieceList and Pindex arrays when a piece is captured or ! 1416: when a capture is unmade. ! 1417: */ ! 1418: ! 1419: { ! 1420: register short i; ! 1421: if (iop == 1) ! 1422: { ! 1423: PieceCnt[side]--; ! 1424: for (i = Pindex[sq]; i <= PieceCnt[side]; i++) ! 1425: { ! 1426: PieceList[side][i] = PieceList[side][i+1]; ! 1427: Pindex[PieceList[side][i]] = i; ! 1428: } ! 1429: } ! 1430: else ! 1431: { ! 1432: PieceCnt[side]++; ! 1433: PieceList[side][PieceCnt[side]] = sq; ! 1434: Pindex[sq] = PieceCnt[side]; ! 1435: } ! 1436: } ! 1437: ! 1438: ! 1439: InitializeStats() ! 1440: ! 1441: /* ! 1442: Scan thru the board seeing what's on each square. If a piece is found, ! 1443: update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also ! 1444: determine the material for each side and set the hashkey and hashbd ! 1445: variables to represent the current board position. Array ! 1446: PieceList[side][indx] contains the location of all the pieces of ! 1447: either side. Array Pindex[sq] contains the indx into PieceList for a ! 1448: given square. ! 1449: */ ! 1450: ! 1451: { ! 1452: register short i,sq; ! 1453: epsquare = -1; ! 1454: for (i = 0; i < 8; i++) ! 1455: PawnCnt[white][i] = PawnCnt[black][i] = 0; ! 1456: mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0; ! 1457: PieceCnt[white] = PieceCnt[black] = 0; ! 1458: hashbd = hashkey = 0; ! 1459: for (sq = 0; sq < 64; sq++) ! 1460: if (color[sq] != neutral) ! 1461: { ! 1462: mtl[color[sq]] += value[board[sq]]; ! 1463: if (board[sq] == pawn) ! 1464: { ! 1465: pmtl[color[sq]] += valueP; ! 1466: ++PawnCnt[color[sq]][column[sq]]; ! 1467: } ! 1468: if (board[sq] == king) Pindex[sq] = 0; ! 1469: else Pindex[sq] = ++PieceCnt[color[sq]]; ! 1470: PieceList[color[sq]][Pindex[sq]] = sq; ! 1471: hashbd ^= hashcode[color[sq]][board[sq]][sq].bd; ! 1472: hashkey ^= hashcode[color[sq]][board[sq]][sq].key; ! 1473: } ! 1474: } ! 1475: ! 1476: ! 1477: pick(p1,p2) ! 1478: short p1,p2; ! 1479: ! 1480: /* ! 1481: Find the best move in the tree between indexes p1 and p2. Swap the ! 1482: best move into the p1 element. ! 1483: */ ! 1484: ! 1485: { ! 1486: register short p,s; ! 1487: short p0,s0; ! 1488: struct leaf temp; ! 1489: ! 1490: s0 = Tree[p1].score; p0 = p1; ! 1491: for (p = p1+1; p <= p2; p++) ! 1492: if ((s = Tree[p].score) > s0) ! 1493: { ! 1494: s0 = s; p0 = p; ! 1495: } ! 1496: if (p0 != p1) ! 1497: { ! 1498: temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp; ! 1499: } ! 1500: } ! 1501: ! 1502: ! 1503: repetition(cnt) ! 1504: short *cnt; ! 1505: ! 1506: /* ! 1507: Check for draw by threefold repetition. ! 1508: */ ! 1509: ! 1510: { ! 1511: register short i,c; ! 1512: short f,t,b[64]; ! 1513: unsigned short m; ! 1514: *cnt = c = 0; ! 1515: if (GameCnt > Game50+3) ! 1516: { ! 1517: /* ! 1518: memset((char *)b,0,64*sizeof(short)); ! 1519: */ ! 1520: for (i = 0; i < 64; b[i++] = 0); ! 1521: for (i = GameCnt; i > Game50; i--) ! 1522: { ! 1523: m = GameList[i].gmove; f = m>>8; t = m & 0xFF; ! 1524: if (++b[f] == 0) c--; else c++; ! 1525: if (--b[t] == 0) c--; else c++; ! 1526: if (c == 0) (*cnt)++; ! 1527: } ! 1528: } ! 1529: } ! 1530: ! 1531: #if (NEWMOVE < 3) ! 1532: int SqAtakd(sq,side) ! 1533: short sq,side; ! 1534: ! 1535: /* ! 1536: See if any piece with color 'side' ataks sq. First check for pawns ! 1537: or king, then try other pieces. Array Dcode is used to check for ! 1538: knight attacks or R,B,Q co-linearity. ! 1539: */ ! 1540: ! 1541: { ! 1542: register short m,d; ! 1543: short i,m0,m1,loc,piece,*PL; ! 1544: ! 1545: m1 = map[sq]; ! 1546: if (side == white) m = m1-0x0F; else m = m1+0x0F; ! 1547: if (!(m & 0x88)) ! 1548: if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true); ! 1549: if (side == white) m = m1-0x11; else m = m1+0x11; ! 1550: if (!(m & 0x88)) ! 1551: if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true); ! 1552: if (distance(sq,PieceList[side][0]) == 1) return(true); ! 1553: ! 1554: PL = PieceList[side]; ! 1555: for (i = 1; i <= PieceCnt[side]; i++) ! 1556: { ! 1557: loc = PL[i]; piece = board[loc]; ! 1558: if (piece == pawn) continue; ! 1559: m0 = map[loc]; d = Dcode[abs(m1-m0)]; ! 1560: if (d == 0 || (Pdir[d] & pbit[piece]) == 0) continue; ! 1561: if (piece == knight) return(true); ! 1562: else ! 1563: { ! 1564: if (m1 < m0) d = -d; ! 1565: for (m = m0+d; m != m1; m += d) ! 1566: if (color[unmap[m]] != neutral) break; ! 1567: if (m == m1) return(true); ! 1568: } ! 1569: } ! 1570: return(false); ! 1571: } ! 1572: #endif ! 1573: ! 1574: #if (NEWMOVE < 2) ! 1575: ataks(side,a) ! 1576: short side,*a; ! 1577: ! 1578: /* ! 1579: Fill array atak[][] with info about ataks to a square. Bits 8-15 ! 1580: are set if the piece (king..pawn) ataks the square. Bits 0-7 ! 1581: contain a count of total ataks to the square. ! 1582: */ ! 1583: ! 1584: { ! 1585: register short u,m; ! 1586: short d,c,j,j1,j2,piece,i,m0,sq,*PL; ! 1587: ! 1588: /* ! 1589: memset((char *)a,0,64*sizeof(short)); ! 1590: */ ! 1591: for (u = 0; u < 64; a[u++] = 0); ! 1592: Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1; ! 1593: PL = PieceList[side]; ! 1594: for (i = 0; i <= PieceCnt[side]; i++) ! 1595: { ! 1596: sq = PL[i]; ! 1597: m0 = map[sq]; ! 1598: piece = board[sq]; ! 1599: c = control[piece]; j1 = Dstart[piece]; j2 = Dstop[piece]; ! 1600: if (sweep[piece]) ! 1601: for (j = j1; j <= j2; j++) ! 1602: { ! 1603: d = Dir[j]; m = m0+d; ! 1604: while (!(m & 0x88)) ! 1605: { ! 1606: u = unmap[m]; ! 1607: a[u] = ++a[u] | c; ! 1608: if (color[u] == neutral) m += d; ! 1609: else break; ! 1610: } ! 1611: } ! 1612: else ! 1613: for (j = j1; j <= j2; j++) ! 1614: if (!((m = m0+Dir[j]) & 0x88)) ! 1615: { ! 1616: u = unmap[m]; ! 1617: a[u] = ++a[u] | c; ! 1618: } ! 1619: } ! 1620: } ! 1621: #endif ! 1622: ! 1623: /* ............ POSITIONAL EVALUATION ROUTINES ............ */ ! 1624: ! 1625: ScorePosition(side,score) ! 1626: short side,*score; ! 1627: ! 1628: /* ! 1629: Perform normal static evaluation of board position. A score is ! 1630: generated for each piece and these are summed to get a score for each ! 1631: side. ! 1632: */ ! 1633: ! 1634: { ! 1635: register short sq,s; ! 1636: short i,xside,pscore[3]; ! 1637: ! 1638: wking = PieceList[white][0]; bking = PieceList[black][0]; ! 1639: UpdateWeights(); ! 1640: xside = otherside[side]; ! 1641: pscore[white] = pscore[black] = 0; ! 1642: ! 1643: for (c1 = white; c1 <= black; c1++) ! 1644: { ! 1645: c2 = otherside[c1]; ! 1646: if (c1 == white) EnemyKing = bking; else EnemyKing = wking; ! 1647: atk1 = atak[c1]; atk2 = atak[c2]; ! 1648: PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; ! 1649: for (i = 0; i <= PieceCnt[c1]; i++) ! 1650: { ! 1651: sq = PieceList[c1][i]; ! 1652: s = SqValue(sq,side); ! 1653: pscore[c1] += s; ! 1654: svalue[sq] = s; ! 1655: } ! 1656: } ! 1657: if (hung[side] > 1) pscore[side] += HUNGX; ! 1658: if (hung[xside] > 1) pscore[xside] += HUNGX; ! 1659: ! 1660: *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10; ! 1661: if (dither) *score += rand() % dither; ! 1662: ! 1663: if (*score > 0 && pmtl[side] == 0) ! 1664: if (emtl[side] < valueR) *score = 0; ! 1665: else if (*score < valueR) *score /= 2; ! 1666: if (*score < 0 && pmtl[xside] == 0) ! 1667: if (emtl[xside] < valueR) *score = 0; ! 1668: else if (-*score < valueR) *score /= 2; ! 1669: ! 1670: if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200; ! 1671: if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200; ! 1672: } ! 1673: ! 1674: ! 1675: ScoreLoneKing(side,score) ! 1676: short side,*score; ! 1677: ! 1678: /* ! 1679: Static evaluation when loser has only a king and winner has no pawns ! 1680: or no pieces. ! 1681: */ ! 1682: ! 1683: { ! 1684: short winner,loser,king1,king2,s,i; ! 1685: ! 1686: UpdateWeights(); ! 1687: if (mtl[white] > mtl[black]) winner = white; else winner = black; ! 1688: loser = otherside[winner]; ! 1689: king1 = PieceList[winner][0]; king2 = PieceList[loser][0]; ! 1690: ! 1691: s = 0; ! 1692: ! 1693: if (pmtl[winner] > 0) ! 1694: for (i = 1; i <= PieceCnt[winner]; i++) ! 1695: s += ScoreKPK(side,winner,loser,king1,king2,PieceList[winner][i]); ! 1696: ! 1697: else if (emtl[winner] == valueB+valueN) ! 1698: s = ScoreKBNK(winner,king1,king2); ! 1699: ! 1700: else if (emtl[winner] > valueB) ! 1701: s = 500 + emtl[winner] - DyingKing[king2] - 2*distance(king1,king2); ! 1702: ! 1703: if (side == winner) *score = s; else *score = -s; ! 1704: } ! 1705: ! 1706: ! 1707: int ScoreKPK(side,winner,loser,king1,king2,sq) ! 1708: short side,winner,loser,king1,king2,sq; ! 1709: ! 1710: /* ! 1711: Score King and Pawns versus King endings. ! 1712: */ ! 1713: ! 1714: { ! 1715: short s,r; ! 1716: ! 1717: if (PieceCnt[winner] == 1) s = 50; else s = 120; ! 1718: if (winner == white) ! 1719: { ! 1720: if (side == loser) r = row[sq]-1; else r = row[sq]; ! 1721: if (row[king2] >= r && distance(sq,king2) < 8-r) s += 10*row[sq]; ! 1722: else s = 500+50*row[sq]; ! 1723: if (row[sq] < 6) sq += 16; else sq += 8; ! 1724: } ! 1725: else ! 1726: { ! 1727: if (side == loser) r = row[sq]+1; else r = row[sq]; ! 1728: if (row[king2] <= r && distance(sq,king2) < r+1) s += 10*(7-row[sq]); ! 1729: else s = 500+50*(7-row[sq]); ! 1730: if (row[sq] > 1) sq -= 16; else sq -= 8; ! 1731: } ! 1732: s += 8*(taxicab(king2,sq) - taxicab(king1,sq)); ! 1733: return(s); ! 1734: } ! 1735: ! 1736: ! 1737: int ScoreKBNK(winner,king1,king2) ! 1738: short winner,king1,king2; ! 1739: ! 1740: /* ! 1741: Score King+Bishop+Knight versus King endings. ! 1742: This doesn't work all that well but it's better than nothing. ! 1743: */ ! 1744: ! 1745: { ! 1746: short s; ! 1747: s = emtl[winner] - 300; ! 1748: if (KBNKsq == 0) s += KBNK[king2]; ! 1749: else s += KBNK[locn[row[king2]][7-column[king2]]]; ! 1750: s -= taxicab(king1,king2); ! 1751: s -= distance(PieceList[winner][1],king2); ! 1752: s -= distance(PieceList[winner][2],king2); ! 1753: return(s); ! 1754: } ! 1755: ! 1756: ! 1757: SqValue(sq,side) ! 1758: short sq,side; ! 1759: ! 1760: /* ! 1761: Calculate the positional value for the piece on 'sq'. ! 1762: */ ! 1763: ! 1764: { ! 1765: register short j,fyle,rank; ! 1766: short s,piece,a1,a2,in_square,r,mob,e,c; ! 1767: ! 1768: piece = board[sq]; ! 1769: a1 = (atk1[sq] & 0x4FFF); a2 = (atk2[sq] & 0x4FFF); ! 1770: rank = row[sq]; fyle = column[sq]; ! 1771: s = 0; ! 1772: if (piece == pawn && c1 == white) ! 1773: { ! 1774: s = Mwpawn[sq]; ! 1775: if (sq == 11 || sq == 12) ! 1776: if (color[sq+8] != neutral) s += PEDRNK2B; ! 1777: if ((fyle == 0 || PC1[fyle-1] == 0) && ! 1778: (fyle == 7 || PC1[fyle+1] == 0)) ! 1779: s += ISOLANI[fyle]; ! 1780: else if (PC1[fyle] > 1) s += PDOUBLED; ! 1781: if (a1 < ctlP && atk1[sq+8] < ctlP) ! 1782: { ! 1783: s += BACKWARD[a2 & 0xFF]; ! 1784: if (PC2[fyle] == 0) s += PWEAKH; ! 1785: if (color[sq+8] != neutral) s += PBLOK; ! 1786: } ! 1787: if (PC2[fyle] == 0) ! 1788: { ! 1789: if (side == black) r = rank-1; else r = rank; ! 1790: in_square = (row[bking] >= r && distance(sq,bking) < 8-r); ! 1791: if (a2 == 0 || side == white) e = 0; else e = 1; ! 1792: for (j = sq+8; j < 64; j += 8) ! 1793: if (atk2[j] >= ctlP) { e = 2; break; } ! 1794: else if (atk2[j] > 0 || color[j] != neutral) e = 1; ! 1795: if (e == 2) s += (stage*PassedPawn3[rank]) / 10; ! 1796: else if (in_square || e == 1) s += (stage*PassedPawn2[rank]) / 10; ! 1797: else if (emtl[black] > 0) s += (stage*PassedPawn1[rank]) / 10; ! 1798: else s += PassedPawn0[rank]; ! 1799: } ! 1800: } ! 1801: else if (piece == pawn && c1 == black) ! 1802: { ! 1803: s = Mbpawn[sq]; ! 1804: if (sq == 51 || sq == 52) ! 1805: if (color[sq-8] != neutral) s += PEDRNK2B; ! 1806: if ((fyle == 0 || PC1[fyle-1] == 0) && ! 1807: (fyle == 7 || PC1[fyle+1] == 0)) ! 1808: s += ISOLANI[fyle]; ! 1809: else if (PC1[fyle] > 1) s += PDOUBLED; ! 1810: if (a1 < ctlP && atk1[sq-8] < ctlP) ! 1811: { ! 1812: s += BACKWARD[a2 & 0xFF]; ! 1813: if (PC2[fyle] == 0) s += PWEAKH; ! 1814: if (color[sq-8] != neutral) s += PBLOK; ! 1815: } ! 1816: if (PC2[fyle] == 0) ! 1817: { ! 1818: if (side == white) r = rank+1; else r = rank; ! 1819: in_square = (row[wking] <= r && distance(sq,wking) < r+1); ! 1820: if (a2 == 0 || side == black) e = 0; else e = 1; ! 1821: for (j = sq-8; j >= 0; j -= 8) ! 1822: if (atk2[j] >= ctlP) { e = 2; break; } ! 1823: else if (atk2[j] > 0 || color[j] != neutral) e = 1; ! 1824: if (e == 2) s += (stage*PassedPawn3[7-rank]) / 10; ! 1825: else if (in_square || e == 1) s += (stage*PassedPawn2[7-rank]) / 10; ! 1826: else if (emtl[white] > 0) s += (stage*PassedPawn1[7-rank]) / 10; ! 1827: else s += PassedPawn0[7-rank]; ! 1828: } ! 1829: } ! 1830: else if (piece == knight) ! 1831: { ! 1832: s = Mknight[c1][sq]; ! 1833: } ! 1834: else if (piece == bishop) ! 1835: { ! 1836: s = Mbishop[c1][sq]; ! 1837: BRscan(sq,&s,&mob); ! 1838: s += BMBLTY[mob]; ! 1839: } ! 1840: else if (piece == rook) ! 1841: { ! 1842: s += RookBonus; ! 1843: BRscan(sq,&s,&mob); ! 1844: s += RMBLTY[mob]; ! 1845: if (PC1[fyle] == 0) s += RHOPN; ! 1846: if (PC2[fyle] == 0) s += RHOPNX; ! 1847: if (rank == rank7[c1] && pmtl[c2] > 100) s += 10; ! 1848: if (stage > 2) s += 14 - taxicab(sq,EnemyKing); ! 1849: } ! 1850: else if (piece == queen) ! 1851: { ! 1852: if (stage > 2) s += 14 - taxicab(sq,EnemyKing); ! 1853: if (distance(sq,EnemyKing) < 3) s += 12; ! 1854: } ! 1855: else if (piece == king) ! 1856: { ! 1857: s = Mking[c1][sq]; ! 1858: if (KSFTY > 0) ! 1859: if (Developed[c2] || stage > 0) KingScan(sq,&s); ! 1860: if (castld[c1]) s += KCASTLD; ! 1861: else if (kingmoved[c1]) s += KMOVD; ! 1862: ! 1863: if (PC1[fyle] == 0) s += KHOPN; ! 1864: if (PC2[fyle] == 0) s += KHOPNX; ! 1865: if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7) ! 1866: { ! 1867: if (PC1[fyle-1] == 0) s += KHOPN; ! 1868: if (PC2[fyle-1] == 0) s += KHOPNX; ! 1869: } ! 1870: if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0) ! 1871: { ! 1872: if (PC1[fyle+1] == 0) s += KHOPN; ! 1873: if (PC2[fyle+1] == 0) s += KHOPNX; ! 1874: } ! 1875: if (fyle == 2) ! 1876: { ! 1877: if (PC1[0] == 0) s += KHOPN; ! 1878: if (PC2[0] == 0) s += KHOPNX; ! 1879: } ! 1880: if (fyle == 5) ! 1881: { ! 1882: if (PC1[7] == 0) s += KHOPN; ! 1883: if (PC2[7] == 0) s += KHOPNX; ! 1884: } ! 1885: } ! 1886: ! 1887: if (a2 > 0) ! 1888: { ! 1889: c = (control[piece] & 0x4FFF); ! 1890: if (a1 == 0 || a2 > c+1) ! 1891: { ! 1892: s += HUNGP; ! 1893: ++hung[c1]; ! 1894: if (piece != king && trapped(sq,piece)) ++hung[c1]; ! 1895: } ! 1896: else if (piece != pawn || a2 > a1) ! 1897: if (a2 >= c || a1 < ctlP) s += ATAKD; ! 1898: } ! 1899: return(s); ! 1900: } ! 1901: ! 1902: #if (NEWMOVE > 6) ! 1903: KingScan(sq,s) ! 1904: short sq,*s; ! 1905: ! 1906: /* ! 1907: Assign penalties if king can be threatened by checks, if squares ! 1908: near the king are controlled by the enemy (especially the queen), ! 1909: or if there are no pawns near the king. ! 1910: */ ! 1911: ! 1912: #define ScoreThreat\ ! 1913: if (color[u] != c2)\ ! 1914: if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\ ! 1915: else *s -= 3 ! 1916: ! 1917: { ! 1918: register short m,u; ! 1919: short d,i,m0,cnt,ok; ! 1920: ! 1921: cnt = 0; ! 1922: m0 = map[sq]; ! 1923: if (HasBishop[c2] || HasQueen[c2]) ! 1924: for (i = Dstart[bishop]; i <= Dstop[bishop]; i++) ! 1925: { ! 1926: d = Dir[i]; m = m0+d; ! 1927: while (!(m & 0x88)) ! 1928: { ! 1929: u = unmap[m]; ! 1930: if (atk2[u] & ctlBQ) ScoreThreat; ! 1931: if (color[u] != neutral) break; ! 1932: m += d; ! 1933: } ! 1934: } ! 1935: if (HasRook[c2] || HasQueen[c2]) ! 1936: for (i = Dstart[rook]; i <= Dstop[rook]; i++) ! 1937: { ! 1938: d = Dir[i]; m = m0+d; ! 1939: while (!(m & 0x88)) ! 1940: { ! 1941: u = unmap[m]; ! 1942: if (atk2[u] & ctlRQ) ScoreThreat; ! 1943: if (color[u] != neutral) break; ! 1944: m += d; ! 1945: } ! 1946: } ! 1947: if (HasKnight[c2]) ! 1948: for (i = Dstart[knight]; i <= Dstop[knight]; i++) ! 1949: if (!((m = m0+Dir[i]) & 0x88)) ! 1950: { ! 1951: u = unmap[m]; ! 1952: if (atk2[u] & ctlNN) ScoreThreat; ! 1953: } ! 1954: *s += (KSFTY*Kthreat[cnt]) / 16; ! 1955: ! 1956: cnt = 0; ok = false; ! 1957: m0 = map[sq]; ! 1958: for (i = Dstart[king]; i <= Dstop[king]; i++) ! 1959: if (!((m = m0+Dir[i]) & 0x88)) ! 1960: { ! 1961: u = unmap[m]; ! 1962: if (board[u] == pawn) ok = true; ! 1963: if (atk2[u] > atk1[u]) ! 1964: { ! 1965: ++cnt; ! 1966: if (atk2[u] & ctlQ) ! 1967: if (atk2[u] > ctlQ+1 && atk1[u] < ctlQ) *s -= 4*KSFTY; ! 1968: } ! 1969: } ! 1970: if (!ok) *s -= KSFTY; ! 1971: if (cnt > 1) *s -= KSFTY; ! 1972: } ! 1973: #endif ! 1974: ! 1975: #if (NEWMOVE < 4) ! 1976: BRscan(sq,s,mob) ! 1977: short sq,*s,*mob; ! 1978: ! 1979: /* ! 1980: Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the ! 1981: hung[] array if a pin is found. ! 1982: */ ! 1983: ! 1984: { ! 1985: register short m,u; ! 1986: short d,j,m0,piece,pin,*Kf; ! 1987: ! 1988: Kf = Kfield[c1]; ! 1989: *mob = 0; ! 1990: m0 = map[sq]; piece = board[sq]; ! 1991: for (j = Dstart[piece]; j <= Dstop[piece]; j++) ! 1992: { ! 1993: pin = -1; ! 1994: d = Dir[j]; m = m0+d; ! 1995: while (!(m & 0x88)) ! 1996: { ! 1997: u = unmap[m]; *s += Kf[u]; ! 1998: if (color[u] == neutral) ! 1999: { ! 2000: (*mob)++; ! 2001: m += d; ! 2002: } ! 2003: else if (pin < 0) ! 2004: { ! 2005: if (board[u] == pawn || board[u] == king) break; ! 2006: pin = u; ! 2007: m += d; ! 2008: } ! 2009: else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0)) ! 2010: { ! 2011: if (color[pin] == c2) ! 2012: { ! 2013: *s += PINVAL; ! 2014: if (atk2[pin] == 0 || ! 2015: atk1[pin] > control[board[pin]]+1) ! 2016: ++hung[c2]; ! 2017: } ! 2018: else *s += XRAY; ! 2019: break; ! 2020: } ! 2021: else break; ! 2022: } ! 2023: } ! 2024: } ! 2025: #endif ! 2026: ! 2027: #if (NEWMOVE > 5) ! 2028: int trapped(sq,piece) ! 2029: short sq,piece; ! 2030: ! 2031: /* ! 2032: See if the attacked piece has unattacked squares to move to. ! 2033: */ ! 2034: ! 2035: { ! 2036: register short u,m,d; ! 2037: short i,m0; ! 2038: ! 2039: m0 = map[sq]; ! 2040: if (sweep[piece]) ! 2041: for (i = Dstart[piece]; i <= Dstop[piece]; i++) ! 2042: { ! 2043: d = Dir[i]; m = m0+d; ! 2044: while (!(m & 0x88)) ! 2045: { ! 2046: u = unmap[m]; ! 2047: if (color[u] == c1) break; ! 2048: if (atk2[u] == 0 || board[u] >= piece) return(false); ! 2049: if (color[u] == c2) break; ! 2050: m += d; ! 2051: } ! 2052: } ! 2053: else if (piece == pawn) ! 2054: { ! 2055: if (c1 == white) u = sq+8; else u = sq-8; ! 2056: if (color[u] == neutral && atk1[u] >= atk2[u]) ! 2057: return(false); ! 2058: if (!((m = m0+Dir[Dpwn[c1]]) & 0x88)) ! 2059: if (color[unmap[m]] == c2) return(false); ! 2060: if (!((m = m0+Dir[Dpwn[c1]+1]) & 0x88)) ! 2061: if (color[unmap[m]] == c2) return(false); ! 2062: } ! 2063: else ! 2064: { ! 2065: for (i = Dstart[piece]; i <= Dstop[piece]; i++) ! 2066: if (!((m = m0+Dir[i]) & 0x88)) ! 2067: { ! 2068: u = unmap[m]; ! 2069: if (color[u] != c1) ! 2070: if (atk2[u] == 0 || board[u] >= piece) return(false); ! 2071: } ! 2072: } ! 2073: return(true); ! 2074: } ! 2075: #endif ! 2076: ! 2077: ExaminePosition() ! 2078: ! 2079: /* ! 2080: This is done one time before the search is started. Set up arrays ! 2081: Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the ! 2082: SqValue() function to determine the positional value of each piece. ! 2083: */ ! 2084: ! 2085: { ! 2086: register short i,sq; ! 2087: short wpadv,bpadv,wstrong,bstrong,z,side,pp,j,val,Pd,fyle,rank; ! 2088: ! 2089: wking = PieceList[white][0]; bking = PieceList[black][0]; ! 2090: ataks(white,atak[white]); ataks(black,atak[black]); ! 2091: Zwmtl = Zbmtl = 0; ! 2092: UpdateWeights(); ! 2093: HasPawn[white] = HasPawn[black] = 0; ! 2094: HasKnight[white] = HasKnight[black] = 0; ! 2095: HasBishop[white] = HasBishop[black] = 0; ! 2096: HasRook[white] = HasRook[black] = 0; ! 2097: HasQueen[white] = HasQueen[black] = 0; ! 2098: for (side = white; side <= black; side++) ! 2099: for (i = 0; i <= PieceCnt[side]; i++) ! 2100: switch (board[PieceList[side][i]]) ! 2101: { ! 2102: case pawn : ++HasPawn[side]; break; ! 2103: case knight : ++HasKnight[side]; break; ! 2104: case bishop : ++HasBishop[side]; break; ! 2105: case rook : ++HasRook[side]; break; ! 2106: case queen : ++HasQueen[side]; break; ! 2107: } ! 2108: if (!Developed[white]) ! 2109: Developed[white] = (board[1] != knight && board[2] != bishop && ! 2110: board[5] != bishop && board[6] != knight); ! 2111: if (!Developed[black]) ! 2112: Developed[black] = (board[57] != knight && board[58] != bishop && ! 2113: board[61] != bishop && board[62] != knight); ! 2114: if (!PawnStorm && stage < 5) ! 2115: PawnStorm = ((column[wking] < 3 && column[bking] > 4) || ! 2116: (column[wking] > 4 && column[bking] < 3)); ! 2117: ! 2118: CopyBoard(pknight,Mknight[white]); ! 2119: CopyBoard(pknight,Mknight[black]); ! 2120: CopyBoard(pbishop,Mbishop[white]); ! 2121: CopyBoard(pbishop,Mbishop[black]); ! 2122: BlendBoard(KingOpening,KingEnding,Mking[white]); ! 2123: BlendBoard(KingOpening,KingEnding,Mking[black]); ! 2124: ! 2125: for (sq = 0; sq < 64; sq++) ! 2126: { ! 2127: fyle = column[sq]; rank = row[sq]; ! 2128: wstrong = bstrong = true; ! 2129: for (i = sq; i < 64; i += 8) ! 2130: if (atak[black][i] >= ctlP) wstrong = false; ! 2131: for (i = sq; i >= 0; i -= 8) ! 2132: if (atak[white][i] >= ctlP) bstrong = false; ! 2133: wpadv = bpadv = PADVNCM; ! 2134: if ((fyle == 0 || PawnCnt[white][fyle-1] == 0) && ! 2135: (fyle == 7 || PawnCnt[white][fyle+1] == 0)) wpadv = PADVNCI; ! 2136: if ((fyle == 0 || PawnCnt[black][fyle-1] == 0) && ! 2137: (fyle == 7 || PawnCnt[black][fyle+1] == 0)) bpadv = PADVNCI; ! 2138: Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10; ! 2139: Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10; ! 2140: Mwpawn[sq] += PawnBonus; Mbpawn[sq] += PawnBonus; ! 2141: if (castld[white] || kingmoved[white]) ! 2142: { ! 2143: if ((fyle < 3 || fyle > 4) && distance(sq,wking) < 3) ! 2144: Mwpawn[sq] += PAWNSHIELD; ! 2145: } ! 2146: else if (rank < 3 && (fyle < 2 || fyle > 5)) ! 2147: Mwpawn[sq] += PAWNSHIELD / 2; ! 2148: if (castld[black] || kingmoved[black]) ! 2149: { ! 2150: if ((fyle < 3 || fyle > 4) && distance(sq,bking) < 3) ! 2151: Mbpawn[sq] += PAWNSHIELD; ! 2152: } ! 2153: else if (rank > 4 && (fyle < 2 || fyle > 5)) ! 2154: Mbpawn[sq] += PAWNSHIELD / 2; ! 2155: if (PawnStorm) ! 2156: { ! 2157: if ((column[wking] < 4 && fyle > 4) || ! 2158: (column[wking] > 3 && fyle < 3)) Mwpawn[sq] += 3*rank - 21; ! 2159: if ((column[bking] < 4 && fyle > 4) || ! 2160: (column[bking] > 3 && fyle < 3)) Mbpawn[sq] -= 3*rank; ! 2161: } ! 2162: ! 2163: Mknight[white][sq] += 5 - distance(sq,bking); ! 2164: Mknight[white][sq] += 5 - distance(sq,wking); ! 2165: Mknight[black][sq] += 5 - distance(sq,wking); ! 2166: Mknight[black][sq] += 5 - distance(sq,bking); ! 2167: Mbishop[white][sq] += BishopBonus; ! 2168: Mbishop[black][sq] += BishopBonus; ! 2169: for (i = 0; i <= PieceCnt[black]; i++) ! 2170: if (distance(sq,PieceList[black][i]) < 3) ! 2171: Mknight[white][sq] += KNIGHTPOST; ! 2172: for (i = 0; i <= PieceCnt[white]; i++) ! 2173: if (distance(sq,PieceList[white][i]) < 3) ! 2174: Mknight[black][sq] += KNIGHTPOST; ! 2175: if (wstrong) Mknight[white][sq] += KNIGHTSTRONG; ! 2176: if (bstrong) Mknight[black][sq] += KNIGHTSTRONG; ! 2177: if (wstrong) Mbishop[white][sq] += BISHOPSTRONG; ! 2178: if (bstrong) Mbishop[black][sq] += BISHOPSTRONG; ! 2179: ! 2180: if (HasBishop[white] == 2) Mbishop[white][sq] += 8; ! 2181: if (HasBishop[black] == 2) Mbishop[black][sq] += 8; ! 2182: if (HasKnight[white] == 2) Mknight[white][sq] += 5; ! 2183: if (HasKnight[black] == 2) Mknight[black][sq] += 5; ! 2184: ! 2185: if (board[sq] == bishop) ! 2186: if (rank % 2 == fyle % 2) KBNKsq = 0; else KBNKsq = 7; ! 2187: ! 2188: Kfield[white][sq] = Kfield[black][sq] = 0; ! 2189: if (distance(sq,wking) == 1) Kfield[black][sq] = KATAK; ! 2190: if (distance(sq,bking) == 1) Kfield[white][sq] = KATAK; ! 2191: ! 2192: Pd = 0; ! 2193: for (i = 0; i < 64; i++) ! 2194: if (board[i] == pawn) ! 2195: { ! 2196: if (color[i] == white) ! 2197: { ! 2198: pp = true; ! 2199: if (row[i] == 6) z = i+8; else z = i+16; ! 2200: for (j = i+8; j < 64; j += 8) ! 2201: if (atak[black][j] > ctlP || board[j] == pawn) pp = false; ! 2202: } ! 2203: else ! 2204: { ! 2205: pp = true; ! 2206: if (row[i] == 1) z = i-8; else z = i-16; ! 2207: for (j = i-8; j >= 0; j -= 8) ! 2208: if (atak[white][j] > ctlP || board[j] == pawn) pp = false; ! 2209: } ! 2210: if (pp) Pd += 5*taxicab(sq,z); else Pd += taxicab(sq,z); ! 2211: } ! 2212: if (Pd != 0) ! 2213: { ! 2214: val = (Pd*stage2) / 10; ! 2215: Mking[white][sq] -= val; ! 2216: Mking[black][sq] -= val; ! 2217: } ! 2218: } ! 2219: } ! 2220: ! 2221: ! 2222: UpdateWeights() ! 2223: ! 2224: /* ! 2225: If material balance has changed, determine the values for the ! 2226: positional evaluation terms. ! 2227: */ ! 2228: ! 2229: { ! 2230: short tmtl; ! 2231: ! 2232: if (mtl[white] != Zwmtl || mtl[black] != Zbmtl) ! 2233: { ! 2234: Zwmtl = mtl[white]; Zbmtl = mtl[black]; ! 2235: emtl[white] = Zwmtl - pmtl[white] - valueK; ! 2236: emtl[black] = Zbmtl - pmtl[black] - valueK; ! 2237: tmtl = emtl[white] + emtl[black]; ! 2238: if (tmtl > 6600) stage = 0; ! 2239: else if (tmtl < 1400) stage = 10; ! 2240: else stage = (6600-tmtl) / 520; ! 2241: if (tmtl > 3600) stage2 = 0; ! 2242: else if (tmtl < 1400) stage2 = 10; ! 2243: else stage2 = (3600-tmtl) / 220; ! 2244: ! 2245: PEDRNK2B = -15; /* centre pawn on 2nd rank & blocked */ ! 2246: PBLOK = -4; /* blocked backward pawn */ ! 2247: PDOUBLED = -14; /* doubled pawn */ ! 2248: PWEAKH = -4; /* weak pawn on half open file */ ! 2249: PAWNSHIELD = 10-stage; /* pawn near friendly king */ ! 2250: PADVNCM = 10; /* advanced pawn multiplier */ ! 2251: PADVNCI = 7; /* muliplier for isolated pawn */ ! 2252: PawnBonus = stage; ! 2253: ! 2254: KNIGHTPOST = (stage+2)/3; /* knight near enemy pieces */ ! 2255: KNIGHTSTRONG = (stage+6)/2; /* occupies pawn hole */ ! 2256: ! 2257: BISHOPSTRONG = (stage+6)/2; /* occupies pawn hole */ ! 2258: BishopBonus = 2*stage; ! 2259: ! 2260: RHOPN = 10; /* rook on half open file */ ! 2261: RHOPNX = 4; ! 2262: RookBonus = 6*stage; ! 2263: ! 2264: XRAY = 8; /* Xray attack on piece */ ! 2265: PINVAL = 10; /* Pin */ ! 2266: ! 2267: KHOPN = (3*stage-30) / 2; /* king on half open file */ ! 2268: KHOPNX = KHOPN / 2; ! 2269: KCASTLD = 10 - stage; ! 2270: KMOVD = -40 / (stage+1); /* king moved before castling */ ! 2271: KATAK = (10-stage) / 2; /* B,R attacks near enemy king */ ! 2272: if (stage < 8) KSFTY = 16-2*stage; else KSFTY = 0; ! 2273: ! 2274: ATAKD = -6; /* defender > attacker */ ! 2275: HUNGP = -8; /* each hung piece */ ! 2276: HUNGX = -12; /* extra for >1 hung piece */ ! 2277: } ! 2278: } ! 2279: ! 2280: #if (NEWMOVE < 1) ! 2281: int distance(a,b) ! 2282: short a,b; ! 2283: { ! 2284: register short d1,d2; ! 2285: ! 2286: d1 = abs(column[a]-column[b]); ! 2287: d2 = abs(row[a]-row[b]); ! 2288: return(d1 > d2 ? d1 : d2); ! 2289: } ! 2290: #endif ! 2291: ! 2292: BlendBoard(a,b,c) ! 2293: short a[64],b[64],c[64]; ! 2294: { ! 2295: register int sq; ! 2296: for (sq = 0; sq < 64; sq++) ! 2297: c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10; ! 2298: } ! 2299: ! 2300: ! 2301: CopyBoard(a,b) ! 2302: short a[64],b[64]; ! 2303: { ! 2304: register int sq; ! 2305: for (sq = 0; sq < 64; sq++) ! 2306: b[sq] = a[sq]; ! 2307: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.