Track move to gitlab.
[super-star-trek.git] / sst.py
diff --git a/sst.py b/sst.py
index c1d49dd21fa209841b4323a0d8ac7ffc67cce636..757c8c884b07d25b3984cb8853f6a2f0bfef0722 100755 (executable)
--- a/sst.py
+++ b/sst.py
@@ -11,7 +11,8 @@ Stas Sergeev, and Eric S. Raymond.
 See the doc/HACKING file in the distribution for designers notes and advice
 on how to modify (and how not to modify!) this code.
 """
-import os, sys, math, curses, time, readline, pickle, random, copy, gettext, getpass
+import os, sys, math, curses, time, pickle, random, copy, gettext, getpass
+import getopt, socket, locale
 
 # This import only works on Unixes.  The intention is to enable
 # Ctrl-P, Ctrl-N, and friends in Cmd.
@@ -81,7 +82,7 @@ class Coord:
     def __eq__(self, other):
         return other != None and self.i == other.i and self.j == other.j
     def __ne__(self, other):
-        return other == None or self.i != other.i or self.j != other.j
+        return other is None or self.i != other.i or self.j != other.j
     def __add__(self, other):
         return Coord(self.i+other.i, self.j+other.j)
     def __sub__(self, other):
@@ -126,7 +127,7 @@ class Coord:
         s.j = self.j + randrange(-1, 2)
         return s
     def __str__(self):
-        if self.i == None or self.j == None:
+        if self.i is None or self.j is None:
             return "Nowhere"
         return "%s - %s" % (self.i+1, self.j+1)
     __repr__ = __str__
@@ -489,7 +490,7 @@ def tryexit(enemy, look, irun):
                 game.state.kcmdr.append(iq)
                 break
     # report move out of quadrant.
-    return [(True, enemy, oldloc, ibq)]
+    return [(True, enemy, oldloc, iq)]
 
 # The bad-guy movement algorithm:
 #
@@ -1405,7 +1406,7 @@ def attack(torps_ok):
                 finish(FWON) # Klingons did themselves in!
             if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.alldone:
                 return # Supernova or finished
-            if hit == None:
+            if hit is None:
                 continue
         # incoming phaser or torpedo, shields may dissipate it
         if game.shldup or game.shldchg or game.condition == "docked":
@@ -1595,10 +1596,10 @@ def torps():
             break
         scanner.push(scanner.token)
         target.append(scanner.getcoord())
-        if target[-1] == None:
+        if target[-1] is None:
             return
         tcourse.append(targetcheck(target[-1]))
-        if tcourse[-1] == None:
+        if tcourse[-1] is None:
             return
     scanner.chew()
     if len(target) == 0:
@@ -1607,10 +1608,10 @@ def torps():
             proutn(_("Target sector for torpedo number %d- ") % (i+1))
             scanner.chew()
             target.append(scanner.getcoord())
-            if target[-1] == None:
+            if target[-1] is None:
                 return
             tcourse.append(targetcheck(target[-1]))
-            if tcourse[-1] == None:
+            if tcourse[-1] is None:
                 return
     game.ididit = True
     # Loop for moving <n> torpedoes
@@ -1741,9 +1742,9 @@ def phasers():
     no = False
     itarg = True
     msgflag = True
-    rpow = 0
+    rpow = 0.0
     automode = "NOTSET"
-    key = 0
+    key = ""
     skip(1)
     # SR sensors and Computer are needed for automode
     if damaged(DSRSENS) or damaged(DCOMPTR):
@@ -2234,16 +2235,16 @@ def events():
                 unschedule(FBATTAK)
                 unschedule(FCDBAS)
                 continue
+            ibq = None # Force battle location to persist past loop
             try:
                 for ibq in game.state.baseq:
                     for cmdr in game.state.kcmdr:
                         if ibq == cmdr and ibq != game.quadrant and ibq != game.state.kscmdr:
                             raise JumpOut
-                else:
-                    # no match found -- try later
-                    schedule(FBATTAK, expran(0.3*game.intime))
-                    unschedule(FCDBAS)
-                    continue
+                # no match found -- try later
+                schedule(FBATTAK, expran(0.3*game.intime))
+                unschedule(FCDBAS)
+                continue
             except JumpOut:
                 pass
             # commander + starbase combination found -- launch attack
@@ -2334,7 +2335,7 @@ def events():
                 # supernova'ed, and which has some Klingons in it
                 w = randplace(GALSIZE)
                 q = game.state.galaxy[w.i][w.j]
-                if not (game.quadrant == w or q.planet == None or \
+                if not (game.quadrant == w or q.planet is None or \
                       not q.planet.inhabited or \
                       q.supernova or q.status!="secure" or q.klingons<=0):
                     break
@@ -2398,8 +2399,8 @@ def events():
                             if q.klingons >= MAXKLQUAD or q.supernova:
                                 continue
                             raise JumpOut
-                    else:
-                        continue        # search for eligible quadrant failed
+                    # search for eligible quadrant failed
+                    continue
                 except JumpOut:
                     w = m
             # deliver the child
@@ -2469,7 +2470,7 @@ def wait():
         if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
             break
     game.resting = False
-    game.optime = 0
+    game.optime = 0.0
 
 def nova(nov):
     "Star goes nova."
@@ -2558,33 +2559,37 @@ def nova(nov):
                 elif iquad == 'K': # kill klingon
                     deadkl(neighbor, iquad, neighbor)
                 elif iquad in ('C','S','R'): # Damage/destroy big enemies
+                    target = None
                     for ll in range(len(game.enemies)):
                         if game.enemies[ll].location == neighbor:
+                            target = game.enemies[ll]
                             break
-                    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[-1]
-                    proutn(crmena(True, iquad, "sector", neighbor) + _(" damaged"))
-                    if not newc.valid_sector():
-                        # can't leave quadrant
-                        skip(1)
-                        break
-                    iquad1 = game.quad[newc.i][newc.j]
-                    if iquad1 == ' ':
-                        proutn(_(", blasted into ") + crmena(False, ' ', "sector", newc))
-                        skip(1)
-                        deadkl(neighbor, iquad, newc)
-                        break
-                    if iquad1 != '.':
-                        # can't move into something else
-                        skip(1)
-                        break
-                    proutn(_(", buffeted to Sector %s") % newc)
-                    game.quad[neighbor.i][neighbor.j] = '.'
-                    game.quad[newc.i][newc.j] = iquad
-                    game.enemies[ll].move(newc)
+                    if target is not None:
+                        target.power -= 800.0 # If firepower is lost, die
+                        if target.power <= 0.0:
+                            deadkl(neighbor, iquad, neighbor)
+                            continue   # neighbor loop
+                        # Else enemy gets flung by the blast wave
+                        newc = neighbor + neighbor - hits[-1]
+                        proutn(crmena(True, iquad, "sector", neighbor) + _(" damaged"))
+                        if not newc.valid_sector():
+                            # can't leave quadrant
+                            skip(1)
+                            continue
+                        iquad1 = game.quad[newc.i][newc.j]
+                        if iquad1 == ' ':
+                            proutn(_(", blasted into ") + crmena(False, ' ', "sector", newc))
+                            skip(1)
+                            deadkl(neighbor, iquad, newc)
+                            continue
+                        if iquad1 != '.':
+                            # can't move into something else
+                            skip(1)
+                            continue
+                        proutn(_(", buffeted to Sector %s") % newc)
+                        game.quad[neighbor.i][neighbor.j] = '.'
+                        game.quad[newc.i][newc.j] = iquad
+                        target.move(newc)
     # Starship affected by nova -- kick it away.
     dist = kount*0.1
     direc = ncourse[3*(bump.i+1)+bump.j+2]
@@ -2593,11 +2598,11 @@ def nova(nov):
     if dist == 0.0:
         return
     scourse = course(bearing=direc, distance=dist)
-    game.optime = scourse.time(warp=4)
+    game.optime = scourse.time(w=4)
     skip(1)
     prout(_("Force of nova displaces starship."))
     imove(scourse, noattack=True)
-    game.optime = scourse.time(warp=4)
+    game.optime = scourse.time(w=4)
     return
 
 def supernova(w):
@@ -2607,14 +2612,14 @@ def supernova(w):
         nq = copy.copy(w)
     else:
         # Scheduled supernova -- select star at random.
-        stars = 0
+        nstars = 0
         nq = Coord()
         for nq.i in range(GALSIZE):
             for nq.j in range(GALSIZE):
-                stars += game.state.galaxy[nq.i][nq.j].stars
+                nstars += game.state.galaxy[nq.i][nq.j].stars
         if stars == 0:
             return # nothing to supernova exists
-        num = randrange(stars) + 1
+        num = randrange(nstars) + 1
         for nq.i in range(GALSIZE):
             for nq.j in range(GALSIZE):
                 num -= game.state.galaxy[nq.i][nq.j].stars
@@ -2692,7 +2697,7 @@ def supernova(w):
     # If supernova destroys last Klingons give special message
     if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0 and not nq == game.quadrant:
         skip(2)
-        if w == None:
+        if w is None:
             prout(_("Lucky you!"))
         proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
         finish(FWON)
@@ -2778,7 +2783,7 @@ def badpoints():
             3.0*game.abandoned
     if game.ship == 'F':
         badpt += 100.0
-    elif game.ship == None:
+    elif game.ship is None:
         badpt += 200.0
     return badpt
 
@@ -3110,7 +3115,7 @@ def plaque():
         fp.write(_(" Cheat level\n\n"))
     timestring = time.ctime()
     fp.write(_("                                                 This day of %.6s %.4s, %.8s\n\n") %
-                    (timestring+4, timestring+20, timestring+11))
+             (timestring+4, timestring+20, timestring+11))
     fp.write(_("                                                        Your score:  %d\n\n") % game.score)
     fp.write(_("                                                    Klingons per stardate:  %.2f\n") % game.perdate)
     fp.close()
@@ -3131,11 +3136,10 @@ curwnd = None
 
 def iostart():
     global stdscr, rows
-    "for some recent versions of python2, the following enables UTF8"
-    "for the older ones we probably need to set C locale, and the python3"
-    "has no problems at all"
+    # for some recent versions of python2, the following enables UTF8
+    # for the older ones we probably need to set C locale, and python3
+    # has no problems at all
     if sys.version_info[0] < 3:
-        import locale
         locale.setlocale(locale.LC_ALL, "")
     gettext.bindtextdomain("sst", "/usr/local/share/locale")
     gettext.textdomain("sst")
@@ -3163,7 +3167,7 @@ def iostart():
             curses.init_pair(curses.COLOR_YELLOW,  curses.COLOR_YELLOW, -1)
         global fullscreen_window, srscan_window, report_window, status_window
         global lrscan_window, message_window, prompt_window
-        (rows, columns)   = stdscr.getmaxyx()
+        (rows, _columns)   = stdscr.getmaxyx()
         fullscreen_window = stdscr
         srscan_window     = curses.newwin(12, 25, 0,       0)
         report_window     = curses.newwin(11, 0,  1,       25)
@@ -3218,9 +3222,9 @@ def pause_game():
 
 def skip(i):
     "Skip i lines.  Pause game if this would cause a scrolling event."
-    for dummy in range(i):
+    for _dummy in range(i):
         if game.options & OPTION_CURSES:
-            (y, x) = curwnd.getyx()
+            (y, _x) = curwnd.getyx()
             try:
                 curwnd.move(y+1, 0)
             except curses.error:
@@ -3233,30 +3237,30 @@ def skip(i):
             else:
                 sys.stdout.write('\n')
 
-def proutn(line):
+def proutn(proutntline):
     "Utter a line with no following line feed."
     if game.options & OPTION_CURSES:
         (y, x) = curwnd.getyx()
-        (my, mx) = curwnd.getmaxyx()
+        (my, _mx) = curwnd.getmaxyx()
         if curwnd == message_window and y >= my - 2:
             pause_game()
             clrscr()
         # Uncomment this to debug curses problems
         if logfp:
-            logfp.write("#curses: at %s proutn(%s)\n" % ((y, x), repr(line)))
-        curwnd.addstr(line)
+            logfp.write("#curses: at %s proutn(%s)\n" % ((y, x), repr(proutntline)))
+        curwnd.addstr(proutntline)
         curwnd.refresh()
     else:
-        sys.stdout.write(line)
+        sys.stdout.write(proutntline)
         sys.stdout.flush()
 
-def prout(line):
-    proutn(line)
+def prout(proutline):
+    proutn(proutline)
     skip(1)
 
-def prouts(line):
+def prouts(proutsline):
     "Emit slowly!"
-    for c in line:
+    for c in proutsline:
         if not replayfp or replayfp.closed:        # Don't slow down replays
             time.sleep(0.03)
         proutn(c)
@@ -3270,24 +3274,24 @@ def prouts(line):
 def cgetline():
     "Get a line of input."
     if game.options & OPTION_CURSES:
-        line = curwnd.getstr() + "\n"
+        linein = curwnd.getstr() + "\n"
         curwnd.refresh()
     else:
         if replayfp and not replayfp.closed:
             while True:
-                line = replayfp.readline()
-                proutn(line)
-                if line == '':
+                linein = replayfp.readline()
+                proutn(linein)
+                if linein == '':
                     prout("*** Replay finished")
                     replayfp.close()
                     break
-                elif line[0] != "#":
+                elif linein[0] != "#":
                     break
         else:
-            line = eval(input()) + "\n"
+            linein = eval(input()) + "\n"
     if logfp:
-        logfp.write(line)
-    return line
+        logfp.write(linein)
+    return linein
 
 def setwnd(wnd):
     "Change windows -- OK for this to be a no-op in tty mode."
@@ -3515,6 +3519,8 @@ def imove(icourse=None, noattack=False):
         # check for edge of galaxy
         kinks = 0
         while True:
+
+
             kink = False
             if icourse.final.i < 0:
                 icourse.final.i = -icourse.final.i
@@ -3562,9 +3568,11 @@ def imove(icourse=None, noattack=False):
             if iquad in ('T', 'K', 'C', 'S', 'R', '?'):
                 for enemy in game.enemies:
                     if enemy.location == game.sector:
-                        break
-                collision(rammed=False, enemy=enemy)
-                return True
+                        collision(rammed=False, enemy=enemy)
+                        return True
+                # This should not happen
+                prout(_("Which way did he go?"))
+                return False
             elif iquad == ' ':
                 skip(1)
                 prouts(_("***RED ALERT!  RED ALERT!"))
@@ -3612,7 +3620,7 @@ def imove(icourse=None, noattack=False):
         game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
     # Move out
     game.quad[game.sector.i][game.sector.j] = '.'
-    for m in range(icourse.moves):
+    for _m in range(icourse.moves):
         icourse.nexttok()
         w = icourse.sector()
         if icourse.origin.quadrant() != icourse.location.quadrant():
@@ -3653,7 +3661,7 @@ def dock(verbose):
         prout(crmshp() + _(" not adjacent to base."))
         return
     game.condition = "docked"
-    if "verbose":
+    if verbose:
         prout(_("Docked."))
     game.ididit = True
     if game.energy < game.inenrg:
@@ -3679,7 +3687,7 @@ def cartesian(loc1=None, loc2=None):
 
 def getcourse(isprobe):
     "Get a course and distance from the user."
-    key = 0
+    key = ""
     dquad = copy.copy(game.quadrant)
     navmode = "unspecified"
     itemp = "curt"
@@ -3821,16 +3829,14 @@ class course:
         if self.bearing < 0.0:
             self.bearing += 12.0
         self.angle = ((15.0 - self.bearing) * 0.5235988)
-        if origin is None:
-            self.origin = cartesian(game.quadrant, game.sector)
-        else:
-            self.origin = cartesian(game.quadrant, origin)
         self.increment = Coord(-math.sin(self.angle), math.cos(self.angle))
         bigger = max(abs(self.increment.i), abs(self.increment.j))
         self.increment /= bigger
         self.moves = int(round(10*self.distance*bigger))
         self.reset()
         self.final = (self.location + self.moves*self.increment).roundtogrid()
+        self.location = self.origin
+        self.nextlocation = None
     def reset(self):
         self.location = self.origin
         self.step = 0
@@ -3847,10 +3853,10 @@ class course:
         return self.location.quadrant()
     def sector(self):
         return self.location.sector()
-    def power(self, warp):
-        return self.distance*(warp**3)*(game.shldup+1)
-    def time(self, warp):
-        return 10.0*self.distance/warp**2
+    def power(self, w):
+        return self.distance*(w**3)*(game.shldup+1)
+    def time(self, w):
+        return 10.0*self.distance/w**2
 
 def impulse():
     "Move under impulse power."
@@ -3862,10 +3868,10 @@ def impulse():
         return
     if game.energy > 30.0:
         try:
-            course = getcourse(isprobe=False)
+            icourse = getcourse(isprobe=False)
         except TrekError:
             return
-        power = 20.0 + 100.0*course.distance
+        power = 20.0 + 100.0*icourse.distance
     else:
         power = 30.0
     if power >= game.energy:
@@ -3875,14 +3881,14 @@ def impulse():
         prout(_("require 20.0 units to engage, plus 100.0 units per"))
         if game.energy > 30:
             proutn(_("quadrant.  We can go, therefore, a maximum of %d") %
-                     int(0.01 * (game.energy-20.0)-0.05))
+                   int(0.01 * (game.energy-20.0)-0.05))
             prout(_(" quadrants.\""))
         else:
             prout(_("quadrant.  They are, therefore, useless.\""))
         scanner.chew()
         return
     # Make sure enough time is left for the trip
-    game.optime = course.distance/0.095
+    game.optime = icourse.distance/0.095
     if game.optime >= game.state.remtime:
         prout(_("First Officer Spock- \"Captain, our speed under impulse"))
         prout(_("power is only 0.95 sectors per stardate. Are you sure"))
@@ -3890,13 +3896,13 @@ def impulse():
         if not ja():
             return
     # Activate impulse engines and pay the cost
-    imove(course, noattack=False)
+    imove(icourse, noattack=False)
     game.ididit = True
     if game.alldone:
         return
-    power = 20.0 + 100.0*course.distance
+    power = 20.0 + 100.0*icourse.distance
     game.energy -= power
-    game.optime = course.distance/0.095
+    game.optime = icourse.distance/0.095
     if game.energy <= 0:
         finish(FNRG)
     return
@@ -3918,7 +3924,7 @@ def warp(wcourse, involuntary):
             prout(_("  is repaired, I can only give you warp 4.\""))
             return
                # Read in course and distance
-        if wcourse==None:
+        if wcourse is None:
             try:
                 wcourse = getcourse(isprobe=False)
             except TrekError:
@@ -4035,7 +4041,7 @@ def setwarp():
     game.warpfac = scanner.real
     if game.warpfac <= oldfac or game.warpfac <= 6.0:
         prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
-               int(game.warpfac))
+              int(game.warpfac))
         return
     if game.warpfac < 8.00:
         prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
@@ -4247,11 +4253,15 @@ def mayday():
         # There's one in this quadrant
         ddist = (game.base - game.sector).distance()
     else:
+        ibq = None     # Force base-quadrant game to persist past loop
         ddist = FOREVER
         for ibq in game.state.baseq:
             xdist = QUADSIZE * (ibq - game.quadrant).distance()
             if xdist < ddist:
                 ddist = xdist
+        if ibq is None:
+            prout(_("No starbases remain. You are alone in a hostile galaxy."))
+            return
         # Since starbase not in quadrant, set up new quadrant
         game.quadrant = ibq
         newqad()
@@ -4342,10 +4352,10 @@ def abandon():
             prout(_("to nearest habitable planet."))
         elif q.planet != None and not damaged(DTRANSP):
             prout(_("Remainder of ship's complement beam down to %s.") %
-                    q.planet)
+                  q.planet)
         else:
             prout(_("Entire crew of %d left to die in outer space.") %
-                    game.state.crew)
+                  game.state.crew)
             game.casual += game.state.crew
             game.abandoned += game.state.crew
         # If at least one base left, give 'em the Faerie Queene
@@ -4363,12 +4373,13 @@ def abandon():
         while True:
             # position next to base by trial and error
             game.quad[game.sector.i][game.sector.j] = '.'
+            l = QUADSIZE
             for l in range(QUADSIZE):
                 game.sector = game.base.scatter()
                 if game.sector.valid_sector() and \
                        game.quad[game.sector.i][game.sector.j] == '.':
                     break
-            if l < QUADSIZE+1:
+            if l < QUADSIZE:
                 break # found a spot
             game.sector.i=QUADSIZE/2
             game.sector.j=QUADSIZE/2
@@ -4467,7 +4478,7 @@ def sensor():
         if game.options & OPTION_TTY:
             prout(_("Short range sensors damaged."))
         return
-    if game.iplnet == None:
+    if game.iplnet is None:
         if game.options & OPTION_TTY:
             prout(_("Spock- \"No planet in this quadrant, Captain.\""))
         return
@@ -4888,7 +4899,7 @@ def report():
         prout(_("This is tournament game %d.") % game.tourn)
     prout(_("Your secret password is \"%s\"") % game.passwd)
     proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)),
-           (game.inkling + game.incom + game.inscom)))
+                                                      (game.inkling + game.incom + game.inscom)))
     if game.incom - len(game.state.kcmdr):
         prout(_(", including %d Commander%s.") % (game.incom - len(game.state.kcmdr), (_("s"), "")[(game.incom - len(game.state.kcmdr))==1]))
     elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
@@ -4930,7 +4941,7 @@ def report():
             proutn(_("An armed deep space probe is in "))
         else:
             proutn(_("A deep space probe is in "))
-        prout("Quadrant %s." % game.probec)
+        prout("Quadrant %s." % game.probe.quadrant())
     if game.icrystl:
         if game.cryprob <= .05:
             prout(_("Dilithium crystals aboard ship... not yet used."))
@@ -5186,7 +5197,7 @@ def eta():
         huh()
         return
     dist = math.sqrt((w1.j-game.quadrant.j+(w2.j-game.sector.j)/(QUADSIZE*1.0))**2+
-                (w1.i-game.quadrant.i+(w2.i-game.sector.i)/(QUADSIZE*1.0))**2)
+                     (w1.i-game.quadrant.i+(w2.i-game.sector.i)/(QUADSIZE*1.0))**2)
     wfl = False
     if prompt:
         prout(_("Answer \"no\" if you don't know the value:"))
@@ -5366,34 +5377,34 @@ systnames = (
     _("Beta III"),                # TOS: "The Return of the Archons"
     _("Triacus"),                # TOS: "And the Children Shall Lead",
     _("Exo III"),                # TOS: "What Are Little Girls Made Of?" (Class P)
-#        # Others
-#    _("Hansen's Planet"),        # TOS: "The Galileo Seven"
-#    _("Taurus IV"),                # TOS: "The Galileo Seven" (class G)
-#    _("Antos IV (Doraphane)"),        # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
-#    _("Izar"),                        # TOS: "Whom Gods Destroy"
-#    _("Tiburon"),                # TOS: "The Way to Eden"
-#    _("Merak II"),                # TOS: "The Cloud Minders"
-#    _("Coridan (Desotriana)"),        # TOS: "Journey to Babel"
-#    _("Iotia"),                # TOS: "A Piece of the Action"
+    #        # Others
+    #    _("Hansen's Planet"),        # TOS: "The Galileo Seven"
+    #    _("Taurus IV"),                # TOS: "The Galileo Seven" (class G)
+    #    _("Antos IV (Doraphane)"),        # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
+    #    _("Izar"),                        # TOS: "Whom Gods Destroy"
+    #    _("Tiburon"),                # TOS: "The Way to Eden"
+    #    _("Merak II"),                # TOS: "The Cloud Minders"
+    #    _("Coridan (Desotriana)"),        # TOS: "Journey to Babel"
+    #    _("Iotia"),                # TOS: "A Piece of the Action"
 )
 
 device = (
-        _("S. R. Sensors"), \
-        _("L. R. Sensors"), \
-        _("Phasers"), \
-        _("Photon Tubes"), \
-        _("Life Support"), \
-        _("Warp Engines"), \
-        _("Impulse Engines"), \
-        _("Shields"), \
-        _("Subspace Radio"), \
-        _("Shuttle Craft"), \
-        _("Computer"), \
-        _("Navigation System"), \
-        _("Transporter"), \
-        _("Shield Control"), \
-        _("Death Ray"), \
-        _("D. S. Probe"), \
+    _("S. R. Sensors"), \
+    _("L. R. Sensors"), \
+    _("Phasers"), \
+    _("Photon Tubes"), \
+    _("Life Support"), \
+    _("Warp Engines"), \
+    _("Impulse Engines"), \
+    _("Shields"), \
+    _("Subspace Radio"), \
+    _("Shuttle Craft"), \
+    _("Computer"), \
+    _("Navigation System"), \
+    _("Transporter"), \
+    _("Shield Control"), \
+    _("Death Ray"), \
+    _("D. S. Probe"), \
 )
 
 def setup():
@@ -5511,7 +5522,7 @@ def setup():
     for i in range(game.inplan):
         while True:
             w = randplace(GALSIZE)
-            if game.state.galaxy[w.i][w.j].planet == None:
+            if game.state.galaxy[w.i][w.j].planet is None:
                 break
         new = Planet()
         new.quadrant = w
@@ -5634,7 +5645,7 @@ def choose():
             if thaw():
                 continue
             scanner.chew()
-            if game.passwd == None:
+            if game.passwd is None:
                 continue
             if not game.alldone:
                 game.thawed = True # No plaque if not finished
@@ -5766,7 +5777,7 @@ def newqad():
     game.enemies = []
     if q.klingons:
         # Position ordinary Klingons
-        for i in range(game.klhere):
+        for _i in range(game.klhere):
             newkling()
         # If we need a commander, promote a Klingon
         for cmdr in game.state.kcmdr:
@@ -5782,7 +5793,7 @@ def newqad():
             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):
+    for _i in range(q.romulans):
         Enemy('R', loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
     # If quadrant needs a starbase, put it in
     if q.starbase:
@@ -5809,7 +5820,7 @@ def newqad():
     # Put in THING if needed
     if thing == game.quadrant:
         Enemy(etype='?', loc=dropin(),
-                  power=randreal(6000,6500.0)+250.0*game.skill)
+              power=randreal(6000,6500.0)+250.0*game.skill)
         if not damaged(DSRSENS):
             skip(1)
             prout(_("Mr. Spock- \"Captain, this is most unusual."))
@@ -5838,10 +5849,10 @@ def newqad():
                 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
     sortenemies()
     # And finally the stars
-    for i in range(q.stars):
+    for _i in range(q.stars):
         dropin('*')
     # Put in a few black holes
-    for i in range(1, 3+1):
+    for _i in range(1, 3+1):
         if withprob(0.5):
             dropin(' ')
     # Take out X's in corners if Tholian present
@@ -6004,6 +6015,8 @@ def makemoves():
             setwnd(message_window)
             clrscr()
             abandon_passed = False
+            cmd = ""   # Force cmd to persist after loop
+            opt = 0    # Force opt to persist after loop
             for (cmd, opt) in commands:
                 # commands after ABANDON cannot be abbreviated
                 if cmd == "ABANDON":
@@ -6142,27 +6155,27 @@ def makemoves():
     if game.idebug:
         prout("=== Ending")
 
-def cramen(type):
+def cramen(ch):
     "Emit the name of an enemy or feature."
-    if   type == 'R': s = _("Romulan")
-    elif type == 'K': s = _("Klingon")
-    elif type == 'C': s = _("Commander")
-    elif type == 'S': s = _("Super-commander")
-    elif type == '*': s = _("Star")
-    elif type == 'P': s = _("Planet")
-    elif type == 'B': s = _("Starbase")
-    elif type == ' ': s = _("Black hole")
-    elif type == 'T': s = _("Tholian")
-    elif type == '#': s = _("Tholian web")
-    elif type == '?': s = _("Stranger")
-    elif type == '@': s = _("Inhabited World")
+    if   ch == 'R': s = _("Romulan")
+    elif ch == 'K': s = _("Klingon")
+    elif ch == 'C': s = _("Commander")
+    elif ch == 'S': s = _("Super-commander")
+    elif ch == '*': s = _("Star")
+    elif ch == 'P': s = _("Planet")
+    elif ch == 'B': s = _("Starbase")
+    elif ch == ' ': s = _("Black hole")
+    elif ch == 'T': s = _("Tholian")
+    elif ch == '#': s = _("Tholian web")
+    elif ch == '?': s = _("Stranger")
+    elif ch == '@': s = _("Inhabited World")
     else: s = "Unknown??"
     return s
 
-def crmena(stars, enemy, loctype, w):
+def crmena(loud, enemy, loctype, w):
     "Emit the name of an enemy and his location."
     buf = ""
-    if stars:
+    if loud:
         buf += "***"
     buf += cramen(enemy) + _(" at ")
     if loctype == "quadrant":
@@ -6202,17 +6215,17 @@ class sstscanner:
         self.token = ''
         # Fill the token quue if nothing here
         while not self.inqueue:
-            line = cgetline()
+            sline = cgetline()
             if curwnd==prompt_window:
                 clrscr()
                 setwnd(message_window)
                 clrscr()
-            if line == '':
+            if sline == '':
                 return None
-            if not line:
+            if not sline:
                 continue
             else:
-                self.inqueue = line.lstrip().split() + ["\n"]
+                self.inqueue = sline.lstrip().split() + ["\n"]
         # From here on in it's all looking at the queue
         self.token = self.inqueue.pop(0)
         if self.token == "\n":
@@ -6244,22 +6257,22 @@ class sstscanner:
         return s.startswith(self.token)
     def int(self):
         # Round token value to nearest integer
-        return int(round(scanner.real))
+        return int(round(self.real))
     def getcoord(self):
         s = Coord()
-        scanner.nexttok()
-        if scanner.type != "IHREAL":
+        self.nexttok()
+        if self.type != "IHREAL":
             huh()
             return None
-        s.i = scanner.int()-1
-        scanner.nexttok()
-        if scanner.type != "IHREAL":
+        s.i = self.int()-1
+        self.nexttok()
+        if self.type != "IHREAL":
             huh()
             return None
-        s.j = scanner.int()-1
+        s.j = self.int()-1
         return s
     def __repr__(self):
-        return "<sstcanner: token=%s, type=%s, queue=%s>" % (scanner.token, scanner.type, scanner.inqueue)
+        return "<sstcanner: token=%s, type=%s, queue=%s>" % (self.token, self.type, self.inqueue)
 
 def ja():
     "Yes-or-no confirmation."
@@ -6367,9 +6380,8 @@ def debugme():
         atover(True)
 
 if __name__ == '__main__':
-    import getopt, socket
     try:
-        global line, thing, game
+        #global line, thing, game
         game = None
         thing = Thingy()
         game = Gamestate()