2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 Contains stuff for setting up boards in examine mode
25 static int check_valid_square(char* square)
27 if (strlen (square) == 2) {
28 if ( (square[0] <= 'a') && (square[0] >= 'h')
29 && (square[1] <= '1') && (square [1] >= '8') )
36 /* Check the position is valid
37 ie two kings - one white one black
38 ie no pawns on 1st or 8th ranks
39 only the king that is to move may be in check,
40 checkmate and stalemate */
42 static int validate_position (int p,struct game_state_t *b)
48 for (f = 0; (f < b->files); f++) {
49 for (r = 0; (r < b->ranks); r++) {
50 if (b->board[f][r] == W_KING) {
53 pprintf (p,"You can only have one white king.\n");
57 if (b->board[f][r] == B_KING) {
60 pprintf (p,"You can only have one black king.\n");
64 if (((b->board[f][r] == W_PAWN) || (b->board[f][r] == B_PAWN)) &&
65 ((r == 0) || (r == b->ranks-1))) {
66 pprintf (p,"Pawns cannot be placed on the first or eighth rank.\n");
72 pprintf (p,"There is no white king.\n");
76 pprintf (p,"There is no black king.\n");
79 if (b->onMove == WHITE) { pprintf(p, "WHITE to move\n"); }
80 else if (b->onMove == BLACK) { pprintf(p, "BLACK to move\n"); }
81 else pprintf(p, "ERROR!!\n");
84 pprintf (p,"Only the player to move may be in check.\n");
87 if (!has_legal_move(b)) {
88 b->onMove = CToggle(b->onMove);
90 pprintf (p, "%s is checkmated.\n",
91 b->onMove == WHITE ? "BLACK" : "WHITE");
93 pprintf (p, "%s is stalemated.\n",
94 b->onMove == WHITE ? "BLACK" : "WHITE");
96 b->onMove = CToggle(b->onMove);
98 return 1; /* valid position */
101 int com_setup (int p,param_list param)
103 struct player *pp = &player_globals.parray[p];
106 if ((pp->game <0) || (game_globals.garray[pp->game].status != GAME_SETUP)) {
107 if (param[0].type == TYPE_NULL) {
109 if (game_globals.garray[pp->game].status == GAME_EXAMINE) {
110 game_free (pp->game);
111 game_globals.garray[pp->game].status = GAME_SETUP;
112 game_globals.garray[pp->game].numHalfMoves = 0;
113 game_globals.garray[pp->game].totalHalfMoves = 0;
114 game_globals.garray[pp->game].revertHalfMove = 0;
115 pprintf (p,"Entering examine(setup) mode.\n");
118 pcommand (p,"examine setup");
119 return COM_OK_NOPROMPT;
121 pprintf(p, "You are not setting up a position.\n");
125 gamenum = game_globals.garray[pp->game].game_state.gameNum;
126 if (param[0].type != TYPE_NULL) {
127 if (!strcmp("clear",param[0].val.word)) {
128 board_clear(&(game_globals.garray[pp->game].game_state));
129 game_globals.garray[pp->game].game_state.gameNum = gamenum;
130 send_board_to(pp->game, p);
131 pprintf (p,"Board cleared.\n");
133 } else if (!strcmp("start",param[0].val.word)) {
134 board_standard(&(game_globals.garray[pp->game].game_state));
135 game_globals.garray[pp->game].game_state.gameNum = gamenum;
136 send_board_to(pp->game, p);
137 pprintf (p,"Board set up as starting position.\n");
139 } else if (!strcmp("fen",param[0].val.word) && param[1].type != TYPE_NULL) {
140 FEN_to_board(param[1].val.string, &(game_globals.garray[pp->game].game_state));
141 game_globals.garray[pp->game].game_state.gameNum = gamenum;
142 send_board_to(pp->game, p);
143 pprintf (p,"Board set up by FEN.\n");
145 } else if (!strcmp("done",param[0].val.word)) {
146 if (validate_position (p,&(game_globals.garray[pp->game].game_state))) {
147 game_globals.garray[pp->game].status = GAME_EXAMINE;
148 pprintf(p,"Game is validated - entering examine mode.\n");
149 MakeFENpos(pp->game, game_globals.garray[pp->game].FENstartPos);
151 pprintf(p,"The position is not valid - staying in setup mode.\n");
153 } else { /* try to load a category of board */
154 char *board = param[1].val.word;
155 if (param[1].type == TYPE_NULL) board = "0";
156 game_globals.garray[pp->game].FENstartPos[0] = 0; // [HGM] new shuffle
157 if (!board_init (pp->game,&(game_globals.garray[pp->game].game_state),param[0].val.word,board)) {
158 game_globals.garray[pp->game].game_state.gameNum = gamenum;
159 if(!strcmp(board,"0"))
160 sprintf(game_globals.garray[pp->game].variant, "%s",param[0].val.word);
162 sprintf(game_globals.garray[pp->game].variant, "%s/%s",param[0].val.word,board);
163 send_board_to(pp->game, p);
164 pprintf (p,"Board set up as %s %s.\n",param[0].val.word,board);
166 pprintf (p,"Board %s %s is unavailable.\n",param[0].val.word,board);
167 game_globals.garray[pp->game].game_state.gameNum = gamenum;
173 pprintf (p, "You have supplied an incorrect parameter to setup.\n");
177 int com_tomove (int p,param_list param)
179 struct player *pp = &player_globals.parray[p];
180 if ((pp->game <0) || (game_globals.garray[pp->game].status != GAME_SETUP)) {
182 if (game_globals.garray[pp->game].status == GAME_EXAMINE) {
183 pprintf (p,"This game is active - type 'setup' to allow editing.\n");
186 pprintf(p, "You are not setting up a position.\n");
189 if (!strcmp("white",param[0].val.word))
190 game_globals.garray[pp->game].game_state.onMove = WHITE;
191 else if (!strcmp("black",param[0].val.word))
192 game_globals.garray[pp->game].game_state.onMove = BLACK;
194 pprintf (p,"Please type: tomove white or tomove black\n");
197 pcommand (p,"refresh");
198 return COM_OK_NOPROMPT;
201 int com_clrsquare (int p,param_list param)
203 struct player *pp = &player_globals.parray[p];
204 if ((pp->game <0) || (game_globals.garray[pp->game].status != GAME_SETUP)) {
206 if (game_globals.garray[pp->game].status == GAME_EXAMINE) {
207 pprintf (p,"This game is active - type 'setup' to allow editing.\n");
210 pprintf(p, "You are not setting up a position.\n");
214 if (!check_valid_square(param[0].val.word)) {
215 pprintf (p,"You must specify a square.");
219 pcommand (p,"x@%s",param[0].val.word);
220 return COM_OK_NOPROMPT;
223 /* allows the following
225 x@rf or X@rf - clear a square
226 P@rf - drop a white pawn
227 p@rf - drop a black pawn
228 wp@rf - drop a white pawn
229 bp@rf - drop a black pawn
230 can replace the @ with a * - some people do not have a @ key
233 /* having to check before then after is lame - will change this later */
234 int is_drop(char* dropstr)
237 int len = strlen (dropstr);
239 if ((len < 4) || (len > 5))
244 if ((dropstr[0] == 'x') || (dropstr[0] == 'X')) {
245 if (!((dropstr[1] == '@') || (dropstr[1] == '*')))
247 if (!check_valid_square(dropstr+2))
252 } else if (dropstr[0] == 'w') {
253 if (!((dropstr[1] == 'p') || (dropstr[1] == 'r') || (dropstr[1] == 'n') || (dropstr[1] == 'b') || (dropstr[1] == 'q') || (dropstr[1] == 'k')))
255 if (!((dropstr[2] == '@') || (dropstr[2] == '*')))
257 if (!check_valid_square(dropstr+3))
262 } else if (len == 5) { /* so b@e2 and bb@e2 aren't confused */
263 if (dropstr[0] == 'b') {
264 if (!((dropstr[1] == 'p') || (dropstr[1] == 'r') || (dropstr[1] == 'n') || (dropstr[1] == 'b') || (dropstr[1] == 'q') || (dropstr[1] == 'k')))
266 if (!((dropstr[2] == '@') || (dropstr[2] == '*')))
268 if (!check_valid_square(dropstr+3))
270 } else return 0; /* Exhausted 5 char possibilities */
272 /* check p@e3 and P@e3 */
274 } else if ((dropstr[0] == 'p') || (dropstr[0] == 'r') || (dropstr[0] == 'n') || (dropstr[0] == 'b') || (dropstr[0] == 'q') || (dropstr[0] == 'k') ||
275 (dropstr[0] == 'P') || (dropstr[0] == 'R') || (dropstr[0] == 'N') || (dropstr[0] == 'B') || (dropstr[0] == 'Q') || (dropstr[0] == 'K')) {
277 if (!((dropstr[1] == '@') || (dropstr[1] == '*')))
279 if (!check_valid_square(dropstr+2))
282 return 1; /* valid drop */
285 static void getsquare(char* square,int *f, int *r)
287 *f = square[0] - 'a';
288 *r = square[1] - '1';
291 int attempt_drop(int p,int g,char* dropstr)
293 int len = strlen (dropstr);
299 if ((len < 4) || (len > 5))
304 if ((dropstr[0] == 'x') || (dropstr[0] == 'X')) { /* as x must be clear */
305 getsquare(dropstr+2,&f,&r);
310 } else if (dropstr[0] == 'w') {
311 piece = CharToPiece(dropstr[1], game_globals.garray[g].game_state.variant) & 0x7F;
313 getsquare(dropstr+3,&f,&r);
317 } else if (len == 5) { /* check length to avoid b@e2 and bb@e2 being confused */
318 if (dropstr[0] == 'b') {
319 piece = CharToPiece(dropstr[1], game_globals.garray[g].game_state.variant) | BLACK;
320 getsquare(dropstr+3,&f,&r);
323 /* check p@e3 and P@e3 */
326 if (!((dropstr[1] == '@') || (dropstr[1] == '*')))
329 piece = CharToPiece(dropstr[0], game_globals.garray[g].game_state.variant);
330 getsquare(dropstr+2,&f,&r);
334 game_globals.garray[g].game_state.board[f][r] = piece;
335 return 1; /* valid drop */