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