1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: static char sccsid[] = "@(#)phaser.c	5.1 (Berkeley) 1/29/86";
   9: #endif not lint
  10: 
  11: # include   "trek.h"
  12: # include   "getpar.h"
  13: 
  14: /* factors for phaser hits; see description below */
  15: 
  16: # define    ALPHA       3.0     /* spread */
  17: # define    BETA        3.0     /* franf() */
  18: # define    GAMMA       0.30        /* cos(angle) */
  19: # define    EPSILON     150.0       /* dist ** 2 */
  20: # define    OMEGA       10.596      /* overall scaling factor */
  21: 
  22: /* OMEGA ~= 100 * (ALPHA + 1) * (BETA + 1) / (EPSILON + 1) */
  23: 
  24: /*
  25: **  Phaser Control
  26: **
  27: **	There are up to NBANKS phaser banks which may be fired
  28: **	simultaneously.  There are two modes, "manual" and
  29: **	"automatic".  In manual mode, you specify exactly which
  30: **	direction you want each bank to be aimed, the number
  31: **	of units to fire, and the spread angle.  In automatic
  32: **	mode, you give only the total number of units to fire.
  33: **
  34: **	The spread is specified as a number between zero and
  35: **	one, with zero being minimum spread and one being maximum
  36: **	spread.  You  will normally want zero spread, unless your
  37: **	short range scanners are out, in which case you probably
  38: **	don't know exactly where the Klingons are.  In that case,
  39: **	you really don't have any choice except to specify a
  40: **	fairly large spread.
  41: **
  42: **	Phasers spread slightly, even if you specify zero spread.
  43: **
  44: **	Uses trace flag 30
  45: */
  46: 
  47: struct cvntab   Matab[] =
  48: {
  49:     "m",        "anual",        (int (*)())1,       0,
  50:     "a",        "utomatic",     0,      0,
  51:     0
  52: };
  53: 
  54: struct banks
  55: {
  56:     int units;
  57:     double  angle;
  58:     double  spread;
  59: };
  60: 
  61: 
  62: 
  63: phaser()
  64: {
  65:     register int        i;
  66:     int         j;
  67:     register struct kling   *k;
  68:     double          dx, dy;
  69:     double          anglefactor, distfactor;
  70:     register struct banks   *b;
  71:     int         manual, flag, extra;
  72:     int         hit;
  73:     double          tot;
  74:     int         n;
  75:     int         hitreqd[NBANKS];
  76:     struct banks        bank[NBANKS];
  77:     struct cvntab       *ptr;
  78: 
  79:     if (Ship.cond == DOCKED)
  80:         return(printf("Phasers cannot fire through starbase shields\n"));
  81:     if (damaged(PHASER))
  82:         return (out(PHASER));
  83:     if (Ship.shldup)
  84:         return (printf("Sulu: Captain, we cannot fire through shields.\n"));
  85:     if (Ship.cloaked)
  86:     {
  87:         printf("Sulu: Captain, surely you must realize that we cannot fire\n");
  88:         printf("  phasers with the cloaking device up.\n");
  89:         return;
  90:     }
  91: 
  92:     /* decide if we want manual or automatic mode */
  93:     manual = 0;
  94:     if (testnl())
  95:     {
  96:         if (damaged(COMPUTER))
  97:         {
  98:             printf(Device[COMPUTER].name);
  99:             manual++;
 100:         }
 101:         else
 102:             if (damaged(SRSCAN))
 103:             {
 104:                 printf(Device[SRSCAN].name);
 105:                 manual++;
 106:             }
 107:         if (manual)
 108:             printf(" damaged, manual mode selected\n");
 109:     }
 110: 
 111:     if (!manual)
 112:     {
 113:         ptr = getcodpar("Manual or automatic", Matab);
 114:         manual = (int) ptr->value;
 115:     }
 116:     if (!manual && damaged(COMPUTER))
 117:     {
 118:         printf("Computer damaged, manual selected\n");
 119:         skiptonl(0);
 120:         manual++;
 121:     }
 122: 
 123:     /* initialize the bank[] array */
 124:     flag = 1;
 125:     for (i = 0; i < NBANKS; i++)
 126:         bank[i].units = 0;
 127:     if (manual)
 128:     {
 129:         /* collect manual mode statistics */
 130:         while (flag)
 131:         {
 132:             printf("%d units available\n", Ship.energy);
 133:             extra = 0;
 134:             flag = 0;
 135:             for (i = 0; i < NBANKS; i++)
 136:             {
 137:                 b = &bank[i];
 138:                 printf("\nBank %d:\n", i);
 139:                 hit = getintpar("units");
 140:                 if (hit < 0)
 141:                     return;
 142:                 if (hit == 0)
 143:                     break;
 144:                 extra += hit;
 145:                 if (extra > Ship.energy)
 146:                 {
 147:                     printf("available energy exceeded.  ");
 148:                     skiptonl(0);
 149:                     flag++;
 150:                     break;
 151:                 }
 152:                 b->units = hit;
 153:                 hit = getintpar("course");
 154:                 if (hit < 0 || hit > 360)
 155:                     return;
 156:                 b->angle = hit * 0.0174532925;
 157:                 b->spread = getfltpar("spread");
 158:                 if (b->spread < 0 || b->spread > 1)
 159:                     return;
 160:             }
 161:             Ship.energy -= extra;
 162:         }
 163:         extra = 0;
 164:     }
 165:     else
 166:     {
 167:         /* automatic distribution of power */
 168:         if (Etc.nkling <= 0)
 169:             return (printf("Sulu: But there are no Klingons in this quadrant\n"));
 170:         printf("Phasers locked on target.  ");
 171:         while (flag)
 172:         {
 173:             printf("%d units available\n", Ship.energy);
 174:             hit = getintpar("Units to fire");
 175:             if (hit <= 0)
 176:                 return;
 177:             if (hit > Ship.energy)
 178:             {
 179:                 printf("available energy exceeded.  ");
 180:                 skiptonl(0);
 181:                 continue;
 182:             }
 183:             flag = 0;
 184:             Ship.energy -= hit;
 185:             extra = hit;
 186:             n = Etc.nkling;
 187:             if (n > NBANKS)
 188:                 n = NBANKS;
 189:             tot = n * (n + 1) / 2;
 190:             for (i = 0; i < n; i++)
 191:             {
 192:                 k = &Etc.klingon[i];
 193:                 b = &bank[i];
 194:                 distfactor = k->dist;
 195:                 anglefactor = ALPHA * BETA * OMEGA / (distfactor * distfactor + EPSILON);
 196:                 anglefactor *= GAMMA;
 197:                 distfactor = k->power;
 198:                 distfactor /= anglefactor;
 199:                 hitreqd[i] = distfactor + 0.5;
 200:                 dx = Ship.sectx - k->x;
 201:                 dy = k->y - Ship.secty;
 202:                 b->angle = atan2(dy, dx);
 203:                 b->spread = 0.0;
 204:                 b->units = ((n - i) / tot) * extra;
 205: #				ifdef xTRACE
 206:                 if (Trace)
 207:                 {
 208:                     printf("b%d hr%d u%d df%.2f af%.2f\n",
 209:                         i, hitreqd[i], b->units,
 210:                         distfactor, anglefactor);
 211:                 }
 212: #				endif
 213:                 extra -= b->units;
 214:                 hit = b->units - hitreqd[i];
 215:                 if (hit > 0)
 216:                 {
 217:                     extra += hit;
 218:                     b->units -= hit;
 219:                 }
 220:             }
 221: 
 222:             /* give out any extra energy we might have around */
 223:             if (extra > 0)
 224:             {
 225:                 for (i = 0; i < n; i++)
 226:                 {
 227:                     b = &bank[i];
 228:                     hit = hitreqd[i] - b->units;
 229:                     if (hit <= 0)
 230:                         continue;
 231:                     if (hit >= extra)
 232:                     {
 233:                         b->units += extra;
 234:                         extra = 0;
 235:                         break;
 236:                     }
 237:                     b->units = hitreqd[i];
 238:                     extra -= hit;
 239:                 }
 240:                 if (extra > 0)
 241:                     printf("%d units overkill\n", extra);
 242:             }
 243:         }
 244:     }
 245: 
 246: #	ifdef xTRACE
 247:     if (Trace)
 248:     {
 249:         for (i = 0; i < NBANKS; i++)
 250:         {
 251:             b = &bank[i];
 252:             printf("b%d u%d", i, b->units);
 253:             if (b->units > 0)
 254:                 printf(" a%.2f s%.2f\n", b->angle, b->spread);
 255:             else
 256:                 printf("\n");
 257:         }
 258:     }
 259: #	endif
 260: 
 261:     /* actually fire the shots */
 262:     Move.free = 0;
 263:     for (i = 0; i < NBANKS; i++)
 264:     {
 265:         b = &bank[i];
 266:         if (b->units <= 0)
 267:         {
 268:             continue;
 269:         }
 270:         printf("\nPhaser bank %d fires:\n", i);
 271:         n = Etc.nkling;
 272:         k = Etc.klingon;
 273:         for (j = 0; j < n; j++)
 274:         {
 275:             if (b->units <= 0)
 276:                 break;
 277:             /*
 278: 			** The formula for hit is as follows:
 279: 			**
 280: 			**  zap = OMEGA * [(sigma + ALPHA) * (rho + BETA)]
 281: 			**	/ (dist ** 2 + EPSILON)]
 282: 			**	* [cos(delta * sigma) + GAMMA]
 283: 			**	* hit
 284: 			**
 285: 			** where sigma is the spread factor,
 286: 			** rho is a random number (0 -> 1),
 287: 			** GAMMA is a crud factor for angle (essentially
 288: 			**	cruds up the spread factor),
 289: 			** delta is the difference in radians between the
 290: 			**	angle you are shooting at and the actual
 291: 			**	angle of the klingon,
 292: 			** ALPHA scales down the significance of sigma,
 293: 			** BETA scales down the significance of rho,
 294: 			** OMEGA is the magic number which makes everything
 295: 			**	up to "* hit" between zero and one,
 296: 			** dist is the distance to the klingon
 297: 			** hit is the number of units in the bank, and
 298: 			** zap is the amount of the actual hit.
 299: 			**
 300: 			** Everything up through dist squared should maximize
 301: 			** at 1.0, so that the distance factor is never
 302: 			** greater than one.  Conveniently, cos() is
 303: 			** never greater than one, but the same restric-
 304: 			** tion applies.
 305: 			*/
 306:             distfactor = BETA + franf();
 307:             distfactor *= ALPHA + b->spread;
 308:             distfactor *= OMEGA;
 309:             anglefactor = k->dist;
 310:             distfactor /= anglefactor * anglefactor + EPSILON;
 311:             distfactor *= b->units;
 312:             dx = Ship.sectx - k->x;
 313:             dy = k->y - Ship.secty;
 314:             anglefactor = atan2(dy, dx) - b->angle;
 315:             anglefactor = cos((anglefactor * b->spread) + GAMMA);
 316:             if (anglefactor < 0.0)
 317:             {
 318:                 k++;
 319:                 continue;
 320:             }
 321:             hit = anglefactor * distfactor + 0.5;
 322:             k->power -= hit;
 323:             printf("%d unit hit on Klingon", hit);
 324:             if (!damaged(SRSCAN))
 325:                 printf(" at %d,%d", k->x, k->y);
 326:             printf("\n");
 327:             b->units -= hit;
 328:             if (k->power <= 0)
 329:             {
 330:                 killk(k->x, k->y);
 331:                 continue;
 332:             }
 333:             k++;
 334:         }
 335:     }
 336: 
 337:     /* compute overkill */
 338:     for (i = 0; i < NBANKS; i++)
 339:         extra += bank[i].units;
 340:     if (extra > 0)
 341:         printf("\n%d units expended on empty space\n", extra);
 342: }

Defined functions

phaser defined in line 63; used 2 times

Defined variables

Matab defined in line 47; used 1 times
sccsid defined in line 8; never used

Defined struct's

banks defined in line 54; used 4 times
  • in line 70(2), 76(2)

Defined macros

ALPHA defined in line 16; used 2 times
BETA defined in line 17; used 2 times
EPSILON defined in line 19; used 2 times
GAMMA defined in line 18; used 2 times
OMEGA defined in line 20; used 2 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2575
Valid CSS Valid XHTML 1.0 Strict