6 prout("-SUPER- STAR TREK");
\r
8 prout("Latest update-21 Sept 78");
\r
12 void freeze(int boss) {
\r
17 strcpy(citem, "emsave.trk");
\r
20 if ((key = scan()) == IHEOL) {
\r
21 proutn("File name: ");
\r
24 if (key != IHALPHA) {
\r
29 if (strchr(citem, '.') == NULL) {
\r
30 strcat(citem, ".trk");
\r
33 if ((fp = fopen(citem, "wb")) == NULL) {
\r
34 proutn("Can't freeze game as file ");
\r
39 fwrite(&state, sizeof(state), 1, fp);
\r
40 fwrite(&snapsht, sizeof(snapsht), 1, fp);
\r
41 fwrite(&frozen, sizeof(frozen), 1, fp);
\r
45 /* I hope that's enough! */
\r
54 frozen.passwd[0] = '\0';
\r
55 if ((key = scan()) == IHEOL) {
\r
56 proutn("File name: ");
\r
59 if (key != IHALPHA) {
\r
64 if (strchr(citem, '.') == NULL) {
\r
65 strcat(citem, ".trk");
\r
67 if ((fp = fopen(citem, "rb")) == NULL) {
\r
68 proutn("Can't find game file ");
\r
73 fread(&state, sizeof(state), 1, fp);
\r
74 fread(&snapsht, sizeof(snapsht), 1, fp);
\r
75 fread(&frozen, sizeof(frozen), 1, fp);
\r
79 /* I hope that's enough! */
\r
86 if (condit==IHDOCKED) {
\r
88 prout("You cannot abandon Ye Faerie Queene.");
\r
93 /* Must take shuttle craft to exit */
\r
94 if (frozen.damage[DSHUTTL]==-1) {
\r
95 prout("Ye Faerie Queene has no shuttle craft.");
\r
98 if (frozen.damage[DSHUTTL]<0) {
\r
99 prout("Shuttle craft now serving Big Mac's.");
\r
102 if (frozen.damage[DSHUTTL]>0) {
\r
103 prout("Shuttle craft damaged.");
\r
107 prout("You must be aboard the Enterprise.");
\r
111 prout("Shuttle craft not currently available.");
\r
114 /* Print abandon ship messages */
\r
116 prouts("***ABANDON SHIP! ABANDON SHIP!");
\r
118 prouts("***ALL HANDS ABANDON SHIP!");
\r
120 prout("Captain and crew escape in shuttle craft.");
\r
121 prout("Remainder of ship's complement beam down");
\r
122 prout("to nearest habitable planet.");
\r
123 if (state.rembase==0) {
\r
124 /* Ops! no place to go... */
\r
128 /* If at least one base left, give 'em the Faerie Queene */
\r
130 icrystl = 0; /* crystals are lost */
\r
131 nprobes = 0; /* No probes */
\r
132 prout("You are captured by Klingons and released to");
\r
133 prout("the Federation in a prisoner-of-war exchange.");
\r
134 nb = Rand()*state.rembase+1;
\r
135 /* Set up quadrant and position FQ adjacient to base */
\r
136 if (quadx!=state.baseqx[nb] || quady!=state.baseqy[nb]) {
\r
137 quadx = state.baseqx[nb];
\r
138 quady = state.baseqy[nb];
\r
143 /* position next to base by trial and error */
\r
144 frozen.quad[sectx][secty] = IHDOT;
\r
145 for (l = 1; l <= 10; l++) {
\r
146 sectx = 3.0*Rand() - 1.0 + basex;
\r
147 secty = 3.0*Rand() - 1.0 + basey;
\r
148 if (sectx >= 1 && sectx <= 10 &&
\r
149 secty >= 1 && secty <= 10 &&
\r
150 frozen.quad[sectx][secty] == IHDOT) break;
\r
152 if (l < 11) break; /* found a spot */
\r
158 /* Get new commission */
\r
159 frozen.quad[sectx][secty] = ship = IHF;
\r
160 prout("Starfleet puts you in command of another ship,");
\r
161 prout("the Faerie Queene, which is antiquated but,");
\r
162 prout("still useable.");
\r
163 if (icrystl!=0) prout("The dilithium crystals have been moved.");
\r
165 iscraft=0; /* Gallileo disappears */
\r
166 /* Resupply ship */
\r
168 for (l = 1; l <= ndevice; l++) frozen.damage[l] = 0.0;
\r
169 frozen.damage[DSHUTTL] = -1;
\r
170 energy = inenrg = 3000.0;
\r
171 shield = inshld = 1250.0;
\r
172 torps = intorps = 6;
\r
181 int i,j, krem, klumper;
\r
183 alldone = gamewon = 0;
\r
187 // Decide how many of everything
\r
188 if (choose()) return; // frozen game
\r
189 // Prepare the Enterprise
\r
191 energy = inenrg = 5000.0;
\r
192 shield = inshld = 2500.0;
\r
193 shldchg = shldup = 0;
\r
196 iran8(&quadx, &quady);
\r
197 iran10(§x, §y);
\r
198 torps = intorps = 10;
\r
199 nprobes = (int)(3.0*Rand() + 2.0); /* Give them 2-4 of these wonders */
\r
201 wfacsq = warpfac * warpfac;
\r
202 for (i=0; i <= ndevice; i++) frozen.damage[i] = 0.0;
\r
203 // Set up assorted game parameters
\r
205 state.date = indate = 100.0*(int)(31.0*Rand()+20.0);
\r
206 state.killk = state.killc = nkinks = nhelp = resting = casual = state.nromkl = 0;
\r
207 isatb = iscate = imine = icrystl = icraft = state.nsckill = state.nplankl = 0;
\r
212 for (i = 1; i <= 8; i++)
\r
213 for (j = 1; j <= 8; j++) state.newstuf[i][j] = frozen.starch[i][j] = 0;
\r
214 // Initialize times for extraneous events
\r
215 frozen.future[FSNOVA] = state.date + expran(0.5 * intime);
\r
216 frozen.future[FTBEAM] = state.date + expran(1.5 * (intime / state.remcom));
\r
217 frozen.future[FSNAP] = state.date + 1.0 + Rand(); // Force an early snapshot
\r
218 frozen.future[FBATTAK] = state.date + expran(0.3*intime);
\r
219 frozen.future[FCDBAS] = 1e30;
\r
220 frozen.future[FSCMOVE] = state.nscrem ? state.date+0.2777 : 1e30;
\r
221 frozen.future[FSCDBAS] = 1e30;
\r
222 frozen.future[FDSPROB] = 1e30;
\r
223 // Starchart is functional
\r
225 // Put stars in the galaxy
\r
227 for (i=1; i<=8; i++)
\r
228 for (j=1; j<=8; j++) {
\r
229 int k = Rand()*9.0 + 1.0;
\r
231 state.galaxy[i][j] = k;
\r
233 // Locate star bases in galaxy
\r
234 for (i = 1; i <= inbase; i++) {
\r
237 do iran8(&ix, &iy);
\r
238 while (state.galaxy[ix][iy] >= 10);
\r
240 for (j = i-1; j > 0; j--) {
\r
241 /* Improved placement algorithm to spread out bases */
\r
242 double distq = square(ix-state.baseqx[j]) + square(iy-state.baseqy[j]);
\r
243 if (distq < 6.0*(6-inbase) && Rand() < 0.75) {
\r
246 printf("DEBUG: Abandoning base #%d at %d-%d\n", i, ix, iy);
\r
251 else if (distq < 6.0 * (6-inbase)) {
\r
252 printf("DEBUG: saving base #%d, close to #%d\n", i, j);
\r
256 } while (contflag);
\r
258 state.baseqx[i] = ix;
\r
259 state.baseqy[i] = iy;
\r
260 frozen.starch[ix][iy] = -1;
\r
261 state.galaxy[ix][iy] += 10;
\r
263 // Position ordinary Klingon Battle Cruisers
\r
264 krem = inkling - incom - state.nscrem;
\r
265 klumper = 0.25*skill*(9.0-length)+1.0;
\r
266 if (klumper > 9) klumper = 9; // Can't have more than 9 in quadrant
\r
269 int klump = (1.0 - r*r)*klumper;
\r
270 if (klump > krem) klump = krem;
\r
273 do iran8(&ix, &iy);
\r
274 while (state.galaxy[ix][iy] + klump >= 1000);
\r
275 state.galaxy[ix][iy] += klump;
\r
276 } while (krem > 0);
\r
277 // Position Klingon Commander Ships
\r
281 for (i = 1; i <= incom; i++) {
\r
283 do { /* IF debugging, put commanders by bases, always! */
\r
285 if (idebug && klumper <= inbase) {
\r
286 ix = state.baseqx[klumper];
\r
287 iy = state.baseqy[klumper];
\r
294 while ((state.galaxy[ix][iy] < 99 && Rand() < 0.75)||
\r
295 state.galaxy[ix][iy]>899);
\r
296 // check for duplicate
\r
297 for (j = 1; j < i; j++)
\r
298 if (state.cx[j]==ix && state.cy[j]==iy) break;
\r
300 state.galaxy[ix][iy] += 100;
\r
304 // Locate planets in galaxy
\r
305 for (i = 1; i <= inplan; i++) {
\r
306 do iran8(&ix, &iy);
\r
307 while (state.newstuf[ix][iy] > 0);
\r
308 state.newstuf[ix][iy] = 1;
\r
309 state.plnets[i].x = ix;
\r
310 state.plnets[i].y = iy;
\r
311 state.plnets[i].pclass = Rand()*3.0 + 1.0; // Planet class M N or O
\r
312 state.plnets[i].crystals = 1.5*Rand(); // 1 in 3 chance of crystals
\r
313 state.plnets[i].known = 0;
\r
316 for (i = 1; i <= state.nromrem; i++) {
\r
318 state.newstuf[ix][iy] += 10;
\r
320 // Locate the Super Commander
\r
321 if (state.nscrem > 0) {
\r
322 do iran8(&ix, &iy);
\r
323 while (state.galaxy[ix][iy] >= 900);
\r
326 state.galaxy[ix][iy] += 100;
\r
328 // Place thing (in tournament game, thingx == -1, don't want one!)
\r
329 if (Rand() < 0.1 && thingx != -1) {
\r
330 iran8(&thingx, &thingy);
\r
333 thingx = thingy = 0;
\r
341 printf("It is stardate %d. The Federation is being attacked by\n",
\r
343 printf("a deadly Klingon invasion force. As captain of the United\n"
\r
344 "Starship U.S.S. Enterprise, it is your mission to seek out\n"
\r
345 "and destroy this invasion force of %d battle cruisers.\n",
\r
347 printf("You have an initial allotment of %d stardates to complete\n"
\r
348 "your mission. As you proceed you may be given more time.\n\n"
\r
349 "You will have %d supporting starbases.\n"
\r
350 "Starbase locations- ",
\r
351 (int)intime, inbase);
\r
354 printf("Stardate %d.\n\n"
\r
355 "%d Klingons.\nAn unknown number of Romulans\n",
\r
356 (int)state.date, inkling);
\r
357 if (state.nscrem) printf("and one (GULP) Super-Commander.\n");
\r
358 printf("%d stardates\n%d starbases in ",(int)intime, inbase);
\r
360 for (i = 1; i <= inbase; i++) {
\r
361 cramlc(0, state.baseqx[i], state.baseqy[i]);
\r
362 if (i < inbase) proutn(" ");
\r
365 proutn("The Enterprise is currently in");
\r
366 cramlc(1, quadx, quady);
\r
368 cramlc(2, sectx, secty);
\r
370 prout("Good Luck!");
\r
371 if (state.nscrem) proutn(" YOU'LL NEED IT.");
\r
374 if (nenhere) shldup=1.0;
\r
375 if (neutz) attack(0); // bad luck to start in a Romulan Neutral Zone
\r
384 if (fromcommandline) /* Can start with command line options */
\r
385 fromcommandline = 0;
\r
387 proutn("Would you like a regular, tournament, or frozen game?");
\r
389 if (strlen(citem)==0) continue; // Try again
\r
390 if (isit("tournament")) {
\r
391 while (scan() == IHEOL) {
\r
392 proutn("Type in tournament number-");
\r
396 continue; // We don't want a blank entry
\r
398 tourn = (int)aaitem;
\r
400 srand((unsigned int)(int)aaitem);
\r
403 if (isit("frozen")) {
\r
406 if (*frozen.passwd==0) continue;
\r
408 Rand(); Rand(); Rand(); Rand();
\r
409 if (!alldone) thawed = 1; // No plaque if not finished
\r
413 if (isit("regular")) {
\r
416 Rand(); Rand(); Rand(); Rand();
\r
419 proutn("What is \"");
\r
424 while (length==0 || skill==0) {
\r
425 if (scan() == IHALPHA) {
\r
426 if (isit("short")) length = 1;
\r
427 else if (isit("medium")) length = 2;
\r
428 else if (isit("long")) length = 4;
\r
429 else if (isit("novice")) skill = 1;
\r
430 else if (isit("fair")) skill = 2;
\r
431 else if (isit("good")) skill = 3;
\r
432 else if (isit("expert")) skill = 4;
\r
433 else if (isit("emeritus")) skill = 5;
\r
435 proutn("What is \"");
\r
442 if (length==0) proutn("Would you like a Short, Medium, or Long game? ");
\r
443 else if (skill == 0) proutn("Are you a Novice, Fair, Good, Expert, or Emeritus player?");
\r
448 strcpy(frozen.passwd, citem);
\r
450 if (*frozen.passwd != 0) break;
\r
451 proutn("Please type in a secret password-");
\r
454 if (strcmp(frozen.passwd, "debug")==0) idebug = 1;
\r
457 // Use parameters to generate initial values of things
\r
458 damfac = 0.5 * skill;
\r
459 state.rembase = 3.0*Rand()+2.0;
\r
460 inbase = state.rembase;
\r
461 inplan = (PLNETMAX/2) + (PLNETMAX/2+1)*Rand();
\r
462 state.nromrem = (2.0+Rand())*skill;
\r
463 state.nscrem = (skill > 2? 1 : 0);
\r
464 state.remtime = 7.0 * length;
\r
465 intime = state.remtime;
\r
466 state.remkl = 2.0*intime*((skill+1 - 2*Rand())*skill*0.1+.15);
\r
467 inkling = state.remkl;
\r
468 incom = skill + 0.0625*inkling*Rand();
\r
469 state.remcom= min(10, incom);
\r
470 incom = state.remcom;
\r
471 state.remres = (inkling+4*incom)*intime;
\r
472 inresor = state.remres;
\r
473 if (inkling > 50) {
\r
474 inbase = (state.rembase += 1);
\r
479 void dropin(int iquad, int *ix, int *iy) {
\r
481 while (frozen.quad[*ix][*iy] != IHDOT);
\r
482 frozen.quad[*ix][*iy] = iquad;
\r
485 void newcnd(void) {
\r
487 if (energy < 1000.0) condit = IHYELLOW;
\r
488 if (state.galaxy[quadx][quady] > 99 || state.newstuf[quadx][quady] > 9)
\r
493 void newqad(int shutup) {
\r
494 int quadnum = state.galaxy[quadx][quady];
\r
495 int newnum = state.newstuf[quadx][quady];
\r
496 int i, j, ix, iy, nplan;
\r
503 plnetx = plnety = 0;
\r
515 // Attempt to escape Super-commander, so tbeam back!
\r
520 for (i=1; i <= 10; i++)
\r
521 for (j=1; j <= 10; j++) frozen.quad[i][j] = IHDOT;
\r
522 // cope with supernova
\r
523 if (quadnum > 999) {
\r
526 klhere = quadnum/100;
\r
527 irhere = newnum/10;
\r
529 nenhere = klhere + irhere;
\r
531 // Position Starship
\r
532 frozen.quad[sectx][secty] = ship;
\r
534 // Decide if quadrant needs a Tholian
\r
535 if ((skill < 3 && Rand() <= 0.02) || /* Lighten up if skill is low */
\r
536 (skill == 3 && Rand() <= 0.05) ||
\r
537 (skill > 3 && Rand() <= 0.08)
\r
539 || strcmp(frozen.passwd, "tholianx")==0
\r
543 ithx = Rand() > 0.5 ? 10 : 1;
\r
544 ithy = Rand() > 0.5 ? 10 : 1;
\r
545 } while (frozen.quad[ithx][ithy] != IHDOT);
\r
546 frozen.quad[ithx][ithy] = IHT;
\r
548 /* Reserve unocupied corners */
\r
549 if (frozen.quad[1][1]==IHDOT) frozen.quad[1][1] = 'X';
\r
550 if (frozen.quad[1][10]==IHDOT) frozen.quad[1][10] = 'X';
\r
551 if (frozen.quad[10][1]==IHDOT) frozen.quad[10][1] = 'X';
\r
552 if (frozen.quad[10][10]==IHDOT) frozen.quad[10][10] = 'X';
\r
555 if (quadnum >= 100) {
\r
556 // Position ordinary Klingons
\r
557 quadnum -= 100*klhere;
\r
558 for (i = 1; i <= klhere; i++) {
\r
559 dropin(IHK, &ix, &iy);
\r
562 frozen.kdist[i] = frozen.kavgd[i] = sqrt(square(sectx-ix) + square(secty-iy));
\r
563 frozen.kpower[i] = Rand()*150.0 +300.0 +25.0*skill;
\r
565 // If we need a commander, promote a Klingon
\r
566 for (i = 1; i <= state.remcom ; i++)
\r
567 if (state.cx[i]==quadx && state.cy[i]==quady) break;
\r
569 if (i <= state.remcom) {
\r
570 frozen.quad[ix][iy] = IHC;
\r
571 frozen.kpower[klhere] = 950.0+400.0*Rand()+50.0*skill;
\r
575 // If we need a super-commander, promote a Klingon
\r
576 if (quadx == state.isx && quady == state.isy) {
\r
577 frozen.quad[frozen.kx[1]][frozen.ky[1]] = IHS;
\r
578 frozen.kpower[1] = 1175.0 + 400.0*Rand() + 125.0*skill;
\r
583 // Put in Romulans if needed
\r
584 for (i = klhere+1; i <= nenhere; i++) {
\r
585 dropin(IHR, &ix, &iy);
\r
588 frozen.kdist[i] = frozen.kavgd[i] = sqrt(square(sectx-ix) + square(secty-iy));
\r
589 frozen.kpower[i] = Rand()*400.0 + 450.0 + 50.0*skill;
\r
592 // If quadrant needs a starbase, put it in
\r
593 if (quadnum >= 10) {
\r
595 dropin(IHB, &basex, &basey);
\r
599 // If quadrant needs a planet, put it in
\r
600 for (i=1; i <= inplan; i++)
\r
601 if (state.plnets[i].x == quadx && state.plnets[i].y == quady) break;
\r
604 dropin(IHP, &plnetx, &plnety);
\r
607 // Check for condition
\r
609 // And finally the stars
\r
610 for (i = 1; i <= quadnum; i++) dropin(IHSTAR, &ix, &iy);
\r
613 if (irhere > 0 && klhere == 0 && basex == 0) {
\r
615 if (frozen.damage[DRADIO] <= 0.0) {
\r
617 prout("LT. Uhura- \"Captain, an urgent message.");
\r
618 prout(" I'll put it on audio.\" CLICK");
\r
620 prout("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE.");
\r
621 prout("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!");
\r
626 // Put in THING if needed
\r
627 if (thingx == quadx && thingy == quady) {
\r
628 dropin(IHQUEST, &ix, &iy);
\r
629 thingx = thingy = 0; // Transient
\r
630 if (frozen.damage[DSRSENS] == 0.0) {
\r
632 prout("MR. SPOCK- \"Captain, this is most unusual.");
\r
633 prout(" Please examine your short-range scan.\"");
\r
638 // Put in a few black holes
\r
639 for (i = 1; i <= 3; i++)
\r
640 if (Rand() > 0.5) dropin(IHBLANK, &ix, &iy);
\r
642 // Take out X's in corners if Tholian present
\r
644 if (frozen.quad[1][1]=='X') frozen.quad[1][1] = IHDOT;
\r
645 if (frozen.quad[1][10]=='X') frozen.quad[1][10] = IHDOT;
\r
646 if (frozen.quad[10][1]=='X') frozen.quad[10][1] = IHDOT;
\r
647 if (frozen.quad[10][10]=='X') frozen.quad[10][10] = IHDOT;
\r
651 void sortkl(void) {
\r
655 // The author liked bubble sort. So we will use it. :-(
\r
657 if (nenhere < 2) return;
\r
661 for (j = 1; j < nenhere; j++)
\r
662 if (frozen.kdist[j] > frozen.kdist[j+1]) {
\r
664 t = frozen.kdist[j];
\r
665 frozen.kdist[j] = frozen.kdist[j+1];
\r
666 frozen.kdist[j+1] = t;
\r
667 t = frozen.kavgd[j];
\r
668 frozen.kavgd[j] = frozen.kavgd[j+1];
\r
669 frozen.kavgd[j+1] = t;
\r
671 frozen.kx[j] = frozen.kx[j+1];
\r
672 frozen.kx[j+1] = k;
\r
674 frozen.ky[j] = frozen.ky[j+1];
\r
675 frozen.ky[j+1] = k;
\r
676 t = frozen.kpower[j];
\r
677 frozen.kpower[j] = frozen.kpower[j+1];
\r
678 frozen.kpower[j+1] = t;
\r