Annotation of 43BSDReno/games/chess/gnuchess.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.