home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR2 / CBUFF09.ZIP / SRC.ZIP / POSITION.C < prev    next >
C/C++ Source or Header  |  1993-11-16  |  21KB  |  765 lines

  1. /*  $Id: position.c,v 1.1.1.1 1993/06/21 11:12:00 anjo Exp $
  2.  *  
  3.  *  File    position.c
  4.  *  Part of    ChessBase utilities file format (CBUFF)
  5.  *  Author    Horst Aurisch, aurisch@informatik.uni-bonn.de
  6.  *        Anjo Anjewierden, anjo@swi.psy.uva.nl
  7.  *  Purpose    Internal board representation and move generation
  8.  *  Works with    GNU CC 2.4.5
  9.  *  
  10.  *  Notice    Copyright (c) 1993  Anjo Anjewierden
  11.  *  
  12.  *  History    08/06/93  (Created)
  13.  *          30/06/93  (Integrated getmove.c)
  14.  *          05/08/93  (Last modified)
  15.  */ 
  16.  
  17.  
  18. /*------------------------------------------------------------
  19.  *  Directives
  20.  *------------------------------------------------------------*/
  21.  
  22. #include "cbuff.h"
  23.  
  24.  
  25. /*------------------------------------------------------------
  26.  *  Definitions
  27.  *------------------------------------------------------------*/
  28.  
  29. Piece        first[8] = { ROOK, KNIGHT, BISHOP, QUEEN,
  30.                  KING, BISHOP, KNIGHT, ROOK
  31.                };
  32.  
  33.  
  34. /*------------------------------------------------------------
  35.  *  Initialisation
  36.  *------------------------------------------------------------*/
  37.  
  38. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  39. @node newPosition
  40. @deftypefun Position newPosition ()
  41. Returns a new chess position.  The position is initialised to the
  42. initial position.
  43. @end deftypefun
  44. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  45.  
  46. Position
  47. newPosition()
  48. { Square sq;
  49.   Position p;
  50.  
  51.   p = alloc(sizeof(struct position));
  52.  
  53.   for (sq=0; sq<8; sq++)
  54.   { p->board[0+sq*8] = first[sq] | WHITE_MASK;
  55.     p->board[7+sq*8] = first[sq] | BLACK_MASK;
  56.     p->board[1+sq*8] = WHITE_PAWN;
  57.     p->board[6+sq*8] = BLACK_PAWN;
  58.     p->board[2+sq*8] = NO_PIECE;
  59.     p->board[3+sq*8] = NO_PIECE;
  60.     p->board[4+sq*8] = NO_PIECE;
  61.     p->board[5+sq*8] = NO_PIECE;
  62.   }
  63.  
  64.   p->enPassant = 0;
  65.   p->toMove = WHITE;
  66.   p->nextMove = 1;
  67.   p->castling = (WHITE_SHORT | WHITE_LONG | BLACK_SHORT | BLACK_LONG);
  68.  
  69.   return p;
  70. }
  71.  
  72.  
  73. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  74. @node freePosition
  75. @deftypefun void freePosition (Position @var{p})
  76. Reclaims the memory associated with position @var{p}.
  77. @end deftypefun
  78. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  79.  
  80. void
  81. freePosition(Position p)
  82. { unalloc(p);
  83. }
  84.  
  85.  
  86. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  87. @node clearPosition
  88. @deftypefun void clearPosition (Position @var{p})
  89. Clears position @var{p} such that it is empty (e.g. there are no pieces
  90. on the board).
  91. @end deftypefun
  92. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  93.  
  94. void
  95. clearPosition(Position p)
  96. { Square sq;
  97.  
  98.   for_squares(sq)
  99.     p->board[sq] = NO_PIECE;
  100. }
  101.  
  102.  
  103. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  104. @node copyPosition
  105. @deftypefun void copyPosition (Position @var{p1}, Position @var{p2})
  106. Copies position @var{p2} to @var{p1} (argument order is the same
  107. as @code{strcpy}).  Note: @var{p1} must have been allocated with @code{newPosition}
  108. previously.
  109. @end deftypefun
  110. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  111.  
  112. void
  113. copyPosition(Position p1, Position p2)
  114. { memcpy(p1, p2, sizeof(struct position));
  115. }
  116.  
  117.  
  118. /*------------------------------------------------------------
  119.  *  Functions
  120.  *------------------------------------------------------------*/
  121.  
  122. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  123. @node doMovePosition
  124. @deftypefun void doMovePosition (Position @var{p}, Move @var{m})
  125. Plays move @var{m} in position @var{p}.  The caller must ensure that
  126. @var{m} is a legal move.
  127. @end deftypefun
  128. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  129.  
  130. void
  131. doMovePosition(Position pos, Move move)
  132. { Square f = move->from;
  133.   Square t = move->to;
  134.   Piece p = move->piece;
  135.   int c = pos->toMove;
  136.   int ep = pos->enPassant;
  137.   int d = (c == WHITE ? 1 : -1);
  138.   Piece *board = pos->board;
  139.  
  140.   pos->enPassant = 0;
  141.  
  142.     /* En passant capture */
  143.   if (isPawnP(board[f]) && fileSquare(t) != fileSquare(f) && !board[t])
  144.     board[t-d] = 0;
  145.  
  146.     /* Move the piece */
  147.   board[t] = board[f];
  148.   board[f] = NO_PIECE;
  149.  
  150.       /* Promotion */
  151.   if (isPawnP(board[t]) && (rankSquare(t)==RANK_1 || rankSquare(t)==RANK_8))
  152.     board[t] = (p | (c == WHITE ? WHITE_MASK : BLACK_MASK));
  153.  
  154.       /* Set new en passant flag */
  155.   if (isPawnP(board[t]) && abs(t-f) == 2)
  156.     pos->enPassant = 1 + (t>>3);
  157.  
  158.       /* Castling */
  159.   if (isKingP(board[t]) && abs(t-f) == 16)
  160.   { pos->enPassant = ep;
  161.     if (t>f)
  162.     { board[t-8] = board[t+8];
  163.       board[t+8] = 0;
  164.     }
  165.     if (t<f)
  166.     { board[t+8] = board[t-16];
  167.       board[t-16] = 0;
  168.     }
  169.   }
  170.  
  171.   pos->toMove = (c ? WHITE : BLACK);
  172. }
  173.  
  174.  
  175. /*------------------------------------------------------------
  176.  *  Ambiguous moves
  177.  *------------------------------------------------------------*/
  178.  
  179. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  180. @node ambiguousMovePositionP
  181. @deftypefun bool ambiguousMovePositionP (Position @var{p}, Move @var{m}, Square * @var{sq})
  182. Succeeds if move @var{m} is ambiguous in position @var{p}.  The
  183. ambiguous square is then stored in @var{sq}.  The meaning of
  184. ambiguous is that it is not possible to print @var{m} using short
  185. algebraic notation.
  186. @end deftypefun
  187. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  188.  
  189. bool
  190. ambiguousMovePositionP(Position p, Move m, Square *from)
  191. { Piece *board = p->board;
  192.   Piece piece = board[m->from];
  193.   Square sq;
  194.  
  195.   switch (piece)
  196.   { case WHITE_KING:
  197.     case BLACK_KING:
  198.     case WHITE_PAWN:
  199.     case BLACK_PAWN:    return FALSE;
  200.     case WHITE_ROOK:
  201.     case BLACK_ROOK:
  202.     case WHITE_KNIGHT:
  203.     case BLACK_KNIGHT:
  204.     case WHITE_BISHOP:
  205.     case BLACK_BISHOP:
  206.     case WHITE_QUEEN:
  207.     case BLACK_QUEEN:    break;
  208.     default:
  209.         setError(ERR_UNKNOWN_PIECE);
  210.         return FALSE;
  211.   }
  212.  
  213.   for_squares(sq)
  214.   { if (board[sq] == piece)
  215.     { if (m->from == sq)
  216.     continue;
  217.       if (attacksSquarePositionP(p, piece, sq, m->to))
  218.       { *from = sq;
  219.     return TRUE;
  220.       }
  221.     }
  222.   }
  223.   return FALSE;
  224. }
  225.  
  226.  
  227. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  228. @node enPassantMovePositionP
  229. @deftypefun bool enPassantMovePositionP (Position @var{p}, Move @var{m})
  230. Succeeds if move @var{m} in position @var{p} is an en passant capture.
  231. @end deftypefun
  232. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  233.  
  234. bool
  235. enPassantMovePositionP(Position p, Move m)
  236. { if (   isPawnP(p->board[m->from])
  237.       && fileSquare(m->from) != fileSquare(m->to)
  238.       && p->board[m->to] == NO_PIECE)
  239.     return TRUE;
  240.   return FALSE;
  241. }
  242.  
  243.  
  244. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  245. @node castlingMovePositionP
  246. @deftypefun bool castlingMovePositionP (Position @var{p}, Move @var{m})
  247. Succeeds if move @var{m} in position @var{p} is a castling move.
  248. @end deftypefun
  249. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  250.  
  251. bool
  252. castlingMovePositionP(Position p, Move m)
  253. { if (   isKingP(p->board[m->from])
  254.       && (m->from == E1 || m->from == E8 )
  255.       && (rankSquare(m->from) == rankSquare(m->to))
  256.       && (abs(fileSquare(m->from) - fileSquare(m->to)) == 2))
  257.     return TRUE;
  258.   return FALSE;
  259. }
  260.  
  261.  
  262. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  263. @node checkMovePositionP
  264. @deftypefun bool checkMovePositionP (Position @var{p}, Move @var{m})
  265. Succeeds if playing move @var{m} in position @var{p} results in
  266. checking the opponent's king.
  267. @end deftypefun
  268. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  269.  
  270. bool
  271. checkMovePositionP(Position p, Move m)
  272. { Piece piece = p->board[m->from];
  273.   Square kingSquare;
  274.   Square sq;
  275.  
  276.   for_squares(sq)
  277.   { if (isKingP(p->board[sq]))
  278.     { if (   (p->toMove == WHITE && p->board[sq] == BLACK_KING)
  279.       || (p->toMove == BLACK && p->board[sq] == WHITE_KING))
  280.       { kingSquare = sq;
  281.     break;
  282.       }
  283.     }
  284.   }
  285.  
  286.   if (attacksSquarePositionP(p, piece, m->to, kingSquare))
  287.     return TRUE;
  288.  
  289.   p->board[m->from] = NO_PIECE;
  290.  
  291.   for_squares(sq)
  292.   { if (   (p->toMove == WHITE && isWhitePieceP(p->board[sq]))
  293.         || (p->toMove == BLACK && isBlackPieceP(p->board[sq])))
  294.     { if (attacksSquarePositionP(p, p->board[sq], sq, kingSquare))
  295.       { p->board[m->from] = piece;
  296.     return TRUE;
  297.       }
  298.     }
  299.   }
  300.   p->board[m->from] = piece;
  301.   return FALSE;
  302. }
  303.  
  304.  
  305. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  306. @node attacksSquarePositionP
  307. @deftypefun bool attacksSquarePositionP (Position @var{p}, Piece @var{piece}, Square @var{from}, Square @var{to})
  308. Succeeds if piece @var{piece} on square @var{from} attacks square @var{to}
  309. in the given position @var{p}.  The @var{piece} does not need to be on
  310. square @var{from}.
  311. @end deftypefun
  312. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  313.  
  314. bool
  315. attacksSquarePositionP(Position p, Piece piece, Square from, Square to)
  316. { int file;
  317.   int rank;
  318.   Piece *board = p->board;
  319.  
  320.   file = fileSquare(to) - fileSquare(from);
  321.   rank = rankSquare(to) - rankSquare(from);
  322.  
  323.   if (piece == WHITE_PAWN)
  324.   { if (rank == 1 && abs(file) == 1)    /* Only consider pawn captures. */
  325.       return TRUE;
  326.     return FALSE;
  327.   }
  328.  
  329.   if (piece == BLACK_PAWN)
  330.   { if (rank == -1 && abs(file) == 1)
  331.       return TRUE;
  332.     return FALSE;
  333.   }
  334.  
  335.   if (isKingP(piece))
  336.   { if (abs(file) <= 1 && abs(rank) <= 1)
  337.       return TRUE;
  338.     return FALSE;
  339.   }
  340.  
  341.   if (isKnightP(piece))
  342.   { if (   (abs(file) == 2 && abs(rank) == 1)
  343.     || (abs(file) == 1 && abs(rank) == 2))
  344.       return TRUE;
  345.     return FALSE;
  346.   }
  347.  
  348.   if (file == 0)
  349.   { if (isQueenP(piece) || isRookP(piece))
  350.     { int inc = (rank > 0 ? 1 : -1);
  351.  
  352.       for (rank=rankSquare(from)+inc; rank!=rankSquare(to); rank+=inc)
  353.     if (board[makeSquare(fileSquare(to), rank)])
  354.       return FALSE;
  355.       return TRUE;
  356.     }
  357.   }
  358.  
  359.   if (rank == 0)
  360.   { if (isQueenP(piece) || isRookP(piece))
  361.     { int inc = (file > 0 ? 1 : -1);
  362.  
  363.       for (file=fileSquare(from)+inc; file!=fileSquare(to); file+=inc)
  364.     if (board[makeSquare(file, rankSquare(to))])
  365.       return FALSE;
  366.       return TRUE;
  367.     }
  368.   }
  369.  
  370.   if (abs(file) == abs(rank))
  371.   { if (isQueenP(piece) || isBishopP(piece))
  372.     { int incFile = (file > 0 ? 1 : -1);
  373.       int incRank = (rank > 0 ? 1 : -1);
  374.  
  375.       for (file=fileSquare(from)+incFile, rank=rankSquare(from)+incRank;
  376.        file!=fileSquare(to) && rank!=rankSquare(to);
  377.        file+=incFile, rank+=incRank)
  378.     if (board[makeSquare(file, rank)])
  379.       return FALSE;
  380.       return TRUE;
  381.     }
  382.   }
  383.  
  384.   return FALSE;
  385. }
  386.  
  387.  
  388. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  389. @node getStringMovePosition
  390. @deftypefun {char *} getStringMovePosition (Position @var{p}, Move @var{m}, int @var{notation})
  391. Returns the textual representation of playing move @var{m} in the
  392. position @var{p}.  The returned string is statically allocated.  The
  393. format of printing the move is determined by the current set of chess
  394. symbols (@pxref{Chess symbols}) and by @var{notation}.  If
  395. @var{notation} is @code{LONG_ALGEBRAIC} the move is printed using long
  396. algebraic notation, otherwise it is printed using short algebraic
  397. notation.
  398. @end deftypefun
  399. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  400.  
  401. char *
  402. getStringMovePosition(Position p, Move m, int notation)
  403. { static char str[100];
  404.   Square from = m->from;
  405.   Square to = m->to;
  406.   Piece piece = p->board[from];
  407.   char *s;
  408.  
  409.   if (castlingMovePositionP(p, m))
  410.   { if (to == G1 || to == G8)
  411.     { strcpy(str, chessSymbol(CASTLING_SHORT));
  412.       return str;
  413.     }
  414.     if (to == C1 || to == C8)
  415.     { strcpy(str, chessSymbol(CASTLING_LONG));
  416.       return str;
  417.     }
  418.   }
  419.  
  420.   switch (piece)
  421.   { case WHITE_KING:
  422.     case BLACK_KING:    strcpy(str, chessSymbol(KING_SYMBOL)); break;
  423.     case WHITE_QUEEN:
  424.     case BLACK_QUEEN:    strcpy(str, chessSymbol(QUEEN_SYMBOL)); break;
  425.     case WHITE_ROOK:
  426.     case BLACK_ROOK:    strcpy(str, chessSymbol(ROOK_SYMBOL)); break;
  427.     case WHITE_BISHOP:
  428.     case BLACK_BISHOP:    strcpy(str, chessSymbol(BISHOP_SYMBOL)); break;
  429.     case WHITE_KNIGHT:
  430.     case BLACK_KNIGHT:    strcpy(str, chessSymbol(KNIGHT_SYMBOL)); break;
  431.     default:        str[0] = '\0';
  432.   }
  433.  
  434.   s = strrchr(str, '\0');
  435.  
  436.   if (notation == LONG_ALGEBRAIC)
  437.   { *s++ = 'a' + fileSquare(from);
  438.     *s++ = '1' + rankSquare(from);
  439.     if (p->board[to])
  440.       strcpy(s, chessSymbol(CAPTURE_SYMBOL));
  441.     else
  442.       strcpy(s, chessSymbol(MOVE_HYPHEN));
  443.     s = strrchr(s, '\0');
  444.   } else
  445.   { Square ambiguous;
  446.  
  447.     if (ambiguousMovePositionP(p, m, &ambiguous))
  448.     { if (fileSquare(from) != fileSquare(ambiguous))
  449.           *s++ = 'a' + fileSquare(from);
  450.       else
  451.     *s++ = '1' + rankSquare(from);
  452.     }
  453.  
  454.     if (isPawnP(p->board[from]) && (fileSquare(from) != fileSquare(to)))
  455.       *s++ = 'a' + fileSquare(from);
  456.  
  457.     if (p->board[to])
  458.     { strcpy(s, chessSymbol(CAPTURE_SYMBOL));
  459.       s = strrchr(s, '\0');
  460.     }
  461.   }
  462.   *s++ = 'a' + fileSquare(to);
  463.   *s++ = '1' + rankSquare(to);
  464.  
  465.   if (m->piece)
  466.   { strcpy(s, chessSymbol(PROMOTION_SYMBOL));
  467.     s = strrchr(s, '\0');
  468.          if (isQueenP(m->piece))  strcpy(s, chessSymbol(QUEEN_SYMBOL));
  469.     else if (isRookP(m->piece))   strcpy(s, chessSymbol(ROOK_SYMBOL));
  470.     else if (isKnightP(m->piece)) strcpy(s, chessSymbol(KNIGHT_SYMBOL));
  471.     else if (isBishopP(m->piece)) strcpy(s, chessSymbol(BISHOP_SYMBOL));
  472.     s = strrchr(s, '\0');
  473.   }
  474.  
  475.   if (checkMovePositionP(p, m))
  476.   { strcpy(s, chessSymbol(INCHECK_SYMBOL));
  477.     s = strrchr(s, '\0');
  478.   }
  479.  
  480.   *s = '\0';
  481.  
  482.   return str;
  483. }
  484.  
  485.  
  486. /*------------------------------------------------------------
  487.  *  Printing diagrams part of a game
  488.  *------------------------------------------------------------*/
  489.  
  490. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  491. @node diagramPosition
  492. @deftypefun void diagramPosition (Position @var{p}, TextBuffer @var{tb})
  493. Prints position @var{p} as a diagram in text-buffer @var{tb}.  This
  494. function takes all user defined chess symbols into account and is
  495. therefore usable to print diagrams as part of a game.
  496. @end deftypefun
  497. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  498.  
  499. void
  500. diagramPosition(Position p, TextBuffer tb)
  501. { int file, rank;
  502.  
  503.   stringTextBuffer(tb, chessSymbol(START_DIAGRAM));
  504.   for (rank=7; rank>=0; rank--)
  505.   { if (rank != 7)
  506.       stringTextBuffer(tb, chessSymbol(START_DIAGRAM_RANK));
  507.     for (file=0; file<=7; file++)
  508.     { switch (p->board[makeSquare(file,rank)])
  509.       { case WHITE_KING:   stringTextBuffer(tb,chessSymbol(DIAGRAM_WK)); break;
  510.         case WHITE_QUEEN:  stringTextBuffer(tb,chessSymbol(DIAGRAM_WQ)); break;
  511.         case WHITE_ROOK:   stringTextBuffer(tb,chessSymbol(DIAGRAM_WR)); break;
  512.         case WHITE_BISHOP: stringTextBuffer(tb,chessSymbol(DIAGRAM_WB)); break;
  513.         case WHITE_KNIGHT: stringTextBuffer(tb,chessSymbol(DIAGRAM_WN)); break;
  514.         case WHITE_PAWN:   stringTextBuffer(tb,chessSymbol(DIAGRAM_WP)); break;
  515.         case BLACK_KING:   stringTextBuffer(tb,chessSymbol(DIAGRAM_BK)); break;
  516.         case BLACK_QUEEN:  stringTextBuffer(tb,chessSymbol(DIAGRAM_BQ)); break;
  517.         case BLACK_ROOK:   stringTextBuffer(tb,chessSymbol(DIAGRAM_BR)); break;
  518.         case BLACK_BISHOP: stringTextBuffer(tb,chessSymbol(DIAGRAM_BB)); break;
  519.         case BLACK_KNIGHT: stringTextBuffer(tb,chessSymbol(DIAGRAM_BN)); break;
  520.         case BLACK_PAWN:   stringTextBuffer(tb,chessSymbol(DIAGRAM_BP)); break;
  521.     default:  if ((file+rank) & 1)
  522.               stringTextBuffer(tb, chessSymbol(DIAGRAM_WHITE_SQUARE));
  523.           else
  524.             stringTextBuffer(tb, chessSymbol(DIAGRAM_BLACK_SQUARE));
  525.       }
  526.     }
  527.     if (rank != 0)
  528.       stringTextBuffer(tb, chessSymbol(END_DIAGRAM_RANK));
  529.   }
  530.   stringTextBuffer(tb, chessSymbol(END_DIAGRAM));
  531. }
  532.  
  533.  
  534. /*------------------------------------------------------------
  535.  *  Move generation
  536.  *------------------------------------------------------------*/
  537.  
  538. Square        fromfield;
  539. Square        tofield;
  540. Piece        prompiece;
  541.  
  542. static jmp_buf    env;
  543. static int    searchmove;
  544. static int    movnum;
  545.  
  546.  
  547. /*------------------------------------------------------------
  548.  *  Prototypes
  549.  *------------------------------------------------------------*/
  550.  
  551. static void    PutMove(Square, Square, Piece);
  552. static int    OnBoard(int, int, int);
  553. static void    MovePiece(Position pos, Square, int, int, int, int);
  554. static void    Promote(Square, Square);
  555. static void    MakePawnMoves(Position, Square, int);
  556. static void    MakeKingMoves(Position, Square, int);
  557. static void    MakeRookMoves(Position, Square, int);
  558. static void    MakeBishopMoves(Position, Square, int);
  559. static void    MakeQueenMoves(Position, Square, int);
  560. static void    MakeKnightMoves(Position, Square, int);
  561.  
  562.  
  563. /*------------------------------------------------------------
  564.  *  Ordinal move generation (according to ChessBase format)
  565.  *------------------------------------------------------------*/
  566.  
  567. static void
  568. PutMove(Square f, Square t, Piece p)
  569. { fromfield = f;
  570.   tofield = t;
  571.   prompiece = p;
  572.   movnum++;
  573.   if (movnum == searchmove)
  574.     longjmp(env, 1);
  575. }
  576.  
  577.  
  578. static int
  579. OnBoard(int n, int y, int x)
  580. { return ((unsigned)(y+(n&7)) < 8) &&
  581.          ((unsigned)(x+(n>>3)) < 8);
  582. }
  583.  
  584.  
  585. static void
  586. MovePiece(Position pos, Square from, int c, int y, int x, int s)
  587. { Square to = from;
  588.   Square inc = 8*x+y;
  589.  
  590.   if (!OnBoard(to,y,x))
  591.     return;
  592.   do
  593.   { to += inc;
  594.     if (!pos->board[to])
  595.       PutMove(from,to,0);
  596.     else if ((pos->board[to]^c)>8)
  597.     { PutMove(from,to,0);
  598.       return;
  599.     }
  600.     else return;
  601.   } while (s && OnBoard(to,y,x));
  602. }
  603.  
  604.  
  605. static void
  606. Promote(Square from, Square to)
  607. { PutMove(from, to, QUEEN);
  608.   PutMove(from, to, ROOK);
  609.   PutMove(from, to, BISHOP);
  610.   PutMove(from, to, KNIGHT);
  611. }
  612.  
  613.  
  614. static void
  615. MakePawnMoves(Position pos, Square f, int c)
  616. { int h;
  617.   int t;
  618.   int d;
  619.   int g;
  620.  
  621.   if (c == WHITE)
  622.   { d = 1;
  623.     g = 1;
  624.   } else
  625.   { d = -1;
  626.     g = 6;
  627.   }
  628.  
  629.   t = f+d;
  630.   if (!pos->board[t])
  631.   { t += d;
  632.     if ((f&7) == g && !pos->board[t])
  633.       PutMove(f,t,0);
  634.     t -= d;
  635.     if ((t&7) == 7-g+d)
  636.       Promote(f,t);
  637.     else
  638.       PutMove(f,t,0);
  639.   }
  640.  
  641.   t = f-8+d;
  642.   if (f&0x38 && (pos->board[t]^c)>8)
  643.     if ((t&7) == 7-g+d)
  644.       Promote(f,t);
  645.     else
  646.       PutMove(f,t,0);
  647.  
  648.   t = f+8+d;
  649.   if ((f&0x38) != 0x38 && (pos->board[t]^c)>8)
  650.     if ((t&7) == 7-g+d)
  651.       Promote(f,t);
  652.     else
  653.       PutMove(f,t,0);
  654.  
  655.   if ((f&7) == g+3*d)
  656.   { h = (f>>3) - pos->enPassant;
  657.     t = f-8+d;
  658.     if (!h)
  659.       PutMove(f,t,0);
  660.     t = f+8+d;
  661.     if (h == -2)
  662.       PutMove(f,t,0);
  663.   }
  664. }
  665.  
  666.  
  667. static void
  668. MakeKingMoves(Position pos, Square from, int c)
  669. { Piece *board = pos->board;
  670.  
  671.   MovePiece(pos, from, c, -1, -1, 0);
  672.   MovePiece(pos, from, c,  0, -1, 0);
  673.   MovePiece(pos, from, c,  1, -1, 0);
  674.   MovePiece(pos, from, c, -1,  0, 0);
  675.   MovePiece(pos, from, c,  1,  0, 0);
  676.   MovePiece(pos, from, c, -1,  1, 0);
  677.   MovePiece(pos, from, c,  0,  1, 0);
  678.   MovePiece(pos, from, c,  1,  1, 0);
  679.  
  680.   if (c == WHITE_MASK && from == E1)
  681.   { if (board[H1] == WHITE_ROOK && !board[F1] && !board[G1])
  682.       PutMove(from,G1,0);
  683.     if (board[A1] == WHITE_ROOK && !board[D1] && !board[C1] && !board[B1])
  684.       PutMove(from,C1,0);
  685.     return;
  686.   }
  687.  
  688.   if (c == BLACK_MASK && from == E8)
  689.   { if (board[H8] == BLACK_ROOK && !board[F8] && !board[G8])
  690.       PutMove(from,G8,0);
  691.     if (board[A8] == BLACK_ROOK && !board[D8] && !board[C8] && !board[B8])
  692.       PutMove(from,C8,0);
  693.     return;
  694.   }
  695. }
  696.  
  697.  
  698. static void
  699. MakeRookMoves(Position pos, Square from, int c)
  700. { MovePiece(pos, from, c,  0, -1, 1);
  701.   MovePiece(pos, from, c, -1,  0, 1);
  702.   MovePiece(pos, from, c,  0,  1, 1);
  703.   MovePiece(pos, from, c,  1,  0, 1);
  704. }
  705.  
  706.  
  707. static void
  708. MakeBishopMoves(Position pos, Square from, int c)
  709. { MovePiece(pos, from, c, -1, -1, 1);
  710.   MovePiece(pos, from, c, -1,  1, 1);
  711.   MovePiece(pos, from, c,  1,  1, 1);
  712.   MovePiece(pos, from, c,  1, -1, 1);
  713. }
  714.  
  715.  
  716. static void
  717. MakeQueenMoves(Position pos, Square from, int c)
  718. { MakeBishopMoves(pos, from, c);
  719.   MakeRookMoves(pos, from, c);
  720. }
  721.  
  722.  
  723. static void
  724. MakeKnightMoves(Position pos, Square from, int c)
  725. { MovePiece(pos, from, c, -1, -2, 0);
  726.   MovePiece(pos, from, c,  1, -2, 0);
  727.   MovePiece(pos, from, c, -1,  2, 0);
  728.   MovePiece(pos, from, c,  1,  2, 0);
  729.   MovePiece(pos, from, c, -2, -1, 0);
  730.   MovePiece(pos, from, c,  2, -1, 0);
  731.   MovePiece(pos, from, c, -2,  1, 0);
  732.   MovePiece(pos, from, c,  2,  1, 0);
  733. }
  734.  
  735.  
  736. bool
  737. getMovePosition(Position pos, int n, Move move)
  738. { Square sq;
  739.   int c;
  740.  
  741.   c = (pos->toMove == WHITE ? WHITE_MASK : BLACK_MASK);
  742.  
  743.   searchmove = n;
  744.   if (setjmp(env) == 0)
  745.   { movnum = 0;
  746.     for (sq=0; sq<64; sq++)
  747.     { switch ((pos->board[sq])^c)
  748.       { case PAWN:    MakePawnMoves(pos, sq, c);    break;
  749.     case ROOK:    MakeRookMoves(pos, sq, c);    break;
  750.     case BISHOP:    MakeBishopMoves(pos, sq, c);  break;
  751.         case KNIGHT:    MakeKnightMoves(pos, sq, c);  break;
  752.     case QUEEN:    MakeQueenMoves(pos, sq, c);   break;
  753.     case KING:    MakeKingMoves(pos, sq, c);    break;
  754.       }
  755.     }
  756.     return FALSE;
  757.   }
  758.  
  759.   move->from = fromfield;
  760.   move->to = tofield;
  761.   move->piece = prompiece;
  762.  
  763.   return TRUE;
  764. }
  765.