home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume4 / chtrans / trmoves.c < prev   
C/C++ Source or Header  |  1988-06-07  |  20KB  |  786 lines

  1. /*
  2.  *    Copyright (c) 1986 by Ray Balogh (rabalogh@ccng.waterloo.edu)
  3.  *
  4.  *    Permission is granted to anyone to use this software for any
  5.  *    purpose on any computer system, and to redistribute it freely,
  6.  *    subject to the following restrictions:
  7.  *
  8.  *    1. The author is not responsible for the consequences of use of
  9.  *    this software, no matter how awful, even if they arise
  10.  *    from defects in it.
  11.  *
  12.  *    2. The origin of this software must not be misrepresented, either
  13.  *    by explicit claim or by omission.
  14.  *
  15.  *    3. Altered versions must be plainly marked as such, and must not
  16.  *    be misrepresented as being the original software.
  17.  *
  18.  */
  19.  
  20. /*  The following copyright notice appears in the chess program from which
  21.  *  legal move generation code was derived:
  22.  *
  23.          C source for CHESS               Rev. 3-10-87
  24.  
  25.        Written by John Stanback (hplabs!hpfcla!hpisla!hpltca!jhs)
  26.  
  27.        Patches for BSD Unix by Rich Salz (rs@mirror.TMC.COM) - 5/3/87
  28.  *
  29.  *
  30.  ****************************************************************************
  31.  */
  32.  
  33.  
  34. #include <stdio.h>
  35.  
  36. #define true 1
  37. #define false 0
  38. #define neutral 0
  39. #define white 1
  40. #define black 2 
  41. #define no_piece 0
  42. #define pawn 1
  43. #define knight 2
  44. #define bishop 3
  45. #define rook 4
  46. #define queen 5
  47. #define king 6
  48. #define px " PNBRQK"
  49. #define qx " pnbrqk"
  50. #define rx "12345678"
  51. #define cx "abcdefgh"
  52. #define check     0x00000001
  53. #define capture   0x00000002
  54. #define draw      0x00000004
  55. #define promote_n 0x00000010
  56. #define promote_b 0x00000020
  57. #define promote_r 0x00000040
  58. #define promote_q 0x00000080
  59. #define promote   (promote_n|promote_b|promote_r|promote_q)
  60. #define incheck   0x00000100
  61. #define epmask    0x00000200
  62. #define exact     0x00000400
  63. #define pwnthrt   0x00000800
  64.  
  65. #define MAXMVSTR    12
  66. #define DUNNO        '_'
  67. #define ETC        '*'
  68. #define BADCHAR        '\004'
  69.  
  70. #define PLYSIDE(ply)    (ply % 2 ? "black" : "white")
  71.  
  72.  
  73. struct leaf
  74.   {
  75.     int f,t;
  76.     unsigned int flags;
  77.   };
  78.  
  79. int row[64],col[64],Index[64];
  80. int PieceList[3][16],PieceCnt[3];
  81. int castld[3],kingmoved[3],mtl[3],pmtl[3];
  82. int qrookmoved[3],krookmoved[3];
  83. int PawnCnt[3][8];
  84. int GameCnt,epsquare = -1;
  85. unsigned int GameList[240];
  86. int GamePc[240],GameClr[240];
  87. int GamePiece[240],GameColor[240],GamePromote[240];
  88. int value[8]={0,100,330,330,500,950,999};
  89. int otherside[3]={0,2,1};
  90. int map[64]=
  91.    {26,27,28,29,30,31,32,33,38,39,40,41,42,43,44,45,
  92.     50,51,52,53,54,55,56,57,62,63,64,65,66,67,68,69,
  93.     74,75,76,77,78,79,80,81,86,87,88,89,90,91,92,93,
  94.     98,99,100,101,102,103,104,105,110,111,112,113,114,115,116,117};
  95. int unmap[144]=
  96.    {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  97.     -1,-1,0,1,2,3,4,5,6,7,-1,-1,-1,-1,8,9,10,11,12,13,14,15,-1,-1,
  98.     -1,-1,16,17,18,19,20,21,22,23,-1,-1,-1,-1,24,25,26,27,28,29,30,31,-1,-1,
  99.     -1,-1,32,33,34,35,36,37,38,39,-1,-1,-1,-1,40,41,42,43,44,45,46,47,-1,-1,
  100.     -1,-1,48,49,50,51,52,53,54,55,-1,-1,-1,-1,56,57,58,59,60,61,62,63,-1,-1,
  101.     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
  102. int board[64]=
  103.    {rook,knight,bishop,queen,king,bishop,knight,rook,
  104.     pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
  105.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  106.     pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
  107.     rook,knight,bishop,queen,king,bishop,knight,rook};
  108. int color[64]=
  109.    {white,white,white,white,white,white,white,white,
  110.     white,white,white,white,white,white,white,white,
  111.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  112.     black,black,black,black,black,black,black,black,
  113.     black,black,black,black,black,black,black,black};
  114. int sweep[7]= {false,false,false,true,true,true,false};
  115. int Dstpwn[3]={0,4,6};
  116. int Dstart[7]={6,4,8,4,0,0,0};
  117. int Dstop[7]={7,5,15,7,3,7,7};
  118. int Dir[16]={1,12,-1,-12,11,13,-11,-13,10,-10,14,-14,23,-23,25,-25};
  119. int MovePnt = 0;
  120. struct leaf Moves[2000];
  121. char charmap[] = " PNBRQK";
  122. int real_ep_square = -1;
  123.  
  124. InitializeStats()
  125. {
  126. register int i,loc;
  127. int l,r,c;
  128.  
  129.   for (r = 0; r < 8; r++)
  130.     for (c = 0; c < 8; c++)
  131.       {
  132.         l = 8*r+c;
  133.         row[l] = r; col[l] = c;
  134.       }
  135.   for (i = 0; i < 8; i++)
  136.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  137.  
  138.   /*epsquare = -1;*/
  139.   GameCnt = -1;
  140.   castld[white] = castld[black] = false;
  141.   kingmoved[white] = kingmoved[black] = 0;
  142.   krookmoved[white] = krookmoved[black] = 0;
  143.   qrookmoved[white] = qrookmoved[black] = 0;
  144.  
  145.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black]=0;
  146.   PieceCnt[white] = PieceCnt[black] = 0;
  147.   for (loc = 0; loc < 64; loc++)
  148.     if (color[loc] != neutral)
  149.       {
  150.         mtl[color[loc]] += value[board[loc]];
  151.         if (board[loc] == pawn)
  152.           {
  153.             pmtl[color[loc]] += value[pawn];
  154.             ++PawnCnt[color[loc]][col[loc]];
  155.           }
  156.         if (board[loc] == king) Index[loc] = 0;
  157.           else Index[loc] = ++PieceCnt[color[loc]];
  158.         PieceList[color[loc]][Index[loc]] = loc;
  159.       }
  160. }
  161.  
  162.  
  163. MakeMove(side,node,tempb,tempc)
  164. int side,*tempc,*tempb;
  165. struct leaf *node;
  166.  
  167. /*
  168.     Update Arrays board[], color[], and Index[] to reflect the new
  169.     board position obtained after making the move pointed to by
  170.     node.  Also update miscellaneous stuff that changes when a move
  171.     is made.
  172. */
  173.     
  174. {
  175. register int f,t;
  176. int ok,xside;
  177. int prom_val;
  178. int bf, bt;
  179.  
  180.   xside = otherside[side];
  181.   epsquare = -1;
  182.   f = node->f; t = node->t;
  183.   GameList[++GameCnt] = (f<<8) + t;
  184.   if (f == 255 || t == 255)
  185.     {
  186.       GamePc[GameCnt] = no_piece; GameClr[GameCnt] = neutral;
  187.       GamePiece[GameCnt] = no_piece; GameColor[GameCnt] = neutral;
  188.       GamePromote[GameCnt] = no_piece;
  189.       castle(side,f,t,1,&ok);
  190.     }
  191.   else
  192.     {
  193.       bf = board[f]; bt = board[t];
  194.       *tempc = color[t]; *tempb = bt;
  195.       GamePc[GameCnt] = *tempb; GameClr[GameCnt] = *tempc;
  196.       GamePiece[GameCnt] = bf; GameColor[GameCnt] = color[f];
  197.       GamePromote[GameCnt] = prompiece( node->flags );
  198.       if (*tempc != neutral)
  199.         {
  200.           UpdatePieceList(*tempc,t,1);
  201.           if (*tempb == pawn) --PawnCnt[*tempc][col[t]];
  202.           if (bf == pawn)
  203.             {
  204.               --PawnCnt[side][col[f]];
  205.               ++PawnCnt[side][col[t]];
  206.             }
  207.           mtl[xside] -= value[*tempb];
  208.           if (*tempb == pawn) pmtl[xside] -= value[pawn];
  209.         }
  210.       if (bf == king) ++kingmoved[side];
  211.       if (f==0 && bf==rook || t==0 && bt==rook) ++qrookmoved[white];
  212.       if (f==7 && bf==rook || t==7 && bt==rook) ++krookmoved[white];
  213.       if (f==56 && bf==rook || t==56 && bt==rook) ++qrookmoved[black];
  214.       if (f==63 && bf==rook || t==63 && bt==rook) ++krookmoved[black];
  215.  
  216.       color[t] = color[f]; board[t] = bf;
  217.       Index[t] = Index[f]; PieceList[side][Index[t]] = t;
  218.       color[f] = neutral; board[f] = no_piece;
  219.       if (board[t] == pawn)
  220.         if (t-f == 16) epsquare = f+8;
  221.         else if (f-t == 16) epsquare = f-8;
  222.       if (node->flags & promote)
  223.         {
  224.           prom_val = prompiece( node->flags );
  225.           board[t] = prom_val;
  226.           mtl[side] += value[prom_val] - value[pawn];
  227.           pmtl[side] -= value[pawn];
  228.         } 
  229.       if (node->flags & epmask) en_passant(side,xside,f,t,1);
  230.     }
  231. }
  232.  
  233.  
  234. UnmakeMove(side,node,tempb,tempc)
  235. int side,*tempc,*tempb;
  236. struct leaf *node;
  237.  
  238. /*
  239.     Take back the move pointed to by node.
  240. */
  241.  
  242. {
  243. register int f,t;
  244. int ok,xside;
  245. int prom_val;
  246. int bf, bt;
  247.  
  248.   xside = otherside[side];
  249.   epsquare = -1;
  250.   f = node->f; t = node->t;
  251.   GameCnt--;
  252.   if (f == 255 || t == 255) castle(side,f,t,2,&ok);
  253.   else
  254.     {
  255.       if (board[t] == king) --kingmoved[side];
  256.       bf = board[f]; bt = board[t];
  257.       if (f==0 && bt==rook || t==0 && bf==rook) --qrookmoved[white];
  258.       if (f==7 && bt==rook || t==7 && bf==rook) --krookmoved[white];
  259.       if (f==56 && bt==rook || t==56 && bf==rook) --qrookmoved[black];
  260.       if (f==63 && bt==rook || t==63 && bf==rook) --krookmoved[black];
  261.  
  262.       color[f] = color[t]; board[f] = board[t];
  263.       Index[f] = Index[t]; PieceList[side][Index[f]] = f;
  264.       color[t] = *tempc; board[t] = *tempb;
  265.       if (*tempc != neutral)
  266.         {
  267.           UpdatePieceList(*tempc,t,2);
  268.           if (*tempb == pawn) ++PawnCnt[*tempc][col[t]];
  269.           if (board[f] == pawn)
  270.             {
  271.               --PawnCnt[side][col[t]];
  272.               ++PawnCnt[side][col[f]];
  273.             }
  274.           mtl[xside] += value[*tempb];
  275.           if (*tempb == pawn) pmtl[xside] += value[pawn];
  276.         }
  277.       if (node->flags & promote)
  278.         {
  279.           prom_val = prompiece( node->flags );
  280.           board[f] = pawn;
  281.           mtl[side] += value[pawn] - value[prom_val];
  282.           pmtl[side] += value[pawn];
  283.         } 
  284.       if (node->flags & epmask) en_passant(side,xside,f,t,2);
  285.     }
  286. }
  287.  
  288.  
  289. int
  290. prompiece( promflags )
  291. int promflags;
  292. {
  293.     return( (promflags & promote_q) ? queen  :
  294.         (promflags & promote_r) ? rook   :
  295.         (promflags & promote_b) ? bishop :
  296.         (promflags & promote_n) ? knight :
  297.                                   no_piece
  298.       );
  299. }
  300.  
  301.  
  302. UpdatePieceList(side,loc,iop)
  303. int side,loc,iop;
  304.  
  305. /*
  306.     Array PieceList[side][indx] contains the location of all the pieces of
  307.     either side. Array Index[loc] contains the indx into PieceList for a
  308.     given square.
  309. */
  310.  
  311. {
  312. register int i;
  313.   if (iop == 1)
  314.     {
  315.       PieceCnt[side]--;
  316.       for (i = Index[loc]; i <= PieceCnt[side]; i++)
  317.         {
  318.           PieceList[side][i] = PieceList[side][i+1];
  319.           Index[PieceList[side][i]] = i;
  320.         }
  321.     }
  322.   else
  323.     {
  324.       PieceCnt[side]++;
  325.       PieceList[side][PieceCnt[side]] = loc;
  326.       Index[loc] = PieceCnt[side];
  327.     }
  328. }
  329.   
  330.  
  331. castle(side,f,t,iop,ok)
  332. int side,f,t,iop,*ok;
  333. {
  334. int i,e,k1,k2,r1,r2,c1,c2,t0,xside;
  335.  
  336.   xside = otherside[side];
  337.   if (side == white) e = 0; else e = 56;
  338.   if (f == 255)
  339.     {
  340.       /* castle king's side */
  341.       k1 = e+4; k2 = e+6; r1 = e+7; r2 = e+5; c1 = k1; c2 = r1;
  342.     }
  343.   else
  344.     {
  345.       /* castle queen's side */
  346.       k1 = e+4; k2 = e+2; r1 = e; r2 = e+3; c1 = r1; c2 = k1;
  347.     }
  348.   if (iop == 0)
  349.     {
  350.       *ok = false;
  351.       if (f == 255)
  352.     {
  353.       if (castld[side] || krookmoved[side] > 0 || kingmoved[side] > 0)
  354.           return;
  355.     }
  356.       else
  357.     {
  358.       if (castld[side] || qrookmoved[side] > 0 || kingmoved[side] > 0)
  359.           return;
  360.     }
  361.       if (board[k1] == king && board[r1] == rook)
  362.     {
  363.       *ok = true;
  364.       for (i = c1; i <= c2; i++)
  365.         if (isincheck(side,i)) {*ok = false; break;}
  366.       if (*ok)
  367.           for (i = c1+1; i < c2; i++)
  368.         if (color[i] != neutral) {*ok = false; break;}
  369.     }
  370.     }
  371.   else
  372.     {
  373.       if (iop == 1) castld[side] = true; else castld[side] = false;
  374.       if (iop == 2)
  375.         {
  376.           t0 = k1; k1 = k2; k2 = t0;
  377.           t0 = r1; r1 = r2; r2 = t0;
  378.         }
  379.       board[k2] = king; color[k2] = side; Index[k2] = 0;
  380.       board[k1] = no_piece; color[k1] = neutral;
  381.       board[r2] = rook; color[r2] = side; Index[r2] = Index[r1];
  382.       board[r1] = no_piece; color[r1] = neutral;
  383.       PieceList[side][Index[k2]] = k2;
  384.       PieceList[side][Index[r2]] = r2;
  385.     }
  386. }
  387.  
  388.  
  389. en_passant(side,xside,f,t,iop)
  390. int side,f,t,iop;
  391. {
  392. int l;
  393.   if (t > f) l = t-8; else l = t+8;
  394.   if (iop == 1)
  395.     {
  396.       board[l] = no_piece; color[l] = neutral;
  397.     }
  398.   else 
  399.     {
  400.       board[l] = pawn; color[l] = xside;
  401.     }
  402.   InitializeStats();
  403. }
  404.  
  405. int
  406. isincheck(side,kingloc)
  407. int side,kingloc;
  408.  
  409. /*
  410.     Determine if king is in check (efficiently).
  411. */
  412.  
  413. {
  414.   register int u, d, m, j, loc;
  415.   int co, ro;
  416.   int xside;
  417.   int stop;
  418.   int m0;
  419.   int piece;
  420.  
  421.   xside = otherside[side];
  422.   /*kingloc = PieceList[side][0];*/
  423.   co = col[kingloc]; ro = row[kingloc];
  424.   /* check for pawn checks */
  425.   if ( side == white ) {
  426.       if ( ro < 6 ) {
  427.       if ( co > 0 && color[kingloc+7] == xside && board[kingloc+7] == pawn )
  428.           return( true );
  429.       if ( co < 7 && color[kingloc+9] == xside && board[kingloc+9] == pawn )
  430.           return( true );
  431.       }
  432.   } else {
  433.       if ( ro > 1 ) {
  434.       if ( co < 7 && color[kingloc-7] == xside && board[kingloc-7] == pawn )
  435.           return( true );
  436.       if ( co > 0 && color[kingloc-9] == xside && board[kingloc-9] == pawn )
  437.           return( true );
  438.       }
  439.   }
  440.   /* check for knight checks */
  441.   m0 = map[kingloc]; stop = Dstop[knight];
  442.   for ( j = Dstart[knight]; j <= stop; j++ ) {
  443.       if ( (loc = unmap[m0+Dir[j]]) < 0 ) continue;
  444.       if ( board[loc] == knight && color[loc] == xside )
  445.       return( true );
  446.   }
  447.   /* check for bishop, rook and queen checks */
  448.   for ( piece = bishop; piece <= rook; piece+=(rook-bishop) )
  449.     {
  450.       stop = Dstop[piece];
  451.       for (j = Dstart[piece]; j <= stop; j++)
  452.     {
  453.       d = Dir[j]; m = m0+d; u = unmap[m];
  454.       while (u >= 0)
  455.         {
  456.           if (color[u] == neutral)
  457.         {
  458.           m += d; u = unmap[m];
  459.         }
  460.           else
  461.             {
  462.           if ( (board[u] == piece || board[u] == queen)
  463.               && color[u] == xside ) return( true );
  464.           u = -1;
  465.             }
  466.         }
  467.     }
  468.     }
  469.   return( false );
  470. }
  471.  
  472.  
  473. LinkMove(f,t,side,promoteto)
  474. int f,t,side,promoteto;
  475. {
  476.  
  477. /*
  478.     Add a move to the tree.
  479. */
  480.  
  481. struct leaf *node;
  482.  
  483. struct leaf tnode;
  484. int tempb, tempc;
  485.  
  486.   if ( !(f == 255 || t == 255) ) {
  487.       /* Don't bother to link the move if the king is in check afterwards;
  488.      ie. it is really illegal */
  489.       tnode.f = f; tnode.t = t;
  490.       tnode.flags = 0;
  491.       MakeMove(side,&tnode,&tempb,&tempc);
  492.       if (isincheck(side,PieceList[side][0]))
  493.     {
  494.       UnmakeMove(side,&tnode,&tempb,&tempc);
  495.       return;
  496.     }
  497.       else
  498.       UnmakeMove(side,&tnode,&tempb,&tempc);
  499.   }
  500.   
  501.   node = &Moves[MovePnt];
  502.   ++MovePnt;
  503.   node->flags = 0;
  504.   node->f = f; node->t = t;
  505.  
  506.   if ( !(f == 255 || t == 255) )
  507.     {
  508.       if (color[t] != neutral)
  509.         {
  510.           node->flags |= capture;
  511.         }
  512.       if (board[f] == pawn)
  513.         {
  514.           if (row[t] == 0 || row[t] == 7) node->flags |= promoteto;
  515.           else if (t == real_ep_square) node->flags |= epmask;
  516.         }
  517.     }
  518. }
  519.  
  520.  
  521. GenMoves(loc,side,xside)
  522. int loc,side,xside;
  523.  
  524. /*
  525.      Generate moves for a piece. The from square is mapped onto a 12 by 
  526.      12 board and offsets (taken from array Dir[]) are added to the 
  527.      mapped location. Array unmap[] maps the move back onto array 
  528.      board[] (yielding a value of -1 if the to square is off the board). 
  529.      This process is repeated for bishops, rooks, and queens until a 
  530.      piece is encountered or the the move falls off the board. Legal 
  531.      moves are then linked into the tree. 
  532. */
  533.     
  534. {
  535. register int m,u,d;
  536. int i,m0,piece; 
  537.  
  538.   piece = board[loc]; m0 = map[loc];
  539.  
  540.   if (sweep[piece])
  541.     {
  542.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  543.         {
  544.           d = Dir[i]; m = m0+d; u = unmap[m];
  545.           while (u >= 0)
  546.             if (color[u] == neutral)
  547.               {
  548.                 LinkMove(loc,u,side,no_piece);
  549.                 m += d; u = unmap[m];
  550.               }
  551.             else if (color[u] == xside)
  552.               {
  553.                 LinkMove(loc,u,side,no_piece);
  554.                 u = -1;
  555.               }
  556.             else u = -1;
  557.         }
  558.     }
  559.   else if (piece == pawn)
  560.     {
  561.       if (side == white && color[loc+8] == neutral)
  562.         {
  563.           if (row[loc] == 6)
  564.         {
  565.           LinkMove(loc,loc+8,side,promote_q);
  566.           LinkMove(loc,loc+8,side,promote_r);
  567.           LinkMove(loc,loc+8,side,promote_b);
  568.           LinkMove(loc,loc+8,side,promote_n);
  569.         }
  570.       else
  571.           LinkMove(loc,loc+8,side,no_piece);
  572.           if (row[loc] == 1)
  573.             if (color[loc+16] == neutral)
  574.               LinkMove(loc,loc+16,side,no_piece);
  575.         }
  576.       else if (side == black && color[loc-8] == neutral)
  577.         {
  578.           if (row[loc] == 1)
  579.         {
  580.           LinkMove(loc,loc-8,side,promote_q);
  581.           LinkMove(loc,loc-8,side,promote_r);
  582.           LinkMove(loc,loc-8,side,promote_b);
  583.           LinkMove(loc,loc-8,side,promote_n);
  584.         }
  585.       else
  586.           LinkMove(loc,loc-8,side,no_piece);
  587.           if (row[loc] == 6)
  588.             if (color[loc-16] == neutral)
  589.               LinkMove(loc,loc-16,side,no_piece);
  590.         }
  591.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  592.         if ((u = unmap[m0+Dir[i]]) >= 0)
  593.           if (color[u] == xside || u == real_ep_square)
  594.         if (side==white && row[loc]==6 || side==black && row[loc]==1)
  595.           {
  596.         LinkMove(loc,u,side,promote_q);
  597.         LinkMove(loc,u,side,promote_r);
  598.         LinkMove(loc,u,side,promote_b);
  599.         LinkMove(loc,u,side,promote_n);
  600.           }
  601.         else
  602.         LinkMove(loc,u,side,no_piece);
  603.     }
  604.   else
  605.     {
  606.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  607.         if ((u = unmap[m0+Dir[i]]) >= 0)
  608.           if (color[u] != side)
  609.             LinkMove(loc,u,side,no_piece);
  610.     }
  611. }
  612.  
  613.  
  614.  
  615. MoveList(side)
  616. int side;
  617.  
  618. /*
  619.     Fill the array Moves[] with all available moves for side to
  620.     play. Array MovePnt contains the index into Moves[].
  621. */
  622.     
  623. {
  624. register int i;
  625. int ok,xside;
  626. static int initted = false;
  627.  
  628.   if ( !initted ) {
  629.       InitializeStats();
  630.       initted = true;
  631.   }
  632.  
  633.   MovePnt = 0;
  634.   xside = otherside[side];
  635.   Dstart[pawn] = Dstpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
  636.  
  637.   for (i = 0; i <= PieceCnt[side]; i++)
  638.     GenMoves(PieceList[side][i],side,xside);
  639.  
  640.   castle(side,255,0,0,&ok);
  641.   if (ok) LinkMove(255,0,side,no_piece);
  642.   castle(side,0,255,0,&ok);
  643.   if (ok) LinkMove(0,255,side,no_piece);
  644.  
  645. }
  646.  
  647.  
  648. ToAlgNot( form1, form2, form3, node, side )
  649. char form1[], form2[], form3[];
  650. struct leaf *node;
  651. {
  652.     int f, t, fr, tr;
  653.     char ff, tf, piece, cap;
  654.     char prom;
  655.  
  656.     f = node->f;  t = node->t;
  657.     if ( f == 255 ) {        /* castle king's side */
  658.     ff = 'e'; tf = 'g';
  659.     fr = tr = (side == white) ? 1 : 8;
  660.     cap = '-';
  661.     piece = 'K';
  662.     } else if ( t == 255 ) {    /* castle queen's side */
  663.     ff = 'e'; tf = 'c';
  664.     fr = tr = (side == white) ? 1 : 8;
  665.     cap = '-';
  666.     piece = 'K';
  667.     } else {
  668.     ff = col[f] + 'a'; tf = col[t] + 'a';
  669.     fr = row[f] + 1; tr = row[t] + 1;
  670.     cap = node->flags&(capture|epmask) ? ':' : '-';
  671.     piece = charmap[board[f]];
  672.     }
  673.     switch ( node->flags & promote ) {
  674.     case promote_n: prom = 'N'; break;
  675.     case promote_b: prom = 'B'; break;
  676.     case promote_r: prom = 'R'; break;
  677.     case promote_q:
  678.     prom = 'Q';
  679.     sprintf( form2, "%c%c%d%c%c%d*", piece, ff, fr, cap, tf, tr );
  680.     break;
  681.     default:        prom = '*';
  682.     }
  683.     sprintf( form1, "%c%c%d%c%c%d%c*", piece, ff, fr, cap, tf, tr, prom );
  684.     sprintf( form3, "%c%d%c%d", ff, fr, tf, tr );
  685.     if ( prom != 'Q' )
  686.     strcpy( form2, form1 );
  687. }
  688.  
  689.  
  690. int
  691. MvComp( incomp, reference )
  692. char *incomp, *reference;
  693. {
  694.     for ( ; *incomp == *reference || *incomp == DUNNO; incomp++, reference++ )
  695.     if ( *incomp == '\0' || *reference == '\0' )
  696.         return( true );
  697.     if ( *incomp == ETC ||
  698.         (*reference == ETC &&
  699.         (*incomp == '\0' || index("nbrqNBRQ",*incomp) == NULL)) )
  700.     return( true );
  701.     return( false );
  702. }
  703.  
  704.  
  705. int
  706. DoMove(side, move, ply)
  707. int side;
  708. char move[];
  709. int ply;
  710. {
  711.     int i, j, n;
  712.     int tempb, tempc;
  713.     char expandp[MAXMVSTR], expand[MAXMVSTR], compact[MAXMVSTR];
  714.     char gexpand[MAXMVSTR], gcompact[MAXMVSTR];
  715.     struct leaf *gnode;
  716.  
  717.  
  718.     MoveList( side );
  719.  
  720.     for ( n = 0, i = 0; i < MovePnt; i++ ) {
  721.     ToAlgNot( expandp, expand, compact, &Moves[i], side );
  722.     if ( MvComp(move,expandp) || MvComp(move,expand) ) {
  723. #ifdef DEBUG
  724.         printf( "%s,%s,%s,%s\n", move, expandp, expand, compact );
  725. #endif
  726.         strcpy( gexpand, expand );
  727.         strcpy( gcompact, compact );
  728.         gnode = &Moves[i];
  729.         n++;
  730.     }
  731.     }
  732.  
  733.     switch ( n ) {
  734.     case 0:
  735. #ifdef VERBOSE
  736.     printf( "move %d, %s: illegal move (%s) -- legal moves are:\n",
  737.                 ply/2+1, PLYSIDE(ply), move );
  738.     for ( i = 0; i < MovePnt; ) {
  739.         printf("    ");
  740.         for (j = 0; j < 8 && i < MovePnt; j++, i++) {
  741.         ToAlgNot( expandp, expand, compact, &Moves[i], side );
  742.         printf( "  %s", expand );
  743.         }
  744.         printf("\n");
  745.     }
  746. #else
  747.     printf( "illegal move\n" );
  748. #endif
  749.     return( false );
  750.     case 1:
  751.     printf( "%s\n", gcompact ); fflush( stdout );
  752.     MakeMove( side, gnode, &tempb, &tempc );
  753.     real_ep_square = epsquare;
  754.     return( true );
  755.     default:
  756. #ifdef VERBOSE
  757.     printf( "move %d, %s: ambiguous move (%s) matches:\n",
  758.                 ply/2+1, PLYSIDE(ply), move );
  759.     for (i = 0; i < MovePnt;) {
  760.         printf("    ");
  761.         for (j = 0; j < 8 && i < MovePnt; j++, i++) {
  762.         ToAlgNot( expandp, expand, compact, &Moves[i], side );
  763.         if ( MvComp(move,expandp) || MvComp(move,expand) )
  764.             printf( "  %s\n", expand );
  765.         }
  766.         printf( "\n" );
  767.     }
  768. #else
  769.     printf( "ambiguous move\n" );
  770. #endif
  771.     return( false );
  772.     }
  773. }
  774.  
  775.  
  776. trans(move, ply)
  777. char move[];
  778. int ply;
  779. {
  780.     static int side = white;
  781.  
  782.     if ( !DoMove(side,move,ply) )
  783.     return;
  784.     side = otherside[side];
  785. }
  786.