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 #include <stdio.h> 00020 #include <string.h> 00021 #include <assert.h> 00022 #include <stdlib.h> 00023 #include <time.h> 00024 #include <gdk/gdkkeysyms.h> 00025 00026 00027 #include "game.h" 00028 #include "../pixmaps/alpha.xpm" 00029 #include "flwords.h" 00030 00031 00032 #define FLW_CELL_SIZE 36 00033 00034 #define FLW_NUM_PIECES 26 00035 00036 #define FLW_BOARD_WID 4 00037 #define FLW_BOARD_HEIT 6 00038 00039 #define FLW_LEN 4 00040 00041 char flw_colors[9] = {0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0, 0, 0xff}; 00042 char flw_highlight_colors[9] = {0xff, 0, 0, 0, 0, 0, 0, 0, 0}; 00043 00044 static char **flw_pixmaps [] = 00045 { 00046 char_A_grey_36_36_xpm, 00047 char_B_grey_36_36_xpm, 00048 char_C_grey_36_36_xpm, 00049 char_D_grey_36_36_xpm, 00050 char_E_grey_36_36_xpm, 00051 char_F_grey_36_36_xpm, 00052 char_G_grey_36_36_xpm, 00053 char_H_grey_36_36_xpm, 00054 char_I_grey_36_36_xpm, 00055 char_J_grey_36_36_xpm, 00056 char_K_grey_36_36_xpm, 00057 char_L_grey_36_36_xpm, 00058 char_M_grey_36_36_xpm, 00059 char_N_grey_36_36_xpm, 00060 char_O_grey_36_36_xpm, 00061 char_P_grey_36_36_xpm, 00062 char_Q_grey_36_36_xpm, 00063 char_R_grey_36_36_xpm, 00064 char_S_grey_36_36_xpm, 00065 char_T_grey_36_36_xpm, 00066 char_U_grey_36_36_xpm, 00067 char_V_grey_36_36_xpm, 00068 char_W_grey_36_36_xpm, 00069 char_X_grey_36_36_xpm, 00070 char_Y_grey_36_36_xpm, 00071 char_Z_grey_36_36_xpm, 00072 }; 00073 00074 SCORE_FIELD flw_score_fields[] = {SCORE_FIELD_USER, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE}; 00075 char *flw_score_field_names[] = {"User", "Time", "Date", NULL}; 00076 00077 static int flw_wordcmp (const void *p1, const void *p2) 00078 { 00079 return strcmp ((char *)p1, *(char **)p2); 00080 } 00081 00082 void flw_find_chain (char chain[FLW_LEN+1][FLW_LEN+1]) 00083 { 00084 int i, j, idx, found; 00085 int done[FLW_LEN]; 00086 char word[FLW_LEN+1]; 00087 do 00088 { 00089 strncpy (word, flwords[random() % num_flwords], FLW_LEN+1); 00090 sprintf (chain[0], "%s", word); 00091 for (i=0, memset (done, 0, FLW_LEN * sizeof (int)); i<FLW_LEN; i++) 00092 { 00093 char orig; 00094 do {idx = random() % FLW_LEN;} while (done[idx]); done[idx] = 1; 00095 orig= word[idx]; 00096 for (j=0, found=0; j<100; j++) 00097 { 00098 if ((word[idx] = random() % 26 + 'a') == orig) continue; 00099 if (bsearch (word, flwords, num_flwords, sizeof (flwords[0]), flw_wordcmp)) 00100 { 00101 sprintf (chain[i+1], "%s", word); 00102 found = 1; 00103 break; 00104 } 00105 } 00106 if (!found) 00107 break; 00108 } 00109 } 00110 while (!found); 00111 } 00112 00113 static void flw_init (); 00114 int flw_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **); 00115 int flw_getmove_kb (Pos *, int, Player, byte **, int **); 00116 void flw_free (); 00117 ResultType flw_who_won (Pos *, Player , char **); 00118 00119 Game Flw = { FLW_CELL_SIZE, FLW_BOARD_WID, FLW_BOARD_HEIT, 00120 FLW_NUM_PIECES, 00121 flw_colors, NULL, flw_pixmaps, 00122 "Four Letter Words", 00123 flw_init}; 00124 00125 00126 static char flw_chain[FLW_LEN+1][FLW_LEN+1]; 00127 00128 00129 static void flw_set_init_pos (Pos *pos) 00130 { 00131 int i, j; 00132 for (i=0; i<board_wid * board_heit; i++) 00133 pos->board[i] = 0; 00134 flw_find_chain (flw_chain); 00135 for (i=0; i<FLW_LEN; i++) 00136 { 00137 pos->board[(board_heit - 1) * board_wid + i] = flw_chain[0][i] - 'a' + 1; 00138 pos->board[i] = flw_chain[FLW_LEN][i] - 'a' + 1; 00139 } 00140 } 00141 00142 static void flw_init () 00143 { 00144 game_single_player = TRUE; 00145 game_set_init_pos = flw_set_init_pos; 00146 game_draw_cell_boundaries = TRUE; 00147 game_free = flw_free; 00148 game_getmove = flw_getmove; 00149 game_getmove_kb = flw_getmove_kb; 00150 game_who_won = flw_who_won; 00151 game_start_immediately = TRUE; 00152 game_scorecmp = game_scorecmp_def_iscore; 00153 game_score_fields = flw_score_fields; 00154 game_score_field_names = flw_score_field_names; 00155 game_highlight_colors = flw_highlight_colors; 00156 game_doc_about = 00157 "Four letter words\n" 00158 "Single player game\n" 00159 "Status: Partially implemented (playable)\n" 00160 "URL: "GAME_DEFAULT_URL("flw"); 00161 game_doc_rules = 00162 " Four Letter Words rules\n\n" 00163 " This is a simple game in which the objective is to change the word at the top to the word at the bottom by changing one letter at a time. All intermediate words must be legal.\n" 00164 " To start playing, hit enter. This will make a copy of the top word on the second row. Click on the letter you want to change and change it by typing the new letter. Now hit enter. Repeat until all the rows are filled."; 00165 } 00166 00167 static int flw_curx = -1, flw_cury = -1; 00168 00169 ResultType flw_who_won (Pos *pos, Player to_play, char **commp) 00170 { 00171 static char comment[32] = "You won."; 00172 int i; 00173 for (i=0; i<FLW_LEN; i++) 00174 if (pos->board [i] != pos->board [board_wid + i]) 00175 return RESULT_NOTYET; 00176 *commp = comment; 00177 return RESULT_WON; 00178 } 00179 00180 static int flw_get_cur_row (byte *board) 00181 { 00182 int j; 00183 for (j = board_heit - 1; j>=0 && board[j * board_wid]; j--) 00184 ; 00185 if (j < 0) j = 0; 00186 return j+1; 00187 } 00188 00189 void flw_get_render (Pos *pos, byte *move, int type, int **rmovp) 00190 { 00191 static int rmove[7]; 00192 int *rp = rmove; 00193 int i, j; 00194 int oldx = 0; 00195 for (i=0; i<board_wid; i++) 00196 for (j=0; j<board_heit; j++) 00197 if (pos->render [j * board_wid + i] == RENDER_HIGHLIGHT1) 00198 { 00199 assert (rp == rmove); 00200 *rp++ = i; 00201 *rp++ = j; 00202 *rp++ = 0; 00203 oldx = i; 00204 } 00205 *rp++ = oldx; 00206 *rp++ = flw_get_cur_row (pos->board); 00207 *rp++ = RENDER_HIGHLIGHT1; 00208 *rp++ = -1; 00209 *rmovp = rmove; 00210 } 00211 00212 00213 int flw_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, 00214 byte **movp, int ** rmovep) 00215 { 00216 static int rmove[7]; 00217 int *rp = rmove; 00218 if (type != GTKBOARD_BUTTON_RELEASE) 00219 return 0; 00220 if (y == 0 || y == board_heit - 1) return 0; 00221 if (pos->board [y * board_wid + x] == 0) return 0; 00222 if (y != 1 && pos->board [(y-1) * board_wid + x] != 0) return 0; 00223 if (flw_curx == x && flw_cury == y) return 0; 00224 *rp++ = flw_curx; *rp++ = flw_cury; *rp++ = 0; 00225 *rp++ = x; *rp++ = y; *rp++ = RENDER_HIGHLIGHT1; 00226 *rp++ = -1; 00227 *rmovep = rmove; 00228 flw_curx = x; 00229 flw_cury = y; 00230 return 0; 00231 } 00232 00233 int flw_getmove_kb (Pos *pos, int key, Player glob_to_play, byte **movp, int **rmovp) 00234 { 00235 static int rmove[7]; 00236 int *rp = rmove; 00237 static byte move[10]; 00238 byte *mp = move; 00239 int i, j, cury; 00240 char word[FLW_LEN+1], prevword[FLW_LEN+1]; 00241 if (flw_cury >= 0) 00242 { 00243 if (!(pos->board [flw_cury * board_wid] && 00244 (pos->board [(flw_cury-1) * board_wid] == 0 || flw_cury == 1))) 00245 { 00246 assert (0); 00247 // find the current row 00248 /*for (j = board_heit - 1; j>=0 && pos->board[j * board_wid]; j--) 00249 ; 00250 if (j < 0) j = 0; 00251 flw_cury = j+1; 00252 flw_curx = 0;*/ 00253 flw_cury = flw_get_cur_row (pos->board); 00254 flw_curx = 0; 00255 } 00256 } 00257 if (key == GDK_Return) 00258 { 00259 if ((cury = flw_cury) < 0) 00260 cury = board_heit - 1; 00261 for (i=0; i<FLW_LEN; i++) 00262 { 00263 word[i] = pos->board [cury * board_wid + i] + 'a' - 1; 00264 if (flw_cury >= 0) 00265 prevword[i] = pos->board [(cury+1) * board_wid + i] + 'a' - 1; 00266 } 00267 word[FLW_LEN] = '\0'; 00268 prevword[FLW_LEN] = '\0'; 00269 if (!bsearch (word, flwords, num_flwords, sizeof (flwords[0]), flw_wordcmp)) 00270 return -1; 00271 if (flw_cury >= 0) 00272 { 00273 int diff_cnt_prev = 0, diff_cnt_last = 0; 00274 for (i=0; i<FLW_LEN; i++) 00275 { 00276 if (word[i] != prevword[i]) 00277 diff_cnt_prev++; 00278 if (word[i] != flw_chain[FLW_LEN+1][i]) 00279 diff_cnt_last++; 00280 } 00281 if (diff_cnt_prev != 1) 00282 return -1; 00283 if (cury == 1 && diff_cnt_last != 1) 00284 return -1; 00285 } 00286 if (flw_cury >= 0) 00287 { 00288 *rp++ = flw_curx; *rp++ = flw_cury; *rp++ = 0; 00289 } 00290 if (flw_cury < 0) 00291 { 00292 flw_curx = 0; 00293 flw_cury = board_heit - 1; 00294 } 00295 flw_cury --; 00296 *rp++ = flw_curx; *rp++ = flw_cury; *rp++ = RENDER_HIGHLIGHT1; 00297 *rp++ = -1; 00298 *rmovp = rmove; 00299 for (i=0; i<FLW_LEN; i++) 00300 { 00301 *mp++ = i; *mp++ = flw_cury; *mp++ = word[i] - 'a' + 1; 00302 } 00303 *mp++ = -1; 00304 *movp = move; 00305 return 1; 00306 } 00307 if (flw_cury < 0 || flw_cury == board_heit - 1) 00308 return -1; 00309 if (key == GDK_Right) 00310 { 00311 *rp++ = flw_curx; *rp++ = flw_cury; *rp++ = 0; 00312 if (++flw_curx == FLW_LEN) flw_curx = 0; 00313 *rp++ = flw_curx; *rp++ = flw_cury; *rp++ = RENDER_HIGHLIGHT1; 00314 *rp++ = -1; 00315 *rmovp = rmove; 00316 return 0; 00317 } 00318 if (key == GDK_Left) 00319 { 00320 *rp++ = flw_curx; *rp++ = flw_cury; *rp++ = 0; 00321 if (--flw_curx < 0) flw_curx = FLW_LEN - 1; 00322 *rp++ = flw_curx; *rp++ = flw_cury; *rp++ = RENDER_HIGHLIGHT1; 00323 *rp++ = -1; 00324 *rmovp = rmove; 00325 return 0; 00326 } 00327 if (key >= GDK_A && key <= GDK_Z) 00328 key = key + GDK_a - GDK_A; 00329 if (key >= GDK_a && key <= GDK_z) 00330 { 00331 *mp++ = flw_curx; *mp++ = flw_cury; *mp++ = key - GDK_a + 1; 00332 *mp++ = -1; 00333 *movp = move; 00334 return 1; 00335 } 00336 return -1; 00337 } 00338 00339 void flw_free () 00340 { 00341 flw_curx = flw_cury = -1; 00342 } 00343