X-Git-Url: https://jxself.org/git/?p=super-star-trek.git;a=blobdiff_plain;f=sst.py;h=3c985160fba4019a27ce677f09b12dd9040f7eb4;hp=c1d49dd21fa209841b4323a0d8ac7ffc67cce636;hb=0a154af018fad598ab67742e26429e7272fc5c2e;hpb=fea7d5a0f4201c2e9d0510bfc40bda28d7beb549 diff --git a/sst.py b/sst.py index c1d49dd..3c98516 100755 --- 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. @@ -22,7 +23,7 @@ except ImportError: version = "2.1" -docpath = (".", "../doc", "/usr/share/doc/sst") +docpath = (".", "doc/", "/usr/share/doc/sst/") def _(st): return gettext.gettext(st) @@ -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__ @@ -211,22 +212,23 @@ class Event: # game options OPTION_ALL = 0xffffffff OPTION_TTY = 0x00000001 # old interface -OPTION_CURSES = 0x00000002 # new interface -OPTION_IOMODES = 0x00000003 # cover both interfaces -OPTION_PLANETS = 0x00000004 # planets and mining -OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version) -OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005) -OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980) -OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart -OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy) -OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy) -OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005) -OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005) -OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006) -OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006) -OPTION_PLAIN = 0x01000000 # user chose plain game -OPTION_ALMY = 0x02000000 # user chose Almy variant -OPTION_COLOR = 0x04000000 # enable color display (experimental, ESR, 2010) +OPTION_CURSES = 0x00000002 # new interface +OPTION_IOMODES = 0x00000003 # cover both interfaces +OPTION_PLANETS = 0x00000004 # planets and mining +OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version) +OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005) +OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980) +OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart +OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy) +OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy) +OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005) +OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005) +OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006) +OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006) +OPTION_PLAIN = 0x01000000 # user chose plain game +OPTION_ALMY = 0x02000000 # user chose Almy variant +OPTION_COLOR = 0x04000000 # enable color display (ESR, 2010) +OPTION_CAPTURE = 0x80000000 # Enable BSD-Trek capture (Almy, 2013). # Define devices DSRSENS = 0 @@ -393,6 +395,9 @@ class Gamestate: self.perdate = 0.0 # rate of kills self.idebug = False # Debugging instrumentation enabled? self.statekscmdr = None # No SuperCommander coordinates yet. + self.brigcapacity = 400 # Enterprise brig capacity + self.brigfree = 400 # How many klingons can we put in the brig? + self.kcaptured = 0 # Total Klingons captured, for scoring. def recompute(self): # Stas thinks this should be (C expression): # game.state.remkl + len(game.state.kcmdr) > 0 ? @@ -489,7 +494,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 +1410,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 +1600,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 +1612,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 torpedoes @@ -1741,9 +1746,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): @@ -1982,7 +1987,67 @@ def phasers(): game.shldup = False overheat(rpow) -# Code from events,c begins here. + +def capture(): + game.ididit = False # Nothing if we fail + Time = 0.0; + + # Make sure there is room in the brig */ + if game.brigfree == 0: + prout(_("Security reports the brig is already full.")) + return; + + if damaged(DRADIO): + prout(_("Uhura- \"We have no subspace radio communication, sir.\"")) + return + + if damaged(DTRANSP): + prout(_("Scotty- \"Transporter damaged, sir.\"")) + return + + # find out if there are any at all + if game.klhere < 1: + prout(_("Uhura- \"Getting no response, sir.\"")) + return + + # if there is more than one Klingon, find out which one */ + # Cruddy, just takes one at random. Should ask the captain. + # Nah, just select the weakest one since it is most likely to + # surrender (Tom Almy mod) + klingons = [e for e in game.enemies if e.type == 'K'] + weakest = sorted(klingons, key=lambda e: e.power) + Time = 0.05 # This action will take some time + game.ididit = True # So any others can strike back + + # check out that Klingon + # The algorithm isn't that great and could use some more + # intelligent design + # x = 300 + 25*skill; + x = game.energy / (weakest.power * len(klingons)) + x *= 2.5; # would originally have been equivalent of 1.4, + # but we want command to work more often, more humanely */ + #prout(_("Prob = %d (%.4f)\n", i, x)) + # x = 100; // For testing, of course! + if x > randreal(100): + # guess what, he surrendered!!! */ + prout(_("Klingon captain at %s surrenders.") % weakest.location) + i = randreal(200) + if i > 0: + prout(_("%d Klingons commit suicide rather than be taken captive.") % 200 - i) + if i > brigfree: + prout(_("%d Klingons die because there is no room for them in the brig.") % i-brigfree) + i = brigfree + brigfree -= i + prout(_("%d captives taken") % i) + deadkl(weakest.location, weakest.type, game.sector) + if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)<=0: + finish(FWON) + return + + # big surprise, he refuses to surrender */ + prout(_("Fat chance, captain!")) + +# Code from events.c begins here. # This isn't a real event queue a la BSD Trek yet -- you can only have one # event of each type active at any given time. Mostly these means we can @@ -2234,16 +2299,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 +2399,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 +2463,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 +2534,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 +2623,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 +2662,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 +2676,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 +2761,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 +2847,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 @@ -2796,6 +2865,9 @@ def finish(ifin): prout(_("You have smashed the Klingon invasion fleet and saved")) prout(_("the Federation.")) + if game.alive and game.brigcapacity-game.brigfree > 0: + game.kcaptured += game.brigcapacity-game.brigfree + prout(_("The %d captured Klingons are transferred to Star Fleet Command.") % (game.brigcapacity-game.brigfree)) game.gamewon = True if game.alive: badpt = badpoints() @@ -2997,6 +3069,7 @@ def score(): + 20*(game.inrom - game.state.nromrem) \ + 200*(game.inscom - game.state.nscrem) \ - game.state.nromrem \ + + 3 * game.kcaptured \ - badpoints() if not game.alive: game.score -= 200 @@ -3014,6 +3087,9 @@ def score(): if game.incom - len(game.state.kcmdr): prout(_("%6d Klingon commanders destroyed %5d") % (game.incom - len(game.state.kcmdr), 50*(game.incom - len(game.state.kcmdr)))) + if game.kcaptured: + prout(_("%d Klingons captured %5d") % + (game.kcaptured, 3 * game.kcaptured)) if game.inscom - game.state.nscrem: prout(_("%6d Super-Commander destroyed %5d") % (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem))) @@ -3110,7 +3186,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 +3207,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 +3238,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 +3293,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 +3308,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 +3345,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 +3590,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 +3639,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 +3691,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 +3732,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: @@ -3662,6 +3741,10 @@ def dock(verbose): game.torps = game.intorps game.lsupres = game.inlsr game.state.crew = FULLCREW + if game.brigcapacity-game.brigfree > 0: + prout(_("%d captured Klingons transferred to base") % (game.brigcapacity-game.brigfree)) + game.kcaptured += game.brigcapacity-game.brigfree + game.brigfree = game.brigcapacity if not damaged(DRADIO) and \ ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit): # get attack report from base @@ -3679,7 +3762,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 +3904,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 +3928,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 +3943,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 +3956,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 +3971,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 +3999,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 +4116,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 +4328,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 +4427,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 +4448,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 @@ -4394,6 +4480,7 @@ def abandon(): game.lsupres=game.inlsr=3.0 game.shldup=False game.warpfac=5.0 + game.brigfree = game.brigcapacity = 300 return # Code from planets.c begins here. @@ -4467,7 +4554,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 +4975,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: @@ -4913,6 +5000,18 @@ def report(): game.iseenit = True if game.casual: prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1])) + if game.brigcapacity != game.brigfree: + embriggened = brigcapacity-brigfree + if embriggened == 1: + prout(_("1 Klingon in brig")) + else: + prout(_("%d Klingons in brig.") % embriggened) + if game.kcaptured == 0: + pass + elif game.kcaptured == 1: + prout(_("1 captured Klingon turned in to Starfleet.")) + else: + prout(_("%d captured Klingons turned in to Star Fleet.") % game.kcaptured) if game.nhelp: prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1])) if game.ship == 'E': @@ -4930,7 +5029,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.")) @@ -5043,13 +5142,20 @@ def chart(): def sectscan(goodScan, i, j): "Light up an individual dot in a sector." if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1): - textcolor({"green":GREEN, - "yellow":YELLOW, - "red":RED, - "docked":CYAN, - "dead":BROWN}[game.condition]) - if game.quad[i][j] != game.ship: - highvideo() + if game.quad[i][j] in ('E', 'F'): + textcolor({"green":GREEN, + "yellow":YELLOW, + "red":RED, + "docked":CYAN, + "dead":BROWN}[game.condition]) + else: + textcolor({'?':LIGHTMAGENTA, + 'K':LIGHTRED, + 'S':LIGHTRED, + 'C':LIGHTRED, + 'R':LIGHTRED, + 'T':LIGHTRED, + }.get(game.quad[i][j], DEFAULT)) proutn("%c " % game.quad[i][j]) textcolor(DEFAULT) else: @@ -5186,7 +5292,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 +5472,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 +5617,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 +5740,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 @@ -5680,17 +5786,16 @@ def choose(): scanner.nexttok() if scanner.sees("plain"): # Approximates the UT FORTRAN version. - game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS) + game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS | OPTION_COLOR | OPTION_CAPTURE) game.options |= OPTION_PLAIN elif scanner.sees("almy"): # Approximates Tom Almy's version. - game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS) + game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS | OPTION_COLOR) game.options |= OPTION_ALMY elif scanner.sees("fancy") or scanner.sees("\n"): pass elif len(scanner.token): proutn(_("What is \"%s\"?") % scanner.token) - game.options &=~ OPTION_COLOR setpassword() if game.passwd == "debug": game.idebug = True @@ -5766,7 +5871,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 +5887,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 +5914,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 +5943,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 @@ -5889,7 +5994,6 @@ commands = [ ("IMPULSE", 0), ("REST", 0), ("WARP", 0), - ("SCORE", 0), ("SENSORS", OPTION_PLANETS), ("ORBIT", OPTION_PLANETS), ("TRANSPORT", OPTION_PLANETS), @@ -5907,12 +6011,14 @@ commands = [ ("ABANDON", 0), ("DESTRUCT", 0), ("DEATHRAY", 0), + ("CAPTURE", OPTION_CAPTURE), ("DEBUG", 0), ("MAYDAY", 0), ("SOS", 0), # Synonym for MAYDAY ("CALL", 0), # Synonym for MAYDAY ("QUIT", 0), ("HELP", 0), + ("SCORE", 0), ("", 0), ] @@ -6004,6 +6110,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": @@ -6057,8 +6165,6 @@ def makemoves(): hitme = True elif cmd == "WARP": # warp setwarp() - elif cmd == "SCORE": # score - score() elif cmd == "SENSORS": # sensors sensor() elif cmd == "ORBIT": # orbit @@ -6108,6 +6214,8 @@ def makemoves(): deathray() if game.ididit: hitme = True + elif cmd == "CAPTURE": + capture() elif cmd == "DEBUGCMD": # What do we want for debug??? debugme() elif cmd == "MAYDAY": # Call for help @@ -6118,6 +6226,8 @@ def makemoves(): game.alldone = True # quit the game elif cmd == "HELP": helpme() # get help + elif cmd == "SCORE": + score() # see current score while True: if game.alldone: break # Game has ended @@ -6142,27 +6252,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 +6312,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 +6354,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 "" % (scanner.token, scanner.type, scanner.inqueue) + return "" % (self.token, self.type, self.inqueue) def ja(): "Yes-or-no confirmation." @@ -6367,9 +6477,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()