home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d02xx / d0216.lha / Wanderer / src / game.c < prev    next >
C/C++ Source or Header  |  1989-06-02  |  23KB  |  970 lines

  1. #include "wand_head.h"
  2.  
  3. #define viable(x,y) (((screen[y][x] == ' ') || (screen[y][x] == ':') ||\
  4.     (screen[y][x] == '@') || (screen[y][x] == '+') ||\
  5.     (screen[y][x] == 'S')) && (y >= 0) &&\
  6.     (x >= 0) && (y < NOOFROWS) && (x < ROWLEN))
  7.  
  8. /* typedef struct mon_rec        *//* M002 struct mon_rec moved    */
  9. /*     {                *//* to header file because it     */
  10. /*     int x,y,mx,my;            *//* is needed by save.c    */
  11. /*     char under;            */
  12. /*     struct mon_rec *next,*prev;    */
  13. /*     };                */
  14.  
  15. typedef struct { int d[2]; } direction;
  16.  
  17. #ifdef    LINT_ARGS    /* M001 */
  18. direction new_direction(int, int, int, int);
  19. #else
  20. direction new_direction();
  21. #endif
  22.  
  23. extern int jumpscreen();
  24.  
  25. extern int check();
  26.  
  27. extern void showpass();
  28.  
  29. extern void draw_symbol();
  30.  
  31. extern void display();
  32.  
  33. extern int fall();
  34.  
  35. extern void map();
  36.  
  37. extern void redraw_screen();
  38. extern int debug_disp;
  39. extern int edit_mode;
  40. extern int saved_game;
  41. extern char screen[NOOFROWS][ROWLEN+1];
  42.  
  43. /* Add a spirit to the chain */
  44. /* Maintain a doubly linked list to make reuse possible.
  45.    tail_of_list is *NOT* the last monster allocated, but
  46.    the last monster alloted to a screen.  start_of_list
  47.    is a dummy entry to ease processing. last_of_list
  48.    is the last entry allocated. */
  49. static struct mon_rec start_of_list = {0,0,0,0,0,NULL,NULL};
  50.  
  51. struct mon_rec *tail_of_list;
  52. struct mon_rec *last_of_list;
  53.  
  54. struct mon_rec *make_monster(x,y)
  55. int x,y;
  56. {
  57. char *malloc();
  58. #define MALLOC (struct mon_rec *)malloc(sizeof(struct mon_rec))
  59. struct mon_rec *monster;
  60. if(tail_of_list->next == NULL)
  61.     {
  62.     if((last_of_list = MALLOC) == NULL)
  63.     return NULL;
  64.     tail_of_list->next = last_of_list;
  65.     last_of_list->prev = tail_of_list;
  66.     last_of_list->next = NULL;
  67.     }
  68. monster = tail_of_list = tail_of_list->next;
  69. monster->x = x;
  70. monster->y = y;
  71. monster->mx = 1;      /* always start moving RIGHT. (fix later)  */
  72. monster->my = 0;
  73. monster->under = ' ';
  74. return monster;
  75. }
  76.  
  77. /* 'follow lefthand wall' algorithm for baby monsters */
  78.  
  79. direction new_direction(x,y,bx,by)
  80. int x,y,bx,by;
  81. {
  82. direction out;
  83. if(viable((x+by),(y-bx)))
  84.     {
  85.     out.d[0] = by;
  86.     out.d[1] = -bx;
  87.     return out;
  88.     }
  89. if(viable((x+bx),(y+by)))
  90.     {
  91.     out.d[0] = bx;
  92.     out.d[1] = by;
  93.     return out;
  94.     }
  95. if(viable((x-by),(y+bx)))
  96.     {
  97.     out.d[0] = -by;
  98.     out.d[1] = bx;
  99.     return out;
  100.     }
  101. if(viable((x-bx),(y-by)))
  102.     {
  103.     out.d[0] = -bx;
  104.     out.d[1] = -by;
  105.     return out;
  106.     }
  107. out.d[0] = -bx;
  108. out.d[1] = -by;
  109. return out;
  110. }
  111.  
  112. /* tell player if monster exists */
  113. show_monster(yes)
  114. int yes;
  115. {
  116. if(yes)           
  117.     draw_symbol(48,10,'M');
  118. else
  119.   {
  120.     move(48,10);
  121.     addstr("   ");
  122.     move(48,11);
  123.     addstr("   ");
  124.   }
  125. }
  126.  
  127. /* Actual game function - Calls fall() to move
  128.        boulders and arrows recursively */
  129. /* Variable explaination :
  130.     All the var names make sense to ME, but some people think them a bit confusing... :-) So heres an explanation.
  131.    x,y : where you are
  132.    nx,ny : where you're trying to move to
  133.    sx,sy : where the screen window on the playing area is
  134.    mx,my : where the monster is
  135.    tx,ty : teleport arrival
  136.    bx,by : baby monster position
  137.    nbx,nby : where it wants to be
  138.    lx,ly : the place you left when teleporting
  139.    nf : how many diamonds youve got so far
  140.    new_disp : the vector the baby monster is trying
  141. */
  142.  
  143. char *playscreen(num,score,bell,maxmoves,keys)
  144. int  *num, maxmoves,
  145.      *bell,
  146.      *score;
  147. char keys[10];
  148. {
  149. int  x,y,nx,ny,deadyet =0,
  150.      sx = -1,sy = -1,tx = -1,ty = -1,lx = 0,ly = 0,mx = -1,my = -1,
  151.      bx, by, nbx, nby, tmpx,tmpy,
  152.      newnum,
  153.      max_score = 250,
  154.      diamonds = 0, nf = 0,hd ,vd ,xdirection,ydirection;
  155. char (*frow)[ROWLEN+1] = screen,
  156.      ch,
  157.      buffer[25];
  158. static char     howdead[25];    /* M001 can't use auto var for return value */
  159. direction new_disp;
  160. struct mon_rec *monster,*current;
  161.  
  162. tail_of_list = &start_of_list;
  163.  
  164. for(x=0;x<=ROWLEN;x++)
  165.     for(y=0;y<NOOFROWS;y++)
  166.     {
  167.     if((screen[y][x] == '*')||(screen[y][x] == '+'))
  168.         {
  169.         diamonds++;
  170.         max_score += 10;
  171.         if(screen[y][x] == '+')
  172.         max_score += 20;
  173.         }
  174.         if(screen[y][x] == 'A')     /* note teleport arrival point &  */
  175.         {                       /* replace with space */
  176.         tx = x;
  177.         ty = y;
  178.          screen[y][x] = ' ';
  179.         }
  180.         if(screen[y][x] == '@')
  181.         {
  182.         sx = x;
  183.         sy = y;
  184.         }
  185.         if(screen[y][x] == 'M')     /* Put megamonster in */
  186.         {
  187.         mx = x;
  188.         my = y;
  189.         }
  190.     if(screen[y][x] == 'S')     /* link small monster to pointer chain */
  191.         {
  192.         if((monster = make_monster(x,y)) == NULL)
  193.         {
  194.         strcpy(howdead,"running out of memory");
  195.         return howdead;
  196.         }
  197.         if(!viable(x,y-1))     /* make sure its running in the correct */
  198.         {                  /* direction..                          */
  199.         monster->mx = 1;
  200.         monster->my = 0;
  201.         }
  202.         else if(!viable(x+1,y))
  203.         {
  204.         monster->mx = 0;
  205.         monster->my = 1;
  206.         }
  207.         else if(!viable(x,y+1))
  208.         {
  209.         monster->mx = -1;
  210.         monster->my = 0;
  211.         }
  212.         else if(!viable(x-1,y))
  213.         {
  214.         monster->mx = 0;
  215.         monster->my = -1;
  216.         }
  217.         }
  218.         if(screen[y][x] == '-')
  219.             screen[y][x] = ' ';
  220.         };
  221. x=sx;
  222. y=sy;
  223. if((x == -1)&&(y == -1))              /* no start position in screen ? */
  224.     {
  225.     strcpy(howdead,"a screen design error");
  226.     return(howdead);
  227.     }
  228.  
  229. update_game:    /* M002  restored game restarts here    */
  230.  
  231. move(0,48);
  232. (void) addstr("Score\t   Diamonds");
  233. move(1,48);
  234. (void) addstr("\tFound\tTotal");
  235. move(3,48);
  236. (void) sprintf(buffer,"%d\t %d\t %d  ",*score,nf,diamonds);
  237. (void) addstr(buffer);
  238. move(6,48);
  239. (void) sprintf(buffer,"Current screen %d",*num);
  240. (void) addstr(buffer);
  241. if(maxmoves != 0)
  242. (void) sprintf(buffer,"Moves remaining = %d   ",maxmoves);
  243. else
  244. {
  245.     (void) strcpy(buffer,"     Unlimited moves     ");
  246.     maxmoves = -1;
  247. };
  248. move(15,48);
  249. (void) addstr(buffer);
  250. show_monster(mx != -1);        /* tell player if monster exists */
  251.  
  252. if(!debug_disp)
  253.     display(sx,sy,frow,*score);
  254. else
  255.     map(frow);
  256.  
  257. /* ACTUAL GAME FUNCTION - Returns method of death in string  */
  258.  
  259. while(deadyet == 0)
  260. {
  261. #ifdef MOUSE
  262. /* get next keyboard character or mouse click (AMIGA) */
  263. if ((ch = mouseorkey()) == MOUSE) {
  264.     int mouserow, mousecol, deltax, deltay;
  265. #define UP    keys[0]
  266. #define DOWN    keys[1]
  267. #define LEFT    keys[2]
  268. #define RIGHT    keys[3]
  269.     /* convert mouse coordinates to the keystroke in that direction */
  270.     getmouse(&mouserow, &mousecol);
  271.     /* adjust mouse coordinates to the game window */
  272.     if (debug_disp) {
  273.         --mouserow;
  274.         --mousecol;
  275.     } else {
  276.             mouserow = mouserow/2+sy-3;
  277.             mousecol = mousecol/3+sx-5;
  278.     }
  279.     deltax = mousecol - x;
  280.     deltay = mouserow - y;
  281.     if (deltax == 0 && deltay == 0) {
  282.         ch = ' ';    /* no change */
  283.     } else if (deltax >= 0 && deltay >= 0) {
  284.         if (deltax > deltay) ch = RIGHT; else ch = DOWN;
  285.     } else if (deltax >= 0 && deltay <= 0) {
  286.         if (deltax > abs(deltay)) ch = RIGHT; else ch = UP;
  287.     } else if (deltax <= 0 && deltay >= 0) {
  288.         if (abs(deltax) > deltay) ch = LEFT; else ch = DOWN;
  289.     } else {
  290.         if (abs(deltax) > abs(deltay)) ch = LEFT; else ch = UP;
  291.     }
  292. }
  293. #else
  294. /* get next keyboard character */
  295. ch = getch();
  296. #endif
  297.  
  298. nx=x;
  299. ny=y;
  300.  
  301. if((ch == keys[3]) && (x <(ROWLEN-1)))  /* move about - but thats obvious */
  302.     nx++;
  303. if((ch == keys[2]) && (x > 0))
  304.     nx--;
  305. if((ch == keys[1]) && (y <(NOOFROWS-1)))
  306.     ny++;
  307. if((ch == keys[0]) && (y > 0))
  308.         ny--;
  309. #ifndef AMIGA
  310. if(ch == '1')                  /* Add or get rid of that awful sound */
  311.     {
  312.         move(10,45);
  313.         *bell = 1;
  314.         (void) addstr("Bell ON ");
  315.     move(16,0);
  316.         refresh();
  317.     continue;
  318.     }
  319. if(ch == '0')
  320.     {
  321.         *bell = 0;
  322.         move(10,45);
  323.         (void) addstr("Bell OFF");
  324.     move(16,0);
  325.         refresh();
  326.     continue;
  327.     }
  328. #endif
  329. if(ch == '~')                             /* level jump */
  330.     {
  331.     if((newnum = jumpscreen(*num)) == 0)
  332.         {
  333.         strcpy(howdead,"a jump error.");
  334.         return howdead;
  335.         }
  336.     if(newnum != *num)
  337.         {                  /* Sorry Greg, no points for free */
  338.         sprintf(howdead,"~%c",newnum);
  339.         return howdead;
  340.         }
  341.     continue;
  342.     }
  343. if(ch == '!')                      /* look at the map */
  344.     {
  345.     if(debug_disp)
  346.         continue;
  347.     map(frow);
  348.         display(sx,sy,frow,*score);
  349.     continue;
  350.     }
  351. if(ch == 'q')
  352.         {
  353.         strcpy(howdead,"quitting the game");
  354.     return howdead;
  355.     }
  356. if(ch == '?')
  357.     {
  358.     helpme();
  359.     if(debug_disp)
  360.         map(frow);
  361.         else
  362.         display(sx,sy,frow,*score);
  363.     continue;
  364.     }
  365. if (ch == 'c')
  366.     {
  367.     credits();
  368.         redraw_screen(maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow);
  369.     continue;
  370.     }
  371. if((ch == '@')&&(!debug_disp))
  372.     {
  373.     sx = x;
  374.     sy = y;
  375.     display(sx,sy,frow,*score);
  376.     continue;
  377.     }
  378. if(ch == '#')
  379.     {
  380.     debug_disp = 1 - debug_disp;
  381.     if(debug_disp)
  382.         map(frow);
  383.     else
  384.         {
  385.          for(tmpy=0;tmpy<=(NOOFROWS+1);tmpy++)
  386.                 {
  387.                 move(tmpy,0);
  388.             addstr("                                          ");
  389.             }
  390.         sx = x; sy = y;
  391.         display(sx,sy,frow,*score);
  392.         }
  393.     continue;
  394.     }
  395. if(ch == 'W')
  396.     {
  397.         redraw_screen(maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow);
  398.     continue;
  399.     }
  400.  
  401. /* M002  Added save/restore game feature.  Gregory H. Margo    */
  402. if(ch == 'S')           /* save game */
  403.     {
  404.     extern    struct    save_vars    zz;
  405.  
  406.     /* stuff away important local variables to be saved */
  407.     /* so the game state may be acurately restored    */
  408.     zz.z_x        = x;
  409.     zz.z_y        = y;
  410.     zz.z_nx        = nx;
  411.     zz.z_ny        = ny;
  412.     zz.z_sx        = sx;
  413.     zz.z_sy        = sy;
  414.     zz.z_tx        = tx;
  415.     zz.z_ty        = ty;
  416.     zz.z_lx        = lx;
  417.     zz.z_ly        = ly;
  418.     zz.z_mx        = mx;
  419.     zz.z_my        = my;
  420.     zz.z_bx        = bx;
  421.     zz.z_by        = by;
  422.     zz.z_nbx    = nbx;
  423.     zz.z_nby    = nby;
  424.     zz.z_max_score    = max_score;
  425.     zz.z_diamonds    = diamonds;
  426.     zz.z_nf        = nf;
  427.     zz.z_hd        = hd;
  428.     zz.z_vd        = vd;
  429.     zz.z_xdirection    = xdirection;
  430.     zz.z_ydirection    = ydirection;
  431.  
  432.     save_game(*num, score, bell, maxmoves, &start_of_list, tail_of_list);
  433.     /* if save fails, we come back here */
  434.         redraw_screen(maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow);
  435.     continue;
  436.     }
  437. if(ch == 'R')        /* restore game */
  438.     {
  439.     extern    struct    save_vars    zz;
  440.  
  441.     restore_game(num, score, bell, &maxmoves, &start_of_list, &tail_of_list);
  442.  
  443.     /* recover important local variables */
  444.     x        = zz.z_x;
  445.     y        = zz.z_y;
  446.     nx        = zz.z_nx;
  447.     ny        = zz.z_ny;
  448.     sx        = zz.z_sx;
  449.     sy        = zz.z_sy;
  450.     tx        = zz.z_tx;
  451.     ty        = zz.z_ty;
  452.     lx        = zz.z_lx;
  453.     ly        = zz.z_ly;
  454.     mx        = zz.z_mx;
  455.     my        = zz.z_my;
  456.     bx        = zz.z_bx;
  457.     by        = zz.z_by;
  458.     nbx        = zz.z_nbx;
  459.     nby        = zz.z_nby;
  460.     max_score    = zz.z_max_score;
  461.     diamonds    = zz.z_diamonds;
  462.     nf        = zz.z_nf;
  463.     hd        = zz.z_hd;
  464.     vd        = zz.z_vd;
  465.     xdirection    = zz.z_xdirection;
  466.     ydirection    = zz.z_ydirection;
  467.  
  468.     if (maxmoves == -1)
  469.         maxmoves = 0;    /* to get the "unlimited moves" message */
  470.  
  471.     goto update_game;    /* the dreaded goto    */
  472.     }
  473.  
  474. if(screen[ny][nx] == 'C')
  475.     {
  476.     playSound(CLOCK_SOUND);
  477.     screen[ny][nx] = ':';
  478.     *score+=4;
  479.     if(maxmoves != -1)
  480.         maxmoves+=250;
  481.     }
  482. switch(screen[ny][nx])
  483.     {
  484.     case '@': break;
  485.     case '*': *score+=9;
  486.     max_score -= 10;
  487.         nf++;
  488.     playSound(DIAMOND_SOUND);
  489.     case ':': *score+=1;
  490.         move(3,48);
  491.         sprintf(buffer,"%d\t %d",*score,nf);
  492.         (void) addstr(buffer);
  493.     case ' ':
  494.     if (screen[ny][nx] != '*') playSound(STEP_SOUND);
  495.     screen[y][x] = ' ';
  496.        screen[ny][nx] = '@';
  497.     if(!debug_disp)
  498.         {
  499.             draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
  500.             draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
  501.         }
  502.     else
  503.         {
  504.         move(y+1,x+1);
  505.         draw_map_symbol(' ');
  506.         move(ny+1,nx+1);
  507.         draw_map_symbol('@');
  508.         }
  509.     deadyet += check(&mx,&my,x,y,nx-x,ny-y,sx,sy,howdead);
  510.         move(16,0);
  511.         refresh();
  512.     y = ny;
  513.     x = nx;
  514.         break;
  515.     case 'O':
  516.     if(screen[y][nx*2-x] == 'M')
  517.         {
  518.         screen[y][nx*2-x] = ' ';
  519.         mx = my = -1;
  520.         *score+=100;
  521.             move(3,48);
  522.             sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
  523.             (void) addstr(buffer);
  524.         playSound(DEADMONSTER_SOUND);
  525.         show_monster(0);
  526.         move(16,0);
  527.             refresh();
  528.         }
  529.     if(screen[y][nx*2-x] == ' ')
  530.         {
  531.         playSound(PUSH_SOUND);
  532.         screen[y][nx*2-x] = 'O';
  533.         screen[y][x] = ' ';
  534.             screen[ny][nx] = '@';
  535.         if(!debug_disp)
  536.         {
  537.                 draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
  538.                 draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
  539.         if(nx*2-x>sx-6&&nx*2-x<sx+6)
  540.                     draw_symbol((nx*2-x-sx+5)*3,(y-sy+3)*2,'O');
  541.         }
  542.         else
  543.         {
  544.         move(y+1,x+1);
  545.         draw_map_symbol(' ');
  546.         move(ny+1,nx+1);
  547.         draw_map_symbol('@');
  548.         move(y+1,nx*2-x+1);
  549.         draw_map_symbol('O');
  550.         }
  551.             deadyet += fall(&mx,&my,nx*2-x,y+1,sx,sy,howdead);
  552.             deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead);
  553.             deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
  554.             deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead);
  555.             deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead);
  556.             move(16,0);
  557.             refresh();
  558.         y = ny;
  559.         x = nx;
  560.         }
  561.     break;
  562.     case '^':
  563.     if(screen[y][nx*2-x] == ' ')
  564.         {
  565.         screen[y][nx*2-x] = '^';
  566.         screen[y][x] = ' ';
  567.             screen[ny][nx] = '@';
  568.         if(!debug_disp)
  569.         {
  570.                 draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
  571.                 draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
  572.         if(nx*2-x>sx-6&&nx*2-x<sx+6)
  573.                     draw_symbol((nx*2-x-sx+5)*3,(y-sy+3)*2,'^');
  574.         }
  575.         else
  576.         {
  577.         move(y+1,x+1);
  578.         draw_map_symbol(' ');
  579.         move(ny+1,nx+1);
  580.         draw_map_symbol('@');
  581.         move(y+1,nx*2-x+1);
  582.         draw_map_symbol('^');
  583.         }
  584.             deadyet += fall(&mx,&my,nx*2-x,y-1,sx,sy,howdead);
  585.             deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead);
  586.             deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
  587.             deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead);
  588.             deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead);
  589.             move(16,0);
  590.             refresh();
  591.         y = ny;
  592.         x = nx;
  593.         }
  594.     break;
  595.     case '<':
  596.     case '>':
  597.     if(screen[ny*2-y][x] == 'M')
  598.         {
  599.         screen[ny*2-y][x] = ' ';
  600.         mx = my = -1;
  601.         *score+=100;
  602.             move(3,48);
  603.             sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
  604.             (void) addstr(buffer);
  605.         playSound(DEADMONSTER_SOUND);
  606.         show_monster(0);
  607.         move(16,0);
  608.             refresh();
  609.         }
  610.     if(screen[ny*2-y][x] == ' ')
  611.         {
  612.         screen[ny*2-y][x] = screen[ny][nx];
  613.         screen[y][x] = ' ';
  614.             screen[ny][nx] = '@';
  615.         if(!debug_disp)
  616.         {
  617.                 draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
  618.                 draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
  619.         if(ny*2-y>sy-4&&ny*2-y<sy+4)
  620.                     draw_symbol((x-sx+5)*3,(ny*2-y-sy+3)*2,screen[ny*2-y][x]);
  621.         }
  622.         else
  623.         {
  624.         move(y+1,x+1);
  625.         draw_map_symbol(' ');
  626.         move(ny+1,nx+1);
  627.         draw_map_symbol('@');
  628.         move(ny*2-y+1,x+1);
  629.         draw_map_symbol(screen[ny*2-y][x]);
  630.         }
  631.             deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
  632.             deadyet += fall(&mx,&my,x-1,(ny>y)?y:(y-1),sx,sy,howdead);
  633.             deadyet += fall(&mx,&my,x+1,(ny>y)?y:(y-1),sx,sy,howdead);
  634.             deadyet += fall(&mx,&my,x-1,ny*2-y,sx,sy,howdead);
  635.             deadyet += fall(&mx,&my,x+1,ny*2-y,sx,sy,howdead);
  636.             move(16,0);
  637.             refresh();
  638.         y = ny;
  639.         x = nx;
  640.         }
  641.     break;
  642.     case '!':
  643.         strcpy(howdead,"an exploding landmine");
  644.     deadyet = 1;
  645.     if(!debug_disp)
  646.         {
  647.             draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
  648.             draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
  649.         }
  650.     else
  651.         {
  652.         move(y+1,x+1);
  653.         draw_map_symbol(' ');
  654.         move(ny+1,nx+1);
  655.         draw_map_symbol('@');
  656.         }
  657.         move(16,0);
  658.     refresh();
  659.     playSound(KABOOM_SOUND);
  660.         break;
  661.     case 'X':
  662.     if(nf == diamonds)
  663.         {
  664.         playSound(EXIT_SOUND);
  665.         *score+=250;
  666.         showpass(*num);
  667.         return NULL;
  668.         }
  669.     break;
  670.     case 'T':
  671.     if(tx > -1)
  672.         {
  673.         playSound(TELEPORT_SOUND);
  674.         screen[ny][nx] = ' ';
  675.         screen[y][x] = ' ';
  676.         lx = x;
  677.         ly = y;
  678.         y = ty;
  679.         x = tx;
  680.         screen[y][x] = '@';
  681.         sx = x;
  682.         sy = y;
  683.         *score += 20;
  684.             move(3,48);
  685.             sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
  686.             (void) addstr(buffer);
  687.         if(!debug_disp)
  688.             display(sx,sy,frow,*score);
  689.         else
  690.         map(frow);
  691.         deadyet = fall(&mx,&my,nx,ny,sx,sy,howdead);
  692.         if(deadyet == 0)
  693.         deadyet = fall(&mx,&my,lx,ly,sx,sy,howdead);
  694.         if(deadyet == 0)
  695.         deadyet = fall(&mx,&my,lx+1,ly-1,sx,sy,howdead);
  696.         if(deadyet == 0)
  697.         deadyet = fall(&mx,&my,lx+1,ly+1,sx,sy,howdead);
  698.         if(deadyet == 0)
  699.         deadyet = fall(&mx,&my,lx-1,ly+1,sx,sy,howdead);
  700.         if(deadyet == 0)
  701.         deadyet = fall(&mx,&my,lx-1,ly-1,sx,sy,howdead);
  702.         move(16,0);
  703.         refresh();
  704.         }
  705.     else
  706.         {
  707.         screen[ny][nx] = ' ';
  708.         move(16,0);
  709.         addstr("Teleport out of order");
  710.         refresh();
  711.         }
  712.     break;
  713.     case 'M':
  714.     playSound(MUNCH_SOUND);
  715.     strcpy(howdead,"a hungry monster");
  716.     deadyet = 1;
  717.     if(!debug_disp)
  718.             draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
  719.     else
  720.         {
  721.         move(y+1,x+1);
  722.         draw_map_symbol(' ');
  723.         }
  724.         move(16,0);
  725.     refresh();
  726.         break;
  727.     case 'S':
  728.     playSound(MUNCH_SOUND);
  729.     strcpy(howdead,"walking into a monster");
  730.     deadyet = 1;
  731.     if(!debug_disp)
  732.             draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
  733.     else
  734.         {
  735.         move(y+1,x+1);
  736.         draw_map_symbol(' ');
  737.         }
  738.         move(16,0);
  739.     refresh();
  740.         break;
  741.     default:
  742.         break;
  743.     }
  744. if((y == ny) && (x == nx) && (maxmoves>0))
  745.     {
  746.     (void) sprintf(buffer,"Moves remaining = %d ",--maxmoves);
  747.     move(15,48);
  748.     (void) addstr(buffer);
  749.     }
  750. if(maxmoves == 0)
  751.     {
  752.     strcpy(howdead,"running out of time");
  753.     return(howdead);
  754.     }
  755. if(!debug_disp)
  756.     {
  757.     if ((x<(sx-3))&& (deadyet ==0))         /* screen scrolling if necessary */
  758.         {
  759.         sx-=6;
  760.         if(sx < 4)
  761.         sx = 4;
  762.         scroll(sx,sy,frow,*score);
  763.         }
  764.     if ((y<(sy-2))&& (deadyet == 0))
  765.         {
  766.         sy-=5;
  767.         if(sy < 2)
  768.         sy = 2;
  769.         scroll(sx,sy,frow,*score);
  770.         }
  771.     if ((x>(sx+3)) && (deadyet == 0))
  772.         {
  773.         sx+=6;
  774.         if(sx>(ROWLEN -5))
  775.         sx = ROWLEN -5;
  776.         scroll(sx,sy,frow,*score);
  777.         }
  778.     if ((y>(sy+2))&& (deadyet ==0))
  779.         {
  780.         sy+=5;
  781.         if(sy > (NOOFROWS-3))
  782.         sy = NOOFROWS -3;
  783.         scroll(sx,sy,frow,*score);
  784.         }
  785.     }
  786.  
  787.     /* MONSTER SECTION  */
  788.  
  789. /* big monster first */
  790. if(mx == -2)                              /* has the monster been killed ? */
  791.     {
  792.     playSound(DEADMONSTER_SOUND);
  793.     *score+=100;
  794.     mx = my = -1;
  795.     move(3,48);
  796.     sprintf(buffer,"%d\t %d\t",*score,nf);
  797.     (void) addstr(buffer);
  798.     show_monster(0);
  799.     move(16,0);
  800.     refresh();
  801.     }                                     /* if monster still alive */
  802. if(mx != -1)                              /* then move that monster ! */
  803.     {
  804.     screen[my][mx] = ' ';
  805.     if(mx>x)
  806.         xdirection = -1;
  807.     else
  808.         xdirection = 1;
  809.     if(!debug_disp)
  810.     {
  811.         if((my<(sy+4))&&(my>(sy-4))&&(mx<(sx+6))&&(mx>(sx-6)))
  812.             draw_symbol((mx-sx+5)*3,(my-sy+3)*2,' ');
  813.     }
  814.     else
  815.     {
  816.     move(my+1,mx+1);
  817.     draw_map_symbol(' ');
  818.     }
  819.     if((hd = (mx-x))<0)
  820.     hd = -hd;
  821.     if((vd = (my-y))<0)
  822.     vd = -vd;
  823.     if((hd>vd)&&((screen[my][mx+xdirection] == ' ')||(screen[my][mx+xdirection] == '@')))
  824.     mx+=xdirection;
  825.     else
  826.         {
  827.         if(my>y)
  828.             ydirection = -1;
  829.     else
  830.             ydirection = 1;
  831.         if((screen[my+ydirection][mx] == ' ')||(screen[my+ydirection][mx] == '@'))
  832.         my+=ydirection;
  833.     else
  834.             if((screen[my][mx+xdirection] == ' ')||(screen[my][mx+xdirection] == '@'))
  835.     mx+=xdirection;
  836.     }
  837.     if(!debug_disp)
  838.     {
  839.         if((my<(sy+4))&&(my>(sy-4))&&(mx<(sx+6))&&(mx>(sx-6)))
  840.             draw_symbol((mx-sx+5)*3,(my-sy+3)*2,'M');
  841.     }
  842.     else
  843.     {
  844.     move(my+1,mx+1);
  845.     draw_map_symbol('M');
  846.     }
  847.     if(screen[my][mx] == '@')                     /* ha! gottim! */
  848.     {
  849.     playSound(MUNCH_SOUND);
  850.     strcpy(howdead,"a hungry monster");
  851.         move(16,0);
  852.     refresh();
  853.         return(howdead);
  854.     }
  855.     screen[my][mx] = 'M';
  856.     move(16,0);
  857.     refresh();
  858.     }
  859.  
  860. current = &start_of_list;                         /* baby monsters now */
  861. while((current != tail_of_list)&&(!deadyet))
  862.     /* deal with those little monsters */
  863.     {
  864.     monster = current->next;
  865.     new_disp = new_direction( monster->x, monster->y, monster->mx, monster->my );
  866.     if(monster->under!='S')             /* if on top of another baby */
  867.     {
  868.         screen[monster->y][monster->x] = monster->under;
  869.         if(!debug_disp)
  870.         {
  871.             if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
  872.                 draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,monster->under);
  873.         }
  874.         else
  875.         {
  876.             move(monster->y+1,monster->x+1);
  877.             draw_map_symbol(monster->under);
  878.         }
  879.         if(monster->under == ' ')
  880.          deadyet+=check(&mx,&my,monster->x,monster->y,new_disp.d[0],new_disp.d[1],sx,sy,howdead);
  881.     }
  882.     else
  883.     monster->under=' ';
  884.     monster->mx = new_disp.d[0];
  885.     monster->my = new_disp.d[1];
  886.     monster->x += monster->mx;
  887.     monster->y += monster->my;
  888.     monster->under = screen[monster->y][monster->x];
  889.     screen[monster->y][monster->x] = 'S';        /* move into new space */
  890.     if(!debug_disp)
  891.     {
  892.         if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
  893.             draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'S');
  894.     }
  895.     else
  896.     {
  897.     move(monster->y+1,monster->x+1);
  898.     draw_map_symbol('S');
  899.     }
  900.     if(monster->under == '@')                     /* monster hit you? */
  901.         {
  902.     playSound(MUNCH_SOUND);
  903.     strcpy(howdead,"the little monsters");
  904.     move(16,0);
  905.     refresh();
  906.         return(howdead);
  907.         }
  908.     if(monster->under == '+')                    /* monster hit cage? */
  909.         {
  910.     playSound(CAGE_SOUND);
  911.     *score +=20;
  912.     max_score -= 20;
  913.         move(3,48);
  914.         sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
  915.         (void) addstr(buffer);
  916.         /* remove from chain, and insert at the end (at last_of_list) */
  917.     if(monster == tail_of_list)
  918.         tail_of_list = tail_of_list->prev;
  919.     else
  920.         {
  921.           current->next = monster-> next;
  922.         current->next->prev = current;
  923.         monster->next = NULL;
  924.         monster->prev = last_of_list;
  925.         last_of_list->next = monster;
  926.         last_of_list = monster;
  927.         }
  928.     screen[monster->y][monster->x] = '*';
  929.     if(!debug_disp)
  930.         {
  931.             if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
  932.                     draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'*');
  933.         }
  934.     else
  935.         {
  936.         move(monster->y+1,monster->x+1);
  937.         draw_map_symbol('*');
  938.         }
  939.         }
  940.     else
  941.     current = monster;
  942.     move(16,0);
  943.     refresh();
  944.     }
  945.  
  946. if((edit_mode)&&(deadyet)) {         /* stop death if testing */
  947.     if(!debug_disp)
  948.     move(18,0);
  949.     else
  950.     move(20,0);
  951.     addstr("You were killed by ");
  952.     addstr(howdead);
  953.     addstr("\nPress 'c' to continue.");
  954.     refresh();
  955.     ch=getch();
  956.     if(ch == 'c')
  957.     deadyet = 0;
  958.     if(!debug_disp)
  959.     move(18,0);
  960.      else
  961.     move(20,0);
  962.     addstr("                                                              ");
  963.     addstr("\n                      ");
  964.     refresh();
  965.     }
  966.  
  967. }
  968. return(howdead);
  969. }
  970.