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