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
339 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
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.probe = None # location of probe
528 self.probein = None # probe i,j increment
529 self.height = 0.0 # height of orbit around planet
531 # Stas thinks this should be (C expression):
532 # game.state.remkl + len(game.state.kcmdr) > 0 ?
533 # game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr)) : 99
534 # He says the existing expression is prone to divide-by-zero errors
535 # after killing the last klingon when score is shown -- perhaps also
536 # if the only remaining klingon is SCOM.
537 game.state.remtime = game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr))
583 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
586 def randrange(*args):
587 v = random.randrange(*args)
588 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
594 v *= args[0] # returns from [0, args[0])
596 v = args[0] + v*(args[1]-args[0]) # returns from [args[0], args[1])
597 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
600 # Code from ai.c begins here
603 "Would this quadrant welcome another Klingon?"
604 return VALID_QUADRANT(iq.i,iq.j) and \
605 not game.state.galaxy[iq.i][iq.j].supernova and \
606 game.state.galaxy[iq.i][iq.j].klingons < MAXKLQUAD
608 def tryexit(enemy, look, irun):
609 "A bad guy attempts to bug out."
611 iq.i = game.quadrant.i+(look.i+(QUADSIZE-1))/QUADSIZE - 1
612 iq.j = game.quadrant.j+(look.j+(QUADSIZE-1))/QUADSIZE - 1
613 if not welcoming(iq):
615 if enemy.type == IHR:
616 return False; # Romulans cannot escape!
618 # avoid intruding on another commander's territory
619 if enemy.type == IHC:
620 if iq in game.state.kcmdr:
622 # refuse to leave if currently attacking starbase
623 if game.battle == game.quadrant:
625 # don't leave if over 1000 units of energy
626 if enemy.kpower > 1000.0:
628 # emit escape message and move out of quadrant.
629 # we know this if either short or long range sensors are working
630 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
631 game.condition == "docked":
632 prout(crmena(True, enemy.type, "sector", enemy.kloc) + \
633 (_(" escapes to Quadrant %s (and regains strength).") % q))
634 # handle local matters related to escape
637 if game.condition != "docked":
639 # Handle global matters related to escape
640 game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
641 game.state.galaxy[iq.i][iq.j].klingons += 1
646 schedule(FSCMOVE, 0.2777)
650 for cmdr in game.state.kcmdr:
651 if cmdr == game.quadrant:
652 game.state.kcmdr[n] = iq
654 return True; # success
656 # The bad-guy movement algorithm:
658 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
659 # If both are operating full strength, force is 1000. If both are damaged,
660 # force is -1000. Having shields down subtracts an additional 1000.
662 # 2. Enemy has forces equal to the energy of the attacker plus
663 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
664 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
666 # Attacker Initial energy levels (nominal):
667 # Klingon Romulan Commander Super-Commander
668 # Novice 400 700 1200
670 # Good 450 800 1300 1750
671 # Expert 475 850 1350 1875
672 # Emeritus 500 900 1400 2000
673 # VARIANCE 75 200 200 200
675 # Enemy vessels only move prior to their attack. In Novice - Good games
676 # only commanders move. In Expert games, all enemy vessels move if there
677 # is a commander present. In Emeritus games all enemy vessels move.
679 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
680 # forces are 1000 greater than Enterprise.
682 # Agressive action on average cuts the distance between the ship and
683 # the enemy to 1/4 the original.
685 # 4. At lower energy advantage, movement units are proportional to the
686 # advantage with a 650 advantage being to hold ground, 800 to move forward
687 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
689 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
690 # retreat, especially at high skill levels.
692 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
694 def movebaddy(enemy):
695 "Tactical movement for the bad guys."
696 next = coord(); look = coord()
698 # This should probably be just (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
699 if game.skill >= SKILL_EXPERT:
700 nbaddys = (((game.quadrant in game.state.kcmdr)*2 + (game.state.kscmdr==game.quadrant)*2+game.klhere*1.23+game.irhere*1.5)/2.0)
702 nbaddys = (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
704 mdist = int(dist1 + 0.5); # Nearest integer distance
705 # If SC, check with spy to see if should hi-tail it
706 if enemy.type==IHS and \
707 (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
711 # decide whether to advance, retreat, or hold position
712 forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
714 forces += 1000; # Good for enemy if shield is down!
715 if not damaged(DPHASER) or not damaged(DPHOTON):
716 if damaged(DPHASER): # phasers damaged
719 forces -= 0.2*(game.energy - 2500.0)
720 if damaged(DPHOTON): # photon torpedoes damaged
723 forces -= 50.0*game.torps
725 # phasers and photon tubes both out!
728 if forces <= 1000.0 and game.condition != "docked": # Typical situation
729 motion = ((forces + randreal(200))/150.0) - 5.0
731 if forces > 1000.0: # Very strong -- move in for kill
732 motion = (1.0 - randreal())**2 * dist1 + 1.0
733 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
734 motion -= game.skill*(2.0-randreal()**2)
736 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
737 # don't move if no motion
740 # Limit motion according to skill
741 if abs(motion) > game.skill:
746 # calculate preferred number of steps
747 nsteps = abs(int(motion))
748 if motion > 0 and nsteps > mdist:
749 nsteps = mdist; # don't overshoot
750 if nsteps > QUADSIZE:
751 nsteps = QUADSIZE; # This shouldn't be necessary
753 nsteps = 1; # This shouldn't be necessary
755 proutn("NSTEPS = %d:" % nsteps)
756 # Compute preferred values of delta X and Y
757 m = game.sector - enemy.kloc
758 if 2.0 * abs(m.i) < abs(m.j):
760 if 2.0 * abs(m.j) < abs(game.sector.i-enemy.kloc.i):
762 m = (motion * m).sgn()
765 for ll in range(nsteps):
767 proutn(" %d" % (ll+1))
768 # Check if preferred position available
779 attempts = 0; # Settle mysterious hang problem
780 while attempts < 20 and not success:
782 if look.i < 0 or look.i >= QUADSIZE:
783 if motion < 0 and tryexit(enemy, look, irun):
785 if krawli == m.i or m.j == 0:
787 look.i = next.i + krawli
789 elif look.j < 0 or look.j >= QUADSIZE:
790 if motion < 0 and tryexit(enemy, look, irun):
792 if krawlj == m.j or m.i == 0:
794 look.j = next.j + krawlj
796 elif (game.options & OPTION_RAMMING) and game.quad[look.i][look.j] != IHDOT:
797 # See if enemy should ram ship
798 if game.quad[look.i][look.j] == game.ship and \
799 (enemy.type == IHC or enemy.type == IHS):
800 collision(rammed=True, enemy=enemy)
802 if krawli != m.i and m.j != 0:
803 look.i = next.i + krawli
805 elif krawlj != m.j and m.i != 0:
806 look.j = next.j + krawlj
809 break; # we have failed
821 if not damaged(DSRSENS) or game.condition == "docked":
822 proutn(_("*** %s from Sector %s") % (cramen(enemy.type), enemy.kloc))
823 if enemy.kdist < dist1:
824 proutn(_(" advances to "))
826 proutn(_(" retreats to "))
827 prout("Sector %s." % next)
830 "Sequence Klingon tactical movement."
833 # Figure out which Klingon is the commander (or Supercommander)
835 if game.quadrant in game.state.kcmdr:
836 for enemy in game.enemies:
837 if enemy.type == IHC:
839 if game.state.kscmdr==game.quadrant:
840 for enemy in game.enemies:
841 if enemy.type == IHS:
844 # If skill level is high, move other Klingons and Romulans too!
845 # Move these last so they can base their actions on what the
847 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
848 for enemy in game.enemies:
849 if enemy.type in (IHK, IHR):
851 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
853 def movescom(iq, avoid):
854 "Commander movement helper."
855 # Avoid quadrants with bases if we want to avoid Enterprise
856 if not welcoming(iq) or (avoid and iq in game.state.baseq):
858 if game.justin and not game.iscate:
861 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons -= 1
862 game.state.kscmdr = iq
863 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons += 1
864 if game.state.kscmdr==game.quadrant:
865 # SC has scooted, Remove him from current quadrant
870 for enemy in game.enemies:
871 if enemy.type == IHS:
875 if game.condition != "docked":
877 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
878 # check for a helpful planet
879 for i in range(game.inplan):
880 if game.state.planets[i].quadrant == game.state.kscmdr and \
881 game.state.planets[i].crystals == "present":
883 game.state.planets[i].pclass = "destroyed"
884 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].planet = None
887 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
888 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
889 prout(_(" by the Super-commander.\""))
891 return False; # looks good!
893 def supercommander():
894 "Move the Super Commander."
895 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
898 prout("== SUPERCOMMANDER")
899 # Decide on being active or passive
900 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 \
901 (game.state.date-game.indate) < 3.0)
902 if not game.iscate and avoid:
903 # compute move away from Enterprise
904 idelta = game.state.kscmdr-game.quadrant
905 if idelta.distance() > 2.0:
907 idelta.i = game.state.kscmdr.j-game.quadrant.j
908 idelta.j = game.quadrant.i-game.state.kscmdr.i
910 # compute distances to starbases
911 if not game.state.baseq:
915 sc = game.state.kscmdr
916 for base in game.state.baseq:
917 basetbl.append((i, (base - sc).distance()))
918 if game.state.baseq > 1:
919 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
920 # look for nearest base without a commander, no Enterprise, and
921 # without too many Klingons, and not already under attack.
922 ifindit = iwhichb = 0
923 for (i2, base) in enumerate(game.state.baseq):
924 i = basetbl[i2][0]; # bug in original had it not finding nearest
925 if base==game.quadrant or base==game.battle or not welcoming(base):
927 # if there is a commander, and no other base is appropriate,
928 # we will take the one with the commander
929 for cmdr in game.state.kcmdr:
930 if base == cmdr and ifindit != 2:
934 else: # no commander -- use this one
939 return # Nothing suitable -- wait until next time
940 ibq = game.state.baseq[iwhichb]
941 # decide how to move toward base
942 idelta = ibq - game.state.kscmdr
943 # Maximum movement is 1 quadrant in either or both axes
944 idelta = idelta.sgn()
945 # try moving in both x and y directions
946 # there was what looked like a bug in the Almy C code here,
947 # but it might be this translation is just wrong.
948 iq = game.state.kscmdr + idelta
949 if movescom(iq, avoid):
950 # failed -- try some other maneuvers
951 if idelta.i==0 or idelta.j==0:
954 iq.j = game.state.kscmdr.j + 1
955 if movescom(iq, avoid):
956 iq.j = game.state.kscmdr.j - 1
959 iq.i = game.state.kscmdr.i + 1
960 if movescom(iq, avoid):
961 iq.i = game.state.kscmdr.i - 1
964 # try moving just in x or y
965 iq.j = game.state.kscmdr.j
966 if movescom(iq, avoid):
967 iq.j = game.state.kscmdr.j + idelta.j
968 iq.i = game.state.kscmdr.i
971 if len(game.state.baseq) == 0:
974 for (i, ibq) in enumerate(game.state.baseq):
975 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
978 return # no, don't attack base!
981 schedule(FSCDBAS, randreal(1.0, 3.0))
982 if is_scheduled(FCDBAS):
983 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
984 if not communicating():
988 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
990 prout(_(" reports that it is under attack from the Klingon Super-commander."))
991 proutn(_(" It can survive until stardate %d.\"") \
992 % int(scheduled(FSCDBAS)))
995 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
999 game.optime = 0.0; # actually finished
1001 # Check for intelligence report
1004 (not communicating()) or \
1005 not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].charted):
1008 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1009 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1014 if not game.tholian or game.justin:
1017 if game.tholian.kloc.i == 0 and game.tholian.kloc.j == 0:
1018 id.i = 0; id.j = QUADSIZE-1
1019 elif game.tholian.kloc.i == 0 and game.tholian.kloc.j == QUADSIZE-1:
1020 id.i = QUADSIZE-1; id.j = QUADSIZE-1
1021 elif game.tholian.kloc.i == QUADSIZE-1 and game.tholian.kloc.j == QUADSIZE-1:
1022 id.i = QUADSIZE-1; id.j = 0
1023 elif game.tholian.kloc.i == QUADSIZE-1 and game.tholian.kloc.j == 0:
1026 # something is wrong!
1027 game.tholian.move(None)
1028 prout("***Internal error: Tholian in a bad spot.")
1030 # do nothing if we are blocked
1031 if game.quad[id.i][id.j] not in (IHDOT, IHWEB):
1033 here = copy.copy(game.tholian.kloc)
1034 delta = (id - game.tholian.kloc).sgn()
1036 while here.i != id.i:
1038 if game.quad[here.i][here.j]==IHDOT:
1039 game.tholian.move(here)
1041 while here.j != id.j:
1043 if game.quad[here.i][here.j]==IHDOT:
1044 game.tholian.move(here)
1045 # check to see if all holes plugged
1046 for i in range(QUADSIZE):
1047 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1049 if game.quad[QUADSIZE-1][i]!=IHWEB and game.quad[QUADSIZE-1][i]!=IHT:
1051 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1053 if game.quad[i][QUADSIZE-1]!=IHWEB and game.quad[i][QUADSIZE-1]!=IHT:
1055 # All plugged up -- Tholian splits
1056 game.quad[game.tholian.kloc.i][game.tholian.kloc.j]=IHWEB
1058 prout(crmena(True, IHT, "sector", game.tholian) + _(" completes web."))
1059 game.tholian.move(None)
1062 # Code from battle.c begins here
1064 def doshield(shraise):
1065 "Change shield status."
1071 key = scanner.next()
1072 if key == "IHALPHA":
1073 if scanner.sees("transfer"):
1076 if damaged(DSHIELD):
1077 prout(_("Shields damaged and down."))
1079 if scanner.sees("up"):
1081 elif scanner.sees("down"):
1084 proutn(_("Do you wish to change shield energy? "))
1086 proutn(_("Energy to transfer to shields- "))
1088 elif damaged(DSHIELD):
1089 prout(_("Shields damaged and down."))
1092 proutn(_("Shields are up. Do you want them down? "))
1099 proutn(_("Shields are down. Do you want them up? "))
1105 if action == "SHUP": # raise shields
1107 prout(_("Shields already up."))
1111 if game.condition != "docked":
1113 prout(_("Shields raised."))
1114 if game.energy <= 0:
1116 prout(_("Shields raising uses up last of energy."))
1121 elif action == "SHDN":
1123 prout(_("Shields already down."))
1127 prout(_("Shields lowered."))
1130 elif action == "NRG":
1131 while scanner.next() != "IHREAL":
1133 proutn(_("Energy to transfer to shields- "))
1135 if scanner.real == 0:
1137 if scanner.real > game.energy:
1138 prout(_("Insufficient ship energy."))
1141 if game.shield+scanner.real >= game.inshld:
1142 prout(_("Shield energy maximized."))
1143 if game.shield+scanner.real > game.inshld:
1144 prout(_("Excess energy requested returned to ship energy"))
1145 game.energy -= game.inshld-game.shield
1146 game.shield = game.inshld
1148 if scanner.real < 0.0 and game.energy-scanner.real > game.inenrg:
1149 # Prevent shield drain loophole
1151 prout(_("Engineering to bridge--"))
1152 prout(_(" Scott here. Power circuit problem, Captain."))
1153 prout(_(" I can't drain the shields."))
1156 if game.shield+scanner.real < 0:
1157 prout(_("All shield energy transferred to ship."))
1158 game.energy += game.shield
1161 proutn(_("Scotty- \""))
1162 if scanner.real > 0:
1163 prout(_("Transferring energy to shields.\""))
1165 prout(_("Draining energy from shields.\""))
1166 game.shield += scanner.real
1167 game.energy -= scanner.real
1171 "Choose a device to damage, at random."
1172 # Quoth Eric Allman in the code of BSD-Trek:
1173 # "Under certain conditions you can get a critical hit. This
1174 # sort of hit damages devices. The probability that a given
1175 # device is damaged depends on the device. Well protected
1176 # devices (such as the computer, which is in the core of the
1177 # ship and has considerable redundancy) almost never get
1178 # damaged, whereas devices which are exposed (such as the
1179 # warp engines) or which are particularly delicate (such as
1180 # the transporter) have a much higher probability of being
1183 # This is one place where OPTION_PLAIN does not restore the
1184 # original behavior, which was equiprobable damage across
1185 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1186 # and have done with it. Also, in the original game, DNAVYS
1187 # and DCOMPTR were the same device.
1189 # Instead, we use a table of weights similar to the one from BSD Trek.
1190 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1191 # We don't have a cloaking device. The shuttle got the allocation
1192 # for the cloaking device, then we shaved a half-percent off
1193 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1195 105, # DSRSENS: short range scanners 10.5%
1196 105, # DLRSENS: long range scanners 10.5%
1197 120, # DPHASER: phasers 12.0%
1198 120, # DPHOTON: photon torpedoes 12.0%
1199 25, # DLIFSUP: life support 2.5%
1200 65, # DWARPEN: warp drive 6.5%
1201 70, # DIMPULS: impulse engines 6.5%
1202 145, # DSHIELD: deflector shields 14.5%
1203 30, # DRADIO: subspace radio 3.0%
1204 45, # DSHUTTL: shuttle 4.5%
1205 15, # DCOMPTR: computer 1.5%
1206 20, # NAVCOMP: navigation system 2.0%
1207 75, # DTRANSP: transporter 7.5%
1208 20, # DSHCTRL: high-speed shield controller 2.0%
1209 10, # DDRAY: death ray 1.0%
1210 30, # DDSP: deep-space probes 3.0%
1212 idx = randrange(1000) # weights must sum to 1000
1214 for (i, w) in enumerate(weights):
1218 return None; # we should never get here
1220 def collision(rammed, enemy):
1221 "Collision handling fot rammong events."
1222 prouts(_("***RED ALERT! RED ALERT!"))
1224 prout(_("***COLLISION IMMINENT."))
1228 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(enemy.type, 1.0)
1230 proutn(_(" rammed by "))
1233 proutn(crmena(False, enemy.type, "sector", enemy.kloc))
1235 proutn(_(" (original position)"))
1237 deadkl(enemy.kloc, enemy.type, game.sector)
1238 proutn("***" + crmship() + " heavily damaged.")
1239 icas = randrange(10, 30)
1240 prout(_("***Sickbay reports %d casualties"), icas)
1242 game.state.crew -= icas
1243 # In the pre-SST2K version, all devices got equiprobably damaged,
1244 # which was silly. Instead, pick up to half the devices at
1245 # random according to our weighting table,
1246 ncrits = randrange(NDEVICES/2)
1247 for m in range(ncrits):
1249 if game.damage[dev] < 0:
1251 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1252 # Damage for at least time of travel!
1253 game.damage[dev] += game.optime + extradm
1255 prout(_("***Shields are down."))
1256 if game.state.remkl + len(game.state.kcmdr) + game.state.nscrem:
1263 def torpedo(origin, course, dispersion, number, nburst):
1264 "Let a photon torpedo fly"
1265 if not damaged(DSRSENS) or game.condition=="docked":
1266 setwnd(srscan_window)
1268 setwnd(message_window)
1270 ac = course + 0.25*dispersion
1271 angle = (15.0-ac)*0.5235988
1272 bullseye = (15.0 - course)*0.5235988
1273 delta = coord(-math.sin(angle), math.cos(angle))
1274 bigger = max(abs(delta.i), abs(delta.j))
1276 w = coord(0, 0); jw = coord(0, 0)
1277 ungridded = copy.copy(origin)
1278 # Loop to move a single torpedo
1279 for step in range(1, QUADSIZE*2):
1281 w = ungridded.snaptogrid()
1282 if not VALID_SECTOR(w.i, w.j):
1284 iquad=game.quad[w.i][w.j]
1285 tracktorpedo(origin, w, step, number, nburst, iquad)
1289 setwnd(message_window)
1290 if damaged(DSRSENS) and not game.condition=="docked":
1291 skip(1); # start new line after text track
1292 if iquad in (IHE, IHF): # Hit our ship
1294 prout(_("Torpedo hits %s.") % crmshp())
1295 hit = 700.0 + randreal(100) - \
1296 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1297 newcnd(); # we're blown out of dock
1298 # We may be displaced.
1299 if game.landed or game.condition=="docked":
1300 return hit # Cheat if on a planet
1301 ang = angle + 2.5*(randreal()-0.5)
1302 temp = math.fabs(math.sin(ang))
1303 if math.fabs(math.cos(ang)) > temp:
1304 temp = math.fabs(math.cos(ang))
1305 xx = -math.sin(ang)/temp
1306 yy = math.cos(ang)/temp
1307 jw.i = int(w.i+xx+0.5)
1308 jw.j = int(w.j+yy+0.5)
1309 if not VALID_SECTOR(jw.i, jw.j):
1311 if game.quad[jw.i][jw.j]==IHBLANK:
1314 if game.quad[jw.i][jw.j]!=IHDOT:
1315 # can't move into object
1320 elif iquad in (IHC, IHS, IHR, IHK): # Hit a regular enemy
1322 if iquad in (IHC, IHS) and withprob(0.05):
1323 prout(crmena(True, iquad, "sector", w) + _(" uses anti-photon device;"))
1324 prout(_(" torpedo neutralized."))
1326 for enemy in game.enemies:
1329 kp = math.fabs(enemy.kpower)
1330 h1 = 700.0 + randrange(100) - \
1331 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1335 if enemy.kpower < 0:
1339 if enemy.kpower == 0:
1342 proutn(crmena(True, iquad, "sector", w))
1343 # If enemy damaged but not destroyed, try to displace
1344 ang = angle + 2.5*(randreal()-0.5)
1345 temp = math.fabs(math.sin(ang))
1346 if math.fabs(math.cos(ang)) > temp:
1347 temp = math.fabs(math.cos(ang))
1348 xx = -math.sin(ang)/temp
1349 yy = math.cos(ang)/temp
1350 jw.i = int(w.i+xx+0.5)
1351 jw.j = int(w.j+yy+0.5)
1352 if not VALID_SECTOR(jw.i, jw.j):
1353 prout(_(" damaged but not destroyed."))
1355 if game.quad[jw.i][jw.j]==IHBLANK:
1356 prout(_(" buffeted into black hole."))
1357 deadkl(w, iquad, jw)
1359 if game.quad[jw.i][jw.j]!=IHDOT:
1360 # can't move into object
1361 prout(_(" damaged but not destroyed."))
1363 proutn(_(" damaged--"))
1367 elif iquad == IHB: # Hit a base
1369 prout(_("***STARBASE DESTROYED.."))
1370 game.state.baseq = filter(lambda x: x != game.quadrant, game.state.baseq)
1371 game.quad[w.i][w.j]=IHDOT
1372 game.base.invalidate()
1373 game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase -= 1
1374 game.state.chart[game.quadrant.i][game.quadrant.j].starbase -= 1
1375 game.state.basekl += 1
1378 elif iquad == IHP: # Hit a planet
1379 prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
1380 game.state.nplankl += 1
1381 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
1382 game.iplnet.pclass = "destroyed"
1384 game.plnet.invalidate()
1385 game.quad[w.i][w.j] = IHDOT
1387 # captain perishes on planet
1390 elif iquad == IHW: # Hit an inhabited world -- very bad!
1391 prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
1392 game.state.nworldkl += 1
1393 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
1394 game.iplnet.pclass = "destroyed"
1396 game.plnet.invalidate()
1397 game.quad[w.i][w.j] = IHDOT
1399 # captain perishes on planet
1401 prout(_("You have just destroyed an inhabited planet."))
1402 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1404 elif iquad == IHSTAR: # Hit a star
1408 prout(crmena(True, IHSTAR, "sector", w) + _(" unaffected by photon blast."))
1410 elif iquad == IHQUEST: # Hit a thingy
1411 if not (game.options & OPTION_THINGY) or withprob(0.3):
1413 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1415 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1417 proutn(_("Mr. Spock-"))
1418 prouts(_(" \"Fascinating!\""))
1422 # Stas Sergeev added the possibility that
1423 # you can shove the Thingy and piss it off.
1424 # It then becomes an enemy and may fire at you.
1428 elif iquad == IHBLANK: # Black hole
1430 prout(crmena(True, IHBLANK, "sector", w) + _(" swallows torpedo."))
1432 elif iquad == IHWEB: # hit the web
1434 prout(_("***Torpedo absorbed by Tholian web."))
1436 elif iquad == IHT: # Hit a Tholian
1437 h1 = 700.0 + randrange(100) - \
1438 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1441 game.quad[w.i][w.j] = IHDOT
1446 proutn(crmena(True, IHT, "sector", w))
1448 prout(_(" survives photon blast."))
1450 prout(_(" disappears."))
1451 game.tholian.move(None)
1452 game.quad[w.i][w.j] = IHWEB
1457 proutn("Don't know how to handle torpedo collision with ")
1458 proutn(crmena(True, iquad, "sector", w))
1462 if curwnd!=message_window:
1463 setwnd(message_window)
1465 game.quad[w.i][w.j]=IHDOT
1466 game.quad[jw.i][jw.j]=iquad
1467 prout(_(" displaced by blast to Sector %s ") % jw)
1468 for ll in range(len(game.enemies)):
1469 game.enemies[ll].kdist = game.enemies[ll].kavgd = (game.sector-game.enemies[ll].kloc).distance()
1470 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1473 prout(_("Torpedo missed."))
1477 "Critical-hit resolution."
1478 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1480 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1481 proutn(_("***CRITICAL HIT--"))
1482 # Select devices and cause damage
1484 for loop1 in range(ncrit):
1487 # Cheat to prevent shuttle damage unless on ship
1488 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1491 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1492 game.damage[j] += extradm
1494 for (i, j) in enumerate(cdam):
1496 if skipcount % 3 == 2 and i < len(cdam)-1:
1501 prout(_(" damaged."))
1502 if damaged(DSHIELD) and game.shldup:
1503 prout(_("***Shields knocked down."))
1506 def attack(torps_ok):
1507 # bad guy attacks us
1508 # torps_ok == False forces use of phasers in an attack
1509 # game could be over at this point, check
1512 attempt = False; ihurt = False;
1513 hitmax=0.0; hittot=0.0; chgfac=1.0
1516 prout("=== ATTACK!")
1517 # Tholian gets to move before attacking
1520 # if you have just entered the RNZ, you'll get a warning
1521 if game.neutz: # The one chance not to be attacked
1524 # commanders get a chance to tac-move towards you
1525 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:
1527 # if no enemies remain after movement, we're done
1528 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1530 # set up partial hits if attack happens during shield status change
1531 pfac = 1.0/game.inshld
1533 chgfac = 0.25 + randreal(0.5)
1535 # message verbosity control
1536 if game.skill <= SKILL_FAIR:
1538 for enemy in game.enemies:
1539 if enemy.kpower < 0:
1540 continue; # too weak to attack
1541 # compute hit strength and diminish shield power
1543 # Increase chance of photon torpedos if docked or enemy energy is low
1544 if game.condition == "docked":
1546 if enemy.kpower < 500:
1548 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1550 # different enemies have different probabilities of throwing a torp
1551 usephasers = not torps_ok or \
1552 (enemy.type == IHK and r > 0.0005) or \
1553 (enemy.type==IHC and r > 0.015) or \
1554 (enemy.type==IHR and r > 0.3) or \
1555 (enemy.type==IHS and r > 0.07) or \
1556 (enemy.type==IHQUEST and r > 0.05)
1557 if usephasers: # Enemy uses phasers
1558 if game.condition == "docked":
1559 continue; # Don't waste the effort!
1560 attempt = True; # Attempt to attack
1561 dustfac = randreal(0.8, 0.85)
1562 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1563 enemy.kpower *= 0.75
1564 else: # Enemy uses photon torpedo
1565 # We should be able to make the bearing() method work here
1566 course = 1.90985*math.atan2(game.sector.j-enemy.kloc.j, enemy.kloc.i-game.sector.i)
1568 proutn(_("***TORPEDO INCOMING"))
1569 if not damaged(DSRSENS):
1570 proutn(_(" From ") + crmena(False, enemy.type, where, enemy.kloc))
1573 dispersion = (randreal()+randreal())*0.5 - 0.5
1574 dispersion += 0.002*enemy.kpower*dispersion
1575 hit = torpedo(enemy.kloc, course, dispersion, number=1, nburst=1)
1576 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1577 finish(FWON); # Klingons did themselves in!
1578 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.alldone:
1579 return # Supernova or finished
1582 # incoming phaser or torpedo, shields may dissipate it
1583 if game.shldup or game.shldchg or game.condition=="docked":
1584 # shields will take hits
1585 propor = pfac * game.shield
1586 if game.condition =="docked":
1590 hitsh = propor*chgfac*hit+1.0
1592 if absorb > game.shield:
1593 absorb = game.shield
1594 game.shield -= absorb
1596 # taking a hit blasts us out of a starbase dock
1597 if game.condition == "docked":
1599 # but the shields may take care of it
1600 if propor > 0.1 and hit < 0.005*game.energy:
1602 # hit from this opponent got through shields, so take damage
1604 proutn(_("%d unit hit") % int(hit))
1605 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1606 proutn(_(" on the ") + crmshp())
1607 if not damaged(DSRSENS) and usephasers:
1608 prout(_(" from ") + crmena(False, enemy.type, where, enemy.kloc))
1610 # Decide if hit is critical
1616 if game.energy <= 0:
1617 # Returning home upon your shield, not with it...
1620 if not attempt and game.condition == "docked":
1621 prout(_("***Enemies decide against attacking your ship."))
1622 percent = 100.0*pfac*game.shield+0.5
1624 # Shields fully protect ship
1625 proutn(_("Enemy attack reduces shield strength to "))
1627 # Emit message if starship suffered hit(s)
1629 proutn(_("Energy left %2d shields ") % int(game.energy))
1632 elif not damaged(DSHIELD):
1635 proutn(_("damaged, "))
1636 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1637 # Check if anyone was hurt
1638 if hitmax >= 200 or hittot >= 500:
1639 icas = randrange(int(hittot * 0.015))
1642 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1643 prout(_(" in that last attack.\""))
1645 game.state.crew -= icas
1646 # After attack, reset average distance to enemies
1647 for enemy in game.enemies:
1648 enemy.kavgd = enemy.kdist
1649 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1652 def deadkl(w, type, mv):
1653 "Kill a Klingon, Tholian, Romulan, or Thingy."
1654 # Added mv to allow enemy to "move" before dying
1655 proutn(crmena(True, type, "sector", mv))
1656 # Decide what kind of enemy it is and update appropriately
1658 # chalk up a Romulan
1659 game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans -= 1
1661 game.state.nromrem -= 1
1665 elif type == IHQUEST:
1670 # Some type of a Klingon
1671 game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
1674 game.state.kcmdr.remove(game.quadrant)
1676 if game.state.kcmdr:
1677 schedule(FTBEAM, expran(1.0*game.incom/len(game.state.kcmdr)))
1678 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1681 game.state.remkl -= 1
1683 game.state.nscrem -= 1
1684 game.state.kscmdr.invalidate()
1689 # For each kind of enemy, finish message to player
1690 prout(_(" destroyed."))
1691 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1694 # Remove enemy ship from arrays describing local conditions
1695 for e in game.enemies:
1702 "Return None if target is invalid, otherwise return a course angle."
1703 if not VALID_SECTOR(w.i, w.j):
1707 # FIXME: C code this was translated from is wacky -- why the sign reversal?
1708 delta.j = (w.j - game.sector.j);
1709 delta.i = (game.sector.i - w.i);
1710 if delta == coord(0, 0):
1712 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1713 prout(_(" I recommend an immediate review of"))
1714 prout(_(" the Captain's psychological profile.\""))
1717 return delta.bearing()
1720 "Launch photon torpedo."
1723 if damaged(DPHOTON):
1724 prout(_("Photon tubes damaged."))
1728 prout(_("No torpedoes left."))
1731 # First, get torpedo count
1734 if scanner.token == "IHALPHA":
1737 elif scanner.token == "IHEOL" or not scanner.waiting():
1738 prout(_("%d torpedoes left.") % game.torps)
1740 proutn(_("Number of torpedoes to fire- "))
1741 continue # Go back around to get a number
1742 else: # key == "IHREAL"
1744 if n <= 0: # abort command
1749 prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
1752 scanner.chew() # User requested more torps than available
1753 continue # Go back around
1754 break # All is good, go to next stage
1758 key = scanner.next()
1759 if i==0 and key == "IHEOL":
1760 break; # no coordinate waiting, we will try prompting
1761 if i==1 and key == "IHEOL":
1762 # direct all torpedoes at one target
1764 target.append(target[0])
1765 course.append(course[0])
1768 scanner.push(scanner.token)
1769 target.append(scanner.getcoord())
1770 if target[-1] == None:
1772 course.append(targetcheck(target[-1]))
1773 if course[-1] == None:
1776 if len(target) == 0:
1777 # prompt for each one
1779 proutn(_("Target sector for torpedo number %d- ") % (i+1))
1781 target.append(scanner.getcoord())
1782 if target[-1] == None:
1784 course.append(targetcheck(target[-1]))
1785 if course[-1] == None:
1788 # Loop for moving <n> torpedoes
1790 if game.condition != "docked":
1792 dispersion = (randreal()+randreal())*0.5 -0.5
1793 if math.fabs(dispersion) >= 0.47:
1795 dispersion *= randreal(1.2, 2.2)
1797 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1799 prouts(_("***TORPEDO MISFIRES."))
1802 prout(_(" Remainder of burst aborted."))
1804 prout(_("***Photon tubes damaged by misfire."))
1805 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1807 if game.shldup or game.condition == "docked":
1808 dispersion *= 1.0 + 0.0001*game.shield
1809 torpedo(game.sector, course[i], dispersion, number=i, nburst=n)
1810 if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
1812 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1816 "Check for phasers overheating."
1818 checkburn = (rpow-1500.0)*0.00038
1819 if withprob(checkburn):
1820 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1821 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1823 def checkshctrl(rpow):
1824 "Check shield control."
1827 prout(_("Shields lowered."))
1829 # Something bad has happened
1830 prouts(_("***RED ALERT! RED ALERT!"))
1832 hit = rpow*game.shield/game.inshld
1833 game.energy -= rpow+hit*0.8
1834 game.shield -= hit*0.2
1835 if game.energy <= 0.0:
1836 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1841 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1843 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1844 icas = randrange(int(hit*0.012))
1849 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1850 prout(_(" %d casualties so far.\"") % icas)
1852 game.state.crew -= icas
1854 prout(_("Phaser energy dispersed by shields."))
1855 prout(_("Enemy unaffected."))
1860 "Register a phaser hit on Klingons and Romulans."
1861 nenhr2 = len(game.enemies); kk=0
1864 for (k, wham) in enumerate(hits):
1867 dustfac = randreal(0.9, 1.0)
1868 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1869 kpini = game.enemies[kk].kpower
1870 kp = math.fabs(kpini)
1871 if PHASEFAC*hit < kp:
1873 if game.enemies[kk].kpower < 0:
1874 game.enemies[kk].kpower -= -kp
1876 game.enemies[kk].kpower -= kp
1877 kpow = game.enemies[kk].kpower
1878 w = game.enemies[kk].kloc
1880 if not damaged(DSRSENS):
1882 proutn(_("%d unit hit on ") % int(hit))
1884 proutn(_("Very small hit on "))
1885 ienm = game.quad[w.i][w.j]
1888 proutn(crmena(False, ienm, "sector", w))
1892 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1896 kk -= 1 # don't do the increment
1898 else: # decide whether or not to emasculate klingon
1899 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
1900 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
1901 prout(_(" has just lost its firepower.\""))
1902 game.enemies[kk].kpower = -kpow
1907 "Fire phasers at bad guys."
1909 kz = 0; k = 1; irec=0 # Cheating inhibitor
1910 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
1914 # SR sensors and Computer are needed for automode
1915 if damaged(DSRSENS) or damaged(DCOMPTR):
1917 if game.condition == "docked":
1918 prout(_("Phasers can't be fired through base shields."))
1921 if damaged(DPHASER):
1922 prout(_("Phaser control damaged."))
1926 if damaged(DSHCTRL):
1927 prout(_("High speed shield control damaged."))
1930 if game.energy <= 200.0:
1931 prout(_("Insufficient energy to activate high-speed shield control."))
1934 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
1936 # Original code so convoluted, I re-did it all
1937 # (That was Tom Almy talking about the C code, I think -- ESR)
1938 while automode=="NOTSET":
1940 if key == "IHALPHA":
1941 if scanner.sees("manual"):
1942 if len(game.enemies)==0:
1943 prout(_("There is no enemy present to select."))
1946 automode="AUTOMATIC"
1949 key = scanner.next()
1950 elif scanner.sees("automatic"):
1951 if (not itarg) and len(game.enemies) != 0:
1952 automode = "FORCEMAN"
1954 if len(game.enemies)==0:
1955 prout(_("Energy will be expended into space."))
1956 automode = "AUTOMATIC"
1957 key = scanner.next()
1958 elif scanner.sees("no"):
1963 elif key == "IHREAL":
1964 if len(game.enemies)==0:
1965 prout(_("Energy will be expended into space."))
1966 automode = "AUTOMATIC"
1968 automode = "FORCEMAN"
1970 automode = "AUTOMATIC"
1973 if len(game.enemies)==0:
1974 prout(_("Energy will be expended into space."))
1975 automode = "AUTOMATIC"
1977 automode = "FORCEMAN"
1979 proutn(_("Manual or automatic? "))
1984 if automode == "AUTOMATIC":
1985 if key == "IHALPHA" and scanner.sees("no"):
1987 key = scanner.next()
1988 if key != "IHREAL" and len(game.enemies) != 0:
1989 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
1994 for i in range(len(game.enemies)):
1995 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
1997 proutn(_("%d units required. ") % irec)
1999 proutn(_("Units to fire= "))
2000 key = scanner.next()
2005 proutn(_("Energy available= %.2f") % avail)
2008 if not rpow > avail:
2015 if key == "IHALPHA" and scanner.sees("no"):
2018 game.energy -= 200; # Go and do it!
2019 if checkshctrl(rpow):
2024 if len(game.enemies):
2027 for i in range(len(game.enemies)):
2031 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2032 over = randreal(1.01, 1.06) * hits[i]
2034 powrem -= hits[i] + over
2035 if powrem <= 0 and temp < hits[i]:
2044 if extra > 0 and not game.alldone:
2046 proutn(_("*** Tholian web absorbs "))
2047 if len(game.enemies)>0:
2048 proutn(_("excess "))
2049 prout(_("phaser energy."))
2051 prout(_("%d expended on empty space.") % int(extra))
2052 elif automode == "FORCEMAN":
2055 if damaged(DCOMPTR):
2056 prout(_("Battle computer damaged, manual fire only."))
2059 prouts(_("---WORKING---"))
2061 prout(_("Short-range-sensors-damaged"))
2062 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2063 prout(_("Manual-fire-must-be-used"))
2065 elif automode == "MANUAL":
2067 for k in range(len(game.enemies)):
2068 aim = game.enemies[k].kloc
2069 ienm = game.quad[aim.i][aim.j]
2071 proutn(_("Energy available= %.2f") % (avail-0.006))
2075 if damaged(DSRSENS) and \
2076 not game.sector.distance(aim)<2**0.5 and ienm in (IHC, IHS):
2077 prout(cramen(ienm) + _(" can't be located without short range scan."))
2080 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2085 if itarg and k > kz:
2086 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2089 if not damaged(DCOMPTR):
2094 proutn(_("units to fire at %s- ") % crmena(False, ienm, "sector", aim))
2095 key = scanner.next()
2096 if key == "IHALPHA" and scanner.sees("no"):
2098 key = scanner.next()
2100 if key == "IHALPHA":
2104 if k==1: # Let me say I'm baffled by this
2107 if scanner.real < 0:
2111 hits[k] = scanner.real
2112 rpow += scanner.real
2113 # If total requested is too much, inform and start over
2115 prout(_("Available energy exceeded -- try again."))
2118 key = scanner.next(); # scan for next value
2121 # zero energy -- abort
2124 if key == "IHALPHA" and scanner.sees("no"):
2129 game.energy -= 200.0
2130 if checkshctrl(rpow):
2134 # Say shield raised or malfunction, if necessary
2141 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2142 prouts(_(" CLICK CLICK POP . . ."))
2143 prout(_(" No response, sir!"))
2146 prout(_("Shields raised."))
2151 # Code from events,c begins here.
2153 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2154 # event of each type active at any given time. Mostly these means we can
2155 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2156 # BSD Trek, from which we swiped the idea, can have up to 5.
2158 def unschedule(evtype):
2159 "Remove an event from the schedule."
2160 game.future[evtype].date = FOREVER
2161 return game.future[evtype]
2163 def is_scheduled(evtype):
2164 "Is an event of specified type scheduled."
2165 return game.future[evtype].date != FOREVER
2167 def scheduled(evtype):
2168 "When will this event happen?"
2169 return game.future[evtype].date
2171 def schedule(evtype, offset):
2172 "Schedule an event of specified type."
2173 game.future[evtype].date = game.state.date + offset
2174 return game.future[evtype]
2176 def postpone(evtype, offset):
2177 "Postpone a scheduled event."
2178 game.future[evtype].date += offset
2181 "Rest period is interrupted by event."
2184 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2186 game.resting = False
2192 "Run through the event queue looking for things to do."
2194 fintim = game.state.date + game.optime; yank=0
2195 ictbeam = False; istract = False
2196 w = coord(); hold = coord()
2197 ev = event(); ev2 = event()
2199 def tractorbeam(yank):
2200 "Tractor-beaming cases merge here."
2202 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2204 prout("***" + crmshp() + _(" caught in long range tractor beam--"))
2205 # If Kirk & Co. screwing around on planet, handle
2206 atover(True) # atover(true) is Grab
2209 if game.icraft: # Caught in Galileo?
2212 # Check to see if shuttle is aboard
2213 if game.iscraft == "offship":
2216 prout(_("Galileo, left on the planet surface, is captured"))
2217 prout(_("by aliens and made into a flying McDonald's."))
2218 game.damage[DSHUTTL] = -10
2219 game.iscraft = "removed"
2221 prout(_("Galileo, left on the planet surface, is well hidden."))
2223 game.quadrant = game.state.kscmdr
2225 game.quadrant = game.state.kcmdr[i]
2226 game.sector = randplace(QUADSIZE)
2227 prout(crmshp() + _(" is pulled to Quadrant %s, Sector %s") \
2228 % (game.quadrant, game.sector))
2230 prout(_("(Remainder of rest/repair period cancelled.)"))
2231 game.resting = False
2233 if not damaged(DSHIELD) and game.shield > 0:
2234 doshield(shraise=True) # raise shields
2235 game.shldchg = False
2237 prout(_("(Shields not currently useable.)"))
2239 # Adjust finish time to time of tractor beaming
2240 fintim = game.state.date+game.optime
2241 attack(torps_ok=False)
2242 if not game.state.kcmdr:
2245 schedule(FTBEAM, game.optime+expran(1.5*game.intime/len(game.state.kcmdr)))
2248 "Code merges here for any commander destroying a starbase."
2249 # Not perfect, but will have to do
2250 # Handle case where base is in same quadrant as starship
2251 if game.battle == game.quadrant:
2252 game.state.chart[game.battle.i][game.battle.j].starbase = False
2253 game.quad[game.base.i][game.base.j] = IHDOT
2254 game.base.invalidate()
2257 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2258 elif game.state.baseq and communicating():
2259 # Get word via subspace radio
2262 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2263 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2265 prout(_("the Klingon Super-Commander"))
2267 prout(_("a Klingon Commander"))
2268 game.state.chart[game.battle.i][game.battle.j].starbase = False
2269 # Remove Starbase from galaxy
2270 game.state.galaxy[game.battle.i][game.battle.j].starbase = False
2271 game.state.baseq = filter(lambda x: x != game.battle, game.state.baseq)
2273 # reinstate a commander's base attack
2277 game.battle.invalidate()
2279 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2280 for i in range(1, NEVENTS):
2281 if i == FSNOVA: proutn("=== Supernova ")
2282 elif i == FTBEAM: proutn("=== T Beam ")
2283 elif i == FSNAP: proutn("=== Snapshot ")
2284 elif i == FBATTAK: proutn("=== Base Attack ")
2285 elif i == FCDBAS: proutn("=== Base Destroy ")
2286 elif i == FSCMOVE: proutn("=== SC Move ")
2287 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2288 elif i == FDSPROB: proutn("=== Probe Move ")
2289 elif i == FDISTR: proutn("=== Distress Call ")
2290 elif i == FENSLV: proutn("=== Enslavement ")
2291 elif i == FREPRO: proutn("=== Klingon Build ")
2293 prout("%.2f" % (scheduled(i)))
2296 radio_was_broken = damaged(DRADIO)
2299 # Select earliest extraneous event, evcode==0 if no events
2304 for l in range(1, NEVENTS):
2305 if game.future[l].date < datemin:
2308 prout("== Event %d fires" % evcode)
2309 datemin = game.future[l].date
2310 xtime = datemin-game.state.date
2311 game.state.date = datemin
2312 # Decrement Federation resources and recompute remaining time
2313 game.state.remres -= (game.state.remkl+4*len(game.state.kcmdr))*xtime
2315 if game.state.remtime <=0:
2318 # Any crew left alive?
2319 if game.state.crew <=0:
2322 # Is life support adequate?
2323 if damaged(DLIFSUP) and game.condition != "docked":
2324 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2327 game.lsupres -= xtime
2328 if game.damage[DLIFSUP] <= xtime:
2329 game.lsupres = game.inlsr
2332 if game.condition == "docked":
2333 repair /= game.docfac
2334 # Don't fix Deathray here
2335 for l in range(NDEVICES):
2336 if game.damage[l] > 0.0 and l != DDRAY:
2337 if game.damage[l]-repair > 0.0:
2338 game.damage[l] -= repair
2340 game.damage[l] = 0.0
2341 # If radio repaired, update star chart and attack reports
2342 if radio_was_broken and not damaged(DRADIO):
2343 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2344 prout(_(" surveillance reports are coming in."))
2346 if not game.iseenit:
2350 prout(_(" The star chart is now up to date.\""))
2352 # Cause extraneous event EVCODE to occur
2353 game.optime -= xtime
2354 if evcode == FSNOVA: # Supernova
2357 schedule(FSNOVA, expran(0.5*game.intime))
2358 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2360 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2361 if game.state.nscrem == 0 or \
2362 ictbeam or istract or \
2363 game.condition=="docked" or game.isatb==1 or game.iscate:
2365 if game.ientesc or \
2366 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2367 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2368 (damaged(DSHIELD) and \
2369 (game.energy < 2500 or damaged(DPHASER)) and \
2370 (game.torps < 5 or damaged(DPHOTON))):
2372 istract = ictbeam = True
2373 tractorbeam((game.state.kscmdr-game.quadrant).distance())
2376 elif evcode == FTBEAM: # Tractor beam
2377 if not game.state.kcmdr:
2380 i = randrange(len(game.state.kcmdr))
2381 yank = (game.state.kcmdr[i]-game.quadrant).distance()
2382 if istract or game.condition == "docked" or yank == 0:
2383 # Drats! Have to reschedule
2385 game.optime + expran(1.5*game.intime/len(game.state.kcmdr)))
2389 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2390 game.snapsht = copy.deepcopy(game.state)
2391 game.state.snap = True
2392 schedule(FSNAP, expran(0.5 * game.intime))
2393 elif evcode == FBATTAK: # Commander attacks starbase
2394 if not game.state.kcmdr or not game.state.baseq:
2400 for ibq in game.state.baseq:
2401 for cmdr in game.state.kcmdr:
2402 if ibq == cmdr and ibq != game.quadrant and ibq != game.state.kscmdr:
2405 # no match found -- try later
2406 schedule(FBATTAK, expran(0.3*game.intime))
2411 # commander + starbase combination found -- launch attack
2413 schedule(FCDBAS, randreal(1.0, 4.0))
2414 if game.isatb: # extra time if SC already attacking
2415 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2416 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2417 game.iseenit = False
2418 if not communicating():
2419 continue # No warning :-(
2423 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2424 prout(_(" reports that it is under attack and that it can"))
2425 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2428 elif evcode == FSCDBAS: # Supercommander destroys base
2431 if not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].starbase:
2432 continue # WAS RETURN!
2434 game.battle = game.state.kscmdr
2436 elif evcode == FCDBAS: # Commander succeeds in destroying base
2439 if not game.state.baseq() \
2440 or not game.state.galaxy[game.battle.i][game.battle.j].starbase:
2441 game.battle.invalidate()
2443 # find the lucky pair
2444 for cmdr in game.state.kcmdr:
2445 if cmdr == game.battle:
2448 # No action to take after all
2451 elif evcode == FSCMOVE: # Supercommander moves
2452 schedule(FSCMOVE, 0.2777)
2453 if not game.ientesc and not istract and game.isatb != 1 and \
2454 (not game.iscate or not game.justin):
2456 elif evcode == FDSPROB: # Move deep space probe
2457 schedule(FDSPROB, 0.01)
2458 game.probe += game.probein
2459 i = int(round(game.probe.i/float(QUADSIZE)))
2460 j = int(round(game.probe.j/float(QUADSIZE)))
2461 if game.probec.i != i or game.probec.j != j:
2464 if not VALID_QUADRANT(i, j) or \
2465 game.state.galaxy[game.probec.i][game.probec.j].supernova:
2466 # Left galaxy or ran into supernova
2470 proutn(_("Lt. Uhura- \"The deep space probe "))
2471 if not VALID_QUADRANT(i, j):
2472 proutn(_("has left the galaxy"))
2474 proutn(_("is no longer transmitting"))
2478 if not communicating():
2481 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2482 pdest = game.state.galaxy[game.probec.i][game.probec.j]
2483 # Update star chart if Radio is working or have access to radio
2485 chp = game.state.chart[game.probec.i][game.probec.j]
2486 chp.klingons = pdest.klingons
2487 chp.starbase = pdest.starbase
2488 chp.stars = pdest.stars
2489 pdest.charted = True
2490 game.proben -= 1 # One less to travel
2491 if game.proben == 0 and game.isarmed and pdest.stars:
2492 supernova(game.probec) # fire in the hole!
2494 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2496 elif evcode == FDISTR: # inhabited system issues distress call
2498 # try a whole bunch of times to find something suitable
2499 for i in range(100):
2500 # need a quadrant which is not the current one,
2501 # which has some stars which are inhabited and
2502 # not already under attack, which is not
2503 # supernova'ed, and which has some Klingons in it
2504 w = randplace(GALSIZE)
2505 q = game.state.galaxy[w.i][w.j]
2506 if not (game.quadrant == w or q.planet == None or \
2507 not q.planet.inhabited or \
2508 q.supernova or q.status!="secure" or q.klingons<=0):
2511 # can't seem to find one; ignore this call
2513 prout("=== Couldn't find location for distress event.")
2515 # got one!! Schedule its enslavement
2516 ev = schedule(FENSLV, expran(game.intime))
2518 q.status = "distressed"
2519 # tell the captain about it if we can
2521 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2523 prout(_("by a Klingon invasion fleet."))
2526 elif evcode == FENSLV: # starsystem is enslaved
2527 ev = unschedule(FENSLV)
2528 # see if current distress call still active
2529 q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
2533 q.status = "enslaved"
2535 # play stork and schedule the first baby
2536 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2537 ev2.quadrant = ev.quadrant
2539 # report the disaster if we can
2541 prout(_("Uhura- We've lost contact with starsystem %s") % \
2543 prout(_("in Quadrant %s.\n") % ev.quadrant)
2544 elif evcode == FREPRO: # Klingon reproduces
2545 # If we ever switch to a real event queue, we'll need to
2546 # explicitly retrieve and restore the x and y.
2547 ev = schedule(FREPRO, expran(1.0 * game.intime))
2548 # see if current distress call still active
2549 q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
2553 if game.state.remkl >=MAXKLGAME:
2554 continue # full right now
2555 # reproduce one Klingon
2557 if game.klhere >= MAXKLQUAD:
2559 # this quadrant not ok, pick an adjacent one
2560 for i in range(w.i - 1, w.i + 2):
2561 for j in range(w.j - 1, w.j + 2):
2562 if not VALID_QUADRANT(i, j):
2564 q = game.state.galaxy[w.i][w.j]
2565 # check for this quad ok (not full & no snova)
2566 if q.klingons >= MAXKLQUAD or q.supernova:
2570 continue # search for eligible quadrant failed
2574 game.state.remkl += 1
2576 if game.quadrant == w:
2578 game.enemies.append(newkling())
2579 # recompute time left
2581 # report the disaster if we can
2583 if game.quadrant == w:
2584 prout(_("Spock- sensors indicate the Klingons have"))
2585 prout(_("launched a warship from %s.") % q.planet)
2587 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2588 if q.planet != None:
2589 proutn(_("near %s") % q.planet)
2590 prout(_("in Quadrant %s.") % w)
2596 key = scanner.next()
2599 proutn(_("How long? "))
2604 origTime = delay = scanner.real
2607 if delay >= game.state.remtime or len(game.enemies) != 0:
2608 proutn(_("Are you sure? "))
2611 # Alternate resting periods (events) with attacks
2615 game.resting = False
2616 if not game.resting:
2617 prout(_("%d stardates left.") % int(game.state.remtime))
2619 temp = game.optime = delay
2620 if len(game.enemies):
2621 rtime = randreal(1.0, 2.0)
2625 if game.optime < delay:
2626 attack(torps_ok=False)
2634 # Repair Deathray if long rest at starbase
2635 if origTime-delay >= 9.99 and game.condition == "docked":
2636 game.damage[DDRAY] = 0.0
2637 # leave if quadrant supernovas
2638 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2640 game.resting = False
2645 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2646 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2648 # Wow! We've supernova'ed
2649 supernova(game.quadrant)
2651 # handle initial nova
2652 game.quad[nov.i][nov.j] = IHDOT
2653 prout(crmena(False, IHSTAR, "sector", nov) + _(" novas."))
2654 game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
2655 game.state.starkl += 1
2656 # Set up queue to recursively trigger adjacent stars
2662 for offset.i in range(-1, 1+1):
2663 for offset.j in range(-1, 1+1):
2664 if offset.j==0 and offset.i==0:
2666 neighbor = start + offset
2667 if not VALID_SECTOR(neighbor.j, neighbor.i):
2669 iquad = game.quad[neighbor.i][neighbor.j]
2670 # Empty space ends reaction
2671 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2673 elif iquad == IHSTAR: # Affect another star
2675 # This star supernovas
2676 supernova(game.quadrant)
2679 hits.append(neighbor)
2680 game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
2681 game.state.starkl += 1
2682 proutn(crmena(True, IHSTAR, "sector", neighbor))
2684 game.quad[neighbor.i][neighbor.j] = IHDOT
2686 elif iquad in (IHP, IHW): # Destroy planet
2687 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
2689 game.state.nplankl += 1
2691 game.state.worldkl += 1
2692 prout(crmena(True, IHB, "sector", neighbor) + _(" destroyed."))
2693 game.iplnet.pclass = "destroyed"
2695 game.plnet.invalidate()
2699 game.quad[neighbor.i][neighbor.j] = IHDOT
2700 elif iquad == IHB: # Destroy base
2701 game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase = False
2702 game.state.baseq = filter(lambda x: x!= game.quadrant, game.state.baseq)
2703 game.base.invalidate()
2704 game.state.basekl += 1
2706 prout(crmena(True, IHB, "sector", neighbor) + _(" destroyed."))
2707 game.quad[neighbor.i][neighbor.j] = IHDOT
2708 elif iquad in (IHE, IHF): # Buffet ship
2709 prout(_("***Starship buffeted by nova."))
2711 if game.shield >= 2000.0:
2712 game.shield -= 2000.0
2714 diff = 2000.0 - game.shield
2718 prout(_("***Shields knocked out."))
2719 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2721 game.energy -= 2000.0
2722 if game.energy <= 0:
2725 # add in course nova contributes to kicking starship
2726 bump += (game.sector-hits[mm]).sgn()
2727 elif iquad == IHK: # kill klingon
2728 deadkl(neighbor, iquad, neighbor)
2729 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2730 for ll in range(len(game.enemies)):
2731 if game.enemies[ll].kloc == neighbor:
2733 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2734 if game.enemies[ll].kpower <= 0.0:
2735 deadkl(neighbor, iquad, neighbor)
2737 newc = neighbor + neighbor - hits[mm]
2738 proutn(crmena(True, iquad, "sector", neighbor) + _(" damaged"))
2739 if not VALID_SECTOR(newc.i, newc.j):
2740 # can't leave quadrant
2743 iquad1 = game.quad[newc.i][newc.j]
2744 if iquad1 == IHBLANK:
2745 proutn(_(", blasted into ") + crmena(False, IHBLANK, "sector", newc))
2747 deadkl(neighbor, iquad, newc)
2750 # can't move into something else
2753 proutn(_(", buffeted to Sector %s") % newc)
2754 game.quad[neighbor.i][neighbor.j] = IHDOT
2755 game.quad[newc.i][newc.j] = iquad
2756 game.enemies[ll].move(newc)
2757 # Starship affected by nova -- kick it away.
2758 game.dist = kount*0.1
2759 game.direc = course[3*(bump.i+1)+bump.j+2]
2760 if game.direc == 0.0:
2762 if game.dist == 0.0:
2764 game.optime = 10.0*game.dist/16.0
2766 prout(_("Force of nova displaces starship."))
2767 imove(novapush=True)
2768 game.optime = 10.0*game.dist/16.0
2772 "Star goes supernova."
2777 # Scheduled supernova -- select star at random.
2780 for nq.i in range(GALSIZE):
2781 for nq.j in range(GALSIZE):
2782 stars += game.state.galaxy[nq.i][nq.j].stars
2784 return # nothing to supernova exists
2785 num = randrange(stars) + 1
2786 for nq.i in range(GALSIZE):
2787 for nq.j in range(GALSIZE):
2788 num -= game.state.galaxy[nq.i][nq.j].stars
2794 proutn("=== Super nova here?")
2797 if not nq == game.quadrant or game.justin:
2798 # it isn't here, or we just entered (treat as enroute)
2801 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2802 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2805 # we are in the quadrant!
2806 num = randrange(game.state.galaxy[nq.i][nq.j].stars) + 1
2807 for ns.i in range(QUADSIZE):
2808 for ns.j in range(QUADSIZE):
2809 if game.quad[ns.i][ns.j]==IHSTAR:
2816 prouts(_("***RED ALERT! RED ALERT!"))
2818 prout(_("***Incipient supernova detected at Sector %s") % ns)
2819 if (ns.i-game.sector.i)**2 + (ns.j-game.sector.j)**2 <= 2.1:
2820 proutn(_("Emergency override attempts t"))
2821 prouts("***************")
2825 # destroy any Klingons in supernovaed quadrant
2826 kldead = game.state.galaxy[nq.i][nq.j].klingons
2827 game.state.galaxy[nq.i][nq.j].klingons = 0
2828 if nq == game.state.kscmdr:
2829 # did in the Supercommander!
2830 game.state.nscrem = game.state.kscmdr.i = game.state.kscmdr.j = game.isatb = 0
2834 survivors = filter(lambda w: w != nq, game.state.kcmdr)
2835 comkills = len(game.state.kcmdr) - len(survivors)
2836 game.state.kcmdr = survivors
2838 if not game.state.kcmdr:
2840 game.state.remkl -= kldead
2841 # destroy Romulans and planets in supernovaed quadrant
2842 nrmdead = game.state.galaxy[nq.i][nq.j].romulans
2843 game.state.galaxy[nq.i][nq.j].romulans = 0
2844 game.state.nromrem -= nrmdead
2846 for loop in range(game.inplan):
2847 if game.state.planets[loop].quadrant == nq:
2848 game.state.planets[loop].pclass = "destroyed"
2850 # Destroy any base in supernovaed quadrant
2851 game.state.baseq = filter(lambda x: x != nq, game.state.baseq)
2852 # If starship caused supernova, tally up destruction
2854 game.state.starkl += game.state.galaxy[nq.i][nq.j].stars
2855 game.state.basekl += game.state.galaxy[nq.i][nq.j].starbase
2856 game.state.nplankl += npdead
2857 # mark supernova in galaxy and in star chart
2858 if game.quadrant == nq or communicating():
2859 game.state.galaxy[nq.i][nq.j].supernova = True
2860 # If supernova destroys last Klingons give special message
2861 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0 and not nq == game.quadrant:
2864 prout(_("Lucky you!"))
2865 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
2868 # if some Klingons remain, continue or die in supernova
2873 # Code from finish.c ends here.
2876 "Self-destruct maneuver. Finish with a BANG!"
2878 if damaged(DCOMPTR):
2879 prout(_("Computer damaged; cannot execute destruct sequence."))
2881 prouts(_("---WORKING---")); skip(1)
2882 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
2883 prouts(" 10"); skip(1)
2884 prouts(" 9"); skip(1)
2885 prouts(" 8"); skip(1)
2886 prouts(" 7"); skip(1)
2887 prouts(" 6"); skip(1)
2889 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
2891 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
2893 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
2897 if game.passwd != scanner.token:
2898 prouts(_("PASSWORD-REJECTED;"))
2900 prouts(_("CONTINUITY-EFFECTED"))
2903 prouts(_("PASSWORD-ACCEPTED")); skip(1)
2904 prouts(" 5"); skip(1)
2905 prouts(" 4"); skip(1)
2906 prouts(" 3"); skip(1)
2907 prouts(" 2"); skip(1)
2908 prouts(" 1"); skip(1)
2910 prouts(_("GOODBYE-CRUEL-WORLD"))
2918 prouts(_("********* Entropy of %s maximized *********") % crmshp())
2922 if len(game.enemies) != 0:
2923 whammo = 25.0 * game.energy
2925 while l <= len(game.enemies):
2926 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
2927 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.i][game.enemies[l].kloc.j], game.enemies[l].kloc)
2932 "Compute our rate of kils over time."
2933 elapsed = game.state.date - game.indate
2934 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
2937 starting = (game.inkling + game.incom + game.inscom)
2938 remaining = (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)
2939 return (starting - remaining)/elapsed
2943 badpt = 5.0*game.state.starkl + \
2945 10.0*game.state.nplankl + \
2946 300*game.state.nworldkl + \
2948 100.0*game.state.basekl +\
2950 if game.ship == IHF:
2952 elif game.ship == None:
2957 # end the game, with appropriate notfications
2961 prout(_("It is stardate %.1f.") % game.state.date)
2963 if ifin == FWON: # Game has been won
2964 if game.state.nromrem != 0:
2965 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
2968 prout(_("You have smashed the Klingon invasion fleet and saved"))
2969 prout(_("the Federation."))
2974 badpt = 0.0 # Close enough!
2975 # killsPerDate >= RateMax
2976 if game.state.date-game.indate < 5.0 or \
2977 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
2979 prout(_("In fact, you have done so well that Starfleet Command"))
2980 if game.skill == SKILL_NOVICE:
2981 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
2982 elif game.skill == SKILL_FAIR:
2983 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
2984 elif game.skill == SKILL_GOOD:
2985 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
2986 elif game.skill == SKILL_EXPERT:
2987 prout(_("promotes you to Commodore Emeritus."))
2989 prout(_("Now that you think you're really good, try playing"))
2990 prout(_("the \"Emeritus\" game. It will splatter your ego."))
2991 elif game.skill == SKILL_EMERITUS:
2993 proutn(_("Computer- "))
2994 prouts(_("ERROR-ERROR-ERROR-ERROR"))
2996 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
2998 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3000 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3002 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3004 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3006 prout(_("Now you can retire and write your own Star Trek game!"))
3008 elif game.skill >= SKILL_EXPERT:
3009 if game.thawed and not idebug:
3010 prout(_("You cannot get a citation, so..."))
3012 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3016 # Only grant long life if alive (original didn't!)
3018 prout(_("LIVE LONG AND PROSPER."))
3023 elif ifin == FDEPLETE: # Federation Resources Depleted
3024 prout(_("Your time has run out and the Federation has been"))
3025 prout(_("conquered. Your starship is now Klingon property,"))
3026 prout(_("and you are put on trial as a war criminal. On the"))
3027 proutn(_("basis of your record, you are "))
3028 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3029 prout(_("acquitted."))
3031 prout(_("LIVE LONG AND PROSPER."))
3033 prout(_("found guilty and"))
3034 prout(_("sentenced to death by slow torture."))
3038 elif ifin == FLIFESUP:
3039 prout(_("Your life support reserves have run out, and"))
3040 prout(_("you die of thirst, starvation, and asphyxiation."))
3041 prout(_("Your starship is a derelict in space."))
3043 prout(_("Your energy supply is exhausted."))
3045 prout(_("Your starship is a derelict in space."))
3046 elif ifin == FBATTLE:
3047 prout(_("The %s has been destroyed in battle.") % crmshp())
3049 prout(_("Dulce et decorum est pro patria mori."))
3051 prout(_("You have made three attempts to cross the negative energy"))
3052 prout(_("barrier which surrounds the galaxy."))
3054 prout(_("Your navigation is abominable."))
3057 prout(_("Your starship has been destroyed by a nova."))
3058 prout(_("That was a great shot."))
3060 elif ifin == FSNOVAED:
3061 prout(_("The %s has been fried by a supernova.") % crmshp())
3062 prout(_("...Not even cinders remain..."))
3063 elif ifin == FABANDN:
3064 prout(_("You have been captured by the Klingons. If you still"))
3065 prout(_("had a starbase to be returned to, you would have been"))
3066 prout(_("repatriated and given another chance. Since you have"))
3067 prout(_("no starbases, you will be mercilessly tortured to death."))
3068 elif ifin == FDILITHIUM:
3069 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3070 elif ifin == FMATERIALIZE:
3071 prout(_("Starbase was unable to re-materialize your starship."))
3072 prout(_("Sic transit gloria mundi"))
3073 elif ifin == FPHASER:
3074 prout(_("The %s has been cremated by its own phasers.") % crmshp())
3076 prout(_("You and your landing party have been"))
3077 prout(_("converted to energy, disipating through space."))
3078 elif ifin == FMINING:
3079 prout(_("You are left with your landing party on"))
3080 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3082 prout(_("They are very fond of \"Captain Kirk\" soup."))
3084 prout(_("Without your leadership, the %s is destroyed.") % crmshp())
3085 elif ifin == FDPLANET:
3086 prout(_("You and your mining party perish."))
3088 prout(_("That was a great shot."))
3091 prout(_("The Galileo is instantly annihilated by the supernova."))
3092 prout(_("You and your mining party are atomized."))
3094 prout(_("Mr. Spock takes command of the %s and") % crmshp())
3095 prout(_("joins the Romulans, wreaking terror on the Federation."))
3096 elif ifin == FPNOVA:
3097 prout(_("You and your mining party are atomized."))
3099 prout(_("Mr. Spock takes command of the %s and") % crmshp())
3100 prout(_("joins the Romulans, wreaking terror on the Federation."))
3101 elif ifin == FSTRACTOR:
3102 prout(_("The shuttle craft Galileo is also caught,"))
3103 prout(_("and breaks up under the strain."))
3105 prout(_("Your debris is scattered for millions of miles."))
3106 prout(_("Without your leadership, the %s is destroyed.") % crmshp())
3108 prout(_("The mutants attack and kill Spock."))
3109 prout(_("Your ship is captured by Klingons, and"))
3110 prout(_("your crew is put on display in a Klingon zoo."))
3111 elif ifin == FTRIBBLE:
3112 prout(_("Tribbles consume all remaining water,"))
3113 prout(_("food, and oxygen on your ship."))
3115 prout(_("You die of thirst, starvation, and asphyxiation."))
3116 prout(_("Your starship is a derelict in space."))
3118 prout(_("Your ship is drawn to the center of the black hole."))
3119 prout(_("You are crushed into extremely dense matter."))
3121 prout(_("Your last crew member has died."))
3122 if game.ship == IHF:
3124 elif game.ship == IHE:
3127 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0:
3128 goodies = game.state.remres/game.inresor
3129 baddies = (game.state.remkl + 2.0*len(game.state.kcmdr))/(game.inkling+2.0*game.incom)
3130 if goodies/baddies >= randreal(1.0, 1.5):
3131 prout(_("As a result of your actions, a treaty with the Klingon"))
3132 prout(_("Empire has been signed. The terms of the treaty are"))
3133 if goodies/baddies >= randreal(3.0):
3134 prout(_("favorable to the Federation."))
3136 prout(_("Congratulations!"))
3138 prout(_("highly unfavorable to the Federation."))
3140 prout(_("The Federation will be destroyed."))
3142 prout(_("Since you took the last Klingon with you, you are a"))
3143 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3144 prout(_("statue in your memory. Rest in peace, and try not"))
3145 prout(_("to think about pigeons."))
3150 "Compute player's score."
3151 timused = game.state.date - game.indate
3153 if (timused == 0 or (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0) and timused < 5.0:
3155 perdate = killrate()
3156 ithperd = 500*perdate + 0.5
3159 iwon = 100*game.skill
3160 if game.ship == IHE:
3162 elif game.ship == IHF:
3166 if not game.gamewon:
3167 game.state.nromrem = 0 # None captured if no win
3168 iscore = 10*(game.inkling - game.state.remkl) \
3169 + 50*(game.incom - len(game.state.kcmdr)) \
3171 + 20*(game.inrom - game.state.nromrem) \
3172 + 200*(game.inscom - game.state.nscrem) \
3173 - game.state.nromrem \
3178 prout(_("Your score --"))
3179 if game.inrom - game.state.nromrem:
3180 prout(_("%6d Romulans destroyed %5d") %
3181 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3182 if game.state.nromrem:
3183 prout(_("%6d Romulans captured %5d") %
3184 (game.state.nromrem, game.state.nromrem))
3185 if game.inkling - game.state.remkl:
3186 prout(_("%6d ordinary Klingons destroyed %5d") %
3187 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3188 if game.incom - len(game.state.kcmdr):
3189 prout(_("%6d Klingon commanders destroyed %5d") %
3190 (game.incom - len(game.state.kcmdr), 50*(game.incom - len(game.state.kcmdr))))
3191 if game.inscom - game.state.nscrem:
3192 prout(_("%6d Super-Commander destroyed %5d") %
3193 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3195 prout(_("%6.2f Klingons per stardate %5d") %
3197 if game.state.starkl:
3198 prout(_("%6d stars destroyed by your action %5d") %
3199 (game.state.starkl, -5*game.state.starkl))
3200 if game.state.nplankl:
3201 prout(_("%6d planets destroyed by your action %5d") %
3202 (game.state.nplankl, -10*game.state.nplankl))
3203 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3204 prout(_("%6d inhabited planets destroyed by your action %5d") %
3205 (game.state.nplankl, -300*game.state.nworldkl))
3206 if game.state.basekl:
3207 prout(_("%6d bases destroyed by your action %5d") %
3208 (game.state.basekl, -100*game.state.basekl))
3210 prout(_("%6d calls for help from starbase %5d") %
3211 (game.nhelp, -45*game.nhelp))
3213 prout(_("%6d casualties incurred %5d") %
3214 (game.casual, -game.casual))
3216 prout(_("%6d crew abandoned in space %5d") %
3217 (game.abandoned, -3*game.abandoned))
3219 prout(_("%6d ship(s) lost or destroyed %5d") %
3220 (klship, -100*klship))
3222 prout(_("Penalty for getting yourself killed -200"))
3224 proutn(_("Bonus for winning "))
3225 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3226 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3227 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3228 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3229 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3230 prout(" %5d" % iwon)
3232 prout(_("TOTAL SCORE %5d") % iscore)
3235 "Emit winner's commemmorative plaque."
3238 proutn(_("File or device name for your plaque: "))
3241 fp = open(winner, "w")
3244 prout(_("Invalid name."))
3246 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3248 # The 38 below must be 64 for 132-column paper
3249 nskip = 38 - len(winner)/2
3250 fp.write("\n\n\n\n")
3251 # --------DRAW ENTERPRISE PICTURE.
3252 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3253 fp.write(" EEE E : : : E\n" )
3254 fp.write(" EE EEE E : : NCC-1701 : E\n")
3255 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3256 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3257 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3258 fp.write(" EEEEEEE EEEEE E E E E\n")
3259 fp.write(" EEE E E E E\n")
3260 fp.write(" E E E E\n")
3261 fp.write(" EEEEEEEEEEEEE E E\n")
3262 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3263 fp.write(" :E : EEEE E\n")
3264 fp.write(" .-E -:----- E\n")
3265 fp.write(" :E : E\n")
3266 fp.write(" EE : EEEEEEEE\n")
3267 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3269 fp.write(_(" U. S. S. ENTERPRISE\n"))
3270 fp.write("\n\n\n\n")
3271 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3273 fp.write(_(" Starfleet Command bestows to you\n"))
3275 fp.write("%*s%s\n\n" % (nskip, "", winner))
3276 fp.write(_(" the rank of\n\n"))
3277 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3279 if game.skill == SKILL_EXPERT:
3280 fp.write(_(" Expert level\n\n"))
3281 elif game.skill == SKILL_EMERITUS:
3282 fp.write(_("Emeritus level\n\n"))
3284 fp.write(_(" Cheat level\n\n"))
3285 timestring = ctime()
3286 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3287 (timestring+4, timestring+20, timestring+11))
3288 fp.write(_(" Your score: %d\n\n") % iscore)
3289 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3292 # Code from io.c begins here
3294 rows = linecount = 0 # for paging
3297 fullscreen_window = None
3298 srscan_window = None
3299 report_window = None
3300 status_window = None
3301 lrscan_window = None
3302 message_window = None
3303 prompt_window = None
3308 if not (game.options & OPTION_CURSES):
3309 ln_env = os.getenv("LINES")
3315 stdscr = curses.initscr()
3319 global fullscreen_window, srscan_window, report_window, status_window
3320 global lrscan_window, message_window, prompt_window
3321 (rows, columns) = stdscr.getmaxyx()
3322 fullscreen_window = stdscr
3323 srscan_window = curses.newwin(12, 25, 0, 0)
3324 report_window = curses.newwin(11, 0, 1, 25)
3325 status_window = curses.newwin(10, 0, 1, 39)
3326 lrscan_window = curses.newwin(5, 0, 0, 64)
3327 message_window = curses.newwin(0, 0, 12, 0)
3328 prompt_window = curses.newwin(1, 0, rows-2, 0)
3329 message_window.scrollok(True)
3330 setwnd(fullscreen_window)
3334 if game.options & OPTION_CURSES:
3335 stdscr.keypad(False)
3341 "Wait for user action -- OK to do nothing if on a TTY"
3342 if game.options & OPTION_CURSES:
3347 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3351 if game.skill > SKILL_FAIR:
3352 prompt = _("[CONTINUE?]")
3354 prompt = _("[PRESS ENTER TO CONTINUE]")
3356 if game.options & OPTION_CURSES:
3358 setwnd(prompt_window)
3359 prompt_window.wclear()
3360 prompt_window.addstr(prompt)
3361 prompt_window.getstr()
3362 prompt_window.clear()
3363 prompt_window.refresh()
3364 setwnd(message_window)
3367 sys.stdout.write('\n')
3370 for j in range(rows):
3371 sys.stdout.write('\n')
3375 "Skip i lines. Pause game if this would cause a scrolling event."
3376 for dummy in range(i):
3377 if game.options & OPTION_CURSES:
3378 (y, x) = curwnd.getyx()
3379 (my, mx) = curwnd.getmaxyx()
3380 if curwnd == message_window and y >= my - 3:
3386 except curses.error:
3391 if rows and linecount >= rows:
3394 sys.stdout.write('\n')
3397 "Utter a line with no following line feed."
3398 if game.options & OPTION_CURSES:
3402 sys.stdout.write(line)
3412 if not replayfp or replayfp.closed: # Don't slow down replays
3415 if game.options & OPTION_CURSES:
3419 if not replayfp or replayfp.closed:
3423 "Get a line of input."
3424 if game.options & OPTION_CURSES:
3425 line = curwnd.getstr() + "\n"
3428 if replayfp and not replayfp.closed:
3430 line = replayfp.readline()
3433 prout("*** Replay finished")
3436 elif line[0] != "#":
3439 line = raw_input() + "\n"
3445 "Change windows -- OK for this to be a no-op in tty mode."
3447 if game.options & OPTION_CURSES:
3449 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3452 "Clear to end of line -- can be a no-op in tty mode"
3453 if game.options & OPTION_CURSES:
3458 "Clear screen -- can be a no-op in tty mode."
3460 if game.options & OPTION_CURSES:
3467 "Set highlight video, if this is reasonable."
3468 if game.options & OPTION_CURSES:
3469 curwnd.attron(curses.A_REVERSE)
3472 # Things past this point have policy implications.
3476 "Hook to be called after moving to redraw maps."
3477 if game.options & OPTION_CURSES:
3480 setwnd(srscan_window)
3484 setwnd(status_window)
3485 status_window.clear()
3486 status_window.move(0, 0)
3487 setwnd(report_window)
3488 report_window.clear()
3489 report_window.move(0, 0)
3491 setwnd(lrscan_window)
3492 lrscan_window.clear()
3493 lrscan_window.move(0, 0)
3494 lrscan(silent=False)
3496 def put_srscan_sym(w, sym):
3497 "Emit symbol for short-range scan."
3498 srscan_window.move(w.i+1, w.j*2+2)
3499 srscan_window.addch(sym)
3500 srscan_window.refresh()
3503 "Enemy fall down, go boom."
3504 if game.options & OPTION_CURSES:
3506 setwnd(srscan_window)
3507 srscan_window.attron(curses.A_REVERSE)
3508 put_srscan_sym(w, game.quad[w.i][w.j])
3512 srscan_window.attroff(curses.A_REVERSE)
3513 put_srscan_sym(w, game.quad[w.i][w.j])
3514 curses.delay_output(500)
3515 setwnd(message_window)
3518 "Sound and visual effects for teleportation."
3519 if game.options & OPTION_CURSES:
3521 setwnd(message_window)
3523 prouts(" . . . . . ")
3524 if game.options & OPTION_CURSES:
3525 #curses.delay_output(1000)
3529 def tracktorpedo(origin, w, step, i, n, iquad):
3530 "Torpedo-track animation."
3531 if not game.options & OPTION_CURSES:
3535 proutn(_("Track for %s torpedo number %d- ") % (game.quad[origin.i][origin.j],i+1))
3538 proutn(_("Torpedo track- "))
3539 elif step==4 or step==9:
3543 if not damaged(DSRSENS) or game.condition=="docked":
3544 if i != 0 and step == 1:
3547 if (iquad==IHDOT) or (iquad==IHBLANK):
3548 put_srscan_sym(w, '+')
3552 put_srscan_sym(w, iquad)
3554 curwnd.attron(curses.A_REVERSE)
3555 put_srscan_sym(w, iquad)
3559 curwnd.attroff(curses.A_REVERSE)
3560 put_srscan_sym(w, iquad)
3565 "Display the current galaxy chart."
3566 if game.options & OPTION_CURSES:
3567 setwnd(message_window)
3568 message_window.clear()
3570 if game.options & OPTION_TTY:
3575 def prstat(txt, data):
3577 if game.options & OPTION_CURSES:
3579 setwnd(status_window)
3581 proutn(" " * (NSYM - len(txt)))
3584 if game.options & OPTION_CURSES:
3585 setwnd(report_window)
3587 # Code from moving.c begins here
3589 def imove(novapush):
3590 "Movement execution for warp, impulse, supernova, and tractor-beam events."
3591 w = coord(); final = coord()
3594 def no_quad_change():
3595 # No quadrant change -- compute new average enemy distances
3596 game.quad[game.sector.i][game.sector.j] = game.ship
3598 for enemy in game.enemies:
3599 finald = (w-enemy.kloc).distance()
3600 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3601 enemy.kdist = finald
3602 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3603 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3604 attack(torps_ok=False)
3605 for enemy in game.enemies:
3606 enemy.kavgd = enemy.kdist
3609 setwnd(message_window)
3612 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3613 game.inorbit = False
3614 angle = ((15.0 - game.direc) * 0.5235988)
3615 deltax = -math.sin(angle)
3616 deltay = math.cos(angle)
3617 if math.fabs(deltax) > math.fabs(deltay):
3618 bigger = math.fabs(deltax)
3620 bigger = math.fabs(deltay)
3623 # If tractor beam is to occur, don't move full distance
3624 if game.state.date+game.optime >= scheduled(FTBEAM):
3626 game.condition = "red"
3627 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3628 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3629 # Move within the quadrant
3630 game.quad[game.sector.i][game.sector.j] = IHDOT
3633 n = int(10.0*game.dist*bigger+0.5)
3635 for m in range(1, n+1):
3640 if not VALID_SECTOR(w.i, w.j):
3641 # Leaving quadrant -- allow final enemy attack
3642 # Don't do it if being pushed by Nova
3643 if len(game.enemies) != 0 and not novapush:
3645 for enemy in game.enemies:
3646 finald = (w - enemy.kloc).distance()
3647 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3649 # Stas Sergeev added the condition
3650 # that attacks only happen if Klingons
3651 # are present and your skill is good.
3653 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3654 attack(torps_ok=False)
3657 # compute final position -- new quadrant and sector
3658 x = (QUADSIZE*game.quadrant.i)+game.sector.i
3659 y = (QUADSIZE*game.quadrant.j)+game.sector.j
3660 w.i = int(round(x+10.0*game.dist*bigger*deltax))
3661 w.j = int(round(y+10.0*game.dist*bigger*deltay))
3662 # check for edge of galaxy
3672 if w.i >= GALSIZE*QUADSIZE:
3673 w.i = (GALSIZE*QUADSIZE*2) - w.i
3675 if w.j >= GALSIZE*QUADSIZE:
3676 w.j = (GALSIZE*QUADSIZE*2) - w.j
3684 if game.nkinks == 3:
3685 # Three strikes -- you're out!
3689 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3690 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3691 prout(_("YOU WILL BE DESTROYED."))
3692 # Compute final position in new quadrant
3693 if trbeam: # Don't bother if we are to be beamed
3695 game.quadrant.i = w.i/QUADSIZE
3696 game.quadrant.j = w.j/QUADSIZE
3697 game.sector.i = w.i - (QUADSIZE*game.quadrant.i)
3698 game.sector.j = w.j - (QUADSIZE*game.quadrant.j)
3700 prout(_("Entering Quadrant %s.") % game.quadrant)
3701 game.quad[game.sector.i][game.sector.j] = game.ship
3703 if game.skill>SKILL_NOVICE:
3704 attack(torps_ok=False)
3706 iquad = game.quad[w.i][w.j]
3708 # object encountered in flight path
3709 stopegy = 50.0*game.dist/game.optime
3710 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3711 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3713 for enemy in game.enemies:
3714 if enemy.kloc == game.sector:
3716 collision(rammed=False, enemy=enemy)
3718 elif iquad == IHBLANK:
3720 prouts(_("***RED ALERT! RED ALERT!"))
3722 proutn("***" + crmshp())
3723 proutn(_(" pulled into black hole at Sector %s") % w)
3725 # Getting pulled into a black hole was certain
3726 # death in Almy's original. Stas Sergeev added a
3727 # possibility that you'll get timewarped instead.
3730 for m in range(NDEVICES):
3731 if game.damage[m]>0:
3733 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3734 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3744 prout(_(" encounters Tholian web at %s;") % w)
3746 prout(_(" blocked by object at %s;") % w)
3747 proutn(_("Emergency stop required "))
3748 prout(_("%2d units of energy.") % int(stopegy))
3749 game.energy -= stopegy
3750 final.i = int(round(deltax))
3751 final.j = int(round(deltay))
3753 if game.energy <= 0:
3759 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3766 "Dock our ship at a starbase."
3768 if game.condition == "docked" and verbose:
3769 prout(_("Already docked."))
3772 prout(_("You must first leave standard orbit."))
3774 if not game.base.is_valid() or abs(game.sector.i-game.base.i) > 1 or abs(game.sector.j-game.base.j) > 1:
3775 prout(crmshp() + _(" not adjacent to base."))
3777 game.condition = "docked"
3781 if game.energy < game.inenrg:
3782 game.energy = game.inenrg
3783 game.shield = game.inshld
3784 game.torps = game.intorps
3785 game.lsupres = game.inlsr
3786 game.state.crew = FULLCREW
3787 if not damaged(DRADIO) and \
3788 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
3789 # get attack report from base
3790 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
3794 # This program originally required input in terms of a (clock)
3795 # direction and distance. Somewhere in history, it was changed to
3796 # cartesian coordinates. So we need to convert. Probably
3797 # "manual" input should still be done this way -- it's a real
3798 # pain if the computer isn't working! Manual mode is still confusing
3799 # because it involves giving x and y motions, yet the coordinates
3800 # are always displayed y - x, where +y is downward!
3802 def getcourse(isprobe):
3803 "Get a course and distance from the user."
3805 dquad = copy.copy(game.quadrant)
3806 navmode = "unspecified"
3810 if game.landed and not isprobe:
3811 prout(_("Dummy! You can't leave standard orbit until you"))
3812 proutn(_("are back aboard the ship."))
3815 while navmode == "unspecified":
3816 if damaged(DNAVSYS):
3818 prout(_("Computer damaged; manual navigation only"))
3820 prout(_("Computer damaged; manual movement only"))
3825 key = scanner.next()
3827 proutn(_("Manual or automatic- "))
3830 elif key == "IHALPHA":
3831 if scanner.sees("manual"):
3833 key = scanner.next()
3835 elif scanner.sees("automatic"):
3836 navmode = "automatic"
3837 key = scanner.next()
3845 prout(_("(Manual navigation assumed.)"))
3847 prout(_("(Manual movement assumed.)"))
3850 if navmode == "automatic":
3851 while key == "IHEOL":
3853 proutn(_("Target quadrant or quadrant§or- "))
3855 proutn(_("Destination sector or quadrant§or- "))
3858 key = scanner.next()
3862 xi = int(round(scanner.real))-1
3863 key = scanner.next()
3867 xj = int(round(scanner.real))-1
3868 key = scanner.next()
3870 # both quadrant and sector specified
3871 xk = int(round(scanner.real))-1
3872 key = scanner.next()
3876 xl = int(round(scanner.real))-1
3882 # only one pair of numbers was specified
3884 # only quadrant specified -- go to center of dest quad
3887 dsect.j = dsect.i = 4 # preserves 1-origin behavior
3889 # only sector specified
3893 if not VALID_QUADRANT(dquad.i,dquad.j) or not VALID_SECTOR(dsect.i,dsect.j):
3900 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
3902 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
3903 # the actual deltas get computed here
3905 delta.j = dquad.j-game.quadrant.j + (dsect.j-game.sector.j)/(QUADSIZE*1.0)
3906 delta.i = game.quadrant.i-dquad.i + (game.sector.i-dsect.i)/(QUADSIZE*1.0)
3908 while key == "IHEOL":
3909 proutn(_("X and Y displacements- "))
3912 key = scanner.next()
3917 delta.j = scanner.real
3918 key = scanner.next()
3922 delta.i = scanner.real
3923 # Check for zero movement
3924 if delta.i == 0 and delta.j == 0:
3927 if itemp == "verbose" and not isprobe:
3929 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
3930 # Course actually laid in.
3931 game.dist = delta.distance()
3932 game.direc = delta.bearing()
3933 if game.direc < 0.0:
3939 "Move under impulse power."
3941 if damaged(DIMPULS):
3944 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
3946 if game.energy > 30.0:
3947 if not getcourse(isprobe=False):
3949 power = 20.0 + 100.0*game.dist
3952 if power >= game.energy:
3953 # Insufficient power for trip
3955 prout(_("First Officer Spock- \"Captain, the impulse engines"))
3956 prout(_("require 20.0 units to engage, plus 100.0 units per"))
3957 if game.energy > 30:
3958 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
3959 int(0.01 * (game.energy-20.0)-0.05))
3960 prout(_(" quadrants.\""))
3962 prout(_("quadrant. They are, therefore, useless.\""))
3965 # Make sure enough time is left for the trip
3966 game.optime = game.dist/0.095
3967 if game.optime >= game.state.remtime:
3968 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
3969 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
3970 proutn(_("we dare spend the time?\" "))
3973 # Activate impulse engines and pay the cost
3974 imove(novapush=False)
3978 power = 20.0 + 100.0*game.dist
3979 game.energy -= power
3980 game.optime = game.dist/0.095
3981 if game.energy <= 0:
3986 "ove under warp drive."
3987 blooey = False; twarp = False
3988 if not timewarp: # Not WARPX entry
3990 if game.damage[DWARPEN] > 10.0:
3993 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
3995 if damaged(DWARPEN) and game.warpfac > 4.0:
3998 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
3999 prout(_(" is repaired, I can only give you warp 4.\""))
4001 # Read in course and distance
4002 if not getcourse(isprobe=False):
4004 # Make sure starship has enough energy for the trip
4005 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4006 if power >= game.energy:
4007 # Insufficient power for trip
4010 prout(_("Engineering to bridge--"))
4011 if not game.shldup or 0.5*power > game.energy:
4012 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4014 prout(_("We can't do it, Captain. We don't have enough energy."))
4016 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4019 prout(_("if you'll lower the shields."))
4023 prout(_("We haven't the energy to go that far with the shields up."))
4026 # Make sure enough time is left for the trip
4027 game.optime = 10.0*game.dist/game.warpfac**2
4028 if game.optime >= 0.8*game.state.remtime:
4030 prout(_("First Officer Spock- \"Captain, I compute that such"))
4031 proutn(_(" a trip would require approximately %2.0f") %
4032 (100.0*game.optime/game.state.remtime))
4033 prout(_(" percent of our"))
4034 proutn(_(" remaining time. Are you sure this is wise?\" "))
4040 if game.warpfac > 6.0:
4041 # Decide if engine damage will occur
4042 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4043 prob = game.dist*(6.0-game.warpfac)**2/66.666666666
4044 if prob > randreal():
4046 game.dist = randreal(game.dist)
4047 # Decide if time warp will occur
4048 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4050 if idebug and game.warpfac==10 and not twarp:
4052 proutn("=== Force time warp? ")
4056 # If time warp or engine damage, check path
4057 # If it is obstructed, don't do warp or damage
4058 angle = ((15.0-game.direc)*0.5235998)
4059 deltax = -math.sin(angle)
4060 deltay = math.cos(angle)
4061 if math.fabs(deltax) > math.fabs(deltay):
4062 bigger = math.fabs(deltax)
4064 bigger = math.fabs(deltay)
4067 n = 10.0 * game.dist * bigger +0.5
4070 for l in range(1, n+1):
4075 if not VALID_SECTOR(ix, iy):
4077 if game.quad[ix][iy] != IHDOT:
4080 # Activate Warp Engines and pay the cost
4081 imove(novapush=False)
4084 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4085 if game.energy <= 0:
4087 game.optime = 10.0*game.dist/game.warpfac**2
4091 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4093 prout(_("Engineering to bridge--"))
4094 prout(_(" Scott here. The warp engines are damaged."))
4095 prout(_(" We'll have to reduce speed to warp 4."))
4100 "Change the warp factor."
4106 proutn(_("Warp factor- "))
4111 if game.damage[DWARPEN] > 10.0:
4112 prout(_("Warp engines inoperative."))
4114 if damaged(DWARPEN) and scanner.real > 4.0:
4115 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4116 prout(_(" but right now we can only go warp 4.\""))
4118 if scanner.real > 10.0:
4119 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4121 if scanner.real < 1.0:
4122 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4124 oldfac = game.warpfac
4125 game.warpfac = scanner.real
4126 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4127 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4130 if game.warpfac < 8.00:
4131 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4133 if game.warpfac == 10.0:
4134 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4136 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4140 "Cope with being tossed out of quadrant by supernova or yanked by beam."
4142 # is captain on planet?
4144 if damaged(DTRANSP):
4147 prout(_("Scotty rushes to the transporter controls."))
4149 prout(_("But with the shields up it's hopeless."))
4151 prouts(_("His desperate attempt to rescue you . . ."))
4156 prout(_("SUCCEEDS!"))
4159 proutn(_("The crystals mined were "))
4167 # Check to see if captain in shuttle craft
4172 # Inform captain of attempt to reach safety
4176 prouts(_("***RED ALERT! RED ALERT!"))
4178 proutn(_("The %s has stopped in a quadrant containing") % crmshp())
4179 prouts(_(" a supernova."))
4181 proutn(_("***Emergency automatic override attempts to hurl ")+crmshp())
4182 prout(_("safely out of quadrant."))
4183 if not damaged(DRADIO):
4184 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
4185 # Try to use warp engines
4186 if damaged(DWARPEN):
4188 prout(_("Warp engines damaged."))
4191 game.warpfac = randreal(6.0, 8.0)
4192 prout(_("Warp factor set to %d") % int(game.warpfac))
4193 power = 0.75*game.energy
4194 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4195 distreq = randreal(math.sqrt(2))
4196 if distreq < game.dist:
4198 game.optime = 10.0*game.dist/game.warpfac**2
4199 game.direc = randreal(12) # How dumb!
4201 game.inorbit = False
4204 # This is bad news, we didn't leave quadrant.
4208 prout(_("Insufficient energy to leave quadrant."))
4211 # Repeat if another snova
4212 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
4214 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
4215 finish(FWON) # Snova killed remaining enemy.
4218 "Let's do the time warp again."
4219 prout(_("***TIME WARP ENTERED."))
4220 if game.state.snap and withprob(0.5):
4222 prout(_("You are traveling backwards in time %d stardates.") %
4223 int(game.state.date-game.snapsht.date))
4224 game.state = game.snapsht
4225 game.state.snap = False
4226 if len(game.state.kcmdr):
4227 schedule(FTBEAM, expran(game.intime/len(game.state.kcmdr)))
4228 schedule(FBATTAK, expran(0.3*game.intime))
4229 schedule(FSNOVA, expran(0.5*game.intime))
4230 # next snapshot will be sooner
4231 schedule(FSNAP, expran(0.25*game.state.remtime))
4233 if game.state.nscrem:
4234 schedule(FSCMOVE, 0.2777)
4238 game.battle.invalidate()
4240 # Make sure Galileo is consistant -- Snapshot may have been taken
4241 # when on planet, which would give us two Galileos!
4243 for l in range(game.inplan):
4244 if game.state.planets[l].known == "shuttle_down":
4246 if game.iscraft == "onship" and game.ship==IHE:
4247 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4248 game.iscraft = "offship"
4249 # Likewise, if in the original time the Galileo was abandoned, but
4250 # was on ship earlier, it would have vanished -- let's restore it.
4251 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4252 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4253 game.iscraft = "onship"
4254 # There used to be code to do the actual reconstrction here,
4255 # but the starchart is now part of the snapshotted galaxy state.
4256 prout(_("Spock has reconstructed a correct star chart from memory"))
4258 # Go forward in time
4259 game.optime = -0.5*game.intime*math.log(randreal())
4260 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4261 # cheat to make sure no tractor beams occur during time warp
4262 postpone(FTBEAM, game.optime)
4263 game.damage[DRADIO] += game.optime
4265 events() # Stas Sergeev added this -- do pending events
4268 "Launch deep-space probe."
4269 # New code to launch a deep space probe
4270 if game.nprobes == 0:
4273 if game.ship == IHE:
4274 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4276 prout(_("Ye Faerie Queene has no deep space probes."))
4281 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4283 if is_scheduled(FDSPROB):
4286 if damaged(DRADIO) and game.condition != "docked":
4287 prout(_("Spock- \"Records show the previous probe has not yet"))
4288 prout(_(" reached its destination.\""))
4290 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4292 key = scanner.next()
4294 if game.nprobes == 1:
4295 prout(_("1 probe left."))
4297 prout(_("%d probes left") % game.nprobes)
4298 proutn(_("Are you sure you want to fire a probe? "))
4301 game.isarmed = False
4302 if key == "IHALPHA" and scanner.token == "armed":
4304 key = scanner.next()
4305 elif key == "IHEOL":
4306 proutn(_("Arm NOVAMAX warhead? "))
4308 elif key == "IHREAL": # first element of course
4309 scanner.push(scanner.token)
4310 if not getcourse(isprobe=True):
4313 angle = ((15.0 - game.direc) * 0.5235988)
4314 game.probein = coord(-math.sin(angle), math.cos(angle))
4315 bigger = max(abs(game.probein.i), abs(game.probein.j))
4316 game.probein /= bigger
4317 game.proben = 10.0*game.dist*bigger +0.5
4318 game.probe = coord(game.quadrant.i*QUADSIZE + game.sector.i,
4319 game.quadrant.j*QUADSIZE + game.sector.j)
4320 game.probec = copy.copy(game.quadrant)
4321 schedule(FDSPROB, 0.01) # Time to move one sector
4322 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4327 "Yell for help from nearest starbase."
4328 # There's more than one way to move in this game!
4330 # Test for conditions which prevent calling for help
4331 if game.condition == "docked":
4332 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4335 prout(_("Subspace radio damaged."))
4337 if not game.state.baseq:
4338 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4341 prout(_("You must be aboard the %s.") % crmshp())
4343 # OK -- call for help from nearest starbase
4346 # There's one in this quadrant
4347 ddist = (game.base - game.sector).distance()
4350 for ibq in game.state.baseq:
4351 xdist = QUADSIZE * (ibq - game.quadrant).distance()
4354 # Since starbase not in quadrant, set up new quadrant
4357 # dematerialize starship
4358 game.quad[game.sector.i][game.sector.j]=IHDOT
4359 proutn(_("Starbase in Quadrant %s responds--%s dematerializes") \
4360 % (game.quadrant, crmshp()))
4361 game.sector.invalidate()
4362 for m in range(1, 5+1):
4363 w = game.base.scatter()
4364 if VALID_SECTOR(w.i,w.j) and game.quad[w.i][w.j]==IHDOT:
4365 # found one -- finish up
4368 if not game.sector.is_valid():
4369 prout(_("You have been lost in space..."))
4370 finish(FMATERIALIZE)
4372 # Give starbase three chances to rematerialize starship
4373 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4374 for m in range(1, 3+1):
4375 if m == 1: proutn(_("1st"))
4376 elif m == 2: proutn(_("2nd"))
4377 elif m == 3: proutn(_("3rd"))
4378 proutn(_(" attempt to re-materialize ") + crmshp())
4379 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4382 if randreal() > probf:
4385 curses.delay_output(500)
4388 game.quad[ix][iy]=IHQUEST
4391 setwnd(message_window)
4392 finish(FMATERIALIZE)
4394 game.quad[ix][iy]=game.ship
4396 prout(_("succeeds."))
4400 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4405 if game.condition=="docked":
4407 prout(_("You cannot abandon Ye Faerie Queene."))
4410 # Must take shuttle craft to exit
4411 if game.damage[DSHUTTL]==-1:
4412 prout(_("Ye Faerie Queene has no shuttle craft."))
4414 if game.damage[DSHUTTL]<0:
4415 prout(_("Shuttle craft now serving Big Macs."))
4417 if game.damage[DSHUTTL]>0:
4418 prout(_("Shuttle craft damaged."))
4421 prout(_("You must be aboard the ship."))
4423 if game.iscraft != "onship":
4424 prout(_("Shuttle craft not currently available."))
4426 # Emit abandon ship messages
4428 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4430 prouts(_("***ALL HANDS ABANDON SHIP!"))
4432 prout(_("Captain and crew escape in shuttle craft."))
4433 if not game.state.baseq:
4434 # Oops! no place to go...
4437 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
4439 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4440 prout(_("Remainder of ship's complement beam down"))
4441 prout(_("to nearest habitable planet."))
4442 elif q.planet != None and not damaged(DTRANSP):
4443 prout(_("Remainder of ship's complement beam down to %s.") %
4446 prout(_("Entire crew of %d left to die in outer space.") %
4448 game.casual += game.state.crew
4449 game.abandoned += game.state.crew
4450 # If at least one base left, give 'em the Faerie Queene
4452 game.icrystl = False # crystals are lost
4453 game.nprobes = 0 # No probes
4454 prout(_("You are captured by Klingons and released to"))
4455 prout(_("the Federation in a prisoner-of-war exchange."))
4456 nb = randrange(len(game.state.baseq))
4457 # Set up quadrant and position FQ adjacient to base
4458 if not game.quadrant == game.state.baseq[nb]:
4459 game.quadrant = game.state.baseq[nb]
4460 game.sector.i = game.sector.j = 5
4463 # position next to base by trial and error
4464 game.quad[game.sector.i][game.sector.j] = IHDOT
4465 for l in range(QUADSIZE):
4466 game.sector = game.base.scatter()
4467 if VALID_SECTOR(game.sector.i, game.sector.j) and \
4468 game.quad[game.sector.i][game.sector.j] == IHDOT:
4471 break # found a spot
4472 game.sector.i=QUADSIZE/2
4473 game.sector.j=QUADSIZE/2
4475 # Get new commission
4476 game.quad[game.sector.i][game.sector.j] = game.ship = IHF
4477 game.state.crew = FULLCREW
4478 prout(_("Starfleet puts you in command of another ship,"))
4479 prout(_("the Faerie Queene, which is antiquated but,"))
4480 prout(_("still useable."))
4482 prout(_("The dilithium crystals have been moved."))
4484 game.iscraft = "offship" # Galileo disappears
4486 game.condition="docked"
4487 for l in range(NDEVICES):
4488 game.damage[l] = 0.0
4489 game.damage[DSHUTTL] = -1
4490 game.energy = game.inenrg = 3000.0
4491 game.shield = game.inshld = 1250.0
4492 game.torps = game.intorps = 6
4493 game.lsupres=game.inlsr=3.0
4498 # Code from planets.c begins here.
4501 "Abort a lengthy operation if an event interrupts it."
4504 if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.justin:
4509 "Report on (uninhabited) planets in the galaxy."
4513 prout(_("Spock- \"Planet report follows, Captain.\""))
4515 for i in range(game.inplan):
4516 if game.state.planets[i].pclass == "destroyed":
4518 if (game.state.planets[i].known != "unknown" \
4519 and not game.state.planets[i].inhabited) \
4522 if idebug and game.state.planets[i].known=="unknown":
4523 proutn("(Unknown) ")
4524 proutn(_("Quadrant %s") % game.state.planets[i].quadrant)
4525 proutn(_(" class "))
4526 proutn(game.state.planets[i].pclass)
4528 if game.state.planets[i].crystals != present:
4530 prout(_("dilithium crystals present."))
4531 if game.state.planets[i].known=="shuttle_down":
4532 prout(_(" Shuttle Craft Galileo on surface."))
4534 prout(_("No information available."))
4537 "Enter standard orbit."
4541 prout(_("Already in standard orbit."))
4543 if damaged(DWARPEN) and damaged(DIMPULS):
4544 prout(_("Both warp and impulse engines damaged."))
4546 if not game.plnet.is_valid():
4547 prout("There is no planet in this sector.")
4549 if abs(game.sector.i-game.plnet.i)>1 or abs(game.sector.j-game.plnet.j)>1:
4550 prout(crmshp() + _(" not adjacent to planet."))
4553 game.optime = randreal(0.02, 0.05)
4554 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4558 game.height = randreal(1400, 8600)
4559 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4564 "Examine planets in this quadrant."
4565 if damaged(DSRSENS):
4566 if game.options & OPTION_TTY:
4567 prout(_("Short range sensors damaged."))
4569 if game.iplnet == None:
4570 if game.options & OPTION_TTY:
4571 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4573 if game.iplnet.known == "unknown":
4574 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4576 prout(_(" Planet at Sector %s is of class %s.") %
4577 (game.plnet, game.iplnet.pclass))
4578 if game.iplnet.known=="shuttle_down":
4579 prout(_(" Sensors show Galileo still on surface."))
4580 proutn(_(" Readings indicate"))
4581 if game.iplnet.crystals != "present":
4583 prout(_(" dilithium crystals present.\""))
4584 if game.iplnet.known == "unknown":
4585 game.iplnet.known = "known"
4586 elif game.iplnet.inhabited:
4587 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4588 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4591 "Use the transporter."
4595 if damaged(DTRANSP):
4596 prout(_("Transporter damaged."))
4597 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4599 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4603 if not game.inorbit:
4604 prout(crmshp() + _(" not in standard orbit."))
4607 prout(_("Impossible to transport through shields."))
4609 if game.iplnet.known=="unknown":
4610 prout(_("Spock- \"Captain, we have no information on this planet"))
4611 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4612 prout(_(" you may not go down.\""))
4614 if not game.landed and game.iplnet.crystals=="absent":
4615 prout(_("Spock- \"Captain, I fail to see the logic in"))
4616 prout(_(" exploring a planet with no dilithium crystals."))
4617 proutn(_(" Are you sure this is wise?\" "))
4621 if not (game.options & OPTION_PLAIN):
4622 nrgneed = 50 * game.skill + game.height / 100.0
4623 if nrgneed > game.energy:
4624 prout(_("Engineering to bridge--"))
4625 prout(_(" Captain, we don't have enough energy for transportation."))
4627 if not game.landed and nrgneed * 2 > game.energy:
4628 prout(_("Engineering to bridge--"))
4629 prout(_(" Captain, we have enough energy only to transport you down to"))
4630 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4631 if game.iplnet.known == "shuttle_down":
4632 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4633 proutn(_(" Are you sure this is wise?\" "))
4638 # Coming from planet
4639 if game.iplnet.known=="shuttle_down":
4640 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4644 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4645 prout(_("Landing party assembled, ready to beam up."))
4647 prout(_("Kirk whips out communicator..."))
4648 prouts(_("BEEP BEEP BEEP"))
4650 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4653 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4655 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4657 prout(_("Kirk- \"Energize.\""))
4660 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4663 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4665 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4668 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4669 game.landed = not game.landed
4670 game.energy -= nrgneed
4672 prout(_("Transport complete."))
4673 if game.landed and game.iplnet.known=="shuttle_down":
4674 prout(_("The shuttle craft Galileo is here!"))
4675 if not game.landed and game.imine:
4682 "Strip-mine a world for dilithium."
4686 prout(_("Mining party not on planet."))
4688 if game.iplnet.crystals == "mined":
4689 prout(_("This planet has already been strip-mined for dilithium."))
4691 elif game.iplnet.crystals == "absent":
4692 prout(_("No dilithium crystals on this planet."))
4695 prout(_("You've already mined enough crystals for this trip."))
4697 if game.icrystl and game.cryprob == 0.05:
4698 prout(_("With all those fresh crystals aboard the ") + crmshp())
4699 prout(_("there's no reason to mine more at this time."))
4701 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4704 prout(_("Mining operation complete."))
4705 game.iplnet.crystals = "mined"
4706 game.imine = game.ididit = True
4709 "Use dilithium crystals."
4713 if not game.icrystl:
4714 prout(_("No dilithium crystals available."))
4716 if game.energy >= 1000:
4717 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4718 prout(_(" except when Condition Yellow exists."))
4720 prout(_("Spock- \"Captain, I must warn you that loading"))
4721 prout(_(" raw dilithium crystals into the ship's power"))
4722 prout(_(" system may risk a severe explosion."))
4723 proutn(_(" Are you sure this is wise?\" "))
4728 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
4729 prout(_(" Mr. Spock and I will try it.\""))
4731 prout(_("Spock- \"Crystals in place, Sir."))
4732 prout(_(" Ready to activate circuit.\""))
4734 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
4736 if with(game.cryprob):
4737 prouts(_(" \"Activating now! - - No good! It's***"))
4739 prouts(_("***RED ALERT! RED A*L********************************"))
4742 prouts(_("****************** KA-BOOM!!!! *******************"))
4746 game.energy += randreal(5000.0, 5500.0)
4747 prouts(_(" \"Activating now! - - "))
4748 prout(_("The instruments"))
4749 prout(_(" are going crazy, but I think it's"))
4750 prout(_(" going to work!! Congratulations, Sir!\""))
4755 "Use shuttlecraft for planetary jaunt."
4758 if damaged(DSHUTTL):
4759 if game.damage[DSHUTTL] == -1.0:
4760 if game.inorbit and game.iplnet.known == "shuttle_down":
4761 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
4763 prout(_("Ye Faerie Queene had no shuttle craft."))
4764 elif game.damage[DSHUTTL] > 0:
4765 prout(_("The Galileo is damaged."))
4766 else: # game.damage[DSHUTTL] < 0
4767 prout(_("Shuttle craft is now serving Big Macs."))
4769 if not game.inorbit:
4770 prout(crmshp() + _(" not in standard orbit."))
4772 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
4773 prout(_("Shuttle craft not currently available."))
4775 if not game.landed and game.iplnet.known=="shuttle_down":
4776 prout(_("You will have to beam down to retrieve the shuttle craft."))
4778 if game.shldup or game.condition == "docked":
4779 prout(_("Shuttle craft cannot pass through shields."))
4781 if game.iplnet.known=="unknown":
4782 prout(_("Spock- \"Captain, we have no information on this planet"))
4783 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4784 prout(_(" you may not fly down.\""))
4786 game.optime = 3.0e-5*game.height
4787 if game.optime >= 0.8*game.state.remtime:
4788 prout(_("First Officer Spock- \"Captain, I compute that such"))
4789 proutn(_(" a maneuver would require approximately %2d%% of our") % \
4790 int(100*game.optime/game.state.remtime))
4791 prout(_("remaining time."))
4792 proutn(_("Are you sure this is wise?\" "))
4798 if game.iscraft == "onship":
4800 if not damaged(DTRANSP):
4801 proutn(_("Spock- \"Would you rather use the transporter?\" "))
4805 proutn(_("Shuttle crew"))
4807 proutn(_("Rescue party"))
4808 prout(_(" boards Galileo and swoops toward planet surface."))
4809 game.iscraft = "offship"
4813 game.iplnet.known="shuttle_down"
4814 prout(_("Trip complete."))
4817 # Ready to go back to ship
4818 prout(_("You and your mining party board the"))
4819 prout(_("shuttle craft for the trip back to the Enterprise."))
4821 prouts(_("The short hop begins . . ."))
4823 game.iplnet.known="known"
4829 game.iscraft = "onship"
4835 prout(_("Trip complete."))
4838 # Kirk on ship and so is Galileo
4839 prout(_("Mining party assembles in the hangar deck,"))
4840 prout(_("ready to board the shuttle craft \"Galileo\"."))
4842 prouts(_("The hangar doors open; the trip begins."))
4845 game.iscraft = "offship"
4848 game.iplnet.known = "shuttle_down"
4851 prout(_("Trip complete."))
4855 "Use the big zapper."
4859 if game.ship != IHE:
4860 prout(_("Ye Faerie Queene has no death ray."))
4862 if len(game.enemies)==0:
4863 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
4866 prout(_("Death Ray is damaged."))
4868 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
4869 prout(_(" is highly unpredictible. Considering the alternatives,"))
4870 proutn(_(" are you sure this is wise?\" "))
4873 prout(_("Spock- \"Acknowledged.\""))
4876 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
4878 prout(_("Crew scrambles in emergency preparation."))
4879 prout(_("Spock and Scotty ready the death ray and"))
4880 prout(_("prepare to channel all ship's power to the device."))
4882 prout(_("Spock- \"Preparations complete, sir.\""))
4883 prout(_("Kirk- \"Engage!\""))
4885 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
4888 if game.options & OPTION_PLAIN:
4892 prouts(_("Sulu- \"Captain! It's working!\""))
4894 while len(game.enemies) > 0:
4895 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.i][game.enemies[1].kloc.j],game.enemies[1].kloc)
4896 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
4897 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) == 0:
4899 if (game.options & OPTION_PLAIN) == 0:
4900 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
4902 prout(_(" is still operational.\""))
4904 prout(_(" has been rendered nonfunctional.\""))
4905 game.damage[DDRAY] = 39.95
4907 r = randreal() # Pick failure method
4909 prouts(_("Sulu- \"Captain! It's working!\""))
4911 prouts(_("***RED ALERT! RED ALERT!"))
4913 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
4915 prouts(_("***RED ALERT! RED A*L********************************"))
4918 prouts(_("****************** KA-BOOM!!!! *******************"))
4923 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
4925 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
4927 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
4928 prout(_(" have apparently been transformed into strange mutations."))
4929 prout(_(" Vulcans do not seem to be affected."))
4931 prout(_("Kirk- \"Raauch! Raauch!\""))
4936 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
4938 proutn(_("Spock- \"I believe the word is"))
4939 prouts(_(" *ASTONISHING*"))
4940 prout(_(" Mr. Sulu."))
4941 for i in range(QUADSIZE):
4942 for j in range(QUADSIZE):
4943 if game.quad[i][j] == IHDOT:
4944 game.quad[i][j] = IHQUEST
4945 prout(_(" Captain, our quadrant is now infested with"))
4946 prouts(_(" - - - - - - *THINGS*."))
4948 prout(_(" I have no logical explanation.\""))
4950 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
4952 prout(_("Scotty- \"There are so many tribbles down here"))
4953 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
4957 # Code from reports.c begins here
4959 def attackreport(curt):
4960 "eport status of bases under attack."
4962 if is_scheduled(FCDBAS):
4963 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
4964 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
4965 elif game.isatb == 1:
4966 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
4967 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
4969 prout(_("No Starbase is currently under attack."))
4971 if is_scheduled(FCDBAS):
4972 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
4974 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
4978 # report on general game status
4980 s1 = "" and game.thawed and _("thawed ")
4981 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
4982 s3 = (None, _("novice"). _("fair"),
4983 _("good"), _("expert"), _("emeritus"))[game.skill]
4984 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
4985 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
4986 prout(_("No plaque is allowed."))
4988 prout(_("This is tournament game %d.") % game.tourn)
4989 prout(_("Your secret password is \"%s\"") % game.passwd)
4990 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)),
4991 (game.inkling + game.incom + game.inscom)))
4992 if game.incom - len(game.state.kcmdr):
4993 prout(_(", including %d Commander%s.") % (game.incom - len(game.state.kcmdr), (_("s"), "")[(game.incom - len(game.state.kcmdr))==1]))
4994 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
4995 prout(_(", but no Commanders."))
4998 if game.skill > SKILL_FAIR:
4999 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5000 if len(game.state.baseq) != game.inbase:
5002 if game.inbase-len(game.state.baseq)==1:
5003 proutn(_("has been 1 base"))
5005 proutn(_("have been %d bases") % (game.inbase-len(game.state.baseq)))
5006 prout(_(" destroyed, %d remaining.") % len(game.state.baseq))
5008 prout(_("There are %d bases.") % game.inbase)
5009 if communicating() or game.iseenit:
5010 # Don't report this if not seen and
5011 # either the radio is dead or not at base!
5015 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5017 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5018 if game.ship == IHE:
5019 proutn(_("You have "))
5021 proutn("%d" % (game.nprobes))
5024 proutn(_(" deep space probe"))
5028 if communicating() and is_scheduled(FDSPROB):
5030 proutn(_("An armed deep space probe is in "))
5032 proutn(_("A deep space probe is in "))
5033 prout("Quadrant %s." % game.probec)
5035 if game.cryprob <= .05:
5036 prout(_("Dilithium crystals aboard ship... not yet used."))
5040 while game.cryprob > ai:
5043 prout(_("Dilithium crystals have been used %d time%s.") % \
5044 (i, (_("s"), "")[i==1]))
5048 "Long-range sensor scan."
5049 if damaged(DLRSENS):
5050 # Now allow base's sensors if docked
5051 if game.condition != "docked":
5053 prout(_("LONG-RANGE SENSORS DAMAGED."))
5056 prout(_("Starbase's long-range scan"))
5058 prout(_("Long-range scan"))
5059 for x in range(game.quadrant.i-1, game.quadrant.i+2):
5062 for y in range(game.quadrant.j-1, game.quadrant.j+2):
5063 if not VALID_QUADRANT(x, y):
5067 if not damaged(DRADIO):
5068 game.state.galaxy[x][y].charted = True
5069 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5070 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5071 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5072 if not silent and game.state.galaxy[x][y].supernova:
5075 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5083 for i in range(NDEVICES):
5086 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5087 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5089 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5090 game.damage[i]+0.05,
5091 game.docfac*game.damage[i]+0.005))
5093 prout(_("All devices functional."))
5096 "Update the chart in the Enterprise's computer from galaxy data."
5097 game.lastchart = game.state.date
5098 for i in range(GALSIZE):
5099 for j in range(GALSIZE):
5100 if game.state.galaxy[i][j].charted:
5101 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5102 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5103 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5106 "Display the star chart."
5108 if (game.options & OPTION_AUTOSCAN):
5110 if not damaged(DRADIO):
5112 if game.lastchart < game.state.date and game.condition == "docked":
5113 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5115 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5116 if game.state.date > game.lastchart:
5117 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5118 prout(" 1 2 3 4 5 6 7 8")
5119 for i in range(GALSIZE):
5120 proutn("%d |" % (i+1))
5121 for j in range(GALSIZE):
5122 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
5126 if game.state.galaxy[i][j].supernova:
5128 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5130 elif game.state.galaxy[i][j].charted:
5131 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5135 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
5143 def sectscan(goodScan, i, j):
5144 "Light up an individual dot in a sector."
5145 if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1):
5146 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):
5147 #if game.condition == "red": textcolor("red")
5148 #elif game.condition == "green": textcolor("green")
5149 #elif game.condition == "yellow": textcolor("yellow")
5150 #elif game.condition == "docked": textcolor("cyan")
5151 #elif game.condition == "dead": textcolor("brown")
5152 if game.quad[i][j] != game.ship:
5154 proutn("%c " % game.quad[i][j])
5160 "Emit status report lines"
5161 if not req or req == 1:
5162 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5163 % (game.state.date, game.state.remtime))
5164 if not req or req == 2:
5165 if game.condition != "docked":
5168 for t in range(NDEVICES):
5169 if game.damage[t]>0:
5171 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5172 if not req or req == 3:
5173 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5174 if not req or req == 4:
5175 if damaged(DLIFSUP):
5176 if game.condition == "docked":
5177 s = _("DAMAGED, Base provides")
5179 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5182 prstat(_("Life Support"), s)
5183 if not req or req == 5:
5184 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5185 if not req or req == 6:
5187 if game.icrystl and (game.options & OPTION_SHOWME):
5188 extra = _(" (have crystals)")
5189 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5190 if not req or req == 7:
5191 prstat(_("Torpedoes"), "%d" % (game.torps))
5192 if not req or req == 8:
5193 if damaged(DSHIELD):
5199 data = _(" %d%% %.1f units") \
5200 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5201 prstat(_("Shields"), s+data)
5202 if not req or req == 9:
5203 prstat(_("Klingons Left"), "%d" \
5204 % (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem))
5205 if not req or req == 10:
5206 if game.options & OPTION_WORLDS:
5207 plnet = game.state.galaxy[game.quadrant.i][game.quadrant.j].planet
5208 if plnet and plnet.inhabited:
5209 prstat(_("Major system"), plnet.name)
5211 prout(_("Sector is uninhabited"))
5212 elif not req or req == 11:
5213 attackreport(not req)
5216 "Request specified status data, a historical relic from slow TTYs."
5217 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5218 while scanner.next() == "IHEOL":
5219 proutn(_("Information desired? "))
5221 if scanner.token in requests:
5222 status(requests.index(scanner.token))
5224 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5225 prout((" date, condition, position, lsupport, warpfactor,"))
5226 prout((" energy, torpedoes, shields, klingons, system, time."))
5231 if damaged(DSRSENS):
5232 # Allow base's sensors if docked
5233 if game.condition != "docked":
5234 prout(_(" S.R. SENSORS DAMAGED!"))
5237 prout(_(" [Using Base's sensors]"))
5239 prout(_(" Short-range scan"))
5240 if goodScan and not damaged(DRADIO):
5241 game.state.chart[game.quadrant.i][game.quadrant.j].klingons = game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons
5242 game.state.chart[game.quadrant.i][game.quadrant.j].starbase = game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase
5243 game.state.chart[game.quadrant.i][game.quadrant.j].stars = game.state.galaxy[game.quadrant.i][game.quadrant.j].stars
5244 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
5245 prout(" 1 2 3 4 5 6 7 8 9 10")
5246 if game.condition != "docked":
5248 for i in range(QUADSIZE):
5249 proutn("%2d " % (i+1))
5250 for j in range(QUADSIZE):
5251 sectscan(goodScan, i, j)
5255 "Use computer to get estimated time of arrival for a warp jump."
5256 w1 = coord(); w2 = coord()
5258 if damaged(DCOMPTR):
5259 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5262 if scanner.next() != "IHREAL":
5265 proutn(_("Destination quadrant and/or sector? "))
5266 if scanner.next()!="IHREAL":
5269 w1.j = int(scanner.real-0.5)
5270 if scanner.next() != "IHREAL":
5273 w1.i = int(scanner.real-0.5)
5274 if scanner.next() == "IHREAL":
5275 w2.j = int(scanner.real-0.5)
5276 if scanner.next() != "IHREAL":
5279 w2.i = int(scanner.real-0.5)
5281 if game.quadrant.j>w1.i:
5285 if game.quadrant.i>w1.j:
5289 if not VALID_QUADRANT(w1.i, w1.j) or not VALID_SECTOR(w2.i, w2.j):
5292 game.dist = math.sqrt((w1.j-game.quadrant.j+(w2.j-game.sector.j)/(QUADSIZE*1.0))**2+
5293 (w1.i-game.quadrant.i+(w2.i-game.sector.i)/(QUADSIZE*1.0))**2)
5296 prout(_("Answer \"no\" if you don't know the value:"))
5299 proutn(_("Time or arrival date? "))
5300 if scanner.next()=="IHREAL":
5301 ttime = scanner.real
5302 if ttime > game.state.date:
5303 ttime -= game.state.date # Actually a star date
5304 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5305 if ttime <= 1e-10 or twarp > 10:
5306 prout(_("We'll never make it, sir."))
5313 proutn(_("Warp factor? "))
5314 if scanner.next()== "IHREAL":
5316 twarp = scanner.real
5317 if twarp<1.0 or twarp > 10.0:
5321 prout(_("Captain, certainly you can give me one of these."))
5324 ttime = (10.0*game.dist)/twarp**2
5325 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5326 if tpower >= game.energy:
5327 prout(_("Insufficient energy, sir."))
5328 if not game.shldup or tpower > game.energy*2.0:
5331 proutn(_("New warp factor to try? "))
5332 if scanner.next() == "IHREAL":
5334 twarp = scanner.real
5335 if twarp<1.0 or twarp > 10.0:
5343 prout(_("But if you lower your shields,"))
5344 proutn(_("remaining"))
5347 proutn(_("Remaining"))
5348 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5350 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5352 prout(_("Any warp speed is adequate."))
5354 prout(_("Minimum warp needed is %.2f,") % (twarp))
5355 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5356 if game.state.remtime < ttime:
5357 prout(_("Unfortunately, the Federation will be destroyed by then."))
5359 prout(_("You'll be taking risks at that speed, Captain"))
5360 if (game.isatb==1 and game.state.kscmdr == w1 and \
5361 scheduled(FSCDBAS)< ttime+game.state.date) or \
5362 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5363 prout(_("The starbase there will be destroyed by then."))
5364 proutn(_("New warp factor to try? "))
5365 if scanner.next() == "IHREAL":
5367 twarp = scanner.real
5368 if twarp<1.0 or twarp > 10.0:
5376 # Code from setup.c begins here
5379 "Issue a historically correct banner."
5381 prout(_("-SUPER- STAR TREK"))
5383 # From the FORTRAN original
5384 # prout(_("Latest update-21 Sept 78"))
5390 scanner.token = "emsave.trk"
5392 key = scanner.next()
5394 proutn(_("File name: "))
5395 key = scanner.next()
5396 if key != "IHALPHA":
5400 if '.' not in scanner.token:
5401 scanner.token += ".trk"
5403 fp = open(scanner.token, "wb")
5405 prout(_("Can't freeze game as file %s") % scanner.token)
5407 cPickle.dump(game, fp)
5411 "Retrieve saved game."
5412 game.passwd[0] = '\0'
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, "rb")
5426 prout(_("Can't thaw game in %s") % scanner.token)
5428 game = cPickle.load(fp)
5432 # I used <http://www.memory-alpha.org> to find planets
5433 # with references in ST:TOS. Eath and the Alpha Centauri
5434 # Colony have been omitted.
5436 # Some planets marked Class G and P here will be displayed as class M
5437 # because of the way planets are generated. This is a known bug.
5440 _("Andoria (Fesoan)"), # several episodes
5441 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5442 _("Vulcan (T'Khasi)"), # many episodes
5443 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5444 _("Argelius II (Nelphia)"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5445 _("Ardana"), # TOS: "The Cloud Minders"
5446 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5447 _("Gideon"), # TOS: "The Mark of Gideon"
5448 _("Aldebaran III"), # TOS: "The Deadly Years"
5449 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5450 _("Altair IV"), # TOS: "Amok Time
5451 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5452 _("Benecia"), # TOS: "The Conscience of the King"
5453 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5454 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5455 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5456 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5457 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5458 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5459 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5460 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5461 _("Ingraham B"), # TOS: "Operation: Annihilate"
5462 _("Janus IV"), # TOS: "The Devil in the Dark"
5463 _("Makus III"), # TOS: "The Galileo Seven"
5464 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5465 _("Omega IV"), # TOS: "The Omega Glory"
5466 _("Regulus V"), # TOS: "Amok Time
5467 _("Deneva"), # TOS: "Operation -- Annihilate!"
5468 # Worlds from BSD Trek
5469 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5470 _("Beta III"), # TOS: "The Return of the Archons"
5471 _("Triacus"), # TOS: "And the Children Shall Lead",
5472 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5474 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5475 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5476 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5477 # _("Izar"), # TOS: "Whom Gods Destroy"
5478 # _("Tiburon"), # TOS: "The Way to Eden"
5479 # _("Merak II"), # TOS: "The Cloud Minders"
5480 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5481 # _("Iotia"), # TOS: "A Piece of the Action"
5485 _("S. R. Sensors"), \
5486 _("L. R. Sensors"), \
5488 _("Photon Tubes"), \
5489 _("Life Support"), \
5490 _("Warp Engines"), \
5491 _("Impulse Engines"), \
5493 _("Subspace Radio"), \
5494 _("Shuttle Craft"), \
5496 _("Navigation System"), \
5498 _("Shield Control"), \
5504 "Prepare to play, set up cosmos."
5506 # Decide how many of everything
5508 return # frozen game
5509 # Prepare the Enterprise
5510 game.alldone = game.gamewon = game.shldchg = game.shldup = False
5512 game.state.crew = FULLCREW
5513 game.energy = game.inenrg = 5000.0
5514 game.shield = game.inshld = 2500.0
5517 game.quadrant = randplace(GALSIZE)
5518 game.sector = randplace(QUADSIZE)
5519 game.torps = game.intorps = 10
5520 game.nprobes = randrange(2, 5)
5522 for i in range(NDEVICES):
5523 game.damage[i] = 0.0
5524 # Set up assorted game parameters
5525 game.battle = coord()
5526 game.state.date = game.indate = 100.0 * randreal(20, 51)
5527 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5528 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5529 game.isatb = game.state.nplankl = 0
5530 game.state.starkl = game.state.basekl = 0
5531 game.iscraft = "onship"
5535 # Starchart is functional but we've never seen it
5536 game.lastchart = FOREVER
5537 # Put stars in the galaxy
5539 for i in range(GALSIZE):
5540 for j in range(GALSIZE):
5541 k = randrange(1, QUADSIZE**2/10+1)
5543 game.state.galaxy[i][j].stars = k
5544 # Locate star bases in galaxy
5545 for i in range(game.inbase):
5548 w = randplace(GALSIZE)
5549 if not game.state.galaxy[w.i][w.j].starbase:
5552 # C version: for (j = i-1; j > 0; j--)
5553 # so it did them in the opposite order.
5554 for j in range(1, i):
5555 # Improved placement algorithm to spread out bases
5556 distq = (w - game.state.baseq[j]).distance()
5557 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5560 prout("=== Abandoning base #%d at %s" % (i, w))
5562 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5564 prout("=== Saving base #%d, close to #%d" % (i, j))
5567 game.state.baseq.append(w)
5568 game.state.galaxy[w.i][w.j].starbase = game.state.chart[w.i][w.j].starbase = True
5569 # Position ordinary Klingon Battle Cruisers
5571 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5572 if klumper > MAXKLQUAD:
5576 klump = (1.0 - r*r)*klumper
5581 w = randplace(GALSIZE)
5582 if not game.state.galaxy[w.i][w.j].supernova and \
5583 game.state.galaxy[w.i][w.j].klingons + klump <= MAXKLQUAD:
5585 game.state.galaxy[w.i][w.j].klingons += int(klump)
5588 # Position Klingon Commander Ships
5589 for i in range(game.incom):
5591 w = randplace(GALSIZE)
5592 if not welcoming(w) or w in game.state.kcmdr:
5594 if (game.state.galaxy[w.i][w.j].klingons or withprob(0.25)):
5596 game.state.galaxy[w.i][w.j].klingons += 1
5597 game.state.kcmdr.append(w)
5598 # Locate planets in galaxy
5599 for i in range(game.inplan):
5601 w = randplace(GALSIZE)
5602 if game.state.galaxy[w.i][w.j].planet == None:
5606 new.crystals = "absent"
5607 if (game.options & OPTION_WORLDS) and i < NINHAB:
5608 new.pclass = "M" # All inhabited planets are class M
5609 new.crystals = "absent"
5611 new.name = systnames[i]
5612 new.inhabited = True
5614 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5616 new.crystals = "present"
5617 new.known = "unknown"
5618 new.inhabited = False
5619 game.state.galaxy[w.i][w.j].planet = new
5620 game.state.planets.append(new)
5622 for i in range(game.state.nromrem):
5623 w = randplace(GALSIZE)
5624 game.state.galaxy[w.i][w.j].romulans += 1
5625 # Place the Super-Commander if needed
5626 if game.state.nscrem > 0:
5628 w = randplace(GALSIZE)
5631 game.state.kscmdr = w
5632 game.state.galaxy[w.i][w.j].klingons += 1
5633 # Initialize times for extraneous events
5634 schedule(FSNOVA, expran(0.5 * game.intime))
5635 schedule(FTBEAM, expran(1.5 * (game.intime / len(game.state.kcmdr))))
5636 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5637 schedule(FBATTAK, expran(0.3*game.intime))
5639 if game.state.nscrem:
5640 schedule(FSCMOVE, 0.2777)
5645 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5646 schedule(FDISTR, expran(1.0 + game.intime))
5651 # Place thing (in tournament game, we don't want one!)
5652 # New in SST2K: never place the Thing near a starbase.
5653 # This makes sense and avoids a special case in the old code.
5655 if game.tourn is None:
5657 thing = randplace(GALSIZE)
5658 if thing not in game.state.baseq:
5661 game.state.snap = False
5662 if game.skill == SKILL_NOVICE:
5663 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5664 prout(_("a deadly Klingon invasion force. As captain of the United"))
5665 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5666 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5667 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5668 prout(_("your mission. As you proceed you may be given more time."))
5670 prout(_("You will have %d supporting starbases.") % (game.inbase))
5671 proutn(_("Starbase locations- "))
5673 prout(_("Stardate %d.") % int(game.state.date))
5675 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5676 prout(_("An unknown number of Romulans."))
5677 if game.state.nscrem:
5678 prout(_("And one (GULP) Super-Commander."))
5679 prout(_("%d stardates.") % int(game.intime))
5680 proutn(_("%d starbases in ") % game.inbase)
5681 for i in range(game.inbase):
5682 proutn(`game.state.baseq[i]`)
5685 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5686 proutn(_(" Sector %s") % game.sector)
5688 prout(_("Good Luck!"))
5689 if game.state.nscrem:
5690 prout(_(" YOU'LL NEED IT."))
5693 if len(game.enemies) - (thing == game.quadrant) - (game.tholian != None):
5695 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5696 attack(torps_ok=False)
5699 "Choose your game type."
5704 game.skill = SKILL_NONE
5706 if not scanner.inqueue: # Can start with command line options
5707 proutn(_("Would you like a regular, tournament, or saved game? "))
5709 if scanner.sees("tournament"):
5710 while scanner.next() == "IHEOL":
5711 proutn(_("Type in tournament number-"))
5712 if scanner.real == 0:
5714 continue # We don't want a blank entry
5715 game.tourn = int(round(scanner.real))
5716 random.seed(scanner.real)
5718 logfp.write("# random.seed(%d)\n" % scanner.real)
5720 if scanner.sees("saved") or scanner.sees("frozen"):
5724 if game.passwd == None:
5726 if not game.alldone:
5727 game.thawed = True # No plaque if not finished
5731 if scanner.sees("regular"):
5733 proutn(_("What is \"%s\"?") % scanner.token)
5735 while game.length==0 or game.skill==SKILL_NONE:
5736 if scanner.next() == "IHALPHA":
5737 if scanner.sees("short"):
5739 elif scanner.sees("medium"):
5741 elif scanner.sees("long"):
5743 elif scanner.sees("novice"):
5744 game.skill = SKILL_NOVICE
5745 elif scanner.sees("fair"):
5746 game.skill = SKILL_FAIR
5747 elif scanner.sees("good"):
5748 game.skill = SKILL_GOOD
5749 elif scanner.sees("expert"):
5750 game.skill = SKILL_EXPERT
5751 elif scanner.sees("emeritus"):
5752 game.skill = SKILL_EMERITUS
5754 proutn(_("What is \""))
5755 proutn(scanner.token)
5760 proutn(_("Would you like a Short, Medium, or Long game? "))
5761 elif game.skill == SKILL_NONE:
5762 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
5763 # Choose game options -- added by ESR for SST2K
5764 if scanner.next() != "IHALPHA":
5766 proutn(_("Choose your game style (or just press enter): "))
5768 if scanner.sees("plain"):
5769 # Approximates the UT FORTRAN version.
5770 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5771 game.options |= OPTION_PLAIN
5772 elif scanner.sees("almy"):
5773 # Approximates Tom Almy's version.
5774 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5775 game.options |= OPTION_ALMY
5776 elif scanner.sees("fancy"):
5778 elif len(scanner.token):
5779 proutn(_("What is \"%s\"?") % scanner.token)
5781 if game.passwd == "debug":
5783 prout("=== Debug mode enabled.")
5784 # Use parameters to generate initial values of things
5785 game.damfac = 0.5 * game.skill
5786 game.inbase = randrange(BASEMIN, BASEMAX+1)
5788 if game.options & OPTION_PLANETS:
5789 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
5790 if game.options & OPTION_WORLDS:
5791 game.inplan += int(NINHAB)
5792 game.state.nromrem = game.inrom = randrange(2 *game.skill)
5793 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
5794 game.state.remtime = 7.0 * game.length
5795 game.intime = game.state.remtime
5796 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
5797 game.incom = min(MINCMDR, int(game.skill + 0.0625*game.inkling*randreal()))
5798 game.state.remres = (game.inkling+4*game.incom)*game.intime
5799 game.inresor = game.state.remres
5800 if game.inkling > 50:
5801 game.state.inbase += 1
5804 def dropin(iquad=None):
5805 "Drop a feature on a random dot in the current quadrant."
5807 w = randplace(QUADSIZE)
5808 if game.quad[w.i][w.j] == IHDOT:
5810 if iquad is not None:
5811 game.quad[w.i][w.j] = iquad
5815 "Update our alert status."
5816 game.condition = "green"
5817 if game.energy < 1000.0:
5818 game.condition = "yellow"
5819 if game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons or game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans:
5820 game.condition = "red"
5822 game.condition="dead"
5825 "Drop new Klingon into current quadrant."
5826 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
5829 "Set up a new state of quadrant, for when we enter or re-enter it."
5832 game.neutz = game.inorbit = game.landed = False
5833 game.ientesc = game.iseenit = False
5834 # Create a blank quadrant
5835 game.quad = fill2d(QUADSIZE, lambda i, j: IHDOT)
5837 # Attempt to escape Super-commander, so tbeam back!
5840 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
5841 # cope with supernova
5844 game.klhere = q.klingons
5845 game.irhere = q.romulans
5847 game.quad[game.sector.i][game.sector.j] = game.ship
5850 # Position ordinary Klingons
5851 for i in range(game.klhere):
5853 # If we need a commander, promote a Klingon
5854 for cmdr in game.state.kcmdr:
5855 if cmdr == game.quadrant:
5856 e = game.enemies[game.klhere-1]
5857 game.quad[e.kloc.i][e.kloc.j] = IHC
5858 e.kpower = randreal(950,1350) + 50.0*game.skill
5860 # If we need a super-commander, promote a Klingon
5861 if game.quadrant == game.state.kscmdr:
5863 game.quad[e.kloc.i][e.kloc.j] = IHS
5864 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
5865 game.iscate = (game.state.remkl > 1)
5866 # Put in Romulans if needed
5867 for i in range(q.romulans):
5868 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
5869 # If quadrant needs a starbase, put it in
5871 game.base = dropin(IHB)
5872 # If quadrant needs a planet, put it in
5874 game.iplnet = q.planet
5875 if not q.planet.inhabited:
5876 game.plnet = dropin(IHP)
5878 game.plnet = dropin(IHW)
5879 # Check for condition
5882 if game.irhere > 0 and game.klhere == 0:
5884 if not damaged(DRADIO):
5886 prout(_("LT. Uhura- \"Captain, an urgent message."))
5887 prout(_(" I'll put it on audio.\" CLICK"))
5889 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
5890 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
5891 # Put in THING if needed
5892 if thing == game.quadrant:
5893 enemy(type=IHQUEST, loc=dropin(),
5894 power=randreal(6000,6500.0)+250.0*game.skill)
5895 if not damaged(DSRSENS):
5897 prout(_("Mr. Spock- \"Captain, this is most unusual."))
5898 prout(_(" Please examine your short-range scan.\""))
5899 # Decide if quadrant needs a Tholian; lighten up if skill is low
5900 if game.options & OPTION_THOLIAN:
5901 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
5902 (game.skill == SKILL_GOOD and withprob(0.05)) or \
5903 (game.skill > SKILL_GOOD and withprob(0.08)):
5906 w.i = withprob(0.5) * (QUADSIZE-1)
5907 w.j = withprob(0.5) * (QUADSIZE-1)
5908 if game.quad[w.i][w.j] == IHDOT:
5910 game.tholian = enemy(type=IHT, loc=w,
5911 power=randrange(100, 500) + 25.0*game.skill)
5912 # Reserve unoccupied corners
5913 if game.quad[0][0]==IHDOT:
5914 game.quad[0][0] = 'X'
5915 if game.quad[0][QUADSIZE-1]==IHDOT:
5916 game.quad[0][QUADSIZE-1] = 'X'
5917 if game.quad[QUADSIZE-1][0]==IHDOT:
5918 game.quad[QUADSIZE-1][0] = 'X'
5919 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
5920 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
5921 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
5922 # And finally the stars
5923 for i in range(q.stars):
5925 # Put in a few black holes
5926 for i in range(1, 3+1):
5929 # Take out X's in corners if Tholian present
5931 if game.quad[0][0]=='X':
5932 game.quad[0][0] = IHDOT
5933 if game.quad[0][QUADSIZE-1]=='X':
5934 game.quad[0][QUADSIZE-1] = IHDOT
5935 if game.quad[QUADSIZE-1][0]=='X':
5936 game.quad[QUADSIZE-1][0] = IHDOT
5937 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
5938 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
5941 "Set the self-destruct password."
5942 if game.options & OPTION_PLAIN:
5945 proutn(_("Please type in a secret password- "))
5947 game.passwd = scanner.token
5948 if game.passwd != None:
5953 game.passwd += chr(ord('a')+randrange(26))
5955 # Code from sst.c begins here
5958 "SRSCAN": OPTION_TTY,
5959 "STATUS": OPTION_TTY,
5960 "REQUEST": OPTION_TTY,
5961 "LRSCAN": OPTION_TTY,
5974 "SENSORS": OPTION_PLANETS,
5975 "ORBIT": OPTION_PLANETS,
5976 "TRANSPORT": OPTION_PLANETS,
5977 "MINE": OPTION_PLANETS,
5978 "CRYSTALS": OPTION_PLANETS,
5979 "SHUTTLE": OPTION_PLANETS,
5980 "PLANETS": OPTION_PLANETS,
5985 "PROBE": OPTION_PROBE,
5987 "FREEZE": 0, # Synonym for SAVE
5993 "SOS": 0, # Synonym for MAYDAY
5994 "CALL": 0, # Synonym for MAYDAY
6000 "Generate a list of legal commands."
6001 prout(_("LEGAL COMMANDS ARE:"))
6003 for key in commands:
6004 if not commands[key] or (commands[key] & game.options):
6005 proutn("%-12s " % key)
6007 if emitted % 5 == 4:
6012 "Browse on-line help."
6013 key = scanner.next()
6016 setwnd(prompt_window)
6017 proutn(_("Help on what command? "))
6018 key = scanner.next()
6019 setwnd(message_window)
6022 if scanner.token in commands or scanner.token == "ABBREV":
6029 cmd = scanner.token.upper()
6031 fp = open(SSTDOC, "r")
6034 fp = open(DOC_NAME, "r")
6036 prout(_("Spock- \"Captain, that information is missing from the"))
6037 proutn(_(" computer. You need to find "))
6039 prout(_(" and put it in the"))
6040 proutn(_(" current directory or to "))
6044 # This used to continue: "You need to find SST.DOC and put
6045 # it in the current directory."
6049 linebuf = fp.readline()
6051 prout(_("Spock- \"Captain, there is no information on that command.\""))
6054 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6055 linebuf = linebuf[3:].strip()
6059 prout(_("Spock- \"Captain, I've found the following information:\""))
6061 while linebuf in fp:
6062 if "******" in linebuf:
6068 "Command-interpretation loop."
6070 setwnd(message_window)
6071 while True: # command loop
6073 while True: # get a command
6078 setwnd(prompt_window)
6081 if scanner.next() == "IHEOL":
6082 if game.options & OPTION_CURSES:
6085 elif scanner.token == "":
6089 setwnd(message_window)
6091 candidates = filter(lambda x: x.startswith(scanner.token.upper()),
6093 if len(candidates) == 1:
6096 elif candidates and not (game.options & OPTION_PLAIN):
6097 prout("Commands with prefix '%s': %s" % (scanner.token, " ".join(candidates)))
6101 if cmd == "SRSCAN": # srscan
6103 elif cmd == "STATUS": # status
6105 elif cmd == "REQUEST": # status request
6107 elif cmd == "LRSCAN": # long range scan
6108 lrscan(silent=False)
6109 elif cmd == "PHASERS": # phasers
6113 elif cmd == "TORPEDO": # photon torpedos
6117 elif cmd == "MOVE": # move under warp
6119 elif cmd == "SHIELDS": # shields
6120 doshield(shraise=False)
6123 game.shldchg = False
6124 elif cmd == "DOCK": # dock at starbase
6127 attack(torps_ok=False)
6128 elif cmd == "DAMAGES": # damage reports
6130 elif cmd == "CHART": # chart
6132 elif cmd == "IMPULSE": # impulse
6134 elif cmd == "REST": # rest
6138 elif cmd == "WARP": # warp
6140 elif cmd == "SCORE": # score
6142 elif cmd == "SENSORS": # sensors
6144 elif cmd == "ORBIT": # orbit
6148 elif cmd == "TRANSPORT": # transport "beam"
6150 elif cmd == "MINE": # mine
6154 elif cmd == "CRYSTALS": # crystals
6158 elif cmd == "SHUTTLE": # shuttle
6162 elif cmd == "PLANETS": # Planet list
6164 elif cmd == "REPORT": # Game Report
6166 elif cmd == "COMPUTER": # use COMPUTER!
6168 elif cmd == "COMMANDS":
6170 elif cmd == "EMEXIT": # Emergency exit
6171 clrscr() # Hide screen
6172 freeze(True) # forced save
6173 raise SysExit,1 # And quick exit
6174 elif cmd == "PROBE":
6175 probe() # Launch probe
6178 elif cmd == "ABANDON": # Abandon Ship
6180 elif cmd == "DESTRUCT": # Self Destruct
6182 elif cmd == "SAVE": # Save Game
6185 if game.skill > SKILL_GOOD:
6186 prout(_("WARNING--Saved games produce no plaques!"))
6187 elif cmd == "DEATHRAY": # Try a desparation measure
6191 elif cmd == "DEBUGCMD": # What do we want for debug???
6193 elif cmd == "MAYDAY": # Call for help
6198 game.alldone = True # quit the game
6203 break # Game has ended
6204 if game.optime != 0.0:
6207 break # Events did us in
6208 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
6211 if hitme and not game.justin:
6212 attack(torps_ok=True)
6215 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
6226 "Emit the name of an enemy or feature."
6227 if type == IHR: s = _("Romulan")
6228 elif type == IHK: s = _("Klingon")
6229 elif type == IHC: s = _("Commander")
6230 elif type == IHS: s = _("Super-commander")
6231 elif type == IHSTAR: s = _("Star")
6232 elif type == IHP: s = _("Planet")
6233 elif type == IHB: s = _("Starbase")
6234 elif type == IHBLANK: s = _("Black hole")
6235 elif type == IHT: s = _("Tholian")
6236 elif type == IHWEB: s = _("Tholian web")
6237 elif type == IHQUEST: s = _("Stranger")
6238 elif type == IHW: s = _("Inhabited World")
6239 else: s = "Unknown??"
6242 def crmena(stars, enemy, loctype, w):
6243 "Emit the name of an enemy and his location."
6247 buf += cramen(enemy) + _(" at ")
6248 if loctype == "quadrant":
6249 buf += _("Quadrant ")
6250 elif loctype == "sector":
6255 "Emit our ship name."
6256 return{IHE:_("Enterprise"),IHF:_("Faerie Queene")}.get(game.ship,"Ship???")
6259 "Emit a line of stars"
6260 prouts("******************************************************")
6264 return -avrage*math.log(1e-7 + randreal())
6266 def randplace(size):
6267 "Choose a random location."
6269 w.i = randrange(size)
6270 w.j = randrange(size)
6280 # Get a token from the user
6283 # Fill the token quue if nothing here
6284 while not self.inqueue:
6286 if curwnd==prompt_window:
6288 setwnd(message_window)
6295 self.inqueue = line.lstrip().split() + ["IHEOL"]
6296 # From here on in it's all looking at the queue
6297 self.token = self.inqueue.pop(0)
6298 if self.token == "IHEOL":
6302 self.real = float(self.token)
6303 self.type = "IHREAL"
6308 self.token = self.token.lower()
6309 self.type = "IHALPHA"
6312 def append(self, tok):
6313 self.inqueue.append(tok)
6314 def push(self, tok):
6315 self.inqueue.insert(0, tok)
6319 # Demand input for next scan
6321 self.real = self.token = None
6323 # compares s to item and returns true if it matches to the length of s
6324 return s.startswith(self.token)
6326 # Round token value to nearest integer
6327 return int(round(scanner.real))
6331 if scanner.type != "IHREAL":
6334 s.i = scanner.int()-1
6336 if scanner.type != "IHREAL":
6339 s.j = scanner.int()-1
6342 return "<sstcanner: token=%s, type=%s, queue=%s>" % (scanner.token, scanner.type, scanner.inqueue)
6345 "Yes-or-no confirmation."
6349 if scanner.token == 'y':
6351 if scanner.token == 'n':
6354 proutn(_("Please answer with \"y\" or \"n\": "))
6357 "Complain about unparseable input."
6360 prout(_("Beg your pardon, Captain?"))
6363 "Access to the internals for debugging."
6364 proutn("Reset levels? ")
6366 if game.energy < game.inenrg:
6367 game.energy = game.inenrg
6368 game.shield = game.inshld
6369 game.torps = game.intorps
6370 game.lsupres = game.inlsr
6371 proutn("Reset damage? ")
6373 for i in range(NDEVICES):
6374 if game.damage[i] > 0.0:
6375 game.damage[i] = 0.0
6376 proutn("Toggle debug flag? ")
6380 prout("Debug output ON")
6382 prout("Debug output OFF")
6383 proutn("Cause selective damage? ")
6385 for i in range(NDEVICES):
6386 proutn("Kill %s?" % device[i])
6388 key = scanner.next()
6389 if key == "IHALPHA" and scanner.sees("y"):
6390 game.damage[i] = 10.0
6391 proutn("Examine/change events? ")
6396 FSNOVA: "Supernova ",
6399 FBATTAK: "Base Attack ",
6400 FCDBAS: "Base Destroy ",
6401 FSCMOVE: "SC Move ",
6402 FSCDBAS: "SC Base Destroy ",
6403 FDSPROB: "Probe Move ",
6404 FDISTR: "Distress Call ",
6405 FENSLV: "Enslavement ",
6406 FREPRO: "Klingon Build ",
6408 for i in range(1, NEVENTS):
6411 proutn("%.2f" % (scheduled(i)-game.state.date))
6412 if i == FENSLV or i == FREPRO:
6414 proutn(" in %s" % ev.quadrant)
6419 key = scanner.next()
6423 elif key == "IHREAL":
6424 ev = schedule(i, scanner.real)
6425 if i == FENSLV or i == FREPRO:
6427 proutn("In quadrant- ")
6428 key = scanner.next()
6429 # "IHEOL" says to leave coordinates as they are
6432 prout("Event %d canceled, no x coordinate." % (i))
6435 w.i = int(round(scanner.real))
6436 key = scanner.next()
6438 prout("Event %d canceled, no y coordinate." % (i))
6441 w.j = int(round(scanner.real))
6444 proutn("Induce supernova here? ")
6446 game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova = True
6449 if __name__ == '__main__':
6450 import getopt, socket
6452 global line, thing, game, idebug
6458 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6459 if os.getenv("TERM"):
6460 game.options |= OPTION_CURSES
6462 game.options |= OPTION_TTY
6463 seed = int(time.time())
6464 (options, arguments) = getopt.getopt(sys.argv[1:], "r:s:tx")
6465 for (switch, val) in options:
6468 replayfp = open(val, "r")
6470 sys.stderr.write("sst: can't open replay file %s\n" % val)
6473 line = replayfp.readline().strip()
6474 (leader, key, seed) = line.split()
6476 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6477 line = replayfp.readline().strip()
6478 arguments += line.split()[2:]
6480 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6482 game.options |= OPTION_TTY
6483 game.options &=~ OPTION_CURSES
6484 elif switch == '-s':
6486 elif switch == '-t':
6487 game.options |= OPTION_TTY
6488 game.options &=~ OPTION_CURSES
6489 elif switch == '-x':
6492 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6494 # where to save the input in case of bugs
6496 logfp = open("/usr/tmp/sst-input.log", "w")
6498 sys.stderr.write("sst: warning, can't open logfile\n")
6500 logfp.write("# seed %s\n" % seed)
6501 logfp.write("# options %s\n" % " ".join(arguments))
6502 logfp.write("# recorded by %s@%s on %s\n" % \
6503 (os.getenv("LOGNAME"),socket.gethostname(),time.ctime()))
6505 scanner = sstscanner()
6506 map(scanner.append, arguments)
6509 while True: # Play a game
6510 setwnd(fullscreen_window)
6516 game.alldone = False
6522 if game.tourn and game.alldone:
6523 proutn(_("Do you want your score recorded?"))
6529 proutn(_("Do you want to play again? "))
6533 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6537 except KeyboardInterrupt: