Added the ability to suppress newer features with a game type option.
[super-star-trek.git] / setup.c
diff --git a/setup.c b/setup.c
index 7509711e16d65755d605532b30e2bd0a43b48b90..88884671d08a488c83ddda8e44045680c4ef9b3b 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -156,11 +156,10 @@ void abandn(void)
        for (;;) {
            /* position next to base by trial and error */
            game.quad[sectx][secty] = IHDOT;
-           for (l = 1; l <= QUADSIZE; l++) {
+           for_sectors(l) {
                sectx = 3.0*Rand() - 1.0 + basex;
                secty = 3.0*Rand() - 1.0 + basey;
-               if (sectx >= 1 && sectx <= QUADSIZE &&
-                   secty >= 1 && secty <= QUADSIZE &&
+               if (VALID_SECTOR(sectx, secty) &&
                    game.quad[sectx][secty] == IHDOT) break;
            }
            if (l < QUADSIZE+1) break; /* found a spot */
@@ -179,7 +178,8 @@ void abandn(void)
     iscraft=0; /* Gallileo disappears */
     /* Resupply ship */
     condit=IHDOCKED;
-    for (l = 1; l <= NDEVICES; l++) game.damage[l] = 0.0;
+    for (l = 0; l < NDEVICES; l++) 
+       game.damage[l] = 0.0;
     game.damage[DSHUTTL] = -1;
     energy = inenrg = 3000.0;
     shield = inshld = 1250.0;
@@ -214,58 +214,66 @@ void setup(int needprompt)
     nprobes = (int)(3.0*Rand() + 2.0); /* Give them 2-4 of these wonders */
     warpfac = 5.0;
     wfacsq = warpfac * warpfac;
-    for (i=0; i <= NDEVICES; i++) game.damage[i] = 0.0;
+    for (i=0; i < NDEVICES; i++) 
+       game.damage[i] = 0.0;
     // Set up assorted game parameters
     batx = baty = 0;
     game.state.date = indate = 100.0*(int)(31.0*Rand()+20.0);
-    game.state.killk = game.state.killc = nkinks = nhelp = resting = casual = game.state.nromkl = 0;
-    isatb = iscate = imine = icrystl = icraft = game.state.nsckill = game.state.nplankl = 0;
+    nkinks = nhelp = resting = casual = 0;
+    isatb = iscate = imine = icrystl = icraft = game.state.nplankl = 0;
     game.state.starkl = game.state.basekl = 0;
     iscraft = 1;
     landed = -1;
     alive = 1;
     docfac = 0.25;
-    for (i = 1; i <= GALSIZE; i++)
-       for (j = 1; j <= GALSIZE; j++) game.state.newstuf[i][j] = game.starch[i][j] = 0;
+    for_quadrants(i)
+       for_quadrants(j) {
+           game.state.galaxy[i][j].charted = 0;
+           game.state.galaxy[i][j].planets = 0;
+           game.state.galaxy[i][j].romulans = 0;
+           game.state.galaxy[i][j].klingons = 0;
+           game.state.galaxy[i][j].starbase = 0;
+           game.state.galaxy[i][j].supernova = 0;
+       }
     // Initialize times for extraneous events
     game.future[FSNOVA] = game.state.date + expran(0.5 * intime);
     game.future[FTBEAM] = game.state.date + expran(1.5 * (intime / game.state.remcom));
     game.future[FSNAP] = game.state.date + 1.0 + Rand(); // Force an early snapshot
     game.future[FBATTAK] = game.state.date + expran(0.3*intime);
-    game.future[FCDBAS] = 1e30;
-    game.future[FSCMOVE] = game.state.nscrem ? game.state.date+0.2777 : 1e30;
-    game.future[FSCDBAS] = 1e30;
-    game.future[FDSPROB] = 1e30;
-    // Starchart is functional
-    stdamtim = 1e30;
+    game.future[FCDBAS] = FOREVER;
+    game.future[FSCMOVE] = game.state.nscrem ? game.state.date+0.2777 : FOREVER;
+    game.future[FSCDBAS] = FOREVER;
+    game.future[FDSPROB] = FOREVER;
+    // Starchart is functional but we've never seen it
+    lastchart = FOREVER;
     // Put stars in the galaxy
     instar = 0;
-    for (i=1; i<=GALSIZE; i++)
-       for (j=1; j<=GALSIZE; j++) {
+    for_quadrants(i)
+       for_quadrants(j) {
            int k = Rand()*9.0 + 1.0;
            instar += k;
-           game.state.galaxy[i][j] = k * STAR_PLACE;
+           game.state.galaxy[i][j].stars = k;
        }
     // Locate star bases in galaxy
     for (i = 1; i <= inbase; i++) {
        int contflag;
        do {
            do iran(GALSIZE, &ix, &iy);
-           while (BASES(game.state.galaxy[ix][iy]));
+           while (game.state.galaxy[ix][iy].starbase);
            contflag = FALSE;
            for (j = i-1; j > 0; j--) {
                /* Improved placement algorithm to spread out bases */
                double distq = square(ix-game.state.baseqx[j]) + square(iy-game.state.baseqy[j]);
-               if (distq < 6.0*(BASEMAX-inbase) && Rand() < 0.75) {
+               if (distq < 6.0*(BASEMAX+1-inbase) && Rand() < 0.75) {
                    contflag = TRUE;
 #ifdef DEBUG
-                   proutn("DEBUG: Abandoning base #%d at %d-%d\n", i, ix, iy);
+                   prout("DEBUG: Abandoning base #%d at %d-%d", i, ix, iy);
 #endif
                    break;
                }
 #ifdef DEBUG
-               else if (distq < 6.0 * (BASEMAX-inbase)) {
-                   proutn("DEBUG: saving base #%d, close to #%d\n", i, j);
+               else if (distq < 6.0 * (BASEMAX+1-inbase)) {
+                   prout("DEBUG: saving base #%d, close to #%d", i, j);
                }
 #endif
            }
@@ -273,11 +281,11 @@ void setup(int needprompt)
                        
        game.state.baseqx[i] = ix;
        game.state.baseqy[i] = iy;
-       game.starch[ix][iy] = CHART_UNKNOWN;
-       game.state.galaxy[ix][iy] += BASE_PLACE;
+       game.state.galaxy[ix][iy].starbase = 1;
+       game.state.chart[ix][iy].starbase = 1;
     }
     // Position ordinary Klingon Battle Cruisers
-    krem = inkling - incom - game.state.nscrem;
+    krem = inkling;
     klumper = 0.25*skill*(9.0-length)+1.0;
     if (klumper > 9) klumper = 9; // Can't have more than 9 in quadrant
     do {
@@ -285,10 +293,10 @@ void setup(int needprompt)
        int klump = (1.0 - r*r)*klumper;
        if (klump > krem) klump = krem;
        krem -= klump;
-       klump *= KLINGON_PLACE;
-       do iran(GALSIZE, &ix, &iy);
-       while (game.state.galaxy[ix][iy] + klump >= SUPERNOVA_PLACE);
-       game.state.galaxy[ix][iy] += klump;
+       do iran(GALSIZE,&ix,&iy);
+       while (game.state.galaxy[ix][iy].supernova ||
+               game.state.galaxy[ix][iy].klingons + klump > 9);
+       game.state.galaxy[ix][iy].klingons += klump;
     } while (krem > 0);
     // Position Klingon Commander Ships
 #ifdef DEBUG
@@ -307,21 +315,21 @@ void setup(int needprompt)
 #endif
                    iran(GALSIZE, &ix, &iy);
            }
-           while ((game.state.galaxy[ix][iy] <= KLINGON_PLACE && Rand() < 0.75)||
-                  NOEXIT(game.state.galaxy[ix][iy]));
+           while ((!game.state.galaxy[ix][iy].klingons && Rand() < 0.75)||
+                  game.state.galaxy[ix][iy].supernova||
+                  game.state.galaxy[ix][iy].klingons > 8);
            // check for duplicate
            for (j = 1; j < i; j++)
                if (game.state.cx[j]==ix && game.state.cy[j]==iy) break;
        } while (j < i);
-       game.state.galaxy[ix][iy] += KLINGON_PLACE;
+       game.state.galaxy[ix][iy].klingons++;
        game.state.cx[i] = ix;
        game.state.cy[i] = iy;
     }
     // Locate planets in galaxy
     for (i = 0; i < inplan; i++) {
-       do iran(GALSIZE, &ix, &iy);
-       while (game.state.newstuf[ix][iy] > 0);
-       game.state.newstuf[ix][iy] = 1;
+       do iran(GALSIZE, &ix, &iy); while (game.state.galaxy[ix][iy].planets);
+       game.state.galaxy[ix][iy].planets = 1;
        game.state.plnets[i].x = ix;
        game.state.plnets[i].y = iy;
        game.state.plnets[i].pclass = Rand()*3.0; // Planet class M N or O
@@ -331,15 +339,15 @@ void setup(int needprompt)
     // Locate Romulans
     for (i = 1; i <= game.state.nromrem; i++) {
        iran(GALSIZE, &ix, &iy);
-       game.state.newstuf[ix][iy] += ROMULAN_PLACE;
+       game.state.galaxy[ix][iy].romulans = 1;
     }
     // Locate the Super Commander
     if (game.state.nscrem > 0) {
        do iran(GALSIZE, &ix, &iy);
-       while (game.state.galaxy[ix][iy] >= 900);
+       while (game.state.galaxy[ix][iy].supernova || game.state.galaxy[ix][iy].klingons > 8);
        game.state.isx = ix;
        game.state.isy = iy;
-       game.state.galaxy[ix][iy] += KLINGON_PLACE;
+       game.state.galaxy[ix][iy].klingons++;
     }
     // Place thing (in tournament game, thingx == -1, don't want one!)
     if (thingx != -1) {
@@ -359,7 +367,7 @@ void setup(int needprompt)
        prout("a deadly Klingon invasion force. As captain of the United");
        prout("Starship U.S.S. Enterprise, it is your mission to seek out");
        prout("and destroy this invasion force of %d battle cruisers.",
-             inkling);
+             INKLINGTOT);
        prout("You have an initial allotment of %d stardates to complete", (int)intime);
        prout("your mission.  As you proceed you may be given more time.");
        prout("");
@@ -369,7 +377,7 @@ void setup(int needprompt)
     else {
        prout("Stardate %d.", (int)game.state.date);
        prout("");
-       prout("%d Klingons.", inkling);
+       prout("%d Klingons.", INKLINGTOT);
        prout("An unknown number of Romulans.");
        if (game.state.nscrem) prout("and one (GULP) Super-Commander.");
        prout("%d stardates.",(int)intime);
@@ -459,6 +467,23 @@ int choose(int needprompt)
            else if (skill == SKILL_NONE) proutn("Are you a Novice, Fair, Good, Expert, or Emeritus player? ");
        }
     }
+    // Choose game options -- added by ESR for SST2K
+    if (scan() != IHALPHA) {
+       chew();
+       proutn("Choose your game options: ");
+       scan();
+    }
+    if (isit("plain"))
+       // Approximates the UT FORTRAN version.
+       game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE);
+    if (isit("almy"))
+       // Approximates Tom Almy's version.
+       game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE);
+    else if (strlen(citem)) {
+           proutn("What is \"");
+           proutn(citem);
+           prout("\"?");
+    }
     setpassword();
 #ifdef DEBUG
     if (strcmp(game.passwd, "debug")==0) idebug = 1;
@@ -466,17 +491,17 @@ int choose(int needprompt)
 
     // Use parameters to generate initial values of things
     damfac = 0.5 * skill;
-    game.state.rembase = 3.0*Rand()+2.0;
+    game.state.rembase = 2.0 + Rand()*(BASEMAX-2.0);
     inbase = game.state.rembase;
-    inplan = (PLNETMAX/2) + (PLNETMAX/2+1)*Rand();
-    game.state.nromrem = (2.0+Rand())*skill;
-    game.state.nscrem = (skill > SKILL_FAIR ? 1 : 0);
+    if (game.options & OPTION_PLANETS)
+       inplan = (PLNETMAX/2) + (PLNETMAX/2+1)*Rand();
+    game.state.nromrem = inrom = (2.0+Rand())*skill;
+    game.state.nscrem = inscom = (skill > SKILL_FAIR ? 1 : 0);
     game.state.remtime = 7.0 * length;
     intime = game.state.remtime;
-    game.state.remkl = 2.0*intime*((skill+1 - 2*Rand())*skill*0.1+.15);
-    inkling = game.state.remkl;
+    game.state.remkl = inkling = 2.0*intime*((skill+1 - 2*Rand())*skill*0.1+.15);
     incom = skill + 0.0625*inkling*Rand();
-    game.state.remcom= min(10, incom);
+    game.state.remcom = min(10, incom);
     incom = game.state.remcom;
     game.state.remres = (inkling+4*incom)*intime;
     inresor = game.state.remres;
@@ -497,7 +522,7 @@ void newcnd(void)
 {
     condit = IHGREEN;
     if (energy < 1000.0) condit = IHYELLOW;
-    if (game.state.galaxy[quadx][quady] >= KLINGON_PLACE || game.state.newstuf[quadx][quady] >= ROMULAN_PLACE)
+    if (game.state.galaxy[quadx][quady].klingons || game.state.galaxy[quadx][quady].romulans)
        condit = IHRED;
     if (!alive) condit=IHDEAD;
 }
@@ -505,8 +530,6 @@ void newcnd(void)
 
 void newqad(int shutup) 
 {
-    int quadnum = game.state.galaxy[quadx][quady];
-    int newnum = game.state.newstuf[quadx][quady];
     int i, j, ix, iy, nplan;
 
     iattak = 1;
@@ -533,23 +556,22 @@ void newqad(int shutup)
        ientesc = 1;
     }
     // Clear quadrant
-    for (i=1; i <= QUADSIZE; i++)
-       for (j=1; j <= QUADSIZE; j++) game.quad[i][j] = IHDOT;
+    for_sectors(i)
+       for_sectors(j) 
+           game.quad[i][j] = IHDOT;
     // cope with supernova
-    if (quadnum >= SUPERNOVA_PLACE) {
+    if (game.state.galaxy[quadx][quady].supernova)
        return;
-    }
-    klhere = KLINGONS(quadnum);
-    irhere = ROMULANS(newnum);
-    nplan = newnum%10;
+    klhere = game.state.galaxy[quadx][quady].klingons;
+    irhere = game.state.galaxy[quadx][quady].romulans;
+    nplan  = game.state.galaxy[quadx][quady].planets;
     nenhere = klhere + irhere;
 
     // Position Starship
     game.quad[sectx][secty] = ship;
 
-    if (quadnum >= KLINGON_PLACE) {
+    if (game.state.galaxy[quadx][quady].klingons) {
        // Position ordinary Klingons
-       quadnum -= KLINGON_PLACE*klhere;
        for (i = 1; i <= klhere; i++) {
            dropin(IHK, &ix, &iy);
            game.kx[i] = ix;
@@ -558,7 +580,7 @@ void newqad(int shutup)
            game.kpower[i] = Rand()*150.0 +300.0 +25.0*skill;
        }
        // If we need a commander, promote a Klingon
-       for (i = 1; i <= game.state.remcom ; i++) 
+       for_commanders(i)
            if (game.state.cx[i]==quadx && game.state.cy[i]==quady) break;
                        
        if (i <= game.state.remcom) {
@@ -584,10 +606,8 @@ void newqad(int shutup)
        game.kpower[i] = Rand()*400.0 + 450.0 + 50.0*skill;
     }
     // If quadrant needs a starbase, put it in
-    if (quadnum >= BASE_PLACE) {
-       quadnum -= BASE_PLACE;
+    if (game.state.galaxy[quadx][quady].starbase)
        dropin(IHB, &basex, &basey);
-    }
        
     if (nplan) {
        // If quadrant needs a planet, put it in
@@ -601,7 +621,8 @@ void newqad(int shutup)
     // Check for condition
     newcnd();
     // And finally the stars
-    for (i = 1; i <= quadnum; i++) dropin(IHSTAR, &ix, &iy);
+    for (i = 1; i <= game.state.galaxy[quadx][quady].stars; i++) 
+       dropin(IHSTAR, &ix, &iy);
 
     // Check for RNZ
     if (irhere > 0 && klhere == 0) {
@@ -637,36 +658,40 @@ void newqad(int shutup)
     }
 
     // Decide if quadrant needs a Tholian
-    if ((skill < SKILL_GOOD && Rand() <= 0.02) ||   /* Lighten up if skill is low */
-       (skill == SKILL_GOOD && Rand() <= 0.05) ||
-       (skill > SKILL_GOOD && Rand() <= 0.08)
-#ifdef DEBUG
-       || strcmp(passwd, "tholianx")==0
-#endif
-       ) {
-       do {
-           ithx = Rand() > 0.5 ? QUADSIZE : 1;
-           ithy = Rand() > 0.5 ? QUADSIZE : 1;
-       } while (game.quad[ithx][ithy] != IHDOT);
-       game.quad[ithx][ithy] = IHT;
-       ithere = 1;
-       nenhere++;
-       game.kx[nenhere] = ithx;
-       game.ky[nenhere] = ithy;
-       game.kdist[nenhere] = game.kavgd[nenhere] =
-           sqrt(square(sectx-ithx) + square(secty-ithy));
-       game.kpower[nenhere] = Rand()*400.0 +100.0 +25.0*skill;
-       /* Reserve unocupied corners */
-       if (game.quad[1][1]==IHDOT) game.quad[1][1] = 'X';
-       if (game.quad[1][QUADSIZE]==IHDOT) game.quad[1][QUADSIZE] = 'X';
-       if (game.quad[QUADSIZE][1]==IHDOT) game.quad[QUADSIZE][1] = 'X';
-       if (game.quad[QUADSIZE][QUADSIZE]==IHDOT) game.quad[QUADSIZE][QUADSIZE] = 'X';
+    if (game.options & OPTION_THOLIAN) {
+       if ((skill < SKILL_GOOD && Rand() <= 0.02) ||   /* Lighten up if skill is low */
+           (skill == SKILL_GOOD && Rand() <= 0.05) ||
+           (skill > SKILL_GOOD && Rand() <= 0.08)
+    #ifdef DEBUG
+           || strcmp(game.passwd, "tholianx")==0
+    #endif
+           ) {
+           do {
+               ithx = Rand() > 0.5 ? QUADSIZE : 1;
+               ithy = Rand() > 0.5 ? QUADSIZE : 1;
+           } while (game.quad[ithx][ithy] != IHDOT);
+           game.quad[ithx][ithy] = IHT;
+           ithere = 1;
+           nenhere++;
+           game.kx[nenhere] = ithx;
+           game.ky[nenhere] = ithy;
+           game.kdist[nenhere] = game.kavgd[nenhere] =
+               sqrt(square(sectx-ithx) + square(secty-ithy));
+           game.kpower[nenhere] = Rand()*400.0 +100.0 +25.0*skill;
+           /* Reserve unocupied corners */
+           if (game.quad[1][1]==IHDOT) game.quad[1][1] = 'X';
+           if (game.quad[1][QUADSIZE]==IHDOT) game.quad[1][QUADSIZE] = 'X';
+           if (game.quad[QUADSIZE][1]==IHDOT) game.quad[QUADSIZE][1] = 'X';
+           if (game.quad[QUADSIZE][QUADSIZE]==IHDOT) game.quad[QUADSIZE][QUADSIZE] = 'X';
+       }
     }
+
     sortkl();
 
     // Put in a few black holes
     for (i = 1; i <= 3; i++)
-       if (Rand() > 0.5) dropin(IHBLANK, &ix, &iy);
+       if (Rand() > 0.5) 
+           dropin(IHBLANK, &ix, &iy);
 
     // Take out X's in corners if Tholian present
     if (ithere) {