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