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