long getynpar(const char *s) { struct cvntab *r; r = getcodpar(s, Yntab); return ((long) r->value); }
void play() { while (1) { Move.free = 1; Move.time = 0.0; Move.shldchg = 0; Move.newquad = 0; Move.resting = 0; skiptonl(0); const struct cvntab* r = getcodpar("\nCommand", Comtab); (*r->value)(r->value2); events(0); attack(0); checkcond(); } }
void setup() { const struct cvntab *r; int i, j; double f; int d; int klump; int ix, iy; struct quad *q; struct event *e; while (1) { r = getcodpar("What length game", Lentab); Game.length = (long) r->value; if (Game.length == 0) { if (restartgame()) continue; return; } break; } r = getcodpar("What skill game", Skitab); Game.skill = (long) r->value; Game.tourn = 0; getstrpar("Enter a password", Game.passwd, 14, 0); if (strcmp(Game.passwd, "tournament") == 0) { getstrpar("Enter tournament code", Game.passwd, 14, 0); Game.tourn = 1; d = 0; for (i = 0; Game.passwd[i]; i++) d += Game.passwd[i] << i; srand(d); } Param.bases = Now.bases = ranf(6 - Game.skill) + 2; if (Game.skill == 6) Param.bases = Now.bases = 1; Param.time = Now.time = 6.0 * Game.length + 2.0; i = Game.skill; j = Game.length; Param.klings = Now.klings = i * j * 3.5 * (franf() + 0.75); if (Param.klings < i * j * 5) Param.klings = Now.klings = i * j * 5; if (Param.klings <= i) /* numerical overflow problems */ Param.klings = Now.klings = 127; Param.energy = Ship.energy = 5000; Param.torped = Ship.torped = 10; Ship.ship = ENTERPRISE; Ship.shipname = "Enterprise"; Param.shield = Ship.shield = 1500; Param.resource = Now.resource = Param.klings * Param.time; Param.reserves = Ship.reserves = (6 - Game.skill) * 2.0; Param.crew = Ship.crew = 387; Param.brigfree = Ship.brigfree = 400; Ship.shldup = 1; Ship.cond = GREEN; Ship.warp = 5.0; Ship.warp2 = 25.0; Ship.warp3 = 125.0; Ship.sinsbad = 0; Ship.cloaked = 0; Param.date = Now.date = (ranf(20) + 20) * 100; f = Game.skill; f = log(f + 0.5); for (i = 0; i < NDEV; i++) if (Device[i].name[0] == '*') Param.damfac[i] = 0; else Param.damfac[i] = f; /* these probabilities must sum to 1000 */ Param.damprob[WARP] = 70; /* warp drive 7.0% */ Param.damprob[SRSCAN] = 110; /* short range scanners 11.0% */ Param.damprob[LRSCAN] = 110; /* long range scanners 11.0% */ Param.damprob[PHASER] = 125; /* phasers 12.5% */ Param.damprob[TORPED] = 125; /* photon torpedoes 12.5% */ Param.damprob[IMPULSE] = 75; /* impulse engines 7.5% */ Param.damprob[SHIELD] = 150; /* shield control 15.0% */ Param.damprob[COMPUTER] = 20; /* computer 2.0% */ Param.damprob[SSRADIO] = 35; /* subspace radio 3.5% */ Param.damprob[LIFESUP] = 30; /* life support 3.0% */ Param.damprob[SINS] = 20; /* navigation system 2.0% */ Param.damprob[CLOAK] = 50; /* cloaking device 5.0% */ Param.damprob[XPORTER] = 80; /* transporter 8.0% */ /* check to see that I didn't blow it */ for (i = j = 0; i < NDEV; i++) j += Param.damprob[i]; if (j != 1000) errx(1, "Device probabilities sum to %d", j); Param.dockfac = 0.5; Param.regenfac = (5 - Game.skill) * 0.05; if (Param.regenfac < 0.0) Param.regenfac = 0.0; Param.warptime = 10; Param.stopengy = 50; Param.shupengy = 40; i = Game.skill; Param.klingpwr = 100 + 150 * i; if (i >= 6) Param.klingpwr += 150; Param.phasfac = 0.8; Param.hitfac = 0.5; Param.klingcrew = 200; Param.srndrprob = 0.0035; Param.moveprob[KM_OB] = 45; Param.movefac[KM_OB] = .09; Param.moveprob[KM_OA] = 40; Param.movefac[KM_OA] = -0.05; Param.moveprob[KM_EB] = 40; Param.movefac[KM_EB] = 0.075; Param.moveprob[KM_EA] = 25 + 5 * Game.skill; Param.movefac[KM_EA] = -0.06 * Game.skill; Param.moveprob[KM_LB] = 0; Param.movefac[KM_LB] = 0.0; Param.moveprob[KM_LA] = 10 + 10 * Game.skill; Param.movefac[KM_LA] = 0.25; Param.eventdly[E_SNOVA] = 0.5; Param.eventdly[E_LRTB] = 25.0; Param.eventdly[E_KATSB] = 1.0; Param.eventdly[E_KDESB] = 3.0; Param.eventdly[E_ISSUE] = 1.0; Param.eventdly[E_SNAP] = 0.5; Param.eventdly[E_ENSLV] = 0.5; Param.eventdly[E_REPRO] = 2.0; Param.navigcrud[0] = 1.50; Param.navigcrud[1] = 0.75; Param.cloakenergy = 1000; Param.energylow = 1000; for (i = 0; i < MAXEVENTS; i++) { e = &Event[i]; e->date = 1e50; e->evcode = 0; } xsched(E_SNOVA, 1, 0, 0, 0); xsched(E_LRTB, Param.klings, 0, 0, 0); xsched(E_KATSB, 1, 0, 0, 0); xsched(E_ISSUE, 1, 0, 0, 0); xsched(E_SNAP, 1, 0, 0, 0); Ship.sectx = ranf(NSECTS); Ship.secty = ranf(NSECTS); Game.killk = Game.kills = Game.killb = 0; Game.deaths = Game.negenbar = 0; Game.captives = 0; Game.killinhab = 0; Game.helps = 0; Game.killed = 0; Game.snap = 0; Move.endgame = 0; /* setup stars */ for (i = 0; i < NQUADS; i++) for (j = 0; j < NQUADS; j++) { q = &Quad[i][j]; q->klings = q->bases = 0; q->scanned = -1; q->stars = ranf(9) + 1; q->holes = ranf(3) - q->stars / 5; if (q->holes < 0) q->holes = 0; q->qsystemname = 0; } /* select inhabited starsystems */ for (d = 1; d < NINHAB; d++) { do { i = ranf(NQUADS); j = ranf(NQUADS); q = &Quad[i][j]; } while (q->qsystemname); q->qsystemname = d; } /* position starbases */ for (i = 0; i < Param.bases; i++) { while (1) { ix = ranf(NQUADS); iy = ranf(NQUADS); q = &Quad[ix][iy]; if (q->bases > 0) continue; break; } q->bases = 1; Now.base[i].x = ix; Now.base[i].y = iy; q->scanned = 1001; /* start the Enterprise near starbase */ if (i == 0) { Ship.quadx = ix; Ship.quady = iy; } } /* position klingons */ for (i = Param.klings; i > 0; ) { klump = ranf(4) + 1; if (klump > i) klump = i; while (1) { ix = ranf(NQUADS); iy = ranf(NQUADS); q = &Quad[ix][iy]; if (q->klings + klump > MAXKLQUAD) continue; q->klings += klump; i -= klump; break; } } /* initialize this quadrant */ printf("%d Klingons\n%d starbase", Param.klings, Param.bases); if (Param.bases > 1) printf("s"); printf(" at %d,%d", Now.base[0].x, Now.base[0].y); for (i = 1; i < Param.bases; i++) printf(", %d,%d", Now.base[i].x, Now.base[i].y); printf("\nIt takes %d units to kill a Klingon\n", Param.klingpwr); Move.free = 0; initquad(0); srscan(1); attack(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); }
computer() { int ix, iy; register int i, j; int numout; int tqx, tqy; struct cvntab *r; int cost; int course; double dist, time; double warpfact; struct quad *q; register struct event *e; if (check_out(COMPUTER)) return; while (1) { r = getcodpar("\nRequest", Cputab); switch ((int)r->value) { case 1: /* star chart */ printf("Computer record of galaxy for all long range sensor scans\n\n"); printf(" "); /* print top header */ for (i = 0; i < NQUADS; i++) printf("-%d- ", i); printf("\n"); for (i = 0; i < NQUADS; i++) { printf("%d ", i); for (j = 0; j < NQUADS; j++) { if (i == Ship.quadx && j == Ship.quady) { printf("$$$ "); continue; } q = &Quad[i][j]; /* 1000 or 1001 is special case */ if (q->scanned >= 1000) if (q->scanned > 1000) printf(".1. "); else printf("/// "); else if (q->scanned < 0) printf("... "); else printf("%3d ", q->scanned); } printf("%d\n", i); } printf(" "); /* print bottom footer */ for (i = 0; i < NQUADS; i++) printf("-%d- ", i); printf("\n"); break; case 2: /* trajectory */ if (check_out(SRSCAN)) { break; } if (Etc.nkling <= 0) { printf("No Klingons in this quadrant\n"); break; } /* for each Klingon, give the course & distance */ for (i = 0; i < Etc.nkling; i++) { printf("Klingon at %d,%d", Etc.klingon[i].x, Etc.klingon[i].y); course = kalc(Ship.quadx, Ship.quady, Etc.klingon[i].x, Etc.klingon[i].y, &dist); prkalc(course, dist); } break; case 3: /* course calculation */ if (readdelim('/')) { tqx = Ship.quadx; tqy = Ship.quady; } else { ix = getintpar("Quadrant"); if (ix < 0 || ix >= NSECTS) break; iy = getintpar("q-y"); if (iy < 0 || iy >= NSECTS) break; tqx = ix; tqy = iy; } ix = getintpar("Sector"); if (ix < 0 || ix >= NSECTS) break; iy = getintpar("s-y"); if (iy < 0 || iy >= NSECTS) break; course = kalc(tqx, tqy, ix, iy, &dist); if (r->value2) { warp(-1, course, dist); break; } printf("%d,%d/%d,%d to %d,%d/%d,%d", Ship.quadx, Ship.quady, Ship.sectx, Ship.secty, tqx, tqy, ix, iy); prkalc(course, dist); break; case 4: /* score */ score(); break; case 5: /* phaser effectiveness */ dist = getfltpar("range"); if (dist < 0.0) break; dist *= 10.0; cost = pow(0.90, dist) * 98.0 + 0.5; printf("Phasers are %d%% effective at that range\n", cost); break; case 6: /* warp cost (time/energy) */ dist = getfltpar("distance"); if (dist < 0.0) break; warpfact = getfltpar("warp factor"); if (warpfact <= 0.0) warpfact = Ship.warp; cost = (dist + 0.05) * warpfact * warpfact * warpfact; time = Param.warptime * dist / (warpfact * warpfact); printf("Warp %.2f distance %.2f cost %.2f stardates %d (%d w/ shlds up) units\n", warpfact, dist, time, cost, cost + cost); break; case 7: /* impulse cost */ dist = getfltpar("distance"); if (dist < 0.0) break; cost = 20 + 100 * dist; time = dist / 0.095; printf("Distance %.2f cost %.2f stardates %d units\n", dist, time, cost); break; case 8: /* distresslist */ j = 1; printf("\n"); /* scan the event list */ for (i = 0; i < MAXEVENTS; i++) { e = &Event[i]; /* ignore hidden entries */ if (e->evcode & E_HIDDEN) continue; switch (e->evcode & E_EVENT) { case E_KDESB: printf("Klingon is attacking starbase in quadrant %d,%d\n", e->x, e->y); j = 0; break; case E_ENSLV: case E_REPRO: printf("Starsystem %s in quadrant %d,%d is distressed\n", Systemname[e->systemname], e->x, e->y); j = 0; break; } } if (j) printf("No known distress calls are active\n"); break; } /* skip to next semicolon or newline. Semicolon * means get new computer request; newline means * exit computer mode. */ while ((i = cgetc(0)) != ';') { if (i == '\0') exit(1); if (i == '\n') { ungetc(i, stdin); return; } } } }