3 sst.py =-- Super Star Trek in Python
5 This code is a Python translation of a C translation of a FORTRAN original.
6 The FORTRANness still shows in many ways, notably the use of a lot of
7 parallel arrays where a more modern language would use structures
8 or objects. (However, 1-origin array indexing was fixed.)
12 SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON,
13 LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE
14 were in the original non-"super" version of UT FORTRAN Star Trek.
16 Tholians were not in the original. Dave is dubious about their merits.
17 (They are now controlled by OPTION_THOLIAN and turned off if the game
20 Planets and dilithium crystals were not in the original. Dave is OK
21 with this idea. (It's now controlled by OPTION_PLANETS and turned
22 off if the game type is "plain".)
24 Dave says the bit about the Galileo getting turned into a
25 McDonald's is "consistant with our original vision". (This has been
26 left permanently enabled, as it can only happen if OPTION_PLANETS
29 Dave also says the Space Thingy should not be preserved across saved
30 games, so you can't prove to others that you've seen it. He says it
31 shouldn't fire back, either. It should do nothing except scream and
32 disappear when hit by photon torpedos. It's OK that it may move
33 when attacked, but it didn't in the original. (Whether the Thingy
34 can fire back is now controlled by OPTION_THINGY and turned off if the
35 game type is "plain" or "almy". The no-save behavior has been restored.)
37 The Faerie Queen, black holes, and time warping were in the original.
39 Here are Tom Almy's changes:
41 In early 1997, I got the bright idea to look for references to
42 "Super Star Trek" on the World Wide Web. There weren't many hits,
43 but there was one that came up with 1979 Fortran sources! This
44 version had a few additional features that mine didn't have,
45 however mine had some feature it didn't have. So I merged its
46 features that I liked. I also took a peek at the DECUS version (a
47 port, less sources, to the PDP-10), and some other variations.
49 1, Compared to the original UT version, I've changed the "help" command to
50 "call" and the "terminate" command to "quit" to better match
51 user expectations. The DECUS version apparently made those changes
52 as well as changing "freeze" to "save". However I like "freeze".
53 (Both "freeze" and "save" work in SST2K.)
55 2. The experimental deathray originally had only a 5% chance of
56 success, but could be used repeatedly. I guess after a couple
57 years of use, it was less "experimental" because the 1979
58 version had a 70% success rate. However it was prone to breaking
59 after use. I upgraded the deathray, but kept the original set of
60 failure modes (great humor!). (Now controlled by OPTION_DEATHRAY
61 and turned off if game type is "plain".)
63 3. The 1979 version also mentions srscan and lrscan working when
64 docked (using the starbase's scanners), so I made some changes here
65 to do this (and indicating that fact to the player), and then realized
66 the base would have a subspace radio as well -- doing a Chart when docked
67 updates the star chart, and all radio reports will be heard. The Dock
68 command will also give a report if a base is under attack.
70 4. Tholian Web from the 1979 version. (Now controlled by
71 OPTION_THOLIAN and turned off if game type is "plain".)
73 5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING
74 and turned off if game type is "plain".)
76 6. Regular Klingons and Romulans can move in Expert and Emeritus games.
77 This code could use improvement. (Now controlled by OPTION_MVBADDY
78 and turned off if game type is "plain".)
80 7. The deep-space probe feature from the DECUS version. (Now controlled
81 by OPTION_PROBE and turned off if game type is "plain").
83 8. 'emexit' command from the 1979 version.
85 9. Bugfix: Klingon commander movements are no longer reported if long-range
88 10. Bugfix: Better base positioning at startup (more spread out).
89 That made sense to add because most people abort games with
92 In June 2002, I fixed two known bugs and a documentation typo.
93 In June 2004 I fixed a number of bugs involving: 1) parsing invalid
94 numbers, 2) manual phasers when SR scan is damaged and commander is
95 present, 3) time warping into the future, 4) hang when moving
96 klingons in crowded quadrants. (These fixes are in SST2K.)
98 Here are Stas Sergeev's changes:
100 1. The Space Thingy can be shoved, if you ram it, and can fire back if
101 fired upon. (Now controlled by OPTION_THINGY and turned off if game
102 type is "plain" or "almy".)
104 2. When you are docked, base covers you with an almost invincible shield.
105 (A commander can still ram you, or a Romulan can destroy the base,
106 or a SCom can even succeed with direct attack IIRC, but this rarely
107 happens.) (Now controlled by OPTION_BASE and turned off if game
108 type is "plain" or "almy".)
110 3. Ramming a black hole is no longer instant death. There is a
111 chance you might get timewarped instead. (Now controlled by
112 OPTION_BLKHOLE and turned off if game type is "plain" or "almy".)
114 4. The Tholian can be hit with phasers.
116 5. SCom can't escape from you if no more enemies remain
117 (without this, chasing SCom can take an eternity).
119 6. Probe target you enter is now the destination quadrant. Before I don't
120 remember what it was, but it was something I had difficulty using.
122 7. Secret password is now autogenerated.
124 8. "Plaque" is adjusted for A4 paper :-)
126 9. Phasers now tells you how much energy needed, but only if the computer
129 10. Planets are auto-scanned when you enter the quadrant.
131 11. Mining or using crystals in presense of enemy now yields an attack.
132 There are other minor adjustments to what yields an attack
135 12. "freeze" command reverts to "save", most people will understand this
136 better anyway. (SST2K recognizes both.)
138 13. Screen-oriented interface, with sensor scans always up. (SST2K
139 supports both screen-oriented and TTY modes.)
141 Eric Raymond's changes:
143 Mainly, I translated this C code out of FORTRAN into C -- created #defines
144 for a lot of magic numbers and refactored the heck out of it.
146 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
148 2. Status report now indicates when dilithium crystals are on board.
150 3. Per Dave Matuszek's remarks, Thingy state is never saved across games.
152 4. Added game option selection so you can play a close (but not bug-for-
153 bug identical) approximation of older versions.
155 5. Half the quadrants now have inhabited planets, from which one
156 cannot mine dilithium (there will still be the same additional number
157 of dilithium-bearing planets). Torpedoing an inhabited world is *bad*.
158 There is BSD-Trek-like logic for Klingons to attack and enslave
159 inhabited worlds, producing more ships (only is skill is 'good' or
160 better). (Controlled by OPTION_WORLDS and turned off if game
161 type is "plain" or "almy".)
163 6. User input is now logged so we can do regression testing.
165 7. More BSD-Trek features: You can now lose if your entire crew
166 dies in battle. When abandoning ship in a game with inhabited
167 worlds enabled, they must have one in the quadrant to beam down
168 to; otherwise they die in space and this counts heavily against
169 your score. Docking at a starbase replenishes your crew.
171 8. Still more BSD-Trek: we now have a weighted damage table.
172 Also, the nav subsystem (enabling automatic course
173 setting) can be damaged separately from the main computer (which
174 handles weapons targeting, ETA calculation, and self-destruct).
176 After these features were added, I translated this into Python and added
179 9. A long-range scan is done silently whenever you call CHART; thus
180 the LRSCAN command is no longer needed. (Controlled by OPTION_AUTOSCAN
181 and turned off if game type is "plain" or "almy".)
183 import os,sys,math,curses,time,atexit,readline,cPickle,random,getopt,copy
185 SSTDOC = "/usr/share/doc/sst/sst.doc"
188 # Stub to be replaced
189 def _(str): return str
193 NINHAB = (GALSIZE * GALSIZE / 2)
195 PLNETMAX = (NINHAB + MAXUNINHAB)
198 BASEMAX = (GALSIZE * GALSIZE / 12)
201 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 def square(i): return ((i)*(i))
210 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
211 def invalidate(w): w.x = w.y = 0
212 def is_valid(w): return (w.x != 0 and w.y != 0)
214 # How to represent features
239 def __init__(self, x=None, y=None):
242 def invalidate(self):
243 self.x = self.y = None
245 return self.x != None and self.y != None
246 def __eq__(self, other):
247 return other != None and self.x == other.y and self.x == other.y
248 def __add__(self, other):
249 return coord(self.x+self.x, self.y+self.y)
250 def __sub__(self, other):
251 return coord(self.x-self.x, self.y-self.y)
252 def distance(self, other):
253 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
259 s.x = self.x / abs(self.x)
263 s.y = self.y / abs(self.y)
267 s.x = self.x + randrange(-1, 2)
268 s.y = self.y + randrange(-1, 2)
273 if self.x == None or self.y == None:
275 return "%s - %s" % (self.x+1, self.y+1)
280 self.name = None # string-valued if inhabited
281 self.w = coord() # quadrant located
282 self.pclass = None # could be ""M", "N", "O", or "destroyed"
283 self.crystals = "absent"# could be "mined", "present", "absent"
284 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
285 self.inhabited = False # is it inhabites?
296 self.supernova = None
298 self.status = None # Could be "secure", "distressed", "enslaved"
306 def fill2d(size, fillfun):
307 "Fill an empty list in 2D."
309 for i in range(size):
311 for j in range(size):
312 lst[i].append(fillfun(i, j))
317 self.snap = False # snapshot taken
318 self.crew = 0 # crew complement
319 self.remkl = 0 # remaining klingons
320 self.remcom = 0 # remaining commanders
321 self.nscrem = 0 # remaining super commanders
322 self.rembase = 0 # remaining bases
323 self.starkl = 0 # destroyed stars
324 self.basekl = 0 # destroyed bases
325 self.nromrem = 0 # Romulans remaining
326 self.nplankl = 0 # destroyed uninhabited planets
327 self.nworldkl = 0 # destroyed inhabited planets
328 self.planets = [] # Planet information
329 self.date = 0.0 # stardate
330 self.remres = 0 # remaining resources
331 self.remtime = 0 # remaining time
332 self.baseq = [] # Base quadrant coordinates
333 for i in range(BASEMAX):
334 self.baseq.append(coord())
335 self.kcmdr = [] # Commander quadrant coordinates
336 for i in range(QUADSIZE):
337 self.kcmdr.append(coord())
338 self.kscmdr = coord() # Supercommander quadrant coordinates
339 # the galaxy (subscript 0 not used)
340 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
341 # the starchart (subscript 0 not used)
342 self.chart = fill2d(GALSIZE, lambda i, j: page())
346 self.date = None # A real number
347 self.quadrant = None # A coord structure
350 OPTION_ALL = 0xffffffff
351 OPTION_TTY = 0x00000001 # old interface
352 OPTION_CURSES = 0x00000002 # new interface
353 OPTION_IOMODES = 0x00000003 # cover both interfaces
354 OPTION_PLANETS = 0x00000004 # planets and mining
355 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
356 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
357 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
358 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
359 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
360 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
361 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
362 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
363 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
364 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
365 OPTION_PLAIN = 0x01000000 # user chose plain game
366 OPTION_ALMY = 0x02000000 # user chose Almy variant
385 NDEVICES= 16 # Number of devices
394 def damaged(dev): return (game.damage[dev] != 0.0)
395 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
397 # Define future events
398 FSPY = 0 # Spy event happens always (no future[] entry)
399 # can cause SC to tractor beam Enterprise
400 FSNOVA = 1 # Supernova
401 FTBEAM = 2 # Commander tractor beams Enterprise
402 FSNAP = 3 # Snapshot for time warp
403 FBATTAK = 4 # Commander attacks base
404 FCDBAS = 5 # Commander destroys base
405 FSCMOVE = 6 # Supercommander moves (might attack base)
406 FSCDBAS = 7 # Supercommander destroys base
407 FDSPROB = 8 # Move deep space probe
408 FDISTR = 9 # Emit distress call from an inhabited world
409 FENSLV = 10 # Inhabited word is enslaved */
410 FREPRO = 11 # Klingons build a ship in an enslaved system
414 # abstract out the event handling -- underlying data structures will change
415 # when we implement stateful events
417 def findevent(evtype): return game.future[evtype]
420 def __init__(self, type=None, loc=None, power=None):
425 self.kpower = power # enemy energy level
426 game.enemies.append(self)
428 motion = (loc != self.kloc)
429 if self.kloc.x is not None and self.kloc.y is not None:
430 game.quad[self.kloc.x][self.kloc.y] = IHDOT
433 game.quad[self.kloc.x][self.kloc.y] = self.type
434 self.kdist = self.kavgd = distance(game.sector, loc)
436 self.kloc = coord() # enemy sector location
437 self.kdist = self.kavgd = None
438 game.enemies.remove(self)
441 return "<%s=%f>" % (self.kloc, self.kpower) # For debugging
445 self.options = None # Game options
446 self.state = snapshot() # A snapshot structure
447 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
448 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
449 self.damage = [0.0] * NDEVICES # damage encountered
450 self.future = [] # future events
451 for i in range(NEVENTS):
452 self.future.append(event())
453 self.passwd = None; # Self Destruct password
455 self.quadrant = None # where we are in the large
456 self.sector = None # where we are in the small
457 self.tholian = None # Tholian enemy object
458 self.base = None # position of base in current quadrant
459 self.battle = None # base coordinates being attacked
460 self.plnet = None # location of planet in quadrant
461 self.probec = None # current probe quadrant
462 self.gamewon = False # Finished!
463 self.ididit = False # action taken -- allows enemy to attack
464 self.alive = False # we are alive (not killed)
465 self.justin = False # just entered quadrant
466 self.shldup = False # shields are up
467 self.shldchg = False # shield is changing (affects efficiency)
468 self.comhere = False # commander here
469 self.ishere = False # super-commander in quadrant
470 self.iscate = False # super commander is here
471 self.ientesc = False # attempted escape from supercommander
472 self.resting = False # rest time
473 self.icraft = False # Kirk in Galileo
474 self.landed = False # party on planet (true), on ship (false)
475 self.alldone = False # game is now finished
476 self.neutz = False # Romulan Neutral Zone
477 self.isarmed = False # probe is armed
478 self.inorbit = False # orbiting a planet
479 self.imine = False # mining
480 self.icrystl = False # dilithium crystals aboard
481 self.iseenit = False # seen base attack report
482 self.thawed = False # thawed game
483 self.condition = None # "green", "yellow", "red", "docked", "dead"
484 self.iscraft = None # "onship", "offship", "removed"
485 self.skill = None # Player skill level
486 self.inkling = 0 # initial number of klingons
487 self.inbase = 0 # initial number of bases
488 self.incom = 0 # initial number of commanders
489 self.inscom = 0 # initial number of commanders
490 self.inrom = 0 # initial number of commanders
491 self.instar = 0 # initial stars
492 self.intorps = 0 # initial/max torpedoes
493 self.torps = 0 # number of torpedoes
494 self.ship = 0 # ship type -- 'E' is Enterprise
495 self.abandoned = 0 # count of crew abandoned in space
496 self.length = 0 # length of game
497 self.klhere = 0 # klingons here
498 self.casual = 0 # causalties
499 self.nhelp = 0 # calls for help
500 self.nkinks = 0 # count of energy-barrier crossings
501 self.iplnet = None # planet # in quadrant
502 self.inplan = 0 # initial planets
503 self.irhere = 0 # Romulans in quadrant
504 self.isatb = 0 # =1 if super commander is attacking base
505 self.tourn = None # tournament number
506 self.proben = 0 # number of moves for probe
507 self.nprobes = 0 # number of probes available
508 self.inresor = 0.0 # initial resources
509 self.intime = 0.0 # initial time
510 self.inenrg = 0.0 # initial/max energy
511 self.inshld = 0.0 # initial/max shield
512 self.inlsr = 0.0 # initial life support resources
513 self.indate = 0.0 # initial date
514 self.energy = 0.0 # energy level
515 self.shield = 0.0 # shield level
516 self.warpfac = 0.0 # warp speed
517 self.wfacsq = 0.0 # squared warp factor
518 self.lsupres = 0.0 # life support reserves
519 self.dist = 0.0 # movement distance
520 self.direc = 0.0 # movement direction
521 self.optime = 0.0 # time taken by current operation
522 self.docfac = 0.0 # repair factor when docking (constant?)
523 self.damfac = 0.0 # damage factor
524 self.lastchart = 0.0 # time star chart was last updated
525 self.cryprob = 0.0 # probability that crystal will work
526 self.probex = 0.0 # location of probe
528 self.probeinx = 0.0 # probe x,y increment
529 self.probeiny = 0.0 #
530 self.height = 0.0 # height of orbit around planet
532 # Stas thinks this should be (C expression):
533 # game.state.remkl + game.state.remcom > 0 ?
534 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
535 # He says the existing expression is prone to divide-by-zero errors
536 # after killing the last klingon when score is shown -- perhaps also
537 # if the only remaining klingon is SCOM.
538 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
539 # From enumerated type 'feature'
560 # From enumerated type 'FINTYPE'
584 # From enumerated type 'COLORS'
603 # Log the results of pulling random numbers so we can check determinism.
609 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
612 def randrange(*args):
613 v = random.randrange(*args)
614 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
620 v *= args[0] # returns from [0, a1)
622 v = args[0] + v*args[1] # returns from [a1, a2)
623 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
626 # Code from ai.c begins here
628 def tryexit(enemy, look, irun):
629 # a bad guy attempts to bug out
631 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
632 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
633 if not VALID_QUADRANT(iq.x,iq.y) or \
634 game.state.galaxy[iq.x][iq.y].supernova or \
635 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
636 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
637 if enemy.type == IHR:
638 return False; # Romulans cannot escape!
640 # avoid intruding on another commander's territory
641 if enemy.type == IHC:
642 for n in range(game.state.remcom):
643 if game.state.kcmdr[n] == iq:
645 # refuse to leave if currently attacking starbase
646 if game.battle == game.quadrant:
648 # don't leave if over 1000 units of energy
649 if enemy.kpower > 1000.0:
651 # print escape message and move out of quadrant.
652 # we know this if either short or long range sensors are working
653 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
654 game.condition == "docked":
655 crmena(True, enemy.type, "sector", enemy.kloc)
656 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
657 # handle local matters related to escape
660 if game.condition != "docked":
662 # Handle global matters related to escape
663 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
664 game.state.galaxy[iq.x][iq.y].klingons += 1
670 schedule(FSCMOVE, 0.2777)
674 for n in range(game.state.remcom):
675 if game.state.kcmdr[n] == game.quadrant:
676 game.state.kcmdr[n]=iq
679 return True; # success
682 # The bad-guy movement algorithm:
684 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
685 # If both are operating full strength, force is 1000. If both are damaged,
686 # force is -1000. Having shields down subtracts an additional 1000.
688 # 2. Enemy has forces equal to the energy of the attacker plus
689 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
690 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
692 # Attacker Initial energy levels (nominal):
693 # Klingon Romulan Commander Super-Commander
694 # Novice 400 700 1200
696 # Good 450 800 1300 1750
697 # Expert 475 850 1350 1875
698 # Emeritus 500 900 1400 2000
699 # VARIANCE 75 200 200 200
701 # Enemy vessels only move prior to their attack. In Novice - Good games
702 # only commanders move. In Expert games, all enemy vessels move if there
703 # is a commander present. In Emeritus games all enemy vessels move.
705 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
706 # forces are 1000 greater than Enterprise.
708 # Agressive action on average cuts the distance between the ship and
709 # the enemy to 1/4 the original.
711 # 4. At lower energy advantage, movement units are proportional to the
712 # advantage with a 650 advantage being to hold ground, 800 to move forward
713 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
715 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
716 # retreat, especially at high skill levels.
718 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
721 def movebaddy(enemy):
722 # tactical movement for the bad guys
723 next = coord(); look = coord()
725 # This should probably be just game.comhere + game.ishere
726 if game.skill >= SKILL_EXPERT:
727 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
729 nbaddys = game.comhere + game.ishere
731 mdist = int(dist1 + 0.5); # Nearest integer distance
732 # If SC, check with spy to see if should hi-tail it
733 if enemy.type==IHS and \
734 (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
738 # decide whether to advance, retreat, or hold position
739 forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
741 forces += 1000; # Good for enemy if shield is down!
742 if not damaged(DPHASER) or not damaged(DPHOTON):
743 if damaged(DPHASER): # phasers damaged
746 forces -= 0.2*(game.energy - 2500.0)
747 if damaged(DPHOTON): # photon torpedoes damaged
750 forces -= 50.0*game.torps
752 # phasers and photon tubes both out!
755 if forces <= 1000.0 and game.condition != "docked": # Typical situation
756 motion = ((forces + randreal(200))/150.0) - 5.0
758 if forces > 1000.0: # Very strong -- move in for kill
759 motion = (1.0-square(randreal()))*dist1 + 1.0
760 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
761 motion -= game.skill*(2.0-square(randreal()))
763 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
764 # don't move if no motion
767 # Limit motion according to skill
768 if abs(motion) > game.skill:
773 # calculate preferred number of steps
778 if motion > 0 and nsteps > mdist:
779 nsteps = mdist; # don't overshoot
780 if nsteps > QUADSIZE:
781 nsteps = QUADSIZE; # This shouldn't be necessary
783 nsteps = 1; # This shouldn't be necessary
785 proutn("NSTEPS = %d:" % nsteps)
786 # Compute preferred values of delta X and Y
787 m = game.sector - enemy.kloc
788 if 2.0 * abs(m.x) < abs(m.y):
790 if 2.0 * abs(m.y) < abs(game.sector.x-enemy.kloc.x):
804 for ll in range(nsteps):
806 proutn(" %d" % (ll+1))
807 # Check if preferred position available
818 attempts = 0; # Settle mysterious hang problem
819 while attempts < 20 and not success:
821 if look.x < 0 or look.x >= QUADSIZE:
822 if motion < 0 and tryexit(enemy, look, irun):
824 if krawlx == m.x or m.y == 0:
826 look.x = next.x + krawlx
828 elif look.y < 0 or look.y >= QUADSIZE:
829 if motion < 0 and tryexit(enemy, look, irun):
831 if krawly == m.y or m.x == 0:
833 look.y = next.y + krawly
835 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
836 # See if enemy should ram ship
837 if game.quad[look.x][look.y] == game.ship and \
838 (enemy.type == IHC or enemy.type == IHS):
839 collision(rammed=True, enemy=enemy)
841 if krawlx != m.x and m.y != 0:
842 look.x = next.x + krawlx
844 elif krawly != m.y and m.x != 0:
845 look.y = next.y + krawly
848 break; # we have failed
860 if not damaged(DSRSENS) or game.condition == "docked":
863 proutn(_(" from Sector %s") % enemy.kloc)
864 if enemy.kdist < dist1:
865 proutn(_(" advances to "))
867 proutn(_(" retreats to "))
868 prout("Sector %s." % next)
871 # Klingon tactical movement
874 # Figure out which Klingon is the commander (or Supercommander)
877 for enemy in game.enemies:
878 if enemy.type == IHC:
881 for enemy in game.enemies:
882 if enemy.type == IHS:
885 # If skill level is high, move other Klingons and Romulans too!
886 # Move these last so they can base their actions on what the
888 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
889 for enemy in game.enemies:
890 if enemy.type in (IHK, IHR):
892 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
894 def movescom(iq, avoid):
895 # commander movement helper
896 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
897 game.state.galaxy[iq.x][iq.y].supernova or \
898 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
901 # Avoid quadrants with bases if we want to avoid Enterprise
902 for i in range(game.state.rembase):
903 if game.state.baseq[i] == iq:
905 if game.justin and not game.iscate:
908 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
909 game.state.kscmdr = iq
910 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
912 # SC has scooted, Remove him from current quadrant
918 for enemy in game.enemies:
919 if enemy.type == IHS:
923 if game.condition != "docked":
925 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
926 # check for a helpful planet
927 for i in range(game.inplan):
928 if game.state.planets[i].w == game.state.kscmdr and \
929 game.state.planets[i].crystals == "present":
931 game.state.planets[i].pclass = "destroyed"
932 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
935 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
936 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
937 prout(_(" by the Super-commander.\""))
939 return False; # looks good!
941 def supercommander():
942 # move the Super Commander
943 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
946 prout("== SUPERCOMMANDER")
947 # Decide on being active or passive
948 avoid = ((game.incom - game.state.remcom + game.inkling - game.state.remkl)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) or \
949 (game.state.date-game.indate) < 3.0)
950 if not game.iscate and avoid:
951 # compute move away from Enterprise
952 idelta = game.state.kscmdr-game.quadrant
953 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
955 idelta.x = game.state.kscmdr.y-game.quadrant.y
956 idelta.y = game.quadrant.x-game.state.kscmdr.x
958 # compute distances to starbases
959 if game.state.rembase <= 0:
963 sc = game.state.kscmdr
964 for i in range(game.state.rembase):
965 basetbl.append((i, distance(game.state.baseq[i], sc)))
966 if game.state.rembase > 1:
967 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
968 # look for nearest base without a commander, no Enterprise, and
969 # without too many Klingons, and not already under attack.
970 ifindit = iwhichb = 0
971 for i2 in range(game.state.rembase):
972 i = basetbl[i2][0]; # bug in original had it not finding nearest
973 ibq = game.state.baseq[i]
974 if ibq == game.quadrant or ibq == game.battle or \
975 game.state.galaxy[ibq.x][ibq.y].supernova or \
976 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
978 # if there is a commander, and no other base is appropriate,
979 # we will take the one with the commander
980 for j in range(game.state.remcom):
981 if ibq == game.state.kcmdr[j] and ifindit!= 2:
985 if j > game.state.remcom: # no commander -- use this one
990 return # Nothing suitable -- wait until next time
991 ibq = game.state.baseq[iwhichb]
992 # decide how to move toward base
993 idelta = ibq - game.state.kscmdr
994 # Maximum movement is 1 quadrant in either or both axes
995 idelta = idelta.sgn()
996 # try moving in both x and y directions
997 # there was what looked like a bug in the Almy C code here,
998 # but it might be this translation is just wrong.
999 iq = game.state.kscmdr + idelta
1000 if movescom(iq, avoid):
1001 # failed -- try some other maneuvers
1002 if idelta.x==0 or idelta.y==0:
1003 # attempt angle move
1005 iq.y = game.state.kscmdr.y + 1
1006 if movescom(iq, avoid):
1007 iq.y = game.state.kscmdr.y - 1
1010 iq.x = game.state.kscmdr.x + 1
1011 if movescom(iq, avoid):
1012 iq.x = game.state.kscmdr.x - 1
1015 # try moving just in x or y
1016 iq.y = game.state.kscmdr.y
1017 if movescom(iq, avoid):
1018 iq.y = game.state.kscmdr.y + idelta.y
1019 iq.x = game.state.kscmdr.x
1022 if game.state.rembase == 0:
1025 for i in range(game.state.rembase):
1026 ibq = game.state.baseq[i]
1027 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1030 return # no, don't attack base!
1031 game.iseenit = False
1033 schedule(FSCDBAS, randreal(1.0, 3.0))
1034 if is_scheduled(FCDBAS):
1035 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1036 if not communicating():
1040 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1041 % game.state.kscmdr)
1042 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1043 proutn(_(" It can survive until stardate %d.\"") \
1044 % int(scheduled(FSCDBAS)))
1045 if not game.resting:
1047 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1050 game.resting = False
1051 game.optime = 0.0; # actually finished
1053 # Check for intelligence report
1056 (not communicating()) or \
1057 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1060 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1061 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1066 if not game.tholian or game.justin:
1068 if game.tholian.kloc.x == 0 and game.tholian.kloc.y == 0:
1069 idx = 0; idy = QUADSIZE-1
1070 elif game.tholian.kloc.x == 0 and game.tholian.kloc.y == QUADSIZE-1:
1071 idx = QUADSIZE-1; idy = QUADSIZE-1
1072 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == QUADSIZE-1:
1073 idx = QUADSIZE-1; idy = 0
1074 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == 0:
1077 # something is wrong!
1080 # do nothing if we are blocked
1081 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1083 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1084 if game.tholian.kloc.x != idx:
1086 im = math.fabs(idx - game.tholian.kloc.x)*1.0/(idx - game.tholian.kloc.x)
1087 while game.tholian.kloc.x != idx:
1088 game.tholian.kloc.x += im
1089 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1090 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1091 elif game.tholian.kloc.y != idy:
1093 im = math.fabs(idy - game.tholian.kloc.y)*1.0/(idy - game.tholian.kloc.y)
1094 while game.tholian.kloc.y != idy:
1095 game.tholian.kloc.y += im
1096 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1097 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1098 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHT
1099 #game.enemies[-1].kloc = game.tholian #FIXME
1100 # check to see if all holes plugged
1101 for i in range(QUADSIZE):
1102 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1104 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1106 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1108 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1110 # All plugged up -- Tholian splits
1111 game.quad[game.tholian.kloc.x][game.tholian.kloc.y]=IHWEB
1113 crmena(True, IHT, "sector", game.tholian)
1114 prout(_(" completes web."))
1115 game.tholian.move(None)
1118 # Code from battle.c begins here
1120 def doshield(shraise):
1121 # change shield status
1129 if isit("transfer"):
1133 if damaged(DSHIELD):
1134 prout(_("Shields damaged and down."))
1141 proutn(_("Do you wish to change shield energy? "))
1143 proutn(_("Energy to transfer to shields- "))
1145 elif damaged(DSHIELD):
1146 prout(_("Shields damaged and down."))
1149 proutn(_("Shields are up. Do you want them down? "))
1156 proutn(_("Shields are down. Do you want them up? "))
1162 if action == "SHUP": # raise shields
1164 prout(_("Shields already up."))
1168 if game.condition != "docked":
1170 prout(_("Shields raised."))
1171 if game.energy <= 0:
1173 prout(_("Shields raising uses up last of energy."))
1178 elif action == "SHDN":
1180 prout(_("Shields already down."))
1184 prout(_("Shields lowered."))
1187 elif action == "NRG":
1188 while scan() != IHREAL:
1190 proutn(_("Energy to transfer to shields- "))
1194 if aaitem > game.energy:
1195 prout(_("Insufficient ship energy."))
1198 if game.shield+aaitem >= game.inshld:
1199 prout(_("Shield energy maximized."))
1200 if game.shield+aaitem > game.inshld:
1201 prout(_("Excess energy requested returned to ship energy"))
1202 game.energy -= game.inshld-game.shield
1203 game.shield = game.inshld
1205 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1206 # Prevent shield drain loophole
1208 prout(_("Engineering to bridge--"))
1209 prout(_(" Scott here. Power circuit problem, Captain."))
1210 prout(_(" I can't drain the shields."))
1213 if game.shield+aaitem < 0:
1214 prout(_("All shield energy transferred to ship."))
1215 game.energy += game.shield
1218 proutn(_("Scotty- \""))
1220 prout(_("Transferring energy to shields.\""))
1222 prout(_("Draining energy from shields.\""))
1223 game.shield += aaitem
1224 game.energy -= aaitem
1228 # choose a device to damage, at random.
1230 # Quoth Eric Allman in the code of BSD-Trek:
1231 # "Under certain conditions you can get a critical hit. This
1232 # sort of hit damages devices. The probability that a given
1233 # device is damaged depends on the device. Well protected
1234 # devices (such as the computer, which is in the core of the
1235 # ship and has considerable redundancy) almost never get
1236 # damaged, whereas devices which are exposed (such as the
1237 # warp engines) or which are particularly delicate (such as
1238 # the transporter) have a much higher probability of being
1241 # This is one place where OPTION_PLAIN does not restore the
1242 # original behavior, which was equiprobable damage across
1243 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1244 # and have done with it. Also, in the original game, DNAVYS
1245 # and DCOMPTR were the same device.
1247 # Instead, we use a table of weights similar to the one from BSD Trek.
1248 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1249 # We don't have a cloaking device. The shuttle got the allocation
1250 # for the cloaking device, then we shaved a half-percent off
1251 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1254 105, # DSRSENS: short range scanners 10.5%
1255 105, # DLRSENS: long range scanners 10.5%
1256 120, # DPHASER: phasers 12.0%
1257 120, # DPHOTON: photon torpedoes 12.0%
1258 25, # DLIFSUP: life support 2.5%
1259 65, # DWARPEN: warp drive 6.5%
1260 70, # DIMPULS: impulse engines 6.5%
1261 145, # DSHIELD: deflector shields 14.5%
1262 30, # DRADIO: subspace radio 3.0%
1263 45, # DSHUTTL: shuttle 4.5%
1264 15, # DCOMPTR: computer 1.5%
1265 20, # NAVCOMP: navigation system 2.0%
1266 75, # DTRANSP: transporter 7.5%
1267 20, # DSHCTRL: high-speed shield controller 2.0%
1268 10, # DDRAY: death ray 1.0%
1269 30, # DDSP: deep-space probes 3.0%
1271 idx = randrange(1000) # weights must sum to 1000
1273 for (i, w) in enumerate(weights):
1277 return None; # we should never get here
1279 def collision(rammed, enemy):
1280 # collision handling
1281 prouts(_("***RED ALERT! RED ALERT!"))
1283 prout(_("***COLLISION IMMINENT."))
1287 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(enemy.type, 1.0)
1289 proutn(_(" rammed by "))
1292 crmena(False, enemy.type, "sector", enemy.kloc)
1294 proutn(_(" (original position)"))
1296 deadkl(enemy.kloc, enemy.type, game.sector)
1299 prout(_(" heavily damaged."))
1300 icas = randrange(10, 30)
1301 prout(_("***Sickbay reports %d casualties"), icas)
1303 game.state.crew -= icas
1305 # In the pre-SST2K version, all devices got equiprobably damaged,
1306 # which was silly. Instead, pick up to half the devices at
1307 # random according to our weighting table,
1309 ncrits = randrange(NDEVICES/2)
1310 for m in range(ncrits):
1312 if game.damage[dev] < 0:
1314 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1315 # Damage for at least time of travel!
1316 game.damage[dev] += game.optime + extradm
1318 prout(_("***Shields are down."))
1319 if game.state.remkl + game.state.remcom + game.state.nscrem:
1326 def torpedo(course, dispersion, origin, number, nburst):
1327 # let a photon torpedo fly
1330 ac = course + 0.25*dispersion
1331 angle = (15.0-ac)*0.5235988
1332 bullseye = (15.0 - course)*0.5235988
1333 deltax = -math.sin(angle);
1334 deltay = math.cos(angle);
1335 x = origin.x; y = origin.y
1336 w = coord(); jw = coord()
1337 w.x = w.y = jw.x = jw.y = 0
1338 bigger = max(math.fabs(deltax), math.fabs(deltay))
1341 if not damaged(DSRSENS) or game.condition=="docked":
1342 setwnd(srscan_window)
1344 setwnd(message_window)
1345 # Loop to move a single torpedo
1346 for step in range(1, 15+1):
1351 if not VALID_SECTOR(w.x, w.y):
1353 iquad=game.quad[w.x][w.y]
1354 tracktorpedo(w, step, number, nburst, iquad)
1358 setwnd(message_window)
1359 if damaged(DSRSENS) and not game.condition=="docked":
1360 skip(1); # start new line after text track
1361 if iquad in (IHE, IHF): # Hit our ship
1363 proutn(_("Torpedo hits "))
1366 hit = 700.0 + randreal(100) - \
1367 1000.0 * distance(w, origin) * math.fabs(math.sin(bullseye-angle))
1368 newcnd(); # we're blown out of dock
1369 # We may be displaced.
1370 if game.landed or game.condition=="docked":
1371 return hit # Cheat if on a planet
1372 ang = angle + 2.5*(randreal()-0.5)
1373 temp = math.fabs(math.sin(ang))
1374 if math.fabs(math.cos(ang)) > temp:
1375 temp = math.fabs(math.cos(ang))
1376 xx = -math.sin(ang)/temp
1377 yy = math.cos(ang)/temp
1378 jw.x = int(w.x+xx+0.5)
1379 jw.y = int(w.y+yy+0.5)
1380 if not VALID_SECTOR(jw.x, jw.y):
1382 if game.quad[jw.x][jw.y]==IHBLANK:
1385 if game.quad[jw.x][jw.y]!=IHDOT:
1386 # can't move into object
1391 elif iquad in (IHC, IHS): # Hit a commander
1393 crmena(True, iquad, "sector", w)
1394 prout(_(" uses anti-photon device;"))
1395 prout(_(" torpedo neutralized."))
1397 elif iquad in (IHR, IHK): # Hit a regular enemy
1399 for enemy in game.enemies:
1400 if w == game.enemies[ll].kloc:
1402 kp = math.fabs(e.kpower)
1403 h1 = 700.0 + randrange(100) - \
1404 1000.0 * distance(w, origin) * math.fabs(math.sin(bullseye-angle))
1408 if enemy.kpower < 0:
1412 if enemy.kpower == 0:
1415 crmena(True, iquad, "sector", w)
1416 # If enemy damaged but not destroyed, try to displace
1417 ang = angle + 2.5*(randreal()-0.5)
1418 temp = math.fabs(math.sin(ang))
1419 if math.fabs(math.cos(ang)) > temp:
1420 temp = math.fabs(math.cos(ang))
1421 xx = -math.sin(ang)/temp
1422 yy = math.cos(ang)/temp
1423 jw.x = int(w.x+xx+0.5)
1424 jw.y = int(w.y+yy+0.5)
1425 if not VALID_SECTOR(jw.x, jw.y):
1426 prout(_(" damaged but not destroyed."))
1428 if game.quad[jw.x][jw.y]==IHBLANK:
1429 prout(_(" buffeted into black hole."))
1430 deadkl(w, iquad, jw)
1432 if game.quad[jw.x][jw.y]!=IHDOT:
1433 # can't move into object
1434 prout(_(" damaged but not destroyed."))
1436 proutn(_(" damaged--"))
1440 elif iquad == IHB: # Hit a base
1442 prout(_("***STARBASE DESTROYED.."))
1443 for ll in range(game.state.rembase):
1444 if game.state.baseq[ll] == game.quadrant:
1445 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1447 game.quad[w.x][w.y]=IHDOT
1448 game.state.rembase -= 1
1449 game.base.x=game.base.y=0
1450 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1451 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1452 game.state.basekl += 1
1455 elif iquad == IHP: # Hit a planet
1456 crmena(True, iquad, "sector", w)
1457 prout(_(" destroyed."))
1458 game.state.nplankl += 1
1459 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1460 game.iplnet.pclass = "destroyed"
1462 invalidate(game.plnet)
1463 game.quad[w.x][w.y] = IHDOT
1465 # captain perishes on planet
1468 elif iquad == IHW: # Hit an inhabited world -- very bad!
1469 crmena(True, iquad, "sector", w)
1470 prout(_(" destroyed."))
1471 game.state.nworldkl += 1
1472 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1473 game.iplnet.pclass = "destroyed"
1475 invalidate(game.plnet)
1476 game.quad[w.x][w.y] = IHDOT
1478 # captain perishes on planet
1480 prout(_("You have just destroyed an inhabited planet."))
1481 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1483 elif iquad == IHSTAR: # Hit a star
1487 crmena(True, IHSTAR, "sector", w)
1488 prout(_(" unaffected by photon blast."))
1490 elif iquad == IHQUEST: # Hit a thingy
1491 if not (game.options & OPTION_THINGY) or withprob(0.3):
1493 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1495 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1497 proutn(_("Mr. Spock-"))
1498 prouts(_(" \"Fascinating!\""))
1503 # Stas Sergeev added the possibility that
1504 # you can shove the Thingy and piss it off.
1505 # It then becomes an enemy and may fire at you.
1510 elif iquad == IHBLANK: # Black hole
1512 crmena(True, IHBLANK, "sector", w)
1513 prout(_(" swallows torpedo."))
1515 elif iquad == IHWEB: # hit the web
1517 prout(_("***Torpedo absorbed by Tholian web."))
1519 elif iquad == IHT: # Hit a Tholian
1520 h1 = 700.0 + randrange(100) - \
1521 1000.0 * distance(w, origin) * math.fabs(math.sin(bullseye-angle))
1524 game.quad[w.x][w.y] = IHDOT
1529 crmena(True, IHT, "sector", w)
1531 prout(_(" survives photon blast."))
1533 prout(_(" disappears."))
1534 game.tholian.move(None)
1535 game.quad[w.x][w.y] = IHWEB
1540 proutn("Don't know how to handle torpedo collision with ")
1541 crmena(True, iquad, "sector", w)
1545 if curwnd!=message_window:
1546 setwnd(message_window)
1548 game.quad[w.x][w.y]=IHDOT
1549 game.quad[jw.x][jw.y]=iquad
1550 prout(_(" displaced by blast to Sector %s ") % jw)
1551 for ll in range(len(game.enemies)):
1552 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector,game.enemies[ll].kloc)
1553 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1556 prout(_("Torpedo missed."))
1560 # critical-hit resolution
1561 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1563 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1564 proutn(_("***CRITICAL HIT--"))
1565 # Select devices and cause damage
1567 for loop1 in range(ncrit):
1570 # Cheat to prevent shuttle damage unless on ship
1571 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1574 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1575 game.damage[j] += extradm
1577 for (i, j) in enumerate(cdam):
1579 if skipcount % 3 == 2 and i < len(cdam)-1:
1584 prout(_(" damaged."))
1585 if damaged(DSHIELD) and game.shldup:
1586 prout(_("***Shields knocked down."))
1589 def attack(torps_ok):
1590 # bad guy attacks us
1591 # torps_ok == False forces use of phasers in an attack
1592 attempt = False; ihurt = False;
1593 hitmax=0.0; hittot=0.0; chgfac=1.0
1595 # game could be over at this point, check
1599 prout("=== ATTACK!")
1600 # Tholian gets to move before attacking
1603 # if you have just entered the RNZ, you'll get a warning
1604 if game.neutz: # The one chance not to be attacked
1607 # commanders get a chance to tac-move towards you
1608 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1610 # if no enemies remain after movement, we're done
1611 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1613 # set up partial hits if attack happens during shield status change
1614 pfac = 1.0/game.inshld
1616 chgfac = 0.25 + randreal(0.5)
1618 # message verbosity control
1619 if game.skill <= SKILL_FAIR:
1621 for enemy in game.enemies:
1622 if enemy.kpower < 0:
1623 continue; # too weak to attack
1624 # compute hit strength and diminish shield power
1626 # Increase chance of photon torpedos if docked or enemy energy is low
1627 if game.condition == "docked":
1629 if enemy.kpower < 500:
1631 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1633 # different enemies have different probabilities of throwing a torp
1634 usephasers = not torps_ok or \
1635 (enemy.type == IHK and r > 0.0005) or \
1636 (enemy.type==IHC and r > 0.015) or \
1637 (enemy.type==IHR and r > 0.3) or \
1638 (enemy.type==IHS and r > 0.07) or \
1639 (enemy.type==IHQUEST and r > 0.05)
1640 if usephasers: # Enemy uses phasers
1641 if game.condition == "docked":
1642 continue; # Don't waste the effort!
1643 attempt = True; # Attempt to attack
1644 dustfac = 0.8 + randreal(0.5)
1645 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1646 enemy.kpower *= 0.75
1647 else: # Enemy uses photon torpedo
1648 course = 1.90985*math.atan2(game.sector.y-enemy.kloc.y, enemy.kloc.x-game.sector.x)
1650 proutn(_("***TORPEDO INCOMING"))
1651 if not damaged(DSRSENS):
1653 crmena(False, enemy.type, where, enemy.kloc)
1656 dispersion = (randreal()+randreal())*0.5 - 0.5
1657 dispersion += 0.002*enemy.kpower*dispersion
1658 hit = torpedo(course, dispersion, origin=enemy.kloc, number=1, nburst=1)
1659 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1660 finish(FWON); # Klingons did themselves in!
1661 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1662 return # Supernova or finished
1665 # incoming phaser or torpedo, shields may dissipate it
1666 if game.shldup or game.shldchg or game.condition=="docked":
1667 # shields will take hits
1668 propor = pfac * game.shield
1669 if game.condition =="docked":
1673 hitsh = propor*chgfac*hit+1.0
1675 if absorb > game.shield:
1676 absorb = game.shield
1677 game.shield -= absorb
1679 # taking a hit blasts us out of a starbase dock
1680 if game.condition == "docked":
1682 # but the shields may take care of it
1683 if propor > 0.1 and hit < 0.005*game.energy:
1685 # hit from this opponent got through shields, so take damage
1687 proutn(_("%d unit hit") % int(hit))
1688 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1689 proutn(_(" on the "))
1691 if not damaged(DSRSENS) and usephasers:
1693 crmena(False, enemy.type, where, enemy.kloc)
1695 # Decide if hit is critical
1701 if game.energy <= 0:
1702 # Returning home upon your shield, not with it...
1705 if not attempt and game.condition == "docked":
1706 prout(_("***Enemies decide against attacking your ship."))
1707 percent = 100.0*pfac*game.shield+0.5
1709 # Shields fully protect ship
1710 proutn(_("Enemy attack reduces shield strength to "))
1712 # Print message if starship suffered hit(s)
1714 proutn(_("Energy left %2d shields ") % int(game.energy))
1717 elif not damaged(DSHIELD):
1720 proutn(_("damaged, "))
1721 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1722 # Check if anyone was hurt
1723 if hitmax >= 200 or hittot >= 500:
1724 icas = randrange(hittot * 0.015)
1727 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1728 prout(_(" in that last attack.\""))
1730 game.state.crew -= icas
1731 # After attack, reset average distance to enemies
1732 for enemy in game.enemies:
1733 enemy.kavgd = enemy.kdist
1734 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1737 def deadkl(w, type, mv):
1738 # kill a Klingon, Tholian, Romulan, or Thingy
1739 # Added mv to allow enemy to "move" before dying
1740 crmena(True, type, "sector", mv)
1741 # Decide what kind of enemy it is and update appropriately
1743 # chalk up a Romulan
1744 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1746 game.state.nromrem -= 1
1750 elif type == IHQUEST:
1755 # Some type of a Klingon
1756 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1759 game.comhere = False
1760 for i in range(game.state.remcom):
1761 if game.state.kcmdr[i] == game.quadrant:
1763 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1764 game.state.kcmdr[game.state.remcom].x = 0
1765 game.state.kcmdr[game.state.remcom].y = 0
1766 game.state.remcom -= 1
1768 if game.state.remcom != 0:
1769 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1770 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1773 game.state.remkl -= 1
1775 game.state.nscrem -= 1
1777 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1781 # For each kind of enemy, finish message to player
1782 prout(_(" destroyed."))
1783 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1786 # Remove enemy ship from arrays describing local conditions
1787 for e in game.enemies:
1794 # Return None if target is invalid
1795 if not VALID_SECTOR(w.x, w.y):
1798 deltx = 0.1*(w.y - game.sector.y)
1799 delty = 0.1*(w.x - game.sector.x)
1800 if deltx==0 and delty== 0:
1802 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1803 prout(_(" I recommend an immediate review of"))
1804 prout(_(" the Captain's psychological profile.\""))
1807 return 1.90985932*math.atan2(deltx, delty)
1810 # launch photon torpedo
1812 if damaged(DPHOTON):
1813 prout(_("Photon tubes damaged."))
1817 prout(_("No torpedoes left."))
1826 prout(_("%d torpedoes left.") % game.torps)
1827 proutn(_("Number of torpedoes to fire- "))
1829 else: # key == IHREAL {
1831 if n <= 0: # abort command
1836 prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
1844 for i in range(MAXBURST):
1845 targ.append(coord())
1848 if i==0 and key == IHEOL:
1849 break; # we will try prompting
1850 if i==1 and key == IHEOL:
1851 # direct all torpedoes at one target
1854 course[i] = course[0]
1866 course[i] = targetcheck(targ[i])
1867 if course[i] == None:
1870 if i == 1 and key == IHEOL:
1871 # prompt for each one
1873 proutn(_("Target sector for torpedo number %d- ") % (i+1))
1878 targ[i].x = int(aaitem-0.5)
1883 targ[i].y = int(aaitem-0.5)
1885 course[i] = targetcheck(targ[i])
1886 if course[i] == None:
1889 # Loop for moving <n> torpedoes
1891 if game.condition != "docked":
1893 dispersion = (randreal()+randreal())*0.5 -0.5
1894 if math.fabs(dispersion) >= 0.47:
1896 dispersion *= randreal(1.2, 2.2)
1898 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1900 prouts(_("***TORPEDO MISFIRES."))
1903 prout(_(" Remainder of burst aborted."))
1905 prout(_("***Photon tubes damaged by misfire."))
1906 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1908 if game.shldup or game.condition == "docked":
1909 dispersion *= 1.0 + 0.0001*game.shield
1910 torpedo(course[i], dispersion, origin=game.sector, number=i, nburst=n)
1911 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1913 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1917 # check for phasers overheating
1919 checkburn = (rpow-1500.0)*0.00038
1920 if withprob(checkburn):
1921 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1922 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1924 def checkshctrl(rpow):
1925 # check shield control
1928 prout(_("Shields lowered."))
1930 # Something bad has happened
1931 prouts(_("***RED ALERT! RED ALERT!"))
1933 hit = rpow*game.shield/game.inshld
1934 game.energy -= rpow+hit*0.8
1935 game.shield -= hit*0.2
1936 if game.energy <= 0.0:
1937 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1942 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1944 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1945 icas = randrange(hit*0.012)
1950 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1951 prout(_(" %d casualties so far.\"") % icas)
1953 game.state.crew -= icas
1955 prout(_("Phaser energy dispersed by shields."))
1956 prout(_("Enemy unaffected."))
1961 # register a phaser hit on Klingons and Romulans
1962 nenhr2 = game.nenhere; kk=0
1965 for (k, wham) in enumerate(hits):
1968 dustfac = randreal(0.9, 1.0)
1969 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1970 kpini = game.enemies[kk].kpower
1971 kp = math.fabs(kpini)
1972 if PHASEFAC*hit < kp:
1974 if game.enemies[kk].kpower < 0:
1975 game.enemies[kk].kpower -= -kp
1977 game.enemies[kk].kpower -= kp
1978 kpow = game.enemies[kk].kpower
1979 w = game.enemies[kk].kloc
1981 if not damaged(DSRSENS):
1983 proutn(_("%d unit hit on ") % int(hit))
1985 proutn(_("Very small hit on "))
1986 ienm = game.quad[w.x][w.y]
1989 crmena(False, ienm, "sector", w)
1993 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1997 kk -= 1 # don't do the increment
1999 else: # decide whether or not to emasculate klingon
2000 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2001 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2002 prout(_(" has just lost its firepower.\""))
2003 game.enemies[kk].kpower = -kpow
2010 kz = 0; k = 1; irec=0 # Cheating inhibitor
2011 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2015 # SR sensors and Computer are needed fopr automode
2016 if damaged(DSRSENS) or damaged(DCOMPTR):
2018 if game.condition == "docked":
2019 prout(_("Phasers can't be fired through base shields."))
2022 if damaged(DPHASER):
2023 prout(_("Phaser control damaged."))
2027 if damaged(DSHCTRL):
2028 prout(_("High speed shield control damaged."))
2031 if game.energy <= 200.0:
2032 prout(_("Insufficient energy to activate high-speed shield control."))
2035 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2037 # Original code so convoluted, I re-did it all
2038 # (That was Tom Almy talking about the C code, I think -- ESR)
2039 while automode=="NOTSET":
2044 prout(_("There is no enemy present to select."))
2047 automode="AUTOMATIC"
2051 elif isit("automatic"):
2052 if (not itarg) and game.nenhere != 0:
2053 automode = "FORCEMAN"
2056 prout(_("Energy will be expended into space."))
2057 automode = "AUTOMATIC"
2066 prout(_("Energy will be expended into space."))
2067 automode = "AUTOMATIC"
2069 automode = "FORCEMAN"
2071 automode = "AUTOMATIC"
2075 prout(_("Energy will be expended into space."))
2076 automode = "AUTOMATIC"
2078 automode = "FORCEMAN"
2080 proutn(_("Manual or automatic? "))
2085 if automode == "AUTOMATIC":
2086 if key == IHALPHA and isit("no"):
2089 if key != IHREAL and game.nenhere != 0:
2090 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2095 for i in range(game.nenhere):
2096 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2098 proutn(_("%d units required. ") % irec)
2100 proutn(_("Units to fire= "))
2106 proutn(_("Energy available= %.2f") % avail)
2109 if not rpow > avail:
2116 if key == IHALPHA and isit("no"):
2119 game.energy -= 200; # Go and do it!
2120 if checkshctrl(rpow):
2128 for i in range(game.nenhere):
2132 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2133 over = randreal(1.01, 1.06) * hits[i]
2135 powrem -= hits[i] + over
2136 if powrem <= 0 and temp < hits[i]:
2145 if extra > 0 and not game.alldone:
2147 proutn(_("*** Tholian web absorbs "))
2149 proutn(_("excess "))
2150 prout(_("phaser energy."))
2152 prout(_("%d expended on empty space.") % int(extra))
2153 elif automode == "FORCEMAN":
2156 if damaged(DCOMPTR):
2157 prout(_("Battle computer damaged, manual fire only."))
2160 prouts(_("---WORKING---"))
2162 prout(_("Short-range-sensors-damaged"))
2163 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2164 prout(_("Manual-fire-must-be-used"))
2166 elif automode == "MANUAL":
2168 for k in range(game.nenhere):
2169 aim = game.enemies[k].kloc
2170 ienm = game.quad[aim.x][aim.y]
2172 proutn(_("Energy available= %.2f") % (avail-0.006))
2176 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2177 (ienm == IHC or ienm == IHS):
2179 prout(_(" can't be located without short range scan."))
2182 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2187 if itarg and k > kz:
2188 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2191 if not damaged(DCOMPTR):
2196 proutn(_("units to fire at "))
2197 crmena(False, ienm, "sector", aim)
2200 if key == IHALPHA and isit("no"):
2208 if k==1: # Let me say I'm baffled by this
2217 # If total requested is too much, inform and start over
2219 prout(_("Available energy exceeded -- try again."))
2222 key = scan(); # scan for next value
2225 # zero energy -- abort
2228 if key == IHALPHA and isit("no"):
2233 game.energy -= 200.0
2234 if checkshctrl(rpow):
2238 # Say shield raised or malfunction, if necessary
2245 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2246 prouts(_(" CLICK CLICK POP . . ."))
2247 prout(_(" No response, sir!"))
2250 prout(_("Shields raised."))
2255 # Code from events,c begins here.
2257 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2258 # event of each type active at any given time. Mostly these means we can
2259 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2260 # BSD Trek, from which we swiped the idea, can have up to 5.
2262 def unschedule(evtype):
2263 # remove an event from the schedule
2264 game.future[evtype].date = FOREVER
2265 return game.future[evtype]
2267 def is_scheduled(evtype):
2268 # is an event of specified type scheduled
2269 return game.future[evtype].date != FOREVER
2271 def scheduled(evtype):
2272 # when will this event happen?
2273 return game.future[evtype].date
2275 def schedule(evtype, offset):
2276 # schedule an event of specified type
2277 game.future[evtype].date = game.state.date + offset
2278 return game.future[evtype]
2280 def postpone(evtype, offset):
2281 # postpone a scheduled event
2282 game.future[evtype].date += offset
2285 # rest period is interrupted by event
2288 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2290 game.resting = False
2296 # run through the event queue looking for things to do
2298 fintim = game.state.date + game.optime; yank=0
2299 ictbeam = False; istract = False
2300 w = coord(); hold = coord()
2301 ev = event(); ev2 = event()
2303 def tractorbeam(yank):
2304 # tractor beaming cases merge here
2306 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2310 prout(_(" caught in long range tractor beam--"))
2311 # If Kirk & Co. screwing around on planet, handle
2312 atover(True) # atover(true) is Grab
2315 if game.icraft: # Caught in Galileo?
2318 # Check to see if shuttle is aboard
2319 if game.iscraft == "offship":
2322 prout(_("Galileo, left on the planet surface, is captured"))
2323 prout(_("by aliens and made into a flying McDonald's."))
2324 game.damage[DSHUTTL] = -10
2325 game.iscraft = "removed"
2327 prout(_("Galileo, left on the planet surface, is well hidden."))
2329 game.quadrant = game.state.kscmdr
2331 game.quadrant = game.state.kcmdr[i]
2332 game.sector = randplace(QUADSIZE)
2334 prout(_(" is pulled to Quadrant %s, Sector %s") \
2335 % (game.quadrant, game.sector))
2337 prout(_("(Remainder of rest/repair period cancelled.)"))
2338 game.resting = False
2340 if not damaged(DSHIELD) and game.shield > 0:
2341 doshield(shraise=True) # raise shields
2342 game.shldchg = False
2344 prout(_("(Shields not currently useable.)"))
2346 # Adjust finish time to time of tractor beaming
2347 fintim = game.state.date+game.optime
2348 attack(torps_ok=False)
2349 if game.state.remcom <= 0:
2352 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2355 # Code merges here for any commander destroying base
2356 # Not perfect, but will have to do
2357 # Handle case where base is in same quadrant as starship
2358 if game.battle == game.quadrant:
2359 game.state.chart[game.battle.x][game.battle.y].starbase = False
2360 game.quad[game.base.x][game.base.y] = IHDOT
2361 game.base.x=game.base.y=0
2364 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2365 elif game.state.rembase != 1 and communicating():
2366 # Get word via subspace radio
2369 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2370 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2372 prout(_("the Klingon Super-Commander"))
2374 prout(_("a Klingon Commander"))
2375 game.state.chart[game.battle.x][game.battle.y].starbase = False
2376 # Remove Starbase from galaxy
2377 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2378 for i in range(1, game.state.rembase+1):
2379 if game.state.baseq[i] == game.battle:
2380 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2381 game.state.rembase -= 1
2383 # reinstate a commander's base attack
2387 invalidate(game.battle)
2390 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2391 for i in range(1, NEVENTS):
2392 if i == FSNOVA: proutn("=== Supernova ")
2393 elif i == FTBEAM: proutn("=== T Beam ")
2394 elif i == FSNAP: proutn("=== Snapshot ")
2395 elif i == FBATTAK: proutn("=== Base Attack ")
2396 elif i == FCDBAS: proutn("=== Base Destroy ")
2397 elif i == FSCMOVE: proutn("=== SC Move ")
2398 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2399 elif i == FDSPROB: proutn("=== Probe Move ")
2400 elif i == FDISTR: proutn("=== Distress Call ")
2401 elif i == FENSLV: proutn("=== Enslavement ")
2402 elif i == FREPRO: proutn("=== Klingon Build ")
2404 prout("%.2f" % (scheduled(i)))
2407 radio_was_broken = damaged(DRADIO)
2410 # Select earliest extraneous event, evcode==0 if no events
2415 for l in range(1, NEVENTS):
2416 if game.future[l].date < datemin:
2419 prout("== Event %d fires" % evcode)
2420 datemin = game.future[l].date
2421 xtime = datemin-game.state.date
2422 game.state.date = datemin
2423 # Decrement Federation resources and recompute remaining time
2424 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2426 if game.state.remtime <=0:
2429 # Any crew left alive?
2430 if game.state.crew <=0:
2433 # Is life support adequate?
2434 if damaged(DLIFSUP) and game.condition != "docked":
2435 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2438 game.lsupres -= xtime
2439 if game.damage[DLIFSUP] <= xtime:
2440 game.lsupres = game.inlsr
2443 if game.condition == "docked":
2444 repair /= game.docfac
2445 # Don't fix Deathray here
2446 for l in range(NDEVICES):
2447 if game.damage[l] > 0.0 and l != DDRAY:
2448 if game.damage[l]-repair > 0.0:
2449 game.damage[l] -= repair
2451 game.damage[l] = 0.0
2452 # If radio repaired, update star chart and attack reports
2453 if radio_was_broken and not damaged(DRADIO):
2454 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2455 prout(_(" surveillance reports are coming in."))
2457 if not game.iseenit:
2461 prout(_(" The star chart is now up to date.\""))
2463 # Cause extraneous event EVCODE to occur
2464 game.optime -= xtime
2465 if evcode == FSNOVA: # Supernova
2468 schedule(FSNOVA, expran(0.5*game.intime))
2469 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2471 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2472 if game.state.nscrem == 0 or \
2473 ictbeam or istract or \
2474 game.condition=="docked" or game.isatb==1 or game.iscate:
2476 if game.ientesc or \
2477 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2478 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2479 (damaged(DSHIELD) and \
2480 (game.energy < 2500 or damaged(DPHASER)) and \
2481 (game.torps < 5 or damaged(DPHOTON))):
2483 istract = ictbeam = True
2484 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2487 elif evcode == FTBEAM: # Tractor beam
2488 if game.state.remcom == 0:
2491 i = randrange(game.state.remcom)
2492 yank = distance(game.state.kcmdr[i], game.quadrant)
2493 if istract or game.condition == "docked" or yank == 0:
2494 # Drats! Have to reschedule
2496 game.optime + expran(1.5*game.intime/game.state.remcom))
2500 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2501 game.snapsht = copy.deepcopy(game.state)
2502 game.state.snap = True
2503 schedule(FSNAP, expran(0.5 * game.intime))
2504 elif evcode == FBATTAK: # Commander attacks starbase
2505 if game.state.remcom==0 or game.state.rembase==0:
2511 for j in range(game.state.rembase):
2512 for k in range(game.state.remcom):
2513 if game.state.baseq[j] == game.state.kcmdr[k] and \
2514 not game.state.baseq[j] == game.quadrant and \
2515 not game.state.baseq[j] == game.state.kscmdr:
2519 if j>game.state.rembase:
2520 # no match found -- try later
2521 schedule(FBATTAK, expran(0.3*game.intime))
2524 # commander + starbase combination found -- launch attack
2525 game.battle = game.state.baseq[j]
2526 schedule(FCDBAS, randreal(1.0, 4.0))
2527 if game.isatb: # extra time if SC already attacking
2528 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2529 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2530 game.iseenit = False
2531 if not communicating():
2532 continue # No warning :-(
2536 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2537 prout(_(" reports that it is under attack and that it can"))
2538 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2541 elif evcode == FSCDBAS: # Supercommander destroys base
2544 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2545 continue # WAS RETURN!
2547 game.battle = game.state.kscmdr
2549 elif evcode == FCDBAS: # Commander succeeds in destroying base
2552 # find the lucky pair
2553 for i in range(game.state.remcom):
2554 if game.state.kcmdr[i] == game.battle:
2556 if i > game.state.remcom or game.state.rembase == 0 or \
2557 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2558 # No action to take after all
2559 invalidate(game.battle)
2562 elif evcode == FSCMOVE: # Supercommander moves
2563 schedule(FSCMOVE, 0.2777)
2564 if not game.ientesc and not istract and game.isatb != 1 and \
2565 (not game.iscate or not game.justin):
2567 elif evcode == FDSPROB: # Move deep space probe
2568 schedule(FDSPROB, 0.01)
2569 game.probex += game.probeinx
2570 game.probey += game.probeiny
2571 i = (int)(game.probex/QUADSIZE +0.05)
2572 j = (int)(game.probey/QUADSIZE + 0.05)
2573 if game.probec.x != i or game.probec.y != j:
2576 if not VALID_QUADRANT(i, j) or \
2577 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2578 # Left galaxy or ran into supernova
2582 proutn(_("Lt. Uhura- \"The deep space probe "))
2583 if not VALID_QUADRANT(j, i):
2584 proutn(_("has left the galaxy"))
2586 proutn(_("is no longer transmitting"))
2590 if not communicating():
2593 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2594 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2595 # Update star chart if Radio is working or have access to radio
2597 chp = game.state.chart[game.probec.x][game.probec.y]
2598 chp.klingons = pdest.klingons
2599 chp.starbase = pdest.starbase
2600 chp.stars = pdest.stars
2601 pdest.charted = True
2602 game.proben -= 1 # One less to travel
2603 if game.proben == 0 and game.isarmed and pdest.stars:
2604 # lets blow the sucker!
2605 supernova(True, game.probec)
2607 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2609 elif evcode == FDISTR: # inhabited system issues distress call
2611 # try a whole bunch of times to find something suitable
2612 for i in range(100):
2613 # need a quadrant which is not the current one,
2614 # which has some stars which are inhabited and
2615 # not already under attack, which is not
2616 # supernova'ed, and which has some Klingons in it
2617 w = randplace(GALSIZE)
2618 q = game.state.galaxy[w.x][w.y]
2619 if not (game.quadrant == w or q.planet == None or \
2620 not q.planet.inhabited or \
2621 q.supernova or q.status!="secure" or q.klingons<=0):
2624 # can't seem to find one; ignore this call
2626 prout("=== Couldn't find location for distress event.")
2628 # got one!! Schedule its enslavement
2629 ev = schedule(FENSLV, expran(game.intime))
2631 q.status = distressed
2633 # tell the captain about it if we can
2635 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2637 prout(_("by a Klingon invasion fleet."))
2640 elif evcode == FENSLV: # starsystem is enslaved
2641 ev = unschedule(FENSLV)
2642 # see if current distress call still active
2643 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2647 q.status = "enslaved"
2649 # play stork and schedule the first baby
2650 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2651 ev2.quadrant = ev.quadrant
2653 # report the disaster if we can
2655 prout(_("Uhura- We've lost contact with starsystem %s") % \
2657 prout(_("in Quadrant %s.\n") % ev.quadrant)
2658 elif evcode == FREPRO: # Klingon reproduces
2659 # If we ever switch to a real event queue, we'll need to
2660 # explicitly retrieve and restore the x and y.
2661 ev = schedule(FREPRO, expran(1.0 * game.intime))
2662 # see if current distress call still active
2663 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2667 if game.state.remkl >=MAXKLGAME:
2668 continue # full right now
2669 # reproduce one Klingon
2671 if game.klhere >= MAXKLQUAD:
2673 # this quadrant not ok, pick an adjacent one
2674 for i in range(w.x - 1, w.x + 2):
2675 for j in range(w.y - 1, w.y + 2):
2676 if not VALID_QUADRANT(i, j):
2678 q = game.state.galaxy[w.x][w.y]
2679 # check for this quad ok (not full & no snova)
2680 if q.klingons >= MAXKLQUAD or q.supernova:
2684 continue # search for eligible quadrant failed
2689 game.state.remkl += 1
2691 if game.quadrant == w:
2693 game.enemies.append(newkling())
2694 # recompute time left
2696 # report the disaster if we can
2698 if game.quadrant == w:
2699 prout(_("Spock- sensors indicate the Klingons have"))
2700 prout(_("launched a warship from %s.") % q.planet)
2702 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2703 if q.planet != None:
2704 proutn(_("near %s") % q.planet)
2705 prout(_("in Quadrant %s.") % w)
2714 proutn(_("How long? "))
2719 origTime = delay = aaitem
2722 if delay >= game.state.remtime or game.nenhere != 0:
2723 proutn(_("Are you sure? "))
2726 # Alternate resting periods (events) with attacks
2730 game.resting = False
2731 if not game.resting:
2732 prout(_("%d stardates left.") % int(game.state.remtime))
2734 temp = game.optime = delay
2736 rtime = randreal(1.0, 2.0)
2740 if game.optime < delay:
2741 attack(torps_ok=False)
2749 # Repair Deathray if long rest at starbase
2750 if origTime-delay >= 9.99 and game.condition == "docked":
2751 game.damage[DDRAY] = 0.0
2752 # leave if quadrant supernovas
2753 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2755 game.resting = False
2758 # A nova occurs. It is the result of having a star hit with a
2759 # photon torpedo, or possibly of a probe warhead going off.
2760 # Stars that go nova cause stars which surround them to undergo
2761 # the same probabilistic process. Klingons next to them are
2762 # destroyed. And if the starship is next to it, it gets zapped.
2763 # If the zap is too much, it gets destroyed.
2767 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2768 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2770 # Wow! We've supernova'ed
2771 supernova(False, nov)
2773 # handle initial nova
2774 game.quad[nov.x][nov.y] = IHDOT
2775 crmena(False, IHSTAR, "sector", nov)
2777 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2778 game.state.starkl += 1
2779 # Set up queue to recursively trigger adjacent stars
2785 for offset.x in range(-1, 1+1):
2786 for offset.y in range(-1, 1+1):
2787 if offset.y==0 and offset.x==0:
2789 neighbor = start + offset
2790 if not VALID_SECTOR(neighbor.y, neighbor.x):
2792 iquad = game.quad[neighbor.x][neighbor.y]
2793 # Empty space ends reaction
2794 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2796 elif iquad == IHSTAR: # Affect another star
2798 # This star supernovas
2802 hits.append(neighbor)
2803 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2804 game.state.starkl += 1
2805 crmena(True, IHSTAR, "sector", neighbor)
2807 game.quad[neighbor.x][neighbor.y] = IHDOT
2809 elif iquad in (IHP, IHW): # Destroy planet
2810 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2812 game.state.nplankl += 1
2814 game.state.worldkl += 1
2815 crmena(True, iquad, "sector", neighbor)
2816 prout(_(" destroyed."))
2817 game.iplnet.pclass = "destroyed"
2819 invalidate(game.plnet)
2823 game.quad[neighbor.x][neighbor.y] = IHDOT
2824 elif iquad == IHB: # Destroy base
2825 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2826 for i in range(game.state.rembase):
2827 if game.state.baseq[i] == game.quadrant:
2829 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2830 game.state.rembase -= 1
2831 invalidate(game.base)
2832 game.state.basekl += 1
2834 crmena(True, IHB, "sector", neighbor)
2835 prout(_(" destroyed."))
2836 game.quad[neighbor.x][neighbor.y] = IHDOT
2837 elif iquad in (IHE, IHF): # Buffet ship
2838 prout(_("***Starship buffeted by nova."))
2840 if game.shield >= 2000.0:
2841 game.shield -= 2000.0
2843 diff = 2000.0 - game.shield
2847 prout(_("***Shields knocked out."))
2848 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2850 game.energy -= 2000.0
2851 if game.energy <= 0:
2854 # add in course nova contributes to kicking starship
2855 bump += (game.sector-hits[mm]).sgn()
2856 elif iquad == IHK: # kill klingon
2857 deadkl(neighbor, iquad, neighbor)
2858 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2859 for ll in range(game.nenhere):
2860 if game.enemies[ll].kloc == neighbor:
2862 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2863 if game.enemies[ll].kpower <= 0.0:
2864 deadkl(neighbor, iquad, neighbor)
2866 newc = neighbor + neighbor - hits[mm]
2867 crmena(True, iquad, "sector", neighbor)
2868 proutn(_(" damaged"))
2869 if not VALID_SECTOR(newc.x, newc.y):
2870 # can't leave quadrant
2873 iquad1 = game.quad[newc.x][newc.y]
2874 if iquad1 == IHBLANK:
2875 proutn(_(", blasted into "))
2876 crmena(False, IHBLANK, "sector", newc)
2878 deadkl(neighbor, iquad, newc)
2881 # can't move into something else
2884 proutn(_(", buffeted to Sector %s") % newc)
2885 game.quad[neighbor.x][neighbor.y] = IHDOT
2886 game.quad[newc.x][newc.y] = iquad
2887 game.enemies[ll].move(newc)
2888 # Starship affected by nova -- kick it away.
2889 game.dist = kount*0.1
2890 game.direc = course[3*(bump.x+1)+bump.y+2]
2891 if game.direc == 0.0:
2893 if game.dist == 0.0:
2895 game.optime = 10.0*game.dist/16.0
2897 prout(_("Force of nova displaces starship."))
2898 imove(novapush=True)
2899 game.optime = 10.0*game.dist/16.0
2902 def supernova(induced, w=None):
2903 # star goes supernova
2910 # Scheduled supernova -- select star
2911 # logic changed here so that we won't favor quadrants in top
2913 for nq.x in range(GALSIZE):
2914 for nq.y in range(GALSIZE):
2915 stars += game.state.galaxy[nq.x][nq.y].stars
2917 return # nothing to supernova exists
2918 num = randrange(stars) + 1
2919 for nq.x in range(GALSIZE):
2920 for nq.y in range(GALSIZE):
2921 num -= game.state.galaxy[nq.x][nq.y].stars
2927 proutn("=== Super nova here?")
2930 if not nq == game.quadrant or game.justin:
2931 # it isn't here, or we just entered (treat as enroute)
2934 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2935 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2938 # we are in the quadrant!
2939 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2940 for ns.x in range(QUADSIZE):
2941 for ns.y in range(QUADSIZE):
2942 if game.quad[ns.x][ns.y]==IHSTAR:
2949 prouts(_("***RED ALERT! RED ALERT!"))
2951 prout(_("***Incipient supernova detected at Sector %s") % ns)
2952 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2953 proutn(_("Emergency override attempts t"))
2954 prouts("***************")
2959 # destroy any Klingons in supernovaed quadrant
2960 kldead = game.state.galaxy[nq.x][nq.y].klingons
2961 game.state.galaxy[nq.x][nq.y].klingons = 0
2962 if nq == game.state.kscmdr:
2963 # did in the Supercommander!
2964 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2968 if game.state.remcom:
2969 maxloop = game.state.remcom
2970 for l in range(maxloop):
2971 if game.state.kcmdr[l] == nq:
2972 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
2973 invalidate(game.state.kcmdr[game.state.remcom])
2974 game.state.remcom -= 1
2976 if game.state.remcom==0:
2979 game.state.remkl -= kldead
2980 # destroy Romulans and planets in supernovaed quadrant
2981 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
2982 game.state.galaxy[nq.x][nq.y].romulans = 0
2983 game.state.nromrem -= nrmdead
2985 for loop in range(game.inplan):
2986 if game.state.planets[loop].w == nq:
2987 game.state.planets[loop].pclass = "destroyed"
2989 # Destroy any base in supernovaed quadrant
2990 if game.state.rembase:
2991 maxloop = game.state.rembase
2992 for loop in range(maxloop):
2993 if game.state.baseq[loop] == nq:
2994 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
2995 invalidate(game.state.baseq[game.state.rembase])
2996 game.state.rembase -= 1
2998 # If starship caused supernova, tally up destruction
3000 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3001 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3002 game.state.nplankl += npdead
3003 # mark supernova in galaxy and in star chart
3004 if game.quadrant == nq or communicating():
3005 game.state.galaxy[nq.x][nq.y].supernova = True
3006 # If supernova destroys last Klingons give special message
3007 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3010 prout(_("Lucky you!"))
3011 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3014 # if some Klingons remain, continue or die in supernova
3019 # Code from finish.c ends here.
3022 # self-destruct maneuver
3023 # Finish with a BANG!
3025 if damaged(DCOMPTR):
3026 prout(_("Computer damaged; cannot execute destruct sequence."))
3028 prouts(_("---WORKING---")); skip(1)
3029 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3030 prouts(" 10"); skip(1)
3031 prouts(" 9"); skip(1)
3032 prouts(" 8"); skip(1)
3033 prouts(" 7"); skip(1)
3034 prouts(" 6"); skip(1)
3036 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3038 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3040 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3044 if game.passwd != citem:
3045 prouts(_("PASSWORD-REJECTED;"))
3047 prouts(_("CONTINUITY-EFFECTED"))
3050 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3051 prouts(" 5"); skip(1)
3052 prouts(" 4"); skip(1)
3053 prouts(" 3"); skip(1)
3054 prouts(" 2"); skip(1)
3055 prouts(" 1"); skip(1)
3057 prouts(_("GOODBYE-CRUEL-WORLD"))
3065 prouts(_("********* Entropy of "))
3067 prouts(_(" maximized *********"))
3071 if game.nenhere != 0:
3072 whammo = 25.0 * game.energy
3074 while l <= game.nenhere:
3075 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3076 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3081 "Compute our rate of kils over time."
3082 elapsed = game.state.date - game.indate
3083 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3086 starting = (game.inkling + game.incom + game.inscom)
3087 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3088 return (starting - remaining)/elapsed
3092 badpt = 5.0*game.state.starkl + \
3094 10.0*game.state.nplankl + \
3095 300*game.state.nworldkl + \
3097 100.0*game.state.basekl +\
3099 if game.ship == IHF:
3101 elif game.ship == None:
3106 # end the game, with appropriate notfications
3110 prout(_("It is stardate %.1f.") % game.state.date)
3112 if ifin == FWON: # Game has been won
3113 if game.state.nromrem != 0:
3114 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3117 prout(_("You have smashed the Klingon invasion fleet and saved"))
3118 prout(_("the Federation."))
3123 badpt = 0.0 # Close enough!
3124 # killsPerDate >= RateMax
3125 if game.state.date-game.indate < 5.0 or \
3126 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3128 prout(_("In fact, you have done so well that Starfleet Command"))
3129 if game.skill == SKILL_NOVICE:
3130 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3131 elif game.skill == SKILL_FAIR:
3132 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3133 elif game.skill == SKILL_GOOD:
3134 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3135 elif game.skill == SKILL_EXPERT:
3136 prout(_("promotes you to Commodore Emeritus."))
3138 prout(_("Now that you think you're really good, try playing"))
3139 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3140 elif game.skill == SKILL_EMERITUS:
3142 proutn(_("Computer- "))
3143 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3145 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3147 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3149 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3151 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3153 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3155 prout(_("Now you can retire and write your own Star Trek game!"))
3157 elif game.skill >= SKILL_EXPERT:
3158 if game.thawed and not idebug:
3159 prout(_("You cannot get a citation, so..."))
3161 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3165 # Only grant long life if alive (original didn't!)
3167 prout(_("LIVE LONG AND PROSPER."))
3172 elif ifin == FDEPLETE: # Federation Resources Depleted
3173 prout(_("Your time has run out and the Federation has been"))
3174 prout(_("conquered. Your starship is now Klingon property,"))
3175 prout(_("and you are put on trial as a war criminal. On the"))
3176 proutn(_("basis of your record, you are "))
3177 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3178 prout(_("acquitted."))
3180 prout(_("LIVE LONG AND PROSPER."))
3182 prout(_("found guilty and"))
3183 prout(_("sentenced to death by slow torture."))
3187 elif ifin == FLIFESUP:
3188 prout(_("Your life support reserves have run out, and"))
3189 prout(_("you die of thirst, starvation, and asphyxiation."))
3190 prout(_("Your starship is a derelict in space."))
3192 prout(_("Your energy supply is exhausted."))
3194 prout(_("Your starship is a derelict in space."))
3195 elif ifin == FBATTLE:
3198 prout(_(" has been destroyed in battle."))
3200 prout(_("Dulce et decorum est pro patria mori."))
3202 prout(_("You have made three attempts to cross the negative energy"))
3203 prout(_("barrier which surrounds the galaxy."))
3205 prout(_("Your navigation is abominable."))
3208 prout(_("Your starship has been destroyed by a nova."))
3209 prout(_("That was a great shot."))
3211 elif ifin == FSNOVAED:
3214 prout(_(" has been fried by a supernova."))
3215 prout(_("...Not even cinders remain..."))
3216 elif ifin == FABANDN:
3217 prout(_("You have been captured by the Klingons. If you still"))
3218 prout(_("had a starbase to be returned to, you would have been"))
3219 prout(_("repatriated and given another chance. Since you have"))
3220 prout(_("no starbases, you will be mercilessly tortured to death."))
3221 elif ifin == FDILITHIUM:
3222 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3223 elif ifin == FMATERIALIZE:
3224 prout(_("Starbase was unable to re-materialize your starship."))
3225 prout(_("Sic transit gloria mundi"))
3226 elif ifin == FPHASER:
3229 prout(_(" has been cremated by its own phasers."))
3231 prout(_("You and your landing party have been"))
3232 prout(_("converted to energy, disipating through space."))
3233 elif ifin == FMINING:
3234 prout(_("You are left with your landing party on"))
3235 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3237 prout(_("They are very fond of \"Captain Kirk\" soup."))
3239 proutn(_("Without your leadership, the "))
3241 prout(_(" is destroyed."))
3242 elif ifin == FDPLANET:
3243 prout(_("You and your mining party perish."))
3245 prout(_("That was a great shot."))
3248 prout(_("The Galileo is instantly annihilated by the supernova."))
3249 prout(_("You and your mining party are atomized."))
3251 proutn(_("Mr. Spock takes command of the "))
3254 prout(_("joins the Romulans, reigning terror on the Federation."))
3255 elif ifin == FPNOVA:
3256 prout(_("You and your mining party are atomized."))
3258 proutn(_("Mr. Spock takes command of the "))
3261 prout(_("joins the Romulans, reigning terror on the Federation."))
3262 elif ifin == FSTRACTOR:
3263 prout(_("The shuttle craft Galileo is also caught,"))
3264 prout(_("and breaks up under the strain."))
3266 prout(_("Your debris is scattered for millions of miles."))
3267 proutn(_("Without your leadership, the "))
3269 prout(_(" is destroyed."))
3271 prout(_("The mutants attack and kill Spock."))
3272 prout(_("Your ship is captured by Klingons, and"))
3273 prout(_("your crew is put on display in a Klingon zoo."))
3274 elif ifin == FTRIBBLE:
3275 prout(_("Tribbles consume all remaining water,"))
3276 prout(_("food, and oxygen on your ship."))
3278 prout(_("You die of thirst, starvation, and asphyxiation."))
3279 prout(_("Your starship is a derelict in space."))
3281 prout(_("Your ship is drawn to the center of the black hole."))
3282 prout(_("You are crushed into extremely dense matter."))
3284 prout(_("Your last crew member has died."))
3285 if game.ship == IHF:
3287 elif game.ship == IHE:
3290 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3291 goodies = game.state.remres/game.inresor
3292 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3293 if goodies/baddies >= randreal(1.0, 1.5):
3294 prout(_("As a result of your actions, a treaty with the Klingon"))
3295 prout(_("Empire has been signed. The terms of the treaty are"))
3296 if goodies/baddies >= randreal(3.0):
3297 prout(_("favorable to the Federation."))
3299 prout(_("Congratulations!"))
3301 prout(_("highly unfavorable to the Federation."))
3303 prout(_("The Federation will be destroyed."))
3305 prout(_("Since you took the last Klingon with you, you are a"))
3306 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3307 prout(_("statue in your memory. Rest in peace, and try not"))
3308 prout(_("to think about pigeons."))
3313 # compute player's score
3314 timused = game.state.date - game.indate
3316 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3318 perdate = killrate()
3319 ithperd = 500*perdate + 0.5
3322 iwon = 100*game.skill
3323 if game.ship == IHE:
3325 elif game.ship == IHF:
3329 if not game.gamewon:
3330 game.state.nromrem = 0 # None captured if no win
3331 iscore = 10*(game.inkling - game.state.remkl) \
3332 + 50*(game.incom - game.state.remcom) \
3334 + 20*(game.inrom - game.state.nromrem) \
3335 + 200*(game.inscom - game.state.nscrem) \
3336 - game.state.nromrem \
3341 prout(_("Your score --"))
3342 if game.inrom - game.state.nromrem:
3343 prout(_("%6d Romulans destroyed %5d") %
3344 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3345 if game.state.nromrem:
3346 prout(_("%6d Romulans captured %5d") %
3347 (game.state.nromrem, game.state.nromrem))
3348 if game.inkling - game.state.remkl:
3349 prout(_("%6d ordinary Klingons destroyed %5d") %
3350 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3351 if game.incom - game.state.remcom:
3352 prout(_("%6d Klingon commanders destroyed %5d") %
3353 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3354 if game.inscom - game.state.nscrem:
3355 prout(_("%6d Super-Commander destroyed %5d") %
3356 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3358 prout(_("%6.2f Klingons per stardate %5d") %
3360 if game.state.starkl:
3361 prout(_("%6d stars destroyed by your action %5d") %
3362 (game.state.starkl, -5*game.state.starkl))
3363 if game.state.nplankl:
3364 prout(_("%6d planets destroyed by your action %5d") %
3365 (game.state.nplankl, -10*game.state.nplankl))
3366 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3367 prout(_("%6d inhabited planets destroyed by your action %5d") %
3368 (game.state.nplankl, -300*game.state.nworldkl))
3369 if game.state.basekl:
3370 prout(_("%6d bases destroyed by your action %5d") %
3371 (game.state.basekl, -100*game.state.basekl))
3373 prout(_("%6d calls for help from starbase %5d") %
3374 (game.nhelp, -45*game.nhelp))
3376 prout(_("%6d casualties incurred %5d") %
3377 (game.casual, -game.casual))
3379 prout(_("%6d crew abandoned in space %5d") %
3380 (game.abandoned, -3*game.abandoned))
3382 prout(_("%6d ship(s) lost or destroyed %5d") %
3383 (klship, -100*klship))
3385 prout(_("Penalty for getting yourself killed -200"))
3387 proutn(_("Bonus for winning "))
3388 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3389 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3390 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3391 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3392 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3393 prout(" %5d" % iwon)
3395 prout(_("TOTAL SCORE %5d") % iscore)
3398 # emit winner's commemmorative plaque
3401 proutn(_("File or device name for your plaque: "))
3404 fp = open(winner, "w")
3407 prout(_("Invalid name."))
3409 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3411 # The 38 below must be 64 for 132-column paper
3412 nskip = 38 - len(winner)/2
3413 fp.write("\n\n\n\n")
3414 # --------DRAW ENTERPRISE PICTURE.
3415 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3416 fp.write(" EEE E : : : E\n" )
3417 fp.write(" EE EEE E : : NCC-1701 : E\n")
3418 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3419 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3420 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3421 fp.write(" EEEEEEE EEEEE E E E E\n")
3422 fp.write(" EEE E E E E\n")
3423 fp.write(" E E E E\n")
3424 fp.write(" EEEEEEEEEEEEE E E\n")
3425 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3426 fp.write(" :E : EEEE E\n")
3427 fp.write(" .-E -:----- E\n")
3428 fp.write(" :E : E\n")
3429 fp.write(" EE : EEEEEEEE\n")
3430 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3432 fp.write(_(" U. S. S. ENTERPRISE\n"))
3433 fp.write("\n\n\n\n")
3434 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3436 fp.write(_(" Starfleet Command bestows to you\n"))
3438 fp.write("%*s%s\n\n" % (nskip, "", winner))
3439 fp.write(_(" the rank of\n\n"))
3440 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3442 if game.skill == SKILL_EXPERT:
3443 fp.write(_(" Expert level\n\n"))
3444 elif game.skill == SKILL_EMERITUS:
3445 fp.write(_("Emeritus level\n\n"))
3447 fp.write(_(" Cheat level\n\n"))
3448 timestring = ctime()
3449 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3450 (timestring+4, timestring+20, timestring+11))
3451 fp.write(_(" Your score: %d\n\n") % iscore)
3452 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3455 # Code from io.c begins here
3457 rows = linecount = 0 # for paging
3460 fullscreen_window = None
3461 srscan_window = None
3462 report_window = None
3463 status_window = None
3464 lrscan_window = None
3465 message_window = None
3466 prompt_window = None
3470 "wrap up, either normally or due to signal"
3471 if game.options & OPTION_CURSES:
3478 sys.stdout.write('\n')
3484 #setlocale(LC_ALL, "")
3485 #bindtextdomain(PACKAGE, LOCALEDIR)
3486 #textdomain(PACKAGE)
3487 if atexit.register(outro):
3488 sys.stderr.write("Unable to register outro(), exiting...\n")
3490 if not (game.options & OPTION_CURSES):
3491 ln_env = os.getenv("LINES")
3497 stdscr = curses.initscr()
3502 curses.start_color()
3503 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3504 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3505 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3506 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3507 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3508 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3509 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3510 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3512 global fullscreen_window, srscan_window, report_window, status_window
3513 global lrscan_window, message_window, prompt_window
3514 fullscreen_window = stdscr
3515 srscan_window = curses.newwin(12, 25, 0, 0)
3516 report_window = curses.newwin(11, 0, 1, 25)
3517 status_window = curses.newwin(10, 0, 1, 39)
3518 lrscan_window = curses.newwin(5, 0, 0, 64)
3519 message_window = curses.newwin(0, 0, 12, 0)
3520 prompt_window = curses.newwin(1, 0, rows-2, 0)
3521 message_window.scrollok(True)
3522 setwnd(fullscreen_window)
3526 "wait for user action -- OK to do nothing if on a TTY"
3527 if game.options & OPTION_CURSES:
3532 if game.skill > SKILL_FAIR:
3533 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3535 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3539 if game.skill > SKILL_FAIR:
3540 prompt = _("[CONTINUE?]")
3542 prompt = _("[PRESS ENTER TO CONTINUE]")
3544 if game.options & OPTION_CURSES:
3546 setwnd(prompt_window)
3547 prompt_window.wclear()
3548 prompt_window.addstr(prompt)
3549 prompt_window.getstr()
3550 prompt_window.clear()
3551 prompt_window.refresh()
3552 setwnd(message_window)
3555 sys.stdout.write('\n')
3558 for j in range(rows):
3559 sys.stdout.write('\n')
3563 "Skip i lines. Pause game if this would cause a scrolling event."
3564 for dummy in range(i):
3565 if game.options & OPTION_CURSES:
3566 (y, x) = curwnd.getyx()
3567 (my, mx) = curwnd.getmaxyx()
3568 if curwnd == message_window and y >= my - 3:
3576 if rows and linecount >= rows:
3579 sys.stdout.write('\n')
3582 "Utter a line with no following line feed."
3583 if game.options & OPTION_CURSES:
3587 sys.stdout.write(line)
3597 if not replayfp or replayfp.closed: # Don't slow down replays
3600 if game.options & OPTION_CURSES:
3604 if not replayfp or replayfp.closed:
3608 "Get a line of input."
3609 if game.options & OPTION_CURSES:
3610 line = curwnd.getstr() + "\n"
3613 if replayfp and not replayfp.closed:
3615 line = replayfp.readline()
3618 prout("*** Replay finished")
3621 elif line[0] != "#":
3624 line = raw_input() + "\n"
3630 "Change windows -- OK for this to be a no-op in tty mode."
3632 if game.options & OPTION_CURSES:
3634 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3637 "Clear to end of line -- can be a no-op in tty mode"
3638 if game.options & OPTION_CURSES:
3643 "Clear screen -- can be a no-op in tty mode."
3645 if game.options & OPTION_CURSES:
3651 def textcolor(color):
3652 "Set the current text color"
3653 if game.options & OPTION_CURSES:
3654 if color == DEFAULT:
3656 elif color == BLACK:
3657 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3659 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3660 elif color == GREEN:
3661 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3663 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3665 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3666 elif color == MAGENTA:
3667 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3668 elif color == BROWN:
3669 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3670 elif color == LIGHTGRAY:
3671 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3672 elif color == DARKGRAY:
3673 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3674 elif color == LIGHTBLUE:
3675 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3676 elif color == LIGHTGREEN:
3677 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3678 elif color == LIGHTCYAN:
3679 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3680 elif color == LIGHTRED:
3681 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3682 elif color == LIGHTMAGENTA:
3683 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3684 elif color == YELLOW:
3685 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3686 elif color == WHITE:
3687 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3690 "Set highlight video, if this is reasonable."
3691 if game.options & OPTION_CURSES:
3692 curwnd.attron(curses.A_REVERSE)
3695 # Things past this point have policy implications.
3699 "Hook to be called after moving to redraw maps."
3700 if game.options & OPTION_CURSES:
3703 setwnd(srscan_window)
3707 setwnd(status_window)
3708 status_window.clear()
3709 status_window.move(0, 0)
3710 setwnd(report_window)
3711 report_window.clear()
3712 report_window.move(0, 0)
3714 setwnd(lrscan_window)
3715 lrscan_window.clear()
3716 lrscan_window.move(0, 0)
3717 lrscan(silent=False)
3719 def put_srscan_sym(w, sym):
3720 "Emit symbol for short-range scan."
3721 srscan_window.move(w.x+1, w.y*2+2)
3722 srscan_window.addch(sym)
3723 srscan_window.refresh()
3726 "Enemy fall down, go boom."
3727 if game.options & OPTION_CURSES:
3729 setwnd(srscan_window)
3730 srscan_window.attron(curses.A_REVERSE)
3731 put_srscan_sym(w, game.quad[w.x][w.y])
3735 srscan_window.attroff(curses.A_REVERSE)
3736 put_srscan_sym(w, game.quad[w.x][w.y])
3737 curses.delay_output(500)
3738 setwnd(message_window)
3741 "Sound and visual effects for teleportation."
3742 if game.options & OPTION_CURSES:
3744 setwnd(message_window)
3746 prouts(" . . . . . ")
3747 if game.options & OPTION_CURSES:
3748 #curses.delay_output(1000)
3752 def tracktorpedo(w, step, i, n, iquad):
3753 "Torpedo-track animation."
3754 if not game.options & OPTION_CURSES:
3758 proutn(_("Track for torpedo number %d- ") % i)
3761 proutn(_("Torpedo track- "))
3762 elif step==4 or step==9:
3766 if not damaged(DSRSENS) or game.condition=="docked":
3767 if i != 0 and step == 1:
3770 if (iquad==IHDOT) or (iquad==IHBLANK):
3771 put_srscan_sym(w, '+')
3775 put_srscan_sym(w, iquad)
3777 curwnd.attron(curses.A_REVERSE)
3778 put_srscan_sym(w, iquad)
3782 curwnd.attroff(curses.A_REVERSE)
3783 put_srscan_sym(w, iquad)
3788 "Display the current galaxy chart."
3789 if game.options & OPTION_CURSES:
3790 setwnd(message_window)
3791 message_window.clear()
3793 if game.options & OPTION_TTY:
3798 def prstat(txt, data):
3800 if game.options & OPTION_CURSES:
3802 setwnd(status_window)
3804 proutn(" " * (NSYM - len(txt)))
3807 if game.options & OPTION_CURSES:
3808 setwnd(report_window)
3810 # Code from moving.c begins here
3812 def imove(novapush):
3813 # movement execution for warp, impulse, supernova, and tractor-beam events
3814 w = coord(); final = coord()
3817 def no_quad_change():
3818 # No quadrant change -- compute new average enemy distances
3819 game.quad[game.sector.x][game.sector.y] = game.ship
3821 for m in range(game.nenhere):
3822 finald = distance(w, game.enemies[m].kloc)
3823 game.enemies[m].kavgd = 0.5 * (finald+game.enemies[m].kdist)
3824 game.enemies[m].kdist = finald
3825 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3826 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3827 attack(torps_ok=False)
3828 for m in range(game.nenhere):
3829 game.enemies[m].kavgd = game.enemies[m].kdist
3832 setwnd(message_window)
3835 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3836 game.inorbit = False
3837 angle = ((15.0 - game.direc) * 0.5235988)
3838 deltax = -math.sin(angle)
3839 deltay = math.cos(angle)
3840 if math.fabs(deltax) > math.fabs(deltay):
3841 bigger = math.fabs(deltax)
3843 bigger = math.fabs(deltay)
3846 # If tractor beam is to occur, don't move full distance
3847 if game.state.date+game.optime >= scheduled(FTBEAM):
3849 game.condition = "red"
3850 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3851 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3852 # Move within the quadrant
3853 game.quad[game.sector.x][game.sector.y] = IHDOT
3856 n = int(10.0*game.dist*bigger+0.5)
3858 for m in range(1, n+1):
3863 if not VALID_SECTOR(w.x, w.y):
3864 # Leaving quadrant -- allow final enemy attack
3865 # Don't do it if being pushed by Nova
3866 if game.nenhere != 0 and not novapush:
3868 for m in range(game.nenhere):
3869 finald = distance(w, game.enemies[m].kloc)
3870 game.enemies[m].kavgd = 0.5 * (finald + game.enemies[m].kdist)
3872 # Stas Sergeev added the condition
3873 # that attacks only happen if Klingons
3874 # are present and your skill is good.
3876 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3877 attack(torps_ok=False)
3880 # compute final position -- new quadrant and sector
3881 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3882 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3883 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3884 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3885 # check for edge of galaxy
3895 if w.x >= GALSIZE*QUADSIZE:
3896 w.x = (GALSIZE*QUADSIZE*2) - w.x
3898 if w.y >= GALSIZE*QUADSIZE:
3899 w.y = (GALSIZE*QUADSIZE*2) - w.y
3907 if game.nkinks == 3:
3908 # Three strikes -- you're out!
3912 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3913 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3914 prout(_("YOU WILL BE DESTROYED."))
3915 # Compute final position in new quadrant
3916 if trbeam: # Don't bother if we are to be beamed
3918 game.quadrant.x = w.x/QUADSIZE
3919 game.quadrant.y = w.y/QUADSIZE
3920 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3921 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3923 prout(_("Entering Quadrant %s.") % game.quadrant)
3924 game.quad[game.sector.x][game.sector.y] = game.ship
3926 if game.skill>SKILL_NOVICE:
3927 attack(torps_ok=False)
3929 iquad = game.quad[w.x][w.y]
3931 # object encountered in flight path
3932 stopegy = 50.0*game.dist/game.optime
3933 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3934 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3936 for enemy in game.enemies:
3937 if enemy.kloc == game.sector:
3939 collision(rammed=False, enemy=enemy)
3941 elif iquad == IHBLANK:
3943 prouts(_("***RED ALERT! RED ALERT!"))
3947 proutn(_(" pulled into black hole at Sector %s") % w)
3949 # Getting pulled into a black hole was certain
3950 # death in Almy's original. Stas Sergeev added a
3951 # possibility that you'll get timewarped instead.
3954 for m in range(NDEVICES):
3955 if game.damage[m]>0:
3957 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3958 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3968 proutn(_(" encounters Tholian web at %s;") % w)
3970 proutn(_(" blocked by object at %s;") % w)
3971 proutn(_("Emergency stop required "))
3972 prout(_("%2d units of energy.") % int(stopegy))
3973 game.energy -= stopegy
3974 final.x = x-deltax+0.5
3975 final.y = y-deltay+0.5
3977 if game.energy <= 0:
3983 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3990 # dock our ship at a starbase
3992 if game.condition == "docked" and verbose:
3993 prout(_("Already docked."))
3996 prout(_("You must first leave standard orbit."))
3998 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4000 prout(_(" not adjacent to base."))
4002 game.condition = "docked"
4006 if game.energy < game.inenrg:
4007 game.energy = game.inenrg
4008 game.shield = game.inshld
4009 game.torps = game.intorps
4010 game.lsupres = game.inlsr
4011 game.state.crew = FULLCREW
4012 if not damaged(DRADIO) and \
4013 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4014 # get attack report from base
4015 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4019 # This program originally required input in terms of a (clock)
4020 # direction and distance. Somewhere in history, it was changed to
4021 # cartesian coordinates. So we need to convert. Probably
4022 # "manual" input should still be done this way -- it's a real
4023 # pain if the computer isn't working! Manual mode is still confusing
4024 # because it involves giving x and y motions, yet the coordinates
4025 # are always displayed y - x, where +y is downward!
4027 def getcourse(isprobe, akey):
4028 # get course and distance
4030 dquad = copy.copy(game.quadrant)
4031 navmode = "unspecified"
4035 if game.landed and not isprobe:
4036 prout(_("Dummy! You can't leave standard orbit until you"))
4037 proutn(_("are back aboard the ship."))
4040 while navmode == "unspecified":
4041 if damaged(DNAVSYS):
4043 prout(_("Computer damaged; manual navigation only"))
4045 prout(_("Computer damaged; manual movement only"))
4050 if isprobe and akey != -1:
4051 # For probe launch, use pre-scanned value first time
4057 proutn(_("Manual or automatic- "))
4060 elif key == IHALPHA:
4065 elif isit("automatic"):
4066 navmode = "automatic"
4075 prout(_("(Manual navigation assumed.)"))
4077 prout(_("(Manual movement assumed.)"))
4080 if navmode == "automatic":
4083 proutn(_("Target quadrant or quadrant§or- "))
4085 proutn(_("Destination sector or quadrant§or- "))
4092 xi = int(round(aaitem))-1
4097 xj = int(round(aaitem))-1
4100 # both quadrant and sector specified
4101 xk = int(round(aaitem))-1
4106 xl = int(round(aaitem))-1
4112 # only one pair of numbers was specified
4114 # only quadrant specified -- go to center of dest quad
4117 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4119 # only sector specified
4123 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4130 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4132 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4133 # the actual deltas get computed here
4134 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4135 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4138 proutn(_("X and Y displacements- "))
4152 # Check for zero movement
4153 if deltax == 0 and deltay == 0:
4156 if itemp == "verbose" and not isprobe:
4158 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4159 # Course actually laid in.
4160 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4161 game.direc = math.atan2(deltax, deltay)*1.90985932
4162 if game.direc < 0.0:
4168 # move under impulse power
4170 if damaged(DIMPULS):
4173 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4175 if game.energy > 30.0:
4176 if not getcourse(isprobe=False, akey=0):
4178 power = 20.0 + 100.0*game.dist
4181 if power >= game.energy:
4182 # Insufficient power for trip
4184 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4185 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4186 if game.energy > 30:
4187 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4188 int(0.01 * (game.energy-20.0)-0.05))
4189 prout(_(" quadrants.\""))
4191 prout(_("quadrant. They are, therefore, useless.\""))
4194 # Make sure enough time is left for the trip
4195 game.optime = game.dist/0.095
4196 if game.optime >= game.state.remtime:
4197 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4198 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4199 proutn(_("we dare spend the time?\" "))
4202 # Activate impulse engines and pay the cost
4203 imove(novapush=False)
4207 power = 20.0 + 100.0*game.dist
4208 game.energy -= power
4209 game.optime = game.dist/0.095
4210 if game.energy <= 0:
4215 # move under warp drive
4216 blooey = False; twarp = False
4217 if not timewarp: # Not WARPX entry
4219 if game.damage[DWARPEN] > 10.0:
4222 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4224 if damaged(DWARPEN) and game.warpfac > 4.0:
4227 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4228 prout(_(" is repaired, I can only give you warp 4.\""))
4230 # Read in course and distance
4231 if not getcourse(isprobe=False, akey=0):
4233 # Make sure starship has enough energy for the trip
4234 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4235 if power >= game.energy:
4236 # Insufficient power for trip
4239 prout(_("Engineering to bridge--"))
4240 if not game.shldup or 0.5*power > game.energy:
4241 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4243 prout(_("We can't do it, Captain. We don't have enough energy."))
4245 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4248 prout(_("if you'll lower the shields."))
4252 prout(_("We haven't the energy to go that far with the shields up."))
4255 # Make sure enough time is left for the trip
4256 game.optime = 10.0*game.dist/game.wfacsq
4257 if game.optime >= 0.8*game.state.remtime:
4259 prout(_("First Officer Spock- \"Captain, I compute that such"))
4260 proutn(_(" a trip would require approximately %2.0f") %
4261 (100.0*game.optime/game.state.remtime))
4262 prout(_(" percent of our"))
4263 proutn(_(" remaining time. Are you sure this is wise?\" "))
4269 if game.warpfac > 6.0:
4270 # Decide if engine damage will occur
4271 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4272 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4273 if prob > randreal():
4275 game.dist = randreal(game.dist)
4276 # Decide if time warp will occur
4277 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4279 if idebug and game.warpfac==10 and not twarp:
4281 proutn("=== Force time warp? ")
4285 # If time warp or engine damage, check path
4286 # If it is obstructed, don't do warp or damage
4287 angle = ((15.0-game.direc)*0.5235998)
4288 deltax = -math.sin(angle)
4289 deltay = math.cos(angle)
4290 if math.fabs(deltax) > math.fabs(deltay):
4291 bigger = math.fabs(deltax)
4293 bigger = math.fabs(deltay)
4297 n = 10.0 * game.dist * bigger +0.5
4300 for l in range(1, n+1):
4305 if not VALID_SECTOR(ix, iy):
4307 if game.quad[ix][iy] != IHDOT:
4310 # Activate Warp Engines and pay the cost
4311 imove(novapush=False)
4314 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4315 if game.energy <= 0:
4317 game.optime = 10.0*game.dist/game.wfacsq
4321 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4323 prout(_("Engineering to bridge--"))
4324 prout(_(" Scott here. The warp engines are damaged."))
4325 prout(_(" We'll have to reduce speed to warp 4."))
4330 # change the warp factor
4336 proutn(_("Warp factor- "))
4341 if game.damage[DWARPEN] > 10.0:
4342 prout(_("Warp engines inoperative."))
4344 if damaged(DWARPEN) and aaitem > 4.0:
4345 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4346 prout(_(" but right now we can only go warp 4.\""))
4349 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4352 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4354 oldfac = game.warpfac
4355 game.warpfac = aaitem
4356 game.wfacsq=game.warpfac*game.warpfac
4357 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4358 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4361 if game.warpfac < 8.00:
4362 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4364 if game.warpfac == 10.0:
4365 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4367 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4371 # cope with being tossed out of quadrant by supernova or yanked by beam
4373 # is captain on planet?
4375 if damaged(DTRANSP):
4378 prout(_("Scotty rushes to the transporter controls."))
4380 prout(_("But with the shields up it's hopeless."))
4382 prouts(_("His desperate attempt to rescue you . . ."))
4387 prout(_("SUCCEEDS!"))
4390 proutn(_("The crystals mined were "))
4398 # Check to see if captain in shuttle craft
4403 # Inform captain of attempt to reach safety
4407 prouts(_("***RED ALERT! RED ALERT!"))
4411 prout(_(" has stopped in a quadrant containing"))
4412 prouts(_(" a supernova."))
4414 proutn(_("***Emergency automatic override attempts to hurl "))
4417 prout(_("safely out of quadrant."))
4418 if not damaged(DRADIO):
4419 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4420 # Try to use warp engines
4421 if damaged(DWARPEN):
4423 prout(_("Warp engines damaged."))
4426 game.warpfac = randreal(6.0, 8.0)
4427 game.wfacsq = game.warpfac * game.warpfac
4428 prout(_("Warp factor set to %d") % int(game.warpfac))
4429 power = 0.75*game.energy
4430 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4431 distreq = randreal(math.sqrt(2))
4432 if distreq < game.dist:
4434 game.optime = 10.0*game.dist/game.wfacsq
4435 game.direc = randreal(12) # How dumb!
4437 game.inorbit = False
4440 # This is bad news, we didn't leave quadrant.
4444 prout(_("Insufficient energy to leave quadrant."))
4447 # Repeat if another snova
4448 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4450 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4451 finish(FWON) # Snova killed remaining enemy.
4454 # let's do the time warp again
4455 prout(_("***TIME WARP ENTERED."))
4456 if game.state.snap and withprob(0.5):
4458 prout(_("You are traveling backwards in time %d stardates.") %
4459 int(game.state.date-game.snapsht.date))
4460 game.state = game.snapsht
4461 game.state.snap = False
4462 if game.state.remcom:
4463 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4464 schedule(FBATTAK, expran(0.3*game.intime))
4465 schedule(FSNOVA, expran(0.5*game.intime))
4466 # next snapshot will be sooner
4467 schedule(FSNAP, expran(0.25*game.state.remtime))
4469 if game.state.nscrem:
4470 schedule(FSCMOVE, 0.2777)
4474 invalidate(game.battle)
4476 # Make sure Galileo is consistant -- Snapshot may have been taken
4477 # when on planet, which would give us two Galileos!
4479 for l in range(game.inplan):
4480 if game.state.planets[l].known == "shuttle_down":
4482 if game.iscraft == "onship" and game.ship==IHE:
4483 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4484 game.iscraft = "offship"
4485 # Likewise, if in the original time the Galileo was abandoned, but
4486 # was on ship earlier, it would have vanished -- let's restore it.
4487 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4488 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4489 game.iscraft = "onship"
4491 # * There used to be code to do the actual reconstrction here,
4492 # * but the starchart is now part of the snapshotted galaxy state.
4494 prout(_("Spock has reconstructed a correct star chart from memory"))
4496 # Go forward in time
4497 game.optime = -0.5*game.intime*math.log(randreal())
4498 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4499 # cheat to make sure no tractor beams occur during time warp
4500 postpone(FTBEAM, game.optime)
4501 game.damage[DRADIO] += game.optime
4503 events() # Stas Sergeev added this -- do pending events
4506 # launch deep-space probe
4507 # New code to launch a deep space probe
4508 if game.nprobes == 0:
4511 if game.ship == IHE:
4512 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4514 prout(_("Ye Faerie Queene has no deep space probes."))
4519 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4521 if is_scheduled(FDSPROB):
4524 if damaged(DRADIO) and game.condition != "docked":
4525 prout(_("Spock- \"Records show the previous probe has not yet"))
4526 prout(_(" reached its destination.\""))
4528 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4532 # slow mode, so let Kirk know how many probes there are left
4533 if game.nprobes == 1:
4534 prout(_("1 probe left."))
4536 prout(_("%d probes left") % game.nprobes)
4537 proutn(_("Are you sure you want to fire a probe? "))
4540 game.isarmed = False
4541 if key == IHALPHA and citem == "armed":
4545 proutn(_("Arm NOVAMAX warhead? "))
4547 if not getcourse(isprobe=True, akey=key):
4550 angle = ((15.0 - game.direc) * 0.5235988)
4551 game.probeinx = -math.sin(angle)
4552 game.probeiny = math.cos(angle)
4553 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4554 bigger = math.fabs(game.probeinx)
4556 bigger = math.fabs(game.probeiny)
4557 game.probeiny /= bigger
4558 game.probeinx /= bigger
4559 game.proben = 10.0*game.dist*bigger +0.5
4560 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4561 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4562 game.probec = game.quadrant
4563 schedule(FDSPROB, 0.01) # Time to move one sector
4564 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4568 # Here's how the mayday code works:
4570 # First, the closest starbase is selected. If there is a a starbase
4571 # in your own quadrant, you are in good shape. This distance takes
4572 # quadrant distances into account only.
4574 # A magic number is computed based on the distance which acts as the
4575 # probability that you will be rematerialized. You get three tries.
4577 # When it is determined that you should be able to be rematerialized
4578 # (i.e., when the probability thing mentioned above comes up
4579 # positive), you are put into that quadrant (anywhere). Then, we try
4580 # to see if there is a spot adjacent to the star- base. If not, you
4581 # can't be rematerialized!!! Otherwise, it drops you there. It only
4582 # tries five times to find a spot to drop you. After that, it's your
4586 # yell for help from nearest starbase
4587 # There's more than one way to move in this game!
4590 # Test for conditions which prevent calling for help
4591 if game.condition == "docked":
4592 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4595 prout(_("Subspace radio damaged."))
4597 if game.state.rembase==0:
4598 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4601 proutn(_("You must be aboard the "))
4605 # OK -- call for help from nearest starbase
4608 # There's one in this quadrant
4609 ddist = distance(game.base, game.sector)
4612 for m in range(game.state.rembase):
4613 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4617 # Since starbase not in quadrant, set up new quadrant
4618 game.quadrant = game.state.baseq[line]
4620 # dematerialize starship
4621 game.quad[game.sector.x][game.sector.y]=IHDOT
4622 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4624 prout(_(" dematerializes."))
4626 for m in range(1, 5+1):
4627 w = game.base.scatter()
4628 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4629 # found one -- finish up
4632 if not is_valid(game.sector):
4633 prout(_("You have been lost in space..."))
4634 finish(FMATERIALIZE)
4636 # Give starbase three chances to rematerialize starship
4637 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4638 for m in range(1, 3+1):
4639 if m == 1: proutn(_("1st"))
4640 elif m == 2: proutn(_("2nd"))
4641 elif m == 3: proutn(_("3rd"))
4642 proutn(_(" attempt to re-materialize "))
4644 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4647 if randreal() > probf:
4650 curses.delay_output(500)
4653 game.quad[ix][iy]=IHQUEST
4656 setwnd(message_window)
4657 finish(FMATERIALIZE)
4659 game.quad[ix][iy]=game.ship
4661 prout(_("succeeds."))
4665 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4667 # Abandon Ship (the BSD-Trek description)
4669 # The ship is abandoned. If your current ship is the Faire
4670 # Queene, or if your shuttlecraft is dead, you're out of
4671 # luck. You need the shuttlecraft in order for the captain
4672 # (that's you!!) to escape.
4674 # Your crew can beam to an inhabited starsystem in the
4675 # quadrant, if there is one and if the transporter is working.
4676 # If there is no inhabited starsystem, or if the transporter
4677 # is out, they are left to die in outer space.
4679 # If there are no starbases left, you are captured by the
4680 # Klingons, who torture you mercilessly. However, if there
4681 # is at least one starbase, you are returned to the
4682 # Federation in a prisoner of war exchange. Of course, this
4683 # can't happen unless you have taken some prisoners.
4688 if game.condition=="docked":
4690 prout(_("You cannot abandon Ye Faerie Queene."))
4693 # Must take shuttle craft to exit
4694 if game.damage[DSHUTTL]==-1:
4695 prout(_("Ye Faerie Queene has no shuttle craft."))
4697 if game.damage[DSHUTTL]<0:
4698 prout(_("Shuttle craft now serving Big Macs."))
4700 if game.damage[DSHUTTL]>0:
4701 prout(_("Shuttle craft damaged."))
4704 prout(_("You must be aboard the ship."))
4706 if game.iscraft != "onship":
4707 prout(_("Shuttle craft not currently available."))
4709 # Print abandon ship messages
4711 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4713 prouts(_("***ALL HANDS ABANDON SHIP!"))
4715 prout(_("Captain and crew escape in shuttle craft."))
4716 if game.state.rembase==0:
4717 # Oops! no place to go...
4720 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4722 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4723 prout(_("Remainder of ship's complement beam down"))
4724 prout(_("to nearest habitable planet."))
4725 elif q.planet != None and not damaged(DTRANSP):
4726 prout(_("Remainder of ship's complement beam down to %s.") %
4729 prout(_("Entire crew of %d left to die in outer space.") %
4731 game.casual += game.state.crew
4732 game.abandoned += game.state.crew
4734 # If at least one base left, give 'em the Faerie Queene
4736 game.icrystl = False # crystals are lost
4737 game.nprobes = 0 # No probes
4738 prout(_("You are captured by Klingons and released to"))
4739 prout(_("the Federation in a prisoner-of-war exchange."))
4740 nb = randrange(game.state.rembase)
4741 # Set up quadrant and position FQ adjacient to base
4742 if not game.quadrant == game.state.baseq[nb]:
4743 game.quadrant = game.state.baseq[nb]
4744 game.sector.x = game.sector.y = 5
4747 # position next to base by trial and error
4748 game.quad[game.sector.x][game.sector.y] = IHDOT
4749 for l in range(QUADSIZE):
4750 game.sector = game.base.scatter()
4751 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4752 game.quad[game.sector.x][game.sector.y] == IHDOT:
4755 break # found a spot
4756 game.sector.x=QUADSIZE/2
4757 game.sector.y=QUADSIZE/2
4759 # Get new commission
4760 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4761 game.state.crew = FULLCREW
4762 prout(_("Starfleet puts you in command of another ship,"))
4763 prout(_("the Faerie Queene, which is antiquated but,"))
4764 prout(_("still useable."))
4766 prout(_("The dilithium crystals have been moved."))
4768 game.iscraft = "offship" # Galileo disappears
4770 game.condition="docked"
4771 for l in range(NDEVICES):
4772 game.damage[l] = 0.0
4773 game.damage[DSHUTTL] = -1
4774 game.energy = game.inenrg = 3000.0
4775 game.shield = game.inshld = 1250.0
4776 game.torps = game.intorps = 6
4777 game.lsupres=game.inlsr=3.0
4783 # Code from planets.c begins here.
4786 # abort a lengthy operation if an event interrupts it
4789 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4794 # report on (uninhabited) planets in the galaxy
4798 prout(_("Spock- \"Planet report follows, Captain.\""))
4800 for i in range(game.inplan):
4801 if game.state.planets[i].pclass == "destroyed":
4803 if (game.state.planets[i].known != "unknown" \
4804 and not game.state.planets[i].inhabited) \
4807 if idebug and game.state.planets[i].known=="unknown":
4808 proutn("(Unknown) ")
4809 proutn(_("Quadrant %s") % game.state.planets[i].w)
4810 proutn(_(" class "))
4811 proutn(game.state.planets[i].pclass)
4813 if game.state.planets[i].crystals != present:
4815 prout(_("dilithium crystals present."))
4816 if game.state.planets[i].known=="shuttle_down":
4817 prout(_(" Shuttle Craft Galileo on surface."))
4819 prout(_("No information available."))
4822 # enter standard orbit
4826 prout(_("Already in standard orbit."))
4828 if damaged(DWARPEN) and damaged(DIMPULS):
4829 prout(_("Both warp and impulse engines damaged."))
4831 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4833 prout(_(" not adjacent to planet."))
4836 game.optime = randreal(0.02, 0.05)
4837 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4841 game.height = randreal(1400, 8600)
4842 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4847 # examine planets in this quadrant
4848 if damaged(DSRSENS):
4849 if game.options & OPTION_TTY:
4850 prout(_("Short range sensors damaged."))
4852 if game.iplnet == None:
4853 if game.options & OPTION_TTY:
4854 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4856 if game.iplnet.known == "unknown":
4857 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4859 prout(_(" Planet at Sector %s is of class %s.") %
4860 (game.plnet, game.iplnet.pclass))
4861 if game.iplnet.known=="shuttle_down":
4862 prout(_(" Sensors show Galileo still on surface."))
4863 proutn(_(" Readings indicate"))
4864 if game.iplnet.crystals != "present":
4866 prout(_(" dilithium crystals present.\""))
4867 if game.iplnet.known == "unknown":
4868 game.iplnet.known = "known"
4869 elif game.iplnet.inhabited:
4870 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4871 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4874 # use the transporter
4878 if damaged(DTRANSP):
4879 prout(_("Transporter damaged."))
4880 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4882 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4886 if not game.inorbit:
4888 prout(_(" not in standard orbit."))
4891 prout(_("Impossible to transport through shields."))
4893 if game.iplnet.known=="unknown":
4894 prout(_("Spock- \"Captain, we have no information on this planet"))
4895 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4896 prout(_(" you may not go down.\""))
4898 if not game.landed and game.iplnet.crystals=="absent":
4899 prout(_("Spock- \"Captain, I fail to see the logic in"))
4900 prout(_(" exploring a planet with no dilithium crystals."))
4901 proutn(_(" Are you sure this is wise?\" "))
4905 if not (game.options & OPTION_PLAIN):
4906 nrgneed = 50 * game.skill + game.height / 100.0
4907 if nrgneed > game.energy:
4908 prout(_("Engineering to bridge--"))
4909 prout(_(" Captain, we don't have enough energy for transportation."))
4911 if not game.landed and nrgneed * 2 > game.energy:
4912 prout(_("Engineering to bridge--"))
4913 prout(_(" Captain, we have enough energy only to transport you down to"))
4914 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4915 if game.iplnet.known == "shuttle_down":
4916 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4917 proutn(_(" Are you sure this is wise?\" "))
4922 # Coming from planet
4923 if game.iplnet.known=="shuttle_down":
4924 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4928 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4929 prout(_("Landing party assembled, ready to beam up."))
4931 prout(_("Kirk whips out communicator..."))
4932 prouts(_("BEEP BEEP BEEP"))
4934 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4937 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4939 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4941 prout(_("Kirk- \"Energize.\""))
4944 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4947 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4949 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4952 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4953 game.landed = not game.landed
4954 game.energy -= nrgneed
4956 prout(_("Transport complete."))
4957 if game.landed and game.iplnet.known=="shuttle_down":
4958 prout(_("The shuttle craft Galileo is here!"))
4959 if not game.landed and game.imine:
4966 # strip-mine a world for dilithium
4970 prout(_("Mining party not on planet."))
4972 if game.iplnet.crystals == "mined":
4973 prout(_("This planet has already been strip-mined for dilithium."))
4975 elif game.iplnet.crystals == "absent":
4976 prout(_("No dilithium crystals on this planet."))
4979 prout(_("You've already mined enough crystals for this trip."))
4981 if game.icrystl and game.cryprob == 0.05:
4982 proutn(_("With all those fresh crystals aboard the "))
4985 prout(_("there's no reason to mine more at this time."))
4987 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4990 prout(_("Mining operation complete."))
4991 game.iplnet.crystals = "mined"
4992 game.imine = game.ididit = True
4995 # use dilithium crystals
4999 if not game.icrystl:
5000 prout(_("No dilithium crystals available."))
5002 if game.energy >= 1000:
5003 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5004 prout(_(" except when Condition Yellow exists."))
5006 prout(_("Spock- \"Captain, I must warn you that loading"))
5007 prout(_(" raw dilithium crystals into the ship's power"))
5008 prout(_(" system may risk a severe explosion."))
5009 proutn(_(" Are you sure this is wise?\" "))
5014 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5015 prout(_(" Mr. Spock and I will try it.\""))
5017 prout(_("Spock- \"Crystals in place, Sir."))
5018 prout(_(" Ready to activate circuit.\""))
5020 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5022 if with(game.cryprob):
5023 prouts(_(" \"Activating now! - - No good! It's***"))
5025 prouts(_("***RED ALERT! RED A*L********************************"))
5028 prouts(_("****************** KA-BOOM!!!! *******************"))
5032 game.energy += randreal(5000.0, 5500.0)
5033 prouts(_(" \"Activating now! - - "))
5034 prout(_("The instruments"))
5035 prout(_(" are going crazy, but I think it's"))
5036 prout(_(" going to work!! Congratulations, Sir!\""))
5041 # use shuttlecraft for planetary jaunt
5044 if damaged(DSHUTTL):
5045 if game.damage[DSHUTTL] == -1.0:
5046 if game.inorbit and game.iplnet.known == "shuttle_down":
5047 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5049 prout(_("Ye Faerie Queene had no shuttle craft."))
5050 elif game.damage[DSHUTTL] > 0:
5051 prout(_("The Galileo is damaged."))
5052 else: # game.damage[DSHUTTL] < 0
5053 prout(_("Shuttle craft is now serving Big Macs."))
5055 if not game.inorbit:
5057 prout(_(" not in standard orbit."))
5059 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5060 prout(_("Shuttle craft not currently available."))
5062 if not game.landed and game.iplnet.known=="shuttle_down":
5063 prout(_("You will have to beam down to retrieve the shuttle craft."))
5065 if game.shldup or game.condition == "docked":
5066 prout(_("Shuttle craft cannot pass through shields."))
5068 if game.iplnet.known=="unknown":
5069 prout(_("Spock- \"Captain, we have no information on this planet"))
5070 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5071 prout(_(" you may not fly down.\""))
5073 game.optime = 3.0e-5*game.height
5074 if game.optime >= 0.8*game.state.remtime:
5075 prout(_("First Officer Spock- \"Captain, I compute that such"))
5076 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5077 int(100*game.optime/game.state.remtime))
5078 prout(_("remaining time."))
5079 proutn(_("Are you sure this is wise?\" "))
5085 if game.iscraft == "onship":
5087 if not damaged(DTRANSP):
5088 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5092 proutn(_("Shuttle crew"))
5094 proutn(_("Rescue party"))
5095 prout(_(" boards Galileo and swoops toward planet surface."))
5096 game.iscraft = "offship"
5100 game.iplnet.known="shuttle_down"
5101 prout(_("Trip complete."))
5104 # Ready to go back to ship
5105 prout(_("You and your mining party board the"))
5106 prout(_("shuttle craft for the trip back to the Enterprise."))
5108 prouts(_("The short hop begins . . ."))
5110 game.iplnet.known="known"
5116 game.iscraft = "onship"
5122 prout(_("Trip complete."))
5127 prout(_("Mining party assembles in the hangar deck,"))
5128 prout(_("ready to board the shuttle craft \"Galileo\"."))
5130 prouts(_("The hangar doors open; the trip begins."))
5133 game.iscraft = "offship"
5136 game.iplnet.known = "shuttle_down"
5139 prout(_("Trip complete."))
5143 # use the big zapper
5147 if game.ship != IHE:
5148 prout(_("Ye Faerie Queene has no death ray."))
5151 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5154 prout(_("Death Ray is damaged."))
5156 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5157 prout(_(" is highly unpredictible. Considering the alternatives,"))
5158 proutn(_(" are you sure this is wise?\" "))
5161 prout(_("Spock- \"Acknowledged.\""))
5164 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5166 prout(_("Crew scrambles in emergency preparation."))
5167 prout(_("Spock and Scotty ready the death ray and"))
5168 prout(_("prepare to channel all ship's power to the device."))
5170 prout(_("Spock- \"Preparations complete, sir.\""))
5171 prout(_("Kirk- \"Engage!\""))
5173 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5176 if game.options & OPTION_PLAIN:
5180 prouts(_("Sulu- \"Captain! It's working!\""))
5182 while game.nenhere > 0:
5183 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.x][game.enemies[1].kloc.y],game.enemies[1].kloc)
5184 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5185 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5187 if (game.options & OPTION_PLAIN) == 0:
5188 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5190 prout(_(" is still operational.\""))
5192 prout(_(" has been rendered nonfunctional.\""))
5193 game.damage[DDRAY] = 39.95
5195 r = randreal() # Pick failure method
5197 prouts(_("Sulu- \"Captain! It's working!\""))
5199 prouts(_("***RED ALERT! RED ALERT!"))
5201 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5203 prouts(_("***RED ALERT! RED A*L********************************"))
5206 prouts(_("****************** KA-BOOM!!!! *******************"))
5211 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5213 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5215 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5216 prout(_(" have apparently been transformed into strange mutations."))
5217 prout(_(" Vulcans do not seem to be affected."))
5219 prout(_("Kirk- \"Raauch! Raauch!\""))
5224 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5226 proutn(_("Spock- \"I believe the word is"))
5227 prouts(_(" *ASTONISHING*"))
5228 prout(_(" Mr. Sulu."))
5229 for i in range(QUADSIZE):
5230 for j in range(QUADSIZE):
5231 if game.quad[i][j] == IHDOT:
5232 game.quad[i][j] = IHQUEST
5233 prout(_(" Captain, our quadrant is now infested with"))
5234 prouts(_(" - - - - - - *THINGS*."))
5236 prout(_(" I have no logical explanation.\""))
5238 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5240 prout(_("Scotty- \"There are so many tribbles down here"))
5241 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5245 # Code from reports.c begins here
5247 def attackreport(curt):
5248 # report status of bases under attack
5250 if is_scheduled(FCDBAS):
5251 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5252 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5253 elif game.isatb == 1:
5254 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5255 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5257 prout(_("No Starbase is currently under attack."))
5259 if is_scheduled(FCDBAS):
5260 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5262 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5266 # report on general game status
5268 s1 = "" and game.thawed and _("thawed ")
5269 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5270 s3 = (None, _("novice"). _("fair"),
5271 _("good"), _("expert"), _("emeritus"))[game.skill]
5272 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5273 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5274 prout(_("No plaque is allowed."))
5276 prout(_("This is tournament game %d.") % game.tourn)
5277 prout(_("Your secret password is \"%s\"") % game.passwd)
5278 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5279 (game.inkling + game.incom + game.inscom)))
5280 if game.incom - game.state.remcom:
5281 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5282 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5283 prout(_(", but no Commanders."))
5286 if game.skill > SKILL_FAIR:
5287 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5288 if game.state.rembase != game.inbase:
5290 if game.inbase-game.state.rembase==1:
5291 proutn(_("has been 1 base"))
5293 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5294 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5296 prout(_("There are %d bases.") % game.inbase)
5297 if communicating() or game.iseenit:
5298 # Don't report this if not seen and
5299 # either the radio is dead or not at base!
5303 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5305 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5306 if game.ship == IHE:
5307 proutn(_("You have "))
5309 proutn("%d" % (game.nprobes))
5312 proutn(_(" deep space probe"))
5316 if communicating() and is_scheduled(FDSPROB):
5318 proutn(_("An armed deep space probe is in "))
5320 proutn(_("A deep space probe is in "))
5321 prout("Quadrant %s." % game.probec)
5323 if game.cryprob <= .05:
5324 prout(_("Dilithium crystals aboard ship... not yet used."))
5328 while game.cryprob > ai:
5331 prout(_("Dilithium crystals have been used %d time%s.") % \
5332 (i, (_("s"), "")[i==1]))
5336 # long-range sensor scan
5337 if damaged(DLRSENS):
5338 # Now allow base's sensors if docked
5339 if game.condition != "docked":
5341 prout(_("LONG-RANGE SENSORS DAMAGED."))
5344 prout(_("Starbase's long-range scan"))
5346 prout(_("Long-range scan"))
5347 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5350 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5351 if not VALID_QUADRANT(x, y):
5355 if not damaged(DRADIO):
5356 game.state.galaxy[x][y].charted = True
5357 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5358 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5359 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5360 if not silent and game.state.galaxy[x][y].supernova:
5363 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5371 for i in range(NDEVICES):
5374 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5375 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5377 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5378 game.damage[i]+0.05,
5379 game.docfac*game.damage[i]+0.005))
5381 prout(_("All devices functional."))
5384 # update the chart in the Enterprise's computer from galaxy data
5385 game.lastchart = game.state.date
5386 for i in range(GALSIZE):
5387 for j in range(GALSIZE):
5388 if game.state.galaxy[i][j].charted:
5389 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5390 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5391 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5394 # display the star chart
5396 if (game.options & OPTION_AUTOSCAN):
5398 if not damaged(DRADIO):
5400 if game.lastchart < game.state.date and game.condition == "docked":
5401 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5404 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5405 if game.state.date > game.lastchart:
5406 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5407 prout(" 1 2 3 4 5 6 7 8")
5408 for i in range(GALSIZE):
5409 proutn("%d |" % (i+1))
5410 for j in range(GALSIZE):
5411 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5415 if game.state.galaxy[i][j].supernova:
5417 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5419 elif game.state.galaxy[i][j].charted:
5420 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5424 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5432 def sectscan(goodScan, i, j):
5433 # light up an individual dot in a sector
5434 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5435 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):
5436 if game.condition == "red": textcolor(RED)
5437 elif game.condition == "green": textcolor(GREEN)
5438 elif game.condition == "yellow": textcolor(YELLOW)
5439 elif game.condition == "docked": textcolor(CYAN)
5440 elif game.condition == "dead": textcolor(BROWN)
5441 if game.quad[i][j] != game.ship:
5443 proutn("%c " % game.quad[i][j])
5449 # print status report lines
5451 if not req or req == 1:
5452 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5453 % (game.state.date, game.state.remtime))
5454 if not req or req == 2:
5455 if game.condition != "docked":
5458 for t in range(NDEVICES):
5459 if game.damage[t]>0:
5461 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5462 if not req or req == 3:
5463 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5464 if not req or req == 4:
5465 if damaged(DLIFSUP):
5466 if game.condition == "docked":
5467 s = _("DAMAGED, Base provides")
5469 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5472 prstat(_("Life Support"), s)
5473 if not req or req == 5:
5474 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5475 if not req or req == 6:
5477 if game.icrystl and (game.options & OPTION_SHOWME):
5478 extra = _(" (have crystals)")
5479 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5480 if not req or req == 7:
5481 prstat(_("Torpedoes"), "%d" % (game.torps))
5482 if not req or req == 8:
5483 if damaged(DSHIELD):
5489 data = _(" %d%% %.1f units") \
5490 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5491 prstat(_("Shields"), s+data)
5492 if not req or req == 9:
5493 prstat(_("Klingons Left"), "%d" \
5494 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5495 if not req or req == 10:
5496 if game.options & OPTION_WORLDS:
5497 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5498 if plnet and plnet.inhabited:
5499 prstat(_("Major system"), plnet.name)
5501 prout(_("Sector is uninhabited"))
5502 elif not req or req == 11:
5503 attackreport(not req)
5506 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5507 while scan() == IHEOL:
5508 proutn(_("Information desired? "))
5510 if citem in requests:
5511 status(requests.index(citem))
5513 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5514 prout((" date, condition, position, lsupport, warpfactor,"))
5515 prout((" energy, torpedoes, shields, klingons, system, time."))
5520 if damaged(DSRSENS):
5521 # Allow base's sensors if docked
5522 if game.condition != "docked":
5523 prout(_(" S.R. SENSORS DAMAGED!"))
5526 prout(_(" [Using Base's sensors]"))
5528 prout(_(" Short-range scan"))
5529 if goodScan and not damaged(DRADIO):
5530 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5531 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5532 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5533 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5534 prout(" 1 2 3 4 5 6 7 8 9 10")
5535 if game.condition != "docked":
5537 for i in range(QUADSIZE):
5538 proutn("%2d " % (i+1))
5539 for j in range(QUADSIZE):
5540 sectscan(goodScan, i, j)
5545 # use computer to get estimated time of arrival for a warp jump
5546 w1 = coord(); w2 = coord()
5548 if damaged(DCOMPTR):
5549 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5552 if scan() != IHREAL:
5555 proutn(_("Destination quadrant and/or sector? "))
5559 w1.y = int(aaitem-0.5)
5560 if scan() != IHREAL:
5563 w1.x = int(aaitem-0.5)
5564 if scan() == IHREAL:
5565 w2.y = int(aaitem-0.5)
5566 if scan() != IHREAL:
5569 w2.x = int(aaitem-0.5)
5571 if game.quadrant.y>w1.x:
5575 if game.quadrant.x>w1.y:
5579 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5582 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5583 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5586 prout(_("Answer \"no\" if you don't know the value:"))
5589 proutn(_("Time or arrival date? "))
5592 if ttime > game.state.date:
5593 ttime -= game.state.date # Actually a star date
5594 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5595 if ttime <= 1e-10 or twarp > 10:
5596 prout(_("We'll never make it, sir."))
5603 proutn(_("Warp factor? "))
5607 if twarp<1.0 or twarp > 10.0:
5611 prout(_("Captain, certainly you can give me one of these."))
5614 ttime = (10.0*game.dist)/square(twarp)
5615 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5616 if tpower >= game.energy:
5617 prout(_("Insufficient energy, sir."))
5618 if not game.shldup or tpower > game.energy*2.0:
5621 proutn(_("New warp factor to try? "))
5622 if scan() == IHREAL:
5625 if twarp<1.0 or twarp > 10.0:
5633 prout(_("But if you lower your shields,"))
5634 proutn(_("remaining"))
5637 proutn(_("Remaining"))
5638 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5640 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5642 prout(_("Any warp speed is adequate."))
5644 prout(_("Minimum warp needed is %.2f,") % (twarp))
5645 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5646 if game.state.remtime < ttime:
5647 prout(_("Unfortunately, the Federation will be destroyed by then."))
5649 prout(_("You'll be taking risks at that speed, Captain"))
5650 if (game.isatb==1 and game.state.kscmdr == w1 and \
5651 scheduled(FSCDBAS)< ttime+game.state.date) or \
5652 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5653 prout(_("The starbase there will be destroyed by then."))
5654 proutn(_("New warp factor to try? "))
5655 if scan() == IHREAL:
5658 if twarp<1.0 or twarp > 10.0:
5667 # Code from setup.c begins here
5670 # issue a historically correct banner
5672 prout(_("-SUPER- STAR TREK"))
5674 # From the FORTRAN original
5675 # prout(_("Latest update-21 Sept 78"))
5681 citem = "emsave.trk"
5685 proutn(_("File name: "))
5691 if '.' not in citem:
5694 fp = open(citem, "wb")
5696 prout(_("Can't freeze game as file %s") % citem)
5698 cPickle.dump(game, fp)
5702 # retrieve saved game
5703 game.passwd[0] = '\0'
5706 proutn(_("File name: "))
5712 if '.' not in citem:
5715 fp = open(citem, "rb")
5717 prout(_("Can't thaw game in %s") % citem)
5719 game = cPickle.load(fp)
5723 # I used <http://www.memory-alpha.org> to find planets
5724 # with references in ST:TOS. Eath and the Alpha Centauri
5725 # Colony have been omitted.
5727 # Some planets marked Class G and P here will be displayed as class M
5728 # because of the way planets are generated. This is a known bug.
5731 _("Andoria (Fesoan)"), # several episodes
5732 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5733 _("Vulcan (T'Khasi)"), # many episodes
5734 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5735 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5736 _("Ardana"), # TOS: "The Cloud Minders"
5737 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5738 _("Gideon"), # TOS: "The Mark of Gideon"
5739 _("Aldebaran III"), # TOS: "The Deadly Years"
5740 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5741 _("Altair IV"), # TOS: "Amok Time
5742 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5743 _("Benecia"), # TOS: "The Conscience of the King"
5744 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5745 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5746 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5747 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5748 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5749 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5750 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5751 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5752 _("Ingraham B"), # TOS: "Operation: Annihilate"
5753 _("Janus IV"), # TOS: "The Devil in the Dark"
5754 _("Makus III"), # TOS: "The Galileo Seven"
5755 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5756 _("Omega IV"), # TOS: "The Omega Glory"
5757 _("Regulus V"), # TOS: "Amok Time
5758 _("Deneva"), # TOS: "Operation -- Annihilate!"
5759 # Worlds from BSD Trek
5760 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5761 _("Beta III"), # TOS: "The Return of the Archons"
5762 _("Triacus"), # TOS: "And the Children Shall Lead",
5763 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5765 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5766 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5767 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5768 # _("Izar"), # TOS: "Whom Gods Destroy"
5769 # _("Tiburon"), # TOS: "The Way to Eden"
5770 # _("Merak II"), # TOS: "The Cloud Minders"
5771 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5772 # _("Iotia"), # TOS: "A Piece of the Action"
5776 _("S. R. Sensors"), \
5777 _("L. R. Sensors"), \
5779 _("Photon Tubes"), \
5780 _("Life Support"), \
5781 _("Warp Engines"), \
5782 _("Impulse Engines"), \
5784 _("Subspace Radio"), \
5785 _("Shuttle Craft"), \
5787 _("Navigation System"), \
5789 _("Shield Control"), \
5794 def setup(needprompt):
5795 # prepare to play, set up cosmos
5797 # Decide how many of everything
5798 if choose(needprompt):
5799 return # frozen game
5800 # Prepare the Enterprise
5801 game.alldone = game.gamewon = False
5803 game.state.crew = FULLCREW
5804 game.energy = game.inenrg = 5000.0
5805 game.shield = game.inshld = 2500.0
5806 game.shldchg = False
5810 game.quadrant = randplace(GALSIZE)
5811 game.sector = randplace(QUADSIZE)
5812 game.torps = game.intorps = 10
5813 game.nprobes = randrange(2, 5)
5815 game.wfacsq = game.warpfac * game.warpfac
5816 for i in range(NDEVICES):
5817 game.damage[i] = 0.0
5818 # Set up assorted game parameters
5819 game.battle = coord()
5820 game.state.date = game.indate = 100.0 * randreal(20, 51)
5821 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5822 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5823 game.isatb = game.state.nplankl = 0
5824 game.state.starkl = game.state.basekl = 0
5825 game.iscraft = "onship"
5829 for i in range(GALSIZE):
5830 for j in range(GALSIZE):
5831 quad = game.state.galaxy[i][j]
5836 quad.starbase = False
5837 quad.supernova = False
5838 quad.status = "secure"
5839 # Initialize times for extraneous events
5840 schedule(FSNOVA, expran(0.5 * game.intime))
5841 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5842 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5843 schedule(FBATTAK, expran(0.3*game.intime))
5845 if game.state.nscrem:
5846 schedule(FSCMOVE, 0.2777)
5851 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5852 schedule(FDISTR, expran(1.0 + game.intime))
5857 # Starchart is functional but we've never seen it
5858 game.lastchart = FOREVER
5859 # Put stars in the galaxy
5861 for i in range(GALSIZE):
5862 for j in range(GALSIZE):
5863 k = randrange(1, QUADSIZE**2/10+1)
5865 game.state.galaxy[i][j].stars = k
5866 # Locate star bases in galaxy
5867 for i in range(game.inbase):
5870 w = randplace(GALSIZE)
5871 if not game.state.galaxy[w.x][w.y].starbase:
5874 # C version: for (j = i-1; j > 0; j--)
5875 # so it did them in the opposite order.
5876 for j in range(1, i):
5877 # Improved placement algorithm to spread out bases
5878 distq = w.distance(game.state.baseq[j])
5879 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5882 prout("=== Abandoning base #%d at %s" % (i, w))
5884 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5886 prout("=== Saving base #%d, close to #%d" % (i, j))
5889 game.state.baseq[i] = w
5890 game.state.galaxy[w.x][w.y].starbase = True
5891 game.state.chart[w.x][w.y].starbase = True
5892 # Position ordinary Klingon Battle Cruisers
5894 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5895 if klumper > MAXKLQUAD:
5899 klump = (1.0 - r*r)*klumper
5904 w = randplace(GALSIZE)
5905 if not game.state.galaxy[w.x][w.y].supernova and \
5906 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5908 game.state.galaxy[w.x][w.y].klingons += int(klump)
5911 # Position Klingon Commander Ships
5912 for i in range(1, game.incom+1):
5914 w = randplace(GALSIZE)
5915 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5916 not game.state.galaxy[w.x][w.y].supernova and \
5917 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5918 not w in game.state.kcmdr[:i]:
5920 game.state.galaxy[w.x][w.y].klingons += 1
5921 game.state.kcmdr[i] = w
5922 # Locate planets in galaxy
5923 for i in range(game.inplan):
5925 w = randplace(GALSIZE)
5926 if game.state.galaxy[w.x][w.y].planet == None:
5930 new.crystals = "absent"
5931 if (game.options & OPTION_WORLDS) and i < NINHAB:
5932 new.pclass = "M" # All inhabited planets are class M
5933 new.crystals = "absent"
5935 new.name = systnames[i]
5936 new.inhabited = True
5938 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5940 new.crystals = "present"
5941 new.known = "unknown"
5942 new.inhabited = False
5943 game.state.galaxy[w.x][w.y].planet = new
5944 game.state.planets.append(new)
5946 for i in range(game.state.nromrem):
5947 w = randplace(GALSIZE)
5948 game.state.galaxy[w.x][w.y].romulans += 1
5949 # Locate the Super Commander
5950 if game.state.nscrem > 0:
5952 w = randplace(GALSIZE)
5953 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
5955 game.state.kscmdr = w
5956 game.state.galaxy[w.x][w.y].klingons += 1
5957 # Place thing (in tournament game, we don't want one!)
5959 if game.tourn is None:
5960 thing = randplace(GALSIZE)
5962 game.state.snap = False
5963 if game.skill == SKILL_NOVICE:
5964 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5965 prout(_("a deadly Klingon invasion force. As captain of the United"))
5966 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5967 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5968 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5969 prout(_("your mission. As you proceed you may be given more time."))
5971 prout(_("You will have %d supporting starbases.") % (game.inbase))
5972 proutn(_("Starbase locations- "))
5974 prout(_("Stardate %d.") % int(game.state.date))
5976 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5977 prout(_("An unknown number of Romulans."))
5978 if game.state.nscrem:
5979 prout(_("And one (GULP) Super-Commander."))
5980 prout(_("%d stardates.") % int(game.intime))
5981 proutn(_("%d starbases in ") % game.inbase)
5982 for i in range(game.inbase):
5983 proutn(`game.state.baseq[i]`)
5986 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5987 proutn(_(" Sector %s") % game.sector)
5989 prout(_("Good Luck!"))
5990 if game.state.nscrem:
5991 prout(_(" YOU'LL NEED IT."))
5994 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
5996 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5997 attack(torps_ok=False)
5999 def choose(needprompt):
6000 # choose your game type
6005 game.skill = SKILL_NONE
6007 if needprompt: # Can start with command line options
6008 proutn(_("Would you like a regular, tournament, or saved game? "))
6010 if len(citem)==0: # Try again
6012 if isit("tournament"):
6013 while scan() == IHEOL:
6014 proutn(_("Type in tournament number-"))
6017 continue # We don't want a blank entry
6018 game.tourn = int(round(aaitem))
6021 logfp.write("# random.seed(%d)\n" % aaitem)
6023 if isit("saved") or isit("frozen"):
6027 if game.passwd == None:
6029 if not game.alldone:
6030 game.thawed = True # No plaque if not finished
6036 proutn(_("What is \"%s\"?"), citem)
6038 while game.length==0 or game.skill==SKILL_NONE:
6039 if scan() == IHALPHA:
6042 elif isit("medium"):
6046 elif isit("novice"):
6047 game.skill = SKILL_NOVICE
6049 game.skill = SKILL_FAIR
6051 game.skill = SKILL_GOOD
6052 elif isit("expert"):
6053 game.skill = SKILL_EXPERT
6054 elif isit("emeritus"):
6055 game.skill = SKILL_EMERITUS
6057 proutn(_("What is \""))
6063 proutn(_("Would you like a Short, Medium, or Long game? "))
6064 elif game.skill == SKILL_NONE:
6065 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6066 # Choose game options -- added by ESR for SST2K
6067 if scan() != IHALPHA:
6069 proutn(_("Choose your game style (or just press enter): "))
6072 # Approximates the UT FORTRAN version.
6073 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6074 game.options |= OPTION_PLAIN
6076 # Approximates Tom Almy's version.
6077 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6078 game.options |= OPTION_ALMY
6082 proutn(_("What is \"%s\"?") % citem)
6084 if game.passwd == "debug":
6086 fputs("=== Debug mode enabled\n", sys.stdout)
6088 # Use parameters to generate initial values of things
6089 game.damfac = 0.5 * game.skill
6090 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6091 game.inbase = game.state.rembase
6093 if game.options & OPTION_PLANETS:
6094 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6095 if game.options & OPTION_WORLDS:
6096 game.inplan += int(NINHAB)
6097 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6098 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6099 game.state.remtime = 7.0 * game.length
6100 game.intime = game.state.remtime
6101 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6102 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6103 game.state.remcom = min(10, game.incom)
6104 game.incom = game.state.remcom
6105 game.state.remres = (game.inkling+4*game.incom)*game.intime
6106 game.inresor = game.state.remres
6107 if game.inkling > 50:
6108 game.state.rembase += 1
6109 game.inbase = game.state.rembase
6112 def dropin(iquad=None):
6113 # drop a feature on a random dot in the current quadrant
6116 w = randplace(QUADSIZE)
6117 if game.quad[w.x][w.y] == IHDOT:
6119 if iquad is not None:
6120 game.quad[w.x][w.y] = iquad
6124 # update our alert status
6125 game.condition = "green"
6126 if game.energy < 1000.0:
6127 game.condition = "yellow"
6128 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6129 game.condition = "red"
6131 game.condition="dead"
6134 # drop new Klingon into current quadrant
6135 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
6138 # set up a new state of quadrant, for when we enter or re-enter it
6142 game.comhere = False
6148 game.inorbit = False
6150 game.ientesc = False
6151 game.iseenit = False
6153 # Attempt to escape Super-commander, so tbeam back!
6156 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6157 # cope with supernova
6160 game.klhere = q.klingons
6161 game.irhere = q.romulans
6162 game.nenhere = game.klhere + game.irhere
6164 game.quad[game.sector.x][game.sector.y] = game.ship
6167 # Position ordinary Klingons
6168 for i in range(game.klhere):
6170 # If we need a commander, promote a Klingon
6171 for i in range(game.state.remcom):
6172 if game.state.kcmdr[i] == game.quadrant:
6173 e = game.enemies[game.klhere-1]
6174 game.quad[e.kloc.x][e.kloc.y] = IHC
6175 e.kpower = randreal(950,1350) + 50.0*game.skill
6178 # If we need a super-commander, promote a Klingon
6179 if game.quadrant == game.state.kscmdr:
6181 game.quad[e.kloc.x][e.kloc.y] = IHS
6182 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
6183 game.iscate = (game.state.remkl > 1)
6185 # Put in Romulans if needed
6186 for i in range(game.klhere, game.nenhere):
6187 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
6188 # If quadrant needs a starbase, put it in
6190 game.base = dropin(IHB)
6191 # If quadrant needs a planet, put it in
6193 game.iplnet = q.planet
6194 if not q.planet.inhabited:
6195 game.plnet = dropin(IHP)
6197 game.plnet = dropin(IHW)
6198 # Check for condition
6201 if game.irhere > 0 and game.klhere == 0:
6203 if not damaged(DRADIO):
6205 prout(_("LT. Uhura- \"Captain, an urgent message."))
6206 prout(_(" I'll put it on audio.\" CLICK"))
6208 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6209 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6211 # Put in THING if needed
6212 if thing == game.quadrant:
6213 enemy(symbol=IHQUEST, loc=dropin(),
6214 power=randreal(6000,6500.0)+250.0*game.skill)
6215 if not damaged(DSRSENS):
6217 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6218 prout(_(" Please examine your short-range scan.\""))
6219 # Decide if quadrant needs a Tholian; lighten up if skill is low
6220 if game.options & OPTION_THOLIAN:
6221 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6222 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6223 (game.skill > SKILL_GOOD and withprob(0.08)):
6226 w.x = withprob(0.5) * (QUADSIZE-1)
6227 w.y = withprob(0.5) * (QUADSIZE-1)
6228 if game.quad[w.x][w.y] == IHDOT:
6230 game.tholian = enemy(symbol=IHT, loc=w,
6231 power=randrange(100, 500) + 25.0*game.skill)
6232 # Reserve unoccupied corners
6233 if game.quad[0][0]==IHDOT:
6234 game.quad[0][0] = 'X'
6235 if game.quad[0][QUADSIZE-1]==IHDOT:
6236 game.quad[0][QUADSIZE-1] = 'X'
6237 if game.quad[QUADSIZE-1][0]==IHDOT:
6238 game.quad[QUADSIZE-1][0] = 'X'
6239 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6240 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6241 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
6242 # And finally the stars
6243 for i in range(q.stars):
6245 # Put in a few black holes
6246 for i in range(1, 3+1):
6249 # Take out X's in corners if Tholian present
6251 if game.quad[0][0]=='X':
6252 game.quad[0][0] = IHDOT
6253 if game.quad[0][QUADSIZE-1]=='X':
6254 game.quad[0][QUADSIZE-1] = IHDOT
6255 if game.quad[QUADSIZE-1][0]=='X':
6256 game.quad[QUADSIZE-1][0] = IHDOT
6257 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6258 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6261 # set the self-destruct password
6262 if game.options & OPTION_PLAIN:
6265 proutn(_("Please type in a secret password- "))
6268 if game.passwd != None:
6273 game.passwd += chr(ord('a')+randrange(26))
6275 # Code from sst.c begins here
6278 "SRSCAN": OPTION_TTY,
6279 "STATUS": OPTION_TTY,
6280 "REQUEST": OPTION_TTY,
6281 "LRSCAN": OPTION_TTY,
6294 "SENSORS": OPTION_PLANETS,
6295 "ORBIT": OPTION_PLANETS,
6296 "TRANSPORT": OPTION_PLANETS,
6297 "MINE": OPTION_PLANETS,
6298 "CRYSTALS": OPTION_PLANETS,
6299 "SHUTTLE": OPTION_PLANETS,
6300 "PLANETS": OPTION_PLANETS,
6305 "PROBE": OPTION_PROBE,
6307 "FREEZE": 0, # Synonym for SAVE
6313 "SOS": 0, # Synonym for MAYDAY
6314 "CALL": 0, # Synonym for MAYDAY
6321 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6324 # generate a list of legal commands
6326 proutn(_("LEGAL COMMANDS ARE:"))
6327 for key in commands:
6331 proutn("%-12s " % key)
6336 # browse on-line help
6337 # Give help on commands
6341 setwnd(prompt_window)
6342 proutn(_("Help on what command? "))
6344 setwnd(message_window)
6347 if citem in commands or citem == "ABBREV":
6356 fp = open(SSTDOC, "r")
6359 fp = open(DOC_NAME, "r")
6361 prout(_("Spock- \"Captain, that information is missing from the"))
6362 proutn(_(" computer. You need to find "))
6364 prout(_(" and put it in the"))
6365 proutn(_(" current directory or to "))
6369 # This used to continue: "You need to find SST.DOC and put
6370 # it in the current directory."
6374 linebuf = fp.readline()
6376 prout(_("Spock- \"Captain, there is no information on that command.\""))
6379 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6380 linebuf = linebuf[3:].strip()
6384 prout(_("Spock- \"Captain, I've found the following information:\""))
6386 while linebuf in fp:
6387 if "******" in linebuf:
6393 # command-interpretation loop
6396 setwnd(message_window)
6397 while True: # command loop
6399 while True: # get a command
6404 setwnd(prompt_window)
6408 if game.options & OPTION_CURSES:
6413 setwnd(message_window)
6415 candidates = filter(lambda x: x.startswith(citem.upper()),
6417 if len(candidates) == 1:
6420 elif candidates and not (game.options & OPTION_PLAIN):
6421 prout("Commands with that prefix: " + " ".join(candidates))
6425 if cmd == "SRSCAN": # srscan
6427 elif cmd == "STATUS": # status
6429 elif cmd == "REQUEST": # status request
6431 elif cmd == "LRSCAN": # long range scan
6432 lrscan(silent=False)
6433 elif cmd == "PHASERS": # phasers
6437 elif cmd == "TORPEDO": # photon torpedos
6441 elif cmd == "MOVE": # move under warp
6443 elif cmd == "SHIELDS": # shields
6444 doshield(shraise=False)
6447 game.shldchg = False
6448 elif cmd == "DOCK": # dock at starbase
6451 attack(torps_ok=False)
6452 elif cmd == "DAMAGES": # damage reports
6454 elif cmd == "CHART": # chart
6456 elif cmd == "IMPULSE": # impulse
6458 elif cmd == "REST": # rest
6462 elif cmd == "WARP": # warp
6464 elif cmd == "SCORE": # score
6466 elif cmd == "SENSORS": # sensors
6468 elif cmd == "ORBIT": # orbit
6472 elif cmd == "TRANSPORT": # transport "beam"
6474 elif cmd == "MINE": # mine
6478 elif cmd == "CRYSTALS": # crystals
6482 elif cmd == "SHUTTLE": # shuttle
6486 elif cmd == "PLANETS": # Planet list
6488 elif cmd == "REPORT": # Game Report
6490 elif cmd == "COMPUTER": # use COMPUTER!
6492 elif cmd == "COMMANDS":
6494 elif cmd == "EMEXIT": # Emergency exit
6495 clrscr() # Hide screen
6496 freeze(True) # forced save
6497 raise SysExit,1 # And quick exit
6498 elif cmd == "PROBE":
6499 probe() # Launch probe
6502 elif cmd == "ABANDON": # Abandon Ship
6504 elif cmd == "DESTRUCT": # Self Destruct
6506 elif cmd == "SAVE": # Save Game
6509 if game.skill > SKILL_GOOD:
6510 prout(_("WARNING--Saved games produce no plaques!"))
6511 elif cmd == "DEATHRAY": # Try a desparation measure
6515 elif cmd == "DEBUGCMD": # What do we want for debug???
6517 elif cmd == "MAYDAY": # Call for help
6522 game.alldone = True # quit the game
6527 break # Game has ended
6528 if game.optime != 0.0:
6531 break # Events did us in
6532 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6535 if hitme and not game.justin:
6536 attack(torps_ok=True)
6539 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6551 if cmd == IHR: s = _("Romulan")
6552 elif cmd == IHK: s = _("Klingon")
6553 elif cmd == IHC: s = _("Commander")
6554 elif cmd == IHS: s = _("Super-commander")
6555 elif cmd == IHSTAR: s = _("Star")
6556 elif cmd == IHP: s = _("Planet")
6557 elif cmd == IHB: s = _("Starbase")
6558 elif cmd == IHBLANK: s = _("Black hole")
6559 elif cmd == IHT: s = _("Tholian")
6560 elif cmd == IHWEB: s = _("Tholian web")
6561 elif cmd == IHQUEST: s = _("Stranger")
6562 elif cmd == IHW: s = _("Inhabited World")
6563 else: s = "Unknown??"
6566 def crmena(stars, enemy, loctype, w):
6567 # print an enemy and his location
6573 if loctype == "quadrant":
6574 buf = _("Quadrant ")
6575 elif loctype == "sector":
6580 # print our ship name
6581 if game.ship == IHE:
6583 elif game.ship == IHF:
6584 s = _("Faerie Queene")
6590 # print a line of stars
6591 prouts("******************************************************")
6595 return -avrage*math.log(1e-7 + randreal())
6597 def randplace(size):
6598 # choose a random location
6600 w.x = randrange(size)
6601 w.y = randrange(size)
6605 # Demand input for next scan
6610 # return IHEOL next time
6615 # Get a token from the user
6616 global inqueue, line, citem, aaitem
6620 # Read a line if nothing here
6623 if curwnd==prompt_window:
6625 setwnd(message_window)
6627 # Skip leading white space
6628 line = line.lstrip()
6630 inqueue = line.split()
6636 # From here on in it's all looking at the queue
6637 citem = inqueue.pop(0)
6641 aaitem = float(citem)
6646 citem = citem.lower()
6650 # yes-or-no confirmation
6659 proutn(_("Please answer with \"y\" or \"n\": "))
6662 # complain about unparseable input
6665 prout(_("Beg your pardon, Captain?"))
6668 # compares s to citem and returns true if it matches to the length of s
6669 return s.startswith(citem)
6672 # access to the internals for debugging
6673 proutn("Reset levels? ")
6675 if game.energy < game.inenrg:
6676 game.energy = game.inenrg
6677 game.shield = game.inshld
6678 game.torps = game.intorps
6679 game.lsupres = game.inlsr
6680 proutn("Reset damage? ")
6682 for i in range(NDEVICES):
6683 if game.damage[i] > 0.0:
6684 game.damage[i] = 0.0
6685 proutn("Toggle debug flag? ")
6689 prout("Debug output ON")
6691 prout("Debug output OFF")
6692 proutn("Cause selective damage? ")
6694 for i in range(NDEVICES):
6700 if key == IHALPHA and isit("y"):
6701 game.damage[i] = 10.0
6702 proutn("Examine/change events? ")
6707 FSNOVA: "Supernova ",
6710 FBATTAK: "Base Attack ",
6711 FCDBAS: "Base Destroy ",
6712 FSCMOVE: "SC Move ",
6713 FSCDBAS: "SC Base Destroy ",
6714 FDSPROB: "Probe Move ",
6715 FDISTR: "Distress Call ",
6716 FENSLV: "Enslavement ",
6717 FREPRO: "Klingon Build ",
6719 for i in range(1, NEVENTS):
6722 proutn("%.2f" % (scheduled(i)-game.state.date))
6723 if i == FENSLV or i == FREPRO:
6725 proutn(" in %s" % ev.quadrant)
6735 ev = schedule(i, aaitem)
6736 if i == FENSLV or i == FREPRO:
6738 proutn("In quadrant- ")
6740 # IHEOL says to leave coordinates as they are
6743 prout("Event %d canceled, no x coordinate." % (i))
6746 w.x = int(round(aaitem))
6749 prout("Event %d canceled, no y coordinate." % (i))
6752 w.y = int(round(aaitem))
6755 proutn("Induce supernova here? ")
6757 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6760 if __name__ == '__main__':
6762 global line, thing, game, idebug
6763 game = citem = aaitem = inqueue = None
6769 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6770 # Disable curses mode until the game logic is working.
6771 # if os.getenv("TERM"):
6772 # game.options |= OPTION_CURSES | OPTION_SHOWME
6774 game.options |= OPTION_TTY
6775 seed = int(time.time())
6776 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6777 for (switch, val) in options:
6780 replayfp = open(val, "r")
6782 sys.stderr.write("sst: can't open replay file %s\n" % val)
6785 line = replayfp.readline().strip()
6786 (leader, key, seed) = line.split()
6788 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6789 line = replayfp.readline().strip()
6790 arguments += line.split()[2:]
6792 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6794 game.options |= OPTION_TTY
6795 game.options &=~ OPTION_CURSES
6796 elif switch == '-t':
6797 game.options |= OPTION_TTY
6798 game.options &=~ OPTION_CURSES
6799 elif switch == '-x':
6802 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6804 # where to save the input in case of bugs
6806 logfp = open("/usr/tmp/sst-input.log", "w")
6808 sys.stderr.write("sst: warning, can't open logfile\n")
6810 logfp.write("# seed %s\n" % seed)
6811 logfp.write("# options %s\n" % " ".join(arguments))
6818 while True: # Play a game
6819 setwnd(fullscreen_window)
6822 setup(needprompt=not inqueue)
6825 game.alldone = False
6831 if game.tourn and game.alldone:
6832 proutn(_("Do you want your score recorded?"))
6837 proutn(_("Do you want to play again? "))
6841 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6843 except KeyboardInterrupt: