This is the doxygen documentation for gtkboard.
.00001 /* This file is a part of gtkboard, a board games system. 00002 Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net> 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA 00017 00018 */ 00019 #include <stdio.h> 00020 #include <string.h> 00021 #include <stdlib.h> 00022 #include <assert.h> 00023 00024 #include "game.h" 00025 #include "../pixmaps/chess.xpm" 00026 #include "move.h" 00027 00028 #define CHESS_CELL_SIZE 54 00029 #define CHESS_NUM_PIECES 12 00030 00031 #define CHESS_BOARD_WID 8 00032 #define CHESS_BOARD_HEIT 8 00033 00034 #define CHESS_EMPTY 0 00035 #define CHESS_WK 1 00036 #define CHESS_WQ 2 00037 #define CHESS_WR 3 00038 #define CHESS_WB 4 00039 #define CHESS_WN 5 00040 #define CHESS_WP 6 00041 #define CHESS_BK 7 00042 #define CHESS_BQ 8 00043 #define CHESS_BR 9 00044 #define CHESS_BB 10 00045 #define CHESS_BN 11 00046 #define CHESS_BP 12 00047 00048 #define A_FILE 0 00049 #define B_FILE 1 00050 #define C_FILE 2 00051 #define D_FILE 3 00052 #define E_FILE 4 00053 #define F_FILE 5 00054 #define G_FILE 6 00055 #define H_FILE 7 00056 00057 #define RANK_1 0 00058 #define RANK_2 1 00059 #define RANK_3 2 00060 #define RANK_4 3 00061 #define RANK_5 4 00062 #define RANK_6 5 00063 #define RANK_7 6 00064 #define RANK_8 7 00065 00066 #define CHESS_ISWHITE(x) (x >= 1 && x <= 6) 00067 #define CHESS_ISBLACK(x) (x >= 7 && x <= 12) 00068 00069 #ifndef abs 00070 #define abs(x) ((x) < 0 ? -(x) : (x)) 00071 #endif 00072 00073 char chess_colors[] = 00074 {200, 200, 130, 00075 0, 140, 0}; 00076 00077 int chess_init_pos[] = 00078 { 00079 9 , 11, 10, 8 , 7 , 10, 11, 9 , 00080 12, 12, 12, 12, 12, 12, 12, 12 , 00081 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 00082 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 00083 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 00084 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 00085 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 00086 3 , 5 , 4 , 2 , 1 , 4 , 5 , 3 , 00087 }; 00088 static int chess_max_moves = 200; 00089 00090 char ** chess_pixmaps[] = 00091 00092 { 00093 chess_wk_54_xpm, 00094 chess_wq_54_xpm, 00095 chess_wr_54_xpm, 00096 chess_wb_54_xpm, 00097 chess_wn_54_xpm, 00098 chess_wp_54_xpm, 00099 chess_bk_54_xpm, 00100 chess_bq_54_xpm, 00101 chess_br_54_xpm, 00102 chess_bb_54_xpm, 00103 chess_bn_54_xpm, 00104 chess_bp_54_xpm, 00105 }; 00106 00107 00108 00109 void chess_init (); 00110 int chess_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **); 00111 ResultType chess_who_won (Pos *, Player, char **); 00112 byte *chess_movegen (Pos *); 00113 ResultType chess_eval (Pos *, Player, float *); 00114 void *chess_newstate (Pos *, byte *); 00115 void chess_reset_uistate (); 00116 00117 Game Chess = 00118 { CHESS_CELL_SIZE, CHESS_BOARD_WID, CHESS_BOARD_HEIT, 00119 CHESS_NUM_PIECES, 00120 chess_colors, chess_init_pos, chess_pixmaps, "Chess", 00121 chess_init}; 00122 00123 typedef struct 00124 { 00125 int castle_WK:2; 00126 int castle_WQ:2; 00127 int castle_BK:2; 00128 int castle_BQ:2; 00129 int epfile:4; 00130 } Chess_state; 00131 00132 //Chess_state state; 00133 00134 void chess_init () 00135 { 00136 game_getmove = chess_getmove; 00137 game_who_won = chess_who_won; 00138 game_movegen = chess_movegen; 00139 game_eval = chess_eval; 00140 game_stateful = TRUE; 00141 game_state_size = sizeof (Chess_state); 00142 game_newstate = chess_newstate; 00143 game_file_label = FILERANK_LABEL_TYPE_ALPHA; 00144 game_rank_label = FILERANK_LABEL_TYPE_NUM | FILERANK_LABEL_DESC; 00145 game_reset_uistate = chess_reset_uistate; 00146 game_allow_flip = TRUE; 00147 game_doc_about = 00148 "Chess\n" 00149 "Two player game\n" 00150 "Status: Partially implemented (currently unplayable)\n" 00151 "URL: "GAME_DEFAULT_URL("chess"); 00152 } 00153 00154 void *chess_newstate (Pos *pos, byte *move) 00155 { 00156 static Chess_state state = {1, 1, 1, 1, -1}; 00157 if (!pos->state) return &state; 00158 memcpy (&state, pos->state, sizeof (Chess_state)); 00159 00160 { 00161 int val, to_x, to_y; 00162 // if pawn moves two squares to 4th rank then set epf 00163 if (move[2] != 0) { val = move[2]; to_x = move[0]; to_y = move[1]; } 00164 else if (move[5] != 0) { val = move[5]; to_x = move[3]; to_y = move[4]; } 00165 else assert (0); 00166 if ( 00167 (val == CHESS_WP 00168 && ((move[1] == 1 && move[4] == 3) || (move[1] == 3 && move[4] == 1))) 00169 || 00170 (val == CHESS_BP 00171 && ((move[1] == 6 && move[3] == 4) || (move[1] == 6 && move[4] == 6))) 00172 ) 00173 state.epfile = move[0]; 00174 else state.epfile = -1; 00175 00176 if (val == CHESS_WK) state.castle_WK = state.castle_WQ = 0; 00177 if (val == CHESS_BK) state.castle_BK = state.castle_BQ = 0; 00178 if (val == CHESS_WR && to_x >= 4) state.castle_WK = 0; 00179 if (val == CHESS_WR && to_x < 4) state.castle_WQ = 0; 00180 if (val == CHESS_BR && to_x >= 4) state.castle_BK = 0; 00181 if (val == CHESS_BR && to_x < 4) state.castle_BQ = 0; 00182 } 00183 00184 return &state; 00185 } 00186 00187 static int isfreeline (byte *pos, int oldx, int oldy, int newx, int newy) 00188 { 00189 int x = oldx, y = oldy, dx, dy, diffx = newx - oldx, diffy = newy - oldy; 00190 if (abs (diffx) != abs(diffy) && diffx != 0 && diffy != 0) 00191 return 0; 00192 dx = (diffx ? (diffx / abs (diffx)) : 0); 00193 dy = (diffy ? (diffy / abs (diffy)) : 0); 00194 for (x+=dx, y+=dy; x != newx || y != newy; x+=dx, y+=dy) 00195 if (pos [y * board_wid + x] != 0) 00196 return 0; 00197 return 1; 00198 } 00199 00200 static int islegal (Pos *pos, int oldx, int oldy, int x, int y) 00201 { 00202 int piece = pos->board [oldy * board_wid + oldx]; 00203 byte *board = pos->board; 00204 switch (piece) 00205 { 00206 case CHESS_WK: 00207 case CHESS_BK: 00208 { 00209 int rank, rook; 00210 int diffx = abs (x - oldx), diffy = abs (y - oldy); 00211 if (diffx <= 1 && diffy <= 1) return 1; 00212 // castling 00213 rank = (piece == CHESS_WK ? 0 : 7); 00214 rook = (piece == CHESS_WK ? CHESS_WR : CHESS_BR); 00215 if (oldx != 4) return 0; 00216 if (oldy != rank || y != rank) return 0; 00217 // TODO: not yet checking if 00218 // - the intervening squares are uncontrolled 00219 // - king hasn't moved yet 00220 if (x == 6) 00221 { 00222 if (board [rank * board_wid + 7] != rook) return 0; 00223 if (board [rank * board_wid + 6] != 0) return 0; 00224 if (board [rank * board_wid + 5] != 0) return 0; 00225 return 1; 00226 } 00227 else if (x == 2) 00228 { 00229 if (board [rank * board_wid + 0] != rook) return 0; 00230 if (board [rank * board_wid + 1] != 0) return 0; 00231 if (board [rank * board_wid + 2] != 0) return 0; 00232 if (board [rank * board_wid + 3] != 0) return 0; 00233 return 1; 00234 } 00235 return 0; 00236 } 00237 case CHESS_WQ: 00238 case CHESS_BQ: 00239 return isfreeline (board, oldx, oldy, x, y); 00240 case CHESS_WR: 00241 case CHESS_BR: 00242 if (!isfreeline (board, oldx, oldy, x, y)) 00243 return 0; 00244 if (oldx == x || oldy == y) 00245 return 1; 00246 return 0; 00247 case CHESS_WB: 00248 case CHESS_BB: 00249 if (!isfreeline (board, oldx, oldy, x, y)) 00250 return 0; 00251 if (oldx == x || oldy == y) 00252 return 0; 00253 return 1; 00254 case CHESS_WN: 00255 case CHESS_BN: 00256 { 00257 int diffx = abs (x - oldx), diffy = abs (y - oldy); 00258 if (diffx == 2 && diffy == 1) 00259 return 1; 00260 if (diffx == 1 && diffy == 2) 00261 return 1; 00262 return 0; 00263 } 00264 case CHESS_WP: 00265 if (board [y * board_wid + x] == 0) 00266 { 00267 // en passant 00268 if (y == 5 && oldy == 4 && (x == oldx + 1 || x == oldx - 1) 00269 && board [oldy * board_wid + x] == CHESS_BP) 00270 return 1; 00271 return (x == oldx && (y == oldy + 1 || 00272 (y == 3 && oldy == 1 && board [(2*board_wid + x)] == 0))); 00273 } 00274 return y == oldy + 1 && (x == oldx + 1 || x == oldx - 1) ; 00275 case CHESS_BP: 00276 if (board [y * board_wid + x] == 0) 00277 { 00278 if (y == 4 && oldy == 5 && (x == oldx + 1 || x == oldx - 1) 00279 && board [oldy * board_wid + x] == CHESS_WP) 00280 return 1; 00281 return (x == oldx && (y == oldy - 1 || 00282 (y == 4 && oldy == 6 && board [5*board_wid + x] == 0))); 00283 } 00284 return y == oldy - 1 && (x == oldx + 1 || x == oldx - 1) ; 00285 default: 00286 return 1; 00287 } 00288 } 00289 00290 static int oppcolor (byte *board, int oldx, int oldy, int x, int y) 00291 /* True if one square is W and the other is B */ 00292 { 00293 int oldv = board [oldy * board_wid + oldx], v = board [y * board_wid + x]; 00294 if (CHESS_ISWHITE (oldv) && CHESS_ISBLACK (v)) return 1; 00295 if (CHESS_ISBLACK (oldv) && CHESS_ISWHITE (v)) return 1; 00296 return 0; 00297 } 00298 00299 static gboolean is_in_check (Pos *pos, Player player) 00300 { 00301 int i, j, kingx = -1, kingy = -1; 00302 for (i=0; i<board_wid; i++) 00303 for (j=0; j<board_heit; j++) 00304 { 00305 int val = pos->board [j * board_wid + i]; 00306 if ((player == WHITE && val == CHESS_WK) || 00307 (player == BLACK && val == CHESS_BK)) 00308 { 00309 kingx = i; 00310 kingy = j; 00311 } 00312 } 00313 00314 for (i=0; i<board_wid; i++) 00315 for (j=0; j<board_heit; j++) 00316 { 00317 int val = pos->board [j * board_wid + i]; 00318 if (!((player == WHITE && CHESS_ISBLACK (val)) || 00319 (player == BLACK && CHESS_ISWHITE (val)))) 00320 continue; 00321 if (islegal (pos, i, j, kingx, kingy)) 00322 return TRUE; 00323 } 00324 return FALSE; 00325 } 00326 00328 static gboolean leads_to_check (byte *board, byte *move, Player player) 00329 { 00330 static byte newboard [CHESS_BOARD_WID*CHESS_BOARD_HEIT]; 00331 Pos pos; 00332 memcpy (newboard, board, board_wid * board_heit); 00333 move_apply (newboard, move); 00334 pos.board = newboard; 00335 pos.state = NULL; 00336 return is_in_check (&pos, player); 00337 00338 } 00339 00340 static int oldx = -1, oldy = -1, oldval = -1; 00341 static int prom = 0, prom_x, prom_oldx; 00342 00343 void chess_reset_uistate () 00344 { 00345 oldx = -1, oldy = -1, oldval = -1; 00346 prom = 0; 00347 } 00348 00349 int chess_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player player, 00350 byte ** movep, int ** rmovep) 00351 /* Translate mouse clicks into move */ 00352 { 00353 static byte move [13]; 00354 int val; 00355 if (type != GTKBOARD_BUTTON_RELEASE) 00356 return 0; 00357 00358 if (oldx >= 0 && x == oldx && y == oldy) 00359 { 00360 oldx = -1; oldy = -1; return 0; 00361 } 00362 00363 /* pawn promotion */ 00364 if (prom) 00365 { 00366 int new_p = -1; 00367 prom = 0; 00368 switch(x) 00369 { 00370 case 0: case 7: 00371 new_p = (player == WHITE ? CHESS_WR : CHESS_BR); break; 00372 case 1: case 6: 00373 new_p = (player == WHITE ? CHESS_WN : CHESS_BN); break; 00374 case 2: case 5: 00375 new_p = (player == WHITE ? CHESS_WB : CHESS_BB); break; 00376 case 3: case 4: 00377 new_p = (player == WHITE ? CHESS_WQ : CHESS_BQ); break; 00378 } 00379 move[0] = prom_oldx; 00380 move[1] = (player == WHITE ? 6 : 1); 00381 move[2] = 0; 00382 move[3] = prom_x; 00383 move[4] = (player == WHITE ? 7 : 0); 00384 move[5] = new_p; 00385 move[6] = -1; 00386 00387 if (leads_to_check (pos->board, move, player)) return -1; 00388 00389 if (movep) 00390 *movep = move; 00391 return 1; 00392 } 00393 val = pos->board [y * board_wid + x]; 00394 if (oldx == -1) 00395 { 00396 if (val == 0) return -1; 00397 if (player == WHITE && !CHESS_ISWHITE (val)) 00398 return -1; 00399 if (player == BLACK && !CHESS_ISBLACK (val)) 00400 return -1; 00401 oldx = x; oldy = y, oldval = val; 00402 return 0; 00403 } 00404 if (player == WHITE && CHESS_ISWHITE (val)) 00405 { 00406 oldx = -1; oldy = -1; 00407 return -1; 00408 } 00409 if (player == BLACK && CHESS_ISBLACK (val)) 00410 { 00411 oldx = -1; oldy = -1; 00412 return -1; 00413 } 00414 00415 if (!islegal (pos, oldx, oldy, x, y)) 00416 { 00417 oldx = -1; oldy = -1; 00418 return -1; 00419 } 00420 00421 /* en passant */ 00422 if ((oldval == CHESS_WP || oldval == CHESS_BP) && val == 0 00423 && x != oldx) 00424 { 00425 move[0] = oldx; move[1] = oldy; move[2] = 0; 00426 move[3] = x; move[4] = y; move[5] = oldval; 00427 move[6] = x; move[7] = oldy; move[8] = 0; 00428 move[9] = -1; 00429 if (leads_to_check (pos->board, move, player)) return -1; 00430 if (movep) 00431 *movep = move; 00432 return 1; 00433 } 00434 00435 /* pawn promotion */ 00436 if ((oldval == CHESS_WP || oldval == CHESS_BP) && 00437 (y == 0 || y == board_heit - 1)) 00438 { 00439 prom = 1; 00440 prom_oldx = oldx; 00441 prom_x = x; 00442 oldx = oldy = -1; 00443 return 0; 00444 } 00445 00446 /* castling */ 00447 if ((oldval == CHESS_WK || oldval == CHESS_BK) 00448 && abs (x - oldx) > 1) 00449 { 00450 int rfile = x == 6 ? 7 : 0; 00451 int rook = pos->board [y * board_wid + rfile]; 00452 move[0] = oldx; move[1] = oldy; move[2] = 0; 00453 move[3] = x; move[4] = y; move[5] = oldval; 00454 move[6] = (oldx + x)/2; move[7] = y; move[8] = rook; 00455 move[9] = rfile; move[10] = y; move[11] = 0; 00456 move[12] = -1; 00457 oldx = -1, oldy = -1; 00458 if (leads_to_check (pos->board, move, player)) return -1; 00459 if (movep) 00460 *movep = move; 00461 return 1; 00462 } 00463 00464 move[0] = oldx; move[1] = oldy; move[2] = 0; 00465 move[3] = x; move[4] = y; move[5] = oldval; 00466 move[6] = -1; 00467 00468 oldx = -1; oldy = -1; 00469 if (leads_to_check (pos->board, move, player)) return -1; 00470 00471 if (movep) 00472 *movep = move; 00473 return 1; 00474 } 00475 00476 static int hasmove (Pos *pos, int player) 00477 { 00478 int x1, y1, x2, y2, val; 00479 for (x1 = 0; x1 < board_wid; x1++) 00480 for (y1 = 0; y1 < board_heit; y1++) 00481 { 00482 val = pos->board [y1 * board_wid + x1]; 00483 if (player == WHITE && !CHESS_ISWHITE (val)) continue; 00484 if (player == BLACK && !CHESS_ISBLACK (val)) continue; 00485 for (x2 = 0; x2 < board_wid; x2++) 00486 for (y2 = 0; y2 < board_heit; y2++) 00487 if (islegal (pos, x1, y1, x2, y2)) return 1; 00488 } 00489 return 0; 00490 } 00491 00492 ResultType chess_who_won (Pos *pos, Player player, char **commp) 00493 { 00494 static char comment[32]; 00495 char *who_str [3] = { "White won", "Black won", "Draw" }; 00496 byte *move_list; 00497 *commp = NULL; 00498 move_list = chess_movegen (pos); 00499 if (move_list[0] != -2) 00500 { 00501 if (pos->num_moves > chess_max_moves) 00502 { 00503 fprintf (stderr, "max moves reached\n"); 00504 snprintf (comment, 32, "%s", who_str[2]); 00505 *commp = comment; 00506 return RESULT_TIE; 00507 } 00508 return RESULT_NOTYET; 00509 } 00510 *commp = comment; 00511 if (is_in_check (pos, player)) 00512 { 00513 strncpy (comment, who_str[player == WHITE ? 1 : 0], 31); 00514 return player == WHITE ? RESULT_BLACK : RESULT_WHITE; 00515 } 00516 else 00517 { 00518 strncpy (comment, who_str[2], 31); 00519 return RESULT_TIE; 00520 } 00521 } 00522 00523 int chess_movegen_square (byte *board, byte **movp, int player, 00524 int oldx, int oldy, int x, int y) 00525 { 00526 int val; 00527 if (!ISINBOARD(x, y)) return 0; 00528 val = board [y * board_heit + x]; 00529 if ((player == WHITE && CHESS_ISWHITE (val)) 00530 || (player == BLACK && CHESS_ISBLACK (val))) 00531 return 0; 00532 *(*movp)++ = oldx; 00533 *(*movp)++ = oldy; 00534 *(*movp)++ = 0; 00535 *(*movp)++ = x; 00536 *(*movp)++ = y; 00537 *(*movp)++ = board [oldy * board_heit + oldx]; 00538 *(*movp)++ = -1; 00539 if (leads_to_check (board, *movp-7, player)) 00540 { 00541 *movp -= 7; 00542 return 0; 00543 } 00544 return 1; 00545 } 00546 00547 int chess_movegen_line (byte *pos, byte **movp, int player, 00548 int x, int y, int incx, int incy) 00549 { 00550 int oldx = x, oldy = y; 00551 int capture = 0, val; 00552 do 00553 { 00554 x += incx; 00555 y += incy; 00556 val = pos [y * board_heit + x]; 00557 if (ISINBOARD (x, y) && oppcolor (pos, oldx, oldy, x, y)) 00558 capture = 1; 00559 } while (chess_movegen_square (pos, movp, player, oldx, oldy, x, y) && !capture); 00560 return 0; 00561 } 00562 00563 static void chess_movegen_promote (byte *board, byte **movp, int player, 00564 int oldx, int oldy, int x, int y) 00565 { 00566 int i, j; 00567 int promote_pieces[2][4] = { 00568 {CHESS_WQ, CHESS_WR, CHESS_WB, CHESS_WN}, 00569 {CHESS_BQ, CHESS_BR, CHESS_BB, CHESS_BN} 00570 }; 00571 i = (player == WHITE ? 0 : 1); 00572 for(j=0; j<4; j++) 00573 { 00574 *(*movp)++ = oldx; 00575 *(*movp)++ = oldy; 00576 *(*movp)++ = 0; 00577 *(*movp)++ = x; 00578 *(*movp)++ = y; 00579 *(*movp)++ = promote_pieces[i][j]; 00580 *(*movp)++ = -1; 00581 if (leads_to_check (board, *movp-7, player)) 00582 { 00583 *movp -= 7; 00584 return; 00585 } 00586 } 00587 } 00588 00589 static void chess_movegen_enpassant (Pos *pos, byte **movp, int player, 00590 int x, int y) 00591 { 00592 int val = pos->board [y * board_wid + x]; 00593 int epfile; 00594 if (!pos->state) epfile = -1; 00595 else epfile = ((Chess_state *)pos->state)->epfile; 00596 if (epfile < 0) 00597 return; 00598 if ((player == WHITE && val != CHESS_WP) || 00599 (player == BLACK && val != CHESS_BP)) 00600 return; 00601 if ((player == WHITE && y != 4) || 00602 (player == BLACK && y != 3)) 00603 return; 00604 if (abs (x - epfile) != 1) 00605 return; 00606 *(*movp)++ = x; 00607 *(*movp)++ = y; 00608 *(*movp)++ = 0; 00609 *(*movp)++ = epfile; 00610 *(*movp)++ = y + (player == WHITE ? 1 : -1); 00611 *(*movp)++ = val; 00612 *(*movp)++ = epfile; 00613 *(*movp)++ = y; 00614 *(*movp)++ = 0; 00615 *(*movp)++ = -1; 00616 if (leads_to_check (pos->board, *movp-10, player)) 00617 *movp -= 10; 00618 } 00619 00620 static void chess_movegen_castle (Pos *pos, byte **movp, int player) 00621 { 00622 int rank = player == WHITE ? RANK_1 : RANK_8; 00623 int king = player == WHITE ? CHESS_WK : CHESS_BK; 00624 int rook = player == WHITE ? CHESS_WR : CHESS_BR; 00625 int castle_k, castle_q; 00626 byte *board = pos->board; 00627 if (!pos->state) return; 00628 castle_k = player == WHITE ? 00629 ((Chess_state *)pos->state)->castle_WK : ((Chess_state *)pos->state)->castle_BK; 00630 castle_q = player == WHITE ? 00631 ((Chess_state *)pos->state)->castle_WQ : ((Chess_state *)pos->state)->castle_BQ; 00632 if (board [rank * board_wid + E_FILE] != king) 00633 return; 00634 if (is_in_check (pos, player)) return; 00635 00636 if (board [rank * board_wid + H_FILE] == rook && castle_k) 00637 { 00638 gboolean allowed = TRUE; 00639 *(*movp)++ = E_FILE; 00640 *(*movp)++ = rank; 00641 *(*movp)++ = 0; 00642 *(*movp)++ = F_FILE; 00643 *(*movp)++ = rank; 00644 *(*movp)++ = king; 00645 *(*movp)++ = -1; 00646 if (leads_to_check (pos->board, *movp-7, player)) 00647 allowed = FALSE; 00648 *movp -= 7; 00649 00650 *(*movp)++ = E_FILE; 00651 *(*movp)++ = rank; 00652 *(*movp)++ = 0; 00653 *(*movp)++ = G_FILE; 00654 *(*movp)++ = rank; 00655 *(*movp)++ = king; 00656 *(*movp)++ = -1; 00657 if (leads_to_check (pos->board, *movp-7, player)) 00658 allowed = FALSE; 00659 *movp -= 7; 00660 00661 if (allowed) 00662 { 00663 *(*movp)++ = E_FILE; 00664 *(*movp)++ = rank; 00665 *(*movp)++ = 0; 00666 *(*movp)++ = G_FILE; 00667 *(*movp)++ = rank; 00668 *(*movp)++ = king; 00669 *(*movp)++ = H_FILE; 00670 *(*movp)++ = rank; 00671 *(*movp)++ = 0; 00672 *(*movp)++ = F_FILE; 00673 *(*movp)++ = rank; 00674 *(*movp)++ = rook; 00675 *(*movp)++ = -1; 00676 } 00677 } 00678 00679 if (board [rank * board_wid + A_FILE] == rook && castle_q) 00680 { 00681 gboolean allowed = TRUE; 00682 *(*movp)++ = E_FILE; 00683 *(*movp)++ = rank; 00684 *(*movp)++ = 0; 00685 *(*movp)++ = D_FILE; 00686 *(*movp)++ = rank; 00687 *(*movp)++ = king; 00688 *(*movp)++ = -1; 00689 if (leads_to_check (pos->board, *movp-7, player)) 00690 allowed = FALSE; 00691 *movp -= 7; 00692 00693 *(*movp)++ = E_FILE; 00694 *(*movp)++ = rank; 00695 *(*movp)++ = 0; 00696 *(*movp)++ = C_FILE; 00697 *(*movp)++ = rank; 00698 *(*movp)++ = king; 00699 *(*movp)++ = -1; 00700 if (leads_to_check (pos->board, *movp-7, player)) 00701 allowed = FALSE; 00702 *movp -= 7; 00703 00704 if (allowed) 00705 { 00706 *(*movp)++ = E_FILE; 00707 *(*movp)++ = rank; 00708 *(*movp)++ = 0; 00709 *(*movp)++ = C_FILE; 00710 *(*movp)++ = rank; 00711 *(*movp)++ = king; 00712 *(*movp)++ = A_FILE; 00713 *(*movp)++ = rank; 00714 *(*movp)++ = 0; 00715 *(*movp)++ = D_FILE; 00716 *(*movp)++ = rank; 00717 *(*movp)++ = rook; 00718 *(*movp)++ = -1; 00719 } 00720 } 00721 } 00722 00723 byte *chess_movegen (Pos *pos) 00724 { 00725 byte realbuf[4096]; 00726 byte *realp = realbuf; 00727 byte movbuf[4096], *movp = movbuf; 00728 byte *movlist; 00729 int i, j, k, x, y; 00730 int incxr[] = {0, 0, 1, -1}; 00731 int incyr[] = {1, -1, 0, 0}; 00732 int incxb[] = {1, 1, -1, -1}; 00733 int incyb[] = {1, -1, 1, -1}; 00734 int incxn[] = {2, 2, -2, -2, 1, 1, -1, -1}; 00735 int incyn[] = {1, -1, 1, -1, 2, -2, 2, -2}; 00736 byte *board = pos->board; 00737 Player player = pos->player; 00738 for (i=0; i<board_wid; i++) 00739 for (j=0; j<board_heit; j++) 00740 { 00741 int val = board[j * board_heit + i]; 00742 if ((player == WHITE && CHESS_ISWHITE (val)) 00743 || (player == BLACK && CHESS_ISBLACK (val))) 00744 { 00745 switch (val) 00746 { 00747 case CHESS_WP: 00748 chess_movegen_enpassant (pos, &movp, player, i, j); 00749 if (ISINBOARD (i, j+1) && board [(j+1) * board_heit + i] == 0) 00750 { 00751 if (j == board_heit - 2) 00752 chess_movegen_promote(board, &movp, player, 00753 i, j, i, j+1); 00754 else 00755 chess_movegen_square (board, &movp, player, 00756 i, j, i, j+1); 00757 } 00758 if (ISINBOARD (i+1, j+1) && 00759 CHESS_ISBLACK (board [(j+1) * board_heit + i+1])) 00760 { 00761 if (j == board_heit - 2) 00762 chess_movegen_promote (board, &movp, player, 00763 i, j, i+1, j+1); 00764 else 00765 chess_movegen_square (board, &movp, player, 00766 i, j, i+1, j+1); 00767 } 00768 if (ISINBOARD (i-1, j+1) && 00769 CHESS_ISBLACK (board [(j+1) * board_heit + i-1])) 00770 { 00771 if (j == board_heit - 2) 00772 chess_movegen_promote (board, &movp, player, 00773 i, j, i-1, j+1); 00774 else 00775 chess_movegen_square (board, &movp, player, 00776 i, j, i-1, j+1); 00777 } 00778 if (j == 1 && board [2 * board_heit + i] == 0 00779 && board [3 * board_heit + i] == 0) 00780 chess_movegen_square (board, &movp, player, 00781 i, j, i, j+2); 00782 break; 00783 case CHESS_BP: 00784 chess_movegen_enpassant (pos, &movp, player, i, j); 00785 if (ISINBOARD (i, j-1) && board [(j-1) * board_heit + i] == 0) 00786 { 00787 if (j == 1) 00788 chess_movegen_promote (board, &movp, player, 00789 i, j, i, j-1); 00790 else 00791 chess_movegen_square (board, &movp, player, 00792 i, j, i, j-1); 00793 } 00794 if (ISINBOARD (i+1, j-1) && 00795 CHESS_ISWHITE (board [(j-1) * board_heit + i+1])) 00796 { 00797 if (j == 1) 00798 chess_movegen_promote (board, &movp, player, 00799 i, j, i+1, j-1); 00800 else 00801 chess_movegen_square (board, &movp, player, 00802 i, j, i+1, j-1); 00803 } 00804 if (ISINBOARD (i-1, j-1) && 00805 CHESS_ISWHITE (board [(j-1) * board_heit + i-1])) 00806 { 00807 if (j == 1) 00808 chess_movegen_promote (board, &movp, player, 00809 i, j, i-1, j-1); 00810 else 00811 chess_movegen_square (board, &movp, player, 00812 i, j, i-1, j-1); 00813 } 00814 if (j == 6 && board [5 * board_heit + i] == 0 00815 && board [4 * board_heit + i] == 0) 00816 chess_movegen_square (board, &movp, player, 00817 i, j, i, j-2); 00818 break; 00819 case CHESS_WK: 00820 case CHESS_BK: 00821 chess_movegen_castle (pos, &movp, player); 00822 for (k=0; k<4; k++) 00823 chess_movegen_square(board, &movp, player, 00824 i, j, i + incxr[k], j + incyr[k]); 00825 for (k=0; k<4; k++) 00826 chess_movegen_square(board, &movp, player, 00827 i, j, i + incxb[k], j + incyb[k]); 00828 break; 00829 case CHESS_WB: 00830 case CHESS_BB: 00831 for (k=0; k<4; k++) 00832 chess_movegen_line (board, &movp, player, 00833 i, j, incxb[k], incyb[k]); 00834 break; 00835 case CHESS_WR: 00836 case CHESS_BR: 00837 for (k=0; k<4; k++) 00838 chess_movegen_line (board, &movp, player, 00839 i, j, incxr[k], incyr[k]); 00840 break; 00841 case CHESS_WQ: 00842 case CHESS_BQ: 00843 for (k=0; k<4; k++) 00844 chess_movegen_line (board, &movp, player, 00845 i, j, incxb[k], incyb[k]); 00846 for (k=0; k<4; k++) 00847 chess_movegen_line (board, &movp, player, 00848 i, j, incxr[k], incyr[k]); 00849 break; 00850 case CHESS_WN: 00851 case CHESS_BN: 00852 for (k=0; k<8; k++) 00853 chess_movegen_square(board, &movp, player, 00854 i, j, i + incxn[k], j + incyn[k]); 00855 break; 00856 } 00857 } 00858 } 00859 *movp++ = -2; 00860 00861 movlist = (byte *) malloc (movp - movbuf); 00862 memcpy (movlist, movbuf, movp - movbuf); 00863 return movlist; 00864 } 00865 00866 float getweight (byte val) 00867 { 00868 if (val == 0) 00869 return 0; 00870 switch (val) 00871 { 00872 case CHESS_WK: return 100; 00873 case CHESS_WQ: return 9; 00874 case CHESS_WR: return 5; 00875 case CHESS_WB: return 3; 00876 case CHESS_WN: return 3; 00877 case CHESS_WP: return 1; 00878 case CHESS_BK: return -100; 00879 case CHESS_BQ: return -9; 00880 case CHESS_BR: return -5; 00881 case CHESS_BB: return -3; 00882 case CHESS_BN: return -3; 00883 case CHESS_BP: return -1; 00884 default: return 0; 00885 } 00886 } 00887 00888 ResultType chess_eval (Pos * pos, Player player, float *eval) 00889 { 00890 float sum = 0; 00891 int i; 00892 for (i=0; i<board_wid * board_heit; i++) 00893 sum += getweight (pos->board [i]); 00894 *eval = sum; 00895 return RESULT_NOTYET; 00896 }