Rev 33 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 33 | pmbaty | 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 |  *                                                                             * | ||
| 108 | pmbaty | 31 |  *           K2R/PPP////q/5ppp/7k/ b - -                                       * | 
| 33 | pmbaty | 32 |  *                                                                             * | 
| 33 |  *   this assumes that k represents a white king and -q represents a black     * | ||
| 34 |  *   queen.                                                                    * | ||
| 35 |  *                                                                             * | ||
| 108 | pmbaty | 36 |  *                            k  *  *  r  *  *  *  *                           * | 
| 37 |  *                            p  p  p  *  *  *  *  *                           * | ||
| 38 |  *                            *  *  *  *  *  *  *  *                           * | ||
| 39 |  *                            *  *  *  *  *  *  *  *                           * | ||
| 40 |  *                            *  *  *  *  *  *  *  *                           * | ||
| 41 |  *                           -q  *  *  *  *  *  *  *                           * | ||
| 42 |  *                            *  *  *  *  * -p -p -p                           * | ||
| 43 |  *                            *  *  *  *  *  *  * -k                           * | ||
| 33 | pmbaty | 44 |  *                                                                             * | 
| 45 |  ******************************************************************************* | ||
| 46 |  */ | ||
| 47 | void SetBoard(TREE * tree, int nargs, char *args[], int special) { | ||
| 48 | int twtm, i, match, num, pos, square, tboard[64]; | ||
| 108 | pmbaty | 49 | int bcastle, ep, wcastle, error = 0, whichsq; | 
| 33 | pmbaty | 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 | static const int firstsq[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; | ||
| 108 | pmbaty | 61 | |
| 33 | pmbaty | 62 | if (special) | 
| 108 | pmbaty | 63 | strcpy(input, initial_position); | 
| 33 | pmbaty | 64 |   else | 
| 108 | pmbaty | 65 | strcpy(input, args[0]); | 
| 33 | pmbaty | 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); | ||
| 108 | pmbaty | 250 | rep_index = 0; | 
| 33 | pmbaty | 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 | } |