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 / drones.c < prev    next >
C/C++ Source or Header  |  1996-01-07  |  12KB  |  417 lines

  1. /***********************************************************************
  2. File:   Drones.c
  3.  
  4.  
  5. Abstract:
  6.  
  7.     This file contains the functions which are associated with moving and
  8.     drawing drones.
  9.  
  10.  
  11. Contents:
  12.  
  13.     DeletePlayer() -- Free a record of type PlayerType
  14.     NewPlayer() -- Create & initialize a record of type PlayerType
  15.     RandRange() -- return a random number in a given range
  16.     InitDrones() -- Add/remove drone entries from the list of drones
  17.     MoveDrone() -- Timer callback to change drone positions in data struct
  18.  
  19.  
  20. ************************************************************************/
  21.  
  22. #include <stdlib.h>
  23. #include "winmaze.h"
  24. #include "mazproto.h"
  25. #include <mmsystem.h>
  26.  
  27.  
  28.  
  29. /*=====================================================================
  30. Function: DeletePlayer()
  31.  
  32. Inputs: Pointer to record to delete
  33.  
  34. Outputs: Returns pointer to next record in list
  35.  
  36. Abstract:
  37.     Returns pointer to next element to facilitate maintenance of
  38.     linked lists
  39. ======================================================================*/
  40.  
  41. PlayerType FAR *DeletePlayer(
  42.     PlayerType FAR *ptTrav
  43.     )
  44. {
  45.     PlayerType FAR *ptHold;
  46.     HGLOBAL hMem;
  47.  
  48.     ptHold = NULL;
  49.     if (ptTrav != NULL) {
  50.         ptHold = ptTrav->next;
  51.         hMem = (HGLOBAL) GlobalHandle(SELECTOROF( ptTrav));
  52.         GlobalUnlock(hMem);
  53.         GlobalFree(hMem);
  54.         }
  55.  
  56.     return(ptHold);
  57. }
  58.  
  59.  
  60. /*=====================================================================
  61. Function: NewPlayer()
  62.  
  63. Inputs: Data elements of PlayerType element to be created
  64.  
  65. Outputs: Pointer to newly created & initialize PlayerType record
  66.  
  67. Abstract:
  68.     Needs no explanation
  69. ======================================================================*/
  70.  
  71. PlayerType FAR *NewPlayer(
  72.     unsigned long ulID,     // Unique identifier for this player struct
  73.     DWORD dwPID,            // process id of window
  74.     LPSTR cUserName,        // Name of the player
  75.     LPSTR cComputerName,    // Name of the computer player is on
  76.     int ix,                 // Maze X- coordinate of player
  77.     int iy,                 // Maze Y- coordinate of player
  78.     BYTE Facing,            // Facing of player in maze
  79.     int iScore,             // Points player is reporting
  80.     int iPicNum,            // Picture number to use for player
  81.     int iGridNum,           // Home grid #
  82.     int iGridxPos,          // Home grid x-position (in grid coordinates
  83.     int iGridyPos,          // Home grid y-position (in grid coordinates
  84.     PlayerType FAR *next    // for linked list maintenance
  85.     )
  86. {
  87.     PlayerType FAR *ptRet;
  88.     HGLOBAL hMem;
  89.  
  90.     hMem = GlobalAlloc(GHND,sizeof(PlayerType));
  91.     ptRet = (PlayerType FAR *) GlobalLock(hMem);
  92.  
  93.     if (ptRet == NULL) {
  94.         MessageBox((HWND) NULL,GetStringRes(IDS_MALLOCFAILABT),"NewPlayer",
  95.                MB_APPLMODAL|MB_ICONEXCLAMATION);
  96.         PostMessage(hWndMain,WM_CLOSE,0,0);
  97.         }
  98.     else {
  99.         ptRet->ulID = ulID;
  100.         ptRet->dwPID = dwPID;
  101.         lstrcpy(ptRet->cUserName,cUserName);
  102.         lstrcpy(ptRet->cComputerName,cComputerName);
  103.         ptRet->Pos.ix = ix;
  104.         ptRet->Pos.iy = iy;
  105.         ptRet->Pos.Facing = Facing;
  106.         ptRet->Drawn = FALSE;
  107.         ptRet->iScore = iScore;
  108.         ptRet->iPicNum = iPicNum;
  109.         ptRet->iGridNum = iGridNum;
  110.         ptRet->pGridLoc.x = iGridxPos;
  111.         ptRet->pGridLoc.y = iGridyPos;
  112.  
  113.         ptRet->next = next;
  114.         }
  115.  
  116.     return(ptRet);
  117. }
  118.  
  119.  
  120.  
  121. /*=====================================================================
  122. Function: RandRange()
  123.  
  124. Inputs: Low, high end of range return value should be in
  125.  
  126. Outputs: returns number between iLow and iHigh inclusive
  127.  
  128. Abstract:
  129.     Since this is using rand() it is not so random for a new process.
  130. ======================================================================*/
  131.  
  132. int RandRange(
  133.     int iLow,
  134.     int iHigh
  135.     )
  136. {
  137.     float f;
  138.  
  139.     f = ((float) rand())/((float) RAND_MAX);
  140.  
  141.     return((int) (iLow+f*(iHigh - iLow + 1)));
  142. }
  143.  
  144.  
  145.  
  146. /*=====================================================================
  147. Function: InitDrones()
  148.  
  149. Inputs: Globals only
  150.  
  151. Outputs: none
  152.  
  153. Abstract:
  154.     Performs PART of drone initialization whenever # of drones or their
  155.     speed is changed. This will add or delete drones from the drone list,
  156.     as required.
  157. ======================================================================*/
  158.  
  159. void InitDrones(
  160.     )
  161. {
  162.     int i,iCurNumDrones;
  163.     BYTE b;
  164.     PlayerType FAR *ptTrav;
  165.     char buff[20];
  166.  
  167.  
  168.     b = NORTH;
  169.  
  170.     //
  171.     // If the number of drones has changed, but drones were
  172.     // already active, we need to take a different course of
  173.     // action, ie add or delete drones from active drones,
  174.     // rather than creating completely new ones.
  175.     //
  176.  
  177.     //
  178.     // Find number of drones currently active.
  179.     //
  180.     iCurNumDrones = 0;
  181.     ptTrav = &ptDrones;
  182.     while (ptTrav->next != NULL) {
  183.         iCurNumDrones++;
  184.         ptTrav = ptTrav->next;
  185.         }
  186.  
  187.     //
  188.     // read in/ remove the drone bitmaps, as necessary
  189.     //
  190.     if (iNumDrones > 0) {
  191.         AddPic(PIC_DRONE);
  192.         }
  193.     else {
  194.         DelPic(PIC_DRONE);
  195.         }
  196.  
  197.     //
  198.     // If more drones have been added, we need to create them
  199.     //
  200.     for(i=iCurNumDrones;i<iNumDrones;i++) {
  201.         sprintf(buff,GetStringRes(IDS_FMT_DRONE),i+1);
  202.         ptTrav->next = NewPlayer(i,i,buff,ptSelf.cComputerName,
  203.                     RandRange(5*X_CELLS_PER_SUBGRID,8*X_CELLS_PER_SUBGRID-1),
  204.                     RandRange(7*Y_CELLS_PER_SUBGRID,8*Y_CELLS_PER_SUBGRID-1),
  205.                     b,0,PIC_DRONE,0,0,0,ptTrav->next);
  206.         b = (BYTE) ((b*2 > 0x8) ? 0x1 : b*2);
  207.         }
  208.  
  209.     //
  210.     // Or, delete drones as needed
  211.     //
  212.     for(i=iNumDrones; i < iCurNumDrones;i++) {
  213.         ptDrones.next = DeletePlayer(ptDrones.next);
  214.         }
  215.  
  216.     return;
  217. }
  218.  
  219.  
  220.  
  221. /*=====================================================================
  222. Function: MoveDrone()
  223.  
  224. Inputs: Ignored except for hWnd, handle to current window
  225.  
  226. Outputs:returns success/failure
  227.  
  228. Abstract:
  229.     This is a timer callback function which modifies the position of the
  230.     drones in their data structures. After their positions have been changed
  231.     in their record, a message is sent to the 3-d window telling it that
  232.     drones need to be redrawn.
  233. ======================================================================*/
  234.  
  235. LRESULT CALLBACK MoveDrone(
  236.     HWND hWnd,
  237.     UINT wMsg,
  238.     UINT idTimer,
  239.     DWORD dwTime
  240.     )
  241. {
  242.     int x,y;
  243.     BYTE b1,b2,dForward,dBack,dLeft,dRight;
  244.     BOOL blocked;
  245.     PlayerType FAR *ptTrav;
  246.     PositionType ptPos;
  247.     char cBuff[132];
  248.     LPRECT rUpd;
  249.     HANDLE hMem;
  250.     static DWORD dwCallCount=0;
  251.  
  252.     dwCallCount++;
  253.  
  254.     //
  255.     // If we're in demo mode, use this callback to move US!
  256.     //
  257.     if (bDemoMode) {
  258.  
  259.         x=ptSelf.Pos.ix;
  260.         y=ptSelf.Pos.iy;
  261.         dForward = ptSelf.Pos.Facing;
  262.         dBack = BACK_TO_ABS(dForward);
  263.         dLeft = LEFT_TO_ABS(dForward);
  264.         dRight = RIGHT_TO_ABS(dForward);
  265.         b1 = bMaze[x][y];
  266.         b2 = bMaze[ADJ_X(x,dForward)][ADJ_Y(y,dForward)];
  267.         blocked = FALSE;
  268.         if ((b1&dForward)||(b2&dBack)) {
  269.             blocked = TRUE;
  270.             b2 = bMaze[ADJ_X(x,dRight)][ADJ_Y(y,dRight)];
  271.             if ((b1&dLeft)||(b2&dRight)) {
  272.                 b2 = bMaze[ADJ_X(x,dLeft)][ADJ_Y(y,dLeft)];
  273.                 if ((b1&dLeft)||(b2&dRight)) {
  274.                     x = RIGHT;
  275.                     }
  276.                 else {
  277.                     x = LEFT;
  278.                     }
  279.                 }
  280.             else {
  281.                 x = RIGHT;
  282.                 }
  283.             }
  284.         else {
  285.             x = FORWARD;
  286.             }
  287.  
  288.         y = RandRange(1,11);
  289.  
  290.         switch (y) {
  291.             case 8:
  292.                 x = LEFT;
  293.                 break;
  294.             case 9:
  295.                 x = RIGHT;
  296.                 break;
  297.             case 10:
  298.                 x = FORWARD;
  299.                 break;
  300.             case 11:
  301.                 x = BACK;
  302.                 break;
  303.             }
  304.  
  305.         switch (x) {
  306.             case LEFT:
  307.                 PostMessage(hWndMaze,WM_KEYDOWN,VK_LEFT,0);
  308.                 break;
  309.             case RIGHT:
  310.                 PostMessage(hWndMaze,WM_KEYDOWN,VK_RIGHT,0);
  311.                 break;
  312.             case FORWARD:
  313.                 PostMessage(hWndMaze,WM_KEYDOWN,VK_UP,0);
  314.                 break;
  315.             }
  316.  
  317.         if ((RandRange(1,3) == 3)&&(!blocked)) {
  318.             PostMessage(hWndMaze,WM_KEYDOWN,VK_SPACE,0);
  319.             }
  320.         }
  321.  
  322.     hMem = GlobalAlloc(GHND,sizeof(RECT));
  323.     rUpd = (LPRECT) GlobalLock(hMem);
  324.     if (rUpd == NULL) {
  325.         MessageBox((HWND)NULL,GetStringRes(IDS_RECTALLOCFAIL),"MoveDrone",
  326.                MB_APPLMODAL);
  327.         PostMessage(hWndMain,WM_CLOSE,0,0);
  328.         }
  329.  
  330.     rUpd->right = rMaze.left;
  331.     rUpd->left = rMaze.right;
  332.     rUpd->top = rMaze.bottom;
  333.     rUpd->bottom = rMaze.top;
  334.  
  335.     ptTrav = &ptDrones;
  336.     while ((ptTrav->next != NULL)&&(!GamePaused)) {
  337.         //
  338.         // Only use every 2nd drone move in demo mode
  339.         //
  340.         if (bDemoMode && (dwCallCount % 2)) {
  341.             break;
  342.             }
  343.  
  344.         ptTrav = ptTrav->next;
  345.  
  346.         if (ptTrav->Drawn) {
  347.             rUpd->right = (rUpd->right > ptTrav->rDrawn.right) ? rUpd->right : ptTrav->rDrawn.right;
  348.             rUpd->left = (rUpd->left < ptTrav->rDrawn.left) ? rUpd->left : ptTrav->rDrawn.left;
  349.             rUpd->top = (rUpd->top < ptTrav->rDrawn.top) ? rUpd->top : ptTrav->rDrawn.top;
  350.             rUpd->bottom = (rUpd->bottom > ptTrav->rDrawn.bottom) ? rUpd->bottom : ptTrav->rDrawn.bottom;
  351.             ptTrav->Drawn=FALSE;
  352.             }
  353.         x=ptTrav->Pos.ix;
  354.         y=ptTrav->Pos.iy;
  355.         dForward = ptTrav->Pos.Facing;
  356.         dBack = BACK_TO_ABS(dForward);
  357.         dLeft = LEFT_TO_ABS(dForward);
  358.         dRight = RIGHT_TO_ABS(dForward);
  359.         ptPos.ix = x;
  360.         ptPos.iy = y;
  361.         ptPos.Facing = dForward;
  362.         b1 = bMaze[x][y];
  363.         b2 = bMaze[ADJ_X(x,dForward)][ADJ_Y(y,dForward)];
  364.         if ((b1&dForward)||(b2&dBack)) {
  365.             b2 = bMaze[ADJ_X(x,dLeft)][ADJ_Y(y,dLeft)];
  366.             if ((b1&dLeft)||(b2&dRight)) {
  367.                 b2 = bMaze[ADJ_X(x,dRight)][ADJ_Y(y,dRight)];
  368.                 if ((b1&dRight)||(b2&dLeft)) {
  369.                     ptPos.Facing = LEFT_TO_ABS(ptTrav->Pos.Facing);
  370.                     }
  371.                 else {
  372.                     ptPos.Facing = RIGHT_TO_ABS(ptTrav->Pos.Facing);
  373.                     }
  374.                 }
  375.             else {
  376.                 ptPos.Facing = LEFT_TO_ABS(ptTrav->Pos.Facing);
  377.                 }
  378.             }
  379.         else {
  380.             if (RandRange(1,10) == 1) {
  381.                 ptPos.Facing = LEFT_TO_ABS(ptTrav->Pos.Facing);
  382.                 }
  383.             else {
  384.                 if (RandRange(1,10) == 1) {
  385.                     ptPos.Facing = RIGHT_TO_ABS(ptTrav->Pos.Facing);
  386.                     }
  387.                 else {
  388.                     ptPos.ix = ADJ_X(ptTrav->Pos.ix,dForward);
  389.                     ptPos.iy = ADJ_Y(ptTrav->Pos.iy,dForward);
  390.                     }
  391.                 }
  392.             }
  393.  
  394.         ptTrav->Pos = ptPos;
  395.  
  396.         //
  397.         // If the drone has homed in on us, we are dead!
  398.         //
  399.         if ((!InSanctuary(&ptSelf.Pos))&&
  400.             (ptSelf.Pos.ix == ptPos.ix)&&(ptSelf.Pos.iy == ptPos.iy)
  401.            ) {
  402.             sprintf(cBuff,GetStringRes(IDS_FMT_RUNDOWN),ptTrav->cUserName);
  403.             PrintTextLine(cBuff);
  404.             ptSelf.iScore -=(iDroneSpeed) ? 36/iDroneSpeed/iDroneSpeed : 72;
  405.             KillSelf();
  406.             SendNetMessage(0,0,NULL,NP_SCORE);
  407.             iKilledByDrones++;
  408.             break;
  409.             }
  410.         }
  411.  
  412.     PostMessage(hWndMaze,WM_COMMAND,IDM_DRAWDRONES,(DWORD) rUpd);
  413.  
  414.     return(0);
  415. }
  416.  
  417.