X-Git-Url: https://jxself.org/git/?p=super-star-trek.git;a=blobdiff_plain;f=sst.py;h=fe04293f10fbbc7c98c28d1292e12016727ee91e;hp=a97268c6eea6b33bf4c492bd96e9245cec4f610a;hb=e571d502c19abfb5a3320300c347793da7b43d05;hpb=bb82c32bd0bcb35f79aa61b2c6650f7067fab537 diff --git a/sst.py b/sst.py index a97268c..fe04293 100755 --- a/sst.py +++ b/sst.py @@ -56,9 +56,9 @@ class TrekError(Exception): pass class JumpOut(Exception): - pass + pass -class coord: +class Coord: def __init__(self, x=None, y=None): self.i = x self.j = y @@ -75,28 +75,28 @@ class coord: def __ne__(self, other): return other == 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) + return Coord(self.i+other.i, self.j+other.j) def __sub__(self, other): - return coord(self.i-other.i, self.j-other.j) + return Coord(self.i-other.i, self.j-other.j) def __mul__(self, other): - return coord(self.i*other, self.j*other) + return Coord(self.i*other, self.j*other) def __rmul__(self, other): - return coord(self.i*other, self.j*other) + return Coord(self.i*other, self.j*other) def __div__(self, other): - return coord(self.i/other, self.j/other) + return Coord(self.i/other, self.j/other) def __mod__(self, other): - return coord(self.i % other, self.j % other) + return Coord(self.i % other, self.j % other) def __rdiv__(self, other): - return coord(self.i/other, self.j/other) + return Coord(self.i/other, self.j/other) def roundtogrid(self): - return coord(int(round(self.i)), int(round(self.j))) + return Coord(int(round(self.i)), int(round(self.j))) def distance(self, other=None): - if not other: other = coord(0, 0) + if not other: other = Coord(0, 0) return math.sqrt((self.i - other.i)**2 + (self.j - other.j)**2) def bearing(self): return 1.90985*math.atan2(self.j, self.i) def sgn(self): - s = coord() + s = Coord() if self.i == 0: s.i = 0 else: @@ -112,7 +112,7 @@ class coord: def sector(self): return self.roundtogrid() % QUADSIZE def scatter(self): - s = coord() + s = Coord() s.i = self.i + randrange(-1, 2) s.j = self.j + randrange(-1, 2) return s @@ -122,10 +122,10 @@ class coord: return "%s - %s" % (self.i+1, self.j+1) __repr__ = __str__ -class planet: +class Planet: def __init__(self): self.name = None # string-valued if inhabited - self.quadrant = coord() # quadrant located + self.quadrant = Coord() # quadrant located self.pclass = None # could be ""M", "N", "O", or "destroyed" self.crystals = "absent"# could be "mined", "present", "absent" self.known = "unknown" # could be "unknown", "known", "shuttle_down" @@ -133,7 +133,7 @@ class planet: def __str__(self): return self.name -class quadrant: +class Quadrant: def __init__(self): self.stars = 0 self.planet = None @@ -144,7 +144,7 @@ class quadrant: self.charted = False self.status = "secure" # Could be "secure", "distressed", "enslaved" -class page: +class Page: def __init__(self): self.stars = None self.starbase = None @@ -159,7 +159,7 @@ def fill2d(size, fillfun): lst[i].append(fillfun(i, j)) return lst -class snapshot: +class Snapshot: def __init__(self): self.snap = False # snapshot taken self.crew = 0 # crew complement @@ -176,13 +176,13 @@ class snapshot: self.remtime = 0 # remaining time self.baseq = [] # Base quadrant coordinates self.kcmdr = [] # Commander quadrant coordinates - self.kscmdr = coord() # Supercommander quadrant coordinates + self.kscmdr = Coord() # Supercommander quadrant coordinates # the galaxy - self.galaxy = fill2d(GALSIZE, lambda i_unused, j_unused: quadrant()) + self.galaxy = fill2d(GALSIZE, lambda i_unused, j_unused: Quadrant()) # the starchart - self.chart = fill2d(GALSIZE, lambda i_unused, j_unused: page()) + self.chart = fill2d(GALSIZE, lambda i_unused, j_unused: Page()) -class event: +class Event: def __init__(self): self.date = None # A real number self.quadrant = None # A coord structure @@ -256,10 +256,10 @@ NEVENTS = 12 # when we implement stateful events def findevent(evtype): return game.future[evtype] -class enemy: +class Enemy: def __init__(self, type=None, loc=None, power=None): self.type = type - self.location = coord() + self.location = Coord() if loc: self.move(loc) self.power = power # enemy energy level @@ -277,23 +277,25 @@ class enemy: game.quad[self.location.i][self.location.j] = self.type self.kdist = self.kavgd = (game.sector - loc).distance() else: - self.location = coord() + self.location = Coord() self.kdist = self.kavgd = None game.enemies.remove(self) return motion def __repr__(self): return "<%s,%s.%f>" % (self.type, self.location, self.power) # For debugging -class gamestate: +class Gamestate: def __init__(self): self.options = None # Game options - self.state = snapshot() # A snapshot structure - self.snapsht = snapshot() # Last snapshot taken for time-travel purposes + self.state = Snapshot() # A snapshot structure + self.snapsht = Snapshot() # Last snapshot taken for time-travel purposes self.quad = None # contents of our quadrant self.damage = [0.0] * NDEVICES # damage encountered - self.future = [] # future events - for i_unused in range(NEVENTS): - self.future.append(event()) + self.future = [] # future events + i = NEVENTS + while i > 0: + i -= 1 + self.future.append(Event()) self.passwd = None; # Self Destruct password self.enemies = [] self.quadrant = None # where we are in the large @@ -412,13 +414,13 @@ def randreal(*args): def welcoming(iq): "Would this quadrant welcome another Klingon?" - return iq.valid_quadrant() and \ + return iq.valid_Quadrant() and \ not game.state.galaxy[iq.i][iq.j].supernova and \ game.state.galaxy[iq.i][iq.j].klingons < MAXKLQUAD def tryexit(enemy, look, irun): "A bad guy attempts to bug out." - iq = coord() + iq = Coord() iq.i = game.quadrant.i+(look.i+(QUADSIZE-1))/QUADSIZE - 1 iq.j = game.quadrant.j+(look.j+(QUADSIZE-1))/QUADSIZE - 1 if not welcoming(iq): @@ -504,7 +506,7 @@ def tryexit(enemy, look, irun): def movebaddy(enemy): "Tactical movement for the bad guys." - goto = coord(); look = coord() + goto = Coord(); look = Coord() irun = False # This should probably be just (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant) if game.skill >= SKILL_EXPERT: @@ -703,7 +705,7 @@ def movescom(iq, avoid): def supercommander(): "Move the Super Commander." - iq = coord(); sc = coord(); ibq = coord(); idelta = coord() + iq = Coord(); sc = Coord(); ibq = Coord(); idelta = Coord() basetbl = [] if game.idebug: prout("== SUPERCOMMANDER") @@ -804,7 +806,7 @@ def supercommander(): if not game.resting: return prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\"")) - if ja() == False: + if not ja(): return game.resting = False game.optime = 0.0; # actually finished @@ -824,7 +826,7 @@ def movetholian(): "Move the Tholian." if not game.tholian or game.justin: return - tid = coord() + tid = Coord() if game.tholian.location.i == 0 and game.tholian.location.j == 0: tid.i = 0; tid.j = QUADSIZE-1 elif game.tholian.location.i == 0 and game.tholian.location.j == QUADSIZE-1: @@ -1060,7 +1062,7 @@ def torpedo(origin, bearing, dispersion, number, nburst): ac = bearing + 0.25*dispersion # dispersion is a random variable bullseye = (15.0 - bearing)*0.5235988 track = course(bearing=ac, distance=QUADSIZE, origin=cartesian(origin)) - bumpto = coord(0, 0) + bumpto = Coord(0, 0) # Loop to move a single torpedo setwnd(message_window) for step in range(1, QUADSIZE*2): @@ -1476,11 +1478,11 @@ def targetcheck(w): if not w.valid_sector(): huh() return None - delta = coord() + delta = Coord() # FIXME: C code this was translated from is wacky -- why the sign reversal? delta.j = (w.j - game.sector.j); delta.i = (game.sector.i - w.i); - if delta == coord(0, 0): + if delta == Coord(0, 0): skip(1) prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,")) prout(_(" I recommend an immediate review of")) @@ -1632,7 +1634,7 @@ def checkshctrl(rpow): def hittem(hits): "Register a phaser hit on Klingons and Romulans." kk = 0 - w = coord() + w = Coord() skip(1) for (k, wham) in enumerate(hits): if wham==0: @@ -1966,8 +1968,8 @@ def events(): i=0 fintim = game.state.date + game.optime; yank=0 ictbeam = False; istract = False - w = coord(); hold = coord() - ev = event(); ev2 = event() + w = Coord(); hold = Coord() + ev = Event(); ev2 = Event() def tractorbeam(yank): "Tractor-beaming cases merge here." @@ -2179,7 +2181,7 @@ def events(): schedule(FBATTAK, expran(0.3*game.intime)) unschedule(FCDBAS) continue - except coord: + except Coord: pass # commander + starbase combination found -- launch attack game.battle = ibq @@ -2320,7 +2322,7 @@ def events(): continue # full right now # reproduce one Klingon w = ev.quadrant - m = coord() + m = Coord() if game.klhere >= MAXKLQUAD: try: # this quadrant not ok, pick an adjacent one @@ -2409,7 +2411,7 @@ def wait(): def nova(nov): "Star goes nova." ncourse = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5) - newc = coord(); neighbor = coord(); bump = coord(0, 0) + newc = Coord(); neighbor = Coord(); bump = Coord(0, 0) if withprob(0.05): # Wow! We've supernova'ed supernova(game.quadrant) @@ -2423,7 +2425,7 @@ def nova(nov): hits = [nov] kount = 0 while hits: - offset = coord() + offset = Coord() start = hits.pop() for offset.i in range(-1, 1+1): for offset.j in range(-1, 1+1): @@ -2528,7 +2530,7 @@ def nova(nov): if dist == 0.0: return scourse = course(bearing=direc, distance=dist) - game.optime = course.time(warp=4) + game.optime = scourse.time(warp=4) skip(1) prout(_("Force of nova displaces starship.")) imove(scourse, noattack=True) @@ -2543,7 +2545,7 @@ def supernova(w): else: # Scheduled supernova -- select star at random. stars = 0 - nq = coord() + nq = Coord() for nq.i in range(GALSIZE): for nq.j in range(GALSIZE): stars += game.state.galaxy[nq.i][nq.j].stars @@ -2568,7 +2570,7 @@ def supernova(w): prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date) prout(_(" Supernova in Quadrant %s; caution advised.") % nq) else: - ns = coord() + ns = Coord() # we are in the quadrant! num = randrange(game.state.galaxy[nq.i][nq.j].stars) + 1 for ns.i in range(QUADSIZE): @@ -3151,8 +3153,7 @@ def pause_game(): sys.stdout.write('\n') proutn(prompt) raw_input() - for j_unused in range(rows): - sys.stdout.write('\n') + sys.stdout.write('\n' * rows) linecount = 0 def skip(i): @@ -3406,9 +3407,9 @@ def prstat(txt, data): # Code from moving.c begins here -def imove(course=None, noattack=False): +def imove(icourse=None, noattack=False): "Movement execution for warp, impulse, supernova, and tractor-beam events." - w = coord() + w = Coord() def newquadrant(noattack): # Leaving quadrant -- allow final enemy attack @@ -3429,17 +3430,17 @@ def imove(course=None, noattack=False): kinks = 0 while True: kink = False - if course.final.i < 0: - course.final.i = -course.final.i + if icourse.final.i < 0: + icourse.final.i = -icourse.final.i kink = True - if course.final.j < 0: - course.final.j = -course.final.j + if icourse.final.j < 0: + icourse.final.j = -icourse.final.j kink = True - if course.final.i >= GALSIZE*QUADSIZE: - course.final.i = (GALSIZE*QUADSIZE*2) - course.final.i + if icourse.final.i >= GALSIZE*QUADSIZE: + icourse.final.i = (GALSIZE*QUADSIZE*2) - icourse.final.i kink = True - if course.final.j >= GALSIZE*QUADSIZE: - course.final.j = (GALSIZE*QUADSIZE*2) - course.final.j + if icourse.final.j >= GALSIZE*QUADSIZE: + icourse.final.j = (GALSIZE*QUADSIZE*2) - icourse.final.j kink = True if kink: kinks += 1 @@ -3458,8 +3459,8 @@ def imove(course=None, noattack=False): # Compute final position in new quadrant if trbeam: # Don't bother if we are to be beamed return - game.quadrant = course.final.quadrant() - game.sector = course.final.sector() + game.quadrant = icourse.final.quadrant() + game.sector = icourse.final.sector() skip(1) prout(_("Entering Quadrant %s.") % game.quadrant) game.quad[game.sector.i][game.sector.j] = game.ship @@ -3471,7 +3472,7 @@ def imove(course=None, noattack=False): iquad = game.quad[h.i][h.j] if iquad != '.': # object encountered in flight path - stopegy = 50.0*course.distance/game.optime + stopegy = 50.0*icourse.distance/game.optime if iquad in ('T', 'K', 'C', 'S', 'R', '?'): for enemy in game.enemies: if enemy.location == game.sector: @@ -3521,17 +3522,17 @@ def imove(course=None, noattack=False): if game.state.date+game.optime >= scheduled(FTBEAM): trbeam = True game.condition = "red" - course.distance = course.distance*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1 + icourse.distance = icourse.distance*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5 # Move out game.quad[game.sector.i][game.sector.j] = '.' - for m in range(course.moves): - course.next() - w = course.sector() - if course.origin.quadrant() != course.location.quadrant(): + for m in range(icourse.moves): + icourse.next() + w = icourse.sector() + if icourse.origin.quadrant() != icourse.location.quadrant(): newquadrant(noattack) break - elif check_collision(w): + elif check_collision(icourse, w): print "Collision detected" break else: @@ -3596,7 +3597,7 @@ def getcourse(isprobe): dquad = copy.copy(game.quadrant) navmode = "unspecified" itemp = "curt" - dsect = coord() + dsect = Coord() iprompt = False if game.landed and not isprobe: prout(_("Dummy! You can't leave standard orbit until you")) @@ -3638,7 +3639,7 @@ def getcourse(isprobe): prout(_("(Manual movement assumed.)")) navmode = "manual" break - delta = coord() + delta = Coord() if navmode == "automatic": while key == "IHEOL": if isprobe: @@ -3738,7 +3739,7 @@ class course: 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)) + 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)) @@ -3814,7 +3815,7 @@ def impulse(): finish(FNRG) return -def warp(course, involuntary): +def warp(wcourse, involuntary): "ove under warp drive." blooey = False; twarp = False if not involuntary: # Not WARPX entry @@ -3831,21 +3832,21 @@ def warp(course, involuntary): prout(_(" is repaired, I can only give you warp 4.\"")) return # Read in course and distance - if course==None: + if wcourse==None: try: - course = getcourse(isprobe=False) + wcourse = getcourse(isprobe=False) except TrekError: return # Make sure starship has enough energy for the trip # Note: this formula is slightly different from the C version, # and lets you skate a bit closer to the edge. - if course.power(game.warpfac) >= game.energy: + if wcourse.power(game.warpfac) >= game.energy: # Insufficient power for trip game.ididit = False skip(1) prout(_("Engineering to bridge--")) - if not game.shldup or 0.5*course.power(game.warpfac) > game.energy: - iwarp = (game.energy/(course.dist+0.05)) ** 0.333333333 + if not game.shldup or 0.5*wcourse.power(game.warpfac) > game.energy: + iwarp = (game.energy/(wcourse.dist+0.05)) ** 0.333333333 if iwarp <= 0: prout(_("We can't do it, Captain. We don't have enough energy.")) else: @@ -3859,7 +3860,7 @@ def warp(course, involuntary): prout(_("We haven't the energy to go that far with the shields up.")) return # Make sure enough time is left for the trip - game.optime = course.time(game.warpfac) + game.optime = wcourse.time(game.warpfac) if game.optime >= 0.8*game.state.remtime: skip(1) prout(_("First Officer Spock- \"Captain, I compute that such")) @@ -3875,12 +3876,12 @@ def warp(course, involuntary): if game.warpfac > 6.0: # Decide if engine damage will occur # ESR: Seems wrong. Probability of damage goes *down* with distance? - prob = course.distance*(6.0-game.warpfac)**2/66.666666666 + prob = wcourse.distance*(6.0-game.warpfac)**2/66.666666666 if prob > randreal(): blooey = True - course.distance = randreal(course.distance) + wcourse.distance = randreal(wcourse.distance) # Decide if time warp will occur - if 0.5*course.distance*math.pow(7.0,game.warpfac-10.0) > randreal(): + if 0.5*wcourse.distance*math.pow(7.0,game.warpfac-10.0) > randreal(): twarp = True if game.idebug and game.warpfac==10 and not twarp: blooey = False @@ -3890,23 +3891,23 @@ def warp(course, involuntary): if blooey or twarp: # If time warp or engine damage, check path # If it is obstructed, don't do warp or damage - for m_unused in range(course.moves): - course.next() - w = course.sector() + for m_unused in range(wcourse.moves): + wcourse.next() + w = wcourse.sector() if not w.valid_sector(): break if game.quad[w.i][w.j] != '.': blooey = False twarp = False - course.reset() + wcourse.reset() # Activate Warp Engines and pay the cost imove(course, noattack=False) if game.alldone: return - game.energy -= course.power(game.warpfac) + game.energy -= wcourse.power(game.warpfac) if game.energy <= 0: finish(FNRG) - game.optime = course.time(game.warpfac) + game.optime = wcourse.time(game.warpfac) if twarp: timwrp() if blooey: @@ -4871,7 +4872,7 @@ def lrscan(silent): if not silent: proutn(" ") for y in range(game.quadrant.j-1, game.quadrant.j+2): - if not coord(x, y).valid_quadrant(): + if not Coord(x, y).valid_quadrant(): if not silent: proutn(" -1") else: @@ -5060,7 +5061,7 @@ def srscan(): def eta(): "Use computer to get estimated time of arrival for a warp jump." - w1 = coord(); w2 = coord() + w1 = Coord(); w2 = Coord() prompt = False if damaged(DCOMPTR): prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR.")) @@ -5308,7 +5309,7 @@ device = ( def setup(): "Prepare to play, set up cosmos." - w = coord() + w = Coord() # Decide how many of everything if choose(): return # frozen game @@ -5328,7 +5329,7 @@ def setup(): for i in range(NDEVICES): game.damage[i] = 0.0 # Set up assorted game parameters - game.battle = coord() + game.battle = Coord() game.state.date = game.indate = 100.0 * randreal(20, 51) game.nkinks = game.nhelp = game.casual = game.abandoned = 0 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False @@ -5406,7 +5407,7 @@ def setup(): w = randplace(GALSIZE) if game.state.galaxy[w.i][w.j].planet == None: break - new = planet() + new = Planet() new.quadrant = w new.crystals = "absent" if (game.options & OPTION_WORLDS) and i < NINHAB: @@ -5627,7 +5628,7 @@ def newcnd(): def newkling(): "Drop new Klingon into current quadrant." - return enemy('K', loc=dropin(), power=randreal(300,450)+25.0*game.skill) + return Enemy('K', loc=dropin(), power=randreal(300,450)+25.0*game.skill) def newqad(): "Set up a new state of quadrant, for when we enter or re-enter it." @@ -5669,7 +5670,7 @@ def newqad(): game.iscate = (game.state.remkl > 1) # Put in Romulans if needed for i in range(q.romulans): - enemy('R', loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill) + 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: game.base = dropin('B') @@ -5694,7 +5695,7 @@ def newqad(): prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!")) # Put in THING if needed if thing == game.quadrant: - enemy(type='?', loc=dropin(), + Enemy(type='?', loc=dropin(), power=randreal(6000,6500.0)+250.0*game.skill) if not damaged(DSRSENS): skip(1) @@ -5705,13 +5706,13 @@ def newqad(): if (game.skill < SKILL_GOOD and withprob(0.02)) or \ (game.skill == SKILL_GOOD and withprob(0.05)) or \ (game.skill > SKILL_GOOD and withprob(0.08)): - w = coord() + w = Coord() while True: w.i = withprob(0.5) * (QUADSIZE-1) w.j = withprob(0.5) * (QUADSIZE-1) if game.quad[w.i][w.j] == '.': break - game.tholian = enemy(type='T', loc=w, + game.tholian = Enemy(type='T', loc=w, power=randrange(100, 500) + 25.0*game.skill) # Reserve unoccupied corners if game.quad[0][0]=='.': @@ -5753,8 +5754,9 @@ def setpassword(): break else: game.passwd = "" - for i_unused in range(3): - game.passwd += chr(ord('a')+randrange(26)) + game.passwd += chr(ord('a')+randrange(26)) + game.passwd += chr(ord('a')+randrange(26)) + game.passwd += chr(ord('a')+randrange(26)) # Code from sst.c begins here @@ -5915,7 +5917,7 @@ def makemoves(): if game.ididit: hitme = True elif cmd == "MOVE": # move under warp - warp(course=None, involuntary=False) + warp(wcourse=None, involuntary=False) elif cmd == "SHIELDS": # shields doshield(shraise=False) if game.ididit: @@ -6065,7 +6067,7 @@ def expran(avrage): def randplace(size): "Choose a random location." - w = coord() + w = Coord() w.i = randrange(size) w.j = randrange(size) return w @@ -6126,7 +6128,7 @@ class sstscanner: # Round token value to nearest integer return int(round(scanner.real)) def getcoord(self): - s = coord() + s = Coord() scanner.next() if scanner.type != "IHREAL": huh() @@ -6190,8 +6192,8 @@ def debugme(): game.damage[i] = 10.0 proutn("Examine/change events? ") if ja(): - ev = event() - w = coord() + ev = Event() + w = Coord() legends = { FSNOVA: "Supernova ", FTBEAM: "T Beam ", @@ -6251,9 +6253,9 @@ if __name__ == '__main__': try: global line, thing, game game = None - thing = coord() + thing = Coord() thing.angry = False - game = gamestate() + game = Gamestate() game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY) if os.getenv("TERM"): game.options |= OPTION_CURSES