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
20
/** \file mastermind.c */
26
#include <gdk/gdkkeysyms.h>
30
#include "../pixmaps/misc.xpm"
32
#define MASTERMIND_CELL_SIZE 40
33
#define MASTERMIND_NUM_PIECES 28
35
#define MASTERMIND_BOARD_WID 8
36
#define MASTERMIND_BOARD_HEIT 11
38
#define MASTERMIND_EMPTY 0
39
#define MASTERMIND_MAIN_COL_START 2
40
#define MASTERMIND_MAIN_COL_END 5
42
#define MASTERMIND_ARROW 27
43
#define MASTERMIND_RETURN 28
45
#define MASTERMIND_RIGHT_ROW_START 2
46
#define MASTERMIND_RIGHT_ROW_END 7
47
#define MASTERMIND_GET_SELECTION(x,y) (((x)==7&&(y)>=MASTERMIND_RIGHT_ROW_START&&(y)<(MASTERMIND_RIGHT_ROW_START+6))?(y):-1)
48
#define MASTERMIND_IS_MAIN_COL(x) ((x)>1&&(x)<6)
50
char mastermind_colors[9] = {200, 200, 200, 200, 200, 200, 0, 0, 0};
51
char mastermind_highlight_colors[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
53
static char * arrow_blue_return_40_xpm[]=
79
" ....................... ",
80
" ........................ ",
81
" ........................ ",
82
" ....................... ",
100
static char * arrow_blue_left_40_xpm[]=
123
" ............................ ",
124
" ............................. ",
125
" ............................. ",
126
" ............................ ",
148
int mastermind_init_pos [MASTERMIND_BOARD_WID*MASTERMIND_BOARD_HEIT] =
150
0, 0, 9, 9, 9, 9, 0, 0,
151
0, 0, 0, 0, 0, 0, 0, 0,
152
0, 0, 0, 0, 0, 0, 0, 0,
153
0, 0, 0, 0, 0, 0, 0, 6,
154
0, 0, 0, 0, 0, 0, 0, 5,
155
0, 0, 0, 0, 0, 0, 0, 4,
156
0, 0, 0, 0, 0, 0, 0, 3,
157
0, 0, 0, 0, 0, 0, 0, 2,
158
0, 0, 0, 0, 0, 0, 0, 1,
159
0, 0, 0, 0, 0, 0, 0, 0,
160
0, 0, 0, 0, 0, 0,27, 0,
164
SCORE_FIELD mastermind_score_fields[] = {SCORE_FIELD_USER, SCORE_FIELD_SCORE, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE};
165
char *mastermind_score_field_names[] = {"User", "Tries", "Time", "Date", NULL};
167
void mastermind_init ();
168
char ** mastermind_get_pixmap (int idx, int color);
170
Game Mastermind = { MASTERMIND_CELL_SIZE,
171
MASTERMIND_BOARD_WID, MASTERMIND_BOARD_HEIT,
172
MASTERMIND_NUM_PIECES, mastermind_colors,
173
NULL, NULL, "Mastermind", NULL, mastermind_init};
176
static ResultType mastermind_who_won (Pos *, Player, char **);
177
static void mastermind_set_init_pos (Pos *pos);
178
int mastermind_getmove (Pos *, int, int, GtkboardEventType, Player, byte**, int **);
179
int mastermind_getmove_kb (Pos *, int, byte **, int **);
180
void mastermind_reset_uistate ();
181
int mastermind_get_cur_row (byte *);
182
void mastermind_set_init_render (Pos *);
183
void mastermind_free ();
187
void mastermind_init ()
189
game_getmove = mastermind_getmove;
190
game_getmove_kb = mastermind_getmove_kb;
191
game_who_won = mastermind_who_won;
192
game_set_init_pos = mastermind_set_init_pos;
193
game_get_pixmap = mastermind_get_pixmap;
194
game_single_player = TRUE;
195
game_reset_uistate = mastermind_reset_uistate;
196
game_draw_cell_boundaries = TRUE;
197
game_scorecmp = game_scorecmp_def_iscore;
198
game_score_fields = mastermind_score_fields;
199
game_score_field_names = mastermind_score_field_names;
200
game_highlight_colors = mastermind_highlight_colors;
201
game_set_init_render = mastermind_set_init_render;
202
game_free = mastermind_free;
203
game_doc_about_status = STATUS_COMPLETE;
206
"Single player game\n"
207
"Status: Completely implemented\n"
208
"URL: "GAME_DEFAULT_URL ("mastermind");
210
"The objective is to find the colors of 4 hidden squares in as few tries as possible.\n\n"
211
"Select a color by clicking on one of the balls on the extreme right. Place any 4 colors of your choice on the middle 4 squares of the bottom row and hit enter. You will get two numbers on the left. The number of black balls indicates how many balls you've got in the correct position. The number of white balls indicates how many balls you've got n the wrong position. Now try again on the second row. Repeat until you get all four black balls.";
213
// TODO: complete this
216
void mastermind_set_init_render (Pos *pos)
218
pos->render [MASTERMIND_RIGHT_ROW_START * board_wid + board_wid - 1] = RENDER_HIGHLIGHT1;
221
ResultType mastermind_who_won (Pos *pos, Player to_play, char **commp)
223
static char comment[32];
225
gboolean over = FALSE;
227
/* pos->board [(board_heit - 1) * board_wid+ MASTERMIND_MAIN_COL_START]
230
for (j=0; j<board_heit-1; j++)
231
if (pos->board[j * board_wid] == 20) // FIXME: don't hard code
233
scorestr = over ? "You won! Tries:" : "Tries:";
234
if (!over && mastermind_get_cur_row (pos->board) == board_heit - 1)
236
snprintf (comment, 32, "You lost. Tries: %d", board_heit - 1);
240
for (j=0; j<board_heit-1; j++)
241
if (!pos->board[j * board_wid])
243
snprintf (comment, 32, "%s %d", scorestr, j);
245
return over ? RESULT_WON : RESULT_NOTYET;
249
int mastermind_get_cur_row (byte *board)
252
for (j=board_heit-2; j>=0; j--)
254
if (board [j * board_wid + 0] || board [j * board_wid + 1])
260
void mastermind_set_init_pos (Pos *pos)
263
for (i=0; i<board_wid; i++)
264
for (j=0; j<board_heit; j++)
265
pos->board [j * board_wid + i] =
266
mastermind_init_pos [(board_heit - 1 - j) * board_wid + i];
267
for (i=MASTERMIND_MAIN_COL_START; i<=MASTERMIND_MAIN_COL_END; i++)
268
pos->board [(board_heit - 1) * board_wid + i] = 9 + random() % 6;
271
char ** mastermind_get_pixmap (int idx, int color)
273
int fg = 0, bg = 0, i;
275
static char pixbuf[MASTERMIND_CELL_SIZE*(MASTERMIND_CELL_SIZE)+1];
276
static char dice_pixbuf[MASTERMIND_CELL_SIZE*(MASTERMIND_CELL_SIZE)+1];
277
static gboolean first = TRUE;
278
colors = mastermind_colors;
279
if (idx == MASTERMIND_ARROW)
280
return arrow_blue_left_40_xpm;
281
else if (idx == MASTERMIND_RETURN)
282
return arrow_blue_return_40_xpm;
286
fg += (idx & 2 ? 256 : 0);
287
fg += (idx & 4 ? 65536 : 0);
289
if (idx >= 9 && idx <= 14) fg = 100 * 0x10101;
290
if (color == BLACK) colors += 3;
291
for(i=0, bg=0;i<3;i++)
292
{ int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));}
296
return pixmap_ball_gen
297
(MASTERMIND_CELL_SIZE, pixbuf, fg, bg, 10.0, 30.0);
299
return pixmap_header_gen
300
(MASTERMIND_CELL_SIZE, pixbuf, fg, bg);
304
int num = (idx <= 20 ? idx - 16 : idx - 20);
305
for(i=0, bg=0;i<3;i++)
306
{ int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));}
307
fg = (idx <= 20 ? 0 : 0xffffff);
308
return pixmap_die_gen(MASTERMIND_CELL_SIZE, dice_pixbuf, fg, bg, 3.0, 30.0, num);
310
else return red_X_40_xpm;
314
static int active = MASTERMIND_RIGHT_ROW_START;
316
void mastermind_free ()
318
active = MASTERMIND_RIGHT_ROW_START;
321
void mastermind_reset_uistate ()
325
int mastermind_getmove
326
(Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep)
334
if (type != GTKBOARD_BUTTON_RELEASE)
336
tmp = MASTERMIND_GET_SELECTION(x,y);
341
for (j=0; j<board_heit; j++)
342
if (pos->render [j * board_wid + (board_wid - 1)] == RENDER_HIGHLIGHT1)
345
*rp++ = board_wid - 1;
350
*rp++ = board_wid - 1;
352
*rp++ = RENDER_HIGHLIGHT1;
357
if (active < 1) return -1;
358
if (!MASTERMIND_IS_MAIN_COL(x)) return -1;
359
if (y == board_heit -1) return -1;
360
if (y != mastermind_get_cur_row (pos->board)) return -1;
363
*mp++ = active - MASTERMIND_RIGHT_ROW_START + 1;
366
for (found = 0, i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++)
368
if (pos->board [y * board_wid + i] == MASTERMIND_EMPTY && i != x)
376
*mp++ = MASTERMIND_MAIN_COL_END + 1;
378
*mp++ = MASTERMIND_RETURN;
385
int mastermind_getmove_kb (Pos *pos, int key, byte **movp, int **rmovp)
387
static byte move[32];
391
int i, j, nblack = 0, nwhite = 0, seen[4] = { 0 };
392
byte *board = pos->board;
396
*rp++ = board_wid - 1;
399
if (++active > MASTERMIND_RIGHT_ROW_END)
400
active = MASTERMIND_RIGHT_ROW_START;
401
*rp++ = board_wid - 1;
403
*rp++ = RENDER_HIGHLIGHT1;
410
*rp++ = board_wid - 1;
413
if (--active < MASTERMIND_RIGHT_ROW_START)
414
active = MASTERMIND_RIGHT_ROW_END;
415
*rp++ = board_wid - 1;
417
*rp++ = RENDER_HIGHLIGHT1;
422
if (key != GDK_Return) return 0;
423
if (active < 0) return 0;
424
cur_row = mastermind_get_cur_row (board);
425
if (cur_row == board_heit - 1) return -1;
426
for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++)
428
if (board [cur_row * board_wid + i] == MASTERMIND_EMPTY)
431
*mp++ = MASTERMIND_MAIN_COL_END + 1;
433
*mp++ = MASTERMIND_EMPTY;
434
if (cur_row < board_heit - 2)
436
*mp++ = MASTERMIND_MAIN_COL_END + 1;
438
*mp++ = MASTERMIND_ARROW;
441
for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++)
442
if (board [cur_row * board_wid + i] ==
443
(board [(board_heit - 1) * board_wid + i] & 7))
445
for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++)
447
for (j=MASTERMIND_MAIN_COL_START;j<=MASTERMIND_MAIN_COL_END;j++)
448
if (board [cur_row * board_wid + i] ==
449
(board [(board_heit - 1) * board_wid + j] & 7)
450
&& !seen[j - MASTERMIND_MAIN_COL_START])
453
seen[j - MASTERMIND_MAIN_COL_START] = 1;
457
assert (nwhite >= nblack);
459
*mp++ = 0; *mp++ = cur_row; *mp++ = (nblack ? nblack + 16 : 25);
460
*mp++ = 1; *mp++ = cur_row; *mp++ = (nwhite ? nwhite + 20 : 25);
461
if (nblack == 4 || cur_row == board_heit - 2)
462
for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++)
464
*mp++ = i; *mp++ = board_heit - 1;
465
*mp++ = board [(board_heit - 1) * board_wid + i] & 7;
468
if (movp) *movp = move;