Simple maze demo
authorGé van Geldorp <ge@gse.nl>
Fri, 15 Aug 2003 17:06:49 +0000 (17:06 +0000)
committerGé van Geldorp <ge@gse.nl>
Fri, 15 Aug 2003 17:06:49 +0000 (17:06 +0000)
svn path=/trunk/; revision=5590

rosapps/demos/maze/.cvsignore [new file with mode: 0644]
rosapps/demos/maze/Makefile [new file with mode: 0644]
rosapps/demos/maze/maze.c [new file with mode: 0644]
rosapps/demos/maze/maze.rc [new file with mode: 0644]
rosapps/demos/maze/resource.h [new file with mode: 0644]

diff --git a/rosapps/demos/maze/.cvsignore b/rosapps/demos/maze/.cvsignore
new file mode 100644 (file)
index 0000000..a33442c
--- /dev/null
@@ -0,0 +1,7 @@
+maze.exe
+maze.nostrip.exe
+maze.sym
+maze.coff
+.*.d
+*.o
+*.map
diff --git a/rosapps/demos/maze/Makefile b/rosapps/demos/maze/Makefile
new file mode 100644 (file)
index 0000000..daa885e
--- /dev/null
@@ -0,0 +1,25 @@
+# $Id: Makefile,v 1.1 2003/08/15 17:06:49 gvg Exp $
+
+PATH_TO_TOP = ../../../reactos
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = windows
+
+TARGET_NAME = maze
+
+TARGET_SDKLIBS = kernel32.a gdi32.a
+
+TARGET_OBJECTS = maze.o
+
+TARGET_CFLAGS = -Wall -Werror
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# Automatic dependency tracking
+DEP_OBJECTS := $(TARGET_OBJECTS)
+include $(PATH_TO_TOP)/tools/depend.mk
+
+# EOF
diff --git a/rosapps/demos/maze/maze.c b/rosapps/demos/maze/maze.c
new file mode 100644 (file)
index 0000000..31e561a
--- /dev/null
@@ -0,0 +1,907 @@
+/******************************************************************************
+ * [ maze ] ...
+ *
+ * modified:  [ 03-08-15 ] Ge van Geldorp <ge@gse.nl>
+ *             ported to Reactos
+ * modified:  [ 94-10-8 ] Ge van Geldorp <Ge.vanGeldorp@lr.tudelft.nl>
+ *             ported to MS Windows
+ * modified:  [ 3-7-93 ]  Jamie Zawinski <jwz@lucid.com>
+ *             added the XRoger logo, cleaned up resources, made
+ *             grid size a parameter.
+ * modified:  [ 3-3-93 ]  Jim Randell <jmr@mddjmr.fc.hp.com>
+ *             Added the colour stuff and integrated it with jwz's
+ *             screenhack stuff.  There's still some work that could
+ *             be done on this, particularly allowing a resource to
+ *             specify how big the squares are.
+ * modified:  [ 10-4-88 ]  Richard Hess    ...!uunet!cimshop!rhess  
+ *              [ Revised primary execution loop within main()...
+ *              [ Extended X event handler, check_events()...
+ * modified:  [ 1-29-88 ]  Dave Lemke      lemke@sun.com  
+ *              [ Hacked for X11...
+ *              [  Note the word "hacked" -- this is extremely ugly, but at 
+ *              [   least it does the job.  NOT a good programming example 
+ *              [   for X.
+ * original:  [ 6/21/85 ]  Martin Weiss    Sun Microsystems  [ SunView ]
+ *
+ ******************************************************************************
+ Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
+  
+ All Rights Reserved
+  
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, 
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in 
+ supporting documentation, and that the names of Sun or MIT not be
+ used in advertising or publicity pertaining to distribution of the
+ software without specific prior written permission. Sun and M.I.T. 
+ make no representations about the suitability of this software for 
+ any purpose. It is provided "as is" without any express or implied warranty.
+ SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT
+ OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ OR PERFORMANCE OF THIS SOFTWARE.
+ *****************************************************************************/
+
+#define STRICT
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <windows.h>           /* required for all Windows applications */
+
+#if !defined (APIENTRY) /* Windows NT defines APIENTRY, but 3.x doesn't */
+#define APIENTRY far pascal
+#endif
+
+#if !defined(WIN32)            /* Windows 3.x uses a FARPROC for dialogs */
+#define DLGPROC FARPROC
+#endif
+
+static BOOL InitApplication(HINSTANCE hInstance);
+static BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM uParam,
+                         LPARAM lParam);
+
+HINSTANCE hInst;               /* current instance */
+HWND      hWnd;                        /* Main window handle.*/
+HBRUSH hBrushDead;
+HBRUSH hBrushLiving;
+HDC    hDC;
+static BOOL waiting;
+
+
+char szAppName[] = "Maze";  /* The name of this application */
+char szTitle[]   = "Maze";     /* The title bar text */
+
+static int solve_delay, pre_solve_delay, post_solve_delay;
+
+#define MAX_MAZE_SIZE_X        ((unsigned long) 250)
+#define MAX_MAZE_SIZE_Y        ((unsigned long) 250)
+
+#define MOVE_LIST_SIZE  (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
+
+#define WALL_TOP       0x8000
+#define WALL_RIGHT     0x4000
+#define WALL_BOTTOM    0x2000
+#define WALL_LEFT      0x1000
+
+#define DOOR_IN_TOP    0x800
+#define DOOR_IN_RIGHT  0x400
+#define DOOR_IN_BOTTOM 0x200
+#define DOOR_IN_LEFT   0x100
+#define DOOR_IN_ANY    0xF00
+
+#define DOOR_OUT_TOP   0x80
+#define DOOR_OUT_RIGHT 0x40
+#define DOOR_OUT_BOTTOM        0x20
+#define DOOR_OUT_LEFT  0x10
+
+#define START_SQUARE   0x2
+#define END_SQUARE     0x1
+
+#define        border_x        (0)
+#define        border_y        (0)
+
+#define        get_random(x)   (rand() % (x))
+
+static unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
+
+static struct {
+  unsigned char x;
+  unsigned char y;
+  unsigned char dir;
+  unsigned char dummy;  
+} move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
+
+static int maze_size_x, maze_size_y;
+static long sqnum, path_length;
+static int cur_sq_x, cur_sq_y;
+static int start_x, start_y, start_dir, end_x, end_y, end_dir;
+static int grid_width, grid_height;
+
+static int state = 1, pathi = 0;
+
+static void
+set_maze_sizes (width, height)
+     int width, height;
+{
+  maze_size_x = width / grid_width;
+  maze_size_y = height / grid_height;
+}
+
+
+static void
+initialize_maze()         /* draw the surrounding wall and start/end squares */
+{
+  register int i, j, wall;
+  
+  /* initialize all squares */
+  for ( i=0; i<maze_size_x; i++) {
+    for ( j=0; j<maze_size_y; j++) {
+      maze[i][j] = 0;
+    }
+  }
+  
+  /* top wall */
+  for ( i=0; i<maze_size_x; i++ ) {
+    maze[i][0] |= WALL_TOP;
+  }
+  
+  /* right wall */
+  for ( j=0; j<maze_size_y; j++ ) {
+    maze[maze_size_x-1][j] |= WALL_RIGHT;
+  }
+  
+  /* bottom wall */
+  for ( i=0; i<maze_size_x; i++ ) {
+    maze[i][maze_size_y-1] |= WALL_BOTTOM;
+  }
+  
+  /* left wall */
+  for ( j=0; j<maze_size_y; j++ ) {
+    maze[0][j] |= WALL_LEFT;
+  }
+  
+  /* set start square */
+  wall = get_random(4);
+  switch (wall) {
+  case 0:      
+    i = get_random(maze_size_x);
+    j = 0;
+    break;
+  case 1:      
+    i = maze_size_x - 1;
+    j = get_random(maze_size_y);
+    break;
+  case 2:      
+    i = get_random(maze_size_x);
+    j = maze_size_y - 1;
+    break;
+  case 3:      
+    i = 0;
+    j = get_random(maze_size_y);
+    break;
+  }
+  maze[i][j] |= START_SQUARE;
+  maze[i][j] |= ( DOOR_IN_TOP >> wall );
+  maze[i][j] &= ~( WALL_TOP >> wall );
+  cur_sq_x = i;
+  cur_sq_y = j;
+  start_x = i;
+  start_y = j;
+  start_dir = wall;
+  sqnum = 0;
+  
+  /* set end square */
+  wall = (wall + 2)%4;
+  switch (wall) {
+  case 0:
+    i = get_random(maze_size_x);
+    j = 0;
+    break;
+  case 1:
+    i = maze_size_x - 1;
+    j = get_random(maze_size_y);
+    break;
+  case 2:
+    i = get_random(maze_size_x);
+    j = maze_size_y - 1;
+    break;
+  case 3:
+    i = 0;
+    j = get_random(maze_size_y);
+    break;
+  }
+  maze[i][j] |= END_SQUARE;
+  maze[i][j] |= ( DOOR_OUT_TOP >> wall );
+  maze[i][j] &= ~( WALL_TOP >> wall );
+  end_x = i;
+  end_y = j;
+  end_dir = wall;
+}
+
+static int choose_door ();
+static long backup ();
+static void draw_wall ();
+static void draw_solid_square(int, int, int, HDC, HBRUSH);
+static void enter_square(int, HDC, HBRUSH);
+
+static void
+create_maze()             /* create a maze layout given the intiialized maze */
+{
+  register int i, newdoor = 0;
+  HDC hDC;
+  
+  hDC = GetDC(hWnd);
+  do {
+    move_list[sqnum].x = cur_sq_x;
+    move_list[sqnum].y = cur_sq_y;
+    move_list[sqnum].dir = newdoor;
+    while ( ( newdoor = choose_door(hDC) ) == -1 ) { /* pick a door */
+      if ( backup() == -1 ) { /* no more doors ... backup */
+           ReleaseDC(hWnd, hDC);
+               return; /* done ... return */
+      }
+    }
+    
+    /* mark the out door */
+    maze[cur_sq_x][cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor );
+    
+    switch (newdoor) {
+    case 0: cur_sq_y--;
+      break;
+    case 1: cur_sq_x++;
+      break;
+    case 2: cur_sq_y++;
+      break;
+    case 3: cur_sq_x--;
+      break;
+    }
+    sqnum++;
+    
+    /* mark the in door */
+    maze[cur_sq_x][cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) );
+    
+    /* if end square set path length and save path */
+    if ( maze[cur_sq_x][cur_sq_y] & END_SQUARE ) {
+      path_length = sqnum;
+      for ( i=0; i<path_length; i++) {
+       save_path[i].x = move_list[i].x;
+       save_path[i].y = move_list[i].y;
+       save_path[i].dir = move_list[i].dir;
+      }
+    }
+    
+  } while (1);
+  
+}
+
+
+static int
+choose_door(HDC hDC)                                    /* pick a new path */
+{
+  int candidates[3];
+  register int num_candidates;
+  
+  num_candidates = 0;
+  
+  /* top wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP )
+    goto rightwall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP )
+    goto rightwall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_TOP )
+    goto rightwall;
+  if ( maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
+    maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
+    draw_wall(cur_sq_x, cur_sq_y, 0, hDC);
+    goto rightwall;
+  }
+  candidates[num_candidates++] = 0;
+  
+ rightwall:
+  /* right wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT )
+    goto bottomwall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT )
+    goto bottomwall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_RIGHT )
+    goto bottomwall;
+  if ( maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
+    maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
+    draw_wall(cur_sq_x, cur_sq_y, 1, hDC);
+    goto bottomwall;
+  }
+  candidates[num_candidates++] = 1;
+  
+ bottomwall:
+  /* bottom wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM )
+    goto leftwall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM )
+    goto leftwall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM )
+    goto leftwall;
+  if ( maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
+    maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
+    draw_wall(cur_sq_x, cur_sq_y, 2, hDC);
+    goto leftwall;
+  }
+  candidates[num_candidates++] = 2;
+  
+ leftwall:
+  /* left wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT )
+    goto donewall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT )
+    goto donewall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_LEFT )
+    goto donewall;
+  if ( maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
+    maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
+    draw_wall(cur_sq_x, cur_sq_y, 3, hDC);
+    goto donewall;
+  }
+  candidates[num_candidates++] = 3;
+  
+ donewall:
+  if (num_candidates == 0)
+    return ( -1 );
+  if (num_candidates == 1)
+    return ( candidates[0] );
+  return ( candidates[ get_random(num_candidates) ] );
+  
+}
+
+
+static long
+backup()                                                  /* back up a move */
+{
+  sqnum--;
+  if (0 <= sqnum) {
+       cur_sq_x = move_list[sqnum].x;
+       cur_sq_y = move_list[sqnum].y;
+  }
+  return ( sqnum );
+}
+
+int bw;
+
+static void
+draw_solid_square(i, j, dir, hDC, hBrush)          /* draw a solid square in a square */
+     register int i, j, dir;
+     HDC hDC;
+        HBRUSH hBrush;
+{
+  RECT rc;
+
+  switch (dir) {
+  case 0: 
+    rc.left = border_x + bw + grid_width * i;
+       rc.right = rc.left + grid_width - (bw + bw);
+       rc.top = border_y - bw + grid_height * j;
+       rc.bottom = rc.top + grid_height;
+    break;
+  case 1: 
+       rc.left = border_x + bw + grid_width * i;
+       rc.right = rc.left + grid_width;
+       rc.top = border_y + bw + grid_height * j;
+       rc.bottom = rc.top + grid_height - (bw + bw);
+    break;
+  case 2: 
+    rc.left = border_x + bw + grid_width * i;
+       rc.right = rc.left + grid_width - (bw + bw);
+       rc.top = border_y + bw + grid_height * j;
+       rc.bottom = rc.top + grid_height;
+    break;
+  case 3:
+       rc.left = border_x - bw + grid_width * i;
+       rc.right = rc.left + grid_width;
+       rc.top = border_y + bw + grid_height * j;
+       rc.bottom = rc.top + grid_height - (bw + bw);
+    break;
+  }
+  (void) FillRect(hDC, &rc, hBrush);
+}
+
+static void
+draw_maze_border(HWND hWnd, HDC hDC)   /* draw the maze outline */
+{
+  register int i, j;
+  HBRUSH hBrush;
+  
+  
+  for ( i=0; i<maze_size_x; i++) {
+    if ( maze[i][0] & WALL_TOP ) {
+         MoveToEx(hDC, border_x + grid_width * i, border_y, NULL);
+         (void) LineTo(hDC, border_x + grid_width * (i + 1) - 1, border_y);
+    }
+    if ((maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
+         MoveToEx(hDC, border_x + grid_width * i,
+                  border_y + grid_height * (maze_size_y) - 1, NULL);
+         (void) LineTo(hDC, border_x + grid_width * (i+1) - 1,
+                           border_y + grid_height * (maze_size_y) - 1);
+    }
+  }
+  for ( j=0; j<maze_size_y; j++) {
+    if ( maze[maze_size_x - 1][j] & WALL_RIGHT ) {
+         MoveToEx(hDC, border_x + grid_width * maze_size_x - 1,
+                      border_y + grid_height * j, NULL);
+         (void) LineTo(hDC, border_x + grid_width * maze_size_x - 1,
+                           border_y + grid_height * (j+1) - 1);
+    }
+    if ( maze[0][j] & WALL_LEFT ) {
+         MoveToEx(hDC, border_x, border_y + grid_height * j, NULL);
+         (void) LineTo(hDC, border_x, border_y + grid_height * (j+1) - 1);
+    }
+  }
+
+  hBrush = GetStockObject(BLACK_BRUSH);
+  draw_solid_square (start_x, start_y, start_dir, hDC, hBrush);
+  draw_solid_square (end_x, end_y, end_dir, hDC, hBrush);
+}
+
+
+static void
+draw_wall(i, j, dir, hDC)                                   /* draw a single wall */
+     int i, j, dir;
+        HDC hDC;
+{
+  switch (dir) {
+  case 0:
+       MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j, NULL);
+       (void) LineTo(hDC, border_x + grid_width * (i+1), 
+                     border_y + grid_height * j);
+    break;
+  case 1:
+       MoveToEx(hDC, border_x + grid_width * (i+1), border_y + grid_height * j,
+                NULL);
+       (void) LineTo(hDC, border_x + grid_width * (i+1),
+                     border_y + grid_height * (j+1));
+    break;
+  case 2:
+       MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * (j+1),
+                NULL);
+       (void) LineTo(hDC, border_x + grid_width * (i+1), 
+                     border_y + grid_height * (j+1));
+    break;
+  case 3:
+       MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j,
+                NULL);
+       (void) LineTo(hDC, border_x + grid_width * i, 
+                     border_y + grid_height * (j+1));
+    break;
+  }
+}
+
+static void
+begin_solve_maze()                             /* solve it with graphical feedback */
+{
+  static long grayPattern[] = {
+       0x55555555,
+       0xaaaaaaaa,
+       0x55555555,
+       0xaaaaaaaa,
+       0x55555555,
+       0xaaaaaaaa,
+       0x55555555,
+       0xaaaaaaaa
+  };
+  static RGBQUAD argbq[] = {
+       { 0, 0, 255, 0 },         
+       { 255, 255, 255, 0 }
+  };
+  BITMAPINFO *pbmi;
+  
+  hDC = GetDC(hWnd);
+  pbmi = malloc(sizeof(BITMAPINFOHEADER) + sizeof(argbq) + sizeof(grayPattern));
+  pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+  pbmi->bmiHeader.biWidth = 8;
+  pbmi->bmiHeader.biHeight = 8;
+  pbmi->bmiHeader.biPlanes = 1;
+  pbmi->bmiHeader.biBitCount = 1;
+  pbmi->bmiHeader.biCompression = BI_RGB;
+  (void) memcpy(pbmi->bmiColors, argbq, sizeof(argbq));
+  (void) memcpy(pbmi->bmiColors + 2, grayPattern, sizeof(grayPattern));
+#if 0
+  /* FIXME Pattern brushes not yet implemented in ReactOS */
+  hBrushDead = CreateDIBPatternBrushPt(pbmi, DIB_RGB_COLORS);
+#else
+  hBrushDead = CreateSolidBrush(RGB(255, 0, 0));
+#endif
+//  hBrushDead = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 0));
+  free(pbmi);
+  hBrushLiving = CreateSolidBrush(RGB(0, 255, 0));
+
+  /* plug up the surrounding wall */
+  maze[start_x][start_y] |= (WALL_TOP >> start_dir);
+  maze[end_x][end_y] |= (WALL_TOP >> end_dir);
+  
+  /* initialize search path */
+  pathi = 0;
+  path[pathi].x = end_x;
+  path[pathi].y = end_y;
+  path[pathi].dir = -1;
+}
+  
+static int
+solve_maze()                             /* solve it with graphical feedback */
+{
+  int ret;
+  int action_done;
+                  
+  do {
+    action_done = 1;
+    if ( ++path[pathi].dir >= 4 ) {
+      pathi--;
+      draw_solid_square( (int)(path[pathi].x), (int)(path[pathi].y), 
+                      (int)(path[pathi].dir), hDC, hBrushDead);
+      ret = 0;
+    }
+    else if ( ! (maze[path[pathi].x][path[pathi].y] & 
+               (WALL_TOP >> path[pathi].dir))  && 
+            ( (pathi == 0) || ( (path[pathi].dir != 
+                           (int)(path[pathi-1].dir+2)%4) ) ) ) {
+      enter_square(pathi, hDC, hBrushLiving);
+      pathi++;
+      if ( maze[path[pathi].x][path[pathi].y] & START_SQUARE ) {
+           DeleteObject(hBrushLiving);
+           DeleteObject(hBrushDead);
+           ReleaseDC(hWnd, hDC);
+          ret = 1;
+      } else {
+        ret = 0;
+      }
+    } else {
+      action_done = 0;
+    }
+  } while (! action_done);
+
+  return ret;
+} 
+
+
+static void
+enter_square(int n, HDC hDC, HBRUSH hBrush)  /* move into a neighboring square */
+{
+  draw_solid_square( (int)path[n].x, (int)path[n].y, 
+                   (int)path[n].dir, hDC, hBrush);
+  
+  path[n+1].dir = -1;
+  switch (path[n].dir) {
+  case 0: path[n+1].x = path[n].x;
+    path[n+1].y = path[n].y - 1;
+    break;
+  case 1: path[n+1].x = path[n].x + 1;
+    path[n+1].y = path[n].y;
+    break;
+  case 2: path[n+1].x = path[n].x;
+    path[n+1].y = path[n].y + 1;
+    break;
+  case 3: path[n+1].x = path[n].x - 1;
+    path[n+1].y = path[n].y;
+    break;
+  }
+}
+
+static void
+start_timer(HWND hWnd, int iTimeout)
+{
+       waiting = TRUE;
+       SetTimer(hWnd, 1, iTimeout, NULL);
+}
+
+/****************************************************************************
+
+       FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
+
+       PURPOSE: calls initialization function, processes message loop
+
+       COMMENTS:
+
+               Windows recognizes this function by name as the initial entry point
+               for the program.  This function calls the application initialization
+               routine, if no other instance of the program is running, and always
+               calls the instance initialization routine.  It then executes a message
+               retrieval and dispatch loop that is the top-level control structure
+               for the remainder of execution.  The loop is terminated when a WM_QUIT
+               message is received, at which time this function exits the application
+               instance by returning the value passed by PostQuitMessage().
+
+               If this function must abort before entering the message loop, it
+               returns the conventional value NULL.
+
+****************************************************************************/
+int APIENTRY WinMain(
+       HINSTANCE hInstance,
+    HINSTANCE hPrevInstance,
+       LPSTR lpCmdLine,
+       int nCmdShow)
+{
+       MSG msg;
+       HDC hDC;
+
+       if (!hPrevInstance) {           /* Other instances of app running? */
+                       if (!InitApplication(hInstance)) { /* Initialize shared things */
+                       return (FALSE);         /* Exits if unable to initialize */
+               }
+       }
+
+       /* Perform initializations that apply to a specific instance */
+
+       if (!InitInstance(hInstance, nCmdShow)) {
+               return (FALSE);
+       }
+
+       waiting = FALSE;
+       state = 1;
+
+       /* Acquire and dispatch messages until a WM_QUIT message is received. */
+
+       while (0 != state) {
+               if (waiting) {
+                       (void) WaitMessage();
+               }
+               while (0 != state && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+                       if (WM_QUIT == msg.message) {
+                               state = 0;
+                       } else {
+                               DispatchMessage(&msg); /* Dispatches message to window */
+                       }
+               }
+               switch (state) {
+               case 1:
+                       initialize_maze();
+                       state = 2;
+                       break;
+               case 2:
+                       hDC = GetDC(hWnd);
+                       SendMessage(hWnd, WM_ERASEBKGND, (WPARAM) hDC, (LPARAM) 0);
+                       draw_maze_border(hWnd, hDC);
+                       ReleaseDC(hWnd, hDC);
+                       state = 3;
+                       break;
+               case 3:
+                       create_maze();
+                       state = 4;
+                       break;
+               case 4:
+                       start_timer(hWnd, pre_solve_delay);
+                       state = 5;
+                       break;
+               case 5:
+                       if (! waiting) {
+                               state = 6;
+                       }
+                       break;
+               case 6:
+                       begin_solve_maze();
+                       if (0 != solve_delay) {
+                               start_timer(hWnd, solve_delay);
+                               state = 7;
+                       } else {
+                               state = 8;
+                       }
+                       break;
+               case 7:
+                       if (! waiting) {
+                               state = 8;
+                       }
+                       break;
+               case 8:
+                       if (! solve_maze()) {
+                               if (0 != solve_delay) {
+                                       start_timer(hWnd, solve_delay);
+                                       state = 7;
+                               }
+                       } else {
+                               state = 9;
+                       }
+                       break;
+               case 9:
+                       start_timer(hWnd, post_solve_delay);
+                       state = 10;
+                       break;
+               case 10:
+                       if (! waiting) {
+                               state = 11;
+                       }
+                       break;
+               case 11:
+                       state = 1;
+                       break;
+               }
+       }
+
+       return (msg.wParam); /* Returns the value from PostQuitMessage */
+}
+
+
+/****************************************************************************
+
+       FUNCTION: InitApplication(HINSTANCE)
+
+       PURPOSE: Initializes window data and registers window class
+
+       COMMENTS:
+
+               This function is called at initialization time only if no other
+               instances of the application are running.  This function performs
+               initialization tasks that can be done once for any number of running
+               instances.
+
+               In this case, we initialize a window class by filling out a data
+               structure of type WNDCLASS and calling the Windows RegisterClass()
+               function.  Since all instances of this application use the same window
+               class, we only need to do this when the first instance is initialized.
+
+
+****************************************************************************/
+
+static BOOL InitApplication(HINSTANCE hInstance)
+{
+       WNDCLASS  wc;
+
+       // Fill in window class structure with parameters that describe the
+       // main window.
+
+       wc.style         = CS_HREDRAW | CS_VREDRAW;// Class style(s).
+       wc.lpfnWndProc   = (WNDPROC)WndProc;       // Window Procedure
+       wc.cbClsExtra    = 0;                      // No per-class extra data.
+       wc.cbWndExtra    = 0;                      // No per-window extra data.
+       wc.hInstance     = hInstance;              // Owner of this class
+       wc.hIcon         = LoadIcon (hInstance, szAppName); // Icon name from .RC
+       wc.hCursor       = LoadCursor(NULL, (LPCTSTR) IDC_ARROW);// Cursor
+       wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);// Default color
+       wc.lpszMenuName  = NULL;                    // No menu
+       wc.lpszClassName = szAppName;              // Name to register as
+
+       // Register the window class and return success/failure code.
+       return (RegisterClass(&wc));
+}
+
+
+/****************************************************************************
+
+       FUNCTION:  InitInstance(HINSTANCE, int)
+
+       PURPOSE:  Saves instance handle and creates main window
+
+       COMMENTS:
+
+               This function is called at initialization time for every instance of
+               this application.  This function performs initialization tasks that
+               cannot be shared by multiple instances.
+
+               In this case, we save the instance handle in a static variable and
+               create and display the main program window.
+
+****************************************************************************/
+
+static BOOL InitInstance(
+       HINSTANCE          hInstance,
+       int             nCmdShow)
+{
+       /* Save the instance handle in static variable, which will be used in
+          many subsequence calls from this application to Windows. */
+
+       hInst = hInstance; /* Store instance handle in our global variable */
+
+       /* Create a main window for this application instance. */
+
+       hWnd = CreateWindow(
+               szAppName,              /* See RegisterClass() call. */
+               szTitle,                /* Text for window title bar. */
+               WS_OVERLAPPEDWINDOW,/* Window style. */
+               0, 0, CW_USEDEFAULT, CW_USEDEFAULT, /* Use default positioning */
+               NULL,                   /* Overlapped windows have no parent. */
+               NULL,                   /* Use the window class menu. */
+               hInstance,              /* This instance owns this window. */
+               NULL                    /* We don't use any data in our WM_CREATE */
+       );
+
+       // If window could not be created, return "failure"
+       if (!hWnd) {
+               return (FALSE);
+       }
+
+       // Make the window visible; update its client area; and return "success"
+       ShowWindow(hWnd, nCmdShow); // Show the window
+       UpdateWindow(hWnd);         // Sends WM_PAINT message
+
+       return (TRUE);              // We succeeded...
+
+}
+
+static BOOL
+OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
+{
+       RECT rc;
+       int size;
+
+       srand((unsigned) time(NULL));
+
+#if 0
+       /* FIXME GetPrivateProfileInt not yet implemented in ReactOS */
+       size = GetPrivateProfileInt("maze", "gridsize", 0, "maze.ini");
+       pre_solve_delay = GetPrivateProfileInt("maze", "predelay", 5000,
+                                              "maze.ini");
+       post_solve_delay = GetPrivateProfileInt("maze", "postdelay", 5000,
+                                               "maze.ini");
+       solve_delay = GetPrivateProfileInt("maze", "solvedelay", 10,
+                                          "maze.ini");
+#else
+       size = 10;
+       pre_solve_delay = 5000;
+       post_solve_delay = 5000;
+       solve_delay = 20;
+#endif
+
+       if (size < 2) {
+               size = 7 + (rand() % 30);
+       }
+       grid_width = grid_height = size;
+    bw = (size > 6 ? 3 : (size-1)/2);
+
+       GetClientRect(hWnd, &rc);
+       set_maze_sizes(rc.right - rc.left, rc.bottom - rc.top);
+
+       return TRUE;
+}
+
+void OnTimer(HWND hwnd, UINT id)
+{
+       waiting = FALSE;
+}
+
+/****************************************************************************
+
+       FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
+
+       PURPOSE:  Processes messages
+
+       MESSAGES:
+
+       WM_DESTROY    - destroy window
+
+       COMMENTS:
+
+****************************************************************************/
+
+LRESULT CALLBACK WndProc(
+               HWND hWnd,         // window handle
+               UINT message,      // type of message
+               WPARAM wParam,     // additional information
+               LPARAM lParam)     // additional information
+{
+       PAINTSTRUCT ps;
+
+       switch (message) {
+               case WM_CREATE:
+                       OnCreate(hWnd, (LPCREATESTRUCT) lParam);
+                       break;
+               case WM_PAINT:
+                       BeginPaint(hWnd, &ps);
+                       state = 1;
+                       EndPaint(hWnd, &ps);
+               case WM_TIMER:
+                       OnTimer(hWnd, wParam);
+                       break;
+               case WM_DESTROY:  // message: window being destroyed
+                       PostQuitMessage(0);
+                       break;
+
+               default:          // Passes it on if unproccessed
+                       return (DefWindowProc(hWnd, message, wParam, lParam));
+       }
+       return (0);
+}
diff --git a/rosapps/demos/maze/maze.rc b/rosapps/demos/maze/maze.rc
new file mode 100644 (file)
index 0000000..67cab63
--- /dev/null
@@ -0,0 +1,60 @@
+//Microsoft App Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <scrnsave.h>
+/////////////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    idsAppName              "Screen Saver.Maze"
+END
+
+#ifdef APSTUDIO_INVOKED
+//////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include <scrnsave.h>\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif    // APSTUDIO_INVOKED
+
+
+#ifndef APSTUDIO_INVOKED
+////////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/rosapps/demos/maze/resource.h b/rosapps/demos/maze/resource.h
new file mode 100644 (file)
index 0000000..1efacbb
--- /dev/null
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// App Studio generated include file.
+// Used by MAZE.RC
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         101
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif