X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=sst;h=2c55b91fcb0081ad9e4ee7dc66c8fd2cf5c866fd;hb=94b8d1423ae292c0deebb60ada946180c06a2dd7;hp=b9d9a6acf9c3467a64676c7bcca2962f8450dbc0;hpb=793f66ce5c1dfffc87683b5085ca127b6d9e3159;p=super-star-trek.git diff --git a/sst b/sst index b9d9a6a..2c55b91 100755 --- a/sst +++ b/sst @@ -18,7 +18,7 @@ on how to modify (and how not to modify!) this code. # pylint: disable=multiple-imports import os, sys, math, curses, time, pickle, copy, gettext, getpass -import getopt, socket, locale +import getopt, socket import codecs # This import only works on Unixes. The intention is to enable @@ -88,6 +88,14 @@ class randomizer: # logfp.write("#seed(%d)\n" % n) game.lcg_x = n % randomizer.LCG_M + @staticmethod + def getrngstate(): + return game.lcg_x + + @staticmethod + def setrngstate(n): + game.lcg_x = n + GALSIZE = 8 # Galaxy size in quadrants NINHAB = (GALSIZE * GALSIZE // 2) # Number of inhabited worlds MAXUNINHAB = 10 # Maximum uninhabited worlds @@ -195,11 +203,6 @@ class Coord: return self.roundtogrid() // QUADSIZE def sector(self): return self.roundtogrid() % QUADSIZE - def scatter(self): - s = Coord() - s.i = self.i + rnd.integer(-1, 2) - s.j = self.j + rnd.integer(-1, 2) - return s def __str__(self): if self.i is None or self.j is None: return "Nowhere" # pragma: no cover @@ -208,15 +211,15 @@ class Coord: return "%s - %s" % (self.i+1, self.j+1) __repr__ = __str__ -class Thingy(Coord): +class Thingy(): "Do not anger the Space Thingy!" def __init__(self): - Coord.__init__(self) + self.location = Coord() self.angered = False def angry(self): self.angered = True def at(self, q): - return (q.i, q.j) == (self.i, self.j) + return (q.i, q.j) == (self.location.i, self.location.j) class Planet: def __init__(self): @@ -3412,11 +3415,6 @@ 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 python3 - # has no problems at all - if sys.version_info[0] < 3: - locale.setlocale(locale.LC_ALL, "") gettext.bindtextdomain("sst", "/usr/local/share/locale") gettext.textdomain("sst") if not (game.options & OPTION_CURSES): @@ -3425,7 +3423,7 @@ def iostart(): rows = ln_env else: rows = 25 - else: + else: # pragma: no cover stdscr = curses.initscr() stdscr.keypad(True) curses.nonl() @@ -3456,7 +3454,7 @@ def iostart(): def ioend(): "Wrap up I/O." - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover stdscr.keypad(False) curses.echo() curses.nocbreak() @@ -3464,7 +3462,7 @@ def ioend(): def waitfor(): "Wait for user action -- OK to do nothing if on a TTY" - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover stdscr.getch() def announce(): @@ -3478,7 +3476,7 @@ def pause_game(): else: prompt = _("[PRESS ENTER TO CONTINUE]") - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover drawmaps(0) setwnd(prompt_window) prompt_window.clear() @@ -3499,7 +3497,7 @@ def pause_game(): def skip(i): "Skip i lines. Pause game if this would cause a scrolling event." for _dummy in range(i): - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover (y, _x) = curwnd.getyx() try: curwnd.move(y+1, 0) @@ -3515,7 +3513,7 @@ def skip(i): def proutn(proutntline): "Utter a line with no following line feed." - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover (y, x) = curwnd.getyx() (my, _mx) = curwnd.getmaxyx() if curwnd == message_window and y >= my - 2: @@ -3539,7 +3537,7 @@ def prouts(proutsline): if not replayfp or replayfp.closed: # Don't slow down replays time.sleep(0.03) proutn(c) - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover curwnd.refresh() else: sys.stdout.flush() @@ -3548,7 +3546,7 @@ def prouts(proutsline): def cgetline(): "Get a line of input." - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover linein = codecs.decode(curwnd.getstr()) + "\n" curwnd.refresh() else: @@ -3556,7 +3554,7 @@ def cgetline(): while True: linein = replayfp.readline() proutn(linein) - if linein == '': + if linein == '': # pragma: no cover prout("*** Replay finished") replayfp.close() break @@ -3575,7 +3573,7 @@ def cgetline(): def setwnd(wnd): "Change windows -- OK for this to be a no-op in tty mode." global curwnd - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover if game.cdebug and logfp: if wnd == fullscreen_window: legend = "fullscreen" @@ -3603,21 +3601,21 @@ def setwnd(wnd): def clreol(): "Clear to end of line -- can be a no-op in tty mode" - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover curwnd.clrtoeol() curwnd.refresh() def clrscr(): "Clear screen -- can be a no-op in tty mode." global linecount - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover curwnd.clear() curwnd.move(0, 0) curwnd.refresh() linecount = 0 def textcolor(color=DEFAULT): - if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES): + if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES): # pragma: no cover if color == DEFAULT: curwnd.attrset(0) elif color == BLACK: @@ -3654,7 +3652,7 @@ def textcolor(color=DEFAULT): curwnd.attron(curses.color_pair(curses.COLOR_WHITE) | curses.A_BOLD) def highvideo(): - if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES): + if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES): # pragma: no cover curwnd.attron(curses.A_REVERSE) # @@ -3663,7 +3661,7 @@ def highvideo(): def drawmaps(mode): "Hook to be called after moving to redraw maps." - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover if mode == 1: sensor() setwnd(srscan_window) @@ -3682,7 +3680,7 @@ def drawmaps(mode): lrscan_window.move(0, 0) lrscan(silent=False) -def put_srscan_sym(w, sym): +def put_srscan_sym(w, sym): # pragma: no cover "Emit symbol for short-range scan." srscan_window.move(w.i+1, w.j*2+2) srscan_window.addch(sym) @@ -3690,7 +3688,7 @@ def put_srscan_sym(w, sym): def boom(w): "Enemy fall down, go boom." - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover drawmaps(0) setwnd(srscan_window) srscan_window.attron(curses.A_REVERSE) @@ -3705,12 +3703,12 @@ def boom(w): def warble(): "Sound and visual effects for teleportation." - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover drawmaps(2) setwnd(message_window) #sound(50) prouts(" . . . . . ") - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover #curses.delay_output(1000) #nosound() pass @@ -3728,7 +3726,7 @@ def tracktorpedo(w, step, i, n, iquad): elif step in {4, 9}: skip(1) proutn("%s " % w) - else: + else: # pragma: no cover if not damaged(DSRSENS) or game.condition=="docked": if i != 0 and step == 1: drawmaps(2) @@ -3752,7 +3750,7 @@ def tracktorpedo(w, step, i, n, iquad): def makechart(): "Display the current galaxy chart." - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover setwnd(message_window) message_window.clear() chart() @@ -3763,14 +3761,14 @@ NSYM = 14 def prstat(txt, data): proutn(txt) - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover skip(1) setwnd(status_window) else: proutn(" " * (NSYM - len(txt))) proutn(data) skip(1) - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover setwnd(report_window) # Code from moving.c begins here @@ -3848,7 +3846,7 @@ def imove(icourse=None, noattack=False): return True # This should not happen prout(_("Which way did he go?")) # pragma: no cover - return False + return False # pragma: no cover elif iquad == ' ': skip(1) prouts(_("***RED ALERT! RED ALERT!")) @@ -4590,7 +4588,7 @@ def mayday(): break prout(_("fails.")) textcolor(DEFAULT) - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover curses.delay_output(500) if m > 3: game.quad[game.sector.i][game.sector.j]='?' @@ -5373,7 +5371,7 @@ def sectscan(goodScan, i, j): if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1): if game.quad[i][j] in ('E', 'F'): if game.iscloaked: - highvideo() + highvideo() # pragma: no cover textcolor({"green":GREEN, "yellow":YELLOW, "red":RED, @@ -5634,11 +5632,11 @@ def goptions(): else: prout(_("No such option as ") + scanner.token) if mode == "set": - if (not (game.options & OPTION_CURSES)) and (changemask & OPTION_CURSES): + if (not (game.options & OPTION_CURSES)) and (changemask & OPTION_CURSES): # pragma: no cover iostart() game.options |= changemask elif mode == "clear": - if (game.options & OPTION_CURSES) and (not (changemask & OPTION_CURSES)): + if (game.options & OPTION_CURSES) and (not (changemask & OPTION_CURSES)): # pragma: no cover ioend() game.options &=~ changemask prout(_("Acknowledged, Captain.")) @@ -5940,12 +5938,17 @@ def setup(): # Place thing (in tournament game, we don't want one!) # New in SST2K: never place the Thing near a starbase. # This makes sense and avoids a special case in the old code. - global thing if game.tourn is None: + # Avoid distrubing the RNG chain. This code + # was a late fix and we don't want to mess up + # all the regression tests. + state = randomizer.getrngstate() while True: - thing = randplace(GALSIZE) - if thing not in game.state.baseq: + thing.location = randplace(GALSIZE) + # Put it somewhere a starbase is not + if thing.location not in game.state.baseq: break + randomizer.setrngstate(state) skip(2) game.state.snap = False if game.skill == SKILL_NOVICE: @@ -5981,7 +5984,7 @@ def setup(): clrscr() setwnd(message_window) newqad() - if len(game.enemies) - (thing == game.quadrant) - (game.tholian is not None): + if len(game.enemies) - (thing.location == game.quadrant) - (game.tholian is not None): game.shldup = True if game.neutz: # bad luck to start in a Romulan Neutral Zone attack(torps_ok=False) @@ -5989,7 +5992,8 @@ def setup(): def choose(): "Choose your game type." while True: - game.tourn = game.length = 0 + game.tourn = None + game.length = 0 game.thawed = False game.skill = SKILL_NONE # Do not chew here, we want to use command-line tokens @@ -5997,6 +6001,7 @@ def choose(): proutn(_("Would you like a regular, tournament, or saved game? ")) scanner.nexttok() if scanner.sees("tournament"): + game.tourn = 0 while scanner.nexttok() == "IHEOL": proutn(_("Type in tournament number-")) if scanner.real == 0: @@ -6184,7 +6189,7 @@ def newqad(): prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE.")) prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!")) # Put in THING if needed - if thing == game.quadrant: + if thing.location == game.quadrant: Enemy(etype='?', loc=dropin(), power=rnd.real(6000,6500.0)+250.0*game.skill) if not damaged(DSRSENS): @@ -6387,7 +6392,7 @@ def makemoves(): clrscr() proutn("COMMAND> ") if scanner.nexttok() == "IHEOL": - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover makechart() continue elif scanner.token == "": @@ -6413,7 +6418,7 @@ def makemoves(): huh() else: break - if game.options & OPTION_CURSES: + if game.options & OPTION_CURSES: # pragma: no cover prout("COMMAND> %s" % cmd) if cmd == "SRSCAN": # srscan srscan() @@ -6521,7 +6526,7 @@ def makemoves(): helpme() # get help elif cmd == "SCORE": score() # see current score - elif cmd == "CURSES": + elif cmd == "CURSES": # pragma: no cover game.options |= (OPTION_CURSES | OPTION_COLOR) iostart() elif cmd == "OPTIONS": @@ -6793,7 +6798,7 @@ if __name__ == '__main__': logfp = None game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY) if os.getenv("TERM"): - game.options |= OPTION_CURSES + game.options |= OPTION_CURSES # pragma: no cover else: game.options |= OPTION_TTY seed = int(time.time()) @@ -6821,7 +6826,7 @@ if __name__ == '__main__': game.options &=~ OPTION_CURSES elif switch == '-s': # pragma: no cover seed = int(val) - elif switch == '-t': + elif switch == '-t': # pragma: no cover game.options |= OPTION_TTY game.options &=~ OPTION_CURSES elif switch == '-x': # pragma: no cover