home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume5 / golddig / part02 / golddig1.0 / movement.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-12  |  12.0 KB  |  377 lines

  1. /* This program was written by Alexander Siegel in September of 1989   */
  2. /* at Cornell University.  It may may copied freely for private use or */
  3. /* public dispersion provided that this comment is not removed.  This  */
  4. /* program, any portion of this program, or any derivative of this     */
  5. /* program may not be sold or traded for financial gain.               */
  6.  
  7. #include <stdio.h>
  8. #include <X11/Xlib.h>
  9. #include <X11/keysym.h>
  10. #include "golddig.h"
  11.  
  12. #define MAXHOLE 100     /* Maximum number of holes at once */
  13.  
  14. int holedecay[] = {2,4,6,62,66,70,74};  /* Number of ticks after which */
  15.                                         /* hole will change form. */
  16. int numholes;           /* Total number of holes */
  17. /* Structure to describe a hole */
  18. struct {
  19.   int x,y;      /* Position of hole */
  20.   int ticmade;  /* Value of curtick when hole was created.  Used to */
  21.                 /* time hole transitions. */
  22. } holes[MAXHOLE];   /* Array for holes. */
  23.  
  24. /* Compute the allowable directions of movement out of a block.  The */
  25. /* value in the moveallow array is updated at that position. */
  26. void allow_posit(x,y)
  27. register int x,y;       /* Position of block which is to be checked */
  28. {
  29.   register int pos,code,allow;
  30.  
  31.   /* Get position of block in level array */
  32.   pos = x*ysize + y;
  33.   /* Initially assume that all directions of movement are acceptable */
  34.   allow = MOVEUP | MOVEDOWN | MOVELEFT | MOVERIGHT;
  35.   /* Prevent movement off of the level into nowhere land */
  36.   if(x == 0)
  37.     allow &= ~MOVELEFT;
  38.   if(y == 0)
  39.     allow &= ~MOVEUP;
  40.   if(x == xsize - 1)
  41.     allow &= ~MOVERIGHT;
  42.   if(y == ysize - 1)
  43.     allow &= ~MOVEDOWN;
  44.   
  45.   /* Get the control code for the block at the position */
  46.   code = fast_lookup[level[pos]].code;
  47.   /* Use the control code for space if the block is inactive */
  48.   if((code & INACTIVE) && goldleft > 0)
  49.     code = fast_lookup[SPACE].code;
  50.   /* Use the control bits for the block to reduce the allowable */
  51.   /* movement directions */
  52.   if(! (code & ULEAVE))
  53.     allow &= ~MOVEUP;
  54.   if(! (code & DLEAVE))
  55.     allow &= ~MOVEDOWN;
  56.   if(! (code & HLEAVE))
  57.     allow &= ~(MOVELEFT | MOVERIGHT);
  58.  
  59.   /* Check for blocks where you fall through */
  60.   if(y < ysize - 1 && ! (code & SUPPORT)) {
  61.     /* Get the control code for the block directly underneath */
  62.     code = fast_lookup[level[pos + 1]].code;
  63.     if((code & INACTIVE) && goldleft > 0)
  64.       code = fast_lookup[SPACE].code;
  65.     /* Check if it is possible to fall into block beneath. */
  66.     /* The STOPBAD is so that things can walk over bad guys which are */
  67.     /* stuck in a hole. */
  68.     if((code & VENTER) && ! (code & (ULEAVE | STOPBAD)))
  69.       allow &= ~(MOVELEFT | MOVERIGHT | MOVEUP);
  70.   }
  71.   
  72.   /* Check block to the left to make sure that it is possible to enter */
  73.   /* that block from the current position. */
  74.   if(x > 0) {
  75.     if(! (fast_lookup[level[pos - ysize]].code & HENTER))
  76.       allow &= ~MOVELEFT;
  77.   }
  78.   /* Check block to the right */
  79.   if(x < xsize - 1) {
  80.     if(! (fast_lookup[level[pos + ysize]].code & HENTER))
  81.       allow &= ~MOVERIGHT;
  82.   }
  83.   /* Check block above */
  84.   if(y > 0) {
  85.     if(! (fast_lookup[level[pos - 1]].code & VENTER))
  86.       allow &= ~MOVEUP;
  87.   }
  88.   /* Check block below */
  89.   if(y < ysize - 1) {
  90.     if(! (fast_lookup[level[pos + 1]].code & VENTER))
  91.       allow &= ~MOVEDOWN;
  92.   }
  93.   /* Store value back into moveallow array */
  94.   moveallow[pos] = allow;
  95. }
  96.  
  97. /* Call allow_posit on a position and all surrounding positions */
  98. void allow_area(x,y)
  99. int x,y;        /* Position to call allow_posit at */
  100. {
  101.   allow_posit(x,y);
  102.   if(x < xsize - 1)
  103.     allow_posit(x+1,y);
  104.   if(x > 0)
  105.     allow_posit(x-1,y);
  106.   if(y < ysize - 1)
  107.     allow_posit(x,y+1);
  108.   if(y > 0)
  109.     allow_posit(x,y-1);
  110. }
  111.  
  112. /* Regenerate entire moveallow array */
  113. void regen_allow()
  114. {
  115.   int x,y;
  116.  
  117.   /* Iterate through every possible position and call allow_posit on */
  118.   /* it. */
  119.   for(x=0;x<xsize;++x)
  120.     for(y=0;y<ysize;++y)
  121.       allow_posit(x,y);
  122. }
  123.  
  124. /* Form a hole. */
  125. void make_hole(x,y)
  126. int x,y;        /* Position where hole is to be formed */
  127. {
  128.   register int pos;
  129.  
  130.   /* Compute position in level array where hole is to be created */
  131.   pos = x*ysize + y;
  132.   /* Make sure that the position is inside the level array */
  133.   if(pos < 0 || pos >= xsize * ysize || y < 1 ||
  134.      /* Make sure that the block can be dug */
  135.      ! (fast_lookup[level[pos]].code & CANDIG) ||
  136.      /* Make sure that the block above it allows for digging */
  137.      /* underneath. */
  138.      ! (fast_lookup[level[pos - 1]].code & DIGUND) ||
  139.      /* Prevent the creation of too many holes */
  140.      (numholes >= MAXHOLE))
  141.     return;
  142.   /* Replace the character at the position with the first hole block */
  143.   setchar(x,y,HOLE1);
  144.   /* Add that hole to the hole array */
  145.   holes[numholes].x = x;
  146.   holes[numholes].y = y;
  147.   holes[numholes].ticmade = curtick;
  148.   numholes ++;
  149.   /* Recompute the allowable movement direction for that position and */
  150.   /* all surrounding positions */
  151.   allow_area(x,y);
  152. }
  153.  
  154. /* Fill up a hole with brick */
  155. void fill_hole(x,y)
  156. int x,y;        /* Position specifying hole */
  157. {
  158.   register int i;
  159.  
  160.   /* Look through all the holes until the right one is found */
  161.   for(i=0;i<numholes;++i)
  162.     if(holes[i].x == x && holes[i].y == y) {
  163.       /* Change the block to a brick */
  164.       setchar(holes[i].x,holes[i].y,BRICK);
  165.       /* Recompute the allowable movement for the specified position */
  166.       /* and all surrounding positions. */
  167.       allow_area(holes[i].x,holes[i].y);
  168.       /* Remove the hole from the holes array */
  169.       holes[i] = holes[numholes - 1];
  170.       numholes --;
  171.       return;
  172.     }
  173. }
  174.  
  175. /* Age all holes by one clock tick */
  176. void change_holes()
  177. {
  178.   register int i,j;
  179.  
  180.   /* Look for decaying holes.  Iterate through each hole. */
  181.   for(i=0;i<numholes;++i) {
  182.     /* Check if the hole is exactly at any transition point */
  183.     for(j=0;j<7;++j)
  184.       if(holes[i].ticmade + holedecay[j] == curtick) {
  185.         /* If it is a normal transition point, just change the block */
  186.         /* type */
  187.         if(j < 6)
  188.           setchar(holes[i].x,holes[i].y,(char) (HOLE1 + j + 1));
  189.         /* If it is the last transition point, fill the hole in */
  190.         else {
  191.           fill_hole(holes[i].x,holes[i].y);
  192.           /* Back up one hole since the hole that was at this position */
  193.           /* has now been replaced by another. */
  194.           i --;
  195.         }
  196.         break;
  197.       }
  198.   }
  199. }
  200.  
  201. /* Try to move a thing (player or bad guy) in a given direction.  The */
  202. /* structure describing the things is updated in place with the new */
  203. /* position and apparent active command.  A code value is returned */
  204. /* describing what type of movement actually occurred. */
  205. int movething(thing,newdir,num)
  206. register struct thing_s *thing;     /* Pointer to struct describing */
  207.                                     /* current state of thing */
  208. enum directs newdir;                /* New command being attempted */
  209. int num;                            /* Number of bad guy or -1 for */
  210.                                     /* player */
  211. {
  212.   register int lpos,code;
  213.  
  214.   /* Compute useful local values */
  215.   lpos = (thing->xpos >> 1)*ysize + (thing->ypos >> 1);
  216.   code = fast_lookup[level[lpos]].code;
  217.   if((code & INACTIVE) && goldleft > 0)
  218.     code = fast_lookup[SPACE].code;
  219.  
  220.   /* Complete previous initiated movement */
  221.   if((thing->xpos & 1) || (thing->ypos & 1)) {
  222.     /* Allow partial horizontal movement to complete */
  223.     if(thing->xpos & 1) {
  224.       /* Continue in old direction if trying to stop */
  225.       switch(newdir != LEFT && newdir != RIGHT ? thing->dir : newdir) {
  226.       case LEFT:
  227.         thing->xpos -= 1;
  228.         thing->dir = LEFT;
  229.         break;
  230.       default:
  231.         thing->xpos += 1;
  232.         thing->dir = RIGHT;
  233.         break;
  234.       }
  235.     }
  236.     
  237.     /* Allow partial vertical movement to complete */
  238.     if(thing->ypos & 1) {
  239.       /* Continue in old direction if trying to stop */
  240.       switch(newdir != UP && newdir != DOWN ? thing->dir : newdir) {
  241.       case UP:
  242.         if(moveallow[lpos + 1] & MOVEUP) {
  243.           thing->ypos -= 1;
  244.           thing->dir = UP;
  245.           break;
  246.         }
  247.       default:
  248.         thing->ypos += 1;
  249.         thing->dir = DOWN;
  250.         break;
  251.       }
  252.     }
  253.  
  254.     /* Pickup things which are laying around */
  255.     lpos = (thing->xpos >> 1)*ysize + (thing->ypos >> 1);
  256.     code = fast_lookup[level[lpos]].code;
  257.     if(newdir != PUTDOWN && (code & PICKUP) && thing->hold == SPACE) {
  258.       thing->hold = level[lpos];
  259.       setchar(thing->xpos >> 1,thing->ypos >> 1,SPACE);
  260.       allow_area(thing->xpos >> 1,thing->ypos >> 1);
  261.     }
  262.  
  263.     /* Activate teleporter if standing on one */
  264.     if(code & TELEPORT) {
  265.       do {
  266.         lpos ++;
  267.         thing->ypos += 2;
  268.         if(thing->ypos >> 1 == ysize) {
  269.           thing->ypos = 0;
  270.           thing->xpos += 2;
  271.           if(thing->xpos >> 1 == xsize) {
  272.             lpos = 0;
  273.             thing->xpos = 0;
  274.           }
  275.         }
  276.       } while(! (fast_lookup[level[lpos]].code & TELEPORT));
  277.     }
  278.     return(1);
  279.   } 
  280.  
  281.   /* Allow creature to fall */
  282.   if(! (code & SUPPORT) &&
  283.      (moveallow[lpos] & MOVEDOWN) &&
  284.      ! (moveallow[lpos+1] & MOVEUP) &&
  285.      (thing->hold == SPACE ||
  286.       ! (fast_lookup[thing->hold].code & STOPFALL))) {
  287.     /* Prevent falling into another thing */
  288.     if(! overlap_badguy(thing->xpos,thing->ypos+2,num)) {
  289.       /* Drop item behind if falling into a hole */
  290.       if(level[lpos] == SPACE && thing->hold != SPACE &&
  291.          (fast_lookup[level[lpos+1]].code & STOPBAD)) {
  292.         setchar(thing->xpos >> 1,thing->ypos >> 1,thing->hold);
  293.         thing->hold = SPACE;
  294.         allow_area(thing->xpos >> 1,thing->ypos >> 1);
  295.       }
  296.       /* Increment vertical position */
  297.       thing->ypos += 1;
  298.       thing->dir = STAND;
  299.       return(2);
  300.     }
  301.     /* Since there is something below, allow creature to move left or */
  302.     /* right.  This changes the moveallow array permanently and can */
  303.     /* have an interesting effect on the behavior of the bad guys. */
  304.     else {
  305.       if((thing->xpos >> 1) > 0 &&
  306.          (fast_lookup[level[lpos - ysize]].code & HENTER))
  307.         moveallow[lpos] |= MOVELEFT;
  308.       if((thing->xpos >> 1) < xsize - 1 &&
  309.          (fast_lookup[level[lpos + ysize]].code & HENTER))
  310.         moveallow[lpos] |= MOVERIGHT;
  311.     }
  312.   }
  313.  
  314.   /* Since the thing is not falling or completing a previous movement, */
  315.   /* it can start off in a new direction.  The moveallow array is used */
  316.   /* to determine which directions are possible. */
  317.   thing->dir = STAND;
  318.   switch(newdir) {
  319.   /* Put something down if that is the order */
  320.   case PUTDOWN:
  321.     if(level[lpos] == SPACE && thing->hold != SPACE) {
  322.       setchar(thing->xpos >> 1,thing->ypos >> 1,thing->hold);
  323.       thing->hold = SPACE;
  324.       allow_area(thing->xpos >> 1,thing->ypos >> 1);
  325.     }
  326.     return(3);
  327.   /* Check for possible upward movement. */
  328.   case UP:
  329.     if(moveallow[lpos] & MOVEUP) {
  330.       thing->ypos -= 1;
  331.       thing->dir = UP;
  332.     }
  333.     break;
  334.   /* Check for possible downward movement. */
  335.   case DOWN:
  336.     if(moveallow[lpos] & MOVEDOWN) {
  337.       thing->ypos += 1;
  338.       thing->dir = DOWN;
  339.     }
  340.     break;
  341.   /* Check for possible left movement. */
  342.   case LEFT:
  343.     if(moveallow[lpos] & MOVELEFT) {
  344.       thing->xpos -= 1;
  345.       thing->dir = LEFT;
  346.     }
  347.     break;
  348.   /* Check for possible right movement. */
  349.   case RIGHT:
  350.     if(moveallow[lpos] & MOVERIGHT) {
  351.       thing->xpos += 1;
  352.       thing->dir = RIGHT;
  353.     }
  354.     break;
  355.   /* Dig holes left or right if that is the command.  The make_hole */
  356.   /* command will fail if it is impossible to dig a hole at the */
  357.   /* specified location. */
  358.   case DIGLEFT:
  359.     make_hole((thing->xpos >> 1) - 1,(thing->ypos >> 1) + 1);
  360.     if(fast_lookup[thing->hold].code & NSHOVEL) {
  361.       make_hole((thing->xpos >> 1) - 2,(thing->ypos >> 1) + 1);
  362.       make_hole((thing->xpos >> 1) - 1,(thing->ypos >> 1) + 2);
  363.       make_hole((thing->xpos >> 1) - 2,(thing->ypos >> 1) + 2);
  364.     }
  365.     return(4);
  366.   case DIGRIGHT:
  367.     make_hole((thing->xpos >> 1) + 1,(thing->ypos >> 1) + 1);
  368.     if(fast_lookup[thing->hold].code & NSHOVEL) {
  369.       make_hole((thing->xpos >> 1) + 2,(thing->ypos >> 1) + 1);
  370.       make_hole((thing->xpos >> 1) + 1,(thing->ypos >> 1) + 2);
  371.       make_hole((thing->xpos >> 1) + 2,(thing->ypos >> 1) + 2);
  372.     }
  373.     return(4);
  374.   }
  375.   return(0);
  376. }
  377.