home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / new / game / think / ignuchess / source / gnuchess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-21  |  67.6 KB  |  2,487 lines

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