Subversion Repositories Games.Chess Giants

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "chess.h"
  2. #include "data.h"
  3. /* last modified 05/08/14 */
  4. /*
  5.  *******************************************************************************
  6.  *                                                                             *
  7.  *   SetBoard() is used to set up the board in any position desired.  It uses  *
  8.  *   a forsythe-like string of characters to describe the board position.      *
  9.  *                                                                             *
  10.  *   The standard piece codes p,n,b,r,q,k are used to denote the type of piece *
  11.  *   on a square, upper/lower case are used to indicate the side (program/     *
  12.  *   opponent) of the piece.                                                   *
  13.  *                                                                             *
  14.  *   The pieces are entered with square a8 first, then b8, ... until the full  *
  15.  *   8th rank is completed.  A "/" terminates that rank.  This is repeated for *
  16.  *   each of the 8 ranks, with the last (1st) rank not needing a terminating   *
  17.  *   "/".  For empty squares, a number between 1 and 8 can be used to indicate *
  18.  *   the number of adjacent empty squares.                                     *
  19.  *                                                                             *
  20.  *   That board description must be followed by a "b" or "w" to indicate which *
  21.  *   side is on move.                                                          *
  22.  *                                                                             *
  23.  *   Next, up to 4 characters are used to indicate which side can castle and   *
  24.  *   to which side.  An uppercase K means white can castle kingside, while a   *
  25.  *   lowercase q means black can castle queenside.                             *
  26.  *                                                                             *
  27.  *   Finally, if there is an enpassant capture possible (the last move was a   *
  28.  *   double pawn move and there was an enemy pawn that could capture it.  The  *
  29.  *   square is the square the capturing pawn ends up on.                       *
  30.  *                                                                             *
  31.  *         K2R/PPP////q/5ppp/7k/ b - -                                         *
  32.  *                                                                             *
  33.  *   this assumes that k represents a white king and -q represents a black     *
  34.  *   queen.                                                                    *
  35.  *                                                                             *
  36.  *                          k  *  *  r  *  *  *  *                             *
  37.  *                          p  p  p  *  *  *  *  *                             *
  38.  *                          *  *  *  *  *  *  *  *                             *
  39.  *                          *  *  *  *  *  *  *  *                             *
  40.  *                          *  *  *  *  *  *  *  *                             *
  41.  *                         -q  *  *  *  *  *  *  *                             *
  42.  *                          *  *  *  *  * -p -p -p                             *
  43.  *                          *  *  *  *  *  *  * -k                             *
  44.  *                                                                             *
  45.  *******************************************************************************
  46.  */
  47. void SetBoard(TREE * tree, int nargs, char *args[], int special) {
  48.   int twtm, i, match, num, pos, square, tboard[64];
  49.   int bcastle, ep, wcastle, error = 0;
  50.   char input[80];
  51.   static const char bdinfo[] =
  52.       { 'k', 'q', 'r', 'b', 'n', 'p', '*', 'P', 'N', 'B',
  53.     'R', 'Q', 'K', '*', '1', '2', '3', '4',
  54.     '5', '6', '7', '8', '/'
  55.   };
  56.   static const char status[13] =
  57.       { 'K', 'Q', 'k', 'q', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
  58.     'h', ' '
  59.   };
  60.   int whichsq;
  61.   static const int firstsq[8] = { 56, 48, 40, 32, 24, 16, 8, 0 };
  62.   if (special)
  63.     strcpy_s(input, sizeof (input), initial_position); // Pierre-Marie Baty -- use safe version
  64.   else
  65.     strcpy_s(input, sizeof (input), args[0]); // Pierre-Marie Baty -- use safe version
  66.   for (i = 0; i < 64; i++)
  67.     tboard[i] = 0;
  68. /*
  69.  ************************************************************
  70.  *                                                          *
  71.  *  Scan the input string searching for pieces, numbers     *
  72.  *  [empty squares], slashes [end-of-rank] and a blank      *
  73.  *  [end of board, start of castle status].                 *
  74.  *                                                          *
  75.  ************************************************************
  76.  */
  77.   whichsq = 0;
  78.   square = firstsq[whichsq];
  79.   num = 0;
  80.   for (pos = 0; pos < (int) strlen(args[0]); pos++) {
  81.     for (match = 0; match < 23 && args[0][pos] != bdinfo[match]; match++);
  82.     if (match > 22)
  83.       break;
  84. /*
  85.  "/" -> end of this rank.
  86.  */
  87.     else if (match == 22) {
  88.       num = 0;
  89.       if (whichsq > 6)
  90.         break;
  91.       square = firstsq[++whichsq];
  92.     }
  93. /*
  94.  "1-8" -> empty squares.
  95.  */
  96.     else if (match >= 14) {
  97.       num += match - 13;
  98.       square += match - 13;
  99.       if (num > 8) {
  100.         printf("more than 8 squares on one rank\n");
  101.         error = 1;
  102.         break;
  103.       }
  104.       continue;
  105.     }
  106. /*
  107.  piece codes.
  108.  */
  109.     else {
  110.       if (++num > 8) {
  111.         printf("more than 8 squares on one rank\n");
  112.         error = 1;
  113.         break;
  114.       }
  115.       tboard[square++] = match - 6;
  116.     }
  117.   }
  118. /*
  119.  ************************************************************
  120.  *                                                          *
  121.  *  Now extract (a) side to move [w/b], (b) castle status   *
  122.  *  [KkQq for white/black king-side ok, white/black queen-  *
  123.  *  side ok], (c) enpassant target square.                  *
  124.  *                                                          *
  125.  ************************************************************
  126.  */
  127.   twtm = 0;
  128.   ep = 0;
  129.   wcastle = 0;
  130.   bcastle = 0;
  131. /*
  132.  ************************************************************
  133.  *                                                          *
  134.  *  Side to move.                                           *
  135.  *                                                          *
  136.  ************************************************************
  137.  */
  138.   if (args[1][0] == 'w')
  139.     twtm = 1;
  140.   else if (args[1][0] == 'b')
  141.     twtm = 0;
  142.   else {
  143.     printf("side to move is bad\n");
  144.     error = 1;
  145.   }
  146. /*
  147.  ************************************************************
  148.  *                                                          *
  149.  *  Castling/enpassant status.                              *
  150.  *                                                          *
  151.  ************************************************************
  152.  */
  153.   if (nargs > 2 && strlen(args[2])) {
  154.     if (strcmp(args[2], "-")) {
  155.       for (pos = 0; pos < (int) strlen(args[2]); pos++) {
  156.         for (match = 0; (match < 13) && (args[2][pos] != status[match]);
  157.             match++);
  158.         if (match == 0)
  159.           wcastle += 1;
  160.         else if (match == 1)
  161.           wcastle += 2;
  162.         else if (match == 2)
  163.           bcastle += 1;
  164.         else if (match == 3)
  165.           bcastle += 2;
  166.         else if (args[2][0] != '-') {
  167.           printf("castling status is bad.\n");
  168.           error = 1;
  169.         }
  170.       }
  171.     }
  172.   }
  173.   if (nargs > 3 && strlen(args[3])) {
  174.     if (strcmp(args[3], "-")) {
  175.       if (args[3][0] >= 'a' && args[3][0] <= 'h' && args[3][1] > '0' &&
  176.           args[3][1] < '9') {
  177.         ep = (args[3][1] - '1') * 8 + args[3][0] - 'a';
  178.       } else if (args[3][0] != '-') {
  179.         printf("enpassant status is bad.\n");
  180.         error = 1;
  181.       }
  182.     }
  183.   }
  184.   for (i = 0; i < 64; i++)
  185.     PcOnSq(i) = tboard[i];
  186.   Castle(0, white) = wcastle;
  187.   Castle(0, black) = bcastle;
  188.   EnPassant(0) = 0;
  189.   if (ep) {
  190.     do {
  191.       if (twtm && Rank(ep) == RANK6 && PcOnSq(ep - 8) == -pawn) {
  192.         if (File(ep) != 7 && PcOnSq(ep - 7) == pawn)
  193.           break;
  194.         if (File(ep) != 0 && PcOnSq(ep - 9) == pawn)
  195.           break;
  196.       } else if (!twtm && Rank(ep) == RANK3 && PcOnSq(ep + 8) == pawn) {
  197.         if (File(ep) != 0 && PcOnSq(ep + 7) == -pawn)
  198.           break;
  199.         if (File(ep) != 7 && PcOnSq(ep + 9) == -pawn)
  200.           break;
  201.       } else {
  202.         ep = 0;
  203.       }
  204.       if (!ep) {
  205.         printf("enpassant status is bad.\n");
  206.         ep = 0;
  207.         error = 1;
  208.       }
  209.     } while (0);
  210.     EnPassant(0) = ep;
  211.   }
  212. /*
  213.  ************************************************************
  214.  *                                                          *
  215.  *  Now check the castling status status to make sure that  *
  216.  *  the board is in a state that matches.                   *
  217.  *                                                          *
  218.  ************************************************************
  219.  */
  220.   if (((Castle(0, white) & 2) && (PcOnSq(A1) != rook))
  221.       || ((Castle(0, white) & 1) && (PcOnSq(H1) != rook))
  222.       || ((Castle(0, black) & 2) && (PcOnSq(A8) != -rook))
  223.       || ((Castle(0, black) & 1) && (PcOnSq(H8) != -rook))) {
  224.     printf("ERROR-- castling status does not match board position\n");
  225.     error = 1;
  226.   }
  227. /*
  228.  ************************************************************
  229.  *                                                          *
  230.  *  Now set the bitboards so that error tests can be done.  *
  231.  *                                                          *
  232.  ************************************************************
  233.  */
  234.   SetChessBitBoards(tree);
  235. /*
  236.  ************************************************************
  237.  *                                                          *
  238.  *  Now check the position for a sane position, which means *
  239.  *  no more than 8 pawns, no more than 10 knights, bishops  *
  240.  *  or rooks, no more than 9 queens, no pawns on 1st or 8th *
  241.  *  rank, etc.                                              *
  242.  *                                                          *
  243.  ************************************************************
  244.  */
  245.   game_wtm = twtm;
  246.   error += InvalidPosition(tree);
  247.   if (!error) {
  248.     if (log_file)
  249.       DisplayChessBoard(log_file, tree->position);
  250.     tree->rep_index = 0;
  251.     tree->rep_list[0] = HashKey;
  252.     Reversible(0) = 0;
  253.     if (!special) {
  254.       last_mate_score = 0;
  255.       InitializeKillers();
  256.       last_pv.pathd = 0;
  257.       last_pv.pathl = 0;
  258.       tree->pv[0].pathd = 0;
  259.       tree->pv[0].pathl = 0;
  260.       moves_out_of_book = 0;
  261.     }
  262.   } else {
  263.     if (special)
  264.       Print(4095, "bad string = \"%s\"\n", initial_position);
  265.     else
  266.       Print(4095, "bad string = \"%s\"\n", args[0]);
  267.     InitializeChessBoard(tree);
  268.     Print(4095, "Illegal position, using normal initial chess position\n");
  269.   }
  270. }
  271.