X-Git-Url: https://jxself.org/git/?p=super-star-trek.git;a=blobdiff_plain;f=src%2Fsst.py;h=17f4dab736e1cd2303fc023b2d9ee5a833c0aa12;hp=74dcbaa3aee8ab27ce8b09f73e4e642330a0c2ca;hb=259168763d54340135fd043df4741b7d2427ca9c;hpb=29d86fb395ca01e4a4f65f02d67f5823a4ebba11 diff --git a/src/sst.py b/src/sst.py index 74dcbaa..17f4dab 100644 --- a/src/sst.py +++ b/src/sst.py @@ -2,10 +2,9 @@ """ sst.py =-- Super Star Trek in Python -This code is a Python translation of a C translation of a FORTRAN original. -The FORTRANness still shows in many ways, notably the use of a lot of -parallel arrays where a more modern language would use structures -or objects. (However, 1-origin array indexing was fixed.) +This code is a Python translation of a C translation of a FORTRAN +original dating back to 1973. Beautiful Python it is not. But it +works. Dave Matuszek says: @@ -46,11 +45,11 @@ however mine had some feature it didn't have. So I merged its features that I liked. I also took a peek at the DECUS version (a port, less sources, to the PDP-10), and some other variations. -1, Compared to the original UT version, I've changed the "help" command to -"call" and the "terminate" command to "quit" to better match -user expectations. The DECUS version apparently made those changes -as well as changing "freeze" to "save". However I like "freeze". -(Both "freeze" and "save" work in SST2K.) +1, Compared to the original UT version, I've changed the "help" +command to "call" and the "terminate" command to "quit" to better +match user expectations. The DECUS version apparently made those +changes as well as changing "freeze" to "save". However I like +"freeze". (Both "freeze" and "save" work in SST2K.) 2. The experimental deathray originally had only a 5% chance of success, but could be used repeatedly. I guess after a couple @@ -336,9 +335,9 @@ class snapshot: self.baseq = [] # Base quadrant coordinates self.kcmdr = [] # Commander quadrant coordinates self.kscmdr = coord() # Supercommander quadrant coordinates - # the galaxy (subscript 0 not used) + # the galaxy self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant()) - # the starchart (subscript 0 not used) + # the starchart self.chart = fill2d(GALSIZE, lambda i, j: page()) class event: @@ -525,10 +524,8 @@ class gamestate: self.damfac = 0.0 # damage factor self.lastchart = 0.0 # time star chart was last updated self.cryprob = 0.0 # probability that crystal will work - self.probex = 0.0 # location of probe - self.probey = 0.0 # - self.probeinx = 0.0 # probe x,y increment - self.probeiny = 0.0 # + self.probe = None # location of probe + self.probein = None # probe i,j increment self.height = 0.0 # height of orbit around planet def recompute(self): # Stas thinks this should be (C expression): @@ -538,7 +535,7 @@ class gamestate: # after killing the last klingon when score is shown -- perhaps also # if the only remaining klingon is SCOM. game.state.remtime = game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr)) -# From enumerated type 'feature' + IHR = 'R' IHK = 'K' IHC = 'C' @@ -558,8 +555,6 @@ IHMATER0 = '-' IHMATER1 = 'o' IHMATER2 = '0' - -# From enumerated type 'FINTYPE' FWON = 0 FDEPLETE = 1 FLIFESUP = 2 @@ -583,10 +578,6 @@ FTRIBBLE = 19 FHOLE = 20 FCREW = 21 -# Log the results of pulling random numbers so we can check determinism. - -import traceback - def withprob(p): v = random.random() #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v 2.0: + if idelta.distance() > 2.0: # circulate in space idelta.i = game.state.kscmdr.j-game.quadrant.j idelta.j = game.quadrant.i-game.state.kscmdr.i @@ -2466,21 +2455,20 @@ def events(): supercommander() elif evcode == FDSPROB: # Move deep space probe schedule(FDSPROB, 0.01) - game.probex += game.probeinx - game.probey += game.probeiny - i = (int)(game.probex/QUADSIZE +0.05) - j = (int)(game.probey/QUADSIZE + 0.05) + game.probe += game.probein + i = int(round(game.probe.i/float(QUADSIZE))) + j = int(round(game.probe.j/float(QUADSIZE))) if game.probec.i != i or game.probec.j != j: game.probec.i = i game.probec.j = j if not VALID_QUADRANT(i, j) or \ game.state.galaxy[game.probec.i][game.probec.j].supernova: # Left galaxy or ran into supernova - if comunicating(): + if communicating(): announce() skip(1) proutn(_("Lt. Uhura- \"The deep space probe ")) - if not VALID_QUADRANT(j, i): + if not VALID_QUADRANT(i, j): proutn(_("has left the galaxy")) else: proutn(_("is no longer transmitting")) @@ -2501,8 +2489,7 @@ def events(): pdest.charted = True game.proben -= 1 # One less to travel if game.proben == 0 and game.isarmed and pdest.stars: - # lets blow the sucker! - supernova(game.probec) + supernova(game.probec) # fire in the hole! unschedule(FDSPROB) if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova: return @@ -2653,13 +2640,6 @@ def wait(): game.resting = False game.optime = 0 -# A nova occurs. It is the result of having a star hit with a -# photon torpedo, or possibly of a probe warhead going off. -# Stars that go nova cause stars which surround them to undergo -# the same probabilistic process. Klingons next to them are -# destroyed. And if the starship is next to it, it gets zapped. -# If the zap is too much, it gets destroyed. - def nova(nov): "Star goes nova." course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5) @@ -3350,11 +3330,12 @@ def iostart(): setwnd(fullscreen_window) def ioend(): - "Wrap up I/O. Presently a stub." - stdscr.keypad(False) - curses.echo() - curses.nocbreak() - curses.endwin() + "Wrap up I/O." + if game.options & OPTION_CURSES: + stdscr.keypad(False) + curses.echo() + curses.nocbreak() + curses.endwin() def waitfor(): "Wait for user action -- OK to do nothing if on a TTY" @@ -3818,7 +3799,7 @@ def dock(verbose): # because it involves giving x and y motions, yet the coordinates # are always displayed y - x, where +y is downward! -def getcourse(isprobe, akey): +def getcourse(isprobe): "Get a course and distance from the user." key = 0 dquad = copy.copy(game.quadrant) @@ -3841,12 +3822,7 @@ def getcourse(isprobe, akey): navmode = "manual" key = "IHEOL" break - if isprobe and akey != -1: - # For probe launch, use pre-scanned value first time - key = akey - akey = -1 - else: - key = scanner.next() + key = scanner.next() if key == "IHEOL": proutn(_("Manual or automatic- ")) iprompt = True @@ -3926,8 +3902,8 @@ def getcourse(isprobe, akey): prout(_("Ensign Chekov- \"Course laid in, Captain.\"")) # the actual deltas get computed here delta = coord() - delta.j = dquad.j-game.quadrant.j + 0.1*(dsect.j-game.sector.j) - delta.i = game.quadrant.i-dquad.i + 0.1*(game.sector.i-dsect.i) + delta.j = dquad.j-game.quadrant.j + (dsect.j-game.sector.j)/(QUADSIZE*1.0) + delta.i = game.quadrant.i-dquad.i + (game.sector.i-dsect.i)/(QUADSIZE*1.0) else: # manual while key == "IHEOL": proutn(_("X and Y displacements- ")) @@ -3968,7 +3944,7 @@ def impulse(): prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\"")) return if game.energy > 30.0: - if not getcourse(isprobe=False, akey=0): + if not getcourse(isprobe=False): return power = 20.0 + 100.0*game.dist else: @@ -4023,7 +3999,7 @@ def warp(timewarp): prout(_(" is repaired, I can only give you warp 4.\"")) return # Read in course and distance - if not getcourse(isprobe=False, akey=0): + if not getcourse(isprobe=False): return # Make sure starship has enough energy for the trip power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1) @@ -4202,8 +4178,7 @@ def atover(igrab): proutn(_("The %s has stopped in a quadrant containing") % crmshp()) prouts(_(" a supernova.")) skip(2) - prout(_("***Emergency automatic override attempts to hurl ")+crmshp()) - skip(1) + proutn(_("***Emergency automatic override attempts to hurl ")+crmshp()) prout(_("safely out of quadrant.")) if not damaged(DRADIO): game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True @@ -4316,7 +4291,6 @@ def probe(): return key = scanner.next() if key == "IHEOL": - # slow mode, so let Kirk know how many probes there are left if game.nprobes == 1: prout(_("1 probe left.")) else: @@ -4331,44 +4305,24 @@ def probe(): elif key == "IHEOL": proutn(_("Arm NOVAMAX warhead? ")) game.isarmed = ja() - if not getcourse(isprobe=True, akey=key): + elif key == "IHREAL": # first element of course + scanner.push(scanner.token) + if not getcourse(isprobe=True): return game.nprobes -= 1 angle = ((15.0 - game.direc) * 0.5235988) - game.probeinx = -math.sin(angle) - game.probeiny = math.cos(angle) - if math.fabs(game.probeinx) > math.fabs(game.probeiny): - bigger = math.fabs(game.probeinx) - else: - bigger = math.fabs(game.probeiny) - game.probeiny /= bigger - game.probeinx /= bigger + game.probein = coord(-math.sin(angle), math.cos(angle)) + bigger = max(abs(game.probein.i), abs(game.probein.j)) + game.probein /= bigger game.proben = 10.0*game.dist*bigger +0.5 - game.probex = game.quadrant.i*QUADSIZE + game.sector.i - 1 # We will use better packing than original - game.probey = game.quadrant.j*QUADSIZE + game.sector.j - 1 - game.probec = game.quadrant + game.probe = coord(game.quadrant.i*QUADSIZE + game.sector.i, + game.quadrant.j*QUADSIZE + game.sector.j) + game.probec = copy.copy(game.quadrant) schedule(FDSPROB, 0.01) # Time to move one sector prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\"")) game.ididit = True return -# Here's how the mayday code works: -# -# First, the closest starbase is selected. If there is a a starbase -# in your own quadrant, you are in good shape. This distance takes -# quadrant distances into account only. -# -# A magic number is computed based on the distance which acts as the -# probability that you will be rematerialized. You get three tries. -# -# When it is determined that you should be able to be rematerialized -# (i.e., when the probability thing mentioned above comes up -# positive), you are put into that quadrant (anywhere). Then, we try -# to see if there is a spot adjacent to the star- base. If not, you -# can't be rematerialized!!! Otherwise, it drops you there. It only -# tries five times to find a spot to drop you. After that, it's your -# problem. - def mayday(): "Yell for help from nearest starbase." # There's more than one way to move in this game! @@ -4445,24 +4399,6 @@ def mayday(): skip(1) prout(_("Lt. Uhura- \"Captain, we made it!\"")) -# Abandon Ship (the BSD-Trek description) -# -# The ship is abandoned. If your current ship is the Faire -# Queene, or if your shuttlecraft is dead, you're out of -# luck. You need the shuttlecraft in order for the captain -# (that's you!!) to escape. -# -# Your crew can beam to an inhabited starsystem in the -# quadrant, if there is one and if the transporter is working. -# If there is no inhabited starsystem, or if the transporter -# is out, they are left to die in outer space. -# -# If there are no starbases left, you are captured by the -# Klingons, who torture you mercilessly. However, if there -# is at least one starbase, you are returned to the -# Federation in a prisoner of war exchange. Of course, this -# can't happen unless you have taken some prisoners. - def abandon(): "Abandon ship." scanner.chew() @@ -5353,8 +5289,8 @@ def eta(): if not VALID_QUADRANT(w1.i, w1.j) or not VALID_SECTOR(w2.i, w2.j): huh() return - game.dist = math.sqrt((w1.j-game.quadrant.j+0.1*(w2.j-game.sector.j))**2+ - (w1.i-game.quadrant.i+0.1*(w2.i-game.sector.i))**2) + game.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) wfl = False if prompt: prout(_("Answer \"no\" if you don't know the value:")) @@ -5505,11 +5441,11 @@ systnames = ( _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel" _("Vulcan (T'Khasi)"), # many episodes _("Medusa"), # TOS: "Is There in Truth No Beauty?" - _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD) + _("Argelius II (Nelphia)"), # TOS: "Wolf in the Fold" ("IV" in BSD) _("Ardana"), # TOS: "The Cloud Minders" _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden" _("Gideon"), # TOS: "The Mark of Gideon" - _("Aldebaran III"), # TOS: "The Deadly Years" + _("Aldebaran III"), # TOS: "The Deadly Years" _("Alpha Majoris I"), # TOS: "Wolf in the Fold" _("Altair IV"), # TOS: "Amok Time _("Ariannus"), # TOS: "Let That Be Your Last Battlefield" @@ -5770,8 +5706,6 @@ def choose(): if not scanner.inqueue: # Can start with command line options proutn(_("Would you like a regular, tournament, or saved game? ")) scanner.next() - if len(scanner.token)==0: # Try again - continue if scanner.sees("tournament"): while scanner.next() == "IHEOL": proutn(_("Type in tournament number-")) @@ -6385,10 +6319,6 @@ class sstscanner: # Demand input for next scan self.inqueue = [] self.real = self.token = None - def chew2(self): - # return "IHEOL" next time - self.inqueue = ["IHEOL"] - self.real = self.token = None def sees(self, s): # compares s to item and returns true if it matches to the length of s return s.startswith(self.token) @@ -6592,7 +6522,8 @@ if __name__ == '__main__': if game.tourn and game.alldone: proutn(_("Do you want your score recorded?")) if ja() == True: - scanner.chew2() + scanner.chew() + scanner.push("\n") freeze(False) scanner.chew() proutn(_("Do you want to play again? ")) @@ -6607,4 +6538,3 @@ if __name__ == '__main__': if logfp: logfp.close() print "" - pass