Annotation of 43BSDReno/games/trek/phaser.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.