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)
3345 "Wrap up I/O. Presently a stub."
3346 stdscr.keypad(False)
3352 "Wait for user action -- OK to do nothing if on a TTY"
3353 if game.options & OPTION_CURSES:
3358 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3362 if game.skill > SKILL_FAIR:
3363 prompt = _("[CONTINUE?]")
3365 prompt = _("[PRESS ENTER TO CONTINUE]")
3367 if game.options & OPTION_CURSES:
3369 setwnd(prompt_window)
3370 prompt_window.wclear()
3371 prompt_window.addstr(prompt)
3372 prompt_window.getstr()
3373 prompt_window.clear()
3374 prompt_window.refresh()
3375 setwnd(message_window)
3378 sys.stdout.write('\n')
3381 for j in range(rows):
3382 sys.stdout.write('\n')
3386 "Skip i lines. Pause game if this would cause a scrolling event."
3387 for dummy in range(i):
3388 if game.options & OPTION_CURSES:
3389 (y, x) = curwnd.getyx()
3390 (my, mx) = curwnd.getmaxyx()
3391 if curwnd == message_window and y >= my - 3:
3397 except curses.error:
3402 if rows and linecount >= rows:
3405 sys.stdout.write('\n')
3408 "Utter a line with no following line feed."
3409 if game.options & OPTION_CURSES:
3413 sys.stdout.write(line)
3423 if not replayfp or replayfp.closed: # Don't slow down replays
3426 if game.options & OPTION_CURSES:
3430 if not replayfp or replayfp.closed:
3434 "Get a line of input."
3435 if game.options & OPTION_CURSES:
3436 line = curwnd.getstr() + "\n"
3439 if replayfp and not replayfp.closed:
3441 line = replayfp.readline()
3444 prout("*** Replay finished")
3447 elif line[0] != "#":
3450 line = raw_input() + "\n"
3456 "Change windows -- OK for this to be a no-op in tty mode."
3458 if game.options & OPTION_CURSES:
3460 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3463 "Clear to end of line -- can be a no-op in tty mode"
3464 if game.options & OPTION_CURSES:
3469 "Clear screen -- can be a no-op in tty mode."
3471 if game.options & OPTION_CURSES:
3478 "Set highlight video, if this is reasonable."
3479 if game.options & OPTION_CURSES:
3480 curwnd.attron(curses.A_REVERSE)
3483 # Things past this point have policy implications.
3487 "Hook to be called after moving to redraw maps."
3488 if game.options & OPTION_CURSES:
3491 setwnd(srscan_window)
3495 setwnd(status_window)
3496 status_window.clear()
3497 status_window.move(0, 0)
3498 setwnd(report_window)
3499 report_window.clear()
3500 report_window.move(0, 0)
3502 setwnd(lrscan_window)
3503 lrscan_window.clear()
3504 lrscan_window.move(0, 0)
3505 lrscan(silent=False)
3507 def put_srscan_sym(w, sym):
3508 "Emit symbol for short-range scan."
3509 srscan_window.move(w.i+1, w.j*2+2)
3510 srscan_window.addch(sym)
3511 srscan_window.refresh()
3514 "Enemy fall down, go boom."
3515 if game.options & OPTION_CURSES:
3517 setwnd(srscan_window)
3518 srscan_window.attron(curses.A_REVERSE)
3519 put_srscan_sym(w, game.quad[w.i][w.j])
3523 srscan_window.attroff(curses.A_REVERSE)
3524 put_srscan_sym(w, game.quad[w.i][w.j])
3525 curses.delay_output(500)
3526 setwnd(message_window)
3529 "Sound and visual effects for teleportation."
3530 if game.options & OPTION_CURSES:
3532 setwnd(message_window)
3534 prouts(" . . . . . ")
3535 if game.options & OPTION_CURSES:
3536 #curses.delay_output(1000)
3540 def tracktorpedo(origin, w, step, i, n, iquad):
3541 "Torpedo-track animation."
3542 if not game.options & OPTION_CURSES:
3546 proutn(_("Track for %s torpedo number %d- ") % (game.quad[origin.i][origin.j],i+1))
3549 proutn(_("Torpedo track- "))
3550 elif step==4 or step==9:
3554 if not damaged(DSRSENS) or game.condition=="docked":
3555 if i != 0 and step == 1:
3558 if (iquad==IHDOT) or (iquad==IHBLANK):
3559 put_srscan_sym(w, '+')
3563 put_srscan_sym(w, iquad)
3565 curwnd.attron(curses.A_REVERSE)
3566 put_srscan_sym(w, iquad)
3570 curwnd.attroff(curses.A_REVERSE)
3571 put_srscan_sym(w, iquad)
3576 "Display the current galaxy chart."
3577 if game.options & OPTION_CURSES:
3578 setwnd(message_window)
3579 message_window.clear()
3581 if game.options & OPTION_TTY:
3586 def prstat(txt, data):
3588 if game.options & OPTION_CURSES:
3590 setwnd(status_window)
3592 proutn(" " * (NSYM - len(txt)))
3595 if game.options & OPTION_CURSES:
3596 setwnd(report_window)
3598 # Code from moving.c begins here
3600 def imove(novapush):
3601 "Movement execution for warp, impulse, supernova, and tractor-beam events."
3602 w = coord(); final = coord()
3605 def no_quad_change():
3606 # No quadrant change -- compute new average enemy distances
3607 game.quad[game.sector.i][game.sector.j] = game.ship
3609 for enemy in game.enemies:
3610 finald = (w-enemy.kloc).distance()
3611 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3612 enemy.kdist = finald
3613 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3614 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3615 attack(torps_ok=False)
3616 for enemy in game.enemies:
3617 enemy.kavgd = enemy.kdist
3620 setwnd(message_window)
3623 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3624 game.inorbit = False
3625 angle = ((15.0 - game.direc) * 0.5235988)
3626 deltax = -math.sin(angle)
3627 deltay = math.cos(angle)
3628 if math.fabs(deltax) > math.fabs(deltay):
3629 bigger = math.fabs(deltax)
3631 bigger = math.fabs(deltay)
3634 # If tractor beam is to occur, don't move full distance
3635 if game.state.date+game.optime >= scheduled(FTBEAM):
3637 game.condition = "red"
3638 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3639 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3640 # Move within the quadrant
3641 game.quad[game.sector.i][game.sector.j] = IHDOT
3644 n = int(10.0*game.dist*bigger+0.5)
3646 for m in range(1, n+1):
3651 if not VALID_SECTOR(w.i, w.j):
3652 # Leaving quadrant -- allow final enemy attack
3653 # Don't do it if being pushed by Nova
3654 if len(game.enemies) != 0 and not novapush:
3656 for enemy in game.enemies:
3657 finald = (w - enemy.kloc).distance()
3658 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3660 # Stas Sergeev added the condition
3661 # that attacks only happen if Klingons
3662 # are present and your skill is good.
3664 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3665 attack(torps_ok=False)
3668 # compute final position -- new quadrant and sector
3669 x = (QUADSIZE*game.quadrant.i)+game.sector.i
3670 y = (QUADSIZE*game.quadrant.j)+game.sector.j
3671 w.i = int(round(x+10.0*game.dist*bigger*deltax))
3672 w.j = int(round(y+10.0*game.dist*bigger*deltay))
3673 # check for edge of galaxy
3683 if w.i >= GALSIZE*QUADSIZE:
3684 w.i = (GALSIZE*QUADSIZE*2) - w.i
3686 if w.j >= GALSIZE*QUADSIZE:
3687 w.j = (GALSIZE*QUADSIZE*2) - w.j
3695 if game.nkinks == 3:
3696 # Three strikes -- you're out!
3700 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3701 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3702 prout(_("YOU WILL BE DESTROYED."))
3703 # Compute final position in new quadrant
3704 if trbeam: # Don't bother if we are to be beamed
3706 game.quadrant.i = w.i/QUADSIZE
3707 game.quadrant.j = w.j/QUADSIZE
3708 game.sector.i = w.i - (QUADSIZE*game.quadrant.i)
3709 game.sector.j = w.j - (QUADSIZE*game.quadrant.j)
3711 prout(_("Entering Quadrant %s.") % game.quadrant)
3712 game.quad[game.sector.i][game.sector.j] = game.ship
3714 if game.skill>SKILL_NOVICE:
3715 attack(torps_ok=False)
3717 iquad = game.quad[w.i][w.j]
3719 # object encountered in flight path
3720 stopegy = 50.0*game.dist/game.optime
3721 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3722 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3724 for enemy in game.enemies:
3725 if enemy.kloc == game.sector:
3727 collision(rammed=False, enemy=enemy)
3729 elif iquad == IHBLANK:
3731 prouts(_("***RED ALERT! RED ALERT!"))
3733 proutn("***" + crmshp())
3734 proutn(_(" pulled into black hole at Sector %s") % w)
3736 # Getting pulled into a black hole was certain
3737 # death in Almy's original. Stas Sergeev added a
3738 # possibility that you'll get timewarped instead.
3741 for m in range(NDEVICES):
3742 if game.damage[m]>0:
3744 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3745 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3755 prout(_(" encounters Tholian web at %s;") % w)
3757 prout(_(" blocked by object at %s;") % w)
3758 proutn(_("Emergency stop required "))
3759 prout(_("%2d units of energy.") % int(stopegy))
3760 game.energy -= stopegy
3761 final.i = int(round(deltax))
3762 final.j = int(round(deltay))
3764 if game.energy <= 0:
3770 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3777 "Dock our ship at a starbase."
3779 if game.condition == "docked" and verbose:
3780 prout(_("Already docked."))
3783 prout(_("You must first leave standard orbit."))
3785 if not game.base.is_valid() or abs(game.sector.i-game.base.i) > 1 or abs(game.sector.j-game.base.j) > 1:
3786 prout(crmshp() + _(" not adjacent to base."))
3788 game.condition = "docked"
3792 if game.energy < game.inenrg:
3793 game.energy = game.inenrg
3794 game.shield = game.inshld
3795 game.torps = game.intorps
3796 game.lsupres = game.inlsr
3797 game.state.crew = FULLCREW
3798 if not damaged(DRADIO) and \
3799 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
3800 # get attack report from base
3801 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
3805 # This program originally required input in terms of a (clock)
3806 # direction and distance. Somewhere in history, it was changed to
3807 # cartesian coordinates. So we need to convert. Probably
3808 # "manual" input should still be done this way -- it's a real
3809 # pain if the computer isn't working! Manual mode is still confusing
3810 # because it involves giving x and y motions, yet the coordinates
3811 # are always displayed y - x, where +y is downward!
3813 def getcourse(isprobe, akey):
3814 "Get a course and distance from the user."
3816 dquad = copy.copy(game.quadrant)
3817 navmode = "unspecified"
3821 if game.landed and not isprobe:
3822 prout(_("Dummy! You can't leave standard orbit until you"))
3823 proutn(_("are back aboard the ship."))
3826 while navmode == "unspecified":
3827 if damaged(DNAVSYS):
3829 prout(_("Computer damaged; manual navigation only"))
3831 prout(_("Computer damaged; manual movement only"))
3836 if isprobe and akey != -1:
3837 # For probe launch, use pre-scanned value first time
3841 key = scanner.next()
3843 proutn(_("Manual or automatic- "))
3846 elif key == "IHALPHA":
3847 if scanner.sees("manual"):
3849 key = scanner.next()
3851 elif scanner.sees("automatic"):
3852 navmode = "automatic"
3853 key = scanner.next()
3861 prout(_("(Manual navigation assumed.)"))
3863 prout(_("(Manual movement assumed.)"))
3866 if navmode == "automatic":
3867 while key == "IHEOL":
3869 proutn(_("Target quadrant or quadrant§or- "))
3871 proutn(_("Destination sector or quadrant§or- "))
3874 key = scanner.next()
3878 xi = int(round(scanner.real))-1
3879 key = scanner.next()
3883 xj = int(round(scanner.real))-1
3884 key = scanner.next()
3886 # both quadrant and sector specified
3887 xk = int(round(scanner.real))-1
3888 key = scanner.next()
3892 xl = int(round(scanner.real))-1
3898 # only one pair of numbers was specified
3900 # only quadrant specified -- go to center of dest quad
3903 dsect.j = dsect.i = 4 # preserves 1-origin behavior
3905 # only sector specified
3909 if not VALID_QUADRANT(dquad.i,dquad.j) or not VALID_SECTOR(dsect.i,dsect.j):
3916 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
3918 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
3919 # the actual deltas get computed here
3921 delta.j = dquad.j-game.quadrant.j + 0.1*(dsect.j-game.sector.j)
3922 delta.i = game.quadrant.i-dquad.i + 0.1*(game.sector.i-dsect.i)
3924 while key == "IHEOL":
3925 proutn(_("X and Y displacements- "))
3928 key = scanner.next()
3933 delta.j = scanner.real
3934 key = scanner.next()
3938 delta.i = scanner.real
3939 # Check for zero movement
3940 if delta.i == 0 and delta.j == 0:
3943 if itemp == "verbose" and not isprobe:
3945 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
3946 # Course actually laid in.
3947 game.dist = delta.distance()
3948 game.direc = delta.bearing()
3949 if game.direc < 0.0:
3955 "Move under impulse power."
3957 if damaged(DIMPULS):
3960 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
3962 if game.energy > 30.0:
3963 if not getcourse(isprobe=False, akey=0):
3965 power = 20.0 + 100.0*game.dist
3968 if power >= game.energy:
3969 # Insufficient power for trip
3971 prout(_("First Officer Spock- \"Captain, the impulse engines"))
3972 prout(_("require 20.0 units to engage, plus 100.0 units per"))
3973 if game.energy > 30:
3974 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
3975 int(0.01 * (game.energy-20.0)-0.05))
3976 prout(_(" quadrants.\""))
3978 prout(_("quadrant. They are, therefore, useless.\""))
3981 # Make sure enough time is left for the trip
3982 game.optime = game.dist/0.095
3983 if game.optime >= game.state.remtime:
3984 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
3985 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
3986 proutn(_("we dare spend the time?\" "))
3989 # Activate impulse engines and pay the cost
3990 imove(novapush=False)
3994 power = 20.0 + 100.0*game.dist
3995 game.energy -= power
3996 game.optime = game.dist/0.095
3997 if game.energy <= 0:
4002 "ove under warp drive."
4003 blooey = False; twarp = False
4004 if not timewarp: # Not WARPX entry
4006 if game.damage[DWARPEN] > 10.0:
4009 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4011 if damaged(DWARPEN) and game.warpfac > 4.0:
4014 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4015 prout(_(" is repaired, I can only give you warp 4.\""))
4017 # Read in course and distance
4018 if not getcourse(isprobe=False, akey=0):
4020 # Make sure starship has enough energy for the trip
4021 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4022 if power >= game.energy:
4023 # Insufficient power for trip
4026 prout(_("Engineering to bridge--"))
4027 if not game.shldup or 0.5*power > game.energy:
4028 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4030 prout(_("We can't do it, Captain. We don't have enough energy."))
4032 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4035 prout(_("if you'll lower the shields."))
4039 prout(_("We haven't the energy to go that far with the shields up."))
4042 # Make sure enough time is left for the trip
4043 game.optime = 10.0*game.dist/game.warpfac**2
4044 if game.optime >= 0.8*game.state.remtime:
4046 prout(_("First Officer Spock- \"Captain, I compute that such"))
4047 proutn(_(" a trip would require approximately %2.0f") %
4048 (100.0*game.optime/game.state.remtime))
4049 prout(_(" percent of our"))
4050 proutn(_(" remaining time. Are you sure this is wise?\" "))
4056 if game.warpfac > 6.0:
4057 # Decide if engine damage will occur
4058 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4059 prob = game.dist*(6.0-game.warpfac)**2/66.666666666
4060 if prob > randreal():
4062 game.dist = randreal(game.dist)
4063 # Decide if time warp will occur
4064 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4066 if idebug and game.warpfac==10 and not twarp:
4068 proutn("=== Force time warp? ")
4072 # If time warp or engine damage, check path
4073 # If it is obstructed, don't do warp or damage
4074 angle = ((15.0-game.direc)*0.5235998)
4075 deltax = -math.sin(angle)
4076 deltay = math.cos(angle)
4077 if math.fabs(deltax) > math.fabs(deltay):
4078 bigger = math.fabs(deltax)
4080 bigger = math.fabs(deltay)
4083 n = 10.0 * game.dist * bigger +0.5
4086 for l in range(1, n+1):
4091 if not VALID_SECTOR(ix, iy):
4093 if game.quad[ix][iy] != IHDOT:
4096 # Activate Warp Engines and pay the cost
4097 imove(novapush=False)
4100 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4101 if game.energy <= 0:
4103 game.optime = 10.0*game.dist/game.warpfac**2
4107 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4109 prout(_("Engineering to bridge--"))
4110 prout(_(" Scott here. The warp engines are damaged."))
4111 prout(_(" We'll have to reduce speed to warp 4."))
4116 "Change the warp factor."
4122 proutn(_("Warp factor- "))
4127 if game.damage[DWARPEN] > 10.0:
4128 prout(_("Warp engines inoperative."))
4130 if damaged(DWARPEN) and scanner.real > 4.0:
4131 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4132 prout(_(" but right now we can only go warp 4.\""))
4134 if scanner.real > 10.0:
4135 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4137 if scanner.real < 1.0:
4138 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4140 oldfac = game.warpfac
4141 game.warpfac = scanner.real
4142 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4143 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4146 if game.warpfac < 8.00:
4147 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4149 if game.warpfac == 10.0:
4150 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4152 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4156 "Cope with being tossed out of quadrant by supernova or yanked by beam."
4158 # is captain on planet?
4160 if damaged(DTRANSP):
4163 prout(_("Scotty rushes to the transporter controls."))
4165 prout(_("But with the shields up it's hopeless."))
4167 prouts(_("His desperate attempt to rescue you . . ."))
4172 prout(_("SUCCEEDS!"))
4175 proutn(_("The crystals mined were "))
4183 # Check to see if captain in shuttle craft
4188 # Inform captain of attempt to reach safety
4192 prouts(_("***RED ALERT! RED ALERT!"))
4194 proutn(_("The %s has stopped in a quadrant containing") % crmshp())
4195 prouts(_(" a supernova."))
4197 prout(_("***Emergency automatic override attempts to hurl ")+crmshp())
4199 prout(_("safely out of quadrant."))
4200 if not damaged(DRADIO):
4201 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
4202 # Try to use warp engines
4203 if damaged(DWARPEN):
4205 prout(_("Warp engines damaged."))
4208 game.warpfac = randreal(6.0, 8.0)
4209 prout(_("Warp factor set to %d") % int(game.warpfac))
4210 power = 0.75*game.energy
4211 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4212 distreq = randreal(math.sqrt(2))
4213 if distreq < game.dist:
4215 game.optime = 10.0*game.dist/game.warpfac**2
4216 game.direc = randreal(12) # How dumb!
4218 game.inorbit = False
4221 # This is bad news, we didn't leave quadrant.
4225 prout(_("Insufficient energy to leave quadrant."))
4228 # Repeat if another snova
4229 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
4231 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
4232 finish(FWON) # Snova killed remaining enemy.
4235 "Let's do the time warp again."
4236 prout(_("***TIME WARP ENTERED."))
4237 if game.state.snap and withprob(0.5):
4239 prout(_("You are traveling backwards in time %d stardates.") %
4240 int(game.state.date-game.snapsht.date))
4241 game.state = game.snapsht
4242 game.state.snap = False
4243 if len(game.state.kcmdr):
4244 schedule(FTBEAM, expran(game.intime/len(game.state.kcmdr)))
4245 schedule(FBATTAK, expran(0.3*game.intime))
4246 schedule(FSNOVA, expran(0.5*game.intime))
4247 # next snapshot will be sooner
4248 schedule(FSNAP, expran(0.25*game.state.remtime))
4250 if game.state.nscrem:
4251 schedule(FSCMOVE, 0.2777)
4255 game.battle.invalidate()
4257 # Make sure Galileo is consistant -- Snapshot may have been taken
4258 # when on planet, which would give us two Galileos!
4260 for l in range(game.inplan):
4261 if game.state.planets[l].known == "shuttle_down":
4263 if game.iscraft == "onship" and game.ship==IHE:
4264 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4265 game.iscraft = "offship"
4266 # Likewise, if in the original time the Galileo was abandoned, but
4267 # was on ship earlier, it would have vanished -- let's restore it.
4268 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4269 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4270 game.iscraft = "onship"
4271 # There used to be code to do the actual reconstrction here,
4272 # but the starchart is now part of the snapshotted galaxy state.
4273 prout(_("Spock has reconstructed a correct star chart from memory"))
4275 # Go forward in time
4276 game.optime = -0.5*game.intime*math.log(randreal())
4277 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4278 # cheat to make sure no tractor beams occur during time warp
4279 postpone(FTBEAM, game.optime)
4280 game.damage[DRADIO] += game.optime
4282 events() # Stas Sergeev added this -- do pending events
4285 "Launch deep-space probe."
4286 # New code to launch a deep space probe
4287 if game.nprobes == 0:
4290 if game.ship == IHE:
4291 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4293 prout(_("Ye Faerie Queene has no deep space probes."))
4298 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4300 if is_scheduled(FDSPROB):
4303 if damaged(DRADIO) and game.condition != "docked":
4304 prout(_("Spock- \"Records show the previous probe has not yet"))
4305 prout(_(" reached its destination.\""))
4307 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4309 key = scanner.next()
4311 # slow mode, so let Kirk know how many probes there are left
4312 if game.nprobes == 1:
4313 prout(_("1 probe left."))
4315 prout(_("%d probes left") % game.nprobes)
4316 proutn(_("Are you sure you want to fire a probe? "))
4319 game.isarmed = False
4320 if key == "IHALPHA" and scanner.token == "armed":
4322 key = scanner.next()
4323 elif key == "IHEOL":
4324 proutn(_("Arm NOVAMAX warhead? "))
4326 if not getcourse(isprobe=True, akey=key):
4329 angle = ((15.0 - game.direc) * 0.5235988)
4330 game.probeinx = -math.sin(angle)
4331 game.probeiny = math.cos(angle)
4332 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4333 bigger = math.fabs(game.probeinx)
4335 bigger = math.fabs(game.probeiny)
4336 game.probeiny /= bigger
4337 game.probeinx /= bigger
4338 game.proben = 10.0*game.dist*bigger +0.5
4339 game.probex = game.quadrant.i*QUADSIZE + game.sector.i - 1 # We will use better packing than original
4340 game.probey = game.quadrant.j*QUADSIZE + game.sector.j - 1
4341 game.probec = game.quadrant
4342 schedule(FDSPROB, 0.01) # Time to move one sector
4343 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4348 "Yell for help from nearest starbase."
4349 # There's more than one way to move in this game!
4351 # Test for conditions which prevent calling for help
4352 if game.condition == "docked":
4353 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4356 prout(_("Subspace radio damaged."))
4358 if not game.state.baseq:
4359 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4362 prout(_("You must be aboard the %s.") % crmshp())
4364 # OK -- call for help from nearest starbase
4367 # There's one in this quadrant
4368 ddist = (game.base - game.sector).distance()
4371 for ibq in game.state.baseq:
4372 xdist = QUADSIZE * (ibq - game.quadrant).distance()
4375 # Since starbase not in quadrant, set up new quadrant
4378 # dematerialize starship
4379 game.quad[game.sector.i][game.sector.j]=IHDOT
4380 proutn(_("Starbase in Quadrant %s responds--%s dematerializes") \
4381 % (game.quadrant, crmshp()))
4382 game.sector.invalidate()
4383 for m in range(1, 5+1):
4384 w = game.base.scatter()
4385 if VALID_SECTOR(w.i,w.j) and game.quad[w.i][w.j]==IHDOT:
4386 # found one -- finish up
4389 if not game.sector.is_valid():
4390 prout(_("You have been lost in space..."))
4391 finish(FMATERIALIZE)
4393 # Give starbase three chances to rematerialize starship
4394 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4395 for m in range(1, 3+1):
4396 if m == 1: proutn(_("1st"))
4397 elif m == 2: proutn(_("2nd"))
4398 elif m == 3: proutn(_("3rd"))
4399 proutn(_(" attempt to re-materialize ") + crmshp())
4400 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4403 if randreal() > probf:
4406 curses.delay_output(500)
4409 game.quad[ix][iy]=IHQUEST
4412 setwnd(message_window)
4413 finish(FMATERIALIZE)
4415 game.quad[ix][iy]=game.ship
4417 prout(_("succeeds."))
4421 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4426 if game.condition=="docked":
4428 prout(_("You cannot abandon Ye Faerie Queene."))
4431 # Must take shuttle craft to exit
4432 if game.damage[DSHUTTL]==-1:
4433 prout(_("Ye Faerie Queene has no shuttle craft."))
4435 if game.damage[DSHUTTL]<0:
4436 prout(_("Shuttle craft now serving Big Macs."))
4438 if game.damage[DSHUTTL]>0:
4439 prout(_("Shuttle craft damaged."))
4442 prout(_("You must be aboard the ship."))
4444 if game.iscraft != "onship":
4445 prout(_("Shuttle craft not currently available."))
4447 # Emit abandon ship messages
4449 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4451 prouts(_("***ALL HANDS ABANDON SHIP!"))
4453 prout(_("Captain and crew escape in shuttle craft."))
4454 if not game.state.baseq:
4455 # Oops! no place to go...
4458 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
4460 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4461 prout(_("Remainder of ship's complement beam down"))
4462 prout(_("to nearest habitable planet."))
4463 elif q.planet != None and not damaged(DTRANSP):
4464 prout(_("Remainder of ship's complement beam down to %s.") %
4467 prout(_("Entire crew of %d left to die in outer space.") %
4469 game.casual += game.state.crew
4470 game.abandoned += game.state.crew
4471 # If at least one base left, give 'em the Faerie Queene
4473 game.icrystl = False # crystals are lost
4474 game.nprobes = 0 # No probes
4475 prout(_("You are captured by Klingons and released to"))
4476 prout(_("the Federation in a prisoner-of-war exchange."))
4477 nb = randrange(len(game.state.baseq))
4478 # Set up quadrant and position FQ adjacient to base
4479 if not game.quadrant == game.state.baseq[nb]:
4480 game.quadrant = game.state.baseq[nb]
4481 game.sector.i = game.sector.j = 5
4484 # position next to base by trial and error
4485 game.quad[game.sector.i][game.sector.j] = IHDOT
4486 for l in range(QUADSIZE):
4487 game.sector = game.base.scatter()
4488 if VALID_SECTOR(game.sector.i, game.sector.j) and \
4489 game.quad[game.sector.i][game.sector.j] == IHDOT:
4492 break # found a spot
4493 game.sector.i=QUADSIZE/2
4494 game.sector.j=QUADSIZE/2
4496 # Get new commission
4497 game.quad[game.sector.i][game.sector.j] = game.ship = IHF
4498 game.state.crew = FULLCREW
4499 prout(_("Starfleet puts you in command of another ship,"))
4500 prout(_("the Faerie Queene, which is antiquated but,"))
4501 prout(_("still useable."))
4503 prout(_("The dilithium crystals have been moved."))
4505 game.iscraft = "offship" # Galileo disappears
4507 game.condition="docked"
4508 for l in range(NDEVICES):
4509 game.damage[l] = 0.0
4510 game.damage[DSHUTTL] = -1
4511 game.energy = game.inenrg = 3000.0
4512 game.shield = game.inshld = 1250.0
4513 game.torps = game.intorps = 6
4514 game.lsupres=game.inlsr=3.0
4519 # Code from planets.c begins here.
4522 "Abort a lengthy operation if an event interrupts it."
4525 if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.justin:
4530 "Report on (uninhabited) planets in the galaxy."
4534 prout(_("Spock- \"Planet report follows, Captain.\""))
4536 for i in range(game.inplan):
4537 if game.state.planets[i].pclass == "destroyed":
4539 if (game.state.planets[i].known != "unknown" \
4540 and not game.state.planets[i].inhabited) \
4543 if idebug and game.state.planets[i].known=="unknown":
4544 proutn("(Unknown) ")
4545 proutn(_("Quadrant %s") % game.state.planets[i].quadrant)
4546 proutn(_(" class "))
4547 proutn(game.state.planets[i].pclass)
4549 if game.state.planets[i].crystals != present:
4551 prout(_("dilithium crystals present."))
4552 if game.state.planets[i].known=="shuttle_down":
4553 prout(_(" Shuttle Craft Galileo on surface."))
4555 prout(_("No information available."))
4558 "Enter standard orbit."
4562 prout(_("Already in standard orbit."))
4564 if damaged(DWARPEN) and damaged(DIMPULS):
4565 prout(_("Both warp and impulse engines damaged."))
4567 if not game.plnet.is_valid():
4568 prout("There is no planet in this sector.")
4570 if abs(game.sector.i-game.plnet.i)>1 or abs(game.sector.j-game.plnet.j)>1:
4571 prout(crmshp() + _(" not adjacent to planet."))
4574 game.optime = randreal(0.02, 0.05)
4575 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4579 game.height = randreal(1400, 8600)
4580 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4585 "Examine planets in this quadrant."
4586 if damaged(DSRSENS):
4587 if game.options & OPTION_TTY:
4588 prout(_("Short range sensors damaged."))
4590 if game.iplnet == None:
4591 if game.options & OPTION_TTY:
4592 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4594 if game.iplnet.known == "unknown":
4595 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4597 prout(_(" Planet at Sector %s is of class %s.") %
4598 (game.plnet, game.iplnet.pclass))
4599 if game.iplnet.known=="shuttle_down":
4600 prout(_(" Sensors show Galileo still on surface."))
4601 proutn(_(" Readings indicate"))
4602 if game.iplnet.crystals != "present":
4604 prout(_(" dilithium crystals present.\""))
4605 if game.iplnet.known == "unknown":
4606 game.iplnet.known = "known"
4607 elif game.iplnet.inhabited:
4608 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4609 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4612 "Use the transporter."
4616 if damaged(DTRANSP):
4617 prout(_("Transporter damaged."))
4618 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4620 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4624 if not game.inorbit:
4625 prout(crmshp() + _(" not in standard orbit."))
4628 prout(_("Impossible to transport through shields."))
4630 if game.iplnet.known=="unknown":
4631 prout(_("Spock- \"Captain, we have no information on this planet"))
4632 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4633 prout(_(" you may not go down.\""))
4635 if not game.landed and game.iplnet.crystals=="absent":
4636 prout(_("Spock- \"Captain, I fail to see the logic in"))
4637 prout(_(" exploring a planet with no dilithium crystals."))
4638 proutn(_(" Are you sure this is wise?\" "))
4642 if not (game.options & OPTION_PLAIN):
4643 nrgneed = 50 * game.skill + game.height / 100.0
4644 if nrgneed > game.energy:
4645 prout(_("Engineering to bridge--"))
4646 prout(_(" Captain, we don't have enough energy for transportation."))
4648 if not game.landed and nrgneed * 2 > game.energy:
4649 prout(_("Engineering to bridge--"))
4650 prout(_(" Captain, we have enough energy only to transport you down to"))
4651 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4652 if game.iplnet.known == "shuttle_down":
4653 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4654 proutn(_(" Are you sure this is wise?\" "))
4659 # Coming from planet
4660 if game.iplnet.known=="shuttle_down":
4661 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4665 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4666 prout(_("Landing party assembled, ready to beam up."))
4668 prout(_("Kirk whips out communicator..."))
4669 prouts(_("BEEP BEEP BEEP"))
4671 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4674 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4676 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4678 prout(_("Kirk- \"Energize.\""))
4681 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4684 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4686 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4689 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4690 game.landed = not game.landed
4691 game.energy -= nrgneed
4693 prout(_("Transport complete."))
4694 if game.landed and game.iplnet.known=="shuttle_down":
4695 prout(_("The shuttle craft Galileo is here!"))
4696 if not game.landed and game.imine:
4703 "Strip-mine a world for dilithium."
4707 prout(_("Mining party not on planet."))
4709 if game.iplnet.crystals == "mined":
4710 prout(_("This planet has already been strip-mined for dilithium."))
4712 elif game.iplnet.crystals == "absent":
4713 prout(_("No dilithium crystals on this planet."))
4716 prout(_("You've already mined enough crystals for this trip."))
4718 if game.icrystl and game.cryprob == 0.05:
4719 prout(_("With all those fresh crystals aboard the ") + crmshp())
4720 prout(_("there's no reason to mine more at this time."))
4722 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4725 prout(_("Mining operation complete."))
4726 game.iplnet.crystals = "mined"
4727 game.imine = game.ididit = True
4730 "Use dilithium crystals."
4734 if not game.icrystl:
4735 prout(_("No dilithium crystals available."))
4737 if game.energy >= 1000:
4738 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4739 prout(_(" except when Condition Yellow exists."))
4741 prout(_("Spock- \"Captain, I must warn you that loading"))
4742 prout(_(" raw dilithium crystals into the ship's power"))
4743 prout(_(" system may risk a severe explosion."))
4744 proutn(_(" Are you sure this is wise?\" "))
4749 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
4750 prout(_(" Mr. Spock and I will try it.\""))
4752 prout(_("Spock- \"Crystals in place, Sir."))
4753 prout(_(" Ready to activate circuit.\""))
4755 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
4757 if with(game.cryprob):
4758 prouts(_(" \"Activating now! - - No good! It's***"))
4760 prouts(_("***RED ALERT! RED A*L********************************"))
4763 prouts(_("****************** KA-BOOM!!!! *******************"))
4767 game.energy += randreal(5000.0, 5500.0)
4768 prouts(_(" \"Activating now! - - "))
4769 prout(_("The instruments"))
4770 prout(_(" are going crazy, but I think it's"))
4771 prout(_(" going to work!! Congratulations, Sir!\""))
4776 "Use shuttlecraft for planetary jaunt."
4779 if damaged(DSHUTTL):
4780 if game.damage[DSHUTTL] == -1.0:
4781 if game.inorbit and game.iplnet.known == "shuttle_down":
4782 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
4784 prout(_("Ye Faerie Queene had no shuttle craft."))
4785 elif game.damage[DSHUTTL] > 0:
4786 prout(_("The Galileo is damaged."))
4787 else: # game.damage[DSHUTTL] < 0
4788 prout(_("Shuttle craft is now serving Big Macs."))
4790 if not game.inorbit:
4791 prout(crmshp() + _(" not in standard orbit."))
4793 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
4794 prout(_("Shuttle craft not currently available."))
4796 if not game.landed and game.iplnet.known=="shuttle_down":
4797 prout(_("You will have to beam down to retrieve the shuttle craft."))
4799 if game.shldup or game.condition == "docked":
4800 prout(_("Shuttle craft cannot pass through shields."))
4802 if game.iplnet.known=="unknown":
4803 prout(_("Spock- \"Captain, we have no information on this planet"))
4804 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4805 prout(_(" you may not fly down.\""))
4807 game.optime = 3.0e-5*game.height
4808 if game.optime >= 0.8*game.state.remtime:
4809 prout(_("First Officer Spock- \"Captain, I compute that such"))
4810 proutn(_(" a maneuver would require approximately %2d%% of our") % \
4811 int(100*game.optime/game.state.remtime))
4812 prout(_("remaining time."))
4813 proutn(_("Are you sure this is wise?\" "))
4819 if game.iscraft == "onship":
4821 if not damaged(DTRANSP):
4822 proutn(_("Spock- \"Would you rather use the transporter?\" "))
4826 proutn(_("Shuttle crew"))
4828 proutn(_("Rescue party"))
4829 prout(_(" boards Galileo and swoops toward planet surface."))
4830 game.iscraft = "offship"
4834 game.iplnet.known="shuttle_down"
4835 prout(_("Trip complete."))
4838 # Ready to go back to ship
4839 prout(_("You and your mining party board the"))
4840 prout(_("shuttle craft for the trip back to the Enterprise."))
4842 prouts(_("The short hop begins . . ."))
4844 game.iplnet.known="known"
4850 game.iscraft = "onship"
4856 prout(_("Trip complete."))
4859 # Kirk on ship and so is Galileo
4860 prout(_("Mining party assembles in the hangar deck,"))
4861 prout(_("ready to board the shuttle craft \"Galileo\"."))
4863 prouts(_("The hangar doors open; the trip begins."))
4866 game.iscraft = "offship"
4869 game.iplnet.known = "shuttle_down"
4872 prout(_("Trip complete."))
4876 "Use the big zapper."
4880 if game.ship != IHE:
4881 prout(_("Ye Faerie Queene has no death ray."))
4883 if len(game.enemies)==0:
4884 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
4887 prout(_("Death Ray is damaged."))
4889 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
4890 prout(_(" is highly unpredictible. Considering the alternatives,"))
4891 proutn(_(" are you sure this is wise?\" "))
4894 prout(_("Spock- \"Acknowledged.\""))
4897 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
4899 prout(_("Crew scrambles in emergency preparation."))
4900 prout(_("Spock and Scotty ready the death ray and"))
4901 prout(_("prepare to channel all ship's power to the device."))
4903 prout(_("Spock- \"Preparations complete, sir.\""))
4904 prout(_("Kirk- \"Engage!\""))
4906 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
4909 if game.options & OPTION_PLAIN:
4913 prouts(_("Sulu- \"Captain! It's working!\""))
4915 while len(game.enemies) > 0:
4916 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.i][game.enemies[1].kloc.j],game.enemies[1].kloc)
4917 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
4918 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) == 0:
4920 if (game.options & OPTION_PLAIN) == 0:
4921 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
4923 prout(_(" is still operational.\""))
4925 prout(_(" has been rendered nonfunctional.\""))
4926 game.damage[DDRAY] = 39.95
4928 r = randreal() # Pick failure method
4930 prouts(_("Sulu- \"Captain! It's working!\""))
4932 prouts(_("***RED ALERT! RED ALERT!"))
4934 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
4936 prouts(_("***RED ALERT! RED A*L********************************"))
4939 prouts(_("****************** KA-BOOM!!!! *******************"))
4944 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
4946 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
4948 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
4949 prout(_(" have apparently been transformed into strange mutations."))
4950 prout(_(" Vulcans do not seem to be affected."))
4952 prout(_("Kirk- \"Raauch! Raauch!\""))
4957 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
4959 proutn(_("Spock- \"I believe the word is"))
4960 prouts(_(" *ASTONISHING*"))
4961 prout(_(" Mr. Sulu."))
4962 for i in range(QUADSIZE):
4963 for j in range(QUADSIZE):
4964 if game.quad[i][j] == IHDOT:
4965 game.quad[i][j] = IHQUEST
4966 prout(_(" Captain, our quadrant is now infested with"))
4967 prouts(_(" - - - - - - *THINGS*."))
4969 prout(_(" I have no logical explanation.\""))
4971 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
4973 prout(_("Scotty- \"There are so many tribbles down here"))
4974 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
4978 # Code from reports.c begins here
4980 def attackreport(curt):
4981 "eport status of bases under attack."
4983 if is_scheduled(FCDBAS):
4984 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
4985 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
4986 elif game.isatb == 1:
4987 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
4988 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
4990 prout(_("No Starbase is currently under attack."))
4992 if is_scheduled(FCDBAS):
4993 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
4995 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
4999 # report on general game status
5001 s1 = "" and game.thawed and _("thawed ")
5002 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5003 s3 = (None, _("novice"). _("fair"),
5004 _("good"), _("expert"), _("emeritus"))[game.skill]
5005 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5006 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5007 prout(_("No plaque is allowed."))
5009 prout(_("This is tournament game %d.") % game.tourn)
5010 prout(_("Your secret password is \"%s\"") % game.passwd)
5011 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)),
5012 (game.inkling + game.incom + game.inscom)))
5013 if game.incom - len(game.state.kcmdr):
5014 prout(_(", including %d Commander%s.") % (game.incom - len(game.state.kcmdr), (_("s"), "")[(game.incom - len(game.state.kcmdr))==1]))
5015 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5016 prout(_(", but no Commanders."))
5019 if game.skill > SKILL_FAIR:
5020 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5021 if len(game.state.baseq) != game.inbase:
5023 if game.inbase-len(game.state.baseq)==1:
5024 proutn(_("has been 1 base"))
5026 proutn(_("have been %d bases") % (game.inbase-len(game.state.baseq)))
5027 prout(_(" destroyed, %d remaining.") % len(game.state.baseq))
5029 prout(_("There are %d bases.") % game.inbase)
5030 if communicating() or game.iseenit:
5031 # Don't report this if not seen and
5032 # either the radio is dead or not at base!
5036 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5038 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5039 if game.ship == IHE:
5040 proutn(_("You have "))
5042 proutn("%d" % (game.nprobes))
5045 proutn(_(" deep space probe"))
5049 if communicating() and is_scheduled(FDSPROB):
5051 proutn(_("An armed deep space probe is in "))
5053 proutn(_("A deep space probe is in "))
5054 prout("Quadrant %s." % game.probec)
5056 if game.cryprob <= .05:
5057 prout(_("Dilithium crystals aboard ship... not yet used."))
5061 while game.cryprob > ai:
5064 prout(_("Dilithium crystals have been used %d time%s.") % \
5065 (i, (_("s"), "")[i==1]))
5069 "Long-range sensor scan."
5070 if damaged(DLRSENS):
5071 # Now allow base's sensors if docked
5072 if game.condition != "docked":
5074 prout(_("LONG-RANGE SENSORS DAMAGED."))
5077 prout(_("Starbase's long-range scan"))
5079 prout(_("Long-range scan"))
5080 for x in range(game.quadrant.i-1, game.quadrant.i+2):
5083 for y in range(game.quadrant.j-1, game.quadrant.j+2):
5084 if not VALID_QUADRANT(x, y):
5088 if not damaged(DRADIO):
5089 game.state.galaxy[x][y].charted = True
5090 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5091 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5092 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5093 if not silent and game.state.galaxy[x][y].supernova:
5096 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5104 for i in range(NDEVICES):
5107 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5108 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5110 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5111 game.damage[i]+0.05,
5112 game.docfac*game.damage[i]+0.005))
5114 prout(_("All devices functional."))
5117 "Update the chart in the Enterprise's computer from galaxy data."
5118 game.lastchart = game.state.date
5119 for i in range(GALSIZE):
5120 for j in range(GALSIZE):
5121 if game.state.galaxy[i][j].charted:
5122 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5123 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5124 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5127 "Display the star chart."
5129 if (game.options & OPTION_AUTOSCAN):
5131 if not damaged(DRADIO):
5133 if game.lastchart < game.state.date and game.condition == "docked":
5134 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5136 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5137 if game.state.date > game.lastchart:
5138 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5139 prout(" 1 2 3 4 5 6 7 8")
5140 for i in range(GALSIZE):
5141 proutn("%d |" % (i+1))
5142 for j in range(GALSIZE):
5143 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
5147 if game.state.galaxy[i][j].supernova:
5149 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5151 elif game.state.galaxy[i][j].charted:
5152 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5156 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
5164 def sectscan(goodScan, i, j):
5165 "Light up an individual dot in a sector."
5166 if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1):
5167 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):
5168 #if game.condition == "red": textcolor("red")
5169 #elif game.condition == "green": textcolor("green")
5170 #elif game.condition == "yellow": textcolor("yellow")
5171 #elif game.condition == "docked": textcolor("cyan")
5172 #elif game.condition == "dead": textcolor("brown")
5173 if game.quad[i][j] != game.ship:
5175 proutn("%c " % game.quad[i][j])
5181 "Emit status report lines"
5182 if not req or req == 1:
5183 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5184 % (game.state.date, game.state.remtime))
5185 if not req or req == 2:
5186 if game.condition != "docked":
5189 for t in range(NDEVICES):
5190 if game.damage[t]>0:
5192 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5193 if not req or req == 3:
5194 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5195 if not req or req == 4:
5196 if damaged(DLIFSUP):
5197 if game.condition == "docked":
5198 s = _("DAMAGED, Base provides")
5200 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5203 prstat(_("Life Support"), s)
5204 if not req or req == 5:
5205 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5206 if not req or req == 6:
5208 if game.icrystl and (game.options & OPTION_SHOWME):
5209 extra = _(" (have crystals)")
5210 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5211 if not req or req == 7:
5212 prstat(_("Torpedoes"), "%d" % (game.torps))
5213 if not req or req == 8:
5214 if damaged(DSHIELD):
5220 data = _(" %d%% %.1f units") \
5221 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5222 prstat(_("Shields"), s+data)
5223 if not req or req == 9:
5224 prstat(_("Klingons Left"), "%d" \
5225 % (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem))
5226 if not req or req == 10:
5227 if game.options & OPTION_WORLDS:
5228 plnet = game.state.galaxy[game.quadrant.i][game.quadrant.j].planet
5229 if plnet and plnet.inhabited:
5230 prstat(_("Major system"), plnet.name)
5232 prout(_("Sector is uninhabited"))
5233 elif not req or req == 11:
5234 attackreport(not req)
5237 "Request specified status data, a historical relic from slow TTYs."
5238 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5239 while scanner.next() == "IHEOL":
5240 proutn(_("Information desired? "))
5242 if scanner.token in requests:
5243 status(requests.index(scanner.token))
5245 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5246 prout((" date, condition, position, lsupport, warpfactor,"))
5247 prout((" energy, torpedoes, shields, klingons, system, time."))
5252 if damaged(DSRSENS):
5253 # Allow base's sensors if docked
5254 if game.condition != "docked":
5255 prout(_(" S.R. SENSORS DAMAGED!"))
5258 prout(_(" [Using Base's sensors]"))
5260 prout(_(" Short-range scan"))
5261 if goodScan and not damaged(DRADIO):
5262 game.state.chart[game.quadrant.i][game.quadrant.j].klingons = game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons
5263 game.state.chart[game.quadrant.i][game.quadrant.j].starbase = game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase
5264 game.state.chart[game.quadrant.i][game.quadrant.j].stars = game.state.galaxy[game.quadrant.i][game.quadrant.j].stars
5265 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
5266 prout(" 1 2 3 4 5 6 7 8 9 10")
5267 if game.condition != "docked":
5269 for i in range(QUADSIZE):
5270 proutn("%2d " % (i+1))
5271 for j in range(QUADSIZE):
5272 sectscan(goodScan, i, j)
5276 "Use computer to get estimated time of arrival for a warp jump."
5277 w1 = coord(); w2 = coord()
5279 if damaged(DCOMPTR):
5280 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5283 if scanner.next() != "IHREAL":
5286 proutn(_("Destination quadrant and/or sector? "))
5287 if scanner.next()!="IHREAL":
5290 w1.j = int(scanner.real-0.5)
5291 if scanner.next() != "IHREAL":
5294 w1.i = int(scanner.real-0.5)
5295 if scanner.next() == "IHREAL":
5296 w2.j = int(scanner.real-0.5)
5297 if scanner.next() != "IHREAL":
5300 w2.i = int(scanner.real-0.5)
5302 if game.quadrant.j>w1.i:
5306 if game.quadrant.i>w1.j:
5310 if not VALID_QUADRANT(w1.i, w1.j) or not VALID_SECTOR(w2.i, w2.j):
5313 game.dist = math.sqrt((w1.j-game.quadrant.j+0.1*(w2.j-game.sector.j))**2+
5314 (w1.i-game.quadrant.i+0.1*(w2.i-game.sector.i))**2)
5317 prout(_("Answer \"no\" if you don't know the value:"))
5320 proutn(_("Time or arrival date? "))
5321 if scanner.next()=="IHREAL":
5322 ttime = scanner.real
5323 if ttime > game.state.date:
5324 ttime -= game.state.date # Actually a star date
5325 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5326 if ttime <= 1e-10 or twarp > 10:
5327 prout(_("We'll never make it, sir."))
5334 proutn(_("Warp factor? "))
5335 if scanner.next()== "IHREAL":
5337 twarp = scanner.real
5338 if twarp<1.0 or twarp > 10.0:
5342 prout(_("Captain, certainly you can give me one of these."))
5345 ttime = (10.0*game.dist)/twarp**2
5346 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5347 if tpower >= game.energy:
5348 prout(_("Insufficient energy, sir."))
5349 if not game.shldup or tpower > game.energy*2.0:
5352 proutn(_("New warp factor to try? "))
5353 if scanner.next() == "IHREAL":
5355 twarp = scanner.real
5356 if twarp<1.0 or twarp > 10.0:
5364 prout(_("But if you lower your shields,"))
5365 proutn(_("remaining"))
5368 proutn(_("Remaining"))
5369 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5371 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5373 prout(_("Any warp speed is adequate."))
5375 prout(_("Minimum warp needed is %.2f,") % (twarp))
5376 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5377 if game.state.remtime < ttime:
5378 prout(_("Unfortunately, the Federation will be destroyed by then."))
5380 prout(_("You'll be taking risks at that speed, Captain"))
5381 if (game.isatb==1 and game.state.kscmdr == w1 and \
5382 scheduled(FSCDBAS)< ttime+game.state.date) or \
5383 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5384 prout(_("The starbase there will be destroyed by then."))
5385 proutn(_("New warp factor to try? "))
5386 if scanner.next() == "IHREAL":
5388 twarp = scanner.real
5389 if twarp<1.0 or twarp > 10.0:
5397 # Code from setup.c begins here
5400 "Issue a historically correct banner."
5402 prout(_("-SUPER- STAR TREK"))
5404 # From the FORTRAN original
5405 # prout(_("Latest update-21 Sept 78"))
5411 scanner.token = "emsave.trk"
5413 key = scanner.next()
5415 proutn(_("File name: "))
5416 key = scanner.next()
5417 if key != "IHALPHA":
5421 if '.' not in scanner.token:
5422 scanner.token += ".trk"
5424 fp = open(scanner.token, "wb")
5426 prout(_("Can't freeze game as file %s") % scanner.token)
5428 cPickle.dump(game, fp)
5432 "Retrieve saved game."
5433 game.passwd[0] = '\0'
5434 key = scanner.next()
5436 proutn(_("File name: "))
5437 key = scanner.next()
5438 if key != "IHALPHA":
5442 if '.' not in scanner.token:
5443 scanner.token += ".trk"
5445 fp = open(scanner.token, "rb")
5447 prout(_("Can't thaw game in %s") % scanner.token)
5449 game = cPickle.load(fp)
5453 # I used <http://www.memory-alpha.org> to find planets
5454 # with references in ST:TOS. Eath and the Alpha Centauri
5455 # Colony have been omitted.
5457 # Some planets marked Class G and P here will be displayed as class M
5458 # because of the way planets are generated. This is a known bug.
5461 _("Andoria (Fesoan)"), # several episodes
5462 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5463 _("Vulcan (T'Khasi)"), # many episodes
5464 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5465 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5466 _("Ardana"), # TOS: "The Cloud Minders"
5467 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5468 _("Gideon"), # TOS: "The Mark of Gideon"
5469 _("Aldebaran III"), # TOS: "The Deadly Years"
5470 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5471 _("Altair IV"), # TOS: "Amok Time
5472 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5473 _("Benecia"), # TOS: "The Conscience of the King"
5474 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5475 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5476 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5477 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5478 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5479 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5480 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5481 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5482 _("Ingraham B"), # TOS: "Operation: Annihilate"
5483 _("Janus IV"), # TOS: "The Devil in the Dark"
5484 _("Makus III"), # TOS: "The Galileo Seven"
5485 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5486 _("Omega IV"), # TOS: "The Omega Glory"
5487 _("Regulus V"), # TOS: "Amok Time
5488 _("Deneva"), # TOS: "Operation -- Annihilate!"
5489 # Worlds from BSD Trek
5490 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5491 _("Beta III"), # TOS: "The Return of the Archons"
5492 _("Triacus"), # TOS: "And the Children Shall Lead",
5493 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5495 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5496 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5497 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5498 # _("Izar"), # TOS: "Whom Gods Destroy"
5499 # _("Tiburon"), # TOS: "The Way to Eden"
5500 # _("Merak II"), # TOS: "The Cloud Minders"
5501 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5502 # _("Iotia"), # TOS: "A Piece of the Action"
5506 _("S. R. Sensors"), \
5507 _("L. R. Sensors"), \
5509 _("Photon Tubes"), \
5510 _("Life Support"), \
5511 _("Warp Engines"), \
5512 _("Impulse Engines"), \
5514 _("Subspace Radio"), \
5515 _("Shuttle Craft"), \
5517 _("Navigation System"), \
5519 _("Shield Control"), \
5525 "Prepare to play, set up cosmos."
5527 # Decide how many of everything
5529 return # frozen game
5530 # Prepare the Enterprise
5531 game.alldone = game.gamewon = game.shldchg = game.shldup = False
5533 game.state.crew = FULLCREW
5534 game.energy = game.inenrg = 5000.0
5535 game.shield = game.inshld = 2500.0
5538 game.quadrant = randplace(GALSIZE)
5539 game.sector = randplace(QUADSIZE)
5540 game.torps = game.intorps = 10
5541 game.nprobes = randrange(2, 5)
5543 for i in range(NDEVICES):
5544 game.damage[i] = 0.0
5545 # Set up assorted game parameters
5546 game.battle = coord()
5547 game.state.date = game.indate = 100.0 * randreal(20, 51)
5548 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5549 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5550 game.isatb = game.state.nplankl = 0
5551 game.state.starkl = game.state.basekl = 0
5552 game.iscraft = "onship"
5556 # Starchart is functional but we've never seen it
5557 game.lastchart = FOREVER
5558 # Put stars in the galaxy
5560 for i in range(GALSIZE):
5561 for j in range(GALSIZE):
5562 k = randrange(1, QUADSIZE**2/10+1)
5564 game.state.galaxy[i][j].stars = k
5565 # Locate star bases in galaxy
5566 for i in range(game.inbase):
5569 w = randplace(GALSIZE)
5570 if not game.state.galaxy[w.i][w.j].starbase:
5573 # C version: for (j = i-1; j > 0; j--)
5574 # so it did them in the opposite order.
5575 for j in range(1, i):
5576 # Improved placement algorithm to spread out bases
5577 distq = (w - game.state.baseq[j]).distance()
5578 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5581 prout("=== Abandoning base #%d at %s" % (i, w))
5583 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5585 prout("=== Saving base #%d, close to #%d" % (i, j))
5588 game.state.baseq.append(w)
5589 game.state.galaxy[w.i][w.j].starbase = game.state.chart[w.i][w.j].starbase = True
5590 # Position ordinary Klingon Battle Cruisers
5592 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5593 if klumper > MAXKLQUAD:
5597 klump = (1.0 - r*r)*klumper
5602 w = randplace(GALSIZE)
5603 if not game.state.galaxy[w.i][w.j].supernova and \
5604 game.state.galaxy[w.i][w.j].klingons + klump <= MAXKLQUAD:
5606 game.state.galaxy[w.i][w.j].klingons += int(klump)
5609 # Position Klingon Commander Ships
5610 for i in range(game.incom):
5612 w = randplace(GALSIZE)
5613 if not welcoming(w) or w in game.state.kcmdr:
5615 if (game.state.galaxy[w.i][w.j].klingons or withprob(0.25)):
5617 game.state.galaxy[w.i][w.j].klingons += 1
5618 game.state.kcmdr.append(w)
5619 # Locate planets in galaxy
5620 for i in range(game.inplan):
5622 w = randplace(GALSIZE)
5623 if game.state.galaxy[w.i][w.j].planet == None:
5627 new.crystals = "absent"
5628 if (game.options & OPTION_WORLDS) and i < NINHAB:
5629 new.pclass = "M" # All inhabited planets are class M
5630 new.crystals = "absent"
5632 new.name = systnames[i]
5633 new.inhabited = True
5635 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5637 new.crystals = "present"
5638 new.known = "unknown"
5639 new.inhabited = False
5640 game.state.galaxy[w.i][w.j].planet = new
5641 game.state.planets.append(new)
5643 for i in range(game.state.nromrem):
5644 w = randplace(GALSIZE)
5645 game.state.galaxy[w.i][w.j].romulans += 1
5646 # Place the Super-Commander if needed
5647 if game.state.nscrem > 0:
5649 w = randplace(GALSIZE)
5652 game.state.kscmdr = w
5653 game.state.galaxy[w.i][w.j].klingons += 1
5654 # Initialize times for extraneous events
5655 schedule(FSNOVA, expran(0.5 * game.intime))
5656 schedule(FTBEAM, expran(1.5 * (game.intime / len(game.state.kcmdr))))
5657 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5658 schedule(FBATTAK, expran(0.3*game.intime))
5660 if game.state.nscrem:
5661 schedule(FSCMOVE, 0.2777)
5666 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5667 schedule(FDISTR, expran(1.0 + game.intime))
5672 # Place thing (in tournament game, we don't want one!)
5673 # New in SST2K: never place the Thing near a starbase.
5674 # This makes sense and avoids a special case in the old code.
5676 if game.tourn is None:
5678 thing = randplace(GALSIZE)
5679 if thing not in game.state.baseq:
5682 game.state.snap = False
5683 if game.skill == SKILL_NOVICE:
5684 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5685 prout(_("a deadly Klingon invasion force. As captain of the United"))
5686 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5687 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5688 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5689 prout(_("your mission. As you proceed you may be given more time."))
5691 prout(_("You will have %d supporting starbases.") % (game.inbase))
5692 proutn(_("Starbase locations- "))
5694 prout(_("Stardate %d.") % int(game.state.date))
5696 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5697 prout(_("An unknown number of Romulans."))
5698 if game.state.nscrem:
5699 prout(_("And one (GULP) Super-Commander."))
5700 prout(_("%d stardates.") % int(game.intime))
5701 proutn(_("%d starbases in ") % game.inbase)
5702 for i in range(game.inbase):
5703 proutn(`game.state.baseq[i]`)
5706 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5707 proutn(_(" Sector %s") % game.sector)
5709 prout(_("Good Luck!"))
5710 if game.state.nscrem:
5711 prout(_(" YOU'LL NEED IT."))
5714 if len(game.enemies) - (thing == game.quadrant) - (game.tholian != None):
5716 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5717 attack(torps_ok=False)
5720 "Choose your game type."
5725 game.skill = SKILL_NONE
5727 if not scanner.inqueue: # Can start with command line options
5728 proutn(_("Would you like a regular, tournament, or saved game? "))
5730 if len(scanner.token)==0: # Try again
5732 if scanner.sees("tournament"):
5733 while scanner.next() == "IHEOL":
5734 proutn(_("Type in tournament number-"))
5735 if scanner.real == 0:
5737 continue # We don't want a blank entry
5738 game.tourn = int(round(scanner.real))
5739 random.seed(scanner.real)
5741 logfp.write("# random.seed(%d)\n" % scanner.real)
5743 if scanner.sees("saved") or scanner.sees("frozen"):
5747 if game.passwd == None:
5749 if not game.alldone:
5750 game.thawed = True # No plaque if not finished
5754 if scanner.sees("regular"):
5756 proutn(_("What is \"%s\"?") % scanner.token)
5758 while game.length==0 or game.skill==SKILL_NONE:
5759 if scanner.next() == "IHALPHA":
5760 if scanner.sees("short"):
5762 elif scanner.sees("medium"):
5764 elif scanner.sees("long"):
5766 elif scanner.sees("novice"):
5767 game.skill = SKILL_NOVICE
5768 elif scanner.sees("fair"):
5769 game.skill = SKILL_FAIR
5770 elif scanner.sees("good"):
5771 game.skill = SKILL_GOOD
5772 elif scanner.sees("expert"):
5773 game.skill = SKILL_EXPERT
5774 elif scanner.sees("emeritus"):
5775 game.skill = SKILL_EMERITUS
5777 proutn(_("What is \""))
5778 proutn(scanner.token)
5783 proutn(_("Would you like a Short, Medium, or Long game? "))
5784 elif game.skill == SKILL_NONE:
5785 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
5786 # Choose game options -- added by ESR for SST2K
5787 if scanner.next() != "IHALPHA":
5789 proutn(_("Choose your game style (or just press enter): "))
5791 if scanner.sees("plain"):
5792 # Approximates the UT FORTRAN version.
5793 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5794 game.options |= OPTION_PLAIN
5795 elif scanner.sees("almy"):
5796 # Approximates Tom Almy's version.
5797 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5798 game.options |= OPTION_ALMY
5799 elif scanner.sees("fancy"):
5801 elif len(scanner.token):
5802 proutn(_("What is \"%s\"?") % scanner.token)
5804 if game.passwd == "debug":
5806 prout("=== Debug mode enabled.")
5807 # Use parameters to generate initial values of things
5808 game.damfac = 0.5 * game.skill
5809 game.inbase = randrange(BASEMIN, BASEMAX+1)
5811 if game.options & OPTION_PLANETS:
5812 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
5813 if game.options & OPTION_WORLDS:
5814 game.inplan += int(NINHAB)
5815 game.state.nromrem = game.inrom = randrange(2 *game.skill)
5816 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
5817 game.state.remtime = 7.0 * game.length
5818 game.intime = game.state.remtime
5819 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
5820 game.incom = min(MINCMDR, int(game.skill + 0.0625*game.inkling*randreal()))
5821 game.state.remres = (game.inkling+4*game.incom)*game.intime
5822 game.inresor = game.state.remres
5823 if game.inkling > 50:
5824 game.state.inbase += 1
5827 def dropin(iquad=None):
5828 "Drop a feature on a random dot in the current quadrant."
5830 w = randplace(QUADSIZE)
5831 if game.quad[w.i][w.j] == IHDOT:
5833 if iquad is not None:
5834 game.quad[w.i][w.j] = iquad
5838 "Update our alert status."
5839 game.condition = "green"
5840 if game.energy < 1000.0:
5841 game.condition = "yellow"
5842 if game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons or game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans:
5843 game.condition = "red"
5845 game.condition="dead"
5848 "Drop new Klingon into current quadrant."
5849 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
5852 "Set up a new state of quadrant, for when we enter or re-enter it."
5855 game.neutz = game.inorbit = game.landed = False
5856 game.ientesc = game.iseenit = False
5857 # Create a blank quadrant
5858 game.quad = fill2d(QUADSIZE, lambda i, j: IHDOT)
5860 # Attempt to escape Super-commander, so tbeam back!
5863 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
5864 # cope with supernova
5867 game.klhere = q.klingons
5868 game.irhere = q.romulans
5870 game.quad[game.sector.i][game.sector.j] = game.ship
5873 # Position ordinary Klingons
5874 for i in range(game.klhere):
5876 # If we need a commander, promote a Klingon
5877 for cmdr in game.state.kcmdr:
5878 if cmdr == game.quadrant:
5879 e = game.enemies[game.klhere-1]
5880 game.quad[e.kloc.i][e.kloc.j] = IHC
5881 e.kpower = randreal(950,1350) + 50.0*game.skill
5883 # If we need a super-commander, promote a Klingon
5884 if game.quadrant == game.state.kscmdr:
5886 game.quad[e.kloc.i][e.kloc.j] = IHS
5887 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
5888 game.iscate = (game.state.remkl > 1)
5889 # Put in Romulans if needed
5890 for i in range(q.romulans):
5891 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
5892 # If quadrant needs a starbase, put it in
5894 game.base = dropin(IHB)
5895 # If quadrant needs a planet, put it in
5897 game.iplnet = q.planet
5898 if not q.planet.inhabited:
5899 game.plnet = dropin(IHP)
5901 game.plnet = dropin(IHW)
5902 # Check for condition
5905 if game.irhere > 0 and game.klhere == 0:
5907 if not damaged(DRADIO):
5909 prout(_("LT. Uhura- \"Captain, an urgent message."))
5910 prout(_(" I'll put it on audio.\" CLICK"))
5912 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
5913 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
5914 # Put in THING if needed
5915 if thing == game.quadrant:
5916 enemy(type=IHQUEST, loc=dropin(),
5917 power=randreal(6000,6500.0)+250.0*game.skill)
5918 if not damaged(DSRSENS):
5920 prout(_("Mr. Spock- \"Captain, this is most unusual."))
5921 prout(_(" Please examine your short-range scan.\""))
5922 # Decide if quadrant needs a Tholian; lighten up if skill is low
5923 if game.options & OPTION_THOLIAN:
5924 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
5925 (game.skill == SKILL_GOOD and withprob(0.05)) or \
5926 (game.skill > SKILL_GOOD and withprob(0.08)):
5929 w.i = withprob(0.5) * (QUADSIZE-1)
5930 w.j = withprob(0.5) * (QUADSIZE-1)
5931 if game.quad[w.i][w.j] == IHDOT:
5933 game.tholian = enemy(type=IHT, loc=w,
5934 power=randrange(100, 500) + 25.0*game.skill)
5935 # Reserve unoccupied corners
5936 if game.quad[0][0]==IHDOT:
5937 game.quad[0][0] = 'X'
5938 if game.quad[0][QUADSIZE-1]==IHDOT:
5939 game.quad[0][QUADSIZE-1] = 'X'
5940 if game.quad[QUADSIZE-1][0]==IHDOT:
5941 game.quad[QUADSIZE-1][0] = 'X'
5942 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
5943 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
5944 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
5945 # And finally the stars
5946 for i in range(q.stars):
5948 # Put in a few black holes
5949 for i in range(1, 3+1):
5952 # Take out X's in corners if Tholian present
5954 if game.quad[0][0]=='X':
5955 game.quad[0][0] = IHDOT
5956 if game.quad[0][QUADSIZE-1]=='X':
5957 game.quad[0][QUADSIZE-1] = IHDOT
5958 if game.quad[QUADSIZE-1][0]=='X':
5959 game.quad[QUADSIZE-1][0] = IHDOT
5960 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
5961 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
5964 "Set the self-destruct password."
5965 if game.options & OPTION_PLAIN:
5968 proutn(_("Please type in a secret password- "))
5970 game.passwd = scanner.token
5971 if game.passwd != None:
5976 game.passwd += chr(ord('a')+randrange(26))
5978 # Code from sst.c begins here
5981 "SRSCAN": OPTION_TTY,
5982 "STATUS": OPTION_TTY,
5983 "REQUEST": OPTION_TTY,
5984 "LRSCAN": OPTION_TTY,
5997 "SENSORS": OPTION_PLANETS,
5998 "ORBIT": OPTION_PLANETS,
5999 "TRANSPORT": OPTION_PLANETS,
6000 "MINE": OPTION_PLANETS,
6001 "CRYSTALS": OPTION_PLANETS,
6002 "SHUTTLE": OPTION_PLANETS,
6003 "PLANETS": OPTION_PLANETS,
6008 "PROBE": OPTION_PROBE,
6010 "FREEZE": 0, # Synonym for SAVE
6016 "SOS": 0, # Synonym for MAYDAY
6017 "CALL": 0, # Synonym for MAYDAY
6023 "Generate a list of legal commands."
6024 prout(_("LEGAL COMMANDS ARE:"))
6026 for key in commands:
6027 if not commands[key] or (commands[key] & game.options):
6028 proutn("%-12s " % key)
6030 if emitted % 5 == 4:
6035 "Browse on-line help."
6036 key = scanner.next()
6039 setwnd(prompt_window)
6040 proutn(_("Help on what command? "))
6041 key = scanner.next()
6042 setwnd(message_window)
6045 if scanner.token in commands or scanner.token == "ABBREV":
6052 cmd = scanner.token.upper()
6054 fp = open(SSTDOC, "r")
6057 fp = open(DOC_NAME, "r")
6059 prout(_("Spock- \"Captain, that information is missing from the"))
6060 proutn(_(" computer. You need to find "))
6062 prout(_(" and put it in the"))
6063 proutn(_(" current directory or to "))
6067 # This used to continue: "You need to find SST.DOC and put
6068 # it in the current directory."
6072 linebuf = fp.readline()
6074 prout(_("Spock- \"Captain, there is no information on that command.\""))
6077 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6078 linebuf = linebuf[3:].strip()
6082 prout(_("Spock- \"Captain, I've found the following information:\""))
6084 while linebuf in fp:
6085 if "******" in linebuf:
6091 "Command-interpretation loop."
6093 setwnd(message_window)
6094 while True: # command loop
6096 while True: # get a command
6101 setwnd(prompt_window)
6104 if scanner.next() == "IHEOL":
6105 if game.options & OPTION_CURSES:
6108 elif scanner.token == "":
6112 setwnd(message_window)
6114 candidates = filter(lambda x: x.startswith(scanner.token.upper()),
6116 if len(candidates) == 1:
6119 elif candidates and not (game.options & OPTION_PLAIN):
6120 prout("Commands with prefix '%s': %s" % (scanner.token, " ".join(candidates)))
6124 if cmd == "SRSCAN": # srscan
6126 elif cmd == "STATUS": # status
6128 elif cmd == "REQUEST": # status request
6130 elif cmd == "LRSCAN": # long range scan
6131 lrscan(silent=False)
6132 elif cmd == "PHASERS": # phasers
6136 elif cmd == "TORPEDO": # photon torpedos
6140 elif cmd == "MOVE": # move under warp
6142 elif cmd == "SHIELDS": # shields
6143 doshield(shraise=False)
6146 game.shldchg = False
6147 elif cmd == "DOCK": # dock at starbase
6150 attack(torps_ok=False)
6151 elif cmd == "DAMAGES": # damage reports
6153 elif cmd == "CHART": # chart
6155 elif cmd == "IMPULSE": # impulse
6157 elif cmd == "REST": # rest
6161 elif cmd == "WARP": # warp
6163 elif cmd == "SCORE": # score
6165 elif cmd == "SENSORS": # sensors
6167 elif cmd == "ORBIT": # orbit
6171 elif cmd == "TRANSPORT": # transport "beam"
6173 elif cmd == "MINE": # mine
6177 elif cmd == "CRYSTALS": # crystals
6181 elif cmd == "SHUTTLE": # shuttle
6185 elif cmd == "PLANETS": # Planet list
6187 elif cmd == "REPORT": # Game Report
6189 elif cmd == "COMPUTER": # use COMPUTER!
6191 elif cmd == "COMMANDS":
6193 elif cmd == "EMEXIT": # Emergency exit
6194 clrscr() # Hide screen
6195 freeze(True) # forced save
6196 raise SysExit,1 # And quick exit
6197 elif cmd == "PROBE":
6198 probe() # Launch probe
6201 elif cmd == "ABANDON": # Abandon Ship
6203 elif cmd == "DESTRUCT": # Self Destruct
6205 elif cmd == "SAVE": # Save Game
6208 if game.skill > SKILL_GOOD:
6209 prout(_("WARNING--Saved games produce no plaques!"))
6210 elif cmd == "DEATHRAY": # Try a desparation measure
6214 elif cmd == "DEBUGCMD": # What do we want for debug???
6216 elif cmd == "MAYDAY": # Call for help
6221 game.alldone = True # quit the game
6226 break # Game has ended
6227 if game.optime != 0.0:
6230 break # Events did us in
6231 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
6234 if hitme and not game.justin:
6235 attack(torps_ok=True)
6238 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
6249 "Emit the name of an enemy or feature."
6250 if type == IHR: s = _("Romulan")
6251 elif type == IHK: s = _("Klingon")
6252 elif type == IHC: s = _("Commander")
6253 elif type == IHS: s = _("Super-commander")
6254 elif type == IHSTAR: s = _("Star")
6255 elif type == IHP: s = _("Planet")
6256 elif type == IHB: s = _("Starbase")
6257 elif type == IHBLANK: s = _("Black hole")
6258 elif type == IHT: s = _("Tholian")
6259 elif type == IHWEB: s = _("Tholian web")
6260 elif type == IHQUEST: s = _("Stranger")
6261 elif type == IHW: s = _("Inhabited World")
6262 else: s = "Unknown??"
6265 def crmena(stars, enemy, loctype, w):
6266 "Emit the name of an enemy and his location."
6270 buf += cramen(enemy) + _(" at ")
6271 if loctype == "quadrant":
6272 buf += _("Quadrant ")
6273 elif loctype == "sector":
6278 "Emit our ship name."
6279 return{IHE:_("Enterprise"),IHF:_("Faerie Queene")}.get(game.ship,"Ship???")
6282 "Emit a line of stars"
6283 prouts("******************************************************")
6287 return -avrage*math.log(1e-7 + randreal())
6289 def randplace(size):
6290 "Choose a random location."
6292 w.i = randrange(size)
6293 w.j = randrange(size)
6303 # Get a token from the user
6306 # Fill the token quue if nothing here
6307 while not self.inqueue:
6309 if curwnd==prompt_window:
6311 setwnd(message_window)
6318 self.inqueue = line.lstrip().split() + ["IHEOL"]
6319 # From here on in it's all looking at the queue
6320 self.token = self.inqueue.pop(0)
6321 if self.token == "IHEOL":
6325 self.real = float(self.token)
6326 self.type = "IHREAL"
6331 self.token = self.token.lower()
6332 self.type = "IHALPHA"
6335 def append(self, tok):
6336 self.inqueue.append(tok)
6337 def push(self, tok):
6338 self.inqueue.insert(0, tok)
6342 # Demand input for next scan
6344 self.real = self.token = None
6346 # return "IHEOL" next time
6347 self.inqueue = ["IHEOL"]
6348 self.real = self.token = None
6350 # compares s to item and returns true if it matches to the length of s
6351 return s.startswith(self.token)
6353 # Round token value to nearest integer
6354 return int(round(scanner.real))
6358 if scanner.type != "IHREAL":
6361 s.i = scanner.int()-1
6363 if scanner.type != "IHREAL":
6366 s.j = scanner.int()-1
6369 return "<sstcanner: token=%s, type=%s, queue=%s>" % (scanner.token, scanner.type, scanner.inqueue)
6372 "Yes-or-no confirmation."
6376 if scanner.token == 'y':
6378 if scanner.token == 'n':
6381 proutn(_("Please answer with \"y\" or \"n\": "))
6384 "Complain about unparseable input."
6387 prout(_("Beg your pardon, Captain?"))
6390 "Access to the internals for debugging."
6391 proutn("Reset levels? ")
6393 if game.energy < game.inenrg:
6394 game.energy = game.inenrg
6395 game.shield = game.inshld
6396 game.torps = game.intorps
6397 game.lsupres = game.inlsr
6398 proutn("Reset damage? ")
6400 for i in range(NDEVICES):
6401 if game.damage[i] > 0.0:
6402 game.damage[i] = 0.0
6403 proutn("Toggle debug flag? ")
6407 prout("Debug output ON")
6409 prout("Debug output OFF")
6410 proutn("Cause selective damage? ")
6412 for i in range(NDEVICES):
6413 proutn("Kill %s?" % device[i])
6415 key = scanner.next()
6416 if key == "IHALPHA" and scanner.sees("y"):
6417 game.damage[i] = 10.0
6418 proutn("Examine/change events? ")
6423 FSNOVA: "Supernova ",
6426 FBATTAK: "Base Attack ",
6427 FCDBAS: "Base Destroy ",
6428 FSCMOVE: "SC Move ",
6429 FSCDBAS: "SC Base Destroy ",
6430 FDSPROB: "Probe Move ",
6431 FDISTR: "Distress Call ",
6432 FENSLV: "Enslavement ",
6433 FREPRO: "Klingon Build ",
6435 for i in range(1, NEVENTS):
6438 proutn("%.2f" % (scheduled(i)-game.state.date))
6439 if i == FENSLV or i == FREPRO:
6441 proutn(" in %s" % ev.quadrant)
6446 key = scanner.next()
6450 elif key == "IHREAL":
6451 ev = schedule(i, scanner.real)
6452 if i == FENSLV or i == FREPRO:
6454 proutn("In quadrant- ")
6455 key = scanner.next()
6456 # "IHEOL" says to leave coordinates as they are
6459 prout("Event %d canceled, no x coordinate." % (i))
6462 w.i = int(round(scanner.real))
6463 key = scanner.next()
6465 prout("Event %d canceled, no y coordinate." % (i))
6468 w.j = int(round(scanner.real))
6471 proutn("Induce supernova here? ")
6473 game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova = True
6476 if __name__ == '__main__':
6477 import getopt, socket
6479 global line, thing, game, idebug
6485 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6486 if os.getenv("TERM"):
6487 game.options |= OPTION_CURSES
6489 game.options |= OPTION_TTY
6490 seed = int(time.time())
6491 (options, arguments) = getopt.getopt(sys.argv[1:], "r:s:tx")
6492 for (switch, val) in options:
6495 replayfp = open(val, "r")
6497 sys.stderr.write("sst: can't open replay file %s\n" % val)
6500 line = replayfp.readline().strip()
6501 (leader, key, seed) = line.split()
6503 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6504 line = replayfp.readline().strip()
6505 arguments += line.split()[2:]
6507 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6509 game.options |= OPTION_TTY
6510 game.options &=~ OPTION_CURSES
6511 elif switch == '-s':
6513 elif switch == '-t':
6514 game.options |= OPTION_TTY
6515 game.options &=~ OPTION_CURSES
6516 elif switch == '-x':
6519 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6521 # where to save the input in case of bugs
6523 logfp = open("/usr/tmp/sst-input.log", "w")
6525 sys.stderr.write("sst: warning, can't open logfile\n")
6527 logfp.write("# seed %s\n" % seed)
6528 logfp.write("# options %s\n" % " ".join(arguments))
6529 logfp.write("# recorded by %s@%s on %s\n" % \
6530 (os.getenv("LOGNAME"),socket.gethostname(),time.ctime()))
6532 scanner = sstscanner()
6533 map(scanner.append, arguments)
6536 while True: # Play a game
6537 setwnd(fullscreen_window)
6543 game.alldone = False
6549 if game.tourn and game.alldone:
6550 proutn(_("Do you want your score recorded?"))
6555 proutn(_("Do you want to play again? "))
6559 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6563 except KeyboardInterrupt: