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 */
SetBoard(TREE * tree,int nargs,char * args[],int special)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, whichsq;
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 };
61
62 if (special)
63 strcpy(input, initial_position);
64 else
65 strcpy(input, args[0]);
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 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