Fix another basic error.
[super-star-trek.git] / src / sst.py
index 1fde98c2fc6576844e620900c3cec4dc5669f4ae..51ad07b53cdf03fa18d9e7a55bad2bddfbb6c357 100644 (file)
@@ -240,9 +240,9 @@ class coord:
     def is_valid(self):
         return self.x != None and self.y != None
     def __eq__(self, other):
-        return other != None and self.x == other.y and self.x == other.y
+        return other != None and self.x == other.x and self.y == other.y
     def __add__(self, other):
-        return coord(self.x+self.x, self.y+self.y)
+        return coord(self.x+other.x, self.y+other.y)
     def __sub__(self, other):
         return coord(self.x-other.x, self.y-other.y)
     def __mul__(self, other):
@@ -615,10 +615,9 @@ def randreal(*args):
 def welcoming(iq):
     "Would this quadrant welcome another Klingon?"
     return VALID_QUADRANT(iq.x,iq.y) and \
-       not game.state.galaxy[iq.x][iq.y].supernova or \
+       not game.state.galaxy[iq.x][iq.y].supernova and \
        game.state.galaxy[iq.x][iq.y].klingons < MAXKLQUAD
 
-
 def tryexit(enemy, look, irun):
     "A bad guy attempts to bug out."
     iq = coord()
@@ -1196,8 +1195,7 @@ def doshield(shraise):
        return
 
 def randdevice():
-    # choose a device to damage, at random. 
-    #
+    "Choose a device to damage, at random."
     # Quoth Eric Allman in the code of BSD-Trek:
     # "Under certain conditions you can get a critical hit.  This
     # sort of hit damages devices.  The probability that a given
@@ -1220,7 +1218,6 @@ def randdevice():
     # We don't have a cloaking device.  The shuttle got the allocation
     # for the cloaking device, then we shaved a half-percent off
     # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
-    # 
     weights = (
        105,    # DSRSENS: short range scanners 10.5% 
        105,    # DLRSENS: long range scanners          10.5% 
@@ -1270,11 +1267,9 @@ def collision(rammed, enemy):
     prout(_("***Sickbay reports %d casualties"), icas)
     game.casual += icas
     game.state.crew -= icas
-    #
     # In the pre-SST2K version, all devices got equiprobably damaged,
     # which was silly.  Instead, pick up to half the devices at
     # random according to our weighting table,
-    # 
     ncrits = randrange(NDEVICES/2)
     for m in range(ncrits):
        dev = randdevice()
@@ -1292,30 +1287,26 @@ def collision(rammed, enemy):
        finish(FWON)
     return
 
-def torpedo(course, dispersion, origin, number, nburst):
+def torpedo(origin, course, dispersion, number, nburst):
     "Let a photon torpedo fly" 
-    iquad = 0
     shoved = False
     ac = course + 0.25*dispersion
     angle = (15.0-ac)*0.5235988
     bullseye = (15.0 - course)*0.5235988
-    deltax = -math.sin(angle);
-    deltay = math.cos(angle);
+    delta = coord(-math.sin(angle), math.cos(angle))          
+    bigger = max(abs(delta.x), abs(delta.y))
+    delta /= bigger
     x = origin.x; y = origin.y
     w = coord(0, 0); jw = coord(0, 0)
-    bigger = max(math.fabs(deltax), math.fabs(deltay))
-    deltax /= bigger
-    deltay /= bigger
     if not damaged(DSRSENS) or game.condition=="docked":
        setwnd(srscan_window)
     else: 
        setwnd(message_window)
     # Loop to move a single torpedo 
     for step in range(1, 15+1):
-       x += deltax
-       w.x = int(x + 0.5)
-       y += deltay
-       w.y = int(y + 0.5)
+       x += delta.x
+       y += delta.y
+       w = coord(x, y).snaptogrid()
        if not VALID_SECTOR(w.x, w.y):
            break
        iquad=game.quad[w.x][w.y]
@@ -1362,9 +1353,9 @@ def torpedo(course, dispersion, origin, number, nburst):
        elif iquad in (IHR, IHK): # Hit a regular enemy 
            # find the enemy 
             for enemy in game.enemies:
-               if w == game.enemies[ll].kloc:
+               if w == enemy.kloc:
                    break
-           kp = math.fabs(e.kpower)
+           kp = math.fabs(enemy.kpower)
            h1 = 700.0 + randrange(100) - \
                1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
            h1 = math.fabs(h1)
@@ -1457,11 +1448,9 @@ def torpedo(course, dispersion, origin, number, nburst):
                skip(1)
                deadkl(w, iquad, w)
            else:
-               #
                # Stas Sergeev added the possibility that
                # you can shove the Thingy and piss it off.
                # It then becomes an enemy and may fire at you.
-               #
                thing.angry = True
                shoved = True
            return None
@@ -1546,12 +1535,12 @@ def fry(hit):
 def attack(torps_ok):
     # bad guy attacks us 
     # torps_ok == False forces use of phasers in an attack 
+    # game could be over at this point, check
+    if game.alldone:
+       return
     attempt = False; ihurt = False;
     hitmax=0.0; hittot=0.0; chgfac=1.0
     where = "neither"
-    # game could be over at this point, check 
-    if game.alldone:
-       return
     if idebug:
        prout("=== ATTACK!")
     # Tholian gets to move before attacking 
@@ -1612,7 +1601,7 @@ def attack(torps_ok):
            prout("  ")
            dispersion = (randreal()+randreal())*0.5 - 0.5
            dispersion += 0.002*enemy.kpower*dispersion
-           hit = torpedo(course, dispersion, origin=enemy.kloc, number=1, nburst=1)
+           hit = torpedo(enemy.kloc, course, dispersion, number=1, nburst=1)
            if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
                finish(FWON); # Klingons did themselves in! 
            if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
@@ -1743,19 +1732,22 @@ def targetcheck(w):
     if not VALID_SECTOR(w.x, w.y):
        huh()
        return None
-    delta = 0.1*(w - game.sector)
-    if delta.x==0 and delta.y== 0:
+    delta = coord()
+    # FIXME: C code this was translated from is wacky -- why the sign reversal?
+    delta.y = (w.y - game.sector.y);
+    delta.x = (game.sector.x - w.x);
+    if delta == coord(0, 0):
        skip(1)
        prout(_("Spock-  \"Bridge to sickbay.  Dr. McCoy,"))
        prout(_("  I recommend an immediate review of"))
        prout(_("  the Captain's psychological profile.\""))
        scanner.chew()
        return None
-    return delta.bearing()
+    return 1.90985932*math.atan2(delta.y, delta.x)
 
 def photon():
     "Launch photon torpedo."
-    course = [0.0] * MAXBURST
+    course = []
     game.ididit = False
     if damaged(DPHOTON):
        prout(_("Photon tubes damaged."))
@@ -1843,7 +1835,7 @@ def photon():
            break
        if game.shldup or game.condition == "docked":
            dispersion *= 1.0 + 0.0001*game.shield
-       torpedo(course[i], dispersion, origin=game.sector, number=i, nburst=n)
+       torpedo(game.sector, course[i], dispersion, number=i, nburst=n)
        if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
            return
     if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
@@ -2128,8 +2120,7 @@ def phasers():
                else:
                    proutn("??")
                proutn(")  ")
-               proutn(_("units to fire at %s-  ") % crmena(False, ienm, "sector", aim))
-               
+               proutn(_("units to fire at %s-  ") % crmena(False, ienm, "sector", aim))                
                key = scanner.next()
            if key == IHALPHA and scanner.sees("no"):
                no = True
@@ -2273,7 +2264,7 @@ def events():
                 game.shldchg = False
             else:
                 prout(_("(Shields not currently useable.)"))
-        newqad(False)
+        newqad()
         # Adjust finish time to time of tractor beaming 
         fintim = game.state.date+game.optime
         attack(torps_ok=False)
@@ -2608,8 +2599,7 @@ def events():
                     else:
                         continue       # search for eligible quadrant failed
                 except "FOUNDIT":
-                    w.x = i
-                    w.y = j
+                    w.x = i; w.y = j
            # deliver the child 
            game.state.remkl += 1
            q.klingons += 1
@@ -3776,7 +3766,7 @@ def imove(novapush):
                skip(1)
                prout(_("Entering Quadrant %s.") % game.quadrant)
                game.quad[game.sector.x][game.sector.y] = game.ship
-               newqad(False)
+               newqad()
                if game.skill>SKILL_NOVICE:
                    attack(torps_ok=False)  
                return
@@ -3996,12 +3986,12 @@ def getcourse(isprobe, akey):
        if key != IHREAL:
            huh()
            return False
-       delta.x = scanner.real
+       delta.y = scanner.real
        key = scanner.next()
        if key != IHREAL:
            huh()
            return False
-       delta.y = scanner.real
+       delta.x = scanner.real
     # Check for zero movement 
     if delta.x == 0 and delta.y == 0:
        scanner.chew()
@@ -4144,7 +4134,6 @@ def warp(timewarp):
                bigger = math.fabs(deltax)
            else:
                bigger = math.fabs(deltay)
-                       
            deltax /= bigger
            deltay /= bigger
            n = 10.0 * game.dist * bigger +0.5
@@ -4347,7 +4336,7 @@ def timwrp():
        # cheat to make sure no tractor beams occur during time warp 
        postpone(FTBEAM, game.optime)
        game.damage[DRADIO] += game.optime
-    newqad(False)
+    newqad()
     events()   # Stas Sergeev added this -- do pending events 
 
 def probe():
@@ -4460,7 +4449,7 @@ def mayday():
                ddist = xdist
        # Since starbase not in quadrant, set up new quadrant 
        game.quadrant = ibq
-       newqad(True)
+       newqad()
     # dematerialize starship 
     game.quad[game.sector.x][game.sector.y]=IHDOT
     proutn(_("Starbase in Quadrant %s responds--%s dematerializes") \
@@ -4572,7 +4561,6 @@ def abandon():
                    game.state.crew)
            game.casual += game.state.crew
            game.abandoned += game.state.crew
-
        # If at least one base left, give 'em the Faerie Queene 
        skip(1)
        game.icrystl = False # crystals are lost 
@@ -4584,7 +4572,7 @@ def abandon():
        if not game.quadrant == game.state.baseq[nb]:
            game.quadrant = game.state.baseq[nb]
            game.sector.x = game.sector.y = 5
-           newqad(True)
+           newqad()
        while True:
            # position next to base by trial and error 
            game.quad[game.sector.x][game.sector.y] = IHDOT
@@ -4597,7 +4585,7 @@ def abandon():
                break # found a spot 
            game.sector.x=QUADSIZE/2
            game.sector.y=QUADSIZE/2
-           newqad(True)
+           newqad()
     # Get new commission 
     game.quad[game.sector.x][game.sector.y] = game.ship = IHF
     game.state.crew = FULLCREW
@@ -5499,7 +5487,6 @@ def eta():
            scanner.chew()
            skip(1)
            return
-                       
 
 # Code from setup.c begins here
 
@@ -5780,9 +5767,14 @@ def setup():
     unschedule(FENSLV)
     unschedule(FREPRO)
     # 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:
-        thing = randplace(GALSIZE)
+        while True:
+            thing = randplace(GALSIZE)
+            if thing not in game.state.baseq:
+                break
     skip(2)
     game.state.snap = False
     if game.skill == SKILL_NOVICE:
@@ -5815,7 +5807,7 @@ def setup():
     if game.state.nscrem:
        prout(_("  YOU'LL NEED IT."))
     waitfor()
-    newqad(False)
+    newqad()
     if len(game.enemies) - (thing == game.quadrant) - (game.tholian != None):
        game.shldup = True
     if game.neutz:     # bad luck to start in a Romulan Neutral Zone
@@ -5931,7 +5923,6 @@ def choose():
 
 def dropin(iquad=None):
     "Drop a feature on a random dot in the current quadrant."
-    w = coord()
     while True:
         w = randplace(QUADSIZE)
         if game.quad[w.x][w.y] == IHDOT:
@@ -5954,18 +5945,12 @@ def newkling():
     "Drop new Klingon into current quadrant."
     return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
 
-def newqad(shutup):
+def newqad():
     "Set up a new state of quadrant, for when we enter or re-enter it."
-    w = coord()
     game.justin = True
-    game.klhere = 0
-    game.irhere = 0
-    game.iplnet = 0
-    game.neutz = False
-    game.inorbit = False
-    game.landed = False
-    game.ientesc = False
-    game.iseenit = False
+    game.iplnet = None
+    game.neutz = game.inorbit = game.landed = False
+    game.ientesc = game.iseenit = False
     # Create a blank quadrant
     game.quad = fill2d(QUADSIZE, lambda i, j: IHDOT)
     if game.iscate:
@@ -6023,15 +6008,14 @@ def newqad(shutup):
            skip(1)
            prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
            prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
-    if shutup==0:
-       # Put in THING if needed
-       if thing == game.quadrant:
-           enemy(type=IHQUEST, loc=dropin(),
-                      power=randreal(6000,6500.0)+250.0*game.skill)
-           if not damaged(DSRSENS):
-               skip(1)
-               prout(_("Mr. Spock- \"Captain, this is most unusual."))
-               prout(_("    Please examine your short-range scan.\""))
+    # Put in THING if needed
+    if thing == game.quadrant:
+        enemy(type=IHQUEST, loc=dropin(),
+                  power=randreal(6000,6500.0)+250.0*game.skill)
+        if not damaged(DSRSENS):
+            skip(1)
+            prout(_("Mr. Spock- \"Captain, this is most unusual."))
+            prout(_("    Please examine your short-range scan.\""))
     # Decide if quadrant needs a Tholian; lighten up if skill is low 
     if game.options & OPTION_THOLIAN:
        if (game.skill < SKILL_GOOD and withprob(0.02)) or \
@@ -6132,18 +6116,14 @@ commands = {
     "HELP":            0,
 }
 
-def ACCEPT(cmd):       return (not commands[cmd] or (commands[cmd] & game.options))
-
 def listCommands():
     "Generate a list of legal commands."
-    k = 0
     proutn(_("LEGAL COMMANDS ARE:"))
-    for key in commands:
-       if ACCEPT(key):
+    for (k, key) in enumerate(commands):
+       if not commands[cmd] or (commands[key] & game.options):
             if k % 5 == 0:
                 skip(1)
             proutn("%-12s " % key) 
-            k += 1
     skip(1)
 
 def helpme():
@@ -6204,7 +6184,6 @@ def helpme():
 
 def makemoves():
     "Command-interpretation loop."
-    v = 0
     clrscr()
     setwnd(message_window)
     while True:        # command loop 
@@ -6392,13 +6371,7 @@ def crmena(stars, enemy, loctype, w):
 
 def crmshp():
     "Emit our ship name." 
-    if game.ship == IHE:
-        s = _("Enterprise")
-    elif game.ship == IHF:
-        s = _("Faerie Queene")
-    else:
-        s = "Ship???"
-    return s
+    return{IHE:_("Enterprise"),IHF:_("Faerie Queene")}.get(game.ship,"Ship???")
 
 def stars():
     "Emit a line of stars" 
@@ -6530,9 +6503,7 @@ def debugme():
     proutn("Cause selective damage? ")
     if ja() == True:
        for i in range(NDEVICES):
-           proutn("Kill ")
-           proutn(device[i])
-           proutn("? ")
+           proutn("Kill %s?" % device[i])
            scanner.chew()
            key = scanner.next()
             if key == IHALPHA and scanner.sees("y"):