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
29 #include <wine/debug.h>
31 WINE_DEFAULT_DEBUG_CHANNEL(winemine
);
33 static const DWORD wnd_style
= WS_OVERLAPPEDWINDOW
& ~WS_THICKFRAME
& ~WS_MAXIMIZEBOX
;
34 static const char* registry_key
= "Software\\Microsoft\\WinMine";
37 int WINAPI
WinMain( HINSTANCE hInst
, HINSTANCE hPrevInst
, LPSTR cmdline
, int cmdshow
)
45 LoadString( hInst
, IDS_APPNAME
, appname
, sizeof(appname
));
48 wc
.lpfnWndProc
= MainProc
;
52 wc
.hIcon
= LoadIcon( hInst
, "WINEMINE" );
53 wc
.hCursor
= LoadCursor( 0, IDI_APPLICATION
);
54 wc
.hbrBackground
= (HBRUSH
) GetStockObject( BLACK_BRUSH
);
55 wc
.lpszMenuName
= "MENU_WINEMINE";
56 wc
.lpszClassName
= appname
;
58 if (!RegisterClass(&wc
)) exit(1);
59 hWnd
= CreateWindow( appname
, appname
,
61 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
66 ShowWindow( hWnd
, cmdshow
);
69 haccel
= LoadAccelerators( hInst
, MAKEINTRESOURCE(IDA_WINEMINE
) );
70 SetTimer( hWnd
, ID_TIMER
, 1000, NULL
);
72 while( GetMessage(&msg
, 0, 0, 0) ) {
73 if (!TranslateAccelerator( hWnd
, haccel
, &msg
))
74 TranslateMessage( &msg
);
76 DispatchMessage( &msg
);
81 LRESULT WINAPI
MainProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
90 board
.hInst
= ((LPCREATESTRUCT
) lParam
)->hInstance
;
93 CreateBoard( &board
);
100 WINE_TRACE("WM_PAINT\n");
101 hdc
= BeginPaint( hWnd
, &ps
);
102 hMemDC
= CreateCompatibleDC( hdc
);
104 DrawBoard( hdc
, hMemDC
, &ps
, &board
);
107 EndPaint( hWnd
, &ps
);
113 WINE_TRACE("WM_MOVE\n");
114 board
.pos
.x
= GET_X_LPARAM(lParam
);
115 board
.pos
.y
= GET_Y_LPARAM(lParam
);
120 DestroyBoard( &board
);
121 PostQuitMessage( 0 );
125 if( board
.status
== PLAYING
) {
127 RedrawWindow( hWnd
, &board
.timer_rect
, 0,
128 RDW_INVALIDATE
| RDW_UPDATENOW
);
133 WINE_TRACE("WM_LBUTTONDOWN\n");
134 if( wParam
& MK_RBUTTON
)
135 msg
= WM_MBUTTONDOWN
;
136 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
141 WINE_TRACE("WM_LBUTTONUP\n");
142 if( wParam
& MK_RBUTTON
)
144 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
149 WINE_TRACE("WM_RBUTTONDOWN\n");
150 if( wParam
& MK_LBUTTON
) {
153 msg
= WM_MBUTTONDOWN
;
155 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
159 WINE_TRACE("WM_RBUTTONUP\n");
160 if( wParam
& MK_LBUTTON
)
162 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
166 WINE_TRACE("WM_MBUTTONDOWN\n");
167 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
171 WINE_TRACE("WM_MBUTTONUP\n");
172 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
177 if( (wParam
& MK_LBUTTON
) && (wParam
& MK_RBUTTON
) ) {
178 msg
= WM_MBUTTONDOWN
;
180 else if( wParam
& MK_LBUTTON
) {
181 msg
= WM_LBUTTONDOWN
;
187 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
193 switch(LOWORD(wParam
)) {
195 CreateBoard( &board
);
199 hMenu
= GetMenu( hWnd
);
200 board
.IsMarkQ
= !board
.IsMarkQ
;
202 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
204 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
208 SetDifficulty( &board
, BEGINNER
);
209 CreateBoard( &board
);
213 SetDifficulty( &board
, ADVANCED
);
214 CreateBoard( &board
);
218 SetDifficulty( &board
, EXPERT
);
219 CreateBoard( &board
);
223 SetDifficulty( &board
, CUSTOM
);
224 CreateBoard( &board
);
228 SendMessage( hWnd
, WM_CLOSE
, 0, 0);
232 DialogBoxParam( board
.hInst
, "DLG_TIMES", hWnd
,
233 TimesDlgProc
, (LPARAM
) &board
);
237 DialogBox( board
.hInst
, "DLG_ABOUT", hWnd
, AboutDlgProc
);
240 WINE_TRACE("Unknown WM_COMMAND command message received\n");
244 return( DefWindowProc( hWnd
, msg
, wParam
, lParam
));
247 void InitBoard( BOARD
*p_board
)
251 p_board
->hMinesBMP
= LoadBitmap( p_board
->hInst
, "mines");
252 p_board
->hFacesBMP
= LoadBitmap( p_board
->hInst
, "faces");
253 p_board
->hLedsBMP
= LoadBitmap( p_board
->hInst
, "leds");
255 LoadBoard( p_board
);
257 hMenu
= GetMenu( p_board
->hWnd
);
258 CheckMenuItem( hMenu
, IDM_BEGINNER
+ (unsigned) p_board
->difficulty
,
260 if( p_board
->IsMarkQ
)
261 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
263 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
264 CheckLevel( p_board
);
267 void LoadBoard( BOARD
*p_board
)
276 RegOpenKeyEx( HKEY_CURRENT_USER
, registry_key
,
277 0, KEY_QUERY_VALUE
, &hkey
);
279 size
= sizeof( p_board
->pos
.x
);
280 if( !RegQueryValueEx( hkey
, "Xpos", NULL
, (LPDWORD
) &type
,
281 (LPBYTE
) &p_board
->pos
.x
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
284 size
= sizeof( p_board
->pos
.y
);
285 if( !RegQueryValueEx( hkey
, "Ypos", NULL
, (LPDWORD
) &type
,
286 (LPBYTE
) &p_board
->pos
.y
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
289 size
= sizeof( p_board
->rows
);
290 if( !RegQueryValueEx( hkey
, "Height", NULL
, (LPDWORD
) &type
,
291 (LPBYTE
) &p_board
->rows
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
292 p_board
->rows
= BEGINNER_ROWS
;
294 size
= sizeof( p_board
->cols
);
295 if( !RegQueryValueEx( hkey
, "Width", NULL
, (LPDWORD
) &type
,
296 (LPBYTE
) &p_board
->cols
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
297 p_board
->cols
= BEGINNER_COLS
;
299 size
= sizeof( p_board
->mines
);
300 if( !RegQueryValueEx( hkey
, "Mines", NULL
, (LPDWORD
) &type
,
301 (LPBYTE
) &p_board
->mines
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
302 p_board
->mines
= BEGINNER_MINES
;
304 size
= sizeof( p_board
->difficulty
);
305 if( !RegQueryValueEx( hkey
, "Difficulty", NULL
, (LPDWORD
) &type
,
306 (LPBYTE
) &p_board
->difficulty
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
307 p_board
->difficulty
= BEGINNER
;
309 size
= sizeof( p_board
->IsMarkQ
);
310 if( !RegQueryValueEx( hkey
, "Mark", NULL
, (LPDWORD
) &type
,
311 (LPBYTE
) &p_board
->IsMarkQ
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
312 p_board
->IsMarkQ
= TRUE
;
314 for( i
= 0; i
< 3; i
++ ) {
315 wsprintf( key_name
, "Name%d", i
+1 );
316 size
= sizeof( data
);
317 if( RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
319 (LPDWORD
) &size
) == ERROR_SUCCESS
)
320 lstrcpynA( p_board
->best_name
[i
], data
, sizeof(p_board
->best_name
[i
]) );
322 LoadString( p_board
->hInst
, IDS_NOBODY
, p_board
->best_name
[i
], 16 );
325 for( i
= 0; i
< 3; i
++ ) {
326 wsprintf( key_name
, "Time%d", i
+1 );
327 size
= sizeof( p_board
->best_time
[i
] );
328 if( !RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
329 (LPBYTE
) &p_board
->best_time
[i
],
330 (LPDWORD
) &size
) == ERROR_SUCCESS
)
331 p_board
->best_time
[i
] = 999;
336 void SaveBoard( BOARD
*p_board
)
343 if( RegCreateKeyEx( HKEY_CURRENT_USER
, registry_key
,
345 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
,
346 &hkey
, NULL
) != ERROR_SUCCESS
)
349 RegSetValueEx( hkey
, "Xpos", 0, REG_DWORD
, (LPBYTE
) &p_board
->pos
.x
, sizeof(p_board
->pos
.x
) );
350 RegSetValueEx( hkey
, "Ypos", 0, REG_DWORD
, (LPBYTE
) &p_board
->pos
.y
, sizeof(p_board
->pos
.y
) );
351 RegSetValueEx( hkey
, "Difficulty", 0, REG_DWORD
, (LPBYTE
) &p_board
->difficulty
, sizeof(p_board
->difficulty
) );
352 RegSetValueEx( hkey
, "Height", 0, REG_DWORD
, (LPBYTE
) &p_board
->rows
, sizeof(p_board
->rows
) );
353 RegSetValueEx( hkey
, "Width", 0, REG_DWORD
, (LPBYTE
) &p_board
->cols
, sizeof(p_board
->cols
) );
354 RegSetValueEx( hkey
, "Mines", 0, REG_DWORD
, (LPBYTE
) &p_board
->mines
, sizeof(p_board
->mines
) );
355 RegSetValueEx( hkey
, "Mark", 0, REG_DWORD
, (LPBYTE
) &p_board
->IsMarkQ
, sizeof(p_board
->IsMarkQ
) );
357 for( i
= 0; i
< 3; i
++ ) {
358 wsprintf( key_name
, "Name%u", i
+1 );
359 lstrcpyn( data
, p_board
->best_name
[i
], sizeof( data
) );
360 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
363 for( i
= 0; i
< 3; i
++ ) {
364 wsprintf( key_name
, "Time%u", i
+1 );
365 RegSetValueEx( hkey
, key_name
, 0, REG_DWORD
, (LPBYTE
) &p_board
->best_time
[i
], sizeof(p_board
->best_time
[i
]) );
370 void DestroyBoard( BOARD
*p_board
)
372 DeleteObject( p_board
->hFacesBMP
);
373 DeleteObject( p_board
->hLedsBMP
);
374 DeleteObject( p_board
->hMinesBMP
);
377 void SetDifficulty( BOARD
*p_board
, DIFFICULTY difficulty
)
381 if ( difficulty
== CUSTOM
)
382 if (DialogBoxParam( p_board
->hInst
, "DLG_CUSTOM", p_board
->hWnd
,
383 CustomDlgProc
, (LPARAM
) p_board
) != 0)
386 hMenu
= GetMenu( p_board
->hWnd
);
387 CheckMenuItem( hMenu
, IDM_BEGINNER
+ p_board
->difficulty
, MF_UNCHECKED
);
388 p_board
->difficulty
= difficulty
;
389 CheckMenuItem( hMenu
, IDM_BEGINNER
+ difficulty
, MF_CHECKED
);
391 switch( difficulty
) {
393 p_board
->cols
= BEGINNER_COLS
;
394 p_board
->rows
= BEGINNER_ROWS
;
395 p_board
->mines
= BEGINNER_MINES
;
399 p_board
->cols
= ADVANCED_COLS
;
400 p_board
->rows
= ADVANCED_ROWS
;
401 p_board
->mines
= ADVANCED_MINES
;
405 p_board
->cols
= EXPERT_COLS
;
406 p_board
->rows
= EXPERT_ROWS
;
408 p_board
->mines
= EXPERT_MINES
;
416 static void ShiftBetween(LONG
* x
, LONG
* y
, LONG a
, LONG b
)
428 static void MoveOnScreen(RECT
* rect
)
433 /* find the nearest monitor ... */
434 hMonitor
= MonitorFromRect(rect
, MONITOR_DEFAULTTONEAREST
);
436 /* ... and move it into the work area (ie excluding task bar)*/
437 mi
.cbSize
= sizeof(mi
);
438 GetMonitorInfo(hMonitor
, &mi
);
440 ShiftBetween(&rect
->left
, &rect
->right
, mi
.rcWork
.left
, mi
.rcWork
.right
);
441 ShiftBetween(&rect
->top
, &rect
->bottom
, mi
.rcWork
.top
, mi
.rcWork
.bottom
);
444 void CreateBoard( BOARD
*p_board
)
446 int left
, top
, bottom
, right
;
449 p_board
->mb
= MB_NONE
;
450 p_board
->boxes_left
= p_board
->cols
* p_board
->rows
- p_board
->mines
;
451 p_board
->num_flags
= 0;
453 CreateBoxes( p_board
);
455 p_board
->width
= p_board
->cols
* MINE_WIDTH
+ BOARD_WMARGIN
* 2;
457 p_board
->height
= p_board
->rows
* MINE_HEIGHT
+ LED_HEIGHT
460 /* setting the mines rectangle boundary */
461 left
= BOARD_WMARGIN
;
462 top
= BOARD_HMARGIN
* 2 + LED_HEIGHT
;
463 right
= left
+ p_board
->cols
* MINE_WIDTH
;
464 bottom
= top
+ p_board
->rows
* MINE_HEIGHT
;
465 SetRect( &p_board
->mines_rect
, left
, top
, right
, bottom
);
467 /* setting the face rectangle boundary */
468 left
= p_board
->width
/ 2 - FACE_WIDTH
/ 2;
470 right
= left
+ FACE_WIDTH
;
471 bottom
= top
+ FACE_HEIGHT
;
472 SetRect( &p_board
->face_rect
, left
, top
, right
, bottom
);
474 /* setting the timer rectangle boundary */
475 left
= BOARD_WMARGIN
;
477 right
= left
+ LED_WIDTH
* 3;
478 bottom
= top
+ LED_HEIGHT
;
479 SetRect( &p_board
->timer_rect
, left
, top
, right
, bottom
);
481 /* setting the counter rectangle boundary */
482 left
= p_board
->width
- BOARD_WMARGIN
- LED_WIDTH
* 3;
484 right
= p_board
->width
- BOARD_WMARGIN
;
485 bottom
= top
+ LED_HEIGHT
;
486 SetRect( &p_board
->counter_rect
, left
, top
, right
, bottom
);
488 p_board
->status
= WAITING
;
489 p_board
->face_bmp
= SMILE_BMP
;
492 wnd_rect
.left
= p_board
->pos
.x
;
493 wnd_rect
.right
= p_board
->pos
.x
+ p_board
->width
;
494 wnd_rect
.top
= p_board
->pos
.y
;
495 wnd_rect
.bottom
= p_board
->pos
.y
+ p_board
->height
;
496 AdjustWindowRect(&wnd_rect
, wnd_style
, TRUE
);
498 /* Make sure the window is completely on the screen */
499 MoveOnScreen(&wnd_rect
);
500 MoveWindow( p_board
->hWnd
, wnd_rect
.left
, wnd_rect
.top
,
501 wnd_rect
.right
- wnd_rect
.left
,
502 wnd_rect
.bottom
- wnd_rect
.top
,
504 RedrawWindow( p_board
->hWnd
, NULL
, 0,
505 RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_ERASE
);
509 void CheckLevel( BOARD
*p_board
)
511 if( p_board
->rows
< BEGINNER_ROWS
)
512 p_board
->rows
= BEGINNER_ROWS
;
514 if( p_board
->rows
> MAX_ROWS
)
515 p_board
->rows
= MAX_ROWS
;
517 if( p_board
->cols
< BEGINNER_COLS
)
518 p_board
->cols
= BEGINNER_COLS
;
520 if( p_board
->cols
> MAX_COLS
)
521 p_board
->cols
= MAX_COLS
;
523 if( p_board
->mines
< BEGINNER_MINES
)
524 p_board
->mines
= BEGINNER_MINES
;
526 if( p_board
->mines
> p_board
->cols
* p_board
->rows
- 1 )
527 p_board
->mines
= p_board
->cols
* p_board
->rows
- 1;
531 void CreateBoxes( BOARD
*p_board
)
536 srand( (unsigned) time( NULL
) );
538 /* Create the boxes...
539 * We actually create them with an empty border,
540 * so special care doesn't have to be taken on the edges
543 for( col
= 0; col
<= p_board
->cols
+ 1; col
++ )
544 for( row
= 0; row
<= p_board
->rows
+ 1; row
++ ) {
545 p_board
->box
[col
][row
].IsPressed
= FALSE
;
546 p_board
->box
[col
][row
].IsMine
= FALSE
;
547 p_board
->box
[col
][row
].FlagType
= NORMAL
;
548 p_board
->box
[col
][row
].NumMines
= 0;
553 while( (unsigned) i
< p_board
->mines
) {
554 col
= (int) (p_board
->cols
* (float) rand() / RAND_MAX
+ 1);
555 row
= (int) (p_board
->rows
* (float) rand() / RAND_MAX
+ 1);
557 if( !p_board
->box
[col
][row
].IsMine
) {
559 p_board
->box
[col
][row
].IsMine
= TRUE
;
564 * Now we label the remaining boxes with the
565 * number of mines surrounding them.
568 for( col
= 1; col
< p_board
->cols
+ 1; col
++ )
569 for( row
= 1; row
< p_board
->rows
+ 1; row
++ ) {
570 for( i
= -1; i
<= 1; i
++ )
571 for( j
= -1; j
<= 1; j
++ ) {
572 if( p_board
->box
[col
+ i
][row
+ j
].IsMine
) {
573 p_board
->box
[col
][row
].NumMines
++ ;
579 void DrawMines ( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
583 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
585 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
586 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
587 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
590 SelectObject( hMemDC
, hOldObj
);
593 void DrawMine( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, unsigned col
, unsigned row
, BOOL IsPressed
)
595 MINEBMP_OFFSET offset
= BOX_BMP
;
597 if( col
== 0 || col
> p_board
->cols
|| row
== 0 || row
> p_board
->rows
)
600 if( p_board
->status
== GAMEOVER
) {
601 if( p_board
->box
[col
][row
].IsMine
) {
602 switch( p_board
->box
[col
][row
].FlagType
) {
607 offset
= EXPLODE_BMP
;
615 switch( p_board
->box
[col
][row
].FlagType
) {
617 offset
= QUESTION_BMP
;
629 WINE_TRACE("Unknown FlagType during game over in DrawMine\n");
633 } else { /* WAITING or PLAYING */
634 switch( p_board
->box
[col
][row
].FlagType
) {
637 offset
= QUESTION_BMP
;
654 WINE_TRACE("Unknown FlagType while playing in DrawMine\n");
659 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
660 && !p_board
->box
[col
][row
].IsMine
)
661 offset
= (MINEBMP_OFFSET
) p_board
->box
[col
][row
].NumMines
;
664 (col
- 1) * MINE_WIDTH
+ p_board
->mines_rect
.left
,
665 (row
- 1) * MINE_HEIGHT
+ p_board
->mines_rect
.top
,
666 MINE_WIDTH
, MINE_HEIGHT
,
667 hMemDC
, 0, offset
* MINE_HEIGHT
, SRCCOPY
);
670 void DrawLeds( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, int number
, int x
, int y
)
679 led
[0] = count
/ 100 ;
680 count
-= led
[0] * 100;
683 led
[0] = 10; /* negative sign */
687 count
-= led
[1] * 10;
691 for( i
= 0; i
< 3; i
++ )
695 /* use unlit led if not playing */
696 if( p_board
->status
== WAITING
)
697 for( i
= 0; i
< 3; i
++ )
700 hOldObj
= SelectObject (hMemDC
, p_board
->hLedsBMP
);
702 for( i
= 0; i
< 3; i
++ ) {
714 SelectObject( hMemDC
, hOldObj
);
718 void DrawFace( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
722 hOldObj
= SelectObject (hMemDC
, p_board
->hFacesBMP
);
725 p_board
->face_rect
.left
,
726 p_board
->face_rect
.top
,
729 hMemDC
, 0, p_board
->face_bmp
* FACE_HEIGHT
, SRCCOPY
);
731 SelectObject( hMemDC
, hOldObj
);
735 void DrawBoard( HDC hdc
, HDC hMemDC
, PAINTSTRUCT
*ps
, BOARD
*p_board
)
739 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->counter_rect
) )
740 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->mines
- p_board
->num_flags
,
741 p_board
->counter_rect
.left
,
742 p_board
->counter_rect
.top
);
744 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->timer_rect
) )
745 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->time
,
746 p_board
->timer_rect
.left
,
747 p_board
->timer_rect
.top
);
749 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->face_rect
) )
750 DrawFace( hdc
, hMemDC
, p_board
);
752 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->mines_rect
) )
753 DrawMines( hdc
, hMemDC
, p_board
);
757 void TestBoard( HWND hWnd
, BOARD
*p_board
, unsigned x
, unsigned y
, int msg
)
765 if( PtInRect( &p_board
->mines_rect
, pt
) && p_board
->status
!= GAMEOVER
766 && p_board
->status
!= WON
)
767 TestMines( p_board
, pt
, msg
);
769 UnpressBoxes( p_board
,
772 p_board
->press
.x
= 0;
773 p_board
->press
.y
= 0;
776 if( p_board
->boxes_left
== 0 ) {
777 p_board
->status
= WON
;
779 if (p_board
->num_flags
< p_board
->mines
) {
780 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
781 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
782 if (p_board
->box
[col
][row
].IsMine
&& p_board
->box
[col
][row
].FlagType
!= FLAG
)
783 p_board
->box
[col
][row
].FlagType
= FLAG
;
787 p_board
->num_flags
= p_board
->mines
;
789 RedrawWindow( p_board
->hWnd
, NULL
, 0,
790 RDW_INVALIDATE
| RDW_UPDATENOW
);
793 if( p_board
->difficulty
!= CUSTOM
&&
794 p_board
->time
< p_board
->best_time
[p_board
->difficulty
] ) {
795 p_board
->best_time
[p_board
->difficulty
] = p_board
->time
;
797 DialogBoxParam( p_board
->hInst
, "DLG_CONGRATS", hWnd
,
798 CongratsDlgProc
, (LPARAM
) p_board
);
800 DialogBoxParam( p_board
->hInst
, "DLG_TIMES", hWnd
,
801 TimesDlgProc
, (LPARAM
) p_board
);
804 TestFace( p_board
, pt
, msg
);
807 void TestMines( BOARD
*p_board
, POINT pt
, int msg
)
812 col
= (pt
.x
- p_board
->mines_rect
.left
) / MINE_WIDTH
+ 1;
813 row
= (pt
.y
- p_board
->mines_rect
.top
) / MINE_HEIGHT
+ 1;
817 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
) {
819 p_board
->press
.x
, p_board
->press
.y
);
820 p_board
->press
.x
= col
;
821 p_board
->press
.y
= row
;
822 PressBox( p_board
, col
, row
);
828 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
830 p_board
->press
.x
, p_board
->press
.y
);
831 p_board
->press
.x
= 0;
832 p_board
->press
.y
= 0;
833 if( p_board
->box
[col
][row
].FlagType
!= FLAG
)
834 p_board
->status
= PLAYING
;
835 CompleteBox( p_board
, col
, row
);
839 PressBoxes( p_board
, col
, row
);
844 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
845 UnpressBoxes( p_board
,
846 p_board
->press
.x
, p_board
->press
.y
);
847 p_board
->press
.x
= 0;
848 p_board
->press
.y
= 0;
849 CompleteBoxes( p_board
, col
, row
);
853 AddFlag( p_board
, col
, row
);
854 p_board
->status
= PLAYING
;
857 WINE_TRACE("Unknown message type received in TestMines\n");
863 RedrawWindow( p_board
->hWnd
, NULL
, 0,
864 RDW_INVALIDATE
| RDW_UPDATENOW
);
869 void TestFace( BOARD
*p_board
, POINT pt
, int msg
)
871 if( p_board
->status
== PLAYING
|| p_board
->status
== WAITING
) {
872 if( msg
== WM_LBUTTONDOWN
|| msg
== WM_MBUTTONDOWN
)
873 p_board
->face_bmp
= OOH_BMP
;
874 else p_board
->face_bmp
= SMILE_BMP
;
876 else if( p_board
->status
== GAMEOVER
)
877 p_board
->face_bmp
= DEAD_BMP
;
878 else if( p_board
->status
== WON
)
879 p_board
->face_bmp
= COOL_BMP
;
881 if( PtInRect( &p_board
->face_rect
, pt
) ) {
882 if( msg
== WM_LBUTTONDOWN
)
883 p_board
->face_bmp
= SPRESS_BMP
;
885 if( msg
== WM_LBUTTONUP
)
886 CreateBoard( p_board
);
889 RedrawWindow( p_board
->hWnd
, &p_board
->face_rect
, 0,
890 RDW_INVALIDATE
| RDW_UPDATENOW
);
894 void CompleteBox( BOARD
*p_board
, unsigned col
, unsigned row
)
898 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
&&
899 p_board
->box
[col
][row
].FlagType
!= FLAG
&&
900 col
> 0 && col
< p_board
->cols
+ 1 &&
901 row
> 0 && row
< p_board
->rows
+ 1 ) {
902 p_board
->box
[col
][row
].FlagType
= COMPLETE
;
904 if( p_board
->box
[col
][row
].IsMine
) {
905 p_board
->face_bmp
= DEAD_BMP
;
906 p_board
->status
= GAMEOVER
;
908 else if( p_board
->status
!= GAMEOVER
)
909 p_board
->boxes_left
--;
911 if( p_board
->box
[col
][row
].NumMines
== 0 )
913 for( i
= -1; i
<= 1; i
++ )
914 for( j
= -1; j
<= 1; j
++ )
915 CompleteBox( p_board
, col
+ i
, row
+ j
);
921 void CompleteBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
923 unsigned numFlags
= 0;
926 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
) {
927 for( i
= -1; i
<= 1; i
++ )
928 for( j
= -1; j
<= 1; j
++ ) {
929 if( p_board
->box
[col
+i
][row
+j
].FlagType
== FLAG
)
933 if( numFlags
== p_board
->box
[col
][row
].NumMines
) {
934 for( i
= -1; i
<= 1; i
++ )
935 for( j
= -1; j
<= 1; j
++ ) {
936 if( p_board
->box
[col
+i
][row
+j
].FlagType
!= FLAG
)
937 CompleteBox( p_board
, col
+i
, row
+j
);
944 void AddFlag( BOARD
*p_board
, unsigned col
, unsigned row
)
946 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
) {
947 switch( p_board
->box
[col
][row
].FlagType
) {
949 if( p_board
->IsMarkQ
)
950 p_board
->box
[col
][row
].FlagType
= QUESTION
;
952 p_board
->box
[col
][row
].FlagType
= NORMAL
;
953 p_board
->num_flags
--;
957 p_board
->box
[col
][row
].FlagType
= NORMAL
;
961 p_board
->box
[col
][row
].FlagType
= FLAG
;
962 p_board
->num_flags
++;
968 void PressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
974 hdc
= GetDC( p_board
->hWnd
);
975 hMemDC
= CreateCompatibleDC( hdc
);
976 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
978 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, TRUE
);
980 SelectObject( hMemDC
, hOldObj
);
982 ReleaseDC( p_board
->hWnd
, hdc
);
986 void PressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
990 for( i
= -1; i
<= 1; i
++ )
991 for( j
= -1; j
<= 1; j
++ ) {
992 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= TRUE
;
993 PressBox( p_board
, col
+ i
, row
+ j
);
996 for( i
= -1; i
<= 1; i
++ )
997 for( j
= -1; j
<= 1; j
++ ) {
998 if( !p_board
->box
[p_board
->press
.x
+ i
][p_board
->press
.y
+ j
].IsPressed
)
999 UnpressBox( p_board
, p_board
->press
.x
+ i
, p_board
->press
.y
+ j
);
1002 for( i
= -1; i
<= 1; i
++ )
1003 for( j
= -1; j
<= 1; j
++ ) {
1004 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= FALSE
;
1005 PressBox( p_board
, col
+ i
, row
+ j
);
1008 p_board
->press
.x
= col
;
1009 p_board
->press
.y
= row
;
1013 void UnpressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
1019 hdc
= GetDC( p_board
->hWnd
);
1020 hMemDC
= CreateCompatibleDC( hdc
);
1021 hOldObj
= SelectObject( hMemDC
, p_board
->hMinesBMP
);
1023 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
1025 SelectObject( hMemDC
, hOldObj
);
1027 ReleaseDC( p_board
->hWnd
, hdc
);
1031 void UnpressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
1035 for( i
= -1; i
<= 1; i
++ )
1036 for( j
= -1; j
<= 1; j
++ ) {
1037 UnpressBox( p_board
, col
+ i
, row
+ j
);