# 2.11BSD#431 - /usr/src/games/trek/phaser.c

##### Functions

    phaser            X

##### Variables

    Matab             X

##### Macros

    ALPHA             X
    BETA              X
    EPSILON           X
    GAMMA             X
    OMEGA             X

##### struct's

    banks             X

       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

- in /usr/src/games/trek/play.c line 28, 43

#### Defined variables

Matab defined in line 47; used 1 times

- in line 113

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

- in line 195, 307

BETA defined in line 17; used 2 times

- in line 195, 306

EPSILON defined in line 19; used 2 times

- in line 195, 310

GAMMA defined in line 18; used 2 times

- in line 196, 315

OMEGA defined in line 20; used 2 times

- in line 195, 308

Last modified: 1986-02-01 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 968 |