on how to modify (and how not to modify!) this code.
"""
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.
version = "2.1"
-docpath = (".", "../doc", "/usr/share/doc/sst")
+docpath = (".", "doc/", "/usr/share/doc/sst/")
def _(st):
return gettext.gettext(st)
DOCKFAC = 0.25 # Repair faster when docked
PHASEFAC = 2.0 # Unclear what this is, it was in the C version
+ALGERON = 2311 # Date of the Treaty of Algeron
+
+
DEFAULT = -1
BLACK = 0
BLUE = 1
# 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_CAPTURE = 0x00002000 # Enable BSD-Trek capture (Almy, 2013).
+OPTION_CLOAK = 0x80004000 # Enable BSD-Trek capture (Almy, 2013).
+OPTION_PLAIN = 0x01000000 # user chose plain game
+OPTION_ALMY = 0x02000000 # user chose Almy variant
+OPTION_COLOR = 0x04000000 # enable color display (ESR, 2010)
# Define devices
DSRSENS = 0
DWARPEN = 5
DIMPULS = 6
DSHIELD = 7
-DRADIO = 0
-DSHUTTL = 9
-DCOMPTR = 10
+DRADIO = 8
+DSHUTTL = 9
+DCOMPTR = 10
DNAVSYS = 11
-DTRANSP = 12
+DTRANSP = 12
DSHCTRL = 13
-DDRAY = 14
-DDSP = 15
-NDEVICES = 16 # Number of devices
+DDRAY = 14
+DDSP = 15
+DCLOAK = 16
+NDEVICES = 17 # Number of devices
SKILL_NONE = 0
SKILL_NOVICE = 1
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.
+ self.iscloaked = False # Cloaking device on?
+ self.ncviol = 0 # Algreon treaty violations
+ self.isviolreported = False # We have been warned
def recompute(self):
# Stas thinks this should be (C expression):
# game.state.remkl + len(game.state.kcmdr) > 0 ?
FTRIBBLE = 19
FHOLE = 20
FCREW = 21
+FCLOAK = 22
def withprob(p):
return random.random() < p
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:
#
# Code from battle.c begins here
+def cloak():
+ "Change cloaking-device status."
+ if game.ship == 'F':
+ prout(_("Ye Faerie Queene hath no cloaking device."));
+ return
+
+ key = scanner.nexttok()
+
+ if key == "IHREAL":
+ return
+
+ action = None
+ if key == "IHALPHA":
+ if scanner.sees("on"):
+ if game.iscloaked:
+ prout(_("The cloaking device has already been switched on."))
+ return
+ action = "CLON"
+ elif scanner.sees("off"):
+ if not game.iscloaked:
+ prout(_("The cloaking device has already been switched off."))
+ return
+ action = "CLOFF"
+ else:
+ huh()
+ return
+ else:
+ if not game.iscloaked:
+ proutn(_("Switch cloaking device on?"))
+ if not ja():
+ return
+ action = "CLON"
+ else:
+ proutn(_("Switch cloaking device off?"))
+ if not ja():
+ return
+ action = "CLOFF"
+ if action == None:
+ return;
+
+ if action == "CLOFF":
+ if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
+ prout(_("Spock- \"Captain, the Treaty of Algeron is in effect.\n Are you sure this is wise?\""))
+ if not ja():
+ return;
+ prout("Engineer Scott- \"Aye, Sir.\"");
+ game.iscloaked = FALSE;
+ if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
+ prout(_("The Romulan ship discovers you are breaking the Treaty of Algeron!"))
+ game.ncviol += 1
+ game.isviolreported = True
+
+ #if (neutz and game.state.date >= ALGERON) finish(FCLOAK);
+ return;
+
+ if action == "CLON":
+ if damage(DCLOAK):
+ prout(_("Engineer Scott- \"The cloaking device is damaged, Sir.\""))
+ return;
+
+ if game.condition == "docked":
+ prout(_("You cannot cloak while docked."))
+
+ if game.state.date >= ALGERON and not game.isviolreported:
+ prout(_("Spock- \"Captain, using the cloaking device is be a violation"))
+ prout(_(" of the Treaty of Algeron. Considering the alternatives,"))
+ proutn(" are you sure this is wise?");
+ if not ja():
+ return
+ prout(_("Engineer Scott- \"Cloaking device has engaging, Sir...\""))
+ attack(True)
+ prout(_("Engineer Scott- \"Cloaking device has engaged, Sir.\""))
+ game.iscloaked = True
+
+ if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
+ prout(_("The Romulan ship discovers you are breaking the Treaty of Algeron!"))
+ game.ncviol += 1
+ game.isviolreported = True
+
def doshield(shraise):
"Change shield status."
action = "NONE"
20, # DSHCTRL: high-speed shield controller 2.0%
10, # DDRAY: death ray 1.0%
30, # DDSP: deep-space probes 3.0%
+ 0, # DCLOAK: the cloaking device 0.0
)
assert(sum(weights) == 1000)
idx = randrange(1000)
while True:
j = randdevice()
# Cheat to prevent shuttle damage unless on ship
- if not (game.damage[j]<0.0 or (j == DSHUTTL and game.iscraft != "onship")):
+ if not (game.damage[j]<0.0 or (j == DSHUTTL and game.iscraft != "onship") or (j == DCLOAK and game.ship != 'E' or j == DDRAY)):
break
cdam.append(j)
extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
if damaged(DSHIELD) and game.shldup:
prout(_("***Shields knocked down."))
game.shldup = False
+ if damaged(DCLOAK) and game.iscloaked:
+ prout(_("***Cloaking device rendered inoperative."))
+ game.iscloaked = False
def attack(torps_ok):
# bad guy attacks us
# torps_ok == False forces use of phasers in an attack
+ if game.iscloaked:
+ return
# game could be over at this point, check
if game.alldone:
return
prout(_("***Photon tubes damaged by misfire."))
game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
break
- if game.shldup or game.condition == "docked":
+ if game.iscloaked:
+ dispersion *= 1.2
+ elif game.shldup or game.condition == "docked":
dispersion *= 1.0 + 0.0001*game.shield
torpedo(game.sector, tcourse[i], dispersion, number=i, nburst=n)
if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
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):
game.shldup = False
overheat(rpow)
-# Code from events,c begins here.
+
+def capture():
+ game.ididit = False # Nothing if we fail
+ game.optime = 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)
+ game.optime = 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
prout("== Event %d fires" % evcode)
datemin = game.future[l].date
xtime = datemin-game.state.date
+ if game.iscloaked:
+ game.energy -= xtime*500.0
+ if game.energy <= 0:
+ finish(FNRG)
+ return
game.state.date = datemin
# Decrement Federation resources and recompute remaining time
game.state.remres -= (game.state.remkl+4*len(game.state.kcmdr))*xtime
if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
return
elif evcode == FSPY: # Check with spy to see if SC should tractor beam
- if game.state.nscrem == 0 or \
+ if game.state.nscrem == 0 or game.state.iscloaked or \
ictbeam or istract or \
game.condition == "docked" or game.isatb == 1 or game.iscate:
return
continue
i = randrange(len(game.state.kcmdr))
yank = (game.state.kcmdr[i]-game.quadrant).distance()
- if istract or game.condition == "docked" or yank == 0:
+ if istract or game.condition == "docked" or game.iscloaked or yank == 0:
# Drats! Have to reschedule
schedule(FTBEAM,
game.optime + expran(1.5*game.intime/len(game.state.kcmdr)))
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
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
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."
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]
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):
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
300*game.state.nworldkl + \
45.0*game.nhelp +\
100.0*game.state.basekl +\
- 3.0*game.abandoned
+ 3.0*game.abandoned +\
+ 100*game.ncviol
if game.ship == 'F':
badpt += 100.0
elif game.ship is None:
return badpt
def finish(ifin):
- # end the game, with appropriate notfications
+ # end the game, with appropriate notifications
igotit = False
game.alldone = True
skip(3)
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()
prout(_("The %s has been cremated by its own phasers.") % crmshp())
elif ifin == FLOST:
prout(_("You and your landing party have been"))
- prout(_("converted to energy, disipating through space."))
+ prout(_("converted to energy, dissipating through space."))
elif ifin == FMINING:
prout(_("You are left with your landing party on"))
prout(_("a wild jungle planet inhabited by primitive cannibals."))
elif ifin == FHOLE:
prout(_("Your ship is drawn to the center of the black hole."))
prout(_("You are crushed into extremely dense matter."))
+ elif ifin == FCLOAK:
+ game.ncviol += 1
+ prout(_("You have violated the Treaty of Algeron."))
+ prout(_("The Romulan Empire can never trust you again."))
elif ifin == FCREW:
prout(_("Your last crew member has died."))
+ if ifin != FWON and ifin != FCLOAK and game.iscloaked:
+ prout(_("Your ship was cloaked so your subspace radio did not receive anything."))
+ prout(_("You may have missed some warning messages."))
+ skip(1)
if game.ship == 'F':
game.ship = None
elif game.ship == 'E':
+ 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
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)))
if klship:
prout(_("%6d ship(s) lost or destroyed %5d") %
(klship, -100*klship))
+ if game.ncviol > 0:
+ if ncviol == 1:
+ prout(_("1 Treaty of Algeron violation -100"))
+ else:
+ prout(_("%6d Treaty of Algeron violations %5d\n") %
+ (ncviol, -100*ncviol))
if not game.alive:
prout(_("Penalty for getting yourself killed -200"))
if game.gamewon:
# 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")
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()
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)
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."
def newquadrant(noattack):
# Leaving quadrant -- allow final enemy attack
- # Don't do it if being pushed by Nova
- if len(game.enemies) != 0 and not noattack:
+ # Don't set up attack if being pushed by nova or cloaked
+ if len(game.enemies) != 0 and not noattack and not game.iscloaked:
newcnd()
for enemy in game.enemies:
finald = (w - enemy.location).distance()
# check for edge of galaxy
kinks = 0
while True:
+
+
kink = False
if icourse.final.i < 0:
icourse.final.i = -icourse.final.i
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!"))
game.inorbit = False
# If tractor beam is to occur, don't move full distance
if game.state.date+game.optime >= scheduled(FTBEAM):
- trbeam = True
- game.condition = "red"
- icourse.distance = icourse.distance*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
- game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
+ if game.iscloaked:
+ # We can't be tractor beamed if cloaked,
+ # so move the event into the future
+ postpone(FTBEAM, game.optime + expran(1.5*game.intime/len(game.kcmdr)))
+ pass
+ else:
+ trbeam = True
+ game.condition = "red"
+ 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(icourse.moves):
if not game.base.is_valid() or abs(game.sector.i-game.base.i) > 1 or abs(game.sector.j-game.base.j) > 1:
prout(crmshp() + _(" not adjacent to base."))
return
+ if game.iscloaked:
+ prout(_("You cannot dock while cloaked."))
+ return
game.condition = "docked"
- if "verbose":
+ if verbose:
prout(_("Docked."))
game.ididit = True
if game.energy < game.inenrg:
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
def getcourse(isprobe):
"Get a course and distance from the user."
- key = 0
+ key = ""
dquad = copy.copy(game.quadrant)
navmode = "unspecified"
itemp = "curt"
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
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."
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:
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"))
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
blooey = False; twarp = False
if not involuntary: # Not WARPX entry
game.ididit = False
+ if game.iscloaked:
+ scanner.chew()
+ skip(1)
+ prout(_("Engineer Scott- \"The warp engines can not be used while cloaked, Sir.\""))
+ return
if game.damage[DWARPEN] > 10.0:
scanner.chew()
skip(1)
# 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()
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
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.
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':
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."))
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:
+ 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))
+ if game.iscloaked:
highvideo()
proutn("%c " % game.quad[i][j])
textcolor(DEFAULT)
newcnd()
prstat(_("Condition"), _("%s, %i DAMAGES") % \
(game.condition.upper(), sum([x > 0 for x in game.damage])))
+ if game.iscloaked:
+ prout(_(", CLOAKED"))
if not req or req == 3:
prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
if not req or req == 4:
_("Shield Control"), \
_("Death Ray"), \
_("D. S. Probe"), \
+ _("Cloaking Device"), \
)
def setup():
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 | OPTION_CLOAK)
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
game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
if game.options & OPTION_WORLDS:
game.inplan += int(NINHAB)
- game.state.nromrem = game.inrom = randrange(2 *game.skill)
+ game.state.nromrem = game.inrom = randrange(2 * game.skill)
game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
game.state.remtime = 7.0 * game.length
game.intime = game.state.remtime
game.justin = True
game.iplnet = None
game.neutz = game.inorbit = game.landed = False
- game.ientesc = game.iseenit = False
+ game.ientesc = game.iseenit = game.isviolreported = False
# Create a blank quadrant
game.quad = fill2d(QUADSIZE, lambda i, j: '.')
if game.iscate:
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:
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
("IMPULSE", 0),
("REST", 0),
("WARP", 0),
- ("SCORE", 0),
("SENSORS", OPTION_PLANETS),
("ORBIT", OPTION_PLANETS),
("TRANSPORT", OPTION_PLANETS),
("ABANDON", 0),
("DESTRUCT", 0),
("DEATHRAY", 0),
+ ("CAPTURE", OPTION_CAPTURE),
+ ("CLOAK", OPTION_CLOAK),
("DEBUG", 0),
("MAYDAY", 0),
("SOS", 0), # Synonym for MAYDAY
("CALL", 0), # Synonym for MAYDAY
("QUIT", 0),
("HELP", 0),
+ ("SCORE", 0),
("", 0),
]
def makemoves():
"Command-interpretation loop."
+ def checkviol():
+ if game.irhere and game.state.date >= ALGERON and not game.isviolreported and game.iscloaked:
+ prout(_("The Romulan ship discovers you are breaking the Treaty of Algeron!"))
+ game.ncviol += 1
+ game.isviolreported = True
while True: # command loop
drawmaps(1)
while True: # get a command
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":
elif cmd == "PHASERS": # phasers
phasers()
if game.ididit:
+ checkviol()
hitme = True
elif cmd in ("TORPEDO", "PHOTONS"): # photon torpedos
torps()
if game.ididit:
+ checkviol()
hitme = True
elif cmd == "MOVE": # move under warp
warp(wcourse=None, involuntary=False)
hitme = True
elif cmd == "WARP": # warp
setwarp()
- elif cmd == "SCORE": # score
- score()
elif cmd == "SENSORS": # sensors
sensor()
elif cmd == "ORBIT": # orbit
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
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
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":
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":
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 "<sstcanner: token=%s, type=%s, queue=%s>" % (scanner.token, scanner.type, scanner.inqueue)
+ return "<sstcanner: token=%s, type=%s, queue=%s>" % (self.token, self.type, self.inqueue)
def ja():
"Yes-or-no confirmation."
atover(True)
if __name__ == '__main__':
- import getopt, socket
try:
#global line, thing, game
game = None