4 * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
5 * To be distributed under the Wine License
17 /* Work around a Wine bug which defines handles as UINT rather than LPVOID */
19 #define NULL_HANDLE NULL
26 #define DEBUG(x) fprintf(stderr,x)
31 int WINAPI
WinMain( HINSTANCE hInst
, HINSTANCE hPrevInst
, LPSTR cmdline
, int cmdshow
)
39 LoadString( hInst
, IDS_APPNAME
, appname
, sizeof(appname
));
42 wc
.lpfnWndProc
= MainProc
;
46 wc
.hIcon
= LoadIcon( hInst
, appname
);
47 wc
.hCursor
= LoadCursor( NULL_HANDLE
, IDI_APPLICATION
);
48 wc
.hbrBackground
= (HBRUSH
) GetStockObject( BLACK_BRUSH
);
49 wc
.lpszMenuName
= "MENU_WINEMINE";
50 wc
.lpszClassName
= appname
;
52 if (!RegisterClass(&wc
)) exit(1);
53 hWnd
= CreateWindow( appname
, appname
,
54 WS_OVERLAPPEDWINDOW
& ~WS_THICKFRAME
& ~WS_MAXIMIZEBOX
,
55 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
56 NULL_HANDLE
, NULL_HANDLE
, hInst
, NULL
);
60 ShowWindow( hWnd
, cmdshow
);
63 haccel
= LoadAccelerators( hInst
, appname
);
64 SetTimer( hWnd
, ID_TIMER
, 1000, NULL
);
66 while( GetMessage(&msg
, NULL_HANDLE
, 0, 0) ) {
67 if (!TranslateAccelerator( hWnd
, haccel
, &msg
))
68 TranslateMessage( &msg
);
70 DispatchMessage( &msg
);
75 LRESULT WINAPI
MainProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
84 board
.hInst
= ((LPCREATESTRUCT
) lParam
)->hInstance
;
87 CreateBoard( &board
);
95 hdc
= BeginPaint( hWnd
, &ps
);
96 hMemDC
= CreateCompatibleDC( hdc
);
98 DrawBoard( hdc
, hMemDC
, &ps
, &board
);
101 EndPaint( hWnd
, &ps
);
108 board
.pos
.x
= (unsigned) LOWORD(lParam
);
109 board
.pos
.y
= (unsigned) HIWORD(lParam
);
114 DestroyBoard( &board
);
115 PostQuitMessage( 0 );
119 if( board
.status
== PLAYING
) {
121 RedrawWindow( hWnd
, &board
.timer_rect
, NULL_HANDLE
,
122 RDW_INVALIDATE
| RDW_UPDATENOW
);
127 DEBUG("WM_LBUTTONDOWN\n");
128 if( wParam
& MK_RBUTTON
)
129 msg
= WM_MBUTTONDOWN
;
130 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
135 DEBUG("WM_LBUTTONUP\n");
136 if( wParam
& MK_RBUTTON
)
138 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
143 DEBUG("WM_RBUTTONDOWN\n");
144 if( wParam
& MK_LBUTTON
) {
147 msg
= WM_MBUTTONDOWN
;
149 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
153 DEBUG("WM_RBUTTONUP\n");
154 if( wParam
& MK_LBUTTON
)
156 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
160 DEBUG("WM_MBUTTONDOWN\n");
161 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
165 DEBUG("WM_MBUTTONUP\n");
166 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
171 if( (wParam
& MK_LBUTTON
) && (wParam
& MK_RBUTTON
) ) {
172 msg
= WM_MBUTTONDOWN
;
174 else if( wParam
& MK_LBUTTON
) {
175 msg
= WM_LBUTTONDOWN
;
181 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
187 switch(LOWORD(wParam
)) {
189 CreateBoard( &board
);
193 hMenu
= GetMenu( hWnd
);
194 board
.IsMarkQ
= !board
.IsMarkQ
;
196 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
198 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
202 SetDifficulty( &board
, BEGINNER
);
203 CreateBoard( &board
);
207 SetDifficulty( &board
, ADVANCED
);
208 CreateBoard( &board
);
212 SetDifficulty( &board
, EXPERT
);
213 CreateBoard( &board
);
217 SetDifficulty( &board
, CUSTOM
);
218 CreateBoard( &board
);
222 SendMessage( hWnd
, WM_CLOSE
, 0, 0);
226 DialogBoxParam( board
.hInst
, "DLG_TIMES", hWnd
,
227 TimesDlgProc
, (LPARAM
) &board
);
231 DialogBox( board
.hInst
, "DLG_ABOUT", hWnd
, AboutDlgProc
);
234 DEBUG("Unknown WM_COMMAND command message received\n");
238 return( DefWindowProc( hWnd
, msg
, wParam
, lParam
));
241 void InitBoard( BOARD
*p_board
)
245 p_board
->hMinesBMP
= LoadBitmap( p_board
->hInst
, "mines");
246 p_board
->hFacesBMP
= LoadBitmap( p_board
->hInst
, "faces");
247 p_board
->hLedsBMP
= LoadBitmap( p_board
->hInst
, "leds");
249 LoadBoard( p_board
);
251 if( p_board
->pos
.x
< (unsigned) GetSystemMetrics( SM_CXFIXEDFRAME
))
252 p_board
->pos
.x
= GetSystemMetrics( SM_CXFIXEDFRAME
);
254 if( p_board
->pos
.x
> (unsigned) (GetSystemMetrics( SM_CXSCREEN
)
255 - GetSystemMetrics( SM_CXFIXEDFRAME
))) {
256 p_board
->pos
.x
= GetSystemMetrics( SM_CXSCREEN
)
257 - GetSystemMetrics( SM_CXFIXEDFRAME
);
260 if( p_board
->pos
.y
< (unsigned) (GetSystemMetrics( SM_CYMENU
)
261 + GetSystemMetrics( SM_CYCAPTION
)
262 + GetSystemMetrics( SM_CYFIXEDFRAME
))) {
263 p_board
->pos
.y
= GetSystemMetrics( SM_CYMENU
) +
264 GetSystemMetrics( SM_CYCAPTION
) +
265 GetSystemMetrics( SM_CYFIXEDFRAME
);
268 if( p_board
->pos
.y
> (unsigned) (GetSystemMetrics( SM_CYSCREEN
)
269 - GetSystemMetrics( SM_CYFIXEDFRAME
))) {
270 p_board
->pos
.y
= GetSystemMetrics( SM_CYSCREEN
)
271 - GetSystemMetrics( SM_CYFIXEDFRAME
);
274 hMenu
= GetMenu( p_board
->hWnd
);
275 CheckMenuItem( hMenu
, IDM_BEGINNER
+ (unsigned) p_board
->difficulty
,
277 if( p_board
->IsMarkQ
)
278 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
280 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
281 CheckLevel( p_board
);
284 void LoadBoard( BOARD
*p_board
)
294 RegOpenKeyEx( HKEY_LOCAL_MACHINE
, "Software\\Wine\\WineMine",
295 0, KEY_QUERY_VALUE
, &hkey
);
297 size
= sizeof( data
);
298 if( RegQueryValueEx( hkey
, "Xpos", NULL
, (LPDWORD
) &type
,
299 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
) {
300 p_board
->pos
.x
= atoi( data
);
303 p_board
->pos
.x
= GetSystemMetrics( SM_CXFIXEDFRAME
);
305 size
= sizeof( data
);
306 if( RegQueryValueEx( hkey
, "Ypos", NULL
, (LPDWORD
) &type
,
307 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
308 p_board
->pos
.y
= atoi( data
);
310 p_board
->pos
.y
= GetSystemMetrics( SM_CYMENU
)
311 + GetSystemMetrics( SM_CYCAPTION
)
312 + GetSystemMetrics( SM_CYFIXEDFRAME
);
314 size
= sizeof( data
);
315 if( RegQueryValueEx( hkey
, "Rows", NULL
, (LPDWORD
) &type
,
316 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
317 p_board
->rows
= atoi( data
);
319 p_board
->rows
= BEGINNER_ROWS
;
321 size
= sizeof( data
);
322 if( RegQueryValueEx( hkey
, "Cols", NULL
, (LPDWORD
) &type
,
323 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
324 p_board
->cols
= atoi( data
);
326 p_board
->cols
= BEGINNER_COLS
;
328 size
= sizeof( data
);
329 if( RegQueryValueEx( hkey
, "Mines", NULL
, (LPDWORD
) &type
,
330 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
331 p_board
->mines
= atoi( data
);
333 p_board
->rows
= BEGINNER_ROWS
;
335 size
= sizeof( data
);
336 if( RegQueryValueEx( hkey
, "Difficulty", NULL
, (LPDWORD
) &type
,
337 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
338 p_board
->difficulty
= (DIFFICULTY
) atoi( data
);
340 p_board
->difficulty
= BEGINNER
;
342 size
= sizeof( data
);
343 if( RegQueryValueEx( hkey
, "MarkQ", NULL
, (LPDWORD
) &type
,
344 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
345 p_board
->IsMarkQ
= atoi( data
);
347 p_board
->IsMarkQ
= TRUE
;
349 for( i
= 0; i
< 3; i
++ ) {
350 wsprintf( key_name
, "Name%d", i
);
351 size
= sizeof( data
);
352 if( RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
354 (LPDWORD
) &size
) == ERROR_SUCCESS
)
355 strncpy( p_board
->best_name
[i
], data
, sizeof( data
) );
357 wsprintf( p_board
->best_name
[i
], "Nobody");
360 for( i
= 0; i
< 3; i
++ ) {
361 wsprintf( key_name
, "Time%d", i
);
362 size
= sizeof( data
);
363 if( RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
365 (LPDWORD
) &size
) == ERROR_SUCCESS
)
366 p_board
->best_time
[i
] = atoi( data
);
368 p_board
->best_time
[i
] = 999;
373 void SaveBoard( BOARD
*p_board
)
377 SECURITY_ATTRIBUTES sa
;
382 if( RegCreateKeyEx( HKEY_LOCAL_MACHINE
,
383 "Software\\Wine\\WineMine", 0, NULL
,
384 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, &sa
,
385 &hkey
, &disp
) != ERROR_SUCCESS
)
388 wsprintf( data
, "%d", p_board
->pos
.x
);
389 RegSetValueEx( hkey
, "Xpos", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
391 wsprintf( data
, "%d", p_board
->pos
.x
);
392 RegSetValueEx( hkey
, "Ypos", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
394 wsprintf( data
, "%d", (int) p_board
->difficulty
);
395 RegSetValueEx( hkey
, "Difficulty", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
397 wsprintf( data
, "%d", p_board
->rows
);
398 RegSetValueEx( hkey
, "Rows", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
400 wsprintf( data
, "%d", p_board
->cols
);
401 RegSetValueEx( hkey
, "Cols", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
403 wsprintf( data
, "%d", p_board
->mines
);
404 RegSetValueEx( hkey
, "Mines", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
406 wsprintf( data
, "%d", (int) p_board
->IsMarkQ
);
407 RegSetValueEx( hkey
, "MarkQ", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
409 for( i
= 0; i
< 3; i
++ ) {
410 wsprintf( key_name
, "Name%u", i
);
411 strncpy( data
, p_board
->best_name
[i
], sizeof( data
) );
412 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
415 for( i
= 0; i
< 3; i
++ ) {
416 wsprintf( key_name
, "Time%u", i
);
417 wsprintf( data
, "%d", p_board
->best_time
[i
] );
418 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
423 void DestroyBoard( BOARD
*p_board
)
425 DeleteObject( p_board
->hFacesBMP
);
426 DeleteObject( p_board
->hLedsBMP
);
427 DeleteObject( p_board
->hMinesBMP
);
430 void SetDifficulty( BOARD
*p_board
, DIFFICULTY difficulty
)
432 HMENU hMenu
= GetMenu( p_board
->hWnd
);
434 CheckMenuItem( hMenu
, IDM_BEGINNER
+ p_board
->difficulty
, MF_UNCHECKED
);
435 p_board
->difficulty
= difficulty
;
436 CheckMenuItem( hMenu
, IDM_BEGINNER
+ difficulty
, MF_CHECKED
);
438 switch( difficulty
) {
440 p_board
->cols
= BEGINNER_COLS
;
441 p_board
->rows
= BEGINNER_ROWS
;
442 p_board
->mines
= BEGINNER_MINES
;
446 p_board
->cols
= ADVANCED_COLS
;
447 p_board
->rows
= ADVANCED_ROWS
;
448 p_board
->mines
= ADVANCED_MINES
;
452 p_board
->cols
= EXPERT_COLS
;
453 p_board
->rows
= EXPERT_ROWS
;
454 p_board
->mines
= EXPERT_MINES
;
458 DialogBoxParam( p_board
->hInst
, "DLG_CUSTOM", p_board
->hWnd
,
459 CustomDlgProc
, (LPARAM
) p_board
);
464 void CreateBoard( BOARD
*p_board
)
466 int left
, top
, bottom
, right
, wnd_x
, wnd_y
, wnd_width
, wnd_height
;
468 p_board
->mb
= MB_NONE
;
469 p_board
->boxes_left
= p_board
->cols
* p_board
->rows
- p_board
->mines
;
470 p_board
->num_flags
= 0;
472 CreateBoxes( p_board
);
474 p_board
->width
= p_board
->cols
* MINE_WIDTH
+ BOARD_WMARGIN
* 2;
476 p_board
->height
= p_board
->rows
* MINE_HEIGHT
+ LED_HEIGHT
479 wnd_x
= p_board
->pos
.x
- GetSystemMetrics( SM_CXFIXEDFRAME
);
480 wnd_y
= p_board
->pos
.y
- GetSystemMetrics( SM_CYMENU
)
481 - GetSystemMetrics( SM_CYCAPTION
)
482 - GetSystemMetrics( SM_CYFIXEDFRAME
);
483 wnd_width
= p_board
->width
484 + GetSystemMetrics( SM_CXFIXEDFRAME
) * 2;
485 wnd_height
= p_board
->height
486 + GetSystemMetrics( SM_CYMENU
)
487 + GetSystemMetrics( SM_CYCAPTION
)
488 + GetSystemMetrics( SM_CYFIXEDFRAME
) * 2;
490 /* setting the mines rectangle boundary */
491 left
= BOARD_WMARGIN
;
492 top
= BOARD_HMARGIN
* 2 + LED_HEIGHT
;
493 right
= left
+ p_board
->cols
* MINE_WIDTH
;
494 bottom
= top
+ p_board
->rows
* MINE_HEIGHT
;
495 SetRect( &p_board
->mines_rect
, left
, top
, right
, bottom
);
497 /* setting the face rectangle boundary */
498 left
= p_board
->width
/ 2 - FACE_WIDTH
/ 2;
500 right
= left
+ FACE_WIDTH
;
501 bottom
= top
+ FACE_HEIGHT
;
502 SetRect( &p_board
->face_rect
, left
, top
, right
, bottom
);
504 /* setting the timer rectangle boundary */
505 left
= BOARD_WMARGIN
;
507 right
= left
+ LED_WIDTH
* 3;
508 bottom
= top
+ LED_HEIGHT
;
509 SetRect( &p_board
->timer_rect
, left
, top
, right
, bottom
);
511 /* setting the counter rectangle boundary */
512 left
= p_board
->width
- BOARD_WMARGIN
- LED_WIDTH
* 3;
514 right
= p_board
->width
- BOARD_WMARGIN
;
515 bottom
= top
+ LED_HEIGHT
;
516 SetRect( &p_board
->counter_rect
, left
, top
, right
, bottom
);
518 p_board
->status
= WAITING
;
519 p_board
->face_bmp
= SMILE_BMP
;
522 MoveWindow( p_board
->hWnd
, wnd_x
, wnd_y
, wnd_width
, wnd_height
, TRUE
);
523 RedrawWindow( p_board
->hWnd
, NULL
, NULL_HANDLE
,
524 RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_ERASE
);
528 void CheckLevel( BOARD
*p_board
)
530 if( p_board
->rows
< BEGINNER_ROWS
)
531 p_board
->rows
= BEGINNER_ROWS
;
533 if( p_board
->rows
> MAX_ROWS
)
534 p_board
->rows
= MAX_ROWS
;
536 if( p_board
->cols
< BEGINNER_COLS
)
537 p_board
->cols
= BEGINNER_COLS
;
539 if( p_board
->cols
> MAX_COLS
)
540 p_board
->cols
= MAX_COLS
;
542 if( p_board
->mines
< BEGINNER_MINES
)
543 p_board
->mines
= BEGINNER_MINES
;
545 if( p_board
->mines
> p_board
->cols
* p_board
->rows
- 1 )
546 p_board
->mines
= p_board
->cols
* p_board
->rows
- 1;
550 void CreateBoxes( BOARD
*p_board
)
555 srand( (unsigned) time( NULL
) );
557 /* Create the boxes...
558 * We actually create them with an empty border,
559 * so special care doesn't have to be taken on the edges
562 for( col
= 0; col
<= p_board
->cols
+ 1; col
++ )
563 for( row
= 0; row
<= p_board
->rows
+ 1; row
++ ) {
564 p_board
->box
[col
][row
].IsPressed
= FALSE
;
565 p_board
->box
[col
][row
].IsMine
= FALSE
;
566 p_board
->box
[col
][row
].FlagType
= NORMAL
;
567 p_board
->box
[col
][row
].NumMines
= 0;
572 while( (unsigned) i
< p_board
->mines
) {
573 col
= (int) (p_board
->cols
* (float) rand() / RAND_MAX
+ 1);
574 row
= (int) (p_board
->rows
* (float) rand() / RAND_MAX
+ 1);
576 if( !p_board
->box
[col
][row
].IsMine
) {
578 p_board
->box
[col
][row
].IsMine
= TRUE
;
583 * Now we label the remaining boxes with the
584 * number of mines surrounding them.
587 for( col
= 1; col
< p_board
->cols
+ 1; col
++ )
588 for( row
= 1; row
< p_board
->rows
+ 1; row
++ ) {
589 for( i
= -1; i
<= 1; i
++ )
590 for( j
= -1; j
<= 1; j
++ ) {
591 if( p_board
->box
[col
+ i
][row
+ j
].IsMine
) {
592 p_board
->box
[col
][row
].NumMines
++ ;
598 void DrawMines ( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
602 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
604 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
605 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
606 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
609 SelectObject( hMemDC
, hOldObj
);
612 void DrawMine( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, unsigned col
, unsigned row
, BOOL IsPressed
)
614 MINEBMP_OFFSET offset
= BOX_BMP
;
616 if( col
== 0 || col
> p_board
->cols
|| row
== 0 || row
> p_board
->rows
)
619 if( p_board
->status
== GAMEOVER
) {
620 if( p_board
->box
[col
][row
].IsMine
) {
621 switch( p_board
->box
[col
][row
].FlagType
) {
626 offset
= EXPLODE_BMP
;
632 switch( p_board
->box
[col
][row
].FlagType
) {
634 offset
= QUESTION_BMP
;
646 DEBUG("Unknown FlagType during game over in DrawMine\n");
650 } else { /* WAITING or PLAYING */
651 switch( p_board
->box
[col
][row
].FlagType
) {
654 offset
= QUESTION_BMP
;
671 DEBUG("Unknown FlagType while playing in DrawMine\n");
676 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
677 && !p_board
->box
[col
][row
].IsMine
)
678 offset
= (MINEBMP_OFFSET
) p_board
->box
[col
][row
].NumMines
;
681 (col
- 1) * MINE_WIDTH
+ p_board
->mines_rect
.left
,
682 (row
- 1) * MINE_HEIGHT
+ p_board
->mines_rect
.top
,
683 MINE_WIDTH
, MINE_HEIGHT
,
684 hMemDC
, 0, offset
* MINE_HEIGHT
, SRCCOPY
);
687 void DrawLeds( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, int number
, int x
, int y
)
696 led
[0] = count
/ 100 ;
697 count
-= led
[0] * 100;
700 led
[0] = 10; /* negative sign */
704 count
-= led
[1] * 10;
708 for( i
= 0; i
< 3; i
++ )
712 /* use unlit led if not playing */
713 if( p_board
->status
== WAITING
)
714 for( i
= 0; i
< 3; i
++ )
717 hOldObj
= SelectObject (hMemDC
, p_board
->hLedsBMP
);
719 for( i
= 0; i
< 3; i
++ ) {
731 SelectObject( hMemDC
, hOldObj
);
735 void DrawFace( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
739 hOldObj
= SelectObject (hMemDC
, p_board
->hFacesBMP
);
742 p_board
->face_rect
.left
,
743 p_board
->face_rect
.top
,
746 hMemDC
, 0, p_board
->face_bmp
* FACE_HEIGHT
, SRCCOPY
);
748 SelectObject( hMemDC
, hOldObj
);
752 void DrawBoard( HDC hdc
, HDC hMemDC
, PAINTSTRUCT
*ps
, BOARD
*p_board
)
756 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->counter_rect
) )
757 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->mines
- p_board
->num_flags
,
758 p_board
->counter_rect
.left
,
759 p_board
->counter_rect
.top
);
761 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->timer_rect
) )
762 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->time
,
763 p_board
->timer_rect
.left
,
764 p_board
->timer_rect
.top
);
766 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->face_rect
) )
767 DrawFace( hdc
, hMemDC
, p_board
);
769 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->mines_rect
) )
770 DrawMines( hdc
, hMemDC
, p_board
);
774 void TestBoard( HWND hWnd
, BOARD
*p_board
, unsigned x
, unsigned y
, int msg
)
781 if( PtInRect( &p_board
->mines_rect
, pt
) && p_board
->status
!= GAMEOVER
782 && p_board
->status
!= WON
)
783 TestMines( p_board
, pt
, msg
);
785 UnpressBoxes( p_board
,
788 p_board
->press
.x
= 0;
789 p_board
->press
.y
= 0;
792 if( p_board
->boxes_left
== 0 ) {
793 p_board
->status
= WON
;
795 if( p_board
->difficulty
!= CUSTOM
&&
796 p_board
->time
< p_board
->best_time
[p_board
->difficulty
] ) {
797 p_board
->best_time
[p_board
->difficulty
] = p_board
->time
;
799 DialogBoxParam( p_board
->hInst
, "DLG_CONGRATS", hWnd
,
800 CongratsDlgProc
, (LPARAM
) p_board
);
802 DialogBoxParam( p_board
->hInst
, "DLG_TIMES", hWnd
,
803 TimesDlgProc
, (LPARAM
) p_board
);
806 TestFace( p_board
, pt
, msg
);
809 void TestMines( BOARD
*p_board
, POINT pt
, int msg
)
814 col
= (pt
.x
- p_board
->mines_rect
.left
) / MINE_WIDTH
+ 1;
815 row
= (pt
.y
- p_board
->mines_rect
.top
) / MINE_HEIGHT
+ 1;
819 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
) {
821 p_board
->press
.x
, p_board
->press
.y
);
822 p_board
->press
.x
= col
;
823 p_board
->press
.y
= row
;
824 PressBox( p_board
, col
, row
);
830 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
832 p_board
->press
.x
, p_board
->press
.y
);
833 p_board
->press
.x
= 0;
834 p_board
->press
.y
= 0;
835 if( p_board
->box
[col
][row
].FlagType
!= FLAG
)
836 p_board
->status
= PLAYING
;
837 CompleteBox( p_board
, col
, row
);
841 PressBoxes( p_board
, col
, row
);
846 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
847 UnpressBoxes( p_board
,
848 p_board
->press
.x
, p_board
->press
.y
);
849 p_board
->press
.x
= 0;
850 p_board
->press
.y
= 0;
851 CompleteBoxes( p_board
, col
, row
);
855 AddFlag( p_board
, col
, row
);
856 p_board
->status
= PLAYING
;
859 DEBUG("Unknown message type received in TestMines\n");
865 RedrawWindow( p_board
->hWnd
, NULL
, NULL_HANDLE
,
866 RDW_INVALIDATE
| RDW_UPDATENOW
);
871 void TestFace( BOARD
*p_board
, POINT pt
, int msg
)
873 if( p_board
->status
== PLAYING
|| p_board
->status
== WAITING
) {
874 if( msg
== WM_LBUTTONDOWN
|| msg
== WM_MBUTTONDOWN
)
875 p_board
->face_bmp
= OOH_BMP
;
876 else p_board
->face_bmp
= SMILE_BMP
;
878 else if( p_board
->status
== GAMEOVER
)
879 p_board
->face_bmp
= DEAD_BMP
;
880 else if( p_board
->status
== WON
)
881 p_board
->face_bmp
= COOL_BMP
;
883 if( PtInRect( &p_board
->face_rect
, pt
) ) {
884 if( msg
== WM_LBUTTONDOWN
)
885 p_board
->face_bmp
= SPRESS_BMP
;
887 if( msg
== WM_LBUTTONUP
)
888 CreateBoard( p_board
);
891 RedrawWindow( p_board
->hWnd
, &p_board
->face_rect
, NULL_HANDLE
,
892 RDW_INVALIDATE
| RDW_UPDATENOW
);
896 void CompleteBox( BOARD
*p_board
, unsigned col
, unsigned row
)
900 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
&&
901 p_board
->box
[col
][row
].FlagType
!= FLAG
&&
902 col
> 0 && col
< p_board
->cols
+ 1 &&
903 row
> 0 && row
< p_board
->rows
+ 1 ) {
904 p_board
->box
[col
][row
].FlagType
= COMPLETE
;
906 if( p_board
->box
[col
][row
].IsMine
) {
907 p_board
->face_bmp
= DEAD_BMP
;
908 p_board
->status
= GAMEOVER
;
910 else if( p_board
->status
!= GAMEOVER
)
911 p_board
->boxes_left
--;
913 if( p_board
->box
[col
][row
].NumMines
== 0 )
915 for( i
= -1; i
<= 1; i
++ )
916 for( j
= -1; j
<= 1; j
++ )
917 CompleteBox( p_board
, col
+ i
, row
+ j
);
923 void CompleteBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
925 unsigned numFlags
= 0;
928 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
) {
929 for( i
= -1; i
<= 1; i
++ )
930 for( j
= -1; j
<= 1; j
++ ) {
931 if( p_board
->box
[col
+i
][row
+j
].FlagType
== FLAG
)
935 if( numFlags
== p_board
->box
[col
][row
].NumMines
) {
936 for( i
= -1; i
<= 1; i
++ )
937 for( j
= -1; j
<= 1; j
++ ) {
938 if( p_board
->box
[col
+i
][row
+j
].FlagType
!= FLAG
)
939 CompleteBox( p_board
, col
+i
, row
+j
);
946 void AddFlag( BOARD
*p_board
, unsigned col
, unsigned row
)
948 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
) {
949 switch( p_board
->box
[col
][row
].FlagType
) {
951 if( p_board
->IsMarkQ
)
952 p_board
->box
[col
][row
].FlagType
= QUESTION
;
954 p_board
->box
[col
][row
].FlagType
= NORMAL
;
955 p_board
->num_flags
--;
959 p_board
->box
[col
][row
].FlagType
= NORMAL
;
963 p_board
->box
[col
][row
].FlagType
= FLAG
;
964 p_board
->num_flags
++;
970 void PressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
976 hdc
= GetDC( p_board
->hWnd
);
977 hMemDC
= CreateCompatibleDC( hdc
);
978 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
980 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, TRUE
);
982 SelectObject( hMemDC
, hOldObj
);
984 ReleaseDC( p_board
->hWnd
, hdc
);
988 void PressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
992 for( i
= -1; i
<= 1; i
++ )
993 for( j
= -1; j
<= 1; j
++ ) {
994 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= TRUE
;
995 PressBox( p_board
, col
+ i
, row
+ j
);
998 for( i
= -1; i
<= 1; i
++ )
999 for( j
= -1; j
<= 1; j
++ ) {
1000 if( !p_board
->box
[p_board
->press
.x
+ i
][p_board
->press
.y
+ j
].IsPressed
)
1001 UnpressBox( p_board
, p_board
->press
.x
+ i
, p_board
->press
.y
+ j
);
1004 for( i
= -1; i
<= 1; i
++ )
1005 for( j
= -1; j
<= 1; j
++ ) {
1006 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= FALSE
;
1007 PressBox( p_board
, col
+ i
, row
+ j
);
1010 p_board
->press
.x
= col
;
1011 p_board
->press
.y
= row
;
1015 void UnpressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
1021 hdc
= GetDC( p_board
->hWnd
);
1022 hMemDC
= CreateCompatibleDC( hdc
);
1023 hOldObj
= SelectObject( hMemDC
, p_board
->hMinesBMP
);
1025 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
1027 SelectObject( hMemDC
, hOldObj
);
1029 ReleaseDC( p_board
->hWnd
, hdc
);
1033 void UnpressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
1037 for( i
= -1; i
<= 1; i
++ )
1038 for( j
= -1; j
<= 1; j
++ ) {
1039 UnpressBox( p_board
, col
+ i
, row
+ j
);