This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

maze.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 "aaball.h"
00028 
00029 #define MAZE_CELL_SIZE 8
00030 #define MAZE_NUM_PIECES 127
00031 
00032 #define MAZE_BOARD_WID 60
00033 #define MAZE_BOARD_HEIT 60
00034 
00035 char maze_colors[6] = {100, 150, 200, 100, 150, 200};
00036 
00037 int * maze_init_pos = NULL;
00038 
00039 static int maze_maze[MAZE_BOARD_WID][MAZE_BOARD_HEIT] = {{0}};
00040 
00041 #define MAZE_WALL 2
00042 #define MAZE_CUR 1
00043 
00044 void maze_init ();
00045 
00046 SCORE_FIELD maze_score_fields[] = {SCORE_FIELD_USER, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE};
00047 char *maze_score_field_names[] = {"User", "Time", "Date", NULL};
00048 
00049 
00050 Game Maze = { MAZE_CELL_SIZE, MAZE_BOARD_WID, MAZE_BOARD_HEIT, 
00051         MAZE_NUM_PIECES, maze_colors,  NULL, NULL, "Maze", maze_init};
00052 
00053 
00054 static void maze_set_init_pos (Pos *pos);
00055 static char ** maze_get_pixmap (int idx, int color);
00056 static int maze_getmove_kb (Pos *cur_pos, int key, Player glob_to_play, 
00057                 byte **move, int **);
00058 ResultType maze_who_won (Pos *, Player, char **);
00059 
00060 void maze_init ()
00061 {
00062         game_single_player = TRUE;
00063         game_set_init_pos = maze_set_init_pos;
00064         game_get_pixmap = maze_get_pixmap;
00065         game_getmove_kb = maze_getmove_kb;
00066         game_who_won = maze_who_won;
00067         game_start_immediately = TRUE;
00068         game_scorecmp = game_scorecmp_def_time;
00069         game_score_fields = maze_score_fields;
00070         game_score_field_names = maze_score_field_names;
00071         game_doc_about = 
00072                 "Maze\n"
00073                 "Single player game\n"
00074                 "Status: Partially implemented (playable)\n"
00075                 "URL: "GAME_DEFAULT_URL ("maze");
00076         game_doc_rules = 
00077                 "Maze rules\n"
00078                 "\n"
00079                 "Your objective is to lead the man (or mouse or whatever) trapped in the maze from the lower left corner to the upper right.\n"
00080                 "\n"
00081                 "The maze is randomly generated, and is currently not very good at generating particularly hard-to-solve mazes.\n";
00082 }
00083 
00084 
00085 ResultType maze_who_won (Pos *pos, Player to_play, char **commp)
00086 {
00087         static char comment[32];
00088         gboolean over = (pos->board [board_wid * board_heit - 1] == MAZE_CUR);
00089         snprintf (comment, 32, "%sMoves: %d", 
00090                         over ? "You won. " : "",
00091                         pos->num_moves);
00092         *commp = comment;
00093         return over ? RESULT_WON : RESULT_NOTYET;
00094 }
00095 
00096 void maze_get_cur_pos (byte *pos, int *x, int *y)
00097 {
00098         int i, j;
00099         for (i=0; i<board_wid; i++)
00100         for (j=0; j<board_heit; j++)
00101                 if (pos [j * board_wid + i] == MAZE_CUR)
00102                 { *x = i; *y = j; return;
00103                 }
00104 }
00105 
00106 int maze_getmove_kb (Pos *pos, int key, Player glob_to_play, byte **movp, int **rmovp)
00107 {
00108         static byte move[10];
00109         int curx = -1, cury = -1;
00110         int incx = -1, incy = -1;
00111         int x, y;
00112         maze_get_cur_pos (pos->board, &curx, &cury);
00113         g_assert (curx >= 0 && cury >= 0);
00114         switch (key)
00115         {
00116                 case GDK_Up: incx = 0; incy = 1; break;
00117                 case GDK_Down: incx = 0; incy = -1; break;
00118                 case GDK_Right: incx = 1; incy = 0; break;
00119                 case GDK_Left: incx = -1; incy = 0; break;
00120                 default: return -1;
00121         }
00122         x = curx + incx;
00123         y = cury + incy;
00124         if (x < 0 || y < 0 || x >= board_wid || y >= board_heit) return -1;
00125         if (pos->board[y * board_wid + x] == MAZE_WALL) return -1;
00126         move[0] = curx; move[1] = cury; move[2] = 0;
00127         move[3] = x; move[4] = y; move[5] = MAZE_CUR;
00128         move[6] = -1;
00129         *movp = move;
00130         return 1;
00131 }
00132 
00133 
00134 int maze_checknbrs(int x, int y)
00135 {
00136         int i, j;
00137         int incx[] = {1, 1, 1, 0, -1, -1, -1, 0};
00138         int incy[] = {1, 0, -1, -1, -1, 0, 1, 1};
00139         if (x < 0 || y < 0 || x >= board_wid || y >= board_heit)
00140                 return 0;
00141         for (i=1; i<=7; i+=2)
00142         {
00143                 int found = 0;
00144                 for (j=0; j<3; j++)
00145                 {
00146                         int k = (i+j)%8;
00147                         int newx = x + incx[k], newy = y + incy[k];
00148                         if (newx < 0 || newy < 0 || newx >= board_wid || newy >= board_heit)
00149                                 continue;
00150                         if (maze_maze[newx][newy] == MAZE_WALL)
00151                                 found = 1;
00152                 }
00153                 if (!found) return 0;
00154         }
00155         return 1;       
00156 }
00157 
00158 static void recursive_pathgen (byte *board, int x, int y, int val)
00159 {
00160         static int incx[4] = {-1, 0, 0, 1};
00161         static int incy[4] = {0, -1, 1, 0};
00162 
00163         int i;
00164         if (!ISINBOARD(x, y)) return;
00165         if (board[y * board_wid + x] == val) return;
00166         if (board[y * board_wid + x] == MAZE_WALL) return;
00167         board [y * board_wid + x] = val;
00168         for (i=0; i<4; i++)
00169                 recursive_pathgen (board, x+incx[i], y+incy [i], val);
00170 }
00171 
00172 
00173 static void mazegen ()
00174 {
00175         int x, y, npts = 0;
00176         for (x=0; x<board_wid; x++)
00177         for (y=0; y<board_heit; y++)
00178                 maze_maze[x][y] = MAZE_WALL;
00179         while (npts < board_wid * board_heit * 0.58)
00180         {
00181                 x = random() % board_wid;
00182                 y = random() % board_heit;
00183                 if (maze_maze[x][y] == 0) continue;
00184                 if (maze_checknbrs(x, y))
00185                 {
00186                         maze_maze[x][y] = 0;
00187                         npts++;
00188                 }
00189         }
00190         {
00191         int incx[] = {1, 0, -1, 0};
00192         int incy[] = {0, -1, 0, 1};
00193         int k;
00194         // make the 4 edges into walls
00195         for (y=0; y<board_heit; y++) 
00196         {
00197                 maze_maze[0][y] = MAZE_WALL;
00198                 maze_maze[board_heit-1][y] = MAZE_WALL;
00199         }
00200         for (x=0; x<board_wid; x++) 
00201         {
00202                 maze_maze[x][0] = MAZE_WALL;
00203                 maze_maze[x][board_wid-1] = MAZE_WALL;
00204         }
00205         // if all squares are surrounded then make it a wall
00206         for (x=1; x<board_wid-1; x++)
00207         for (y=1; y<board_heit-1; y++)
00208         {
00209                 int found = 0;
00210                 for (k=0; k<4; k++)
00211                 {
00212                         int newx = x + incx[k], newy = y + incy[k]; 
00213                         if (maze_maze[newx][newy] != MAZE_WALL)
00214                         {
00215                                 found = 1;
00216                                 break;
00217                         }
00218                 }
00219                 if (!found)
00220                         maze_maze [x][y] = MAZE_WALL;
00221         }
00222         }
00223 }
00224 
00225 void maze_set_init_pos (Pos *pos)
00226 {
00227         int i, j, k;
00228         int incx[4] = {0, 0, 1, -1};
00229         int incy[4] = {1, -1, 0, 0};
00230         do
00231         {
00232                 mazegen();
00233                 for (i=0; i<board_wid; i++)
00234                 for (j=0; j<board_heit; j++)
00235                         pos->board [j * board_wid + i] = maze_maze[i][j];
00236                 for (i=0; i<3; i++)
00237                 for (j=0; j<3; j++)
00238                         pos->board [j * board_wid + i] = 0;
00239                 for (i=board_wid-3; i<board_wid; i++)
00240                 for (j=board_heit-3; j<board_heit; j++)
00241                         pos->board [j * board_wid + i] = 0;
00242                 recursive_pathgen (pos->board, 0, 0, -1);
00243         }
00244         while (pos->board [board_wid * board_heit - 1] != -1);
00245         for (i=0; i<board_wid; i++)
00246         for (j=0; j<board_heit; j++)
00247                 if (pos->board [j * board_wid + i] == -1)
00248                         pos->board [j * board_wid + i] = 0;
00249         pos->board[0] = MAZE_CUR;
00250         
00251         /*while(1)
00252         {
00253                 i = random()%board_wid;
00254                 j = random()%board_heit;
00255                 if (pos->board [j*board_wid+i] == 0)
00256                 {
00257                         pos->board [j * board_wid + i] = 1;
00258                         break;
00259                 }
00260         }*/
00261 }
00262 
00263 char ** maze_pixmap_square_gen (int idx, char *col)
00264 {
00265         int i, j;
00266         char **pixmap;
00267         char *line = "        ";
00268         pixmap = g_new(char *, MAZE_CELL_SIZE + 2);
00269         pixmap[0] = "8 8 1 1";
00270         pixmap[1] = g_strdup_printf (" c %s", col);
00271         for (i=0; i<MAZE_CELL_SIZE; i++) pixmap[i+2] = line; return pixmap;
00272 }
00273 
00274 char ** maze_get_pixmap (int idx, int color)
00275 {
00276         int fg, bg, i;
00277         char *colors = maze_colors;
00278         for(i=0, bg=0;i<3;i++) 
00279         { int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));}
00280         if (idx == MAZE_WALL)
00281                 return maze_pixmap_square_gen(idx, "#443333");
00282         return maze_pixmap_square_gen(idx, "#ffff00");
00283         //else return pixmap_ball_gen(MAZE_CELL_SIZE, 0xc0c040, bg, 2, 50);
00284 }
00285