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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define WIN32_LEAN_AND_MEAN
31 #include <wine/debug.h>
33 WINE_DEFAULT_DEBUG_CHANNEL(winemine
);
35 static const DWORD wnd_style
= WS_OVERLAPPEDWINDOW
& ~WS_THICKFRAME
& ~WS_MAXIMIZEBOX
;
37 void CheckLevel( BOARD
*p_board
)
39 if( p_board
->rows
< BEGINNER_ROWS
)
40 p_board
->rows
= BEGINNER_ROWS
;
42 if( p_board
->rows
> MAX_ROWS
)
43 p_board
->rows
= MAX_ROWS
;
45 if( p_board
->cols
< BEGINNER_COLS
)
46 p_board
->cols
= BEGINNER_COLS
;
48 if( p_board
->cols
> MAX_COLS
)
49 p_board
->cols
= MAX_COLS
;
51 if( p_board
->mines
< BEGINNER_MINES
)
52 p_board
->mines
= BEGINNER_MINES
;
54 if( p_board
->mines
> ( p_board
->cols
- 1 ) * ( p_board
->rows
- 1 ) )
55 p_board
->mines
= ( p_board
->cols
- 1 ) * ( p_board
->rows
- 1 );
58 static void LoadBoard( BOARD
*p_board
)
63 WCHAR data
[MAX_PLAYER_NAME_SIZE
+1];
67 RegOpenKeyExW( HKEY_CURRENT_USER
, L
"Software\\Microsoft\\WinMine", 0, KEY_QUERY_VALUE
, &hkey
);
69 size
= sizeof( p_board
->pos
.x
);
70 if( RegQueryValueExW( hkey
, L
"Xpos", NULL
, &type
, (BYTE
*) &p_board
->pos
.x
, &size
) )
73 size
= sizeof( p_board
->pos
.y
);
74 if( RegQueryValueExW( hkey
, L
"Ypos", NULL
, &type
, (BYTE
*) &p_board
->pos
.y
, &size
) )
77 size
= sizeof( p_board
->rows
);
78 if( RegQueryValueExW( hkey
, L
"Height", NULL
, &type
, (BYTE
*) &p_board
->rows
, &size
) )
79 p_board
->rows
= BEGINNER_ROWS
;
81 size
= sizeof( p_board
->cols
);
82 if( RegQueryValueExW( hkey
, L
"Width", NULL
, &type
, (BYTE
*) &p_board
->cols
, &size
) )
83 p_board
->cols
= BEGINNER_COLS
;
85 size
= sizeof( p_board
->mines
);
86 if( RegQueryValueExW( hkey
, L
"Mines", NULL
, &type
, (BYTE
*) &p_board
->mines
, &size
) )
87 p_board
->mines
= BEGINNER_MINES
;
89 size
= sizeof( p_board
->difficulty
);
90 if( RegQueryValueExW( hkey
, L
"Difficulty", NULL
, &type
, (BYTE
*) &p_board
->difficulty
, &size
) )
91 p_board
->difficulty
= BEGINNER
;
93 size
= sizeof( p_board
->IsMarkQ
);
94 if( RegQueryValueExW( hkey
, L
"Mark", NULL
, &type
, (BYTE
*) &p_board
->IsMarkQ
, &size
) )
95 p_board
->IsMarkQ
= TRUE
;
97 for( i
= 0; i
< 3; i
++ ) {
98 wsprintfW( key_name
, L
"Name%u", i
+1 );
99 size
= sizeof( data
);
100 if( RegQueryValueExW( hkey
, key_name
, NULL
, &type
,
101 (LPBYTE
) data
, &size
) == ERROR_SUCCESS
)
102 lstrcpynW( p_board
->best_name
[i
], data
, ARRAY_SIZE(p_board
->best_name
[i
]));
104 LoadStringW( p_board
->hInst
, IDS_NOBODY
, p_board
->best_name
[i
], MAX_PLAYER_NAME_SIZE
+1 );
107 for( i
= 0; i
< 3; i
++ ) {
108 wsprintfW( key_name
, L
"Time%u", i
+1 );
109 size
= sizeof( p_board
->best_time
[i
] );
110 if( RegQueryValueExW( hkey
, key_name
, NULL
, &type
, (BYTE
*) &p_board
->best_time
[i
], &size
) )
111 p_board
->best_time
[i
] = 999;
116 static void InitBoard( BOARD
*p_board
)
120 p_board
->hMinesBMP
= LoadBitmapW( p_board
->hInst
, MAKEINTRESOURCEW(IDI_MINES
));
121 p_board
->hFacesBMP
= LoadBitmapW( p_board
->hInst
, MAKEINTRESOURCEW(IDI_FACES
));
122 p_board
->hLedsBMP
= LoadBitmapW( p_board
->hInst
, MAKEINTRESOURCEW(IDI_LEDS
));
124 LoadBoard( p_board
);
126 hMenu
= GetMenu( p_board
->hWnd
);
127 CheckMenuItem( hMenu
, IDM_BEGINNER
+ (unsigned) p_board
->difficulty
,
129 if( p_board
->IsMarkQ
)
130 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
132 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
133 CheckLevel( p_board
);
136 void ResetResults( BOARD
*p_board
)
140 for( i
= 0; i
< 3; i
++ ) {
141 LoadStringW( p_board
->hInst
, IDS_NOBODY
, p_board
->best_name
[i
], MAX_PLAYER_NAME_SIZE
+1 );
142 p_board
->best_time
[i
] = 999;
146 void SaveBoard( BOARD
*p_board
)
150 WCHAR data
[MAX_PLAYER_NAME_SIZE
+1];
153 if( RegCreateKeyExW( HKEY_CURRENT_USER
, L
"Software\\Microsoft\\WinMine",
155 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
,
156 &hkey
, NULL
) != ERROR_SUCCESS
)
159 RegSetValueExW( hkey
, L
"Xpos", 0, REG_DWORD
, (BYTE
*) &p_board
->pos
.x
, sizeof(p_board
->pos
.x
) );
160 RegSetValueExW( hkey
, L
"Ypos", 0, REG_DWORD
, (BYTE
*) &p_board
->pos
.y
, sizeof(p_board
->pos
.y
) );
161 RegSetValueExW( hkey
, L
"Difficulty", 0, REG_DWORD
, (BYTE
*) &p_board
->difficulty
, sizeof(p_board
->difficulty
) );
162 RegSetValueExW( hkey
, L
"Height", 0, REG_DWORD
, (BYTE
*) &p_board
->rows
, sizeof(p_board
->rows
) );
163 RegSetValueExW( hkey
, L
"Width", 0, REG_DWORD
, (BYTE
*) &p_board
->cols
, sizeof(p_board
->cols
) );
164 RegSetValueExW( hkey
, L
"Mines", 0, REG_DWORD
, (BYTE
*) &p_board
->mines
, sizeof(p_board
->mines
) );
165 RegSetValueExW( hkey
, L
"Mark", 0, REG_DWORD
, (BYTE
*) &p_board
->IsMarkQ
, sizeof(p_board
->IsMarkQ
) );
167 for( i
= 0; i
< 3; i
++ ) {
168 wsprintfW( key_name
, L
"Name%u", i
+1 );
169 lstrcpynW( data
, p_board
->best_name
[i
], ARRAY_SIZE(data
));
170 RegSetValueExW( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, (lstrlenW(data
)+1) * sizeof(WCHAR
) );
173 for( i
= 0; i
< 3; i
++ ) {
174 wsprintfW( key_name
, L
"Time%u", i
+1 );
175 RegSetValueExW( hkey
, key_name
, 0, REG_DWORD
, (LPBYTE
) &p_board
->best_time
[i
], sizeof(p_board
->best_time
[i
]) );
179 WINE_TRACE("Board has been saved.\n");
182 static void DestroyBoard( BOARD
*p_board
)
184 DeleteObject( p_board
->hFacesBMP
);
185 DeleteObject( p_board
->hLedsBMP
);
186 DeleteObject( p_board
->hMinesBMP
);
189 static void SetDifficulty( BOARD
*p_board
, DIFFICULTY difficulty
)
193 if ( difficulty
== CUSTOM
)
194 if (DialogBoxParamW( p_board
->hInst
, MAKEINTRESOURCEW(DLG_CUSTOM
), p_board
->hWnd
,
195 CustomDlgProc
, (LPARAM
) p_board
) != 0)
198 hMenu
= GetMenu( p_board
->hWnd
);
199 CheckMenuItem( hMenu
, IDM_BEGINNER
+ p_board
->difficulty
, MF_UNCHECKED
);
200 p_board
->difficulty
= difficulty
;
201 CheckMenuItem( hMenu
, IDM_BEGINNER
+ difficulty
, MF_CHECKED
);
203 switch( difficulty
) {
205 p_board
->cols
= BEGINNER_COLS
;
206 p_board
->rows
= BEGINNER_ROWS
;
207 p_board
->mines
= BEGINNER_MINES
;
211 p_board
->cols
= ADVANCED_COLS
;
212 p_board
->rows
= ADVANCED_ROWS
;
213 p_board
->mines
= ADVANCED_MINES
;
217 p_board
->cols
= EXPERT_COLS
;
218 p_board
->rows
= EXPERT_ROWS
;
220 p_board
->mines
= EXPERT_MINES
;
228 static void ShiftBetween(LONG
* x
, LONG
* y
, LONG a
, LONG b
)
240 static void MoveOnScreen(RECT
* rect
)
245 /* find the nearest monitor ... */
246 hMonitor
= MonitorFromRect(rect
, MONITOR_DEFAULTTONEAREST
);
248 /* ... and move it into the work area (ie excluding task bar)*/
249 mi
.cbSize
= sizeof(mi
);
250 GetMonitorInfoW(hMonitor
, &mi
);
252 ShiftBetween(&rect
->left
, &rect
->right
, mi
.rcWork
.left
, mi
.rcWork
.right
);
253 ShiftBetween(&rect
->top
, &rect
->bottom
, mi
.rcWork
.top
, mi
.rcWork
.bottom
);
256 static void CreateBoard( BOARD
*p_board
)
258 int left
, top
, bottom
, right
;
262 p_board
->mb
= MB_NONE
;
263 p_board
->boxes_left
= p_board
->cols
* p_board
->rows
- p_board
->mines
;
264 p_board
->num_flags
= 0;
266 /* Create the boxes...
267 * We actually create them with an empty border,
268 * so special care doesn't have to be taken on the edges
270 for( col
= 0; col
<= p_board
->cols
+ 1; col
++ )
271 for( row
= 0; row
<= p_board
->rows
+ 1; row
++ ) {
272 p_board
->box
[col
][row
].IsPressed
= FALSE
;
273 p_board
->box
[col
][row
].IsMine
= FALSE
;
274 p_board
->box
[col
][row
].FlagType
= NORMAL
;
275 p_board
->box
[col
][row
].NumMines
= 0;
278 p_board
->width
= p_board
->cols
* MINE_WIDTH
+ BOARD_WMARGIN
* 2;
280 p_board
->height
= p_board
->rows
* MINE_HEIGHT
+ LED_HEIGHT
283 /* setting the mines rectangle boundary */
284 left
= BOARD_WMARGIN
;
285 top
= BOARD_HMARGIN
* 2 + LED_HEIGHT
;
286 right
= left
+ p_board
->cols
* MINE_WIDTH
;
287 bottom
= top
+ p_board
->rows
* MINE_HEIGHT
;
288 SetRect( &p_board
->mines_rect
, left
, top
, right
, bottom
);
290 /* setting the face rectangle boundary */
291 left
= p_board
->width
/ 2 - FACE_WIDTH
/ 2;
293 right
= left
+ FACE_WIDTH
;
294 bottom
= top
+ FACE_HEIGHT
;
295 SetRect( &p_board
->face_rect
, left
, top
, right
, bottom
);
297 /* setting the timer rectangle boundary */
298 left
= BOARD_WMARGIN
;
300 right
= left
+ LED_WIDTH
* 3;
301 bottom
= top
+ LED_HEIGHT
;
302 SetRect( &p_board
->timer_rect
, left
, top
, right
, bottom
);
304 /* setting the counter rectangle boundary */
305 left
= p_board
->width
- BOARD_WMARGIN
- LED_WIDTH
* 3;
307 right
= p_board
->width
- BOARD_WMARGIN
;
308 bottom
= top
+ LED_HEIGHT
;
309 SetRect( &p_board
->counter_rect
, left
, top
, right
, bottom
);
311 p_board
->status
= WAITING
;
312 p_board
->face_bmp
= SMILE_BMP
;
315 SetRect(&wnd_rect
, p_board
->pos
.x
, p_board
->pos
.y
, p_board
->pos
.x
+ p_board
->width
,
316 p_board
->pos
.y
+ p_board
->height
);
317 AdjustWindowRect(&wnd_rect
, wnd_style
, TRUE
);
319 /* Make sure the window is completely on the screen */
320 MoveOnScreen(&wnd_rect
);
321 MoveWindow( p_board
->hWnd
, wnd_rect
.left
, wnd_rect
.top
,
322 wnd_rect
.right
- wnd_rect
.left
,
323 wnd_rect
.bottom
- wnd_rect
.top
,
325 RedrawWindow( p_board
->hWnd
, NULL
, 0,
326 RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_ERASE
);
330 /* Randomly places mines everywhere except the selected box. */
331 static void PlaceMines ( BOARD
*p_board
, int selected_col
, int selected_row
)
336 srand( (unsigned) time( NULL
) );
338 /* Temporarily place a mine at the selected box until all the other
339 * mines are placed, this avoids checking in the mine creation loop. */
340 p_board
->box
[selected_col
][selected_row
].IsMine
= TRUE
;
344 while( (unsigned) i
< p_board
->mines
) {
345 col
= rand() % p_board
->cols
+ 1;
346 row
= rand() % p_board
->rows
+ 1;
348 if( !p_board
->box
[col
][row
].IsMine
) {
350 p_board
->box
[col
][row
].IsMine
= TRUE
;
354 /* Remove temporarily placed mine for selected box */
355 p_board
->box
[selected_col
][selected_row
].IsMine
= FALSE
;
358 * Now we label the remaining boxes with the
359 * number of mines surrounding them.
361 for( col
= 1; col
< p_board
->cols
+ 1; col
++ )
362 for( row
= 1; row
< p_board
->rows
+ 1; row
++ ) {
363 for( i
= -1; i
<= 1; i
++ )
364 for( j
= -1; j
<= 1; j
++ ) {
365 if( p_board
->box
[col
+ i
][row
+ j
].IsMine
) {
366 p_board
->box
[col
][row
].NumMines
++ ;
372 static void DrawMine( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, unsigned col
, unsigned row
, BOOL IsPressed
)
374 MINEBMP_OFFSET offset
= BOX_BMP
;
376 if( col
== 0 || col
> p_board
->cols
|| row
== 0 || row
> p_board
->rows
)
379 if( p_board
->status
== GAMEOVER
) {
380 if( p_board
->box
[col
][row
].IsMine
) {
381 switch( p_board
->box
[col
][row
].FlagType
) {
386 offset
= EXPLODE_BMP
;
394 switch( p_board
->box
[col
][row
].FlagType
) {
396 offset
= QUESTION_BMP
;
408 WINE_TRACE("Unknown FlagType during game over in DrawMine\n");
412 } else { /* WAITING or PLAYING */
413 switch( p_board
->box
[col
][row
].FlagType
) {
416 offset
= QUESTION_BMP
;
433 WINE_TRACE("Unknown FlagType while playing in DrawMine\n");
438 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
439 && !p_board
->box
[col
][row
].IsMine
)
440 offset
= (MINEBMP_OFFSET
) p_board
->box
[col
][row
].NumMines
;
443 (col
- 1) * MINE_WIDTH
+ p_board
->mines_rect
.left
,
444 (row
- 1) * MINE_HEIGHT
+ p_board
->mines_rect
.top
,
445 MINE_WIDTH
, MINE_HEIGHT
,
446 hMemDC
, 0, offset
* MINE_HEIGHT
, SRCCOPY
);
449 static void DrawMines ( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
453 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
455 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
456 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
457 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
460 SelectObject( hMemDC
, hOldObj
);
463 static void DrawLeds( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, int number
, int x
, int y
)
472 led
[0] = count
/ 100 ;
473 count
-= led
[0] * 100;
476 led
[0] = 10; /* negative sign */
480 count
-= led
[1] * 10;
484 for( i
= 0; i
< 3; i
++ )
488 hOldObj
= SelectObject (hMemDC
, p_board
->hLedsBMP
);
490 for( i
= 0; i
< 3; i
++ ) {
502 SelectObject( hMemDC
, hOldObj
);
506 static void DrawFace( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
510 hOldObj
= SelectObject (hMemDC
, p_board
->hFacesBMP
);
513 p_board
->face_rect
.left
,
514 p_board
->face_rect
.top
,
517 hMemDC
, 0, p_board
->face_bmp
* FACE_HEIGHT
, SRCCOPY
);
519 SelectObject( hMemDC
, hOldObj
);
523 static void DrawBoard( HDC hdc
, HDC hMemDC
, PAINTSTRUCT
*ps
, BOARD
*p_board
)
527 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->counter_rect
) )
528 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->mines
- p_board
->num_flags
,
529 p_board
->counter_rect
.left
,
530 p_board
->counter_rect
.top
);
532 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->timer_rect
) )
533 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->time
,
534 p_board
->timer_rect
.left
,
535 p_board
->timer_rect
.top
);
537 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->face_rect
) )
538 DrawFace( hdc
, hMemDC
, p_board
);
540 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->mines_rect
) )
541 DrawMines( hdc
, hMemDC
, p_board
);
545 static void AddFlag( BOARD
*p_board
, unsigned col
, unsigned row
)
547 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
) {
548 switch( p_board
->box
[col
][row
].FlagType
) {
550 if( p_board
->IsMarkQ
)
551 p_board
->box
[col
][row
].FlagType
= QUESTION
;
553 p_board
->box
[col
][row
].FlagType
= NORMAL
;
554 p_board
->num_flags
--;
558 p_board
->box
[col
][row
].FlagType
= NORMAL
;
562 p_board
->box
[col
][row
].FlagType
= FLAG
;
563 p_board
->num_flags
++;
569 static void UnpressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
575 hdc
= GetDC( p_board
->hWnd
);
576 hMemDC
= CreateCompatibleDC( hdc
);
577 hOldObj
= SelectObject( hMemDC
, p_board
->hMinesBMP
);
579 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
581 SelectObject( hMemDC
, hOldObj
);
583 ReleaseDC( p_board
->hWnd
, hdc
);
587 static void UnpressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
591 for( i
= -1; i
<= 1; i
++ )
592 for( j
= -1; j
<= 1; j
++ ) {
593 UnpressBox( p_board
, col
+ i
, row
+ j
);
598 static void PressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
604 hdc
= GetDC( p_board
->hWnd
);
605 hMemDC
= CreateCompatibleDC( hdc
);
606 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
608 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, TRUE
);
610 SelectObject( hMemDC
, hOldObj
);
612 ReleaseDC( p_board
->hWnd
, hdc
);
616 static void PressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
620 for( i
= -1; i
<= 1; i
++ )
621 for( j
= -1; j
<= 1; j
++ ) {
622 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= TRUE
;
623 PressBox( p_board
, col
+ i
, row
+ j
);
626 for( i
= -1; i
<= 1; i
++ )
627 for( j
= -1; j
<= 1; j
++ ) {
628 if( !p_board
->box
[p_board
->press
.x
+ i
][p_board
->press
.y
+ j
].IsPressed
)
629 UnpressBox( p_board
, p_board
->press
.x
+ i
, p_board
->press
.y
+ j
);
632 for( i
= -1; i
<= 1; i
++ )
633 for( j
= -1; j
<= 1; j
++ ) {
634 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= FALSE
;
635 PressBox( p_board
, col
+ i
, row
+ j
);
638 p_board
->press
.x
= col
;
639 p_board
->press
.y
= row
;
643 static void CompleteBox( BOARD
*p_board
, unsigned col
, unsigned row
)
647 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
&&
648 p_board
->box
[col
][row
].FlagType
!= FLAG
&&
649 col
> 0 && col
< p_board
->cols
+ 1 &&
650 row
> 0 && row
< p_board
->rows
+ 1 ) {
651 p_board
->box
[col
][row
].FlagType
= COMPLETE
;
653 if( p_board
->box
[col
][row
].IsMine
) {
654 p_board
->face_bmp
= DEAD_BMP
;
655 p_board
->status
= GAMEOVER
;
657 else if( p_board
->status
!= GAMEOVER
)
658 p_board
->boxes_left
--;
660 if( p_board
->box
[col
][row
].NumMines
== 0 )
662 for( i
= -1; i
<= 1; i
++ )
663 for( j
= -1; j
<= 1; j
++ )
664 CompleteBox( p_board
, col
+ i
, row
+ j
);
670 static void CompleteBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
672 unsigned numFlags
= 0;
675 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
) {
676 for( i
= -1; i
<= 1; i
++ )
677 for( j
= -1; j
<= 1; j
++ ) {
678 if( p_board
->box
[col
+i
][row
+j
].FlagType
== FLAG
)
682 if( numFlags
== p_board
->box
[col
][row
].NumMines
) {
683 for( i
= -1; i
<= 1; i
++ )
684 for( j
= -1; j
<= 1; j
++ ) {
685 if( p_board
->box
[col
+i
][row
+j
].FlagType
!= FLAG
)
686 CompleteBox( p_board
, col
+i
, row
+j
);
693 static void TestMines( BOARD
*p_board
, POINT pt
, int msg
)
698 col
= (pt
.x
- p_board
->mines_rect
.left
) / MINE_WIDTH
+ 1;
699 row
= (pt
.y
- p_board
->mines_rect
.top
) / MINE_HEIGHT
+ 1;
703 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
) {
705 p_board
->press
.x
, p_board
->press
.y
);
706 p_board
->press
.x
= col
;
707 p_board
->press
.y
= row
;
708 PressBox( p_board
, col
, row
);
714 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
716 p_board
->press
.x
, p_board
->press
.y
);
717 p_board
->press
.x
= 0;
718 p_board
->press
.y
= 0;
719 if( p_board
->box
[col
][row
].FlagType
!= FLAG
720 && p_board
->status
!= PLAYING
)
722 p_board
->status
= PLAYING
;
723 PlaceMines( p_board
, col
, row
);
725 CompleteBox( p_board
, col
, row
);
729 PressBoxes( p_board
, col
, row
);
734 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
735 UnpressBoxes( p_board
,
736 p_board
->press
.x
, p_board
->press
.y
);
737 p_board
->press
.x
= 0;
738 p_board
->press
.y
= 0;
739 CompleteBoxes( p_board
, col
, row
);
743 AddFlag( p_board
, col
, row
);
752 RedrawWindow( p_board
->hWnd
, NULL
, 0,
753 RDW_INVALIDATE
| RDW_UPDATENOW
);
758 static void TestFace( BOARD
*p_board
, POINT pt
, int msg
)
760 if( p_board
->status
== PLAYING
|| p_board
->status
== WAITING
) {
761 if( msg
== WM_LBUTTONDOWN
|| msg
== WM_MBUTTONDOWN
)
762 p_board
->face_bmp
= OOH_BMP
;
763 else p_board
->face_bmp
= SMILE_BMP
;
765 else if( p_board
->status
== GAMEOVER
)
766 p_board
->face_bmp
= DEAD_BMP
;
767 else if( p_board
->status
== WON
)
768 p_board
->face_bmp
= COOL_BMP
;
770 if( PtInRect( &p_board
->face_rect
, pt
) ) {
771 if( msg
== WM_LBUTTONDOWN
)
772 p_board
->face_bmp
= SPRESS_BMP
;
774 if( msg
== WM_LBUTTONUP
)
775 CreateBoard( p_board
);
778 RedrawWindow( p_board
->hWnd
, &p_board
->face_rect
, 0,
779 RDW_INVALIDATE
| RDW_UPDATENOW
);
783 static void TestBoard( HWND hWnd
, BOARD
*p_board
, int x
, int y
, int msg
)
791 if( PtInRect( &p_board
->mines_rect
, pt
) && p_board
->status
!= GAMEOVER
792 && p_board
->status
!= WON
)
793 TestMines( p_board
, pt
, msg
);
795 UnpressBoxes( p_board
,
798 p_board
->press
.x
= 0;
799 p_board
->press
.y
= 0;
802 if( p_board
->boxes_left
== 0 && p_board
->status
!= WON
) {
803 p_board
->status
= WON
;
805 if (p_board
->num_flags
< p_board
->mines
) {
806 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
807 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
808 if (p_board
->box
[col
][row
].IsMine
&& p_board
->box
[col
][row
].FlagType
!= FLAG
)
809 p_board
->box
[col
][row
].FlagType
= FLAG
;
813 p_board
->num_flags
= p_board
->mines
;
815 RedrawWindow( p_board
->hWnd
, NULL
, 0,
816 RDW_INVALIDATE
| RDW_UPDATENOW
);
819 if( p_board
->difficulty
!= CUSTOM
&&
820 p_board
->time
< p_board
->best_time
[p_board
->difficulty
] ) {
821 p_board
->best_time
[p_board
->difficulty
] = p_board
->time
;
823 DialogBoxParamW( p_board
->hInst
, MAKEINTRESOURCEW(DLG_CONGRATS
), hWnd
,
824 CongratsDlgProc
, (LPARAM
) p_board
);
825 SaveBoard( p_board
);
826 DialogBoxParamW( p_board
->hInst
, MAKEINTRESOURCEW(DLG_TIMES
), hWnd
,
827 TimesDlgProc
, (LPARAM
) p_board
);
830 TestFace( p_board
, pt
, msg
);
834 static LRESULT WINAPI
MainProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
843 board
.hInst
= ((LPCREATESTRUCTW
) lParam
)->hInstance
;
846 CreateBoard( &board
);
853 WINE_TRACE("WM_PAINT\n");
854 hdc
= BeginPaint( hWnd
, &ps
);
855 hMemDC
= CreateCompatibleDC( hdc
);
857 DrawBoard( hdc
, hMemDC
, &ps
, &board
);
860 EndPaint( hWnd
, &ps
);
866 WINE_TRACE("WM_MOVE\n");
867 board
.pos
.x
= (short)LOWORD(lParam
);
868 board
.pos
.y
= (short)HIWORD(lParam
);
873 DestroyBoard( &board
);
874 PostQuitMessage( 0 );
878 if( board
.status
== PLAYING
) {
880 RedrawWindow( hWnd
, &board
.timer_rect
, 0,
881 RDW_INVALIDATE
| RDW_UPDATENOW
);
886 WINE_TRACE("WM_LBUTTONDOWN\n");
887 if( wParam
& ( MK_RBUTTON
| MK_SHIFT
) )
888 msg
= WM_MBUTTONDOWN
;
889 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
894 WINE_TRACE("WM_LBUTTONUP\n");
895 if( wParam
& ( MK_RBUTTON
| MK_SHIFT
) )
897 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
902 WINE_TRACE("WM_RBUTTONDOWN\n");
903 if( wParam
& MK_LBUTTON
) {
906 msg
= WM_MBUTTONDOWN
;
908 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
912 WINE_TRACE("WM_RBUTTONUP\n");
913 if( wParam
& MK_LBUTTON
)
915 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
919 WINE_TRACE("WM_MBUTTONDOWN\n");
920 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
924 WINE_TRACE("WM_MBUTTONUP\n");
925 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
930 if( ( wParam
& MK_MBUTTON
) ||
931 ( ( wParam
& MK_LBUTTON
) && ( wParam
& MK_RBUTTON
) ) ) {
932 msg
= WM_MBUTTONDOWN
;
934 else if( wParam
& MK_LBUTTON
) {
935 msg
= WM_LBUTTONDOWN
;
941 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
947 switch(LOWORD(wParam
)) {
949 CreateBoard( &board
);
953 hMenu
= GetMenu( hWnd
);
954 board
.IsMarkQ
= !board
.IsMarkQ
;
956 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
958 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
962 SetDifficulty( &board
, BEGINNER
);
963 CreateBoard( &board
);
967 SetDifficulty( &board
, ADVANCED
);
968 CreateBoard( &board
);
972 SetDifficulty( &board
, EXPERT
);
973 CreateBoard( &board
);
977 SetDifficulty( &board
, CUSTOM
);
978 CreateBoard( &board
);
982 SendMessageW( hWnd
, WM_CLOSE
, 0, 0);
986 DialogBoxParamW( board
.hInst
, MAKEINTRESOURCEW(DLG_TIMES
), hWnd
,
987 TimesDlgProc
, (LPARAM
) &board
);
992 WCHAR appname
[256], other
[256];
993 LoadStringW( board
.hInst
, IDS_APPNAME
, appname
, ARRAY_SIZE(appname
));
994 LoadStringW( board
.hInst
, IDS_ABOUT
, other
, ARRAY_SIZE(other
));
995 ShellAboutW( hWnd
, appname
, other
,
996 LoadImageW(board
.hInst
, MAKEINTRESOURCEW(IDI_WINEMINE
), IMAGE_ICON
, 48, 48, LR_SHARED
));
1000 WINE_TRACE("Unknown WM_COMMAND command message received\n");
1004 return DefWindowProcW( hWnd
, msg
, wParam
, lParam
);
1007 int WINAPI
wWinMain( HINSTANCE hInst
, HINSTANCE hPrevInst
, LPWSTR cmdline
, int cmdshow
)
1015 LoadStringW( hInst
, IDS_APPNAME
, appname
, ARRAY_SIZE(appname
));
1017 wc
.cbSize
= sizeof(wc
);
1019 wc
.lpfnWndProc
= MainProc
;
1022 wc
.hInstance
= hInst
;
1023 wc
.hIcon
= LoadIconW( hInst
, MAKEINTRESOURCEW(IDI_WINEMINE
) );
1024 wc
.hCursor
= LoadCursorW( 0, (LPWSTR
)IDI_APPLICATION
);
1025 wc
.hbrBackground
= GetStockObject( BLACK_BRUSH
);
1026 wc
.lpszMenuName
= MAKEINTRESOURCEW(IDM_WINEMINE
);
1027 wc
.lpszClassName
= appname
;
1028 wc
.hIconSm
= LoadImageW( hInst
, MAKEINTRESOURCEW(IDI_WINEMINE
), IMAGE_ICON
,
1029 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_SHARED
);
1031 if (!RegisterClassExW(&wc
)) ExitProcess(1);
1032 hWnd
= CreateWindowW( appname
, appname
,
1034 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1035 0, 0, hInst
, NULL
);
1037 if (!hWnd
) ExitProcess(1);
1039 ShowWindow( hWnd
, cmdshow
);
1040 UpdateWindow( hWnd
);
1042 haccel
= LoadAcceleratorsW( hInst
, MAKEINTRESOURCEW(IDA_WINEMINE
) );
1043 SetTimer( hWnd
, ID_TIMER
, 1000, NULL
);
1045 while( GetMessageW(&msg
, 0, 0, 0) ) {
1046 if (!TranslateAcceleratorW( hWnd
, haccel
, &msg
))
1047 TranslateMessage( &msg
);
1049 DispatchMessageW( &msg
);