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 INT_PTR CALLBACK 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 case 3: 688 if (!solve_maze(hWnd)) 689 { 690 start_timer(hWnd, solve_delay); 691 } 692 else 693 { 694 state = 1; 695 start_timer(hWnd, post_solve_delay); 696 } 697 break; 698 default: 699 initialize_maze(); 700 701 SendMessage(hWnd, WM_ERASEBKGND, (WPARAM) hDC, (LPARAM) 0); 702 draw_maze_border(hWnd); 703 704 create_maze(hWnd); 705 706 state = 2; 707 708 start_timer(hWnd, pre_solve_delay); 709 break; 710 } 711 break; 712 case WM_DESTROY: // message: window being destroyed 713 DeleteObject(hBrushLiving); 714 DeleteObject(hBrushDead); 715 ReleaseDC(hWnd, hDC); 716 break; 717 default: // Passes it on if unprocessed 718 return DefScreenSaverProc(hWnd, message, wParam, lParam); 719 } 720 return 0; 721 } 722 723 BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam) 724 { 725 switch (message) 726 { 727 case WM_INITDIALOG: 728 ReadRegistry(); 729 //Set slider ranges 730 SendDlgItemMessage(hWnd, IDC_SLIDER_SIZE, TBM_SETRANGE, FALSE, MAKELPARAM(5, 64)); 731 SendDlgItemMessage(hWnd, IDC_SLIDER_PRESD, TBM_SETRANGE, FALSE, MAKELPARAM(1, 10000)); 732 SendDlgItemMessage(hWnd, IDC_SLIDER_POSTSD, TBM_SETRANGE, FALSE, MAKELPARAM(1, 10000)); 733 SendDlgItemMessage(hWnd, IDC_SLIDER_SD, TBM_SETRANGE, FALSE, MAKELPARAM(1, 10000)); 734 //Set current values to slider 735 SendDlgItemMessage(hWnd, IDC_SLIDER_SIZE, TBM_SETPOS, TRUE, size); 736 SendDlgItemMessage(hWnd, IDC_SLIDER_PRESD, TBM_SETPOS, TRUE, pre_solve_delay); 737 SendDlgItemMessage(hWnd, IDC_SLIDER_POSTSD, TBM_SETPOS, TRUE, post_solve_delay); 738 SendDlgItemMessage(hWnd, IDC_SLIDER_SD, TBM_SETPOS, TRUE, solve_delay); 739 //Set current values to texts 740 SetDlgItemInt(hWnd, IDC_TEXT_SIZE, size, FALSE); 741 SetDlgItemInt(hWnd, IDC_TEXT_PRESD, pre_solve_delay, FALSE); 742 SetDlgItemInt(hWnd, IDC_TEXT_POSTSD, post_solve_delay, FALSE); 743 SetDlgItemInt(hWnd, IDC_TEXT_SD, solve_delay, FALSE); 744 return TRUE; 745 case WM_COMMAND: 746 switch (LOWORD(wparam)) 747 { 748 case IDOK: 749 WriteRegistry(); 750 EndDialog(hWnd, TRUE); 751 return TRUE; 752 case IDCANCEL: 753 EndDialog(hWnd, TRUE); 754 break; 755 case IDABOUT: 756 DialogBox(hMainInstance, MAKEINTRESOURCE(IDD_DLG_ABOUT), hWnd, AboutProc); 757 break; 758 } 759 case WM_HSCROLL: 760 ReadSettings(hWnd); 761 return TRUE; 762 } 763 return FALSE; 764 } 765 766 BOOL WINAPI RegisterDialogClasses(HANDLE hmodule) 767 { 768 return TRUE; 769 } 770