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_NO_STATUS
34 #include <wine/debug.h>
36 WINE_DEFAULT_DEBUG_CHANNEL(winemine
);
38 static const DWORD wnd_style
= WS_OVERLAPPEDWINDOW
& ~WS_THICKFRAME
& ~WS_MAXIMIZEBOX
;
39 static const char* registry_key
= "Software\\Microsoft\\WinMine";
42 void CheckLevel( BOARD
*p_board
)
44 if( p_board
->rows
< BEGINNER_ROWS
)
45 p_board
->rows
= BEGINNER_ROWS
;
47 if( p_board
->rows
> MAX_ROWS
)
48 p_board
->rows
= MAX_ROWS
;
50 if( p_board
->cols
< BEGINNER_COLS
)
51 p_board
->cols
= BEGINNER_COLS
;
53 if( p_board
->cols
> MAX_COLS
)
54 p_board
->cols
= MAX_COLS
;
56 if( p_board
->mines
< BEGINNER_MINES
)
57 p_board
->mines
= BEGINNER_MINES
;
59 if( p_board
->mines
> ( p_board
->cols
- 1 ) * ( p_board
->rows
- 1 ) )
60 p_board
->mines
= ( p_board
->cols
- 1 ) * ( p_board
->rows
- 1 );
63 static void LoadBoard( BOARD
*p_board
)
68 char data
[MAX_PLAYER_NAME_SIZE
+1];
72 RegOpenKeyEx( HKEY_CURRENT_USER
, registry_key
,
73 0, KEY_QUERY_VALUE
, &hkey
);
75 size
= sizeof( p_board
->pos
.x
);
76 if( !RegQueryValueEx( hkey
, "Xpos", NULL
, &type
,
77 (LPBYTE
) &p_board
->pos
.x
, &size
) == ERROR_SUCCESS
)
80 size
= sizeof( p_board
->pos
.y
);
81 if( !RegQueryValueEx( hkey
, "Ypos", NULL
, &type
,
82 (LPBYTE
) &p_board
->pos
.y
, &size
) == ERROR_SUCCESS
)
85 size
= sizeof( p_board
->rows
);
86 if( !RegQueryValueEx( hkey
, "Height", NULL
, &type
,
87 (LPBYTE
) &p_board
->rows
, &size
) == ERROR_SUCCESS
)
88 p_board
->rows
= BEGINNER_ROWS
;
90 size
= sizeof( p_board
->cols
);
91 if( !RegQueryValueEx( hkey
, "Width", NULL
, &type
,
92 (LPBYTE
) &p_board
->cols
, &size
) == ERROR_SUCCESS
)
93 p_board
->cols
= BEGINNER_COLS
;
95 size
= sizeof( p_board
->mines
);
96 if( !RegQueryValueEx( hkey
, "Mines", NULL
, &type
,
97 (LPBYTE
) &p_board
->mines
, &size
) == ERROR_SUCCESS
)
98 p_board
->mines
= BEGINNER_MINES
;
100 size
= sizeof( p_board
->difficulty
);
101 if( !RegQueryValueEx( hkey
, "Difficulty", NULL
, &type
,
102 (LPBYTE
) &p_board
->difficulty
, &size
) == ERROR_SUCCESS
)
103 p_board
->difficulty
= BEGINNER
;
105 size
= sizeof( p_board
->IsMarkQ
);
106 if( !RegQueryValueEx( hkey
, "Mark", NULL
, &type
,
107 (LPBYTE
) &p_board
->IsMarkQ
, &size
) == ERROR_SUCCESS
)
108 p_board
->IsMarkQ
= TRUE
;
110 for( i
= 0; i
< 3; i
++ ) {
111 wsprintf( key_name
, "Name%u", i
+1 );
112 size
= sizeof( data
);
113 if( RegQueryValueEx( hkey
, key_name
, NULL
, &type
,
114 (LPBYTE
) data
, &size
) == ERROR_SUCCESS
)
115 lstrcpynA( p_board
->best_name
[i
], data
, sizeof(p_board
->best_name
[i
]) );
117 LoadString( p_board
->hInst
, IDS_NOBODY
, p_board
->best_name
[i
], MAX_PLAYER_NAME_SIZE
+1 );
120 for( i
= 0; i
< 3; i
++ ) {
121 wsprintf( key_name
, "Time%u", i
+1 );
122 size
= sizeof( p_board
->best_time
[i
] );
123 if( !RegQueryValueEx( hkey
, key_name
, NULL
, &type
,
124 (LPBYTE
) &p_board
->best_time
[i
], &size
) == ERROR_SUCCESS
)
125 p_board
->best_time
[i
] = 999;
130 static void InitBoard( BOARD
*p_board
)
134 p_board
->hMinesBMP
= LoadBitmap( p_board
->hInst
, "mines");
135 p_board
->hFacesBMP
= LoadBitmap( p_board
->hInst
, "faces");
136 p_board
->hLedsBMP
= LoadBitmap( p_board
->hInst
, "leds");
138 LoadBoard( p_board
);
140 hMenu
= GetMenu( p_board
->hWnd
);
141 CheckMenuItem( hMenu
, IDM_BEGINNER
+ (unsigned) p_board
->difficulty
,
143 if( p_board
->IsMarkQ
)
144 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
146 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
147 CheckLevel( p_board
);
150 static void SaveBoard( BOARD
*p_board
)
154 char data
[MAX_PLAYER_NAME_SIZE
+1];
157 if( RegCreateKeyEx( HKEY_CURRENT_USER
, registry_key
,
159 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
,
160 &hkey
, NULL
) != ERROR_SUCCESS
)
163 RegSetValueEx( hkey
, "Xpos", 0, REG_DWORD
, (LPBYTE
) &p_board
->pos
.x
, sizeof(p_board
->pos
.x
) );
164 RegSetValueEx( hkey
, "Ypos", 0, REG_DWORD
, (LPBYTE
) &p_board
->pos
.y
, sizeof(p_board
->pos
.y
) );
165 RegSetValueEx( hkey
, "Difficulty", 0, REG_DWORD
, (LPBYTE
) &p_board
->difficulty
, sizeof(p_board
->difficulty
) );
166 RegSetValueEx( hkey
, "Height", 0, REG_DWORD
, (LPBYTE
) &p_board
->rows
, sizeof(p_board
->rows
) );
167 RegSetValueEx( hkey
, "Width", 0, REG_DWORD
, (LPBYTE
) &p_board
->cols
, sizeof(p_board
->cols
) );
168 RegSetValueEx( hkey
, "Mines", 0, REG_DWORD
, (LPBYTE
) &p_board
->mines
, sizeof(p_board
->mines
) );
169 RegSetValueEx( hkey
, "Mark", 0, REG_DWORD
, (LPBYTE
) &p_board
->IsMarkQ
, sizeof(p_board
->IsMarkQ
) );
171 for( i
= 0; i
< 3; i
++ ) {
172 wsprintf( key_name
, "Name%u", i
+1 );
173 lstrcpyn( data
, p_board
->best_name
[i
], sizeof( data
) );
174 RegSetValueEx( hkey
, key_name
, 0, REG_SZ
, (LPBYTE
) data
, strlen(data
)+1 );
177 for( i
= 0; i
< 3; i
++ ) {
178 wsprintf( key_name
, "Time%u", i
+1 );
179 RegSetValueEx( hkey
, key_name
, 0, REG_DWORD
, (LPBYTE
) &p_board
->best_time
[i
], sizeof(p_board
->best_time
[i
]) );
184 static void DestroyBoard( BOARD
*p_board
)
186 DeleteObject( p_board
->hFacesBMP
);
187 DeleteObject( p_board
->hLedsBMP
);
188 DeleteObject( p_board
->hMinesBMP
);
191 static void SetDifficulty( BOARD
*p_board
, DIFFICULTY difficulty
)
195 if ( difficulty
== CUSTOM
)
196 if (DialogBoxParam( p_board
->hInst
, "DLG_CUSTOM", p_board
->hWnd
,
197 CustomDlgProc
, (LPARAM
) p_board
) != 0)
200 hMenu
= GetMenu( p_board
->hWnd
);
201 CheckMenuItem( hMenu
, IDM_BEGINNER
+ p_board
->difficulty
, MF_UNCHECKED
);
202 p_board
->difficulty
= difficulty
;
203 CheckMenuItem( hMenu
, IDM_BEGINNER
+ difficulty
, MF_CHECKED
);
205 switch( difficulty
) {
207 p_board
->cols
= BEGINNER_COLS
;
208 p_board
->rows
= BEGINNER_ROWS
;
209 p_board
->mines
= BEGINNER_MINES
;
213 p_board
->cols
= ADVANCED_COLS
;
214 p_board
->rows
= ADVANCED_ROWS
;
215 p_board
->mines
= ADVANCED_MINES
;
219 p_board
->cols
= EXPERT_COLS
;
220 p_board
->rows
= EXPERT_ROWS
;
222 p_board
->mines
= EXPERT_MINES
;
230 static void ShiftBetween(LONG
* x
, LONG
* y
, LONG a
, LONG b
)
242 static void MoveOnScreen(RECT
* rect
)
247 /* find the nearest monitor ... */
248 hMonitor
= MonitorFromRect(rect
, MONITOR_DEFAULTTONEAREST
);
250 /* ... and move it into the work area (ie excluding task bar)*/
251 mi
.cbSize
= sizeof(mi
);
252 GetMonitorInfo(hMonitor
, &mi
);
254 ShiftBetween(&rect
->left
, &rect
->right
, mi
.rcWork
.left
, mi
.rcWork
.right
);
255 ShiftBetween(&rect
->top
, &rect
->bottom
, mi
.rcWork
.top
, mi
.rcWork
.bottom
);
258 static void CreateBoard( BOARD
*p_board
)
260 int left
, top
, bottom
, right
;
264 p_board
->mb
= MB_NONE
;
265 p_board
->boxes_left
= p_board
->cols
* p_board
->rows
- p_board
->mines
;
266 p_board
->num_flags
= 0;
268 /* Create the boxes...
269 * We actually create them with an empty border,
270 * so special care doesn't have to be taken on the edges
272 for( col
= 0; col
<= p_board
->cols
+ 1; col
++ )
273 for( row
= 0; row
<= p_board
->rows
+ 1; row
++ ) {
274 p_board
->box
[col
][row
].IsPressed
= FALSE
;
275 p_board
->box
[col
][row
].IsMine
= FALSE
;
276 p_board
->box
[col
][row
].FlagType
= NORMAL
;
277 p_board
->box
[col
][row
].NumMines
= 0;
280 p_board
->width
= p_board
->cols
* MINE_WIDTH
+ BOARD_WMARGIN
* 2;
282 p_board
->height
= p_board
->rows
* MINE_HEIGHT
+ LED_HEIGHT
285 /* setting the mines rectangle boundary */
286 left
= BOARD_WMARGIN
;
287 top
= BOARD_HMARGIN
* 2 + LED_HEIGHT
;
288 right
= left
+ p_board
->cols
* MINE_WIDTH
;
289 bottom
= top
+ p_board
->rows
* MINE_HEIGHT
;
290 SetRect( &p_board
->mines_rect
, left
, top
, right
, bottom
);
292 /* setting the face rectangle boundary */
293 left
= p_board
->width
/ 2 - FACE_WIDTH
/ 2;
295 right
= left
+ FACE_WIDTH
;
296 bottom
= top
+ FACE_HEIGHT
;
297 SetRect( &p_board
->face_rect
, left
, top
, right
, bottom
);
299 /* setting the timer rectangle boundary */
300 left
= BOARD_WMARGIN
;
302 right
= left
+ LED_WIDTH
* 3;
303 bottom
= top
+ LED_HEIGHT
;
304 SetRect( &p_board
->timer_rect
, left
, top
, right
, bottom
);
306 /* setting the counter rectangle boundary */
307 left
= p_board
->width
- BOARD_WMARGIN
- LED_WIDTH
* 3;
309 right
= p_board
->width
- BOARD_WMARGIN
;
310 bottom
= top
+ LED_HEIGHT
;
311 SetRect( &p_board
->counter_rect
, left
, top
, right
, bottom
);
313 p_board
->status
= WAITING
;
314 p_board
->face_bmp
= SMILE_BMP
;
317 wnd_rect
.left
= p_board
->pos
.x
;
318 wnd_rect
.right
= p_board
->pos
.x
+ p_board
->width
;
319 wnd_rect
.top
= p_board
->pos
.y
;
320 wnd_rect
.bottom
= p_board
->pos
.y
+ p_board
->height
;
321 AdjustWindowRect(&wnd_rect
, wnd_style
, TRUE
);
323 /* Make sure the window is completely on the screen */
324 MoveOnScreen(&wnd_rect
);
325 MoveWindow( p_board
->hWnd
, wnd_rect
.left
, wnd_rect
.top
,
326 wnd_rect
.right
- wnd_rect
.left
,
327 wnd_rect
.bottom
- wnd_rect
.top
,
329 RedrawWindow( p_board
->hWnd
, NULL
, 0,
330 RDW_INVALIDATE
| RDW_UPDATENOW
| RDW_ERASE
);
334 /* Randomly places mines everywhere except the selected box. */
335 static void PlaceMines ( BOARD
*p_board
, int selected_col
, int selected_row
)
340 srand( (unsigned) time( NULL
) );
342 /* Temporarily place a mine at the selected box until all the other
343 * mines are placed, this avoids checking in the mine creation loop. */
344 p_board
->box
[selected_col
][selected_row
].IsMine
= TRUE
;
348 while( (unsigned) i
< p_board
->mines
) {
349 col
= (int) (p_board
->cols
* (float) rand() / RAND_MAX
+ 1);
350 row
= (int) (p_board
->rows
* (float) rand() / RAND_MAX
+ 1);
352 if( !p_board
->box
[col
][row
].IsMine
) {
354 p_board
->box
[col
][row
].IsMine
= TRUE
;
358 /* Remove temporarily placed mine for selected box */
359 p_board
->box
[selected_col
][selected_row
].IsMine
= FALSE
;
362 * Now we label the remaining boxes with the
363 * number of mines surrounding them.
365 for( col
= 1; col
< p_board
->cols
+ 1; col
++ )
366 for( row
= 1; row
< p_board
->rows
+ 1; row
++ ) {
367 for( i
= -1; i
<= 1; i
++ )
368 for( j
= -1; j
<= 1; j
++ ) {
369 if( p_board
->box
[col
+ i
][row
+ j
].IsMine
) {
370 p_board
->box
[col
][row
].NumMines
++ ;
376 static void DrawMine( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, unsigned col
, unsigned row
, BOOL IsPressed
)
378 MINEBMP_OFFSET offset
= BOX_BMP
;
380 if( col
== 0 || col
> p_board
->cols
|| row
== 0 || row
> p_board
->rows
)
383 if( p_board
->status
== GAMEOVER
) {
384 if( p_board
->box
[col
][row
].IsMine
) {
385 switch( p_board
->box
[col
][row
].FlagType
) {
390 offset
= EXPLODE_BMP
;
398 switch( p_board
->box
[col
][row
].FlagType
) {
400 offset
= QUESTION_BMP
;
412 WINE_TRACE("Unknown FlagType during game over in DrawMine\n");
416 } else { /* WAITING or PLAYING */
417 switch( p_board
->box
[col
][row
].FlagType
) {
420 offset
= QUESTION_BMP
;
437 WINE_TRACE("Unknown FlagType while playing in DrawMine\n");
442 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
443 && !p_board
->box
[col
][row
].IsMine
)
444 offset
= (MINEBMP_OFFSET
) p_board
->box
[col
][row
].NumMines
;
447 (col
- 1) * MINE_WIDTH
+ p_board
->mines_rect
.left
,
448 (row
- 1) * MINE_HEIGHT
+ p_board
->mines_rect
.top
,
449 MINE_WIDTH
, MINE_HEIGHT
,
450 hMemDC
, 0, offset
* MINE_HEIGHT
, SRCCOPY
);
453 static void DrawMines ( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
457 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
459 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
460 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
461 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
464 SelectObject( hMemDC
, hOldObj
);
467 static void DrawLeds( HDC hdc
, HDC hMemDC
, BOARD
*p_board
, int number
, int x
, int y
)
476 led
[0] = count
/ 100 ;
477 count
-= led
[0] * 100;
480 led
[0] = 10; /* negative sign */
484 count
-= led
[1] * 10;
488 for( i
= 0; i
< 3; i
++ )
492 hOldObj
= SelectObject (hMemDC
, p_board
->hLedsBMP
);
494 for( i
= 0; i
< 3; i
++ ) {
506 SelectObject( hMemDC
, hOldObj
);
510 static void DrawFace( HDC hdc
, HDC hMemDC
, BOARD
*p_board
)
514 hOldObj
= SelectObject (hMemDC
, p_board
->hFacesBMP
);
517 p_board
->face_rect
.left
,
518 p_board
->face_rect
.top
,
521 hMemDC
, 0, p_board
->face_bmp
* FACE_HEIGHT
, SRCCOPY
);
523 SelectObject( hMemDC
, hOldObj
);
527 static void DrawBoard( HDC hdc
, HDC hMemDC
, PAINTSTRUCT
*ps
, BOARD
*p_board
)
531 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->counter_rect
) )
532 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->mines
- p_board
->num_flags
,
533 p_board
->counter_rect
.left
,
534 p_board
->counter_rect
.top
);
536 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->timer_rect
) )
537 DrawLeds( hdc
, hMemDC
, p_board
, p_board
->time
,
538 p_board
->timer_rect
.left
,
539 p_board
->timer_rect
.top
);
541 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->face_rect
) )
542 DrawFace( hdc
, hMemDC
, p_board
);
544 if( IntersectRect( &tmp_rect
, &ps
->rcPaint
, &p_board
->mines_rect
) )
545 DrawMines( hdc
, hMemDC
, p_board
);
549 static void AddFlag( BOARD
*p_board
, unsigned col
, unsigned row
)
551 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
) {
552 switch( p_board
->box
[col
][row
].FlagType
) {
554 if( p_board
->IsMarkQ
)
555 p_board
->box
[col
][row
].FlagType
= QUESTION
;
557 p_board
->box
[col
][row
].FlagType
= NORMAL
;
558 p_board
->num_flags
--;
562 p_board
->box
[col
][row
].FlagType
= NORMAL
;
566 p_board
->box
[col
][row
].FlagType
= FLAG
;
567 p_board
->num_flags
++;
573 static void UnpressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
579 hdc
= GetDC( p_board
->hWnd
);
580 hMemDC
= CreateCompatibleDC( hdc
);
581 hOldObj
= SelectObject( hMemDC
, p_board
->hMinesBMP
);
583 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, FALSE
);
585 SelectObject( hMemDC
, hOldObj
);
587 ReleaseDC( p_board
->hWnd
, hdc
);
591 static void UnpressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
595 for( i
= -1; i
<= 1; i
++ )
596 for( j
= -1; j
<= 1; j
++ ) {
597 UnpressBox( p_board
, col
+ i
, row
+ j
);
602 static void PressBox( BOARD
*p_board
, unsigned col
, unsigned row
)
608 hdc
= GetDC( p_board
->hWnd
);
609 hMemDC
= CreateCompatibleDC( hdc
);
610 hOldObj
= SelectObject (hMemDC
, p_board
->hMinesBMP
);
612 DrawMine( hdc
, hMemDC
, p_board
, col
, row
, TRUE
);
614 SelectObject( hMemDC
, hOldObj
);
616 ReleaseDC( p_board
->hWnd
, hdc
);
620 static void PressBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
624 for( i
= -1; i
<= 1; i
++ )
625 for( j
= -1; j
<= 1; j
++ ) {
626 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= TRUE
;
627 PressBox( p_board
, col
+ i
, row
+ j
);
630 for( i
= -1; i
<= 1; i
++ )
631 for( j
= -1; j
<= 1; j
++ ) {
632 if( !p_board
->box
[p_board
->press
.x
+ i
][p_board
->press
.y
+ j
].IsPressed
)
633 UnpressBox( p_board
, p_board
->press
.x
+ i
, p_board
->press
.y
+ j
);
636 for( i
= -1; i
<= 1; i
++ )
637 for( j
= -1; j
<= 1; j
++ ) {
638 p_board
->box
[col
+ i
][row
+ j
].IsPressed
= FALSE
;
639 PressBox( p_board
, col
+ i
, row
+ j
);
642 p_board
->press
.x
= col
;
643 p_board
->press
.y
= row
;
647 static void CompleteBox( BOARD
*p_board
, unsigned col
, unsigned row
)
651 if( p_board
->box
[col
][row
].FlagType
!= COMPLETE
&&
652 p_board
->box
[col
][row
].FlagType
!= FLAG
&&
653 col
> 0 && col
< p_board
->cols
+ 1 &&
654 row
> 0 && row
< p_board
->rows
+ 1 ) {
655 p_board
->box
[col
][row
].FlagType
= COMPLETE
;
657 if( p_board
->box
[col
][row
].IsMine
) {
658 p_board
->face_bmp
= DEAD_BMP
;
659 p_board
->status
= GAMEOVER
;
661 else if( p_board
->status
!= GAMEOVER
)
662 p_board
->boxes_left
--;
664 if( p_board
->box
[col
][row
].NumMines
== 0 )
666 for( i
= -1; i
<= 1; i
++ )
667 for( j
= -1; j
<= 1; j
++ )
668 CompleteBox( p_board
, col
+ i
, row
+ j
);
674 static void CompleteBoxes( BOARD
*p_board
, unsigned col
, unsigned row
)
676 unsigned numFlags
= 0;
679 if( p_board
->box
[col
][row
].FlagType
== COMPLETE
) {
680 for( i
= -1; i
<= 1; i
++ )
681 for( j
= -1; j
<= 1; j
++ ) {
682 if( p_board
->box
[col
+i
][row
+j
].FlagType
== FLAG
)
686 if( numFlags
== p_board
->box
[col
][row
].NumMines
) {
687 for( i
= -1; i
<= 1; i
++ )
688 for( j
= -1; j
<= 1; j
++ ) {
689 if( p_board
->box
[col
+i
][row
+j
].FlagType
!= FLAG
)
690 CompleteBox( p_board
, col
+i
, row
+j
);
697 static void TestMines( BOARD
*p_board
, POINT pt
, int msg
)
702 col
= (pt
.x
- p_board
->mines_rect
.left
) / MINE_WIDTH
+ 1;
703 row
= (pt
.y
- p_board
->mines_rect
.top
) / MINE_HEIGHT
+ 1;
707 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
) {
709 p_board
->press
.x
, p_board
->press
.y
);
710 p_board
->press
.x
= col
;
711 p_board
->press
.y
= row
;
712 PressBox( p_board
, col
, row
);
718 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
720 p_board
->press
.x
, p_board
->press
.y
);
721 p_board
->press
.x
= 0;
722 p_board
->press
.y
= 0;
723 if( p_board
->box
[col
][row
].FlagType
!= FLAG
724 && p_board
->status
!= PLAYING
)
726 p_board
->status
= PLAYING
;
727 PlaceMines( p_board
, col
, row
);
729 CompleteBox( p_board
, col
, row
);
733 PressBoxes( p_board
, col
, row
);
738 if( p_board
->press
.x
!= col
|| p_board
->press
.y
!= row
)
739 UnpressBoxes( p_board
,
740 p_board
->press
.x
, p_board
->press
.y
);
741 p_board
->press
.x
= 0;
742 p_board
->press
.y
= 0;
743 CompleteBoxes( p_board
, col
, row
);
747 AddFlag( p_board
, col
, row
);
750 WINE_TRACE("Unknown message type received in TestMines\n");
756 RedrawWindow( p_board
->hWnd
, NULL
, 0,
757 RDW_INVALIDATE
| RDW_UPDATENOW
);
762 static void TestFace( BOARD
*p_board
, POINT pt
, int msg
)
764 if( p_board
->status
== PLAYING
|| p_board
->status
== WAITING
) {
765 if( msg
== WM_LBUTTONDOWN
|| msg
== WM_MBUTTONDOWN
)
766 p_board
->face_bmp
= OOH_BMP
;
767 else p_board
->face_bmp
= SMILE_BMP
;
769 else if( p_board
->status
== GAMEOVER
)
770 p_board
->face_bmp
= DEAD_BMP
;
771 else if( p_board
->status
== WON
)
772 p_board
->face_bmp
= COOL_BMP
;
774 if( PtInRect( &p_board
->face_rect
, pt
) ) {
775 if( msg
== WM_LBUTTONDOWN
)
776 p_board
->face_bmp
= SPRESS_BMP
;
778 if( msg
== WM_LBUTTONUP
)
779 CreateBoard( p_board
);
782 RedrawWindow( p_board
->hWnd
, &p_board
->face_rect
, 0,
783 RDW_INVALIDATE
| RDW_UPDATENOW
);
787 static void TestBoard( HWND hWnd
, BOARD
*p_board
, int x
, int y
, int msg
)
795 if( PtInRect( &p_board
->mines_rect
, pt
) && p_board
->status
!= GAMEOVER
796 && p_board
->status
!= WON
)
797 TestMines( p_board
, pt
, msg
);
799 UnpressBoxes( p_board
,
802 p_board
->press
.x
= 0;
803 p_board
->press
.y
= 0;
806 if( p_board
->boxes_left
== 0 ) {
807 p_board
->status
= WON
;
809 if (p_board
->num_flags
< p_board
->mines
) {
810 for( row
= 1; row
<= p_board
->rows
; row
++ ) {
811 for( col
= 1; col
<= p_board
->cols
; col
++ ) {
812 if (p_board
->box
[col
][row
].IsMine
&& p_board
->box
[col
][row
].FlagType
!= FLAG
)
813 p_board
->box
[col
][row
].FlagType
= FLAG
;
817 p_board
->num_flags
= p_board
->mines
;
819 RedrawWindow( p_board
->hWnd
, NULL
, 0,
820 RDW_INVALIDATE
| RDW_UPDATENOW
);
823 if( p_board
->difficulty
!= CUSTOM
&&
824 p_board
->time
< p_board
->best_time
[p_board
->difficulty
] ) {
825 p_board
->best_time
[p_board
->difficulty
] = p_board
->time
;
827 DialogBoxParam( p_board
->hInst
, "DLG_CONGRATS", hWnd
,
828 CongratsDlgProc
, (LPARAM
) p_board
);
830 DialogBoxParam( p_board
->hInst
, "DLG_TIMES", hWnd
,
831 TimesDlgProc
, (LPARAM
) p_board
);
834 TestFace( p_board
, pt
, msg
);
838 static LRESULT WINAPI
MainProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
847 board
.hInst
= ((LPCREATESTRUCT
) lParam
)->hInstance
;
850 CreateBoard( &board
);
857 WINE_TRACE("WM_PAINT\n");
858 hdc
= BeginPaint( hWnd
, &ps
);
859 hMemDC
= CreateCompatibleDC( hdc
);
861 DrawBoard( hdc
, hMemDC
, &ps
, &board
);
864 EndPaint( hWnd
, &ps
);
870 WINE_TRACE("WM_MOVE\n");
871 board
.pos
.x
= (short)LOWORD(lParam
);
872 board
.pos
.y
= (short)HIWORD(lParam
);
877 DestroyBoard( &board
);
878 PostQuitMessage( 0 );
882 if( board
.status
== PLAYING
) {
884 RedrawWindow( hWnd
, &board
.timer_rect
, 0,
885 RDW_INVALIDATE
| RDW_UPDATENOW
);
890 WINE_TRACE("WM_LBUTTONDOWN\n");
891 if( wParam
& (MK_RBUTTON
| MK_SHIFT
) )
892 msg
= WM_MBUTTONDOWN
;
893 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
898 WINE_TRACE("WM_LBUTTONUP\n");
899 if( wParam
& (MK_RBUTTON
| MK_SHIFT
) )
901 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
906 WINE_TRACE("WM_RBUTTONDOWN\n");
907 if( wParam
& MK_LBUTTON
) {
910 msg
= WM_MBUTTONDOWN
;
912 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
916 WINE_TRACE("WM_RBUTTONUP\n");
917 if( wParam
& MK_LBUTTON
)
919 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
923 WINE_TRACE("WM_MBUTTONDOWN\n");
924 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
928 WINE_TRACE("WM_MBUTTONUP\n");
929 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
934 if( ( wParam
& MK_MBUTTON
) ||
935 ( ( wParam
& MK_LBUTTON
) && ( wParam
& MK_RBUTTON
) ) ) {
936 msg
= WM_MBUTTONDOWN
;
938 else if( wParam
& MK_LBUTTON
) {
939 msg
= WM_LBUTTONDOWN
;
945 TestBoard( hWnd
, &board
, (short)LOWORD(lParam
), (short)HIWORD(lParam
), msg
);
951 switch(LOWORD(wParam
)) {
953 CreateBoard( &board
);
957 hMenu
= GetMenu( hWnd
);
958 board
.IsMarkQ
= !board
.IsMarkQ
;
960 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_CHECKED
);
962 CheckMenuItem( hMenu
, IDM_MARKQ
, MF_UNCHECKED
);
966 SetDifficulty( &board
, BEGINNER
);
967 CreateBoard( &board
);
971 SetDifficulty( &board
, ADVANCED
);
972 CreateBoard( &board
);
976 SetDifficulty( &board
, EXPERT
);
977 CreateBoard( &board
);
981 SetDifficulty( &board
, CUSTOM
);
982 CreateBoard( &board
);
986 SendMessage( hWnd
, WM_CLOSE
, 0, 0);
990 DialogBoxParam( board
.hInst
, "DLG_TIMES", hWnd
,
991 TimesDlgProc
, (LPARAM
) &board
);
996 WCHAR appname
[256], other
[256];
997 LoadStringW( board
.hInst
, IDS_APPNAME
, appname
, sizeof(appname
)/sizeof(WCHAR
) );
998 LoadStringW( board
.hInst
, IDS_ABOUT
, other
, sizeof(other
)/sizeof(WCHAR
) );
999 ShellAboutW( hWnd
, appname
, other
,
1000 LoadImageA( board
.hInst
, "WINEMINE", IMAGE_ICON
, 48, 48, LR_SHARED
));
1004 WINE_TRACE("Unknown WM_COMMAND command message received\n");
1008 return( DefWindowProc( hWnd
, msg
, wParam
, lParam
));
1011 int WINAPI
WinMain( HINSTANCE hInst
, HINSTANCE hPrevInst
, LPSTR cmdline
, int cmdshow
)
1019 LoadString( hInst
, IDS_APPNAME
, appname
, sizeof(appname
));
1021 wc
.cbSize
= sizeof(wc
);
1023 wc
.lpfnWndProc
= MainProc
;
1026 wc
.hInstance
= hInst
;
1027 wc
.hIcon
= LoadIcon( hInst
, "WINEMINE" );
1028 wc
.hCursor
= LoadCursor( 0, IDI_APPLICATION
);
1029 wc
.hbrBackground
= GetSysColorBrush(COLOR_BTNFACE
); //MOD for ROS
1030 wc
.lpszMenuName
= "MENU_WINEMINE";
1031 wc
.lpszClassName
= appname
;
1032 wc
.hIconSm
= LoadImage( hInst
, "WINEMINE", IMAGE_ICON
,
1033 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_SHARED
);
1035 if (!RegisterClassEx(&wc
)) ExitProcess(1);
1036 hWnd
= CreateWindow( appname
, appname
,
1038 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1039 0, 0, hInst
, NULL
);
1041 if (!hWnd
) ExitProcess(1);
1043 ShowWindow( hWnd
, cmdshow
);
1044 UpdateWindow( hWnd
);
1046 haccel
= LoadAccelerators( hInst
, MAKEINTRESOURCE(IDA_WINEMINE
) );
1047 SetTimer( hWnd
, ID_TIMER
, 1000, NULL
);
1049 while( GetMessage(&msg
, 0, 0, 0) ) {
1050 if (!TranslateAccelerator( hWnd
, haccel
, &msg
))
1051 TranslateMessage( &msg
);
1053 DispatchMessage( &msg
);