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

bsd-games/2.17/trek/phaser.c

    1: /*      $NetBSD: phaser.c,v 1.9 2003/08/07 09:37:53 agc Exp $        */
    2: 
    3: /*
    4:  * Copyright (c) 1980, 1993
    5:  *      The Regents of the University of California.  All rights reserved.
    6:  *
    7:  * Redistribution and use in source and binary forms, with or without
    8:  * modification, are permitted provided that the following conditions
    9:  * are met:
   10:  * 1. Redistributions of source code must retain the above copyright
   11:  *    notice, this list of conditions and the following disclaimer.
   12:  * 2. 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:  * 3. Neither the name of the University nor the names of its contributors
   16:  *    may be used to endorse or promote products derived from this software
   17:  *    without specific prior written permission.
   18:  *
   19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29:  * SUCH DAMAGE.
   30:  */
   31: 
   32: #include <sys/cdefs.h>
   33: #ifndef lint
   34: #if 0
   35: static char sccsid[] = "@(#)phaser.c    8.1 (Berkeley) 5/31/93";
   36: #else
   37: __RCSID("$NetBSD: phaser.c,v 1.9 2003/08/07 09:37:53 agc Exp $");
   38: #endif
   39: #endif /* not lint */
   40: 
   41: #include <stdio.h>
   42: #include <math.h>
   43: #include "trek.h"
   44: #include "getpar.h"
   45: 
   46: /* factors for phaser hits; see description below */
   47: 
   48: # define        ALPHA          3.0             /* spread */
   49: # define        BETA           3.0              /* franf() */
   50: # define        GAMMA          0.30            /* cos(angle) */
   51: # define        EPSILON                150.0         /* dist ** 2 */
   52: # define        OMEGA          10.596          /* overall scaling factor */
   53: 
   54: /* OMEGA ~= 100 * (ALPHA + 1) * (BETA + 1) / (EPSILON + 1) */
   55: 
   56: /*
   57: **  Phaser Control
   58: **
   59: **      There are up to NBANKS phaser banks which may be fired
   60: **      simultaneously.  There are two modes, "manual" and
   61: **      "automatic".  In manual mode, you specify exactly which
   62: **      direction you want each bank to be aimed, the number
   63: **      of units to fire, and the spread angle.  In automatic
   64: **      mode, you give only the total number of units to fire.
   65: **
   66: **      The spread is specified as a number between zero and
   67: **      one, with zero being minimum spread and one being maximum
   68: **      spread.  You  will normally want zero spread, unless your
   69: **      short range scanners are out, in which case you probably
   70: **      don't know exactly where the Klingons are.  In that case,
   71: **      you really don't have any choice except to specify a
   72: **      fairly large spread.
   73: **
   74: **      Phasers spread slightly, even if you specify zero spread.
   75: **
   76: **      Uses trace flag 30
   77: */
   78: 
   79: struct cvntab   Matab[] =
   80: {
   81:         { "m",         "anual",       (cmdfun) 1,   0 },
   82:         { "a",         "utomatic",    (cmdfun) 0,        0 },
   83:         { NULL,                NULL,         NULL,          0 }
   84: };
   85: 
   86: struct banks
   87: {
   88:         int    units;
   89:         double angle;
   90:         double spread;
   91: };
   92: 
   93: 
   94: 
   95: /*ARGSUSED*/
   96: void
   97: phaser(v)
   98:         int v __attribute__((__unused__));
   99: {
  100:         int            i;
  101:         int            j;
  102:         struct kling   *k;
  103:         double         dx, dy;
  104:         double         anglefactor, distfactor;
  105:         struct banks   *b;
  106:         int            manual, flag, extra = 0;
  107:         int            hit;
  108:         double         tot;
  109:         int            n;
  110:         int            hitreqd[NBANKS];
  111:         struct banks   bank[NBANKS];
  112:         const struct cvntab    *ptr;
  113: 
  114:         if (Ship.cond == DOCKED) {
  115:                 printf("Phasers cannot fire through starbase shields\n");
  116:                 return;
  117:         }
  118:         if (damaged(PHASER)) {
  119:                 out(PHASER);
  120:                 return;
  121:         }
  122:         if (Ship.shldup) {
  123:                 printf("Sulu: Captain, we cannot fire through shields.\n");
  124:                 return;
  125:         }
  126:         if (Ship.cloaked)
  127:         {
  128:                 printf("Sulu: Captain, surely you must realize that we cannot fire\n");
  129:                 printf("  phasers with the cloaking device up.\n");
  130:                 return;
  131:         }
  132: 
  133:         /* decide if we want manual or automatic mode */
  134:         manual = 0;
  135:         if (testnl())
  136:         {
  137:                 if (damaged(COMPUTER))
  138:                 {
  139:                         printf("%s", Device[COMPUTER].name);
  140:                         manual++;
  141:                 }
  142:                 else
  143:                         if (damaged(SRSCAN))
  144:                         {
  145:                                 printf("%s", Device[SRSCAN].name);
  146:                                 manual++;
  147:                         }
  148:                 if (manual)
  149:                         printf(" damaged, manual mode selected\n");
  150:         }
  151: 
  152:         if (!manual)
  153:         {
  154:                 ptr = getcodpar("Manual or automatic", Matab);
  155:                 manual = (long) ptr->value;
  156:         }
  157:         if (!manual && damaged(COMPUTER))
  158:         {
  159:                 printf("Computer damaged, manual selected\n");
  160:                 skiptonl(0);
  161:                 manual++;
  162:         }
  163: 
  164:         /* initialize the bank[] array */
  165:         flag = 1;
  166:         for (i = 0; i < NBANKS; i++)
  167:                 bank[i].units = 0;
  168:         if (manual)
  169:         {
  170:                 /* collect manual mode statistics */
  171:                 while (flag)
  172:                 {
  173:                         printf("%d units available\n", Ship.energy);
  174:                         extra = 0;
  175:                         flag = 0;
  176:                         for (i = 0; i < NBANKS; i++)
  177:                         {
  178:                                 b = &bank[i];
  179:                                 printf("\nBank %d:\n", i);
  180:                                 hit = getintpar("units");
  181:                                 if (hit < 0)
  182:                                         return;
  183:                                 if (hit == 0)
  184:                                         break;
  185:                                 extra += hit;
  186:                                 if (extra > Ship.energy)
  187:                                 {
  188:                                         printf("available energy exceeded.  ");
  189:                                         skiptonl(0);
  190:                                         flag++;
  191:                                         break;
  192:                                 }
  193:                                 b->units = hit;
  194:                                 hit = getintpar("course");
  195:                                 if (hit < 0 || hit > 360)
  196:                                         return;
  197:                                 b->angle = hit * 0.0174532925;
  198:                                 b->spread = getfltpar("spread");
  199:                                 if (b->spread < 0 || b->spread > 1)
  200:                                         return;
  201:                         }
  202:                         Ship.energy -= extra;
  203:                 }
  204:                 extra = 0;
  205:         }
  206:         else
  207:         {
  208:                 /* automatic distribution of power */
  209:                 if (Etc.nkling <= 0) {
  210:                         printf("Sulu: But there are no Klingons in this quadrant\n");
  211:                         return;
  212:                 }
  213:                 printf("Phasers locked on target.  ");
  214:                 while (flag)
  215:                 {
  216:                         printf("%d units available\n", Ship.energy);
  217:                         hit = getintpar("Units to fire");
  218:                         if (hit <= 0)
  219:                                 return;
  220:                         if (hit > Ship.energy)
  221:                         {
  222:                                 printf("available energy exceeded.  ");
  223:                                 skiptonl(0);
  224:                                 continue;
  225:                         }
  226:                         flag = 0;
  227:                         Ship.energy -= hit;
  228:                         extra = hit;
  229:                         n = Etc.nkling;
  230:                         if (n > NBANKS)
  231:                                 n = NBANKS;
  232:                         tot = n * (n + 1) / 2;
  233:                         for (i = 0; i < n; i++)
  234:                         {
  235:                                 k = &Etc.klingon[i];
  236:                                 b = &bank[i];
  237:                                 distfactor = k->dist;
  238:                                 anglefactor = ALPHA * BETA * OMEGA / (distfactor * distfactor + EPSILON);
  239:                                 anglefactor *= GAMMA;
  240:                                 distfactor = k->power;
  241:                                 distfactor /= anglefactor;
  242:                                 hitreqd[i] = distfactor + 0.5;
  243:                                 dx = Ship.sectx - k->x;
  244:                                 dy = k->y - Ship.secty;
  245:                                 b->angle = atan2(dy, dx);
  246:                                 b->spread = 0.0;
  247:                                 b->units = ((n - i) / tot) * extra;
  248: #                               ifdef xTRACE
  249:                                 if (Trace)
  250:                                 {
  251:                                         printf("b%d hr%d u%d df%.2f af%.2f\n",
  252:                                                 i, hitreqd[i], b->units,
  253:                                                 distfactor, anglefactor);
  254:                                 }
  255: #                               endif
  256:                                 extra -= b->units;
  257:                                 hit = b->units - hitreqd[i];
  258:                                 if (hit > 0)
  259:                                 {
  260:                                         extra += hit;
  261:                                         b->units -= hit;
  262:                                 }
  263:                         }
  264: 
  265:                         /* give out any extra energy we might have around */
  266:                         if (extra > 0)
  267:                         {
  268:                                 for (i = 0; i < n; i++)
  269:                                 {
  270:                                         b = &bank[i];
  271:                                         hit = hitreqd[i] - b->units;
  272:                                         if (hit <= 0)
  273:                                                 continue;
  274:                                         if (hit >= extra)
  275:                                         {
  276:                                                 b->units += extra;
  277:                                                 extra = 0;
  278:                                                 break;
  279:                                         }
  280:                                         b->units = hitreqd[i];
  281:                                         extra -= hit;
  282:                                 }
  283:                                 if (extra > 0)
  284:                                         printf("%d units overkill\n", extra);
  285:                         }
  286:                 }
  287:         }
  288: 
  289: #       ifdef xTRACE
  290:         if (Trace)
  291:         {
  292:                 for (i = 0; i < NBANKS; i++)
  293:                 {
  294:                         b = &bank[i];
  295:                         printf("b%d u%d", i, b->units);
  296:                         if (b->units > 0)
  297:                                 printf(" a%.2f s%.2f\n", b->angle, b->spread);
  298:                         else
  299:                                 printf("\n");
  300:                 }
  301:         }
  302: #       endif
  303: 
  304:         /* actually fire the shots */
  305:         Move.free = 0;
  306:         for (i = 0; i < NBANKS; i++)
  307:         {
  308:                 b = &bank[i];
  309:                 if (b->units <= 0)
  310:                 {
  311:                         continue;
  312:                 }
  313:                 printf("\nPhaser bank %d fires:\n", i);
  314:                 n = Etc.nkling;
  315:                 k = Etc.klingon;
  316:                 for (j = 0; j < n; j++)
  317:                 {
  318:                         if (b->units <= 0)
  319:                                 break;
  320:                         /*
  321:                         ** The formula for hit is as follows:
  322:                         **
  323:                         **  zap = OMEGA * [(sigma + ALPHA) * (rho + BETA)]
  324:                         **   / (dist ** 2 + EPSILON)]
  325:                         **   * [cos(delta * sigma) + GAMMA]
  326:                         **   * hit
  327:                         **
  328:                         ** where sigma is the spread factor,
  329:                         ** rho is a random number (0 -> 1),
  330:                         ** GAMMA is a crud factor for angle (essentially
  331:                         **   cruds up the spread factor),
  332:                         ** delta is the difference in radians between the
  333:                         **   angle you are shooting at and the actual
  334:                         **   angle of the klingon,
  335:                         ** ALPHA scales down the significance of sigma,
  336:                         ** BETA scales down the significance of rho,
  337:                         ** OMEGA is the magic number which makes everything
  338:                         **   up to "* hit" between zero and one,
  339:                         ** dist is the distance to the klingon
  340:                         ** hit is the number of units in the bank, and
  341:                         ** zap is the amount of the actual hit.
  342:                         **
  343:                         ** Everything up through dist squared should maximize
  344:                         ** at 1.0, so that the distance factor is never
  345:                         ** greater than one.  Conveniently, cos() is
  346:                         ** never greater than one, but the same restric-
  347:                         ** tion applies.
  348:                         */
  349:                         distfactor = BETA + franf();
  350:                         distfactor *= ALPHA + b->spread;
  351:                         distfactor *= OMEGA;
  352:                         anglefactor = k->dist;
  353:                         distfactor /= anglefactor * anglefactor + EPSILON;
  354:                         distfactor *= b->units;
  355:                         dx = Ship.sectx - k->x;
  356:                         dy = k->y - Ship.secty;
  357:                         anglefactor = atan2(dy, dx) - b->angle;
  358:                         anglefactor = cos((anglefactor * b->spread) + GAMMA);
  359:                         if (anglefactor < 0.0)
  360:                         {
  361:                                 k++;
  362:                                 continue;
  363:                         }
  364:                         hit = anglefactor * distfactor + 0.5;
  365:                         k->power -= hit;
  366:                         printf("%d unit hit on Klingon", hit);
  367:                         if (!damaged(SRSCAN))
  368:                                 printf(" at %d,%d", k->x, k->y);
  369:                         printf("\n");
  370:                         b->units -= hit;
  371:                         if (k->power <= 0)
  372:                         {
  373:                                 killk(k->x, k->y);
  374:                                 continue;
  375:                         }
  376:                         k++;
  377:                 }
  378:         }
  379: 
  380:         /* compute overkill */
  381:         for (i = 0; i < NBANKS; i++)
  382:                 extra += bank[i].units;
  383:         if (extra > 0)
  384:                 printf("\n%d units expended on empty space\n", extra);
  385: }
Syntax (Markdown)