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