4 * Copyright 2000 Joshua Thielen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #define DEBUG(x) fprintf(stderr,x)
37 static const DWORD wnd_style
= WS_OVERLAPPEDWINDOW
& ~WS_THICKFRAME
& ~WS_MAXIMIZEBOX
;
38 static const char* registry_key
= "Software\\Wine\\WineMine";
41 int WINAPI
WinMain( HINSTANCE hInst
, HINSTANCE hPrevInst
, LPSTR cmdline
, int cmdshow
)
49 LoadString( hInst
, IDS_APPNAME
, appname
, sizeof(appname
));
52 wc
.lpfnWndProc
= MainProc
;
56 wc
.hIcon
= LoadIcon( hInst
, "WINEMINE" );
57 wc
.hCursor
= LoadCursor( 0, IDI_APPLICATION
);
58 wc
.hbrBackground
= (HBRUSH
) GetStockObject( BLACK_BRUSH
);
59 wc
.lpszMenuName
= "MENU_WINEMINE";
60 wc
.lpszClassName
= appname
;
62 if (!RegisterClass(&wc
)) exit(1);
63 hWnd
= CreateWindow( appname
, appname
,
65 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
70 ShowWindow( hWnd
, cmdshow
);
73 haccel
= LoadAccelerators( hInst
, MAKEINTRESOURCE(IDA_WINEMINE
) );
74 SetTimer( hWnd
, ID_TIMER
, 1000, NULL
);
76 while( GetMessage(&msg
, 0, 0, 0) ) {
77 if (!TranslateAccelerator( hWnd
, haccel
, &msg
))
78 TranslateMessage( &msg
);
80 DispatchMessage( &msg
);
85 LRESULT WINAPI
MainProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
94 board
.hInst
= ((LPCREATESTRUCT
) lParam
)->hInstance
;
97 CreateBoard( &board
);
105 hdc
= BeginPaint( hWnd
, &ps
);
106 hMemDC
= CreateCompatibleDC( hdc
);
108 DrawBoard( hdc
, hMemDC
, &ps
, &board
);
111 EndPaint( hWnd
, &ps
);
118 board
.pos
.x
= GET_X_LPARAM(lParam
);
119 board
.pos
.y
= GET_Y_LPARAM(lParam
);
124 DestroyBoard( &board
);
125 PostQuitMessage( 0 );
129 if( board
.status
== PLAYING
) {
131 RedrawWindow( hWnd
, &board
.timer_rect
, 0,
132 RDW_INVALIDATE
| RDW_UPDATENOW
);
137 DEBUG("WM_LBUTTONDOWN\n");
138 if( wParam
& MK_RBUTTON
)
139 msg
= WM_MBUTTONDOWN
;
140 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
145 DEBUG("WM_LBUTTONUP\n");
146 if( wParam
& MK_RBUTTON
)
148 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
153 DEBUG("WM_RBUTTONDOWN\n");
154 if( wParam
& MK_LBUTTON
) {
157 msg
= WM_MBUTTONDOWN
;
159 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
163 DEBUG("WM_RBUTTONUP\n");
164 if( wParam
& MK_LBUTTON
)
166 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
170 DEBUG("WM_MBUTTONDOWN\n");
171 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
175 DEBUG("WM_MBUTTONUP\n");
176 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
181 if( (wParam
& MK_LBUTTON
) && (wParam
& MK_RBUTTON
) ) {
182 msg
= WM_MBUTTONDOWN
;
184 else if( wParam
& MK_LBUTTON
) {
185 msg
= WM_LBUTTONDOWN
;
191 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
197 switch(LOWORD(wParam
)) {
199 CreateBoard( &board
);
203 hMenu
= GetMenu( hWnd
);
204 board
.IsMarkQ
= !board
.IsMarkQ
;
206 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
208 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
212 SetDifficulty( &board
, BEGINNER
);
213 CreateBoard( &board
);
217 SetDifficulty( &board
, ADVANCED
);
218 CreateBoard( &board
);
222 SetDifficulty( &board
, EXPERT
);
223 CreateBoard( &board
);
227 SetDifficulty( &board
, CUSTOM
);
228 CreateBoard( &board
);
232 SendMessage( hWnd
, WM_CLOSE
, 0, 0);
236 DialogBoxParam( board
.hInst
, "DLG_TIMES", hWnd
,
237 TimesDlgProc
, (LPARAM
) &board
);
241 DialogBox( board
.hInst
, "DLG_ABOUT", hWnd
, AboutDlgProc
);
244 DEBUG("Unknown WM_COMMAND command message received\n");
248 return( DefWindowProc( hWnd
, msg
, wParam
, lParam
));
251 void InitBoard( BOARD
*p_board
)
255 p_board
->hMinesBMP
= LoadBitmap( p_board
->hInst
, "mines");
256 p_board
->hFacesBMP
= LoadBitmap( p_board
->hInst
, "faces");
257 p_board
->hLedsBMP
= LoadBitmap( p_board
->hInst
, "leds");
259 LoadBoard( p_board
);
261 hMenu
= GetMenu( p_board
->hWnd
);
262 CheckMenuItem( hMenu
, IDM_BEGINNER
+ (unsigned) p_board
->difficulty
,
264 if( p_board
->IsMarkQ
)
265 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
267 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
268 CheckLevel( p_board
);
271 void LoadBoard( BOARD
*p_board
)
280 RegOpenKeyEx( HKEY_CURRENT_USER
, registry_key
,
281 0, KEY_QUERY_VALUE
, &hkey
);
283 size
= sizeof( data
);
284 if( RegQueryValueEx( hkey
, "Xpos", NULL
, (LPDWORD
) &type
,
285 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
) {
286 p_board
->pos
.x
= atoi( data
);
291 size
= sizeof( data
);
292 if( RegQueryValueEx( hkey
, "Ypos", NULL
, (LPDWORD
) &type
,
293 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
294 p_board
->pos
.y
= atoi( data
);
298 size
= sizeof( data
);
299 if( RegQueryValueEx( hkey
, "Rows", NULL
, (LPDWORD
) &type
,
300 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
301 p_board
->rows
= atoi( data
);
303 p_board
->rows
= BEGINNER_ROWS
;
305 size
= sizeof( data
);
306 if( RegQueryValueEx( hkey
, "Cols", NULL
, (LPDWORD
) &type
,
307 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
308 p_board
->cols
= atoi( data
);
310 p_board
->cols
= BEGINNER_COLS
;
312 size
= sizeof( data
);
313 if( RegQueryValueEx( hkey
, "Mines", NULL
, (LPDWORD
) &type
,
314 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
315 p_board
->mines
= atoi( data
);
317 p_board
->rows
= BEGINNER_ROWS
;
319 size
= sizeof( data
);
320 if( RegQueryValueEx( hkey
, "Difficulty", NULL
, (LPDWORD
) &type
,
321 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
322 p_board
->difficulty
= (DIFFICULTY
) atoi( data
);
324 p_board
->difficulty
= BEGINNER
;
326 size
= sizeof( data
);
327 if( RegQueryValueEx( hkey
, "MarkQ", NULL
, (LPDWORD
) &type
,
328 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
329 p_board
->IsMarkQ
= atoi( data
);
331 p_board
->IsMarkQ
= TRUE
;
333 for( i
= 0; i
< 3; i
++ ) {
334 wsprintf( key_name
, "Name%d", i
);
335 size
= sizeof( data
);
336 if( RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
338 (LPDWORD
) &size
) == ERROR_SUCCESS
)
339 strncpy( p_board
->best_name
[i
], data
, sizeof( data
) );
341 LoadString( p_board
->hInst
, IDS_NOBODY
, p_board
->best_name
[i
], 16 );
344 for( i
= 0; i
< 3; i
++ ) {
345 wsprintf( key_name
, "Time%d", i
);
346 size
= sizeof( data
);
347 if( RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
349 (LPDWORD
) &size
) == ERROR_SUCCESS
)
350 p_board
->best_time
[i
] = atoi( data
);
352 p_board
->best_time
[i
] = 999;
357 void SaveBoard( BOARD
*p_board
)
364 if( RegCreateKeyEx( HKEY_CURRENT_USER
, registry_key
,
366 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
,
367 &hkey
, NULL
) != ERROR_SUCCESS
)
370 wsprintf( data
, "%d", p_board
->pos
.x
);
371 RegSetValueEx( hkey
, "Xpos", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
373 wsprintf( data
, "%d", p_board
->pos
.y
);
374 RegSetValueEx( hkey
, "Ypos", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
376 wsprintf( data
, "%d", (int) p_board
->difficulty
);
377 RegSetValueEx( hkey
, "Difficulty", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
379 wsprintf( data
, "%d", p_board
->rows
);
380 RegSetValueEx( hkey
, "Rows", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
382 wsprintf( data
, "%d", p_board
->cols
);
383 RegSetValueEx( hkey
, "Cols", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
385 wsprintf( data
, "%d", p_board
->mines
);
386 RegSetValueEx( hkey
, "Mines", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
388 wsprintf( data
, "%d", (int) p_board
->IsMarkQ
);
389 RegSetValueEx( hkey
, "MarkQ", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
391 for( i
= 0; i
< 3; i
++ ) {
392 wsprintf( key_name
, "Name%u", i
);
393 strncpy( data
, p_board
->best_name
[i
], sizeof( data
) );
394 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
397 for( i
= 0; i
< 3; i
++ ) {
398 wsprintf( key_name
, "Time%u", i
);
399 wsprintf( data
, "%d", p_board
->best_time
[i
] );
400 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
405 void DestroyBoard( BOARD
*p_board
)
407 DeleteObject( p_board
->hFacesBMP
);
408 DeleteObject( p_board
->hLedsBMP
);
409 DeleteObject( p_board
->hMinesBMP
);
412 void SetDifficulty( BOARD
*p_board
, DIFFICULTY difficulty
)
416 if ( difficulty
== CUSTOM
)
417 if (DialogBoxParam( p_board
->hInst
, "DLG_CUSTOM", p_board
->hWnd
,
418 CustomDlgProc
, (LPARAM
) p_board
) != 0)
421 hMenu
= GetMenu( p_board
->hWnd
);
422 CheckMenuItem( hMenu
, IDM_BEGINNER
+ p_board
->difficulty
, MF_UNCHECKED
);
423 p_board
->difficulty
= difficulty
;
424 CheckMenuItem( hMenu
, IDM_BEGINNER
+ difficulty
, MF_CHECKED
);
426 switch( difficulty
) {
428 p_board
->cols
= BEGINNER_COLS
;
429 p_board
->rows
= BEGINNER_ROWS
;
430 p_board
->mines
= BEGINNER_MINES
;
434 p_board
->cols
= ADVANCED_COLS
;
435 p_board
->rows
= ADVANCED_ROWS
;
436 p_board
->mines
= ADVANCED_MINES
;
440 p_board
->cols
= EXPERT_COLS
;
441 p_board
->rows
= EXPERT_ROWS
;
443 p_board
->mines
= EXPERT_MINES
;
451 void ShiftBetween(LONG
* x
, LONG
* y
, LONG a
, LONG b
)
462 void MoveOnScreen(RECT
* rect
)
467 /* find the nearest monitor ... */
468 hMonitor
= MonitorFromRect(rect
, MONITOR_DEFAULTTONEAREST
);
470 /* ... and move it into the work area (ie excluding task bar)*/
471 mi
.cbSize
= sizeof(mi
);
472 GetMonitorInfo(hMonitor
, &mi
);
474 ShiftBetween(&rect
->left
, &rect
->right
, mi
.rcWork
.left
, mi
.rcWork
.right
);
475 ShiftBetween(&rect
->top
, &rect
->bottom
, mi
.rcWork
.top
, mi
.rcWork
.bottom
);
478 void CreateBoard( BOARD
*p_board
)
480 int left
, top
, bottom
, right
;
483 p_board
->mb
= MB_NONE
;
484 p_board
->boxes_left
= p_board
->cols
* p_board
->rows
- p_board
->mines
;
485 p_board
->num_flags
= 0;
487 CreateBoxes( p_board
);
489 p_board
->width
= p_board
->cols
* MINE_WIDTH
+ BOARD_WMARGIN
* 2;
491 p_board
->height
= p_board
->rows
* MINE_HEIGHT
+ LED_HEIGHT
494 /* setting the mines rectangle boundary */
495 left
= BOARD_WMARGIN
;
496 top
= BOARD_HMARGIN
* 2 + LED_HEIGHT
;
497 right
= left
+ p_board
->cols
* MINE_WIDTH
;
498 bottom
= top
+ p_board
->rows
* MINE_HEIGHT
;
499 SetRect( &p_board
->mines_rect
, left
, top
, right
, bottom
);
501 /* setting the face rectangle boundary */
502 left
= p_board
->width
/ 2 - FACE_WIDTH
/ 2;
504 right
= left
+ FACE_WIDTH
;
505 bottom
= top
+ FACE_HEIGHT
;
506 SetRect( &p_board
->face_rect
, left
, top
, right
, bottom
);
508 /* setting the timer rectangle boundary */
509 left
= BOARD_WMARGIN
;
511 right
= left
+ LED_WIDTH
* 3;
512 bottom
= top
+ LED_HEIGHT
;
513 SetRect( &p_board
->timer_rect
, left
, top
, right
, bottom
);
515 /* setting the counter rectangle boundary */
516 left
= p_board
->width
- BOARD_WMARGIN
- LED_WIDTH
* 3;
518 right
= p_board
->width
- BOARD_WMARGIN
;
519 bottom
= top
+ LED_HEIGHT
;
520 SetRect( &p_board
->counter_rect
, left
, top
, right
, bottom
);
522 p_board
->status
= WAITING
;
523 p_board
->face_bmp
= SMILE_BMP
;
526 wnd_rect
.left
= p_board
->pos
.x
;
527 wnd_rect
.right
= p_board
->pos
.x
+ p_board
->width
;
528 wnd_rect
.top
= p_board
->pos
.y
;
529 wnd_rect
.bottom
= p_board
->pos
.y
+ p_board
->height
;
530 AdjustWindowRect(&wnd_rect
, wnd_style
, TRUE
);
532 /* Make sure the window is completely on the screen */
533 MoveOnScreen(&wnd_rect
);
534 MoveWindow( p_board
->hWnd
, wnd_rect
.left
, wnd_rect
.top
,
535 wnd_rect
.right
- wnd_rect
.left
,
536 wnd_rect
.bottom
- wnd_rect
.top
,
538 RedrawWindow( p_board
->hWnd
, NULL
, 0,
539 RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_ERASE
);
543 void CheckLevel( BOARD
*p_board
)
545 if( p_board
->rows
< BEGINNER_ROWS
)
546 p_board
->rows
= BEGINNER_ROWS
;
548 if( p_board
->rows
> MAX_ROWS
)
549 p_board
->rows
= MAX_ROWS
;
551 if( p_board
->cols
< BEGINNER_COLS
)
552 p_board
->cols
= BEGINNER_COLS
;
554 if( p_board
->cols
> MAX_COLS
)
555 p_board
->cols
= MAX_COLS
;
557 if( p_board
->mines
< BEGINNER_MINES
)
558 p_board
->mines
= BEGINNER_MINES
;
560 if( p_board
->mines
> p_board
->cols
* p_board
->rows
- 1 )
561 p_board
->mines
= p_board
->cols
* p_board
->rows
- 1;
565 void CreateBoxes( BOARD
*p_board
)
570 srand( (unsigned) time( NULL
) );
572 /* Create the boxes...
573 * We actually create them with an empty border,
574 * so special care doesn't have to be taken on the edges
577 for( col
= 0; col
<= p_board
->cols
+ 1; col
++ )
578 for( row
= 0; row
<= p_board
->rows
+ 1; row
++ ) {
579 p_board
->box
[col
][row
].IsPressed
= FALSE
;
580 p_board
->box
[col
][row
].IsMine
= FALSE
;
581 p_board
->box
[col
][row
].FlagType
= NORMAL
;
582 p_board
->box
[col
][row
].NumMines
= 0;
587 while( (unsigned) i
< p_board
->mines
) {
588 col
= (int) (p_board
->cols
* (float) rand() / RAND_MAX
+ 1);
589 row
= (int) (p_board
->rows
* (float) rand() / RAND_MAX
+ 1);
591 if( !p_board
->box
[col
][row
].IsMine
) {
593 p_board
->box
[col
][row
].IsMine
= TRUE
;
598 * Now we label the remaining boxes with the
599 * number of mines surrounding them.
602 for( col
= 1; col
< p_board
->cols
+ 1; col
++ )
603 for( row
= 1; row
< p_board
->rows
+ 1; row
++ ) {
604 for( i
= -1; i
<= 1; i
++ )
605 for( j
= -1; j
<= 1; j
++ ) {
606 if( p_board
->box
[col
+ i
][row
+ j
].IsMine
) {
607 p_board
->box
[col
][row
].NumMines
++ ;
613 void DrawMines ( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
617 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
619 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
620 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
621 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
624 SelectObject( hMemDC
, hOldObj
);
627 void DrawMine( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, unsigned col
, unsigned row
, BOOL IsPressed
)
629 MINEBMP_OFFSET offset
= BOX_BMP
;
631 if( col
== 0 || col
> p_board
->cols
|| row
== 0 || row
> p_board
->rows
)
634 if( p_board
->status
== GAMEOVER
) {
635 if( p_board
->box
[col
][row
].IsMine
) {
636 switch( p_board
->box
[col
][row
].FlagType
) {
641 offset
= EXPLODE_BMP
;
649 switch( p_board
->box
[col
][row
].FlagType
) {
651 offset
= QUESTION_BMP
;
663 DEBUG("Unknown FlagType during game over in DrawMine\n");
667 } else { /* WAITING or PLAYING */
668 switch( p_board
->box
[col
][row
].FlagType
) {
671 offset
= QUESTION_BMP
;
688 DEBUG("Unknown FlagType while playing in DrawMine\n");
693 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
694 && !p_board
->box
[col
][row
].IsMine
)
695 offset
= (MINEBMP_OFFSET
) p_board
->box
[col
][row
].NumMines
;
698 (col
- 1) * MINE_WIDTH
+ p_board
->mines_rect
.left
,
699 (row
- 1) * MINE_HEIGHT
+ p_board
->mines_rect
.top
,
700 MINE_WIDTH
, MINE_HEIGHT
,
701 hMemDC
, 0, offset
* MINE_HEIGHT
, SRCCOPY
);
704 void DrawLeds( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, int number
, int x
, int y
)
713 led
[0] = count
/ 100 ;
714 count
-= led
[0] * 100;
717 led
[0] = 10; /* negative sign */
721 count
-= led
[1] * 10;
725 for( i
= 0; i
< 3; i
++ )
729 /* use unlit led if not playing */
730 if( p_board
->status
== WAITING
)
731 for( i
= 0; i
< 3; i
++ )
734 hOldObj
= SelectObject (hMemDC
, p_board
->hLedsBMP
);
736 for( i
= 0; i
< 3; i
++ ) {
748 SelectObject( hMemDC
, hOldObj
);
752 void DrawFace( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
756 hOldObj
= SelectObject (hMemDC
, p_board
->hFacesBMP
);
759 p_board
->face_rect
.left
,
760 p_board
->face_rect
.top
,
763 hMemDC
, 0, p_board
->face_bmp
* FACE_HEIGHT
, SRCCOPY
);
765 SelectObject( hMemDC
, hOldObj
);
769 void DrawBoard( HDC hdc
, HDC hMemDC
, PAINTSTRUCT
*ps
, BOARD
*p_board
)
773 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->counter_rect
) )
774 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->mines
- p_board
->num_flags
,
775 p_board
->counter_rect
.left
,
776 p_board
->counter_rect
.top
);
778 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->timer_rect
) )
779 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->time
,
780 p_board
->timer_rect
.left
,
781 p_board
->timer_rect
.top
);
783 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->face_rect
) )
784 DrawFace( hdc
, hMemDC
, p_board
);
786 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->mines_rect
) )
787 DrawMines( hdc
, hMemDC
, p_board
);
791 void TestBoard( HWND hWnd
, BOARD
*p_board
, unsigned x
, unsigned y
, int msg
)
799 if( PtInRect( &p_board
->mines_rect
, pt
) && p_board
->status
!= GAMEOVER
800 && p_board
->status
!= WON
)
801 TestMines( p_board
, pt
, msg
);
803 UnpressBoxes( p_board
,
806 p_board
->press
.x
= 0;
807 p_board
->press
.y
= 0;
810 if( p_board
->boxes_left
== 0 ) {
811 p_board
->status
= WON
;
813 if (p_board
->num_flags
< p_board
->mines
) {
814 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
815 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
816 if (p_board
->box
[col
][row
].IsMine
&& p_board
->box
[col
][row
].FlagType
!= FLAG
)
817 p_board
->box
[col
][row
].FlagType
= FLAG
;
821 p_board
->num_flags
= p_board
->mines
;
823 RedrawWindow( p_board
->hWnd
, NULL
, 0,
824 RDW_INVALIDATE
| RDW_UPDATENOW
);
827 if( p_board
->difficulty
!= CUSTOM
&&
828 p_board
->time
< p_board
->best_time
[p_board
->difficulty
] ) {
829 p_board
->best_time
[p_board
->difficulty
] = p_board
->time
;
831 DialogBoxParam( p_board
->hInst
, "DLG_CONGRATS", hWnd
,
832 CongratsDlgProc
, (LPARAM
) p_board
);
834 DialogBoxParam( p_board
->hInst
, "DLG_TIMES", hWnd
,
835 TimesDlgProc
, (LPARAM
) p_board
);
838 TestFace( p_board
, pt
, msg
);
841 void TestMines( BOARD
*p_board
, POINT pt
, int msg
)
846 col
= (pt
.x
- p_board
->mines_rect
.left
) / MINE_WIDTH
+ 1;
847 row
= (pt
.y
- p_board
->mines_rect
.top
) / MINE_HEIGHT
+ 1;
851 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
) {
853 p_board
->press
.x
, p_board
->press
.y
);
854 p_board
->press
.x
= col
;
855 p_board
->press
.y
= row
;
856 PressBox( p_board
, col
, row
);
862 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
864 p_board
->press
.x
, p_board
->press
.y
);
865 p_board
->press
.x
= 0;
866 p_board
->press
.y
= 0;
867 if( p_board
->box
[col
][row
].FlagType
!= FLAG
)
868 p_board
->status
= PLAYING
;
869 CompleteBox( p_board
, col
, row
);
873 PressBoxes( p_board
, col
, row
);
878 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
879 UnpressBoxes( p_board
,
880 p_board
->press
.x
, p_board
->press
.y
);
881 p_board
->press
.x
= 0;
882 p_board
->press
.y
= 0;
883 CompleteBoxes( p_board
, col
, row
);
887 AddFlag( p_board
, col
, row
);
888 p_board
->status
= PLAYING
;
891 DEBUG("Unknown message type received in TestMines\n");
897 RedrawWindow( p_board
->hWnd
, NULL
, 0,
898 RDW_INVALIDATE
| RDW_UPDATENOW
);
903 void TestFace( BOARD
*p_board
, POINT pt
, int msg
)
905 if( p_board
->status
== PLAYING
|| p_board
->status
== WAITING
) {
906 if( msg
== WM_LBUTTONDOWN
|| msg
== WM_MBUTTONDOWN
)
907 p_board
->face_bmp
= OOH_BMP
;
908 else p_board
->face_bmp
= SMILE_BMP
;
910 else if( p_board
->status
== GAMEOVER
)
911 p_board
->face_bmp
= DEAD_BMP
;
912 else if( p_board
->status
== WON
)
913 p_board
->face_bmp
= COOL_BMP
;
915 if( PtInRect( &p_board
->face_rect
, pt
) ) {
916 if( msg
== WM_LBUTTONDOWN
)
917 p_board
->face_bmp
= SPRESS_BMP
;
919 if( msg
== WM_LBUTTONUP
)
920 CreateBoard( p_board
);
923 RedrawWindow( p_board
->hWnd
, &p_board
->face_rect
, 0,
924 RDW_INVALIDATE
| RDW_UPDATENOW
);
928 void CompleteBox( BOARD
*p_board
, unsigned col
, unsigned row
)
932 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
&&
933 p_board
->box
[col
][row
].FlagType
!= FLAG
&&
934 col
> 0 && col
< p_board
->cols
+ 1 &&
935 row
> 0 && row
< p_board
->rows
+ 1 ) {
936 p_board
->box
[col
][row
].FlagType
= COMPLETE
;
938 if( p_board
->box
[col
][row
].IsMine
) {
939 p_board
->face_bmp
= DEAD_BMP
;
940 p_board
->status
= GAMEOVER
;
942 else if( p_board
->status
!= GAMEOVER
)
943 p_board
->boxes_left
--;
945 if( p_board
->box
[col
][row
].NumMines
== 0 )
947 for( i
= -1; i
<= 1; i
++ )
948 for( j
= -1; j
<= 1; j
++ )
949 CompleteBox( p_board
, col
+ i
, row
+ j
);
955 void CompleteBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
957 unsigned numFlags
= 0;
960 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
) {
961 for( i
= -1; i
<= 1; i
++ )
962 for( j
= -1; j
<= 1; j
++ ) {
963 if( p_board
->box
[col
+i
][row
+j
].FlagType
== FLAG
)
967 if( numFlags
== p_board
->box
[col
][row
].NumMines
) {
968 for( i
= -1; i
<= 1; i
++ )
969 for( j
= -1; j
<= 1; j
++ ) {
970 if( p_board
->box
[col
+i
][row
+j
].FlagType
!= FLAG
)
971 CompleteBox( p_board
, col
+i
, row
+j
);
978 void AddFlag( BOARD
*p_board
, unsigned col
, unsigned row
)
980 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
) {
981 switch( p_board
->box
[col
][row
].FlagType
) {
983 if( p_board
->IsMarkQ
)
984 p_board
->box
[col
][row
].FlagType
= QUESTION
;
986 p_board
->box
[col
][row
].FlagType
= NORMAL
;
987 p_board
->num_flags
--;
991 p_board
->box
[col
][row
].FlagType
= NORMAL
;
995 p_board
->box
[col
][row
].FlagType
= FLAG
;
996 p_board
->num_flags
++;
1002 void PressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
1008 hdc
= GetDC( p_board
->hWnd
);
1009 hMemDC
= CreateCompatibleDC( hdc
);
1010 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
1012 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, TRUE
);
1014 SelectObject( hMemDC
, hOldObj
);
1016 ReleaseDC( p_board
->hWnd
, hdc
);
1020 void PressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
1024 for( i
= -1; i
<= 1; i
++ )
1025 for( j
= -1; j
<= 1; j
++ ) {
1026 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= TRUE
;
1027 PressBox( p_board
, col
+ i
, row
+ j
);
1030 for( i
= -1; i
<= 1; i
++ )
1031 for( j
= -1; j
<= 1; j
++ ) {
1032 if( !p_board
->box
[p_board
->press
.x
+ i
][p_board
->press
.y
+ j
].IsPressed
)
1033 UnpressBox( p_board
, p_board
->press
.x
+ i
, p_board
->press
.y
+ j
);
1036 for( i
= -1; i
<= 1; i
++ )
1037 for( j
= -1; j
<= 1; j
++ ) {
1038 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= FALSE
;
1039 PressBox( p_board
, col
+ i
, row
+ j
);
1042 p_board
->press
.x
= col
;
1043 p_board
->press
.y
= row
;
1047 void UnpressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
1053 hdc
= GetDC( p_board
->hWnd
);
1054 hMemDC
= CreateCompatibleDC( hdc
);
1055 hOldObj
= SelectObject( hMemDC
, p_board
->hMinesBMP
);
1057 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
1059 SelectObject( hMemDC
, hOldObj
);
1061 ReleaseDC( p_board
->hWnd
, hdc
);
1065 void UnpressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
1069 for( i
= -1; i
<= 1; i
++ )
1070 for( j
= -1; j
<= 1; j
++ ) {
1071 UnpressBox( p_board
, col
+ i
, row
+ j
);