Fix buggy processing of shield energy change request.
[super-star-trek.git] / src / sst.py
index 637a65db0033cbc66e1be7d5caee8881cd37ee4f..187bc18a016ae69300af240c5bdd92f6dbb29c32 100644 (file)
@@ -11,27 +11,27 @@ Stas Sergeev, and Eric S. Raymond.
 See the doc/HACKING file in the distribution for designers notes and advice
 ion how to modify (and how not to modify!) this code.
 """
-import os, sys, math, curses, time, readline, cPickle, random, copy, gettext
+import os, sys, math, curses, time, readline, cPickle, random, copy, gettext, getpass
 
 SSTDOC         = "/usr/share/doc/sst/sst.doc"
 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
@@ -229,39 +229,37 @@ FENSLV    = 10    # Inhabited word is enslaved */
 FREPRO = 11    # Klingons build a ship in an enslaved system
 NEVENTS        = 12
 
-#
-# abstract out the event handling -- underlying data structures will change
-# when we implement stateful events
-# 
+# Abstract out the event handling -- underlying data structures will change
+# when we implement stateful events 
 def findevent(evtype): return game.future[evtype]
 
 class enemy:
     def __init__(self, type=None, loc=None, power=None):
         self.type = type
-        self.kloc = coord()
+        self.location = coord()
         if loc:
             self.move(loc)
-        self.kpower = power    # enemy energy level
+        self.power = power     # enemy energy level
         game.enemies.append(self)
     def move(self, loc):
-        motion = (loc != self.kloc)
-        if self.kloc.i is not None and self.kloc.j is not None:
+        motion = (loc != self.location)
+        if self.location.i is not None and self.location.j is not None:
             if motion:
                 if self.type == 'T':
-                    game.quad[self.kloc.i][self.kloc.j] = '#'
+                    game.quad[self.location.i][self.location.j] = '#'
                 else:
-                    game.quad[self.kloc.i][self.kloc.j] = '.'
+                    game.quad[self.location.i][self.location.j] = '.'
         if loc:
-            self.kloc = copy.copy(loc)
-            game.quad[self.kloc.i][self.kloc.j] = self.type
+            self.location = copy.copy(loc)
+            game.quad[self.location.i][self.location.j] = self.type
             self.kdist = self.kavgd = (game.sector - loc).distance()
         else:
-            self.kloc = coord()
+            self.location = coord()
             self.kdist = self.kavgd = None
             game.enemies.remove(self)
         return motion
     def __repr__(self):
-        return "<%s,%s.%f>" % (self.type, self.kloc, self.kpower)      # For debugging
+        return "<%s,%s.%f>" % (self.type, self.location, self.power)   # For debugging
 
 class gamestate:
     def __init__(self):
@@ -333,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
@@ -375,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
@@ -419,13 +410,13 @@ def tryexit(enemy, look, irun):
            if game.battle == game.quadrant:
                return False
        # don't leave if over 1000 units of energy 
-       if enemy.kpower > 1000.0:
+       if enemy.power > 1000.0:
            return False
     # emit escape message and move out of quadrant.
     # we know this if either short or long range sensors are working
     if not damaged(DSRSENS) or not damaged(DLRSENS) or \
        game.condition == "docked":
-       prout(crmena(True, enemy.type, "sector", enemy.kloc) + \
+       prout(crmena(True, enemy.type, "sector", enemy.location) + \
               (_(" escapes to Quadrant %s (and regains strength).") % q))
     # handle local matters related to escape
     enemy.move(None)
@@ -500,12 +491,12 @@ def movebaddy(enemy):
     mdist = int(dist1 + 0.5); # Nearest integer distance 
     # If SC, check with spy to see if should hi-tail it 
     if enemy.type=='S' and \
-       (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
+       (enemy.power <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
        irun = True
        motion = -QUADSIZE
     else:
        # decide whether to advance, retreat, or hold position 
-       forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
+       forces = enemy.power+100.0*len(game.enemies)+400*(nbaddys-1)
        if not game.shldup:
            forces += 1000; # Good for enemy if shield is down! 
        if not damaged(DPHASER) or not damaged(DPHOTON):
@@ -550,13 +541,13 @@ def movebaddy(enemy):
     if idebug:
        proutn("NSTEPS = %d:" % nsteps)
     # Compute preferred values of delta X and Y 
-    m = game.sector - enemy.kloc
+    m = game.sector - enemy.location
     if 2.0 * abs(m.i) < abs(m.j):
        m.i = 0
-    if 2.0 * abs(m.j) < abs(game.sector.i-enemy.kloc.i):
+    if 2.0 * abs(m.j) < abs(game.sector.i-enemy.location.i):
        m.j = 0
     m = (motion * m).sgn()
-    next = enemy.kloc
+    next = enemy.location
     # main move loop 
     for ll in range(nsteps):
        if idebug:
@@ -615,7 +606,7 @@ def movebaddy(enemy):
        skip(1)
     if enemy.move(next):
        if not damaged(DSRSENS) or game.condition == "docked":
-           proutn(_("*** %s from Sector %s") % (cramen(enemy.type), enemy.kloc))
+           proutn(_("*** %s from Sector %s") % (cramen(enemy.type), enemy.location))
            if enemy.kdist < dist1:
                proutn(_(" advances to "))
            else:
@@ -810,13 +801,13 @@ def movetholian():
     if not game.tholian or game.justin:
        return
     id = coord()
-    if game.tholian.kloc.i == 0 and game.tholian.kloc.j == 0:
+    if game.tholian.location.i == 0 and game.tholian.location.j == 0:
        id.i = 0; id.j = QUADSIZE-1
-    elif game.tholian.kloc.i == 0 and game.tholian.kloc.j == QUADSIZE-1:
+    elif game.tholian.location.i == 0 and game.tholian.location.j == QUADSIZE-1:
        id.i = QUADSIZE-1; id.j = QUADSIZE-1
-    elif game.tholian.kloc.i == QUADSIZE-1 and game.tholian.kloc.j == QUADSIZE-1:
+    elif game.tholian.location.i == QUADSIZE-1 and game.tholian.location.j == QUADSIZE-1:
        id.i = QUADSIZE-1; id.j = 0
-    elif game.tholian.kloc.i == QUADSIZE-1 and game.tholian.kloc.j == 0:
+    elif game.tholian.location.i == QUADSIZE-1 and game.tholian.location.j == 0:
        id.i = 0; id.j = 0
     else:
        # something is wrong! 
@@ -826,8 +817,8 @@ def movetholian():
     # do nothing if we are blocked 
     if game.quad[id.i][id.j] not in ('.', '#'):
        return
-    here = copy.copy(game.tholian.kloc)
-    delta = (id - game.tholian.kloc).sgn()
+    here = copy.copy(game.tholian.location)
+    delta = (id - game.tholian.location).sgn()
     # move in x axis 
     while here.i != id.i:
         here.i += delta.i
@@ -849,7 +840,7 @@ def movetholian():
        if game.quad[i][QUADSIZE-1]!='#' and game.quad[i][QUADSIZE-1]!='T':
            return
     # All plugged up -- Tholian splits 
-    game.quad[game.tholian.kloc.i][game.tholian.kloc.j]='#'
+    game.quad[game.tholian.location.i][game.tholian.location.j]='#'
     dropin(' ')
     prout(crmena(True, 'T', "sector", game.tholian) + _(" completes web."))
     game.tholian.move(None)
@@ -879,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."))
@@ -927,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--"))
@@ -949,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% 
@@ -1026,11 +995,11 @@ def collision(rammed, enemy):
         proutn(_(" rammed by "))
     else:
         proutn(_(" rams "))
-    proutn(crmena(False, enemy.type, "sector", enemy.kloc))
+    proutn(crmena(False, enemy.type, "sector", enemy.location))
     if rammed:
        proutn(_(" (original position)"))
     skip(1)
-    deadkl(enemy.kloc, enemy.type, game.sector)
+    deadkl(enemy.location, enemy.type, game.sector)
     proutn("***" + crmship() + " heavily damaged.")
     icas = randrange(10, 30)
     prout(_("***Sickbay reports %d casualties"), icas)
@@ -1107,7 +1076,7 @@ def torpedo(origin, bearing, dispersion, number, nburst):
             game.quad[bumpto.i][bumpto.j]=iquad
             prout(_(" displaced by blast to Sector %s ") % bumpto)
             for enemy in game.enemies:
-                enemy.kdist = enemy.kavgd = (game.sector-enemy.kloc).distance()
+                enemy.kdist = enemy.kavgd = (game.sector-enemy.location).distance()
             game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
             return None
        elif iquad in ('C', 'S', 'R', 'K'): # Hit a regular enemy 
@@ -1117,19 +1086,19 @@ def torpedo(origin, bearing, dispersion, number, nburst):
                prout(_("   torpedo neutralized."))
                return None
             for enemy in game.enemies:
-               if w == enemy.kloc:
+               if w == enemy.location:
                    break
-           kp = math.fabs(enemy.kpower)
+           kp = math.fabs(enemy.power)
            h1 = 700.0 + randrange(100) - \
                1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-track.angle))
            h1 = math.fabs(h1)
            if kp < h1:
                h1 = kp
-            if enemy.kpower < 0:
-                enemy.kpower -= -h1
+            if enemy.power < 0:
+                enemy.power -= -h1
             else:
-                enemy.kpower -= h1
-           if enemy.kpower == 0:
+                enemy.power -= h1
+           if enemy.power == 0:
                deadkl(w, iquad, w)
                return None
            proutn(crmena(True, iquad, "sector", w))
@@ -1146,11 +1115,11 @@ def torpedo(origin, bearing, dispersion, number, nburst):
                prout(_(" damaged but not destroyed."))
             else:
                 prout(_(" damaged-- displaced by blast to Sector %s ")%bumpto)
-                enemy.kloc = bumpto
+                enemy.location = bumpto
                 game.quad[w.i][w.j]='.'
                 game.quad[bumpto.i][bumpto.j]=iquad
                 for enemy in game.enemies:
-                    enemy.kdist = enemy.kavgd = (game.sector-enemy.kloc).distance()
+                    enemy.kdist = enemy.kavgd = (game.sector-enemy.location).distance()
                 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
             return None
        elif iquad == 'B': # Hit a base 
@@ -1314,14 +1283,14 @@ def attack(torps_ok):
     if game.skill <= SKILL_FAIR:
        where = "sector"
     for enemy in game.enemies:
-       if enemy.kpower < 0:
+       if enemy.power < 0:
            continue;   # too weak to attack 
        # compute hit strength and diminish shield power 
        r = randreal()
        # Increase chance of photon torpedos if docked or enemy energy is low 
        if game.condition == "docked":
            r *= 0.25
-       if enemy.kpower < 500:
+       if enemy.power < 500:
            r *= 0.25; 
        if enemy.type=='T' or (enemy.type=='?' and not thing.angry):
            continue
@@ -1337,20 +1306,20 @@ def attack(torps_ok):
                continue; # Don't waste the effort! 
            attempt = True; # Attempt to attack 
            dustfac = randreal(0.8, 0.85)
-           hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
-           enemy.kpower *= 0.75
+           hit = enemy.power*math.pow(dustfac,enemy.kavgd)
+           enemy.power *= 0.75
        else: # Enemy uses photon torpedo 
            # We should be able to make the bearing() method work here
-           course = 1.90985*math.atan2(game.sector.j-enemy.kloc.j, enemy.kloc.i-game.sector.i)
+           course = 1.90985*math.atan2(game.sector.j-enemy.location.j, enemy.location.i-game.sector.i)
            hit = 0
            proutn(_("***TORPEDO INCOMING"))
            if not damaged(DSRSENS):
-               proutn(_(" From ") + crmena(False, enemy.type, where, enemy.kloc))
+               proutn(_(" From ") + crmena(False, enemy.type, where, enemy.location))
            attempt = True
            prout("  ")
            dispersion = (randreal()+randreal())*0.5 - 0.5
-           dispersion += 0.002*enemy.kpower*dispersion
-           hit = torpedo(enemy.kloc, course, dispersion, number=1, nburst=1)
+           dispersion += 0.002*enemy.power*dispersion
+           hit = torpedo(enemy.location, course, dispersion, number=1, nburst=1)
            if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
                finish(FWON); # Klingons did themselves in! 
            if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.alldone:
@@ -1383,7 +1352,7 @@ def attack(torps_ok):
        if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
            proutn(_(" on the ") + crmshp())
        if not damaged(DSRSENS) and usephasers:
-           prout(_(" from ") + crmena(False, enemy.type, where, enemy.kloc))
+           prout(_(" from ") + crmena(False, enemy.type, where, enemy.location))
        skip(1)
        # Decide if hit is critical 
        if hit > hitmax:
@@ -1471,7 +1440,7 @@ def deadkl(w, type, mv):
     game.recompute()
     # Remove enemy ship from arrays describing local conditions
     for e in game.enemies:
-       if e.kloc == w:
+       if e.location == w:
             e.move(None)
            break
     return
@@ -1644,16 +1613,16 @@ def hittem(hits):
            continue
        dustfac = randreal(0.9, 1.0)
        hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
-       kpini = game.enemies[kk].kpower
+       kpini = game.enemies[kk].power
        kp = math.fabs(kpini)
        if PHASEFAC*hit < kp:
            kp = PHASEFAC*hit
-        if game.enemies[kk].kpower < 0:
-            game.enemies[kk].kpower -= -kp
+        if game.enemies[kk].power < 0:
+            game.enemies[kk].power -= -kp
         else:
-            game.enemies[kk].kpower -= kp
-       kpow = game.enemies[kk].kpower
-       w = game.enemies[kk].kloc
+            game.enemies[kk].power -= kp
+       kpow = game.enemies[kk].power
+       w = game.enemies[kk].location
        if hit > 0.005:
            if not damaged(DSRSENS):
                boom(w)
@@ -1677,7 +1646,7 @@ def hittem(hits):
            if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
                prout(_("***Mr. Spock-  \"Captain, the vessel at Sector %s")%w)
                prout(_("   has just lost its firepower.\""))
-               game.enemies[kk].kpower = -kpow
+               game.enemies[kk].power = -kpow
         kk += 1
     return
 
@@ -1770,7 +1739,7 @@ def phasers():
            scanner.chew()
            if not kz:
                for i in range(len(game.enemies)):
-                   irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
+                   irec += math.fabs(game.enemies[i].power)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
            kz=1
            proutn(_("%d units required. ") % irec)
            scanner.chew()
@@ -1806,7 +1775,7 @@ def phasers():
                hits.append(0.0)
                if powrem <= 0:
                    continue
-               hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
+               hits[i] = math.fabs(game.enemies[i].power)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
                over = randreal(1.01, 1.06) * hits[i]
                temp = powrem
                powrem -= hits[i] + over
@@ -1843,7 +1812,7 @@ def phasers():
     elif automode == "MANUAL":
        rpow = 0.0
         for k in range(len(game.enemies)):
-           aim = game.enemies[k].kloc
+           aim = game.enemies[k].location
            ienm = game.quad[aim.i][aim.j]
            if msgflag:
                proutn(_("Energy available= %.2f") % (avail-0.006))
@@ -1861,7 +1830,7 @@ def phasers():
            if key == "IHEOL":
                scanner.chew()
                if itarg and k > kz:
-                   irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
+                   irec=(abs(game.enemies[k].power)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) *  randreal(1.01, 1.06) + 1.0
                kz = k
                proutn("(")
                if not damaged(DCOMPTR):
@@ -2108,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:
@@ -2499,10 +2468,10 @@ def nova(nov):
                     deadkl(neighbor, iquad, neighbor)
                 elif iquad in ('C','S','R'): # Damage/destroy big enemies 
                     for ll in range(len(game.enemies)):
-                        if game.enemies[ll].kloc == neighbor:
+                        if game.enemies[ll].location == neighbor:
                             break
-                    game.enemies[ll].kpower -= 800.0 # If firepower is lost, die 
-                    if game.enemies[ll].kpower <= 0.0:
+                    game.enemies[ll].power -= 800.0 # If firepower is lost, die 
+                    if game.enemies[ll].power <= 0.0:
                         deadkl(neighbor, iquad, neighbor)
                         break
                     newc = neighbor + neighbor - hits[mm]
@@ -2695,8 +2664,8 @@ def kaboom():
        whammo = 25.0 * game.energy
        l=1
        while l <= len(game.enemies):
-           if game.enemies[l].kpower*game.enemies[l].kdist <= whammo: 
-               deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.i][game.enemies[l].kloc.j], game.enemies[l].kloc)
+           if game.enemies[l].power*game.enemies[l].kdist <= whammo: 
+               deadkl(game.enemies[l].location, game.quad[game.enemies[l].location.i][game.enemies[l].location.j], game.enemies[l].location)
            l += 1
     finish(FDILITHIUM)
                                
@@ -3365,7 +3334,7 @@ def imove(course=None, noattack=False):
         if len(game.enemies) != 0 and not noattack:
             newcnd()
             for enemy in game.enemies:
-                finald = (w - enemy.kloc).distance()
+                finald = (w - enemy.location).distance()
                 enemy.kavgd = 0.5 * (finald + enemy.kdist)
             # Stas Sergeev added the condition
             # that attacks only happen if Klingons
@@ -3423,7 +3392,7 @@ def imove(course=None, noattack=False):
             stopegy = 50.0*course.distance/game.optime
             if iquad in ('T', 'K', 'C', 'S', 'R', '?'):
                 for enemy in game.enemies:
-                    if enemy.kloc == game.sector:
+                    if enemy.location == game.sector:
                         break
                 collision(rammed=False, enemy=enemy)
                 return True
@@ -3489,7 +3458,7 @@ def imove(course=None, noattack=False):
     game.quad[game.sector.i][game.sector.j] = game.ship
     if game.enemies:
         for enemy in game.enemies:
-            finald = (w-enemy.kloc).distance()
+            finald = (w-enemy.location).distance()
             enemy.kavgd = 0.5 * (finald + enemy.kdist)
             enemy.kdist = finald
         game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
@@ -3530,14 +3499,6 @@ def dock(verbose):
        prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
        attackreport(False)
        game.iseenit = True
-# This program originally required input in terms of a (clock)
-# direction and distance. Somewhere in history, it was changed to
-# cartesian coordinates. So we need to convert.  Probably
-# "manual" input should still be done this way -- it's a real
-# pain if the computer isn't working! Manual mode is still confusing
-# because it involves giving x and y motions, yet the coordinates
-# are always displayed y - x, where +y is downward!
 
 def cartesian(loc1=None, loc2=None):
     if loc1 is None:
@@ -4025,14 +3986,14 @@ def timwrp():
        # Likewise, if in the original time the Galileo was abandoned, but
        # was on ship earlier, it would have vanished -- let's restore it.
        if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
-           prout(_("Checkov-  \"Security reports the Galileo has reappeared in the dock!\""))
+           prout(_("Chekov-  \"Security reports the Galileo has reappeared in the dock!\""))
            game.iscraft = "onship"
         # There used to be code to do the actual reconstrction here,
         # but the starchart is now part of the snapshotted galaxy state.
        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)
@@ -4658,7 +4619,7 @@ def deathray():
        prouts(_("Sulu- \"Captain!  It's working!\""))
        skip(2)
        while len(game.enemies) > 0:
-           deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.i][game.enemies[1].kloc.j],game.enemies[1].kloc)
+           deadkl(game.enemies[1].location, game.quad[game.enemies[1].location.i][game.enemies[1].location.j],game.enemies[1].location)
        prout(_("Ensign Chekov-  \"Congratulations, Captain!\""))
        if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) == 0:
            finish(FWON)    
@@ -4853,7 +4814,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."))
 
@@ -5283,7 +5244,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
@@ -5449,12 +5409,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()
@@ -5606,14 +5564,14 @@ def newqad():
         for cmdr in game.state.kcmdr:
            if cmdr == game.quadrant:
                 e = game.enemies[game.klhere-1]
-                game.quad[e.kloc.i][e.kloc.j] = 'C'
-                e.kpower = randreal(950,1350) + 50.0*game.skill
+                game.quad[e.location.i][e.location.j] = 'C'
+                e.power = randreal(950,1350) + 50.0*game.skill
                break   
        # If we need a super-commander, promote a Klingon
        if game.quadrant == game.state.kscmdr:
             e = game.enemies[0]
-           game.quad[e.kloc.i][e.kloc.j] = 'S'
-           e.kpower = randreal(1175.0,  1575.0) + 125.0*game.skill
+           game.quad[e.location.i][e.location.j] = 'S'
+           e.power = randreal(1175.0,  1575.0) + 125.0*game.skill
            game.iscate = (game.state.remkl > 1)
     # Put in Romulans if needed
     for i in range(q.romulans):
@@ -5822,8 +5780,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()
@@ -6243,14 +6200,15 @@ 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))
             logfp.write("# recorded by %s@%s on %s\n" % \
-                    (os.getenv("LOGNAME"),socket.gethostname(),time.ctime()))
+                    (getpass.getuser(),socket.gethostname(),time.ctime()))
         random.seed(seed)
         scanner = sstscanner()
         map(scanner.append, arguments)