This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

checkers.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 #include <math.h>
00023 
00024 #include "game.h"
00025 #include "aaball.h"
00026 
00027 #define CHECKERS_CELL_SIZE 40
00028 #define CHECKERS_NUM_PIECES 4
00029 
00030 #define CHECKERS_BOARD_WID 8
00031 #define CHECKERS_BOARD_HEIT 8
00032 
00033 #define CHECKERS_WK 1
00034 #define CHECKERS_WP 2
00035 #define CHECKERS_BK 3
00036 #define CHECKERS_BP 4
00037 
00038 #define CHECKERS_ISKING(x) (x == 1 || x == 3)
00039 #define CHECKERS_ISPAWN(x) (x == 2 || x == 4)
00040 
00041 #define CHECKERS_ISWHITE(x) (x >= 1 && x <= 2)
00042 #define CHECKERS_ISBLACK(x) (x >= 3 && x <= 4)
00043 
00044 char checkers_colors[] = 
00045         {200, 200, 200, 
00046         180, 180, 180};
00047         
00048 int     checkers_init_pos[] = 
00049 {
00050          0 , 4 , 0 , 4 , 0 , 4 , 0 , 4 ,
00051          4 , 0 , 4 , 0 , 4 , 0 , 4 , 0 ,
00052          0 , 4 , 0 , 4 , 0 , 4 , 0 , 4 ,
00053          0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
00054          0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
00055          2 , 0 , 2 , 0 , 2 , 0 , 2 , 0 ,
00056          0 , 2 , 0 , 2 , 0 , 2 , 0 , 2 ,
00057          2 , 0 , 2 , 0 , 2 , 0 , 2 , 0 ,
00058 };
00059 
00060 static int checkers_max_moves = 200;
00061 
00062 
00063 void checkers_init ();
00064 int checkers_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
00065 ResultType checkers_who_won (Pos *, Player, char **);
00066 byte *checkers_movegen (Pos *);
00067 ResultType checkers_eval (Pos *, Player, float *);
00068 char ** checkers_get_pixmap (int idx, int color);
00069 void checkers_reset_uistate ();
00070         
00071 Game Checkers = 
00072         { CHECKERS_CELL_SIZE, CHECKERS_BOARD_WID, CHECKERS_BOARD_HEIT, 
00073         CHECKERS_NUM_PIECES,
00074         checkers_colors, checkers_init_pos, NULL, "Checkers",
00075         checkers_init};
00076 
00077 void checkers_init ()
00078 {
00079         game_getmove = checkers_getmove;
00080         game_movegen = checkers_movegen;
00081         game_who_won = checkers_who_won;
00082         game_eval = checkers_eval;
00083         game_get_pixmap = checkers_get_pixmap;
00084         game_reset_uistate = checkers_reset_uistate;
00085         game_file_label = FILERANK_LABEL_TYPE_ALPHA;
00086         game_rank_label = FILERANK_LABEL_TYPE_NUM | FILERANK_LABEL_DESC;
00087         game_allow_flip = TRUE;
00088         game_doc_about = 
00089                 "Checkers\n"
00090                 "Two player game\n"
00091                 "Status: Partially implemented (currently unplayable)\n"
00092                 "URL: "GAME_DEFAULT_URL("checkers");
00093 }
00094 
00095 ResultType checkers_who_won (Pos *pos, Player player, char **commp)
00096 {
00097         static char comment[32];
00098         char *who_str [2] = { "white won", "black won"};
00099         int found_w = 0, found_b = 0;
00100         int i;
00101         for (i=0; i<board_wid * board_heit; i++)
00102                 if (CHECKERS_ISWHITE (pos->board[i])) found_w = 1;
00103                 else if (CHECKERS_ISBLACK (pos->board[i])) found_b = 1;
00104         if (!found_b)
00105         {
00106                 strncpy (comment, who_str[0], 31);
00107                 *commp = comment;
00108                 return RESULT_WHITE;
00109         }
00110         if (!found_w)
00111         {
00112                 strncpy (comment, who_str[1], 31);
00113                 *commp = comment;
00114                 return RESULT_BLACK;
00115         }
00116         return RESULT_NOTYET;
00117 }
00118 
00119 byte * checkers_movegen (Pos *pos)
00120 {
00121         int i, j, diffx, diffy;
00122         byte movbuf [256];
00123         byte *movlist, *mp = movbuf;
00124         byte *board = pos->board;
00125         Player player = pos->player;
00126         for (i=0; i<board_wid; i++)
00127         for (j=0; j<board_heit; j++)
00128         {
00129                 if (player == BLACK && !CHECKERS_ISBLACK(board [j * board_wid + i]))
00130                         continue;
00131                 if (player == WHITE && !CHECKERS_ISWHITE(board [j * board_wid + i]))
00132                         continue;
00133                 for (diffx = -1; diffx <= 1; diffx += 2)
00134                 for (diffy = -1; diffy <= 1; diffy += 2)
00135                 {
00136                         if (CHECKERS_ISPAWN (board [j * board_wid + i])
00137                                         &&      diffy != (player == WHITE ? 1 : -1))
00138                                 continue;
00139                         if (!ISINBOARD(i+diffx, j+diffy)) continue;
00140                         if (board [(j + diffy) * board_wid + (i + diffx)] != 0)
00141                                 continue;
00142                         *mp++ = i; *mp++ = j; *mp++ = 0;
00143                         *mp++ = i + diffx; *mp++ = j + diffy; 
00144                         if ((player == WHITE && (j + diffy) == board_heit - 1) 
00145                                         || (player == BLACK && (j + diffy) == 0))
00146                                 *mp++ = (player == WHITE ? CHECKERS_WK : CHECKERS_BK);
00147                         else
00148                                 *mp++ = board [j * board_wid + i];
00149                         *mp++ = -1;
00150                 }
00151                 for (diffx = -2; diffx <= 2; diffx += 4)
00152                 for (diffy = -2; diffy <= 2; diffy += 4)
00153                 {
00154                         int val;
00155                         if (CHECKERS_ISPAWN (board [j * board_wid + i])
00156                                         &&      diffy != (player == WHITE ? 2 : -2))
00157                                 continue;
00158                         if (!ISINBOARD(i+diffx, j+diffy)) continue;
00159                         if (board [(j + diffy) * board_wid + (i + diffx)] != 0)
00160                                 continue;
00161                         val = board [(j + diffy/2) * board_wid + i + diffx/2];
00162                         if ((player == WHITE && !CHECKERS_ISBLACK(val)) || 
00163                                         (player == BLACK && !CHECKERS_ISWHITE (val)))
00164                                 continue;
00165                         *mp++ = i; *mp++ = j; *mp++ = 0;
00166                         *mp++ = i + diffx; *mp++ = j + diffy; 
00167                         if ((player == WHITE && (j + diffy) == board_heit - 1) 
00168                                         || (player == BLACK && (j + diffy) == 0))
00169                                 *mp++ = (player == WHITE ? CHECKERS_WK : CHECKERS_BK);
00170                         else
00171                                 *mp++ = board [j * board_wid + i];
00172                         *mp++ = i + diffx/2; *mp++ = j + diffy/2; *mp++ = 0;
00173                         *mp++ = -1;
00174                 }
00175                 
00176                         
00177         }
00178         if (mp == movbuf)
00179                 *mp++ = -1;
00180         *mp++ = -2;
00181         movlist = (byte *) (malloc (mp - movbuf));
00182         memcpy (movlist, movbuf, (mp - movbuf));
00183         return movlist;
00184 }
00185 
00186 ResultType checkers_eval (Pos *pos, Player to_play, float *eval)
00187 {
00188         float sum = 0;
00189         int i, j;
00190         for (i=0; i<board_wid; i++)
00191         for (j=0; j<board_heit; j++)
00192         {
00193                 switch (pos->board [j * board_wid + i])
00194                 {
00195                         case CHECKERS_WK: sum += (5 - fabs ((i-3.5) * (j-3.5)) / 10); break;
00196                         case CHECKERS_WP: sum += (1 + j / 10.0); break;
00197                         case CHECKERS_BK: sum -= (5 - fabs ((i-3.5) * (j-3.5)) / 10); break;
00198                         case CHECKERS_BP: sum -= (1 + (board_heit - 1 - j) / 10.0); break;
00199                 }
00200         }
00201         *eval = sum;
00202         return RESULT_NOTYET;
00203 
00204 }
00205 
00206 static int oldx = -1, oldy = -1;
00207 
00208 void checkers_reset_uistate ()
00209 {
00210         oldx = -1, oldy = -1;
00211 }
00212 
00213 int checkers_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, 
00214                 byte **movp, int ** rmovep)
00215 {
00216         static byte move[10];
00217         byte *mp = move;
00218         int diffx, diffy;
00219         byte *board = pos->board;
00220         if (type != GTKBOARD_BUTTON_RELEASE) return 0;
00221         if (oldx < 0)
00222         {
00223                 int val = board [y * board_wid + x];
00224                 if ((CHECKERS_ISWHITE(val) && !(to_play == WHITE)) ||
00225                 (CHECKERS_ISBLACK(val) && !(to_play == BLACK)))
00226                         return -1;
00227                 oldx = x; oldy = y;
00228                 return 0;
00229         }
00230 
00231         if (x == oldx && y == oldy)
00232         {
00233                 oldx = -1; oldy = -1; return 0;
00234         }
00235         
00236         diffx = x - oldx;
00237         if (abs (diffx) == 1) 
00238         {
00239                 diffy = y - oldy;
00240                 if (abs (diffy) != 1)
00241                 { oldx = oldy = -1; return -1;}
00242                 if (!CHECKERS_ISKING(board [oldy * board_wid + oldx])
00243                                 && diffy != (to_play == WHITE ? 1 : -1))
00244                 { oldx = oldy = -1; return -1;}
00245                 if (board [y * board_wid + x] != 0)
00246                 { oldx = oldy = -1; return -1;}
00247                 *mp++ = oldx; *mp++ = oldy; *mp++ = 0;
00248                 *mp++ = x; *mp++ = y; 
00249                 if ((to_play == WHITE && y == board_heit - 1) 
00250                                 || (to_play == BLACK && y == 0))
00251                         *mp++ = (to_play == WHITE ? CHECKERS_WK : CHECKERS_BK);
00252                 else
00253                         *mp++ = board [oldy * board_wid + oldx];
00254                 *mp++ = -1;
00255                 *movp = move;
00256                 oldx = oldy = -1;
00257                 return 1;
00258         }
00259         if (abs (diffx) == 2)
00260         {
00261                 int val;
00262                 diffy = y - oldy;
00263                 if (abs (diffy) != 2)
00264                 { oldx = oldy = -1; return -1;}
00265                 if (!CHECKERS_ISKING(board [oldy * board_wid + oldx])
00266                                 && diffy != (to_play == WHITE ? 2 : -2))
00267                 { oldx = oldy = -1; return -1;}
00268                 if (board [y * board_wid + x] != 0)
00269                 { oldx = oldy = -1; return -1;}
00270                 val = board [(y-diffy/2) * board_wid + (x-diffx/2)];
00271                 if ((!CHECKERS_ISWHITE(val) && (to_play == BLACK)) ||
00272                 (!CHECKERS_ISBLACK(val) && (to_play == WHITE)))
00273                 { oldx = oldy = -1; return -1;}
00274                 *mp++ = oldx; *mp++ = oldy; *mp++ = 0;
00275                 *mp++ = oldx+diffx/2; *mp++ = oldy+diffy/2; *mp++ = 0;
00276                 *mp++ = x; *mp++ = y; 
00277                 if ((to_play == WHITE && y == board_heit - 1)
00278                                 || (to_play == BLACK && y == 0))
00279                         *mp++ = (to_play == WHITE ? CHECKERS_WK : CHECKERS_BK);
00280                 else
00281                         *mp++ = board [oldy * board_wid + oldx];
00282                 *mp++ = -1;
00283                 *movp = move;
00284                 oldx = oldy = -1;
00285                 return 1;
00286         }
00287         { oldx = oldy = -1; return -1;}
00288 }
00289 
00290 char ** checkers_get_pixmap (int idx, int color)
00291 {
00292         int bg;
00293         int i;
00294         static char pixbuf[CHECKERS_CELL_SIZE * (CHECKERS_CELL_SIZE+1)];
00295         for(i=0, bg=0;i<3;i++) 
00296         { int col = checkers_colors[i+3]; 
00297                 if (col<0) col += 256; bg += col * (1 << (16-8*i));}
00298         return pixmap_ball_gen (CHECKERS_CELL_SIZE, pixbuf,
00299                         CHECKERS_ISWHITE(idx) ? 0xffffff : 0x0000ff, bg, 
00300                         (idx == CHECKERS_WP || idx == CHECKERS_BP) ? 8 : 12, 24);
00301 }