home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / WINDOWS / GAMES / MINES / MINES.C < prev    next >
C/C++ Source or Header  |  1993-12-01  |  20KB  |  753 lines

  1. /************************************************************************/
  2. /*                A N N O T A T E                */
  3. /************************************************************************/
  4.  
  5. /*...vMines:0:*/
  6. /*...vMines\46\def:0:*/
  7. /*...vMines\46\rc:0:*/
  8. /*...vMines\46\dlg:0:*/
  9. /*...vmines\46\h:0:*/
  10.  
  11. /*...sInclude Files:0:*/
  12. /************************************************************************/
  13. /*            I N C L U D E   F I L E S            */
  14. /************************************************************************/
  15.  
  16. #include    <string.h>
  17. #include    <stdio.h>
  18. #include    <stdlib.h>
  19. #define        NOMINMAX
  20. #include    <windows.h>
  21. #include    "mines.h"
  22. /*...e*/
  23. /*...sVariables:0:*/
  24. /************************************************************************/
  25. /*            E X T E R N A L   V A R I A B L E S        */
  26. /************************************************************************/
  27.  
  28. typedef    struct    {
  29.             int    dummy ;
  30.         }    SETUPDATA ;
  31. SETUPDATA    SetUpData ;
  32.  
  33. HANDLE        hInst ;            /* Instance handle        */
  34. HANDLE        hAccel ;        /* Accelerator table handle    */
  35. HWND        hWnd ;
  36.  
  37. char        out[100] ;        /* Debugging variable        */
  38. char        szAppName[]="Mines" ;    /* Application Name        */
  39. char        szProfile[]="Number" ;
  40. char        szChildAppName[]=
  41.             "ChildMines" ;
  42.  
  43. typedef    struct
  44.     {
  45.     RECT    rect ;
  46.     WORD    mine ;
  47.     } MINE_STRUCT ;
  48.  
  49. #define    MAX_X_MINES    16
  50. #define    MAX_Y_MINES    16
  51.  
  52. MINE_STRUCT    minefield[MAX_X_MINES][MAX_Y_MINES] ;    /* The Minefield        */
  53.  
  54. #define    NO_MINE        0x0000
  55. #define    MINE        0x8000
  56.  
  57. #define    VISITED        0x0300
  58. #define    THINK_OK    0x0200
  59. #define    THINK_MINE    0x0100
  60. #define    NOT_SURE    0x0000
  61. #define    INV_MINE    0x0400
  62. #define    INV_OK        0x0500
  63. #define    PAINT_MASK    0x0700
  64.  
  65. #define    INC_THINK    0x0100
  66. #define    MAX_THINK    0x0200
  67.  
  68. #define    NOT_VISITED    0x0000
  69. #define    FILLED        0x2000
  70. #define    HERE        0x1000
  71. #define    HERE_MASK    0xEFFF
  72. #define    MINES_AROUND    0x000F
  73.  
  74. WORD    NoMines = 30 ;
  75. BOOL    InGame = FALSE ;
  76.  
  77. #define    WM_CREATE_MINES        WM_USER+1
  78. #define    WM_NEW_GAME        WM_CREATE_MINES+1
  79. #define    WM_HIT_MINE        WM_NEW_GAME+1
  80. #define    WM_REACHED_END        WM_HIT_MINE+1
  81. #define    WM_SHOW_MINES        WM_REACHED_END+1
  82. #define    WM_SET_NO_OF_MINES    WM_SHOW_MINES+1
  83.  
  84. int    px,py ;     /* player coordinates */
  85. /*...e*/
  86.  
  87. /*...sCountMines\40\\41\\9\Count the mines around a single point:0:*/
  88. WORD    CountMines (int x, int y)
  89.  
  90. {
  91.     int    i,j,total = 0 ;
  92.  
  93.     if ( minefield[x][y].mine & MINE )
  94.         return (0) ;
  95.     for ( i = -1 ; i < 2 ; i++ )
  96.         for ( j = -1 ; j < 2 ; j++ )
  97.             if ( (x+i) >= 0 && (x+i) < MAX_X_MINES &&
  98.                  (y+j) >= 0 && (y+j) < MAX_Y_MINES && !(i == 0 && j == 0) )
  99.                 if ( minefield[x+i][y+j].mine & MINE )
  100.                     total++ ;
  101.     return (total) ;
  102. }
  103.  
  104. /*...e*/
  105. /*...sAmINearby\40\\41\\9\\9\Return TRUE if I am nearby:0:*/
  106. BOOL    AmINearby (int x, int y)
  107.  
  108. {
  109.     int    i,j,total = 0 ;
  110.  
  111.     for ( i = -1 ; i < 2 ; i++ )
  112.         for ( j = -1 ; j < 2 ; j++ )
  113.             if ( (x+i) >= 0 && (x+i) < MAX_X_MINES &&
  114.                  (y+j) >= 0 && (y+j) < MAX_Y_MINES && !(i == 0 && j == 0) )
  115.                 if ( minefield[x+i][y+j].mine & HERE )
  116.                     return (TRUE) ;
  117.     return (FALSE) ;
  118. }
  119.  
  120. /*...e*/
  121. /*...sShowAsMany\40\\41\\9\Show as many of the mines as I can from a certain point:0:*/
  122. BOOL    ShowAsMany (HWND hWnd, int x, int y)
  123.  
  124. {
  125.     int    i,j ;
  126.  
  127.     if ( (minefield[x][y].mine & MINES_AROUND) || (minefield[x][y].mine & MINE) )
  128.         return (FALSE) ;
  129.     for ( i = -1 ; i < 2 ; i++ )
  130.         for ( j = -1 ; j < 2 ; j++ )
  131.             if ( ((x+i) >= 0) && ((x+i) < MAX_X_MINES) &&
  132.                  ((y+j) >= 0) && ((y+j) < MAX_Y_MINES) &&
  133.                   !((i == 0) && (j == 0)) )
  134.             {
  135.                 if ( !(minefield[x+i][y+j].mine & MINE) &&
  136.                      ((minefield[x+i][y+j].mine & VISITED) != VISITED)  )
  137.                 {
  138.                          minefield[x+i][y+j].mine |= VISITED ;
  139.                          InvalidateRect (hWnd,&minefield[x+i][y+j].rect,FALSE) ;
  140.                     if ( !(minefield[x+i][y+j].mine & MINES_AROUND) )
  141.                         ShowAsMany (hWnd, x+i, y+j) ;
  142.                 }
  143.                 else
  144.                          minefield[x+i][y+j].mine |= VISITED ;
  145.             }
  146.     return (FALSE) ;
  147. }
  148.  
  149. /*...e*/
  150. /*...sMineFloodFill\40\\41\\9\Check to see if a minefield is completable:0:*/
  151. void    MineFloodFill (HWND hWnd, int x, int y)
  152.  
  153. {
  154.     int    i,j ;
  155.  
  156.     if ( x < 0 || y < 0 || x >= MAX_X_MINES || y >= MAX_Y_MINES )
  157.         return ;
  158.     if ( minefield[x][y].mine & MINE+FILLED )
  159.         return ;
  160.     minefield[x][y].mine |= FILLED ;
  161. /*    InvalidateRect (hWnd, &minefield[x][y].rect, TRUE) ;
  162.     UpdateWindow (hWnd) ;
  163. */    for ( i = -1 ; i < 2 ; i++)
  164.         for ( j = -1 ; j < 2 ; j++ )
  165.                 MineFloodFill (hWnd, x+i, y+j) ;
  166. }
  167.  
  168. /*...e*/
  169. /*...sCanWeDoIt\40\\41\\9\\9\Fire off Flood fill and check result:0:*/
  170. BOOL    CanWeDoIt (HWND hWnd)
  171.  
  172. {
  173.     MineFloodFill (hWnd, 0, 0) ;
  174.     if ( minefield[MAX_X_MINES-1][MAX_Y_MINES-1].mine & FILLED )
  175.         return (TRUE) ;
  176.     else
  177.         return (FALSE) ;
  178. }
  179.  
  180. /*...e*/
  181.  
  182. /*...sMinesAboutProc\40\\41\\9\Show about window:0:*/
  183. BOOL    FAR PASCAL    MinesAboutProc(HWND hWnd, unsigned message,
  184.                     WORD wParam, LONG lParam )
  185.  
  186. {
  187.     if ( message == WM_COMMAND )
  188.     {
  189.         EndDialog (hWnd, TRUE) ;
  190.         return (TRUE) ;
  191.     }
  192.     else
  193.         return (FALSE) ;
  194. }
  195. /*...e*/
  196. /*...sMinesNoProc\40\\41\:0:*/
  197. BOOL    FAR PASCAL    MinesNoProc(HWND hWnd, unsigned message,
  198.                     WORD wParam, LONG lParam )
  199.  
  200. {
  201.     WORD    fred ;
  202.     switch (message)
  203.     {
  204. /*...sWM_INITDIALOG:8:*/
  205. case WM_INITDIALOG:
  206.     sprintf (out, "%d", NoMines) ;
  207.     SetDlgItemText (hWnd, IDD_NO_MINES, out) ;
  208.     SendMessage (GetDlgItem (hWnd, IDD_NO_MINES), EM_SETSEL, 0,MAKELONG(0,32767)) ;
  209.     SetFocus(GetDlgItem (hWnd, IDD_NO_MINES)) ;
  210.     return (FALSE) ;
  211. /*...e*/
  212. /*...sWM_COMMAND:8:*/
  213. case WM_COMMAND:
  214.     switch (wParam)
  215.     {
  216.     case IDD_OK:
  217.         GetDlgItemText (hWnd, IDD_NO_MINES, out, 10) ;
  218.         fred = atoi(out) ;
  219.         if ( fred < 30 )
  220.         {
  221.             MessageBox (hWnd, "Must be at least 30 mines!", szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  222.             return (TRUE) ;
  223.         }
  224.         if ( fred > 160 )
  225.         {
  226.             MessageBox (hWnd, "No more than 160 mines!", szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  227.             return (TRUE) ;
  228.         }
  229.         NoMines = fred ;
  230.         EndDialog (hWnd,TRUE) ;
  231.         return (TRUE) ;
  232.     case IDD_CANCEL:
  233.         EndDialog (hWnd, FALSE) ;
  234.         return (TRUE) ;
  235.     default:
  236.         return (FALSE) ;
  237.     }
  238.     break ;
  239. /*...e*/
  240. /*...sdefault:8:*/
  241. default:
  242.     return (FALSE) ;
  243. /*...e*/
  244.     }
  245.     return (FALSE) ;
  246. }
  247. /*...e*/
  248. /*...sMessage processing \45\ Main Window:0:*/
  249. /************************************************************************/
  250. /*   T H E   O V E R L A P P I N G   W I N D O W   P R O C E D U R E    */
  251. /************************************************************************/
  252.  
  253. /*    Every message for this window is delivered right here        */
  254.  
  255. long    FAR PASCAL    MinesWndProc (HWND hWnd,unsigned message,
  256.                      WORD wParam, LONG lParam)
  257.  
  258. {
  259.     int        x,y ;        /* Loop for filling square */
  260.     RECT        tRect ;
  261.     HDC        hDC,hMemDC ;
  262.     PAINTSTRUCT    ps ;
  263.     WORD        MineLoop ;
  264.     static    HBITMAP    hMineBit,hOKBit,hVisitedBit,hAtBit,hRectBit,hWrongBit ;
  265.     static    WORD    XOfs, YOfs ;
  266.     TEXTMETRIC    tm ;
  267.     HCURSOR        hCursor ;
  268.     BOOL        flag,first ;
  269.     FARPROC        lpproc ;
  270.     int        iOldMode ;
  271.     switch (message)
  272.     {
  273. /*...sWM_CREATE:8:*/
  274. /* If the annotation item is being created, then bring up a dialog box asking
  275.    for relevant information.
  276. */
  277.  
  278. case WM_CREATE:
  279.     srand(LOWORD (GetCurrentTime())) ;
  280.     for ( x = 0 ; x < MAX_X_MINES ; x++ )
  281.         for ( y = 0 ; y < MAX_Y_MINES ; y++ )
  282.         {
  283.             minefield[x][y].rect.top    = y*16    ;
  284.             minefield[x][y].rect.bottom = y*16+16 ;
  285.             minefield[x][y].rect.left   = x*16 ;
  286.             minefield[x][y].rect.right  = x*16+16 ;
  287.             minefield[x][y].mine        = NO_MINE ;
  288.         }
  289.     hMineBit    = LoadBitmap (hInst, "AMine") ;
  290.     hOKBit      = LoadBitmap (hInst, "AOK") ;
  291.     hVisitedBit = LoadBitmap (hInst, "AVisit") ;
  292.     hAtBit      = LoadBitmap (hInst, "AAt") ;
  293.     hRectBit    = LoadBitmap (hInst, "ARect") ;
  294.     hWrongBit   = LoadBitmap (hInst, "AWrong") ;
  295.     hDC = GetDC (hWnd) ;
  296.     GetTextMetrics (hDC, &tm) ;
  297.     ReleaseDC (hWnd, hDC) ;
  298.     XOfs = (16-tm.tmAveCharWidth) / 2 ;
  299.     YOfs = (16-tm.tmHeight) / 2 ;
  300.     NoMines = GetProfileInt(szAppName,szProfile,30) ;
  301.     if ( (NoMines < 30) || (NoMines > 160) )
  302.         NoMines = 30 ;
  303.     SendMessage (hWnd, WM_SET_NO_OF_MINES, 0, 0L) ;
  304.     PostMessage (hWnd, WM_COMMAND, IDM_NEW_GAME, 0L) ;
  305.     break ;
  306. /*...e*/
  307. /*...sWM_DESTROY:8:*/
  308. case WM_DESTROY:
  309.     DeleteObject (hMineBit) ;
  310.     DeleteObject (hOKBit) ;
  311.     DeleteObject (hVisitedBit) ;
  312.     DeleteObject (hAtBit) ;
  313.     DeleteObject (hRectBit) ;
  314.     DeleteObject (hWrongBit) ;
  315.     PostQuitMessage (0) ;
  316.     break ;
  317. /*...e*/
  318. /*...sWM_COMMAND:8:*/
  319. case WM_COMMAND:
  320.     switch (wParam)
  321.     {
  322. /*...sIDM_NEW_GAME:16:*/
  323. case IDM_NEW_GAME:
  324.     PostMessage (hWnd, WM_CREATE_MINES, 0, 0L) ;
  325.     break ;
  326. /*...e*/
  327. /*...sIDM_QUIT:16:*/
  328. case    IDM_QUIT:
  329.     PostMessage (hWnd, WM_CLOSE, 0, 0L) ;
  330.     break ;
  331. /*...e*/
  332. /*...sIDM_NO_MINES:16:*/
  333. case IDM_NO_MINES:
  334.     lpproc = MakeProcInstance ((FARPROC) MinesNoProc, hInst) ;
  335.     if ( DialogBox (hInst, "NUMBERMINES", hWnd, lpproc) )
  336.     {
  337.         SendMessage (hWnd, WM_SET_NO_OF_MINES, 0, 0L) ;
  338.         PostMessage (hWnd, WM_COMMAND, IDM_NEW_GAME, 0L) ;
  339.     }
  340.     FreeProcInstance (lpproc) ;
  341.     break ;
  342. /*...e*/
  343. /*...sIDM_ABOUT:16:*/
  344. case IDM_ABOUT:
  345.     lpproc = MakeProcInstance ((FARPROC) MinesAboutProc, hInst) ;
  346.     DialogBox (hInst, "ABOUTMINES", hWnd, lpproc) ;
  347.     FreeProcInstance (lpproc) ;
  348.     break ;
  349. /*...e*/
  350.     }
  351.  
  352.     break ;
  353. /*...e*/
  354. /*...sWM_LBUTTONDOWN:8:*/
  355. case WM_LBUTTONDOWN:
  356.     if ( !InGame )
  357.     {
  358.         MessageBeep(0) ;
  359.         break ;
  360.     }
  361.     x = LOWORD(lParam) / 16 ;
  362.     y = HIWORD(lParam) / 16 ;
  363.     if ( AmINearby (x,y) || (minefield[x][y].mine & VISITED) == VISITED)
  364.     {
  365.         if ( (minefield[x][y].mine & VISITED ) == THINK_MINE )
  366.             MessageBeep(0) ;
  367.         else
  368.         {
  369.             flag = minefield[x][y].mine & VISITED ;
  370.             minefield[px][py].mine &= HERE_MASK ;
  371.             minefield[x][y].mine |= HERE+VISITED ;
  372.             InvalidateRect (hWnd, &minefield[px][py].rect, FALSE) ;
  373.             InvalidateRect (hWnd, &minefield[x][y].rect, FALSE) ;
  374.             if ( flag != VISITED )
  375.             {
  376.                 ShowAsMany (hWnd, x, y) ;
  377.                 UpdateWindow (hWnd) ;
  378.             }
  379.             px = x ;
  380.             py = y ;
  381.             if ( minefield[x][y].mine & MINE ) 
  382.             {
  383.                 SendMessage (hWnd, WM_HIT_MINE, 0, 0L) ;
  384.                 break ;
  385.             }
  386.             if ( (minefield[MAX_X_MINES-1][MAX_Y_MINES-1].mine & VISITED) == VISITED )
  387.                 SendMessage (hWnd, WM_REACHED_END, 0, 0L) ;
  388.         }
  389.     }
  390.     else
  391.         MessageBeep(0) ;
  392.     break ;
  393. /*...e*/
  394. /*...sWM_RBUTTONDOWN:8:*/
  395. case WM_RBUTTONDOWN:
  396.     if ( !InGame )
  397.     {
  398.         MessageBeep(0) ;
  399.         break ;
  400.     }
  401.     x = LOWORD(lParam) / 16 ;
  402.     y = HIWORD(lParam) / 16 ;
  403.     if ( (minefield[x][y].mine & VISITED) == VISITED )
  404.     {
  405.         MessageBeep(0) ;
  406.         break ;
  407.     }
  408.     MineLoop = minefield[x][y].mine & VISITED ;
  409.     MineLoop += INC_THINK ;
  410.     if ( MineLoop > MAX_THINK )
  411.         MineLoop = 0 ;
  412.     minefield[x][y].mine = (minefield[x][y].mine & (~VISITED)) | MineLoop ;
  413.     InvalidateRect (hWnd, &minefield[x][y].rect, FALSE) ;
  414.     break ;
  415. /*...e*/
  416. /*...sWM_PAINT:8:*/
  417. case WM_PAINT:
  418.     hDC = BeginPaint (hWnd, &ps) ;
  419.     iOldMode = GetBkMode(hDC) ;
  420.     SetBkMode(hDC,TRANSPARENT) ;
  421.     for ( x = 0 ; x < MAX_X_MINES ; x++ )
  422.         for (y = 0 ; y < MAX_Y_MINES ; y++ )
  423.         {
  424. /*            tRect = minefield[x][y].rect ; */
  425.             if ( IntersectRect (&tRect, &minefield[x][y].rect,&ps.rcPaint) )
  426.             switch (minefield[x][y].mine & PAINT_MASK)
  427.             {
  428. /*...sVISITED:32:*/
  429. case VISITED:
  430.     /* Display no of mines around */
  431.  
  432.     hMemDC = CreateCompatibleDC (hDC) ;
  433.     if ( (minefield[x][y].mine & HERE) )
  434.         SelectObject (hMemDC, hAtBit) ;
  435.     else
  436.         SelectObject (hMemDC, hVisitedBit) ;
  437.     BitBlt (hDC, x*16, y*16, 16, 16, hMemDC, 0, 0, SRCCOPY) ;
  438.     if ( minefield[x][y].mine & MINES_AROUND )
  439.     {
  440.         sprintf (out,"%d",minefield[x][y].mine & MINES_AROUND) ;
  441.         TextOut (hDC, x*16+XOfs, y*16+YOfs, out, strlen(out)) ;
  442.     }
  443.     DeleteDC (hMemDC) ;
  444.     break ;
  445. /*...e*/
  446. /*...sTHINK_OK:32:*/
  447. case THINK_OK:
  448.     hMemDC = CreateCompatibleDC (hDC) ;
  449.     SelectObject (hMemDC, hOKBit) ;
  450.     BitBlt (hDC, x*16, y*16, 16, 16, hMemDC, 0, 0, SRCCOPY) ;
  451.     DeleteDC (hMemDC) ;
  452.     break ;
  453. /*...e*/
  454. /*...sTHINK_MINE:32:*/
  455. case THINK_MINE:
  456.     hMemDC = CreateCompatibleDC (hDC) ;
  457.     SelectObject (hMemDC, hMineBit) ;
  458.     BitBlt (hDC, x*16, y*16, 16, 16, hMemDC, 0, 0, SRCCOPY) ;
  459.     DeleteDC (hMemDC) ;
  460.     break ;
  461. /*...e*/
  462. /*...sNOT_SURE:32:*/
  463. case NOT_SURE:
  464.     hMemDC = CreateCompatibleDC (hDC) ;
  465.     SelectObject (hMemDC, hRectBit) ;
  466.     BitBlt (hDC, x*16, y*16, 16, 16, hMemDC, 0, 0, SRCCOPY) ;
  467.     DeleteDC (hMemDC) ;
  468.     break ;
  469. /*...e*/
  470. /*...sINV_OK:32:*/
  471. case INV_OK:
  472.     hMemDC = CreateCompatibleDC (hDC) ;
  473.     SelectObject (hMemDC, hWrongBit) ;
  474.     BitBlt (hDC, x*16, y*16, 16, 16, hMemDC, 0, 0, SRCCOPY) ;
  475.     DeleteDC (hMemDC) ;
  476.     break ;
  477. /*...e*/
  478. /*...sINV_MINE:32:*/
  479. case INV_MINE:
  480.     hMemDC = CreateCompatibleDC (hDC) ;
  481.     SelectObject (hMemDC, hWrongBit) ;
  482.     BitBlt (hDC, x*16, y*16, 16, 16, hMemDC, 0, 0, SRCCOPY) ;
  483.     DeleteDC (hMemDC) ;
  484.     break ;
  485.  
  486. /*...e*/
  487.             }
  488.         }
  489.     SetBkMode(hDC,iOldMode) ;
  490.     EndPaint (hWnd, &ps) ;
  491.     break ;
  492. /*...e*/
  493. /*...sWM_CREATE_MINES:8:*/
  494. case WM_CREATE_MINES:
  495.  
  496.     SetCapture (hWnd) ;
  497.     hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
  498.     first = TRUE ;
  499.  
  500.     do
  501.     {
  502.     for ( x = 0 ; x < MAX_X_MINES ; x++ )
  503.         for ( y = 0 ; y < MAX_Y_MINES ; y++ )
  504.             minefield[x][y].mine = NO_MINE ;
  505.         if ( !first )
  506.             MessageBeep(0) ;
  507.         first = FALSE ;
  508.         MineLoop = NoMines ;
  509.         while ( MineLoop )
  510.         {
  511.             x = rand() & 15 ;
  512.             y = rand() & 15 ;
  513.             if ( (minefield[x][y].mine == NO_MINE) && !((x <= 1) && (y <= 1)) )
  514.             {
  515.                 minefield[x][y].mine = MINE ;
  516.                 MineLoop-- ;
  517.             }
  518.         }
  519.     minefield[MAX_X_MINES-1][MAX_Y_MINES-1].mine = NO_MINE ;
  520. /*    InvalidateRect (hWnd, NULL, FALSE) ;
  521.     SendMessage (hWnd, WM_SHOW_MINES, 0, 0L) ;
  522. */    }
  523.     while ( !CanWeDoIt(hWnd) ) ;
  524.     for ( x = 0 ; x < MAX_X_MINES ; x++ )
  525.         for ( y = 0 ; y < MAX_Y_MINES ; y++ )
  526.             minefield[x][y].mine |= CountMines(x,y) ;
  527.     minefield[0][0].mine = HERE+VISITED ;
  528.     InvalidateRect (hWnd, NULL, FALSE) ;
  529.     ShowAsMany (hWnd, 0, 0) ;
  530.     UpdateWindow (hWnd) ;
  531.     SetCursor (hCursor) ;
  532.     ReleaseCapture() ;
  533.     px = py = 0 ;
  534.     InGame = TRUE ;
  535.     break ;
  536. /*...e*/
  537. /*...sWM_HIT_MINE:8:*/
  538. case WM_HIT_MINE:
  539.     hDC = GetDC (hWnd) ;
  540.     GetClientRect (hWnd, &tRect) ;
  541.     MessageBeep(0) ;
  542.     InvertRect (hDC, &tRect) ;
  543.     MessageBeep(0) ;
  544.     InvertRect (hDC, &tRect) ;
  545.     MessageBeep(0) ;
  546.     ReleaseDC (hWnd, hDC) ;
  547.     SendMessage (hWnd, WM_SHOW_MINES, 0, 0L) ;
  548.     InGame = FALSE ;
  549.     break ;
  550. /*...e*/
  551. /*...sWM_REACHED_END:8:*/
  552. case WM_REACHED_END:
  553.     SendMessage (hWnd, WM_SHOW_MINES, 0, 0L) ;
  554.     MessageBox (hWnd, "You made it!", "Congratualtions", MB_OK) ;
  555.     InGame = FALSE ;
  556.     break ;
  557. /*...e*/
  558. /*...sWM_SHOW_MINES:8:*/
  559. case WM_SHOW_MINES:
  560.     minefield[px][py].mine &= HERE_MASK ;
  561.     for (x = 0 ; x < MAX_X_MINES ; x++ )
  562.         for (y = 0 ; y < MAX_Y_MINES ; y++ )
  563.             if ( (minefield[x][y].mine & MINE) &&
  564.                  (minefield[x][y].mine & VISITED) == THINK_OK )
  565.             {
  566.                 minefield[x][y].mine &= (~PAINT_MASK) ;
  567.                 minefield[x][y].mine |= INV_MINE ;
  568.                 InvalidateRect (hWnd, &minefield[x][y].rect, FALSE) ;
  569.             }
  570.             else
  571.             if ( !(minefield[x][y].mine & MINE) &&
  572.                  (minefield[x][y].mine & VISITED) == THINK_MINE )
  573.             {
  574.                 minefield[x][y].mine &= (~PAINT_MASK) ;
  575.                 minefield[x][y].mine |= INV_OK ;
  576.                 InvalidateRect (hWnd, &minefield[x][y].rect, FALSE) ;
  577.             }
  578.             else
  579.             if ( minefield[x][y].mine & MINE )
  580.             {
  581.                 minefield[x][y].mine &= (~VISITED) ;
  582.                 minefield[x][y].mine |= THINK_MINE ;
  583.                 InvalidateRect (hWnd, &minefield[x][y].rect, FALSE) ;
  584.             }
  585.     UpdateWindow (hWnd) ;
  586.     break ;
  587. /*...e*/
  588. /*...sWM_SET_NO_OF_MINES:8:*/
  589. case WM_SET_NO_OF_MINES:
  590.     sprintf (out,"%d",NoMines) ;
  591.     WriteProfileString(szAppName,szProfile,out) ;
  592.     sprintf (out, "Playing with %d mines!", NoMines) ;
  593.     SetWindowText (hWnd, out) ;
  594.     break ;
  595. /*...e*/
  596. /*...sdefault:8:*/
  597. default:
  598.     return (DefWindowProc (hWnd, message, wParam, lParam)) ;
  599. /*...e*/
  600.     }
  601.  
  602.     return (0L) ;
  603. }
  604.  
  605. /*...e*/
  606.  
  607. /*...sInitialisation:0:*/
  608. /************************************************************************/
  609. /*            I N I T I A L I S A T I O N            */
  610. /************************************************************************/
  611.  
  612. /*...sInitialise for first instance:0:*/
  613. /************************************************************************/
  614. /*    F I R S T - I N S T A N C E   I N I T I A L I S A T I O N    */
  615. /************************************************************************/
  616.  
  617. /*
  618.     Done first time only. Normally register the window class.
  619. */
  620.  
  621. void    InitMinesFirst (HANDLE hInstance)
  622.  
  623. {
  624.     WNDCLASS    wcMinesClass ;
  625.  
  626.     wcMinesClass.lpszClassName    = szAppName ;
  627.     wcMinesClass.hInstance        = hInstance  ;
  628.     wcMinesClass.lpfnWndProc    = MinesWndProc ;
  629.     wcMinesClass.hCursor        = LoadCursor (NULL, IDC_ARROW) ;
  630.     wcMinesClass.hIcon        = LoadIcon (hInstance, "MINESICON") ;
  631.     wcMinesClass.lpszMenuName    = "MinesMenu" ;
  632.     wcMinesClass.hbrBackground    = GetStockObject (WHITE_BRUSH) ;
  633.     wcMinesClass.style        = CS_HREDRAW | CS_VREDRAW ;
  634.     wcMinesClass.cbClsExtra        = 0 ;
  635.     wcMinesClass.cbWndExtra        = 0 ;
  636.  
  637.     RegisterClass (&wcMinesClass) ;
  638.     
  639. }
  640.  
  641. /*...e*/
  642. /*...sInitialise for 2nd or greater instance:0:*/
  643. /************************************************************************/
  644. /*    A D D E D - I N S T A N C E   I N I T I A L I S A T I O N    */
  645. /************************************************************************/
  646.  
  647.  
  648. /*
  649.     Done for every instance other than the first. Normally copy the
  650.     results of the previous instance's initialisation.
  651. */
  652.  
  653. void    InitMinesAdded (HANDLE hInstance,HANDLE hPrevInstance)
  654.  
  655. {
  656.     GetInstanceData (hPrevInstance, (PSTR)&SetUpData, sizeof(SETUPDATA)) ;
  657. }
  658.  
  659. /*...e*/
  660. /*...sInitialise for every instance:0:*/
  661. /************************************************************************/
  662. /*    E V E R Y - I N S T A N C E   I N I T I A L I S A T I O N    */
  663. /************************************************************************/
  664.  
  665. /*
  666.         Done for each instance of the application.
  667.  
  668. Normally :-
  669.  
  670.     Create the window    (Cause an instance of the window to exist)
  671.     Show the window        (Cause the window to be drawn on the screen)
  672.     Update the window    (Cause the paint proc to be executed (now))
  673. */
  674.  
  675. void    InitMinesEvery (HANDLE hInstance, int cmdShow)
  676.  
  677. {
  678.     hInst = hInstance ;
  679.  
  680.     hWnd = CreateWindow(szAppName,        /* Window Class Name    */
  681.                 NULL,
  682.                 WS_OVERLAPPED | WS_DLGFRAME |
  683.                 WS_CAPTION | WS_SYSMENU |
  684.                 WS_MINIMIZEBOX,    /* Window Style        */
  685.                             /* Type of window    */
  686.                 CW_USEDEFAULT,    /* x - Default location */
  687.                 CW_USEDEFAULT,    /* y            */
  688.                 16*MAX_X_MINES+1,
  689.                 16*MAX_Y_MINES+1+GetSystemMetrics(SM_CYCAPTION)+
  690.                 GetSystemMetrics(SM_CYMENU),
  691.                             /* cy - Half Size*/
  692.                 NULL,        /* No parent for this w.*/
  693.                 NULL,        /* Use the class menu   */
  694.                 hInstance,        /* Who created this w.    */
  695.                 NULL        /* No params to pass on    */
  696.                ) ;
  697.     ShowWindow (hWnd,cmdShow) ;
  698.     UpdateWindow (hWnd) ;
  699. }
  700. /*...e*/
  701.  
  702. void    InitMines (HANDLE hInstance,HANDLE hPrevInstance,int cmdShow) 
  703.  
  704. {
  705.     if (!hPrevInstance)
  706.         InitMinesFirst (hInstance) ;
  707.     else
  708.         InitMinesAdded (hInstance, hPrevInstance) ;
  709.  
  710.     InitMinesEvery (hInstance, cmdShow) ;
  711. }
  712.  
  713. /*...e*/
  714. /*...sClosing Routine:0:*/
  715. /************************************************************************/
  716. /*            C L O S I N G   R O U T I N E            */
  717. /************************************************************************/
  718.  
  719. void    CloseMines (HANDLE hInstance)
  720.  
  721. {
  722. /* Perform any special processing before shutting down the window    */
  723.  
  724. }
  725.  
  726. /*...e*/
  727.  
  728. /*...sMain Procedure:0:*/
  729. /************************************************************************/
  730. /*            M A I N   P R O C E D U R E            */
  731. /************************************************************************/
  732.  
  733. int    PASCAL    WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  734.              LPSTR lpszCmdLine,int  cmdShow)
  735.  
  736. {
  737.     MSG    msg ;            /* Temp buffer to hold message    */
  738.  
  739.     InitMines (hInstance, hPrevInstance, cmdShow) ; /* Initialise*/
  740.  
  741.     hAccel = LoadAccelerators (hInst, "MinesAccel") ;
  742.     while (GetMessage(&msg, NULL, 0, 0))
  743.         if ( !TranslateAccelerator (hWnd, hAccel, &msg) )
  744.         {
  745.             TranslateMessage(&msg) ;
  746.             DispatchMessage(&msg) ;
  747.         }
  748.     CloseMines (hInstance) ;
  749.     return (msg.wParam) ;
  750. }
  751.  
  752. /*...e*/
  753.