This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

dirmaze.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/arrows.xpm"
00028 #include "aaball.h"
00029 
00030 #define HYPERMAZE_CELL_SIZE 20
00031 #define HYPERMAZE_NUM_PIECES 10
00032 
00033 #define HYPERMAZE_BOARD_WID 25
00034 #define HYPERMAZE_BOARD_HEIT 25
00035 
00036 char hypermaze_colors[6] = {100, 150, 200, 100, 150, 200};
00037 
00038 int * hypermaze_init_pos = NULL;
00039 
00040 int hypermaze_hypermaze[HYPERMAZE_BOARD_WID][HYPERMAZE_BOARD_HEIT] = {{0}};
00041 
00042 #define HYPERMAZE_CUR 1
00043 #define HYPERMAZE_N 2
00044 #define HYPERMAZE_E 3
00045 #define HYPERMAZE_S 4
00046 #define HYPERMAZE_W 5
00047 #define HYPERMAZE_NE 6
00048 #define HYPERMAZE_SE 7
00049 #define HYPERMAZE_SW 8
00050 #define HYPERMAZE_NW 9
00051 #define HYPERMAZE_WALL 10
00052 
00053 void hypermaze_init ();
00054 
00055 SCORE_FIELD hypermaze_score_fields[] = {SCORE_FIELD_USER, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE};
00056 char *hypermaze_score_field_names[] = {"User", "Time", "Date", NULL};
00057 
00058 Game Hypermaze = { HYPERMAZE_CELL_SIZE, HYPERMAZE_BOARD_WID, HYPERMAZE_BOARD_HEIT, 
00059         HYPERMAZE_NUM_PIECES, hypermaze_colors,  NULL, NULL, "Hypermaze", hypermaze_init};
00060 
00061 
00062 static void hypermaze_set_init_pos (Pos *pos);
00063 static char ** hypermaze_get_pixmap (int idx, int color);
00064 static int hypermaze_getmove_kb (Pos *, int, Player, byte **, int **);
00065 int hypermaze_getmove (Pos *pos, int, int, GtkboardEventType, Player, byte **, int **);
00066 ResultType hypermaze_who_won (Pos *, Player, char **);
00067 
00068 
00069 void hypermaze_init ()
00070 {
00071         game_single_player = TRUE;
00072         game_set_init_pos = hypermaze_set_init_pos;
00073         game_get_pixmap = hypermaze_get_pixmap;
00074         game_getmove_kb = hypermaze_getmove_kb;
00075         game_getmove = hypermaze_getmove;
00076         game_who_won = hypermaze_who_won;
00077         game_start_immediately = TRUE;
00078         game_scorecmp = game_scorecmp_def_time;
00079         game_score_fields = hypermaze_score_fields;
00080         game_score_field_names = hypermaze_score_field_names;
00081         game_doc_about = 
00082                 "HyperMaze\n"
00083                 "Single player game\n"
00084                 "Status: Partially implemented (playable)\n"
00085                 "URL: "GAME_DEFAULT_URL ("hypermaze");
00086         game_doc_rules = 
00087                 "Hypermaze rules\n"
00088                 "\n"
00089                 "Your goal is to get from the lower left corner to the upper right. But you can travel only along the arrows. Beware - the arrows are one-way! You can easily get trapped in a blind end from which there is no escape."
00090                 "\n"
00091                 "To move with the mouse, click on the square to which you want to move. To move with the keyboard, use the NumPad keys.\n";
00092 }
00093 
00094 void hypermaze_get_cur_pos (byte *pos, int *x, int *y)
00095 {
00096         int i, j;
00097         for (i=0; i<board_wid; i++)
00098         for (j=0; j<board_heit; j++)
00099                 if (pos [j * board_wid + i] == HYPERMAZE_CUR)
00100                 { *x = i; *y = j; return;
00101                 }
00102 }
00103 
00104 
00105 ResultType hypermaze_who_won (Pos *pos, Player to_play, char **commp)
00106 {
00107         static char comment[32];
00108         gboolean over = (pos->board [board_wid * board_heit - 1] == HYPERMAZE_CUR);
00109         snprintf (comment, 32, "%sMoves: %d", 
00110                         over ? "You won. " : "",
00111                         pos->num_moves);
00112         *commp = comment;
00113         return over ? RESULT_WON : RESULT_NOTYET;
00114 }
00115 
00116 int hypermaze_canmove (byte *board, int curx, int cury, int incx, int incy)
00117 {
00118         switch (board [(cury + incy/2) * board_wid + curx + incx/2])
00119         {
00120                 case HYPERMAZE_N: if (incx != 0 || incy != 2) return 0; break;
00121                 case HYPERMAZE_S: if (incx != 0 || incy != -2) return 0; break;
00122                 case HYPERMAZE_E: if (incx != 2 || incy != 0) return 0; break;
00123                 case HYPERMAZE_W: if (incx != -2 || incy != 0) return 0; break;
00124                 case HYPERMAZE_NE: if (incx != 2 || incy != 2) return 0; break;
00125                 case HYPERMAZE_NW: if (incx != -2 || incy != 2) return 0; break;
00126                 case HYPERMAZE_SE: if (incx != 2 || incy != -2) return 0; break;
00127                 case HYPERMAZE_SW: if (incx != -2 || incy != -2) return 0; break;
00128                 case HYPERMAZE_WALL: return 0;
00129         }
00130         return 1;
00131 }
00132 
00133 int hypermaze_getmove_common (Pos *pos, byte **movp, 
00134                 int x, int y, int curx, int cury, int incx, int incy)
00135 {
00136         static byte move[10];
00137         if (x < 0 || y < 0 || x >= board_wid || y >= board_heit) return -1;
00138         if (pos->board[y * board_wid + x] == HYPERMAZE_WALL) return -1;
00139         if (!hypermaze_canmove (pos->board, curx, cury, incx, incy)) return -1;
00140         move[0] = curx; move[1] = cury; move[2] = 0;
00141         move[3] = x; move[4] = y; move[5] = HYPERMAZE_CUR;
00142         move[6] = -1;
00143         *movp = move;
00144         return 1;
00145 }
00146 
00147 int hypermaze_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep)
00148 {
00149         int curx = -1, cury = -1;
00150         int incx = -1, incy = -1;
00151         if (type != GTKBOARD_BUTTON_RELEASE)
00152                 return 0;
00153         hypermaze_get_cur_pos (pos->board, &curx, &cury);
00154         g_assert (curx >= 0 && cury >= 0);
00155         if (abs (x - curx) != 2 && abs (x - curx) != 0) return -1;
00156         if (abs (y - cury) != 2 && abs (y - cury) != 0) return -1;
00157         if (abs (x - curx) == 0 && abs (y - cury) == 0) return -1;
00158         return hypermaze_getmove_common (pos, movp, 
00159                         x, y, curx, cury, x - curx, y - cury);
00160         
00161 }
00162 
00163 int hypermaze_getmove_kb (Pos *pos, int key, Player glob_to_play, byte **movp, int **rmovp)
00164 {
00165         //static byte move[10];
00166         int curx = -1, cury = -1;
00167         int incx = -1, incy = -1;
00168         int x, y;
00169         hypermaze_get_cur_pos (pos->board, &curx, &cury);
00170         g_assert (curx >= 0 && cury >= 0);
00171         switch (key)
00172         {
00173                 case GDK_KP_Home: incx = -2; incy = 2; break;
00174                 case GDK_KP_Page_Up: incx = 2; incy = 2; break;
00175                 case GDK_KP_End: incx = -2; incy = -2; break;
00176                 case GDK_KP_Page_Down: incx = 2; incy = -2; break;
00177                 case GDK_Up:
00178                 case GDK_KP_Up: incx = 0; incy = 2; break;
00179                 case GDK_Down:
00180                 case GDK_KP_Down: incx = 0; incy = -2; break;
00181                 case GDK_Right:
00182                 case GDK_KP_Right: incx = 2; incy = 0; break;
00183                 case GDK_Left:
00184                 case GDK_KP_Left: incx = -2; incy = 0; break;
00185                 default: return -1;
00186         }
00187         x = curx + incx;
00188         y = cury + incy;
00189         return hypermaze_getmove_common (pos, movp, x, y, curx, cury, incx, incy);
00190 }
00191 
00192 static void recursive_pathgen (byte *board, int x, int y, int val)
00193 {
00194         static int incx[8] = {-2, 0, 0, 2, -2, -2, 2, 2};
00195         static int incy[8] = {0, -2, 2, 0, -2, 2, -2, 2};
00196 
00197         int i;
00198         if (!ISINBOARD(x, y)) return;
00199         if (board[y * board_wid + x] == val) return;
00200         board [y * board_wid + x] = val;
00201         for (i=0; i<8; i++)
00202                 if (hypermaze_canmove (board, x, y, incx[i], incy[i]))
00203                         recursive_pathgen (board, x+incx[i], y+incy [i], val);
00204 }
00205 
00206 void hypermaze_set_init_pos (Pos *pos)
00207 {
00208         int i, j;
00209         int x, y;
00210         do
00211         {
00212                 for (i=0; i<board_wid; i++)
00213                 for (j=0; j<board_heit; j++)
00214                         if (i % 2 || j % 2)
00215                         {
00216                                 if ((i + j) % 2 == 0)
00217                                         pos->board [j * board_wid + i] = 6 + random() % 4;
00218                                 else
00219                                         pos->board [j * board_wid + i] = 2 + random() % 4;
00220                         }
00221                         else 
00222                                 pos->board [j * board_wid + i] = 0;
00223 
00224                 // edges can't have arbitrary arrows
00225                 for (i=0; i<board_wid; i+=(board_wid-1))
00226                 for (j=1; j<board_heit; j+=2)
00227                         pos->board [j *  board_wid + i] = (random() % 2 ? HYPERMAZE_N : HYPERMAZE_S);
00228                 for (i=1; i<board_wid; i+=2)
00229                 for (j=0; j<board_heit; j+=(board_heit-1))
00230                         pos->board [j *  board_wid + i] = (random() % 2 ? HYPERMAZE_E : HYPERMAZE_W);
00231 
00232                 recursive_pathgen (pos->board, 0, 0, -1);
00233         }
00234         while (pos->board [(board_heit - 1) * board_wid + (board_wid - 1)] != -1);
00235         for (i=0; i<board_wid; i+=2)
00236         for (j=0; j<board_heit; j+=2)
00237                 pos->board [j * board_wid + i] = 0;
00238         pos->board [0] = HYPERMAZE_CUR;
00239 }
00240 
00241 char ** hypermaze_pixmap_square_gen (int idx, char *col)
00242 {
00243         int i, j;
00244         char **pixmap;
00245         char *line = "        ";
00246         pixmap = g_new(char *, HYPERMAZE_CELL_SIZE + 2);
00247         pixmap[0] = "20 20 1 1";
00248         pixmap[1] = g_strdup_printf (" c %s", col);
00249         for (i=0; i<HYPERMAZE_CELL_SIZE; i++) pixmap[i+2] = line; return pixmap;
00250 }
00251 
00252 char ** hypermaze_get_pixmap (int idx, int color)
00253 {
00254         int fg, bg, i;
00255         char *colors = hypermaze_colors;
00256         static char pixbuf[HYPERMAZE_CELL_SIZE * (HYPERMAZE_CELL_SIZE+1)];
00257         for(i=0, bg=0;i<3;i++) 
00258         { int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));}
00259         if (idx == HYPERMAZE_WALL)
00260                 return hypermaze_pixmap_square_gen(idx, "#443333");
00261         if (idx == HYPERMAZE_CUR)
00262                 return pixmap_ball_gen (HYPERMAZE_CELL_SIZE, pixbuf,
00263                         0xffffff, bg, 6, 20);
00264         //      return hypermaze_pixmap_square_gen(idx, "#ff7777");
00265         switch (idx)
00266         {
00267                 case HYPERMAZE_N: return arrow_blue_n_xpm;
00268                 case HYPERMAZE_S: return arrow_blue_s_xpm;
00269                 case HYPERMAZE_E: return arrow_blue_e_xpm;
00270                 case HYPERMAZE_W: return arrow_blue_w_xpm;
00271                 case HYPERMAZE_NE: return arrow_blue_ne_xpm;
00272                 case HYPERMAZE_NW: return arrow_blue_nw_xpm;
00273                 case HYPERMAZE_SW: return arrow_blue_sw_xpm;
00274                 case HYPERMAZE_SE: return arrow_blue_se_xpm;
00275                 default: assert (0);
00276         }
00277 }
00278