Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmain.c
Go to the documentation of this file.
00001 /* 00002 * WineMine (main.c) 00003 * 00004 * Copyright 2000 Joshua Thielen 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #define WIN32_LEAN_AND_MEAN 00022 00023 #include <string.h> 00024 #include <time.h> 00025 #include <windows.h> 00026 #include <stdlib.h> 00027 #include <shellapi.h> 00028 #include "main.h" 00029 #include "resource.h" 00030 00031 #include <wine/debug.h> 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(winemine); 00034 00035 static const DWORD wnd_style = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX; 00036 static const char* registry_key = "Software\\Microsoft\\WinMine"; 00037 00038 00039 void CheckLevel( BOARD *p_board ) 00040 { 00041 if( p_board->rows < BEGINNER_ROWS ) 00042 p_board->rows = BEGINNER_ROWS; 00043 00044 if( p_board->rows > MAX_ROWS ) 00045 p_board->rows = MAX_ROWS; 00046 00047 if( p_board->cols < BEGINNER_COLS ) 00048 p_board->cols = BEGINNER_COLS; 00049 00050 if( p_board->cols > MAX_COLS ) 00051 p_board->cols = MAX_COLS; 00052 00053 if( p_board->mines < BEGINNER_MINES ) 00054 p_board->mines = BEGINNER_MINES; 00055 00056 if( p_board->mines > ( p_board->cols - 1 ) * ( p_board->rows - 1 ) ) 00057 p_board->mines = ( p_board->cols - 1 ) * ( p_board->rows - 1 ); 00058 } 00059 00060 static void LoadBoard( BOARD *p_board ) 00061 { 00062 DWORD size; 00063 DWORD type; 00064 HKEY hkey; 00065 char data[MAX_PLAYER_NAME_SIZE+1]; 00066 char key_name[8]; 00067 unsigned i; 00068 00069 RegOpenKeyEx( HKEY_CURRENT_USER, registry_key, 00070 0, KEY_QUERY_VALUE, &hkey ); 00071 00072 size = sizeof( p_board->pos.x ); 00073 if( !RegQueryValueEx( hkey, "Xpos", NULL, &type, 00074 (LPBYTE) &p_board->pos.x, &size ) == ERROR_SUCCESS ) 00075 p_board->pos.x = 0; 00076 00077 size = sizeof( p_board->pos.y ); 00078 if( !RegQueryValueEx( hkey, "Ypos", NULL, &type, 00079 (LPBYTE) &p_board->pos.y, &size ) == ERROR_SUCCESS ) 00080 p_board->pos.y = 0; 00081 00082 size = sizeof( p_board->rows ); 00083 if( !RegQueryValueEx( hkey, "Height", NULL, &type, 00084 (LPBYTE) &p_board->rows, &size ) == ERROR_SUCCESS ) 00085 p_board->rows = BEGINNER_ROWS; 00086 00087 size = sizeof( p_board->cols ); 00088 if( !RegQueryValueEx( hkey, "Width", NULL, &type, 00089 (LPBYTE) &p_board->cols, &size ) == ERROR_SUCCESS ) 00090 p_board->cols = BEGINNER_COLS; 00091 00092 size = sizeof( p_board->mines ); 00093 if( !RegQueryValueEx( hkey, "Mines", NULL, &type, 00094 (LPBYTE) &p_board->mines, &size ) == ERROR_SUCCESS ) 00095 p_board->mines = BEGINNER_MINES; 00096 00097 size = sizeof( p_board->difficulty ); 00098 if( !RegQueryValueEx( hkey, "Difficulty", NULL, &type, 00099 (LPBYTE) &p_board->difficulty, &size ) == ERROR_SUCCESS ) 00100 p_board->difficulty = BEGINNER; 00101 00102 size = sizeof( p_board->IsMarkQ ); 00103 if( !RegQueryValueEx( hkey, "Mark", NULL, &type, 00104 (LPBYTE) &p_board->IsMarkQ, &size ) == ERROR_SUCCESS ) 00105 p_board->IsMarkQ = TRUE; 00106 00107 for( i = 0; i < 3; i++ ) { 00108 wsprintf( key_name, "Name%d", i+1 ); 00109 size = sizeof( data ); 00110 if( RegQueryValueEx( hkey, key_name, NULL, &type, 00111 (LPBYTE) data, &size ) == ERROR_SUCCESS ) 00112 lstrcpynA( p_board->best_name[i], data, sizeof(p_board->best_name[i]) ); 00113 else 00114 LoadString( p_board->hInst, IDS_NOBODY, p_board->best_name[i], MAX_PLAYER_NAME_SIZE+1 ); 00115 } 00116 00117 for( i = 0; i < 3; i++ ) { 00118 wsprintf( key_name, "Time%d", i+1 ); 00119 size = sizeof( p_board->best_time[i] ); 00120 if( !RegQueryValueEx( hkey, key_name, NULL, &type, 00121 (LPBYTE) &p_board->best_time[i], &size ) == ERROR_SUCCESS ) 00122 p_board->best_time[i] = 999; 00123 } 00124 RegCloseKey( hkey ); 00125 } 00126 00127 static void InitBoard( BOARD *p_board ) 00128 { 00129 HMENU hMenu; 00130 00131 p_board->hMinesBMP = LoadBitmap( p_board->hInst, "mines"); 00132 p_board->hFacesBMP = LoadBitmap( p_board->hInst, "faces"); 00133 p_board->hLedsBMP = LoadBitmap( p_board->hInst, "leds"); 00134 00135 LoadBoard( p_board ); 00136 00137 hMenu = GetMenu( p_board->hWnd ); 00138 CheckMenuItem( hMenu, IDM_BEGINNER + (unsigned) p_board->difficulty, 00139 MF_CHECKED ); 00140 if( p_board->IsMarkQ ) 00141 CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED ); 00142 else 00143 CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED ); 00144 CheckLevel( p_board ); 00145 } 00146 00147 static void SaveBoard( BOARD *p_board ) 00148 { 00149 HKEY hkey; 00150 unsigned i; 00151 char data[MAX_PLAYER_NAME_SIZE+1]; 00152 char key_name[8]; 00153 00154 if( RegCreateKeyEx( HKEY_CURRENT_USER, registry_key, 00155 0, NULL, 00156 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, 00157 &hkey, NULL ) != ERROR_SUCCESS) 00158 return; 00159 00160 RegSetValueEx( hkey, "Xpos", 0, REG_DWORD, (LPBYTE) &p_board->pos.x, sizeof(p_board->pos.x) ); 00161 RegSetValueEx( hkey, "Ypos", 0, REG_DWORD, (LPBYTE) &p_board->pos.y, sizeof(p_board->pos.y) ); 00162 RegSetValueEx( hkey, "Difficulty", 0, REG_DWORD, (LPBYTE) &p_board->difficulty, sizeof(p_board->difficulty) ); 00163 RegSetValueEx( hkey, "Height", 0, REG_DWORD, (LPBYTE) &p_board->rows, sizeof(p_board->rows) ); 00164 RegSetValueEx( hkey, "Width", 0, REG_DWORD, (LPBYTE) &p_board->cols, sizeof(p_board->cols) ); 00165 RegSetValueEx( hkey, "Mines", 0, REG_DWORD, (LPBYTE) &p_board->mines, sizeof(p_board->mines) ); 00166 RegSetValueEx( hkey, "Mark", 0, REG_DWORD, (LPBYTE) &p_board->IsMarkQ, sizeof(p_board->IsMarkQ) ); 00167 00168 for( i = 0; i < 3; i++ ) { 00169 wsprintf( key_name, "Name%u", i+1 ); 00170 lstrcpyn( data, p_board->best_name[i], sizeof( data ) ); 00171 RegSetValueEx( hkey, key_name, 0, REG_SZ, (LPBYTE) data, strlen(data)+1 ); 00172 } 00173 00174 for( i = 0; i < 3; i++ ) { 00175 wsprintf( key_name, "Time%u", i+1 ); 00176 RegSetValueEx( hkey, key_name, 0, REG_DWORD, (LPBYTE) &p_board->best_time[i], sizeof(p_board->best_time[i]) ); 00177 } 00178 RegCloseKey( hkey ); 00179 } 00180 00181 static void DestroyBoard( BOARD *p_board ) 00182 { 00183 DeleteObject( p_board->hFacesBMP ); 00184 DeleteObject( p_board->hLedsBMP ); 00185 DeleteObject( p_board->hMinesBMP ); 00186 } 00187 00188 static void SetDifficulty( BOARD *p_board, DIFFICULTY difficulty ) 00189 { 00190 HMENU hMenu; 00191 00192 if ( difficulty == CUSTOM ) 00193 if (DialogBoxParam( p_board->hInst, "DLG_CUSTOM", p_board->hWnd, 00194 CustomDlgProc, (LPARAM) p_board) != 0) 00195 return; 00196 00197 hMenu = GetMenu( p_board->hWnd ); 00198 CheckMenuItem( hMenu, IDM_BEGINNER + p_board->difficulty, MF_UNCHECKED ); 00199 p_board->difficulty = difficulty; 00200 CheckMenuItem( hMenu, IDM_BEGINNER + difficulty, MF_CHECKED ); 00201 00202 switch( difficulty ) { 00203 case BEGINNER: 00204 p_board->cols = BEGINNER_COLS; 00205 p_board->rows = BEGINNER_ROWS; 00206 p_board->mines = BEGINNER_MINES; 00207 break; 00208 00209 case ADVANCED: 00210 p_board->cols = ADVANCED_COLS; 00211 p_board->rows = ADVANCED_ROWS; 00212 p_board->mines = ADVANCED_MINES; 00213 break; 00214 00215 case EXPERT: 00216 p_board->cols = EXPERT_COLS; 00217 p_board->rows = EXPERT_ROWS; 00218 00219 p_board->mines = EXPERT_MINES; 00220 break; 00221 00222 case CUSTOM: 00223 break; 00224 } 00225 } 00226 00227 static void ShiftBetween(LONG* x, LONG* y, LONG a, LONG b) 00228 { 00229 if (*x < a) { 00230 *y += a - *x; 00231 *x = a; 00232 } 00233 else if (*y > b) { 00234 *x -= *y - b; 00235 *y = b; 00236 } 00237 } 00238 00239 static void MoveOnScreen(RECT* rect) 00240 { 00241 HMONITOR hMonitor; 00242 MONITORINFO mi; 00243 00244 /* find the nearest monitor ... */ 00245 hMonitor = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST); 00246 00247 /* ... and move it into the work area (ie excluding task bar)*/ 00248 mi.cbSize = sizeof(mi); 00249 GetMonitorInfo(hMonitor, &mi); 00250 00251 ShiftBetween(&rect->left, &rect->right, mi.rcWork.left, mi.rcWork.right); 00252 ShiftBetween(&rect->top, &rect->bottom, mi.rcWork.top, mi.rcWork.bottom); 00253 } 00254 00255 static void CreateBoard( BOARD *p_board ) 00256 { 00257 int left, top, bottom, right; 00258 unsigned col, row; 00259 RECT wnd_rect; 00260 00261 p_board->mb = MB_NONE; 00262 p_board->boxes_left = p_board->cols * p_board->rows - p_board->mines; 00263 p_board->num_flags = 0; 00264 00265 /* Create the boxes... 00266 * We actually create them with an empty border, 00267 * so special care doesn't have to be taken on the edges 00268 */ 00269 for( col = 0; col <= p_board->cols + 1; col++ ) 00270 for( row = 0; row <= p_board->rows + 1; row++ ) { 00271 p_board->box[col][row].IsPressed = FALSE; 00272 p_board->box[col][row].IsMine = FALSE; 00273 p_board->box[col][row].FlagType = NORMAL; 00274 p_board->box[col][row].NumMines = 0; 00275 } 00276 00277 p_board->width = p_board->cols * MINE_WIDTH + BOARD_WMARGIN * 2; 00278 00279 p_board->height = p_board->rows * MINE_HEIGHT + LED_HEIGHT 00280 + BOARD_HMARGIN * 3; 00281 00282 /* setting the mines rectangle boundary */ 00283 left = BOARD_WMARGIN; 00284 top = BOARD_HMARGIN * 2 + LED_HEIGHT; 00285 right = left + p_board->cols * MINE_WIDTH; 00286 bottom = top + p_board->rows * MINE_HEIGHT; 00287 SetRect( &p_board->mines_rect, left, top, right, bottom ); 00288 00289 /* setting the face rectangle boundary */ 00290 left = p_board->width / 2 - FACE_WIDTH / 2; 00291 top = BOARD_HMARGIN; 00292 right = left + FACE_WIDTH; 00293 bottom = top + FACE_HEIGHT; 00294 SetRect( &p_board->face_rect, left, top, right, bottom ); 00295 00296 /* setting the timer rectangle boundary */ 00297 left = BOARD_WMARGIN; 00298 top = BOARD_HMARGIN; 00299 right = left + LED_WIDTH * 3; 00300 bottom = top + LED_HEIGHT; 00301 SetRect( &p_board->timer_rect, left, top, right, bottom ); 00302 00303 /* setting the counter rectangle boundary */ 00304 left = p_board->width - BOARD_WMARGIN - LED_WIDTH * 3; 00305 top = BOARD_HMARGIN; 00306 right = p_board->width - BOARD_WMARGIN; 00307 bottom = top + LED_HEIGHT; 00308 SetRect( &p_board->counter_rect, left, top, right, bottom ); 00309 00310 p_board->status = WAITING; 00311 p_board->face_bmp = SMILE_BMP; 00312 p_board->time = 0; 00313 00314 wnd_rect.left = p_board->pos.x; 00315 wnd_rect.right = p_board->pos.x + p_board->width; 00316 wnd_rect.top = p_board->pos.y; 00317 wnd_rect.bottom = p_board->pos.y + p_board->height; 00318 AdjustWindowRect(&wnd_rect, wnd_style, TRUE); 00319 00320 /* Make sure the window is completely on the screen */ 00321 MoveOnScreen(&wnd_rect); 00322 MoveWindow( p_board->hWnd, wnd_rect.left, wnd_rect.top, 00323 wnd_rect.right - wnd_rect.left, 00324 wnd_rect.bottom - wnd_rect.top, 00325 TRUE ); 00326 RedrawWindow( p_board->hWnd, NULL, 0, 00327 RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 00328 } 00329 00330 00331 /* Randomly places mines everywhere except the selected box. */ 00332 static void PlaceMines ( BOARD *p_board, int selected_col, int selected_row ) 00333 { 00334 int i, j; 00335 unsigned col, row; 00336 00337 srand( (unsigned) time( NULL ) ); 00338 00339 /* Temporarily place a mine at the selected box until all the other 00340 * mines are placed, this avoids checking in the mine creation loop. */ 00341 p_board->box[selected_col][selected_row].IsMine = TRUE; 00342 00343 /* create mines */ 00344 i = 0; 00345 while( (unsigned) i < p_board->mines ) { 00346 col = (int) (p_board->cols * (float) rand() / RAND_MAX + 1); 00347 row = (int) (p_board->rows * (float) rand() / RAND_MAX + 1); 00348 00349 if( !p_board->box[col][row].IsMine ) { 00350 i++; 00351 p_board->box[col][row].IsMine = TRUE; 00352 } 00353 } 00354 00355 /* Remove temporarily placed mine for selected box */ 00356 p_board->box[selected_col][selected_row].IsMine = FALSE; 00357 00358 /* 00359 * Now we label the remaining boxes with the 00360 * number of mines surrounding them. 00361 */ 00362 for( col = 1; col < p_board->cols + 1; col++ ) 00363 for( row = 1; row < p_board->rows + 1; row++ ) { 00364 for( i = -1; i <= 1; i++ ) 00365 for( j = -1; j <= 1; j++ ) { 00366 if( p_board->box[col + i][row + j].IsMine ) { 00367 p_board->box[col][row].NumMines++ ; 00368 } 00369 } 00370 } 00371 } 00372 00373 static void DrawMine( HDC hdc, HDC hMemDC, BOARD *p_board, unsigned col, unsigned row, BOOL IsPressed ) 00374 { 00375 MINEBMP_OFFSET offset = BOX_BMP; 00376 00377 if( col == 0 || col > p_board->cols || row == 0 || row > p_board->rows ) 00378 return; 00379 00380 if( p_board->status == GAMEOVER ) { 00381 if( p_board->box[col][row].IsMine ) { 00382 switch( p_board->box[col][row].FlagType ) { 00383 case FLAG: 00384 offset = FLAG_BMP; 00385 break; 00386 case COMPLETE: 00387 offset = EXPLODE_BMP; 00388 break; 00389 case QUESTION: 00390 /* fall through */ 00391 case NORMAL: 00392 offset = MINE_BMP; 00393 } 00394 } else { 00395 switch( p_board->box[col][row].FlagType ) { 00396 case QUESTION: 00397 offset = QUESTION_BMP; 00398 break; 00399 case FLAG: 00400 offset = WRONG_BMP; 00401 break; 00402 case NORMAL: 00403 offset = BOX_BMP; 00404 break; 00405 case COMPLETE: 00406 /* Do nothing */ 00407 break; 00408 default: 00409 WINE_TRACE("Unknown FlagType during game over in DrawMine\n"); 00410 break; 00411 } 00412 } 00413 } else { /* WAITING or PLAYING */ 00414 switch( p_board->box[col][row].FlagType ) { 00415 case QUESTION: 00416 if( !IsPressed ) 00417 offset = QUESTION_BMP; 00418 else 00419 offset = QPRESS_BMP; 00420 break; 00421 case FLAG: 00422 offset = FLAG_BMP; 00423 break; 00424 case NORMAL: 00425 if( !IsPressed ) 00426 offset = BOX_BMP; 00427 else 00428 offset = MPRESS_BMP; 00429 break; 00430 case COMPLETE: 00431 /* Do nothing */ 00432 break; 00433 default: 00434 WINE_TRACE("Unknown FlagType while playing in DrawMine\n"); 00435 break; 00436 } 00437 } 00438 00439 if( p_board->box[col][row].FlagType == COMPLETE 00440 && !p_board->box[col][row].IsMine ) 00441 offset = (MINEBMP_OFFSET) p_board->box[col][row].NumMines; 00442 00443 BitBlt( hdc, 00444 (col - 1) * MINE_WIDTH + p_board->mines_rect.left, 00445 (row - 1) * MINE_HEIGHT + p_board->mines_rect.top, 00446 MINE_WIDTH, MINE_HEIGHT, 00447 hMemDC, 0, offset * MINE_HEIGHT, SRCCOPY ); 00448 } 00449 00450 static void DrawMines ( HDC hdc, HDC hMemDC, BOARD *p_board ) 00451 { 00452 HGDIOBJ hOldObj; 00453 unsigned col, row; 00454 hOldObj = SelectObject (hMemDC, p_board->hMinesBMP); 00455 00456 for( row = 1; row <= p_board->rows; row++ ) { 00457 for( col = 1; col <= p_board->cols; col++ ) { 00458 DrawMine( hdc, hMemDC, p_board, col, row, FALSE ); 00459 } 00460 } 00461 SelectObject( hMemDC, hOldObj ); 00462 } 00463 00464 static void DrawLeds( HDC hdc, HDC hMemDC, BOARD *p_board, int number, int x, int y ) 00465 { 00466 HGDIOBJ hOldObj; 00467 unsigned led[3], i; 00468 int count; 00469 00470 count = number; 00471 if( count < 1000 ) { 00472 if( count >= 0 ) { 00473 led[0] = count / 100 ; 00474 count -= led[0] * 100; 00475 } 00476 else { 00477 led[0] = 10; /* negative sign */ 00478 count = -count; 00479 } 00480 led[1] = count / 10; 00481 count -= led[1] * 10; 00482 led[2] = count; 00483 } 00484 else { 00485 for( i = 0; i < 3; i++ ) 00486 led[i] = 10; 00487 } 00488 00489 hOldObj = SelectObject (hMemDC, p_board->hLedsBMP); 00490 00491 for( i = 0; i < 3; i++ ) { 00492 BitBlt( hdc, 00493 i * LED_WIDTH + x, 00494 y, 00495 LED_WIDTH, 00496 LED_HEIGHT, 00497 hMemDC, 00498 0, 00499 led[i] * LED_HEIGHT, 00500 SRCCOPY); 00501 } 00502 00503 SelectObject( hMemDC, hOldObj ); 00504 } 00505 00506 00507 static void DrawFace( HDC hdc, HDC hMemDC, BOARD *p_board ) 00508 { 00509 HGDIOBJ hOldObj; 00510 00511 hOldObj = SelectObject (hMemDC, p_board->hFacesBMP); 00512 00513 BitBlt( hdc, 00514 p_board->face_rect.left, 00515 p_board->face_rect.top, 00516 FACE_WIDTH, 00517 FACE_HEIGHT, 00518 hMemDC, 0, p_board->face_bmp * FACE_HEIGHT, SRCCOPY); 00519 00520 SelectObject( hMemDC, hOldObj ); 00521 } 00522 00523 00524 static void DrawBoard( HDC hdc, HDC hMemDC, PAINTSTRUCT *ps, BOARD *p_board ) 00525 { 00526 RECT tmp_rect; 00527 00528 if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->counter_rect ) ) 00529 DrawLeds( hdc, hMemDC, p_board, p_board->mines - p_board->num_flags, 00530 p_board->counter_rect.left, 00531 p_board->counter_rect.top ); 00532 00533 if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->timer_rect ) ) 00534 DrawLeds( hdc, hMemDC, p_board, p_board->time, 00535 p_board->timer_rect.left, 00536 p_board->timer_rect.top ); 00537 00538 if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->face_rect ) ) 00539 DrawFace( hdc, hMemDC, p_board ); 00540 00541 if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->mines_rect ) ) 00542 DrawMines( hdc, hMemDC, p_board ); 00543 } 00544 00545 00546 static void AddFlag( BOARD *p_board, unsigned col, unsigned row ) 00547 { 00548 if( p_board->box[col][row].FlagType != COMPLETE ) { 00549 switch( p_board->box[col][row].FlagType ) { 00550 case FLAG: 00551 if( p_board->IsMarkQ ) 00552 p_board->box[col][row].FlagType = QUESTION; 00553 else 00554 p_board->box[col][row].FlagType = NORMAL; 00555 p_board->num_flags--; 00556 break; 00557 00558 case QUESTION: 00559 p_board->box[col][row].FlagType = NORMAL; 00560 break; 00561 00562 default: 00563 p_board->box[col][row].FlagType = FLAG; 00564 p_board->num_flags++; 00565 } 00566 } 00567 } 00568 00569 00570 static void UnpressBox( BOARD *p_board, unsigned col, unsigned row ) 00571 { 00572 HDC hdc; 00573 HGDIOBJ hOldObj; 00574 HDC hMemDC; 00575 00576 hdc = GetDC( p_board->hWnd ); 00577 hMemDC = CreateCompatibleDC( hdc ); 00578 hOldObj = SelectObject( hMemDC, p_board->hMinesBMP ); 00579 00580 DrawMine( hdc, hMemDC, p_board, col, row, FALSE ); 00581 00582 SelectObject( hMemDC, hOldObj ); 00583 DeleteDC( hMemDC ); 00584 ReleaseDC( p_board->hWnd, hdc ); 00585 } 00586 00587 00588 static void UnpressBoxes( BOARD *p_board, unsigned col, unsigned row ) 00589 { 00590 int i, j; 00591 00592 for( i = -1; i <= 1; i++ ) 00593 for( j = -1; j <= 1; j++ ) { 00594 UnpressBox( p_board, col + i, row + j ); 00595 } 00596 } 00597 00598 00599 static void PressBox( BOARD *p_board, unsigned col, unsigned row ) 00600 { 00601 HDC hdc; 00602 HGDIOBJ hOldObj; 00603 HDC hMemDC; 00604 00605 hdc = GetDC( p_board->hWnd ); 00606 hMemDC = CreateCompatibleDC( hdc ); 00607 hOldObj = SelectObject (hMemDC, p_board->hMinesBMP); 00608 00609 DrawMine( hdc, hMemDC, p_board, col, row, TRUE ); 00610 00611 SelectObject( hMemDC, hOldObj ); 00612 DeleteDC( hMemDC ); 00613 ReleaseDC( p_board->hWnd, hdc ); 00614 } 00615 00616 00617 static void PressBoxes( BOARD *p_board, unsigned col, unsigned row ) 00618 { 00619 int i, j; 00620 00621 for( i = -1; i <= 1; i++ ) 00622 for( j = -1; j <= 1; j++ ) { 00623 p_board->box[col + i][row + j].IsPressed = TRUE; 00624 PressBox( p_board, col + i, row + j ); 00625 } 00626 00627 for( i = -1; i <= 1; i++ ) 00628 for( j = -1; j <= 1; j++ ) { 00629 if( !p_board->box[p_board->press.x + i][p_board->press.y + j].IsPressed ) 00630 UnpressBox( p_board, p_board->press.x + i, p_board->press.y + j ); 00631 } 00632 00633 for( i = -1; i <= 1; i++ ) 00634 for( j = -1; j <= 1; j++ ) { 00635 p_board->box[col + i][row + j].IsPressed = FALSE; 00636 PressBox( p_board, col + i, row + j ); 00637 } 00638 00639 p_board->press.x = col; 00640 p_board->press.y = row; 00641 } 00642 00643 00644 static void CompleteBox( BOARD *p_board, unsigned col, unsigned row ) 00645 { 00646 int i, j; 00647 00648 if( p_board->box[col][row].FlagType != COMPLETE && 00649 p_board->box[col][row].FlagType != FLAG && 00650 col > 0 && col < p_board->cols + 1 && 00651 row > 0 && row < p_board->rows + 1 ) { 00652 p_board->box[col][row].FlagType = COMPLETE; 00653 00654 if( p_board->box[col][row].IsMine ) { 00655 p_board->face_bmp = DEAD_BMP; 00656 p_board->status = GAMEOVER; 00657 } 00658 else if( p_board->status != GAMEOVER ) 00659 p_board->boxes_left--; 00660 00661 if( p_board->box[col][row].NumMines == 0 ) 00662 { 00663 for( i = -1; i <= 1; i++ ) 00664 for( j = -1; j <= 1; j++ ) 00665 CompleteBox( p_board, col + i, row + j ); 00666 } 00667 } 00668 } 00669 00670 00671 static void CompleteBoxes( BOARD *p_board, unsigned col, unsigned row ) 00672 { 00673 unsigned numFlags = 0; 00674 int i, j; 00675 00676 if( p_board->box[col][row].FlagType == COMPLETE ) { 00677 for( i = -1; i <= 1; i++ ) 00678 for( j = -1; j <= 1; j++ ) { 00679 if( p_board->box[col+i][row+j].FlagType == FLAG ) 00680 numFlags++; 00681 } 00682 00683 if( numFlags == p_board->box[col][row].NumMines ) { 00684 for( i = -1; i <= 1; i++ ) 00685 for( j = -1; j <= 1; j++ ) { 00686 if( p_board->box[col+i][row+j].FlagType != FLAG ) 00687 CompleteBox( p_board, col+i, row+j ); 00688 } 00689 } 00690 } 00691 } 00692 00693 00694 static void TestMines( BOARD *p_board, POINT pt, int msg ) 00695 { 00696 BOOL draw = TRUE; 00697 int col, row; 00698 00699 col = (pt.x - p_board->mines_rect.left) / MINE_WIDTH + 1; 00700 row = (pt.y - p_board->mines_rect.top ) / MINE_HEIGHT + 1; 00701 00702 switch ( msg ) { 00703 case WM_LBUTTONDOWN: 00704 if( p_board->press.x != col || p_board->press.y != row ) { 00705 UnpressBox( p_board, 00706 p_board->press.x, p_board->press.y ); 00707 p_board->press.x = col; 00708 p_board->press.y = row; 00709 PressBox( p_board, col, row ); 00710 } 00711 draw = FALSE; 00712 break; 00713 00714 case WM_LBUTTONUP: 00715 if( p_board->press.x != col || p_board->press.y != row ) 00716 UnpressBox( p_board, 00717 p_board->press.x, p_board->press.y ); 00718 p_board->press.x = 0; 00719 p_board->press.y = 0; 00720 if( p_board->box[col][row].FlagType != FLAG 00721 && p_board->status != PLAYING ) 00722 { 00723 p_board->status = PLAYING; 00724 PlaceMines( p_board, col, row ); 00725 } 00726 CompleteBox( p_board, col, row ); 00727 break; 00728 00729 case WM_MBUTTONDOWN: 00730 PressBoxes( p_board, col, row ); 00731 draw = FALSE; 00732 break; 00733 00734 case WM_MBUTTONUP: 00735 if( p_board->press.x != col || p_board->press.y != row ) 00736 UnpressBoxes( p_board, 00737 p_board->press.x, p_board->press.y ); 00738 p_board->press.x = 0; 00739 p_board->press.y = 0; 00740 CompleteBoxes( p_board, col, row ); 00741 break; 00742 00743 case WM_RBUTTONDOWN: 00744 AddFlag( p_board, col, row ); 00745 break; 00746 default: 00747 WINE_TRACE("Unknown message type received in TestMines\n"); 00748 break; 00749 } 00750 00751 if( draw ) 00752 { 00753 RedrawWindow( p_board->hWnd, NULL, 0, 00754 RDW_INVALIDATE | RDW_UPDATENOW ); 00755 } 00756 } 00757 00758 00759 static void TestFace( BOARD *p_board, POINT pt, int msg ) 00760 { 00761 if( p_board->status == PLAYING || p_board->status == WAITING ) { 00762 if( msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN ) 00763 p_board->face_bmp = OOH_BMP; 00764 else p_board->face_bmp = SMILE_BMP; 00765 } 00766 else if( p_board->status == GAMEOVER ) 00767 p_board->face_bmp = DEAD_BMP; 00768 else if( p_board->status == WON ) 00769 p_board->face_bmp = COOL_BMP; 00770 00771 if( PtInRect( &p_board->face_rect, pt ) ) { 00772 if( msg == WM_LBUTTONDOWN ) 00773 p_board->face_bmp = SPRESS_BMP; 00774 00775 if( msg == WM_LBUTTONUP ) 00776 CreateBoard( p_board ); 00777 } 00778 00779 RedrawWindow( p_board->hWnd, &p_board->face_rect, 0, 00780 RDW_INVALIDATE | RDW_UPDATENOW ); 00781 } 00782 00783 00784 static void TestBoard( HWND hWnd, BOARD *p_board, int x, int y, int msg ) 00785 { 00786 POINT pt; 00787 unsigned col,row; 00788 00789 pt.x = x; 00790 pt.y = y; 00791 00792 if( PtInRect( &p_board->mines_rect, pt ) && p_board->status != GAMEOVER 00793 && p_board->status != WON ) 00794 TestMines( p_board, pt, msg ); 00795 else { 00796 UnpressBoxes( p_board, 00797 p_board->press.x, 00798 p_board->press.y ); 00799 p_board->press.x = 0; 00800 p_board->press.y = 0; 00801 } 00802 00803 if( p_board->boxes_left == 0 ) { 00804 p_board->status = WON; 00805 00806 if (p_board->num_flags < p_board->mines) { 00807 for( row = 1; row <= p_board->rows; row++ ) { 00808 for( col = 1; col <= p_board->cols; col++ ) { 00809 if (p_board->box[col][row].IsMine && p_board->box[col][row].FlagType != FLAG) 00810 p_board->box[col][row].FlagType = FLAG; 00811 } 00812 } 00813 00814 p_board->num_flags = p_board->mines; 00815 00816 RedrawWindow( p_board->hWnd, NULL, 0, 00817 RDW_INVALIDATE | RDW_UPDATENOW ); 00818 } 00819 00820 if( p_board->difficulty != CUSTOM && 00821 p_board->time < p_board->best_time[p_board->difficulty] ) { 00822 p_board->best_time[p_board->difficulty] = p_board->time; 00823 00824 DialogBoxParam( p_board->hInst, "DLG_CONGRATS", hWnd, 00825 CongratsDlgProc, (LPARAM) p_board); 00826 00827 DialogBoxParam( p_board->hInst, "DLG_TIMES", hWnd, 00828 TimesDlgProc, (LPARAM) p_board); 00829 } 00830 } 00831 TestFace( p_board, pt, msg ); 00832 } 00833 00834 00835 static LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 00836 { 00837 HDC hdc; 00838 PAINTSTRUCT ps; 00839 HMENU hMenu; 00840 static BOARD board; 00841 00842 switch( msg ) { 00843 case WM_CREATE: 00844 board.hInst = ((LPCREATESTRUCT) lParam)->hInstance; 00845 board.hWnd = hWnd; 00846 InitBoard( &board ); 00847 CreateBoard( &board ); 00848 return 0; 00849 00850 case WM_PAINT: 00851 { 00852 HDC hMemDC; 00853 00854 WINE_TRACE("WM_PAINT\n"); 00855 hdc = BeginPaint( hWnd, &ps ); 00856 hMemDC = CreateCompatibleDC( hdc ); 00857 00858 DrawBoard( hdc, hMemDC, &ps, &board ); 00859 00860 DeleteDC( hMemDC ); 00861 EndPaint( hWnd, &ps ); 00862 00863 return 0; 00864 } 00865 00866 case WM_MOVE: 00867 WINE_TRACE("WM_MOVE\n"); 00868 board.pos.x = (short)LOWORD(lParam); 00869 board.pos.y = (short)HIWORD(lParam); 00870 return 0; 00871 00872 case WM_DESTROY: 00873 SaveBoard( &board ); 00874 DestroyBoard( &board ); 00875 PostQuitMessage( 0 ); 00876 return 0; 00877 00878 case WM_TIMER: 00879 if( board.status == PLAYING ) { 00880 board.time++; 00881 RedrawWindow( hWnd, &board.timer_rect, 0, 00882 RDW_INVALIDATE | RDW_UPDATENOW ); 00883 } 00884 return 0; 00885 00886 case WM_LBUTTONDOWN: 00887 WINE_TRACE("WM_LBUTTONDOWN\n"); 00888 if( wParam & (MK_RBUTTON | MK_SHIFT) ) 00889 msg = WM_MBUTTONDOWN; 00890 TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg ); 00891 SetCapture( hWnd ); 00892 return 0; 00893 00894 case WM_LBUTTONUP: 00895 WINE_TRACE("WM_LBUTTONUP\n"); 00896 if( wParam & (MK_RBUTTON | MK_SHIFT) ) 00897 msg = WM_MBUTTONUP; 00898 TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg ); 00899 ReleaseCapture(); 00900 return 0; 00901 00902 case WM_RBUTTONDOWN: 00903 WINE_TRACE("WM_RBUTTONDOWN\n"); 00904 if( wParam & MK_LBUTTON ) { 00905 board.press.x = 0; 00906 board.press.y = 0; 00907 msg = WM_MBUTTONDOWN; 00908 } 00909 TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg ); 00910 return 0; 00911 00912 case WM_RBUTTONUP: 00913 WINE_TRACE("WM_RBUTTONUP\n"); 00914 if( wParam & MK_LBUTTON ) 00915 msg = WM_MBUTTONUP; 00916 TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg ); 00917 return 0; 00918 00919 case WM_MBUTTONDOWN: 00920 WINE_TRACE("WM_MBUTTONDOWN\n"); 00921 TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg ); 00922 return 0; 00923 00924 case WM_MBUTTONUP: 00925 WINE_TRACE("WM_MBUTTONUP\n"); 00926 TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg ); 00927 return 0; 00928 00929 case WM_MOUSEMOVE: 00930 { 00931 if( ( wParam & MK_MBUTTON ) || 00932 ( ( wParam & MK_LBUTTON ) && ( wParam & MK_RBUTTON ) ) ) { 00933 msg = WM_MBUTTONDOWN; 00934 } 00935 else if( wParam & MK_LBUTTON ) { 00936 msg = WM_LBUTTONDOWN; 00937 } 00938 else { 00939 return 0; 00940 } 00941 00942 TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg ); 00943 00944 return 0; 00945 } 00946 00947 case WM_COMMAND: 00948 switch(LOWORD(wParam)) { 00949 case IDM_NEW: 00950 CreateBoard( &board ); 00951 return 0; 00952 00953 case IDM_MARKQ: 00954 hMenu = GetMenu( hWnd ); 00955 board.IsMarkQ = !board.IsMarkQ; 00956 if( board.IsMarkQ ) 00957 CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED ); 00958 else 00959 CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED ); 00960 return 0; 00961 00962 case IDM_BEGINNER: 00963 SetDifficulty( &board, BEGINNER ); 00964 CreateBoard( &board ); 00965 return 0; 00966 00967 case IDM_ADVANCED: 00968 SetDifficulty( &board, ADVANCED ); 00969 CreateBoard( &board ); 00970 return 0; 00971 00972 case IDM_EXPERT: 00973 SetDifficulty( &board, EXPERT ); 00974 CreateBoard( &board ); 00975 return 0; 00976 00977 case IDM_CUSTOM: 00978 SetDifficulty( &board, CUSTOM ); 00979 CreateBoard( &board ); 00980 return 0; 00981 00982 case IDM_EXIT: 00983 SendMessage( hWnd, WM_CLOSE, 0, 0); 00984 return 0; 00985 00986 case IDM_TIMES: 00987 DialogBoxParam( board.hInst, "DLG_TIMES", hWnd, 00988 TimesDlgProc, (LPARAM) &board); 00989 return 0; 00990 00991 case IDM_ABOUT: 00992 { 00993 WCHAR appname[256], other[256]; 00994 LoadStringW( board.hInst, IDS_APPNAME, appname, sizeof(appname)/sizeof(WCHAR) ); 00995 LoadStringW( board.hInst, IDS_ABOUT, other, sizeof(other)/sizeof(WCHAR) ); 00996 ShellAboutW( hWnd, appname, other, 00997 LoadImageA( board.hInst, "WINEMINE", IMAGE_ICON, 48, 48, LR_SHARED )); 00998 return 0; 00999 } 01000 default: 01001 WINE_TRACE("Unknown WM_COMMAND command message received\n"); 01002 break; 01003 } 01004 } 01005 return( DefWindowProc( hWnd, msg, wParam, lParam )); 01006 } 01007 01008 int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow ) 01009 { 01010 MSG msg; 01011 WNDCLASSEX wc; 01012 HWND hWnd; 01013 HACCEL haccel; 01014 char appname[20]; 01015 01016 LoadString( hInst, IDS_APPNAME, appname, sizeof(appname)); 01017 01018 wc.cbSize = sizeof(wc); 01019 wc.style = 0; 01020 wc.lpfnWndProc = MainProc; 01021 wc.cbClsExtra = 0; 01022 wc.cbWndExtra = 0; 01023 wc.hInstance = hInst; 01024 wc.hIcon = LoadIcon( hInst, "WINEMINE" ); 01025 wc.hCursor = LoadCursor( 0, IDI_APPLICATION ); 01026 wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); //MOD for ROS 01027 wc.lpszMenuName = "MENU_WINEMINE"; 01028 wc.lpszClassName = appname; 01029 wc.hIconSm = LoadImage( hInst, "WINEMINE", IMAGE_ICON, 01030 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED ); 01031 01032 if (!RegisterClassEx(&wc)) ExitProcess(1); 01033 hWnd = CreateWindow( appname, appname, 01034 wnd_style, 01035 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 01036 0, 0, hInst, NULL ); 01037 01038 if (!hWnd) ExitProcess(1); 01039 01040 ShowWindow( hWnd, cmdshow ); 01041 UpdateWindow( hWnd ); 01042 01043 haccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDA_WINEMINE) ); 01044 SetTimer( hWnd, ID_TIMER, 1000, NULL ); 01045 01046 while( GetMessage(&msg, 0, 0, 0) ) { 01047 if (!TranslateAccelerator( hWnd, haccel, &msg )) 01048 TranslateMessage( &msg ); 01049 01050 DispatchMessage( &msg ); 01051 } 01052 return msg.wParam; 01053 } Generated on Sun May 27 2012 04:16:38 for ReactOS by
1.7.6.1
|