Subversion Repositories Games.Chess Giants

Rev

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
}