(linenum→info "unix/slp.c:2238")

bsd-games/2.17/hunt/huntd/execute.c

    1: /*      $NetBSD: execute.c,v 1.4 2004/01/27 20:30:29 jsm Exp $       */
    2: /*
    3:  * Copyright (c) 1983-2003, Regents of the University of California.
    4:  * All rights reserved.
    5:  * 
    6:  * Redistribution and use in source and binary forms, with or without 
    7:  * modification, are permitted provided that the following conditions are 
    8:  * met:
    9:  * 
   10:  * + Redistributions of source code must retain the above copyright 
   11:  *   notice, this list of conditions and the following disclaimer.
   12:  * + Redistributions in binary form must reproduce the above copyright 
   13:  *   notice, this list of conditions and the following disclaimer in the 
   14:  *   documentation and/or other materials provided with the distribution.
   15:  * + Neither the name of the University of California, San Francisco nor 
   16:  *   the names of its contributors may be used to endorse or promote 
   17:  *   products derived from this software without specific prior written 
   18:  *   permission.
   19:  * 
   20:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
   21:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
   22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
   23:  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
   24:  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
   25:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
   26:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
   27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
   28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
   29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
   30:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31:  */
   32: 
   33: #include <sys/cdefs.h>
   34: #ifndef lint
   35: __RCSID("$NetBSD: execute.c,v 1.4 2004/01/27 20:30:29 jsm Exp $");
   36: #endif /* not lint */
   37: 
   38: # include       <stdlib.h>
   39: # include       "hunt.h"
   40: 
   41: static  void     cloak(PLAYER *);
   42: static  void     face(PLAYER *, int);
   43: static  void     fire(PLAYER *, int);
   44: static  void     fire_slime(PLAYER *, int);
   45: static  void     move_player(PLAYER *, int);
   46: static  void     pickup(PLAYER *, int, int, int, int);
   47: static  void     scan(PLAYER *);
   48: 
   49: 
   50: # ifdef MONITOR
   51: /*
   52:  * mon_execute:
   53:  *      Execute a single monitor command
   54:  */
   55: void
   56: mon_execute(pp)
   57:         PLAYER *pp;
   58: {
   59:         char   ch;
   60: 
   61:         ch = pp->p_cbuf[pp->p_ncount++];
   62:         switch (ch) {
   63:           case CTRL('L'):
   64:                 sendcom(pp, REDRAW);
   65:                 break;
   66:           case 'q':
   67:                 (void) strcpy(pp->p_death, "| Quit |");
   68:                 break;
   69:         }
   70: }
   71: # endif
   72: 
   73: /*
   74:  * execute:
   75:  *      Execute a single command
   76:  */
   77: void
   78: execute(pp)
   79:         PLAYER *pp;
   80: {
   81:         char   ch;
   82: 
   83:         ch = pp->p_cbuf[pp->p_ncount++];
   84: 
   85: # ifdef FLY
   86:         if (pp->p_flying >= 0) {
   87:                 switch (ch) {
   88:                   case CTRL('L'):
   89:                         sendcom(pp, REDRAW);
   90:                         break;
   91:                   case 'q':
   92:                         (void) strcpy(pp->p_death, "| Quit |");
   93:                         break;
   94:                 }
   95:                 return;
   96:         }
   97: # endif
   98: 
   99:         switch (ch) {
  100:           case CTRL('L'):
  101:                 sendcom(pp, REDRAW);
  102:                 break;
  103:           case 'h':
  104:                 move_player(pp, LEFTS);
  105:                 break;
  106:           case 'H':
  107:                 face(pp, LEFTS);
  108:                 break;
  109:           case 'j':
  110:                 move_player(pp, BELOW);
  111:                 break;
  112:           case 'J':
  113:                 face(pp, BELOW);
  114:                 break;
  115:           case 'k':
  116:                 move_player(pp, ABOVE);
  117:                 break;
  118:           case 'K':
  119:                 face(pp, ABOVE);
  120:                 break;
  121:           case 'l':
  122:                 move_player(pp, RIGHT);
  123:                 break;
  124:           case 'L':
  125:                 face(pp, RIGHT);
  126:                 break;
  127:           case 'f':
  128:           case '1':
  129:                 fire(pp, 0);          /* SHOT */
  130:                 break;
  131:           case 'g':
  132:           case '2':
  133:                 fire(pp, 1);          /* GRENADE */
  134:                 break;
  135:           case 'F':
  136:           case '3':
  137:                 fire(pp, 2);          /* SATCHEL */
  138:                 break;
  139:           case 'G':
  140:           case '4':
  141:                 fire(pp, 3);          /* 7x7 BOMB */
  142:                 break;
  143:           case '5':
  144:                 fire(pp, 4);          /* 9x9 BOMB */
  145:                 break;
  146:           case '6':
  147:                 fire(pp, 5);          /* 11x11 BOMB */
  148:                 break;
  149:           case '7':
  150:                 fire(pp, 6);          /* 13x13 BOMB */
  151:                 break;
  152:           case '8':
  153:                 fire(pp, 7);          /* 15x15 BOMB */
  154:                 break;
  155:           case '9':
  156:                 fire(pp, 8);          /* 17x17 BOMB */
  157:                 break;
  158:           case '0':
  159:                 fire(pp, 9);          /* 19x19 BOMB */
  160:                 break;
  161:           case '@':
  162:                 fire(pp, 10);         /* 21x21 BOMB */
  163:                 break;
  164: # ifdef OOZE
  165:           case 'o':
  166:                 fire_slime(pp, 0);    /* SLIME */
  167:                 break;
  168:           case 'O':
  169:                 fire_slime(pp, 1);    /* SSLIME */
  170:                 break;
  171:           case 'p':
  172:                 fire_slime(pp, 2);
  173:                 break;
  174:           case 'P':
  175:                 fire_slime(pp, 3);
  176:                 break;
  177: # endif
  178:           case 's':
  179:                 scan(pp);
  180:                 break;
  181:           case 'c':
  182:                 cloak(pp);
  183:                 break;
  184:           case 'q':
  185:                 (void) strcpy(pp->p_death, "| Quit |");
  186:                 break;
  187:         }
  188: }
  189: 
  190: /*
  191:  * move_player:
  192:  *      Execute a move in the given direction
  193:  */
  194: static void
  195: move_player(pp, dir)
  196:         PLAYER *pp;
  197:         int    dir;
  198: {
  199:         PLAYER *newp;
  200:         int    x, y;
  201:         FLAG   moved;
  202:         BULLET *bp;
  203: 
  204:         y = pp->p_y;
  205:         x = pp->p_x;
  206: 
  207:         switch (dir) {
  208:           case LEFTS:
  209:                 x--;
  210:                 break;
  211:           case RIGHT:
  212:                 x++;
  213:                 break;
  214:           case ABOVE:
  215:                 y--;
  216:                 break;
  217:           case BELOW:
  218:                 y++;
  219:                 break;
  220:         }
  221: 
  222:         moved = FALSE;
  223:         switch (Maze[y][x]) {
  224:           case SPACE:
  225: # ifdef RANDOM
  226:           case DOOR:
  227: # endif
  228:                 moved = TRUE;
  229:                 break;
  230:           case WALL1:
  231:           case WALL2:
  232:           case WALL3:
  233: # ifdef REFLECT
  234:           case WALL4:
  235:           case WALL5:
  236: # endif
  237:                 break;
  238:           case MINE:
  239:           case GMINE:
  240:                 if (dir == pp->p_face)
  241:                         pickup(pp, y, x, 2, Maze[y][x]);
  242:                 else if (opposite(dir, pp->p_face))
  243:                         pickup(pp, y, x, 95, Maze[y][x]);
  244:                 else
  245:                         pickup(pp, y, x, 50, Maze[y][x]);
  246:                 Maze[y][x] = SPACE;
  247:                 moved = TRUE;
  248:                 break;
  249:           case SHOT:
  250:           case GRENADE:
  251:           case SATCHEL:
  252:           case BOMB:
  253: # ifdef OOZE
  254:           case SLIME:
  255: # endif
  256: # ifdef DRONE
  257:           case DSHOT:
  258: # endif
  259:                 bp = is_bullet(y, x);
  260:                 if (bp != NULL)
  261:                         bp->b_expl = TRUE;
  262:                 Maze[y][x] = SPACE;
  263:                 moved = TRUE;
  264:                 break;
  265:           case LEFTS:
  266:           case RIGHT:
  267:           case ABOVE:
  268:           case BELOW:
  269:                 if (dir != pp->p_face)
  270:                         sendcom(pp, BELL);
  271:                 else {
  272:                         newp = play_at(y, x);
  273:                         checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE);
  274:                 }
  275:                 break;
  276: # ifdef FLY
  277:           case FLYER:
  278:                 newp = play_at(y, x);
  279:                 message(newp, "Oooh, there's a short guy waving at you!");
  280:                 message(pp, "You couldn't quite reach him!");
  281:                 break;
  282: # endif
  283: # ifdef BOOTS
  284:           case BOOT:
  285:           case BOOT_PAIR:
  286:                 if (Maze[y][x] == BOOT)
  287:                         pp->p_nboots++;
  288:                 else
  289:                         pp->p_nboots += 2;
  290:                 for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
  291:                         if (newp->p_flying < 0)
  292:                                 continue;
  293:                         if (newp->p_y == y && newp->p_x == x) {
  294:                                 newp->p_flying = -1;
  295:                                 if (newp->p_undershot)
  296:                                         fixshots(y, x, newp->p_over);
  297:                         }
  298:                 }
  299:                 if (pp->p_nboots == 2)
  300:                         message(pp, "Wow!  A pair of boots!");
  301:                 else
  302:                         message(pp, "You can hobble around on one boot.");
  303:                 Maze[y][x] = SPACE;
  304:                 moved = TRUE;
  305:                 break;
  306: # endif
  307:         }
  308:         if (moved) {
  309:                 if (pp->p_ncshot > 0)
  310:                         if (--pp->p_ncshot == MAXNCSHOT) {
  311:                                 cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
  312:                                 outstr(pp, " ok", 3);
  313:                         }
  314:                 if (pp->p_undershot) {
  315:                         fixshots(pp->p_y, pp->p_x, pp->p_over);
  316:                         pp->p_undershot = FALSE;
  317:                 }
  318:                 drawplayer(pp, FALSE);
  319:                 pp->p_over = Maze[y][x];
  320:                 pp->p_y = y;
  321:                 pp->p_x = x;
  322:                 drawplayer(pp, TRUE);
  323:         }
  324: }
  325: 
  326: /*
  327:  * face:
  328:  *      Change the direction the player is facing
  329:  */
  330: static void
  331: face(pp, dir)
  332:         PLAYER *pp;
  333:         int    dir;
  334: {
  335:         if (pp->p_face != dir) {
  336:                 pp->p_face = dir;
  337:                 drawplayer(pp, TRUE);
  338:         }
  339: }
  340: 
  341: /*
  342:  * fire:
  343:  *      Fire a shot of the given type in the given direction
  344:  */
  345: static void
  346: fire(pp, req_index)
  347:         PLAYER *pp;
  348:         int    req_index;
  349: {
  350:         if (pp == NULL)
  351:                 return;
  352: # ifdef DEBUG
  353:         if (req_index < 0 || req_index >= MAXBOMB)
  354:                 message(pp, "What you do?");
  355: # endif
  356:         while (req_index >= 0 && pp->p_ammo < shot_req[req_index])
  357:                 req_index--;
  358:         if (req_index < 0) {
  359:                 message(pp, "Not enough charges.");
  360:                 return;
  361:         }
  362:         if (pp->p_ncshot > MAXNCSHOT)
  363:                 return;
  364:         if (pp->p_ncshot++ == MAXNCSHOT) {
  365:                 cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
  366:                 outstr(pp, "   ", 3);
  367:         }
  368:         pp->p_ammo -= shot_req[req_index];
  369:         (void) sprintf(Buf, "%3d", pp->p_ammo);
  370:         cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  371:         outstr(pp, Buf, 3);
  372: 
  373:         add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face,
  374:                 shot_req[req_index], pp, FALSE, pp->p_face);
  375:         pp->p_undershot = TRUE;
  376: 
  377:         /*
  378:          * Show the object to everyone
  379:          */
  380:         showexpl(pp->p_y, pp->p_x, shot_type[req_index]);
  381:         for (pp = Player; pp < End_player; pp++)
  382:                 sendcom(pp, REFRESH);
  383: # ifdef MONITOR
  384:         for (pp = Monitor; pp < End_monitor; pp++)
  385:                 sendcom(pp, REFRESH);
  386: # endif
  387: }
  388: 
  389: # ifdef OOZE
  390: /*
  391:  * fire_slime:
  392:  *      Fire a slime shot in the given direction
  393:  */
  394: static void
  395: fire_slime(pp, req_index)
  396:         PLAYER *pp;
  397:         int    req_index;
  398: {
  399:         if (pp == NULL)
  400:                 return;
  401: # ifdef DEBUG
  402:         if (req_index < 0 || req_index >= MAXSLIME)
  403:                 message(pp, "What you do?");
  404: # endif
  405:         while (req_index >= 0 && pp->p_ammo < slime_req[req_index])
  406:                 req_index--;
  407:         if (req_index < 0) {
  408:                 message(pp, "Not enough charges.");
  409:                 return;
  410:         }
  411:         if (pp->p_ncshot > MAXNCSHOT)
  412:                 return;
  413:         if (pp->p_ncshot++ == MAXNCSHOT) {
  414:                 cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
  415:                 outstr(pp, "   ", 3);
  416:         }
  417:         pp->p_ammo -= slime_req[req_index];
  418:         (void) sprintf(Buf, "%3d", pp->p_ammo);
  419:         cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  420:         outstr(pp, Buf, 3);
  421: 
  422:         add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face,
  423:                 slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face);
  424:         pp->p_undershot = TRUE;
  425: 
  426:         /*
  427:          * Show the object to everyone
  428:          */
  429:         showexpl(pp->p_y, pp->p_x, SLIME);
  430:         for (pp = Player; pp < End_player; pp++)
  431:                 sendcom(pp, REFRESH);
  432: # ifdef MONITOR
  433:         for (pp = Monitor; pp < End_monitor; pp++)
  434:                 sendcom(pp, REFRESH);
  435: # endif
  436: }
  437: # endif
  438: 
  439: /*
  440:  * add_shot:
  441:  *      Create a shot with the given properties
  442:  */
  443: void
  444: add_shot(type, y, x, face, charge, owner, expl, over)
  445: int     type;
  446: int     y, x;
  447: char    face;
  448: int     charge;
  449: PLAYER  *owner;
  450: int     expl;
  451: char    over;
  452: {
  453:         BULLET *bp;
  454:         int    size;
  455: 
  456:         switch (type) {
  457:           case SHOT:
  458:           case MINE:
  459:                 size = 1;
  460:                 break;
  461:           case GRENADE:
  462:           case GMINE:
  463:                 size = 2;
  464:                 break;
  465:           case SATCHEL:
  466:                 size = 3;
  467:                 break;
  468:           case BOMB:
  469:                 for (size = 3; size < MAXBOMB; size++)
  470:                         if (shot_req[size] >= charge)
  471:                                 break;
  472:                 size++;
  473:                 break;
  474:           default:
  475:                 size = 0;
  476:                 break;
  477:         }
  478: 
  479:         bp = create_shot(type, y, x, face, charge, size, owner,
  480:                 (owner == NULL) ? NULL : owner->p_ident, expl, over);
  481:         bp->b_next = Bullets;
  482:         Bullets = bp;
  483: }
  484: 
  485: BULLET *
  486: create_shot(type, y, x, face, charge, size, owner, score, expl, over)
  487:         int    type;
  488:         int    y, x;
  489:         char   face;
  490:         int    charge;
  491:         int    size;
  492:         PLAYER *owner;
  493:         IDENT  *score;
  494:         int    expl;
  495:         char   over;
  496: {
  497:         BULLET *bp;
  498: 
  499:         bp = (BULLET *) malloc(sizeof (BULLET));       /* NOSTRICT */
  500:         if (bp == NULL) {
  501:                 if (owner != NULL)
  502:                         message(owner, "Out of memory");
  503:                 return NULL;
  504:         }
  505: 
  506:         bp->b_face = face;
  507:         bp->b_x = x;
  508:         bp->b_y = y;
  509:         bp->b_charge = charge;
  510:         bp->b_owner = owner;
  511:         bp->b_score = score;
  512:         bp->b_type = type;
  513:         bp->b_size = size;
  514:         bp->b_expl = expl;
  515:         bp->b_over = over;
  516:         bp->b_next = NULL;
  517: 
  518:         return bp;
  519: }
  520: 
  521: /*
  522:  * cloak:
  523:  *      Turn on or increase length of a cloak
  524:  */
  525: static void
  526: cloak(pp)
  527:         PLAYER *pp;
  528: {
  529:         if (pp->p_ammo <= 0) {
  530:                 message(pp, "No more charges");
  531:                 return;
  532:         }
  533: # ifdef BOOTS
  534:         if (pp->p_nboots > 0) {
  535:                 message(pp, "Boots are too noisy to cloak!");
  536:                 return;
  537:         }
  538: # endif
  539:         (void) sprintf(Buf, "%3d", --pp->p_ammo);
  540:         cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  541:         outstr(pp, Buf, 3);
  542: 
  543:         pp->p_cloak += CLOAKLEN;
  544: 
  545:         if (pp->p_scan >= 0)
  546:                 pp->p_scan = -1;
  547: 
  548:         showstat(pp);
  549: }
  550: 
  551: /*
  552:  * scan:
  553:  *      Turn on or increase length of a scan
  554:  */
  555: static void
  556: scan(pp)
  557:         PLAYER *pp;
  558: {
  559:         if (pp->p_ammo <=