1
/* This file is a part of gtkboard, a board games system.
2
Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net>
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.
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.
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
30
#define PLOT4_CELL_SIZE 55
31
#define PLOT4_NUM_PIECES 3
33
#define PLOT4_BOARD_WID 7
34
#define PLOT4_BOARD_HEIT 6
36
char plot4_colors[6] = {160, 140, 100, 160, 140, 100};
38
int * plot4_init_pos = NULL;
47
Game Plot4 = { PLOT4_CELL_SIZE, PLOT4_BOARD_WID, PLOT4_BOARD_HEIT,
49
plot4_colors, NULL, NULL, "Plot 4", "k-in-a-row", plot4_init};
53
static int eval_runs (Pos *, int);
54
static int find_runs (byte *, int, int, int , int, int, int);
55
static int plot4_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
56
static ResultType plot4_who_won (Pos *, Player , char **);
57
static void plot4_set_init_pos (Pos *pos);
58
static char ** plot4_get_pixmap (int, int);
59
static byte * plot4_movegen (Pos *);
60
static ResultType plot4_eval (Pos *, Player, float *);
63
static const int RUN_WT = 20;
68
game_eval = plot4_eval;
69
game_movegen = plot4_movegen;
70
game_getmove = plot4_getmove;
71
game_who_won = plot4_who_won;
72
game_set_init_pos = plot4_set_init_pos;
73
game_get_pixmap = plot4_get_pixmap;
74
game_white_string = "Green";
75
game_black_string = "Yellow";
76
game_doc_about_status = STATUS_COMPLETE;
80
"Status: Fully implemented\n"
81
"URL: "GAME_DEFAULT_URL ("plot4");
83
"Two players alternate in placing balls of either color on a 7x6 board. Not exactly placing, because the balls have gravity and fall down to the lowest unoccupied square on the column. The goal is to get as many 4-in-a-row's as possible. A 5-in-a-row counts as two, 6 as 3, and 7 as 4.\n";
86
void plot4_set_init_pos (Pos *pos)
89
for (i=0; i<board_wid * board_heit; i++)
90
pos->board [i] = PLOT4_EMPTY;
93
ResultType plot4_who_won (Pos *pos, Player to_play, char **commp)
95
static char comment[32];
96
char *who_str [3] = { "Green won", "Yellow won", "Its a tie" };
97
int i, wscore, bscore, who_idx;
98
wscore = eval_runs (pos, WHITE) / RUN_WT;
99
bscore = eval_runs (pos, BLACK) / RUN_WT * -1;
101
for (i=0; i<board_wid * board_heit; i++)
102
if (pos->board[i] == PLOT4_EMPTY)
104
snprintf (comment, 32, "%d : %d", wscore, bscore);
105
return RESULT_NOTYET;
107
if (wscore > bscore) who_idx = 0;
108
else if (wscore < bscore) who_idx = 1;
110
snprintf (comment, 32, "%s (%d : %d)", who_str[who_idx], wscore, bscore);
118
int plot4_islegal (byte *board, int x, int y)
120
check if (x,y) is empty
121
check if (x, y-1) is not empty */
123
return (x >= 0 && x < board_wid && y >= 0 && y < board_heit
124
&& (board[y * board_wid + x] == PLOT4_EMPTY) &&
125
((y == 0) || (board [(y-1) * board_wid + x] != PLOT4_EMPTY)));
128
int plot4_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep)
129
/* translate a sequence of mouse clicks into a cbgf move.
130
pos is the current position, x and y are the square which was
131
clicked, type is the event type: MOUSE_PRESSED, MOUSE_RELEASED
132
to_play is who has the move, movp is used to return the move
134
the return value is 1 if the clicks were successfully translated
135
into a move; -1 if the move is illegal, and 0 if further clicks
136
are required to determine the move. In the latter case, this
137
function is responsible for keeping track of the current state.
141
if (type != GTKBOARD_BUTTON_RELEASE)
143
/* OK to click anywhere in the column */
144
for (y = 0; y < board_heit; y++)
145
if (pos->board[y * board_wid + x] == PLOT4_EMPTY)
151
move[2] = to_play == WHITE ? PLOT4_WP : PLOT4_BP;
158
ResultType plot4_eval (Pos *pos, Player to_play, float *eval)
159
/* always eval from POV of white */
161
/* TODO : add some weights */
162
*eval = eval_runs (pos, -1);
163
return RESULT_NOTYET;
168
static int eval_runs (Pos *pos, int forwhom)
169
/* sum of all the runs of forwhom (both if -1) from POV of WHITE */
172
int i, board_min, min;
173
byte *board = pos->board;
174
board_min = board_wid < board_heit ? board_wid : board_heit;
175
for (i=0; i<board_wid; i++)
176
sum += find_runs (board, i, 0, 0, 1, board_heit, forwhom);
177
for (i=0; i<board_heit; i++)
178
sum += find_runs (board, 0, i, 1, 0, board_wid, forwhom);
179
for (i=0; i<board_wid; i++)
181
min = (board_wid - i) < board_min ? (board_wid - i) : board_min;
182
sum += find_runs (board, i, 0, 1, 1, min, forwhom);
183
sum += find_runs (board, board_wid - i - 1, 0, -1, 1, min, forwhom);
185
for (i=1; i<board_heit; i++)
187
min = (board_heit - i) < board_min ? (board_heit - i) : board_min;
188
sum += find_runs (board, 0, i, 1, 1, min, forwhom);
189
sum += find_runs (board, board_wid - 1, i, -1, 1, min, forwhom);
194
static int find_runs (byte *board, int x0, int y0, int dx, int dy, int len,
196
/* OK this function is very ugly. if forwhom is -1 it returns an
197
* eval of the given line. If not it returns a count forwhom's
198
* score on that line, multiplied by RUN_WT */
200
int sum = 0, i, cur = 0; /* cur = current run length */
202
char prev = -1, cell;
203
int lopen = 0, ropen = 0; /* can we extend this run in either direction*/
204
for (i=0; i<len; i++, x += dx, y += dy, prev = cell)
206
cell = board[y * board_wid + x];
207
if (cell == PLOT4_EMPTY)
217
board [(y + dy) * board_wid + (x + dx)] == PLOT4_EMPTY)
220
if (cell == PLOT4_WP)
223
sum += ((ropen + lopen) * (cur * cur));
224
if (forwhom != BLACK && cur >= 4)
227
if (cell == PLOT4_BP)
230
sum -= ((ropen + lopen) * (cur * cur));
231
if (forwhom != WHITE && cur >= 4)
239
byte * plot4_movegen_single (char *pos, int player, int reset)
240
/* return a move terminated by -1 */
241
/* NULL ==> no more moves */
244
static byte movbuf[4];
247
while (row < board_wid)
250
for (j=board_heit-1; j>=0; j--)
251
if (pos[j * board_wid + row] == PLOT4_EMPTY)
255
movbuf[2] = (player == WHITE ? PLOT4_WP : PLOT4_BP);
268
byte *plot4_movegen (Pos *pos)
274
for (i=0; i<board_wid; i++)
276
for (j=0; j<board_heit; j++)
277
if (pos->board[j * board_wid + i] == PLOT4_EMPTY)
281
*movp++ = (pos->player == WHITE ? PLOT4_WP : PLOT4_BP);
287
movlist = (byte *) (malloc (movp - movbuf));
288
memcpy (movlist, movbuf, (movp - movbuf));
292
char ** plot4_get_pixmap (int idx, int color)
295
char *colors = plot4_colors;
296
static char pixbuf[PLOT4_CELL_SIZE*(PLOT4_CELL_SIZE)+1];
297
if (idx == PLOT4_WP) fg = 0xee << 8;
298
else if (idx == PLOT4_BP) fg = (0xee << 16) + (0xee << 8);
300
for(i=0, bg=0;i<3;i++)
301
{ int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));}
302
return pixmap_ball_gen(55, pixbuf, fg, bg, 17.0, 30.0);