3 sst.py =-- Super Star Trek in Python
5 This code is a Python translation of a C translation of a FORTRAN
6 original dating back to 1973. Beautiful Python it is not. But it
11 SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON,
12 LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE
13 were in the original non-"super" version of UT FORTRAN Star Trek.
15 Tholians were not in the original. Dave is dubious about their merits.
16 (They are now controlled by OPTION_THOLIAN and turned off if the game
19 Planets and dilithium crystals were not in the original. Dave is OK
20 with this idea. (It's now controlled by OPTION_PLANETS and turned
21 off if the game type is "plain".)
23 Dave says the bit about the Galileo getting turned into a
24 McDonald's is "consistant with our original vision". (This has been
25 left permanently enabled, as it can only happen if OPTION_PLANETS
28 Dave also says the Space Thingy should not be preserved across saved
29 games, so you can't prove to others that you've seen it. He says it
30 shouldn't fire back, either. It should do nothing except scream and
31 disappear when hit by photon torpedos. It's OK that it may move
32 when attacked, but it didn't in the original. (Whether the Thingy
33 can fire back is now controlled by OPTION_THINGY and turned off if the
34 game type is "plain" or "almy". The no-save behavior has been restored.)
36 The Faerie Queen, black holes, and time warping were in the original.
38 Here are Tom Almy's changes:
40 In early 1997, I got the bright idea to look for references to
41 "Super Star Trek" on the World Wide Web. There weren't many hits,
42 but there was one that came up with 1979 Fortran sources! This
43 version had a few additional features that mine didn't have,
44 however mine had some feature it didn't have. So I merged its
45 features that I liked. I also took a peek at the DECUS version (a
46 port, less sources, to the PDP-10), and some other variations.
48 1, Compared to the original UT version, I've changed the "help"
49 command to "call" and the "terminate" command to "quit" to better
50 match user expectations. The DECUS version apparently made those
51 changes as well as changing "freeze" to "save". However I like
52 "freeze". (Both "freeze" and "save" work in SST2K.)
54 2. The experimental deathray originally had only a 5% chance of
55 success, but could be used repeatedly. I guess after a couple
56 years of use, it was less "experimental" because the 1979
57 version had a 70% success rate. However it was prone to breaking
58 after use. I upgraded the deathray, but kept the original set of
59 failure modes (great humor!). (Now controlled by OPTION_DEATHRAY
60 and turned off if game type is "plain".)
62 3. The 1979 version also mentions srscan and lrscan working when
63 docked (using the starbase's scanners), so I made some changes here
64 to do this (and indicating that fact to the player), and then realized
65 the base would have a subspace radio as well -- doing a Chart when docked
66 updates the star chart, and all radio reports will be heard. The Dock
67 command will also give a report if a base is under attack.
69 4. Tholian Web from the 1979 version. (Now controlled by
70 OPTION_THOLIAN and turned off if game type is "plain".)
72 5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING
73 and turned off if game type is "plain".)
75 6. Regular Klingons and Romulans can move in Expert and Emeritus games.
76 This code could use improvement. (Now controlled by OPTION_MVBADDY
77 and turned off if game type is "plain".)
79 7. The deep-space probe feature from the DECUS version. (Now controlled
80 by OPTION_PROBE and turned off if game type is "plain").
82 8. 'emexit' command from the 1979 version.
84 9. Bugfix: Klingon commander movements are no longer reported if long-range
87 10. Bugfix: Better base positioning at startup (more spread out).
88 That made sense to add because most people abort games with
91 In June 2002, I fixed two known bugs and a documentation typo.
92 In June 2004 I fixed a number of bugs involving: 1) parsing invalid
93 numbers, 2) manual phasers when SR scan is damaged and commander is
94 present, 3) time warping into the future, 4) hang when moving
95 klingons in crowded quadrants. (These fixes are in SST2K.)
97 Here are Stas Sergeev's changes:
99 1. The Space Thingy can be shoved, if you ram it, and can fire back if
100 fired upon. (Now controlled by OPTION_THINGY and turned off if game
101 type is "plain" or "almy".)
103 2. When you are docked, base covers you with an almost invincible shield.
104 (A commander can still ram you, or a Romulan can destroy the base,
105 or a SCom can even succeed with direct attack IIRC, but this rarely
106 happens.) (Now controlled by OPTION_BASE and turned off if game
107 type is "plain" or "almy".)
109 3. Ramming a black hole is no longer instant death. There is a
110 chance you might get timewarped instead. (Now controlled by
111 OPTION_BLKHOLE and turned off if game type is "plain" or "almy".)
113 4. The Tholian can be hit with phasers.
115 5. SCom can't escape from you if no more enemies remain
116 (without this, chasing SCom can take an eternity).
118 6. Probe target you enter is now the destination quadrant. Before I don't
119 remember what it was, but it was something I had difficulty using.
121 7. Secret password is now autogenerated.
123 8. "Plaque" is adjusted for A4 paper :-)
125 9. Phasers now tells you how much energy needed, but only if the computer
128 10. Planets are auto-scanned when you enter the quadrant.
130 11. Mining or using crystals in presense of enemy now yields an attack.
131 There are other minor adjustments to what yields an attack
134 12. "freeze" command reverts to "save", most people will understand this
135 better anyway. (SST2K recognizes both.)
137 13. Screen-oriented interface, with sensor scans always up. (SST2K
138 supports both screen-oriented and TTY modes.)
140 Eric Raymond's changes:
142 Mainly, I translated this C code out of FORTRAN into C -- created #defines
143 for a lot of magic numbers and refactored the heck out of it.
145 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
147 2. Status report now indicates when dilithium crystals are on board.
149 3. Per Dave Matuszek's remarks, Thingy state is never saved across games.
151 4. Added game option selection so you can play a close (but not bug-for-
152 bug identical) approximation of older versions.
154 5. Half the quadrants now have inhabited planets, from which one
155 cannot mine dilithium (there will still be the same additional number
156 of dilithium-bearing planets). Torpedoing an inhabited world is *bad*.
157 There is BSD-Trek-like logic for Klingons to attack and enslave
158 inhabited worlds, producing more ships (only is skill is 'good' or
159 better). (Controlled by OPTION_WORLDS and turned off if game
160 type is "plain" or "almy".)
162 6. User input is now logged so we can do regression testing.
164 7. More BSD-Trek features: You can now lose if your entire crew
165 dies in battle. When abandoning ship in a game with inhabited
166 worlds enabled, they must have one in the quadrant to beam down
167 to; otherwise they die in space and this counts heavily against
168 your score. Docking at a starbase replenishes your crew.
170 8. Still more BSD-Trek: we now have a weighted damage table.
171 Also, the nav subsystem (enabling automatic course
172 setting) can be damaged separately from the main computer (which
173 handles weapons targeting, ETA calculation, and self-destruct).
175 After these features were added, I translated this into Python and added
178 9. A long-range scan is done silently whenever you call CHART; thus
179 the LRSCAN command is no longer needed. (Controlled by OPTION_AUTOSCAN
180 and turned off if game type is "plain" or "almy".)
182 import os, sys, math, curses, time, readline, cPickle, random, copy
184 SSTDOC = "/usr/share/doc/sst/sst.doc"
187 # Stub to be replaced
188 def _(str): return str
192 NINHAB = (GALSIZE * GALSIZE / 2)
194 PLNETMAX = (NINHAB + MAXUNINHAB)
197 BASEMAX = (GALSIZE * GALSIZE / 12)
200 FULLCREW = 428 # BSD Trek was 387, that's wrong
205 # These functions hide the difference between 0-origin and 1-origin addressing.
206 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
207 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
209 # How to represent features
230 def __init__(self, x=None, y=None):
233 def invalidate(self):
234 self.i = self.j = None
236 return self.i != None and self.j != None
237 def __eq__(self, other):
238 return other != None and self.i == other.i and self.j == other.j
239 def __add__(self, other):
240 return coord(self.i+other.i, self.j+other.j)
241 def __sub__(self, other):
242 return coord(self.i-other.i, self.j-other.j)
243 def __mul__(self, other):
244 return coord(self.i*other, self.j*other)
245 def __rmul__(self, other):
246 return coord(self.i*other, self.j*other)
247 def __div__(self, other):
248 return coord(self.i/other, self.j/other)
249 def __rdiv__(self, other):
250 return coord(self.i/other, self.j/other)
251 def snaptogrid(self):
252 return coord(int(round(self.i)), int(round(self.j)))
253 def distance(self, other=None):
254 if not other: other = coord(0, 0)
255 return math.sqrt((self.i - other.i)**2 + (self.j - other.j)**2)
256 def bearing(self, other=None):
257 if not other: other = coord(0, 0)
258 return 1.90985*math.atan2(self.j-other.j, self.i-other.i)
264 s.i = self.i / abs(self.i)
268 s.j = self.j / abs(self.j)
272 s.i = self.i + randrange(-1, 2)
273 s.j = self.j + randrange(-1, 2)
278 if self.i == None or self.j == None:
280 return "%s - %s" % (self.i+1, self.j+1)
285 self.name = None # string-valued if inhabited
286 self.quadrant = coord() # quadrant located
287 self.pclass = None # could be ""M", "N", "O", or "destroyed"
288 self.crystals = "absent"# could be "mined", "present", "absent"
289 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
290 self.inhabited = False # is it inhabites?
298 self.starbase = False
301 self.supernova = False
303 self.status = "secure" # Could be "secure", "distressed", "enslaved"
311 def fill2d(size, fillfun):
312 "Fill an empty list in 2D."
314 for i in range(size):
316 for j in range(size):
317 lst[i].append(fillfun(i, j))
322 self.snap = False # snapshot taken
323 self.crew = 0 # crew complement
324 self.remkl = 0 # remaining klingons
325 self.nscrem = 0 # remaining super commanders
326 self.starkl = 0 # destroyed stars
327 self.basekl = 0 # destroyed bases
328 self.nromrem = 0 # Romulans remaining
329 self.nplankl = 0 # destroyed uninhabited planets
330 self.nworldkl = 0 # destroyed inhabited planets
331 self.planets = [] # Planet information
332 self.date = 0.0 # stardate
333 self.remres = 0 # remaining resources
334 self.remtime = 0 # remaining time
335 self.baseq = [] # Base quadrant coordinates
336 self.kcmdr = [] # Commander quadrant coordinates
337 self.kscmdr = coord() # Supercommander quadrant coordinates
338 # the galaxy (subscript 0 not used)
339 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
340 # the starchart (subscript 0 not used)
341 self.chart = fill2d(GALSIZE, lambda i, j: page())
345 self.date = None # A real number
346 self.quadrant = None # A coord structure
349 OPTION_ALL = 0xffffffff
350 OPTION_TTY = 0x00000001 # old interface
351 OPTION_CURSES = 0x00000002 # new interface
352 OPTION_IOMODES = 0x00000003 # cover both interfaces
353 OPTION_PLANETS = 0x00000004 # planets and mining
354 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
355 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
356 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
357 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
358 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
359 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
360 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
361 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
362 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
363 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
364 OPTION_PLAIN = 0x01000000 # user chose plain game
365 OPTION_ALMY = 0x02000000 # user chose Almy variant
384 NDEVICES= 16 # Number of devices
393 def damaged(dev): return (game.damage[dev] != 0.0)
394 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
396 # Define future events
397 FSPY = 0 # Spy event happens always (no future[] entry)
398 # can cause SC to tractor beam Enterprise
399 FSNOVA = 1 # Supernova
400 FTBEAM = 2 # Commander tractor beams Enterprise
401 FSNAP = 3 # Snapshot for time warp
402 FBATTAK = 4 # Commander attacks base
403 FCDBAS = 5 # Commander destroys base
404 FSCMOVE = 6 # Supercommander moves (might attack base)
405 FSCDBAS = 7 # Supercommander destroys base
406 FDSPROB = 8 # Move deep space probe
407 FDISTR = 9 # Emit distress call from an inhabited world
408 FENSLV = 10 # Inhabited word is enslaved */
409 FREPRO = 11 # Klingons build a ship in an enslaved system
413 # abstract out the event handling -- underlying data structures will change
414 # when we implement stateful events
416 def findevent(evtype): return game.future[evtype]
419 def __init__(self, type=None, loc=None, power=None):
424 self.kpower = power # enemy energy level
425 game.enemies.append(self)
427 motion = (loc != self.kloc)
428 if self.kloc.i is not None and self.kloc.j is not None:
431 game.quad[self.kloc.i][self.kloc.j] = IHWEB
433 game.quad[self.kloc.i][self.kloc.j] = IHDOT
435 self.kloc = copy.copy(loc)
436 game.quad[self.kloc.i][self.kloc.j] = self.type
437 self.kdist = self.kavgd = (game.sector - loc).distance()
440 self.kdist = self.kavgd = None
441 game.enemies.remove(self)
444 return "<%s,%s.%f>" % (self.type, self.kloc, self.kpower) # For debugging
448 self.options = None # Game options
449 self.state = snapshot() # A snapshot structure
450 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
451 self.quad = None # contents of our quadrant
452 self.damage = [0.0] * NDEVICES # damage encountered
453 self.future = [] # future events
454 for i in range(NEVENTS):
455 self.future.append(event())
456 self.passwd = None; # Self Destruct password
458 self.quadrant = None # where we are in the large
459 self.sector = None # where we are in the small
460 self.tholian = None # Tholian enemy object
461 self.base = None # position of base in current quadrant
462 self.battle = None # base coordinates being attacked
463 self.plnet = None # location of planet in quadrant
464 self.probec = None # current probe quadrant
465 self.gamewon = False # Finished!
466 self.ididit = False # action taken -- allows enemy to attack
467 self.alive = False # we are alive (not killed)
468 self.justin = False # just entered quadrant
469 self.shldup = False # shields are up
470 self.shldchg = False # shield is changing (affects efficiency)
471 self.iscate = False # super commander is here
472 self.ientesc = False # attempted escape from supercommander
473 self.resting = False # rest time
474 self.icraft = False # Kirk in Galileo
475 self.landed = False # party on planet (true), on ship (false)
476 self.alldone = False # game is now finished
477 self.neutz = False # Romulan Neutral Zone
478 self.isarmed = False # probe is armed
479 self.inorbit = False # orbiting a planet
480 self.imine = False # mining
481 self.icrystl = False # dilithium crystals aboard
482 self.iseenit = False # seen base attack report
483 self.thawed = False # thawed game
484 self.condition = None # "green", "yellow", "red", "docked", "dead"
485 self.iscraft = None # "onship", "offship", "removed"
486 self.skill = None # Player skill level
487 self.inkling = 0 # initial number of klingons
488 self.inbase = 0 # initial number of bases
489 self.incom = 0 # initial number of commanders
490 self.inscom = 0 # initial number of commanders
491 self.inrom = 0 # initial number of commanders
492 self.instar = 0 # initial stars
493 self.intorps = 0 # initial/max torpedoes
494 self.torps = 0 # number of torpedoes
495 self.ship = 0 # ship type -- 'E' is Enterprise
496 self.abandoned = 0 # count of crew abandoned in space
497 self.length = 0 # length of game
498 self.klhere = 0 # klingons here
499 self.casual = 0 # causalties
500 self.nhelp = 0 # calls for help
501 self.nkinks = 0 # count of energy-barrier crossings
502 self.iplnet = None # planet # in quadrant
503 self.inplan = 0 # initial planets
504 self.irhere = 0 # Romulans in quadrant
505 self.isatb = 0 # =1 if super commander is attacking base
506 self.tourn = None # tournament number
507 self.proben = 0 # number of moves for probe
508 self.nprobes = 0 # number of probes available
509 self.inresor = 0.0 # initial resources
510 self.intime = 0.0 # initial time
511 self.inenrg = 0.0 # initial/max energy
512 self.inshld = 0.0 # initial/max shield
513 self.inlsr = 0.0 # initial life support resources
514 self.indate = 0.0 # initial date
515 self.energy = 0.0 # energy level
516 self.shield = 0.0 # shield level
517 self.warpfac = 0.0 # warp speed
518 self.wfacsq = 0.0 # squared warp factor
519 self.lsupres = 0.0 # life support reserves
520 self.dist = 0.0 # movement distance
521 self.direc = 0.0 # movement direction
522 self.optime = 0.0 # time taken by current operation
523 self.docfac = 0.0 # repair factor when docking (constant?)
524 self.damfac = 0.0 # damage factor
525 self.lastchart = 0.0 # time star chart was last updated
526 self.cryprob = 0.0 # probability that crystal will work
527 self.probex = 0.0 # location of probe
529 self.probeinx = 0.0 # probe x,y increment
530 self.probeiny = 0.0 #
531 self.height = 0.0 # height of orbit around planet
533 # Stas thinks this should be (C expression):
534 # game.state.remkl + len(game.state.kcmdr) > 0 ?
535 # game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr)) : 99
536 # He says the existing expression is prone to divide-by-zero errors
537 # after killing the last klingon when score is shown -- perhaps also
538 # if the only remaining klingon is SCOM.
539 game.state.remtime = game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr))
540 # From enumerated type 'feature'
561 # From enumerated type 'FINTYPE'
585 # Log the results of pulling random numbers so we can check determinism.
591 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
594 def randrange(*args):
595 v = random.randrange(*args)
596 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
602 v *= args[0] # returns from [0, args[0])
604 v = args[0] + v*(args[1]-args[0]) # returns from [args[0], args[1])
605 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
608 # Code from ai.c begins here
611 "Would this quadrant welcome another Klingon?"
612 return VALID_QUADRANT(iq.i,iq.j) and \
613 not game.state.galaxy[iq.i][iq.j].supernova and \
614 game.state.galaxy[iq.i][iq.j].klingons < MAXKLQUAD
616 def tryexit(enemy, look, irun):
617 "A bad guy attempts to bug out."
619 iq.i = game.quadrant.i+(look.i+(QUADSIZE-1))/QUADSIZE - 1
620 iq.j = game.quadrant.j+(look.j+(QUADSIZE-1))/QUADSIZE - 1
621 if not welcoming(iq):
623 if enemy.type == IHR:
624 return False; # Romulans cannot escape!
626 # avoid intruding on another commander's territory
627 if enemy.type == IHC:
628 if iq in game.state.kcmdr:
630 # refuse to leave if currently attacking starbase
631 if game.battle == game.quadrant:
633 # don't leave if over 1000 units of energy
634 if enemy.kpower > 1000.0:
636 # emit escape message and move out of quadrant.
637 # we know this if either short or long range sensors are working
638 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
639 game.condition == "docked":
640 prout(crmena(True, enemy.type, "sector", enemy.kloc) + \
641 (_(" escapes to Quadrant %s (and regains strength).") % q))
642 # handle local matters related to escape
645 if game.condition != "docked":
647 # Handle global matters related to escape
648 game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
649 game.state.galaxy[iq.i][iq.j].klingons += 1
654 schedule(FSCMOVE, 0.2777)
658 for cmdr in game.state.kcmdr:
659 if cmdr == game.quadrant:
660 game.state.kcmdr[n] = iq
662 return True; # success
665 # The bad-guy movement algorithm:
667 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
668 # If both are operating full strength, force is 1000. If both are damaged,
669 # force is -1000. Having shields down subtracts an additional 1000.
671 # 2. Enemy has forces equal to the energy of the attacker plus
672 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
673 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
675 # Attacker Initial energy levels (nominal):
676 # Klingon Romulan Commander Super-Commander
677 # Novice 400 700 1200
679 # Good 450 800 1300 1750
680 # Expert 475 850 1350 1875
681 # Emeritus 500 900 1400 2000
682 # VARIANCE 75 200 200 200
684 # Enemy vessels only move prior to their attack. In Novice - Good games
685 # only commanders move. In Expert games, all enemy vessels move if there
686 # is a commander present. In Emeritus games all enemy vessels move.
688 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
689 # forces are 1000 greater than Enterprise.
691 # Agressive action on average cuts the distance between the ship and
692 # the enemy to 1/4 the original.
694 # 4. At lower energy advantage, movement units are proportional to the
695 # advantage with a 650 advantage being to hold ground, 800 to move forward
696 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
698 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
699 # retreat, especially at high skill levels.
701 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
704 def movebaddy(enemy):
705 "Tactical movement for the bad guys."
706 next = coord(); look = coord()
708 # This should probably be just (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
709 if game.skill >= SKILL_EXPERT:
710 nbaddys = (((game.quadrant in game.state.kcmdr)*2 + (game.state.kscmdr==game.quadrant)*2+game.klhere*1.23+game.irhere*1.5)/2.0)
712 nbaddys = (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
714 mdist = int(dist1 + 0.5); # Nearest integer distance
715 # If SC, check with spy to see if should hi-tail it
716 if enemy.type==IHS and \
717 (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
721 # decide whether to advance, retreat, or hold position
722 forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
724 forces += 1000; # Good for enemy if shield is down!
725 if not damaged(DPHASER) or not damaged(DPHOTON):
726 if damaged(DPHASER): # phasers damaged
729 forces -= 0.2*(game.energy - 2500.0)
730 if damaged(DPHOTON): # photon torpedoes damaged
733 forces -= 50.0*game.torps
735 # phasers and photon tubes both out!
738 if forces <= 1000.0 and game.condition != "docked": # Typical situation
739 motion = ((forces + randreal(200))/150.0) - 5.0
741 if forces > 1000.0: # Very strong -- move in for kill
742 motion = (1.0 - randreal())**2 * dist1 + 1.0
743 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
744 motion -= game.skill*(2.0-randreal()**2)
746 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
747 # don't move if no motion
750 # Limit motion according to skill
751 if abs(motion) > game.skill:
756 # calculate preferred number of steps
757 nsteps = abs(int(motion))
758 if motion > 0 and nsteps > mdist:
759 nsteps = mdist; # don't overshoot
760 if nsteps > QUADSIZE:
761 nsteps = QUADSIZE; # This shouldn't be necessary
763 nsteps = 1; # This shouldn't be necessary
765 proutn("NSTEPS = %d:" % nsteps)
766 # Compute preferred values of delta X and Y
767 m = game.sector - enemy.kloc
768 if 2.0 * abs(m.i) < abs(m.j):
770 if 2.0 * abs(m.j) < abs(game.sector.i-enemy.kloc.i):
772 m = (motion * m).sgn()
775 for ll in range(nsteps):
777 proutn(" %d" % (ll+1))
778 # Check if preferred position available
789 attempts = 0; # Settle mysterious hang problem
790 while attempts < 20 and not success:
792 if look.i < 0 or look.i >= QUADSIZE:
793 if motion < 0 and tryexit(enemy, look, irun):
795 if krawli == m.i or m.j == 0:
797 look.i = next.i + krawli
799 elif look.j < 0 or look.j >= QUADSIZE:
800 if motion < 0 and tryexit(enemy, look, irun):
802 if krawlj == m.j or m.i == 0:
804 look.j = next.j + krawlj
806 elif (game.options & OPTION_RAMMING) and game.quad[look.i][look.j] != IHDOT:
807 # See if enemy should ram ship
808 if game.quad[look.i][look.j] == game.ship and \
809 (enemy.type == IHC or enemy.type == IHS):
810 collision(rammed=True, enemy=enemy)
812 if krawli != m.i and m.j != 0:
813 look.i = next.i + krawli
815 elif krawlj != m.j and m.i != 0:
816 look.j = next.j + krawlj
819 break; # we have failed
831 if not damaged(DSRSENS) or game.condition == "docked":
832 proutn(_("*** %s from Sector %s") % (cramen(enemy.type), enemy.kloc))
833 if enemy.kdist < dist1:
834 proutn(_(" advances to "))
836 proutn(_(" retreats to "))
837 prout("Sector %s." % next)
840 "Sequence Klingon tactical movement."
843 # Figure out which Klingon is the commander (or Supercommander)
845 if game.quadrant in game.state.kcmdr:
846 for enemy in game.enemies:
847 if enemy.type == IHC:
849 if game.state.kscmdr==game.quadrant:
850 for enemy in game.enemies:
851 if enemy.type == IHS:
854 # If skill level is high, move other Klingons and Romulans too!
855 # Move these last so they can base their actions on what the
857 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
858 for enemy in game.enemies:
859 if enemy.type in (IHK, IHR):
861 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
863 def movescom(iq, avoid):
864 "Commander movement helper."
865 # Avoid quadrants with bases if we want to avoid Enterprise
866 if not welcoming(iq) or (avoid and iq in game.state.baseq):
868 if game.justin and not game.iscate:
871 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons -= 1
872 game.state.kscmdr = iq
873 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons += 1
874 if game.state.kscmdr==game.quadrant:
875 # SC has scooted, Remove him from current quadrant
880 for enemy in game.enemies:
881 if enemy.type == IHS:
885 if game.condition != "docked":
887 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
888 # check for a helpful planet
889 for i in range(game.inplan):
890 if game.state.planets[i].quadrant == game.state.kscmdr and \
891 game.state.planets[i].crystals == "present":
893 game.state.planets[i].pclass = "destroyed"
894 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].planet = None
897 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
898 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
899 prout(_(" by the Super-commander.\""))
901 return False; # looks good!
903 def supercommander():
904 "Move the Super Commander."
905 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
908 prout("== SUPERCOMMANDER")
909 # Decide on being active or passive
910 avoid = ((game.incom - len(game.state.kcmdr) + game.inkling - game.state.remkl)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) or \
911 (game.state.date-game.indate) < 3.0)
912 if not game.iscate and avoid:
913 # compute move away from Enterprise
914 idelta = game.state.kscmdr-game.quadrant
915 if math.sqrt(idelta.i*idelta.i+idelta.j*idelta.j) > 2.0:
917 idelta.i = game.state.kscmdr.j-game.quadrant.j
918 idelta.j = game.quadrant.i-game.state.kscmdr.i
920 # compute distances to starbases
921 if not game.state.baseq:
925 sc = game.state.kscmdr
926 for base in game.state.baseq:
927 basetbl.append((i, (base - sc).distance()))
928 if game.state.baseq > 1:
929 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
930 # look for nearest base without a commander, no Enterprise, and
931 # without too many Klingons, and not already under attack.
932 ifindit = iwhichb = 0
933 for (i2, base) in enumerate(game.state.baseq):
934 i = basetbl[i2][0]; # bug in original had it not finding nearest
935 if base==game.quadrant or base==game.battle or not welcoming(base):
937 # if there is a commander, and no other base is appropriate,
938 # we will take the one with the commander
939 for cmdr in game.state.kcmdr:
940 if base == cmdr and ifindit != 2:
944 else: # no commander -- use this one
949 return # Nothing suitable -- wait until next time
950 ibq = game.state.baseq[iwhichb]
951 # decide how to move toward base
952 idelta = ibq - game.state.kscmdr
953 # Maximum movement is 1 quadrant in either or both axes
954 idelta = idelta.sgn()
955 # try moving in both x and y directions
956 # there was what looked like a bug in the Almy C code here,
957 # but it might be this translation is just wrong.
958 iq = game.state.kscmdr + idelta
959 if movescom(iq, avoid):
960 # failed -- try some other maneuvers
961 if idelta.i==0 or idelta.j==0:
964 iq.j = game.state.kscmdr.j + 1
965 if movescom(iq, avoid):
966 iq.j = game.state.kscmdr.j - 1
969 iq.i = game.state.kscmdr.i + 1
970 if movescom(iq, avoid):
971 iq.i = game.state.kscmdr.i - 1
974 # try moving just in x or y
975 iq.j = game.state.kscmdr.j
976 if movescom(iq, avoid):
977 iq.j = game.state.kscmdr.j + idelta.j
978 iq.i = game.state.kscmdr.i
981 if len(game.state.baseq) == 0:
984 for (i, ibq) in enumerate(game.state.baseq):
985 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
988 return # no, don't attack base!
991 schedule(FSCDBAS, randreal(1.0, 3.0))
992 if is_scheduled(FCDBAS):
993 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
994 if not communicating():
998 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1000 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1001 proutn(_(" It can survive until stardate %d.\"") \
1002 % int(scheduled(FSCDBAS)))
1003 if not game.resting:
1005 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1008 game.resting = False
1009 game.optime = 0.0; # actually finished
1011 # Check for intelligence report
1014 (not communicating()) or \
1015 not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].charted):
1018 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1019 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1024 if not game.tholian or game.justin:
1027 if game.tholian.kloc.i == 0 and game.tholian.kloc.j == 0:
1028 id.i = 0; id.j = QUADSIZE-1
1029 elif game.tholian.kloc.i == 0 and game.tholian.kloc.j == QUADSIZE-1:
1030 id.i = QUADSIZE-1; id.j = QUADSIZE-1
1031 elif game.tholian.kloc.i == QUADSIZE-1 and game.tholian.kloc.j == QUADSIZE-1:
1032 id.i = QUADSIZE-1; id.j = 0
1033 elif game.tholian.kloc.i == QUADSIZE-1 and game.tholian.kloc.j == 0:
1036 # something is wrong!
1037 game.tholian.move(None)
1038 prout("***Internal error: Tholian in a bad spot.")
1040 # do nothing if we are blocked
1041 if game.quad[id.i][id.j] not in (IHDOT, IHWEB):
1043 here = copy.copy(game.tholian.kloc)
1044 delta = (id - game.tholian.kloc).sgn()
1046 while here.i != id.i:
1048 if game.quad[here.i][here.j]==IHDOT:
1049 game.tholian.move(here)
1051 while here.j != id.j:
1053 if game.quad[here.i][here.j]==IHDOT:
1054 game.tholian.move(here)
1055 # check to see if all holes plugged
1056 for i in range(QUADSIZE):
1057 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1059 if game.quad[QUADSIZE-1][i]!=IHWEB and game.quad[QUADSIZE-1][i]!=IHT:
1061 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1063 if game.quad[i][QUADSIZE-1]!=IHWEB and game.quad[i][QUADSIZE-1]!=IHT:
1065 # All plugged up -- Tholian splits
1066 game.quad[game.tholian.kloc.i][game.tholian.kloc.j]=IHWEB
1068 prout(crmena(True, IHT, "sector", game.tholian) + _(" completes web."))
1069 game.tholian.move(None)
1072 # Code from battle.c begins here
1074 def doshield(shraise):
1075 "Change shield status."
1081 key = scanner.next()
1082 if key == "IHALPHA":
1083 if scanner.sees("transfer"):
1086 if damaged(DSHIELD):
1087 prout(_("Shields damaged and down."))
1089 if scanner.sees("up"):
1091 elif scanner.sees("down"):
1094 proutn(_("Do you wish to change shield energy? "))
1096 proutn(_("Energy to transfer to shields- "))
1098 elif damaged(DSHIELD):
1099 prout(_("Shields damaged and down."))
1102 proutn(_("Shields are up. Do you want them down? "))
1109 proutn(_("Shields are down. Do you want them up? "))
1115 if action == "SHUP": # raise shields
1117 prout(_("Shields already up."))
1121 if game.condition != "docked":
1123 prout(_("Shields raised."))
1124 if game.energy <= 0:
1126 prout(_("Shields raising uses up last of energy."))
1131 elif action == "SHDN":
1133 prout(_("Shields already down."))
1137 prout(_("Shields lowered."))
1140 elif action == "NRG":
1141 while scanner.next() != "IHREAL":
1143 proutn(_("Energy to transfer to shields- "))
1145 if scanner.real == 0:
1147 if scanner.real > game.energy:
1148 prout(_("Insufficient ship energy."))
1151 if game.shield+scanner.real >= game.inshld:
1152 prout(_("Shield energy maximized."))
1153 if game.shield+scanner.real > game.inshld:
1154 prout(_("Excess energy requested returned to ship energy"))
1155 game.energy -= game.inshld-game.shield
1156 game.shield = game.inshld
1158 if scanner.real < 0.0 and game.energy-scanner.real > game.inenrg:
1159 # Prevent shield drain loophole
1161 prout(_("Engineering to bridge--"))
1162 prout(_(" Scott here. Power circuit problem, Captain."))
1163 prout(_(" I can't drain the shields."))
1166 if game.shield+scanner.real < 0:
1167 prout(_("All shield energy transferred to ship."))
1168 game.energy += game.shield
1171 proutn(_("Scotty- \""))
1172 if scanner.real > 0:
1173 prout(_("Transferring energy to shields.\""))
1175 prout(_("Draining energy from shields.\""))
1176 game.shield += scanner.real
1177 game.energy -= scanner.real
1181 "Choose a device to damage, at random."
1182 # Quoth Eric Allman in the code of BSD-Trek:
1183 # "Under certain conditions you can get a critical hit. This
1184 # sort of hit damages devices. The probability that a given
1185 # device is damaged depends on the device. Well protected
1186 # devices (such as the computer, which is in the core of the
1187 # ship and has considerable redundancy) almost never get
1188 # damaged, whereas devices which are exposed (such as the
1189 # warp engines) or which are particularly delicate (such as
1190 # the transporter) have a much higher probability of being
1193 # This is one place where OPTION_PLAIN does not restore the
1194 # original behavior, which was equiprobable damage across
1195 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1196 # and have done with it. Also, in the original game, DNAVYS
1197 # and DCOMPTR were the same device.
1199 # Instead, we use a table of weights similar to the one from BSD Trek.
1200 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1201 # We don't have a cloaking device. The shuttle got the allocation
1202 # for the cloaking device, then we shaved a half-percent off
1203 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1205 105, # DSRSENS: short range scanners 10.5%
1206 105, # DLRSENS: long range scanners 10.5%
1207 120, # DPHASER: phasers 12.0%
1208 120, # DPHOTON: photon torpedoes 12.0%
1209 25, # DLIFSUP: life support 2.5%
1210 65, # DWARPEN: warp drive 6.5%
1211 70, # DIMPULS: impulse engines 6.5%
1212 145, # DSHIELD: deflector shields 14.5%
1213 30, # DRADIO: subspace radio 3.0%
1214 45, # DSHUTTL: shuttle 4.5%
1215 15, # DCOMPTR: computer 1.5%
1216 20, # NAVCOMP: navigation system 2.0%
1217 75, # DTRANSP: transporter 7.5%
1218 20, # DSHCTRL: high-speed shield controller 2.0%
1219 10, # DDRAY: death ray 1.0%
1220 30, # DDSP: deep-space probes 3.0%
1222 idx = randrange(1000) # weights must sum to 1000
1224 for (i, w) in enumerate(weights):
1228 return None; # we should never get here
1230 def collision(rammed, enemy):
1231 "Collision handling fot rammong events."
1232 prouts(_("***RED ALERT! RED ALERT!"))
1234 prout(_("***COLLISION IMMINENT."))
1238 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(enemy.type, 1.0)
1240 proutn(_(" rammed by "))
1243 proutn(crmena(False, enemy.type, "sector", enemy.kloc))
1245 proutn(_(" (original position)"))
1247 deadkl(enemy.kloc, enemy.type, game.sector)
1248 proutn("***" + crmship() + " heavily damaged.")
1249 icas = randrange(10, 30)
1250 prout(_("***Sickbay reports %d casualties"), icas)
1252 game.state.crew -= icas
1253 # In the pre-SST2K version, all devices got equiprobably damaged,
1254 # which was silly. Instead, pick up to half the devices at
1255 # random according to our weighting table,
1256 ncrits = randrange(NDEVICES/2)
1257 for m in range(ncrits):
1259 if game.damage[dev] < 0:
1261 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1262 # Damage for at least time of travel!
1263 game.damage[dev] += game.optime + extradm
1265 prout(_("***Shields are down."))
1266 if game.state.remkl + len(game.state.kcmdr) + game.state.nscrem:
1273 def torpedo(origin, course, dispersion, number, nburst):
1274 "Let a photon torpedo fly"
1275 if not damaged(DSRSENS) or game.condition=="docked":
1276 setwnd(srscan_window)
1278 setwnd(message_window)
1280 ac = course + 0.25*dispersion
1281 angle = (15.0-ac)*0.5235988
1282 bullseye = (15.0 - course)*0.5235988
1283 delta = coord(-math.sin(angle), math.cos(angle))
1284 bigger = max(abs(delta.i), abs(delta.j))
1286 w = coord(0, 0); jw = coord(0, 0)
1287 ungridded = copy.copy(origin)
1288 # Loop to move a single torpedo
1289 for step in range(1, QUADSIZE*2):
1291 w = ungridded.snaptogrid()
1292 if not VALID_SECTOR(w.i, w.j):
1294 iquad=game.quad[w.i][w.j]
1295 tracktorpedo(origin, w, step, number, nburst, iquad)
1299 setwnd(message_window)
1300 if damaged(DSRSENS) and not game.condition=="docked":
1301 skip(1); # start new line after text track
1302 if iquad in (IHE, IHF): # Hit our ship
1304 prout(_("Torpedo hits %s.") % crmshp())
1305 hit = 700.0 + randreal(100) - \
1306 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1307 newcnd(); # we're blown out of dock
1308 # We may be displaced.
1309 if game.landed or game.condition=="docked":
1310 return hit # Cheat if on a planet
1311 ang = angle + 2.5*(randreal()-0.5)
1312 temp = math.fabs(math.sin(ang))
1313 if math.fabs(math.cos(ang)) > temp:
1314 temp = math.fabs(math.cos(ang))
1315 xx = -math.sin(ang)/temp
1316 yy = math.cos(ang)/temp
1317 jw.i = int(w.i+xx+0.5)
1318 jw.j = int(w.j+yy+0.5)
1319 if not VALID_SECTOR(jw.i, jw.j):
1321 if game.quad[jw.i][jw.j]==IHBLANK:
1324 if game.quad[jw.i][jw.j]!=IHDOT:
1325 # can't move into object
1330 elif iquad in (IHC, IHS, IHR, IHK): # Hit a regular enemy
1332 if iquad in (IHC, IHS) and withprob(0.05):
1333 prout(crmena(True, iquad, "sector", w) + _(" uses anti-photon device;"))
1334 prout(_(" torpedo neutralized."))
1336 for enemy in game.enemies:
1339 kp = math.fabs(enemy.kpower)
1340 h1 = 700.0 + randrange(100) - \
1341 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1345 if enemy.kpower < 0:
1349 if enemy.kpower == 0:
1352 proutn(crmena(True, iquad, "sector", w))
1353 # If enemy damaged but not destroyed, try to displace
1354 ang = angle + 2.5*(randreal()-0.5)
1355 temp = math.fabs(math.sin(ang))
1356 if math.fabs(math.cos(ang)) > temp:
1357 temp = math.fabs(math.cos(ang))
1358 xx = -math.sin(ang)/temp
1359 yy = math.cos(ang)/temp
1360 jw.i = int(w.i+xx+0.5)
1361 jw.j = int(w.j+yy+0.5)
1362 if not VALID_SECTOR(jw.i, jw.j):
1363 prout(_(" damaged but not destroyed."))
1365 if game.quad[jw.i][jw.j]==IHBLANK:
1366 prout(_(" buffeted into black hole."))
1367 deadkl(w, iquad, jw)
1369 if game.quad[jw.i][jw.j]!=IHDOT:
1370 # can't move into object
1371 prout(_(" damaged but not destroyed."))
1373 proutn(_(" damaged--"))
1377 elif iquad == IHB: # Hit a base
1379 prout(_("***STARBASE DESTROYED.."))
1380 game.state.baseq = filter(lambda x: x != game.quadrant, game.state.baseq)
1381 game.quad[w.i][w.j]=IHDOT
1382 game.base.invalidate()
1383 game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase -= 1
1384 game.state.chart[game.quadrant.i][game.quadrant.j].starbase -= 1
1385 game.state.basekl += 1
1388 elif iquad == IHP: # Hit a planet
1389 prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
1390 game.state.nplankl += 1
1391 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
1392 game.iplnet.pclass = "destroyed"
1394 game.plnet.invalidate()
1395 game.quad[w.i][w.j] = IHDOT
1397 # captain perishes on planet
1400 elif iquad == IHW: # Hit an inhabited world -- very bad!
1401 prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
1402 game.state.nworldkl += 1
1403 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
1404 game.iplnet.pclass = "destroyed"
1406 game.plnet.invalidate()
1407 game.quad[w.i][w.j] = IHDOT
1409 # captain perishes on planet
1411 prout(_("You have just destroyed an inhabited planet."))
1412 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1414 elif iquad == IHSTAR: # Hit a star
1418 prout(crmena(True, IHSTAR, "sector", w) + _(" unaffected by photon blast."))
1420 elif iquad == IHQUEST: # Hit a thingy
1421 if not (game.options & OPTION_THINGY) or withprob(0.3):
1423 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1425 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1427 proutn(_("Mr. Spock-"))
1428 prouts(_(" \"Fascinating!\""))
1432 # Stas Sergeev added the possibility that
1433 # you can shove the Thingy and piss it off.
1434 # It then becomes an enemy and may fire at you.
1438 elif iquad == IHBLANK: # Black hole
1440 prout(crmena(True, IHBLANK, "sector", w) + _(" swallows torpedo."))
1442 elif iquad == IHWEB: # hit the web
1444 prout(_("***Torpedo absorbed by Tholian web."))
1446 elif iquad == IHT: # Hit a Tholian
1447 h1 = 700.0 + randrange(100) - \
1448 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1451 game.quad[w.i][w.j] = IHDOT
1456 proutn(crmena(True, IHT, "sector", w))
1458 prout(_(" survives photon blast."))
1460 prout(_(" disappears."))
1461 game.tholian.move(None)
1462 game.quad[w.i][w.j] = IHWEB
1467 proutn("Don't know how to handle torpedo collision with ")
1468 proutn(crmena(True, iquad, "sector", w))
1472 if curwnd!=message_window:
1473 setwnd(message_window)
1475 game.quad[w.i][w.j]=IHDOT
1476 game.quad[jw.i][jw.j]=iquad
1477 prout(_(" displaced by blast to Sector %s ") % jw)
1478 for ll in range(len(game.enemies)):
1479 game.enemies[ll].kdist = game.enemies[ll].kavgd = (game.sector-game.enemies[ll].kloc).distance()
1480 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1483 prout(_("Torpedo missed."))
1487 "Critical-hit resolution."
1488 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1490 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1491 proutn(_("***CRITICAL HIT--"))
1492 # Select devices and cause damage
1494 for loop1 in range(ncrit):
1497 # Cheat to prevent shuttle damage unless on ship
1498 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1501 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1502 game.damage[j] += extradm
1504 for (i, j) in enumerate(cdam):
1506 if skipcount % 3 == 2 and i < len(cdam)-1:
1511 prout(_(" damaged."))
1512 if damaged(DSHIELD) and game.shldup:
1513 prout(_("***Shields knocked down."))
1516 def attack(torps_ok):
1517 # bad guy attacks us
1518 # torps_ok == False forces use of phasers in an attack
1519 # game could be over at this point, check
1522 attempt = False; ihurt = False;
1523 hitmax=0.0; hittot=0.0; chgfac=1.0
1526 prout("=== ATTACK!")
1527 # Tholian gets to move before attacking
1530 # if you have just entered the RNZ, you'll get a warning
1531 if game.neutz: # The one chance not to be attacked
1534 # commanders get a chance to tac-move towards you
1535 if (((game.quadrant in game.state.kcmdr or game.state.kscmdr==game.quadrant) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1537 # if no enemies remain after movement, we're done
1538 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1540 # set up partial hits if attack happens during shield status change
1541 pfac = 1.0/game.inshld
1543 chgfac = 0.25 + randreal(0.5)
1545 # message verbosity control
1546 if game.skill <= SKILL_FAIR:
1548 for enemy in game.enemies:
1549 if enemy.kpower < 0:
1550 continue; # too weak to attack
1551 # compute hit strength and diminish shield power
1553 # Increase chance of photon torpedos if docked or enemy energy is low
1554 if game.condition == "docked":
1556 if enemy.kpower < 500:
1558 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1560 # different enemies have different probabilities of throwing a torp
1561 usephasers = not torps_ok or \
1562 (enemy.type == IHK and r > 0.0005) or \
1563 (enemy.type==IHC and r > 0.015) or \
1564 (enemy.type==IHR and r > 0.3) or \
1565 (enemy.type==IHS and r > 0.07) or \
1566 (enemy.type==IHQUEST and r > 0.05)
1567 if usephasers: # Enemy uses phasers
1568 if game.condition == "docked":
1569 continue; # Don't waste the effort!
1570 attempt = True; # Attempt to attack
1571 dustfac = randreal(0.8, 0.85)
1572 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1573 enemy.kpower *= 0.75
1574 else: # Enemy uses photon torpedo
1575 # We should be able to make the bearing() method work here
1576 course = 1.90985*math.atan2(game.sector.j-enemy.kloc.j, enemy.kloc.i-game.sector.i)
1578 proutn(_("***TORPEDO INCOMING"))
1579 if not damaged(DSRSENS):
1580 proutn(_(" From ") + crmena(False, enemy.type, where, enemy.kloc))
1583 dispersion = (randreal()+randreal())*0.5 - 0.5
1584 dispersion += 0.002*enemy.kpower*dispersion
1585 hit = torpedo(enemy.kloc, course, dispersion, number=1, nburst=1)
1586 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1587 finish(FWON); # Klingons did themselves in!
1588 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.alldone:
1589 return # Supernova or finished
1592 # incoming phaser or torpedo, shields may dissipate it
1593 if game.shldup or game.shldchg or game.condition=="docked":
1594 # shields will take hits
1595 propor = pfac * game.shield
1596 if game.condition =="docked":
1600 hitsh = propor*chgfac*hit+1.0
1602 if absorb > game.shield:
1603 absorb = game.shield
1604 game.shield -= absorb
1606 # taking a hit blasts us out of a starbase dock
1607 if game.condition == "docked":
1609 # but the shields may take care of it
1610 if propor > 0.1 and hit < 0.005*game.energy:
1612 # hit from this opponent got through shields, so take damage
1614 proutn(_("%d unit hit") % int(hit))
1615 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1616 proutn(_(" on the ") + crmshp())
1617 if not damaged(DSRSENS) and usephasers:
1618 prout(_(" from ") + crmena(False, enemy.type, where, enemy.kloc))
1620 # Decide if hit is critical
1626 if game.energy <= 0:
1627 # Returning home upon your shield, not with it...
1630 if not attempt and game.condition == "docked":
1631 prout(_("***Enemies decide against attacking your ship."))
1632 percent = 100.0*pfac*game.shield+0.5
1634 # Shields fully protect ship
1635 proutn(_("Enemy attack reduces shield strength to "))
1637 # Emit message if starship suffered hit(s)
1639 proutn(_("Energy left %2d shields ") % int(game.energy))
1642 elif not damaged(DSHIELD):
1645 proutn(_("damaged, "))
1646 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1647 # Check if anyone was hurt
1648 if hitmax >= 200 or hittot >= 500:
1649 icas = randrange(int(hittot * 0.015))
1652 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1653 prout(_(" in that last attack.\""))
1655 game.state.crew -= icas
1656 # After attack, reset average distance to enemies
1657 for enemy in game.enemies:
1658 enemy.kavgd = enemy.kdist
1659 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1662 def deadkl(w, type, mv):
1663 "Kill a Klingon, Tholian, Romulan, or Thingy."
1664 # Added mv to allow enemy to "move" before dying
1665 proutn(crmena(True, type, "sector", mv))
1666 # Decide what kind of enemy it is and update appropriately
1668 # chalk up a Romulan
1669 game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans -= 1
1671 game.state.nromrem -= 1
1675 elif type == IHQUEST:
1680 # Some type of a Klingon
1681 game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
1684 game.state.kcmdr.remove(game.quadrant)
1686 if game.state.kcmdr:
1687 schedule(FTBEAM, expran(1.0*game.incom/len(game.state.kcmdr)))
1688 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1691 game.state.remkl -= 1
1693 game.state.nscrem -= 1
1694 game.state.kscmdr.invalidate()
1699 # For each kind of enemy, finish message to player
1700 prout(_(" destroyed."))
1701 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1704 # Remove enemy ship from arrays describing local conditions
1705 for e in game.enemies:
1712 "Return None if target is invalid, otherwise return a course angle."
1713 if not VALID_SECTOR(w.i, w.j):
1717 # FIXME: C code this was translated from is wacky -- why the sign reversal?
1718 delta.j = (w.j - game.sector.j);
1719 delta.i = (game.sector.i - w.i);
1720 if delta == coord(0, 0):
1722 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1723 prout(_(" I recommend an immediate review of"))
1724 prout(_(" the Captain's psychological profile.\""))
1727 return delta.bearing()
1730 "Launch photon torpedo."
1733 if damaged(DPHOTON):
1734 prout(_("Photon tubes damaged."))
1738 prout(_("No torpedoes left."))
1741 # First, get torpedo count
1744 if scanner.token == "IHALPHA":
1747 elif scanner.token == "IHEOL" or not scanner.waiting():
1748 prout(_("%d torpedoes left.") % game.torps)
1750 proutn(_("Number of torpedoes to fire- "))
1751 continue # Go back around to get a number
1752 else: # key == "IHREAL"
1754 if n <= 0: # abort command
1759 prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
1762 scanner.chew() # User requested more torps than available
1763 continue # Go back around
1764 break # All is good, go to next stage
1768 key = scanner.next()
1769 if i==0 and key == "IHEOL":
1770 break; # no coordinate waiting, we will try prompting
1771 if i==1 and key == "IHEOL":
1772 # direct all torpedoes at one target
1774 target.append(target[0])
1775 course.append(course[0])
1778 scanner.push(scanner.token)
1779 target.append(scanner.getcoord())
1780 if target[-1] == None:
1782 course.append(targetcheck(target[-1]))
1783 if course[-1] == None:
1786 if len(target) == 0:
1787 # prompt for each one
1789 proutn(_("Target sector for torpedo number %d- ") % (i+1))
1791 target.append(scanner.getcoord())
1792 if target[-1] == None:
1794 course.append(targetcheck(target[-1]))
1795 if course[-1] == None:
1798 # Loop for moving <n> torpedoes
1800 if game.condition != "docked":
1802 dispersion = (randreal()+randreal())*0.5 -0.5
1803 if math.fabs(dispersion) >= 0.47:
1805 dispersion *= randreal(1.2, 2.2)
1807 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1809 prouts(_("***TORPEDO MISFIRES."))
1812 prout(_(" Remainder of burst aborted."))
1814 prout(_("***Photon tubes damaged by misfire."))
1815 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1817 if game.shldup or game.condition == "docked":
1818 dispersion *= 1.0 + 0.0001*game.shield
1819 torpedo(game.sector, course[i], dispersion, number=i, nburst=n)
1820 if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
1822 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1826 "Check for phasers overheating."
1828 checkburn = (rpow-1500.0)*0.00038
1829 if withprob(checkburn):
1830 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1831 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1833 def checkshctrl(rpow):
1834 "Check shield control."
1837 prout(_("Shields lowered."))
1839 # Something bad has happened
1840 prouts(_("***RED ALERT! RED ALERT!"))
1842 hit = rpow*game.shield/game.inshld
1843 game.energy -= rpow+hit*0.8
1844 game.shield -= hit*0.2
1845 if game.energy <= 0.0:
1846 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1851 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1853 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1854 icas = randrange(int(hit*0.012))
1859 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1860 prout(_(" %d casualties so far.\"") % icas)
1862 game.state.crew -= icas
1864 prout(_("Phaser energy dispersed by shields."))
1865 prout(_("Enemy unaffected."))
1870 "Register a phaser hit on Klingons and Romulans."
1871 nenhr2 = len(game.enemies); kk=0
1874 for (k, wham) in enumerate(hits):
1877 dustfac = randreal(0.9, 1.0)
1878 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1879 kpini = game.enemies[kk].kpower
1880 kp = math.fabs(kpini)
1881 if PHASEFAC*hit < kp:
1883 if game.enemies[kk].kpower < 0:
1884 game.enemies[kk].kpower -= -kp
1886 game.enemies[kk].kpower -= kp
1887 kpow = game.enemies[kk].kpower
1888 w = game.enemies[kk].kloc
1890 if not damaged(DSRSENS):
1892 proutn(_("%d unit hit on ") % int(hit))
1894 proutn(_("Very small hit on "))
1895 ienm = game.quad[w.i][w.j]
1898 proutn(crmena(False, ienm, "sector", w))
1902 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1906 kk -= 1 # don't do the increment
1908 else: # decide whether or not to emasculate klingon
1909 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
1910 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
1911 prout(_(" has just lost its firepower.\""))
1912 game.enemies[kk].kpower = -kpow
1917 "Fire phasers at bad guys."
1919 kz = 0; k = 1; irec=0 # Cheating inhibitor
1920 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
1924 # SR sensors and Computer are needed for automode
1925 if damaged(DSRSENS) or damaged(DCOMPTR):
1927 if game.condition == "docked":
1928 prout(_("Phasers can't be fired through base shields."))
1931 if damaged(DPHASER):
1932 prout(_("Phaser control damaged."))
1936 if damaged(DSHCTRL):
1937 prout(_("High speed shield control damaged."))
1940 if game.energy <= 200.0:
1941 prout(_("Insufficient energy to activate high-speed shield control."))
1944 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
1946 # Original code so convoluted, I re-did it all
1947 # (That was Tom Almy talking about the C code, I think -- ESR)
1948 while automode=="NOTSET":
1950 if key == "IHALPHA":
1951 if scanner.sees("manual"):
1952 if len(game.enemies)==0:
1953 prout(_("There is no enemy present to select."))
1956 automode="AUTOMATIC"
1959 key = scanner.next()
1960 elif scanner.sees("automatic"):
1961 if (not itarg) and len(game.enemies) != 0:
1962 automode = "FORCEMAN"
1964 if len(game.enemies)==0:
1965 prout(_("Energy will be expended into space."))
1966 automode = "AUTOMATIC"
1967 key = scanner.next()
1968 elif scanner.sees("no"):
1973 elif key == "IHREAL":
1974 if len(game.enemies)==0:
1975 prout(_("Energy will be expended into space."))
1976 automode = "AUTOMATIC"
1978 automode = "FORCEMAN"
1980 automode = "AUTOMATIC"
1983 if len(game.enemies)==0:
1984 prout(_("Energy will be expended into space."))
1985 automode = "AUTOMATIC"
1987 automode = "FORCEMAN"
1989 proutn(_("Manual or automatic? "))
1994 if automode == "AUTOMATIC":
1995 if key == "IHALPHA" and scanner.sees("no"):
1997 key = scanner.next()
1998 if key != "IHREAL" and len(game.enemies) != 0:
1999 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2004 for i in range(len(game.enemies)):
2005 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2007 proutn(_("%d units required. ") % irec)
2009 proutn(_("Units to fire= "))
2010 key = scanner.next()
2015 proutn(_("Energy available= %.2f") % avail)
2018 if not rpow > avail:
2025 if key == "IHALPHA" and scanner.sees("no"):
2028 game.energy -= 200; # Go and do it!
2029 if checkshctrl(rpow):
2034 if len(game.enemies):
2037 for i in range(len(game.enemies)):
2041 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2042 over = randreal(1.01, 1.06) * hits[i]
2044 powrem -= hits[i] + over
2045 if powrem <= 0 and temp < hits[i]:
2054 if extra > 0 and not game.alldone:
2056 proutn(_("*** Tholian web absorbs "))
2057 if len(game.enemies)>0:
2058 proutn(_("excess "))
2059 prout(_("phaser energy."))
2061 prout(_("%d expended on empty space.") % int(extra))
2062 elif automode == "FORCEMAN":
2065 if damaged(DCOMPTR):
2066 prout(_("Battle computer damaged, manual fire only."))
2069 prouts(_("---WORKING---"))
2071 prout(_("Short-range-sensors-damaged"))
2072 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2073 prout(_("Manual-fire-must-be-used"))
2075 elif automode == "MANUAL":
2077 for k in range(len(game.enemies)):
2078 aim = game.enemies[k].kloc
2079 ienm = game.quad[aim.i][aim.j]
2081 proutn(_("Energy available= %.2f") % (avail-0.006))
2085 if damaged(DSRSENS) and \
2086 not game.sector.distance(aim)<2**0.5 and ienm in (IHC, IHS):
2087 prout(cramen(ienm) + _(" can't be located without short range scan."))
2090 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2095 if itarg and k > kz:
2096 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2099 if not damaged(DCOMPTR):
2104 proutn(_("units to fire at %s- ") % crmena(False, ienm, "sector", aim))
2105 key = scanner.next()
2106 if key == "IHALPHA" and scanner.sees("no"):
2108 key = scanner.next()
2110 if key == "IHALPHA":
2114 if k==1: # Let me say I'm baffled by this
2117 if scanner.real < 0:
2121 hits[k] = scanner.real
2122 rpow += scanner.real
2123 # If total requested is too much, inform and start over
2125 prout(_("Available energy exceeded -- try again."))
2128 key = scanner.next(); # scan for next value
2131 # zero energy -- abort
2134 if key == "IHALPHA" and scanner.sees("no"):
2139 game.energy -= 200.0
2140 if checkshctrl(rpow):
2144 # Say shield raised or malfunction, if necessary
2151 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2152 prouts(_(" CLICK CLICK POP . . ."))
2153 prout(_(" No response, sir!"))
2156 prout(_("Shields raised."))
2161 # Code from events,c begins here.
2163 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2164 # event of each type active at any given time. Mostly these means we can
2165 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2166 # BSD Trek, from which we swiped the idea, can have up to 5.
2168 def unschedule(evtype):
2169 "Remove an event from the schedule."
2170 game.future[evtype].date = FOREVER
2171 return game.future[evtype]
2173 def is_scheduled(evtype):
2174 "Is an event of specified type scheduled."
2175 return game.future[evtype].date != FOREVER
2177 def scheduled(evtype):
2178 "When will this event happen?"
2179 return game.future[evtype].date
2181 def schedule(evtype, offset):
2182 "Schedule an event of specified type."
2183 game.future[evtype].date = game.state.date + offset
2184 return game.future[evtype]
2186 def postpone(evtype, offset):
2187 "Postpone a scheduled event."
2188 game.future[evtype].date += offset
2191 "Rest period is interrupted by event."
2194 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2196 game.resting = False
2202 "Run through the event queue looking for things to do."
2204 fintim = game.state.date + game.optime; yank=0
2205 ictbeam = False; istract = False
2206 w = coord(); hold = coord()
2207 ev = event(); ev2 = event()
2209 def tractorbeam(yank):
2210 "Tractor-beaming cases merge here."
2212 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2214 prout("***" + crmshp() + _(" caught in long range tractor beam--"))
2215 # If Kirk & Co. screwing around on planet, handle
2216 atover(True) # atover(true) is Grab
2219 if game.icraft: # Caught in Galileo?
2222 # Check to see if shuttle is aboard
2223 if game.iscraft == "offship":
2226 prout(_("Galileo, left on the planet surface, is captured"))
2227 prout(_("by aliens and made into a flying McDonald's."))
2228 game.damage[DSHUTTL] = -10
2229 game.iscraft = "removed"
2231 prout(_("Galileo, left on the planet surface, is well hidden."))
2233 game.quadrant = game.state.kscmdr
2235 game.quadrant = game.state.kcmdr[i]
2236 game.sector = randplace(QUADSIZE)
2237 prout(crmshp() + _(" is pulled to Quadrant %s, Sector %s") \
2238 % (game.quadrant, game.sector))
2240 prout(_("(Remainder of rest/repair period cancelled.)"))
2241 game.resting = False
2243 if not damaged(DSHIELD) and game.shield > 0:
2244 doshield(shraise=True) # raise shields
2245 game.shldchg = False
2247 prout(_("(Shields not currently useable.)"))
2249 # Adjust finish time to time of tractor beaming
2250 fintim = game.state.date+game.optime
2251 attack(torps_ok=False)
2252 if not game.state.kcmdr:
2255 schedule(FTBEAM, game.optime+expran(1.5*game.intime/len(game.state.kcmdr)))
2258 "Code merges here for any commander destroying a starbase."
2259 # Not perfect, but will have to do
2260 # Handle case where base is in same quadrant as starship
2261 if game.battle == game.quadrant:
2262 game.state.chart[game.battle.i][game.battle.j].starbase = False
2263 game.quad[game.base.i][game.base.j] = IHDOT
2264 game.base.invalidate()
2267 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2268 elif game.state.baseq and communicating():
2269 # Get word via subspace radio
2272 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2273 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2275 prout(_("the Klingon Super-Commander"))
2277 prout(_("a Klingon Commander"))
2278 game.state.chart[game.battle.i][game.battle.j].starbase = False
2279 # Remove Starbase from galaxy
2280 game.state.galaxy[game.battle.i][game.battle.j].starbase = False
2281 game.state.baseq = filter(lambda x: x != game.battle, game.state.baseq)
2283 # reinstate a commander's base attack
2287 game.battle.invalidate()
2289 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2290 for i in range(1, NEVENTS):
2291 if i == FSNOVA: proutn("=== Supernova ")
2292 elif i == FTBEAM: proutn("=== T Beam ")
2293 elif i == FSNAP: proutn("=== Snapshot ")
2294 elif i == FBATTAK: proutn("=== Base Attack ")
2295 elif i == FCDBAS: proutn("=== Base Destroy ")
2296 elif i == FSCMOVE: proutn("=== SC Move ")
2297 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2298 elif i == FDSPROB: proutn("=== Probe Move ")
2299 elif i == FDISTR: proutn("=== Distress Call ")
2300 elif i == FENSLV: proutn("=== Enslavement ")
2301 elif i == FREPRO: proutn("=== Klingon Build ")
2303 prout("%.2f" % (scheduled(i)))
2306 radio_was_broken = damaged(DRADIO)
2309 # Select earliest extraneous event, evcode==0 if no events
2314 for l in range(1, NEVENTS):
2315 if game.future[l].date < datemin:
2318 prout("== Event %d fires" % evcode)
2319 datemin = game.future[l].date
2320 xtime = datemin-game.state.date
2321 game.state.date = datemin
2322 # Decrement Federation resources and recompute remaining time
2323 game.state.remres -= (game.state.remkl+4*len(game.state.kcmdr))*xtime
2325 if game.state.remtime <=0:
2328 # Any crew left alive?
2329 if game.state.crew <=0:
2332 # Is life support adequate?
2333 if damaged(DLIFSUP) and game.condition != "docked":
2334 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2337 game.lsupres -= xtime
2338 if game.damage[DLIFSUP] <= xtime:
2339 game.lsupres = game.inlsr
2342 if game.condition == "docked":
2343 repair /= game.docfac
2344 # Don't fix Deathray here
2345 for l in range(NDEVICES):
2346 if game.damage[l] > 0.0 and l != DDRAY:
2347 if game.damage[l]-repair > 0.0:
2348 game.damage[l] -= repair
2350 game.damage[l] = 0.0
2351 # If radio repaired, update star chart and attack reports
2352 if radio_was_broken and not damaged(DRADIO):
2353 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2354 prout(_(" surveillance reports are coming in."))
2356 if not game.iseenit:
2360 prout(_(" The star chart is now up to date.\""))
2362 # Cause extraneous event EVCODE to occur
2363 game.optime -= xtime
2364 if evcode == FSNOVA: # Supernova
2367 schedule(FSNOVA, expran(0.5*game.intime))
2368 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2370 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2371 if game.state.nscrem == 0 or \
2372 ictbeam or istract or \
2373 game.condition=="docked" or game.isatb==1 or game.iscate:
2375 if game.ientesc or \
2376 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2377 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2378 (damaged(DSHIELD) and \
2379 (game.energy < 2500 or damaged(DPHASER)) and \
2380 (game.torps < 5 or damaged(DPHOTON))):
2382 istract = ictbeam = True
2383 tractorbeam((game.state.kscmdr-game.quadrant).distance())
2386 elif evcode == FTBEAM: # Tractor beam
2387 if not game.state.kcmdr:
2390 i = randrange(len(game.state.kcmdr))
2391 yank = (game.state.kcmdr[i]-game.quadrant).distance()
2392 if istract or game.condition == "docked" or yank == 0:
2393 # Drats! Have to reschedule
2395 game.optime + expran(1.5*game.intime/len(game.state.kcmdr)))
2399 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2400 game.snapsht = copy.deepcopy(game.state)
2401 game.state.snap = True
2402 schedule(FSNAP, expran(0.5 * game.intime))
2403 elif evcode == FBATTAK: # Commander attacks starbase
2404 if not game.state.kcmdr or not game.state.baseq:
2410 for ibq in game.state.baseq:
2411 for cmdr in game.state.kcmdr:
2412 if ibq == cmdr and ibq != game.quadrant and ibq != game.state.kscmdr:
2415 # no match found -- try later
2416 schedule(FBATTAK, expran(0.3*game.intime))
2421 # commander + starbase combination found -- launch attack
2423 schedule(FCDBAS, randreal(1.0, 4.0))
2424 if game.isatb: # extra time if SC already attacking
2425 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2426 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2427 game.iseenit = False
2428 if not communicating():
2429 continue # No warning :-(
2433 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2434 prout(_(" reports that it is under attack and that it can"))
2435 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2438 elif evcode == FSCDBAS: # Supercommander destroys base
2441 if not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].starbase:
2442 continue # WAS RETURN!
2444 game.battle = game.state.kscmdr
2446 elif evcode == FCDBAS: # Commander succeeds in destroying base
2449 if not game.state.baseq() \
2450 or not game.state.galaxy[game.battle.i][game.battle.j].starbase:
2451 game.battle.invalidate()
2453 # find the lucky pair
2454 for cmdr in game.state.kcmdr:
2455 if cmdr == game.battle:
2458 # No action to take after all
2461 elif evcode == FSCMOVE: # Supercommander moves
2462 schedule(FSCMOVE, 0.2777)
2463 if not game.ientesc and not istract and game.isatb != 1 and \
2464 (not game.iscate or not game.justin):
2466 elif evcode == FDSPROB: # Move deep space probe
2467 schedule(FDSPROB, 0.01)
2468 game.probex += game.probeinx
2469 game.probey += game.probeiny
2470 i = (int)(game.probex/QUADSIZE +0.05)
2471 j = (int)(game.probey/QUADSIZE + 0.05)
2472 if game.probec.i != i or game.probec.j != j:
2475 if not VALID_QUADRANT(i, j) or \
2476 game.state.galaxy[game.probec.i][game.probec.j].supernova:
2477 # Left galaxy or ran into supernova
2481 proutn(_("Lt. Uhura- \"The deep space probe "))
2482 if not VALID_QUADRANT(j, i):
2483 proutn(_("has left the galaxy"))
2485 proutn(_("is no longer transmitting"))
2489 if not communicating():
2492 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2493 pdest = game.state.galaxy[game.probec.i][game.probec.j]
2494 # Update star chart if Radio is working or have access to radio
2496 chp = game.state.chart[game.probec.i][game.probec.j]
2497 chp.klingons = pdest.klingons
2498 chp.starbase = pdest.starbase
2499 chp.stars = pdest.stars
2500 pdest.charted = True
2501 game.proben -= 1 # One less to travel
2502 if game.proben == 0 and game.isarmed and pdest.stars:
2503 # lets blow the sucker!
2504 supernova(game.probec)
2506 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2508 elif evcode == FDISTR: # inhabited system issues distress call
2510 # try a whole bunch of times to find something suitable
2511 for i in range(100):
2512 # need a quadrant which is not the current one,
2513 # which has some stars which are inhabited and
2514 # not already under attack, which is not
2515 # supernova'ed, and which has some Klingons in it
2516 w = randplace(GALSIZE)
2517 q = game.state.galaxy[w.i][w.j]
2518 if not (game.quadrant == w or q.planet == None or \
2519 not q.planet.inhabited or \
2520 q.supernova or q.status!="secure" or q.klingons<=0):
2523 # can't seem to find one; ignore this call
2525 prout("=== Couldn't find location for distress event.")
2527 # got one!! Schedule its enslavement
2528 ev = schedule(FENSLV, expran(game.intime))
2530 q.status = "distressed"
2531 # tell the captain about it if we can
2533 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2535 prout(_("by a Klingon invasion fleet."))
2538 elif evcode == FENSLV: # starsystem is enslaved
2539 ev = unschedule(FENSLV)
2540 # see if current distress call still active
2541 q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
2545 q.status = "enslaved"
2547 # play stork and schedule the first baby
2548 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2549 ev2.quadrant = ev.quadrant
2551 # report the disaster if we can
2553 prout(_("Uhura- We've lost contact with starsystem %s") % \
2555 prout(_("in Quadrant %s.\n") % ev.quadrant)
2556 elif evcode == FREPRO: # Klingon reproduces
2557 # If we ever switch to a real event queue, we'll need to
2558 # explicitly retrieve and restore the x and y.
2559 ev = schedule(FREPRO, expran(1.0 * game.intime))
2560 # see if current distress call still active
2561 q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
2565 if game.state.remkl >=MAXKLGAME:
2566 continue # full right now
2567 # reproduce one Klingon
2569 if game.klhere >= MAXKLQUAD:
2571 # this quadrant not ok, pick an adjacent one
2572 for i in range(w.i - 1, w.i + 2):
2573 for j in range(w.j - 1, w.j + 2):
2574 if not VALID_QUADRANT(i, j):
2576 q = game.state.galaxy[w.i][w.j]
2577 # check for this quad ok (not full & no snova)
2578 if q.klingons >= MAXKLQUAD or q.supernova:
2582 continue # search for eligible quadrant failed
2586 game.state.remkl += 1
2588 if game.quadrant == w:
2590 game.enemies.append(newkling())
2591 # recompute time left
2593 # report the disaster if we can
2595 if game.quadrant == w:
2596 prout(_("Spock- sensors indicate the Klingons have"))
2597 prout(_("launched a warship from %s.") % q.planet)
2599 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2600 if q.planet != None:
2601 proutn(_("near %s") % q.planet)
2602 prout(_("in Quadrant %s.") % w)
2608 key = scanner.next()
2611 proutn(_("How long? "))
2616 origTime = delay = scanner.real
2619 if delay >= game.state.remtime or len(game.enemies) != 0:
2620 proutn(_("Are you sure? "))
2623 # Alternate resting periods (events) with attacks
2627 game.resting = False
2628 if not game.resting:
2629 prout(_("%d stardates left.") % int(game.state.remtime))
2631 temp = game.optime = delay
2632 if len(game.enemies):
2633 rtime = randreal(1.0, 2.0)
2637 if game.optime < delay:
2638 attack(torps_ok=False)
2646 # Repair Deathray if long rest at starbase
2647 if origTime-delay >= 9.99 and game.condition == "docked":
2648 game.damage[DDRAY] = 0.0
2649 # leave if quadrant supernovas
2650 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2652 game.resting = False
2657 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2658 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2660 # Wow! We've supernova'ed
2661 supernova(game.quadrant)
2663 # handle initial nova
2664 game.quad[nov.i][nov.j] = IHDOT
2665 prout(crmena(False, IHSTAR, "sector", nov) + _(" novas."))
2666 game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
2667 game.state.starkl += 1
2668 # Set up queue to recursively trigger adjacent stars
2674 for offset.i in range(-1, 1+1):
2675 for offset.j in range(-1, 1+1):
2676 if offset.j==0 and offset.i==0:
2678 neighbor = start + offset
2679 if not VALID_SECTOR(neighbor.j, neighbor.i):
2681 iquad = game.quad[neighbor.i][neighbor.j]
2682 # Empty space ends reaction
2683 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2685 elif iquad == IHSTAR: # Affect another star
2687 # This star supernovas
2688 supernova(game.quadrant)
2691 hits.append(neighbor)
2692 game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
2693 game.state.starkl += 1
2694 proutn(crmena(True, IHSTAR, "sector", neighbor))
2696 game.quad[neighbor.i][neighbor.j] = IHDOT
2698 elif iquad in (IHP, IHW): # Destroy planet
2699 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
2701 game.state.nplankl += 1
2703 game.state.worldkl += 1
2704 prout(crmena(True, IHB, "sector", neighbor) + _(" destroyed."))
2705 game.iplnet.pclass = "destroyed"
2707 game.plnet.invalidate()
2711 game.quad[neighbor.i][neighbor.j] = IHDOT
2712 elif iquad == IHB: # Destroy base
2713 game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase = False
2714 game.state.baseq = filter(lambda x: x!= game.quadrant, game.state.baseq)
2715 game.base.invalidate()
2716 game.state.basekl += 1
2718 prout(crmena(True, IHB, "sector", neighbor) + _(" destroyed."))
2719 game.quad[neighbor.i][neighbor.j] = IHDOT
2720 elif iquad in (IHE, IHF): # Buffet ship
2721 prout(_("***Starship buffeted by nova."))
2723 if game.shield >= 2000.0:
2724 game.shield -= 2000.0
2726 diff = 2000.0 - game.shield
2730 prout(_("***Shields knocked out."))
2731 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2733 game.energy -= 2000.0
2734 if game.energy <= 0:
2737 # add in course nova contributes to kicking starship
2738 bump += (game.sector-hits[mm]).sgn()
2739 elif iquad == IHK: # kill klingon
2740 deadkl(neighbor, iquad, neighbor)
2741 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2742 for ll in range(len(game.enemies)):
2743 if game.enemies[ll].kloc == neighbor:
2745 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2746 if game.enemies[ll].kpower <= 0.0:
2747 deadkl(neighbor, iquad, neighbor)
2749 newc = neighbor + neighbor - hits[mm]
2750 proutn(crmena(True, iquad, "sector", neighbor) + _(" damaged"))
2751 if not VALID_SECTOR(newc.i, newc.j):
2752 # can't leave quadrant
2755 iquad1 = game.quad[newc.i][newc.j]
2756 if iquad1 == IHBLANK:
2757 proutn(_(", blasted into ") + crmena(False, IHBLANK, "sector", newc))
2759 deadkl(neighbor, iquad, newc)
2762 # can't move into something else
2765 proutn(_(", buffeted to Sector %s") % newc)
2766 game.quad[neighbor.i][neighbor.j] = IHDOT
2767 game.quad[newc.i][newc.j] = iquad
2768 game.enemies[ll].move(newc)
2769 # Starship affected by nova -- kick it away.
2770 game.dist = kount*0.1
2771 game.direc = course[3*(bump.i+1)+bump.j+2]
2772 if game.direc == 0.0:
2774 if game.dist == 0.0:
2776 game.optime = 10.0*game.dist/16.0
2778 prout(_("Force of nova displaces starship."))
2779 imove(novapush=True)
2780 game.optime = 10.0*game.dist/16.0
2784 "Star goes supernova."
2789 # Scheduled supernova -- select star at random.
2792 for nq.i in range(GALSIZE):
2793 for nq.j in range(GALSIZE):
2794 stars += game.state.galaxy[nq.i][nq.j].stars
2796 return # nothing to supernova exists
2797 num = randrange(stars) + 1
2798 for nq.i in range(GALSIZE):
2799 for nq.j in range(GALSIZE):
2800 num -= game.state.galaxy[nq.i][nq.j].stars
2806 proutn("=== Super nova here?")
2809 if not nq == game.quadrant or game.justin:
2810 # it isn't here, or we just entered (treat as enroute)
2813 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2814 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2817 # we are in the quadrant!
2818 num = randrange(game.state.galaxy[nq.i][nq.j].stars) + 1
2819 for ns.i in range(QUADSIZE):
2820 for ns.j in range(QUADSIZE):
2821 if game.quad[ns.i][ns.j]==IHSTAR:
2828 prouts(_("***RED ALERT! RED ALERT!"))
2830 prout(_("***Incipient supernova detected at Sector %s") % ns)
2831 if (ns.i-game.sector.i)**2 + (ns.j-game.sector.j)**2 <= 2.1:
2832 proutn(_("Emergency override attempts t"))
2833 prouts("***************")
2837 # destroy any Klingons in supernovaed quadrant
2838 kldead = game.state.galaxy[nq.i][nq.j].klingons
2839 game.state.galaxy[nq.i][nq.j].klingons = 0
2840 if nq == game.state.kscmdr:
2841 # did in the Supercommander!
2842 game.state.nscrem = game.state.kscmdr.i = game.state.kscmdr.j = game.isatb = 0
2846 survivors = filter(lambda w: w != nq, game.state.kcmdr)
2847 comkills = len(game.state.kcmdr) - len(survivors)
2848 game.state.kcmdr = survivors
2850 if not game.state.kcmdr:
2852 game.state.remkl -= kldead
2853 # destroy Romulans and planets in supernovaed quadrant
2854 nrmdead = game.state.galaxy[nq.i][nq.j].romulans
2855 game.state.galaxy[nq.i][nq.j].romulans = 0
2856 game.state.nromrem -= nrmdead
2858 for loop in range(game.inplan):
2859 if game.state.planets[loop].quadrant == nq:
2860 game.state.planets[loop].pclass = "destroyed"
2862 # Destroy any base in supernovaed quadrant
2863 game.state.baseq = filter(lambda x: x != nq, game.state.baseq)
2864 # If starship caused supernova, tally up destruction
2866 game.state.starkl += game.state.galaxy[nq.i][nq.j].stars
2867 game.state.basekl += game.state.galaxy[nq.i][nq.j].starbase
2868 game.state.nplankl += npdead
2869 # mark supernova in galaxy and in star chart
2870 if game.quadrant == nq or communicating():
2871 game.state.galaxy[nq.i][nq.j].supernova = True
2872 # If supernova destroys last Klingons give special message
2873 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0 and not nq == game.quadrant:
2876 prout(_("Lucky you!"))
2877 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
2880 # if some Klingons remain, continue or die in supernova
2885 # Code from finish.c ends here.
2888 "Self-destruct maneuver. Finish with a BANG!"
2890 if damaged(DCOMPTR):
2891 prout(_("Computer damaged; cannot execute destruct sequence."))
2893 prouts(_("---WORKING---")); skip(1)
2894 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
2895 prouts(" 10"); skip(1)
2896 prouts(" 9"); skip(1)
2897 prouts(" 8"); skip(1)
2898 prouts(" 7"); skip(1)
2899 prouts(" 6"); skip(1)
2901 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
2903 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
2905 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
2909 if game.passwd != scanner.token:
2910 prouts(_("PASSWORD-REJECTED;"))
2912 prouts(_("CONTINUITY-EFFECTED"))
2915 prouts(_("PASSWORD-ACCEPTED")); skip(1)
2916 prouts(" 5"); skip(1)
2917 prouts(" 4"); skip(1)
2918 prouts(" 3"); skip(1)
2919 prouts(" 2"); skip(1)
2920 prouts(" 1"); skip(1)
2922 prouts(_("GOODBYE-CRUEL-WORLD"))
2930 prouts(_("********* Entropy of %s maximized *********") % crmshp())
2934 if len(game.enemies) != 0:
2935 whammo = 25.0 * game.energy
2937 while l <= len(game.enemies):
2938 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
2939 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.i][game.enemies[l].kloc.j], game.enemies[l].kloc)
2944 "Compute our rate of kils over time."
2945 elapsed = game.state.date - game.indate
2946 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
2949 starting = (game.inkling + game.incom + game.inscom)
2950 remaining = (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)
2951 return (starting - remaining)/elapsed
2955 badpt = 5.0*game.state.starkl + \
2957 10.0*game.state.nplankl + \
2958 300*game.state.nworldkl + \
2960 100.0*game.state.basekl +\
2962 if game.ship == IHF:
2964 elif game.ship == None:
2969 # end the game, with appropriate notfications
2973 prout(_("It is stardate %.1f.") % game.state.date)
2975 if ifin == FWON: # Game has been won
2976 if game.state.nromrem != 0:
2977 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
2980 prout(_("You have smashed the Klingon invasion fleet and saved"))
2981 prout(_("the Federation."))
2986 badpt = 0.0 # Close enough!
2987 # killsPerDate >= RateMax
2988 if game.state.date-game.indate < 5.0 or \
2989 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
2991 prout(_("In fact, you have done so well that Starfleet Command"))
2992 if game.skill == SKILL_NOVICE:
2993 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
2994 elif game.skill == SKILL_FAIR:
2995 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
2996 elif game.skill == SKILL_GOOD:
2997 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
2998 elif game.skill == SKILL_EXPERT:
2999 prout(_("promotes you to Commodore Emeritus."))
3001 prout(_("Now that you think you're really good, try playing"))
3002 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3003 elif game.skill == SKILL_EMERITUS:
3005 proutn(_("Computer- "))
3006 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3008 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3010 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3012 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3014 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3016 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3018 prout(_("Now you can retire and write your own Star Trek game!"))
3020 elif game.skill >= SKILL_EXPERT:
3021 if game.thawed and not idebug:
3022 prout(_("You cannot get a citation, so..."))
3024 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3028 # Only grant long life if alive (original didn't!)
3030 prout(_("LIVE LONG AND PROSPER."))
3035 elif ifin == FDEPLETE: # Federation Resources Depleted
3036 prout(_("Your time has run out and the Federation has been"))
3037 prout(_("conquered. Your starship is now Klingon property,"))
3038 prout(_("and you are put on trial as a war criminal. On the"))
3039 proutn(_("basis of your record, you are "))
3040 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3041 prout(_("acquitted."))
3043 prout(_("LIVE LONG AND PROSPER."))
3045 prout(_("found guilty and"))
3046 prout(_("sentenced to death by slow torture."))
3050 elif ifin == FLIFESUP:
3051 prout(_("Your life support reserves have run out, and"))
3052 prout(_("you die of thirst, starvation, and asphyxiation."))
3053 prout(_("Your starship is a derelict in space."))
3055 prout(_("Your energy supply is exhausted."))
3057 prout(_("Your starship is a derelict in space."))
3058 elif ifin == FBATTLE:
3059 prout(_("The %s has been destroyed in battle.") % crmshp())
3061 prout(_("Dulce et decorum est pro patria mori."))
3063 prout(_("You have made three attempts to cross the negative energy"))
3064 prout(_("barrier which surrounds the galaxy."))
3066 prout(_("Your navigation is abominable."))
3069 prout(_("Your starship has been destroyed by a nova."))
3070 prout(_("That was a great shot."))
3072 elif ifin == FSNOVAED:
3073 prout(_("The %s has been fried by a supernova.") % crmshp())
3074 prout(_("...Not even cinders remain..."))
3075 elif ifin == FABANDN:
3076 prout(_("You have been captured by the Klingons. If you still"))
3077 prout(_("had a starbase to be returned to, you would have been"))
3078 prout(_("repatriated and given another chance. Since you have"))
3079 prout(_("no starbases, you will be mercilessly tortured to death."))
3080 elif ifin == FDILITHIUM:
3081 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3082 elif ifin == FMATERIALIZE:
3083 prout(_("Starbase was unable to re-materialize your starship."))
3084 prout(_("Sic transit gloria mundi"))
3085 elif ifin == FPHASER:
3086 prout(_("The %s has been cremated by its own phasers.") % crmshp())
3088 prout(_("You and your landing party have been"))
3089 prout(_("converted to energy, disipating through space."))
3090 elif ifin == FMINING:
3091 prout(_("You are left with your landing party on"))
3092 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3094 prout(_("They are very fond of \"Captain Kirk\" soup."))
3096 prout(_("Without your leadership, the %s is destroyed.") % crmshp())
3097 elif ifin == FDPLANET:
3098 prout(_("You and your mining party perish."))
3100 prout(_("That was a great shot."))
3103 prout(_("The Galileo is instantly annihilated by the supernova."))
3104 prout(_("You and your mining party are atomized."))
3106 prout(_("Mr. Spock takes command of the %s and") % crmshp())
3107 prout(_("joins the Romulans, wreaking terror on the Federation."))
3108 elif ifin == FPNOVA:
3109 prout(_("You and your mining party are atomized."))
3111 prout(_("Mr. Spock takes command of the %s and") % crmshp())
3112 prout(_("joins the Romulans, wreaking terror on the Federation."))
3113 elif ifin == FSTRACTOR:
3114 prout(_("The shuttle craft Galileo is also caught,"))
3115 prout(_("and breaks up under the strain."))
3117 prout(_("Your debris is scattered for millions of miles."))
3118 prout(_("Without your leadership, the %s is destroyed.") % crmshp())
3120 prout(_("The mutants attack and kill Spock."))
3121 prout(_("Your ship is captured by Klingons, and"))
3122 prout(_("your crew is put on display in a Klingon zoo."))
3123 elif ifin == FTRIBBLE:
3124 prout(_("Tribbles consume all remaining water,"))
3125 prout(_("food, and oxygen on your ship."))
3127 prout(_("You die of thirst, starvation, and asphyxiation."))
3128 prout(_("Your starship is a derelict in space."))
3130 prout(_("Your ship is drawn to the center of the black hole."))
3131 prout(_("You are crushed into extremely dense matter."))
3133 prout(_("Your last crew member has died."))
3134 if game.ship == IHF:
3136 elif game.ship == IHE:
3139 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0:
3140 goodies = game.state.remres/game.inresor
3141 baddies = (game.state.remkl + 2.0*len(game.state.kcmdr))/(game.inkling+2.0*game.incom)
3142 if goodies/baddies >= randreal(1.0, 1.5):
3143 prout(_("As a result of your actions, a treaty with the Klingon"))
3144 prout(_("Empire has been signed. The terms of the treaty are"))
3145 if goodies/baddies >= randreal(3.0):
3146 prout(_("favorable to the Federation."))
3148 prout(_("Congratulations!"))
3150 prout(_("highly unfavorable to the Federation."))
3152 prout(_("The Federation will be destroyed."))
3154 prout(_("Since you took the last Klingon with you, you are a"))
3155 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3156 prout(_("statue in your memory. Rest in peace, and try not"))
3157 prout(_("to think about pigeons."))
3162 "Compute player's score."
3163 timused = game.state.date - game.indate
3165 if (timused == 0 or (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0) and timused < 5.0:
3167 perdate = killrate()
3168 ithperd = 500*perdate + 0.5
3171 iwon = 100*game.skill
3172 if game.ship == IHE:
3174 elif game.ship == IHF:
3178 if not game.gamewon:
3179 game.state.nromrem = 0 # None captured if no win
3180 iscore = 10*(game.inkling - game.state.remkl) \
3181 + 50*(game.incom - len(game.state.kcmdr)) \
3183 + 20*(game.inrom - game.state.nromrem) \
3184 + 200*(game.inscom - game.state.nscrem) \
3185 - game.state.nromrem \
3190 prout(_("Your score --"))
3191 if game.inrom - game.state.nromrem:
3192 prout(_("%6d Romulans destroyed %5d") %
3193 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3194 if game.state.nromrem:
3195 prout(_("%6d Romulans captured %5d") %
3196 (game.state.nromrem, game.state.nromrem))
3197 if game.inkling - game.state.remkl:
3198 prout(_("%6d ordinary Klingons destroyed %5d") %
3199 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3200 if game.incom - len(game.state.kcmdr):
3201 prout(_("%6d Klingon commanders destroyed %5d") %
3202 (game.incom - len(game.state.kcmdr), 50*(game.incom - len(game.state.kcmdr))))
3203 if game.inscom - game.state.nscrem:
3204 prout(_("%6d Super-Commander destroyed %5d") %
3205 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3207 prout(_("%6.2f Klingons per stardate %5d") %
3209 if game.state.starkl:
3210 prout(_("%6d stars destroyed by your action %5d") %
3211 (game.state.starkl, -5*game.state.starkl))
3212 if game.state.nplankl:
3213 prout(_("%6d planets destroyed by your action %5d") %
3214 (game.state.nplankl, -10*game.state.nplankl))
3215 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3216 prout(_("%6d inhabited planets destroyed by your action %5d") %
3217 (game.state.nplankl, -300*game.state.nworldkl))
3218 if game.state.basekl:
3219 prout(_("%6d bases destroyed by your action %5d") %
3220 (game.state.basekl, -100*game.state.basekl))
3222 prout(_("%6d calls for help from starbase %5d") %
3223 (game.nhelp, -45*game.nhelp))
3225 prout(_("%6d casualties incurred %5d") %
3226 (game.casual, -game.casual))
3228 prout(_("%6d crew abandoned in space %5d") %
3229 (game.abandoned, -3*game.abandoned))
3231 prout(_("%6d ship(s) lost or destroyed %5d") %
3232 (klship, -100*klship))
3234 prout(_("Penalty for getting yourself killed -200"))
3236 proutn(_("Bonus for winning "))
3237 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3238 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3239 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3240 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3241 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3242 prout(" %5d" % iwon)
3244 prout(_("TOTAL SCORE %5d") % iscore)
3247 "Emit winner's commemmorative plaque."
3250 proutn(_("File or device name for your plaque: "))
3253 fp = open(winner, "w")
3256 prout(_("Invalid name."))
3258 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3260 # The 38 below must be 64 for 132-column paper
3261 nskip = 38 - len(winner)/2
3262 fp.write("\n\n\n\n")
3263 # --------DRAW ENTERPRISE PICTURE.
3264 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3265 fp.write(" EEE E : : : E\n" )
3266 fp.write(" EE EEE E : : NCC-1701 : E\n")
3267 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3268 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3269 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3270 fp.write(" EEEEEEE EEEEE E E E E\n")
3271 fp.write(" EEE E E E E\n")
3272 fp.write(" E E E E\n")
3273 fp.write(" EEEEEEEEEEEEE E E\n")
3274 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3275 fp.write(" :E : EEEE E\n")
3276 fp.write(" .-E -:----- E\n")
3277 fp.write(" :E : E\n")
3278 fp.write(" EE : EEEEEEEE\n")
3279 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3281 fp.write(_(" U. S. S. ENTERPRISE\n"))
3282 fp.write("\n\n\n\n")
3283 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3285 fp.write(_(" Starfleet Command bestows to you\n"))
3287 fp.write("%*s%s\n\n" % (nskip, "", winner))
3288 fp.write(_(" the rank of\n\n"))
3289 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3291 if game.skill == SKILL_EXPERT:
3292 fp.write(_(" Expert level\n\n"))
3293 elif game.skill == SKILL_EMERITUS:
3294 fp.write(_("Emeritus level\n\n"))
3296 fp.write(_(" Cheat level\n\n"))
3297 timestring = ctime()
3298 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3299 (timestring+4, timestring+20, timestring+11))
3300 fp.write(_(" Your score: %d\n\n") % iscore)
3301 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3304 # Code from io.c begins here
3306 rows = linecount = 0 # for paging
3309 fullscreen_window = None
3310 srscan_window = None
3311 report_window = None
3312 status_window = None
3313 lrscan_window = None
3314 message_window = None
3315 prompt_window = None
3320 if not (game.options & OPTION_CURSES):
3321 ln_env = os.getenv("LINES")
3327 stdscr = curses.initscr()
3331 global fullscreen_window, srscan_window, report_window, status_window
3332 global lrscan_window, message_window, prompt_window
3333 (rows, columns) = stdscr.getmaxyx()
3334 fullscreen_window = stdscr
3335 srscan_window = curses.newwin(12, 25, 0, 0)
3336 report_window = curses.newwin(11, 0, 1, 25)
3337 status_window = curses.newwin(10, 0, 1, 39)
3338 lrscan_window = curses.newwin(5, 0, 0, 64)
3339 message_window = curses.newwin(0, 0, 12, 0)
3340 prompt_window = curses.newwin(1, 0, rows-2, 0)
3341 message_window.scrollok(True)
3342 setwnd(fullscreen_window)
3346 if game.options & OPTION_CURSES:
3347 stdscr.keypad(False)
3353 "Wait for user action -- OK to do nothing if on a TTY"
3354 if game.options & OPTION_CURSES:
3359 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3363 if game.skill > SKILL_FAIR:
3364 prompt = _("[CONTINUE?]")
3366 prompt = _("[PRESS ENTER TO CONTINUE]")
3368 if game.options & OPTION_CURSES:
3370 setwnd(prompt_window)
3371 prompt_window.wclear()
3372 prompt_window.addstr(prompt)
3373 prompt_window.getstr()
3374 prompt_window.clear()
3375 prompt_window.refresh()
3376 setwnd(message_window)
3379 sys.stdout.write('\n')
3382 for j in range(rows):
3383 sys.stdout.write('\n')
3387 "Skip i lines. Pause game if this would cause a scrolling event."
3388 for dummy in range(i):
3389 if game.options & OPTION_CURSES:
3390 (y, x) = curwnd.getyx()
3391 (my, mx) = curwnd.getmaxyx()
3392 if curwnd == message_window and y >= my - 3:
3398 except curses.error:
3403 if rows and linecount >= rows:
3406 sys.stdout.write('\n')
3409 "Utter a line with no following line feed."
3410 if game.options & OPTION_CURSES:
3414 sys.stdout.write(line)
3424 if not replayfp or replayfp.closed: # Don't slow down replays
3427 if game.options & OPTION_CURSES:
3431 if not replayfp or replayfp.closed:
3435 "Get a line of input."
3436 if game.options & OPTION_CURSES:
3437 line = curwnd.getstr() + "\n"
3440 if replayfp and not replayfp.closed:
3442 line = replayfp.readline()
3445 prout("*** Replay finished")
3448 elif line[0] != "#":
3451 line = raw_input() + "\n"
3457 "Change windows -- OK for this to be a no-op in tty mode."
3459 if game.options & OPTION_CURSES:
3461 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3464 "Clear to end of line -- can be a no-op in tty mode"
3465 if game.options & OPTION_CURSES:
3470 "Clear screen -- can be a no-op in tty mode."
3472 if game.options & OPTION_CURSES:
3479 "Set highlight video, if this is reasonable."
3480 if game.options & OPTION_CURSES:
3481 curwnd.attron(curses.A_REVERSE)
3484 # Things past this point have policy implications.
3488 "Hook to be called after moving to redraw maps."
3489 if game.options & OPTION_CURSES:
3492 setwnd(srscan_window)
3496 setwnd(status_window)
3497 status_window.clear()
3498 status_window.move(0, 0)
3499 setwnd(report_window)
3500 report_window.clear()
3501 report_window.move(0, 0)
3503 setwnd(lrscan_window)
3504 lrscan_window.clear()
3505 lrscan_window.move(0, 0)
3506 lrscan(silent=False)
3508 def put_srscan_sym(w, sym):
3509 "Emit symbol for short-range scan."
3510 srscan_window.move(w.i+1, w.j*2+2)
3511 srscan_window.addch(sym)
3512 srscan_window.refresh()
3515 "Enemy fall down, go boom."
3516 if game.options & OPTION_CURSES:
3518 setwnd(srscan_window)
3519 srscan_window.attron(curses.A_REVERSE)
3520 put_srscan_sym(w, game.quad[w.i][w.j])
3524 srscan_window.attroff(curses.A_REVERSE)
3525 put_srscan_sym(w, game.quad[w.i][w.j])
3526 curses.delay_output(500)
3527 setwnd(message_window)
3530 "Sound and visual effects for teleportation."
3531 if game.options & OPTION_CURSES:
3533 setwnd(message_window)
3535 prouts(" . . . . . ")
3536 if game.options & OPTION_CURSES:
3537 #curses.delay_output(1000)
3541 def tracktorpedo(origin, w, step, i, n, iquad):
3542 "Torpedo-track animation."
3543 if not game.options & OPTION_CURSES:
3547 proutn(_("Track for %s torpedo number %d- ") % (game.quad[origin.i][origin.j],i+1))
3550 proutn(_("Torpedo track- "))
3551 elif step==4 or step==9:
3555 if not damaged(DSRSENS) or game.condition=="docked":
3556 if i != 0 and step == 1:
3559 if (iquad==IHDOT) or (iquad==IHBLANK):
3560 put_srscan_sym(w, '+')
3564 put_srscan_sym(w, iquad)
3566 curwnd.attron(curses.A_REVERSE)
3567 put_srscan_sym(w, iquad)
3571 curwnd.attroff(curses.A_REVERSE)
3572 put_srscan_sym(w, iquad)
3577 "Display the current galaxy chart."
3578 if game.options & OPTION_CURSES:
3579 setwnd(message_window)
3580 message_window.clear()
3582 if game.options & OPTION_TTY:
3587 def prstat(txt, data):
3589 if game.options & OPTION_CURSES:
3591 setwnd(status_window)
3593 proutn(" " * (NSYM - len(txt)))
3596 if game.options & OPTION_CURSES:
3597 setwnd(report_window)
3599 # Code from moving.c begins here
3601 def imove(novapush):
3602 "Movement execution for warp, impulse, supernova, and tractor-beam events."
3603 w = coord(); final = coord()
3606 def no_quad_change():
3607 # No quadrant change -- compute new average enemy distances
3608 game.quad[game.sector.i][game.sector.j] = game.ship
3610 for enemy in game.enemies:
3611 finald = (w-enemy.kloc).distance()
3612 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3613 enemy.kdist = finald
3614 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3615 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3616 attack(torps_ok=False)
3617 for enemy in game.enemies:
3618 enemy.kavgd = enemy.kdist
3621 setwnd(message_window)
3624 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3625 game.inorbit = False
3626 angle = ((15.0 - game.direc) * 0.5235988)
3627 deltax = -math.sin(angle)
3628 deltay = math.cos(angle)
3629 if math.fabs(deltax) > math.fabs(deltay):
3630 bigger = math.fabs(deltax)
3632 bigger = math.fabs(deltay)
3635 # If tractor beam is to occur, don't move full distance
3636 if game.state.date+game.optime >= scheduled(FTBEAM):
3638 game.condition = "red"
3639 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3640 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3641 # Move within the quadrant
3642 game.quad[game.sector.i][game.sector.j] = IHDOT
3645 n = int(10.0*game.dist*bigger+0.5)
3647 for m in range(1, n+1):
3652 if not VALID_SECTOR(w.i, w.j):
3653 # Leaving quadrant -- allow final enemy attack
3654 # Don't do it if being pushed by Nova
3655 if len(game.enemies) != 0 and not novapush:
3657 for enemy in game.enemies:
3658 finald = (w - enemy.kloc).distance()
3659 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3661 # Stas Sergeev added the condition
3662 # that attacks only happen if Klingons
3663 # are present and your skill is good.
3665 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3666 attack(torps_ok=False)
3669 # compute final position -- new quadrant and sector
3670 x = (QUADSIZE*game.quadrant.i)+game.sector.i
3671 y = (QUADSIZE*game.quadrant.j)+game.sector.j
3672 w.i = int(round(x+10.0*game.dist*bigger*deltax))
3673 w.j = int(round(y+10.0*game.dist*bigger*deltay))
3674 # check for edge of galaxy
3684 if w.i >= GALSIZE*QUADSIZE:
3685 w.i = (GALSIZE*QUADSIZE*2) - w.i
3687 if w.j >= GALSIZE*QUADSIZE:
3688 w.j = (GALSIZE*QUADSIZE*2) - w.j
3696 if game.nkinks == 3:
3697 # Three strikes -- you're out!
3701 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3702 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3703 prout(_("YOU WILL BE DESTROYED."))
3704 # Compute final position in new quadrant
3705 if trbeam: # Don't bother if we are to be beamed
3707 game.quadrant.i = w.i/QUADSIZE
3708 game.quadrant.j = w.j/QUADSIZE
3709 game.sector.i = w.i - (QUADSIZE*game.quadrant.i)
3710 game.sector.j = w.j - (QUADSIZE*game.quadrant.j)
3712 prout(_("Entering Quadrant %s.") % game.quadrant)
3713 game.quad[game.sector.i][game.sector.j] = game.ship
3715 if game.skill>SKILL_NOVICE:
3716 attack(torps_ok=False)
3718 iquad = game.quad[w.i][w.j]
3720 # object encountered in flight path
3721 stopegy = 50.0*game.dist/game.optime
3722 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3723 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3725 for enemy in game.enemies:
3726 if enemy.kloc == game.sector:
3728 collision(rammed=False, enemy=enemy)
3730 elif iquad == IHBLANK:
3732 prouts(_("***RED ALERT! RED ALERT!"))
3734 proutn("***" + crmshp())
3735 proutn(_(" pulled into black hole at Sector %s") % w)
3737 # Getting pulled into a black hole was certain
3738 # death in Almy's original. Stas Sergeev added a
3739 # possibility that you'll get timewarped instead.
3742 for m in range(NDEVICES):
3743 if game.damage[m]>0:
3745 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3746 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3756 prout(_(" encounters Tholian web at %s;") % w)
3758 prout(_(" blocked by object at %s;") % w)
3759 proutn(_("Emergency stop required "))
3760 prout(_("%2d units of energy.") % int(stopegy))
3761 game.energy -= stopegy
3762 final.i = int(round(deltax))
3763 final.j = int(round(deltay))
3765 if game.energy <= 0:
3771 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3778 "Dock our ship at a starbase."
3780 if game.condition == "docked" and verbose:
3781 prout(_("Already docked."))
3784 prout(_("You must first leave standard orbit."))
3786 if not game.base.is_valid() or abs(game.sector.i-game.base.i) > 1 or abs(game.sector.j-game.base.j) > 1:
3787 prout(crmshp() + _(" not adjacent to base."))
3789 game.condition = "docked"
3793 if game.energy < game.inenrg:
3794 game.energy = game.inenrg
3795 game.shield = game.inshld
3796 game.torps = game.intorps
3797 game.lsupres = game.inlsr
3798 game.state.crew = FULLCREW
3799 if not damaged(DRADIO) and \
3800 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
3801 # get attack report from base
3802 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
3806 # This program originally required input in terms of a (clock)
3807 # direction and distance. Somewhere in history, it was changed to
3808 # cartesian coordinates. So we need to convert. Probably
3809 # "manual" input should still be done this way -- it's a real
3810 # pain if the computer isn't working! Manual mode is still confusing
3811 # because it involves giving x and y motions, yet the coordinates
3812 # are always displayed y - x, where +y is downward!
3814 def getcourse(isprobe, akey):
3815 "Get a course and distance from the user."
3817 dquad = copy.copy(game.quadrant)
3818 navmode = "unspecified"
3822 if game.landed and not isprobe:
3823 prout(_("Dummy! You can't leave standard orbit until you"))
3824 proutn(_("are back aboard the ship."))
3827 while navmode == "unspecified":
3828 if damaged(DNAVSYS):
3830 prout(_("Computer damaged; manual navigation only"))
3832 prout(_("Computer damaged; manual movement only"))
3837 if isprobe and akey != -1:
3838 # For probe launch, use pre-scanned value first time
3842 key = scanner.next()
3844 proutn(_("Manual or automatic- "))
3847 elif key == "IHALPHA":
3848 if scanner.sees("manual"):
3850 key = scanner.next()
3852 elif scanner.sees("automatic"):
3853 navmode = "automatic"
3854 key = scanner.next()
3862 prout(_("(Manual navigation assumed.)"))
3864 prout(_("(Manual movement assumed.)"))
3867 if navmode == "automatic":
3868 while key == "IHEOL":
3870 proutn(_("Target quadrant or quadrant§or- "))
3872 proutn(_("Destination sector or quadrant§or- "))
3875 key = scanner.next()
3879 xi = int(round(scanner.real))-1
3880 key = scanner.next()
3884 xj = int(round(scanner.real))-1
3885 key = scanner.next()
3887 # both quadrant and sector specified
3888 xk = int(round(scanner.real))-1
3889 key = scanner.next()
3893 xl = int(round(scanner.real))-1
3899 # only one pair of numbers was specified
3901 # only quadrant specified -- go to center of dest quad
3904 dsect.j = dsect.i = 4 # preserves 1-origin behavior
3906 # only sector specified
3910 if not VALID_QUADRANT(dquad.i,dquad.j) or not VALID_SECTOR(dsect.i,dsect.j):
3917 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
3919 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
3920 # the actual deltas get computed here
3922 delta.j = dquad.j-game.quadrant.j + 0.1*(dsect.j-game.sector.j)
3923 delta.i = game.quadrant.i-dquad.i + 0.1*(game.sector.i-dsect.i)
3925 while key == "IHEOL":
3926 proutn(_("X and Y displacements- "))
3929 key = scanner.next()
3934 delta.j = scanner.real
3935 key = scanner.next()
3939 delta.i = scanner.real
3940 # Check for zero movement
3941 if delta.i == 0 and delta.j == 0:
3944 if itemp == "verbose" and not isprobe:
3946 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
3947 # Course actually laid in.
3948 game.dist = delta.distance()
3949 game.direc = delta.bearing()
3950 if game.direc < 0.0:
3956 "Move under impulse power."
3958 if damaged(DIMPULS):
3961 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
3963 if game.energy > 30.0:
3964 if not getcourse(isprobe=False, akey=0):
3966 power = 20.0 + 100.0*game.dist
3969 if power >= game.energy:
3970 # Insufficient power for trip
3972 prout(_("First Officer Spock- \"Captain, the impulse engines"))
3973 prout(_("require 20.0 units to engage, plus 100.0 units per"))
3974 if game.energy > 30:
3975 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
3976 int(0.01 * (game.energy-20.0)-0.05))
3977 prout(_(" quadrants.\""))
3979 prout(_("quadrant. They are, therefore, useless.\""))
3982 # Make sure enough time is left for the trip
3983 game.optime = game.dist/0.095
3984 if game.optime >= game.state.remtime:
3985 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
3986 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
3987 proutn(_("we dare spend the time?\" "))
3990 # Activate impulse engines and pay the cost
3991 imove(novapush=False)
3995 power = 20.0 + 100.0*game.dist
3996 game.energy -= power
3997 game.optime = game.dist/0.095
3998 if game.energy <= 0:
4003 "ove under warp drive."
4004 blooey = False; twarp = False
4005 if not timewarp: # Not WARPX entry
4007 if game.damage[DWARPEN] > 10.0:
4010 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4012 if damaged(DWARPEN) and game.warpfac > 4.0:
4015 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4016 prout(_(" is repaired, I can only give you warp 4.\""))
4018 # Read in course and distance
4019 if not getcourse(isprobe=False, akey=0):
4021 # Make sure starship has enough energy for the trip
4022 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4023 if power >= game.energy:
4024 # Insufficient power for trip
4027 prout(_("Engineering to bridge--"))
4028 if not game.shldup or 0.5*power > game.energy:
4029 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4031 prout(_("We can't do it, Captain. We don't have enough energy."))
4033 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4036 prout(_("if you'll lower the shields."))
4040 prout(_("We haven't the energy to go that far with the shields up."))
4043 # Make sure enough time is left for the trip
4044 game.optime = 10.0*game.dist/game.warpfac**2
4045 if game.optime >= 0.8*game.state.remtime:
4047 prout(_("First Officer Spock- \"Captain, I compute that such"))
4048 proutn(_(" a trip would require approximately %2.0f") %
4049 (100.0*game.optime/game.state.remtime))
4050 prout(_(" percent of our"))
4051 proutn(_(" remaining time. Are you sure this is wise?\" "))
4057 if game.warpfac > 6.0:
4058 # Decide if engine damage will occur
4059 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4060 prob = game.dist*(6.0-game.warpfac)**2/66.666666666
4061 if prob > randreal():
4063 game.dist = randreal(game.dist)
4064 # Decide if time warp will occur
4065 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4067 if idebug and game.warpfac==10 and not twarp:
4069 proutn("=== Force time warp? ")
4073 # If time warp or engine damage, check path
4074 # If it is obstructed, don't do warp or damage
4075 angle = ((15.0-game.direc)*0.5235998)
4076 deltax = -math.sin(angle)
4077 deltay = math.cos(angle)
4078 if math.fabs(deltax) > math.fabs(deltay):
4079 bigger = math.fabs(deltax)
4081 bigger = math.fabs(deltay)
4084 n = 10.0 * game.dist * bigger +0.5
4087 for l in range(1, n+1):
4092 if not VALID_SECTOR(ix, iy):
4094 if game.quad[ix][iy] != IHDOT:
4097 # Activate Warp Engines and pay the cost
4098 imove(novapush=False)
4101 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4102 if game.energy <= 0:
4104 game.optime = 10.0*game.dist/game.warpfac**2
4108 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4110 prout(_("Engineering to bridge--"))
4111 prout(_(" Scott here. The warp engines are damaged."))
4112 prout(_(" We'll have to reduce speed to warp 4."))
4117 "Change the warp factor."
4123 proutn(_("Warp factor- "))
4128 if game.damage[DWARPEN] > 10.0:
4129 prout(_("Warp engines inoperative."))
4131 if damaged(DWARPEN) and scanner.real > 4.0:
4132 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4133 prout(_(" but right now we can only go warp 4.\""))
4135 if scanner.real > 10.0:
4136 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4138 if scanner.real < 1.0:
4139 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4141 oldfac = game.warpfac
4142 game.warpfac = scanner.real
4143 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4144 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4147 if game.warpfac < 8.00:
4148 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4150 if game.warpfac == 10.0:
4151 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4153 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4157 "Cope with being tossed out of quadrant by supernova or yanked by beam."
4159 # is captain on planet?
4161 if damaged(DTRANSP):
4164 prout(_("Scotty rushes to the transporter controls."))
4166 prout(_("But with the shields up it's hopeless."))
4168 prouts(_("His desperate attempt to rescue you . . ."))
4173 prout(_("SUCCEEDS!"))
4176 proutn(_("The crystals mined were "))
4184 # Check to see if captain in shuttle craft
4189 # Inform captain of attempt to reach safety
4193 prouts(_("***RED ALERT! RED ALERT!"))
4195 proutn(_("The %s has stopped in a quadrant containing") % crmshp())
4196 prouts(_(" a supernova."))
4198 prout(_("***Emergency automatic override attempts to hurl ")+crmshp())
4200 prout(_("safely out of quadrant."))
4201 if not damaged(DRADIO):
4202 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
4203 # Try to use warp engines
4204 if damaged(DWARPEN):
4206 prout(_("Warp engines damaged."))
4209 game.warpfac = randreal(6.0, 8.0)
4210 prout(_("Warp factor set to %d") % int(game.warpfac))
4211 power = 0.75*game.energy
4212 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4213 distreq = randreal(math.sqrt(2))
4214 if distreq < game.dist:
4216 game.optime = 10.0*game.dist/game.warpfac**2
4217 game.direc = randreal(12) # How dumb!
4219 game.inorbit = False
4222 # This is bad news, we didn't leave quadrant.
4226 prout(_("Insufficient energy to leave quadrant."))
4229 # Repeat if another snova
4230 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
4232 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
4233 finish(FWON) # Snova killed remaining enemy.
4236 "Let's do the time warp again."
4237 prout(_("***TIME WARP ENTERED."))
4238 if game.state.snap and withprob(0.5):
4240 prout(_("You are traveling backwards in time %d stardates.") %
4241 int(game.state.date-game.snapsht.date))
4242 game.state = game.snapsht
4243 game.state.snap = False
4244 if len(game.state.kcmdr):
4245 schedule(FTBEAM, expran(game.intime/len(game.state.kcmdr)))
4246 schedule(FBATTAK, expran(0.3*game.intime))
4247 schedule(FSNOVA, expran(0.5*game.intime))
4248 # next snapshot will be sooner
4249 schedule(FSNAP, expran(0.25*game.state.remtime))
4251 if game.state.nscrem:
4252 schedule(FSCMOVE, 0.2777)
4256 game.battle.invalidate()
4258 # Make sure Galileo is consistant -- Snapshot may have been taken
4259 # when on planet, which would give us two Galileos!
4261 for l in range(game.inplan):
4262 if game.state.planets[l].known == "shuttle_down":
4264 if game.iscraft == "onship" and game.ship==IHE:
4265 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4266 game.iscraft = "offship"
4267 # Likewise, if in the original time the Galileo was abandoned, but
4268 # was on ship earlier, it would have vanished -- let's restore it.
4269 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4270 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4271 game.iscraft = "onship"
4272 # There used to be code to do the actual reconstrction here,
4273 # but the starchart is now part of the snapshotted galaxy state.
4274 prout(_("Spock has reconstructed a correct star chart from memory"))
4276 # Go forward in time
4277 game.optime = -0.5*game.intime*math.log(randreal())
4278 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4279 # cheat to make sure no tractor beams occur during time warp
4280 postpone(FTBEAM, game.optime)
4281 game.damage[DRADIO] += game.optime
4283 events() # Stas Sergeev added this -- do pending events
4286 "Launch deep-space probe."
4287 # New code to launch a deep space probe
4288 if game.nprobes == 0:
4291 if game.ship == IHE:
4292 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4294 prout(_("Ye Faerie Queene has no deep space probes."))
4299 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4301 if is_scheduled(FDSPROB):
4304 if damaged(DRADIO) and game.condition != "docked":
4305 prout(_("Spock- \"Records show the previous probe has not yet"))
4306 prout(_(" reached its destination.\""))
4308 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4310 key = scanner.next()
4312 # slow mode, so let Kirk know how many probes there are left
4313 if game.nprobes == 1:
4314 prout(_("1 probe left."))
4316 prout(_("%d probes left") % game.nprobes)
4317 proutn(_("Are you sure you want to fire a probe? "))
4320 game.isarmed = False
4321 if key == "IHALPHA" and scanner.token == "armed":
4323 key = scanner.next()
4324 elif key == "IHEOL":
4325 proutn(_("Arm NOVAMAX warhead? "))
4327 if not getcourse(isprobe=True, akey=key):
4330 angle = ((15.0 - game.direc) * 0.5235988)
4331 game.probeinx = -math.sin(angle)
4332 game.probeiny = math.cos(angle)
4333 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4334 bigger = math.fabs(game.probeinx)
4336 bigger = math.fabs(game.probeiny)
4337 game.probeiny /= bigger
4338 game.probeinx /= bigger
4339 game.proben = 10.0*game.dist*bigger +0.5
4340 game.probex = game.quadrant.i*QUADSIZE + game.sector.i - 1 # We will use better packing than original
4341 game.probey = game.quadrant.j*QUADSIZE + game.sector.j - 1
4342 game.probec = game.quadrant
4343 schedule(FDSPROB, 0.01) # Time to move one sector
4344 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4349 "Yell for help from nearest starbase."
4350 # There's more than one way to move in this game!
4352 # Test for conditions which prevent calling for help
4353 if game.condition == "docked":
4354 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4357 prout(_("Subspace radio damaged."))
4359 if not game.state.baseq:
4360 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4363 prout(_("You must be aboard the %s.") % crmshp())
4365 # OK -- call for help from nearest starbase
4368 # There's one in this quadrant
4369 ddist = (game.base - game.sector).distance()
4372 for ibq in game.state.baseq:
4373 xdist = QUADSIZE * (ibq - game.quadrant).distance()
4376 # Since starbase not in quadrant, set up new quadrant
4379 # dematerialize starship
4380 game.quad[game.sector.i][game.sector.j]=IHDOT
4381 proutn(_("Starbase in Quadrant %s responds--%s dematerializes") \
4382 % (game.quadrant, crmshp()))
4383 game.sector.invalidate()
4384 for m in range(1, 5+1):
4385 w = game.base.scatter()
4386 if VALID_SECTOR(w.i,w.j) and game.quad[w.i][w.j]==IHDOT:
4387 # found one -- finish up
4390 if not game.sector.is_valid():
4391 prout(_("You have been lost in space..."))
4392 finish(FMATERIALIZE)
4394 # Give starbase three chances to rematerialize starship
4395 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4396 for m in range(1, 3+1):
4397 if m == 1: proutn(_("1st"))
4398 elif m == 2: proutn(_("2nd"))
4399 elif m == 3: proutn(_("3rd"))
4400 proutn(_(" attempt to re-materialize ") + crmshp())
4401 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4404 if randreal() > probf:
4407 curses.delay_output(500)
4410 game.quad[ix][iy]=IHQUEST
4413 setwnd(message_window)
4414 finish(FMATERIALIZE)
4416 game.quad[ix][iy]=game.ship
4418 prout(_("succeeds."))
4422 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4427 if game.condition=="docked":
4429 prout(_("You cannot abandon Ye Faerie Queene."))
4432 # Must take shuttle craft to exit
4433 if game.damage[DSHUTTL]==-1:
4434 prout(_("Ye Faerie Queene has no shuttle craft."))
4436 if game.damage[DSHUTTL]<0:
4437 prout(_("Shuttle craft now serving Big Macs."))
4439 if game.damage[DSHUTTL]>0:
4440 prout(_("Shuttle craft damaged."))
4443 prout(_("You must be aboard the ship."))
4445 if game.iscraft != "onship":
4446 prout(_("Shuttle craft not currently available."))
4448 # Emit abandon ship messages
4450 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4452 prouts(_("***ALL HANDS ABANDON SHIP!"))
4454 prout(_("Captain and crew escape in shuttle craft."))
4455 if not game.state.baseq:
4456 # Oops! no place to go...
4459 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
4461 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4462 prout(_("Remainder of ship's complement beam down"))
4463 prout(_("to nearest habitable planet."))
4464 elif q.planet != None and not damaged(DTRANSP):
4465 prout(_("Remainder of ship's complement beam down to %s.") %
4468 prout(_("Entire crew of %d left to die in outer space.") %
4470 game.casual += game.state.crew
4471 game.abandoned += game.state.crew
4472 # If at least one base left, give 'em the Faerie Queene
4474 game.icrystl = False # crystals are lost
4475 game.nprobes = 0 # No probes
4476 prout(_("You are captured by Klingons and released to"))
4477 prout(_("the Federation in a prisoner-of-war exchange."))
4478 nb = randrange(len(game.state.baseq))
4479 # Set up quadrant and position FQ adjacient to base
4480 if not game.quadrant == game.state.baseq[nb]:
4481 game.quadrant = game.state.baseq[nb]
4482 game.sector.i = game.sector.j = 5
4485 # position next to base by trial and error
4486 game.quad[game.sector.i][game.sector.j] = IHDOT
4487 for l in range(QUADSIZE):
4488 game.sector = game.base.scatter()
4489 if VALID_SECTOR(game.sector.i, game.sector.j) and \
4490 game.quad[game.sector.i][game.sector.j] == IHDOT:
4493 break # found a spot
4494 game.sector.i=QUADSIZE/2
4495 game.sector.j=QUADSIZE/2
4497 # Get new commission
4498 game.quad[game.sector.i][game.sector.j] = game.ship = IHF
4499 game.state.crew = FULLCREW
4500 prout(_("Starfleet puts you in command of another ship,"))
4501 prout(_("the Faerie Queene, which is antiquated but,"))
4502 prout(_("still useable."))
4504 prout(_("The dilithium crystals have been moved."))
4506 game.iscraft = "offship" # Galileo disappears
4508 game.condition="docked"
4509 for l in range(NDEVICES):
4510 game.damage[l] = 0.0
4511 game.damage[DSHUTTL] = -1
4512 game.energy = game.inenrg = 3000.0
4513 game.shield = game.inshld = 1250.0
4514 game.torps = game.intorps = 6
4515 game.lsupres=game.inlsr=3.0
4520 # Code from planets.c begins here.
4523 "Abort a lengthy operation if an event interrupts it."
4526 if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.justin:
4531 "Report on (uninhabited) planets in the galaxy."
4535 prout(_("Spock- \"Planet report follows, Captain.\""))
4537 for i in range(game.inplan):
4538 if game.state.planets[i].pclass == "destroyed":
4540 if (game.state.planets[i].known != "unknown" \
4541 and not game.state.planets[i].inhabited) \
4544 if idebug and game.state.planets[i].known=="unknown":
4545 proutn("(Unknown) ")
4546 proutn(_("Quadrant %s") % game.state.planets[i].quadrant)
4547 proutn(_(" class "))
4548 proutn(game.state.planets[i].pclass)
4550 if game.state.planets[i].crystals != present:
4552 prout(_("dilithium crystals present."))
4553 if game.state.planets[i].known=="shuttle_down":
4554 prout(_(" Shuttle Craft Galileo on surface."))
4556 prout(_("No information available."))
4559 "Enter standard orbit."
4563 prout(_("Already in standard orbit."))
4565 if damaged(DWARPEN) and damaged(DIMPULS):
4566 prout(_("Both warp and impulse engines damaged."))
4568 if not game.plnet.is_valid():
4569 prout("There is no planet in this sector.")
4571 if abs(game.sector.i-game.plnet.i)>1 or abs(game.sector.j-game.plnet.j)>1:
4572 prout(crmshp() + _(" not adjacent to planet."))
4575 game.optime = randreal(0.02, 0.05)
4576 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4580 game.height = randreal(1400, 8600)
4581 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4586 "Examine planets in this quadrant."
4587 if damaged(DSRSENS):
4588 if game.options & OPTION_TTY:
4589 prout(_("Short range sensors damaged."))
4591 if game.iplnet == None:
4592 if game.options & OPTION_TTY:
4593 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4595 if game.iplnet.known == "unknown":
4596 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4598 prout(_(" Planet at Sector %s is of class %s.") %
4599 (game.plnet, game.iplnet.pclass))
4600 if game.iplnet.known=="shuttle_down":
4601 prout(_(" Sensors show Galileo still on surface."))
4602 proutn(_(" Readings indicate"))
4603 if game.iplnet.crystals != "present":
4605 prout(_(" dilithium crystals present.\""))
4606 if game.iplnet.known == "unknown":
4607 game.iplnet.known = "known"
4608 elif game.iplnet.inhabited:
4609 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4610 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4613 "Use the transporter."
4617 if damaged(DTRANSP):
4618 prout(_("Transporter damaged."))
4619 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4621 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4625 if not game.inorbit:
4626 prout(crmshp() + _(" not in standard orbit."))
4629 prout(_("Impossible to transport through shields."))
4631 if game.iplnet.known=="unknown":
4632 prout(_("Spock- \"Captain, we have no information on this planet"))
4633 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4634 prout(_(" you may not go down.\""))
4636 if not game.landed and game.iplnet.crystals=="absent":
4637 prout(_("Spock- \"Captain, I fail to see the logic in"))
4638 prout(_(" exploring a planet with no dilithium crystals."))
4639 proutn(_(" Are you sure this is wise?\" "))
4643 if not (game.options & OPTION_PLAIN):
4644 nrgneed = 50 * game.skill + game.height / 100.0
4645 if nrgneed > game.energy:
4646 prout(_("Engineering to bridge--"))
4647 prout(_(" Captain, we don't have enough energy for transportation."))
4649 if not game.landed and nrgneed * 2 > game.energy:
4650 prout(_("Engineering to bridge--"))
4651 prout(_(" Captain, we have enough energy only to transport you down to"))
4652 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4653 if game.iplnet.known == "shuttle_down":
4654 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4655 proutn(_(" Are you sure this is wise?\" "))
4660 # Coming from planet
4661 if game.iplnet.known=="shuttle_down":
4662 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4666 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4667 prout(_("Landing party assembled, ready to beam up."))
4669 prout(_("Kirk whips out communicator..."))
4670 prouts(_("BEEP BEEP BEEP"))
4672 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4675 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4677 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4679 prout(_("Kirk- \"Energize.\""))
4682 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4685 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4687 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4690 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4691 game.landed = not game.landed
4692 game.energy -= nrgneed
4694 prout(_("Transport complete."))
4695 if game.landed and game.iplnet.known=="shuttle_down":
4696 prout(_("The shuttle craft Galileo is here!"))
4697 if not game.landed and game.imine:
4704 "Strip-mine a world for dilithium."
4708 prout(_("Mining party not on planet."))
4710 if game.iplnet.crystals == "mined":
4711 prout(_("This planet has already been strip-mined for dilithium."))
4713 elif game.iplnet.crystals == "absent":
4714 prout(_("No dilithium crystals on this planet."))
4717 prout(_("You've already mined enough crystals for this trip."))
4719 if game.icrystl and game.cryprob == 0.05:
4720 prout(_("With all those fresh crystals aboard the ") + crmshp())
4721 prout(_("there's no reason to mine more at this time."))
4723 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4726 prout(_("Mining operation complete."))
4727 game.iplnet.crystals = "mined"
4728 game.imine = game.ididit = True
4731 "Use dilithium crystals."
4735 if not game.icrystl:
4736 prout(_("No dilithium crystals available."))
4738 if game.energy >= 1000:
4739 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4740 prout(_(" except when Condition Yellow exists."))
4742 prout(_("Spock- \"Captain, I must warn you that loading"))
4743 prout(_(" raw dilithium crystals into the ship's power"))
4744 prout(_(" system may risk a severe explosion."))
4745 proutn(_(" Are you sure this is wise?\" "))
4750 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
4751 prout(_(" Mr. Spock and I will try it.\""))
4753 prout(_("Spock- \"Crystals in place, Sir."))
4754 prout(_(" Ready to activate circuit.\""))
4756 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
4758 if with(game.cryprob):
4759 prouts(_(" \"Activating now! - - No good! It's***"))
4761 prouts(_("***RED ALERT! RED A*L********************************"))
4764 prouts(_("****************** KA-BOOM!!!! *******************"))
4768 game.energy += randreal(5000.0, 5500.0)
4769 prouts(_(" \"Activating now! - - "))
4770 prout(_("The instruments"))
4771 prout(_(" are going crazy, but I think it's"))
4772 prout(_(" going to work!! Congratulations, Sir!\""))
4777 "Use shuttlecraft for planetary jaunt."
4780 if damaged(DSHUTTL):
4781 if game.damage[DSHUTTL] == -1.0:
4782 if game.inorbit and game.iplnet.known == "shuttle_down":
4783 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
4785 prout(_("Ye Faerie Queene had no shuttle craft."))
4786 elif game.damage[DSHUTTL] > 0:
4787 prout(_("The Galileo is damaged."))
4788 else: # game.damage[DSHUTTL] < 0
4789 prout(_("Shuttle craft is now serving Big Macs."))
4791 if not game.inorbit:
4792 prout(crmshp() + _(" not in standard orbit."))
4794 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
4795 prout(_("Shuttle craft not currently available."))
4797 if not game.landed and game.iplnet.known=="shuttle_down":
4798 prout(_("You will have to beam down to retrieve the shuttle craft."))
4800 if game.shldup or game.condition == "docked":
4801 prout(_("Shuttle craft cannot pass through shields."))
4803 if game.iplnet.known=="unknown":
4804 prout(_("Spock- \"Captain, we have no information on this planet"))
4805 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4806 prout(_(" you may not fly down.\""))
4808 game.optime = 3.0e-5*game.height
4809 if game.optime >= 0.8*game.state.remtime:
4810 prout(_("First Officer Spock- \"Captain, I compute that such"))
4811 proutn(_(" a maneuver would require approximately %2d%% of our") % \
4812 int(100*game.optime/game.state.remtime))
4813 prout(_("remaining time."))
4814 proutn(_("Are you sure this is wise?\" "))
4820 if game.iscraft == "onship":
4822 if not damaged(DTRANSP):
4823 proutn(_("Spock- \"Would you rather use the transporter?\" "))
4827 proutn(_("Shuttle crew"))
4829 proutn(_("Rescue party"))
4830 prout(_(" boards Galileo and swoops toward planet surface."))
4831 game.iscraft = "offship"
4835 game.iplnet.known="shuttle_down"
4836 prout(_("Trip complete."))
4839 # Ready to go back to ship
4840 prout(_("You and your mining party board the"))
4841 prout(_("shuttle craft for the trip back to the Enterprise."))
4843 prouts(_("The short hop begins . . ."))
4845 game.iplnet.known="known"
4851 game.iscraft = "onship"
4857 prout(_("Trip complete."))
4860 # Kirk on ship and so is Galileo
4861 prout(_("Mining party assembles in the hangar deck,"))
4862 prout(_("ready to board the shuttle craft \"Galileo\"."))
4864 prouts(_("The hangar doors open; the trip begins."))
4867 game.iscraft = "offship"
4870 game.iplnet.known = "shuttle_down"
4873 prout(_("Trip complete."))
4877 "Use the big zapper."
4881 if game.ship != IHE:
4882 prout(_("Ye Faerie Queene has no death ray."))
4884 if len(game.enemies)==0:
4885 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
4888 prout(_("Death Ray is damaged."))
4890 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
4891 prout(_(" is highly unpredictible. Considering the alternatives,"))
4892 proutn(_(" are you sure this is wise?\" "))
4895 prout(_("Spock- \"Acknowledged.\""))
4898 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
4900 prout(_("Crew scrambles in emergency preparation."))
4901 prout(_("Spock and Scotty ready the death ray and"))
4902 prout(_("prepare to channel all ship's power to the device."))
4904 prout(_("Spock- \"Preparations complete, sir.\""))
4905 prout(_("Kirk- \"Engage!\""))
4907 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
4910 if game.options & OPTION_PLAIN:
4914 prouts(_("Sulu- \"Captain! It's working!\""))
4916 while len(game.enemies) > 0:
4917 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.i][game.enemies[1].kloc.j],game.enemies[1].kloc)
4918 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
4919 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) == 0:
4921 if (game.options & OPTION_PLAIN) == 0:
4922 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
4924 prout(_(" is still operational.\""))
4926 prout(_(" has been rendered nonfunctional.\""))
4927 game.damage[DDRAY] = 39.95
4929 r = randreal() # Pick failure method
4931 prouts(_("Sulu- \"Captain! It's working!\""))
4933 prouts(_("***RED ALERT! RED ALERT!"))
4935 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
4937 prouts(_("***RED ALERT! RED A*L********************************"))
4940 prouts(_("****************** KA-BOOM!!!! *******************"))
4945 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
4947 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
4949 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
4950 prout(_(" have apparently been transformed into strange mutations."))
4951 prout(_(" Vulcans do not seem to be affected."))
4953 prout(_("Kirk- \"Raauch! Raauch!\""))
4958 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
4960 proutn(_("Spock- \"I believe the word is"))
4961 prouts(_(" *ASTONISHING*"))
4962 prout(_(" Mr. Sulu."))
4963 for i in range(QUADSIZE):
4964 for j in range(QUADSIZE):
4965 if game.quad[i][j] == IHDOT:
4966 game.quad[i][j] = IHQUEST
4967 prout(_(" Captain, our quadrant is now infested with"))
4968 prouts(_(" - - - - - - *THINGS*."))
4970 prout(_(" I have no logical explanation.\""))
4972 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
4974 prout(_("Scotty- \"There are so many tribbles down here"))
4975 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
4979 # Code from reports.c begins here
4981 def attackreport(curt):
4982 "eport status of bases under attack."
4984 if is_scheduled(FCDBAS):
4985 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
4986 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
4987 elif game.isatb == 1:
4988 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
4989 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
4991 prout(_("No Starbase is currently under attack."))
4993 if is_scheduled(FCDBAS):
4994 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
4996 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5000 # report on general game status
5002 s1 = "" and game.thawed and _("thawed ")
5003 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5004 s3 = (None, _("novice"). _("fair"),
5005 _("good"), _("expert"), _("emeritus"))[game.skill]
5006 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5007 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5008 prout(_("No plaque is allowed."))
5010 prout(_("This is tournament game %d.") % game.tourn)
5011 prout(_("Your secret password is \"%s\"") % game.passwd)
5012 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)),
5013 (game.inkling + game.incom + game.inscom)))
5014 if game.incom - len(game.state.kcmdr):
5015 prout(_(", including %d Commander%s.") % (game.incom - len(game.state.kcmdr), (_("s"), "")[(game.incom - len(game.state.kcmdr))==1]))
5016 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5017 prout(_(", but no Commanders."))
5020 if game.skill > SKILL_FAIR:
5021 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5022 if len(game.state.baseq) != game.inbase:
5024 if game.inbase-len(game.state.baseq)==1:
5025 proutn(_("has been 1 base"))
5027 proutn(_("have been %d bases") % (game.inbase-len(game.state.baseq)))
5028 prout(_(" destroyed, %d remaining.") % len(game.state.baseq))
5030 prout(_("There are %d bases.") % game.inbase)
5031 if communicating() or game.iseenit:
5032 # Don't report this if not seen and
5033 # either the radio is dead or not at base!
5037 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5039 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5040 if game.ship == IHE:
5041 proutn(_("You have "))
5043 proutn("%d" % (game.nprobes))
5046 proutn(_(" deep space probe"))
5050 if communicating() and is_scheduled(FDSPROB):
5052 proutn(_("An armed deep space probe is in "))
5054 proutn(_("A deep space probe is in "))
5055 prout("Quadrant %s." % game.probec)
5057 if game.cryprob <= .05:
5058 prout(_("Dilithium crystals aboard ship... not yet used."))
5062 while game.cryprob > ai:
5065 prout(_("Dilithium crystals have been used %d time%s.") % \
5066 (i, (_("s"), "")[i==1]))
5070 "Long-range sensor scan."
5071 if damaged(DLRSENS):
5072 # Now allow base's sensors if docked
5073 if game.condition != "docked":
5075 prout(_("LONG-RANGE SENSORS DAMAGED."))
5078 prout(_("Starbase's long-range scan"))
5080 prout(_("Long-range scan"))
5081 for x in range(game.quadrant.i-1, game.quadrant.i+2):
5084 for y in range(game.quadrant.j-1, game.quadrant.j+2):
5085 if not VALID_QUADRANT(x, y):
5089 if not damaged(DRADIO):
5090 game.state.galaxy[x][y].charted = True
5091 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5092 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5093 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5094 if not silent and game.state.galaxy[x][y].supernova:
5097 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5105 for i in range(NDEVICES):
5108 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5109 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5111 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5112 game.damage[i]+0.05,
5113 game.docfac*game.damage[i]+0.005))
5115 prout(_("All devices functional."))
5118 "Update the chart in the Enterprise's computer from galaxy data."
5119 game.lastchart = game.state.date
5120 for i in range(GALSIZE):
5121 for j in range(GALSIZE):
5122 if game.state.galaxy[i][j].charted:
5123 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5124 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5125 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5128 "Display the star chart."
5130 if (game.options & OPTION_AUTOSCAN):
5132 if not damaged(DRADIO):
5134 if game.lastchart < game.state.date and game.condition == "docked":
5135 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5137 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5138 if game.state.date > game.lastchart:
5139 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5140 prout(" 1 2 3 4 5 6 7 8")
5141 for i in range(GALSIZE):
5142 proutn("%d |" % (i+1))
5143 for j in range(GALSIZE):
5144 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
5148 if game.state.galaxy[i][j].supernova:
5150 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5152 elif game.state.galaxy[i][j].charted:
5153 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5157 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
5165 def sectscan(goodScan, i, j):
5166 "Light up an individual dot in a sector."
5167 if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1):
5168 if (game.quad[i][j]==IHMATER0) or (game.quad[i][j]==IHMATER1) or (game.quad[i][j]==IHMATER2) or (game.quad[i][j]==IHE) or (game.quad[i][j]==IHF):
5169 #if game.condition == "red": textcolor("red")
5170 #elif game.condition == "green": textcolor("green")
5171 #elif game.condition == "yellow": textcolor("yellow")
5172 #elif game.condition == "docked": textcolor("cyan")
5173 #elif game.condition == "dead": textcolor("brown")
5174 if game.quad[i][j] != game.ship:
5176 proutn("%c " % game.quad[i][j])
5182 "Emit status report lines"
5183 if not req or req == 1:
5184 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5185 % (game.state.date, game.state.remtime))
5186 if not req or req == 2:
5187 if game.condition != "docked":
5190 for t in range(NDEVICES):
5191 if game.damage[t]>0:
5193 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5194 if not req or req == 3:
5195 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5196 if not req or req == 4:
5197 if damaged(DLIFSUP):
5198 if game.condition == "docked":
5199 s = _("DAMAGED, Base provides")
5201 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5204 prstat(_("Life Support"), s)
5205 if not req or req == 5:
5206 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5207 if not req or req == 6:
5209 if game.icrystl and (game.options & OPTION_SHOWME):
5210 extra = _(" (have crystals)")
5211 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5212 if not req or req == 7:
5213 prstat(_("Torpedoes"), "%d" % (game.torps))
5214 if not req or req == 8:
5215 if damaged(DSHIELD):
5221 data = _(" %d%% %.1f units") \
5222 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5223 prstat(_("Shields"), s+data)
5224 if not req or req == 9:
5225 prstat(_("Klingons Left"), "%d" \
5226 % (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem))
5227 if not req or req == 10:
5228 if game.options & OPTION_WORLDS:
5229 plnet = game.state.galaxy[game.quadrant.i][game.quadrant.j].planet
5230 if plnet and plnet.inhabited:
5231 prstat(_("Major system"), plnet.name)
5233 prout(_("Sector is uninhabited"))
5234 elif not req or req == 11:
5235 attackreport(not req)
5238 "Request specified status data, a historical relic from slow TTYs."
5239 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5240 while scanner.next() == "IHEOL":
5241 proutn(_("Information desired? "))
5243 if scanner.token in requests:
5244 status(requests.index(scanner.token))
5246 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5247 prout((" date, condition, position, lsupport, warpfactor,"))
5248 prout((" energy, torpedoes, shields, klingons, system, time."))
5253 if damaged(DSRSENS):
5254 # Allow base's sensors if docked
5255 if game.condition != "docked":
5256 prout(_(" S.R. SENSORS DAMAGED!"))
5259 prout(_(" [Using Base's sensors]"))
5261 prout(_(" Short-range scan"))
5262 if goodScan and not damaged(DRADIO):
5263 game.state.chart[game.quadrant.i][game.quadrant.j].klingons = game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons
5264 game.state.chart[game.quadrant.i][game.quadrant.j].starbase = game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase
5265 game.state.chart[game.quadrant.i][game.quadrant.j].stars = game.state.galaxy[game.quadrant.i][game.quadrant.j].stars
5266 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
5267 prout(" 1 2 3 4 5 6 7 8 9 10")
5268 if game.condition != "docked":
5270 for i in range(QUADSIZE):
5271 proutn("%2d " % (i+1))
5272 for j in range(QUADSIZE):
5273 sectscan(goodScan, i, j)
5277 "Use computer to get estimated time of arrival for a warp jump."
5278 w1 = coord(); w2 = coord()
5280 if damaged(DCOMPTR):
5281 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5284 if scanner.next() != "IHREAL":
5287 proutn(_("Destination quadrant and/or sector? "))
5288 if scanner.next()!="IHREAL":
5291 w1.j = int(scanner.real-0.5)
5292 if scanner.next() != "IHREAL":
5295 w1.i = int(scanner.real-0.5)
5296 if scanner.next() == "IHREAL":
5297 w2.j = int(scanner.real-0.5)
5298 if scanner.next() != "IHREAL":
5301 w2.i = int(scanner.real-0.5)
5303 if game.quadrant.j>w1.i:
5307 if game.quadrant.i>w1.j:
5311 if not VALID_QUADRANT(w1.i, w1.j) or not VALID_SECTOR(w2.i, w2.j):
5314 game.dist = math.sqrt((w1.j-game.quadrant.j+0.1*(w2.j-game.sector.j))**2+
5315 (w1.i-game.quadrant.i+0.1*(w2.i-game.sector.i))**2)
5318 prout(_("Answer \"no\" if you don't know the value:"))
5321 proutn(_("Time or arrival date? "))
5322 if scanner.next()=="IHREAL":
5323 ttime = scanner.real
5324 if ttime > game.state.date:
5325 ttime -= game.state.date # Actually a star date
5326 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5327 if ttime <= 1e-10 or twarp > 10:
5328 prout(_("We'll never make it, sir."))
5335 proutn(_("Warp factor? "))
5336 if scanner.next()== "IHREAL":
5338 twarp = scanner.real
5339 if twarp<1.0 or twarp > 10.0:
5343 prout(_("Captain, certainly you can give me one of these."))
5346 ttime = (10.0*game.dist)/twarp**2
5347 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5348 if tpower >= game.energy:
5349 prout(_("Insufficient energy, sir."))
5350 if not game.shldup or tpower > game.energy*2.0:
5353 proutn(_("New warp factor to try? "))
5354 if scanner.next() == "IHREAL":
5356 twarp = scanner.real
5357 if twarp<1.0 or twarp > 10.0:
5365 prout(_("But if you lower your shields,"))
5366 proutn(_("remaining"))
5369 proutn(_("Remaining"))
5370 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5372 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5374 prout(_("Any warp speed is adequate."))
5376 prout(_("Minimum warp needed is %.2f,") % (twarp))
5377 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5378 if game.state.remtime < ttime:
5379 prout(_("Unfortunately, the Federation will be destroyed by then."))
5381 prout(_("You'll be taking risks at that speed, Captain"))
5382 if (game.isatb==1 and game.state.kscmdr == w1 and \
5383 scheduled(FSCDBAS)< ttime+game.state.date) or \
5384 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5385 prout(_("The starbase there will be destroyed by then."))
5386 proutn(_("New warp factor to try? "))
5387 if scanner.next() == "IHREAL":
5389 twarp = scanner.real
5390 if twarp<1.0 or twarp > 10.0:
5398 # Code from setup.c begins here
5401 "Issue a historically correct banner."
5403 prout(_("-SUPER- STAR TREK"))
5405 # From the FORTRAN original
5406 # prout(_("Latest update-21 Sept 78"))
5412 scanner.token = "emsave.trk"
5414 key = scanner.next()
5416 proutn(_("File name: "))
5417 key = scanner.next()
5418 if key != "IHALPHA":
5422 if '.' not in scanner.token:
5423 scanner.token += ".trk"
5425 fp = open(scanner.token, "wb")
5427 prout(_("Can't freeze game as file %s") % scanner.token)
5429 cPickle.dump(game, fp)
5433 "Retrieve saved game."
5434 game.passwd[0] = '\0'
5435 key = scanner.next()
5437 proutn(_("File name: "))
5438 key = scanner.next()
5439 if key != "IHALPHA":
5443 if '.' not in scanner.token:
5444 scanner.token += ".trk"
5446 fp = open(scanner.token, "rb")
5448 prout(_("Can't thaw game in %s") % scanner.token)
5450 game = cPickle.load(fp)
5454 # I used <http://www.memory-alpha.org> to find planets
5455 # with references in ST:TOS. Eath and the Alpha Centauri
5456 # Colony have been omitted.
5458 # Some planets marked Class G and P here will be displayed as class M
5459 # because of the way planets are generated. This is a known bug.
5462 _("Andoria (Fesoan)"), # several episodes
5463 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5464 _("Vulcan (T'Khasi)"), # many episodes
5465 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5466 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5467 _("Ardana"), # TOS: "The Cloud Minders"
5468 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5469 _("Gideon"), # TOS: "The Mark of Gideon"
5470 _("Aldebaran III"), # TOS: "The Deadly Years"
5471 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5472 _("Altair IV"), # TOS: "Amok Time
5473 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5474 _("Benecia"), # TOS: "The Conscience of the King"
5475 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5476 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5477 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5478 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5479 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5480 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5481 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5482 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5483 _("Ingraham B"), # TOS: "Operation: Annihilate"
5484 _("Janus IV"), # TOS: "The Devil in the Dark"
5485 _("Makus III"), # TOS: "The Galileo Seven"
5486 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5487 _("Omega IV"), # TOS: "The Omega Glory"
5488 _("Regulus V"), # TOS: "Amok Time
5489 _("Deneva"), # TOS: "Operation -- Annihilate!"
5490 # Worlds from BSD Trek
5491 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5492 _("Beta III"), # TOS: "The Return of the Archons"
5493 _("Triacus"), # TOS: "And the Children Shall Lead",
5494 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5496 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5497 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5498 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5499 # _("Izar"), # TOS: "Whom Gods Destroy"
5500 # _("Tiburon"), # TOS: "The Way to Eden"
5501 # _("Merak II"), # TOS: "The Cloud Minders"
5502 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5503 # _("Iotia"), # TOS: "A Piece of the Action"
5507 _("S. R. Sensors"), \
5508 _("L. R. Sensors"), \
5510 _("Photon Tubes"), \
5511 _("Life Support"), \
5512 _("Warp Engines"), \
5513 _("Impulse Engines"), \
5515 _("Subspace Radio"), \
5516 _("Shuttle Craft"), \
5518 _("Navigation System"), \
5520 _("Shield Control"), \
5526 "Prepare to play, set up cosmos."
5528 # Decide how many of everything
5530 return # frozen game
5531 # Prepare the Enterprise
5532 game.alldone = game.gamewon = game.shldchg = game.shldup = False
5534 game.state.crew = FULLCREW
5535 game.energy = game.inenrg = 5000.0
5536 game.shield = game.inshld = 2500.0
5539 game.quadrant = randplace(GALSIZE)
5540 game.sector = randplace(QUADSIZE)
5541 game.torps = game.intorps = 10
5542 game.nprobes = randrange(2, 5)
5544 for i in range(NDEVICES):
5545 game.damage[i] = 0.0
5546 # Set up assorted game parameters
5547 game.battle = coord()
5548 game.state.date = game.indate = 100.0 * randreal(20, 51)
5549 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5550 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5551 game.isatb = game.state.nplankl = 0
5552 game.state.starkl = game.state.basekl = 0
5553 game.iscraft = "onship"
5557 # Starchart is functional but we've never seen it
5558 game.lastchart = FOREVER
5559 # Put stars in the galaxy
5561 for i in range(GALSIZE):
5562 for j in range(GALSIZE):
5563 k = randrange(1, QUADSIZE**2/10+1)
5565 game.state.galaxy[i][j].stars = k
5566 # Locate star bases in galaxy
5567 for i in range(game.inbase):
5570 w = randplace(GALSIZE)
5571 if not game.state.galaxy[w.i][w.j].starbase:
5574 # C version: for (j = i-1; j > 0; j--)
5575 # so it did them in the opposite order.
5576 for j in range(1, i):
5577 # Improved placement algorithm to spread out bases
5578 distq = (w - game.state.baseq[j]).distance()
5579 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5582 prout("=== Abandoning base #%d at %s" % (i, w))
5584 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5586 prout("=== Saving base #%d, close to #%d" % (i, j))
5589 game.state.baseq.append(w)
5590 game.state.galaxy[w.i][w.j].starbase = game.state.chart[w.i][w.j].starbase = True
5591 # Position ordinary Klingon Battle Cruisers
5593 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5594 if klumper > MAXKLQUAD:
5598 klump = (1.0 - r*r)*klumper
5603 w = randplace(GALSIZE)
5604 if not game.state.galaxy[w.i][w.j].supernova and \
5605 game.state.galaxy[w.i][w.j].klingons + klump <= MAXKLQUAD:
5607 game.state.galaxy[w.i][w.j].klingons += int(klump)
5610 # Position Klingon Commander Ships
5611 for i in range(game.incom):
5613 w = randplace(GALSIZE)
5614 if not welcoming(w) or w in game.state.kcmdr:
5616 if (game.state.galaxy[w.i][w.j].klingons or withprob(0.25)):
5618 game.state.galaxy[w.i][w.j].klingons += 1
5619 game.state.kcmdr.append(w)
5620 # Locate planets in galaxy
5621 for i in range(game.inplan):
5623 w = randplace(GALSIZE)
5624 if game.state.galaxy[w.i][w.j].planet == None:
5628 new.crystals = "absent"
5629 if (game.options & OPTION_WORLDS) and i < NINHAB:
5630 new.pclass = "M" # All inhabited planets are class M
5631 new.crystals = "absent"
5633 new.name = systnames[i]
5634 new.inhabited = True
5636 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5638 new.crystals = "present"
5639 new.known = "unknown"
5640 new.inhabited = False
5641 game.state.galaxy[w.i][w.j].planet = new
5642 game.state.planets.append(new)
5644 for i in range(game.state.nromrem):
5645 w = randplace(GALSIZE)
5646 game.state.galaxy[w.i][w.j].romulans += 1
5647 # Place the Super-Commander if needed
5648 if game.state.nscrem > 0:
5650 w = randplace(GALSIZE)
5653 game.state.kscmdr = w
5654 game.state.galaxy[w.i][w.j].klingons += 1
5655 # Initialize times for extraneous events
5656 schedule(FSNOVA, expran(0.5 * game.intime))
5657 schedule(FTBEAM, expran(1.5 * (game.intime / len(game.state.kcmdr))))
5658 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5659 schedule(FBATTAK, expran(0.3*game.intime))
5661 if game.state.nscrem:
5662 schedule(FSCMOVE, 0.2777)
5667 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5668 schedule(FDISTR, expran(1.0 + game.intime))
5673 # Place thing (in tournament game, we don't want one!)
5674 # New in SST2K: never place the Thing near a starbase.
5675 # This makes sense and avoids a special case in the old code.
5677 if game.tourn is None:
5679 thing = randplace(GALSIZE)
5680 if thing not in game.state.baseq:
5683 game.state.snap = False
5684 if game.skill == SKILL_NOVICE:
5685 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5686 prout(_("a deadly Klingon invasion force. As captain of the United"))
5687 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5688 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5689 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5690 prout(_("your mission. As you proceed you may be given more time."))
5692 prout(_("You will have %d supporting starbases.") % (game.inbase))
5693 proutn(_("Starbase locations- "))
5695 prout(_("Stardate %d.") % int(game.state.date))
5697 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5698 prout(_("An unknown number of Romulans."))
5699 if game.state.nscrem:
5700 prout(_("And one (GULP) Super-Commander."))
5701 prout(_("%d stardates.") % int(game.intime))
5702 proutn(_("%d starbases in ") % game.inbase)
5703 for i in range(game.inbase):
5704 proutn(`game.state.baseq[i]`)
5707 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5708 proutn(_(" Sector %s") % game.sector)
5710 prout(_("Good Luck!"))
5711 if game.state.nscrem:
5712 prout(_(" YOU'LL NEED IT."))
5715 if len(game.enemies) - (thing == game.quadrant) - (game.tholian != None):
5717 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5718 attack(torps_ok=False)
5721 "Choose your game type."
5726 game.skill = SKILL_NONE
5728 if not scanner.inqueue: # Can start with command line options
5729 proutn(_("Would you like a regular, tournament, or saved game? "))
5731 if len(scanner.token)==0: # Try again
5733 if scanner.sees("tournament"):
5734 while scanner.next() == "IHEOL":
5735 proutn(_("Type in tournament number-"))
5736 if scanner.real == 0:
5738 continue # We don't want a blank entry
5739 game.tourn = int(round(scanner.real))
5740 random.seed(scanner.real)
5742 logfp.write("# random.seed(%d)\n" % scanner.real)
5744 if scanner.sees("saved") or scanner.sees("frozen"):
5748 if game.passwd == None:
5750 if not game.alldone:
5751 game.thawed = True # No plaque if not finished
5755 if scanner.sees("regular"):
5757 proutn(_("What is \"%s\"?") % scanner.token)
5759 while game.length==0 or game.skill==SKILL_NONE:
5760 if scanner.next() == "IHALPHA":
5761 if scanner.sees("short"):
5763 elif scanner.sees("medium"):
5765 elif scanner.sees("long"):
5767 elif scanner.sees("novice"):
5768 game.skill = SKILL_NOVICE
5769 elif scanner.sees("fair"):
5770 game.skill = SKILL_FAIR
5771 elif scanner.sees("good"):
5772 game.skill = SKILL_GOOD
5773 elif scanner.sees("expert"):
5774 game.skill = SKILL_EXPERT
5775 elif scanner.sees("emeritus"):
5776 game.skill = SKILL_EMERITUS
5778 proutn(_("What is \""))
5779 proutn(scanner.token)
5784 proutn(_("Would you like a Short, Medium, or Long game? "))
5785 elif game.skill == SKILL_NONE:
5786 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
5787 # Choose game options -- added by ESR for SST2K
5788 if scanner.next() != "IHALPHA":
5790 proutn(_("Choose your game style (or just press enter): "))
5792 if scanner.sees("plain"):
5793 # Approximates the UT FORTRAN version.
5794 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5795 game.options |= OPTION_PLAIN
5796 elif scanner.sees("almy"):
5797 # Approximates Tom Almy's version.
5798 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5799 game.options |= OPTION_ALMY
5800 elif scanner.sees("fancy"):
5802 elif len(scanner.token):
5803 proutn(_("What is \"%s\"?") % scanner.token)
5805 if game.passwd == "debug":
5807 prout("=== Debug mode enabled.")
5808 # Use parameters to generate initial values of things
5809 game.damfac = 0.5 * game.skill
5810 game.inbase = randrange(BASEMIN, BASEMAX+1)
5812 if game.options & OPTION_PLANETS:
5813 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
5814 if game.options & OPTION_WORLDS:
5815 game.inplan += int(NINHAB)
5816 game.state.nromrem = game.inrom = randrange(2 *game.skill)
5817 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
5818 game.state.remtime = 7.0 * game.length
5819 game.intime = game.state.remtime
5820 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
5821 game.incom = min(MINCMDR, int(game.skill + 0.0625*game.inkling*randreal()))
5822 game.state.remres = (game.inkling+4*game.incom)*game.intime
5823 game.inresor = game.state.remres
5824 if game.inkling > 50:
5825 game.state.inbase += 1
5828 def dropin(iquad=None):
5829 "Drop a feature on a random dot in the current quadrant."
5831 w = randplace(QUADSIZE)
5832 if game.quad[w.i][w.j] == IHDOT:
5834 if iquad is not None:
5835 game.quad[w.i][w.j] = iquad
5839 "Update our alert status."
5840 game.condition = "green"
5841 if game.energy < 1000.0:
5842 game.condition = "yellow"
5843 if game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons or game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans:
5844 game.condition = "red"
5846 game.condition="dead"
5849 "Drop new Klingon into current quadrant."
5850 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
5853 "Set up a new state of quadrant, for when we enter or re-enter it."
5856 game.neutz = game.inorbit = game.landed = False
5857 game.ientesc = game.iseenit = False
5858 # Create a blank quadrant
5859 game.quad = fill2d(QUADSIZE, lambda i, j: IHDOT)
5861 # Attempt to escape Super-commander, so tbeam back!
5864 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
5865 # cope with supernova
5868 game.klhere = q.klingons
5869 game.irhere = q.romulans
5871 game.quad[game.sector.i][game.sector.j] = game.ship
5874 # Position ordinary Klingons
5875 for i in range(game.klhere):
5877 # If we need a commander, promote a Klingon
5878 for cmdr in game.state.kcmdr:
5879 if cmdr == game.quadrant:
5880 e = game.enemies[game.klhere-1]
5881 game.quad[e.kloc.i][e.kloc.j] = IHC
5882 e.kpower = randreal(950,1350) + 50.0*game.skill
5884 # If we need a super-commander, promote a Klingon
5885 if game.quadrant == game.state.kscmdr:
5887 game.quad[e.kloc.i][e.kloc.j] = IHS
5888 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
5889 game.iscate = (game.state.remkl > 1)
5890 # Put in Romulans if needed
5891 for i in range(q.romulans):
5892 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
5893 # If quadrant needs a starbase, put it in
5895 game.base = dropin(IHB)
5896 # If quadrant needs a planet, put it in
5898 game.iplnet = q.planet
5899 if not q.planet.inhabited:
5900 game.plnet = dropin(IHP)
5902 game.plnet = dropin(IHW)
5903 # Check for condition
5906 if game.irhere > 0 and game.klhere == 0:
5908 if not damaged(DRADIO):
5910 prout(_("LT. Uhura- \"Captain, an urgent message."))
5911 prout(_(" I'll put it on audio.\" CLICK"))
5913 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
5914 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
5915 # Put in THING if needed
5916 if thing == game.quadrant:
5917 enemy(type=IHQUEST, loc=dropin(),
5918 power=randreal(6000,6500.0)+250.0*game.skill)
5919 if not damaged(DSRSENS):
5921 prout(_("Mr. Spock- \"Captain, this is most unusual."))
5922 prout(_(" Please examine your short-range scan.\""))
5923 # Decide if quadrant needs a Tholian; lighten up if skill is low
5924 if game.options & OPTION_THOLIAN:
5925 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
5926 (game.skill == SKILL_GOOD and withprob(0.05)) or \
5927 (game.skill > SKILL_GOOD and withprob(0.08)):
5930 w.i = withprob(0.5) * (QUADSIZE-1)
5931 w.j = withprob(0.5) * (QUADSIZE-1)
5932 if game.quad[w.i][w.j] == IHDOT:
5934 game.tholian = enemy(type=IHT, loc=w,
5935 power=randrange(100, 500) + 25.0*game.skill)
5936 # Reserve unoccupied corners
5937 if game.quad[0][0]==IHDOT:
5938 game.quad[0][0] = 'X'
5939 if game.quad[0][QUADSIZE-1]==IHDOT:
5940 game.quad[0][QUADSIZE-1] = 'X'
5941 if game.quad[QUADSIZE-1][0]==IHDOT:
5942 game.quad[QUADSIZE-1][0] = 'X'
5943 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
5944 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
5945 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
5946 # And finally the stars
5947 for i in range(q.stars):
5949 # Put in a few black holes
5950 for i in range(1, 3+1):
5953 # Take out X's in corners if Tholian present
5955 if game.quad[0][0]=='X':
5956 game.quad[0][0] = IHDOT
5957 if game.quad[0][QUADSIZE-1]=='X':
5958 game.quad[0][QUADSIZE-1] = IHDOT
5959 if game.quad[QUADSIZE-1][0]=='X':
5960 game.quad[QUADSIZE-1][0] = IHDOT
5961 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
5962 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
5965 "Set the self-destruct password."
5966 if game.options & OPTION_PLAIN:
5969 proutn(_("Please type in a secret password- "))
5971 game.passwd = scanner.token
5972 if game.passwd != None:
5977 game.passwd += chr(ord('a')+randrange(26))
5979 # Code from sst.c begins here
5982 "SRSCAN": OPTION_TTY,
5983 "STATUS": OPTION_TTY,
5984 "REQUEST": OPTION_TTY,
5985 "LRSCAN": OPTION_TTY,
5998 "SENSORS": OPTION_PLANETS,
5999 "ORBIT": OPTION_PLANETS,
6000 "TRANSPORT": OPTION_PLANETS,
6001 "MINE": OPTION_PLANETS,
6002 "CRYSTALS": OPTION_PLANETS,
6003 "SHUTTLE": OPTION_PLANETS,
6004 "PLANETS": OPTION_PLANETS,
6009 "PROBE": OPTION_PROBE,
6011 "FREEZE": 0, # Synonym for SAVE
6017 "SOS": 0, # Synonym for MAYDAY
6018 "CALL": 0, # Synonym for MAYDAY
6024 "Generate a list of legal commands."
6025 prout(_("LEGAL COMMANDS ARE:"))
6027 for key in commands:
6028 if not commands[key] or (commands[key] & game.options):
6029 proutn("%-12s " % key)
6031 if emitted % 5 == 4:
6036 "Browse on-line help."
6037 key = scanner.next()
6040 setwnd(prompt_window)
6041 proutn(_("Help on what command? "))
6042 key = scanner.next()
6043 setwnd(message_window)
6046 if scanner.token in commands or scanner.token == "ABBREV":
6053 cmd = scanner.token.upper()
6055 fp = open(SSTDOC, "r")
6058 fp = open(DOC_NAME, "r")
6060 prout(_("Spock- \"Captain, that information is missing from the"))
6061 proutn(_(" computer. You need to find "))
6063 prout(_(" and put it in the"))
6064 proutn(_(" current directory or to "))
6068 # This used to continue: "You need to find SST.DOC and put
6069 # it in the current directory."
6073 linebuf = fp.readline()
6075 prout(_("Spock- \"Captain, there is no information on that command.\""))
6078 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6079 linebuf = linebuf[3:].strip()
6083 prout(_("Spock- \"Captain, I've found the following information:\""))
6085 while linebuf in fp:
6086 if "******" in linebuf:
6092 "Command-interpretation loop."
6094 setwnd(message_window)
6095 while True: # command loop
6097 while True: # get a command
6102 setwnd(prompt_window)
6105 if scanner.next() == "IHEOL":
6106 if game.options & OPTION_CURSES:
6109 elif scanner.token == "":
6113 setwnd(message_window)
6115 candidates = filter(lambda x: x.startswith(scanner.token.upper()),
6117 if len(candidates) == 1:
6120 elif candidates and not (game.options & OPTION_PLAIN):
6121 prout("Commands with prefix '%s': %s" % (scanner.token, " ".join(candidates)))
6125 if cmd == "SRSCAN": # srscan
6127 elif cmd == "STATUS": # status
6129 elif cmd == "REQUEST": # status request
6131 elif cmd == "LRSCAN": # long range scan
6132 lrscan(silent=False)
6133 elif cmd == "PHASERS": # phasers
6137 elif cmd == "TORPEDO": # photon torpedos
6141 elif cmd == "MOVE": # move under warp
6143 elif cmd == "SHIELDS": # shields
6144 doshield(shraise=False)
6147 game.shldchg = False
6148 elif cmd == "DOCK": # dock at starbase
6151 attack(torps_ok=False)
6152 elif cmd == "DAMAGES": # damage reports
6154 elif cmd == "CHART": # chart
6156 elif cmd == "IMPULSE": # impulse
6158 elif cmd == "REST": # rest
6162 elif cmd == "WARP": # warp
6164 elif cmd == "SCORE": # score
6166 elif cmd == "SENSORS": # sensors
6168 elif cmd == "ORBIT": # orbit
6172 elif cmd == "TRANSPORT": # transport "beam"
6174 elif cmd == "MINE": # mine
6178 elif cmd == "CRYSTALS": # crystals
6182 elif cmd == "SHUTTLE": # shuttle
6186 elif cmd == "PLANETS": # Planet list
6188 elif cmd == "REPORT": # Game Report
6190 elif cmd == "COMPUTER": # use COMPUTER!
6192 elif cmd == "COMMANDS":
6194 elif cmd == "EMEXIT": # Emergency exit
6195 clrscr() # Hide screen
6196 freeze(True) # forced save
6197 raise SysExit,1 # And quick exit
6198 elif cmd == "PROBE":
6199 probe() # Launch probe
6202 elif cmd == "ABANDON": # Abandon Ship
6204 elif cmd == "DESTRUCT": # Self Destruct
6206 elif cmd == "SAVE": # Save Game
6209 if game.skill > SKILL_GOOD:
6210 prout(_("WARNING--Saved games produce no plaques!"))
6211 elif cmd == "DEATHRAY": # Try a desparation measure
6215 elif cmd == "DEBUGCMD": # What do we want for debug???
6217 elif cmd == "MAYDAY": # Call for help
6222 game.alldone = True # quit the game
6227 break # Game has ended
6228 if game.optime != 0.0:
6231 break # Events did us in
6232 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
6235 if hitme and not game.justin:
6236 attack(torps_ok=True)
6239 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
6250 "Emit the name of an enemy or feature."
6251 if type == IHR: s = _("Romulan")
6252 elif type == IHK: s = _("Klingon")
6253 elif type == IHC: s = _("Commander")
6254 elif type == IHS: s = _("Super-commander")
6255 elif type == IHSTAR: s = _("Star")
6256 elif type == IHP: s = _("Planet")
6257 elif type == IHB: s = _("Starbase")
6258 elif type == IHBLANK: s = _("Black hole")
6259 elif type == IHT: s = _("Tholian")
6260 elif type == IHWEB: s = _("Tholian web")
6261 elif type == IHQUEST: s = _("Stranger")
6262 elif type == IHW: s = _("Inhabited World")
6263 else: s = "Unknown??"
6266 def crmena(stars, enemy, loctype, w):
6267 "Emit the name of an enemy and his location."
6271 buf += cramen(enemy) + _(" at ")
6272 if loctype == "quadrant":
6273 buf += _("Quadrant ")
6274 elif loctype == "sector":
6279 "Emit our ship name."
6280 return{IHE:_("Enterprise"),IHF:_("Faerie Queene")}.get(game.ship,"Ship???")
6283 "Emit a line of stars"
6284 prouts("******************************************************")
6288 return -avrage*math.log(1e-7 + randreal())
6290 def randplace(size):
6291 "Choose a random location."
6293 w.i = randrange(size)
6294 w.j = randrange(size)
6304 # Get a token from the user
6307 # Fill the token quue if nothing here
6308 while not self.inqueue:
6310 if curwnd==prompt_window:
6312 setwnd(message_window)
6319 self.inqueue = line.lstrip().split() + ["IHEOL"]
6320 # From here on in it's all looking at the queue
6321 self.token = self.inqueue.pop(0)
6322 if self.token == "IHEOL":
6326 self.real = float(self.token)
6327 self.type = "IHREAL"
6332 self.token = self.token.lower()
6333 self.type = "IHALPHA"
6336 def append(self, tok):
6337 self.inqueue.append(tok)
6338 def push(self, tok):
6339 self.inqueue.insert(0, tok)
6343 # Demand input for next scan
6345 self.real = self.token = None
6347 # return "IHEOL" next time
6348 self.inqueue = ["IHEOL"]
6349 self.real = self.token = None
6351 # compares s to item and returns true if it matches to the length of s
6352 return s.startswith(self.token)
6354 # Round token value to nearest integer
6355 return int(round(scanner.real))
6359 if scanner.type != "IHREAL":
6362 s.i = scanner.int()-1
6364 if scanner.type != "IHREAL":
6367 s.j = scanner.int()-1
6370 return "<sstcanner: token=%s, type=%s, queue=%s>" % (scanner.token, scanner.type, scanner.inqueue)
6373 "Yes-or-no confirmation."
6377 if scanner.token == 'y':
6379 if scanner.token == 'n':
6382 proutn(_("Please answer with \"y\" or \"n\": "))
6385 "Complain about unparseable input."
6388 prout(_("Beg your pardon, Captain?"))
6391 "Access to the internals for debugging."
6392 proutn("Reset levels? ")
6394 if game.energy < game.inenrg:
6395 game.energy = game.inenrg
6396 game.shield = game.inshld
6397 game.torps = game.intorps
6398 game.lsupres = game.inlsr
6399 proutn("Reset damage? ")
6401 for i in range(NDEVICES):
6402 if game.damage[i] > 0.0:
6403 game.damage[i] = 0.0
6404 proutn("Toggle debug flag? ")
6408 prout("Debug output ON")
6410 prout("Debug output OFF")
6411 proutn("Cause selective damage? ")
6413 for i in range(NDEVICES):
6414 proutn("Kill %s?" % device[i])
6416 key = scanner.next()
6417 if key == "IHALPHA" and scanner.sees("y"):
6418 game.damage[i] = 10.0
6419 proutn("Examine/change events? ")
6424 FSNOVA: "Supernova ",
6427 FBATTAK: "Base Attack ",
6428 FCDBAS: "Base Destroy ",
6429 FSCMOVE: "SC Move ",
6430 FSCDBAS: "SC Base Destroy ",
6431 FDSPROB: "Probe Move ",
6432 FDISTR: "Distress Call ",
6433 FENSLV: "Enslavement ",
6434 FREPRO: "Klingon Build ",
6436 for i in range(1, NEVENTS):
6439 proutn("%.2f" % (scheduled(i)-game.state.date))
6440 if i == FENSLV or i == FREPRO:
6442 proutn(" in %s" % ev.quadrant)
6447 key = scanner.next()
6451 elif key == "IHREAL":
6452 ev = schedule(i, scanner.real)
6453 if i == FENSLV or i == FREPRO:
6455 proutn("In quadrant- ")
6456 key = scanner.next()
6457 # "IHEOL" says to leave coordinates as they are
6460 prout("Event %d canceled, no x coordinate." % (i))
6463 w.i = int(round(scanner.real))
6464 key = scanner.next()
6466 prout("Event %d canceled, no y coordinate." % (i))
6469 w.j = int(round(scanner.real))
6472 proutn("Induce supernova here? ")
6474 game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova = True
6477 if __name__ == '__main__':
6478 import getopt, socket
6480 global line, thing, game, idebug
6486 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6487 if os.getenv("TERM"):
6488 game.options |= OPTION_CURSES
6490 game.options |= OPTION_TTY
6491 seed = int(time.time())
6492 (options, arguments) = getopt.getopt(sys.argv[1:], "r:s:tx")
6493 for (switch, val) in options:
6496 replayfp = open(val, "r")
6498 sys.stderr.write("sst: can't open replay file %s\n" % val)
6501 line = replayfp.readline().strip()
6502 (leader, key, seed) = line.split()
6504 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6505 line = replayfp.readline().strip()
6506 arguments += line.split()[2:]
6508 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6510 game.options |= OPTION_TTY
6511 game.options &=~ OPTION_CURSES
6512 elif switch == '-s':
6514 elif switch == '-t':
6515 game.options |= OPTION_TTY
6516 game.options &=~ OPTION_CURSES
6517 elif switch == '-x':
6520 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6522 # where to save the input in case of bugs
6524 logfp = open("/usr/tmp/sst-input.log", "w")
6526 sys.stderr.write("sst: warning, can't open logfile\n")
6528 logfp.write("# seed %s\n" % seed)
6529 logfp.write("# options %s\n" % " ".join(arguments))
6530 logfp.write("# recorded by %s@%s on %s\n" % \
6531 (os.getenv("LOGNAME"),socket.gethostname(),time.ctime()))
6533 scanner = sstscanner()
6534 map(scanner.append, arguments)
6537 while True: # Play a game
6538 setwnd(fullscreen_window)
6544 game.alldone = False
6550 if game.tourn and game.alldone:
6551 proutn(_("Do you want your score recorded?"))
6556 proutn(_("Do you want to play again? "))
6560 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6564 except KeyboardInterrupt: