home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnuch40.zip / gnuchess-4.0.pl79 / src / genmoves.c < prev    next >
C/C++ Source or Header  |  1998-09-28  |  12KB  |  545 lines

  1. /*
  2.  * genmoves.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1985-1996 Stuart Cracraft, John Stanback,
  5.  *                         Daryl Baker, Conor McCarthy,
  6.  *                         Mike McGann, Chua Kong Sian
  7.  * Copyright (c) 1985-1996 Free Software Foundation
  8.  *
  9.  * This file is part of GNU CHESS.
  10.  *
  11.  * GNU Chess is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2, or (at your option)
  14.  * any later version.
  15.  *
  16.  * GNU Chess is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GNU Chess; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25. #include "gnuchess.h"
  26. #include "ataks.h"
  27. SHORT *TrP, InCheck;
  28.  
  29. #define Link(from,to,flag,s) \
  30. {\
  31.    node->f = from; node->t = to;\
  32.      node->reply = 0;\
  33.        node->flags = flag;\
  34.      node->score = s;\
  35.        ++node;\
  36.          (*TrP)++;\
  37.          }
  38.  
  39. inline int
  40. CheckMove (SHORT f, SHORT t, SHORT flag)
  41. {
  42.   SHORT side, incheck;
  43.   SHORT tempb, tempc, tempsf, tempst;   
  44.   struct leaf node;
  45.  
  46.   side = color[f];
  47.   node.f = f;
  48.   node.t = t;
  49.   node.flags = flag;
  50.   MakeMove (side, &node, &tempb, &tempc, &tempsf, &tempst);
  51.   incheck = SqAtakd (PieceList[side][0], 1 ^ side);
  52.   UnmakeMove (side, &node, &tempb, &tempc, &tempsf, &tempst);
  53.   return (!incheck);
  54. }
  55.  
  56.  
  57.  
  58. inline void
  59. LinkMove (SHORT ply, SHORT f,
  60.       register SHORT t,
  61.       SHORT flag,
  62.       SHORT xside)
  63.  
  64. /*
  65.  * Add a move to the tree.  Assign a bonus to order the moves as follows:
  66.     1. Principle variation
  67.     2. Capture of last moved piece
  68.     3. Other captures (major pieces first)
  69.     4. Killer moves
  70.     5.
  71.  */
  72.  
  73. {
  74.     register SHORT s = 0;
  75. #if defined HISTORY
  76.     register SHORT z;
  77. #endif
  78.     register utshort mv;
  79.     SHORT piece;
  80.     register struct leaf *node;
  81.  
  82.     node = &Tree[*TrP];
  83.     mv = (f << 8) | t;
  84.     piece = board[f];
  85. #ifdef KILLT
  86.     s += killt[mv ];
  87. #endif
  88. #ifdef HISTORY
  89.     z = mv;
  90.     if (xside == white)
  91.     z |= 0x4000;
  92.     s += history[z];
  93. #endif
  94.     if (color[t] != neutral)
  95.       {
  96.       /* TOsquare is the square the last piece moved moved to */
  97.       s += value[board[t]] - piece + ((t == TOsquare) ? 500 : 0);
  98.       }
  99.     if (board[f] == pawn)
  100.     if (row (t) == 0 || row (t) == 7)
  101.       {
  102.           flag |= promote;
  103.           s += 800;
  104. #if !defined CHESSTOOL
  105.           Link (f, t, flag | queen, s - 20000);
  106.           s -= 200;
  107.           Link (f, t, flag | rook, s - 20000);
  108.           s -= 50;
  109.           Link (f, t, flag | knight, s - 20000);
  110.           flag |= bishop;
  111.           s -= 50;
  112. #else
  113.           flag |= queen;
  114. #endif
  115.       }
  116.     else if (row (t) == 1 || row (t) == 6)
  117.       {
  118.           flag |= pwnthrt;
  119.           s += 600;
  120.       }
  121.     else if ((row (t) == ((color[f] == white) ? 5 : 2)) && (ply > MINDEPTH) && (ply < Sdepth + 3))
  122.       {
  123.           if ((mtl[white] - pmtl[white] + mtl[black] - pmtl[black]) < PTVALUE)
  124.         {
  125.             flag |= pwnthrt;
  126.             s += 400;
  127.         }
  128.       }
  129.     Link (f, t, flag, s - 20000);
  130. }
  131.  
  132. inline
  133. void
  134. GenMoves (register SHORT ply, register SHORT sq, SHORT side, SHORT xside)
  135.  
  136. /*
  137.  * Generate moves for a piece. The moves are taken from the precalulated
  138.  * array nextpos/nextdir. If the board is free, next move is choosen from
  139.  * nextpos else from nextdir.
  140.  */
  141.  
  142. {
  143.     register SHORT u, piece;
  144.     register UCHAR *ppos, *pdir;
  145.  
  146.  
  147.     TrP = &TrPnt[ply + 1];
  148.     piece = board[sq];
  149.     if (piece == pawn)
  150.       {
  151.           ppos = nextpos[ptype[side][piece]][sq];
  152.           pdir = nextdir[ptype[side][piece]][sq];
  153.       u = ppos[sq];        /* follow no captures thread */
  154.       if (color[u] == neutral)
  155.         {
  156.         LinkMove (ply, sq, u, 0, xside);
  157.         u = ppos[u];
  158.         if (color[u] == neutral)
  159.               LinkMove (ply, sq, u, 0, xside);
  160.         }
  161.       u = pdir[sq];        /* follow captures thread */
  162.       if (color[u] == xside /*&& board[u] != king*/)
  163.         {
  164.               LinkMove (ply, sq, u, capture, xside);
  165.         }
  166.       u = pdir[u];
  167.       if (color[u] == xside /*&& board[u] != king*/)
  168.         {
  169.               LinkMove (ply, sq, u, capture, xside);
  170.         }
  171.       }
  172.     else
  173.       {
  174.       ppos = nextpos[piece][sq];
  175.       pdir = nextdir[piece][sq];
  176.       u = ppos[sq];
  177.       do
  178.         {
  179.         if (color[u] == neutral)
  180.           {
  181.                 LinkMove (ply, sq, u, 0, xside);
  182.               u = ppos[u];
  183.           }
  184.         else
  185.           {
  186.               if (color[u] == xside /*&& board[u] != king*/)
  187.             {
  188.                   LinkMove (ply, sq, u, capture, xside);
  189.             }
  190.               u = pdir[u];
  191.           }
  192.         }
  193.       while (u != sq);
  194.       }
  195. }
  196.  
  197. void
  198. MoveList (SHORT side, register SHORT ply)
  199.  
  200. /*
  201.  * Fill the array Tree[] with all available moves for side to play. Array
  202.  * TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  203.  */
  204.  
  205. {
  206.     register SHORT i, xside, f;
  207.  
  208.     xside = side ^ 1;
  209.     TrP = &TrPnt[ply + 1];
  210.     *TrP = TrPnt[ply];
  211.     if (!PV)
  212.     Swag0 = killr0[ply];
  213.     else
  214.     Swag0 = PV;
  215.     Swag1 = killr1[ply];
  216.     Swag2 = killr2[ply];
  217.     if (ply > 2)
  218.     Swag4 = killr1[ply - 2];
  219.     else
  220.     Swag4 = 0;
  221. #ifdef KILLT
  222.     killt[SwagHt ] += 5000;
  223.     killt[Swag0 ] += 2000;
  224.     killt[Swag1 ] += 60;
  225.     killt[Swag2 ] += 50;
  226.     killt[Swag4 ] += 30;
  227. #endif
  228.     for (i = PieceCnt[side]; i >= 0; i--)
  229.     GenMoves (ply, PieceList[side][i], side, xside);
  230.     if (!castld[side])
  231.       {
  232.       f = PieceList[side][0];
  233.       if (castle (side, f, f + 2, 0))
  234.         {
  235.         LinkMove (ply, f, f + 2, cstlmask, xside);
  236.         }
  237.       if (castle (side, f, f - 2, 0))
  238.         {
  239.         LinkMove (ply, f, f - 2, cstlmask, xside);
  240.         }
  241.       }
  242.     if (epsquare > 0)
  243.       {
  244. /*      register SHORT l; */
  245.  
  246.       f = epmove1[epsquare];
  247.       if (color[f] == side && board[f] == pawn)
  248.         {
  249. /*        l = epsquare + ((epsquare > f) ? -8 : 8);
  250.         board[l] = no_piece;
  251.         color[l] = neutral; */
  252.         LinkMove (ply, f, epsquare, capture | epmask, xside);
  253. /*        board[l] = pawn;
  254.         color[l] = xside; */
  255.         }
  256.       f = epmove2[epsquare];
  257.       if (color[f] == side && board[f] == pawn)
  258.         {
  259. /*        l = epsquare + ((epsquare > f) ? -8 : 8);
  260.         board[l] = no_piece;
  261.         color[l] = neutral; */
  262.         LinkMove (ply, f, epsquare, capture | epmask, xside);
  263. /*        board[l] = pawn;
  264.         color[l] = xside; */
  265.         }
  266.       }
  267. #ifdef KILLT
  268.     killt[SwagHt ] -= 5000;
  269.     killt[Swag0 ] -= 2000;
  270.     killt[Swag1 ] -= 60;
  271.     killt[Swag2 ] -= 50;
  272.     killt[Swag4 ] -= 30;
  273. #endif
  274.     SwagHt = 0;            /* SwagHt is only used once */
  275.     GenCnt += (TrPnt[ply + 1] - TrPnt[ply]);
  276. }
  277.  
  278. void
  279. CaptureList (register SHORT side, SHORT ply)
  280.  
  281. /*
  282.  * Fill the array Tree[] with all available cature and promote moves for side
  283.  * to play. Array TrPnt[ply] contains the index into Tree[] of the first move
  284.  * at a ply.
  285.  */
  286.  
  287. {
  288.     register SHORT u, sq;
  289.     register UCHAR *ppos, *pdir;
  290.     struct leaf *node;
  291.     SHORT i, piece, *PL, r7;
  292.     SHORT xside = side^1;
  293.  
  294.     xside = side ^ 1;
  295.     TrP = &TrPnt[ply + 1];
  296.     *TrP = TrPnt[ply];
  297.     node = &Tree[*TrP];
  298.     r7 = rank7[side];
  299.     PL = PieceList[side];
  300.  
  301.     for (i = 0; i <= PieceCnt[side]; i++)
  302.       {
  303.       sq = PL[i];
  304.       piece = board[sq];
  305.       if (sweep[piece])
  306.         {
  307.         ppos = nextpos[piece][sq];
  308.         pdir = nextdir[piece][sq];
  309.         u = ppos[sq];
  310.         do
  311.           { 
  312.             if (color[u] == neutral) 
  313.             u = ppos[u];
  314.             else 
  315.               {
  316.             if (color[u] == xside) 
  317.               {
  318.                 Link (sq, u, capture, value[board[u]] + svalue[u] - piece); 
  319.               }
  320.             u = pdir[u];
  321.               } 
  322.           }
  323.         while (u != sq);
  324.         } else {
  325.         pdir = nextdir[ptype[side][piece]][sq];
  326.         if (piece == pawn && row (sq) == r7)
  327.           {
  328.               u = pdir[sq];
  329.               if (color[u] == xside)
  330.             {
  331.               Link (sq, u, capture | promote | queen, valueQ);
  332. #if !defined CHESSTOOL
  333.                 Link (sq, u, capture | promote | rook, valueR);
  334.                 Link (sq, u, capture | promote | knight, valueN);
  335.                 Link (sq, u, capture | promote | bishop, valueB);
  336. #endif
  337.               }
  338.               u = pdir[u];
  339.               if (color[u] == xside)
  340.             {
  341.                 Link (sq, u, capture | promote | queen, valueQ);
  342. #if !defined CHESSTOOL
  343.                 Link (sq, u, capture | promote | rook, valueR);
  344.                 Link (sq, u, capture | promote | knight, valueN);
  345.                 Link (sq, u, capture | promote | bishop, valueB);
  346. #endif
  347.             }
  348.               ppos = nextpos[ptype[side][piece]][sq];
  349.               u = ppos[sq];    /* also generate non capture promote */
  350.               if (color[u] == neutral)
  351.             {
  352.                 Link (sq, u, promote | queen, valueQ);
  353. #if !defined CHESSTOOL
  354.                 Link (sq, u, promote | rook, valueR);
  355.                 Link (sq, u, promote | knight, valueN);
  356.                 Link (sq, u, promote | bishop, valueB);
  357. #endif
  358.             }
  359.           }
  360.         else
  361.           {
  362.               u = pdir[sq];
  363.               do
  364.             {
  365.                 if (color[u] == xside)
  366.                 Link (sq, u, capture, value[board[u]] + svalue[u] - piece);
  367.                 u = pdir[u];
  368.             }
  369.               while (u != sq);
  370.           }
  371.         }
  372.       }
  373.     SwagHt = 0;            /* SwagHt is only used once */
  374.     GenCnt += (TrPnt[ply + 1] - TrPnt[ply]);
  375. }
  376.  
  377. inline
  378. void
  379. VGenMoves (register SHORT ply, register SHORT sq, SHORT side, SHORT xside)
  380.  
  381. /*
  382.  * Generate moves for a piece. The moves are taken from the precalulated
  383.  * array nextpos/nextdir. If the board is free, next move is choosen from
  384.  * nextpos else from nextdir.
  385.  */
  386.  
  387. {
  388.     register SHORT u, piece;
  389.     register UCHAR *ppos, *pdir;
  390.  
  391.  
  392.     TrP = &TrPnt[ply + 1];
  393.     piece = board[sq];
  394.     ppos = nextpos[ptype[side][piece]][sq];
  395.     pdir = nextdir[ptype[side][piece]][sq];
  396.     if (piece == pawn)
  397.       {
  398.       u = ppos[sq];        /* follow no captures thread */
  399.       if (color[u] == neutral)
  400.         {
  401.         if (CheckMove (sq, u, 0))
  402.           {
  403.               LinkMove (ply, sq, u, 0, xside);
  404.           }
  405.         u = ppos[u];
  406.         if (color[u] == neutral)
  407.             if (CheckMove (sq, u, 0))
  408.               {
  409.               LinkMove (ply, sq, u, 0, xside);
  410.               }
  411.         }
  412.       u = pdir[sq];        /* follow captures thread */
  413.       if (color[u] == xside /* && board[u] != king */)
  414.         {
  415.         if (CheckMove (sq, u, capture))
  416.           {
  417.               LinkMove (ply, sq, u, capture, xside);
  418.           }
  419.         }
  420.       u = pdir[u];
  421.       if (color[u] == xside /*&& board[u] != king*/)
  422.         {
  423.         if (CheckMove (sq, u, capture))
  424.           {
  425.               LinkMove (ply, sq, u, capture, xside);
  426.           }
  427.         }
  428.       }
  429.     else
  430.       {
  431.       u = ppos[sq];
  432.       do
  433.         {
  434.         if (color[u] == neutral)
  435.           {
  436.               if (CheckMove (sq, u, 0))
  437.             {
  438.                 LinkMove (ply, sq, u, 0, xside);
  439.             }
  440.               u = ppos[u];
  441.           }
  442.         else
  443.           {
  444.               if (color[u] == xside /*&& board[u] != king */)
  445.             {
  446.                 if (CheckMove (sq, u, capture))
  447.                   {
  448.                   LinkMove (ply, sq, u, capture, xside);
  449.                   }
  450.             }
  451.               u = pdir[u];
  452.           }
  453.         }
  454.       while (u != sq);
  455.       }
  456. }
  457.  
  458. void
  459. VMoveList (SHORT side, register SHORT ply)
  460.  
  461. /*
  462.  * Fill the array Tree[] with all available moves for side to play. Array
  463.  * TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  464.  */
  465.  
  466. {
  467.     register SHORT i, xside, f;
  468.  
  469.     xside = side ^ 1;
  470.     TrP = &TrPnt[ply + 1];
  471.     *TrP = TrPnt[ply];
  472.     InCheck = SqAtakd (PieceList[side][0], side ^ 1);
  473.     if (!PV)
  474.     Swag0 = killr0[ply];
  475.     else
  476.     Swag0 = PV;
  477.     Swag1 = killr1[ply];
  478.     Swag2 = killr2[ply];
  479.     if (ply > 2)
  480.     Swag4 = killr1[ply - 2];
  481.     else
  482.     Swag4 = 0;
  483. #ifdef KILLT
  484.     killt[SwagHt] += 5000;
  485.     killt[Swag0] += 2000;
  486.     killt[Swag1] += 60;
  487.     killt[Swag2] += 50;
  488.     killt[Swag4] += 30;
  489. #endif
  490.     for (i = PieceCnt[side]; i >= 0; i--)
  491.     VGenMoves (ply, PieceList[side][i], side, xside);
  492.     if (!castld[side])
  493.       {
  494.       f = PieceList[side][0];
  495.       if (castle (side, f, f + 2, 0))
  496.         {
  497.         LinkMove (ply, f, f + 2, cstlmask, xside);
  498.         }
  499.       if (castle (side, f, f - 2, 0))
  500.         {
  501.         LinkMove (ply, f, f - 2, cstlmask, xside);
  502.         }
  503.       }
  504.     if (epsquare > 0)
  505.       {
  506.       register SHORT l;
  507.  
  508.       f = epmove1[epsquare];
  509.       if (color[f] == side && board[f] == pawn)
  510.         {
  511.         l = epsquare + ((epsquare > f) ? -8 : 8);
  512.         board[l] = no_piece;
  513.         color[l] = neutral;
  514.         if (CheckMove (f, epsquare, capture | epmask))
  515.           {
  516.               LinkMove (ply, f, epsquare, capture | epmask, xside);
  517.           }
  518.         board[l] = pawn;
  519.         color[l] = xside;
  520.         }
  521.       f = epmove2[epsquare];
  522.       if (color[f] == side && board[f] == pawn)
  523.         {
  524.         l = epsquare + ((epsquare > f) ? -8 : 8);
  525.         board[l] = no_piece;
  526.         color[l] = neutral;
  527.         if (CheckMove (f, epsquare, capture | epmask))
  528.           {
  529.               LinkMove (ply, f, epsquare, capture | epmask, xside);
  530.           }
  531.         board[l] = pawn;
  532.         color[l] = xside;
  533.         }
  534.       }
  535. #ifdef KILLT
  536.     killt[SwagHt] -= 5000;
  537.     killt[Swag0] -= 2000;
  538.     killt[Swag1] -= 60;
  539.     killt[Swag2] -= 50;
  540.     killt[Swag4] -= 30;
  541. #endif
  542.     SwagHt = 0;            /* SwagHt is only used once */
  543.     GenCnt += (TrPnt[ply + 1] - TrPnt[ply]);
  544. }
  545.