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 <assert.h> 00021 00022 #include "game.h" 00023 00024 #define TOWERS_CELL_SIZE 16 00025 #define TOWERS_NUM_PIECES 3 00026 00027 #define TOWERS_TOWER_WID 17 00028 #define TOWERS_BOARD_WID (3 * TOWERS_TOWER_WID) 00029 #define TOWERS_BOARD_HEIT 18 00030 00031 #define TOWERS_EMPTY 0 00032 #define TOWERS_POLE 1 00033 #define TOWERS_RING_TOP 2 00034 #define TOWERS_RING_BOT 3 00035 #define TOWERS_RING_MID 3 00036 #define TOWERS_RING_LEFT 4 00037 #define TOWERS_RING_RIGHT 5 00038 00039 char towers_colors[6] = {150, 150, 150, 150, 150, 150}; 00040 00041 static char *pole_16_16_xpm[] = { 00042 "16 16 5 1", 00043 "1 c #AAAA66", 00044 "2 c #999955", 00045 "3 c #888844", 00046 "4 c #80803b", 00047 "5 c #777733", 00048 "5433221111223345", 00049 "5433221111223345", 00050 "5433221111223345", 00051 "5433221111223345", 00052 "5433221111223345", 00053 "5433221111223345", 00054 "5433221111223345", 00055 "5433221111223345", 00056 "5433221111223345", 00057 "5433221111223345", 00058 "5433221111223345", 00059 "5433221111223345", 00060 "5433221111223345", 00061 "5433221111223345", 00062 "5433221111223345", 00063 "5433221111223345", 00064 }; 00065 00066 00067 static char *ring_top_16_16_xpm[] = { 00068 "16 16 2 1", 00069 " c #cccc99", 00070 ". c #aaaa77", 00071 "................", 00072 "................", 00073 " ", 00074 " ", 00075 " ", 00076 " ", 00077 " ", 00078 " ", 00079 " ", 00080 " ", 00081 " ", 00082 " ", 00083 " ", 00084 " ", 00085 " ", 00086 " ", 00087 }; 00088 00089 static char *ring_bot_16_16_xpm[] = { 00090 "16 16 2 1", 00091 " c #cccc99", 00092 ". c #aaaa77", 00093 " ", 00094 " ", 00095 " ", 00096 " ", 00097 " ", 00098 " ", 00099 " ", 00100 " ", 00101 " ", 00102 " ", 00103 " ", 00104 " ", 00105 " ", 00106 " ", 00107 "................", 00108 "................", 00109 }; 00110 00111 00112 static char **towers_pixmaps[] = 00113 { 00114 pole_16_16_xpm, 00115 ring_top_16_16_xpm, 00116 ring_bot_16_16_xpm, 00117 }; 00118 00119 static int towers_init_pos[] = 00120 { 00121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00123 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00124 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00125 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00126 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00127 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00128 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00129 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00130 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00131 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00132 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00133 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00134 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00135 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00136 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00137 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00138 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 00139 }; 00140 00141 00142 void towers_init (); 00143 00144 Game Towers = { TOWERS_CELL_SIZE, TOWERS_BOARD_WID, TOWERS_BOARD_HEIT, 00145 TOWERS_NUM_PIECES, 00146 towers_colors, towers_init_pos, towers_pixmaps, 00147 "Tower of Hanoi", 00148 towers_init}; 00149 00150 SCORE_FIELD towers_score_fields[] = {SCORE_FIELD_RANK, SCORE_FIELD_USER, SCORE_FIELD_SCORE, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE}; 00151 char *towers_score_field_names[] = {"Rank", "User", "Moves", "Time", "Date", NULL}; 00152 00153 static int towers_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **); 00154 static ResultType towers_who_won (Pos *, Player, char **); 00155 void towers_reset_uistate (); 00156 void towers_get_render (Pos *pos, byte *move, int **rmovp); 00157 00158 void towers_init () 00159 { 00160 game_single_player = TRUE; 00161 game_getmove = towers_getmove; 00162 game_who_won = towers_who_won; 00163 game_scorecmp = game_scorecmp_def_iscore; 00164 game_score_fields = towers_score_fields; 00165 game_score_field_names = towers_score_field_names; 00166 game_reset_uistate = towers_reset_uistate; 00167 game_get_render = towers_get_render; 00168 game_doc_about = 00169 "Towers\n" 00170 "Single player game\n" 00171 "Status: Partially implemented\n" 00172 "URL: "GAME_DEFAULT_URL("towers"); 00173 game_doc_rules = 00174 " Towers rules\n\n" 00175 " Transfer all the rings from the first pole to the last. A ring can never lie on a smaller one."; 00176 ; 00177 } 00178 00179 static gboolean towers_over (byte *board) 00180 { 00181 return board [TOWERS_TOWER_WID/2] != TOWERS_RING_BOT && 00182 board [TOWERS_TOWER_WID/2+TOWERS_TOWER_WID] != TOWERS_RING_BOT; 00183 } 00184 00185 ResultType towers_who_won (Pos *pos, Player to_play, char **commp) 00186 { 00187 static char comment[32]; 00188 gboolean over = towers_over (pos->board); 00189 char *scorestr = over ? "You won. Moves:" : "Moves:"; 00190 snprintf (comment, 32, "%s %d", scorestr, pos->num_moves); 00191 *commp = comment; 00192 return over ? RESULT_WON : RESULT_NOTYET; 00193 } 00194 00195 00196 static int cur_row = -1; 00197 00198 #define POLE_ROW(x) (((x)/TOWERS_TOWER_WID)*TOWERS_TOWER_WID+TOWERS_TOWER_WID/2) 00199 00200 // Find the heit and len of the top ring in the tower corresp to row 00201 static void get_top_ring (byte *board, int row, int *heit, int *len) 00202 { 00203 int pole_row = POLE_ROW (row); 00204 int i, j; 00205 for (j = board_heit - 1; j >= 0; j--) 00206 if (board [j * board_wid + pole_row] == TOWERS_RING_TOP) 00207 break; 00208 if (j < 0) 00209 { 00210 if (heit) *heit = -1; 00211 if (len) *len = -1; 00212 return; 00213 } 00214 for (i=0; ; i++) 00215 if (board [j * board_wid + pole_row + i] != TOWERS_RING_TOP) 00216 break; 00217 if (heit) *heit = j; 00218 if (len) *len = i; 00219 } 00220 00221 int towers_getmove 00222 (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep) 00223 { 00224 static byte move[512]; 00225 static int rmove[512]; 00226 byte *mp = move; 00227 int *rp = rmove; 00228 int heit1, heit2, len1, len2; 00229 int i, j, pole_row; 00230 00231 if (type != GTKBOARD_BUTTON_RELEASE) 00232 return 0; 00233 if (cur_row < 0) 00234 { 00235 get_top_ring (pos->board, x, &heit1, &len1); 00236 if (heit1 < 0) 00237 return -1; 00238 cur_row = x; 00239 pole_row = POLE_ROW(x); 00240 for (j=0; j<=1; j++) 00241 for (i = pole_row - len1 + 1; i <= pole_row + len1 - 1; i++) 00242 { 00243 *rp++ = i; 00244 *rp++ = heit1 - j; 00245 *rp++ = RENDER_SHADE1; 00246 } 00247 *rp++ = -1; 00248 *rmovep = rmove; 00249 return 0; 00250 } 00251 00252 get_top_ring (pos->board, cur_row, &heit1, &len1); 00253 get_top_ring (pos->board, x, &heit2, &len2); 00254 00255 pole_row = POLE_ROW(cur_row); 00256 for (j=0; j<=1; j++) 00257 for (i = pole_row - len1 + 1; i <= pole_row + len1 - 1; i++) 00258 { 00259 *mp++ = i; 00260 *mp++ = heit1 - j; 00261 *mp++ = i == pole_row ? TOWERS_POLE : TOWERS_EMPTY; 00262 *rp++ = i; 00263 *rp++ = heit1 - j; 00264 *rp++ = 0; 00265 } 00266 *rp++ = -1; 00267 *rmovep = rmove; 00268 00269 if (POLE_ROW(cur_row) == POLE_ROW(x)) 00270 { 00271 cur_row = -1; 00272 return 0; 00273 } 00274 00275 if (heit2 >= 0 && len1 > len2) 00276 { 00277 cur_row = -1; 00278 return -1; 00279 } 00280 00281 heit2 += 2; 00282 00283 pole_row = POLE_ROW(x); 00284 for (j=0; j<=1; j++) 00285 for (i = pole_row - len1 + 1; i <= pole_row + len1 - 1; i++) 00286 { 00287 *mp++ = i; 00288 *mp++ = heit2 - j; 00289 *mp++ = j == 0 ? TOWERS_RING_TOP : TOWERS_RING_BOT; 00290 } 00291 *mp++ = -1; 00292 *movp = move; 00293 cur_row = -1; 00294 return 1; 00295 } 00296 00297 void towers_reset_uistate () 00298 { 00299 cur_row = -1; 00300 } 00301 00302 void towers_get_render (Pos *pos, byte *move, int **rmovp) 00303 { 00304 static int rmove[512]; 00305 int *rp = rmove; 00306 int i, j; 00307 for (i=0; i<board_wid; i++) 00308 for (j=0; j<board_heit; j++) 00309 if (pos->render[j * board_wid + i] != RENDER_NONE) 00310 { 00311 *rp++ = i; 00312 *rp++ = j; 00313 *rp++ = RENDER_NONE; 00314 } 00315 *rp++ = -1; 00316 *rmovp = rmove; 00317 }