· 8 years ago · Dec 02, 2016, 06:16 PM
100001 /* This file is a part of gtkboard, a board games system.
200002 Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net>
300003
400004 This program is free software; you can redistribute it and/or modify
500005 it under the terms of the GNU General Public License as published by
600006 the Free Software Foundation; either version 2 of the License, or
700007 (at your option) any later version.
800008
900009 This program is distributed in the hope that it will be useful,
1000010 but WITHOUT ANY WARRANTY; without even the implied warranty of
1100011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1200012 GNU General Public License for more details.
1300013
1400014 You should have received a copy of the GNU General Public License
1500015 along with this program; if not, write to the Free Software
1600016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
1700017
1800018 */
1900019 #include <stdio.h>
2000020 #include <string.h>
2100021 #include <stdlib.h>
2200022 #include <math.h>
2300023
2400024 #include "game.h"
2500025 #include "aaball.h"
2600026
2700027 #define CHECKERS_CELL_SIZE 40
2800028 #define CHECKERS_NUM_PIECES 4
2900029
3000030 #define CHECKERS_BOARD_WID 8
3100031 #define CHECKERS_BOARD_HEIT 8
3200032
3300033 #define CHECKERS_WK 1
3400034 #define CHECKERS_WP 2
3500035 #define CHECKERS_BK 3
3600036 #define CHECKERS_BP 4
3700037
3800038 #define CHECKERS_ISKING(x) (x == 1 || x == 3)
3900039 #define CHECKERS_ISPAWN(x) (x == 2 || x == 4)
4000040
4100041 #define CHECKERS_ISWHITE(x) (x >= 1 && x <= 2)
4200042 #define CHECKERS_ISBLACK(x) (x >= 3 && x <= 4)
4300043
4400044 char checkers_colors[] =
4500045 {200, 200, 200,
4600046 180, 180, 180};
4700047
4800048 int checkers_init_pos[] =
4900049 {
5000050 0 , 4 , 0 , 4 , 0 , 4 , 0 , 4 ,
5100051 4 , 0 , 4 , 0 , 4 , 0 , 4 , 0 ,
5200052 0 , 4 , 0 , 4 , 0 , 4 , 0 , 4 ,
5300053 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
5400054 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
5500055 2 , 0 , 2 , 0 , 2 , 0 , 2 , 0 ,
5600056 0 , 2 , 0 , 2 , 0 , 2 , 0 , 2 ,
5700057 2 , 0 , 2 , 0 , 2 , 0 , 2 , 0 ,
5800058 };
5900059
6000060 static int checkers_max_moves = 200;
6100061
6200062
6300063 void checkers_init ();
6400064 int checkers_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
6500065 ResultType checkers_who_won (Pos *, Player, char **);
6600066 byte *checkers_movegen (Pos *);
6700067 ResultType checkers_eval (Pos *, Player, float *);
6800068 char ** checkers_get_pixmap (int idx, int color);
6900069 void checkers_reset_uistate ();
7000070
7100071 Game Checkers =
7200072 { CHECKERS_CELL_SIZE, CHECKERS_BOARD_WID, CHECKERS_BOARD_HEIT,
7300073 CHECKERS_NUM_PIECES,
7400074 checkers_colors, checkers_init_pos, NULL, "Checkers",
7500075 checkers_init};
7600076
7700077 void checkers_init ()
7800078 {
7900079 game_getmove = checkers_getmove;
8000080 game_movegen = checkers_movegen;
8100081 game_who_won = checkers_who_won;
8200082 game_eval = checkers_eval;
8300083 game_get_pixmap = checkers_get_pixmap;
8400084 game_reset_uistate = checkers_reset_uistate;
8500085 game_file_label = FILERANK_LABEL_TYPE_ALPHA;
8600086 game_rank_label = FILERANK_LABEL_TYPE_NUM | FILERANK_LABEL_DESC;
8700087 game_allow_flip = TRUE;
8800088 game_doc_about =
8900089 "Checkers\n"
9000090 "Two player game\n"
9100091 "Status: Partially implemented (currently unplayable)\n"
9200092 "URL: "GAME_DEFAULT_URL("checkers");
9300093 }
9400094
9500095 ResultType checkers_who_won (Pos *pos, Player player, char **commp)
9600096 {
9700097 static char comment[32];
9800098 char *who_str [2] = { "white won", "black won"};
9900099 int found_w = 0, found_b = 0;
10000100 int i;
10100101 for (i=0; i<board_wid * board_heit; i++)
10200102 if (CHECKERS_ISWHITE (pos->board[i])) found_w = 1;
10300103 else if (CHECKERS_ISBLACK (pos->board[i])) found_b = 1;
10400104 if (!found_b)
10500105 {
10600106 strncpy (comment, who_str[0], 31);
10700107 *commp = comment;
10800108 return RESULT_WHITE;
10900109 }
11000110 if (!found_w)
11100111 {
11200112 strncpy (comment, who_str[1], 31);
11300113 *commp = comment;
11400114 return RESULT_BLACK;
11500115 }
11600116 return RESULT_NOTYET;
11700117 }
11800118
11900119 byte * checkers_movegen (Pos *pos)
12000120 {
12100121 int i, j, diffx, diffy;
12200122 byte movbuf [256];
12300123 byte *movlist, *mp = movbuf;
12400124 byte *board = pos->board;
12500125 Player player = pos->player;
12600126 for (i=0; i<board_wid; i++)
12700127 for (j=0; j<board_heit; j++)
12800128 {
12900129 if (player == BLACK && !CHECKERS_ISBLACK(board [j * board_wid + i]))
13000130 continue;
13100131 if (player == WHITE && !CHECKERS_ISWHITE(board [j * board_wid + i]))
13200132 continue;
13300133 for (diffx = -1; diffx <= 1; diffx += 2)
13400134 for (diffy = -1; diffy <= 1; diffy += 2)
13500135 {
13600136 if (CHECKERS_ISPAWN (board [j * board_wid + i])
13700137 && diffy != (player == WHITE ? 1 : -1))
13800138 continue;
13900139 if (!ISINBOARD(i+diffx, j+diffy)) continue;
14000140 if (board [(j + diffy) * board_wid + (i + diffx)] != 0)
14100141 continue;
14200142 *mp++ = i; *mp++ = j; *mp++ = 0;
14300143 *mp++ = i + diffx; *mp++ = j + diffy;
14400144 if ((player == WHITE && (j + diffy) == board_heit - 1)
14500145 || (player == BLACK && (j + diffy) == 0))
14600146 *mp++ = (player == WHITE ? CHECKERS_WK : CHECKERS_BK);
14700147 else
14800148 *mp++ = board [j * board_wid + i];
14900149 *mp++ = -1;
15000150 }
15100151 for (diffx = -2; diffx <= 2; diffx += 4)
15200152 for (diffy = -2; diffy <= 2; diffy += 4)
15300153 {
15400154 int val;
15500155 if (CHECKERS_ISPAWN (board [j * board_wid + i])
15600156 && diffy != (player == WHITE ? 2 : -2))
15700157 continue;
15800158 if (!ISINBOARD(i+diffx, j+diffy)) continue;
15900159 if (board [(j + diffy) * board_wid + (i + diffx)] != 0)
16000160 continue;
16100161 val = board [(j + diffy/2) * board_wid + i + diffx/2];
16200162 if ((player == WHITE && !CHECKERS_ISBLACK(val)) ||
16300163 (player == BLACK && !CHECKERS_ISWHITE (val)))
16400164 continue;
16500165 *mp++ = i; *mp++ = j; *mp++ = 0;
16600166 *mp++ = i + diffx; *mp++ = j + diffy;
16700167 if ((player == WHITE && (j + diffy) == board_heit - 1)
16800168 || (player == BLACK && (j + diffy) == 0))
16900169 *mp++ = (player == WHITE ? CHECKERS_WK : CHECKERS_BK);
17000170 else
17100171 *mp++ = board [j * board_wid + i];
17200172 *mp++ = i + diffx/2; *mp++ = j + diffy/2; *mp++ = 0;
17300173 *mp++ = -1;
17400174 }
17500175
17600176
17700177 }
17800178 if (mp == movbuf)
17900179 *mp++ = -1;
18000180 *mp++ = -2;
18100181 movlist = (byte *) (malloc (mp - movbuf));
18200182 memcpy (movlist, movbuf, (mp - movbuf));
18300183 return movlist;
18400184 }
18500185
18600186 ResultType checkers_eval (Pos *pos, Player to_play, float *eval)
18700187 {
18800188 float sum = 0;
18900189 int i, j;
19000190 for (i=0; i<board_wid; i++)
19100191 for (j=0; j<board_heit; j++)
19200192 {
19300193 switch (pos->board [j * board_wid + i])
19400194 {
19500195 case CHECKERS_WK: sum += (5 - fabs ((i-3.5) * (j-3.5)) / 10); break;
19600196 case CHECKERS_WP: sum += (1 + j / 10.0); break;
19700197 case CHECKERS_BK: sum -= (5 - fabs ((i-3.5) * (j-3.5)) / 10); break;
19800198 case CHECKERS_BP: sum -= (1 + (board_heit - 1 - j) / 10.0); break;
19900199 }
20000200 }
20100201 *eval = sum;
20200202 return RESULT_NOTYET;
20300203
20400204 }
20500205
20600206 static int oldx = -1, oldy = -1;
20700207
20800208 void checkers_reset_uistate ()
20900209 {
21000210 oldx = -1, oldy = -1;
21100211 }
21200212
21300213 int checkers_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play,
21400214 byte **movp, int ** rmovep)
21500215 {
21600216 static byte move[10];
21700217 byte *mp = move;
21800218 int diffx, diffy;
21900219 byte *board = pos->board;
22000220 if (type != GTKBOARD_BUTTON_RELEASE) return 0;
22100221 if (oldx < 0)
22200222 {
22300223 int val = board [y * board_wid + x];
22400224 if ((CHECKERS_ISWHITE(val) && !(to_play == WHITE)) ||
22500225 (CHECKERS_ISBLACK(val) && !(to_play == BLACK)))
22600226 return -1;
22700227 oldx = x; oldy = y;
22800228 return 0;
22900229 }
23000230
23100231 if (x == oldx && y == oldy)
23200232 {
23300233 oldx = -1; oldy = -1; return 0;
23400234 }
23500235
23600236 diffx = x - oldx;
23700237 if (abs (diffx) == 1)
23800238 {
23900239 diffy = y - oldy;
24000240 if (abs (diffy) != 1)
24100241 { oldx = oldy = -1; return -1;}
24200242 if (!CHECKERS_ISKING(board [oldy * board_wid + oldx])
24300243 && diffy != (to_play == WHITE ? 1 : -1))
24400244 { oldx = oldy = -1; return -1;}
24500245 if (board [y * board_wid + x] != 0)
24600246 { oldx = oldy = -1; return -1;}
24700247 *mp++ = oldx; *mp++ = oldy; *mp++ = 0;
24800248 *mp++ = x; *mp++ = y;
24900249 if ((to_play == WHITE && y == board_heit - 1)
25000250 || (to_play == BLACK && y == 0))
25100251 *mp++ = (to_play == WHITE ? CHECKERS_WK : CHECKERS_BK);
25200252 else
25300253 *mp++ = board [oldy * board_wid + oldx];
25400254 *mp++ = -1;
25500255 *movp = move;
25600256 oldx = oldy = -1;
25700257 return 1;
25800258 }
25900259 if (abs (diffx) == 2)
26000260 {
26100261 int val;
26200262 diffy = y - oldy;
26300263 if (abs (diffy) != 2)
26400264 { oldx = oldy = -1; return -1;}
26500265 if (!CHECKERS_ISKING(board [oldy * board_wid + oldx])
26600266 && diffy != (to_play == WHITE ? 2 : -2))
26700267 { oldx = oldy = -1; return -1;}
26800268 if (board [y * board_wid + x] != 0)
26900269 { oldx = oldy = -1; return -1;}
27000270 val = board [(y-diffy/2) * board_wid + (x-diffx/2)];
27100271 if ((!CHECKERS_ISWHITE(val) && (to_play == BLACK)) ||
27200272 (!CHECKERS_ISBLACK(val) && (to_play == WHITE)))
27300273 { oldx = oldy = -1; return -1;}
27400274 *mp++ = oldx; *mp++ = oldy; *mp++ = 0;
27500275 *mp++ = oldx+diffx/2; *mp++ = oldy+diffy/2; *mp++ = 0;
27600276 *mp++ = x; *mp++ = y;
27700277 if ((to_play == WHITE && y == board_heit - 1)
27800278 || (to_play == BLACK && y == 0))
27900279 *mp++ = (to_play == WHITE ? CHECKERS_WK : CHECKERS_BK);
28000280 else
28100281 *mp++ = board [oldy * board_wid + oldx];
28200282 *mp++ = -1;
28300283 *movp = move;
28400284 oldx = oldy = -1;
28500285 return 1;
28600286 }
28700287 { oldx = oldy = -1; return -1;}
28800288 }
28900289
29000290 char ** checkers_get_pixmap (int idx, int color)
29100291 {
29200292 int bg;
29300293 int i;
29400294 static char pixbuf[CHECKERS_CELL_SIZE * (CHECKERS_CELL_SIZE+1)];
29500295 for(i=0, bg=0;i<3;i++)
29600296 { int col = checkers_colors[i+3];
29700297 if (col<0) col += 256; bg += col * (1 << (16-8*i));}
29800298 return pixmap_ball_gen (CHECKERS_CELL_SIZE, pixbuf,
29900299 CHECKERS_ISWHITE(idx) ? 0xffffff : 0x0000ff, bg,
30000300 (idx == CHECKERS_WP || idx == CHECKERS_BP) ? 8 : 12, 24);
30100301 }