|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.