Partial merge of the condrv_restructure branch, including:
[reactos.git] / rosapps / applications / screensavers / mazescr / maze.c
1 /******************************************************************************
2 * [ maze ] ...
3 *
4 * modified: [ 03-08-15 ] Ge van Geldorp <ge@gse.nl>
5 * ported to Reactos
6 * modified: [ 94-10-8 ] Ge van Geldorp <Ge.vanGeldorp@lr.tudelft.nl>
7 * ported to MS Windows
8 * modified: [ 3-7-93 ] Jamie Zawinski <jwz@lucid.com>
9 * added the XRoger logo, cleaned up resources, made
10 * grid size a parameter.
11 * modified: [ 3-3-93 ] Jim Randell <jmr@mddjmr.fc.hp.com>
12 * Added the colour stuff and integrated it with jwz's
13 * screenhack stuff. There's still some work that could
14 * be done on this, particularly allowing a resource to
15 * specify how big the squares are.
16 * modified: [ 10-4-88 ] Richard Hess ...!uunet!cimshop!rhess
17 * [ Revised primary execution loop within main()...
18 * [ Extended X event handler, check_events()...
19 * modified: [ 1-29-88 ] Dave Lemke lemke@sun.com
20 * [ Hacked for X11...
21 * [ Note the word "hacked" -- this is extremely ugly, but at
22 * [ least it does the job. NOT a good programming example
23 * [ for X.
24 * original: [ 6/21/85 ] Martin Weiss Sun Microsystems [ SunView ]
25 *
26 ******************************************************************************
27 Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
28
29 All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its
32 documentation for any purpose and without fee is hereby granted,
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in
35 supporting documentation, and that the names of Sun or MIT not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific prior written permission. Sun and M.I.T.
38 make no representations about the suitability of this software for
39 any purpose. It is provided "as is" without any express or implied warranty.
40
41 SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
42 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 PURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT
44 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
45 OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
46 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
47 OR PERFORMANCE OF THIS SOFTWARE.
48 *****************************************************************************/
49
50 #define STRICT
51
52 #include <stdlib.h>
53 #include <string.h>
54 #include <time.h>
55 #include <windows.h> /* required for all Windows applications */
56
57 #if !defined (APIENTRY) /* Windows NT defines APIENTRY, but 3.x doesn't */
58 #define APIENTRY far pascal
59 #endif
60
61 #if !defined(WIN32) /* Windows 3.x uses a FARPROC for dialogs */
62 #define DLGPROC FARPROC
63 #endif
64
65 static BOOL InitInstance(HINSTANCE hInstance, HWND hParent);
66 LRESULT CALLBACK MazeWndProc(HWND hWnd, UINT message, WPARAM uParam,
67 LPARAM lParam);
68
69 HINSTANCE hInst; /* current instance */
70 HWND hWnd; /* Main window handle.*/
71 HBRUSH hBrushDead;
72 HBRUSH hBrushLiving;
73 HPEN hPenWall;
74 HDC hDC;
75 static BOOL waiting;
76
77
78 WCHAR szAppName[] = L"Maze"; /* The name of this application */
79 WCHAR szTitle[] = L"Maze"; /* The title bar text */
80
81 static int solve_delay, pre_solve_delay, post_solve_delay;
82
83 #define MAX_MAZE_SIZE_X ((unsigned long) 250)
84 #define MAX_MAZE_SIZE_Y ((unsigned long) 250)
85
86 #define MOVE_LIST_SIZE (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
87
88 #define WALL_TOP 0x8000
89 #define WALL_RIGHT 0x4000
90 #define WALL_BOTTOM 0x2000
91 #define WALL_LEFT 0x1000
92
93 #define DOOR_IN_TOP 0x800
94 #define DOOR_IN_RIGHT 0x400
95 #define DOOR_IN_BOTTOM 0x200
96 #define DOOR_IN_LEFT 0x100
97 #define DOOR_IN_ANY 0xF00
98
99 #define DOOR_OUT_TOP 0x80
100 #define DOOR_OUT_RIGHT 0x40
101 #define DOOR_OUT_BOTTOM 0x20
102 #define DOOR_OUT_LEFT 0x10
103
104 #define START_SQUARE 0x2
105 #define END_SQUARE 0x1
106
107 #define border_x (0)
108 #define border_y (0)
109
110 #define get_random(x) (rand() % (x))
111
112 static unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
113
114 static struct {
115 unsigned char x;
116 unsigned char y;
117 unsigned char dir;
118 unsigned char dummy;
119 } move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
120
121 static int maze_size_x, maze_size_y;
122 static long sqnum, path_length;
123 static int cur_sq_x, cur_sq_y;
124 static int start_x, start_y, start_dir, end_x, end_y, end_dir;
125 static int grid_width, grid_height;
126
127 static int state = 1, pathi = 0;
128
129 static void
130 set_maze_sizes (width, height)
131 int width, height;
132 {
133 maze_size_x = width / grid_width;
134 maze_size_y = height / grid_height;
135 }
136
137
138 static void
139 initialize_maze() /* draw the surrounding wall and start/end squares */
140 {
141 register int i, j, wall;
142
143 /* initialize all squares */
144 for ( i=0; i<maze_size_x; i++) {
145 for ( j=0; j<maze_size_y; j++) {
146 maze[i][j] = 0;
147 }
148 }
149
150 /* top wall */
151 for ( i=0; i<maze_size_x; i++ ) {
152 maze[i][0] |= WALL_TOP;
153 }
154
155 /* right wall */
156 for ( j=0; j<maze_size_y; j++ ) {
157 maze[maze_size_x-1][j] |= WALL_RIGHT;
158 }
159
160 /* bottom wall */
161 for ( i=0; i<maze_size_x; i++ ) {
162 maze[i][maze_size_y-1] |= WALL_BOTTOM;
163 }
164
165 /* left wall */
166 for ( j=0; j<maze_size_y; j++ ) {
167 maze[0][j] |= WALL_LEFT;
168 }
169
170 /* set start square */
171 wall = get_random(4);
172 switch (wall) {
173 case 0:
174 i = get_random(maze_size_x);
175 j = 0;
176 break;
177 case 1:
178 i = maze_size_x - 1;
179 j = get_random(maze_size_y);
180 break;
181 case 2:
182 i = get_random(maze_size_x);
183 j = maze_size_y - 1;
184 break;
185 case 3:
186 i = 0;
187 j = get_random(maze_size_y);
188 break;
189 }
190 maze[i][j] |= START_SQUARE;
191 maze[i][j] |= ( DOOR_IN_TOP >> wall );
192 maze[i][j] &= ~( WALL_TOP >> wall );
193 cur_sq_x = i;
194 cur_sq_y = j;
195 start_x = i;
196 start_y = j;
197 start_dir = wall;
198 sqnum = 0;
199
200 /* set end square */
201 wall = (wall + 2)%4;
202 switch (wall) {
203 case 0:
204 i = get_random(maze_size_x);
205 j = 0;
206 break;
207 case 1:
208 i = maze_size_x - 1;
209 j = get_random(maze_size_y);
210 break;
211 case 2:
212 i = get_random(maze_size_x);
213 j = maze_size_y - 1;
214 break;
215 case 3:
216 i = 0;
217 j = get_random(maze_size_y);
218 break;
219 }
220 maze[i][j] |= END_SQUARE;
221 maze[i][j] |= ( DOOR_OUT_TOP >> wall );
222 maze[i][j] &= ~( WALL_TOP >> wall );
223 end_x = i;
224 end_y = j;
225 end_dir = wall;
226 }
227
228 static int choose_door ();
229 static long backup ();
230 static void draw_wall ();
231 static void draw_solid_square(int, int, int, HDC, HBRUSH);
232 static void enter_square(int, HDC, HBRUSH);
233
234 static void
235 create_maze() /* create a maze layout given the intiialized maze */
236 {
237 register int i, newdoor = 0;
238 HDC hDC;
239
240 hDC = GetDC(hWnd);
241 do {
242 move_list[sqnum].x = cur_sq_x;
243 move_list[sqnum].y = cur_sq_y;
244 move_list[sqnum].dir = newdoor;
245 while ( ( newdoor = choose_door(hDC) ) == -1 ) { /* pick a door */
246 if ( backup() == -1 ) { /* no more doors ... backup */
247 ReleaseDC(hWnd, hDC);
248 return; /* done ... return */
249 }
250 }
251
252 /* mark the out door */
253 maze[cur_sq_x][cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor );
254
255 switch (newdoor) {
256 case 0: cur_sq_y--;
257 break;
258 case 1: cur_sq_x++;
259 break;
260 case 2: cur_sq_y++;
261 break;
262 case 3: cur_sq_x--;
263 break;
264 }
265 sqnum++;
266
267 /* mark the in door */
268 maze[cur_sq_x][cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) );
269
270 /* if end square set path length and save path */
271 if ( maze[cur_sq_x][cur_sq_y] & END_SQUARE ) {
272 path_length = sqnum;
273 for ( i=0; i<path_length; i++) {
274 save_path[i].x = move_list[i].x;
275 save_path[i].y = move_list[i].y;
276 save_path[i].dir = move_list[i].dir;
277 }
278 }
279
280 } while (1);
281
282 }
283
284
285 static int
286 choose_door(HDC hDC) /* pick a new path */
287 {
288 int candidates[3];
289 register int num_candidates;
290
291 num_candidates = 0;
292
293 /* top wall */
294 if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP )
295 goto rightwall;
296 if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP )
297 goto rightwall;
298 if ( maze[cur_sq_x][cur_sq_y] & WALL_TOP )
299 goto rightwall;
300 if ( maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY ) {
301 maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
302 maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
303 draw_wall(cur_sq_x, cur_sq_y, 0, hDC);
304 goto rightwall;
305 }
306 candidates[num_candidates++] = 0;
307
308 rightwall:
309 /* right wall */
310 if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT )
311 goto bottomwall;
312 if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT )
313 goto bottomwall;
314 if ( maze[cur_sq_x][cur_sq_y] & WALL_RIGHT )
315 goto bottomwall;
316 if ( maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY ) {
317 maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
318 maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
319 draw_wall(cur_sq_x, cur_sq_y, 1, hDC);
320 goto bottomwall;
321 }
322 candidates[num_candidates++] = 1;
323
324 bottomwall:
325 /* bottom wall */
326 if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM )
327 goto leftwall;
328 if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM )
329 goto leftwall;
330 if ( maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM )
331 goto leftwall;
332 if ( maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY ) {
333 maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
334 maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
335 draw_wall(cur_sq_x, cur_sq_y, 2, hDC);
336 goto leftwall;
337 }
338 candidates[num_candidates++] = 2;
339
340 leftwall:
341 /* left wall */
342 if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT )
343 goto donewall;
344 if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT )
345 goto donewall;
346 if ( maze[cur_sq_x][cur_sq_y] & WALL_LEFT )
347 goto donewall;
348 if ( maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY ) {
349 maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
350 maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
351 draw_wall(cur_sq_x, cur_sq_y, 3, hDC);
352 goto donewall;
353 }
354 candidates[num_candidates++] = 3;
355
356 donewall:
357 if (num_candidates == 0)
358 return ( -1 );
359 if (num_candidates == 1)
360 return ( candidates[0] );
361 return ( candidates[ get_random(num_candidates) ] );
362
363 }
364
365
366 static long
367 backup() /* back up a move */
368 {
369 sqnum--;
370 if (0 <= sqnum) {
371 cur_sq_x = move_list[sqnum].x;
372 cur_sq_y = move_list[sqnum].y;
373 }
374 return ( sqnum );
375 }
376
377 int bw;
378
379 static void
380 draw_solid_square(i, j, dir, hDC, hBrush) /* draw a solid square in a square */
381 register int i, j, dir;
382 HDC hDC;
383 HBRUSH hBrush;
384 {
385 RECT rc;
386
387 switch (dir) {
388 case 0:
389 rc.left = border_x + bw + grid_width * i;
390 rc.right = rc.left + grid_width - (bw + bw);
391 rc.top = border_y - bw + grid_height * j;
392 rc.bottom = rc.top + grid_height;
393 break;
394 case 1:
395 rc.left = border_x + bw + grid_width * i;
396 rc.right = rc.left + grid_width;
397 rc.top = border_y + bw + grid_height * j;
398 rc.bottom = rc.top + grid_height - (bw + bw);
399 break;
400 case 2:
401 rc.left = border_x + bw + grid_width * i;
402 rc.right = rc.left + grid_width - (bw + bw);
403 rc.top = border_y + bw + grid_height * j;
404 rc.bottom = rc.top + grid_height;
405 break;
406 case 3:
407 rc.left = border_x - bw + grid_width * i;
408 rc.right = rc.left + grid_width;
409 rc.top = border_y + bw + grid_height * j;
410 rc.bottom = rc.top + grid_height - (bw + bw);
411 break;
412 }
413 (void) FillRect(hDC, &rc, hBrush);
414 }
415
416 static void
417 draw_maze_border(HWND hWnd, HDC hDC) /* draw the maze outline */
418 {
419 register int i, j;
420 HBRUSH hBrush;
421
422 SelectObject(hDC, hPenWall);
423
424 for ( i=0; i<maze_size_x; i++) {
425 if ( maze[i][0] & WALL_TOP ) {
426 MoveToEx(hDC, border_x + grid_width * i, border_y, NULL);
427 (void) LineTo(hDC, border_x + grid_width * (i + 1) - 1, border_y);
428 }
429 if ((maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
430 MoveToEx(hDC, border_x + grid_width * i,
431 border_y + grid_height * (maze_size_y) - 1, NULL);
432 (void) LineTo(hDC, border_x + grid_width * (i+1) - 1,
433 border_y + grid_height * (maze_size_y) - 1);
434 }
435 }
436 for ( j=0; j<maze_size_y; j++) {
437 if ( maze[maze_size_x - 1][j] & WALL_RIGHT ) {
438 MoveToEx(hDC, border_x + grid_width * maze_size_x - 1,
439 border_y + grid_height * j, NULL);
440 (void) LineTo(hDC, border_x + grid_width * maze_size_x - 1,
441 border_y + grid_height * (j+1) - 1);
442 }
443 if ( maze[0][j] & WALL_LEFT ) {
444 MoveToEx(hDC, border_x, border_y + grid_height * j, NULL);
445 (void) LineTo(hDC, border_x, border_y + grid_height * (j+1) - 1);
446 }
447 }
448
449 hBrush = GetStockObject(WHITE_BRUSH); // FIXME: do not hardcode
450 draw_solid_square (start_x, start_y, start_dir, hDC, hBrush);
451 draw_solid_square (end_x, end_y, end_dir, hDC, hBrush);
452 }
453
454
455 static void
456 draw_wall(i, j, dir, hDC) /* draw a single wall */
457 int i, j, dir;
458 HDC hDC;
459 {
460 SelectObject(hDC, hPenWall);
461
462 switch (dir) {
463 case 0:
464 MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j, NULL);
465 (void) LineTo(hDC, border_x + grid_width * (i+1),
466 border_y + grid_height * j);
467 break;
468 case 1:
469 MoveToEx(hDC, border_x + grid_width * (i+1), border_y + grid_height * j,
470 NULL);
471 (void) LineTo(hDC, border_x + grid_width * (i+1),
472 border_y + grid_height * (j+1));
473 break;
474 case 2:
475 MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * (j+1),
476 NULL);
477 (void) LineTo(hDC, border_x + grid_width * (i+1),
478 border_y + grid_height * (j+1));
479 break;
480 case 3:
481 MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j,
482 NULL);
483 (void) LineTo(hDC, border_x + grid_width * i,
484 border_y + grid_height * (j+1));
485 break;
486 }
487 }
488
489 static void
490 begin_solve_maze() /* solve it with graphical feedback */
491 {
492 static long grayPattern[] = {
493 0x55555555,
494 0xaaaaaaaa,
495 0x55555555,
496 0xaaaaaaaa,
497 0x55555555,
498 0xaaaaaaaa,
499 0x55555555,
500 0xaaaaaaaa
501 };
502 static RGBQUAD argbq[] = {
503 { 0, 0, 255, 0 },
504 { 255, 255, 255, 0 }
505 };
506 BITMAPINFO *pbmi;
507
508 hDC = GetDC(hWnd);
509 pbmi = malloc(sizeof(BITMAPINFOHEADER) + sizeof(argbq) + sizeof(grayPattern));
510 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
511 pbmi->bmiHeader.biWidth = 8;
512 pbmi->bmiHeader.biHeight = 8;
513 pbmi->bmiHeader.biPlanes = 1;
514 pbmi->bmiHeader.biBitCount = 1;
515 pbmi->bmiHeader.biCompression = BI_RGB;
516 (void) memcpy(pbmi->bmiColors, argbq, sizeof(argbq));
517 (void) memcpy(pbmi->bmiColors + 2, grayPattern, sizeof(grayPattern));
518 #if 0
519 /* FIXME Pattern brushes not yet implemented in ReactOS */
520 hBrushDead = CreateDIBPatternBrushPt(pbmi, DIB_RGB_COLORS);
521 #else
522 hBrushDead = CreateSolidBrush(RGB(255, 0, 0));
523 #endif
524 // hBrushDead = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 0));
525 free(pbmi);
526 hBrushLiving = CreateSolidBrush(RGB(0, 255, 0));
527
528 /* plug up the surrounding wall */
529 maze[start_x][start_y] |= (WALL_TOP >> start_dir);
530 maze[end_x][end_y] |= (WALL_TOP >> end_dir);
531
532 /* initialize search path */
533 pathi = 0;
534 path[pathi].x = end_x;
535 path[pathi].y = end_y;
536 path[pathi].dir = -1;
537 }
538
539 static int
540 solve_maze() /* solve it with graphical feedback */
541 {
542 int ret;
543 int action_done;
544
545 do {
546 action_done = 1;
547 if ( ++path[pathi].dir >= 4 ) {
548 pathi--;
549 draw_solid_square( (int)(path[pathi].x), (int)(path[pathi].y),
550 (int)(path[pathi].dir), hDC, hBrushDead);
551 ret = 0;
552 }
553 else if ( ! (maze[path[pathi].x][path[pathi].y] &
554 (WALL_TOP >> path[pathi].dir)) &&
555 ( (pathi == 0) || ( (path[pathi].dir !=
556 (int)(path[pathi-1].dir+2)%4) ) ) ) {
557 enter_square(pathi, hDC, hBrushLiving);
558 pathi++;
559 if ( maze[path[pathi].x][path[pathi].y] & START_SQUARE ) {
560 DeleteObject(hBrushLiving);
561 DeleteObject(hBrushDead);
562 ReleaseDC(hWnd, hDC);
563 ret = 1;
564 } else {
565 ret = 0;
566 }
567 } else {
568 action_done = 0;
569 }
570 } while (! action_done);
571
572 return ret;
573 }
574
575
576 static void
577 enter_square(int n, HDC hDC, HBRUSH hBrush) /* move into a neighboring square */
578 {
579 draw_solid_square( (int)path[n].x, (int)path[n].y,
580 (int)path[n].dir, hDC, hBrush);
581
582 path[n+1].dir = -1;
583 switch (path[n].dir) {
584 case 0: path[n+1].x = path[n].x;
585 path[n+1].y = path[n].y - 1;
586 break;
587 case 1: path[n+1].x = path[n].x + 1;
588 path[n+1].y = path[n].y;
589 break;
590 case 2: path[n+1].x = path[n].x;
591 path[n+1].y = path[n].y + 1;
592 break;
593 case 3: path[n+1].x = path[n].x - 1;
594 path[n+1].y = path[n].y;
595 break;
596 }
597 }
598
599 static void
600 start_timer(HWND hWnd, int iTimeout)
601 {
602 waiting = TRUE;
603 SetTimer(hWnd, 1, iTimeout, NULL);
604 }
605
606 /****************************************************************************
607
608 FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
609
610 PURPOSE: calls initialization function, processes message loop
611
612 COMMENTS:
613
614 Windows recognizes this function by name as the initial entry point
615 for the program. This function calls the application initialization
616 routine, if no other instance of the program is running, and always
617 calls the instance initialization routine. It then executes a message
618 retrieval and dispatch loop that is the top-level control structure
619 for the remainder of execution. The loop is terminated when a WM_QUIT
620 message is received, at which time this function exits the application
621 instance by returning the value passed by PostQuitMessage().
622
623 If this function must abort before entering the message loop, it
624 returns the conventional value NULL.
625
626 ****************************************************************************/
627
628 int APIENTRY MazeMain(
629 HINSTANCE hInstance,
630 HINSTANCE hPrevInstance,
631 LPSTR lpCmdLine,
632 HWND hParent)
633 {
634 MSG msg;
635 HDC hDC;
636
637 /* Perform initializations that apply to a specific instance */
638
639 if (!InitInstance(hInstance, hParent)) {
640 return (FALSE);
641 }
642
643 waiting = FALSE;
644 state = 1;
645
646 /* Acquire and dispatch messages until a WM_QUIT message is received. */
647
648 while (0 != state) {
649 if (waiting) {
650 (void) WaitMessage();
651 }
652 while (0 != state && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
653 if (WM_QUIT == msg.message) {
654 state = 0;
655 } else {
656 DispatchMessage(&msg); /* Dispatches message to window */
657 }
658 }
659 switch (state) {
660 case 1:
661 initialize_maze();
662 state = 2;
663 break;
664 case 2:
665 hDC = GetDC(hWnd);
666 SendMessage(hWnd, WM_ERASEBKGND, (WPARAM) hDC, (LPARAM) 0);
667 draw_maze_border(hWnd, hDC);
668 ReleaseDC(hWnd, hDC);
669 state = 3;
670 break;
671 case 3:
672 create_maze();
673 state = 4;
674 break;
675 case 4:
676 start_timer(hWnd, pre_solve_delay);
677 state = 5;
678 break;
679 case 5:
680 if (! waiting) {
681 state = 6;
682 }
683 break;
684 case 6:
685 begin_solve_maze();
686 if (0 != solve_delay) {
687 start_timer(hWnd, solve_delay);
688 state = 7;
689 } else {
690 state = 8;
691 }
692 break;
693 case 7:
694 if (! waiting) {
695 state = 8;
696 }
697 break;
698 case 8:
699 if (! solve_maze()) {
700 if (0 != solve_delay) {
701 start_timer(hWnd, solve_delay);
702 state = 7;
703 }
704 } else {
705 state = 9;
706 }
707 break;
708 case 9:
709 start_timer(hWnd, post_solve_delay);
710 state = 10;
711 break;
712 case 10:
713 if (! waiting) {
714 state = 11;
715 }
716 break;
717 case 11:
718 state = 1;
719 break;
720 }
721 }
722
723 return (msg.wParam); /* Returns the value from PostQuitMessage */
724 }
725
726
727 /****************************************************************************
728
729 FUNCTION: InitInstance(HINSTANCE, int)
730
731 PURPOSE: Saves instance handle and creates main window
732
733 COMMENTS:
734
735 This function is called at initialization time for every instance of
736 this application. This function performs initialization tasks that
737 cannot be shared by multiple instances.
738
739 In this case, we save the instance handle in a static variable and
740 create and display the main program window.
741
742 ****************************************************************************/
743
744 static BOOL InitInstance(
745 HINSTANCE hInstance,
746 HWND hParent)
747 {
748 RECT rect;
749
750 /* Save the instance handle in static variable, which will be used in
751 many subsequence calls from this application to Windows. */
752
753 hInst = hInstance; /* Store instance handle in our global variable */
754
755 GetClientRect(hParent, &rect);
756 #if 0
757 /* Create a main window for this application instance. */
758 hWnd = CreateWindow(
759 szAppName, /* See RegisterClass() call. */
760 szTitle, /* Text for window title bar. */
761 WS_CHILD,/* Window style. */
762 0, 0, rect.right/2, rect.bottom/2, /* Use default positioning */
763 hParent, /* We use a Parent. */
764 NULL, /* Use the window class menu. */
765 hInstance, /* This instance owns this window. */
766 NULL /* We don't use any data in our WM_CREATE */
767 );
768 #endif
769 hWnd = hParent;
770 // If window could not be created, return "failure"
771 if (!hWnd) {
772 return (FALSE);
773 }
774
775 // Make the window visible; update its client area; and return "success"
776 ShowWindow(hWnd, SW_SHOW); // Show the window
777 SetCursor(NULL);
778 UpdateWindow(hWnd); // Sends WM_PAINT message
779
780 hPenWall = CreatePen(PS_SOLID, 3, RGB(150,150,150));
781
782 return (TRUE); // We succeeded...
783
784 }
785
786 static BOOL
787 OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
788 {
789 RECT rc;
790 int size;
791
792 srand((unsigned) time(NULL));
793
794 #if 0
795 /* FIXME GetPrivateProfileInt not yet implemented in ReactOS */
796 size = GetPrivateProfileInt("maze", "gridsize", 0, "maze.ini");
797 pre_solve_delay = GetPrivateProfileInt("maze", "predelay", 5000,
798 "maze.ini");
799 post_solve_delay = GetPrivateProfileInt("maze", "postdelay", 5000,
800 "maze.ini");
801 solve_delay = GetPrivateProfileInt("maze", "solvedelay", 10,
802 "maze.ini");
803 #else
804 size = 10;
805 pre_solve_delay = 5000;
806 post_solve_delay = 5000;
807 solve_delay = 1;
808 #endif
809
810 if (size < 2) {
811 size = 7 + (rand() % 30);
812 }
813 grid_width = grid_height = size;
814 bw = (size > 6 ? 3 : (size-1)/2);
815
816 GetClientRect(hWnd, &rc);
817 set_maze_sizes(rc.right - rc.left, rc.bottom - rc.top);
818
819 return TRUE;
820 }
821
822 void OnTimer(HWND hwnd, UINT id)
823 {
824 waiting = FALSE;
825 }
826
827 /****************************************************************************
828
829 FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
830
831 PURPOSE: Processes messages
832
833 MESSAGES:
834
835 WM_DESTROY - destroy window
836
837 COMMENTS:
838
839 ****************************************************************************/
840
841 LRESULT CALLBACK MazeWndProc(
842 HWND hWnd, // window handle
843 UINT message, // type of message
844 WPARAM wParam, // additional information
845 LPARAM lParam) // additional information
846 {
847 PAINTSTRUCT ps;
848
849 switch (message) {
850 case WM_CREATE:
851 OnCreate(hWnd, (LPCREATESTRUCT) lParam);
852 break;
853 case WM_PAINT:
854 BeginPaint(hWnd, &ps);
855 state = 1;
856 EndPaint(hWnd, &ps);
857 case WM_TIMER:
858 OnTimer(hWnd, wParam);
859 break;
860 case WM_DESTROY: // message: window being destroyed
861 PostQuitMessage(0);
862 break;
863
864 default: // Passes it on if unproccessed
865 return (DefWindowProc(hWnd, message, wParam, lParam));
866 }
867 return (0);
868 }