This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

flw.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 <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