REmove half the conditionals.
[super-star-trek.git] / setup.c
1 #include <time.h>
2 #include <sys/stat.h>
3 #include "conio.h"
4 #include "sst.h"
5
6 #ifdef __linux__
7 static long filelength(int fd) {
8 struct stat buf;
9     fstat(fd, &buf);
10     return buf.st_size;
11 }
12 #endif
13
14 void prelim(void) {
15         skip(2);
16         prout("-SUPER- STAR TREK");
17         skip(1);
18 #ifndef __HISTORICAL__
19         prout("Latest update-21 Sept 78");
20         skip(1);
21 #endif /* __HISTORICAL__ */
22 }
23
24 void freeze(int boss) {
25         FILE *fp;
26         int key;
27         if (boss) {
28                 strcpy(citem, "emsave.trk");
29         }
30         else {
31                 if ((key = scan()) == IHEOL) {
32                         proutn("File name: ");
33                         key = scan();
34                 }
35                 if (key != IHALPHA) {
36                         huh();
37                         return;
38                 }
39                 chew();
40                 if (strchr(citem, '.') == NULL) {
41                         strcat(citem, ".trk");
42                 }
43         }
44         if ((fp = fopen(citem, "wb")) == NULL) {
45                 proutn("Can't freeze game as file ");
46                 proutn(citem);
47                 skip(1);
48                 return;
49         }
50         strcpy(game.magic, SSTMAGIC);
51         fwrite(&game, sizeof(game), 1, fp);
52
53         fclose(fp);
54
55         /* I hope that's enough! */
56 }
57
58
59 int thaw(void) {
60         FILE *fp;
61         int key;
62
63         game.passwd[0] = '\0';
64         if ((key = scan()) == IHEOL) {
65                 proutn("File name: ");
66                 key = scan();
67         }
68         if (key != IHALPHA) {
69                 huh();
70                 return 1;
71         }
72         chew();
73         if (strchr(citem, '.') == NULL) {
74                 strcat(citem, ".trk");
75         }
76         if ((fp = fopen(citem, "rb")) == NULL) {
77                 proutn("Can't find game file ");
78                 proutn(citem);
79                 skip(1);
80                 return 1;
81         }
82         fread(&game, sizeof(game), 1, fp);
83         if (feof(fp) || ftell(fp) != filelength(fileno(fp)) || strcmp(game.magic, SSTMAGIC)) {
84                 prout("Game file format is bad, should begin with " SSTMAGIC);
85                 skip(1);
86                 fclose(fp);
87                 return 1;
88         }
89
90         fclose(fp);
91
92         return 0;
93 }
94
95 void abandn(void) {
96         int nb, l;
97
98         chew();
99         if (condit==IHDOCKED) {
100                 if (ship!=IHE) {
101                         prout("You cannot abandon Ye Faerie Queene.");
102                         return;
103                 }
104         }
105         else {
106                 /* Must take shuttle craft to exit */
107                 if (game.damage[DSHUTTL]==-1) {
108                         prout("Ye Faerie Queene has no shuttle craft.");
109                         return;
110                 }
111                 if (game.damage[DSHUTTL]<0) {
112                         prout("Shuttle craft now serving Big Mac's.");
113                         return;
114                 }
115                 if (game.damage[DSHUTTL]>0) {
116                         prout("Shuttle craft damaged.");
117                         return;
118                 }
119                 if (landed==1) {
120                         prout("You must be aboard the Enterprise.");
121                         return;
122                 }
123                 if (iscraft!=1) {
124                         prout("Shuttle craft not currently available.");
125                         return;
126                 }
127                 /* Print abandon ship messages */
128                 skip(1);
129                 prouts("***ABANDON SHIP!  ABANDON SHIP!");
130                 skip(1);
131                 prouts("***ALL HANDS ABANDON SHIP!");
132                 skip(2);
133                 prout("Captain and crew escape in shuttle craft.");
134                 prout("Remainder of ship's complement beam down");
135                 prout("to nearest habitable planet.");
136                 if (game.state.rembase==0) {
137                         /* Ops! no place to go... */
138                         finish(FABANDN);
139                         return;
140                 }
141                 /* If at least one base left, give 'em the Faerie Queene */
142                 skip(1);
143                 icrystl = 0; /* crystals are lost */
144                 nprobes = 0; /* No probes */
145                 prout("You are captured by Klingons and released to");
146                 prout("the Federation in a prisoner-of-war exchange.");
147                 nb = Rand()*game.state.rembase+1;
148                 /* Set up quadrant and position FQ adjacient to base */
149                 if (quadx!=game.state.baseqx[nb] || quady!=game.state.baseqy[nb]) {
150                         quadx = game.state.baseqx[nb];
151                         quady = game.state.baseqy[nb];
152                         sectx = secty = 5;
153                         newqad(1);
154                 }
155                 for (;;) {
156                         /* position next to base by trial and error */
157                         game.quad[sectx][secty] = IHDOT;
158                         for (l = 1; l <= 10; l++) {
159                                 sectx = 3.0*Rand() - 1.0 + basex;
160                                 secty = 3.0*Rand() - 1.0 + basey;
161                                 if (sectx >= 1 && sectx <= 10 &&
162                                         secty >= 1 && secty <= 10 &&
163                                         game.quad[sectx][secty] == IHDOT) break;
164                         }
165                         if (l < 11) break; /* found a spot */
166                         sectx=5;
167                         secty=5;
168                         newqad(1);
169                 }
170         }
171         /* Get new commission */
172         game.quad[sectx][secty] = ship = IHF;
173         prout("Starfleet puts you in command of another ship,");
174         prout("the Faerie Queene, which is antiquated but,");
175         prout("still useable.");
176         if (icrystl!=0) prout("The dilithium crystals have been moved.");
177         imine=0;
178         iscraft=0; /* Gallileo disappears */
179         /* Resupply ship */
180         condit=IHDOCKED;
181         for (l = 1; l <= NDEVICES; l++) game.damage[l] = 0.0;
182         game.damage[DSHUTTL] = -1;
183         energy = inenrg = 3000.0;
184         shield = inshld = 1250.0;
185         torps = intorps = 6;
186         lsupres=inlsr=3.0;
187         shldup=0;
188         warpfac=5.0;
189         wfacsq=25.0;
190         return;
191 }
192         
193 void setup(int needprompt) {
194         int i,j, krem, klumper;
195         int ix, iy;
196 #ifdef DEBUG
197         idebug = 0;
198 #endif
199         //  Decide how many of everything
200         if (choose(needprompt)) return; // frozen game
201         // Prepare the Enterprise
202         alldone = gamewon = 0;
203         ship = IHE;
204         energy = inenrg = 5000.0;
205         shield = inshld = 2500.0;
206         shldchg = shldup = 0;
207         inlsr = 4.0;
208         lsupres = 4.0;
209         iran8(&quadx, &quady);
210         iran10(&sectx, &secty);
211         torps = intorps = 10;
212         nprobes = (int)(3.0*Rand() + 2.0);      /* Give them 2-4 of these wonders */
213         warpfac = 5.0;
214         wfacsq = warpfac * warpfac;
215         for (i=0; i <= NDEVICES; i++) game.damage[i] = 0.0;
216         // Set up assorted game parameters
217         batx = baty = 0;
218         game.state.date = indate = 100.0*(int)(31.0*Rand()+20.0);
219         game.state.killk = game.state.killc = nkinks = nhelp = resting = casual = game.state.nromkl = 0;
220         isatb = iscate = imine = icrystl = icraft = game.state.nsckill = game.state.nplankl = 0;
221         game.state.starkl = game.state.basekl = 0;
222         iscraft = 1;
223         landed = -1;
224         alive = 1;
225         docfac = 0.25;
226         for (i = 1; i <= 8; i++)
227                 for (j = 1; j <= 8; j++) game.state.newstuf[i][j] = game.starch[i][j] = 0;
228         // Initialize times for extraneous events
229         game.future[FSNOVA] = game.state.date + expran(0.5 * intime);
230         game.future[FTBEAM] = game.state.date + expran(1.5 * (intime / game.state.remcom));
231         game.future[FSNAP] = game.state.date + 1.0 + Rand(); // Force an early snapshot
232         game.future[FBATTAK] = game.state.date + expran(0.3*intime);
233         game.future[FCDBAS] = 1e30;
234         game.future[FSCMOVE] = game.state.nscrem ? game.state.date+0.2777 : 1e30;
235         game.future[FSCDBAS] = 1e30;
236         game.future[FDSPROB] = 1e30;
237         // Starchart is functional
238         stdamtim = 1e30;
239         // Put stars in the galaxy
240         instar = 0;
241         for (i=1; i<=8; i++)
242                 for (j=1; j<=8; j++) {
243                         int k = Rand()*9.0 + 1.0;
244                         instar += k;
245                         game.state.galaxy[i][j] = k;
246                 }
247         // Locate star bases in galaxy
248         for (i = 1; i <= inbase; i++) {
249                 int contflag;
250                 do {
251                         do iran8(&ix, &iy);
252                         while (game.state.galaxy[ix][iy] >= 10);
253                         contflag = FALSE;
254                         for (j = i-1; j > 0; j--) {
255                                 /* Improved placement algorithm to spread out bases */
256                                 double distq = square(ix-game.state.baseqx[j]) + square(iy-game.state.baseqy[j]);
257                                 if (distq < 6.0*(6-inbase) && Rand() < 0.75) {
258                                         contflag = TRUE;
259 #ifdef DEBUG
260                                         proutn("DEBUG: Abandoning base #%d at %d-%d\n", i, ix, iy);
261 #endif
262                                         break;
263                                 }
264 #ifdef DEBUG
265                                 else if (distq < 6.0 * (6-inbase)) {
266                                         proutn("DEBUG: saving base #%d, close to #%d\n", i, j);
267                                 }
268 #endif
269                         }
270                 } while (contflag);
271                         
272                 game.state.baseqx[i] = ix;
273                 game.state.baseqy[i] = iy;
274                 game.starch[ix][iy] = -1;
275                 game.state.galaxy[ix][iy] += 10;
276         }
277         // Position ordinary Klingon Battle Cruisers
278         krem = inkling - incom - game.state.nscrem;
279         klumper = 0.25*skill*(9.0-length)+1.0;
280         if (klumper > 9) klumper = 9; // Can't have more than 9 in quadrant
281         do {
282                 double r = Rand();
283                 int klump = (1.0 - r*r)*klumper;
284                 if (klump > krem) klump = krem;
285                 krem -= klump;
286                 klump *= 100;
287                 do iran8(&ix, &iy);
288                 while (game.state.galaxy[ix][iy] + klump >= 1000);
289                 game.state.galaxy[ix][iy] += klump;
290         } while (krem > 0);
291         // Position Klingon Commander Ships
292 #ifdef DEBUG
293         klumper = 1;
294 #endif
295         for (i = 1; i <= incom; i++) {
296                 do {
297                         do { /* IF debugging, put commanders by bases, always! */
298 #ifdef DEBUG
299                                 if (idebug && klumper <= inbase) {
300                                         ix = game.state.baseqx[klumper];
301                                         iy = game.state.baseqy[klumper];
302                                         klumper++;
303                                 }
304                                 else
305 #endif
306                                         iran8(&ix, &iy);
307                         }
308                         while ((game.state.galaxy[ix][iy] < 99 && Rand() < 0.75)||
309                                    game.state.galaxy[ix][iy]>899);
310                         // check for duplicate
311                         for (j = 1; j < i; j++)
312                                 if (game.state.cx[j]==ix && game.state.cy[j]==iy) break;
313                 } while (j < i);
314                 game.state.galaxy[ix][iy] += 100;
315                 game.state.cx[i] = ix;
316                 game.state.cy[i] = iy;
317         }
318         // Locate planets in galaxy
319         for (i = 0; i < inplan; i++) {
320                 do iran8(&ix, &iy);
321                 while (game.state.newstuf[ix][iy] > 0);
322                 game.state.newstuf[ix][iy] = 1;
323                 game.state.plnets[i].x = ix;
324                 game.state.plnets[i].y = iy;
325                 game.state.plnets[i].pclass = Rand()*3.0; // Planet class M N or O
326                 game.state.plnets[i].crystals = 1.5*Rand();             // 1 in 3 chance of crystals
327                 game.state.plnets[i].known = unknown;
328         }
329         // Locate Romulans
330         for (i = 1; i <= game.state.nromrem; i++) {
331                 iran8(&ix, &iy);
332                 game.state.newstuf[ix][iy] += 10;
333         }
334         // Locate the Super Commander
335         if (game.state.nscrem > 0) {
336                 do iran8(&ix, &iy);
337                 while (game.state.galaxy[ix][iy] >= 900);
338                 game.state.isx = ix;
339                 game.state.isy = iy;
340                 game.state.galaxy[ix][iy] += 100;
341         }
342         // Place thing (in tournament game, thingx == -1, don't want one!)
343         if (thingx != -1) {
344                 iran8(&thingx, &thingy);
345         }
346         else {
347                 thingx = thingy = 0;
348         }
349
350 //      idate = date;
351         skip(2);
352         game.state.snap = 0;
353                 
354         if (skill == 1) {
355                 prout("It is stardate %d. The Federation is being attacked by",
356                            (int)game.state.date);
357                 prout("a deadly Klingon invasion force. As captain of the United");
358                 prout("Starship U.S.S. Enterprise, it is your mission to seek out");
359                 prout("and destroy this invasion force of %d battle cruisers.",
360                            inkling);
361                 prout("You have an initial allotment of %d stardates to complete", (int)intime);
362                 prout("your mission.  As you proceed you may be given more time.");
363                 prout("");
364                 prout("You will have %d supporting starbases.", inbase);
365                 proutn("Starbase locations-  ");
366         }
367         else {
368                 prout("Stardate %d.", (int)game.state.date);
369                 prout("");
370                 prout("%d Klingons.", inkling);
371                 prout("An unknown number of Romulans.");
372                 if (game.state.nscrem) prout("and one (GULP) Super-Commander.");
373                         prout("%d stardates.",(int)intime);
374                         proutn("%d starbases in ", inbase);
375         }
376         for (i = 1; i <= inbase; i++) {
377                 proutn(cramlc(0, game.state.baseqx[i], game.state.baseqy[i]));
378                 proutn("  ");
379         }
380         skip(2);
381         proutn("The Enterprise is currently in ");
382         proutn(cramlc(quadrant, quadx, quady));
383         proutn(" ");
384         proutn(cramlc(sector, sectx, secty));
385         skip(2);
386         prout("Good Luck!");
387         if (game.state.nscrem) prout("  YOU'LL NEED IT.");
388 #ifdef SERGEEV
389         getche();
390 #endif /* SERGEEV */
391         newqad(0);
392         if (nenhere-iqhere-ithere) shldup=1.0;
393         if (neutz) attack(0);   // bad luck to start in a Romulan Neutral Zone
394 }
395
396 void randomize(void) {
397         srand((int)time(NULL));
398 }
399
400 int choose(int needprompt) {
401         while (TRUE) {
402         tourn = 0;
403         thawed = 0;
404         skill = 0;
405         length = 0;
406                 if (needprompt) /* Can start with command line options */
407                         proutn("Would you like a regular, tournament, or saved game? ");
408                 scan();
409                 if (strlen(citem)==0) continue; // Try again
410                 if (isit("tournament")) {
411                         while (scan() == IHEOL) {
412                                 proutn("Type in tournament number-");
413                         }
414                         if (aaitem == 0) {
415                                 chew();
416                                 continue; // We don't want a blank entry
417                         }
418                         tourn = (int)aaitem;
419                         thingx = -1;
420                         srand((unsigned int)(int)aaitem);
421                         break;
422                 }
423                 if (isit("frozen") || isit("frozen")) {
424                         if (thaw()) continue;
425                         chew();
426 #ifndef SERGEEV
427                         if (*game.passwd==0) continue;
428                         randomize();
429                         Rand(); Rand(); Rand(); Rand();
430 #endif
431                         if (!alldone) thawed = 1; // No plaque if not finished
432                         report();
433 #ifdef SERGEEV
434                         getche();
435 #endif /* SERGEEV */
436                         return TRUE;
437                 }
438                 if (isit("regular")) break;
439                 proutn("What is \"");
440                 proutn(citem);
441                 prout("\"?");
442                 chew();
443         }
444         while (length==0 || skill==0) {
445                 if (scan() == IHALPHA) {
446                         if (isit("short")) length = 1;
447                         else if (isit("medium")) length = 2;
448                         else if (isit("long")) length = 4;
449                         else if (isit("novice")) skill = 1;
450                         else if (isit("fair")) skill = 2;
451                         else if (isit("good")) skill = 3;
452                         else if (isit("expert")) skill = 4;
453                         else if (isit("emeritus")) skill = 5;
454                         else {
455                                 proutn("What is \"");
456                                 proutn(citem);
457                                 prout("\"?");
458                         }
459                 }
460                 else {
461                         chew();
462                         if (length==0) proutn("Would you like a Short, Medium, or Long game? ");
463                         else if (skill == 0) proutn("Are you a Novice, Fair, Good, Expert, or Emeritus player? ");
464                 }
465         }
466 #ifndef SERGEEV
467         while (TRUE) {
468                 scan();
469                 strcpy(game.passwd, citem);
470                 chew();
471                 if (*game.passwd != 0) break;
472                 proutn("Please type in a secret password-");
473         }
474 #else
475         for(i=0;i<3;i++) game.passwd[i]=(char)(97+(int)(Rand()*25));
476         game.passwd[3]=0;
477 #endif /* SERGEEV */
478 #ifdef DEBUG
479         if (strcmp(game.passwd, "debug")==0) idebug = 1;
480 #endif
481
482         // Use parameters to generate initial values of things
483         damfac = 0.5 * skill;
484         game.state.rembase = 3.0*Rand()+2.0;
485         inbase = game.state.rembase;
486         inplan = (PLNETMAX/2) + (PLNETMAX/2+1)*Rand();
487         game.state.nromrem = (2.0+Rand())*skill;
488         game.state.nscrem = (skill > 2? 1 : 0);
489         game.state.remtime = 7.0 * length;
490         intime = game.state.remtime;
491         game.state.remkl = 2.0*intime*((skill+1 - 2*Rand())*skill*0.1+.15);
492         inkling = game.state.remkl;
493         incom = skill + 0.0625*inkling*Rand();
494         game.state.remcom= min(10, incom);
495         incom = game.state.remcom;
496         game.state.remres = (inkling+4*incom)*intime;
497         inresor = game.state.remres;
498         if (inkling > 50) {
499                 inbase = (game.state.rembase += 1);
500         }
501         return FALSE;
502 }
503
504 void dropin(int iquad, int *ix, int *iy) {
505         do iran10(ix, iy);
506         while (game.quad[*ix][*iy] != IHDOT);
507         game.quad[*ix][*iy] = iquad;
508 }
509
510 void newcnd(void) {
511         condit = IHGREEN;
512         if (energy < 1000.0) condit = IHYELLOW;
513         if (game.state.galaxy[quadx][quady] > 99 || game.state.newstuf[quadx][quady] > 9)
514                 condit = IHRED;
515         if (!alive) condit=IHDEAD;
516 }
517
518
519 void newqad(int shutup) {
520         int quadnum = game.state.galaxy[quadx][quady];
521         int newnum = game.state.newstuf[quadx][quady];
522         int i, j, ix, iy, nplan;
523
524         iattak = 1;
525         justin = 1;
526         basex = basey = 0;
527         klhere = 0;
528         comhere = 0;
529         plnetx = plnety = 0;
530         ishere = 0;
531         irhere = 0;
532         iplnet = 0;
533         nenhere = 0;
534         neutz = 0;
535         inorbit = 0;
536         landed = -1;
537         ientesc = 0;
538         ithere = 0;
539         iqhere=0;
540         iqengry=0;
541         iseenit = 0;
542         if (iscate) {
543                 // Attempt to escape Super-commander, so tbeam back!
544                 iscate = 0;
545                 ientesc = 1;
546         }
547         // Clear quadrant
548         for (i=1; i <= 10; i++)
549                 for (j=1; j <= 10; j++) game.quad[i][j] = IHDOT;
550         // cope with supernova
551         if (quadnum > 999) {
552                 return;
553         }
554         klhere = quadnum/100;
555         irhere = newnum/10;
556         nplan = newnum%10;
557         nenhere = klhere + irhere;
558
559         // Position Starship
560         game.quad[sectx][secty] = ship;
561
562         if (quadnum >= 100) {
563                 // Position ordinary Klingons
564                 quadnum -= 100*klhere;
565                 for (i = 1; i <= klhere; i++) {
566                         dropin(IHK, &ix, &iy);
567                         game.kx[i] = ix;
568                         game.ky[i] = iy;
569                         game.kdist[i] = game.kavgd[i] = sqrt(square(sectx-ix) + square(secty-iy));
570                         game.kpower[i] = Rand()*150.0 +300.0 +25.0*skill;
571                 }
572                 // If we need a commander, promote a Klingon
573                 for (i = 1; i <= game.state.remcom ; i++) 
574                         if (game.state.cx[i]==quadx && game.state.cy[i]==quady) break;
575                         
576                 if (i <= game.state.remcom) {
577                         game.quad[ix][iy] = IHC;
578                         game.kpower[klhere] = 950.0+400.0*Rand()+50.0*skill;
579                         comhere = 1;
580                 }
581
582                 // If we need a super-commander, promote a Klingon
583                 if (quadx == game.state.isx && quady == game.state.isy) {
584                         game.quad[game.kx[1]][game.ky[1]] = IHS;
585                         game.kpower[1] = 1175.0 + 400.0*Rand() + 125.0*skill;
586                         iscate = game.state.remkl>1;
587                         ishere = 1;
588                 }
589         }
590         // Put in Romulans if needed
591         for (i = klhere+1; i <= nenhere; i++) {
592                 dropin(IHR, &ix, &iy);
593                 game.kx[i] = ix;
594                 game.ky[i] = iy;
595                 game.kdist[i] = game.kavgd[i] = sqrt(square(sectx-ix) + square(secty-iy));
596                 game.kpower[i] = Rand()*400.0 + 450.0 + 50.0*skill;
597         }
598         // If quadrant needs a starbase, put it in
599         if (quadnum >= 10) {
600                 quadnum -= 10;
601                 dropin(IHB, &basex, &basey);
602         }
603         
604         if (nplan) {
605                 // If quadrant needs a planet, put it in
606                 for (i=0; i < inplan; i++)
607                         if (game.state.plnets[i].x == quadx && game.state.plnets[i].y == quady) break;
608                 if (i < inplan) {
609                         iplnet = i;
610                         dropin(IHP, &plnetx, &plnety);
611                 }
612         }
613         // Check for condition
614         newcnd();
615         // And finally the stars
616         for (i = 1; i <= quadnum; i++) dropin(IHSTAR, &ix, &iy);
617
618         // Check for RNZ
619         if (irhere > 0 && klhere == 0) {
620                 neutz = 1;
621                 if (game.damage[DRADIO] <= 0.0) {
622                         skip(1);
623                         prout("LT. Uhura- \"Captain, an urgent message.");
624                         prout("  I'll put it on audio.\"  CLICK");
625                         skip(1);
626                         prout("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE.");
627                         prout("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!");
628                 }
629         }
630
631         if (shutup==0) {
632                 // Put in THING if needed
633                 if (thingx == quadx && thingy == quady) {
634                         dropin(IHQUEST, &ix, &iy);
635                         iran8(&thingx, &thingy);
636                         nenhere++;
637                         iqhere=1;
638                         game.kx[nenhere] = ix;
639                         game.ky[nenhere] = iy;
640                         game.kdist[nenhere] = game.kavgd[nenhere] =
641                             sqrt(square(sectx-ix) + square(secty-iy));
642                         game.kpower[nenhere] = Rand()*6000.0 +500.0 +250.0*skill;
643                         if (game.damage[DSRSENS] == 0.0) {
644                                 skip(1);
645                                 prout("MR. SPOCK- \"Captain, this is most unusual.");
646                                 prout("    Please examine your short-range scan.\"");
647                         }
648                 }
649         }
650
651         // Decide if quadrant needs a Tholian
652         if ((skill < 3 && Rand() <= 0.02) ||   /* Lighten up if skill is low */
653                 (skill == 3 && Rand() <= 0.05) ||
654                 (skill > 3 && Rand() <= 0.08)
655 #ifdef DEBUG
656                 || strcmp(passwd, "tholianx")==0
657 #endif
658                 ) {
659                 do {
660                         ithx = Rand() > 0.5 ? 10 : 1;
661                         ithy = Rand() > 0.5 ? 10 : 1;
662                 } while (game.quad[ithx][ithy] != IHDOT);
663                 game.quad[ithx][ithy] = IHT;
664                 ithere = 1;
665                 nenhere++;
666                 game.kx[nenhere] = ithx;
667                 game.ky[nenhere] = ithy;
668                 game.kdist[nenhere] = game.kavgd[nenhere] =
669                     sqrt(square(sectx-ithx) + square(secty-ithy));
670                 game.kpower[nenhere] = Rand()*400.0 +100.0 +25.0*skill;
671                 /* Reserve unocupied corners */
672                 if (game.quad[1][1]==IHDOT) game.quad[1][1] = 'X';
673                 if (game.quad[1][10]==IHDOT) game.quad[1][10] = 'X';
674                 if (game.quad[10][1]==IHDOT) game.quad[10][1] = 'X';
675                 if (game.quad[10][10]==IHDOT) game.quad[10][10] = 'X';
676         }
677         sortkl();
678
679         // Put in a few black holes
680         for (i = 1; i <= 3; i++)
681                 if (Rand() > 0.5) dropin(IHBLANK, &ix, &iy);
682
683         // Take out X's in corners if Tholian present
684         if (ithere) {
685                 if (game.quad[1][1]=='X') game.quad[1][1] = IHDOT;
686                 if (game.quad[1][10]=='X') game.quad[1][10] = IHDOT;
687                 if (game.quad[10][1]=='X') game.quad[10][1] = IHDOT;
688                 if (game.quad[10][10]=='X') game.quad[10][10] = IHDOT;
689         }               
690 }
691
692 void sortkl(void) {
693         double t;
694         int sw, j, k;
695
696         // The author liked bubble sort. So we will use it. :-(
697
698         if (nenhere-iqhere-ithere < 2) return;
699
700         do {
701                 sw = FALSE;
702                 for (j = 1; j < nenhere; j++)
703                         if (game.kdist[j] > game.kdist[j+1]) {
704                                 sw = TRUE;
705                                 t = game.kdist[j];
706                                 game.kdist[j] = game.kdist[j+1];
707                                 game.kdist[j+1] = t;
708                                 t = game.kavgd[j];
709                                 game.kavgd[j] = game.kavgd[j+1];
710                                 game.kavgd[j+1] = t;
711                                 k = game.kx[j];
712                                 game.kx[j] = game.kx[j+1];
713                                 game.kx[j+1] = k;
714                                 k = game.ky[j];
715                                 game.ky[j] = game.ky[j+1];
716                                 game.ky[j+1] = k;
717                                 t = game.kpower[j];
718                                 game.kpower[j] = game.kpower[j+1];
719                                 game.kpower[j+1] = t;
720                         }
721         } while (sw);
722 }