home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 25: Programming / pc_actual_25.iso / Delphi / CheesboardComponent / bcb3 / CHTHREAD.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-27  |  32.8 KB  |  1,126 lines

  1. //---------------------------------------------------------------------------
  2. #include <vcl\vcl.h>
  3. #pragma hdrstop
  4.  
  5. #include "CHESSBRD.H"
  6. #include "CHTHREAD.H"
  7.  
  8.  
  9. // Invokes the thread  at once
  10. __fastcall ChessThread::ChessThread(char *position, bool *whitetomove,
  11.     Square *enpassant, CastleSet *castling, bool *thinking,
  12.     int *searchdepth, MoveFunc move) : TThread(false)
  13. {
  14.     StopThinkingNow=FALSE;
  15.     Thinking=thinking;
  16.     Position=position;
  17.     WhiteToMove=whitetomove;
  18.     EnPassant=enpassant;
  19.     Castling=castling;
  20.     SearchDepth=searchdepth;
  21.     Move=move;
  22.  
  23.     InitValues();
  24. }
  25.  
  26. //---------------------------------------------------------------------------
  27. void __fastcall ChessThread::Execute()
  28. {
  29.     int i;
  30.     int v;
  31.  
  32.     // Should use WaitForSingleObject(...) - but how ?
  33.     for (;;)
  34.     {
  35.         if (Terminated) break;
  36.  
  37.         if (*Thinking==TRUE)
  38.         {
  39.             for(int r=0;r<64;r++)
  40.             {
  41.                 v=ColorOfPiece((Square)(r+1));
  42.                 if      (v==Black) color[r]=DARK;
  43.                 else if (v==White) color[r]=LIGHT;
  44.                 else color[r]=EMPTY;
  45.  
  46.                 switch (Position[r+1])
  47.                 {
  48.                     case 'P':
  49.                     case 'p':{piece[r]=PAWN;  break;}
  50.                     case 'N':
  51.                     case 'n':{piece[r]=KNIGHT;break;}
  52.                     case 'B':
  53.                     case 'b':{piece[r]=BISHOP;break;}
  54.                     case 'R':
  55.                     case 'r':{piece[r]=ROOK;  break;}
  56.                     case 'Q':
  57.                     case 'q':{piece[r]=QUEEN; break;}
  58.                     case 'K':
  59.                     case 'k':{piece[r]=KING;  break;}
  60.                     default: {piece[r]=EMPTY; break;}
  61.                 }
  62.             }
  63.  
  64.         if (*WhiteToMove)
  65.             {
  66.                 side=LIGHT;
  67.                 xside=DARK;
  68.             }
  69.             else
  70.             {
  71.                 side=DARK;
  72.                 xside=LIGHT;
  73.             }
  74.  
  75.             castle=0;
  76.             if (Castling->Contains(WhiteKingSide))
  77.                 castle|=1;
  78.             if (Castling->Contains(WhiteQueenSide))
  79.                 castle|=2;
  80.             if (Castling->Contains(BlackKingSide))
  81.                 castle|=4;
  82.             if (Castling->Contains(BlackQueenSide))
  83.                 castle|=8;
  84.  
  85.             ep=*EnPassant-1;
  86.             fifty=0;
  87.             ply=0;
  88.             gen_begin[0]=0;
  89.  
  90.             nodes=0;
  91.             init_eval();
  92.             memset(history,0,sizeof(history));
  93.  
  94.             follow_pv=TRUE;
  95.  
  96.             for(i=1;i<=*SearchDepth;i++)
  97.             {
  98.                     follow_pv=TRUE;
  99.                     search(-10000,10000,i);
  100.                     if (StopThinkingNow) break;
  101.             }
  102.  
  103.             if (StopThinkingNow)
  104.             {
  105.                  *Thinking=FALSE;
  106.             }
  107.             else
  108.             {
  109.                 makemove(pv[0][0].b);
  110.                 gen();
  111.                 Synchronize(PerformMove);
  112.             }
  113.         }
  114.     }
  115.  
  116.     WaitFor();
  117. }
  118.  
  119. void __fastcall ChessThread::CancelThinking(void)
  120. {
  121.     StopThinkingNow=TRUE;
  122.     while (*Thinking) {} //Think
  123.     StopThinkingNow=FALSE;
  124. }
  125.  
  126. // Synchronizer - Modifies VCL
  127. void __fastcall ChessThread::PerformMove(void)
  128. {
  129.     if (Terminated) WaitFor();
  130.  
  131.     //Move expects *Thinking to be FALSE
  132.     *Thinking=FALSE;
  133.     if (Move (Square(pv[0][0].b.from+1),Square(pv[0][0].b.to+1))==FALSE)
  134.     {
  135.         Application->MessageBox("Engine tried to perform Illegal Move","Error",IDOK);
  136.         WaitFor();
  137.     }
  138. }
  139.  
  140. //-------------------------------------------------------------------------
  141.  
  142.  
  143. void __fastcall ChessThread::IntCopy (int *dest, const int *source, int count)
  144. {
  145.     const int *org=source;
  146.     if (dest==NULL || source==NULL) return;
  147.     for (;source<(org+count);source++,dest++)
  148.     {
  149.         *dest=*source;
  150.     }
  151.  
  152.     return;
  153. }
  154.  
  155.  
  156. int  __fastcall ChessThread::ColorOfPiece (Square sq)
  157. {
  158.     if ((Position[sq]>='b')&&(Position[sq]<='r')) return Black;
  159.     else if ((Position[sq]>='B')&&(Position[sq]<='R')) return White;
  160.     else return NoPiece;
  161. }
  162.  
  163. /* sort_pv() is called when the search function is following
  164.    the PV (Principal Variation). It looks through the current
  165.    ply's move list to see if the PV move is there. If so,
  166.    it adds 10,000,000 to the move's score so it's played first
  167.    by the search function. If not, follow_pv remains FALSE and
  168.    search() stops calling sort_pv(). */
  169.  
  170. void __fastcall ChessThread::sort_pv(void)
  171. {
  172.     int i;
  173.  
  174.     follow_pv=FALSE;
  175.     for(i=gen_begin[ply];i<gen_end[ply];i++)
  176.         if(gen_dat[i].m.i==pv[0][ply].i) {
  177.             follow_pv=TRUE;
  178.             gen_dat[i].score+=10000000;
  179.             return;
  180.         }
  181. }
  182.  
  183.  
  184. /* sort() searches the current ply's move list from 'from'
  185.    to the end to find the move with the highest score. Then it
  186.    swaps that move and the 'from' move so the move with the
  187.    highest score gets searched next, and hopefully produces
  188.    a cutoff. */
  189.  
  190. void __fastcall ChessThread::sort(int from)
  191. {
  192.     int i;
  193.     int bs;  /* best score */
  194.     int bi;  /* best i */
  195.     gen_rec g;
  196.  
  197.     bs=-1;
  198.     for(i=from;i<gen_end[ply];i++)
  199.         if(gen_dat[i].score>bs) {
  200.             bs=gen_dat[i].score;
  201.             bi=i;
  202.         }
  203.     g=gen_dat[from];
  204.     gen_dat[from]=gen_dat[bi];
  205.     gen_dat[bi]=g;
  206. }
  207.  
  208.  
  209. /* quiesce() is a recursive minimax search function with
  210.    alpha-beta cutoffs. In other words, negamax. It basically
  211.    only searches capture sequences and allows the evaluation
  212.    function to cut the search off (and set alpha). The idea
  213.    is to find a position where there isn't a lot going on
  214.    so the static evaluation function will work. */
  215.  
  216. int __fastcall ChessThread::quiesce(int alpha,int beta)
  217. {
  218.     int i,j,x;
  219.     BOOL c;  /* in check */
  220.     BOOL f;  /* legal move found */
  221.  
  222.     nodes++;
  223.     pv_length[ply]=ply;
  224.     c=in_check(side);
  225.  
  226.     /* if we're in check, try all moves to get out. (not
  227.        necessary, just something I decided to do) */
  228.     if(c)
  229.         gen();
  230.  
  231.     /* otherwise, use the evaluation function. */
  232.     else {
  233.         x=eval();
  234.         if(x>=beta)
  235.             return(beta);
  236.         if(x>alpha)
  237.             alpha=x;
  238.         gen_caps();
  239.     }
  240.     if(follow_pv)  /* are we following the PV? */
  241.         sort_pv();
  242.     f=FALSE;
  243.  
  244.     /* loop through the moves */
  245.     for(i=gen_begin[ply];i<gen_end[ply];i++) {
  246.         sort(i);
  247.         if(!makemove(gen_dat[i].m.b))
  248.             continue;
  249.         f=TRUE;  /* we found a legal move! */
  250.         x=-quiesce(-beta,-alpha);
  251.         takeback();
  252.         if(x>alpha) {
  253.             if(x>=beta)
  254.                 return(beta);
  255.             alpha=x;
  256.  
  257.             /* update the PV */
  258.             pv[ply][ply]=gen_dat[i].m;
  259.             for(j=ply+1;j<pv_length[ply+1];j++)
  260.                 pv[ply][j]=pv[ply+1][j];
  261.             pv_length[ply]=pv_length[ply+1];
  262.         }
  263.     }
  264.  
  265.     /* if we're in check and there aren't any legal moves,
  266.        well, we lost */
  267.     if((!f)&&c)
  268.         return(-10000+ply);
  269.     return(alpha);
  270. }
  271.  
  272.  
  273. /* search() does just that, in negamax fashion */
  274.  
  275. int __fastcall ChessThread::search(int alpha,int beta,int depth)
  276. {
  277.     int i,j,x;
  278.     BOOL c,f;
  279.  
  280.     /* we're as deep as we want to be; call quiesce() to get
  281.        a reasonable score and return it. */
  282.     if(!depth)
  283.         return(quiesce(alpha,beta));
  284.     nodes++;
  285.     pv_length[ply]=ply;
  286.  
  287.     /* are we in check? if so, we want to search deeper */
  288.     c=in_check(side);
  289.     if(c)
  290.         depth++;
  291.     gen();
  292.     if(follow_pv)  /* are we following the PV? */
  293.         sort_pv();
  294.     f=FALSE;
  295.  
  296.     /* loop through the moves */
  297.     for(i=gen_begin[ply];i<gen_end[ply];i++) {
  298.         sort(i);
  299.         if(!makemove(gen_dat[i].m.b))
  300.             continue;
  301.  
  302.         //
  303.         if (StopThinkingNow) return -1;
  304.  
  305.         f=TRUE;
  306.         x=-search(-beta,-alpha,depth-1);
  307.         takeback();
  308.         if(x>alpha) {
  309.  
  310.             /* this move caused a cutoff, so increase the history
  311.                value so it gets ordered high next time we can
  312.                search it */
  313.             history[gen_dat[i].m.b.from][gen_dat[i].m.b.to]+=depth;
  314.             if(x>=beta)
  315.                 return(beta);
  316.             alpha=x;
  317.  
  318.             /* update the PV */
  319.             pv[ply][ply]=gen_dat[i].m;
  320.             for(j=ply+1;j<pv_length[ply+1];j++)
  321.                 pv[ply][j]=pv[ply+1][j];
  322.             pv_length[ply]=pv_length[ply+1];
  323.         }
  324.     }
  325.  
  326.     /* no legal moves? then we're in checkmate or stalemate */
  327.     if(!f) {
  328.         if(c)
  329.             return(-10000+ply);
  330.         else
  331.             return(0);
  332.     }
  333.  
  334.     /* fifty move draw rule */
  335.     if(fifty>100)
  336.         return(0);
  337.     return(alpha);
  338. }
  339.  
  340.  
  341. /* think() calls search() iteratively and prints the results
  342.    after every iteration. */
  343.  
  344.  
  345. void __fastcall ChessThread::init(void)
  346. {
  347.     int i;
  348.  
  349.     for(i=0;i<64;i++) {
  350.         color[i]=init_color[i];
  351.         piece[i]=init_piece[i];
  352.     }
  353.     side=LIGHT;
  354.     xside=DARK;
  355.     castle=15;
  356.     ep=-1;
  357.     fifty=0;
  358.     ply=0;
  359.     gen_begin[0]=0;
  360. }
  361.  
  362.  
  363. /* in_check() returns TRUE if side s is in check and FALSE
  364.    otherwise. It just scans the board to find side s's king
  365.    and calls attack() to see if it's being attacked. */
  366.  
  367. BOOL __fastcall ChessThread::in_check(int s)
  368. {
  369.     int i;
  370.  
  371.     for(i=0;i<64;i++)
  372.         if(color[i]==s&&piece[i]==KING)
  373.             return(attack(i,s^1));
  374.     return FALSE;
  375. }
  376.  
  377.  
  378. /* attack returns TRUE if square sq is being attacked by side
  379.    s and FALSE otherwise. */
  380.  
  381. BOOL __fastcall ChessThread::attack(int sq,int s)
  382. {
  383.     int i,j,n;
  384.  
  385.     for(i=0;i<64;i++)
  386.         if(color[i]==s) {
  387.             if(piece[i]==PAWN) {
  388.                 if(s==LIGHT) {
  389.                     if(FILE(i)!=0&&i-9==sq)
  390.                         return(TRUE);
  391.                     if(FILE(i)!=7&&i-7==sq)
  392.                         return(TRUE);
  393.                 }
  394.                 else {
  395.                     if(FILE(i)!=0&&i+7==sq)
  396.                         return(TRUE);
  397.                     if(FILE(i)!=7&&i+9==sq)
  398.                         return(TRUE);
  399.                 }
  400.             }
  401.             else
  402.                 for(j=0;j<offsets[piece[i]];j++)
  403.                     for(n=i;;) {
  404.                         n=mailbox[mailbox64[n]+offset[piece[i]][j]];
  405.                         if(n==-1)
  406.                             break;
  407.                         if(n==sq)
  408.                             return(TRUE);
  409.                         if(color[n]!=EMPTY)
  410.                             break;
  411.                         if(!slide[piece[i]])
  412.                             break;
  413.                     }
  414.         }
  415.     return(FALSE);
  416. }
  417.  
  418.  
  419. /* gen() generates pseudo-legal moves for the current position.
  420.    It scans the board to find friendly pieces and then determines
  421.    what squares they attack. When it finds a piece/square
  422.    combination, it calls gen_push to put the move on the "move
  423.    stack." */
  424.  
  425. void __fastcall ChessThread::gen(void)
  426. {
  427.     int i,j,n;
  428.  
  429.     /* so far, we have no moves for the current ply */
  430.     gen_end[ply]=gen_begin[ply];
  431.     for(i=0;i<64;i++)
  432.         if(color[i]==side) {
  433.             if(piece[i]==PAWN) {
  434.                 if(side==LIGHT) {
  435.                     if(FILE(i)!=0&&color[i-9]==DARK)
  436.                         gen_push(i,i-9,17);
  437.                     if(FILE(i)!=7&&color[i-7]==DARK)
  438.                         gen_push(i,i-7,17);
  439.                     if(color[i-8]==EMPTY) {
  440.                         gen_push(i,i-8,16);
  441.                         if(i>=48&&color[i-16]==EMPTY)
  442.                             gen_push(i,i-16,24);
  443.                     }
  444.                 }
  445.                 else {
  446.                     if(FILE(i)!=0&&color[i+7]==LIGHT)
  447.                         gen_push(i,i+7,17);
  448.                     if(FILE(i)!=7&&color[i+9]==LIGHT)
  449.                         gen_push(i,i+9,17);
  450.                     if(color[i+8]==EMPTY) {
  451.                         gen_push(i,i+8,16);
  452.                         if(i<=15&&color[i+16]==EMPTY)
  453.                             gen_push(i,i+16,24);
  454.                     }
  455.                 }
  456.             }
  457.             else
  458.                 for(j=0;j<offsets[piece[i]];j++)
  459.                     for(n=i;;) {
  460.                         n=mailbox[mailbox64[n]+offset[piece[i]][j]];
  461.                         if(n==-1)
  462.                             break;
  463.                         if(color[n]!=EMPTY) {
  464.                             if(color[n]==xside)
  465.                                 gen_push(i,n,1);
  466.                             break;
  467.                         }
  468.                         gen_push(i,n,0);
  469.                         if(!slide[piece[i]])
  470.                             break;
  471.                     }
  472.         }
  473.  
  474.     /* generate castle moves */
  475.     if(side==LIGHT) {
  476.         if(castle&1)
  477.             gen_push(60,62,2);
  478.         if(castle&2)
  479.             gen_push(60,58,2);
  480.     }
  481.     else {
  482.         if(castle&4)
  483.             gen_push(4,6,2);
  484.         if(castle&8)
  485.             gen_push(4,2,2);
  486.     }
  487.  
  488.     /* generate en passant moves */
  489.     if(ep!=-1) {
  490.         if(side==LIGHT) {
  491.             if(FILE(ep)!=0&&color[ep+7]==LIGHT&&piece[ep+7]==PAWN)
  492.                 gen_push(ep+7,ep,21);
  493.             if(FILE(ep)!=7&&color[ep+9]==LIGHT&&piece[ep+9]==PAWN)
  494.                 gen_push(ep+9,ep,21);
  495.         }
  496.         else {
  497.             if(FILE(ep)!=0&&color[ep-9]==DARK&&piece[ep-9]==PAWN)
  498.                 gen_push(ep-9,ep,21);
  499.             if(FILE(ep)!=7&&color[ep-7]==DARK&&piece[ep-7]==PAWN)
  500.                 gen_push(ep-7,ep,21);
  501.         }
  502.     }
  503.  
  504.     /* the next ply's moves need to start where the current
  505.        ply's end */
  506.     gen_begin[ply+1]=gen_end[ply];
  507. }
  508.  
  509.  
  510. /* gen_caps() is basically a copy of gen() that's modified to
  511.    only generate capture and promote moves. It's used by the
  512.    quiescence search. */
  513.  
  514. void __fastcall ChessThread::gen_caps(void)
  515. {
  516.     int i,j,n;
  517.  
  518.     gen_end[ply]=gen_begin[ply];
  519.     for(i=0;i<64;i++)
  520.         if(color[i]==side) {
  521.             if(piece[i]==PAWN) {
  522.                 if(side==LIGHT) {
  523.                     if(FILE(i)!=0&&color[i-9]==DARK)
  524.                         gen_push(i,i-9,17);
  525.                     if(FILE(i)!=7&&color[i-7]==DARK)
  526.                         gen_push(i,i-7,17);
  527.                     if(i<=15&&color[i-8]==EMPTY)
  528.                         gen_push(i,i-8,16);
  529.                 }
  530.                 if(side==DARK) {
  531.                     if(FILE(i)!=0&&color[i+7]==LIGHT)
  532.                         gen_push(i,i+7,17);
  533.                     if(FILE(i)!=7&&color[i+9]==LIGHT)
  534.                         gen_push(i,i+9,17);
  535.                     if(i>=48&&color[i+8]==EMPTY)
  536.                         gen_push(i,i+8,16);
  537.                 }
  538.             }
  539.             else
  540.                 for(j=0;j<offsets[piece[i]];j++)
  541.                     for(n=i;;) {
  542.                         n=mailbox[mailbox64[n]+offset[piece[i]][j]];
  543.                         if(n==-1)
  544.                             break;
  545.                         if(color[n]!=EMPTY) {
  546.                             if(color[n]==xside)
  547.                                 gen_push(i,n,1);
  548.                             break;
  549.                         }
  550.                         if(!slide[piece[i]])
  551.                             break;
  552.                     }
  553.         }
  554.     if(ep!=-1) {
  555.         if(side==LIGHT) {
  556.             if(FILE(ep)!=0&&color[ep+7]==LIGHT&&piece[ep+7]==PAWN)
  557.                 gen_push(ep+7,ep,21);
  558.             if(FILE(ep)!=7&&color[ep+9]==LIGHT&&piece[ep+9]==PAWN)
  559.                 gen_push(ep+9,ep,21);
  560.         }
  561.         else {
  562.             if(FILE(ep)!=0&&color[ep-9]==DARK&&piece[ep-9]==PAWN)
  563.                 gen_push(ep-9,ep,21);
  564.             if(FILE(ep)!=7&&color[ep-7]==DARK&&piece[ep-7]==PAWN)
  565.                 gen_push(ep-7,ep,21);
  566.         }
  567.     }
  568.     gen_begin[ply+1]=gen_end[ply];
  569. }
  570.  
  571.  
  572. /* gen_push() puts a move on the move stack, unless it's a
  573.    pawn promotion that needs to be handled by gen_promote().
  574.    It also assigns a score to the move for alpha-beta move
  575.    ordering. If the move is a capture, it uses MVV/LVA
  576.    (Most Valuable Victim/Least Valuable Attacker). Otherwise,
  577.    it uses the move's history heuristic value. Note that
  578.    1,000,000 is added to a capture move's score, so it
  579.    always gets ordered above a "normal" move. */
  580.  
  581. void __fastcall ChessThread::gen_push(int from,int to,int bits)
  582. {
  583.     gen_rec *g;
  584.  
  585.     if(bits&16) {
  586.         if(side==LIGHT) {
  587.             if(to<=8) {
  588.                 gen_promote(from,to,bits);
  589.                 return;
  590.             }
  591.         }
  592.         else {
  593.             if(to>=56) {
  594.                 gen_promote(from,to,bits);
  595.                 return;
  596.             }
  597.         }
  598.     }
  599.     g=&gen_dat[gen_end[ply]];
  600.     gen_end[ply]++;
  601.     g->m.b.from=char(from);
  602.     g->m.b.to=char(to);
  603.     g->m.b.promote=0;
  604.     g->m.b.bits=char(bits);
  605.     if(bits&1)
  606.         g->score=1000000+(piece[to]*10)-piece[from];
  607.     else
  608.         g->score=history[from][to];
  609. }
  610.  
  611.  
  612. /* gen_promote() is just like gen_push(), only it puts 4 moves
  613.    on the move stack, one for each possible promotion piece */
  614.  
  615. void __fastcall ChessThread::gen_promote(int from,int to,int bits)
  616. {
  617.     int i;
  618.     gen_rec *g;
  619.  
  620.     for(i=KNIGHT;i<=QUEEN;i++) {
  621.         g=&gen_dat[gen_end[ply]];
  622.         gen_end[ply]++;
  623.         g->m.b.from=char(from);
  624.         g->m.b.to=char(to);
  625.         g->m.b.promote=char(i);
  626.         g->m.b.bits=char(bits|32);
  627.         g->score=1000000+(i*10);
  628.     }
  629. }
  630.  
  631.  
  632. /* makemove() makes a move. If the move is illegal, it
  633.    undoes whatever it did and returns FALSE. Otherwise, it
  634.    returns TRUE. */
  635.  
  636. BOOL __fastcall ChessThread::makemove(move_bytes m)
  637. {
  638.  
  639.     /* test to see if a castle move is legal and move the rook
  640.        (the king is moved with the usual move code later) */
  641.     if(m.bits&2) {
  642.         if(in_check(side))
  643.             return(FALSE);
  644.         switch(m.to) {
  645.             case 62:
  646.                 if(color[61]!=EMPTY||color[62]!=EMPTY||
  647.                         attack(61,xside)||attack(62,xside))
  648.                     return(FALSE);
  649.                 color[61]=LIGHT;
  650.                 piece[61]=ROOK;
  651.                 color[63]=EMPTY;
  652.                 piece[63]=EMPTY;
  653.                 break;
  654.             case 58:
  655.                 if(color[57]!=EMPTY||color[58]!=EMPTY||color[59]!=EMPTY||
  656.                         attack(58,xside)||attack(59,xside))
  657.                     return(FALSE);
  658.                 color[59]=LIGHT;
  659.                 piece[59]=ROOK;
  660.                 color[56]=EMPTY;
  661.                 piece[56]=EMPTY;
  662.                 break;
  663.             case 6:
  664.                 if(color[5]!=EMPTY||color[6]!=EMPTY||
  665.                         attack(5,xside)||attack(6,xside))
  666.                     return(FALSE);
  667.                 color[5]=DARK;
  668.                 piece[5]=ROOK;
  669.                 color[7]=EMPTY;
  670.                 piece[7]=EMPTY;
  671.                 break;
  672.             case 2:
  673.                 if(color[1]!=EMPTY||color[2]!=EMPTY||color[3]!=EMPTY||
  674.                         attack(2,xside)||attack(3,xside))
  675.                     return(FALSE);
  676.                 color[3]=DARK;
  677.                 piece[3]=ROOK;
  678.                 color[0]=EMPTY;
  679.                 piece[0]=EMPTY;
  680.                 break;
  681.         }
  682.     }
  683.  
  684.     /* back up information so we can take the move back later. */
  685.     hist_dat[ply].m.b=m;
  686.     hist_dat[ply].capture=piece[m.to];
  687.     hist_dat[ply].castle=castle;
  688.     hist_dat[ply].ep=ep;
  689.     hist_dat[ply].fifty=fifty;
  690.     ply++;
  691.  
  692.     /* update the castle, en passant, and
  693.        fifty-move-draw variables */
  694.     castle&=castle_mask[m.from]&castle_mask[m.to];
  695.     if(m.bits&8) {
  696.         if(side==LIGHT)
  697.             ep=m.to+8;
  698.         else
  699.             ep=m.to-8;
  700.     }
  701.     else
  702.         ep=-1;
  703.     if(m.bits&17)
  704.         fifty=0;
  705.     else
  706.         fifty++;
  707.  
  708.     /* move the piece */
  709.     color[m.to]=side;
  710.     if(m.bits&32)
  711.         piece[m.to]=m.promote;
  712.     else
  713.         piece[m.to]=piece[m.from];
  714.     color[m.from]=EMPTY;
  715.     piece[m.from]=EMPTY;
  716.  
  717.     /* erase the pawn if this is an en passant move */
  718.     if(m.bits&4) {
  719.         if(side==LIGHT) {
  720.             color[m.to+8]=EMPTY;
  721.             piece[m.to+8]=EMPTY;
  722.         }
  723.         else {
  724.             color[m.to-8]=EMPTY;
  725.             piece[m.to-8]=EMPTY;
  726.         }
  727.     }
  728.  
  729.     /* switch sides and test for legality (if we can capture
  730.        the other guy's king, it's an illegal position and
  731.        we need to take the move back) */
  732.     side^=1;
  733.     xside^=1;
  734.     if(in_check(xside)) {
  735.         takeback();
  736.         return(FALSE);
  737.     }
  738.     return(TRUE);
  739. }
  740.  
  741.  
  742. /* takeback() is very similar to makemove(), only backwards :)  */
  743.  
  744. void __fastcall ChessThread::takeback(void)
  745. {
  746.     move_bytes m;
  747.  
  748.     side^=1;
  749.     xside^=1;
  750.     ply--;
  751.     m=hist_dat[ply].m.b;
  752.     castle=hist_dat[ply].castle;
  753.     ep=hist_dat[ply].ep;
  754.     fifty=hist_dat[ply].fifty;
  755.     color[m.from]=side;
  756.     if(m.bits&32)
  757.         piece[m.from]=PAWN;
  758.     else
  759.         piece[m.from]=piece[m.to];
  760.     if(hist_dat[ply].capture==EMPTY) {
  761.         color[m.to]=EMPTY;
  762.         piece[m.to]=EMPTY;
  763.     }
  764.     else {
  765.         color[m.to]=xside;
  766.         piece[m.to]=hist_dat[ply].capture;
  767.     }
  768.     if(m.bits&2) {
  769.         int from,to;
  770.  
  771.         switch(m.to) {
  772.             case 62: from=61; to=63; break;
  773.             case 58: from=59; to=56; break;
  774.             case 6: from=5; to=7; break;
  775.             case 2: from=3; to=0; break;
  776.         }
  777.         color[to]=side;
  778.         piece[to]=ROOK;
  779.         color[from]=EMPTY;
  780.         piece[from]=EMPTY;
  781.     }
  782.     if(m.bits&4) {
  783.         if(side==LIGHT) {
  784.             color[m.to+8]=xside;
  785.             piece[m.to+8]=PAWN;
  786.         }
  787.         else {
  788.             color[m.to-8]=xside;
  789.             piece[m.to-8]=PAWN;
  790.         }
  791.     }
  792. }
  793.  
  794. int __fastcall ChessThread::eval(void)
  795. {
  796.     int i;
  797.     int c;  /* color */
  798.     int xc;  /* not c */
  799.     int f;  /* file */
  800.     int score[2];  /* the score for each side */
  801.     int pawns[2][10];  /* the number of pawns of each color on each file */
  802.  
  803.     score[LIGHT]=score[DARK]=0;
  804.     memset(pawns,0,sizeof(pawns));
  805.  
  806.     /* loop through to set up the pawns array and to add up the
  807.        piece/square table values for each piece. */
  808.     for(i=0;i<64;i++) {
  809.         if(color[i]==EMPTY)
  810.             continue;
  811.         if(piece[i]==PAWN)
  812.             pawns[color[i]][FILE(i)+1]++;
  813.         score[color[i]]+=pcsq[color[i]][piece[i]][i];
  814.     }
  815.  
  816.     /* now that we have the pawns array set up, evaluate the pawns
  817.        and rooks */
  818.     for(i=0;i<64;i++) {
  819.         if(color[i]==EMPTY)
  820.             continue;
  821.         c=color[i];  /* set up c, xc, and f so we don't have to type a lot */
  822.         xc=c^1;
  823.         f=FILE(i)+1;
  824.         if(piece[i]==PAWN) {
  825.             if(pawns[c][f]>1)  /* this pawn is doubled */
  826.                 score[c]-=5;
  827.             if((!pawns[c][f-1])&&
  828.                     (!pawns[c][f+1])) {  /* isolated */
  829.                 score[c]-=20;
  830.                 if(!pawns[xc][f])
  831.                     score[c]-=10;
  832.             }
  833.             if((!pawns[xc][f-1])&&  /* passed */
  834.                     (!pawns[xc][f])&&
  835.                     (!pawns[xc][f+1]))
  836.                 score[c]+=2*pcsq[c][PAWN][i];
  837.         }
  838.         if(piece[i]==ROOK)
  839.             if(!pawns[c][f]) {  /* the rook is on a half-open file */
  840.                 score[c]+=10;
  841.                 if(!pawns[xc][f])  /* actually, it's totally open */
  842.                     score[c]+=5;
  843.             }
  844.     }
  845.  
  846.     /* return the score relative to the side to move (i.e.,
  847.        a positive score means the side to move is winning) */
  848.     if(side==LIGHT)
  849.         return(score[LIGHT]-score[DARK]);
  850.     return(score[DARK]-score[LIGHT]);
  851. }
  852.  
  853. void __fastcall ChessThread::init_eval(void)
  854. {
  855.     int i,material,king_sq;
  856.  
  857.     memset(pcsq,0,sizeof(pcsq));
  858.  
  859.     /* initialize the no-brainer piece/square tables */
  860.     for(i=0;i<64;i++) {
  861.         pcsq[LIGHT][PAWN][i]=value[PAWN]+pawn_pcsq[i];
  862.         pcsq[LIGHT][KNIGHT][i]=value[KNIGHT]+minor_pcsq[i];
  863.         pcsq[LIGHT][BISHOP][i]=value[BISHOP]+minor_pcsq[i];
  864.         pcsq[LIGHT][ROOK][i]=value[ROOK];
  865.         pcsq[LIGHT][QUEEN][i]=value[QUEEN];
  866.         pcsq[DARK][PAWN][i]=value[PAWN]+pawn_pcsq[flip[i]];
  867.         pcsq[DARK][KNIGHT][i]=value[KNIGHT]+minor_pcsq[flip[i]];
  868.         pcsq[DARK][BISHOP][i]=value[BISHOP]+minor_pcsq[flip[i]];
  869.         pcsq[DARK][ROOK][i]=value[ROOK];
  870.         pcsq[DARK][QUEEN][i]=value[QUEEN];
  871.     }
  872.  
  873.     /* now scan the board to see how much piece material the
  874.        enemy has and figure out what side of the board the
  875.        king is on */
  876.     material=0;
  877.     for(i=0;i<64;i++) {
  878.         if(color[i]==DARK&&piece[i]!=PAWN)
  879.             material+=value[piece[i]];
  880.         if(color[i]==LIGHT&&piece[i]==KING)
  881.             king_sq=i;
  882.     }
  883.     if(material>1400) {  /* use the middlegame tables */
  884.         for(i=0;i<64;i++)
  885.             pcsq[LIGHT][KING][i]=king_pcsq[i];
  886.         if(FILE(king_sq)>=5)
  887.             for(i=0;i<64;i++)
  888.                 pcsq[LIGHT][PAWN][i]+=kingside_pawn_pcsq[i];
  889.         if(FILE(king_sq)<=2)
  890.             for(i=0;i<64;i++)
  891.                 pcsq[LIGHT][PAWN][i]+=queenside_pawn_pcsq[i];
  892.     }
  893.     else
  894.         for(i=0;i<64;i++)
  895.             pcsq[LIGHT][KING][i]=endgame_king_pcsq[i];
  896.  
  897.     /* do the same for black */
  898.     material=0;
  899.     for(i=0;i<64;i++) {
  900.         if(color[i]==LIGHT&&piece[i]!=PAWN)
  901.             material+=value[piece[i]];
  902.         if(color[i]==DARK&&piece[i]==KING)
  903.             king_sq=i;
  904.     }
  905.     if(material>1400) {
  906.         for(i=0;i<64;i++)
  907.             pcsq[DARK][KING][i]=king_pcsq[flip[i]];
  908.         if(FILE(king_sq)>=5)
  909.             for(i=0;i<64;i++)
  910.                 pcsq[DARK][PAWN][i]+=kingside_pawn_pcsq[flip[i]];
  911.         if(FILE(king_sq)<=2)
  912.             for(i=0;i<64;i++)
  913.                 pcsq[DARK][PAWN][i]+=queenside_pawn_pcsq[flip[i]];
  914.     }
  915.     else
  916.         for(i=0;i<64;i++)
  917.             pcsq[DARK][KING][i]=endgame_king_pcsq[flip[i]];
  918. }
  919.  
  920.  
  921. //---------------------------------------------------------------------------
  922. void __fastcall ChessThread::InitValues()
  923. {
  924.     static int _flip[64]=
  925.        {
  926.              56,  57,  58,  59,  60,  61,  62,  63,
  927.              48,  49,  50,  51,  52,  53,  54,  55,
  928.              40,  41,  42,  43,  44,  45,  46,  47,
  929.              32,  33,  34,  35,  36,  37,  38,  39,
  930.              24,  25,  26,  27,  28,  29,  30,  31,
  931.              16,  17,  18,  19,  20,  21,  22,  23,
  932.               8,   9,  10,  11,  12,  13,  14,  15,
  933.               0,   1,   2,   3,   4,   5,   6,   7
  934.         };
  935.  
  936.     IntCopy (&flip[0],&_flip[0],64);
  937.  
  938.     static int _pawn_pcsq[64]= {
  939.               0,   0,   0,   0,   0,   0,   0,   0,
  940.               5,  10,  15,  20,  20,  15,  10,   5,
  941.               4,   8,  12,  16,  16,  12,   8,   4,
  942.               3,   6,   9,  12,  12,   9,   6,   3,
  943.               2,   4,   6,   8,   8,   6,   4,   2,
  944.               1,   2,   3,   4,   4,   3,   2,   1,
  945.               0,   0,   0, -20, -20,   0,   0,   0,
  946.               0,   0,   0,   0,   0,   0,   0,   0
  947.         };
  948.  
  949.     IntCopy (&pawn_pcsq[0],&_pawn_pcsq[0],64);
  950.  
  951.     static int _kingside_pawn_pcsq[64]= {
  952.               0,   0,   0,   0,   0,   0,   0,   0,
  953.               0,   0,   0,   0,   0,   0,   0,   0,
  954.               0,   0,   0,   0,   0,   0,   0,   0,
  955.               0,   0,   0,   0,   0,   0,   0,   0,
  956.               0,   0,   0,   0,   0,   5,   5,   5,
  957.               0,   0,   0,   0,   0,  10,  10,  10,
  958.               0,   0,   0,   0,   0,  20,  20,  20,
  959.               0,   0,   0,   0,   0,   0,   0,   0
  960.         };
  961.  
  962.     IntCopy (&kingside_pawn_pcsq[0],&_kingside_pawn_pcsq[0],64);
  963.  
  964.     int _queenside_pawn_pcsq[64]= {
  965.               0,   0,   0,   0,   0,   0,   0,   0,
  966.               0,   0,   0,   0,   0,   0,   0,   0,
  967.               0,   0,   0,   0,   0,   0,   0,   0,
  968.               0,   0,   0,   0,   0,   0,   0,   0,
  969.               5,   5,   5,   0,   0,   0,   0,   0,
  970.              10,  10,  10,   0,   0,   0,   0,   0,
  971.              20,  20,  20,   0,   0,   0,   0,   0,
  972.               0,   0,   0,   0,   0,   0,   0,   0
  973.         };
  974.  
  975.     IntCopy (&queenside_pawn_pcsq[0],&_queenside_pawn_pcsq[0],64);
  976.  
  977.     int _minor_pcsq[64]= {
  978.             -10, -10, -10, -10, -10, -10, -10, -10,
  979.             -10,   0,   0,   0,   0,   0,   0, -10,
  980.             -10,   0,   5,   5,   5,   5,   0, -10,
  981.             -10,   0,   5,  10,  10,   5,   0, -10,
  982.             -10,   0,   5,  10,  10,   5,   0, -10,
  983.             -10,   0,   5,   5,   5,   5,   0, -10,
  984.             -10,   0,   0,   0,   0,   0,   0, -10,
  985.             -20, -20, -20, -20, -20, -20, -20, -20,
  986.         };
  987.  
  988.     IntCopy (&minor_pcsq[0],&_minor_pcsq[0],64);
  989.  
  990.     int _king_pcsq[64]= {
  991.             -40, -40, -40, -40, -40, -40, -40, -40,
  992.             -40, -40, -40, -40, -40, -40, -40, -40,
  993.             -40, -40, -40, -40, -40, -40, -40, -40,
  994.             -40, -40, -40, -40, -40, -40, -40, -40,
  995.             -40, -40, -40, -40, -40, -40, -40, -40,
  996.             -40, -40, -40, -40, -40, -40, -40, -40,
  997.             -20, -20, -20, -20, -20, -20, -20, -20,
  998.             -10,   0,  10, -20,   0, -20,  10,   0
  999.         };
  1000.  
  1001.     IntCopy (&king_pcsq[0],&_king_pcsq[0],64);
  1002.  
  1003.     int _endgame_king_pcsq[64]= {
  1004.              -5,  -5,  -5,  -5,  -5,  -5,  -5,  -5,
  1005.              -5,   0,   0,   0,   0,   0,   0,  -5,
  1006.              -5,   0,   5,   5,   5,   5,   0,  -5,
  1007.              -5,   0,   5,  10,  10,   5,   0,  -5,
  1008.              -5,   0,   5,  10,  10,   5,   0,  -5,
  1009.              -5,   0,   5,   5,   5,   5,   0,  -5,
  1010.              -5,   0,   0,   0,   0,   0,   0,  -5,
  1011.              -5,  -5,  -5,  -5,  -5,  -5,  -5,  -5
  1012.         };
  1013.  
  1014.     IntCopy (&endgame_king_pcsq[0],&_endgame_king_pcsq[0],64);
  1015.  
  1016.  
  1017.     int _mailbox[120]= {
  1018.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1019.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1020.              -1,  0,  1,  2,  3,  4,  5,  6,  7, -1,
  1021.              -1,  8,  9, 10, 11, 12, 13, 14, 15, -1,
  1022.              -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  1023.              -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  1024.              -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  1025.              -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  1026.              -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  1027.              -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  1028.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1029.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
  1030.         };
  1031.  
  1032.     IntCopy (&mailbox[0],&_mailbox[0],120);
  1033.  
  1034.  
  1035.     int _mailbox64[64]= {
  1036.             21, 22, 23, 24, 25, 26, 27, 28,
  1037.             31, 32, 33, 34, 35, 36, 37, 38,
  1038.             41, 42, 43, 44, 45, 46, 47, 48,
  1039.             51, 52, 53, 54, 55, 56, 57, 58,
  1040.             61, 62, 63, 64, 65, 66, 67, 68,
  1041.             71, 72, 73, 74, 75, 76, 77, 78,
  1042.             81, 82, 83, 84, 85, 86, 87, 88,
  1043.             91, 92, 93, 94, 95, 96, 97, 98
  1044.         };
  1045.  
  1046.     IntCopy (&mailbox64[0],&_mailbox64[0],64);
  1047.  
  1048.     slide[0]=FALSE;
  1049.     slide[1]=FALSE;
  1050.     slide[2]=TRUE;
  1051.     slide[3]=TRUE;
  1052.     slide[4]=TRUE;
  1053.     slide[5]=FALSE;
  1054.  
  1055.     int _offsets[6]= {
  1056.             0, 8, 4, 4, 8, 8
  1057.         };
  1058.  
  1059.     IntCopy (&offsets[0],&_offsets[0],6);
  1060.  
  1061.  
  1062.     int _offset[6][8]={
  1063.             {0, 0, 0, 0, 0, 0, 0, 0,},
  1064.             {-21, -19, -12, -8, 8, 12, 19, 21,},
  1065.             {-11, -9, 9, 11, 0, 0, 0, 0,},
  1066.             {-10, -1, 1, 10, 0, 0, 0, 0,},
  1067.             {-11, -10, -9, -1, 1, 9, 10, 11,},
  1068.             {-11, -10, -9, -1, 1, 9, 10, 11}
  1069.         };
  1070.  
  1071.     IntCopy (&offset[0][0],&_offset[0][0],48);
  1072.  
  1073.     int _castle_mask[64]= {
  1074.              7, 15, 15, 15,  3, 15, 15, 11,
  1075.             15, 15, 15, 15, 15, 15, 15, 15,
  1076.             15, 15, 15, 15, 15, 15, 15, 15,
  1077.             15, 15, 15, 15, 15, 15, 15, 15,
  1078.             15, 15, 15, 15, 15, 15, 15, 15,
  1079.             15, 15, 15, 15, 15, 15, 15, 15,
  1080.             15, 15, 15, 15, 15, 15, 15, 15,
  1081.             13, 15, 15, 15, 12, 15, 15, 14
  1082.         };
  1083.  
  1084.     IntCopy (&castle_mask[0],&_castle_mask[0],64);
  1085.  
  1086.     int _value[6]= {
  1087.             100, 300, 300, 500, 900, 10000
  1088.         };
  1089.  
  1090.     IntCopy (&value[0],&_value[0],6);
  1091.  
  1092.     piece_char[0]='P';
  1093.     piece_char[1]='N';
  1094.     piece_char[2]='B';
  1095.     piece_char[3]='R';
  1096.     piece_char[4]='Q';
  1097.     piece_char[5]='K';
  1098.  
  1099.     int _init_color[64]= {
  1100.             1, 1, 1, 1, 1, 1, 1, 1,
  1101.             1, 1, 1, 1, 1, 1, 1, 1,
  1102.             6, 6, 6, 6, 6, 6, 6, 6,
  1103.             6, 6, 6, 6, 6, 6, 6, 6,
  1104.             6, 6, 6, 6, 6, 6, 6, 6,
  1105.             6, 6, 6, 6, 6, 6, 6, 6,
  1106.             0, 0, 0, 0, 0, 0, 0, 0,
  1107.             0, 0, 0, 0, 0, 0, 0, 0
  1108.         };
  1109.  
  1110.     IntCopy (&init_color[0],&_init_color[0],64);
  1111.  
  1112.     int _init_piece[64]= {
  1113.             3, 1, 2, 4, 5, 2, 1, 3,
  1114.             0, 0, 0, 0, 0, 0, 0, 0,
  1115.             6, 6, 6, 6, 6, 6, 6, 6,
  1116.             6, 6, 6, 6, 6, 6, 6, 6,
  1117.             6, 6, 6, 6, 6, 6, 6, 6,
  1118.             6, 6, 6, 6, 6, 6, 6, 6,
  1119.             0, 0, 0, 0, 0, 0, 0, 0,
  1120.             3, 1, 2, 4, 5, 2, 1, 3
  1121.         };
  1122.  
  1123.     IntCopy (&init_piece[0],&_init_piece[0],64);
  1124. }
  1125. //-----------------------------------------------------------------------
  1126.