This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

towers.c

Go to the documentation of this file.
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 }