Starchart and base-attack tweaks.
[super-star-trek.git] / src / sst.py
index ebcf75f8a297f9575b8889f47dfc9e0931a2016d..00f6df3dfa65ec08b449a6fa8c933283ebca08ca 100644 (file)
@@ -18,20 +18,20 @@ DOC_NAME    = "sst.doc"
 
 def _(str): return gettext.gettext(str)
 
-PHASEFAC       = 2.0
-GALSIZE        = 8
-NINHAB         = (GALSIZE * GALSIZE / 2)
-MAXUNINHAB     = 10
-PLNETMAX       = (NINHAB + MAXUNINHAB)
-QUADSIZE       = 10
-BASEMIN                = 2
-BASEMAX        = (GALSIZE * GALSIZE / 12)
-MAXKLGAME      = 127
-MAXKLQUAD      = 9
-FULLCREW       = 428   # BSD Trek was 387, that's wrong 
-FOREVER        = 1e30
-MAXBURST       = 3
-MINCMDR        = 10
+GALSIZE        = 8             # Galaxy size in quadrants
+NINHAB         = (GALSIZE * GALSIZE / 2)       # Number of inhabited worlds
+MAXUNINHAB     = 10            # Maximum uninhabited worlds
+QUADSIZE       = 10            # Quadrant size in sectors
+BASEMIN                = 2                             # Minimum starbases
+BASEMAX        = (GALSIZE * GALSIZE / 12)      # Maximum starbases
+MAXKLGAME      = 127           # Maximum Klingons per game
+MAXKLQUAD      = 9             # Maximum Klingons per quadrant
+FULLCREW       = 428           # Crew size. BSD Trek was 387, that's wrong 
+FOREVER        = 1e30          # Time for the indefinite future
+MAXBURST       = 3             # Max # of torps you can launch in one turn
+MINCMDR        = 10            # Minimum number of Klingon commanders
+DOCKFAC                = 0.25          # Repair faster when docked
+PHASEFAC       = 2.0           # Unclear what this is, it was in the C version
 
 class TrekError:
     pass
@@ -331,10 +331,8 @@ class gamestate:
         self.energy = 0.0      # energy level
         self.shield = 0.0      # shield level
         self.warpfac = 0.0     # warp speed
-        self.wfacsq = 0.0      # squared warp factor
         self.lsupres = 0.0     # life support reserves
         self.optime = 0.0      # time taken by current operation
-        self.docfac = 0.0      # repair factor when docking (constant?)
         self.damfac = 0.0      # damage factor
         self.lastchart = 0.0   # time star chart was last updated
         self.cryprob = 0.0     # probability that crystal will work
@@ -373,22 +371,17 @@ FHOLE = 20
 FCREW = 21
 
 def withprob(p):
-    v = random.random()
-    #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
-    return v < p
+    return random.random() < p
 
 def randrange(*args):
-    v = random.randrange(*args)
-    #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
-    return v
+    return random.randrange(*args)
 
 def randreal(*args):
     v = random.random()
     if len(args) == 1:
-        v *= args[0]           # returns from [0, args[0])
+        v *= args[0]           # from [0, args[0])
     elif len(args) == 2:
-        v = args[0] + v*(args[1]-args[0])      # returns from [args[0], args[1])
-    #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
+        v = args[0] + v*(args[1]-args[0])      # from [args[0], args[1])
     return v
 
 # Code from ai.c begins here
@@ -877,7 +870,6 @@ def doshield(shraise):
        if action=="NONE":
            proutn(_("Do you wish to change shield energy? "))
            if ja() == True:
-               proutn(_("Energy to transfer to shields- "))
                action = "NRG"
            elif damaged(DSHIELD):
                prout(_("Shields damaged and down."))
@@ -925,21 +917,22 @@ def doshield(shraise):
        while scanner.next() != "IHREAL":
            scanner.chew()
            proutn(_("Energy to transfer to shields- "))
+        nrg = scanner.real
        scanner.chew()
-       if scanner.real == 0:
+       if nrg == 0:
            return
-       if scanner.real > game.energy:
+       if nrg > game.energy:
            prout(_("Insufficient ship energy."))
            return
        game.ididit = True
-       if game.shield+scanner.real >= game.inshld:
+       if game.shield+nrg >= game.inshld:
            prout(_("Shield energy maximized."))
-           if game.shield+scanner.real > game.inshld:
+           if game.shield+nrg > game.inshld:
                prout(_("Excess energy requested returned to ship energy"))
            game.energy -= game.inshld-game.shield
            game.shield = game.inshld
            return
-       if scanner.real < 0.0 and game.energy-scanner.real > game.inenrg:
+       if nrg < 0.0 and game.energy-nrg > game.inenrg:
            # Prevent shield drain loophole 
            skip(1)
            prout(_("Engineering to bridge--"))
@@ -947,50 +940,28 @@ def doshield(shraise):
            prout(_("  I can't drain the shields."))
            game.ididit = False
            return
-       if game.shield+scanner.real < 0:
+       if game.shield+nrg < 0:
            prout(_("All shield energy transferred to ship."))
            game.energy += game.shield
            game.shield = 0.0
            return
        proutn(_("Scotty- \""))
-       if scanner.real > 0:
+       if nrg > 0:
            prout(_("Transferring energy to shields.\""))
        else:
            prout(_("Draining energy from shields.\""))
-       game.shield += scanner.real
-       game.energy -= scanner.real
+       game.shield += nrg
+       game.energy -= nrg
        return
 
 def randdevice():
     "Choose a device to damage, at random."
-    # Quoth Eric Allman in the code of BSD-Trek:
-    # "Under certain conditions you can get a critical hit.  This
-    # sort of hit damages devices.  The probability that a given
-    # device is damaged depends on the device.  Well protected
-    # devices (such as the computer, which is in the core of the
-    # ship and has considerable redundancy) almost never get
-    # damaged, whereas devices which are exposed (such as the
-    # warp engines) or which are particularly delicate (such as
-    # the transporter) have a much higher probability of being
-    # damaged."
-    # 
-    # This is one place where OPTION_PLAIN does not restore the
-    # original behavior, which was equiprobable damage across
-    # all devices.  If we wanted that, we'd return randrange(NDEVICES)
-    # and have done with it.  Also, in the original game, DNAVYS
-    # and DCOMPTR were the same device. 
-    # 
-    # Instead, we use a table of weights similar to the one from BSD Trek.
-    # BSD doesn't have the shuttle, shield controller, death ray, or probes. 
-    # We don't have a cloaking device.  The shuttle got the allocation
-    # for the cloaking device, then we shaved a half-percent off
-    # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
     weights = (
        105,    # DSRSENS: short range scanners 10.5% 
        105,    # DLRSENS: long range scanners          10.5% 
        120,    # DPHASER: phasers                      12.0% 
        120,    # DPHOTON: photon torpedoes             12.0% 
-       25,     # DLIFSUP: life support          2.5% 
+       25,     # DLIFSUP: life support                  2.5% 
        65,     # DWARPEN: warp drive                    6.5% 
        70,     # DIMPULS: impulse engines               6.5% 
        145,    # DSHIELD: deflector shields            14.5% 
@@ -2106,7 +2077,7 @@ def events():
        # Fix devices 
        repair = xtime
        if game.condition == "docked":
-           repair /= game.docfac
+           repair /= DOCKFAC
        # Don't fix Deathray here 
        for l in range(NDEVICES):
            if game.damage[l] > 0.0 and l != DDRAY:
@@ -2355,7 +2326,7 @@ def events():
                else:
                    prout(_("Uhura- Starfleet reports increased Klingon activity"))
                    if q.planet != None:
-                       proutn(_("near %s") % q.planet)
+                       proutn(_("near %s ") % q.planet)
                    prout(_("in Quadrant %s.") % w)
                                
 def wait():
@@ -2933,8 +2904,6 @@ def score():
        klship = 1
     else:
        klship = 2
-    if not game.gamewon:
-       game.state.nromrem = 0 # None captured if no win
     iscore = 10*(game.inkling - game.state.remkl) \
              + 50*(game.incom - len(game.state.kcmdr)) \
              + ithperd + iwon \
@@ -2949,7 +2918,7 @@ def score():
     if game.inrom - game.state.nromrem:
        prout(_("%6d Romulans destroyed                 %5d") %
              (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
-    if game.state.nromrem:
+    if game.state.nromrem and game.gamewon:
        prout(_("%6d Romulans captured                  %5d") %
              (game.state.nromrem, game.state.nromrem))
     if game.inkling - game.state.remkl:
@@ -2972,7 +2941,7 @@ def score():
              (game.state.nplankl, -10*game.state.nplankl))
     if (game.options & OPTION_WORLDS) and game.state.nworldkl:
        prout(_("%6d inhabited planets destroyed by your action   %5d") %
-             (game.state.nplankl, -300*game.state.nworldkl))
+             (game.state.nworldkl, -300*game.state.nworldkl))
     if game.state.basekl:
        prout(_("%6d bases destroyed by your action     %5d") %
              (game.state.basekl, -100*game.state.basekl))
@@ -4022,7 +3991,7 @@ def timwrp():
        prout(_("Spock has reconstructed a correct star chart from memory"))
     else:
        # Go forward in time 
-       game.optime = -0.5*game.intime*math.log(randreal())
+       game.optime = expran(0.5*game.intime)
        prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
        # cheat to make sure no tractor beams occur during time warp 
        postpone(FTBEAM, game.optime)
@@ -4843,7 +4812,7 @@ def damagereport():
                jdam = True
            prout("  %-26s\t%8.2f\t\t%8.2f" % (device[i],
                                                game.damage[i]+0.05,
-                                               game.docfac*game.damage[i]+0.005))
+                                               DOCKFAC*game.damage[i]+0.005))
     if not jdam:
        prout(_("All devices functional."))
 
@@ -5273,7 +5242,6 @@ def setup():
     game.iscraft = "onship"
     game.landed = False
     game.alive = True
-    game.docfac = 0.25
     # Starchart is functional but we've never seen it
     game.lastchart = FOREVER
     # Put stars in the galaxy
@@ -5439,12 +5407,10 @@ def setup():
 
 def choose():
     "Choose your game type."
-    global thing
     while True:
-       game.tourn = 0
+       game.tourn = game.length = 0
        game.thawed = False
        game.skill = SKILL_NONE
-       game.length = 0
        if not scanner.inqueue: # Can start with command line options 
            proutn(_("Would you like a regular, tournament, or saved game? "))
         scanner.next()
@@ -5505,7 +5471,7 @@ def choose():
     # Choose game options -- added by ESR for SST2K
     if scanner.next() != "IHALPHA":
        scanner.chew()
-       proutn(_("Choose your game style (or just press enter): "))
+       proutn(_("Choose your game style (plain, almy, fancy or just press enter): "))
        scanner.next()
     if scanner.sees("plain"):
        # Approximates the UT FORTRAN version.
@@ -5812,8 +5778,7 @@ def makemoves():
        drawmaps(1)
         while True:    # get a command 
            hitme = False
-           game.justin = False
-           game.optime = 0.0
+           game.optime = game.justin = False
            scanner.chew()
            setwnd(prompt_window)
            clrscr()
@@ -6233,9 +6198,10 @@ if __name__ == '__main__':
                 raise SystemExit, 1
         # where to save the input in case of bugs
         try:
-            logfp = open("/usr/tmp/sst-input.log", "w")
+            logfp = open("/tmp/sst-input.log", "w")
         except IOError:
             sys.stderr.write("sst: warning, can't open logfile\n")
+            sys.exit(1)
         if logfp:
             logfp.write("# seed %s\n" % seed)
             logfp.write("# options %s\n" % " ".join(arguments))