This is the doxygen documentation for gtkboard.
.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 00022 #include <stdio.h> 00023 #include <string.h> 00024 #include <assert.h> 00025 #include <stdlib.h> 00026 #include <gdk/gdkkeysyms.h> 00027 00028 #include "game.h" 00029 #include "aaball.h" 00030 #include "../pixmaps/misc.xpm" 00031 00032 #define MASTERMIND_CELL_SIZE 40 00033 #define MASTERMIND_NUM_PIECES 28 00034 00035 #define MASTERMIND_BOARD_WID 8 00036 #define MASTERMIND_BOARD_HEIT 11 00037 00038 #define MASTERMIND_EMPTY 0 00039 #define MASTERMIND_MAIN_COL_START 2 00040 #define MASTERMIND_MAIN_COL_END 5 00041 00042 #define MASTERMIND_ARROW 27 00043 #define MASTERMIND_RETURN 28 00044 00045 #define MASTERMIND_RIGHT_ROW_START 2 00046 #define MASTERMIND_RIGHT_ROW_END 7 00047 #define MASTERMIND_GET_SELECTION(x,y) (((x)==7&&(y)>=MASTERMIND_RIGHT_ROW_START&&(y)<(MASTERMIND_RIGHT_ROW_START+6))?(y):-1) 00048 #define MASTERMIND_IS_MAIN_COL(x) ((x)>1&&(x)<6) 00049 00050 char mastermind_colors[9] = {200, 200, 200, 200, 200, 200, 0, 0, 0}; 00051 char mastermind_highlight_colors[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 00052 00053 static char * arrow_blue_return_40_xpm[]= 00054 { 00055 "40 40 2 1", 00056 ". c blue", 00057 " c none", 00058 " ", 00059 " ", 00060 " ", 00061 " ", 00062 " ", 00063 " ", 00064 " ", 00065 " ", 00066 " .... ", 00067 " .... ", 00068 " .... ", 00069 " .... ", 00070 " .... ", 00071 " .... ", 00072 " .... ", 00073 " . .... ", 00074 " .. .... ", 00075 " ... .... ", 00076 " .... .... ", 00077 " ..... .... ", 00078 " ...... .... ", 00079 " ....................... ", 00080 " ........................ ", 00081 " ........................ ", 00082 " ....................... ", 00083 " ...... ", 00084 " ..... ", 00085 " .... ", 00086 " ... ", 00087 " .. ", 00088 " . ", 00089 " ", 00090 " ", 00091 " ", 00092 " ", 00093 " ", 00094 " ", 00095 " ", 00096 " ", 00097 " ", 00098 }; 00099 00100 static char * arrow_blue_left_40_xpm[]= 00101 { 00102 "40 40 2 1", 00103 ". c blue", 00104 " c none", 00105 " ", 00106 " ", 00107 " ", 00108 " ", 00109 " ", 00110 " ", 00111 " ", 00112 " ", 00113 " ", 00114 " . ", 00115 " .. ", 00116 " ... ", 00117 " .... ", 00118 " ..... ", 00119 " ...... ", 00120 " ....... ", 00121 " ........ ", 00122 " ......... ", 00123 " ............................ ", 00124 " ............................. ", 00125 " ............................. ", 00126 " ............................ ", 00127 " ......... ", 00128 " ........ ", 00129 " ....... ", 00130 " ...... ", 00131 " ..... ", 00132 " .... ", 00133 " ... ", 00134 " .. ", 00135 " . ", 00136 " ", 00137 " ", 00138 " ", 00139 " ", 00140 " ", 00141 " ", 00142 " ", 00143 " ", 00144 " ", 00145 }; 00146 00147 00148 int mastermind_init_pos [MASTERMIND_BOARD_WID*MASTERMIND_BOARD_HEIT] = 00149 { 00150 0, 0, 9, 9, 9, 9, 0, 0, 00151 0, 0, 0, 0, 0, 0, 0, 0, 00152 0, 0, 0, 0, 0, 0, 0, 0, 00153 0, 0, 0, 0, 0, 0, 0, 6, 00154 0, 0, 0, 0, 0, 0, 0, 5, 00155 0, 0, 0, 0, 0, 0, 0, 4, 00156 0, 0, 0, 0, 0, 0, 0, 3, 00157 0, 0, 0, 0, 0, 0, 0, 2, 00158 0, 0, 0, 0, 0, 0, 0, 1, 00159 0, 0, 0, 0, 0, 0, 0, 0, 00160 0, 0, 0, 0, 0, 0,27, 0, 00161 }; 00162 00163 00164 SCORE_FIELD mastermind_score_fields[] = {SCORE_FIELD_USER, SCORE_FIELD_SCORE, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE}; 00165 char *mastermind_score_field_names[] = {"User", "Tries", "Time", "Date", NULL}; 00166 00167 void mastermind_init (); 00168 char ** mastermind_get_pixmap (int idx, int color); 00169 00170 Game Mastermind = { MASTERMIND_CELL_SIZE, 00171 MASTERMIND_BOARD_WID, MASTERMIND_BOARD_HEIT, 00172 MASTERMIND_NUM_PIECES, mastermind_colors, 00173 NULL, NULL, "Mastermind", mastermind_init}; 00174 00175 00176 static ResultType mastermind_who_won (Pos *, Player, char **); 00177 static void mastermind_set_init_pos (Pos *pos); 00178 int mastermind_getmove (Pos *, int, int, GtkboardEventType, Player, byte**, int **); 00179 int mastermind_getmove_kb (Pos *, int , Player, byte **, int **); 00180 void mastermind_reset_uistate (); 00181 int mastermind_get_cur_row (byte *); 00182 void mastermind_set_init_render (Pos *); 00183 void mastermind_free (); 00184 00185 00186 00187 void mastermind_init () 00188 { 00189 game_getmove = mastermind_getmove; 00190 game_getmove_kb = mastermind_getmove_kb; 00191 game_who_won = mastermind_who_won; 00192 game_set_init_pos = mastermind_set_init_pos; 00193 game_get_pixmap = mastermind_get_pixmap; 00194 game_single_player = TRUE; 00195 game_reset_uistate = mastermind_reset_uistate; 00196 game_draw_cell_boundaries = TRUE; 00197 game_scorecmp = game_scorecmp_def_iscore; 00198 game_score_fields = mastermind_score_fields; 00199 game_score_field_names = mastermind_score_field_names; 00200 game_highlight_colors = mastermind_highlight_colors; 00201 game_set_init_render = mastermind_set_init_render; 00202 game_free = mastermind_free; 00203 game_doc_about = 00204 "Mastermind\n" 00205 "Single player game\n" 00206 "Status: Completely implemented\n" 00207 "URL: "GAME_DEFAULT_URL ("mastermind"); 00208 game_doc_rules = 00209 "Mastermind rules\n" 00210 "\n" 00211 "The objective is to find the colors of 4 hidden squares in as few tries as possible.\n\n" 00212 "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."; 00213 00214 // TODO: complete this 00215 } 00216 00217 void mastermind_set_init_render (Pos *pos) 00218 { 00219 pos->render [MASTERMIND_RIGHT_ROW_START * board_wid + board_wid - 1] = RENDER_HIGHLIGHT1; 00220 } 00221 00222 ResultType mastermind_who_won (Pos *pos, Player to_play, char **commp) 00223 { 00224 static char comment[32]; 00225 int j; 00226 gboolean over = FALSE; 00227 char *scorestr; 00228 /* pos->board [(board_heit - 1) * board_wid+ MASTERMIND_MAIN_COL_START] 00229 <= 8 ? TRUE : FALSE; 00230 */ 00231 for (j=0; j<board_heit-1; j++) 00232 if (pos->board[j * board_wid] == 20) // FIXME: don't hard code 00233 over = TRUE; 00234 scorestr = over ? "You won! Tries:" : "Tries:"; 00235 if (!over && mastermind_get_cur_row (pos->board) == board_heit - 1) 00236 { 00237 snprintf (comment, 32, "You lost. Tries: %d", board_heit - 1); 00238 *commp = comment; 00239 return RESULT_LOST; 00240 } 00241 for (j=0; j<board_heit-1; j++) 00242 if (!pos->board[j * board_wid]) 00243 break; 00244 snprintf (comment, 32, "%s %d", scorestr, j); 00245 *commp = comment; 00246 return over ? RESULT_WON : RESULT_NOTYET; 00247 00248 } 00249 00250 int mastermind_get_cur_row (byte *board) 00251 { 00252 int j; 00253 for (j=board_heit-2; j>=0; j--) 00254 { 00255 if (board [j * board_wid + 0] || board [j * board_wid + 1]) 00256 return j+1; 00257 } 00258 return 0; 00259 } 00260 00261 void mastermind_set_init_pos (Pos *pos) 00262 { 00263 int i, j; 00264 for (i=0; i<board_wid; i++) 00265 for (j=0; j<board_heit; j++) 00266 pos->board [j * board_wid + i] = 00267 mastermind_init_pos [(board_heit - 1 - j) * board_wid + i]; 00268 for (i=MASTERMIND_MAIN_COL_START; i<=MASTERMIND_MAIN_COL_END; i++) 00269 pos->board [(board_heit - 1) * board_wid + i] = 9 + random() % 6; 00270 } 00271 00272 char ** mastermind_get_pixmap (int idx, int color) 00273 { 00274 int fg = 0, bg = 0, i; 00275 char *colors; 00276 static char pixbuf[MASTERMIND_CELL_SIZE*(MASTERMIND_CELL_SIZE)+1]; 00277 static char dice_pixbuf[MASTERMIND_CELL_SIZE*(MASTERMIND_CELL_SIZE)+1]; 00278 static gboolean first = TRUE; 00279 colors = mastermind_colors; 00280 if (idx == MASTERMIND_ARROW) 00281 return arrow_blue_left_40_xpm; 00282 else if (idx == MASTERMIND_RETURN) 00283 return arrow_blue_return_40_xpm; 00284 if (idx < 16) 00285 { 00286 fg += (idx & 1); 00287 fg += (idx & 2 ? 256 : 0); 00288 fg += (idx & 4 ? 65536 : 0); 00289 fg *= 255; 00290 if (idx >= 9 && idx <= 14) fg = 100 * 0x10101; 00291 if (color == BLACK) colors += 3; 00292 for(i=0, bg=0;i<3;i++) 00293 { int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));} 00294 if (first) 00295 { 00296 first = FALSE; 00297 return pixmap_ball_gen 00298 (MASTERMIND_CELL_SIZE, pixbuf, fg, bg, 10.0, 30.0); 00299 } 00300 return pixmap_header_gen 00301 (MASTERMIND_CELL_SIZE, pixbuf, fg, bg); 00302 } 00303 else if (idx < 25) 00304 { 00305 int num = (idx <= 20 ? idx - 16 : idx - 20); 00306 for(i=0, bg=0;i<3;i++) 00307 { int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));} 00308 fg = (idx <= 20 ? 0 : 0xffffff); 00309 return pixmap_die_gen(MASTERMIND_CELL_SIZE, dice_pixbuf, fg, bg, 3.0, 30.0, num); 00310 } 00311 else return red_X_40_xpm; 00312 return NULL; 00313 } 00314 00315 static int active = MASTERMIND_RIGHT_ROW_START; 00316 00317 void mastermind_free () 00318 { 00319 active = MASTERMIND_RIGHT_ROW_START; 00320 } 00321 00322 void mastermind_reset_uistate () 00323 { 00324 } 00325 00326 int mastermind_getmove 00327 (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep) 00328 { 00329 static int rmove[7]; 00330 int *rp = rmove; 00331 int tmp; 00332 int i, found; 00333 static byte move[7]; 00334 byte *mp = move; 00335 if (type != GTKBOARD_BUTTON_RELEASE) 00336 return 0; 00337 tmp = MASTERMIND_GET_SELECTION(x,y); 00338 if (tmp > 0) 00339 { 00340 int j; 00341 active = tmp; 00342 for (j=0; j<board_heit; j++) 00343 if (pos->render [j * board_wid + (board_wid - 1)] == RENDER_HIGHLIGHT1) 00344 { 00345 if (j == y) break; 00346 *rp++ = board_wid - 1; 00347 *rp++ = j; 00348 *rp++ = 0; 00349 break; 00350 } 00351 *rp++ = board_wid - 1; 00352 *rp++ = y; 00353 *rp++ = RENDER_HIGHLIGHT1; 00354 *rp++ = -1; 00355 *rmovep = rmove; 00356 return 0; 00357 } 00358 if (active < 1) return -1; 00359 if (!MASTERMIND_IS_MAIN_COL(x)) return -1; 00360 if (y == board_heit -1) return -1; 00361 if (y != mastermind_get_cur_row (pos->board)) return -1; 00362 *mp++ = x; 00363 *mp++ = y; 00364 *mp++ = active - MASTERMIND_RIGHT_ROW_START + 1; 00365 if (movp) 00366 *movp = move; 00367 for (found = 0, i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++) 00368 { 00369 if (pos->board [y * board_wid + i] == MASTERMIND_EMPTY && i != x) 00370 { 00371 found = 1; 00372 break; 00373 } 00374 } 00375 if (!found) 00376 { 00377 *mp++ = MASTERMIND_MAIN_COL_END + 1; 00378 *mp++ = y; 00379 *mp++ = MASTERMIND_RETURN; 00380 } 00381 *mp++ = -1; 00382 return 1; 00383 } 00384 00385 00386 int mastermind_getmove_kb (Pos *pos, int key, Player glob_to_play, byte **movp, int **rmovp) 00387 { 00388 static byte move[32]; 00389 static int rmove[7]; 00390 byte *mp = move; 00391 int *rp = rmove; 00392 int i, j, nblack = 0, nwhite = 0, seen[4] = { 0 }; 00393 byte *board = pos->board; 00394 int cur_row; 00395 if (key == GDK_Up) 00396 { 00397 *rp++ = board_wid - 1; 00398 *rp++ = active; 00399 *rp++ = 0; 00400 if (++active > MASTERMIND_RIGHT_ROW_END) 00401 active = MASTERMIND_RIGHT_ROW_START; 00402 *rp++ = board_wid - 1; 00403 *rp++ = active; 00404 *rp++ = RENDER_HIGHLIGHT1; 00405 *rp++ = -1; 00406 *rmovp = rmove; 00407 return 0; 00408 } 00409 if (key == GDK_Down) 00410 { 00411 *rp++ = board_wid - 1; 00412 *rp++ = active; 00413 *rp++ = 0; 00414 if (--active < MASTERMIND_RIGHT_ROW_START) 00415 active = MASTERMIND_RIGHT_ROW_END; 00416 *rp++ = board_wid - 1; 00417 *rp++ = active; 00418 *rp++ = RENDER_HIGHLIGHT1; 00419 *rp++ = -1; 00420 *rmovp = rmove; 00421 return 0; 00422 } 00423 if (key != GDK_Return) return 0; 00424 if (active < 0) return 0; 00425 cur_row = mastermind_get_cur_row (board); 00426 if (cur_row == board_heit - 1) return -1; 00427 for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++) 00428 { 00429 if (board [cur_row * board_wid + i] == MASTERMIND_EMPTY) 00430 return 0; 00431 } 00432 *mp++ = MASTERMIND_MAIN_COL_END + 1; 00433 *mp++ = cur_row; 00434 *mp++ = MASTERMIND_EMPTY; 00435 if (cur_row < board_heit - 2) 00436 { 00437 *mp++ = MASTERMIND_MAIN_COL_END + 1; 00438 *mp++ = cur_row+1; 00439 *mp++ = MASTERMIND_ARROW; 00440 } 00441 nblack = 0; 00442 for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++) 00443 if (board [cur_row * board_wid + i] == 00444 (board [(board_heit - 1) * board_wid + i] & 7)) 00445 nblack++; 00446 for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++) 00447 { 00448 for (j=MASTERMIND_MAIN_COL_START;j<=MASTERMIND_MAIN_COL_END;j++) 00449 if (board [cur_row * board_wid + i] == 00450 (board [(board_heit - 1) * board_wid + j] & 7) 00451 && !seen[j - MASTERMIND_MAIN_COL_START]) 00452 { 00453 nwhite++; 00454 seen[j - MASTERMIND_MAIN_COL_START] = 1; 00455 break; 00456 } 00457 } 00458 assert (nwhite >= nblack); 00459 nwhite -= nblack; 00460 *mp++ = 0; *mp++ = cur_row; *mp++ = (nblack ? nblack + 16 : 25); 00461 *mp++ = 1; *mp++ = cur_row; *mp++ = (nwhite ? nwhite + 20 : 25); 00462 if (nblack == 4 || cur_row == board_heit - 2) 00463 for (i=MASTERMIND_MAIN_COL_START;i<=MASTERMIND_MAIN_COL_END;i++) 00464 { 00465 *mp++ = i; *mp++ = board_heit - 1; 00466 *mp++ = board [(board_heit - 1) * board_wid + i] & 7; 00467 } 00468 *mp++ = -1; 00469 if (movp) *movp = move; 00470 cur_row++; 00471 return 1; 00472 } 00473