This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

memory.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 <math.h>
00024 #include <gdk/gdkkeysyms.h>
00025 
00026 #include "game.h"
00027 #include "../pixmaps/memory.xpm"
00028 
00029 #define MEMORY_CELL_SIZE 48
00030 #define MEMORY_NUM_PIECES 72
00031 
00032 #define MEMORY_BOARD_WID 9
00033 #define MEMORY_BOARD_HEIT 8
00034 
00035 
00036 #define MEMORY_EMPTY 0
00037 #define MEMORY_ISOPEN(x) ((x)>MEMORY_NUM_PIECES/2)
00038 #define MEMORY_FLIP(x) ((x)>MEMORY_NUM_PIECES/2?\
00039                 (x)-MEMORY_NUM_PIECES/2:(x)+MEMORY_NUM_PIECES/2)
00040 
00041 char ** memory_pixmaps [] = {
00042 memory_blank_xpm,
00043 memory_blank_xpm,
00044 memory_blank_xpm,
00045 memory_blank_xpm,
00046 memory_blank_xpm,
00047 memory_blank_xpm,
00048 memory_blank_xpm,
00049 memory_blank_xpm,
00050 memory_blank_xpm,
00051 memory_blank_xpm,
00052 memory_blank_xpm,
00053 memory_blank_xpm,
00054 memory_blank_xpm,
00055 memory_blank_xpm,
00056 memory_blank_xpm,
00057 memory_blank_xpm,
00058 memory_blank_xpm,
00059 memory_blank_xpm,
00060 memory_blank_xpm,
00061 memory_blank_xpm,
00062 memory_blank_xpm,
00063 memory_blank_xpm,
00064 memory_blank_xpm,
00065 memory_blank_xpm,
00066 memory_blank_xpm,
00067 memory_blank_xpm,
00068 memory_blank_xpm,
00069 memory_blank_xpm,
00070 memory_blank_xpm,
00071 memory_blank_xpm,
00072 memory_blank_xpm,
00073 memory_blank_xpm,
00074 memory_blank_xpm,
00075 memory_blank_xpm,
00076 memory_blank_xpm,
00077 memory_blank_xpm,
00078 memory1_xpm,
00079 memory2_xpm,
00080 //memory3_xpm,
00081 memory4_xpm,
00082 memory5_xpm,
00083 memory6_xpm,
00084 memory7_xpm,
00085 memory8_xpm,
00086 //memory9_xpm,
00087 memory10_xpm,
00088 //memory11_xpm,
00089 memory12_xpm,
00090 memory13_xpm,
00091 memory14_xpm,
00092 memory15_xpm,
00093 memory16_xpm,
00094 memory17_xpm,
00095 memory18_xpm,
00096 memory19_xpm,
00097 //memory20_xpm,
00098 memory21_xpm,
00099 memory22_xpm,
00100 memory23_xpm,
00101 //memory24_xpm,
00102 memory25_xpm,
00103 memory26_xpm,
00104 memory27_xpm,
00105 memory28_xpm,
00106 memory29_xpm,
00107 memory30_xpm,
00108 memory31_xpm,
00109 //memory32_xpm,
00110 memory33_xpm,
00111 memory34_xpm,
00112 memory35_xpm,
00113 memory36_xpm,
00114 memory37_xpm,
00115 memory38_xpm,
00116 memory39_xpm,
00117 memory40_xpm,
00118 memory41_xpm,
00119 memory42_xpm,
00120 };
00121 
00122 char memory_colors[9] = {220, 220, 180, 220, 220, 180, 0, 0, 0};
00123 
00124 int * memory_init_pos = NULL;
00125 
00126 void memory_init ();
00127 
00128 Game Memory = { MEMORY_CELL_SIZE, MEMORY_BOARD_WID, MEMORY_BOARD_HEIT, 
00129         MEMORY_NUM_PIECES, memory_colors,  NULL, memory_pixmaps, 
00130         "Memory", memory_init};
00131 
00132 
00133 typedef struct
00134 {
00135         int num_moves;
00136         int num_found;
00137 } Memory_state;
00138 
00139 static Memory_state state = {0, 0};
00140 
00141 static int memory_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
00142 static int memory_animate (Pos *pos, byte **movp);
00143 static void memory_set_init_pos (Pos *pos);
00144 void *memory_newstate (Pos *, byte *);
00145 ResultType memory_who_won (Pos *, Player, char **);
00146 void memory_free ();
00147 
00148 void memory_init ()
00149 {
00150         game_single_player = TRUE;
00151         game_set_init_pos = memory_set_init_pos;
00152         game_getmove = memory_getmove;
00153         game_animate = memory_animate;
00154         game_animation_time = 100;
00155         game_stateful = TRUE;
00156         game_state_size = sizeof (Memory_state);
00157         game_newstate = memory_newstate;
00158         game_who_won = memory_who_won;
00159         game_free = memory_free;
00160         game_draw_cell_boundaries = FALSE;
00161         game_allow_back_forw = FALSE;
00162         game_scorecmp = game_scorecmp_def_iscore;
00163         game_doc_about = 
00164                 "Memory\n"
00165                 "Single player game\n"
00166                 "Status: Fully implemented\n"
00167                 "URL: "GAME_DEFAULT_URL("memory");
00168         game_doc_rules = 
00169                 "Memory rules\n"
00170                 "\n"
00171                 "There are 36 pairs of images. Your goal is to match these pairs in as few turns as possible.\n"
00172                 "In each turn you click on two squares. If they match they stay uncovered for the rest of the game. If not they go back to being hidden.";
00173 }
00174 
00175 static int waiting = 0;
00176 
00177 void memory_free ()
00178 {
00179         waiting = 0;
00180 }
00181 
00182 void *memory_newstate (Pos *pos, byte *move)
00183 {
00184         int i, j, found;
00185         state.num_moves = pos->state ? ((Memory_state *)pos->state)->num_moves : 0;
00186         state.num_found = pos->state ? ((Memory_state *)pos->state)->num_found : 0;
00187         if (move[2] <= MEMORY_NUM_PIECES/2)
00188                 state.num_moves = pos->state ? ((Memory_state *)pos->state)->num_moves + 1 : 1;
00189         else
00190                 for (i=0, found=0; i<board_wid; i++)
00191                 {
00192                         for (j=0; j<board_heit; j++)
00193                         {
00194                                 if (i == move[0] && j == move[1])
00195                                         continue;
00196                                 if (pos->board [j * board_wid + i] == move[2])
00197                                 {
00198                                         state.num_found = pos->state ? ((Memory_state *)pos->state)->num_found + 1 : 1;
00199                                         found = 1;
00200                                         break;
00201                                 }
00202                         }
00203                         if (found) break;
00204                 }
00205         return &state;
00206 }
00207 
00208 ResultType memory_who_won (Pos *pos, Player to_play, char **commp)
00209 {
00210         static char comment[32];
00211         int found = pos->state ? ((Memory_state *)pos->state)->num_found : 0;
00212         snprintf (comment, 32, "%s %d;  %s %d", 
00213                         "Missed:", pos->state ? ((Memory_state *)pos->state)->num_moves : 0,
00214                         "Found:", found);
00215         *commp = comment;
00216         return (found == board_wid * board_heit / 2) ? RESULT_WON : RESULT_NOTYET;
00217 }
00218 
00219 
00220 int memory_animate (Pos *pos, byte **movp)
00221 {
00222         static byte move[10];
00223         static int count = 0;
00224         byte *mp = move;
00225         int val;
00226         int i, j;
00227         int pair [MEMORY_BOARD_HEIT * MEMORY_BOARD_WID/2+1];
00228         if (waiting > 0) waiting ++;
00229         if (waiting == 10)
00230         {
00231                 waiting = 0;
00232                 for (i=0; i<=MEMORY_BOARD_WID * MEMORY_BOARD_HEIT/2; i++)
00233                         pair [i] = 0;
00234                 for (i=0; i<board_wid; i++)
00235                 for (j=0; j<board_heit; j++)
00236                         if (MEMORY_ISOPEN (val = pos->board [j * board_wid + i]))
00237                                 pair [MEMORY_FLIP (val)] ++;
00238                 for (i=0; i<board_wid; i++)
00239                 for (j=0; j<board_heit; j++)
00240                 {
00241                         if (MEMORY_ISOPEN (val = pos->board [j * board_wid + i])
00242                                         && pair [MEMORY_FLIP (val)] == 1)
00243                         {
00244                                 *mp++ = i;
00245                                 *mp++ = j;
00246                                 *mp++ = MEMORY_FLIP(val);
00247                         }
00248                 }
00249         }
00250         else return -1;
00251         *mp++ = -1;
00252         *movp = move;
00253         return 1;
00254 }
00255 
00256 void memory_set_init_pos (Pos *pos)
00257 {
00258         int i, j, tmp;
00259         int size = board_wid * board_heit;
00260         int swaps = 0;
00261         byte *board = pos->board;
00262         for (i=0; i<size; i++)
00263                 board[i] = i/2+1;
00264         for (i=1; i<size; i++)
00265         {
00266                 j = random() % i;
00267                 tmp = board[i]; board[i] = board[j]; board[j] = tmp;
00268         }
00269 }
00270 
00271 int memory_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, 
00272                 byte **movp, int **rmovp)
00273 {
00274         static byte move[16];
00275         byte *mp = move;
00276         int val, num;
00277         int i, j;
00278         gboolean pair = FALSE;
00279         int found = 0;
00280         if (type != GTKBOARD_BUTTON_RELEASE)
00281                 return 0;
00282         if (waiting > 0) return 0;
00283         if ((val = pos->board [y * board_wid + x]) == MEMORY_EMPTY) return 0;
00284         if (MEMORY_ISOPEN (val)) return 0;
00285         *mp++ = x; *mp++ = y;
00286         num = board_wid * board_heit / 2;
00287         if (val <= num) val += num; else val -= num;
00288         *mp++ = val;
00289         *mp++ = -1;
00290         *movp = move;
00291         
00292         for (i=0; i<board_wid; i++)
00293         for (j=0; j<board_heit; j++)
00294         {
00295                 if (x == i && y == j) continue;
00296                 if (MEMORY_ISOPEN(pos->board [j * board_wid + i]))
00297                 {
00298                         found++;
00299                         if (pos->board [j * board_wid + i] == val) pair = TRUE;
00300                 }
00301         }
00302         if (!pair && (found %2 == 1)) waiting = 1;
00303         return 1;
00304 }
00305