Annotation of 43BSDReno/games/chess/gnuchess.c, revision 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.