/*ARGSUSED*/ void capture(int v __unused) { int i; struct kling *k; double x; /* check for not cloaked */ if (Ship.cloaked) { printf("Ship-ship communications out when cloaked\n"); return; } if (damaged(SSRADIO)) { out(SSRADIO); return; } /* find out if there are any at all */ if (Etc.nkling <= 0) { printf("Uhura: Getting no response, sir\n"); return; } /* if there is more than one Klingon, find out which one */ k = selectklingon(); Move.free = 0; Move.time = 0.05; /* check out that Klingon */ k->srndreq++; x = Param.klingpwr; x *= Ship.energy; x /= k->power * Etc.nkling; x *= Param.srndrprob; i = x; #ifdef xTRACE if (Trace) printf("Prob = %d (%.4f)\n", i, x); #endif if (i > ranf(100)) { /* guess what, he surrendered!!! */ printf("Klingon at %d,%d surrenders\n", k->x, k->y); i = ranf(Param.klingcrew); if ( i > 0 ) printf("%d klingons commit suicide rather than be " "taken captive\n", Param.klingcrew - i); if (i > Ship.brigfree) i = Ship.brigfree; Ship.brigfree -= i; printf("%d captives taken\n", i); killk(k->x, k->y); return; } /* big surprise, he refuses to surrender */ printf("Fat chance, captain\n"); return; }
void ram(int ix, int iy) { int i; char c; printf("\07RED ALERT\07: collision imminent\n"); c = Sect[ix][iy]; switch (c) { case KLINGON: printf("%s rams Klingon at %d,%d\n", Ship.shipname, ix, iy); killk(ix, iy); break; case STAR: case INHABIT: printf("Yeoman Rand: Captain, isn't it getting hot in here?\n"); sleep(2); printf("Spock: Hull temperature approaching 550 Degrees Kelvin.\n"); lose(L_STAR); case BASE: printf("You ran into the starbase at %d,%d\n", ix, iy); killb(Ship.quadx, Ship.quady); /* don't penalize the captain if it wasn't his fault */ if (!damaged(SINS)) Game.killb += 1; break; } sleep(2); printf("%s heavily damaged\n", Ship.shipname); /* select the number of deaths to occur */ i = 10 + ranf(20 * Game.skill); Game.deaths += i; Ship.crew -= i; printf("McCoy: Take it easy Jim; we had %d casualties.\n", i); /* damage devices with an 80% probability */ for (i = 0; i < NDEV; i++) { if (ranf(100) < 20) continue; damage(i, (2.5 * (franf() + franf()) + 1.0) * Param.damfac[i]); } /* no chance that your shields remained up in all that */ Ship.shldup = 0; }
/*ARGSUSED*/ void torped(int v __unused) { int ix, iy; double x, y, dx, dy; double angle; int course, course2; int k; double bigger; double sectsize; int burst; int n; if (Ship.cloaked) { printf("Federation regulations do not permit attack while " "cloaked.\n"); return; } if (check_out(TORPED)) return; if (Ship.torped <= 0) { printf("All photon torpedos expended\n"); return; } /* get the course */ course = getintpar("Torpedo course"); if (course < 0 || course > 360) return; burst = -1; /* need at least three torpedoes for a burst */ if (Ship.torped < 3) { printf("No-burst mode selected\n"); burst = 0; } else { /* see if the user wants one */ if (!testnl()) { k = ungetc(getchar(), stdin); if (k >= '0' && k <= '9') burst = 1; } } if (burst < 0) { burst = getynpar("Do you want a burst"); } if (burst) { burst = getintpar("burst angle"); if (burst <= 0) return; if (burst > 15) { printf("Maximum burst angle is 15 degrees\n"); return; } } sectsize = NSECTS; n = -1; if (burst) { n = 1; course -= burst; } for (; n && n <= 3; n++) { /* select a nice random course */ course2 = course + randcourse(n); /* convert to radians */ angle = course2 * 0.0174532925; dx = -cos(angle); dy = sin(angle); bigger = fabs(dx); x = fabs(dy); if (x > bigger) bigger = x; dx /= bigger; dy /= bigger; x = Ship.sectx + 0.5; y = Ship.secty + 0.5; if (Ship.cond != DOCKED) Ship.torped -= 1; printf("Torpedo track"); if (n > 0) printf(", torpedo number %d", n); printf(":\n%6.1f\t%4.1f\n", x, y); while (1) { ix = x += dx; iy = y += dy; if (x < 0.0 || x >= sectsize || y < 0.0 || y >= sectsize) { printf("Torpedo missed\n"); break; } printf("%6.1f\t%4.1f\n", x, y); switch (Sect[ix][iy]) { case EMPTY: continue; case HOLE: printf("Torpedo disappears into a black " "hole\n"); break; case KLINGON: for (k = 0; k < Etc.nkling; k++) { if (Etc.klingon[k].x != ix || Etc.klingon[k].y != iy) continue; Etc.klingon[k].power -= 500 + ranf(501); if (Etc.klingon[k].power > 0) { printf("*** Hit on Klingon at " "%d,%d: extensive " "damages\n", ix, iy); break; } killk(ix, iy); break; } break; case STAR: nova(ix, iy); break; case INHABIT: kills(ix, iy, -1); break; case BASE: killb(Ship.quadx, Ship.quady); Game.killb += 1; break; default: printf("Unknown object %c at %d,%d destroyed\n", Sect[ix][iy], ix, iy); Sect[ix][iy] = EMPTY; break; } break; } if (damaged(TORPED) || Quad[Ship.quadx][Ship.quady].stars < 0) break; course += burst; } Move.free = 0; }
phaser() { register int i; int j; register struct kling *k; double dx, dy; double anglefactor, distfactor; register struct banks *b; int manual, flag, extra; int hit; double tot; int n; int hitreqd[NBANKS]; struct banks bank[NBANKS]; struct cvntab *ptr; if (Ship.cond == DOCKED) return(printf("Phasers cannot fire through starbase shields\n")); if (damaged(PHASER)) return (out(PHASER)); if (Ship.shldup) return (printf("Sulu: Captain, we cannot fire through shields.\n")); if (Ship.cloaked) { printf("Sulu: Captain, surely you must realize that we cannot fire\n"); printf(" phasers with the cloaking device up.\n"); return; } /* decide if we want manual or automatic mode */ manual = 0; if (testnl()) { if (damaged(COMPUTER)) { printf(Device[COMPUTER].name); manual++; } else if (damaged(SRSCAN)) { printf(Device[SRSCAN].name); manual++; } if (manual) printf(" damaged, manual mode selected\n"); } if (!manual) { ptr = getcodpar("Manual or automatic", Matab); manual = (int) ptr->value; } if (!manual && damaged(COMPUTER)) { printf("Computer damaged, manual selected\n"); skiptonl(0); manual++; } /* initialize the bank[] array */ flag = 1; for (i = 0; i < NBANKS; i++) bank[i].units = 0; if (manual) { /* collect manual mode statistics */ while (flag) { printf("%d units available\n", Ship.energy); extra = 0; flag = 0; for (i = 0; i < NBANKS; i++) { b = &bank[i]; printf("\nBank %d:\n", i); hit = getintpar("units"); if (hit < 0) return; if (hit == 0) break; extra += hit; if (extra > Ship.energy) { printf("available energy exceeded. "); skiptonl(0); flag++; break; } b->units = hit; hit = getintpar("course"); if (hit < 0 || hit > 360) return; b->angle = hit * 0.0174532925; b->spread = getfltpar("spread"); if (b->spread < 0 || b->spread > 1) return; } Ship.energy -= extra; } extra = 0; } else { /* automatic distribution of power */ if (Etc.nkling <= 0) return (printf("Sulu: But there are no Klingons in this quadrant\n")); printf("Phasers locked on target. "); while (flag) { printf("%d units available\n", Ship.energy); hit = getintpar("Units to fire"); if (hit <= 0) return; if (hit > Ship.energy) { printf("available energy exceeded. "); skiptonl(0); continue; } flag = 0; Ship.energy -= hit; extra = hit; n = Etc.nkling; if (n > NBANKS) n = NBANKS; tot = n * (n + 1) / 2; for (i = 0; i < n; i++) { k = &Etc.klingon[i]; b = &bank[i]; distfactor = k->dist; anglefactor = ALPHA * BETA * OMEGA / (distfactor * distfactor + EPSILON); anglefactor *= GAMMA; distfactor = k->power; distfactor /= anglefactor; hitreqd[i] = distfactor + 0.5; dx = Ship.sectx - k->x; dy = k->y - Ship.secty; b->angle = atan2(dy, dx); b->spread = 0.0; b->units = ((n - i) / tot) * extra; # ifdef xTRACE if (Trace) { printf("b%d hr%d u%d df%.2f af%.2f\n", i, hitreqd[i], b->units, distfactor, anglefactor); } # endif extra -= b->units; hit = b->units - hitreqd[i]; if (hit > 0) { extra += hit; b->units -= hit; } } /* give out any extra energy we might have around */ if (extra > 0) { for (i = 0; i < n; i++) { b = &bank[i]; hit = hitreqd[i] - b->units; if (hit <= 0) continue; if (hit >= extra) { b->units += extra; extra = 0; break; } b->units = hitreqd[i]; extra -= hit; } if (extra > 0) printf("%d units overkill\n", extra); } } } # ifdef xTRACE if (Trace) { for (i = 0; i < NBANKS; i++) { b = &bank[i]; printf("b%d u%d", i, b->units); if (b->units > 0) printf(" a%.2f s%.2f\n", b->angle, b->spread); else printf("\n"); } } # endif /* actually fire the shots */ Move.free = 0; for (i = 0; i < NBANKS; i++) { b = &bank[i]; if (b->units <= 0) { continue; } printf("\nPhaser bank %d fires:\n", i); n = Etc.nkling; k = Etc.klingon; for (j = 0; j < n; j++) { if (b->units <= 0) break; /* ** The formula for hit is as follows: ** ** zap = OMEGA * [(sigma + ALPHA) * (rho + BETA)] ** / (dist ** 2 + EPSILON)] ** * [cos(delta * sigma) + GAMMA] ** * hit ** ** where sigma is the spread factor, ** rho is a random number (0 -> 1), ** GAMMA is a crud factor for angle (essentially ** cruds up the spread factor), ** delta is the difference in radians between the ** angle you are shooting at and the actual ** angle of the klingon, ** ALPHA scales down the significance of sigma, ** BETA scales down the significance of rho, ** OMEGA is the magic number which makes everything ** up to "* hit" between zero and one, ** dist is the distance to the klingon ** hit is the number of units in the bank, and ** zap is the amount of the actual hit. ** ** Everything up through dist squared should maximize ** at 1.0, so that the distance factor is never ** greater than one. Conveniently, cos() is ** never greater than one, but the same restric- ** tion applies. */ distfactor = BETA + franf(); distfactor *= ALPHA + b->spread; distfactor *= OMEGA; anglefactor = k->dist; distfactor /= anglefactor * anglefactor + EPSILON; distfactor *= b->units; dx = Ship.sectx - k->x; dy = k->y - Ship.secty; anglefactor = atan2(dy, dx) - b->angle; anglefactor = cos((anglefactor * b->spread) + GAMMA); if (anglefactor < 0.0) { k++; continue; } hit = anglefactor * distfactor + 0.5; k->power -= hit; printf("%d unit hit on Klingon", hit); if (!damaged(SRSCAN)) printf(" at %d,%d", k->x, k->y); printf("\n"); b->units -= hit; if (k->power <= 0) { killk(k->x, k->y); continue; } k++; } } /* compute overkill */ for (i = 0; i < NBANKS; i++) extra += bank[i].units; if (extra > 0) printf("\n%d units expended on empty space\n", extra); }
static void finishtimeout (void) { strerr_warnw1x("finish script takes too long - killing it") ; killc() ; killk() ; settimeout(3) ; }