1 /******************************************************************************
4 * modified: [ 03-08-15 ] Ge van Geldorp <ge@gse.nl>
6 * modified: [ 94-10-8 ] Ge van Geldorp <Ge.vanGeldorp@lr.tudelft.nl>
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
21 * [ Note the word "hacked" -- this is extremely ugly, but at
22 * [ least it does the job. NOT a good programming example
24 * original: [ 6/21/85 ] Martin Weiss Sun Microsystems [ SunView ]
26 ******************************************************************************
27 Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
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.
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 *****************************************************************************/
55 #include <windows.h> /* required for all Windows applications */
59 #define APPNAME _T("Maze")
61 //static BOOL InitInstance(HWND hParent);
62 LRESULT CALLBACK
ScreenSaverProc(HWND hWnd
, UINT message
, WPARAM uParam
, LPARAM lParam
);
63 static int choose_door();
65 static void draw_wall();
66 static void draw_solid_square(int, int, int, HDC
, HBRUSH
);
67 static void enter_square(int, HDC
, HBRUSH
);
69 extern HINSTANCE hMainInstance
; /* current instance */
74 //static BOOL waiting;
76 static int solve_delay
, pre_solve_delay
, post_solve_delay
;
78 #define MAX_MAZE_SIZE_X ((unsigned long) 1000) // Dynamic detection?
79 #define MAX_MAZE_SIZE_Y ((unsigned long) 1000) // Dynamic detection?
81 #define MOVE_LIST_SIZE (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
83 #define WALL_TOP 0x8000
84 #define WALL_RIGHT 0x4000
85 #define WALL_BOTTOM 0x2000
86 #define WALL_LEFT 0x1000
88 #define DOOR_IN_TOP 0x800
89 #define DOOR_IN_RIGHT 0x400
90 #define DOOR_IN_BOTTOM 0x200
91 #define DOOR_IN_LEFT 0x100
92 #define DOOR_IN_ANY 0xF00
94 #define DOOR_OUT_TOP 0x80
95 #define DOOR_OUT_RIGHT 0x40
96 #define DOOR_OUT_BOTTOM 0x20
97 #define DOOR_OUT_LEFT 0x10
99 #define START_SQUARE 0x2
100 #define END_SQUARE 0x1
105 #define get_random(x) (rand() % (x))
107 static unsigned short maze
[MAX_MAZE_SIZE_X
][MAX_MAZE_SIZE_Y
];
113 } move_list
[MOVE_LIST_SIZE
], save_path
[MOVE_LIST_SIZE
], path
[MOVE_LIST_SIZE
];
115 static int maze_size_x
, maze_size_y
;
116 static long sqnum
, path_length
;
117 static int cur_sq_x
, cur_sq_y
;
118 static int start_x
, start_y
, start_dir
, end_x
, end_y
, end_dir
;
119 static int grid_width
, grid_height
;
121 static int state
= 1, pathi
= 0;
123 static void set_maze_sizes(width
, height
)
126 maze_size_x
= (width
-1)/ grid_width
;
127 maze_size_y
= (height
-1) / grid_height
;
128 if (maze_size_x
> MAX_MAZE_SIZE_X
)
129 maze_size_x
= MAX_MAZE_SIZE_X
;
130 if (maze_size_y
> MAX_MAZE_SIZE_Y
)
131 maze_size_y
= MAX_MAZE_SIZE_Y
;
134 static void initialize_maze() /* draw the surrounding wall and start/end squares */
136 register int i
, j
, wall
;
138 /* initialize all squares */
139 for (i
= 0; i
< maze_size_x
; i
++) {
140 for (j
= 0; j
< maze_size_y
; j
++) {
146 for (i
= 0; i
< maze_size_x
; i
++) {
147 maze
[i
][0] |= WALL_TOP
;
151 for (j
= 0; j
< maze_size_y
; j
++) {
152 maze
[maze_size_x
- 1][j
] |= WALL_RIGHT
;
156 for (i
= 0; i
< maze_size_x
; i
++) {
157 maze
[i
][maze_size_y
- 1] |= WALL_BOTTOM
;
161 for (j
= 0; j
< maze_size_y
; j
++) {
162 maze
[0][j
] |= WALL_LEFT
;
165 /* set start square */
166 wall
= get_random(4);
169 i
= get_random(maze_size_x
);
174 j
= get_random(maze_size_y
);
177 i
= get_random(maze_size_x
);
182 j
= get_random(maze_size_y
);
185 maze
[i
][j
] |= START_SQUARE
;
186 maze
[i
][j
] |= (DOOR_IN_TOP
>> wall
);
187 maze
[i
][j
] &= ~(WALL_TOP
>> wall
);
196 wall
= (wall
+ 2) % 4;
199 i
= get_random(maze_size_x
);
204 j
= get_random(maze_size_y
);
207 i
= get_random(maze_size_x
);
212 j
= get_random(maze_size_y
);
215 maze
[i
][j
] |= END_SQUARE
;
216 maze
[i
][j
] |= (DOOR_OUT_TOP
>> wall
);
217 maze
[i
][j
] &= ~(WALL_TOP
>> wall
);
223 static void create_maze(HWND hWnd
) /* create a maze layout given the initialized maze */
225 register int i
, newdoor
= 0;
228 move_list
[sqnum
].x
= cur_sq_x
;
229 move_list
[sqnum
].y
= cur_sq_y
;
230 move_list
[sqnum
].dir
= newdoor
;
231 while ((newdoor
= choose_door(hDC
)) == -1) { /* pick a door */
232 if (backup() == -1) { /* no more doors ... backup */
233 return; /* done ... return */
237 /* mark the out door */
238 maze
[cur_sq_x
][cur_sq_y
] |= (DOOR_OUT_TOP
>> newdoor
);
252 /* mark the in door */
253 maze
[cur_sq_x
][cur_sq_y
] |= (DOOR_IN_TOP
>> ((newdoor
+ 2) % 4));
255 /* if end square set path length and save path */
256 if (maze
[cur_sq_x
][cur_sq_y
] & END_SQUARE
) {
258 for (i
= 0; i
< path_length
; i
++) {
259 save_path
[i
].x
= move_list
[i
].x
;
260 save_path
[i
].y
= move_list
[i
].y
;
261 save_path
[i
].dir
= move_list
[i
].dir
;
267 static int choose_door(HDC hDC
) /* pick a new path */
270 register int num_candidates
;
275 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_IN_TOP
)
277 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_OUT_TOP
)
279 if (maze
[cur_sq_x
][cur_sq_y
] & WALL_TOP
)
281 if (maze
[cur_sq_x
][cur_sq_y
- 1] & DOOR_IN_ANY
) {
282 maze
[cur_sq_x
][cur_sq_y
] |= WALL_TOP
;
283 maze
[cur_sq_x
][cur_sq_y
- 1] |= WALL_BOTTOM
;
284 draw_wall(cur_sq_x
, cur_sq_y
, 0, hDC
);
287 candidates
[num_candidates
++] = 0;
291 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_IN_RIGHT
)
293 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_OUT_RIGHT
)
295 if (maze
[cur_sq_x
][cur_sq_y
] & WALL_RIGHT
)
297 if (maze
[cur_sq_x
+ 1][cur_sq_y
] & DOOR_IN_ANY
) {
298 maze
[cur_sq_x
][cur_sq_y
] |= WALL_RIGHT
;
299 maze
[cur_sq_x
+ 1][cur_sq_y
] |= WALL_LEFT
;
300 draw_wall(cur_sq_x
, cur_sq_y
, 1, hDC
);
303 candidates
[num_candidates
++] = 1;
307 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_IN_BOTTOM
)
309 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_OUT_BOTTOM
)
311 if (maze
[cur_sq_x
][cur_sq_y
] & WALL_BOTTOM
)
313 if (maze
[cur_sq_x
][cur_sq_y
+ 1] & DOOR_IN_ANY
) {
314 maze
[cur_sq_x
][cur_sq_y
] |= WALL_BOTTOM
;
315 maze
[cur_sq_x
][cur_sq_y
+ 1] |= WALL_TOP
;
316 draw_wall(cur_sq_x
, cur_sq_y
, 2, hDC
);
319 candidates
[num_candidates
++] = 2;
323 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_IN_LEFT
)
325 if (maze
[cur_sq_x
][cur_sq_y
] & DOOR_OUT_LEFT
)
327 if (maze
[cur_sq_x
][cur_sq_y
] & WALL_LEFT
)
329 if (maze
[cur_sq_x
- 1][cur_sq_y
] & DOOR_IN_ANY
) {
330 maze
[cur_sq_x
][cur_sq_y
] |= WALL_LEFT
;
331 maze
[cur_sq_x
- 1][cur_sq_y
] |= WALL_RIGHT
;
332 draw_wall(cur_sq_x
, cur_sq_y
, 3, hDC
);
335 candidates
[num_candidates
++] = 3;
338 if (num_candidates
== 0)
340 if (num_candidates
== 1)
341 return candidates
[0];
342 return candidates
[get_random(num_candidates
)];
346 static long backup() /* back up a move */
350 cur_sq_x
= move_list
[sqnum
].x
;
351 cur_sq_y
= move_list
[sqnum
].y
;
356 static void draw_solid_square(i
, j
, dir
, hDC
, hBrush
) /* draw a solid square in a square */
357 register int i
, j
, dir
;
365 rc
.left
= border_x
+ bw
+ grid_width
* i
;
366 rc
.right
= rc
.left
+ grid_width
- (bw
+ bw
);
367 rc
.top
= border_y
- bw
+ grid_height
* j
;
368 rc
.bottom
= rc
.top
+ grid_height
;
371 rc
.left
= border_x
+ bw
+ grid_width
* i
;
372 rc
.right
= rc
.left
+ grid_width
;
373 rc
.top
= border_y
+ bw
+ grid_height
* j
;
374 rc
.bottom
= rc
.top
+ grid_height
- (bw
+ bw
);
377 rc
.left
= border_x
+ bw
+ grid_width
* i
;
378 rc
.right
= rc
.left
+ grid_width
- (bw
+ bw
);
379 rc
.top
= border_y
+ bw
+ grid_height
* j
;
380 rc
.bottom
= rc
.top
+ grid_height
;
383 rc
.left
= border_x
- bw
+ grid_width
* i
;
384 rc
.right
= rc
.left
+ grid_width
;
385 rc
.top
= border_y
+ bw
+ grid_height
* j
;
386 rc
.bottom
= rc
.top
+ grid_height
- (bw
+ bw
);
389 (void) FillRect(hDC
, &rc
, hBrush
);
392 static void draw_maze_border(HWND hWnd
) /* draw the maze outline */
397 SelectObject(hDC
, hPenWall
);
399 for (i
= 0; i
< maze_size_x
; i
++) {
400 if (maze
[i
][0] & WALL_TOP
) {
401 MoveToEx(hDC
, border_x
+ grid_width
* i
, border_y
, NULL
);
402 (void) LineTo(hDC
, border_x
+ grid_width
* (i
+ 1) - 1, border_y
);
404 if ((maze
[i
][maze_size_y
- 1] & WALL_BOTTOM
)) {
405 MoveToEx(hDC
, border_x
+ grid_width
* i
, border_y
+ grid_height
* (maze_size_y
) -1, NULL
);
406 (void) LineTo(hDC
, border_x
+ grid_width
* (i
+ 1) - 1, border_y
+ grid_height
* (maze_size_y
) -1);
409 for (j
= 0; j
< maze_size_y
; j
++) {
410 if (maze
[maze_size_x
- 1][j
] & WALL_RIGHT
) {
411 MoveToEx(hDC
, border_x
+ grid_width
* maze_size_x
- 1, border_y
+ grid_height
* j
, NULL
);
412 (void) LineTo(hDC
, border_x
+ grid_width
* maze_size_x
- 1, border_y
+ grid_height
* (j
+ 1) - 1);
414 if (maze
[0][j
] & WALL_LEFT
) {
415 MoveToEx(hDC
, border_x
, border_y
+ grid_height
* j
, NULL
);
416 (void) LineTo(hDC
, border_x
, border_y
+ grid_height
* (j
+ 1) - 1);
420 hBrush
= GetStockObject(WHITE_BRUSH
); // FIXME: do not hardcode
421 draw_solid_square(start_x
, start_y
, start_dir
, hDC
, hBrush
);
422 draw_solid_square(end_x
, end_y
, end_dir
, hDC
, hBrush
);
425 static void draw_wall(i
, j
, dir
, hDC
) /* draw a single wall */
426 register int i
, j
, dir
;
429 SelectObject(hDC
, hPenWall
);
433 MoveToEx(hDC
, border_x
+ grid_width
* i
, border_y
+ grid_height
* j
, NULL
);
434 (void) LineTo(hDC
, border_x
+ grid_width
* (i
+ 1), border_y
+ grid_height
* j
);
437 MoveToEx(hDC
, border_x
+ grid_width
* (i
+ 1), border_y
+ grid_height
* j
, NULL
);
438 (void) LineTo(hDC
, border_x
+ grid_width
* (i
+ 1), border_y
+ grid_height
* (j
+ 1));
441 MoveToEx(hDC
, border_x
+ grid_width
* i
, border_y
+ grid_height
* (j
+ 1), NULL
);
442 (void) LineTo(hDC
, border_x
+ grid_width
* (i
+ 1), border_y
+ grid_height
* (j
+ 1));
445 MoveToEx(hDC
, border_x
+ grid_width
* i
, border_y
+ grid_height
* j
, NULL
);
446 (void) LineTo(hDC
, border_x
+ grid_width
* i
, border_y
+ grid_height
* (j
+ 1));
451 static void begin_solve_maze(HWND hWnd
) /* solve it with graphical feedback */
453 /* plug up the surrounding wall */
454 maze
[start_x
][start_y
] |= (WALL_TOP
>> start_dir
);
455 maze
[end_x
][end_y
] |= (WALL_TOP
>> end_dir
);
457 /* initialize search path */
459 path
[pathi
].x
= end_x
;
460 path
[pathi
].y
= end_y
;
461 path
[pathi
].dir
= -1;
464 static int solve_maze(HWND hWnd
) /* solve it with graphical feedback */
471 if (++path
[pathi
].dir
>= 4) {
473 draw_solid_square((int) (path
[pathi
].x
), (int) (path
[pathi
].y
), (int) (path
[pathi
].dir
), hDC
, hBrushDead
);
476 else if (!(maze
[path
[pathi
].x
][path
[pathi
].y
] & (WALL_TOP
>> path
[pathi
].dir
)) &&
477 ((pathi
== 0) || ((path
[pathi
].dir
!= (int) (path
[pathi
- 1].dir
+ 2) % 4)))) {
478 enter_square(pathi
, hDC
, hBrushLiving
);
480 if (maze
[path
[pathi
].x
][path
[pathi
].y
] & START_SQUARE
) {
491 } while (!action_done
);
495 static void enter_square(int n
, HDC hDC
, HBRUSH hBrush
) /* move into a neighboring square */
497 draw_solid_square((int) path
[n
].x
, (int) path
[n
].y
, (int) path
[n
].dir
, hDC
, hBrush
);
499 path
[n
+ 1].dir
= -1;
500 switch (path
[n
].dir
) {
501 case 0: path
[n
+ 1].x
= path
[n
].x
;
502 path
[n
+ 1].y
= path
[n
].y
- 1;
504 case 1: path
[n
+ 1].x
= path
[n
].x
+ 1;
505 path
[n
+ 1].y
= path
[n
].y
;
507 case 2: path
[n
+ 1].x
= path
[n
].x
;
508 path
[n
+ 1].y
= path
[n
].y
+ 1;
510 case 3: path
[n
+ 1].x
= path
[n
].x
- 1;
511 path
[n
+ 1].y
= path
[n
].y
;
516 static void start_timer(HWND hWnd
, int iTimeout
)
518 SetTimer(hWnd
, 1, iTimeout
, NULL
);
521 static BOOL
OnCreate(HWND hWnd
, LPCREATESTRUCT lpCreateStruct
)
525 srand((unsigned) time(NULL
));
527 size
= GetPrivateProfileIntW(L
"maze", L
"gridsize", 10, L
"maze.ini");
528 pre_solve_delay
= GetPrivateProfileIntW(L
"maze", L
"predelay", 5000, L
"maze.ini");
529 post_solve_delay
= GetPrivateProfileIntW(L
"maze", L
"postdelay", 5000, L
"maze.ini");
530 solve_delay
= GetPrivateProfileIntW(L
"maze", L
"solvedelay", 1, L
"maze.ini");
533 size
= 7 + (rand() % 30);
535 grid_width
= grid_height
= size
;
536 bw
= (size
> 6 ? 3 : (size
- 1) / 2);
539 /* FIXME Pattern brushes not yet implemented in ReactOS */
541 static long grayPattern
[] = {
551 static RGBQUAD argbq
[] = {
557 pbmi
= malloc(sizeof(BITMAPINFOHEADER
) + sizeof(argbq
) + sizeof(grayPattern
));
558 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
559 pbmi
->bmiHeader
.biWidth
= 8;
560 pbmi
->bmiHeader
.biHeight
= 8;
561 pbmi
->bmiHeader
.biPlanes
= 1;
562 pbmi
->bmiHeader
.biBitCount
= 1;
563 pbmi
->bmiHeader
.biCompression
= BI_RGB
;
564 (void) memcpy(pbmi
->bmiColors
, argbq
, sizeof(argbq
));
565 (void) memcpy(pbmi
->bmiColors
+ 2, grayPattern
, sizeof(grayPattern
));
566 hBrushDead
= CreateDIBPatternBrushPt(pbmi
, DIB_RGB_COLORS
);
567 // hBrushDead = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 0));
571 hBrushDead
= CreateSolidBrush(RGB(255, 0, 0));
573 hBrushLiving
= CreateSolidBrush(RGB(0, 255, 0));
574 hPenWall
= CreatePen(PS_SOLID
, 3, RGB(150, 150, 150));
578 start_timer(hWnd
, 1);
583 LRESULT CALLBACK
ScreenSaverProc(
584 HWND hWnd
, // window handle
585 UINT message
, // type of message
586 WPARAM wParam
, // additional information
587 LPARAM lParam
) // additional information
592 OnCreate(hWnd
, (LPCREATESTRUCT
) lParam
);
595 set_maze_sizes(LOWORD(lParam
), HIWORD(lParam
));
601 begin_solve_maze(hWnd
);
605 start_timer(hWnd
, solve_delay
);
609 if (!solve_maze(hWnd
))
611 start_timer(hWnd
, solve_delay
);
616 start_timer(hWnd
, post_solve_delay
);
623 SendMessage(hWnd
, WM_ERASEBKGND
, (WPARAM
) hDC
, (LPARAM
) 0);
624 draw_maze_border(hWnd
);
630 start_timer(hWnd
, pre_solve_delay
);
635 case WM_DESTROY
: // message: window being destroyed
636 DeleteObject(hBrushLiving
);
637 DeleteObject(hBrushDead
);
638 ReleaseDC(hWnd
, hDC
);
641 default: // Passes it on if unproccessed
642 return DefScreenSaverProc(hWnd
, message
, wParam
, lParam
);
647 BOOL WINAPI
ScreenSaverConfigureDialog(HWND hWnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
652 BOOL WINAPI
RegisterDialogClasses(HANDLE hmodule
)
657 LoadString(hmodule
, IDS_TITLE
, szTitle
, 256);
659 LoadString(hmodule
, IDS_TEXT
, szText
, 256);
661 MessageBox(0, szText
, szTitle
, MB_OK
| MB_ICONWARNING
);