[MAZESCR]
[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 <windows.h> /* required for all Windows applications */
53 #include <scrnsave.h>
54 #include <tchar.h>
55 #include <stdlib.h>
56 #include <commctrl.h>
57 #include <string.h>
58 #include <time.h>
59 #include "resource.h"
60
61 #define APPNAME _T("Maze")
62
63 LRESULT CALLBACK ScreenSaverProc(HWND hWnd, UINT message, WPARAM uParam, LPARAM lParam);
64 static int choose_door();
65 static long backup();
66 static void draw_wall();
67 static void draw_solid_square(int, int, int, HDC, HBRUSH);
68 static void enter_square(int, HDC, HBRUSH);
69
70 extern HINSTANCE hMainInstance; /* current instance */
71 HBRUSH hBrushDead;
72 HBRUSH hBrushLiving;
73 HPEN hPenWall;
74 HDC hDC;
75
76 static int solve_delay, pre_solve_delay, post_solve_delay, size;
77
78 #define MAX_MAZE_SIZE_X ((unsigned long) 1000) // Dynamic detection?
79 #define MAX_MAZE_SIZE_Y ((unsigned long) 1000) // Dynamic detection?
80
81 #define MOVE_LIST_SIZE (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
82
83 #define WALL_TOP 0x8000
84 #define WALL_RIGHT 0x4000
85 #define WALL_BOTTOM 0x2000
86 #define WALL_LEFT 0x1000
87
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
93
94 #define DOOR_OUT_TOP 0x80
95 #define DOOR_OUT_RIGHT 0x40
96 #define DOOR_OUT_BOTTOM 0x20
97 #define DOOR_OUT_LEFT 0x10
98
99 #define START_SQUARE 0x2
100 #define END_SQUARE 0x1
101
102 #define border_x (0)
103 #define border_y (0)
104
105 #define get_random(x) (rand() % (x))
106
107 static unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
108
109 static struct {
110 unsigned int x;
111 unsigned int y;
112 unsigned int dir;
113 } move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
114
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;
120 static int bw;
121 static int state = 1, pathi = 0;
122 static LPCWSTR registryPath = _T("Software\\Microsoft\\ScreenSavers\\mazescr");
123
124 static void SetDefaults()
125 {
126 size = 10;
127 pre_solve_delay = 5000;
128 post_solve_delay = 5000;
129 solve_delay = 1;
130 }
131
132 static void ReadRegistry()
133 {
134 LONG result;
135 HKEY skey;
136 DWORD valuetype, valuesize, val_size, val_presd, val_postsd, val_sd;
137
138 SetDefaults();
139
140 result = RegOpenKeyEx(HKEY_CURRENT_USER, registryPath, 0, KEY_READ, &skey);
141 if(result != ERROR_SUCCESS)
142 return;
143
144 valuesize = sizeof(DWORD);
145
146 result = RegQueryValueEx(skey, _T("size"), NULL, &valuetype, (LPBYTE)&val_size, &valuesize);
147 if(result == ERROR_SUCCESS)
148 size = val_size;
149 result = RegQueryValueEx(skey, _T("pre_solve_delay"), NULL, &valuetype, (LPBYTE)&val_presd, &valuesize);
150 if(result == ERROR_SUCCESS)
151 pre_solve_delay = val_presd;
152 result = RegQueryValueEx(skey, _T("post_solve_delay"), NULL, &valuetype, (LPBYTE)&val_postsd, &valuesize);
153 if(result == ERROR_SUCCESS)
154 post_solve_delay = val_postsd;
155 result = RegQueryValueEx(skey, _T("solve_delay"), NULL, &valuetype, (LPBYTE)&val_sd, &valuesize);
156 if(result == ERROR_SUCCESS)
157 solve_delay = val_sd;
158
159 RegCloseKey(skey);
160 }
161
162 static void WriteRegistry()
163 {
164 LONG result;
165 HKEY skey;
166 DWORD disp;
167
168 result = RegCreateKeyEx(HKEY_CURRENT_USER, registryPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &skey, &disp);
169 if(result != ERROR_SUCCESS)
170 return;
171
172 RegSetValueEx(skey, _T("size"), 0, REG_DWORD, (LPBYTE)&size, sizeof(size));
173 RegSetValueEx(skey, _T("pre_solve_delay"), 0, REG_DWORD, (LPBYTE)&pre_solve_delay, sizeof(pre_solve_delay));
174 RegSetValueEx(skey, _T("post_solve_delay"), 0, REG_DWORD, (LPBYTE)&post_solve_delay, sizeof(post_solve_delay));
175 RegSetValueEx(skey, _T("solve_delay"), 0, REG_DWORD, (LPBYTE)&solve_delay, sizeof(solve_delay));
176
177 RegCloseKey(skey);
178 }
179
180 static void set_maze_sizes(width, height)
181 int width, height;
182 {
183 maze_size_x = (width -1)/ grid_width;
184 maze_size_y = (height-1) / grid_height;
185 if (maze_size_x > MAX_MAZE_SIZE_X)
186 maze_size_x = MAX_MAZE_SIZE_X;
187 if (maze_size_y > MAX_MAZE_SIZE_Y)
188 maze_size_y = MAX_MAZE_SIZE_Y;
189 }
190
191 static void initialize_maze() /* draw the surrounding wall and start/end squares */
192 {
193 register int i, j, wall;
194
195 /* initialize all squares */
196 for (i = 0; i < maze_size_x; i++) {
197 for (j = 0; j < maze_size_y; j++) {
198 maze[i][j] = 0;
199 }
200 }
201
202 /* top wall */
203 for (i = 0; i < maze_size_x; i++) {
204 maze[i][0] |= WALL_TOP;
205 }
206
207 /* right wall */
208 for (j = 0; j < maze_size_y; j++) {
209 maze[maze_size_x - 1][j] |= WALL_RIGHT;
210 }
211
212 /* bottom wall */
213 for (i = 0; i < maze_size_x; i++) {
214 maze[i][maze_size_y - 1] |= WALL_BOTTOM;
215 }
216
217 /* left wall */
218 for (j = 0; j < maze_size_y; j++) {
219 maze[0][j] |= WALL_LEFT;
220 }
221
222 /* set start square */
223 wall = get_random(4);
224 switch (wall) {
225 case 0:
226 i = get_random(maze_size_x);
227 j = 0;
228 break;
229 case 1:
230 i = maze_size_x - 1;
231 j = get_random(maze_size_y);
232 break;
233 case 2:
234 i = get_random(maze_size_x);
235 j = maze_size_y - 1;
236 break;
237 case 3:
238 i = 0;
239 j = get_random(maze_size_y);
240 break;
241 }
242 maze[i][j] |= START_SQUARE;
243 maze[i][j] |= (DOOR_IN_TOP >> wall);
244 maze[i][j] &= ~(WALL_TOP >> wall);
245 cur_sq_x = i;
246 cur_sq_y = j;
247 start_x = i;
248 start_y = j;
249 start_dir = wall;
250 sqnum = 0;
251
252 /* set end square */
253 wall = (wall + 2) % 4;
254 switch (wall) {
255 case 0:
256 i = get_random(maze_size_x);
257 j = 0;
258 break;
259 case 1:
260 i = maze_size_x - 1;
261 j = get_random(maze_size_y);
262 break;
263 case 2:
264 i = get_random(maze_size_x);
265 j = maze_size_y - 1;
266 break;
267 case 3:
268 i = 0;
269 j = get_random(maze_size_y);
270 break;
271 }
272 maze[i][j] |= END_SQUARE;
273 maze[i][j] |= (DOOR_OUT_TOP >> wall);
274 maze[i][j] &= ~(WALL_TOP >> wall);
275 end_x = i;
276 end_y = j;
277 end_dir = wall;
278 }
279
280 static void create_maze(HWND hWnd) /* create a maze layout given the initialized maze */
281 {
282 register int i, newdoor = 0;
283
284 do {
285 move_list[sqnum].x = cur_sq_x;
286 move_list[sqnum].y = cur_sq_y;
287 move_list[sqnum].dir = newdoor;
288 while ((newdoor = choose_door(hDC)) == -1) { /* pick a door */
289 if (backup() == -1) { /* no more doors ... backup */
290 return; /* done ... return */
291 }
292 }
293
294 /* mark the out door */
295 maze[cur_sq_x][cur_sq_y] |= (DOOR_OUT_TOP >> newdoor);
296
297 switch (newdoor) {
298 case 0: cur_sq_y--;
299 break;
300 case 1: cur_sq_x++;
301 break;
302 case 2: cur_sq_y++;
303 break;
304 case 3: cur_sq_x--;
305 break;
306 }
307 sqnum++;
308
309 /* mark the in door */
310 maze[cur_sq_x][cur_sq_y] |= (DOOR_IN_TOP >> ((newdoor + 2) % 4));
311
312 /* if end square set path length and save path */
313 if (maze[cur_sq_x][cur_sq_y] & END_SQUARE) {
314 path_length = sqnum;
315 for (i = 0; i < path_length; i++) {
316 save_path[i].x = move_list[i].x;
317 save_path[i].y = move_list[i].y;
318 save_path[i].dir = move_list[i].dir;
319 }
320 }
321 } while (1);
322 }
323
324 static int choose_door(HDC hDC) /* pick a new path */
325 {
326 int candidates[3];
327 register int num_candidates;
328
329 num_candidates = 0;
330
331 /* top wall */
332 if (maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP)
333 goto rightwall;
334 if (maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP)
335 goto rightwall;
336 if (maze[cur_sq_x][cur_sq_y] & WALL_TOP)
337 goto rightwall;
338 if (maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY) {
339 maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
340 maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
341 draw_wall(cur_sq_x, cur_sq_y, 0, hDC);
342 goto rightwall;
343 }
344 candidates[num_candidates++] = 0;
345
346 rightwall:
347 /* right wall */
348 if (maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT)
349 goto bottomwall;
350 if (maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT)
351 goto bottomwall;
352 if (maze[cur_sq_x][cur_sq_y] & WALL_RIGHT)
353 goto bottomwall;
354 if (maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY) {
355 maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
356 maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
357 draw_wall(cur_sq_x, cur_sq_y, 1, hDC);
358 goto bottomwall;
359 }
360 candidates[num_candidates++] = 1;
361
362 bottomwall:
363 /* bottom wall */
364 if (maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM)
365 goto leftwall;
366 if (maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM)
367 goto leftwall;
368 if (maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM)
369 goto leftwall;
370 if (maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY) {
371 maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
372 maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
373 draw_wall(cur_sq_x, cur_sq_y, 2, hDC);
374 goto leftwall;
375 }
376 candidates[num_candidates++] = 2;
377
378 leftwall:
379 /* left wall */
380 if (maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT)
381 goto donewall;
382 if (maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT)
383 goto donewall;
384 if (maze[cur_sq_x][cur_sq_y] & WALL_LEFT)
385 goto donewall;
386 if (maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY) {
387 maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
388 maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
389 draw_wall(cur_sq_x, cur_sq_y, 3, hDC);
390 goto donewall;
391 }
392 candidates[num_candidates++] = 3;
393
394 donewall:
395 if (num_candidates == 0)
396 return -1;
397 if (num_candidates == 1)
398 return candidates[0];
399 return candidates[get_random(num_candidates)];
400
401 }
402
403 static long backup() /* back up a move */
404 {
405 sqnum--;
406 if (0 <= sqnum) {
407 cur_sq_x = move_list[sqnum].x;
408 cur_sq_y = move_list[sqnum].y;
409 }
410 return sqnum;
411 }
412
413 static void draw_solid_square(i, j, dir, hDC, hBrush) /* draw a solid square in a square */
414 register int i, j, dir;
415 HDC hDC;
416 HBRUSH hBrush;
417 {
418 RECT rc;
419
420 switch (dir) {
421 case 0:
422 rc.left = border_x + bw + grid_width * i;
423 rc.right = rc.left + grid_width - (bw + bw);
424 rc.top = border_y - bw + grid_height * j;
425 rc.bottom = rc.top + grid_height;
426 break;
427 case 1:
428 rc.left = border_x + bw + grid_width * i;
429 rc.right = rc.left + grid_width;
430 rc.top = border_y + bw + grid_height * j;
431 rc.bottom = rc.top + grid_height - (bw + bw);
432 break;
433 case 2:
434 rc.left = border_x + bw + grid_width * i;
435 rc.right = rc.left + grid_width - (bw + bw);
436 rc.top = border_y + bw + grid_height * j;
437 rc.bottom = rc.top + grid_height;
438 break;
439 case 3:
440 rc.left = border_x - bw + grid_width * i;
441 rc.right = rc.left + grid_width;
442 rc.top = border_y + bw + grid_height * j;
443 rc.bottom = rc.top + grid_height - (bw + bw);
444 break;
445 }
446 (void) FillRect(hDC, &rc, hBrush);
447 }
448
449 static void draw_maze_border(HWND hWnd) /* draw the maze outline */
450 {
451 register int i, j;
452 HBRUSH hBrush;
453
454 SelectObject(hDC, hPenWall);
455
456 for (i = 0; i < maze_size_x; i++) {
457 if (maze[i][0] & WALL_TOP) {
458 MoveToEx(hDC, border_x + grid_width * i, border_y, NULL);
459 (void) LineTo(hDC, border_x + grid_width * (i + 1) - 1, border_y);
460 }
461 if ((maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
462 MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * (maze_size_y) -1, NULL);
463 (void) LineTo(hDC, border_x + grid_width * (i + 1) - 1, border_y + grid_height * (maze_size_y) -1);
464 }
465 }
466 for (j = 0; j < maze_size_y; j++) {
467 if (maze[maze_size_x - 1][j] & WALL_RIGHT) {
468 MoveToEx(hDC, border_x + grid_width * maze_size_x - 1, border_y + grid_height * j, NULL);
469 (void) LineTo(hDC, border_x + grid_width * maze_size_x - 1, border_y + grid_height * (j + 1) - 1);
470 }
471 if (maze[0][j] & WALL_LEFT) {
472 MoveToEx(hDC, border_x, border_y + grid_height * j, NULL);
473 (void) LineTo(hDC, border_x, border_y + grid_height * (j + 1) - 1);
474 }
475 }
476
477 hBrush = GetStockObject(WHITE_BRUSH);
478 draw_solid_square(start_x, start_y, start_dir, hDC, hBrush);
479 draw_solid_square(end_x, end_y, end_dir, hDC, hBrush);
480 }
481
482 static void draw_wall(i, j, dir, hDC) /* draw a single wall */
483 register int i, j, dir;
484 HDC hDC;
485 {
486 SelectObject(hDC, hPenWall);
487
488 switch (dir) {
489 case 0:
490 MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j, NULL);
491 (void) LineTo(hDC, border_x + grid_width * (i + 1), border_y + grid_height * j);
492 break;
493 case 1:
494 MoveToEx(hDC, border_x + grid_width * (i + 1), border_y + grid_height * j, NULL);
495 (void) LineTo(hDC, border_x + grid_width * (i + 1), border_y + grid_height * (j + 1));
496 break;
497 case 2:
498 MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * (j + 1), NULL);
499 (void) LineTo(hDC, border_x + grid_width * (i + 1), border_y + grid_height * (j + 1));
500 break;
501 case 3:
502 MoveToEx(hDC, border_x + grid_width * i, border_y + grid_height * j, NULL);
503 (void) LineTo(hDC, border_x + grid_width * i, border_y + grid_height * (j + 1));
504 break;
505 }
506 }
507
508 static void begin_solve_maze(HWND hWnd) /* solve it with graphical feedback */
509 {
510 /* plug up the surrounding wall */
511 maze[start_x][start_y] |= (WALL_TOP >> start_dir);
512 maze[end_x][end_y] |= (WALL_TOP >> end_dir);
513
514 /* initialize search path */
515 pathi = 0;
516 path[pathi].x = end_x;
517 path[pathi].y = end_y;
518 path[pathi].dir = -1;
519 }
520
521 static int solve_maze(HWND hWnd) /* solve it with graphical feedback */
522 {
523 int ret;
524 int action_done;
525
526 do {
527 action_done = 1;
528 if (++path[pathi].dir >= 4) {
529 pathi--;
530 draw_solid_square((int) (path[pathi].x), (int) (path[pathi].y), (int) (path[pathi].dir), hDC, hBrushDead);
531 ret = 0;
532 }
533 else if (!(maze[path[pathi].x][path[pathi].y] & (WALL_TOP >> path[pathi].dir)) &&
534 ((pathi == 0) || ((path[pathi].dir != (int) (path[pathi - 1].dir + 2) % 4)))) {
535 enter_square(pathi, hDC, hBrushLiving);
536 pathi++;
537 if (maze[path[pathi].x][path[pathi].y] & START_SQUARE) {
538
539 ret = 1;
540 }
541 else {
542 ret = 0;
543 }
544 }
545 else {
546 action_done = 0;
547 }
548 } while (!action_done);
549 return ret;
550 }
551
552 static void enter_square(int n, HDC hDC, HBRUSH hBrush) /* move into a neighboring square */
553 {
554 draw_solid_square((int) path[n].x, (int) path[n].y, (int) path[n].dir, hDC, hBrush);
555
556 path[n + 1].dir = -1;
557 switch (path[n].dir) {
558 case 0: path[n + 1].x = path[n].x;
559 path[n + 1].y = path[n].y - 1;
560 break;
561 case 1: path[n + 1].x = path[n].x + 1;
562 path[n + 1].y = path[n].y;
563 break;
564 case 2: path[n + 1].x = path[n].x;
565 path[n + 1].y = path[n].y + 1;
566 break;
567 case 3: path[n + 1].x = path[n].x - 1;
568 path[n + 1].y = path[n].y;
569 break;
570 }
571 }
572
573 static void start_timer(HWND hWnd, int iTimeout)
574 {
575 SetTimer(hWnd, 1, iTimeout, NULL);
576 }
577
578 static BOOL OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
579 {
580 srand((unsigned) time(NULL));
581
582 ReadRegistry();
583
584 if (size < 2) {
585 size = 7 + (rand() % 30);
586 }
587 grid_width = grid_height = size;
588 bw = (size > 6 ? 3 : (size - 1) / 2);
589
590 #if 0
591 /* FIXME Pattern brushes not yet implemented in ReactOS */
592 {
593 static long grayPattern [] = {
594 0x55555555,
595 0xaaaaaaaa,
596 0x55555555,
597 0xaaaaaaaa,
598 0x55555555,
599 0xaaaaaaaa,
600 0x55555555,
601 0xaaaaaaaa
602 };
603 static RGBQUAD argbq [] = {
604 { 0, 0, 255, 0 },
605 { 255, 255, 255, 0 }
606 };
607 BITMAPINFO *pbmi;
608
609 pbmi = malloc(sizeof(BITMAPINFOHEADER) + sizeof(argbq) + sizeof(grayPattern));
610 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
611 pbmi->bmiHeader.biWidth = 8;
612 pbmi->bmiHeader.biHeight = 8;
613 pbmi->bmiHeader.biPlanes = 1;
614 pbmi->bmiHeader.biBitCount = 1;
615 pbmi->bmiHeader.biCompression = BI_RGB;
616 (void) memcpy(pbmi->bmiColors, argbq, sizeof(argbq));
617 (void) memcpy(pbmi->bmiColors + 2, grayPattern, sizeof(grayPattern));
618 hBrushDead = CreateDIBPatternBrushPt(pbmi, DIB_RGB_COLORS);
619 // hBrushDead = CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 0));
620 free(pbmi);
621 }
622 #else
623 hBrushDead = CreateSolidBrush(RGB(255, 0, 0));
624 #endif
625 hBrushLiving = CreateSolidBrush(RGB(0, 255, 0));
626 hPenWall = CreatePen(PS_SOLID, 3, RGB(150, 150, 150));
627
628 hDC = GetDC(hWnd);
629
630 start_timer(hWnd, 1);
631
632 return TRUE;
633 }
634
635 BOOL WINAPI AboutProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
636 {
637 switch(message){
638 case WM_COMMAND:
639 switch(LOWORD(wparam)){
640 case IDOK:
641 EndDialog(hWnd, LOWORD(wparam));
642 return TRUE;
643 }
644 }
645 return FALSE;
646 }
647
648 static void ReadSettings(HWND hWnd)
649 {
650 size = SendDlgItemMessage(hWnd, IDC_SLIDER_SIZE, TBM_GETPOS, 0, 0);
651 SetDlgItemInt(hWnd, IDC_TEXT_SIZE, size, FALSE);
652
653 pre_solve_delay = SendDlgItemMessage(hWnd, IDC_SLIDER_PRESD, TBM_GETPOS, 0, 0);
654 SetDlgItemInt(hWnd, IDC_TEXT_PRESD, pre_solve_delay, FALSE);
655
656 post_solve_delay = SendDlgItemMessage(hWnd, IDC_SLIDER_POSTSD, TBM_GETPOS, 0, 0);
657 SetDlgItemInt(hWnd, IDC_TEXT_POSTSD, post_solve_delay, FALSE);
658
659 solve_delay = SendDlgItemMessage(hWnd, IDC_SLIDER_SD, TBM_GETPOS, 0, 0);
660 SetDlgItemInt(hWnd, IDC_TEXT_SD, solve_delay, FALSE);
661 }
662
663 LRESULT CALLBACK ScreenSaverProc(
664 HWND hWnd, // window handle
665 UINT message, // type of message
666 WPARAM wParam, // additional information
667 LPARAM lParam) // additional information
668 {
669 switch (message)
670 {
671 case WM_CREATE:
672 OnCreate(hWnd, (LPCREATESTRUCT) lParam);
673 break;
674 case WM_SIZE:
675 set_maze_sizes(LOWORD(lParam), HIWORD(lParam));
676 break;
677 case WM_TIMER:
678 switch (state)
679 {
680 case 2:
681 begin_solve_maze(hWnd);
682
683 state = 3;
684
685 start_timer(hWnd, solve_delay);
686 break;
687
688 case 3:
689 if (!solve_maze(hWnd))
690 {
691 start_timer(hWnd, solve_delay);
692 }
693 else
694 {
695 state = 1;
696 start_timer(hWnd, post_solve_delay);
697 }
698 break;
699
700 default:
701 initialize_maze();
702
703 SendMessage(hWnd, WM_ERASEBKGND, (WPARAM) hDC, (LPARAM) 0);
704 draw_maze_border(hWnd);
705
706 create_maze(hWnd);
707
708 state = 2;
709
710 start_timer(hWnd, pre_solve_delay);
711 break;
712 }
713 break;
714
715 case WM_DESTROY: // message: window being destroyed
716 DeleteObject(hBrushLiving);
717 DeleteObject(hBrushDead);
718 ReleaseDC(hWnd, hDC);
719 break;
720
721 default: // Passes it on if unproccessed
722 return DefScreenSaverProc(hWnd, message, wParam, lParam);
723 }
724 return 0;
725 }
726
727 BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
728 {
729 switch (message)
730 {
731 case WM_INITDIALOG:
732 ReadRegistry();
733 //Set slider ranges
734 SendDlgItemMessage(hWnd, IDC_SLIDER_SIZE, TBM_SETRANGE, FALSE, MAKELPARAM(5, 64));
735 SendDlgItemMessage(hWnd, IDC_SLIDER_PRESD, TBM_SETRANGE, FALSE, MAKELPARAM(1, 10000));
736 SendDlgItemMessage(hWnd, IDC_SLIDER_POSTSD, TBM_SETRANGE, FALSE, MAKELPARAM(1, 10000));
737 SendDlgItemMessage(hWnd, IDC_SLIDER_SD, TBM_SETRANGE, FALSE, MAKELPARAM(1, 10000));
738 //Set current values to slider
739 SendDlgItemMessage(hWnd, IDC_SLIDER_SIZE, TBM_SETPOS, TRUE, size);
740 SendDlgItemMessage(hWnd, IDC_SLIDER_PRESD, TBM_SETPOS, TRUE, pre_solve_delay);
741 SendDlgItemMessage(hWnd, IDC_SLIDER_POSTSD, TBM_SETPOS, TRUE, post_solve_delay);
742 SendDlgItemMessage(hWnd, IDC_SLIDER_SD, TBM_SETPOS, TRUE, solve_delay);
743 //Set current values to texts
744 SetDlgItemInt(hWnd, IDC_TEXT_SIZE, size, FALSE);
745 SetDlgItemInt(hWnd, IDC_TEXT_PRESD, pre_solve_delay, FALSE);
746 SetDlgItemInt(hWnd, IDC_TEXT_POSTSD, post_solve_delay, FALSE);
747 SetDlgItemInt(hWnd, IDC_TEXT_SD, solve_delay, FALSE);
748 return TRUE;
749 case WM_COMMAND:
750 switch (LOWORD(wparam))
751 {
752 case IDOK:
753 WriteRegistry();
754 EndDialog(hWnd, TRUE);
755 return TRUE;
756 case IDCANCEL:
757 EndDialog(hWnd, TRUE);
758 break;
759 case IDABOUT:
760 DialogBox(hMainInstance, MAKEINTRESOURCE(IDD_DLG_ABOUT), hWnd, (DLGPROC)AboutProc);
761 break;
762 }
763 case WM_HSCROLL:
764 ReadSettings(hWnd);
765 return TRUE;
766 }
767 return FALSE;
768 }
769
770 BOOL WINAPI RegisterDialogClasses(HANDLE hmodule)
771 {
772 return TRUE;
773 }