~ubuntu-branches/ubuntu/trusty/gcompris/trusty

« back to all changes in this revision

Viewing changes to src/boards/maze.c

  • Committer: Bazaar Package Importer
  • Author(s): Yann Dirson
  • Date: 2002-04-21 16:16:27 UTC
  • Revision ID: james.westby@ubuntu.com-20020421161627-s07yahahm817qxs6
Tags: upstream-1.0.3
ImportĀ upstreamĀ versionĀ 1.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gcompris - maze.c
 
2
 *
 
3
 * Copyright (C) 2002 Bastiaan Verhoef
 
4
 *
 
5
 *   This program is free software; you can redistribute it and/or modify
 
6
 *   it under the terms of the GNU General Public License as published by
 
7
 *   the Free Software Foundation; either version 2 of the License, or
 
8
 *   (at your option) any later version.
 
9
 *
 
10
 *   This program is distributed in the hope that it will be useful,
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *   GNU General Public License for more details.
 
14
 *
 
15
 *   You should have received a copy of the GNU General Public License
 
16
 *   along with this program; if not, write to the Free Software
 
17
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 */
 
19
 
 
20
#include <ctype.h>
 
21
#include <assert.h>
 
22
 
 
23
#include "gcompris/gcompris.h"
 
24
 
 
25
#define SOUNDLISTFILE PACKAGE
 
26
/*-------------------*/
 
27
#define NORTH 1
 
28
#define WEST 2
 
29
#define SOUTH 4
 
30
#define EAST 8
 
31
#define SET 16
 
32
#define BAD 32
 
33
#define DOOR 64
 
34
#define MAX_WIDTH 37
 
35
#define MAX_HEIGHT 20
 
36
#define BASE_X1 50
 
37
#define BASE_Y1 50
 
38
#define BASE_X2 800
 
39
#define BASE_Y2 500
 
40
 
 
41
 
 
42
/* array of the board */
 
43
static int Maze[MAX_WIDTH][MAX_HEIGHT];
 
44
/* historyarray */
 
45
static int pathhistory[MAX_WIDTH*MAX_HEIGHT][2];
 
46
static int p_index=0;
 
47
 
 
48
static int begin;
 
49
static int end; 
 
50
static int width=10;
 
51
static int height=20;
 
52
static int cellsize=20;
 
53
static int buffer=4;
 
54
static int board_border_x=20;
 
55
static int board_border_y=3;
 
56
static int thickness=2;
 
57
static int speed=120;
 
58
static int don=0;
 
59
/*-----------------------*/
 
60
 
 
61
GcomprisBoard *gcomprisBoard = NULL;
 
62
gboolean board_paused = TRUE;
 
63
 
 
64
static void start_board (GcomprisBoard *agcomprisBoard);
 
65
static void pause_board (gboolean pause);
 
66
static void end_board (void);
 
67
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
 
68
static gboolean won=FALSE;
 
69
static gboolean computer_solving=FALSE;
 
70
 
 
71
static void repeat(void);
 
72
static void game_won(gboolean computersolve);
 
73
 
 
74
/* ================================================================ */
 
75
static GnomeCanvasGroup *boardRootItem = NULL;
 
76
static GnomeCanvasGroup *mazegroup = NULL;
 
77
static GnomeCanvasItem *tuxitem = NULL;
 
78
 
 
79
static GnomeCanvasItem *maze_create_item(GnomeCanvasGroup *parent);
 
80
static void maze_destroy_all_items(void);
 
81
static void maze_next_level(void);
 
82
static void set_level (guint level);
 
83
gint key_press(guint keyval);
 
84
/*--------------------*/
 
85
static void draw_a_rect(GnomeCanvasGroup *group, int x1, int y1, int x2, int y2, char *color);
 
86
static void draw_a_line(GnomeCanvasGroup *group, int x1, int y1, int x2, int y2, char *color);
 
87
static GnomeCanvasItem *draw_image(GnomeCanvasGroup *group, int x,int y, GdkPixbuf *pixmap);
 
88
static void move_image(GnomeCanvasGroup *group, int x,int y, GnomeCanvasItem *item);
 
89
static void draw_rect(GnomeCanvasGroup *group, int x,int y,char *color);
 
90
static void draw_combined_rect(GnomeCanvasGroup *group, int x1, int y1, int x2,int y2, char *color);
 
91
static void initMaze(void);
 
92
static int check(int x,int y);
 
93
static int* isPossible(int x, int y);
 
94
static void generateMaze(int x, int y);
 
95
static void removeSet(void);
 
96
static void draw_maze(void);
 
97
static void setlevelproperties(void);
 
98
static void solveMaze(void);
 
99
static gboolean movePos(int x1, int y1, int x2,int y2,gboolean computersolve);
 
100
static int* checkPos(int x, int y);
 
101
static gint solvM(GtkWidget *widget, gpointer data);
 
102
/*----------------------*/
 
103
 
 
104
/* Description of this plugin */
 
105
BoardPlugin menu_bp =
 
106
  {
 
107
    NULL,
 
108
    NULL,
 
109
    N_("maze"),
 
110
    N_("Click on the right color"),
 
111
    "Bastiaan Verhoef <b.f.verhoef@student.utwente.nl>",
 
112
    NULL,
 
113
    NULL,
 
114
    NULL,
 
115
    NULL,
 
116
    start_board,
 
117
    pause_board,
 
118
    end_board,
 
119
    is_our_board,
 
120
    key_press,
 
121
    NULL,
 
122
    set_level,//set_level,
 
123
    NULL,
 
124
    repeat
 
125
  };
 
126
 
 
127
/* =====================================================================
 
128
 *
 
129
 * =====================================================================*/
 
130
BoardPlugin *get_bplugin_info(void) {
 
131
  return &menu_bp;
 
132
}
 
133
 
 
134
/* =====================================================================
 
135
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
 
136
 * =====================================================================*/
 
137
static void pause_board (gboolean pause)
 
138
{
 
139
  if(gcomprisBoard==NULL)
 
140
    return;
 
141
 
 
142
//  if(gamewon == TRUE && pause == FALSE) /* the game is won */
 
143
//      game_won(FALSE);
 
144
 
 
145
  board_paused = pause;
 
146
}
 
147
 
 
148
static void set_level (guint level) {
 
149
  if(gcomprisBoard!=NULL) {
 
150
      gcomprisBoard->level=level;
 
151
      maze_next_level();
 
152
    }
 
153
}
 
154
 
 
155
/* =====================================================================
 
156
 *
 
157
 * =====================================================================*/
 
158
static void start_board (GcomprisBoard *agcomprisBoard) {
 
159
 
 
160
  if(agcomprisBoard!=NULL) {
 
161
      gcomprisBoard=agcomprisBoard;
 
162
      gcompris_set_background(gnome_canvas_root(gcomprisBoard->canvas), "gcompris/gcompris-bg.jpg");
 
163
      gcomprisBoard->level=1;
 
164
      gcomprisBoard->maxlevel=9;
 
165
      gcompris_bar_set(GCOMPRIS_BAR_LEVEL|GCOMPRIS_BAR_REPEAT);
 
166
 
 
167
                maze_next_level();
 
168
      pause_board(FALSE);
 
169
    }
 
170
}
 
171
 
 
172
/* =====================================================================
 
173
 *
 
174
 * =====================================================================*/
 
175
static void end_board () {
 
176
 
 
177
  if(gcomprisBoard!=NULL){
 
178
      pause_board(TRUE);
 
179
      gcompris_score_end();
 
180
      maze_destroy_all_items();
 
181
  }
 
182
  gcomprisBoard = NULL;
 
183
}
 
184
 
 
185
/* =====================================================================
 
186
 *
 
187
 * =====================================================================*/
 
188
gboolean is_our_board (GcomprisBoard *gcomprisBoard) {
 
189
        if (gcomprisBoard) {
 
190
      if(g_strcasecmp(gcomprisBoard->type, "maze")==0) {
 
191
                        /* Set the plugin entry */
 
192
                        gcomprisBoard->plugin=&menu_bp;
 
193
                        return TRUE;
 
194
                        }
 
195
  }
 
196
  return FALSE;
 
197
}
 
198
/* =====================================================================
 
199
 * set initial values for the next level
 
200
 * =====================================================================*/
 
201
static void maze_next_level() {
 
202
        GdkPixbuf *pixmap = NULL;       
 
203
        if (!computer_solving)
 
204
        {
 
205
                maze_destroy_all_items();
 
206
                gcompris_bar_set_level(gcomprisBoard);
 
207
                setlevelproperties();
 
208
                
 
209
                /* generate maze */
 
210
                initMaze();
 
211
                generateMaze((random()%width),(random()%height));
 
212
                removeSet();    
 
213
                
 
214
                /* Try the next level */
 
215
                maze_create_item(gnome_canvas_root(gcomprisBoard->canvas));
 
216
                draw_maze();
 
217
                
 
218
                /* make a new group for the items */
 
219
                begin=random()%height;
 
220
                end=random()%height;
 
221
                
 
222
                /* Draw the tux */
 
223
                pixmap = gcompris_load_pixmap("gcompris/misc/tux.png");
 
224
                if(pixmap)
 
225
                  {
 
226
                        tuxitem = draw_image(mazegroup,0,begin,pixmap);
 
227
                        gdk_pixbuf_unref(pixmap);
 
228
                  }
 
229
                
 
230
                /* Draw the target */
 
231
                pixmap = gcompris_load_pixmap("gcompris/misc/door.png");
 
232
                if(pixmap)
 
233
                  {
 
234
                        draw_image(mazegroup,width-1,end,pixmap);
 
235
                        gdk_pixbuf_unref(pixmap);
 
236
                  }
 
237
                pathhistory[p_index][0]=0;
 
238
                pathhistory[p_index][1]=begin;
 
239
                Maze[0][begin]=Maze[0][begin]+SET;      
 
240
                Maze[width-1][end]=Maze[width-1][end]+DOOR;
 
241
          }
 
242
}
 
243
/* ======================================= */
 
244
static void setlevelproperties(){
 
245
        if (gcomprisBoard->level==1)
 
246
        {
 
247
                width=5;
 
248
                height=4;
 
249
                cellsize=70;
 
250
                buffer=8;
 
251
                
 
252
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
253
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;
 
254
        }
 
255
        else if (gcomprisBoard->level==2)
 
256
        {
 
257
                
 
258
                width=9;
 
259
                height=6;
 
260
                cellsize=70;
 
261
                buffer=7;
 
262
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
263
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;               
 
264
        }       
 
265
        else if (gcomprisBoard->level==3)
 
266
        {
 
267
                width=13;
 
268
                height=8;
 
269
                cellsize=60;
 
270
                buffer=6;
 
271
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
272
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;               
 
273
        }       
 
274
        else if (gcomprisBoard->level==4)
 
275
        {
 
276
                width=17;
 
277
                height=10;
 
278
                cellsize=45;
 
279
                buffer=5;
 
280
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
281
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;               
 
282
        }
 
283
        else if (gcomprisBoard->level==5)
 
284
        {
 
285
                width=21;
 
286
                height=12;
 
287
                cellsize=35;            
 
288
                buffer=4;
 
289
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
290
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;               
 
291
        }
 
292
        else if (gcomprisBoard->level==6)
 
293
        {
 
294
                width=25;
 
295
                height=14;
 
296
                cellsize=30;            
 
297
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
298
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;
 
299
        }       
 
300
        else if (gcomprisBoard->level==7)
 
301
        {
 
302
                width=29;
 
303
                height=16;
 
304
                cellsize=25;            
 
305
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
306
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;               
 
307
        }       
 
308
        else if (gcomprisBoard->level==8)
 
309
        {
 
310
                width=33;
 
311
                height=18;
 
312
                cellsize=23;            
 
313
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
314
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;               
 
315
        }       
 
316
        else if (gcomprisBoard->level==9)
 
317
        {
 
318
                width=37;
 
319
                height=20;
 
320
                cellsize=20;            
 
321
                board_border_x=(int) (BASE_X2-width*cellsize)/2;
 
322
                board_border_y=(int) (BASE_Y2-height*cellsize)/2;               
 
323
        }               
 
324
}
 
325
/* =====================================================================
 
326
 * Destroy all the items
 
327
 * =====================================================================*/
 
328
static void maze_destroy_all_items() {
 
329
        if (mazegroup!=NULL)
 
330
                gtk_object_destroy (GTK_OBJECT(mazegroup));
 
331
        if(boardRootItem!=NULL)
 
332
                gtk_object_destroy (GTK_OBJECT(boardRootItem));
 
333
        mazegroup = NULL;
 
334
        boardRootItem = NULL;
 
335
        
 
336
 
 
337
}
 
338
 
 
339
/* =====================================================================
 
340
 *
 
341
 * =====================================================================*/
 
342
static GnomeCanvasItem *maze_create_item(GnomeCanvasGroup *parent) {
 
343
        boardRootItem = GNOME_CANVAS_GROUP(
 
344
                                     gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
 
345
                                                            gnome_canvas_group_get_type (),
 
346
                                                            "x", (double) 0,
 
347
                                                            "y", (double) 0,
 
348
                                                            NULL));
 
349
        mazegroup=GNOME_CANVAS_GROUP(gnome_canvas_item_new(boardRootItem,
 
350
                                     gnome_canvas_group_get_type(),
 
351
                                     "x",(double)width,
 
352
                                     "y",(double)height,
 
353
                                     NULL));
 
354
 
 
355
  return NULL;
 
356
}
 
357
/* =====================================================================
 
358
 *
 
359
 * =====================================================================*/
 
360
static void game_won(gboolean computersolve) {
 
361
        gcompris_play_sound (SOUNDLISTFILE, "bonus");
 
362
  /* Try the next level */
 
363
        if (!computersolve)
 
364
                gcomprisBoard->level++;
 
365
        else computer_solving=FALSE;
 
366
        if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
 
367
                board_finished(BOARD_FINISHED_RANDOM);
 
368
                return;
 
369
        }
 
370
        maze_next_level();
 
371
}
 
372
/* =====================================================================
 
373
 *
 
374
 * =====================================================================*/
 
375
static void repeat() {
 
376
        if (!computer_solving)
 
377
        {
 
378
                won=FALSE;
 
379
                computer_solving=TRUE;
 
380
                don = gtk_timeout_add (speed, (GtkFunction) solvM, NULL);
 
381
        }
 
382
}
 
383
 
 
384
/* =====================================================================
 
385
 * Draw a rectangle
 
386
 * =====================================================================*/
 
387
static void draw_a_rect(GnomeCanvasGroup *group, int x1, int y1, int x2, int y2, char *color)
 
388
{
 
389
        if (group!=NULL)
 
390
                gnome_canvas_item_show(gnome_canvas_item_new(group,gnome_canvas_rect_get_type(),
 
391
                                          "x1",(double)x1,
 
392
                                          "y1",(double)y1,
 
393
                                          "x2",(double)x2,
 
394
                                          "y2",(double)y2,
 
395
                                                "fill_color", color,
 
396
                                          NULL));
 
397
}
 
398
 
 
399
/* =====================================================================
 
400
 * Draw a line
 
401
 * =====================================================================*/
 
402
static void draw_a_line(GnomeCanvasGroup *group, int x1, int y1, int x2, int y2, char *color)
 
403
{
 
404
        GnomeCanvasPoints *points;
 
405
        if (group!=NULL)
 
406
        {       
 
407
                        points = gnome_canvas_points_new (2);
 
408
                
 
409
                        points->coords[0] = x1;
 
410
                        points->coords[1] = y1;
 
411
                        points->coords[2] = x2;
 
412
                        points->coords[3] = y2;
 
413
                        gnome_canvas_item_new(group,
 
414
                                                  gnome_canvas_line_get_type(),
 
415
                                                  "points", points,
 
416
                                                  "fill_color", color,
 
417
                                                  "width_units", (double)thickness,
 
418
                                                  NULL);
 
419
                
 
420
                        gnome_canvas_points_free(points);
 
421
        }
 
422
}
 
423
 
 
424
/* =====================================================================
 
425
 * Draw a rectangle on the right position
 
426
 * =====================================================================*/
 
427
static void draw_rect(GnomeCanvasGroup *group, int x,int y,char *color)
 
428
{
 
429
        int x1,y1;
 
430
        if (group!=NULL)
 
431
        {
 
432
                y1=cellsize*(y)-height + board_border_y;
 
433
                x1=cellsize*(x)-width + board_border_x;
 
434
                draw_a_rect(group,x1+buffer,y1+buffer ,x1+cellsize-buffer ,y1+cellsize-buffer ,color);
 
435
        }
 
436
}
 
437
 
 
438
/* =====================================================================
 
439
 * Combines rectangles
 
440
 * =====================================================================*/
 
441
static void draw_combined_rect(GnomeCanvasGroup *group, int x1,int y1,int x2,int y2,char *color)
 
442
{
 
443
        int xx1,yy1,xx2,yy2;
 
444
        if (group!=NULL)
 
445
        {
 
446
                yy1=cellsize*(y1)-height + board_border_y;
 
447
                xx1=cellsize*(x1)-width + board_border_x;
 
448
                yy2=cellsize*(y2)-height + board_border_y;
 
449
                xx2=cellsize*(x2)-width + board_border_x;
 
450
                if (y1==y2 && x1<x2)
 
451
                {
 
452
                        draw_a_rect(group,xx1+cellsize-buffer,yy1+buffer,xx2+buffer,yy2+cellsize-buffer,color);
 
453
                }
 
454
                else if (y1==y2 && x1>x2)
 
455
                {
 
456
                        draw_a_rect(group,xx2+cellsize-buffer,yy2+buffer,xx1+buffer,yy1+cellsize-buffer,color);         
 
457
                }
 
458
                else if (x1==x2 && y1<y2)
 
459
                {
 
460
                        draw_a_rect(group,xx1+buffer,yy1+cellsize-buffer,xx2+cellsize-buffer,yy2+buffer,color);
 
461
                }
 
462
                else if (x1==x2 && y1>y2)
 
463
                {
 
464
                        draw_a_rect(group,xx2+buffer,yy2+cellsize-buffer,xx1+cellsize-buffer,yy1+buffer,color);
 
465
                }
 
466
        }
 
467
 
 
468
}
 
469
 
 
470
/* =====================================================================
 
471
 * Draw a image
 
472
 * =====================================================================*/
 
473
static GnomeCanvasItem *draw_image(GnomeCanvasGroup *group, int x,int y, GdkPixbuf *pixmap)
 
474
{
 
475
        GnomeCanvasItem *item = NULL;
 
476
        int x1,y1;
 
477
        if (group!=NULL)
 
478
        {
 
479
                y1=cellsize*(y)-height + board_border_y;
 
480
                x1=cellsize*(x)-width + board_border_x;
 
481
        
 
482
                item = gnome_canvas_item_new (group,
 
483
                                                  gnome_canvas_pixbuf_get_type (),
 
484
                                                  "pixbuf", pixmap, 
 
485
                                                  "x",  (double)x1+buffer,
 
486
                                                  "y",  (double)y1+buffer,
 
487
                                                  "width",      (double)cellsize-buffer*2,
 
488
                                                  "height",(double)cellsize-buffer*2,
 
489
                                                  "width_set", TRUE, 
 
490
                                                  "height_set", TRUE,
 
491
                                                  NULL);
 
492
        
 
493
                return(item);
 
494
        }
 
495
        else return NULL;
 
496
}
 
497
 
 
498
/*
 
499
 * Same as draw rect but for an image
 
500
 */
 
501
static void move_image(GnomeCanvasGroup *group, int x,int y, GnomeCanvasItem *item)
 
502
{
 
503
        int x1,y1;
 
504
        if (group!=NULL)
 
505
        {
 
506
                y1=cellsize*(y)-height + board_border_y;
 
507
                x1=cellsize*(x)-width + board_border_x;
 
508
        
 
509
                gnome_canvas_item_set (item,
 
510
                                           "x", (double)x1+buffer,
 
511
                                           "y", (double)y1+buffer,
 
512
                                           NULL);
 
513
                gnome_canvas_item_raise_to_top(item);
 
514
        }
 
515
}
 
516
 
 
517
/* =====================================================================
 
518
 * Init of the mazeboard.
 
519
 * set initvalue to 15= NORTH+SOUTH+WEST+EAST
 
520
 * So each cell in the bord have four walls
 
521
 * =====================================================================*/
 
522
static void initMaze(void)
 
523
{
 
524
        int x,y;
 
525
        for (x=0; x<width;x++)
 
526
        {
 
527
            for (y=0; y <height; y++)
 
528
            {
 
529
                        Maze[x][y]=15;
 
530
            }
 
531
        }
 
532
}
 
533
 
 
534
/* =====================================================================
 
535
 * Draw the maze
 
536
 * =====================================================================*/
 
537
static void draw_maze(void)
 
538
{
 
539
        int x,y,x1,y1;
 
540
        int wall;
 
541
        /*draw the lines*/
 
542
        for (x1=0; x1< width; x1++)
 
543
        {
 
544
            for (y1=0; y1 < height; y1++)
 
545
            {
 
546
                        wall=Maze[x1][y1];;
 
547
                        y=cellsize*(y1)+board_border_y;
 
548
                        x=cellsize*(x1)+board_border_x;
 
549
                        if (x1==0)
 
550
                                draw_a_line(boardRootItem,x, y, x, y+cellsize, "black");
 
551
 
 
552
                        if (y1==0)
 
553
                                draw_a_line(boardRootItem,x, y, x+cellsize, y, "black");
 
554
                        if ((wall-EAST>=0))
 
555
                        {
 
556
                                draw_a_line(boardRootItem,x+cellsize, y, x+cellsize, y+cellsize, "black");                      
 
557
                                wall=wall-EAST;
 
558
                        }
 
559
 
 
560
                        if ((wall-SOUTH)>=0)
 
561
                        {
 
562
                                draw_a_line(boardRootItem,x, y+cellsize, x+cellsize, y+cellsize, "black");
 
563
                                wall=wall-SOUTH;
 
564
                        }
 
565
 
 
566
            }
 
567
        }
 
568
}
 
569
 
 
570
static int check(int x,int y)
 
571
{
 
572
        if ((Maze[x][y]-DOOR)>=0)
 
573
        {
 
574
                return 2;
 
575
        }
 
576
        if ((Maze[x][y]-BAD)>=0)
 
577
                return 1;
 
578
        if ((Maze[x][y]-SET)>=0)
 
579
            return 1;
 
580
        else return 0;
 
581
}
 
582
/* =====================================================================
 
583
 * checks what are the possibilities to move
 
584
 * =====================================================================*/    
 
585
static int* isPossible(int x, int y)
 
586
{
 
587
        int wall=Maze[x][y];
 
588
        int pos[5];
 
589
        wall=wall-SET;
 
590
        pos[0]=0;
 
591
        if(x==0)
 
592
        {
 
593
            wall=wall-WEST;
 
594
        }
 
595
        if (y==0)
 
596
        {
 
597
            wall=wall-NORTH;
 
598
        }
 
599
        if(x==(width-1))
 
600
        {
 
601
            wall=wall-EAST;
 
602
        }
 
603
        if (y==(height-1))
 
604
        {
 
605
            wall=wall-SOUTH;
 
606
        }
 
607
        if (wall-EAST>=0)
 
608
        {
 
609
            if(check(x+1,y)==0)
 
610
            {
 
611
                        pos[0]=pos[0]+1;
 
612
                        pos[(pos[0])]=EAST;
 
613
            }
 
614
            wall=wall-EAST;
 
615
        }
 
616
        if (wall-SOUTH>=0)
 
617
        {
 
618
            if (check(x,y+1)==0)
 
619
            {
 
620
                        pos[0]=pos[0]+1;
 
621
                        pos[(pos[0])]=SOUTH;
 
622
            }
 
623
            wall=wall-SOUTH;
 
624
        }
 
625
        if (wall-WEST>=0)
 
626
        {
 
627
            if (check(x-1,y)==0)
 
628
            {
 
629
                        pos[0]=pos[0]+1;
 
630
                        pos[(pos[0])]=WEST;
 
631
            }
 
632
            wall=wall-WEST;
 
633
        }
 
634
        if (wall-NORTH>=0)
 
635
        {
 
636
            if (check(x,y-1)==0)
 
637
            {
 
638
                        pos[0]=pos[0]+1;
 
639
                        pos[(pos[0])]=NORTH;
 
640
            }
 
641
            wall=wall-NORTH;
 
642
        }
 
643
        return &pos[0];
 
644
}
 
645
 
 
646
/* =====================================================================
 
647
 * Generate a maze
 
648
 * =====================================================================*/
 
649
static void generateMaze(int x, int y)
 
650
{
 
651
        int *possible;
 
652
        Maze[x][y]= Maze[x][y] + SET;
 
653
        possible = isPossible(x,y);
 
654
        while (*possible>0)
 
655
        {
 
656
            int nr = *possible;
 
657
            int ran, in;
 
658
            in=(random()%nr)+1;
 
659
            ran=*(possible + in);
 
660
            if (nr>=1)
 
661
                        switch (ran)
 
662
                        {
 
663
                        case EAST:
 
664
                                Maze[x][y]=Maze[x][y]-EAST;
 
665
                                Maze[x+1][y]=Maze[x+1][y]-WEST;
 
666
                                generateMaze(x+1,y);
 
667
                                break;
 
668
                        case SOUTH:
 
669
                                Maze[x][y]=Maze[x][y]-SOUTH;
 
670
                                Maze[x][y+1]=Maze[x][y+1]-NORTH;
 
671
                                generateMaze(x,y+1);
 
672
                                break;
 
673
                        case WEST:
 
674
                                Maze[x][y]=Maze[x][y]-WEST;
 
675
                                Maze[x-1][y]=Maze[x-1][y]-EAST;         
 
676
                                generateMaze(x-1,y);
 
677
                                break;
 
678
                        case NORTH:
 
679
                                Maze[x][y]=Maze[x][y]-NORTH;
 
680
                                Maze[x][y-1]=Maze[x][y-1]-SOUTH;
 
681
                                generateMaze(x,y-1);
 
682
                                break;
 
683
                        
 
684
                        }
 
685
                possible=isPossible(x,y);
 
686
        }
 
687
 
 
688
}
 
689
 
 
690
static int* checkPos(int x, int y)
 
691
{
 
692
        int wall=Maze[x][y];
 
693
        gboolean found_door=FALSE;
 
694
        int pos[5];
 
695
        wall=wall-SET;
 
696
        pos[0]=0;
 
697
        if (wall-EAST>=0)
 
698
                wall=wall-EAST;
 
699
        else 
 
700
        {
 
701
                if(check(x+1,y)==0)
 
702
                {
 
703
                        pos[0]=pos[0]+1;
 
704
                        pos[(pos[0])]=EAST;
 
705
                }
 
706
                else if(check(x+1,y)==2)
 
707
                {
 
708
                        pos[0]=1;
 
709
                        pos[1]=EAST;
 
710
                        found_door=TRUE;
 
711
                }               
 
712
        }
 
713
        if (wall-SOUTH>=0)
 
714
            wall=wall-SOUTH;
 
715
        else
 
716
        {
 
717
            if (check(x,y+1)==0)
 
718
            {           
 
719
                        pos[0]=pos[0]+1;
 
720
                        pos[(pos[0])]=SOUTH;
 
721
                }
 
722
                else if(check(x,y+1)==2)
 
723
                {
 
724
                        pos[0]=1;
 
725
                        pos[1]=SOUTH;
 
726
                        found_door=TRUE;
 
727
                }                       
 
728
        }
 
729
        if (wall-WEST>=0)
 
730
            wall=wall-WEST;
 
731
        else
 
732
        {
 
733
                if(check(x-1,y)==0)
 
734
                {
 
735
                        pos[0]=pos[0]+1;
 
736
                        pos[(pos[0])]=WEST;             
 
737
                }
 
738
                else if(check(x-1,y)==2)
 
739
                {
 
740
                        pos[0]=1;
 
741
                        pos[1]=WEST;
 
742
                        found_door=TRUE;
 
743
                }                       
 
744
        }
 
745
        if (wall-NORTH>=0)
 
746
            wall=wall-NORTH;
 
747
        else
 
748
        {
 
749
            if (check(x,y-1)==0)
 
750
                {
 
751
                        pos[0]=pos[0]+1;
 
752
                        pos[(pos[0])]=NORTH;
 
753
                }
 
754
                else if(check(x,y-1)==2)
 
755
                {
 
756
                        pos[0]=1;
 
757
                        pos[1]=NORTH;
 
758
                        found_door=TRUE;
 
759
                }                       
 
760
        }
 
761
        if (found_door)
 
762
                pos[0]=1;
 
763
        return &pos[0];
 
764
}
 
765
 
 
766
static gint solvM(GtkWidget *widget, gpointer data)
 
767
{
 
768
        solveMaze();
 
769
        if (!won && mazegroup!=NULL)
 
770
                don = gtk_timeout_add (speed, (GtkFunction) solvM, NULL);       
 
771
  return FALSE;
 
772
}
 
773
 
 
774
/* =====================================================================
 
775
 * computersolving algoritme
 
776
 * =====================================================================*/
 
777
static void solveMaze()
 
778
{
 
779
        int *possible;
 
780
        possible = checkPos(pathhistory[p_index][0],pathhistory[p_index][1]);
 
781
        if (*possible>0 && !won)
 
782
        {
 
783
            int nr = *possible;
 
784
            int ran, in;
 
785
            in=(random()%nr)+1;
 
786
            ran=*(possible+in);
 
787
            if (nr>=1)
 
788
                        switch (ran)
 
789
                        {
 
790
                        case EAST:
 
791
 
 
792
                                movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0]+1,pathhistory[p_index][1],TRUE);
 
793
                                break;
 
794
                        case SOUTH:
 
795
                                movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0],pathhistory[p_index][1]+1,TRUE);
 
796
                                break;
 
797
                        case WEST:
 
798
                                movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0]-1,pathhistory[p_index][1],TRUE);
 
799
                                break;
 
800
                        case NORTH:
 
801
                                movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0],pathhistory[p_index][1]-1,TRUE);
 
802
                                break;
 
803
                        }
 
804
                possible=checkPos(pathhistory[p_index][0],pathhistory[p_index][1]);
 
805
        }
 
806
        else 
 
807
                movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index-1][0],pathhistory[p_index-1][1],TRUE);
 
808
}
 
809
 
 
810
static void removeSet(void)
 
811
{
 
812
        int x,y;
 
813
        for (x=0; x< width;x++)
 
814
        {
 
815
            for (y=0; y < height; y++)
 
816
            {
 
817
                if (Maze[x][y]>=16)
 
818
                    Maze[x][y]=Maze[x][y]-SET;
 
819
            }
 
820
        }
 
821
}
 
822
 
 
823
/* =====================================================================
 
824
 * move from position (x1,y1) to (x2,y2) if possible
 
825
 * =====================================================================*/
 
826
static gboolean movePos(int x1, int y1, int x2,int y2, gboolean computersolve)
 
827
{
 
828
        int direction,wall,i;
 
829
        gboolean pos_to_move,found_cycle;
 
830
        found_cycle=FALSE;
 
831
        direction=0;
 
832
        pos_to_move=TRUE;
 
833
        wall=Maze[x1][y1];
 
834
        /* looking for what is the direction */
 
835
        if (x1==x2 && y1>y2)
 
836
        {       
 
837
                direction=NORTH;
 
838
        }
 
839
        if (x1==x2 && y1<y2)
 
840
        {       
 
841
                direction=SOUTH;
 
842
        }
 
843
        if (x1>x2 && y1==y2)
 
844
        {
 
845
                direction=WEST;
 
846
        }
 
847
        if (x1<x2 && y1==y2)
 
848
        {
 
849
                direction=EAST;
 
850
        }
 
851
        if((wall-SET)>=0)
 
852
        {
 
853
                wall=wall-SET;
 
854
        }
 
855
        
 
856
        /* check if move to that direction is possible */
 
857
        if((wall-EAST)>=0)
 
858
        {
 
859
                wall=wall-EAST;
 
860
                if (direction==EAST)
 
861
                        pos_to_move=FALSE;
 
862
        }
 
863
        if((wall-SOUTH)>=0)
 
864
        {
 
865
                wall=wall-SOUTH;
 
866
                if (direction==SOUTH)
 
867
                        pos_to_move=FALSE;
 
868
        }
 
869
        if((wall-WEST)>=0)
 
870
        {
 
871
                wall=wall-WEST;
 
872
                if (direction==WEST)
 
873
                        pos_to_move=FALSE;
 
874
        }
 
875
        if((wall-NORTH)>=0)
 
876
        {
 
877
                wall=wall-NORTH;
 
878
                if (direction==NORTH)
 
879
                        pos_to_move=FALSE;
 
880
        }
 
881
        /* move position */
 
882
        if (pos_to_move)
 
883
        {
 
884
                if (Maze[x2][y2]-DOOR>=0)
 
885
                {
 
886
                        if (computersolve)
 
887
                        {
 
888
                                won=TRUE;
 
889
                                gtk_timeout_remove(don);
 
890
                                game_won(computersolve);
 
891
                        }
 
892
                        else
 
893
                                game_won(FALSE);
 
894
                }
 
895
                else if (Maze[x2][y2]-SET>=0)
 
896
                {
 
897
                        for (i=(p_index); i>=0 && !found_cycle; i--)
 
898
                        {
 
899
 
 
900
                                if(pathhistory[i][0]==x2 && pathhistory[i][1]==y2)
 
901
                                {       
 
902
                                        found_cycle=TRUE;
 
903
                                        move_image(mazegroup,x2,y2,tuxitem);
 
904
                                }
 
905
                                else
 
906
                                {
 
907
                                        Maze[pathhistory[i][0]][pathhistory[i][1]]=Maze[pathhistory[i][0]][pathhistory[i][1]]-SET;
 
908
                                        draw_rect(mazegroup,pathhistory[i][0],pathhistory[i][1],"red");
 
909
                                        Maze[pathhistory[i][0]][pathhistory[i][1]]=Maze[pathhistory[i][0]][pathhistory[i][1]]+BAD;
 
910
                                        draw_combined_rect(mazegroup,pathhistory[i-1][0],pathhistory[i-1][1],pathhistory[i][0],pathhistory[i][1],"red");
 
911
                                        p_index--;
 
912
                                }
 
913
                                
 
914
                                
 
915
                        }
 
916
                }
 
917
                else
 
918
                {
 
919
                        p_index++;
 
920
                        pathhistory[p_index][0]=x2;
 
921
                        pathhistory[p_index][1]=y2;
 
922
                        Maze[x2][y2]=Maze[x2][y2]+SET;
 
923
                        move_image(mazegroup,x2,y2,tuxitem);
 
924
                        draw_combined_rect(mazegroup,x1,y1,x2,y2,"green");
 
925
                        draw_rect(mazegroup,x1,y1,"green");
 
926
                }
 
927
                return TRUE;
 
928
        }
 
929
        else
 
930
                return FALSE;
 
931
        
 
932
}
 
933
 
 
934
 
 
935
gint key_press(guint keyval){
 
936
 
 
937
        if ( keyval== GDK_Left)
 
938
        {
 
939
                if (!computer_solving)
 
940
                        movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0]-1,pathhistory[p_index][1],FALSE);
 
941
                return TRUE;
 
942
        }
 
943
        else if (keyval==GDK_Right)
 
944
        {
 
945
                if (!computer_solving)
 
946
                        movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0]+1,pathhistory[p_index][1],FALSE);
 
947
                return TRUE;            
 
948
        }
 
949
        else if (keyval==GDK_Up)
 
950
        {
 
951
                if (!computer_solving)
 
952
                        movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0],pathhistory[p_index][1]-1,FALSE);
 
953
                return TRUE;            
 
954
        }
 
955
        else if (keyval==GDK_Down)
 
956
        {
 
957
                if (!computer_solving)
 
958
                        movePos(pathhistory[p_index][0],pathhistory[p_index][1],pathhistory[p_index][0],pathhistory[p_index][1]+1,FALSE);
 
959
                return TRUE;            
 
960
        }
 
961
  return FALSE;
 
962
}