This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

antichess.c

Go to the documentation of this file.
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 
00023 #include "game.h"
00024 #include "../pixmaps/chess.xpm"
00025 
00026 
00027 #define ANTICHESS_CELL_SIZE 54
00028 #define ANTICHESS_NUM_PIECES 12
00029 
00030 #define ANTICHESS_BOARD_WID 8
00031 #define ANTICHESS_BOARD_HEIT 8
00032 
00033 #define ANTICHESS_WK 1
00034 #define ANTICHESS_WQ 2
00035 #define ANTICHESS_WR 3
00036 #define ANTICHESS_WB 4
00037 #define ANTICHESS_WN 5
00038 #define ANTICHESS_WP 6
00039 #define ANTICHESS_BK 7
00040 #define ANTICHESS_BQ 8
00041 #define ANTICHESS_BR 9
00042 #define ANTICHESS_BB 10
00043 #define ANTICHESS_BN 11
00044 #define ANTICHESS_BP 12
00045 
00046 #define ANTICHESS_ISWHITE(x) (x >= 1 && x <= 6)
00047 #define ANTICHESS_ISBLACK(x) (x >= 7 && x <= 12)
00048 
00049 #ifndef abs
00050 #define abs(x) ((x) < 0 ? -(x) : (x))
00051 #endif
00052 
00053 static char antichess_colors[] = 
00054         {200, 200, 130, 
00055         0, 140, 0};
00056 char antichess_highlight_colors[9] = {0xff, 0, 0};
00057 
00058 static int antichess_init_pos[] = 
00059 {
00060          9 , 11, 10, 8 , 7 , 10, 11, 9  ,
00061          12, 12, 12, 12, 12, 12, 12, 12 ,
00062          0 , 0 , 0 , 0 , 0 , 0 , 0 , 0  ,
00063          0 , 0 , 0 , 0 , 0 , 0 , 0 , 0  ,
00064          0 , 0 , 0 , 0 , 0 , 0 , 0 , 0  ,
00065          0 , 0 , 0 , 0 , 0 , 0 , 0 , 0  ,
00066          6 , 6 , 6 , 6 , 6 , 6 , 6 , 6  ,
00067          3 , 5 , 4 , 2 , 1 , 4 , 5 , 3  ,
00068 };
00069 static int antichess_max_moves = 200;
00070 
00071 static char ** antichess_pixmaps[] =
00072 
00073 {
00074         chess_wk_54_xpm, 
00075         chess_wq_54_xpm, 
00076         chess_wr_54_xpm, 
00077         chess_wb_54_xpm, 
00078         chess_wn_54_xpm, 
00079         chess_wp_54_xpm, 
00080         chess_bk_54_xpm, 
00081         chess_bq_54_xpm, 
00082         chess_br_54_xpm, 
00083         chess_bb_54_xpm, 
00084         chess_bn_54_xpm, 
00085         chess_bp_54_xpm,
00086 };
00087 
00088 
00089 
00090 void antichess_init ();
00091 int antichess_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
00092 ResultType antichess_who_won (Pos *, Player, char **);
00093 byte *antichess_movegen (Pos *);
00094 ResultType antichess_eval (Pos *, Player, float *);
00095 ResultType antichess_eval_incr (Pos *, Player, byte *, float *);
00096         
00097 Game Antichess = 
00098         { ANTICHESS_CELL_SIZE, ANTICHESS_BOARD_WID, ANTICHESS_BOARD_HEIT, 
00099         ANTICHESS_NUM_PIECES,
00100         antichess_colors, antichess_init_pos, antichess_pixmaps, "Antichess",
00101         antichess_init};
00102 
00103 Game * plugin_game = &Antichess;
00104 
00105 void antichess_init ()
00106 {
00107         game_getmove = antichess_getmove;
00108         game_who_won = antichess_who_won;
00109         game_movegen = antichess_movegen;
00110         game_eval = antichess_eval;
00111 //      game_eval_incr = antichess_eval_incr;
00112         game_file_label = FILERANK_LABEL_TYPE_ALPHA;
00113         game_rank_label = FILERANK_LABEL_TYPE_NUM | FILERANK_LABEL_DESC;
00114         game_highlight_colors = antichess_highlight_colors;
00115         game_allow_flip = TRUE;
00116         game_doc_about = 
00117                 "Antichess\n"
00118                 "Two player game\n"
00119                 "Status: Fully implemented\n"
00120                 "URL: "GAME_DEFAULT_URL("antichess");
00121         game_doc_rules = 
00122                 "Antichess rules\n"
00123                 "\n"
00124                 "The objective of the game is to force your opponent to capture all your pieces or to stalemate you. What makes this possible is that if you can capture, then you MUST.\n"
00125                 "\n"
00126                 "The pieces move as in chess. However:\n"
00127                 "   - The king is NOT a special piece. No check(mate), no castling. The king can be captured like any other piece.\n"
00128                 "   - No taking en passant.\n"
00129                 "   - Pawn promotion is as in chess.\n"
00130                 "\n"
00131                 "A couple of notes on the gtkboard implementation of chess and antichess:\n"
00132                 "   - Drag and drop doesn't work (yet). To make the move 1. e4, you have to click on e2 and then on e4.\n"
00133                 "   - To promote, after clicking on the pawn and then on the promotion square, you have to click on a third square which indicates which piece you want to promote to. This square should be any one of the squares of the file of that piece. (Thus, to queen, click anywhere on the 'd' file, etc.)";
00134 }
00135 
00136 static int isfreeline (byte *pos, int oldx, int oldy, int newx, int newy)
00137 {
00138         int x = oldx, y = oldy, dx, dy, diffx = newx - oldx, diffy = newy - oldy;
00139         if (abs (diffx) != abs(diffy) && diffx != 0 && diffy != 0)
00140                 return 0;
00141         dx = (diffx ? (diffx / abs (diffx)) : 0);
00142         dy = (diffy ? (diffy / abs (diffy)) : 0);
00143         for (x+=dx, y+=dy; x != newx || y != newy; x+=dx, y+=dy)
00144                 if (pos [y * board_wid + x] != 0)
00145                         return 0;
00146         return 1;       
00147 }
00148 
00149 static int islegal (Pos *pos, int oldx, int oldy, int x, int y, int player)
00150 {
00151         int piece = pos->board [oldy * board_wid + oldx];
00152         byte *board = pos->board;
00153         switch (piece)
00154         {
00155                 case ANTICHESS_WK:
00156                 case ANTICHESS_BK:
00157                         {
00158                                 int diffx = abs (x - oldx), diffy = abs (y - oldy);
00159                                 return diffx <= 1 && diffy <= 1;
00160                         }
00161                 case ANTICHESS_WQ:
00162                 case ANTICHESS_BQ:
00163                         return isfreeline (board, oldx, oldy, x, y);
00164                 case ANTICHESS_WR:
00165                 case ANTICHESS_BR:
00166                         if (!isfreeline (board, oldx, oldy, x, y))
00167                                 return 0;
00168                         if (oldx == x || oldy == y)
00169                                 return 1;
00170                         return 0;
00171                 case ANTICHESS_WB:
00172                 case ANTICHESS_BB:
00173                         if (!isfreeline (board, oldx, oldy, x, y))
00174                                 return 0;
00175                         if (oldx == x || oldy == y)
00176                                 return 0;
00177                         return 1;
00178                 case ANTICHESS_WN:
00179                 case ANTICHESS_BN:
00180                         {
00181                                 int diffx = abs (x - oldx), diffy = abs (y - oldy);
00182                                 if (diffx == 2 && diffy == 1)
00183                                         return 1;
00184                                 if (diffx == 1 && diffy == 2)
00185                                         return 1;
00186                                 return 0;
00187                         }
00188                 case ANTICHESS_WP:
00189                         if (board [y * board_wid + x] == 0)
00190                                 return (x == oldx && (y == oldy + 1 || 
00191                                                 (y == 3 && oldy == 1 && board [(2*board_wid + x)] == 0)));
00192                         return y == oldy + 1  && (x == oldx + 1 || x == oldx - 1) ;
00193                 case ANTICHESS_BP:
00194                         if (board [y * board_wid + x] == 0)
00195                                 return (x == oldx && (y == oldy - 1 ||
00196                                                 (y == 4 && oldy == 6 && board [5*board_wid + x] == 0)));
00197                         return y == oldy - 1  && (x == oldx + 1 || x == oldx - 1) ;
00198                 default:
00199                         return 1;
00200         }
00201 }
00202 
00203 static int can_capture (Pos *pos, int player)
00204 {
00205         int x1, y1, x2, y2, val;
00206         for (x1 = 0; x1 < board_wid; x1++)
00207         for (y1 = 0; y1 < board_heit; y1++)
00208         {
00209                 val = pos->board [y1 * board_wid + x1];
00210                 if (player == WHITE && !ANTICHESS_ISWHITE (val)) continue;
00211                 if (player == BLACK && !ANTICHESS_ISBLACK (val)) continue;
00212                 for (x2 = 0; x2 < board_wid; x2++)
00213                 for (y2 = 0; y2 < board_heit; y2++)
00214                 {
00215                         val = pos->board [y2 * board_wid + x2];
00216                         if (player == WHITE && !ANTICHESS_ISBLACK (val)) continue;
00217                         if (player == BLACK && !ANTICHESS_ISWHITE (val)) continue;
00218                         if (islegal (pos, x1, y1, x2, y2, player)) return 1;
00219                 }               
00220         }
00221         return 0;
00222 }
00223 
00224 static int oppcolor (byte *pos, int oldx, int oldy, int x, int y)
00225         /* True if one square is W and the other is B */
00226 {
00227         int oldv = pos [oldy * board_wid + oldx], v = pos [y * board_wid + x];
00228         if (ANTICHESS_ISWHITE (oldv) && ANTICHESS_ISBLACK (v)) return 1;
00229         if (ANTICHESS_ISBLACK (oldv) && ANTICHESS_ISWHITE (v)) return 1;
00230         return 0;
00231 }
00232 
00233 static int oldx = -1, oldy = -1, oldval = -1;
00234 static int prom = 0, prom_x, prom_oldx;
00235 
00236 void antichess_free ()
00237 {
00238         oldx = -1, oldy = -1, prom = 0;
00239 }
00240 
00241 int antichess_getmove (Pos *pos, int x, int y, 
00242                 GtkboardEventType type, Player player, byte ** movep, int ** rmovep)
00243         /* Translate mouse clicks into move */
00244 {
00245         static byte move [7];
00246         static int rmove [7];
00247         int *rp = rmove;
00248         int val;
00249         if (type != GTKBOARD_BUTTON_RELEASE)
00250                 return 0;
00251 
00252         val = pos->board [y * board_wid + x];
00253 
00254         if (oldx >= 0 && x == oldx && y == oldy)
00255         {
00256                 *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_NONE; *rp++ = -1; *rmovep = rmove;
00257                 oldx = -1; oldy = -1; return 0;
00258         }
00259         
00260         // if you can capture you must capture
00261         if (oldx >= 0 && can_capture (pos, player) && 
00262                         !((ANTICHESS_ISWHITE (val) && ANTICHESS_ISBLACK (oldval))
00263                          || (ANTICHESS_ISBLACK (val) && ANTICHESS_ISWHITE (oldval))))
00264         {
00265                 *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_NONE; *rp++ = -1; *rmovep = rmove;
00266                 oldx = oldy = -1;
00267                 return -1;
00268         }
00269         
00270         /* pawn promotion */ 
00271         if (prom)
00272         {
00273                 int new_p = -1;
00274                 prom = 0;
00275                 switch(x)
00276                 {
00277                         case 0: case 7:
00278                                 new_p = (player == WHITE ? ANTICHESS_WR : ANTICHESS_BR); break;
00279                         case 1: case 6:
00280                                 new_p = (player == WHITE ? ANTICHESS_WN : ANTICHESS_BN); break;
00281                         case 2: case 5:
00282                                 new_p = (player == WHITE ? ANTICHESS_WB : ANTICHESS_BB); break;
00283                         case 3: case 4:
00284                                 new_p = (player == WHITE ? ANTICHESS_WQ : ANTICHESS_BQ); break;
00285                 }
00286                 move[0] = prom_oldx;
00287                 move[1] = (player == WHITE ? 6 : 1);
00288                 move[2] = 0;
00289                 move[3] = prom_x;
00290                 move[4] = (player == WHITE ? 7 : 0);
00291                 move[5] = new_p;
00292                 move[6] = -1;
00293                 
00294                 if (movep)
00295                         *movep = move;
00296                 return 1;
00297         }
00298         if (oldx == -1)
00299         {
00300                 if (val == 0) return -1;
00301                 if (player == WHITE && !ANTICHESS_ISWHITE (val))
00302                         return -1;
00303                 if (player == BLACK && !ANTICHESS_ISBLACK (val))
00304                         return -1;
00305                 oldx = x; oldy = y, oldval = val;
00306                 *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_HIGHLIGHT1; *rp++ = -1; *rmovep = rmove;
00307                 return 0;
00308         }
00309         if (player == WHITE && ANTICHESS_ISWHITE (val))
00310         {
00311                 *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_NONE; *rp++ = -1; *rmovep = rmove;
00312                 oldx = -1; oldy = -1;
00313                 return -1;
00314         }
00315         if (player == BLACK && ANTICHESS_ISBLACK (val))
00316         {
00317                 *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_NONE; *rp++ = -1; *rmovep = rmove;
00318                 oldx = -1; oldy = -1;
00319                 return -1;
00320         }
00321 
00322         if (!islegal (pos, oldx, oldy, x, y, player))
00323                 // FIXME
00324                 //|| (can_capture (pos, player) && !oppcolor (pos, oldx, oldy, x, y)))
00325         {
00326                 *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_NONE; *rp++ = -1; *rmovep = rmove;
00327                 oldx = -1; oldy = -1;
00328                 return -1;
00329         }
00330 
00331         /* pawn promotion */
00332         if ((oldval == ANTICHESS_WP || oldval == ANTICHESS_BP) &&
00333                         (y == 0 || y == board_heit - 1))
00334         {
00335                 prom = 1;
00336                 prom_oldx = oldx;
00337                 prom_x = x;
00338                 *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_NONE; *rp++ = -1; *rmovep = rmove;
00339                 oldx = oldy = -1;
00340                 return 0;
00341         }
00342 
00343         move[0] = oldx; move[1] = oldy; move[2] = 0;
00344         move[3] = x; move[4] = y; move[5] = pos->board [oldy * board_wid + oldx];
00345         move[6] = -1;
00346 
00347         *rp++ = oldx; *rp++ = oldy; *rp++ = RENDER_NONE; *rp++ = -1; *rmovep = rmove;
00348         oldx = -1; oldy = -1;
00349         
00350         if (movep)
00351                 *movep = move;
00352         return 1;
00353         /*if (player == WHITE && ANTICHESS_ISWHITE (val))
00354                 return 0;*/
00355 }
00356 
00357 static int hasmove (Pos *pos, int player)
00358 {
00359         int x1, y1, x2, y2, val;
00360         for (x1 = 0; x1 < board_wid; x1++)
00361         for (y1 = 0; y1 < board_heit; y1++)
00362         {
00363                 val = pos->board [y1 * board_wid + x1];
00364                 if (player == WHITE && !ANTICHESS_ISWHITE (val)) continue;
00365                 if (player == BLACK && !ANTICHESS_ISBLACK (val)) continue;
00366                 for (x2 = 0; x2 < board_wid; x2++)
00367                 for (y2 = 0; y2 < board_heit; y2++)
00368                         if (islegal (pos, x1, y1, x2, y2, player)) return 1;
00369         }
00370         return 0;
00371 }
00372 
00373 ResultType antichess_who_won (Pos *pos, Player player, char **commp)
00374 {
00375         static char comment[32];
00376         char *who_str [3] = { "White won", "Black won", "Draw" };
00377         *commp = NULL;
00378         if (hasmove (pos, player)) //return RESULT_NOTYET;
00379         {
00380                 if (pos->num_moves > antichess_max_moves)
00381                 {
00382                         fprintf (stderr, "max moves reached\n");
00383                         snprintf (comment, 32, "%s", who_str[2]);
00384                         *commp = comment;
00385                         return RESULT_TIE;
00386                 }
00387                 return RESULT_NOTYET;
00388         }
00389         *commp = comment;
00390         if (hasmove (pos, player == WHITE ? BLACK : WHITE))
00391         {
00392                 strncpy (comment, who_str[player == WHITE ? 0 : 1], 31);
00393                 return player == WHITE ? RESULT_WHITE : RESULT_BLACK;
00394         }
00395         else 
00396         {
00397                 strncpy (comment, who_str[2], 31);
00398                 return RESULT_TIE;
00399         }
00400 }
00401 
00402 int antichess_movegen_square (byte *pos, byte **movp, int player,
00403                 int oldx, int oldy, int x, int y)
00404 {
00405         int val;
00406         if (!ISINBOARD(x, y)) return 0;
00407         val = pos [y * board_heit + x];
00408         if ((player == WHITE && ANTICHESS_ISWHITE (val))
00409                 || (player == BLACK && ANTICHESS_ISBLACK (val)))
00410                 return 0;
00411         *(*movp)++ = oldx;
00412         *(*movp)++ = oldy;
00413         *(*movp)++ = 0;
00414         *(*movp)++ = x;
00415         *(*movp)++ = y;
00416         *(*movp)++ = pos [oldy * board_heit + oldx];
00417         *(*movp)++ = -1;
00418         return 1;
00419 }
00420 
00421 int antichess_movegen_line (byte *pos, byte **movp, int player,
00422                 int x, int y, int incx, int incy)
00423 {
00424         int oldx = x, oldy = y;
00425         int capture = 0, val;
00426         do
00427         {
00428                 if (capture) return 1;
00429                 x += incx;
00430                 y += incy;
00431                 val = pos [y * board_heit + x];
00432                 if (ISINBOARD (x, y) && oppcolor (pos, oldx, oldy, x, y))
00433                         capture = 1;
00434         } while (antichess_movegen_square (pos, movp, player, oldx, oldy, x, y));
00435         return 0;
00436 }
00437 
00438 static void antichess_movegen_promote (byte *board, byte **movp, int player,
00439                 int oldx, int oldy, int x, int y)
00440 {
00441         int i, j;
00442         int promote_pieces[2][4] = {
00443                 {ANTICHESS_WQ, ANTICHESS_WR, ANTICHESS_WB, ANTICHESS_WN},
00444                 {ANTICHESS_BQ, ANTICHESS_BR, ANTICHESS_BB, ANTICHESS_BN}
00445         };
00446         i = (player == WHITE ? 0 : 1);
00447         for(j=0; j<4; j++) 
00448         {
00449                 *(*movp)++ = oldx;
00450                 *(*movp)++ = oldy;
00451                 *(*movp)++ = 0;
00452                 *(*movp)++ = x;
00453                 *(*movp)++ = y;
00454                 *(*movp)++ = promote_pieces[i][j];
00455                 *(*movp)++ = -1;
00456         }
00457 }
00458 
00459 byte *antichess_movegen (Pos *pos)
00460 {
00461         byte realbuf[4096];
00462         byte *realp = realbuf;
00463         byte movbuf[4096], *movp = movbuf;
00464         byte *movlist;
00465         int i, j, k, x, y, capture = 0;
00466         int incxr[] = {0, 0, 1, -1};
00467         int incyr[] = {1, -1, 0, 0};
00468         int incxb[] = {1, 1, -1, -1};
00469         int incyb[] = {1, -1, 1, -1};
00470         int incxn[] = {2, 2, -2, -2, 1, 1, -1, -1};
00471         int incyn[] = {1, -1, 1, -1, 2, -2, 2, -2};
00472         byte *board = pos->board;
00473         Player player = pos->player;
00474         for (i=0; i<board_wid; i++)
00475         for (j=0; j<board_heit; j++)
00476         {
00477                 int val = board[j * board_heit + i];
00478                 if ((player == WHITE && ANTICHESS_ISWHITE (val))
00479                         || (player == BLACK && ANTICHESS_ISBLACK (val)))
00480                 {
00481                         switch (val)
00482                         {
00483                                 case ANTICHESS_WP:
00484                                         if (ISINBOARD (i, j+1) && board [(j+1) * board_heit + i] == 0)
00485                                         {
00486                                                 if (j == board_heit - 2)
00487                                                         antichess_movegen_promote(board, &movp, player,
00488                                                                 i, j, i, j+1);
00489                                                 else
00490                                                         antichess_movegen_square (board, &movp, player,
00491                                                                 i, j, i, j+1);
00492                                         }
00493                                         if (ISINBOARD (i+1, j+1) && 
00494                                                         ANTICHESS_ISBLACK (board [(j+1) * board_heit + i+1]))
00495                                         {
00496                                                 if (j == board_heit - 2)
00497                                                         antichess_movegen_promote (board, &movp, player,
00498                                                                 i, j, i+1, j+1);
00499                                                 else
00500                                                         antichess_movegen_square (board, &movp, player,
00501                                                                 i, j, i+1, j+1);
00502                                                 capture ++;
00503                                         }
00504                                         if (ISINBOARD (i-1, j+1) && 
00505                                                         ANTICHESS_ISBLACK (board [(j+1) * board_heit + i-1]))
00506                                         {
00507                                                 if (j == board_heit - 2)
00508                                                         antichess_movegen_promote (board, &movp, player,
00509                                                                 i, j, i-1, j+1);
00510                                                 else
00511                                                         antichess_movegen_square (board, &movp, player,
00512                                                                 i, j, i-1, j+1);
00513                                                 capture ++;
00514                                         }
00515                                         if (j == 1 && board [2 * board_heit + i] == 0
00516                                                         && board [3 * board_heit + i] == 0)
00517                                                 antichess_movegen_square (board, &movp, player,
00518                                                                 i, j, i, j+2);
00519                                         break;
00520                                 case ANTICHESS_BP:
00521                                         if (ISINBOARD (i, j-1) && board [(j-1) * board_heit + i] == 0)
00522                                         {
00523                                                 if (j == 1)
00524                                                         antichess_movegen_promote (board, &movp, player,
00525                                                                 i, j, i, j-1);
00526                                                 else
00527                                                         antichess_movegen_square (board, &movp, player,
00528                                                                 i, j, i, j-1);
00529                                         }
00530                                         if (ISINBOARD (i+1, j-1) && 
00531                                                         ANTICHESS_ISWHITE (board [(j-1) * board_heit + i+1]))
00532                                         {
00533                                                 if (j == 1)
00534                                                         antichess_movegen_promote (board, &movp, player,
00535                                                                 i, j, i+1, j-1);
00536                                                 else
00537                                                         antichess_movegen_square (board, &movp, player,
00538                                                                 i, j, i+1, j-1);
00539                                                 capture ++;
00540                                         }
00541                                         if (ISINBOARD (i-1, j-1) && 
00542                                                         ANTICHESS_ISWHITE (board [(j-1) * board_heit + i-1]))
00543                                         {
00544                                                 if (j == 1)
00545                                                         antichess_movegen_promote (board, &movp, player,
00546                                                                 i, j, i-1, j-1);
00547                                                 else
00548                                                         antichess_movegen_square (board, &movp, player,
00549                                                                 i, j, i-1, j-1);
00550                                                 capture ++;
00551                                         }
00552                                         if (j == 6 && board [5 * board_heit + i] == 0
00553                                                         && board [4 * board_heit + i] == 0)
00554                                                 antichess_movegen_square (board, &movp, player,
00555                                                                 i, j, i, j-2);
00556                                         break;
00557                                 case ANTICHESS_WK:
00558                                 case ANTICHESS_BK:
00559                                         for (k=0; k<4; k++)
00560                                         {
00561                                                 antichess_movegen_square(board, &movp, player, 
00562                                                                 i, j, i + incxr[k], j + incyr[k]);
00563                                                 if (ISINBOARD(i + incxr[k], j + incyr[k]) 
00564                                                                 && oppcolor (board, i, j, i+incxr[k], j+incyr[k]))
00565                                                         capture ++;
00566                                         }
00567                                         for (k=0; k<4; k++)
00568                                         {
00569                                                 antichess_movegen_square(board, &movp, player, 
00570                                                                 i, j, i + incxb[k], j + incyb[k]);
00571                                                 if (ISINBOARD(i + incxb[k], j + incyb[k]) 
00572                                                                 && oppcolor (board, i, j, i+incxb[k], j+incyb[k]))
00573                                                         capture ++;
00574                                         }
00575                                         break;
00576                                 case ANTICHESS_WB:
00577                                 case ANTICHESS_BB:
00578                                         for (k=0; k<4; k++)
00579                                                 capture += antichess_movegen_line (board, &movp, player, 
00580                                                                 i, j, incxb[k], incyb[k]);
00581                                         break;
00582                                 case ANTICHESS_WR:
00583                                 case ANTICHESS_BR:
00584                                         for (k=0; k<4; k++)
00585                                                 capture += antichess_movegen_line (board, &movp, player, 
00586                                                                 i, j, incxr[k], incyr[k]);
00587                                         break;
00588                                 case ANTICHESS_WQ:
00589                                 case ANTICHESS_BQ:
00590                                         for (k=0; k<4; k++)
00591                                                 capture += antichess_movegen_line (board, &movp, player, 
00592                                                                 i, j, incxb[k], incyb[k]);
00593                                         for (k=0; k<4; k++)
00594                                                 capture += antichess_movegen_line (board, &movp, player, 
00595                                                                 i, j, incxr[k], incyr[k]);
00596                                         break;
00597                                 case ANTICHESS_WN:
00598                                 case ANTICHESS_BN:
00599                                         for (k=0; k<8; k++)
00600                                         {
00601                                                 antichess_movegen_square(board, &movp, player, 
00602                                                                 i, j, i + incxn[k], j + incyn[k]);
00603                                                 if (ISINBOARD(i + incxn[k], j + incyn[k]) 
00604                                                                 && oppcolor (board, i, j, i+incxn[k], j+incyn[k]))
00605                                                         capture ++;
00606                                         }
00607                                         break;
00608                         }
00609                 }
00610         }
00611         *movp++ = -2;
00612 
00613         /* if there is a capture eliminate all other moves */
00614         if (!capture)
00615         {
00616                 movlist = (byte *) malloc (movp - movbuf);
00617                 memcpy (movlist, movbuf, movp - movbuf);
00618                 return movlist;
00619         }
00620         movp = movbuf;
00621         realp = realbuf;
00622         while (1)
00623         {
00624                 byte *tmp;
00625                 int w = 0, b = 0;
00626                 if (*movp == -2)
00627                         break;
00628                 /* a capture is a move that involves a W as well as a B piece */
00629                 for (tmp = movp; *tmp != -1; tmp += 3)
00630                 {
00631                         if (ANTICHESS_ISWHITE (board [tmp[1] * board_heit + tmp[0]]))   w = 1;
00632                         if (ANTICHESS_ISBLACK (board [tmp[1] * board_heit + tmp[0]]))   b = 1;
00633                 }
00634                 if (w && b)
00635                 {
00636                         while (*movp != -1)
00637                         {
00638                                 *realp++ = *movp++;
00639                                 *realp++ = *movp++;
00640                                 *realp++ = *movp++;
00641                         }
00642                         *realp++ = *movp++;
00643                 }
00644                 else 
00645                         movp = tmp+1;
00646         }
00647         *realp++ = -2;
00648         movlist = (byte *) malloc (realp - realbuf);
00649         memcpy (movlist, realbuf, realp - realbuf);
00650         return movlist;
00651 }
00652 
00653 ResultType antichess_eval (Pos * pos, Player player, float *eval)
00654         // TODO: detect end of game by stalemate
00655 {
00656         int wsum = 0, bsum = 0, i;
00657         for (i=0; i < board_wid * board_heit; i++)
00658                 if (ANTICHESS_ISWHITE (pos->board[i]))
00659                         wsum++;
00660                 else if (ANTICHESS_ISBLACK (pos->board[i]))
00661                         bsum++;
00662         if (wsum == 0)
00663         {
00664                 *eval = GAME_EVAL_INFTY;
00665                 return RESULT_WHITE;
00666         }
00667         if (bsum == 0)
00668         {
00669                 *eval = -GAME_EVAL_INFTY;
00670                 return RESULT_BLACK;
00671         }
00672         *eval = bsum - wsum;
00673         return RESULT_NOTYET;
00674 }
00675 
00676 ResultType antichess_eval_incr (Pos *pos, Player player, byte *move, float *eval)
00677         // check if there's a capture
00678 {
00679         byte *board = pos->board;
00680         if (player == WHITE)
00681         {
00682                 if (move[2] && board[move[1] * board_wid + move[0]]) *eval = -1;
00683                 else if (move[5] && board[move[4] * board_wid + move[3]]) return -1;
00684                 else *eval = 0;
00685         }
00686         else
00687         {
00688                 if (move[2] && board[move[1] * board_wid + move[0]]) *eval = 1;
00689                 else if (move[5] && board[move[4] * board_wid + move[3]]) *eval = 1;
00690                 else *eval = 0;
00691         }
00692         return RESULT_NOTYET;
00693 }