· 8 years ago · Nov 09, 2016, 04:44 AM
1/* This file is a part of gtkboard, a board games system.
2 Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
17
18*/
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <math.h>
23
24#include "game.h"
25#include "aaball.h"
26
27#define CHECKERS_CELL_SIZE 40
28#define CHECKERS_NUM_PIECES 4
29
30#define CHECKERS_BOARD_WID 8
31#define CHECKERS_BOARD_HEIT 8
32
33#define CHECKERS_WK 1
34#define CHECKERS_WP 2
35#define CHECKERS_BK 3
36#define CHECKERS_BP 4
37
38#define CHECKERS_ISKING(x) (x == 1 || x == 3)
39#define CHECKERS_ISPAWN(x) (x == 2 || x == 4)
40
41#define CHECKERS_ISWHITE(x) (x >= 1 && x <= 2)
42#define CHECKERS_ISBLACK(x) (x >= 3 && x <= 4)
43
44char checkers_colors[] =
45 {200, 200, 200,
46 180, 180, 180};
47
48int checkers_init_pos[] =
49{
50 0 , 4 , 0 , 4 , 0 , 4 , 0 , 4 ,
51 4 , 0 , 4 , 0 , 4 , 0 , 4 , 0 ,
52 0 , 4 , 0 , 4 , 0 , 4 , 0 , 4 ,
53 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
54 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
55 2 , 0 , 2 , 0 , 2 , 0 , 2 , 0 ,
56 0 , 2 , 0 , 2 , 0 , 2 , 0 , 2 ,
57 2 , 0 , 2 , 0 , 2 , 0 , 2 , 0 ,
58};
59
60static int checkers_max_moves = 200;
61
62
63void checkers_init ();
64int checkers_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
65ResultType checkers_who_won (Pos *, Player, char **);
66byte *checkers_movegen (Pos *);
67ResultType checkers_eval (Pos *, Player, float *);
68char ** checkers_get_pixmap (int idx, int color);
69void checkers_reset_uistate ();
70
71Game Checkers =
72 { CHECKERS_CELL_SIZE, CHECKERS_BOARD_WID, CHECKERS_BOARD_HEIT,
73 CHECKERS_NUM_PIECES,
74 checkers_colors, checkers_init_pos, NULL, "Checkers",
75 checkers_init};
76
77void checkers_init ()
78{
79 game_getmove = checkers_getmove;
80 game_movegen = checkers_movegen;
81 game_who_won = checkers_who_won;
82 game_eval = checkers_eval;
83 game_get_pixmap = checkers_get_pixmap;
84 game_reset_uistate = checkers_reset_uistate;
85 game_file_label = FILERANK_LABEL_TYPE_ALPHA;
86 game_rank_label = FILERANK_LABEL_TYPE_NUM | FILERANK_LABEL_DESC;
87 game_allow_flip = TRUE;
88 game_doc_about =
89 "Checkers\n"
90 "Two player game\n"
91 "Status: Partially implemented (currently unplayable)\n"
92 "URL: "GAME_DEFAULT_URL("checkers");
93}
94
95ResultType checkers_who_won (Pos *pos, Player player, char **commp)
96{
97 static char comment[32];
98 char *who_str [2] = { "white won", "black won"};
99 int found_w = 0, found_b = 0;
100 int i;
101 for (i=0; i<board_wid * board_heit; i++)
102 if (CHECKERS_ISWHITE (pos->board[i])) found_w = 1;
103 else if (CHECKERS_ISBLACK (pos->board[i])) found_b = 1;
104 if (!found_b)
105 {
106 strncpy (comment, who_str[0], 31);
107 *commp = comment;
108 return RESULT_WHITE;
109 }
110 if (!found_w)
111 {
112 strncpy (comment, who_str[1], 31);
113 *commp = comment;
114 return RESULT_BLACK;
115 }
116 return RESULT_NOTYET;
117}
118
119byte * checkers_movegen (Pos *pos)
120{
121 int i, j, diffx, diffy;
122 byte movbuf [256];
123 byte *movlist, *mp = movbuf;
124 byte *board = pos->board;
125 Player player = pos->player;
126 for (i=0; i<board_wid; i++)
127 for (j=0; j<board_heit; j++)
128 {
129 if (player == BLACK && !CHECKERS_ISBLACK(board [j * board_wid + i]))
130 continue;
131 if (player == WHITE && !CHECKERS_ISWHITE(board [j * board_wid + i]))
132 continue;
133 for (diffx = -1; diffx <= 1; diffx += 2)
134 for (diffy = -1; diffy <= 1; diffy += 2)
135 {
136 if (CHECKERS_ISPAWN (board [j * board_wid + i])
137 && diffy != (player == WHITE ? 1 : -1))
138 continue;
139 if (!ISINBOARD(i+diffx, j+diffy)) continue;
140 if (board [(j + diffy) * board_wid + (i + diffx)] != 0)
141 continue;
142 *mp++ = i; *mp++ = j; *mp++ = 0;
143 *mp++ = i + diffx; *mp++ = j + diffy;
144 if ((player == WHITE && (j + diffy) == board_heit - 1)
145 || (player == BLACK && (j + diffy) == 0))
146 *mp++ = (player == WHITE ? CHECKERS_WK : CHECKERS_BK);
147 else
148 *mp++ = board [j * board_wid + i];
149 *mp++ = -1;
150 }
151 for (diffx = -2; diffx <= 2; diffx += 4)
152 for (diffy = -2; diffy <= 2; diffy += 4)
153 {
154 int val;
155 if (CHECKERS_ISPAWN (board [j * board_wid + i])
156 && diffy != (player == WHITE ? 2 : -2))
157 continue;
158 if (!ISINBOARD(i+diffx, j+diffy)) continue;
159 if (board [(j + diffy) * board_wid + (i + diffx)] != 0)
160 continue;
161 val = board [(j + diffy/2) * board_wid + i + diffx/2];
162 if ((player == WHITE && !CHECKERS_ISBLACK(val)) ||
163 (player == BLACK && !CHECKERS_ISWHITE (val)))
164 continue;
165 *mp++ = i; *mp++ = j; *mp++ = 0;
166 *mp++ = i + diffx; *mp++ = j + diffy;
167 if ((player == WHITE && (j + diffy) == board_heit - 1)
168 || (player == BLACK && (j + diffy) == 0))
169 *mp++ = (player == WHITE ? CHECKERS_WK : CHECKERS_BK);
170 else
171 *mp++ = board [j * board_wid + i];
172 *mp++ = i + diffx/2; *mp++ = j + diffy/2; *mp++ = 0;
173 *mp++ = -1;
174 }
175
176
177 }
178 if (mp == movbuf)
179 *mp++ = -1;
180 *mp++ = -2;
181 movlist = (byte *) (malloc (mp - movbuf));
182 memcpy (movlist, movbuf, (mp - movbuf));
183 return movlist;
184}
185
186ResultType checkers_eval (Pos *pos, Player to_play, float *eval)
187{
188 float sum = 0;
189 int i, j;
190 for (i=0; i<board_wid; i++)
191 for (j=0; j<board_heit; j++)
192 {
193 switch (pos->board [j * board_wid + i])
194 {
195 case CHECKERS_WK: sum += (5 - fabs ((i-3.5) * (j-3.5)) / 10); break;
196 case CHECKERS_WP: sum += (1 + j / 10.0); break;
197 case CHECKERS_BK: sum -= (5 - fabs ((i-3.5) * (j-3.5)) / 10); break;
198 case CHECKERS_BP: sum -= (1 + (board_heit - 1 - j) / 10.0); break;
199 }
200 }
201 *eval = sum;
202 return RESULT_NOTYET;
203
204}
205
206static int oldx = -1, oldy = -1;
207
208void checkers_reset_uistate ()
209{
210 oldx = -1, oldy = -1;
211}
212
213int checkers_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play,
214 byte **movp, int ** rmovep)
215 {
216 static byte move[10];
217 byte *mp = move;
218 int diffx, diffy;
219 byte *board = pos->board;
220 if (type != GTKBOARD_BUTTON_RELEASE) return 0;
221 if (oldx < 0)
222 {
223 int val = board [y * board_wid + x];
224 if ((CHECKERS_ISWHITE(val) && !(to_play == WHITE)) ||
225 (CHECKERS_ISBLACK(val) && !(to_play == BLACK)))
226 return -1;
227 oldx = x; oldy = y;
228 return 0;
229 }
230
231 if (x == oldx && y == oldy)
232 {
233 oldx = -1; oldy = -1; return 0;
234 }
235
236 diffx = x - oldx;
237 if (abs (diffx) == 1)
238 {
239 diffy = y - oldy;
240 if (abs (diffy) != 1)
241 { oldx = oldy = -1; return -1;}
242 if (!CHECKERS_ISKING(board [oldy * board_wid + oldx])
243 && diffy != (to_play == WHITE ? 1 : -1))
244 { oldx = oldy = -1; return -1;}
245 if (board [y * board_wid + x] != 0)
246 { oldx = oldy = -1; return -1;}
247 *mp++ = oldx; *mp++ = oldy; *mp++ = 0;
248 *mp++ = x; *mp++ = y;
249 if ((to_play == WHITE && y == board_heit - 1)
250 || (to_play == BLACK && y == 0))
251 *mp++ = (to_play == WHITE ? CHECKERS_WK : CHECKERS_BK);
252 else
253 *mp++ = board [oldy * board_wid + oldx];
254 *mp++ = -1;
255 *movp = move;
256 oldx = oldy = -1;
257 return 1;
258 }
259 if (abs (diffx) == 2)
260 {
261 int val;
262 diffy = y - oldy;
263 if (abs (diffy) != 2)
264 { oldx = oldy = -1; return -1;}
265 if (!CHECKERS_ISKING(board [oldy * board_wid + oldx])
266 && diffy != (to_play == WHITE ? 2 : -2))
267 { oldx = oldy = -1; return -1;}
268 if (board [y * board_wid + x] != 0)
269 { oldx = oldy = -1; return -1;}
270 val = board [(y-diffy/2) * board_wid + (x-diffx/2)];
271 if ((!CHECKERS_ISWHITE(val) && (to_play == BLACK)) ||
272 (!CHECKERS_ISBLACK(val) && (to_play == WHITE)))
273 { oldx = oldy = -1; return -1;}
274 *mp++ = oldx; *mp++ = oldy; *mp++ = 0;
275 *mp++ = oldx+diffx/2; *mp++ = oldy+diffy/2; *mp++ = 0;
276 *mp++ = x; *mp++ = y;
277 if ((to_play == WHITE && y == board_heit - 1)
278 || (to_play == BLACK && y == 0))
279 *mp++ = (to_play == WHITE ? CHECKERS_WK : CHECKERS_BK);
280 else
281 *mp++ = board [oldy * board_wid + oldx];
282 *mp++ = -1;
283 *movp = move;
284 oldx = oldy = -1;
285 return 1;
286 }
287 { oldx = oldy = -1; return -1;}
288}
289
290char ** checkers_get_pixmap (int idx, int color)
291{
292 int bg;
293 int i;
294 static char pixbuf[CHECKERS_CELL_SIZE * (CHECKERS_CELL_SIZE+1)];
295 for(i=0, bg=0;i<3;i++)
296 { int col = checkers_colors[i+3];
297 if (col<0) col += 256; bg += col * (1 << (16-8*i));}
298 return pixmap_ball_gen (CHECKERS_CELL_SIZE, pixbuf,
299 CHECKERS_ISWHITE(idx) ? 0xffffff : 0x0000ff, bg,
300 (idx == CHECKERS_WP || idx == CHECKERS_BP) ? 8 : 12, 24);
301}