4 * Copyright 2000 Joshua Thielen <jt85296@ltu.edu>
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 /* Work around a Wine bug which defines handles as UINT rather than LPVOID */
31 #define NULL_HANDLE NULL
38 #define DEBUG(x) fprintf(stderr,x)
44 int WINAPI
WinMain( HINSTANCE hInst
, HINSTANCE hPrevInst
, LPSTR cmdline
, int cmdshow
)
52 LoadString( hInst
, IDS_APPNAME
, appname
, sizeof(appname
));
55 wc
.lpfnWndProc
= MainProc
;
59 wc
.hIcon
= LoadIcon( hInst
, appname
);
60 wc
.hCursor
= LoadCursor( NULL_HANDLE
, (LPCTSTR
)IDI_APPLICATION
);
61 wc
.hbrBackground
= (HBRUSH
) GetStockObject( BLACK_BRUSH
);
62 wc
.lpszMenuName
= "MENU_WINEMINE";
63 wc
.lpszClassName
= appname
;
65 if (!RegisterClass(&wc
)) exit(1);
66 hWnd
= CreateWindow( appname
, appname
,
67 WS_OVERLAPPEDWINDOW
& ~WS_THICKFRAME
& ~WS_MAXIMIZEBOX
,
68 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
69 NULL_HANDLE
, NULL_HANDLE
, hInst
, NULL
);
73 ShowWindow( hWnd
, cmdshow
);
76 haccel
= LoadAccelerators( hInst
, appname
);
77 SetTimer( hWnd
, ID_TIMER
, 1000, NULL
);
79 while( GetMessage(&msg
, NULL_HANDLE
, 0, 0) ) {
80 if (!TranslateAccelerator( hWnd
, haccel
, &msg
))
81 TranslateMessage( &msg
);
83 DispatchMessage( &msg
);
89 LRESULT WINAPI
MainProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
98 board
.hInst
= ((LPCREATESTRUCT
) lParam
)->hInstance
;
101 CreateBoard( &board
);
109 hdc
= BeginPaint( hWnd
, &ps
);
110 hMemDC
= CreateCompatibleDC( hdc
);
112 DrawBoard( hdc
, hMemDC
, &ps
, &board
);
115 EndPaint( hWnd
, &ps
);
122 board
.pos
.x
= (unsigned) LOWORD(lParam
);
123 board
.pos
.y
= (unsigned) HIWORD(lParam
);
128 DestroyBoard( &board
);
129 PostQuitMessage( 0 );
133 if( board
.status
== PLAYING
) {
135 RedrawWindow( hWnd
, &board
.timer_rect
, NULL_HANDLE
,
136 RDW_INVALIDATE
| RDW_UPDATENOW
);
141 DEBUG("WM_LBUTTONDOWN\n");
142 if( wParam
& MK_RBUTTON
)
143 msg
= WM_MBUTTONDOWN
;
144 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
149 DEBUG("WM_LBUTTONUP\n");
150 if( wParam
& MK_RBUTTON
)
152 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
157 DEBUG("WM_RBUTTONDOWN\n");
158 if( wParam
& MK_LBUTTON
) {
161 msg
= WM_MBUTTONDOWN
;
163 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
167 DEBUG("WM_RBUTTONUP\n");
168 if( wParam
& MK_LBUTTON
)
170 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
174 DEBUG("WM_MBUTTONDOWN\n");
175 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
179 DEBUG("WM_MBUTTONUP\n");
180 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
185 if( (wParam
& MK_LBUTTON
) && (wParam
& MK_RBUTTON
) ) {
186 msg
= WM_MBUTTONDOWN
;
188 else if( wParam
& MK_LBUTTON
) {
189 msg
= WM_LBUTTONDOWN
;
195 TestBoard( hWnd
, &board
, LOWORD(lParam
), HIWORD(lParam
), msg
);
201 switch(LOWORD(wParam
)) {
203 CreateBoard( &board
);
207 hMenu
= GetMenu( hWnd
);
208 board
.IsMarkQ
= !board
.IsMarkQ
;
210 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
212 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
216 SetDifficulty( &board
, BEGINNER
);
217 CreateBoard( &board
);
221 SetDifficulty( &board
, ADVANCED
);
222 CreateBoard( &board
);
226 SetDifficulty( &board
, EXPERT
);
227 CreateBoard( &board
);
231 SetDifficulty( &board
, CUSTOM
);
232 CreateBoard( &board
);
236 SendMessage( hWnd
, WM_CLOSE
, 0, 0);
240 DialogBoxParam( board
.hInst
, "DLG_TIMES", hWnd
,
241 TimesDlgProc
, (LPARAM
) &board
);
245 DialogBox( board
.hInst
, "DLG_ABOUT", hWnd
, AboutDlgProc
);
248 DEBUG("Unknown WM_COMMAND command message received\n");
252 return( DefWindowProc( hWnd
, msg
, wParam
, lParam
));
255 void InitBoard( BOARD
*p_board
)
259 p_board
->hMinesBMP
= LoadBitmap( p_board
->hInst
, (LPCSTR
) IDB_MINES
);
260 p_board
->hFacesBMP
= LoadBitmap( p_board
->hInst
, (LPCSTR
) IDB_FACES
);
261 p_board
->hLedsBMP
= LoadBitmap( p_board
->hInst
, (LPCSTR
) IDB_LEDS
);
263 LoadBoard( p_board
);
265 if( p_board
->pos
.x
< (unsigned) GetSystemMetrics( SM_CXFIXEDFRAME
))
266 p_board
->pos
.x
= GetSystemMetrics( SM_CXFIXEDFRAME
);
268 if( p_board
->pos
.x
> (unsigned) (GetSystemMetrics( SM_CXSCREEN
)
269 - GetSystemMetrics( SM_CXFIXEDFRAME
))) {
270 p_board
->pos
.x
= GetSystemMetrics( SM_CXSCREEN
)
271 - GetSystemMetrics( SM_CXFIXEDFRAME
);
274 if( p_board
->pos
.y
< (unsigned) (GetSystemMetrics( SM_CYMENU
)
275 + GetSystemMetrics( SM_CYCAPTION
)
276 + GetSystemMetrics( SM_CYFIXEDFRAME
))) {
277 p_board
->pos
.y
= GetSystemMetrics( SM_CYMENU
) +
278 GetSystemMetrics( SM_CYCAPTION
) +
279 GetSystemMetrics( SM_CYFIXEDFRAME
);
282 if( p_board
->pos
.y
> (unsigned) (GetSystemMetrics( SM_CYSCREEN
)
283 - GetSystemMetrics( SM_CYFIXEDFRAME
))) {
284 p_board
->pos
.y
= GetSystemMetrics( SM_CYSCREEN
)
285 - GetSystemMetrics( SM_CYFIXEDFRAME
);
288 hMenu
= GetMenu( p_board
->hWnd
);
289 CheckMenuItem( hMenu
, IDM_BEGINNER
+ (unsigned) p_board
->difficulty
,
291 if( p_board
->IsMarkQ
)
292 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
294 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
295 CheckLevel( p_board
);
298 void LoadBoard( BOARD
*p_board
)
308 RegOpenKeyEx( HKEY_LOCAL_MACHINE
, "Software\\Wine\\WineMine",
309 0, KEY_QUERY_VALUE
, &hkey
);
311 size
= sizeof( data
);
312 if( RegQueryValueEx( hkey
, "Xpos", NULL
, (LPDWORD
) &type
,
313 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
) {
314 p_board
->pos
.x
= atoi( data
);
317 p_board
->pos
.x
= GetSystemMetrics( SM_CXFIXEDFRAME
);
319 size
= sizeof( data
);
320 if( RegQueryValueEx( hkey
, "Ypos", NULL
, (LPDWORD
) &type
,
321 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
322 p_board
->pos
.y
= atoi( data
);
324 p_board
->pos
.y
= GetSystemMetrics( SM_CYMENU
)
325 + GetSystemMetrics( SM_CYCAPTION
)
326 + GetSystemMetrics( SM_CYFIXEDFRAME
);
328 size
= sizeof( data
);
329 if( RegQueryValueEx( hkey
, "Rows", NULL
, (LPDWORD
) &type
,
330 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
331 p_board
->rows
= atoi( data
);
333 p_board
->rows
= BEGINNER_ROWS
;
335 size
= sizeof( data
);
336 if( RegQueryValueEx( hkey
, "Cols", NULL
, (LPDWORD
) &type
,
337 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
338 p_board
->cols
= atoi( data
);
340 p_board
->cols
= BEGINNER_COLS
;
342 size
= sizeof( data
);
343 if( RegQueryValueEx( hkey
, "Mines", NULL
, (LPDWORD
) &type
,
344 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
345 p_board
->mines
= atoi( data
);
347 p_board
->rows
= BEGINNER_ROWS
;
349 size
= sizeof( data
);
350 if( RegQueryValueEx( hkey
, "Difficulty", NULL
, (LPDWORD
) &type
,
351 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
352 p_board
->difficulty
= (DIFFICULTY
) atoi( data
);
354 p_board
->difficulty
= BEGINNER
;
356 size
= sizeof( data
);
357 if( RegQueryValueEx( hkey
, "MarkQ", NULL
, (LPDWORD
) &type
,
358 (LPBYTE
) data
, (LPDWORD
) &size
) == ERROR_SUCCESS
)
359 p_board
->IsMarkQ
= atoi( data
);
361 p_board
->IsMarkQ
= TRUE
;
363 for( i
= 0; i
< 3; i
++ ) {
364 wsprintf( key_name
, "Name%d", i
);
365 size
= sizeof( data
);
366 if( RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
368 (LPDWORD
) &size
) == ERROR_SUCCESS
)
369 strncpy( p_board
->best_name
[i
], data
, sizeof( data
) );
371 wsprintf( p_board
->best_name
[i
], "Nobody");
374 for( i
= 0; i
< 3; i
++ ) {
375 wsprintf( key_name
, "Time%d", i
);
376 size
= sizeof( data
);
377 if( RegQueryValueEx( hkey
, key_name
, NULL
, (LPDWORD
) &type
,
379 (LPDWORD
) &size
) == ERROR_SUCCESS
)
380 p_board
->best_time
[i
] = atoi( data
);
382 p_board
->best_time
[i
] = 999;
387 void SaveBoard( BOARD
*p_board
)
395 if( RegCreateKeyEx( HKEY_LOCAL_MACHINE
,
396 "Software\\Wine\\WineMine", 0, NULL
,
397 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
,
398 &hkey
, &disp
) != ERROR_SUCCESS
)
401 wsprintf( data
, "%d", p_board
->pos
.x
);
402 RegSetValueEx( hkey
, "Xpos", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
404 wsprintf( data
, "%d", p_board
->pos
.x
);
405 RegSetValueEx( hkey
, "Ypos", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
407 wsprintf( data
, "%d", (int) p_board
->difficulty
);
408 RegSetValueEx( hkey
, "Difficulty", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
410 wsprintf( data
, "%d", p_board
->rows
);
411 RegSetValueEx( hkey
, "Rows", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
413 wsprintf( data
, "%d", p_board
->cols
);
414 RegSetValueEx( hkey
, "Cols", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
416 wsprintf( data
, "%d", p_board
->mines
);
417 RegSetValueEx( hkey
, "Mines", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
419 wsprintf( data
, "%d", (int) p_board
->IsMarkQ
);
420 RegSetValueEx( hkey
, "MarkQ", 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
422 for( i
= 0; i
< 3; i
++ ) {
423 wsprintf( key_name
, "Name%u", i
);
424 strncpy( data
, p_board
->best_name
[i
], sizeof( data
) );
425 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
428 for( i
= 0; i
< 3; i
++ ) {
429 wsprintf( key_name
, "Time%u", i
);
430 wsprintf( data
, "%d", p_board
->best_time
[i
] );
431 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
436 void DestroyBoard( BOARD
*p_board
)
438 DeleteObject( p_board
->hFacesBMP
);
439 DeleteObject( p_board
->hLedsBMP
);
440 DeleteObject( p_board
->hMinesBMP
);
443 void SetDifficulty( BOARD
*p_board
, DIFFICULTY difficulty
)
445 HMENU hMenu
= GetMenu( p_board
->hWnd
);
447 CheckMenuItem( hMenu
, IDM_BEGINNER
+ p_board
->difficulty
, MF_UNCHECKED
);
448 p_board
->difficulty
= difficulty
;
449 CheckMenuItem( hMenu
, IDM_BEGINNER
+ difficulty
, MF_CHECKED
);
451 switch( difficulty
) {
453 p_board
->cols
= BEGINNER_COLS
;
454 p_board
->rows
= BEGINNER_ROWS
;
455 p_board
->mines
= BEGINNER_MINES
;
459 p_board
->cols
= ADVANCED_COLS
;
460 p_board
->rows
= ADVANCED_ROWS
;
461 p_board
->mines
= ADVANCED_MINES
;
465 p_board
->cols
= EXPERT_COLS
;
466 p_board
->rows
= EXPERT_ROWS
;
467 p_board
->mines
= EXPERT_MINES
;
471 DialogBoxParam( p_board
->hInst
, "DLG_CUSTOM", p_board
->hWnd
,
472 CustomDlgProc
, (LPARAM
) p_board
);
477 void CreateBoard( BOARD
*p_board
)
479 int left
, top
, bottom
, right
, wnd_x
, wnd_y
, wnd_width
, wnd_height
;
481 p_board
->mb
= MB_NONE
;
482 p_board
->boxes_left
= p_board
->cols
* p_board
->rows
- p_board
->mines
;
483 p_board
->num_flags
= 0;
485 CreateBoxes( p_board
);
487 p_board
->width
= p_board
->cols
* MINE_WIDTH
+ BOARD_WMARGIN
* 2;
489 p_board
->height
= p_board
->rows
* MINE_HEIGHT
+ LED_HEIGHT
492 wnd_x
= p_board
->pos
.x
- GetSystemMetrics( SM_CXFIXEDFRAME
);
493 wnd_y
= p_board
->pos
.y
- GetSystemMetrics( SM_CYMENU
)
494 - GetSystemMetrics( SM_CYCAPTION
)
495 - GetSystemMetrics( SM_CYFIXEDFRAME
);
496 wnd_width
= p_board
->width
497 + GetSystemMetrics( SM_CXFIXEDFRAME
) * 2;
498 wnd_height
= p_board
->height
499 + GetSystemMetrics( SM_CYMENU
)
500 + GetSystemMetrics( SM_CYCAPTION
)
501 + GetSystemMetrics( SM_CYFIXEDFRAME
) * 2;
503 /* setting the mines rectangle boundary */
504 left
= BOARD_WMARGIN
;
505 top
= BOARD_HMARGIN
* 2 + LED_HEIGHT
;
506 right
= left
+ p_board
->cols
* MINE_WIDTH
;
507 bottom
= top
+ p_board
->rows
* MINE_HEIGHT
;
508 SetRect( &p_board
->mines_rect
, left
, top
, right
, bottom
);
510 /* setting the face rectangle boundary */
511 left
= p_board
->width
/ 2 - FACE_WIDTH
/ 2;
513 right
= left
+ FACE_WIDTH
;
514 bottom
= top
+ FACE_HEIGHT
;
515 SetRect( &p_board
->face_rect
, left
, top
, right
, bottom
);
517 /* setting the timer rectangle boundary */
518 left
= BOARD_WMARGIN
;
520 right
= left
+ LED_WIDTH
* 3;
521 bottom
= top
+ LED_HEIGHT
;
522 SetRect( &p_board
->timer_rect
, left
, top
, right
, bottom
);
524 /* setting the counter rectangle boundary */
525 left
= p_board
->width
- BOARD_WMARGIN
- LED_WIDTH
* 3;
527 right
= p_board
->width
- BOARD_WMARGIN
;
528 bottom
= top
+ LED_HEIGHT
;
529 SetRect( &p_board
->counter_rect
, left
, top
, right
, bottom
);
531 p_board
->status
= WAITING
;
532 p_board
->face_bmp
= SMILE_BMP
;
535 MoveWindow( p_board
->hWnd
, wnd_x
, wnd_y
, wnd_width
, wnd_height
, TRUE
);
536 RedrawWindow( p_board
->hWnd
, NULL
, NULL_HANDLE
,
537 RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_ERASE
);
541 void CheckLevel( BOARD
*p_board
)
543 if( p_board
->rows
< BEGINNER_ROWS
)
544 p_board
->rows
= BEGINNER_ROWS
;
546 if( p_board
->rows
> MAX_ROWS
)
547 p_board
->rows
= MAX_ROWS
;
549 if( p_board
->cols
< BEGINNER_COLS
)
550 p_board
->cols
= BEGINNER_COLS
;
552 if( p_board
->cols
> MAX_COLS
)
553 p_board
->cols
= MAX_COLS
;
555 if( p_board
->mines
< BEGINNER_MINES
)
556 p_board
->mines
= BEGINNER_MINES
;
558 if( p_board
->mines
> p_board
->cols
* p_board
->rows
- 1 )
559 p_board
->mines
= p_board
->cols
* p_board
->rows
- 1;
563 void CreateBoxes( BOARD
*p_board
)
568 srand( (unsigned) time( NULL
) );
570 /* Create the boxes...
571 * We actually create them with an empty border,
572 * so special care doesn't have to be taken on the edges
575 for( col
= 0; col
<= p_board
->cols
+ 1; col
++ )
576 for( row
= 0; row
<= p_board
->rows
+ 1; row
++ ) {
577 p_board
->box
[col
][row
].IsPressed
= FALSE
;
578 p_board
->box
[col
][row
].IsMine
= FALSE
;
579 p_board
->box
[col
][row
].FlagType
= NORMAL
;
580 p_board
->box
[col
][row
].NumMines
= 0;
585 while( (unsigned) i
< p_board
->mines
) {
586 col
= (int) (p_board
->cols
* (float) rand() / RAND_MAX
+ 1);
587 row
= (int) (p_board
->rows
* (float) rand() / RAND_MAX
+ 1);
589 if( !p_board
->box
[col
][row
].IsMine
) {
591 p_board
->box
[col
][row
].IsMine
= TRUE
;
596 * Now we label the remaining boxes with the
597 * number of mines surrounding them.
600 for( col
= 1; col
< p_board
->cols
+ 1; col
++ )
601 for( row
= 1; row
< p_board
->rows
+ 1; row
++ ) {
602 for( i
= -1; i
<= 1; i
++ )
603 for( j
= -1; j
<= 1; j
++ ) {
604 if( p_board
->box
[col
+ i
][row
+ j
].IsMine
) {
605 p_board
->box
[col
][row
].NumMines
++ ;
611 void DrawMines ( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
615 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
617 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
618 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
619 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
622 SelectObject( hMemDC
, hOldObj
);
625 void DrawMine( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, unsigned col
, unsigned row
, BOOL IsPressed
)
627 MINEBMP_OFFSET offset
= BOX_BMP
;
629 if( col
== 0 || col
> p_board
->cols
|| row
== 0 || row
> p_board
->rows
)
632 if( p_board
->status
== GAMEOVER
) {
633 if( p_board
->box
[col
][row
].IsMine
) {
634 switch( p_board
->box
[col
][row
].FlagType
) {
639 offset
= EXPLODE_BMP
;
645 switch( p_board
->box
[col
][row
].FlagType
) {
647 offset
= QUESTION_BMP
;
659 DEBUG("Unknown FlagType during game over in DrawMine\n");
663 } else { /* WAITING or PLAYING */
664 switch( p_board
->box
[col
][row
].FlagType
) {
667 offset
= QUESTION_BMP
;
684 DEBUG("Unknown FlagType while playing in DrawMine\n");
689 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
690 && !p_board
->box
[col
][row
].IsMine
)
691 offset
= (MINEBMP_OFFSET
) p_board
->box
[col
][row
].NumMines
;
694 (col
- 1) * MINE_WIDTH
+ p_board
->mines_rect
.left
,
695 (row
- 1) * MINE_HEIGHT
+ p_board
->mines_rect
.top
,
696 MINE_WIDTH
, MINE_HEIGHT
,
697 hMemDC
, 0, offset
* MINE_HEIGHT
, SRCCOPY
);
700 void DrawLeds( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, int number
, int x
, int y
)
709 led
[0] = count
/ 100 ;
710 count
-= led
[0] * 100;
713 led
[0] = 10; /* negative sign */
717 count
-= led
[1] * 10;
721 for( i
= 0; i
< 3; i
++ )
725 /* use unlit led if not playing */
726 if( p_board
->status
== WAITING
)
727 for( i
= 0; i
< 3; i
++ )
730 hOldObj
= SelectObject (hMemDC
, p_board
->hLedsBMP
);
732 for( i
= 0; i
< 3; i
++ ) {
744 SelectObject( hMemDC
, hOldObj
);
748 void DrawFace( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
752 hOldObj
= SelectObject (hMemDC
, p_board
->hFacesBMP
);
755 p_board
->face_rect
.left
,
756 p_board
->face_rect
.top
,
759 hMemDC
, 0, p_board
->face_bmp
* FACE_HEIGHT
, SRCCOPY
);
761 SelectObject( hMemDC
, hOldObj
);
765 void DrawBoard( HDC hdc
, HDC hMemDC
, PAINTSTRUCT
*ps
, BOARD
*p_board
)
769 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->counter_rect
) )
770 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->mines
- p_board
->num_flags
,
771 p_board
->counter_rect
.left
,
772 p_board
->counter_rect
.top
);
774 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->timer_rect
) )
775 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->time
,
776 p_board
->timer_rect
.left
,
777 p_board
->timer_rect
.top
);
779 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->face_rect
) )
780 DrawFace( hdc
, hMemDC
, p_board
);
782 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->mines_rect
) )
783 DrawMines( hdc
, hMemDC
, p_board
);
787 void TestBoard( HWND hWnd
, BOARD
*p_board
, unsigned x
, unsigned y
, int msg
)
794 if( PtInRect( &p_board
->mines_rect
, pt
) && p_board
->status
!= GAMEOVER
795 && p_board
->status
!= WON
)
796 TestMines( p_board
, pt
, msg
);
798 UnpressBoxes( p_board
,
801 p_board
->press
.x
= 0;
802 p_board
->press
.y
= 0;
805 if( p_board
->boxes_left
== 0 ) {
806 p_board
->status
= WON
;
808 if( p_board
->difficulty
!= CUSTOM
&&
809 p_board
->time
< p_board
->best_time
[p_board
->difficulty
] ) {
810 p_board
->best_time
[p_board
->difficulty
] = p_board
->time
;
812 DialogBoxParam( p_board
->hInst
, "DLG_CONGRATS", hWnd
,
813 CongratsDlgProc
, (LPARAM
) p_board
);
815 DialogBoxParam( p_board
->hInst
, "DLG_TIMES", hWnd
,
816 TimesDlgProc
, (LPARAM
) p_board
);
819 TestFace( p_board
, pt
, msg
);
822 void TestMines( BOARD
*p_board
, POINT pt
, int msg
)
827 col
= (pt
.x
- p_board
->mines_rect
.left
) / MINE_WIDTH
+ 1;
828 row
= (pt
.y
- p_board
->mines_rect
.top
) / MINE_HEIGHT
+ 1;
832 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
) {
834 p_board
->press
.x
, p_board
->press
.y
);
835 p_board
->press
.x
= col
;
836 p_board
->press
.y
= row
;
837 PressBox( p_board
, col
, row
);
843 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
845 p_board
->press
.x
, p_board
->press
.y
);
846 p_board
->press
.x
= 0;
847 p_board
->press
.y
= 0;
848 if( p_board
->box
[col
][row
].FlagType
!= FLAG
)
849 p_board
->status
= PLAYING
;
850 CompleteBox( p_board
, col
, row
);
854 PressBoxes( p_board
, col
, row
);
859 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
860 UnpressBoxes( p_board
,
861 p_board
->press
.x
, p_board
->press
.y
);
862 p_board
->press
.x
= 0;
863 p_board
->press
.y
= 0;
864 CompleteBoxes( p_board
, col
, row
);
868 AddFlag( p_board
, col
, row
);
869 p_board
->status
= PLAYING
;
872 DEBUG("Unknown message type received in TestMines\n");
878 RedrawWindow( p_board
->hWnd
, NULL
, NULL_HANDLE
,
879 RDW_INVALIDATE
| RDW_UPDATENOW
);
884 void TestFace( BOARD
*p_board
, POINT pt
, int msg
)
886 if( p_board
->status
== PLAYING
|| p_board
->status
== WAITING
) {
887 if( msg
== WM_LBUTTONDOWN
|| msg
== WM_MBUTTONDOWN
)
888 p_board
->face_bmp
= OOH_BMP
;
889 else p_board
->face_bmp
= SMILE_BMP
;
891 else if( p_board
->status
== GAMEOVER
)
892 p_board
->face_bmp
= DEAD_BMP
;
893 else if( p_board
->status
== WON
)
894 p_board
->face_bmp
= COOL_BMP
;
896 if( PtInRect( &p_board
->face_rect
, pt
) ) {
897 if( msg
== WM_LBUTTONDOWN
)
898 p_board
->face_bmp
= SPRESS_BMP
;
900 if( msg
== WM_LBUTTONUP
)
901 CreateBoard( p_board
);
904 RedrawWindow( p_board
->hWnd
, &p_board
->face_rect
, NULL_HANDLE
,
905 RDW_INVALIDATE
| RDW_UPDATENOW
);
909 void CompleteBox( BOARD
*p_board
, unsigned col
, unsigned row
)
913 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
&&
914 p_board
->box
[col
][row
].FlagType
!= FLAG
&&
915 col
> 0 && col
< p_board
->cols
+ 1 &&
916 row
> 0 && row
< p_board
->rows
+ 1 ) {
917 p_board
->box
[col
][row
].FlagType
= COMPLETE
;
919 if( p_board
->box
[col
][row
].IsMine
) {
920 p_board
->face_bmp
= DEAD_BMP
;
921 p_board
->status
= GAMEOVER
;
923 else if( p_board
->status
!= GAMEOVER
)
924 p_board
->boxes_left
--;
926 if( p_board
->box
[col
][row
].NumMines
== 0 )
928 for( i
= -1; i
<= 1; i
++ )
929 for( j
= -1; j
<= 1; j
++ )
930 CompleteBox( p_board
, col
+ i
, row
+ j
);
936 void CompleteBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
938 unsigned numFlags
= 0;
941 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
) {
942 for( i
= -1; i
<= 1; i
++ )
943 for( j
= -1; j
<= 1; j
++ ) {
944 if( p_board
->box
[col
+i
][row
+j
].FlagType
== FLAG
)
948 if( numFlags
== p_board
->box
[col
][row
].NumMines
) {
949 for( i
= -1; i
<= 1; i
++ )
950 for( j
= -1; j
<= 1; j
++ ) {
951 if( p_board
->box
[col
+i
][row
+j
].FlagType
!= FLAG
)
952 CompleteBox( p_board
, col
+i
, row
+j
);
959 void AddFlag( BOARD
*p_board
, unsigned col
, unsigned row
)
961 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
) {
962 switch( p_board
->box
[col
][row
].FlagType
) {
964 if( p_board
->IsMarkQ
)
965 p_board
->box
[col
][row
].FlagType
= QUESTION
;
967 p_board
->box
[col
][row
].FlagType
= NORMAL
;
968 p_board
->num_flags
--;
972 p_board
->box
[col
][row
].FlagType
= NORMAL
;
976 p_board
->box
[col
][row
].FlagType
= FLAG
;
977 p_board
->num_flags
++;
983 void PressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
989 hdc
= GetDC( p_board
->hWnd
);
990 hMemDC
= CreateCompatibleDC( hdc
);
991 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
993 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, TRUE
);
995 SelectObject( hMemDC
, hOldObj
);
997 ReleaseDC( p_board
->hWnd
, hdc
);
1001 void PressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
1005 for( i
= -1; i
<= 1; i
++ )
1006 for( j
= -1; j
<= 1; j
++ ) {
1007 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= TRUE
;
1008 PressBox( p_board
, col
+ i
, row
+ j
);
1011 for( i
= -1; i
<= 1; i
++ )
1012 for( j
= -1; j
<= 1; j
++ ) {
1013 if( !p_board
->box
[p_board
->press
.x
+ i
][p_board
->press
.y
+ j
].IsPressed
)
1014 UnpressBox( p_board
, p_board
->press
.x
+ i
, p_board
->press
.y
+ j
);
1017 for( i
= -1; i
<= 1; i
++ )
1018 for( j
= -1; j
<= 1; j
++ ) {
1019 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= FALSE
;
1020 PressBox( p_board
, col
+ i
, row
+ j
);
1023 p_board
->press
.x
= col
;
1024 p_board
->press
.y
= row
;
1028 void UnpressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
1034 hdc
= GetDC( p_board
->hWnd
);
1035 hMemDC
= CreateCompatibleDC( hdc
);
1036 hOldObj
= SelectObject( hMemDC
, p_board
->hMinesBMP
);
1038 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
1040 SelectObject( hMemDC
, hOldObj
);
1042 ReleaseDC( p_board
->hWnd
, hdc
);
1046 void UnpressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
1050 for( i
= -1; i
<= 1; i
++ )
1051 for( j
= -1; j
<= 1; j
++ ) {
1052 UnpressBox( p_board
, col
+ i
, row
+ j
);