home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / rpc / mazelord / maze.c < prev    next >
C/C++ Source or Header  |  1996-01-07  |  35KB  |  1,089 lines

  1. /***********************************************************************
  2. File:   Maze.c
  3.  
  4. Abstract:
  5.  
  6.     This is the main module for MazeLords. It Contains WinMain, as well as the
  7.     WndProcs for the main modules.
  8.  
  9.  
  10. Contents:
  11.  
  12.     InSanctuary() -- determines whether a maze position is in the Sanctuary
  13.     WinMain() -- Main windows entrypoint
  14.     WndProc() -- Main window processing entrypoint
  15.     RegisterClasses() -- Register different window classes
  16.     OneTimeInit() -- Initialization done first time window created
  17.     EachTimeInit() -- Initialization done each new game
  18.     OneTimeShutdown() -- cleanup done last time window destroyed
  19.     EachTimeShutdown() -- cleanup done each time the game is STOPped.
  20.  
  21. Revision History:
  22.  
  23. ************************************************************************/
  24.  
  25. #define FULL_REDRAW 200
  26. #define IN_MAIN
  27. #include "winmaze.h"
  28. #include "mazproto.h"
  29. #include "net.h"
  30.  
  31. int ngCmdShow;
  32. HDC hHoldDC;
  33.  
  34.  
  35.  
  36. /*=====================================================================
  37. Function: InSanctuary()
  38.  
  39. Inputs: Position
  40.  
  41. Outputs: TRUE if position in Sanctuary, else FALSE
  42.  
  43. Abstract:
  44.     This function is used to determine if a given position is inside
  45.     the sanctuary. If it is, then combat isn't allowed from/to that
  46.     position, with the exception of shooting drones from outside the
  47.     sanctuary.
  48. ======================================================================*/
  49.  
  50. BOOL InSanctuary(
  51.     PositionType FAR *Pos
  52.     )
  53. {
  54.     BOOL bRet;
  55.     int iLeft,iTop;
  56.  
  57.     iLeft = 6*X_CELLS_PER_SUBGRID+1;
  58.     iTop = 7*Y_CELLS_PER_SUBGRID+1;
  59.  
  60.  
  61.     bRet = ((Pos->ix >= iLeft)&&(Pos->ix <= iLeft+2));
  62.     bRet = bRet&&((Pos->iy >= iTop)&&(Pos->iy <= iTop+2));
  63.  
  64.     return(bRet);
  65. }
  66.  
  67.  
  68.  
  69. /*=====================================================================
  70. Function: WinMain()
  71.  
  72. Inputs: Standard winmain inputs
  73.  
  74. Outputs:success
  75.  
  76. Abstract:
  77.     This is the WinMain for MazeLords. It is responsible for, among
  78.     other things, registering the windows classes, and allocating some
  79.     of the larger dynamic data structures.
  80. ======================================================================*/
  81.  
  82. int PASCAL WinMain(
  83.     HINSTANCE hInstance,
  84.     HINSTANCE hPrevInstance,
  85.     LPSTR lpszCmdLine,
  86.     int nCmdShow
  87.     )
  88. {
  89.     MSG     msg;
  90.     int     i,j,nRc;
  91.     HGLOBAL hMem;
  92.  
  93.     //
  94.     // DYNAMIC ALLOCATION OF GLOBAL VARS
  95.     //
  96.     hMem = GlobalAlloc(GHND,(MAX_DRAW_DIST*2+2+1) * sizeof(LPPOINT FAR *));
  97.     pPost = (LPPOINT FAR * FAR *) GlobalLock(hMem);
  98.     for(i=0;i<(MAX_DRAW_DIST*2+2+1);i++) {
  99.         hMem = GlobalAlloc(GHND,(MAX_DRAW_DIST+2+1)*sizeof(LPPOINT));
  100.         pPost[i] = (LPPOINT FAR *) GlobalLock(hMem);
  101.         for(j=0;j<(MAX_DRAW_DIST+2+1);j++) {
  102.             hMem = GlobalAlloc(GHND,2*sizeof(POINT));
  103.             pPost[i][j] = (LPPOINT) GlobalLock(hMem);
  104.             }
  105.         }
  106.  
  107.     hMem = GlobalAlloc(GHND,NUM_PICS * sizeof(FullPicType FAR *));
  108.     PreStretch = (FullPicType FAR * FAR *) GlobalLock(hMem);
  109.     for(i=0;i<NUM_PICS;i++) {
  110.         hMem = GlobalAlloc(GHND,MAX_DRAW_DIST * sizeof(FullPicType));
  111.         PreStretch[i] = (FullPicType FAR *) GlobalLock(hMem);
  112.         }
  113.  
  114.     hMem = GlobalAlloc(GHND,X_SIZE * sizeof(BYTE FAR *));
  115.     bMaze = (BYTE FAR * FAR *) GlobalLock(hMem);
  116.     for(i=0;i<X_SIZE;i++) {
  117.         hMem = GlobalAlloc(GHND,Y_SIZE * sizeof(BYTE));
  118.         bMaze[i] = (LPBYTE) GlobalLock(hMem);
  119.         }
  120.  
  121.     hMem = GlobalAlloc(GHND,X_SUBGRIDS_PER_GRID * sizeof(SubGridType FAR *));
  122.     Grid = (SubGridType FAR * FAR *) GlobalLock(hMem);
  123.     for(i=0;i<X_SUBGRIDS_PER_GRID;i++) {
  124.         hMem = GlobalAlloc(GHND,Y_SUBGRIDS_PER_GRID * sizeof(SubGridType));
  125.         Grid[i] = (SubGridType FAR *) GlobalLock(hMem);
  126.         }
  127.  
  128.     hMem = GlobalAlloc(GHND,NUM_SUBGRIDS * sizeof(SubGridCellsType));
  129.     SubGrids = (SubGridCellsType FAR *) GlobalLock(hMem);
  130.  
  131.  
  132.  
  133.     lstrcpy(szAppName, "MAZE");
  134.     hInst = hInstance;
  135.  
  136.     //
  137.     // We need to register the different windows and child
  138.     // windows we'll be using if this is the first instance
  139.     // of MazeLords.
  140.     //
  141.     if(!hPrevInstance) {
  142.       if ((nRc = RegisterClasses()) == -1) {
  143.         LoadString(hInst, IDS_ERR_REGISTER_CLASS, szString, sizeof(szString));
  144.         MessageBox((HWND)NULL, szString, (LPSTR)NULL, MB_ICONEXCLAMATION);
  145.         return nRc;
  146.         }
  147.       }
  148.  
  149.     //
  150.     // Display the Main window for MazeLords
  151.     //
  152.     hWndMain = CreateWindow(
  153.                   szAppName,
  154.                   "Maze Lords",
  155.                   WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX |
  156.                              WS_THICKFRAME|WS_CLIPCHILDREN|WS_OVERLAPPED,
  157.                   CW_USEDEFAULT, 0,
  158.                   CW_USEDEFAULT, 0,
  159.                   (HWND)NULL,
  160.                   (HMENU)NULL,
  161.                   hInst,
  162.                   NULL);
  163.  
  164.     OneTimeInit();
  165.  
  166.     if(hWndMain == (HWND)NULL){
  167.         LoadString(hInst, IDS_ERR_CREATE_WINDOW, szString, sizeof(szString));
  168.         MessageBox((HWND)NULL, szString, "WinMain", MB_ICONEXCLAMATION);
  169.         return IDS_ERR_CREATE_WINDOW;
  170.         }
  171.  
  172.  
  173.     ShowWindow(hWndMain, nCmdShow);
  174.     ngCmdShow = nCmdShow;
  175.  
  176.  
  177.  
  178.     while(GetMessage(&msg, (HWND)NULL, 0, 0)) {
  179.         TranslateMessage(&msg);
  180.         DispatchMessage(&msg);
  181.         }
  182.  
  183.     UnRegisterClasses();
  184.     return msg.wParam;
  185. }
  186.  
  187.  
  188. /*=====================================================================
  189. Function: Wndproc()
  190.  
  191. Inputs: Standard windows message processing entrypoint parms
  192.  
  193. Outputs:returns Success
  194.  
  195. Abstract:
  196.     This is the window procedure for the main window. It takes care of
  197.     spawning and destroying child windows, interpreting menu-item
  198.     command messages, and most of the none-movement keystrokes.
  199. ======================================================================*/
  200.  
  201. LONG FAR PASCAL WndProc(
  202.     HWND hWnd,
  203.     UINT Message,
  204.     WPARAM wParam,
  205.     LPARAM lParam
  206.     )
  207. {
  208.     HMENU           hMenu=0;
  209.     HBITMAP         hBitmap=0;
  210.     HDC             hDC,hBMDC;
  211.     PAINTSTRUCT     ps;
  212.     int             nRc=0;
  213.     INT             i,j,MazexDim,MazeyDim,TopxDim,TopyDim;
  214.     UINT            uCmdId,uCmdCmd;
  215.     HWND            hCmd;
  216.  
  217.  
  218.     switch (Message) {
  219.  
  220.  
  221.         case WM_TIMER:
  222.             if ((!UserIntCount)&&(!bDemoMode)&&(bDemoEnable)) {
  223.                 StartDemo();
  224.                 }
  225.             UserIntCount = 0;
  226.             break;
  227.  
  228.  
  229.         case WM_INITMENU:
  230.             if (bDemoMode) {
  231.                 StopDemo();
  232.                 }
  233.             UserIntCount++;
  234.             return DefWindowProc(hWnd, Message, wParam, lParam);
  235.  
  236.         case WM_COMMAND:
  237.             uCmdId = GET_WM_COMMAND_ID(wParam,lParam);
  238.             uCmdCmd = GET_WM_COMMAND_CMD(wParam,lParam);
  239.             hCmd = GET_WM_COMMAND_HWND(wParam,lParam);
  240.             hMenu = GetMenu(hWnd);
  241.  
  242.             switch (uCmdId) {
  243.  
  244.                 case IDT_NEWMAIL:
  245.                     ProcessNewMail();
  246.                     break;
  247.  
  248.                 case IDM_F_HIGHSCORES:
  249.                     bDemoEnable = FALSE;
  250.                     MessageBox((HWND)NULL,GetStringRes(IDS_HSCONOTIMPL),
  251.         GetStringRes2(IDS_HSCO),  MB_ICONHAND | MB_APPLMODAL);
  252.                     bDemoEnable = TRUE;
  253.                     break;
  254.  
  255.                 case IDM_F_NEWGAME:
  256.  
  257.                     bDemoEnable = FALSE;
  258.  
  259.                     SetCursor(LoadCursor((HINSTANCE)NULL,IDC_WAIT));
  260.  
  261.                     EachTimeInit();
  262.  
  263.                     GetClientRect(hWndMain,&rMain);
  264.  
  265.  
  266.                     MazexDim = (rMain.right - rMain.left)/2;
  267.                     MazeyDim = (rMain.bottom - rMain.top)*2/3;
  268.                     MazexDim = MazeyDim = (MazexDim < MazeyDim) ? MazexDim : MazeyDim;
  269.  
  270.                     TopxDim = (rMain.right - rMain.left)/4;
  271.                     TopyDim = (rMain.bottom - rMain.top)/3;
  272.                     TopxDim = TopyDim = (TopxDim < TopyDim) ? TopxDim : TopyDim;
  273.                     rTopView.right = rMain.right - 10;
  274.                     rTopView.bottom = rMain.bottom - 10;
  275.                     rTopView.left = rTopView.right - TopxDim;
  276.                     rTopView.top = rTopView.bottom - TopyDim;
  277.  
  278.                     rText.left = rMain.left + 10;
  279.                     rText.right = rMain.right - 10 - TopxDim - 10;
  280.                     rText.top = rMain.top + 10 + MazeyDim + 10;
  281.                     rText.bottom = rMain.bottom-10;
  282.  
  283.                     rScore.left = rMain.left + 10 + MazexDim +10;
  284.                     rScore.right = rMain.right - 10;
  285.                     rScore.top = rMain.top + 10;
  286.                     rScore.bottom = rMain.bottom - 10 - TopyDim - 10;
  287.  
  288.                     //
  289.                     // create the 3-d view window
  290.                     //
  291.                     rMaze.left = 0;rMaze.right = 0;
  292.                     rMaze.right = MazexDim;
  293.                     rMaze.bottom = MazeyDim;
  294.  
  295.                     InitMaze();
  296.                     Calc3DMaze();
  297.                     InitNetwork();
  298.  
  299.                     rMaze.left = rMain.left+10;
  300.                     rMaze.top = rMain.top +10;
  301.                     rMaze.right = rMaze.left + MazexDim;
  302.                     rMaze.bottom = rMaze.top + MazeyDim;
  303.  
  304.                     hWndMaze = CreateWindow((LPSTR) "MazeDrawWindow",
  305.                                             (LPSTR) "",
  306.                                             WS_CHILD | WS_DLGFRAME,
  307.                                             rMaze.left,rMaze.top,
  308.                                             rMaze.right - rMaze.left,
  309.                                             rMaze.bottom - rMaze.top,
  310.                                             hWndMain,
  311.                                             (HMENU) NULL,
  312.                                             hInst,
  313.                                             NULL);
  314.  
  315.                     if(hWndMaze == (HWND)NULL) {
  316.                         return IDS_ERR_CREATE_WINDOW;
  317.                         }
  318.  
  319.                     StretchBitmaps();
  320.  
  321.                     GetClientRect(hWndMaze,&rMaze);
  322.                     ShowWindow(hWndMaze, ngCmdShow);
  323.  
  324.                     //
  325.                     // Create the top-view window
  326.                     //
  327.                     hWndTopView = CreateWindow((LPSTR) "TopViewWindow",
  328.                                                NULL,
  329.                                                WS_CHILD | WS_DLGFRAME,
  330.                                                rTopView.left,rTopView.top,
  331.                                                rTopView.right - rTopView.left,
  332.                                                rTopView.bottom - rTopView.top,
  333.                                                hWndMain,
  334.                                                (HMENU)NULL,
  335.                                                hInst,
  336.                                                NULL);
  337.  
  338.                     if(hWndTopView == (HWND)NULL) {
  339.                         LoadString(hInst, IDS_ERR_CREATE_WINDOW, szString, sizeof(szString));
  340.                         MessageBox((HWND)NULL, szString, "Main", MB_ICONEXCLAMATION);
  341.                         return IDS_ERR_CREATE_WINDOW;
  342.                         }
  343.  
  344.                     GetClientRect(hWndTopView,&rTopView);
  345.                     ShowWindow(hWndTopView, ngCmdShow);
  346.  
  347.                     //
  348.                     // Create the Text window
  349.                     //
  350.                     hWndText = CreateWindow((LPSTR) "TextWindow",
  351.                                             NULL,
  352.                                             WS_CHILD | WS_DLGFRAME,
  353.                                             rText.left,rText.top,
  354.                                             rText.right - rText.left,
  355.                                             rText.bottom - rText.top,
  356.                                             hWndMain,
  357.                                             (HMENU)NULL,
  358.                                             hInst,
  359.                                             NULL);
  360.  
  361.                     if(hWndText == (HWND)NULL) {
  362.                         LoadString(hInst, IDS_ERR_CREATE_WINDOW, szString, sizeof(szString));
  363.                         MessageBox((HWND)NULL, szString, "Main", MB_ICONEXCLAMATION);
  364.                         return IDS_ERR_CREATE_WINDOW;
  365.                         }
  366.  
  367.                     GetClientRect(hWndText,&rText);
  368.                     ShowWindow(hWndText, ngCmdShow);
  369.                     PrintTextLine(GetStringRes(IDS_SANCTUARY));
  370.                     PrintTextLine(GetStringRes(IDS_SAFEZONE));
  371.  
  372.  
  373.                     //
  374.                     // Create the Score window
  375.                     //
  376.                     hWndScore = CreateWindow((LPSTR) "ScoreWindow",
  377.                                              NULL,
  378.                                              WS_CHILD | WS_DLGFRAME,
  379.                                              rScore.left,rScore.top,
  380.                                              rScore.right - rScore.left,
  381.                                              rScore.bottom - rScore.top,
  382.                                              hWndMain,
  383.                                              (HMENU) NULL,
  384.                                              hInst,
  385.                                              NULL);
  386.  
  387.                     if(hWndScore == (HWND)NULL) {
  388.                         LoadString(hInst, IDS_ERR_CREATE_WINDOW, szString, sizeof(szString));
  389.                         MessageBox((HWND)NULL, szString, "Main", MB_ICONEXCLAMATION);
  390.                         return IDS_ERR_CREATE_WINDOW;
  391.                         }
  392.  
  393.                     GetClientRect(hWndScore,&rScore);
  394.                     ShowWindow(hWndScore, ngCmdShow);
  395.  
  396.                     //
  397.                     // The game is started. reset the cursor as well.
  398.                     //
  399.                     GameStarted = TRUE;
  400.                     SetCursor(LoadCursor((HINSTANCE)NULL,IDC_ARROW));
  401.                     break;
  402.  
  403.                 case IDM_F_EXIT:
  404.                     SendMessage(hWnd,WM_CLOSE,0,0);
  405.                     break;
  406.  
  407.                 case IDM_O_NET:
  408.                     bNetworked = TRUE;
  409.                     CheckMenuItem(hMenu,IDM_O_NET,MF_CHECKED);
  410.                     CheckMenuItem(hMenu,IDM_O_LOCAL,MF_UNCHECKED);
  411.                     break;
  412.  
  413.                 case IDM_O_LOCAL:
  414.                     bNetworked = FALSE;
  415.                     CheckMenuItem(hMenu,IDM_O_NET,MF_UNCHECKED);
  416.                     CheckMenuItem(hMenu,IDM_O_LOCAL,MF_CHECKED);
  417.                     break;
  418.  
  419.                 case IDM_O_PLAYERSTRETCH:
  420.                     bPlayerPrestretch = !bPlayerPrestretch;
  421.                     CheckMenuItem(hMenu,IDM_O_PLAYERSTRETCH,
  422.                     bPlayerPrestretch?MF_CHECKED:MF_UNCHECKED);
  423.                     if (bPlayerPrestretch) {
  424.                         bDronePrestretch = TRUE;
  425.                         CheckMenuItem(hMenu,IDM_O_DRONESTRETCH,MF_CHECKED);
  426.                         }
  427.                     if (GameStarted) {
  428.                         StretchBitmaps();
  429.                         }
  430.                     break;
  431.  
  432.                 case IDM_O_DRONESTRETCH:
  433.                     bDronePrestretch = !bDronePrestretch;
  434.                     CheckMenuItem(hMenu,IDM_O_DRONESTRETCH,
  435.                               bDronePrestretch?MF_CHECKED:MF_UNCHECKED);
  436.                     if (bPlayerPrestretch) {
  437.                         bDronePrestretch = TRUE;
  438.                         CheckMenuItem(hMenu,IDM_O_DRONESTRETCH,MF_CHECKED);
  439.                         }
  440.                     if (GameStarted) {
  441.                         StretchBitmaps();
  442.                         }
  443.                     break;
  444.  
  445.                 case IDM_O_BITMAP:
  446.                     if (bBitmapDraw) {
  447.                         CheckMenuItem(hMenu,IDM_O_BITMAP,MF_UNCHECKED);
  448.                         bBitmapDraw = FALSE;
  449.                         hDC = hHoldDC;
  450.                         hHoldDC = hMazeDC;
  451.                         hMazeDC = hDC;
  452.                         }
  453.                     else {
  454.                         CheckMenuItem(hMenu,IDM_O_BITMAP,MF_CHECKED);
  455.                         bBitmapDraw = TRUE;
  456.                         if ((((HWND)hMaze3DBM) == (HWND)NULL)&&(GameStarted)) {
  457.                             hHoldDC = hMazeDC;
  458.                             GetClientRect(hWnd,&rMaze);
  459.                             hDC = GetDC(hWnd);
  460.                             if (hMazeDC != NULL) {
  461.                                 DeleteDC(hMazeDC);
  462.                             }
  463.                             hMazeDC = CreateCompatibleDC(hDC);
  464.                             if (hMaze3DBM != NULL) {
  465.                                 DeleteObject(hMaze3DBM);
  466.                             }
  467.                             hMaze3DBM = CreateCompatibleBitmap(hDC,rMaze.right-rMaze.left,
  468.                                                                rMaze.bottom-rMaze.top);
  469.                             SelectObject(hMazeDC,hMaze3DBM);
  470.                             ReleaseDC(hWnd,hDC);
  471.                             }
  472.                         else {
  473.                             hDC = hHoldDC;
  474.                             hHoldDC = hMazeDC;
  475.                             hMazeDC = hDC;
  476.                             }
  477.                         }
  478.                     break;
  479.  
  480.                 case IDM_O_PLAYERSET:
  481.                     bDemoEnable = FALSE;
  482.                     nRc = DialogBox(hInst,"PLAY_CONF_DLG",hWnd,PlayerDlg);
  483.                     bDemoEnable = TRUE;
  484.                     break;
  485.  
  486.                 case IDM_O_DRONES:
  487.                     bDemoEnable = FALSE;
  488.                     nRc = DialogBox(hInst,"DRONE_DLG", hWnd, DroneDlg);
  489.                     if (GameStarted) {
  490.                         if (uiTimer != (UINT) NULL) {
  491.                             KillTimer((HWND)NULL,uiTimer);
  492.                             }
  493.  
  494.                         if ((iNumDrones)&&(iDroneSpeed != 0)) {
  495.                             if (! (uiTimer = SetTimer((HWND)NULL,0,ONE_SECOND/iDroneSpeed,MoveDrone))) {
  496.                                 MessageBox((HWND)NULL,GetStringRes(IDS_CRETMRFAIL),GetStringRes(IDS_FATALERR),
  497.                                            MB_ICONEXCLAMATION|MB_APPLMODAL);
  498.                                 SendMessage(hWndMain,WM_CLOSE,0,0);
  499.                                 }
  500.                             }
  501.  
  502.                         InitDrones();
  503.                         }
  504.                     bDemoEnable = TRUE;
  505.                     break;
  506.  
  507.                 case IDM_O_PAUSE:
  508.                     GamePaused = ! GamePaused;
  509.                     break;
  510.  
  511.                 case IDM_F_STOP:
  512.                     if (GameStarted) {
  513.                         nRc = MessageBox((HWND)NULL, GetStringRes(IDS_ASKSTOP),
  514.                                          GetStringRes(IDS_STOP), MB_YESNO);
  515.                         //
  516.                         // If they really want to stop the game, do it...
  517.                         //
  518.                         if (nRc == IDYES) {
  519.                             SendMessage(hWndScore,WM_CLOSE,0,0);
  520.                             SendMessage(hWndText,WM_CLOSE,0,0);
  521.                             SendMessage(hWndTopView,WM_CLOSE,0,0);
  522.                             SendMessage(hWndMaze,WM_CLOSE,0,0);
  523.                             EachTimeShutdown();
  524.                             bDemoEnable = TRUE;
  525.                             }
  526.                         }
  527.  
  528.                     break;
  529.  
  530.                 case IDM_ABOUT:
  531.                     bDemoEnable = FALSE;
  532.                     nRc = DialogBox(hInst,"MDLG_ABOUT", hWnd, AboutDlg);
  533.                     bDemoEnable = TRUE;
  534.                     break;
  535.  
  536.                 default:
  537.                     return DefWindowProc(hWnd, Message, wParam, lParam);
  538.                 }
  539.             break;
  540.  
  541.  
  542.         case WM_KEYDOWN:
  543.  
  544.             if (bDemoMode) {
  545.                 StopDemo();
  546.                 }
  547.             UserIntCount++;
  548.  
  549.             switch(wParam) {
  550.  
  551.                 //
  552.                 // X = Quit the game
  553.                 //
  554.                 case 'X':
  555.                     if (!SendNetMessage(0,0,NULL,NP_LEAVINGGAME)) {
  556.                         MessageBox((HWND)NULL,GetStringRes(IDS_SNDPCKTFAIL),"WndProc",
  557.                                      MB_ICONEXCLAMATION|MB_APPLMODAL);
  558.                         }
  559.  
  560.                     SendMessage(hWndMain,WM_CLOSE,0,0);
  561.                     return(0);
  562.                     break;
  563.  
  564.                 //
  565.                 // movement messages go to the MazeWindow
  566.                 //
  567.                 case VK_SPACE:
  568.                 case VK_UP:
  569.                 case VK_LEFT:
  570.                 case VK_RIGHT:
  571.                 case VK_DOWN:
  572.                 case 'w':
  573.                 case 'W':
  574.                 case 's':
  575.                 case 'S':
  576.                     SendMessage(hWndMaze,WM_KEYDOWN,wParam,lParam);
  577.                     break;
  578.                 }
  579.             break;
  580.  
  581.         case WM_CREATE:
  582.             //
  583.             // Set timer for 30-second intervals to go into demo-mode.
  584.             //
  585.             SetTimer(hWnd,(UINT) NULL, (UINT) (30*1000),(TIMERPROC) NULL);
  586.             //
  587.             // We decide on the basis of user interaction whether to
  588.             // start demo-mode or not.
  589.             //
  590.             UserIntCount = 0;
  591.             bDemoMode = FALSE;
  592.             CheckMenuItem(hMenu,IDM_O_NET,MF_CHECKED);
  593.             CheckMenuItem(hMenu,IDM_O_LOCAL,MF_UNCHECKED);
  594.             bNetworked = TRUE;
  595.             break;
  596.  
  597.         case WM_MOVE:
  598.             break;
  599.  
  600.         case WM_SIZE:
  601.             GetClientRect(hWndMain,&rMain);
  602.  
  603.             MazexDim = (rMain.right - rMain.left)/2;
  604.             MazeyDim = (rMain.bottom - rMain.top)*2/3;
  605.             MazexDim = MazeyDim = (MazexDim < MazeyDim) ? MazexDim : MazeyDim;
  606.  
  607.             rMaze.left = rMain.left+10;
  608.             rMaze.top = rMain.top +10;
  609.             rMaze.right = rMaze.left + MazexDim;
  610.             rMaze.bottom = rMaze.top + MazeyDim;
  611.             MoveWindow(hWndMaze,rMaze.left,rMaze.top,
  612.                        rMaze.right-rMaze.left,rMaze.bottom-rMaze.top,TRUE);
  613.  
  614.             TopxDim = (rMain.right - rMain.left)/4;
  615.             TopyDim = (rMain.bottom - rMain.top)/3;
  616.             TopxDim = TopyDim = (TopxDim < TopyDim) ? TopxDim : TopyDim;
  617.             rTopView.right = rMain.right - 10;
  618.             rTopView.bottom = rMain.bottom - 10;
  619.             rTopView.left = rTopView.right - TopxDim;
  620.             rTopView.top = rTopView.bottom - TopyDim;
  621.             MoveWindow(hWndTopView,rTopView.left,rTopView.top,
  622.                        rTopView.right - rTopView.left,
  623.                        rTopView.bottom - rTopView.top,TRUE);
  624.  
  625.             rText.left = rMain.left + 10;
  626.             rText.right = rMain.right - 10 - TopxDim - 10;
  627.             rText.top = rMain.top + 10 + MazeyDim + 10;
  628.             rText.bottom = rMain.bottom-10;
  629.  
  630.             MoveWindow(hWndText,rText.left,rText.top,
  631.                        rText.right - rText.left,
  632.                        rText.bottom - rText.top,TRUE);
  633.  
  634.             rScore.left = rMain.left + 10 + MazexDim +10;
  635.             rScore.right = rMain.right - 10;
  636.             rScore.top = rMain.top + 10;
  637.             rScore.bottom = rMain.bottom - 10 - TopyDim - 10;
  638.  
  639.             MoveWindow(hWndScore,rScore.left,rScore.top,
  640.                     rScore.right - rScore.left,
  641.                     rScore.bottom - rScore.top,TRUE);
  642.             break;
  643.  
  644.         case WM_PAINT:
  645.             memset(&ps, 0x00, sizeof(PAINTSTRUCT));
  646.             hDC = BeginPaint(hWnd, &ps);
  647.  
  648.             SetBkMode(hDC, TRANSPARENT);
  649.             hBitmap = LoadBitmap(hInst,"MAZE");
  650.             hBMDC = CreateCompatibleDC(hDC);
  651.             SelectObject(hBMDC,hBitmap);
  652.             GetClientRect(hWndMain,&rMain);
  653.             //
  654.             // Fill the destination with the bitmap
  655.             //
  656.             for(i=rMain.left;i<rMain.right;i+=54) {
  657.                 for(j=rMain.top;j<rMain.bottom;j+=42) {
  658.                     BitBlt(hDC,i,j,54,42,
  659.                            hBMDC,0,0,
  660.                            SRCCOPY
  661.                           );
  662.                     }
  663.                 }
  664.             DeleteDC(hBMDC);
  665.             DeleteObject(hBitmap);
  666.  
  667.             EndPaint(hWnd, &ps);
  668.             break;
  669.  
  670.         case WM_CLOSE:
  671.             DestroyWindow(hWnd);
  672.             if (hWnd == hWndMain) {
  673.                 PostQuitMessage(0);
  674.                 EachTimeShutdown();
  675.                 OneTimeShutdown();
  676.                 }
  677.             break;
  678.  
  679.         default:
  680.             return DefWindowProc(hWnd, Message, wParam, lParam);
  681.         }
  682.  
  683.     return(0);
  684. }
  685.  
  686.  
  687.  
  688. /*=====================================================================
  689. Function:RegisterClasses()
  690.  
  691. Inputs: None
  692.  
  693. Outputs:returns Success/failure
  694.  
  695. Abstract:
  696.     This is responsible for registering the main window class and the
  697.     child window classes as well.
  698. ======================================================================*/
  699.  
  700. int RegisterClasses(
  701.     void
  702.     )
  703. {
  704.     WNDCLASS   wndclass;
  705.  
  706.  
  707.     memset(&wndclass, 0x00, sizeof(WNDCLASS));
  708.     wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
  709.     wndclass.lpfnWndProc = WndProc;
  710.     wndclass.cbClsExtra = 0;
  711.     wndclass.cbWndExtra = 0;
  712.     wndclass.hInstance = hInst;
  713.     wndclass.hIcon = LoadIcon(hInst, "MAZE");
  714.     wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
  715.     wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  716.     wndclass.lpszMenuName = szAppName;
  717.     wndclass.lpszClassName = szAppName;
  718.  
  719.     if(!RegisterClass(&wndclass)) {
  720.         return(-1);
  721.         }
  722.  
  723.     //
  724.     // Register the 3-d window class
  725.     //
  726.     wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE | CS_OWNDC | CS_BYTEALIGNWINDOW;
  727.     wndclass.lpfnWndProc = MazeWndProc;
  728.     wndclass.hIcon = (HICON)NULL;
  729.     wndclass.lpszMenuName = NULL;
  730.     wndclass.lpszClassName = (LPSTR) "MazeDrawWindow";
  731.  
  732.     if(!RegisterClass(&wndclass)) {
  733.         return(-1);
  734.         }
  735.  
  736.     //
  737.     // Register the top view window class
  738.     //
  739.     wndclass.lpfnWndProc = TopViewWndProc;
  740.     wndclass.lpszClassName = (LPSTR) "TopViewWindow";
  741.  
  742.     if(!RegisterClass(&wndclass)) {
  743.         return(-1);
  744.         }
  745.  
  746.     //
  747.     // Register the text window class
  748.     //
  749.     wndclass.lpfnWndProc = TextWndProc;
  750.     wndclass.lpszClassName = (LPSTR) "TextWindow";
  751.  
  752.     if(!RegisterClass(&wndclass)) {
  753.         return(-1);
  754.         }
  755.  
  756.     //
  757.     // Register the Score window class
  758.     //
  759.     wndclass.lpfnWndProc = ScoreWndProc;
  760.     wndclass.lpszClassName = (LPSTR) "ScoreWindow";
  761.  
  762.     if(!RegisterClass(&wndclass)) {
  763.         return(-1);
  764.         }
  765.  
  766.     return(0);
  767. }
  768.  
  769.  
  770.  
  771. /*=====================================================================
  772. Function: UnRegisterClasses
  773.  
  774. Inputs: none
  775.  
  776. Outputs:none
  777.  
  778. Abstract:
  779.     This deletes the windows classes we registered for MazeLords.
  780. ======================================================================*/
  781.  
  782. void UnRegisterClasses(
  783.     void
  784.     )
  785. {
  786.     WNDCLASS   wndclass;
  787.     memset(&wndclass, 0x00, sizeof(WNDCLASS));
  788.  
  789.     UnregisterClass(szAppName, hInst);
  790.     UnregisterClass((LPSTR) "MazeDrawWindow",hInst);
  791.     UnregisterClass((LPSTR) "TopViewWindow",hInst);
  792.     UnregisterClass((LPSTR) "TextWindow",hInst);
  793.     UnregisterClass((LPSTR) "ScoreWindow",hInst);
  794. }
  795.  
  796.  
  797.  
  798. /*=====================================================================
  799. Function: OneTimeInit()
  800.  
  801. Inputs: none
  802.  
  803. Outputs:none
  804.  
  805. Abstract:
  806.     This initialization routine is called the first time a game is started.
  807.     It reads in the subgrids, initializes the network, makes a mailslot,
  808.     and sets many of the global variables.
  809. ======================================================================*/
  810.  
  811. void OneTimeInit()
  812. {
  813.     DWORD dwScratch,dwSize,dwType;
  814.     HMENU hMenu;
  815.     BOOL bRet;
  816.     int i,j,k;
  817. #ifdef WIN32
  818.     HKEY hKey;
  819. #endif
  820.  
  821.     if (!ReadSubGrids()) {
  822.         MessageBox((HWND)NULL,GetStringRes(IDS_RDSGRDTXTFLFAIL),
  823.     GetStringRes2(IDS_INITFAIL), MB_ICONEXCLAMATION);
  824.         }
  825.  
  826.  
  827.     dwScratch = MAX_USERNAME_LENGTH;
  828.     strcpy(ptSelf.cUserName,"<A Player>");
  829.     strcpy(ptSelf.cComputerName,"MachineName");
  830.     dwSize =MAX_COMPUTERNAME_LENGTH;
  831.     ptSelf.ulID = 0;
  832.     ptSelf.iPicNum = PIC_DEFAULT;
  833.     ptSelf.iGridNum = SUBGRID_DEFAULT;
  834.  
  835.     hMenu = GetMenu(hWndMain);
  836.     EnableMenuItem(hMenu,IDM_F_STOP,MF_GRAYED);
  837.     EnableMenuItem(hMenu,IDM_O_PAUSE,MF_GRAYED);
  838.  
  839. #ifdef WIN32
  840.     if (!(bRet = GetUserName(ptSelf.cUserName,&dwScratch))) {
  841.         MessageBox((HWND)NULL,GetStringRes(IDS_GETUSRNMFAIL),
  842.     GetStringRes2(IDS_NETINIT), MB_ICONEXCLAMATION|MB_APPLMODAL);
  843.         }
  844.     dwType = REG_SZ;
  845.     RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  846.                  "SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName",
  847.                  0,
  848.                  KEY_READ,
  849.                  &hKey);
  850.     RegQueryValueEx(hKey,"ComputerName",NULL,&dwType,
  851.                     ptSelf.cComputerName,&dwSize);
  852.     ptSelf.dwPID = GetCurrentProcessId();
  853. #endif
  854.     ptSelf.ulID = MemCRC((LPSTR) &ptSelf.ulID,(int) sizeof(ptSelf));
  855.     bDemoMode = FALSE;
  856.     bDemoEnable = TRUE;
  857.     iNumDrones = 10;
  858.     iDroneSpeed = 2;
  859.     iDroneMoveAlg = 1;
  860.     bBitmapDraw = FALSE;
  861.     bPlayerPrestretch = FALSE;
  862.     bDronePrestretch = FALSE;
  863.     for(i=0;i<NUM_PICS;i++) {
  864.         for (j=0;j<MAX_DRAW_DIST;j++) {
  865.             for(k=0;k<4;k++) {
  866.                 PreStretch[i][j].P[k].hBitmap = (HBITMAP)NULL;
  867.                 PreStretch[i][j].M[k].hBitmap = (HBITMAP)NULL;
  868.                 }
  869.             }
  870.         }
  871.  
  872.     return;
  873. }
  874.  
  875.  
  876.  
  877. /*=====================================================================
  878. Function: EachTimeInit()
  879.  
  880. Inputs: none
  881.  
  882. Outputs:none
  883.  
  884. Abstract:
  885.     This function is called each time a new game is started (initially,
  886.     and any time after a STOP selection from the menu) This loads some
  887.     bitmaps, changes the state on menu-items whose validity is changed by
  888.     a game in progress, and resets some global variables.
  889. ======================================================================*/
  890.  
  891. void EachTimeInit(
  892.     void
  893.     )
  894. {
  895.     HMENU hMenu;
  896.  
  897.     hMenu = GetMenu(hWndMain);
  898.  
  899.     EnableMenuItem(hMenu,IDM_O_NET,MF_GRAYED);
  900.     EnableMenuItem(hMenu,IDM_O_LOCAL,MF_GRAYED);
  901.     EnableMenuItem(hMenu,IDM_O_PLAYERSET,MF_GRAYED);
  902.     EnableMenuItem(hMenu,IDM_F_NEWGAME,MF_GRAYED);
  903.     EnableMenuItem(hMenu,IDM_F_STOP,MF_ENABLED);
  904.     EnableMenuItem(hMenu,IDM_O_PAUSE,MF_ENABLED);
  905.     uiTimer = (UINT) NULL;
  906.     ptDrones.next = NULL;
  907.     fptPic.next = NULL;
  908.     bSelfInSanct = TRUE;
  909.  
  910.     hShotBM[0]=LoadBitmap(hInst,"SHOT1");
  911.     hShotBM[1]=LoadBitmap(hInst,"SHOT2");
  912.     hFadeBM[0]=LoadBitmap(hInst,"FADE1");
  913.     hFadeBM[1]=LoadBitmap(hInst,"FADE2");
  914.  
  915.     hMaze3DBM = (HBITMAP)NULL;
  916.     hMazeDC = (HDC)NULL;
  917.     iWhisperDist = 2;
  918.     iShoutDist = 10;
  919.     iPlayersKilled = iTimesKilled = iDronesKilled = 0;
  920.     ptSelf.iScore = iKilledByDrones = 0;
  921.     GamePaused = GameStarted = FALSE;
  922.     Scores.next = NULL;
  923.  
  924.     return;
  925. }
  926.  
  927.  
  928.  
  929. /*=====================================================================
  930. Function: OneTimeShutdown()
  931.  
  932. Inputs: none
  933.  
  934. Outputs:none
  935.  
  936. Abstract:
  937.     This function does NOTHING right now. It'll be called at the very
  938.     end of everything.
  939. ======================================================================*/
  940.  
  941. void OneTimeShutdown(
  942.     void
  943.     )
  944. {
  945.     return;
  946. }
  947.  
  948.  
  949.  
  950. /*=====================================================================
  951. Function: EachTimeShutdown()
  952.  
  953. Inputs: none
  954.  
  955. Outputs:none
  956.  
  957. Abstract:
  958.     This function is called each time a STOP command is selected and
  959.     approved. It changes menu items to the correct state, changes some
  960.     global state variables, and notifies the network that we're quitting
  961.     the game.
  962. ======================================================================*/
  963.  
  964. void EachTimeShutdown(
  965.     void
  966.     )
  967. {
  968.     HMENU hMenu;
  969.  
  970.     hMenu = GetMenu(hWndMain);
  971.  
  972.     DeleteObject(hShotBM[0]);
  973.     DeleteObject(hShotBM[1]);
  974.     DeleteObject(hFadeBM[0]);
  975.     DeleteObject(hFadeBM[1]);
  976.     DeleteObject(hMaze3DBM);
  977.     DeleteDC(hMazeDC);
  978.  
  979.  
  980.     EnableMenuItem(hMenu,IDM_O_NET,MF_ENABLED);
  981.     EnableMenuItem(hMenu,IDM_O_LOCAL,MF_ENABLED);
  982.     EnableMenuItem(hMenu,IDM_O_PLAYERSET,MF_ENABLED);
  983.     EnableMenuItem(hMenu,IDM_F_STOP,MF_GRAYED);
  984.     EnableMenuItem(hMenu,IDM_O_PAUSE,MF_GRAYED);
  985.     EnableMenuItem(hMenu,IDM_F_NEWGAME,MF_ENABLED);
  986.  
  987.  
  988.     if (!SendNetMessage(0,0,NULL,NP_LEAVINGGAME)) {
  989.         MessageBox((HWND)NULL,GetStringRes(IDS_SNDQUITPCKTFAIL),"EachTimeShutDown",
  990.                    MB_ICONEXCLAMATION|MB_APPLMODAL);
  991.         }
  992.  
  993.     bNetworked = TRUE;
  994.     GameStarted = FALSE;
  995.  
  996.     iNumDrones = 0;
  997.     iDroneSpeed = 0;
  998.     iDroneMoveAlg = 1;
  999.     bBitmapDraw = FALSE;
  1000.  
  1001.     return;
  1002. }
  1003.  
  1004.  
  1005.  
  1006.  
  1007. /*=====================================================================
  1008. Function: StartDemo()
  1009.  
  1010. Inputs: none
  1011.  
  1012. Outputs:none
  1013.  
  1014. Abstract:
  1015.     This function is responsible for causing MazeLords to enter Demo
  1016.     mode.
  1017. ======================================================================*/
  1018.  
  1019. void StartDemo(
  1020.     void
  1021.     )
  1022. {
  1023.     bDemoMode = TRUE;
  1024.     SetWindowText(hWndMain,GetStringRes(IDS_DEMOMODE));
  1025.     SendMessage(hWndMain,WM_COMMAND,MAKELONG(IDM_F_NEWGAME,0),(LPARAM)NULL);
  1026.     return;
  1027. }
  1028.  
  1029.  
  1030.  
  1031. /*=====================================================================
  1032. Function: StopDemo()
  1033.  
  1034. Inputs: none
  1035.  
  1036. Outputs:none
  1037.  
  1038. Abstract:
  1039.     This function is responsible for ending the mazelords demo and
  1040.     putting it into a state that the user can interact with.
  1041. ======================================================================*/
  1042.  
  1043.  
  1044. void StopDemo(
  1045.     void
  1046.     )
  1047. {
  1048.     bDemoMode = FALSE;
  1049.     SendMessage(hWndScore,WM_CLOSE,0,0);
  1050.     SendMessage(hWndText,WM_CLOSE,0,0);
  1051.     SendMessage(hWndTopView,WM_CLOSE,0,0);
  1052.     SendMessage(hWndMaze,WM_CLOSE,0,0);
  1053.     EachTimeShutdown();
  1054.     iNumDrones  = 10;
  1055.     iDroneSpeed = 2;
  1056.     bDemoEnable = TRUE;
  1057.     UserIntCount++;
  1058.     SetWindowText(hWndMain,"Maze Lords");
  1059.     return;
  1060. }
  1061.  
  1062. /******************************************************************************\
  1063. *
  1064. *  FUNCTION:    GetStringRes (int id INPUT ONLY)
  1065. *
  1066. *  COMMENTS:    Load the resource string with the ID given, and return a
  1067. *               pointer to it.  Notice that the buffer is common memory so
  1068. *               the string must be used before this call is made a second time.
  1069. *
  1070. \******************************************************************************/
  1071.  
  1072. LPTSTR   GetStringRes (int id)
  1073. {
  1074.   static TCHAR buffer[MAX_PATH];
  1075.  
  1076.   buffer[0]=0;
  1077.   LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  1078.   return buffer;
  1079. }
  1080.  
  1081. LPTSTR   GetStringRes2 (int id)
  1082. {
  1083.   static TCHAR buffer[MAX_PATH];
  1084.  
  1085.   buffer[0]=0;
  1086.   LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  1087.   return buffer;
  1088. }
  1089.