Suppress Supercommander creation befor 1979 versiom.
[super-star-trek.git] / sst
diff --git a/sst b/sst
index 21935f4ebee7b9c7faa103c9150c208222fe3303..3d30875c8c47e9b5dbfb62fe08c4b6ae4055d5d4 100755 (executable)
--- a/sst
+++ b/sst
@@ -298,43 +298,46 @@ OPTION_CURSES     = 0x00000002        # new interface
 OPTION_IOMODES    = 0x00000003        # cover both interfaces
 OPTION_PLANETS    = 0x00000004        # planets and mining (> 1974)
 OPTION_THOLIAN    = 0x00000008        # Tholians and their webs (UT 1979 version)
+OPTION_SUPERCMDR  = 0x00000010        # Supercommanders (UT 1979 version)
 OPTION_PROBE      = 0x00000020        # deep-space probes (DECUS version, 1980)
-OPTION_SHOWME     = 0x00000040        # bracket Enterprise in chart (ESR, 2005)
-OPTION_RAMMING    = 0x00000080        # enemies may ram Enterprise (Almy, 1979)
-OPTION_MVBADDY    = 0x00000100        # more enemies can move (Almy, 1979?)
+OPTION_MVBADDY    = 0x00000040        # more enemies can move (Almy, 1979?)
+OPTION_RAMMING    = 0x00000080        # enemies may ram Enterprise (Almy, 1979?)
+OPTION_ALMY       = 0x00000100        # Almy's death ray upgrade (1997?)
 OPTION_AUTOPASS   = 0x00000200        # Autogenerate password (Almy, 1997?)
-OPTION_BLKHOLE    = 0x00000400        # black hole may timewarp you (Stas, 2005)
-OPTION_BASE       = 0x00000800        # bases have good shields (Stas, 2005)
-OPTION_WORLDS     = 0x00001000        # logic for inhabited worlds (ESR, 2006)
-OPTION_AUTOSCAN   = 0x00002000        # automatic LRSCAN before CHART (ESR, 2006)
-OPTION_CAPTURE    = 0x00004000        # Enable BSD-Trek capture (Almy, 2013).
-OPTION_CLOAK      = 0x80008000        # Enable BSD-Trek capture (Almy, 2013).
-OPTION_ALMY       = 0x01000000        # Almy's death ray upgrade (1997?)
-OPTION_COLOR      = 0x04000000        # enable color display (ESR, 2010)
-OPTION_DOTFILL    = 0x08000000        # fix dotfill glitch in chart (ESR, 2019)
-OPTION_ALPHAMERIC = 0x10000000        # Alpha Y coordinates (ESR, 2023)
+OPTION_BASE       = 0x00000400        # bases have good shields (Stas, 2005)
+OPTION_BLKHOLE    = 0x00000800        # black hole may timewarp you (Stas, 2005)
+OPTION_SHOWME     = 0x00001000        # bracket Enterprise in chart (ESR, 2005)
+OPTION_WORLDS     = 0x00002000        # logic for inhabited worlds (ESR, 2006)
+OPTION_AUTOSCAN   = 0x00004000        # automatic LRSCAN before CHART (ESR, 2006)
+OPTION_COLOR      = 0x00008000        # enable color display (ESR, 2010)
+OPTION_CAPTURE    = 0x00010000        # Enable BSD-Trek capture (Almy, 2013).
+OPTION_CLOAK      = 0x10020000        # Enable BSD-Trek capture (Almy, 2013).
+OPTION_DOTFILL    = 0x01040000        # fix dotfill glitch in chart (ESR, 2019)
+OPTION_ALPHAMERIC = 0x00080000        # Alpha Y coordinates (ESR, 2023)
 
 option_names = {
-    "ALL": OPTION_ALL,
-    "TTY": OPTION_TTY,
-    "IOMODES": OPTION_IOMODES,
-    "PLANETS": OPTION_PLANETS,
-    "PROBE": OPTION_PROBE,
-    "SHOWME": OPTION_SHOWME,
-    "RAMMING": OPTION_RAMMING,
-    "MVBADDY": OPTION_MVBADDY,
-    "AUTOPASS": OPTION_AUTOPASS,
-    "BLKHOLE": OPTION_BLKHOLE,
-    "BASE": OPTION_BASE,
-    "WORLDS": OPTION_WORLDS,
-    "AUTOSCAN": OPTION_AUTOSCAN,
-    "CAPTURE": OPTION_CAPTURE,
-    "CLOAK": OPTION_CLOAK,
-    "ALMY": OPTION_ALMY,
-    "COLOR": OPTION_COLOR,
-    "DOTFILL": OPTION_DOTFILL,
-    "ALPHAMERIC": OPTION_ALPHAMERIC,
-    }
+    "ALL": (OPTION_ALL, 0),
+    "TTY": (OPTION_TTY, 0),
+    "IOMODES": (OPTION_IOMODES, 0),
+    "PLANETS": (OPTION_PLANETS, 1974),
+    "THOLIAN": (OPTION_THOLIAN, 1979),
+    "SUPERCMDR": (OPTION_SUPERCMDR, 1979),
+    "PROBE": (OPTION_PROBE, 1980),
+    "MVBADDY": (OPTION_MVBADDY, 1981),   # year bumped to make it distinct
+    "RAMMING": (OPTION_RAMMING, 1982),   # year bumped to make it distinct
+    "ALMY": (OPTION_ALMY, 1997),
+    "AUTOPASS": (OPTION_AUTOPASS, 1998), # year bumped to make it distinct
+    "BASE": (OPTION_BASE, 2004),        # year bumped to make it distinct
+    "BLKHOLE": (OPTION_BLKHOLE, 2004),   # year bumped to make it distinct
+    "SHOWME": (OPTION_SHOWME, 2005),
+    "WORLDS": (OPTION_WORLDS, 2006),
+    "AUTOSCAN": (OPTION_AUTOSCAN, 2007),  # year bumped to make it distinct
+    "COLOR": (OPTION_COLOR, 2010),
+    "CAPTURE": (OPTION_CAPTURE, 2013),
+    "CLOAK": (OPTION_CLOAK, 2014),        # year bumped to make it distinct
+    "DOTFILL": (OPTION_DOTFILL, 2019),
+    "ALPHAMERIC": (OPTION_ALPHAMERIC, 2023)
+}
 
 # Define devices
 DSRSENS         = 0
@@ -4184,7 +4187,7 @@ def impulse():
     return
 
 def warp(wcourse, involuntary):
-    "ove under warp drive."
+    "Move under warp drive."
     blooey = False; twarp = False
     if not involuntary: # Not WARPX entry
         game.ididit = False
@@ -5606,7 +5609,7 @@ def goptions():
     if mode == "IHEOL":
         active = []
         for k, v in option_names.items():
-            if (v & game.options) and k != "ALL":
+            if (v[0] & game.options) and k != "ALL":
                 active.append(k)
         active.sort()
         prout(str(" ".join(active)))
@@ -5618,7 +5621,7 @@ def goptions():
             if scanner.type == "IHEOL":
                 break
             if scanner.token.upper() in option_names:
-                changemask |= option_names[scanner.token.upper()]
+                changemask |= option_names[scanner.token.upper()][0]
             else:
                 prout(_("No such option as ") + scanner.token)
         if mode == "set":
@@ -5981,28 +5984,45 @@ def setup():
 
 def choose():
     "Choose your game type."
-    while True:
-        game.tourn = None
-        game.length = 0
-        game.thawed = False
-        game.skill = SKILL_NONE
-        # Do not chew here, we want to use command-line tokens
-        if not scanner.inqueue: # Can start with command line options
-            proutn(_("Would you like a regular, tournament, or saved game? "))
+    game.tourn = None
+    game.length = 0
+    game.thawed = False
+    game.skill = SKILL_NONE
+    gametype = None
+    wayback = 0
+    while gametype is None or game.length == 0 or game.skill == SKILL_NONE or wayback == 0:
+        eol_is_fancy = False
+        if not scanner.inqueue or scanner.token == "IHEOL": # Can start with command line options
+            if gametype is None:
+                proutn(_("Would you like a regular, tournament, or saved game? "))
+            elif game.length==0:
+                proutn(_("Would you like a Short, Medium, or Long game? "))
+            elif game.skill == SKILL_NONE:
+                proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
+            elif wayback == 0:
+                proutn(_("Wayback setting (press enter for current year): "))
+                eol_is_fancy = True
         scanner.nexttok()
-        if scanner.sees("tournament"):
+        if game.idebug:
+            prout("-- Token: %s=%s" % (scanner.type, repr(scanner.token)))
+        if scanner.token == "":
+            raise SystemExit(0)        # Early end of replay
+        if scanner.token.startswith("r"):      # regular
+            gametype = "regular"
+        elif scanner.token.startswith("t"):
+            gametype = "tournament"
+            proutn(_("Type in tournament number-"))
             game.tourn = 0
             while scanner.nexttok() == "IHEOL":
-                proutn(_("Type in tournament number-"))
-            if scanner.real == 0:
-                scanner.chew()
-                continue # We don't want a blank entry
+                if scanner.real == 0:
+                    scanner.chew()
+                    continue # We don't want a blank entry
             game.tourn = int(round(scanner.real))
             rnd.seed(scanner.real)
             if logfp:
                 logfp.write("# rnd.seed(%d)\n" % scanner.real)
-            break
-        if scanner.sees("saved") or scanner.sees("frozen"):
+        elif scanner.token.startswith("sa") or scanner.token.startswith("fr"): # saved or frozen
+            gametype = "saved"
             if thaw():
                 continue
             scanner.chew()
@@ -6013,57 +6033,42 @@ def choose():
             report()
             waitfor()
             return True
-        if scanner.sees("regular"):
-            break
-        proutn(_("What game type is \"%s\"? ") % scanner.token)
-        scanner.chew()
-    while game.length==0 or game.skill==SKILL_NONE:
-        if scanner.nexttok() == "IHALPHA":
-            if scanner.sees("short"):
-                game.length = 1
-            elif scanner.sees("medium"):
-                game.length = 2
-            elif scanner.sees("long"):
-                game.length = 4
-            elif scanner.sees("novice"):
-                game.skill = SKILL_NOVICE
-            elif scanner.sees("fair"):
-                game.skill = SKILL_FAIR
-            elif scanner.sees("good"):
-                game.skill = SKILL_GOOD
-            elif scanner.sees("expert"):
-                game.skill = SKILL_EXPERT
-            elif scanner.sees("emeritus"):
-                game.skill = SKILL_EMERITUS
-            else:
-                proutn(_("What skill level is is \""))
-                proutn(scanner.token)
-                prout("\"?")
+        elif scanner.token.startswith("s"):            # short
+            game.length = 1
+        elif scanner.token.startswith("m"):            # medium
+            game.length = 2
+        elif scanner.token.startswith("l"):            # long
+            game.length = 4
+        elif scanner.token.startswith("n"):            # novice
+            game.skill = SKILL_NOVICE
+        elif (game.skill is None) and scanner.token.startswith("f"):           # fair
+            game.skill = SKILL_FAIR
+        elif scanner.token.startswith("g"):            # good
+            game.skill = SKILL_GOOD
+        elif scanner.token.startswith("e"):            # expert
+            game.skill = SKILL_EXPERT
+        elif scanner.token.startswith("em"):   # emeritus
+            game.skill = SKILL_EMERITUS
+        elif scanner.type == "IHREAL":
+            wayback = scanner.int()
+        elif (eol_is_fancy and scanner.token.startswith("\n")):
+            wayback = time.localtime().tm_year
+        elif scanner.token.startswith("\n"):
+            continue
+        elif scanner.token.startswith("idebug"):
+            game.idebug = True
         else:
-            scanner.chew()
-            if game.length==0:
-                proutn(_("Would you like a Short, Medium, or Long game? "))
-            elif game.skill == SKILL_NONE:
-                proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
-    # Choose game options -- added by ESR for SST2K
-    if scanner.nexttok() != "IHALPHA":
-        scanner.chew()
-        proutn(_("Choose your game style (plain, almy, fancy or just press enter): "))
-        scanner.nexttok()
-    if scanner.sees("plain"):
-        # Approximates the UT FORTRAN version.
-        game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS | OPTION_COLOR | OPTION_CAPTURE | OPTION_CLOAK | OPTION_ALMY | OPTION_AUTOPASS | OPTION_DOTFILL | OPTION_ALPHAMERIC)
-    elif scanner.sees("almy"):
-        # Approximates Tom Almy's version.
-        game.options &=~ (OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS | OPTION_COLOR | OPTION_DOTFILL | OPTION_ALPHAMERIC)
-    elif scanner.sees("fancy") or scanner.sees("\n"):
-        pass
-    elif len(scanner.token):
-        proutn(_("What game style is \"%s\"?") % scanner.token)
+            # Unrecognized token
+            prout(_("Can't interpret %s") % repr(scanner.token))
+    for (name, (option, year)) in option_names.items():
+        if wayback < year:
+            game.options &=~ option
     setpassword()
     if game.passwd == "debug":                # pragma: no cover
         game.idebug = True
         prout("=== Debug mode enabled.")
+    if game.idebug:
+        prout("--- Setup: type=%s length=%s skill=%s wayback=%s" % (gametype, game.length, game.skill, wayback))
     # Use parameters to generate initial values of things
     game.damfac = 0.5 * game.skill
     game.inbase = rnd.integer(BASEMIN, BASEMAX+1)
@@ -6073,7 +6078,7 @@ def choose():
     if game.options & OPTION_WORLDS:
         game.inplan += int(NINHAB)
     game.state.nromrem = game.inrom = rnd.integer(2 * game.skill)
-    game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
+    game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR) and ((game.options & OPTION_SUPERCMDR) != 0)
     game.state.remtime = 7.0 * game.length
     game.intime = game.state.remtime
     game.inkling = int(2.0*game.intime*((game.skill+1 - 2*rnd.real())*game.skill*0.1+.15))
@@ -6802,12 +6807,17 @@ if __name__ == '__main__':
                         raise SystemExit(1)
                     # pylint: disable=raise-missing-from
                     try:
-                        line = replayfp.readline().strip()
-                        (leader, __, seed) = line.split()
-                        # pylint: disable=eval-used
-                        seed = eval(seed)
-                        line = replayfp.readline().strip()
-                        arguments += line.split()[2:]
+                        while True:
+                            line = replayfp.readline().strip()
+                            print(line)
+                            if line == "#":
+                                break
+                            if line.startswith("# seed"):
+                                (__, __, seed) = line.split()
+                                # pylint: disable=eval-used
+                                seed = eval(seed)
+                            elif line.startswith("# arguments"):
+                                arguments += line.split()[2:]
                     except ValueError:                # pragma: no cover
                         sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
                         raise SystemExit(1)