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
204 # These functions hide the difference between 0-origin and 1-origin addressing.
205 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
206 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
208 def square(i): return ((i)*(i))
209 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
210 def invalidate(w): w.x = w.y = 0
211 def is_valid(w): return (w.x != 0 and w.y != 0)
213 # How to represent features
238 def __init__(self, x=None, y=None):
241 def invalidate(self):
242 self.x = self.y = None
244 return self.x != None and self.y != None
245 def __eq__(self, other):
246 return other != None and self.x == other.y and self.x == other.y
247 def __add__(self, other):
248 return coord(self.x+self.x, self.y+self.y)
249 def __sub__(self, other):
250 return coord(self.x-self.x, self.y-self.y)
251 def distance(self, other):
252 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
258 s.x = self.x / abs(self.x)
262 s.y = self.y / abs(self.y)
266 s.x = self.x + randrange(-1, 2)
267 s.y = self.y + randrange(-1, 2)
272 if self.x == None or self.y == None:
274 return "%s - %s" % (self.x+1, self.y+1)
279 self.name = None # string-valued if inhabited
280 self.w = coord() # quadrant located
281 self.pclass = None # could be ""M", "N", "O", or "destroyed"
282 self.crystals = "absent"# could be "mined", "present", "absent"
283 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
284 self.inhabited = False # is it inhabites?
295 self.supernova = None
297 self.status = None # Could be "secure", "distressed", "enslaved"
305 def fill2d(size, fillfun):
306 "Fill an empty list in 2D."
308 for i in range(size):
310 for j in range(size):
311 lst[i].append(fillfun(i, j))
316 self.snap = False # snapshot taken
317 self.crew = 0 # crew complement
318 self.remkl = 0 # remaining klingons
319 self.remcom = 0 # remaining commanders
320 self.nscrem = 0 # remaining super commanders
321 self.rembase = 0 # remaining bases
322 self.starkl = 0 # destroyed stars
323 self.basekl = 0 # destroyed bases
324 self.nromrem = 0 # Romulans remaining
325 self.nplankl = 0 # destroyed uninhabited planets
326 self.nworldkl = 0 # destroyed inhabited planets
327 self.planets = [] # Planet information
328 self.date = 0.0 # stardate
329 self.remres = 0 # remaining resources
330 self.remtime = 0 # remaining time
331 self.baseq = [] # Base quadrant coordinates
332 for i in range(BASEMAX):
333 self.baseq.append(coord())
334 self.kcmdr = [] # Commander quadrant coordinates
335 for i in range(QUADSIZE):
336 self.kcmdr.append(coord())
337 self.kscmdr = coord() # Supercommander quadrant coordinates
338 # the galaxy (subscript 0 not used)
339 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
340 # the starchart (subscript 0 not used)
341 self.chart = fill2d(GALSIZE, lambda i, j: page())
345 self.date = None # A real number
346 self.quadrant = None # A coord structure
349 OPTION_ALL = 0xffffffff
350 OPTION_TTY = 0x00000001 # old interface
351 OPTION_CURSES = 0x00000002 # new interface
352 OPTION_IOMODES = 0x00000003 # cover both interfaces
353 OPTION_PLANETS = 0x00000004 # planets and mining
354 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
355 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
356 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
357 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
358 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
359 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
360 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
361 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
362 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
363 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
364 OPTION_PLAIN = 0x01000000 # user chose plain game
365 OPTION_ALMY = 0x02000000 # user chose Almy variant
384 NDEVICES= 16 # Number of devices
393 def damaged(dev): return (game.damage[dev] != 0.0)
394 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
396 # Define future events
397 FSPY = 0 # Spy event happens always (no future[] entry)
398 # can cause SC to tractor beam Enterprise
399 FSNOVA = 1 # Supernova
400 FTBEAM = 2 # Commander tractor beams Enterprise
401 FSNAP = 3 # Snapshot for time warp
402 FBATTAK = 4 # Commander attacks base
403 FCDBAS = 5 # Commander destroys base
404 FSCMOVE = 6 # Supercommander moves (might attack base)
405 FSCDBAS = 7 # Supercommander destroys base
406 FDSPROB = 8 # Move deep space probe
407 FDISTR = 9 # Emit distress call from an inhabited world
408 FENSLV = 10 # Inhabited word is enslaved */
409 FREPRO = 11 # Klingons build a ship in an enslaved system
413 # abstract out the event handling -- underlying data structures will change
414 # when we implement stateful events
416 def findevent(evtype): return game.future[evtype]
419 def __init__(self, loc=None, power=None):
422 self.kdist = self.kavgd = distance(game.sector, loc)
424 self.kloc = coord() # enemy sector location
425 self.kdist = self.kavgd = None
426 self.kpower = power # enemy energy levels
428 return "<%s=%f>" % (self.kloc, self.kpower) # For debugging
432 self.options = None # Game options
433 self.state = snapshot() # A snapshot structure
434 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
435 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
436 self.damage = [0.0] * NDEVICES # damage encountered
437 self.future = [] # future events
438 for i in range(NEVENTS):
439 self.future.append(event())
440 self.passwd = None; # Self Destruct password
442 self.quadrant = None # where we are in the large
443 self.sector = None # where we are in the small
444 self.tholian = None # coordinates of Tholian
445 self.base = None # position of base in current quadrant
446 self.battle = None # base coordinates being attacked
447 self.plnet = None # location of planet in quadrant
448 self.probec = None # current probe quadrant
449 self.gamewon = False # Finished!
450 self.ididit = False # action taken -- allows enemy to attack
451 self.alive = False # we are alive (not killed)
452 self.justin = False # just entered quadrant
453 self.shldup = False # shields are up
454 self.shldchg = False # shield is changing (affects efficiency)
455 self.comhere = False # commander here
456 self.ishere = False # super-commander in quadrant
457 self.iscate = False # super commander is here
458 self.ientesc = False # attempted escape from supercommander
459 self.resting = False # rest time
460 self.icraft = False # Kirk in Galileo
461 self.landed = False # party on planet (true), on ship (false)
462 self.alldone = False # game is now finished
463 self.neutz = False # Romulan Neutral Zone
464 self.isarmed = False # probe is armed
465 self.inorbit = False # orbiting a planet
466 self.imine = False # mining
467 self.icrystl = False # dilithium crystals aboard
468 self.iseenit = False # seen base attack report
469 self.thawed = False # thawed game
470 self.condition = None # "green", "yellow", "red", "docked", "dead"
471 self.iscraft = None # "onship", "offship", "removed"
472 self.skill = None # Player skill level
473 self.inkling = 0 # initial number of klingons
474 self.inbase = 0 # initial number of bases
475 self.incom = 0 # initial number of commanders
476 self.inscom = 0 # initial number of commanders
477 self.inrom = 0 # initial number of commanders
478 self.instar = 0 # initial stars
479 self.intorps = 0 # initial/max torpedoes
480 self.torps = 0 # number of torpedoes
481 self.ship = 0 # ship type -- 'E' is Enterprise
482 self.abandoned = 0 # count of crew abandoned in space
483 self.length = 0 # length of game
484 self.klhere = 0 # klingons here
485 self.casual = 0 # causalties
486 self.nhelp = 0 # calls for help
487 self.nkinks = 0 # count of energy-barrier crossings
488 self.iplnet = None # planet # in quadrant
489 self.inplan = 0 # initial planets
490 self.nenhere = 0 # number of enemies in quadrant
491 self.irhere = 0 # Romulans in quadrant
492 self.isatb = 0 # =1 if super commander is attacking base
493 self.tourn = None # tournament number
494 self.proben = 0 # number of moves for probe
495 self.nprobes = 0 # number of probes available
496 self.inresor = 0.0 # initial resources
497 self.intime = 0.0 # initial time
498 self.inenrg = 0.0 # initial/max energy
499 self.inshld = 0.0 # initial/max shield
500 self.inlsr = 0.0 # initial life support resources
501 self.indate = 0.0 # initial date
502 self.energy = 0.0 # energy level
503 self.shield = 0.0 # shield level
504 self.warpfac = 0.0 # warp speed
505 self.wfacsq = 0.0 # squared warp factor
506 self.lsupres = 0.0 # life support reserves
507 self.dist = 0.0 # movement distance
508 self.direc = 0.0 # movement direction
509 self.optime = 0.0 # time taken by current operation
510 self.docfac = 0.0 # repair factor when docking (constant?)
511 self.damfac = 0.0 # damage factor
512 self.lastchart = 0.0 # time star chart was last updated
513 self.cryprob = 0.0 # probability that crystal will work
514 self.probex = 0.0 # location of probe
516 self.probeinx = 0.0 # probe x,y increment
517 self.probeiny = 0.0 #
518 self.height = 0.0 # height of orbit around planet
520 # Stas thinks this should be (C expression):
521 # game.state.remkl + game.state.remcom > 0 ?
522 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
523 # He says the existing expression is prone to divide-by-zero errors
524 # after killing the last klingon when score is shown -- perhaps also
525 # if the only remaining klingon is SCOM.
526 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
527 # From enumerated type 'feature'
548 # From enumerated type 'FINTYPE'
572 # From enumerated type 'COLORS'
591 # Log the results of pulling random numbers so we can check determinism.
597 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
600 def randrange(*args):
601 v = random.randrange(*args)
602 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
608 v *= args[0] # returns from [0, a1)
610 v = args[0] + v*args[1] # returns from [a1, a2)
611 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
614 # Code from ai.c begins here
616 def tryexit(look, ienm, loccom, irun):
617 # a bad guy attempts to bug out
619 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
620 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
621 if not VALID_QUADRANT(iq.x,iq.y) or \
622 game.state.galaxy[iq.x][iq.y].supernova or \
623 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
624 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
626 return False; # Romulans cannot escape!
628 # avoid intruding on another commander's territory
630 for n in range(game.state.remcom):
631 if game.state.kcmdr[n] == iq:
633 # refuse to leave if currently attacking starbase
634 if game.battle == game.quadrant:
636 # don't leave if over 1000 units of energy
637 if game.enemies[loccom].kpower > 1000.0:
639 # print escape message and move out of quadrant.
640 # we know this if either short or long range sensors are working
641 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
642 game.condition == docked:
643 crmena(True, ienm, "sector", game.enemies[loccom].kloc)
644 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
645 # handle local matters related to escape
646 game.quad[game.enemies[loccom].kloc.x][game.enemies[loccom].kloc.y] = IHDOT
647 game.enemies[loccom].kloc = game.enemies[game.nenhere].kloc
648 game.enemies[loccom].kavgd = game.enemies[game.nenhere].kavgd
649 game.enemies[loccom].kpower = game.enemies[game.nenhere].kpower
650 game.enemies[loccom].kdist = game.enemies[game.nenhere].kdist
653 if game.condition != docked:
655 # Handle global matters related to escape
656 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
657 game.state.galaxy[iq.x][iq.y].klingons += 1
663 schedule(FSCMOVE, 0.2777)
667 for n in range(game.state.remcom):
668 if game.state.kcmdr[n] == game.quadrant:
669 game.state.kcmdr[n]=iq
672 return True; # success
675 # The bad-guy movement algorithm:
677 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
678 # If both are operating full strength, force is 1000. If both are damaged,
679 # force is -1000. Having shields down subtracts an additional 1000.
681 # 2. Enemy has forces equal to the energy of the attacker plus
682 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
683 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
685 # Attacker Initial energy levels (nominal):
686 # Klingon Romulan Commander Super-Commander
687 # Novice 400 700 1200
689 # Good 450 800 1300 1750
690 # Expert 475 850 1350 1875
691 # Emeritus 500 900 1400 2000
692 # VARIANCE 75 200 200 200
694 # Enemy vessels only move prior to their attack. In Novice - Good games
695 # only commanders move. In Expert games, all enemy vessels move if there
696 # is a commander present. In Emeritus games all enemy vessels move.
698 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
699 # forces are 1000 greater than Enterprise.
701 # Agressive action on average cuts the distance between the ship and
702 # the enemy to 1/4 the original.
704 # 4. At lower energy advantage, movement units are proportional to the
705 # advantage with a 650 advantage being to hold ground, 800 to move forward
706 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
708 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
709 # retreat, especially at high skill levels.
711 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
714 def movebaddy(com, loccom, ienm):
715 # tactical movement for the bad guys
716 next = coord(); look = coord()
718 # This should probably be just game.comhere + game.ishere
719 if game.skill >= SKILL_EXPERT:
720 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
722 nbaddys = game.comhere + game.ishere
724 dist1 = game.enemies[loccom].kdist
725 mdist = int(dist1 + 0.5); # Nearest integer distance
727 # If SC, check with spy to see if should hi-tail it
729 (game.enemies[loccom].kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
733 # decide whether to advance, retreat, or hold position
734 forces = game.enemies[loccom].kpower+100.0*game.nenhere+400*(nbaddys-1)
736 forces += 1000; # Good for enemy if shield is down!
737 if not damaged(DPHASER) or not damaged(DPHOTON):
738 if damaged(DPHASER): # phasers damaged
741 forces -= 0.2*(game.energy - 2500.0)
742 if damaged(DPHOTON): # photon torpedoes damaged
745 forces -= 50.0*game.torps
747 # phasers and photon tubes both out!
750 if forces <= 1000.0 and game.condition != "docked": # Typical situation
751 motion = ((forces + randreal(200))/150.0) - 5.0
753 if forces > 1000.0: # Very strong -- move in for kill
754 motion = (1.0-square(randreal()))*dist1 + 1.0
755 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
756 motion -= game.skill*(2.0-square(randreal()))
758 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
759 # don't move if no motion
762 # Limit motion according to skill
763 if abs(motion) > game.skill:
768 # calculate preferred number of steps
773 if motion > 0 and nsteps > mdist:
774 nsteps = mdist; # don't overshoot
775 if nsteps > QUADSIZE:
776 nsteps = QUADSIZE; # This shouldn't be necessary
778 nsteps = 1; # This shouldn't be necessary
780 proutn("NSTEPS = %d:" % nsteps)
781 # Compute preferred values of delta X and Y
782 mx = game.sector.x - com.x
783 my = game.sector.y - com.y
784 if 2.0 * abs(mx) < abs(my):
786 if 2.0 * abs(my) < abs(game.sector.x-com.x):
800 for ll in range(nsteps):
802 proutn(" %d" % (ll+1))
803 # Check if preferred position available
815 attempts = 0; # Settle mysterious hang problem
816 while attempts < 20 and not success:
818 if look.x < 0 or look.x >= QUADSIZE:
819 if motion < 0 and tryexit(look, ienm, loccom, irun):
821 if krawlx == mx or my == 0:
823 look.x = next.x + krawlx
825 elif look.y < 0 or look.y >= QUADSIZE:
826 if motion < 0 and tryexit(look, ienm, loccom, irun):
828 if krawly == my or mx == 0:
830 look.y = next.y + krawly
832 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
833 # See if we should ram ship
834 if game.quad[look.x][look.y] == game.ship and \
835 (ienm == IHC or ienm == IHS):
838 if krawlx != mx and my != 0:
839 look.x = next.x + krawlx
841 elif krawly != my and mx != 0:
842 look.y = next.y + krawly
845 break; # we have failed
857 # Put commander in place within same quadrant
858 game.quad[com.x][com.y] = IHDOT
859 game.quad[next.x][next.y] = ienm
862 game.enemies[loccom].kloc = next
863 game.enemies[loccom].kdist = game.enemies[loccom].kavgd = distance(game.sector, next)
864 if not damaged(DSRSENS) or game.condition == docked:
867 proutn(_(" from Sector %s") % com)
868 if game.enemies[loccom].kdist < dist1:
869 proutn(_(" advances to "))
871 proutn(_(" retreats to "))
872 prout("Sector %s." % next)
875 # Klingon tactical movement
878 # Figure out which Klingon is the commander (or Supercommander)
881 for i in range(game.nenhere):
882 w = game.enemies[i].kloc
883 if game.quad[w.x][w.y] == IHC:
887 for i in range(game.nenhere):
888 w = game.enemies[i].kloc
889 if game.quad[w.x][w.y] == IHS:
892 # If skill level is high, move other Klingons and Romulans too!
893 # Move these last so they can base their actions on what the
895 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
896 for i in range(game.nenhere):
897 w = game.enemies[i].kloc
898 if game.quad[w.x][w.y] == IHK or game.quad[w.x][w.y] == IHR:
899 movebaddy(w, i, game.quad[w.x][w.y])
900 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
902 def movescom(iq, avoid):
903 # commander movement helper
904 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
905 game.state.galaxy[iq.x][iq.y].supernova or \
906 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
909 # Avoid quadrants with bases if we want to avoid Enterprise
910 for i in range(game.state.rembase):
911 if game.state.baseq[i] == iq:
913 if game.justin and not game.iscate:
916 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
917 game.state.kscmdr = iq
918 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
920 # SC has scooted, Remove him from current quadrant
926 for i in range(game.nenhere):
927 if game.quad[game.enemies[i].kloc.x][game.enemies[i].kloc.y] == IHS:
929 game.quad[game.enemies[i].kloc.x][game.enemies[i].kloc.y] = IHDOT
930 game.enemies[i].kloc = game.enemies[game.nenhere].kloc
931 game.enemies[i].kdist = game.enemies[game.nenhere].kdist
932 game.enemies[i].kavgd = game.enemies[game.nenhere].kavgd
933 game.enemies[i].kpower = game.enemies[game.nenhere].kpower
936 if game.condition!=docked:
938 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
939 # check for a helpful planet
940 for i in range(game.inplan):
941 if game.state.planets[i].w == game.state.kscmdr and \
942 game.state.planets[i].crystals == "present":
944 game.state.planets[i].pclass = "destroyed"
945 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
948 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
949 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
950 prout(_(" by the Super-commander.\""))
952 return False; # looks good!
954 def supercommander():
955 # move the Super Commander
956 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
959 prout("== SUPERCOMMANDER")
960 # Decide on being active or passive
961 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 \
962 (game.state.date-game.indate) < 3.0)
963 if not game.iscate and avoid:
964 # compute move away from Enterprise
965 idelta = game.state.kscmdr-game.quadrant
966 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
968 idelta.x = game.state.kscmdr.y-game.quadrant.y
969 idelta.y = game.quadrant.x-game.state.kscmdr.x
971 # compute distances to starbases
972 if game.state.rembase <= 0:
976 sc = game.state.kscmdr
977 for i in range(game.state.rembase):
978 basetbl.append((i, distance(game.state.baseq[i], sc)))
979 if game.state.rembase > 1:
980 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
981 # look for nearest base without a commander, no Enterprise, and
982 # without too many Klingons, and not already under attack.
983 ifindit = iwhichb = 0
984 for i2 in range(game.state.rembase):
985 i = basetbl[i2][0]; # bug in original had it not finding nearest
986 ibq = game.state.baseq[i]
987 if ibq == game.quadrant or ibq == game.battle or \
988 game.state.galaxy[ibq.x][ibq.y].supernova or \
989 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
991 # if there is a commander, and no other base is appropriate,
992 # we will take the one with the commander
993 for j in range(game.state.remcom):
994 if ibq == game.state.kcmdr[j] and ifindit!= 2:
998 if j > game.state.remcom: # no commander -- use this one
1003 return; # Nothing suitable -- wait until next time
1004 ibq = game.state.baseq[iwhichb]
1005 # decide how to move toward base
1006 idelta = ibq - game.state.kscmdr
1007 # Maximum movement is 1 quadrant in either or both axes
1008 idelta = idelta.sgn()
1009 # try moving in both x and y directions
1010 # there was what looked like a bug in the Almy C code here,
1011 # but it might be this translation is just wrong.
1012 iq = game.state.kscmdr + idelta
1013 if movescom(iq, avoid):
1014 # failed -- try some other maneuvers
1015 if idelta.x==0 or idelta.y==0:
1016 # attempt angle move
1018 iq.y = game.state.kscmdr.y + 1
1019 if movescom(iq, avoid):
1020 iq.y = game.state.kscmdr.y - 1
1023 iq.x = game.state.kscmdr.x + 1
1024 if movescom(iq, avoid):
1025 iq.x = game.state.kscmdr.x - 1
1028 # try moving just in x or y
1029 iq.y = game.state.kscmdr.y
1030 if movescom(iq, avoid):
1031 iq.y = game.state.kscmdr.y + idelta.y
1032 iq.x = game.state.kscmdr.x
1035 if game.state.rembase == 0:
1038 for i in range(game.state.rembase):
1039 ibq = game.state.baseq[i]
1040 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1043 return; # no, don't attack base!
1044 game.iseenit = False
1046 schedule(FSCDBAS, randreal(1.0, 3.0))
1047 if is_scheduled(FCDBAS):
1048 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1049 if not communicating():
1050 return; # no warning
1053 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1054 % game.state.kscmdr)
1055 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1056 proutn(_(" It can survive until stardate %d.\"") \
1057 % int(scheduled(FSCDBAS)))
1058 if not game.resting:
1060 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1063 game.resting = False
1064 game.optime = 0.0; # actually finished
1066 # Check for intelligence report
1069 (not communicating()) or \
1070 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1073 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1074 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1079 if not game.tholian or game.justin:
1081 if game.tholian.x == 0 and game.tholian.y == 0:
1082 idx = 0; idy = QUADSIZE-1
1083 elif game.tholian.x == 0 and game.tholian.y == QUADSIZE-1:
1084 idx = QUADSIZE-1; idy = QUADSIZE-1
1085 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == QUADSIZE-1:
1086 idx = QUADSIZE-1; idy = 0
1087 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == 0:
1090 # something is wrong!
1093 # do nothing if we are blocked
1094 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1096 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1097 if game.tholian.x != idx:
1099 im = math.fabs(idx - game.tholian.x)*1.0/(idx - game.tholian.x)
1100 while game.tholian.x != idx:
1101 game.tholian.x += im
1102 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1103 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1104 elif game.tholian.y != idy:
1106 im = math.fabs(idy - game.tholian.y)*1.0/(idy - game.tholian.y)
1107 while game.tholian.y != idy:
1108 game.tholian.y += im
1109 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1110 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1111 game.quad[game.tholian.x][game.tholian.y] = IHT
1112 game.enemies[game.nenhere].kloc = game.tholian
1114 # check to see if all holes plugged
1115 for i in range(QUADSIZE):
1116 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1118 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1120 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1122 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1124 # All plugged up -- Tholian splits
1125 game.quad[game.tholian.x][game.tholian.y]=IHWEB
1127 crmena(True, IHT, "sector", game.tholian)
1128 prout(_(" completes web."))
1133 # Code from battle.c begins here
1135 def doshield(shraise):
1136 # change shield status
1144 if isit("transfer"):
1148 if damaged(DSHIELD):
1149 prout(_("Shields damaged and down."))
1156 proutn(_("Do you wish to change shield energy? "))
1158 proutn(_("Energy to transfer to shields- "))
1160 elif damaged(DSHIELD):
1161 prout(_("Shields damaged and down."))
1164 proutn(_("Shields are up. Do you want them down? "))
1171 proutn(_("Shields are down. Do you want them up? "))
1177 if action == "SHUP": # raise shields
1179 prout(_("Shields already up."))
1183 if game.condition != "docked":
1185 prout(_("Shields raised."))
1186 if game.energy <= 0:
1188 prout(_("Shields raising uses up last of energy."))
1193 elif action == "SHDN":
1195 prout(_("Shields already down."))
1199 prout(_("Shields lowered."))
1202 elif action == "NRG":
1203 while scan() != IHREAL:
1205 proutn(_("Energy to transfer to shields- "))
1209 if aaitem > game.energy:
1210 prout(_("Insufficient ship energy."))
1213 if game.shield+aaitem >= game.inshld:
1214 prout(_("Shield energy maximized."))
1215 if game.shield+aaitem > game.inshld:
1216 prout(_("Excess energy requested returned to ship energy"))
1217 game.energy -= game.inshld-game.shield
1218 game.shield = game.inshld
1220 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1221 # Prevent shield drain loophole
1223 prout(_("Engineering to bridge--"))
1224 prout(_(" Scott here. Power circuit problem, Captain."))
1225 prout(_(" I can't drain the shields."))
1228 if game.shield+aaitem < 0:
1229 prout(_("All shield energy transferred to ship."))
1230 game.energy += game.shield
1233 proutn(_("Scotty- \""))
1235 prout(_("Transferring energy to shields.\""))
1237 prout(_("Draining energy from shields.\""))
1238 game.shield += aaitem
1239 game.energy -= aaitem
1243 # choose a device to damage, at random.
1245 # Quoth Eric Allman in the code of BSD-Trek:
1246 # "Under certain conditions you can get a critical hit. This
1247 # sort of hit damages devices. The probability that a given
1248 # device is damaged depends on the device. Well protected
1249 # devices (such as the computer, which is in the core of the
1250 # ship and has considerable redundancy) almost never get
1251 # damaged, whereas devices which are exposed (such as the
1252 # warp engines) or which are particularly delicate (such as
1253 # the transporter) have a much higher probability of being
1256 # This is one place where OPTION_PLAIN does not restore the
1257 # original behavior, which was equiprobable damage across
1258 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1259 # and have done with it. Also, in the original game, DNAVYS
1260 # and DCOMPTR were the same device.
1262 # Instead, we use a table of weights similar to the one from BSD Trek.
1263 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1264 # We don't have a cloaking device. The shuttle got the allocation
1265 # for the cloaking device, then we shaved a half-percent off
1266 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1269 105, # DSRSENS: short range scanners 10.5%
1270 105, # DLRSENS: long range scanners 10.5%
1271 120, # DPHASER: phasers 12.0%
1272 120, # DPHOTON: photon torpedoes 12.0%
1273 25, # DLIFSUP: life support 2.5%
1274 65, # DWARPEN: warp drive 6.5%
1275 70, # DIMPULS: impulse engines 6.5%
1276 145, # DSHIELD: deflector shields 14.5%
1277 30, # DRADIO: subspace radio 3.0%
1278 45, # DSHUTTL: shuttle 4.5%
1279 15, # DCOMPTR: computer 1.5%
1280 20, # NAVCOMP: navigation system 2.0%
1281 75, # DTRANSP: transporter 7.5%
1282 20, # DSHCTRL: high-speed shield controller 2.0%
1283 10, # DDRAY: death ray 1.0%
1284 30, # DDSP: deep-space probes 3.0%
1286 idx = randrange(1000) # weights must sum to 1000
1288 for (i, w) in enumerate(weights):
1292 return None; # we should never get here
1294 def ram(ibumpd, ienm, w):
1295 # make our ship ram something
1296 prouts(_("***RED ALERT! RED ALERT!"))
1298 prout(_("***COLLISION IMMINENT."))
1302 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1304 proutn(_(" rammed by "))
1307 crmena(False, ienm, "sector", w)
1309 proutn(_(" (original position)"))
1311 deadkl(w, ienm, game.sector)
1314 prout(_(" heavily damaged."))
1315 icas = randrange(10, 30)
1316 prout(_("***Sickbay reports %d casualties"), icas)
1318 game.state.crew -= icas
1320 # In the pre-SST2K version, all devices got equiprobably damaged,
1321 # which was silly. Instead, pick up to half the devices at
1322 # random according to our weighting table,
1324 ncrits = randrange(NDEVICES/2)
1325 for m in range(ncrits):
1327 if game.damage[dev] < 0:
1329 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1330 # Damage for at least time of travel!
1331 game.damage[dev] += game.optime + extradm
1333 prout(_("***Shields are down."))
1334 if game.state.remkl + game.state.remcom + game.state.nscrem:
1341 def torpedo(course, r, incoming, i, n):
1342 # let a photon torpedo fly
1345 ac = course + 0.25*r
1346 angle = (15.0-ac)*0.5235988
1347 bullseye = (15.0 - course)*0.5235988
1348 deltax = -math.sin(angle);
1349 deltay = math.cos(angle);
1350 x = incoming.x; y = incoming.y
1351 w = coord(); jw = coord()
1352 w.x = w.y = jw.x = jw.y = 0
1353 bigger = max(math.fabs(deltax), math.fabs(deltay))
1356 if not damaged(DSRSENS) or game.condition=="docked":
1357 setwnd(srscan_window)
1359 setwnd(message_window)
1360 # Loop to move a single torpedo
1361 for l in range(1, 15+1):
1366 if not VALID_SECTOR(w.x, w.y):
1368 iquad=game.quad[w.x][w.y]
1369 tracktorpedo(w, l, i, n, iquad)
1373 setwnd(message_window)
1374 if damaged(DSRSENS) and not game.condition=="docked":
1375 skip(1); # start new line after text track
1376 if iquad in (IHE, IHF): # Hit our ship
1378 proutn(_("Torpedo hits "))
1381 hit = 700.0 + randreal(100) - \
1382 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1383 newcnd(); # we're blown out of dock
1384 # We may be displaced.
1385 if game.landed or game.condition=="docked":
1386 return hit # Cheat if on a planet
1387 ang = angle + 2.5*(randreal()-0.5)
1388 temp = math.fabs(math.sin(ang))
1389 if math.fabs(math.cos(ang)) > temp:
1390 temp = math.fabs(math.cos(ang))
1391 xx = -math.sin(ang)/temp
1392 yy = math.cos(ang)/temp
1395 if not VALID_SECTOR(jw.x, jw.y):
1397 if game.quad[jw.x][jw.y]==IHBLANK:
1400 if game.quad[jw.x][jw.y]!=IHDOT:
1401 # can't move into object
1406 elif iquad in (IHC, IHS): # Hit a commander
1408 crmena(True, iquad, "sector", w)
1409 prout(_(" uses anti-photon device;"))
1410 prout(_(" torpedo neutralized."))
1412 elif iquad in (IHR, IHK): # Hit a regular enemy
1414 for ll in range(game.nenhere):
1415 if w == game.enemies[ll].kloc:
1417 kp = math.fabs(game.enemies[ll].kpower)
1418 h1 = 700.0 + randrange(100) - \
1419 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1423 if game.enemies[ll].kpower < 0:
1424 game.enemies[ll].kpower -= -h1
1426 game.enemies[ll].kpower -= h1
1427 if game.enemies[ll].kpower == 0:
1430 crmena(True, iquad, "sector", w)
1431 # If enemy damaged but not destroyed, try to displace
1432 ang = angle + 2.5*(randreal()-0.5)
1433 temp = math.fabs(math.sin(ang))
1434 if math.fabs(math.cos(ang)) > temp:
1435 temp = math.fabs(math.cos(ang))
1436 xx = -math.sin(ang)/temp
1437 yy = math.cos(ang)/temp
1440 if not VALID_SECTOR(jw.x, jw.y):
1441 prout(_(" damaged but not destroyed."))
1443 if game.quad[jw.x][jw.y]==IHBLANK:
1444 prout(_(" buffeted into black hole."))
1445 deadkl(w, iquad, jw)
1447 if game.quad[jw.x][jw.y]!=IHDOT:
1448 # can't move into object
1449 prout(_(" damaged but not destroyed."))
1451 proutn(_(" damaged--"))
1452 game.enemies[ll].kloc = jw
1455 elif iquad == IHB: # Hit a base
1457 prout(_("***STARBASE DESTROYED.."))
1458 for ll in range(game.state.rembase):
1459 if game.state.baseq[ll] == game.quadrant:
1460 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1462 game.quad[w.x][w.y]=IHDOT
1463 game.state.rembase -= 1
1464 game.base.x=game.base.y=0
1465 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1466 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1467 game.state.basekl += 1
1470 elif iquad == IHP: # Hit a planet
1471 crmena(True, iquad, "sector", w)
1472 prout(_(" destroyed."))
1473 game.state.nplankl += 1
1474 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1475 game.iplnet.pclass = "destroyed"
1477 invalidate(game.plnet)
1478 game.quad[w.x][w.y] = IHDOT
1480 # captain perishes on planet
1483 elif iquad == IHW: # Hit an inhabited world -- very bad!
1484 crmena(True, iquad, "sector", w)
1485 prout(_(" destroyed."))
1486 game.state.nworldkl += 1
1487 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1488 game.iplnet.pclass = "destroyed"
1490 invalidate(game.plnet)
1491 game.quad[w.x][w.y] = IHDOT
1493 # captain perishes on planet
1495 prout(_("You have just destroyed an inhabited planet."))
1496 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1498 elif iquad == IHSTAR: # Hit a star
1502 crmena(True, IHSTAR, "sector", w)
1503 prout(_(" unaffected by photon blast."))
1505 elif iquad == IHQUEST: # Hit a thingy
1506 if not (game.options & OPTION_THINGY) or withprob(0.3):
1508 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1510 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1512 proutn(_("Mr. Spock-"))
1513 prouts(_(" \"Fascinating!\""))
1518 # Stas Sergeev added the possibility that
1519 # you can shove the Thingy and piss it off.
1520 # It then becomes an enemy and may fire at you.
1526 elif iquad == IHBLANK: # Black hole
1528 crmena(True, IHBLANK, "sector", w)
1529 prout(_(" swallows torpedo."))
1531 elif iquad == IHWEB: # hit the web
1533 prout(_("***Torpedo absorbed by Tholian web."))
1535 elif iquad == IHT: # Hit a Tholian
1536 h1 = 700.0 + randrange(100) - \
1537 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1540 game.quad[w.x][w.y] = IHDOT
1545 crmena(True, IHT, "sector", w)
1547 prout(_(" survives photon blast."))
1549 prout(_(" disappears."))
1550 game.quad[w.x][w.y] = IHWEB
1557 proutn("Don't know how to handle torpedo collision with ")
1558 crmena(True, iquad, "sector", w)
1562 if curwnd!=message_window:
1563 setwnd(message_window)
1565 game.quad[w.x][w.y]=IHDOT
1566 game.quad[jw.x][jw.y]=iquad
1567 prout(_(" displaced by blast to Sector %s ") % jw)
1568 for ll in range(game.nenhere):
1569 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector,game.enemies[ll].kloc)
1570 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1573 prout(_("Torpedo missed."))
1577 # critical-hit resolution
1578 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1580 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1581 proutn(_("***CRITICAL HIT--"))
1582 # Select devices and cause damage
1584 for loop1 in range(ncrit):
1587 # Cheat to prevent shuttle damage unless on ship
1588 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1591 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1592 game.damage[j] += extradm
1594 for (i, j) in enumerate(cdam):
1596 if skipcount % 3 == 2 and i < len(cdam)-1:
1601 prout(_(" damaged."))
1602 if damaged(DSHIELD) and game.shldup:
1603 prout(_("***Shields knocked down."))
1606 def attack(torps_ok):
1607 # bad guy attacks us
1608 # torps_ok == false forces use of phasers in an attack
1609 atackd = False; attempt = False; ihurt = False;
1610 hitmax=0.0; hittot=0.0; chgfac=1.0
1613 # game could be over at this point, check
1617 prout("=== ATTACK!")
1618 # Tholian gets to move before attacking
1621 # if you have just entered the RNZ, you'll get a warning
1622 if game.neutz: # The one chance not to be attacked
1625 # commanders get a chance to tac-move towards you
1626 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1628 # if no enemies remain after movement, we're done
1629 if game.nenhere==0 or (game.nenhere==1 and thing == game.quadrant and not iqengry):
1631 # set up partial hits if attack happens during shield status change
1632 pfac = 1.0/game.inshld
1634 chgfac = 0.25 + randreal(0.5)
1636 # message verbosity control
1637 if game.skill <= SKILL_FAIR:
1639 for loop in range(game.nenhere):
1640 if game.enemies[loop].kpower < 0:
1641 continue; # too weak to attack
1642 # compute hit strength and diminish shield power
1644 # Increase chance of photon torpedos if docked or enemy energy low
1645 if game.condition == "docked":
1647 if game.enemies[loop].kpower < 500:
1649 jay = game.enemies[loop].kloc
1650 iquad = game.quad[jay.x][jay.y]
1651 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1653 # different enemies have different probabilities of throwing a torp
1654 usephasers = not torps_ok or \
1655 (iquad == IHK and r > 0.0005) or \
1656 (iquad==IHC and r > 0.015) or \
1657 (iquad==IHR and r > 0.3) or \
1658 (iquad==IHS and r > 0.07) or \
1659 (iquad==IHQUEST and r > 0.05)
1660 if usephasers: # Enemy uses phasers
1661 if game.condition == "docked":
1662 continue; # Don't waste the effort!
1663 attempt = True; # Attempt to attack
1664 dustfac = 0.8 + randreal(0.5)
1665 hit = game.enemies[loop].kpower*math.pow(dustfac,game.enemies[loop].kavgd)
1666 game.enemies[loop].kpower *= 0.75
1667 else: # Enemy uses photon torpedo
1668 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1670 proutn(_("***TORPEDO INCOMING"))
1671 if not damaged(DSRSENS):
1673 crmena(False, iquad, where, jay)
1676 r = (randreal()+randreal())*0.5 - 0.5
1677 r += 0.002*game.enemies[loop].kpower*r
1678 hit = torpedo(course, r, jay, 1, 1)
1679 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1680 finish(FWON); # Klingons did themselves in!
1681 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1682 return; # Supernova or finished
1685 # incoming phaser or torpedo, shields may dissipate it
1686 if game.shldup or game.shldchg or game.condition=="docked":
1687 # shields will take hits
1688 propor = pfac * game.shield
1689 if game.condition =="docked":
1693 hitsh = propor*chgfac*hit+1.0
1695 if absorb > game.shield:
1696 absorb = game.shield
1697 game.shield -= absorb
1699 # taking a hit blasts us out of a starbase dock
1700 if game.condition == "docked":
1702 # but the shields may take care of it
1703 if propor > 0.1 and hit < 0.005*game.energy:
1705 # hit from this opponent got through shields, so take damage
1707 proutn(_("%d unit hit") % int(hit))
1708 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1709 proutn(_(" on the "))
1711 if not damaged(DSRSENS) and usephasers:
1713 crmena(False, iquad, where, jay)
1715 # Decide if hit is critical
1721 if game.energy <= 0:
1722 # Returning home upon your shield, not with it...
1725 if not attempt and game.condition == "docked":
1726 prout(_("***Enemies decide against attacking your ship."))
1729 percent = 100.0*pfac*game.shield+0.5
1731 # Shields fully protect ship
1732 proutn(_("Enemy attack reduces shield strength to "))
1734 # Print message if starship suffered hit(s)
1736 proutn(_("Energy left %2d shields ") % int(game.energy))
1739 elif not damaged(DSHIELD):
1742 proutn(_("damaged, "))
1743 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1744 # Check if anyone was hurt
1745 if hitmax >= 200 or hittot >= 500:
1746 icas = randrange(hittot * 0.015)
1749 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1750 prout(_(" in that last attack.\""))
1752 game.state.crew -= icas
1753 # After attack, reset average distance to enemies
1754 for loop in range(game.nenhere):
1755 game.enemies[loop].kavgd = game.enemies[loop].kdist
1756 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1759 def deadkl(w, type, mv):
1760 # kill a Klingon, Tholian, Romulan, or Thingy
1761 # Added mv to allow enemy to "move" before dying
1762 crmena(True, type, "sector", mv)
1763 # Decide what kind of enemy it is and update appropriately
1765 # chalk up a Romulan
1766 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1768 game.state.nromrem -= 1
1772 elif type == IHQUEST:
1778 # Some type of a Klingon
1779 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1782 game.comhere = False
1783 for i in range(game.state.remcom):
1784 if game.state.kcmdr[i] == game.quadrant:
1786 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1787 game.state.kcmdr[game.state.remcom].x = 0
1788 game.state.kcmdr[game.state.remcom].y = 0
1789 game.state.remcom -= 1
1791 if game.state.remcom != 0:
1792 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1794 game.state.remkl -= 1
1796 game.state.nscrem -= 1
1798 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1803 prout("*** Internal error, deadkl() called on %s\n" % type)
1804 # For each kind of enemy, finish message to player
1805 prout(_(" destroyed."))
1806 game.quad[w.x][w.y] = IHDOT
1807 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1810 # Remove enemy ship from arrays describing local conditions
1811 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1813 for i in range(game.nenhere):
1814 if game.enemies[i].kloc == w:
1815 for j in range(i, game.nenhere):
1816 game.enemies[j].kloc = game.enemies[j+1].kloc
1817 game.enemies[j].kpower = game.enemies[j+1].kpower
1818 game.enemies[j].kavgd = game.enemies[j].kdist = game.enemies[j+1].kdist
1819 game.enemies[game.nenhere].kloc.x = 0
1820 game.enemies[game.nenhere].kloc.y = 0
1821 game.enemies[game.nenhere].kdist = 0
1822 game.enemies[game.nenhere].kavgd = 0
1823 game.enemies[game.nenhere].kpower = 0
1829 def targetcheck(x, y):
1830 # Return None if target is invalid
1831 if not VALID_SECTOR(x, y):
1834 deltx = 0.1*(y - game.sector.y)
1835 delty = 0.1*(x - game.sector.x)
1836 if deltx==0 and delty== 0:
1838 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1839 prout(_(" I recommend an immediate review of"))
1840 prout(_(" the Captain's psychological profile.\""))
1843 return 1.90985932*math.atan2(deltx, delty)
1846 # launch photon torpedo
1848 if damaged(DPHOTON):
1849 prout(_("Photon tubes damaged."))
1853 prout(_("No torpedoes left."))
1862 prout(_("%d torpedoes left.") % game.torps)
1863 proutn(_("Number of torpedoes to fire- "))
1865 else: # key == IHREAL {
1867 if n <= 0: # abort command
1872 prout(_("Maximum of 3 torpedoes per burst."))
1879 for i in range(1, n+1):
1881 if i==1 and key == IHEOL:
1882 break; # we will try prompting
1883 if i==2 and key == IHEOL:
1884 # direct all torpedoes at one target
1886 targ[i][1] = targ[1][1]
1887 targ[i][2] = targ[1][2]
1888 course[i] = course[1]
1900 course[i] = targetcheck(targ[i][1], targ[i][2])
1901 if course[i] == None:
1904 if i == 1 and key == IHEOL:
1905 # prompt for each one
1906 for i in range(1, n+1):
1907 proutn(_("Target sector for torpedo number %d- ") % i)
1912 targ[i][1] = int(aaitem-0.5)
1917 targ[i][2] = int(aaitem-0.5)
1919 course[i] = targetcheck(targ[i][1], targ[i][2])
1920 if course[i] == None:
1923 # Loop for moving <n> torpedoes
1925 if game.condition != "docked":
1927 r = (randreal()+randreal())*0.5 -0.5
1928 if math.fabs(r) >= 0.47:
1930 r *= randreal(1.2, 2.2)
1932 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1934 prouts(_("***TORPEDO MISFIRES."))
1937 prout(_(" Remainder of burst aborted."))
1939 prout(_("***Photon tubes damaged by misfire."))
1940 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1942 if game.shldup or game.condition == "docked":
1943 r *= 1.0 + 0.0001*game.shield
1944 torpedo(course[i], r, game.sector, i, n)
1945 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1947 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1951 # check for phasers overheating
1953 checkburn = (rpow-1500.0)*0.00038
1954 if withprob(checkburn):
1955 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1956 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1958 def checkshctrl(rpow):
1959 # check shield control
1962 prout(_("Shields lowered."))
1964 # Something bad has happened
1965 prouts(_("***RED ALERT! RED ALERT!"))
1967 hit = rpow*game.shield/game.inshld
1968 game.energy -= rpow+hit*0.8
1969 game.shield -= hit*0.2
1970 if game.energy <= 0.0:
1971 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1976 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1978 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1979 icas = randrange(hit*0.012)
1984 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1985 prout(_(" %d casualties so far.\"") % icas)
1987 game.state.crew -= icas
1989 prout(_("Phaser energy dispersed by shields."))
1990 prout(_("Enemy unaffected."))
1995 # register a phaser hit on Klingons and Romulans
1996 nenhr2 = game.nenhere; kk=0
1999 for (k, wham) in enumerate(hits):
2002 dustfac = randreal(0.9, 1.0)
2003 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
2004 kpini = game.enemies[kk].kpower
2005 kp = math.fabs(kpini)
2006 if PHASEFAC*hit < kp:
2008 if game.enemies[kk].kpower < 0:
2009 game.enemies[kk].kpower -= -kp
2011 game.enemies[kk].kpower -= kp
2012 kpow = game.enemies[kk].kpower
2013 w = game.enemies[kk].kloc
2015 if not damaged(DSRSENS):
2017 proutn(_("%d unit hit on ") % int(hit))
2019 proutn(_("Very small hit on "))
2020 ienm = game.quad[w.x][w.y]
2024 crmena(False, ienm, "sector", w)
2028 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2032 kk -= 1 # don't do the increment
2034 else: # decide whether or not to emasculate klingon
2035 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2036 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2037 prout(_(" has just lost its firepower.\""))
2038 game.enemies[kk].kpower = -kpow
2045 kz = 0; k = 1; irec=0 # Cheating inhibitor
2046 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2050 # SR sensors and Computer are needed fopr automode
2051 if damaged(DSRSENS) or damaged(DCOMPTR):
2053 if game.condition == "docked":
2054 prout(_("Phasers can't be fired through base shields."))
2057 if damaged(DPHASER):
2058 prout(_("Phaser control damaged."))
2062 if damaged(DSHCTRL):
2063 prout(_("High speed shield control damaged."))
2066 if game.energy <= 200.0:
2067 prout(_("Insufficient energy to activate high-speed shield control."))
2070 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2072 # Original code so convoluted, I re-did it all
2073 # (That was Tom Almy talking about the C code, I think -- ESR)
2074 while automode=="NOTSET":
2079 prout(_("There is no enemy present to select."))
2082 automode="AUTOMATIC"
2086 elif isit("automatic"):
2087 if (not itarg) and game.nenhere != 0:
2088 automode = "FORCEMAN"
2091 prout(_("Energy will be expended into space."))
2092 automode = "AUTOMATIC"
2101 prout(_("Energy will be expended into space."))
2102 automode = "AUTOMATIC"
2104 automode = "FORCEMAN"
2106 automode = "AUTOMATIC"
2110 prout(_("Energy will be expended into space."))
2111 automode = "AUTOMATIC"
2113 automode = "FORCEMAN"
2115 proutn(_("Manual or automatic? "))
2120 if automode == "AUTOMATIC":
2121 if key == IHALPHA and isit("no"):
2124 if key != IHREAL and game.nenhere != 0:
2125 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2130 for i in range(game.nenhere):
2131 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2133 proutn(_("%d units required. ") % irec)
2135 proutn(_("Units to fire= "))
2141 proutn(_("Energy available= %.2f") % avail)
2144 if not rpow > avail:
2151 if key == IHALPHA and isit("no"):
2154 game.energy -= 200; # Go and do it!
2155 if checkshctrl(rpow):
2163 for i in range(game.nenhere):
2167 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2168 over = randreal(1.01, 1.06) * hits[i]
2170 powrem -= hits[i] + over
2171 if powrem <= 0 and temp < hits[i]:
2180 if extra > 0 and not game.alldone:
2182 proutn(_("*** Tholian web absorbs "))
2184 proutn(_("excess "))
2185 prout(_("phaser energy."))
2187 prout(_("%d expended on empty space.") % int(extra))
2188 elif automode == "FORCEMAN":
2191 if damaged(DCOMPTR):
2192 prout(_("Battle computer damaged, manual fire only."))
2195 prouts(_("---WORKING---"))
2197 prout(_("Short-range-sensors-damaged"))
2198 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2199 prout(_("Manual-fire-must-be-used"))
2201 elif automode == "MANUAL":
2203 for k in range(game.nenhere):
2204 aim = game.enemies[k].kloc
2205 ienm = game.quad[aim.x][aim.y]
2207 proutn(_("Energy available= %.2f") % (avail-0.006))
2211 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2212 (ienm == IHC or ienm == IHS):
2214 prout(_(" can't be located without short range scan."))
2217 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2222 if itarg and k > kz:
2223 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2226 if not damaged(DCOMPTR):
2231 proutn(_("units to fire at "))
2232 crmena(False, ienm, "sector", aim)
2235 if key == IHALPHA and isit("no"):
2243 if k==1: # Let me say I'm baffled by this
2252 # If total requested is too much, inform and start over
2254 prout(_("Available energy exceeded -- try again."))
2257 key = scan(); # scan for next value
2260 # zero energy -- abort
2263 if key == IHALPHA and isit("no"):
2268 game.energy -= 200.0
2269 if checkshctrl(rpow):
2273 # Say shield raised or malfunction, if necessary
2280 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2281 prouts(_(" CLICK CLICK POP . . ."))
2282 prout(_(" No response, sir!"))
2285 prout(_("Shields raised."))
2290 # Code from events,c begins here.
2292 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2293 # event of each type active at any given time. Mostly these means we can
2294 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2295 # BSD Trek, from which we swiped the idea, can have up to 5.
2297 def unschedule(evtype):
2298 # remove an event from the schedule
2299 game.future[evtype].date = FOREVER
2300 return game.future[evtype]
2302 def is_scheduled(evtype):
2303 # is an event of specified type scheduled
2304 return game.future[evtype].date != FOREVER
2306 def scheduled(evtype):
2307 # when will this event happen?
2308 return game.future[evtype].date
2310 def schedule(evtype, offset):
2311 # schedule an event of specified type
2312 game.future[evtype].date = game.state.date + offset
2313 return game.future[evtype]
2315 def postpone(evtype, offset):
2316 # postpone a scheduled event
2317 game.future[evtype].date += offset
2320 # rest period is interrupted by event
2323 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2325 game.resting = False
2331 # run through the event queue looking for things to do
2333 fintim = game.state.date + game.optime; yank=0
2334 ictbeam = False; istract = False
2335 w = coord(); hold = coord()
2336 ev = event(); ev2 = event()
2338 def tractorbeam(yank):
2339 # tractor beaming cases merge here
2341 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2345 prout(_(" caught in long range tractor beam--"))
2346 # If Kirk & Co. screwing around on planet, handle
2347 atover(True) # atover(true) is Grab
2350 if game.icraft: # Caught in Galileo?
2353 # Check to see if shuttle is aboard
2354 if game.iscraft == "offship":
2357 prout(_("Galileo, left on the planet surface, is captured"))
2358 prout(_("by aliens and made into a flying McDonald's."))
2359 game.damage[DSHUTTL] = -10
2360 game.iscraft = "removed"
2362 prout(_("Galileo, left on the planet surface, is well hidden."))
2364 game.quadrant = game.state.kscmdr
2366 game.quadrant = game.state.kcmdr[i]
2367 game.sector = randplace(QUADSIZE)
2369 prout(_(" is pulled to Quadrant %s, Sector %s") \
2370 % (game.quadrant, game.sector))
2372 prout(_("(Remainder of rest/repair period cancelled.)"))
2373 game.resting = False
2375 if not damaged(DSHIELD) and game.shield > 0:
2376 doshield(shraise=True) # raise shields
2377 game.shldchg = False
2379 prout(_("(Shields not currently useable.)"))
2381 # Adjust finish time to time of tractor beaming
2382 fintim = game.state.date+game.optime
2384 if game.state.remcom <= 0:
2387 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2390 # Code merges here for any commander destroying base
2391 # Not perfect, but will have to do
2392 # Handle case where base is in same quadrant as starship
2393 if game.battle == game.quadrant:
2394 game.state.chart[game.battle.x][game.battle.y].starbase = False
2395 game.quad[game.base.x][game.base.y] = IHDOT
2396 game.base.x=game.base.y=0
2399 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2400 elif game.state.rembase != 1 and communicating():
2401 # Get word via subspace radio
2404 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2405 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2407 prout(_("the Klingon Super-Commander"))
2409 prout(_("a Klingon Commander"))
2410 game.state.chart[game.battle.x][game.battle.y].starbase = False
2411 # Remove Starbase from galaxy
2412 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2413 for i in range(1, game.state.rembase+1):
2414 if game.state.baseq[i] == game.battle:
2415 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2416 game.state.rembase -= 1
2418 # reinstate a commander's base attack
2422 invalidate(game.battle)
2425 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2426 for i in range(1, NEVENTS):
2427 if i == FSNOVA: proutn("=== Supernova ")
2428 elif i == FTBEAM: proutn("=== T Beam ")
2429 elif i == FSNAP: proutn("=== Snapshot ")
2430 elif i == FBATTAK: proutn("=== Base Attack ")
2431 elif i == FCDBAS: proutn("=== Base Destroy ")
2432 elif i == FSCMOVE: proutn("=== SC Move ")
2433 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2434 elif i == FDSPROB: proutn("=== Probe Move ")
2435 elif i == FDISTR: proutn("=== Distress Call ")
2436 elif i == FENSLV: proutn("=== Enslavement ")
2437 elif i == FREPRO: proutn("=== Klingon Build ")
2439 prout("%.2f" % (scheduled(i)))
2442 radio_was_broken = damaged(DRADIO)
2445 # Select earliest extraneous event, evcode==0 if no events
2450 for l in range(1, NEVENTS):
2451 if game.future[l].date < datemin:
2454 prout("== Event %d fires" % evcode)
2455 datemin = game.future[l].date
2456 xtime = datemin-game.state.date
2457 game.state.date = datemin
2458 # Decrement Federation resources and recompute remaining time
2459 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2461 if game.state.remtime <=0:
2464 # Any crew left alive?
2465 if game.state.crew <=0:
2468 # Is life support adequate?
2469 if damaged(DLIFSUP) and game.condition != "docked":
2470 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2473 game.lsupres -= xtime
2474 if game.damage[DLIFSUP] <= xtime:
2475 game.lsupres = game.inlsr
2478 if game.condition == "docked":
2479 repair /= game.docfac
2480 # Don't fix Deathray here
2481 for l in range(NDEVICES):
2482 if game.damage[l] > 0.0 and l != DDRAY:
2483 if game.damage[l]-repair > 0.0:
2484 game.damage[l] -= repair
2486 game.damage[l] = 0.0
2487 # If radio repaired, update star chart and attack reports
2488 if radio_was_broken and not damaged(DRADIO):
2489 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2490 prout(_(" surveillance reports are coming in."))
2492 if not game.iseenit:
2496 prout(_(" The star chart is now up to date.\""))
2498 # Cause extraneous event EVCODE to occur
2499 game.optime -= xtime
2500 if evcode == FSNOVA: # Supernova
2503 schedule(FSNOVA, expran(0.5*game.intime))
2504 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2506 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2507 if game.state.nscrem == 0 or \
2508 ictbeam or istract or \
2509 game.condition=="docked" or game.isatb==1 or game.iscate:
2511 if game.ientesc or \
2512 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2513 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2514 (damaged(DSHIELD) and \
2515 (game.energy < 2500 or damaged(DPHASER)) and \
2516 (game.torps < 5 or damaged(DPHOTON))):
2518 istract = ictbeam = True
2519 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2522 elif evcode == FTBEAM: # Tractor beam
2523 if game.state.remcom == 0:
2526 i = randrange(game.state.remcom)
2527 yank = distance(game.state.kcmdr[i], game.quadrant)
2528 if istract or game.condition == "docked" or yank == 0:
2529 # Drats! Have to reschedule
2531 game.optime + expran(1.5*game.intime/game.state.remcom))
2535 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2536 game.snapsht = copy.deepcopy(game.state)
2537 game.state.snap = True
2538 schedule(FSNAP, expran(0.5 * game.intime))
2539 elif evcode == FBATTAK: # Commander attacks starbase
2540 if game.state.remcom==0 or game.state.rembase==0:
2546 for j in range(game.state.rembase):
2547 for k in range(game.state.remcom):
2548 if game.state.baseq[j] == game.state.kcmdr[k] and \
2549 not game.state.baseq[j] == game.quadrant and \
2550 not game.state.baseq[j] == game.state.kscmdr:
2554 if j>game.state.rembase:
2555 # no match found -- try later
2556 schedule(FBATTAK, expran(0.3*game.intime))
2559 # commander + starbase combination found -- launch attack
2560 game.battle = game.state.baseq[j]
2561 schedule(FCDBAS, randreal(1.0, 4.0))
2562 if game.isatb: # extra time if SC already attacking
2563 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2564 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2565 game.iseenit = False
2566 if not communicating():
2567 continue # No warning :-(
2571 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2572 prout(_(" reports that it is under attack and that it can"))
2573 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2576 elif evcode == FSCDBAS: # Supercommander destroys base
2579 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2580 continue # WAS RETURN!
2582 game.battle = game.state.kscmdr
2584 elif evcode == FCDBAS: # Commander succeeds in destroying base
2587 # find the lucky pair
2588 for i in range(game.state.remcom):
2589 if game.state.kcmdr[i] == game.battle:
2591 if i > game.state.remcom or game.state.rembase == 0 or \
2592 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2593 # No action to take after all
2594 invalidate(game.battle)
2597 elif evcode == FSCMOVE: # Supercommander moves
2598 schedule(FSCMOVE, 0.2777)
2599 if not game.ientesc and not istract and game.isatb != 1 and \
2600 (not game.iscate or not game.justin):
2602 elif evcode == FDSPROB: # Move deep space probe
2603 schedule(FDSPROB, 0.01)
2604 game.probex += game.probeinx
2605 game.probey += game.probeiny
2606 i = (int)(game.probex/QUADSIZE +0.05)
2607 j = (int)(game.probey/QUADSIZE + 0.05)
2608 if game.probec.x != i or game.probec.y != j:
2611 if not VALID_QUADRANT(i, j) or \
2612 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2613 # Left galaxy or ran into supernova
2617 proutn(_("Lt. Uhura- \"The deep space probe "))
2618 if not VALID_QUADRANT(j, i):
2619 proutn(_("has left the galaxy"))
2621 proutn(_("is no longer transmitting"))
2625 if not communicating():
2628 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2629 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2630 # Update star chart if Radio is working or have access to radio
2632 chp = game.state.chart[game.probec.x][game.probec.y]
2633 chp.klingons = pdest.klingons
2634 chp.starbase = pdest.starbase
2635 chp.stars = pdest.stars
2636 pdest.charted = True
2637 game.proben -= 1 # One less to travel
2638 if game.proben == 0 and game.isarmed and pdest.stars:
2639 # lets blow the sucker!
2640 supernova(True, game.probec)
2642 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2644 elif evcode == FDISTR: # inhabited system issues distress call
2646 # try a whole bunch of times to find something suitable
2647 for i in range(100):
2648 # need a quadrant which is not the current one,
2649 # which has some stars which are inhabited and
2650 # not already under attack, which is not
2651 # supernova'ed, and which has some Klingons in it
2652 w = randplace(GALSIZE)
2653 q = game.state.galaxy[w.x][w.y]
2654 if not (game.quadrant == w or q.planet == None or \
2655 not q.planet.inhabited or \
2656 q.supernova or q.status!="secure" or q.klingons<=0):
2659 # can't seem to find one; ignore this call
2661 prout("=== Couldn't find location for distress event.")
2663 # got one!! Schedule its enslavement
2664 ev = schedule(FENSLV, expran(game.intime))
2666 q.status = distressed
2668 # tell the captain about it if we can
2670 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2672 prout(_("by a Klingon invasion fleet."))
2675 elif evcode == FENSLV: # starsystem is enslaved
2676 ev = unschedule(FENSLV)
2677 # see if current distress call still active
2678 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2682 q.status = "enslaved"
2684 # play stork and schedule the first baby
2685 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2686 ev2.quadrant = ev.quadrant
2688 # report the disaster if we can
2690 prout(_("Uhura- We've lost contact with starsystem %s") % \
2692 prout(_("in Quadrant %s.\n") % ev.quadrant)
2693 elif evcode == FREPRO: # Klingon reproduces
2694 # If we ever switch to a real event queue, we'll need to
2695 # explicitly retrieve and restore the x and y.
2696 ev = schedule(FREPRO, expran(1.0 * game.intime))
2697 # see if current distress call still active
2698 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2702 if game.state.remkl >=MAXKLGAME:
2703 continue # full right now
2704 # reproduce one Klingon
2706 if game.klhere >= MAXKLQUAD:
2708 # this quadrant not ok, pick an adjacent one
2709 for i in range(w.x - 1, w.x + 2):
2710 for j in range(w.y - 1, w.y + 2):
2711 if not VALID_QUADRANT(i, j):
2713 q = game.state.galaxy[w.x][w.y]
2714 # check for this quad ok (not full & no snova)
2715 if q.klingons >= MAXKLQUAD or q.supernova:
2719 continue # search for eligible quadrant failed
2724 game.state.remkl += 1
2726 if game.quadrant == w:
2728 game.enemies.append(newkling())
2729 # recompute time left
2731 # report the disaster if we can
2733 if game.quadrant == w:
2734 prout(_("Spock- sensors indicate the Klingons have"))
2735 prout(_("launched a warship from %s.") % q.planet)
2737 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2738 if q.planet != None:
2739 proutn(_("near %s") % q.planet)
2740 prout(_("in Quadrant %s.") % w)
2749 proutn(_("How long? "))
2754 origTime = delay = aaitem
2757 if delay >= game.state.remtime or game.nenhere != 0:
2758 proutn(_("Are you sure? "))
2761 # Alternate resting periods (events) with attacks
2765 game.resting = False
2766 if not game.resting:
2767 prout(_("%d stardates left.") % int(game.state.remtime))
2769 temp = game.optime = delay
2771 rtime = randreal(1.0, 2.0)
2775 if game.optime < delay:
2784 # Repair Deathray if long rest at starbase
2785 if origTime-delay >= 9.99 and game.condition == "docked":
2786 game.damage[DDRAY] = 0.0
2787 # leave if quadrant supernovas
2788 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2790 game.resting = False
2793 # A nova occurs. It is the result of having a star hit with a
2794 # photon torpedo, or possibly of a probe warhead going off.
2795 # Stars that go nova cause stars which surround them to undergo
2796 # the same probabilistic process. Klingons next to them are
2797 # destroyed. And if the starship is next to it, it gets zapped.
2798 # If the zap is too much, it gets destroyed.
2802 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2803 newc = coord(); scratch = coord()
2805 # Wow! We've supernova'ed
2806 supernova(False, nov)
2808 # handle initial nova
2809 game.quad[nov.x][nov.y] = IHDOT
2810 crmena(False, IHSTAR, "sector", nov)
2812 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2813 game.state.starkl += 1
2815 # Set up stack to recursively trigger adjacent stars
2816 bot = top = top2 = 1
2822 for mm in range(bot, top+1):
2823 for nn in range(1, 3+1): # nn,j represents coordinates around current
2824 for j in range(1, 3+1):
2827 scratch.x = hits[mm][1]+nn-2
2828 scratch.y = hits[mm][2]+j-2
2829 if not VALID_SECTOR(scratch.y, scratch.x):
2831 iquad = game.quad[scratch.x][scratch.y]
2832 # Empty space ends reaction
2833 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2835 elif iquad == IHSTAR: # Affect another star
2837 # This star supernovas
2838 scratch = supernova(False)
2841 hits[top2][1]=scratch.x
2842 hits[top2][2]=scratch.y
2843 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2844 game.state.starkl += 1
2845 crmena(True, IHSTAR, "sector", scratch)
2847 game.quad[scratch.x][scratch.y] = IHDOT
2848 elif iquad == IHP: # Destroy planet
2849 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2850 game.state.nplankl += 1
2851 crmena(True, IHP, "sector", scratch)
2852 prout(_(" destroyed."))
2853 game.iplnet.pclass = "destroyed"
2855 invalidate(game.plnet)
2859 game.quad[scratch.x][scratch.y] = IHDOT
2860 elif iquad == IHB: # Destroy base
2861 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2862 for i in range(game.state.rembase):
2863 if game.state.baseq[i] == game.quadrant:
2865 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2866 game.state.rembase -= 1
2867 invalidate(game.base)
2868 game.state.basekl += 1
2870 crmena(True, IHB, "sector", scratch)
2871 prout(_(" destroyed."))
2872 game.quad[scratch.x][scratch.y] = IHDOT
2873 elif iquad in (IHE, IHF): # Buffet ship
2874 prout(_("***Starship buffeted by nova."))
2876 if game.shield >= 2000.0:
2877 game.shield -= 2000.0
2879 diff = 2000.0 - game.shield
2883 prout(_("***Shields knocked out."))
2884 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2886 game.energy -= 2000.0
2887 if game.energy <= 0:
2890 # add in course nova contributes to kicking starship
2891 icx += game.sector.x-hits[mm][1]
2892 icy += game.sector.y-hits[mm][2]
2894 elif iquad == IHK: # kill klingon
2895 deadkl(scratch,iquad, scratch)
2896 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2897 for ll in range(game.nenhere):
2898 if game.enemies[ll].kloc == scratch:
2900 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2901 if game.enemies[ll].kpower <= 0.0:
2902 deadkl(scratch, iquad, scratch)
2904 newc.x = scratch.x + scratch.x - hits[mm][1]
2905 newc.y = scratch.y + scratch.y - hits[mm][2]
2906 crmena(True, iquad, "sector", scratch)
2907 proutn(_(" damaged"))
2908 if not VALID_SECTOR(newc.x, newc.y):
2909 # can't leave quadrant
2912 iquad1 = game.quad[newc.x][newc.y]
2913 if iquad1 == IHBLANK:
2914 proutn(_(", blasted into "))
2915 crmena(False, IHBLANK, "sector", newc)
2917 deadkl(scratch, iquad, newc)
2920 # can't move into something else
2923 proutn(_(", buffeted to Sector %s") % newc)
2924 game.quad[scratch.x][scratch.y] = IHDOT
2925 game.quad[newc.x][newc.y] = iquad
2926 game.enemies[ll].kloc = newc
2927 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector, newc)
2936 # Starship affected by nova -- kick it away.
2937 game.dist = kount*0.1
2940 game.direc = course[3*(icx+1)+icy+2]
2941 if game.direc == 0.0:
2943 if game.dist == 0.0:
2945 game.optime = 10.0*game.dist/16.0
2947 prout(_("Force of nova displaces starship."))
2948 imove(novapush=True)
2949 game.optime = 10.0*game.dist/16.0
2952 def supernova(induced, w=None):
2953 # star goes supernova
2960 # Scheduled supernova -- select star
2961 # logic changed here so that we won't favor quadrants in top
2963 for nq.x in range(GALSIZE):
2964 for nq.y in range(GALSIZE):
2965 stars += game.state.galaxy[nq.x][nq.y].stars
2967 return # nothing to supernova exists
2968 num = randrange(stars) + 1
2969 for nq.x in range(GALSIZE):
2970 for nq.y in range(GALSIZE):
2971 num -= game.state.galaxy[nq.x][nq.y].stars
2977 proutn("=== Super nova here?")
2980 if not nq == game.quadrant or game.justin:
2981 # it isn't here, or we just entered (treat as enroute)
2984 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2985 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2988 # we are in the quadrant!
2989 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2990 for ns.x in range(QUADSIZE):
2991 for ns.y in range(QUADSIZE):
2992 if game.quad[ns.x][ns.y]==IHSTAR:
2999 prouts(_("***RED ALERT! RED ALERT!"))
3001 prout(_("***Incipient supernova detected at Sector %s") % ns)
3002 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
3003 proutn(_("Emergency override attempts t"))
3004 prouts("***************")
3009 # destroy any Klingons in supernovaed quadrant
3010 kldead = game.state.galaxy[nq.x][nq.y].klingons
3011 game.state.galaxy[nq.x][nq.y].klingons = 0
3012 if nq == game.state.kscmdr:
3013 # did in the Supercommander!
3014 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
3018 if game.state.remcom:
3019 maxloop = game.state.remcom
3020 for l in range(maxloop):
3021 if game.state.kcmdr[l] == nq:
3022 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
3023 invalidate(game.state.kcmdr[game.state.remcom])
3024 game.state.remcom -= 1
3026 if game.state.remcom==0:
3029 game.state.remkl -= kldead
3030 # destroy Romulans and planets in supernovaed quadrant
3031 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
3032 game.state.galaxy[nq.x][nq.y].romulans = 0
3033 game.state.nromrem -= nrmdead
3035 for loop in range(game.inplan):
3036 if game.state.planets[loop].w == nq:
3037 game.state.planets[loop].pclass = "destroyed"
3039 # Destroy any base in supernovaed quadrant
3040 if game.state.rembase:
3041 maxloop = game.state.rembase
3042 for loop in range(maxloop):
3043 if game.state.baseq[loop] == nq:
3044 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3045 invalidate(game.state.baseq[game.state.rembase])
3046 game.state.rembase -= 1
3048 # If starship caused supernova, tally up destruction
3050 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3051 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3052 game.state.nplankl += npdead
3053 # mark supernova in galaxy and in star chart
3054 if game.quadrant == nq or communicating():
3055 game.state.galaxy[nq.x][nq.y].supernova = True
3056 # If supernova destroys last Klingons give special message
3057 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3060 prout(_("Lucky you!"))
3061 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3064 # if some Klingons remain, continue or die in supernova
3069 # Code from finish.c ends here.
3072 # self-destruct maneuver
3073 # Finish with a BANG!
3075 if damaged(DCOMPTR):
3076 prout(_("Computer damaged; cannot execute destruct sequence."))
3078 prouts(_("---WORKING---")); skip(1)
3079 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3080 prouts(" 10"); skip(1)
3081 prouts(" 9"); skip(1)
3082 prouts(" 8"); skip(1)
3083 prouts(" 7"); skip(1)
3084 prouts(" 6"); skip(1)
3086 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3088 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3090 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3094 if game.passwd != citem:
3095 prouts(_("PASSWORD-REJECTED;"))
3097 prouts(_("CONTINUITY-EFFECTED"))
3100 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3101 prouts(" 5"); skip(1)
3102 prouts(" 4"); skip(1)
3103 prouts(" 3"); skip(1)
3104 prouts(" 2"); skip(1)
3105 prouts(" 1"); skip(1)
3107 prouts(_("GOODBYE-CRUEL-WORLD"))
3115 prouts(_("********* Entropy of "))
3117 prouts(_(" maximized *********"))
3121 if game.nenhere != 0:
3122 whammo = 25.0 * game.energy
3124 while l <= game.nenhere:
3125 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3126 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3131 "Compute our rate of kils over time."
3132 elapsed = game.state.date - game.indate
3133 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3136 starting = (game.inkling + game.incom + game.inscom)
3137 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3138 return (starting - remaining)/elapsed
3142 badpt = 5.0*game.state.starkl + \
3144 10.0*game.state.nplankl + \
3145 300*game.state.nworldkl + \
3147 100.0*game.state.basekl +\
3149 if game.ship == IHF:
3151 elif game.ship == None:
3156 # end the game, with appropriate notfications
3160 prout(_("It is stardate %.1f.") % game.state.date)
3162 if ifin == FWON: # Game has been won
3163 if game.state.nromrem != 0:
3164 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3167 prout(_("You have smashed the Klingon invasion fleet and saved"))
3168 prout(_("the Federation."))
3173 badpt = 0.0 # Close enough!
3174 # killsPerDate >= RateMax
3175 if game.state.date-game.indate < 5.0 or \
3176 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3178 prout(_("In fact, you have done so well that Starfleet Command"))
3179 if game.skill == SKILL_NOVICE:
3180 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3181 elif game.skill == SKILL_FAIR:
3182 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3183 elif game.skill == SKILL_GOOD:
3184 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3185 elif game.skill == SKILL_EXPERT:
3186 prout(_("promotes you to Commodore Emeritus."))
3188 prout(_("Now that you think you're really good, try playing"))
3189 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3190 elif game.skill == SKILL_EMERITUS:
3192 proutn(_("Computer- "))
3193 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3195 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3197 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3199 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3201 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3203 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3205 prout(_("Now you can retire and write your own Star Trek game!"))
3207 elif game.skill >= SKILL_EXPERT:
3208 if game.thawed and not idebug:
3209 prout(_("You cannot get a citation, so..."))
3211 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3215 # Only grant long life if alive (original didn't!)
3217 prout(_("LIVE LONG AND PROSPER."))
3222 elif ifin == FDEPLETE: # Federation Resources Depleted
3223 prout(_("Your time has run out and the Federation has been"))
3224 prout(_("conquered. Your starship is now Klingon property,"))
3225 prout(_("and you are put on trial as a war criminal. On the"))
3226 proutn(_("basis of your record, you are "))
3227 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3228 prout(_("acquitted."))
3230 prout(_("LIVE LONG AND PROSPER."))
3232 prout(_("found guilty and"))
3233 prout(_("sentenced to death by slow torture."))
3237 elif ifin == FLIFESUP:
3238 prout(_("Your life support reserves have run out, and"))
3239 prout(_("you die of thirst, starvation, and asphyxiation."))
3240 prout(_("Your starship is a derelict in space."))
3242 prout(_("Your energy supply is exhausted."))
3244 prout(_("Your starship is a derelict in space."))
3245 elif ifin == FBATTLE:
3248 prout(_("has been destroyed in battle."))
3250 prout(_("Dulce et decorum est pro patria mori."))
3252 prout(_("You have made three attempts to cross the negative energy"))
3253 prout(_("barrier which surrounds the galaxy."))
3255 prout(_("Your navigation is abominable."))
3258 prout(_("Your starship has been destroyed by a nova."))
3259 prout(_("That was a great shot."))
3261 elif ifin == FSNOVAED:
3264 prout(_(" has been fried by a supernova."))
3265 prout(_("...Not even cinders remain..."))
3266 elif ifin == FABANDN:
3267 prout(_("You have been captured by the Klingons. If you still"))
3268 prout(_("had a starbase to be returned to, you would have been"))
3269 prout(_("repatriated and given another chance. Since you have"))
3270 prout(_("no starbases, you will be mercilessly tortured to death."))
3271 elif ifin == FDILITHIUM:
3272 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3273 elif ifin == FMATERIALIZE:
3274 prout(_("Starbase was unable to re-materialize your starship."))
3275 prout(_("Sic transit gloria mundi"))
3276 elif ifin == FPHASER:
3279 prout(_(" has been cremated by its own phasers."))
3281 prout(_("You and your landing party have been"))
3282 prout(_("converted to energy, disipating through space."))
3283 elif ifin == FMINING:
3284 prout(_("You are left with your landing party on"))
3285 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3287 prout(_("They are very fond of \"Captain Kirk\" soup."))
3289 proutn(_("Without your leadership, the "))
3291 prout(_(" is destroyed."))
3292 elif ifin == FDPLANET:
3293 prout(_("You and your mining party perish."))
3295 prout(_("That was a great shot."))
3298 prout(_("The Galileo is instantly annihilated by the supernova."))
3299 prout(_("You and your mining party are atomized."))
3301 proutn(_("Mr. Spock takes command of the "))
3304 prout(_("joins the Romulans, reigning terror on the Federation."))
3305 elif ifin == FPNOVA:
3306 prout(_("You and your mining party are atomized."))
3308 proutn(_("Mr. Spock takes command of the "))
3311 prout(_("joins the Romulans, reigning terror on the Federation."))
3312 elif ifin == FSTRACTOR:
3313 prout(_("The shuttle craft Galileo is also caught,"))
3314 prout(_("and breaks up under the strain."))
3316 prout(_("Your debris is scattered for millions of miles."))
3317 proutn(_("Without your leadership, the "))
3319 prout(_(" is destroyed."))
3321 prout(_("The mutants attack and kill Spock."))
3322 prout(_("Your ship is captured by Klingons, and"))
3323 prout(_("your crew is put on display in a Klingon zoo."))
3324 elif ifin == FTRIBBLE:
3325 prout(_("Tribbles consume all remaining water,"))
3326 prout(_("food, and oxygen on your ship."))
3328 prout(_("You die of thirst, starvation, and asphyxiation."))
3329 prout(_("Your starship is a derelict in space."))
3331 prout(_("Your ship is drawn to the center of the black hole."))
3332 prout(_("You are crushed into extremely dense matter."))
3334 prout(_("Your last crew member has died."))
3335 if game.ship == IHF:
3337 elif game.ship == IHE:
3340 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3341 goodies = game.state.remres/game.inresor
3342 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3343 if goodies/baddies >= randreal(1.0, 1.5):
3344 prout(_("As a result of your actions, a treaty with the Klingon"))
3345 prout(_("Empire has been signed. The terms of the treaty are"))
3346 if goodies/baddies >= randreal(3.0):
3347 prout(_("favorable to the Federation."))
3349 prout(_("Congratulations!"))
3351 prout(_("highly unfavorable to the Federation."))
3353 prout(_("The Federation will be destroyed."))
3355 prout(_("Since you took the last Klingon with you, you are a"))
3356 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3357 prout(_("statue in your memory. Rest in peace, and try not"))
3358 prout(_("to think about pigeons."))
3363 # compute player's score
3364 timused = game.state.date - game.indate
3366 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3368 perdate = killrate()
3369 ithperd = 500*perdate + 0.5
3372 iwon = 100*game.skill
3373 if game.ship == IHE:
3375 elif game.ship == IHF:
3379 if not game.gamewon:
3380 game.state.nromrem = 0 # None captured if no win
3381 iscore = 10*(game.inkling - game.state.remkl) \
3382 + 50*(game.incom - game.state.remcom) \
3384 + 20*(game.inrom - game.state.nromrem) \
3385 + 200*(game.inscom - game.state.nscrem) \
3386 - game.state.nromrem \
3391 prout(_("Your score --"))
3392 if game.inrom - game.state.nromrem:
3393 prout(_("%6d Romulans destroyed %5d") %
3394 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3395 if game.state.nromrem:
3396 prout(_("%6d Romulans captured %5d") %
3397 (game.state.nromrem, game.state.nromrem))
3398 if game.inkling - game.state.remkl:
3399 prout(_("%6d ordinary Klingons destroyed %5d") %
3400 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3401 if game.incom - game.state.remcom:
3402 prout(_("%6d Klingon commanders destroyed %5d") %
3403 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3404 if game.inscom - game.state.nscrem:
3405 prout(_("%6d Super-Commander destroyed %5d") %
3406 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3408 prout(_("%6.2f Klingons per stardate %5d") %
3410 if game.state.starkl:
3411 prout(_("%6d stars destroyed by your action %5d") %
3412 (game.state.starkl, -5*game.state.starkl))
3413 if game.state.nplankl:
3414 prout(_("%6d planets destroyed by your action %5d") %
3415 (game.state.nplankl, -10*game.state.nplankl))
3416 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3417 prout(_("%6d inhabited planets destroyed by your action %5d") %
3418 (game.state.nplankl, -300*game.state.nworldkl))
3419 if game.state.basekl:
3420 prout(_("%6d bases destroyed by your action %5d") %
3421 (game.state.basekl, -100*game.state.basekl))
3423 prout(_("%6d calls for help from starbase %5d") %
3424 (game.nhelp, -45*game.nhelp))
3426 prout(_("%6d casualties incurred %5d") %
3427 (game.casual, -game.casual))
3429 prout(_("%6d crew abandoned in space %5d") %
3430 (game.abandoned, -3*game.abandoned))
3432 prout(_("%6d ship(s) lost or destroyed %5d") %
3433 (klship, -100*klship))
3435 prout(_("Penalty for getting yourself killed -200"))
3437 proutn(_("Bonus for winning "))
3438 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3439 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3440 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3441 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3442 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3443 prout(" %5d" % iwon)
3445 prout(_("TOTAL SCORE %5d") % iscore)
3448 # emit winner's commemmorative plaque
3451 proutn(_("File or device name for your plaque: "))
3454 fp = open(winner, "w")
3457 prout(_("Invalid name."))
3459 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3461 # The 38 below must be 64 for 132-column paper
3462 nskip = 38 - len(winner)/2
3463 fp.write("\n\n\n\n")
3464 # --------DRAW ENTERPRISE PICTURE.
3465 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3466 fp.write(" EEE E : : : E\n" )
3467 fp.write(" EE EEE E : : NCC-1701 : E\n")
3468 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3469 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3470 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3471 fp.write(" EEEEEEE EEEEE E E E E\n")
3472 fp.write(" EEE E E E E\n")
3473 fp.write(" E E E E\n")
3474 fp.write(" EEEEEEEEEEEEE E E\n")
3475 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3476 fp.write(" :E : EEEE E\n")
3477 fp.write(" .-E -:----- E\n")
3478 fp.write(" :E : E\n")
3479 fp.write(" EE : EEEEEEEE\n")
3480 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3482 fp.write(_(" U. S. S. ENTERPRISE\n"))
3483 fp.write("\n\n\n\n")
3484 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3486 fp.write(_(" Starfleet Command bestows to you\n"))
3488 fp.write("%*s%s\n\n" % (nskip, "", winner))
3489 fp.write(_(" the rank of\n\n"))
3490 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3492 if game.skill == SKILL_EXPERT:
3493 fp.write(_(" Expert level\n\n"))
3494 elif game.skill == SKILL_EMERITUS:
3495 fp.write(_("Emeritus level\n\n"))
3497 fp.write(_(" Cheat level\n\n"))
3498 timestring = ctime()
3499 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3500 (timestring+4, timestring+20, timestring+11))
3501 fp.write(_(" Your score: %d\n\n") % iscore)
3502 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3505 # Code from io.c begins here
3507 rows = linecount = 0 # for paging
3510 fullscreen_window = None
3511 srscan_window = None
3512 report_window = None
3513 status_window = None
3514 lrscan_window = None
3515 message_window = None
3516 prompt_window = None
3520 "wrap up, either normally or due to signal"
3521 if game.options & OPTION_CURSES:
3528 sys.stdout.write('\n')
3534 #setlocale(LC_ALL, "")
3535 #bindtextdomain(PACKAGE, LOCALEDIR)
3536 #textdomain(PACKAGE)
3537 if atexit.register(outro):
3538 sys.stderr.write("Unable to register outro(), exiting...\n")
3540 if not (game.options & OPTION_CURSES):
3541 ln_env = os.getenv("LINES")
3547 stdscr = curses.initscr()
3552 curses.start_color()
3553 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3554 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3555 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3556 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3557 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3558 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3559 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3560 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3562 global fullscreen_window, srscan_window, report_window, status_window
3563 global lrscan_window, message_window, prompt_window
3564 fullscreen_window = stdscr
3565 srscan_window = curses.newwin(12, 25, 0, 0)
3566 report_window = curses.newwin(11, 0, 1, 25)
3567 status_window = curses.newwin(10, 0, 1, 39)
3568 lrscan_window = curses.newwin(5, 0, 0, 64)
3569 message_window = curses.newwin(0, 0, 12, 0)
3570 prompt_window = curses.newwin(1, 0, rows-2, 0)
3571 message_window.scrollok(True)
3572 setwnd(fullscreen_window)
3576 "wait for user action -- OK to do nothing if on a TTY"
3577 if game.options & OPTION_CURSES:
3582 if game.skill > SKILL_FAIR:
3583 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3585 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3589 if game.skill > SKILL_FAIR:
3590 prompt = _("[CONTINUE?]")
3592 prompt = _("[PRESS ENTER TO CONTINUE]")
3594 if game.options & OPTION_CURSES:
3596 setwnd(prompt_window)
3597 prompt_window.wclear()
3598 prompt_window.addstr(prompt)
3599 prompt_window.getstr()
3600 prompt_window.clear()
3601 prompt_window.refresh()
3602 setwnd(message_window)
3605 sys.stdout.write('\n')
3608 for j in range(rows):
3609 sys.stdout.write('\n')
3613 "Skip i lines. Pause game if this would cause a scrolling event."
3614 for dummy in range(i):
3615 if game.options & OPTION_CURSES:
3616 (y, x) = curwnd.getyx()
3617 (my, mx) = curwnd.getmaxyx()
3618 if curwnd == message_window and y >= my - 3:
3626 if rows and linecount >= rows:
3629 sys.stdout.write('\n')
3632 "Utter a line with no following line feed."
3633 if game.options & OPTION_CURSES:
3637 sys.stdout.write(line)
3647 if not replayfp or replayfp.closed: # Don't slow down replays
3650 if game.options & OPTION_CURSES:
3654 if not replayfp or replayfp.closed:
3658 "Get a line of input."
3659 if game.options & OPTION_CURSES:
3660 line = curwnd.getstr() + "\n"
3663 if replayfp and not replayfp.closed:
3665 line = replayfp.readline()
3668 prout("*** Replay finished")
3671 elif line[0] != "#":
3676 logfp.write(line + "\n")
3680 "Change windows -- OK for this to be a no-op in tty mode."
3682 if game.options & OPTION_CURSES:
3684 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3687 "Clear to end of line -- can be a no-op in tty mode"
3688 if game.options & OPTION_CURSES:
3693 "Clear screen -- can be a no-op in tty mode."
3695 if game.options & OPTION_CURSES:
3701 def textcolor(color):
3702 "Set the current text color"
3703 if game.options & OPTION_CURSES:
3704 if color == DEFAULT:
3706 elif color == BLACK:
3707 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3709 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3710 elif color == GREEN:
3711 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3713 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3715 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3716 elif color == MAGENTA:
3717 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3718 elif color == BROWN:
3719 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3720 elif color == LIGHTGRAY:
3721 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3722 elif color == DARKGRAY:
3723 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3724 elif color == LIGHTBLUE:
3725 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3726 elif color == LIGHTGREEN:
3727 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3728 elif color == LIGHTCYAN:
3729 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3730 elif color == LIGHTRED:
3731 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3732 elif color == LIGHTMAGENTA:
3733 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3734 elif color == YELLOW:
3735 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3736 elif color == WHITE:
3737 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3740 "Set highlight video, if this is reasonable."
3741 if game.options & OPTION_CURSES:
3742 curwnd.attron(curses.A_REVERSE)
3745 # Things past this point have policy implications.
3749 "Hook to be called after moving to redraw maps."
3750 if game.options & OPTION_CURSES:
3753 setwnd(srscan_window)
3757 setwnd(status_window)
3758 status_window.clear()
3759 status_window.move(0, 0)
3760 setwnd(report_window)
3761 report_window.clear()
3762 report_window.move(0, 0)
3764 setwnd(lrscan_window)
3765 lrscan_window.clear()
3766 lrscan_window.move(0, 0)
3767 lrscan(silent=False)
3769 def put_srscan_sym(w, sym):
3770 "Emit symbol for short-range scan."
3771 srscan_window.move(w.x+1, w.y*2+2)
3772 srscan_window.addch(sym)
3773 srscan_window.refresh()
3776 "Enemy fall down, go boom."
3777 if game.options & OPTION_CURSES:
3779 setwnd(srscan_window)
3780 srscan_window.attron(curses.A_REVERSE)
3781 put_srscan_sym(w, game.quad[w.x][w.y])
3785 srscan_window.attroff(curses.A_REVERSE)
3786 put_srscan_sym(w, game.quad[w.x][w.y])
3787 curses.delay_output(500)
3788 setwnd(message_window)
3791 "Sound and visual effects for teleportation."
3792 if game.options & OPTION_CURSES:
3794 setwnd(message_window)
3796 prouts(" . . . . . ")
3797 if game.options & OPTION_CURSES:
3798 #curses.delay_output(1000)
3802 def tracktorpedo(w, l, i, n, iquad):
3803 "Torpedo-track animation."
3804 if not game.options & OPTION_CURSES:
3808 proutn(_("Track for torpedo number %d- ") % i)
3811 proutn(_("Torpedo track- "))
3814 proutn("%d - %d " % (w.x, w.y))
3816 if not damaged(DSRSENS) or game.condition=="docked":
3817 if i != 1 and l == 1:
3820 if (iquad==IHDOT) or (iquad==IHBLANK):
3821 put_srscan_sym(w, '+')
3825 put_srscan_sym(w, iquad)
3827 curwnd.attron(curses.A_REVERSE)
3828 put_srscan_sym(w, iquad)
3832 curwnd.attroff(curses.A_REVERSE)
3833 put_srscan_sym(w, iquad)
3835 proutn("%d - %d " % (w.x, w.y))
3838 "Display the current galaxy chart."
3839 if game.options & OPTION_CURSES:
3840 setwnd(message_window)
3841 message_window.clear()
3843 if game.options & OPTION_TTY:
3848 def prstat(txt, data):
3850 if game.options & OPTION_CURSES:
3852 setwnd(status_window)
3854 proutn(" " * (NSYM - len(txt)))
3857 if game.options & OPTION_CURSES:
3858 setwnd(report_window)
3860 # Code from moving.c begins here
3862 def imove(novapush):
3863 # movement execution for warp, impulse, supernova, and tractor-beam events
3864 w = coord(); final = coord()
3867 def no_quad_change():
3868 # No quadrant change -- compute new average enemy distances
3869 game.quad[game.sector.x][game.sector.y] = game.ship
3871 for m in range(game.nenhere):
3872 finald = distance(w, game.enemies[m].kloc)
3873 game.enemies[m].kavgd = 0.5 * (finald+game.enemies[m].kdist)
3874 game.enemies[m].kdist = finald
3875 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3876 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3878 for m in range(game.nenhere):
3879 game.enemies[m].kavgd = game.enemies[m].kdist
3882 setwnd(message_window)
3885 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3886 game.inorbit = False
3887 angle = ((15.0 - game.direc) * 0.5235988)
3888 deltax = -math.sin(angle)
3889 deltay = math.cos(angle)
3890 if math.fabs(deltax) > math.fabs(deltay):
3891 bigger = math.fabs(deltax)
3893 bigger = math.fabs(deltay)
3896 # If tractor beam is to occur, don't move full distance
3897 if game.state.date+game.optime >= scheduled(FTBEAM):
3899 game.condition = "red"
3900 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3901 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3902 # Move within the quadrant
3903 game.quad[game.sector.x][game.sector.y] = IHDOT
3906 n = int(10.0*game.dist*bigger+0.5)
3908 for m in range(1, n+1):
3913 if not VALID_SECTOR(w.x, w.y):
3914 # Leaving quadrant -- allow final enemy attack
3915 # Don't do it if being pushed by Nova
3916 if game.nenhere != 0 and not novapush:
3918 for m in range(game.nenhere):
3919 finald = distance(w, game.enemies[m].kloc)
3920 game.enemies[m].kavgd = 0.5 * (finald + game.enemies[m].kdist)
3922 # Stas Sergeev added the condition
3923 # that attacks only happen if Klingons
3924 # are present and your skill is good.
3926 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3930 # compute final position -- new quadrant and sector
3931 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3932 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3933 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3934 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3935 # check for edge of galaxy
3945 if w.x >= GALSIZE*QUADSIZE:
3946 w.x = (GALSIZE*QUADSIZE*2) - w.x
3948 if w.y >= GALSIZE*QUADSIZE:
3949 w.y = (GALSIZE*QUADSIZE*2) - w.y
3957 if game.nkinks == 3:
3958 # Three strikes -- you're out!
3962 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3963 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3964 prout(_("YOU WILL BE DESTROYED."))
3965 # Compute final position in new quadrant
3966 if trbeam: # Don't bother if we are to be beamed
3968 game.quadrant.x = w.x/QUADSIZE
3969 game.quadrant.y = w.y/QUADSIZE
3970 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3971 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3973 prout(_("Entering Quadrant %s.") % game.quadrant)
3974 game.quad[game.sector.x][game.sector.y] = game.ship
3976 if game.skill>SKILL_NOVICE:
3979 iquad = game.quad[w.x][w.y]
3981 # object encountered in flight path
3982 stopegy = 50.0*game.dist/game.optime
3983 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3984 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3986 ram(False, iquad, game.sector)
3988 elif iquad == IHBLANK:
3990 prouts(_("***RED ALERT! RED ALERT!"))
3994 proutn(_(" pulled into black hole at Sector %s") % w)
3996 # Getting pulled into a black hole was certain
3997 # death in Almy's original. Stas Sergeev added a
3998 # possibility that you'll get timewarped instead.
4001 for m in range(NDEVICES):
4002 if game.damage[m]>0:
4004 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
4005 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
4015 proutn(_(" encounters Tholian web at %s;") % w)
4017 proutn(_(" blocked by object at %s;") % w)
4018 proutn(_("Emergency stop required "))
4019 prout(_("%2d units of energy.") % int(stopegy))
4020 game.energy -= stopegy
4021 final.x = x-deltax+0.5
4022 final.y = y-deltay+0.5
4024 if game.energy <= 0:
4030 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4037 # dock our ship at a starbase
4039 if game.condition == "docked" and verbose:
4040 prout(_("Already docked."))
4043 prout(_("You must first leave standard orbit."))
4045 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4047 prout(_(" not adjacent to base."))
4049 game.condition = "docked"
4053 if game.energy < game.inenrg:
4054 game.energy = game.inenrg
4055 game.shield = game.inshld
4056 game.torps = game.intorps
4057 game.lsupres = game.inlsr
4058 game.state.crew = FULLCREW
4059 if not damaged(DRADIO) and \
4060 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4061 # get attack report from base
4062 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4066 # This program originally required input in terms of a (clock)
4067 # direction and distance. Somewhere in history, it was changed to
4068 # cartesian coordinates. So we need to convert. Probably
4069 # "manual" input should still be done this way -- it's a real
4070 # pain if the computer isn't working! Manual mode is still confusing
4071 # because it involves giving x and y motions, yet the coordinates
4072 # are always displayed y - x, where +y is downward!
4074 def getcourse(isprobe, akey):
4075 # get course and distance
4077 dquad = copy.copy(game.quadrant)
4078 navmode = "unspecified"
4082 if game.landed and not isprobe:
4083 prout(_("Dummy! You can't leave standard orbit until you"))
4084 proutn(_("are back aboard the ship."))
4087 while navmode == "unspecified":
4088 if damaged(DNAVSYS):
4090 prout(_("Computer damaged; manual navigation only"))
4092 prout(_("Computer damaged; manual movement only"))
4097 if isprobe and akey != -1:
4098 # For probe launch, use pre-scanned value first time
4104 proutn(_("Manual or automatic- "))
4107 elif key == IHALPHA:
4112 elif isit("automatic"):
4113 navmode = "automatic"
4122 prout(_("(Manual navigation assumed.)"))
4124 prout(_("(Manual movement assumed.)"))
4127 if navmode == "automatic":
4130 proutn(_("Target quadrant or quadrant§or- "))
4132 proutn(_("Destination sector or quadrant§or- "))
4139 xi = int(round(aaitem))-1
4144 xj = int(round(aaitem))-1
4147 # both quadrant and sector specified
4148 xk = int(round(aaitem))-1
4153 xl = int(round(aaitem))-1
4159 # only one pair of numbers was specified
4161 # only quadrant specified -- go to center of dest quad
4164 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4166 # only sector specified
4170 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4177 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4179 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4180 # the actual deltas get computed here
4181 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4182 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4185 proutn(_("X and Y displacements- "))
4199 # Check for zero movement
4200 if deltax == 0 and deltay == 0:
4203 if itemp == "verbose" and not isprobe:
4205 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4206 # Course actually laid in.
4207 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4208 game.direc = math.atan2(deltax, deltay)*1.90985932
4209 if game.direc < 0.0:
4215 # move under impulse power
4217 if damaged(DIMPULS):
4220 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4222 if game.energy > 30.0:
4223 if not getcourse(isprobe=False, akey=0):
4225 power = 20.0 + 100.0*game.dist
4228 if power >= game.energy:
4229 # Insufficient power for trip
4231 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4232 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4233 if game.energy > 30:
4234 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4235 int(0.01 * (game.energy-20.0)-0.05))
4236 prout(_(" quadrants.\""))
4238 prout(_("quadrant. They are, therefore, useless.\""))
4241 # Make sure enough time is left for the trip
4242 game.optime = game.dist/0.095
4243 if game.optime >= game.state.remtime:
4244 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4245 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4246 proutn(_("we dare spend the time?\" "))
4249 # Activate impulse engines and pay the cost
4250 imove(novapush=False)
4254 power = 20.0 + 100.0*game.dist
4255 game.energy -= power
4256 game.optime = game.dist/0.095
4257 if game.energy <= 0:
4262 # move under warp drive
4263 blooey = False; twarp = False
4264 if not timewarp: # Not WARPX entry
4266 if game.damage[DWARPEN] > 10.0:
4269 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4271 if damaged(DWARPEN) and game.warpfac > 4.0:
4274 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4275 prout(_(" is repaired, I can only give you warp 4.\""))
4277 # Read in course and distance
4278 if not getcourse(isprobe=False, akey=0):
4280 # Make sure starship has enough energy for the trip
4281 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4282 if power >= game.energy:
4283 # Insufficient power for trip
4286 prout(_("Engineering to bridge--"))
4287 if not game.shldup or 0.5*power > game.energy:
4288 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4290 prout(_("We can't do it, Captain. We don't have enough energy."))
4292 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4295 prout(_("if you'll lower the shields."))
4299 prout(_("We haven't the energy to go that far with the shields up."))
4302 # Make sure enough time is left for the trip
4303 game.optime = 10.0*game.dist/game.wfacsq
4304 if game.optime >= 0.8*game.state.remtime:
4306 prout(_("First Officer Spock- \"Captain, I compute that such"))
4307 proutn(_(" a trip would require approximately %2.0f") %
4308 (100.0*game.optime/game.state.remtime))
4309 prout(_(" percent of our"))
4310 proutn(_(" remaining time. Are you sure this is wise?\" "))
4316 if game.warpfac > 6.0:
4317 # Decide if engine damage will occur
4318 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4319 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4320 if prob > randreal():
4322 game.dist = randreal(game.dist)
4323 # Decide if time warp will occur
4324 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4326 if idebug and game.warpfac==10 and not twarp:
4328 proutn("=== Force time warp? ")
4332 # If time warp or engine damage, check path
4333 # If it is obstructed, don't do warp or damage
4334 angle = ((15.0-game.direc)*0.5235998)
4335 deltax = -math.sin(angle)
4336 deltay = math.cos(angle)
4337 if math.fabs(deltax) > math.fabs(deltay):
4338 bigger = math.fabs(deltax)
4340 bigger = math.fabs(deltay)
4344 n = 10.0 * game.dist * bigger +0.5
4347 for l in range(1, n+1):
4352 if not VALID_SECTOR(ix, iy):
4354 if game.quad[ix][iy] != IHDOT:
4357 # Activate Warp Engines and pay the cost
4358 imove(novapush=False)
4361 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4362 if game.energy <= 0:
4364 game.optime = 10.0*game.dist/game.wfacsq
4368 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4370 prout(_("Engineering to bridge--"))
4371 prout(_(" Scott here. The warp engines are damaged."))
4372 prout(_(" We'll have to reduce speed to warp 4."))
4377 # change the warp factor
4383 proutn(_("Warp factor- "))
4388 if game.damage[DWARPEN] > 10.0:
4389 prout(_("Warp engines inoperative."))
4391 if damaged(DWARPEN) and aaitem > 4.0:
4392 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4393 prout(_(" but right now we can only go warp 4.\""))
4396 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4399 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4401 oldfac = game.warpfac
4402 game.warpfac = aaitem
4403 game.wfacsq=game.warpfac*game.warpfac
4404 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4405 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4408 if game.warpfac < 8.00:
4409 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4411 if game.warpfac == 10.0:
4412 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4414 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4418 # cope with being tossed out of quadrant by supernova or yanked by beam
4420 # is captain on planet?
4422 if damaged(DTRANSP):
4425 prout(_("Scotty rushes to the transporter controls."))
4427 prout(_("But with the shields up it's hopeless."))
4429 prouts(_("His desperate attempt to rescue you . . ."))
4434 prout(_("SUCCEEDS!"))
4437 proutn(_("The crystals mined were "))
4445 # Check to see if captain in shuttle craft
4450 # Inform captain of attempt to reach safety
4454 prouts(_("***RED ALERT! RED ALERT!"))
4458 prout(_(" has stopped in a quadrant containing"))
4459 prouts(_(" a supernova."))
4461 proutn(_("***Emergency automatic override attempts to hurl "))
4464 prout(_("safely out of quadrant."))
4465 if not damaged(DRADIO):
4466 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4467 # Try to use warp engines
4468 if damaged(DWARPEN):
4470 prout(_("Warp engines damaged."))
4473 game.warpfac = randreal(6.0, 8.0)
4474 game.wfacsq = game.warpfac * game.warpfac
4475 prout(_("Warp factor set to %d") % int(game.warpfac))
4476 power = 0.75*game.energy
4477 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4478 distreq = randreal(math.sqrt(2))
4479 if distreq < game.dist:
4481 game.optime = 10.0*game.dist/game.wfacsq
4482 game.direc = randreal(12) # How dumb!
4484 game.inorbit = False
4487 # This is bad news, we didn't leave quadrant.
4491 prout(_("Insufficient energy to leave quadrant."))
4494 # Repeat if another snova
4495 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4497 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4498 finish(FWON) # Snova killed remaining enemy.
4501 # let's do the time warp again
4502 prout(_("***TIME WARP ENTERED."))
4503 if game.state.snap and withprob(0.5):
4505 prout(_("You are traveling backwards in time %d stardates.") %
4506 int(game.state.date-game.snapsht.date))
4507 game.state = game.snapsht
4508 game.state.snap = False
4509 if game.state.remcom:
4510 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4511 schedule(FBATTAK, expran(0.3*game.intime))
4512 schedule(FSNOVA, expran(0.5*game.intime))
4513 # next snapshot will be sooner
4514 schedule(FSNAP, expran(0.25*game.state.remtime))
4516 if game.state.nscrem:
4517 schedule(FSCMOVE, 0.2777)
4521 invalidate(game.battle)
4523 # Make sure Galileo is consistant -- Snapshot may have been taken
4524 # when on planet, which would give us two Galileos!
4526 for l in range(game.inplan):
4527 if game.state.planets[l].known == "shuttle_down":
4529 if game.iscraft == "onship" and game.ship==IHE:
4530 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4531 game.iscraft = "offship"
4532 # Likewise, if in the original time the Galileo was abandoned, but
4533 # was on ship earlier, it would have vanished -- let's restore it.
4534 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4535 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4536 game.iscraft = "onship"
4538 # * There used to be code to do the actual reconstrction here,
4539 # * but the starchart is now part of the snapshotted galaxy state.
4541 prout(_("Spock has reconstructed a correct star chart from memory"))
4543 # Go forward in time
4544 game.optime = -0.5*game.intime*math.log(randreal())
4545 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4546 # cheat to make sure no tractor beams occur during time warp
4547 postpone(FTBEAM, game.optime)
4548 game.damage[DRADIO] += game.optime
4550 events() # Stas Sergeev added this -- do pending events
4553 # launch deep-space probe
4554 # New code to launch a deep space probe
4555 if game.nprobes == 0:
4558 if game.ship == IHE:
4559 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4561 prout(_("Ye Faerie Queene has no deep space probes."))
4566 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4568 if is_scheduled(FDSPROB):
4571 if damaged(DRADIO) and game.condition != "docked":
4572 prout(_("Spock- \"Records show the previous probe has not yet"))
4573 prout(_(" reached its destination.\""))
4575 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4579 # slow mode, so let Kirk know how many probes there are left
4580 if game.nprobes == 1:
4581 prout(_("1 probe left."))
4583 prout(_("%d probes left") % game.nprobes)
4584 proutn(_("Are you sure you want to fire a probe? "))
4587 game.isarmed = False
4588 if key == IHALPHA and citem == "armed":
4592 proutn(_("Arm NOVAMAX warhead? "))
4594 if not getcourse(isprobe=True, akey=key):
4597 angle = ((15.0 - game.direc) * 0.5235988)
4598 game.probeinx = -math.sin(angle)
4599 game.probeiny = math.cos(angle)
4600 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4601 bigger = math.fabs(game.probeinx)
4603 bigger = math.fabs(game.probeiny)
4604 game.probeiny /= bigger
4605 game.probeinx /= bigger
4606 game.proben = 10.0*game.dist*bigger +0.5
4607 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4608 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4609 game.probec = game.quadrant
4610 schedule(FDSPROB, 0.01) # Time to move one sector
4611 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4615 # Here's how the mayday code works:
4617 # First, the closest starbase is selected. If there is a a starbase
4618 # in your own quadrant, you are in good shape. This distance takes
4619 # quadrant distances into account only.
4621 # A magic number is computed based on the distance which acts as the
4622 # probability that you will be rematerialized. You get three tries.
4624 # When it is determined that you should be able to be rematerialized
4625 # (i.e., when the probability thing mentioned above comes up
4626 # positive), you are put into that quadrant (anywhere). Then, we try
4627 # to see if there is a spot adjacent to the star- base. If not, you
4628 # can't be rematerialized!!! Otherwise, it drops you there. It only
4629 # tries five times to find a spot to drop you. After that, it's your
4633 # yell for help from nearest starbase
4634 # There's more than one way to move in this game!
4637 # Test for conditions which prevent calling for help
4638 if game.condition == "docked":
4639 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4642 prout(_("Subspace radio damaged."))
4644 if game.state.rembase==0:
4645 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4648 proutn(_("You must be aboard the "))
4652 # OK -- call for help from nearest starbase
4655 # There's one in this quadrant
4656 ddist = distance(game.base, game.sector)
4659 for m in range(game.state.rembase):
4660 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4664 # Since starbase not in quadrant, set up new quadrant
4665 game.quadrant = game.state.baseq[line]
4667 # dematerialize starship
4668 game.quad[game.sector.x][game.sector.y]=IHDOT
4669 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4671 prout(_(" dematerializes."))
4673 for m in range(1, 5+1):
4674 w = game.base.scatter()
4675 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4676 # found one -- finish up
4679 if not is_valid(game.sector):
4680 prout(_("You have been lost in space..."))
4681 finish(FMATERIALIZE)
4683 # Give starbase three chances to rematerialize starship
4684 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4685 for m in range(1, 3+1):
4686 if m == 1: proutn(_("1st"))
4687 elif m == 2: proutn(_("2nd"))
4688 elif m == 3: proutn(_("3rd"))
4689 proutn(_(" attempt to re-materialize "))
4691 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4694 if randreal() > probf:
4697 curses.delay_output(500)
4700 game.quad[ix][iy]=IHQUEST
4703 setwnd(message_window)
4704 finish(FMATERIALIZE)
4706 game.quad[ix][iy]=game.ship
4708 prout(_("succeeds."))
4712 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4714 # Abandon Ship (the BSD-Trek description)
4716 # The ship is abandoned. If your current ship is the Faire
4717 # Queene, or if your shuttlecraft is dead, you're out of
4718 # luck. You need the shuttlecraft in order for the captain
4719 # (that's you!!) to escape.
4721 # Your crew can beam to an inhabited starsystem in the
4722 # quadrant, if there is one and if the transporter is working.
4723 # If there is no inhabited starsystem, or if the transporter
4724 # is out, they are left to die in outer space.
4726 # If there are no starbases left, you are captured by the
4727 # Klingons, who torture you mercilessly. However, if there
4728 # is at least one starbase, you are returned to the
4729 # Federation in a prisoner of war exchange. Of course, this
4730 # can't happen unless you have taken some prisoners.
4735 if game.condition=="docked":
4737 prout(_("You cannot abandon Ye Faerie Queene."))
4740 # Must take shuttle craft to exit
4741 if game.damage[DSHUTTL]==-1:
4742 prout(_("Ye Faerie Queene has no shuttle craft."))
4744 if game.damage[DSHUTTL]<0:
4745 prout(_("Shuttle craft now serving Big Macs."))
4747 if game.damage[DSHUTTL]>0:
4748 prout(_("Shuttle craft damaged."))
4751 prout(_("You must be aboard the ship."))
4753 if game.iscraft != "onship":
4754 prout(_("Shuttle craft not currently available."))
4756 # Print abandon ship messages
4758 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4760 prouts(_("***ALL HANDS ABANDON SHIP!"))
4762 prout(_("Captain and crew escape in shuttle craft."))
4763 if game.state.rembase==0:
4764 # Oops! no place to go...
4767 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4769 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4770 prout(_("Remainder of ship's complement beam down"))
4771 prout(_("to nearest habitable planet."))
4772 elif q.planet != None and not damaged(DTRANSP):
4773 prout(_("Remainder of ship's complement beam down to %s.") %
4776 prout(_("Entire crew of %d left to die in outer space.") %
4778 game.casual += game.state.crew
4779 game.abandoned += game.state.crew
4781 # If at least one base left, give 'em the Faerie Queene
4783 game.icrystl = False # crystals are lost
4784 game.nprobes = 0 # No probes
4785 prout(_("You are captured by Klingons and released to"))
4786 prout(_("the Federation in a prisoner-of-war exchange."))
4787 nb = randrange(game.state.rembase)
4788 # Set up quadrant and position FQ adjacient to base
4789 if not game.quadrant == game.state.baseq[nb]:
4790 game.quadrant = game.state.baseq[nb]
4791 game.sector.x = game.sector.y = 5
4794 # position next to base by trial and error
4795 game.quad[game.sector.x][game.sector.y] = IHDOT
4796 for l in range(QUADSIZE):
4797 game.sector = game.base.scatter()
4798 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4799 game.quad[game.sector.x][game.sector.y] == IHDOT:
4802 break # found a spot
4803 game.sector.x=QUADSIZE/2
4804 game.sector.y=QUADSIZE/2
4806 # Get new commission
4807 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4808 game.state.crew = FULLCREW
4809 prout(_("Starfleet puts you in command of another ship,"))
4810 prout(_("the Faerie Queene, which is antiquated but,"))
4811 prout(_("still useable."))
4813 prout(_("The dilithium crystals have been moved."))
4815 game.iscraft = "offship" # Galileo disappears
4817 game.condition="docked"
4818 for l in range(NDEVICES):
4819 game.damage[l] = 0.0
4820 game.damage[DSHUTTL] = -1
4821 game.energy = game.inenrg = 3000.0
4822 game.shield = game.inshld = 1250.0
4823 game.torps = game.intorps = 6
4824 game.lsupres=game.inlsr=3.0
4830 # Code from planets.c begins here.
4833 # abort a lengthy operation if an event interrupts it
4836 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4841 # report on (uninhabited) planets in the galaxy
4845 prout(_("Spock- \"Planet report follows, Captain.\""))
4847 for i in range(game.inplan):
4848 if game.state.planets[i].pclass == "destroyed":
4850 if (game.state.planets[i].known != "unknown" \
4851 and not game.state.planets[i].inhabited) \
4854 if idebug and game.state.planets[i].known=="unknown":
4855 proutn("(Unknown) ")
4856 proutn(_("Quadrant %s") % game.state.planets[i].w)
4857 proutn(_(" class "))
4858 proutn(game.state.planets[i].pclass)
4860 if game.state.planets[i].crystals != present:
4862 prout(_("dilithium crystals present."))
4863 if game.state.planets[i].known=="shuttle_down":
4864 prout(_(" Shuttle Craft Galileo on surface."))
4866 prout(_("No information available."))
4869 # enter standard orbit
4873 prout(_("Already in standard orbit."))
4875 if damaged(DWARPEN) and damaged(DIMPULS):
4876 prout(_("Both warp and impulse engines damaged."))
4878 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4880 prout(_(" not adjacent to planet."))
4883 game.optime = randreal(0.02, 0.05)
4884 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4888 game.height = randreal(1400, 8600)
4889 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4894 # examine planets in this quadrant
4895 if damaged(DSRSENS):
4896 if game.options & OPTION_TTY:
4897 prout(_("Short range sensors damaged."))
4899 if game.iplnet == None:
4900 if game.options & OPTION_TTY:
4901 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4903 if game.iplnet.known == "unknown":
4904 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4906 prout(_(" Planet at Sector %s is of class %s.") %
4907 (game.plnet, game.iplnet.pclass))
4908 if game.iplnet.known=="shuttle_down":
4909 prout(_(" Sensors show Galileo still on surface."))
4910 proutn(_(" Readings indicate"))
4911 if game.iplnet.crystals != "present":
4913 prout(_(" dilithium crystals present.\""))
4914 if game.iplnet.known == "unknown":
4915 game.iplnet.known = "known"
4916 elif game.iplnet.inhabited:
4917 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4918 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4921 # use the transporter
4925 if damaged(DTRANSP):
4926 prout(_("Transporter damaged."))
4927 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4929 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4933 if not game.inorbit:
4935 prout(_(" not in standard orbit."))
4938 prout(_("Impossible to transport through shields."))
4940 if game.iplnet.known=="unknown":
4941 prout(_("Spock- \"Captain, we have no information on this planet"))
4942 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4943 prout(_(" you may not go down.\""))
4945 if not game.landed and game.iplnet.crystals=="absent":
4946 prout(_("Spock- \"Captain, I fail to see the logic in"))
4947 prout(_(" exploring a planet with no dilithium crystals."))
4948 proutn(_(" Are you sure this is wise?\" "))
4952 if not (game.options & OPTION_PLAIN):
4953 nrgneed = 50 * game.skill + game.height / 100.0
4954 if nrgneed > game.energy:
4955 prout(_("Engineering to bridge--"))
4956 prout(_(" Captain, we don't have enough energy for transportation."))
4958 if not game.landed and nrgneed * 2 > game.energy:
4959 prout(_("Engineering to bridge--"))
4960 prout(_(" Captain, we have enough energy only to transport you down to"))
4961 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4962 if game.iplnet.known == "shuttle_down":
4963 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4964 proutn(_(" Are you sure this is wise?\" "))
4969 # Coming from planet
4970 if game.iplnet.known=="shuttle_down":
4971 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4975 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4976 prout(_("Landing party assembled, ready to beam up."))
4978 prout(_("Kirk whips out communicator..."))
4979 prouts(_("BEEP BEEP BEEP"))
4981 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4984 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4986 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4988 prout(_("Kirk- \"Energize.\""))
4991 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4994 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4996 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4999 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
5000 game.landed = not game.landed
5001 game.energy -= nrgneed
5003 prout(_("Transport complete."))
5004 if game.landed and game.iplnet.known=="shuttle_down":
5005 prout(_("The shuttle craft Galileo is here!"))
5006 if not game.landed and game.imine:
5013 # strip-mine a world for dilithium
5017 prout(_("Mining party not on planet."))
5019 if game.iplnet.crystals == "mined":
5020 prout(_("This planet has already been strip-mined for dilithium."))
5022 elif game.iplnet.crystals == "absent":
5023 prout(_("No dilithium crystals on this planet."))
5026 prout(_("You've already mined enough crystals for this trip."))
5028 if game.icrystl and game.cryprob == 0.05:
5029 proutn(_("With all those fresh crystals aboard the "))
5032 prout(_("there's no reason to mine more at this time."))
5034 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
5037 prout(_("Mining operation complete."))
5038 game.iplnet.crystals = "mined"
5039 game.imine = game.ididit = True
5042 # use dilithium crystals
5046 if not game.icrystl:
5047 prout(_("No dilithium crystals available."))
5049 if game.energy >= 1000:
5050 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5051 prout(_(" except when Condition Yellow exists."))
5053 prout(_("Spock- \"Captain, I must warn you that loading"))
5054 prout(_(" raw dilithium crystals into the ship's power"))
5055 prout(_(" system may risk a severe explosion."))
5056 proutn(_(" Are you sure this is wise?\" "))
5061 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5062 prout(_(" Mr. Spock and I will try it.\""))
5064 prout(_("Spock- \"Crystals in place, Sir."))
5065 prout(_(" Ready to activate circuit.\""))
5067 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5069 if with(game.cryprob):
5070 prouts(_(" \"Activating now! - - No good! It's***"))
5072 prouts(_("***RED ALERT! RED A*L********************************"))
5075 prouts(_("****************** KA-BOOM!!!! *******************"))
5079 game.energy += randreal(5000.0, 5500.0)
5080 prouts(_(" \"Activating now! - - "))
5081 prout(_("The instruments"))
5082 prout(_(" are going crazy, but I think it's"))
5083 prout(_(" going to work!! Congratulations, Sir!\""))
5088 # use shuttlecraft for planetary jaunt
5091 if damaged(DSHUTTL):
5092 if game.damage[DSHUTTL] == -1.0:
5093 if game.inorbit and game.iplnet.known == "shuttle_down":
5094 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5096 prout(_("Ye Faerie Queene had no shuttle craft."))
5097 elif game.damage[DSHUTTL] > 0:
5098 prout(_("The Galileo is damaged."))
5099 else: # game.damage[DSHUTTL] < 0
5100 prout(_("Shuttle craft is now serving Big Macs."))
5102 if not game.inorbit:
5104 prout(_(" not in standard orbit."))
5106 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5107 prout(_("Shuttle craft not currently available."))
5109 if not game.landed and game.iplnet.known=="shuttle_down":
5110 prout(_("You will have to beam down to retrieve the shuttle craft."))
5112 if game.shldup or game.condition == "docked":
5113 prout(_("Shuttle craft cannot pass through shields."))
5115 if game.iplnet.known=="unknown":
5116 prout(_("Spock- \"Captain, we have no information on this planet"))
5117 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5118 prout(_(" you may not fly down.\""))
5120 game.optime = 3.0e-5*game.height
5121 if game.optime >= 0.8*game.state.remtime:
5122 prout(_("First Officer Spock- \"Captain, I compute that such"))
5123 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5124 int(100*game.optime/game.state.remtime))
5125 prout(_("remaining time."))
5126 proutn(_("Are you sure this is wise?\" "))
5132 if game.iscraft == "onship":
5134 if not damaged(DTRANSP):
5135 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5139 proutn(_("Shuttle crew"))
5141 proutn(_("Rescue party"))
5142 prout(_(" boards Galileo and swoops toward planet surface."))
5143 game.iscraft = "offship"
5147 game.iplnet.known="shuttle_down"
5148 prout(_("Trip complete."))
5151 # Ready to go back to ship
5152 prout(_("You and your mining party board the"))
5153 prout(_("shuttle craft for the trip back to the Enterprise."))
5155 prouts(_("The short hop begins . . ."))
5157 game.iplnet.known="known"
5163 game.iscraft = "onship"
5169 prout(_("Trip complete."))
5174 prout(_("Mining party assembles in the hangar deck,"))
5175 prout(_("ready to board the shuttle craft \"Galileo\"."))
5177 prouts(_("The hangar doors open; the trip begins."))
5180 game.iscraft = "offship"
5183 game.iplnet.known = "shuttle_down"
5186 prout(_("Trip complete."))
5190 # use the big zapper
5194 if game.ship != IHE:
5195 prout(_("Ye Faerie Queene has no death ray."))
5198 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5201 prout(_("Death Ray is damaged."))
5203 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5204 prout(_(" is highly unpredictible. Considering the alternatives,"))
5205 proutn(_(" are you sure this is wise?\" "))
5208 prout(_("Spock- \"Acknowledged.\""))
5211 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5213 prout(_("Crew scrambles in emergency preparation."))
5214 prout(_("Spock and Scotty ready the death ray and"))
5215 prout(_("prepare to channel all ship's power to the device."))
5217 prout(_("Spock- \"Preparations complete, sir.\""))
5218 prout(_("Kirk- \"Engage!\""))
5220 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5223 if game.options & OPTION_PLAIN:
5227 prouts(_("Sulu- \"Captain! It's working!\""))
5229 while game.nenhere > 0:
5230 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.x][game.enemies[1].kloc.y],game.enemies[1].kloc)
5231 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5232 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5234 if (game.options & OPTION_PLAIN) == 0:
5235 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5237 prout(_(" is still operational.\""))
5239 prout(_(" has been rendered nonfunctional.\""))
5240 game.damage[DDRAY] = 39.95
5242 r = randreal() # Pick failure method
5244 prouts(_("Sulu- \"Captain! It's working!\""))
5246 prouts(_("***RED ALERT! RED ALERT!"))
5248 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5250 prouts(_("***RED ALERT! RED A*L********************************"))
5253 prouts(_("****************** KA-BOOM!!!! *******************"))
5258 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5260 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5262 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5263 prout(_(" have apparently been transformed into strange mutations."))
5264 prout(_(" Vulcans do not seem to be affected."))
5266 prout(_("Kirk- \"Raauch! Raauch!\""))
5271 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5273 proutn(_("Spock- \"I believe the word is"))
5274 prouts(_(" *ASTONISHING*"))
5275 prout(_(" Mr. Sulu."))
5276 for i in range(QUADSIZE):
5277 for j in range(QUADSIZE):
5278 if game.quad[i][j] == IHDOT:
5279 game.quad[i][j] = IHQUEST
5280 prout(_(" Captain, our quadrant is now infested with"))
5281 prouts(_(" - - - - - - *THINGS*."))
5283 prout(_(" I have no logical explanation.\""))
5285 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5287 prout(_("Scotty- \"There are so many tribbles down here"))
5288 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5292 # Code from reports.c begins here
5294 def attackreport(curt):
5295 # report status of bases under attack
5297 if is_scheduled(FCDBAS):
5298 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5299 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5300 elif game.isatb == 1:
5301 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5302 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5304 prout(_("No Starbase is currently under attack."))
5306 if is_scheduled(FCDBAS):
5307 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5309 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5313 # report on general game status
5315 s1 = "" and game.thawed and _("thawed ")
5316 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5317 s3 = (None, _("novice"). _("fair"),
5318 _("good"), _("expert"), _("emeritus"))[game.skill]
5319 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5320 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5321 prout(_("No plaque is allowed."))
5323 prout(_("This is tournament game %d.") % game.tourn)
5324 prout(_("Your secret password is \"%s\"") % game.passwd)
5325 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5326 (game.inkling + game.incom + game.inscom)))
5327 if game.incom - game.state.remcom:
5328 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5329 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5330 prout(_(", but no Commanders."))
5333 if game.skill > SKILL_FAIR:
5334 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5335 if game.state.rembase != game.inbase:
5337 if game.inbase-game.state.rembase==1:
5338 proutn(_("has been 1 base"))
5340 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5341 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5343 prout(_("There are %d bases.") % game.inbase)
5344 if communicating() or game.iseenit:
5345 # Don't report this if not seen and
5346 # either the radio is dead or not at base!
5350 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5352 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5353 if game.ship == IHE:
5354 proutn(_("You have "))
5356 proutn("%d" % (game.nprobes))
5359 proutn(_(" deep space probe"))
5363 if communicating() and is_scheduled(FDSPROB):
5365 proutn(_("An armed deep space probe is in "))
5367 proutn(_("A deep space probe is in "))
5368 prout("Quadrant %s." % game.probec)
5370 if game.cryprob <= .05:
5371 prout(_("Dilithium crystals aboard ship... not yet used."))
5375 while game.cryprob > ai:
5378 prout(_("Dilithium crystals have been used %d time%s.") % \
5379 (i, (_("s"), "")[i==1]))
5383 # long-range sensor scan
5384 if damaged(DLRSENS):
5385 # Now allow base's sensors if docked
5386 if game.condition != "docked":
5388 prout(_("LONG-RANGE SENSORS DAMAGED."))
5391 prout(_("Starbase's long-range scan"))
5393 prout(_("Long-range scan"))
5394 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5397 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5398 if not VALID_QUADRANT(x, y):
5402 if not damaged(DRADIO):
5403 game.state.galaxy[x][y].charted = True
5404 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5405 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5406 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5407 if not silent and game.state.galaxy[x][y].supernova:
5410 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5418 for i in range(NDEVICES):
5421 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5422 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5424 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5425 game.damage[i]+0.05,
5426 game.docfac*game.damage[i]+0.005))
5428 prout(_("All devices functional."))
5431 # update the chart in the Enterprise's computer from galaxy data
5432 game.lastchart = game.state.date
5433 for i in range(GALSIZE):
5434 for j in range(GALSIZE):
5435 if game.state.galaxy[i][j].charted:
5436 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5437 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5438 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5441 # display the star chart
5443 if (game.options & OPTION_AUTOSCAN):
5445 if not damaged(DRADIO):
5447 if game.lastchart < game.state.date and game.condition == "docked":
5448 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5451 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5452 if game.state.date > game.lastchart:
5453 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5454 prout(" 1 2 3 4 5 6 7 8")
5455 for i in range(GALSIZE):
5456 proutn("%d |" % (i+1))
5457 for j in range(GALSIZE):
5458 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5462 if game.state.galaxy[i][j].supernova:
5464 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5466 elif game.state.galaxy[i][j].charted:
5467 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5471 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5479 def sectscan(goodScan, i, j):
5480 # light up an individual dot in a sector
5481 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5482 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):
5483 if game.condition == "red": textcolor(RED)
5484 elif game.condition == "green": textcolor(GREEN)
5485 elif game.condition == "yellow": textcolor(YELLOW)
5486 elif game.condition == "docked": textcolor(CYAN)
5487 elif game.condition == "dead": textcolor(BROWN)
5488 if game.quad[i][j] != game.ship:
5490 proutn("%c " % game.quad[i][j])
5496 # print status report lines
5498 if not req or req == 1:
5499 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5500 % (game.state.date, game.state.remtime))
5501 if not req or req == 2:
5502 if game.condition != "docked":
5505 for t in range(NDEVICES):
5506 if game.damage[t]>0:
5508 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5509 if not req or req == 3:
5510 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5511 if not req or req == 4:
5512 if damaged(DLIFSUP):
5513 if game.condition == "docked":
5514 s = _("DAMAGED, Base provides")
5516 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5519 prstat(_("Life Support"), s)
5520 if not req or req == 5:
5521 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5522 if not req or req == 6:
5524 if game.icrystl and (game.options & OPTION_SHOWME):
5525 extra = _(" (have crystals)")
5526 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5527 if not req or req == 7:
5528 prstat(_("Torpedoes"), "%d" % (game.torps))
5529 if not req or req == 8:
5530 if damaged(DSHIELD):
5536 data = _(" %d%% %.1f units") \
5537 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5538 prstat(_("Shields"), s+data)
5539 if not req or req == 9:
5540 prstat(_("Klingons Left"), "%d" \
5541 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5542 if not req or req == 10:
5543 if game.options & OPTION_WORLDS:
5544 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5545 if plnet and plnet.inhabited:
5546 prstat(_("Major system"), plnet.name)
5548 prout(_("Sector is uninhabited"))
5549 elif not req or req == 11:
5550 attackreport(not req)
5553 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5554 while scan() == IHEOL:
5555 proutn(_("Information desired? "))
5557 if citem in requests:
5558 status(requests.index(citem))
5560 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5561 prout((" date, condition, position, lsupport, warpfactor,"))
5562 prout((" energy, torpedoes, shields, klingons, system, time."))
5567 if damaged(DSRSENS):
5568 # Allow base's sensors if docked
5569 if game.condition != "docked":
5570 prout(_(" S.R. SENSORS DAMAGED!"))
5573 prout(_(" [Using Base's sensors]"))
5575 prout(_(" Short-range scan"))
5576 if goodScan and not damaged(DRADIO):
5577 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5578 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5579 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5580 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5581 prout(" 1 2 3 4 5 6 7 8 9 10")
5582 if game.condition != "docked":
5584 for i in range(QUADSIZE):
5585 proutn("%2d " % (i+1))
5586 for j in range(QUADSIZE):
5587 sectscan(goodScan, i, j)
5592 # use computer to get estimated time of arrival for a warp jump
5593 w1 = coord(); w2 = coord()
5595 if damaged(DCOMPTR):
5596 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5599 if scan() != IHREAL:
5602 proutn(_("Destination quadrant and/or sector? "))
5606 w1.y = int(aaitem-0.5)
5607 if scan() != IHREAL:
5610 w1.x = int(aaitem-0.5)
5611 if scan() == IHREAL:
5612 w2.y = int(aaitem-0.5)
5613 if scan() != IHREAL:
5616 w2.x = int(aaitem-0.5)
5618 if game.quadrant.y>w1.x:
5622 if game.quadrant.x>w1.y:
5626 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5629 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5630 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5633 prout(_("Answer \"no\" if you don't know the value:"))
5636 proutn(_("Time or arrival date? "))
5639 if ttime > game.state.date:
5640 ttime -= game.state.date # Actually a star date
5641 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5642 if ttime <= 1e-10 or twarp > 10:
5643 prout(_("We'll never make it, sir."))
5650 proutn(_("Warp factor? "))
5654 if twarp<1.0 or twarp > 10.0:
5658 prout(_("Captain, certainly you can give me one of these."))
5661 ttime = (10.0*game.dist)/square(twarp)
5662 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5663 if tpower >= game.energy:
5664 prout(_("Insufficient energy, sir."))
5665 if not game.shldup or tpower > game.energy*2.0:
5668 proutn(_("New warp factor to try? "))
5669 if scan() == IHREAL:
5672 if twarp<1.0 or twarp > 10.0:
5680 prout(_("But if you lower your shields,"))
5681 proutn(_("remaining"))
5684 proutn(_("Remaining"))
5685 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5687 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5689 prout(_("Any warp speed is adequate."))
5691 prout(_("Minimum warp needed is %.2f,") % (twarp))
5692 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5693 if game.state.remtime < ttime:
5694 prout(_("Unfortunately, the Federation will be destroyed by then."))
5696 prout(_("You'll be taking risks at that speed, Captain"))
5697 if (game.isatb==1 and game.state.kscmdr == w1 and \
5698 scheduled(FSCDBAS)< ttime+game.state.date) or \
5699 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5700 prout(_("The starbase there will be destroyed by then."))
5701 proutn(_("New warp factor to try? "))
5702 if scan() == IHREAL:
5705 if twarp<1.0 or twarp > 10.0:
5714 # Code from setup.c begins here
5717 # issue a historically correct banner
5719 prout(_("-SUPER- STAR TREK"))
5721 # From the FORTRAN original
5722 # prout(_("Latest update-21 Sept 78"))
5728 citem = "emsave.trk"
5732 proutn(_("File name: "))
5738 if '.' not in citem:
5741 fp = open(citem, "wb")
5743 prout(_("Can't freeze game as file %s") % citem)
5745 cPickle.dump(game, fp)
5749 # retrieve saved game
5750 game.passwd[0] = '\0'
5753 proutn(_("File name: "))
5759 if '.' not in citem:
5762 fp = open(citem, "rb")
5764 prout(_("Can't thaw game in %s") % citem)
5766 game = cPickle.load(fp)
5770 # I used <http://www.memory-alpha.org> to find planets
5771 # with references in ST:TOS. Eath and the Alpha Centauri
5772 # Colony have been omitted.
5774 # Some planets marked Class G and P here will be displayed as class M
5775 # because of the way planets are generated. This is a known bug.
5778 _("Andoria (Fesoan)"), # several episodes
5779 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5780 _("Vulcan (T'Khasi)"), # many episodes
5781 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5782 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5783 _("Ardana"), # TOS: "The Cloud Minders"
5784 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5785 _("Gideon"), # TOS: "The Mark of Gideon"
5786 _("Aldebaran III"), # TOS: "The Deadly Years"
5787 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5788 _("Altair IV"), # TOS: "Amok Time
5789 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5790 _("Benecia"), # TOS: "The Conscience of the King"
5791 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5792 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5793 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5794 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5795 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5796 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5797 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5798 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5799 _("Ingraham B"), # TOS: "Operation: Annihilate"
5800 _("Janus IV"), # TOS: "The Devil in the Dark"
5801 _("Makus III"), # TOS: "The Galileo Seven"
5802 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5803 _("Omega IV"), # TOS: "The Omega Glory"
5804 _("Regulus V"), # TOS: "Amok Time
5805 _("Deneva"), # TOS: "Operation -- Annihilate!"
5806 # Worlds from BSD Trek
5807 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5808 _("Beta III"), # TOS: "The Return of the Archons"
5809 _("Triacus"), # TOS: "And the Children Shall Lead",
5810 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5812 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5813 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5814 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5815 # _("Izar"), # TOS: "Whom Gods Destroy"
5816 # _("Tiburon"), # TOS: "The Way to Eden"
5817 # _("Merak II"), # TOS: "The Cloud Minders"
5818 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5819 # _("Iotia"), # TOS: "A Piece of the Action"
5823 _("S. R. Sensors"), \
5824 _("L. R. Sensors"), \
5826 _("Photon Tubes"), \
5827 _("Life Support"), \
5828 _("Warp Engines"), \
5829 _("Impulse Engines"), \
5831 _("Subspace Radio"), \
5832 _("Shuttle Craft"), \
5834 _("Navigation System"), \
5836 _("Shield Control"), \
5841 def setup(needprompt):
5842 # prepare to play, set up cosmos
5844 # Decide how many of everything
5845 if choose(needprompt):
5846 return # frozen game
5847 # Prepare the Enterprise
5848 game.alldone = game.gamewon = False
5850 game.state.crew = FULLCREW
5851 game.energy = game.inenrg = 5000.0
5852 game.shield = game.inshld = 2500.0
5853 game.shldchg = False
5857 game.quadrant = randplace(GALSIZE)
5858 game.sector = randplace(QUADSIZE)
5859 game.torps = game.intorps = 10
5860 game.nprobes = randrange(2, 5)
5862 game.wfacsq = game.warpfac * game.warpfac
5863 for i in range(NDEVICES):
5864 game.damage[i] = 0.0
5865 # Set up assorted game parameters
5866 game.battle = coord()
5867 game.state.date = game.indate = 100.0 * randreal(20, 51)
5868 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5869 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5870 game.isatb = game.state.nplankl = 0
5871 game.state.starkl = game.state.basekl = 0
5872 game.iscraft = "onship"
5876 for i in range(GALSIZE):
5877 for j in range(GALSIZE):
5878 quad = game.state.galaxy[i][j]
5883 quad.starbase = False
5884 quad.supernova = False
5885 quad.status = "secure"
5886 # Initialize times for extraneous events
5887 schedule(FSNOVA, expran(0.5 * game.intime))
5888 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5889 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5890 schedule(FBATTAK, expran(0.3*game.intime))
5892 if game.state.nscrem:
5893 schedule(FSCMOVE, 0.2777)
5898 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5899 schedule(FDISTR, expran(1.0 + game.intime))
5904 # Starchart is functional but we've never seen it
5905 game.lastchart = FOREVER
5906 # Put stars in the galaxy
5908 for i in range(GALSIZE):
5909 for j in range(GALSIZE):
5910 k = randrange(1, QUADSIZE**2/10+1)
5912 game.state.galaxy[i][j].stars = k
5913 # Locate star bases in galaxy
5914 for i in range(game.inbase):
5917 w = randplace(GALSIZE)
5918 if not game.state.galaxy[w.x][w.y].starbase:
5921 # C version: for (j = i-1; j > 0; j--)
5922 # so it did them in the opposite order.
5923 for j in range(1, i):
5924 # Improved placement algorithm to spread out bases
5925 distq = w.distance(game.state.baseq[j])
5926 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5929 prout("=== Abandoning base #%d at %s" % (i, w))
5931 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5933 prout("=== Saving base #%d, close to #%d" % (i, j))
5936 game.state.baseq[i] = w
5937 game.state.galaxy[w.x][w.y].starbase = True
5938 game.state.chart[w.x][w.y].starbase = True
5939 # Position ordinary Klingon Battle Cruisers
5941 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5942 if klumper > MAXKLQUAD:
5946 klump = (1.0 - r*r)*klumper
5951 w = randplace(GALSIZE)
5952 if not game.state.galaxy[w.x][w.y].supernova and \
5953 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5955 game.state.galaxy[w.x][w.y].klingons += int(klump)
5958 # Position Klingon Commander Ships
5959 for i in range(1, game.incom+1):
5961 w = randplace(GALSIZE)
5962 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5963 not game.state.galaxy[w.x][w.y].supernova and \
5964 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5965 not w in game.state.kcmdr[:i]:
5967 game.state.galaxy[w.x][w.y].klingons += 1
5968 game.state.kcmdr[i] = w
5969 # Locate planets in galaxy
5970 for i in range(game.inplan):
5972 w = randplace(GALSIZE)
5973 if game.state.galaxy[w.x][w.y].planet == None:
5977 new.crystals = "absent"
5978 if (game.options & OPTION_WORLDS) and i < NINHAB:
5979 new.pclass = "M" # All inhabited planets are class M
5980 new.crystals = "absent"
5982 new.name = systnames[i]
5983 new.inhabited = True
5985 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5987 new.crystals = "present"
5988 new.known = "unknown"
5989 new.inhabited = False
5990 game.state.galaxy[w.x][w.y].planet = new
5991 game.state.planets.append(new)
5993 for i in range(game.state.nromrem):
5994 w = randplace(GALSIZE)
5995 game.state.galaxy[w.x][w.y].romulans += 1
5996 # Locate the Super Commander
5997 if game.state.nscrem > 0:
5999 w = randplace(GALSIZE)
6000 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
6002 game.state.kscmdr = w
6003 game.state.galaxy[w.x][w.y].klingons += 1
6004 # Place thing (in tournament game, we don't want one!)
6006 if game.tourn is None:
6007 thing = randplace(GALSIZE)
6009 game.state.snap = False
6010 if game.skill == SKILL_NOVICE:
6011 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6012 prout(_("a deadly Klingon invasion force. As captain of the United"))
6013 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6014 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6015 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6016 prout(_("your mission. As you proceed you may be given more time."))
6018 prout(_("You will have %d supporting starbases.") % (game.inbase))
6019 proutn(_("Starbase locations- "))
6021 prout(_("Stardate %d.") % int(game.state.date))
6023 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6024 prout(_("An unknown number of Romulans."))
6025 if game.state.nscrem:
6026 prout(_("And one (GULP) Super-Commander."))
6027 prout(_("%d stardates.") % int(game.intime))
6028 proutn(_("%d starbases in ") % game.inbase)
6029 for i in range(game.inbase):
6030 proutn(`game.state.baseq[i]`)
6033 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6034 proutn(_(" Sector %s") % game.sector)
6036 prout(_("Good Luck!"))
6037 if game.state.nscrem:
6038 prout(_(" YOU'LL NEED IT."))
6041 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
6043 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6046 def choose(needprompt):
6047 # choose your game type
6052 game.skill = SKILL_NONE
6054 if needprompt: # Can start with command line options
6055 proutn(_("Would you like a regular, tournament, or saved game? "))
6057 if len(citem)==0: # Try again
6059 if isit("tournament"):
6060 while scan() == IHEOL:
6061 proutn(_("Type in tournament number-"))
6064 continue # We don't want a blank entry
6065 game.tourn = int(round(aaitem))
6068 logfp.write("# random.seed(%d)\n" % aaitem)
6070 if isit("saved") or isit("frozen"):
6074 if game.passwd == None:
6076 if not game.alldone:
6077 game.thawed = True # No plaque if not finished
6083 proutn(_("What is \"%s\"?"), citem)
6085 while game.length==0 or game.skill==SKILL_NONE:
6086 if scan() == IHALPHA:
6089 elif isit("medium"):
6093 elif isit("novice"):
6094 game.skill = SKILL_NOVICE
6096 game.skill = SKILL_FAIR
6098 game.skill = SKILL_GOOD
6099 elif isit("expert"):
6100 game.skill = SKILL_EXPERT
6101 elif isit("emeritus"):
6102 game.skill = SKILL_EMERITUS
6104 proutn(_("What is \""))
6110 proutn(_("Would you like a Short, Medium, or Long game? "))
6111 elif game.skill == SKILL_NONE:
6112 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6113 # Choose game options -- added by ESR for SST2K
6114 if scan() != IHALPHA:
6116 proutn(_("Choose your game style (or just press enter): "))
6119 # Approximates the UT FORTRAN version.
6120 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6121 game.options |= OPTION_PLAIN
6123 # Approximates Tom Almy's version.
6124 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6125 game.options |= OPTION_ALMY
6129 proutn(_("What is \"%s\"?") % citem)
6131 if game.passwd == "debug":
6133 fputs("=== Debug mode enabled\n", sys.stdout)
6135 # Use parameters to generate initial values of things
6136 game.damfac = 0.5 * game.skill
6137 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6138 game.inbase = game.state.rembase
6140 if game.options & OPTION_PLANETS:
6141 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6142 if game.options & OPTION_WORLDS:
6143 game.inplan += int(NINHAB)
6144 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6145 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6146 game.state.remtime = 7.0 * game.length
6147 game.intime = game.state.remtime
6148 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6149 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6150 game.state.remcom = min(10, game.incom)
6151 game.incom = game.state.remcom
6152 game.state.remres = (game.inkling+4*game.incom)*game.intime
6153 game.inresor = game.state.remres
6154 if game.inkling > 50:
6155 game.state.rembase += 1
6156 game.inbase = game.state.rembase
6160 # drop a feature on a random dot in the current quadrant
6163 w = randplace(QUADSIZE)
6164 if game.quad[w.x][w.y] == IHDOT:
6166 game.quad[w.x][w.y] = iquad
6170 # update our alert status
6171 game.condition = "green"
6172 if game.energy < 1000.0:
6173 game.condition = "yellow"
6174 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6175 game.condition = "red"
6177 game.condition="dead"
6180 # drop new Klingon into current quadrant
6181 return enemy(loc=dropin(IHK), power=randreal(300, 450) + 25.0*game.skill)
6184 # set up a new state of quadrant, for when we enter or re-enter it
6188 game.comhere = False
6194 game.inorbit = False
6196 game.ientesc = False
6199 game.iseenit = False
6201 # Attempt to escape Super-commander, so tbeam back!
6204 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6205 # cope with supernova
6208 game.klhere = q.klingons
6209 game.irhere = q.romulans
6210 game.nenhere = game.klhere + game.irhere
6212 game.quad[game.sector.x][game.sector.y] = game.ship
6215 # Position ordinary Klingons
6216 for i in range(game.klhere):
6217 game.enemies.append(newkling())
6218 # If we need a commander, promote a Klingon
6219 for i in range(game.state.remcom):
6220 if game.state.kcmdr[i] == game.quadrant:
6221 e = game.enemies[game.klhere-1]
6222 game.quad[e.kloc.x][e.kloc.y] = IHC
6223 e.kpower = randreal(950,1350) + 50.0*game.skill
6226 # If we need a super-commander, promote a Klingon
6227 if game.quadrant == game.state.kscmdr:
6229 game.quad[e.kloc.x][e.kloc.y] = IHS
6230 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
6231 game.iscate = (game.state.remkl > 1)
6233 # Put in Romulans if needed
6234 for i in range(game.klhere, game.nenhere):
6235 game.enemies.append(enemy(loc=dropin(IHR),
6236 power=randreal(400.0,850.0)+50.0*game.skill))
6237 # If quadrant needs a starbase, put it in
6239 game.base = dropin(IHB)
6240 # If quadrant needs a planet, put it in
6242 game.iplnet = q.planet
6243 if not q.planet.inhabited:
6244 game.plnet = dropin(IHP)
6246 game.plnet = dropin(IHW)
6247 # Check for condition
6249 # And finally the stars
6250 for i in range(q.stars):
6253 if game.irhere > 0 and game.klhere == 0:
6255 if not damaged(DRADIO):
6257 prout(_("LT. Uhura- \"Captain, an urgent message."))
6258 prout(_(" I'll put it on audio.\" CLICK"))
6260 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6261 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6263 # Put in THING if needed
6264 if thing == game.quadrant:
6265 e = enemy(dropin(IHQUEST))
6266 e.kdist = e.kavgd = distance(game.sector, e.kloc)
6267 e.kpower = randreal(6000,6500.0)+250.0*game.skill
6268 games.enemies.append(e)
6270 if not damaged(DSRSENS):
6272 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6273 prout(_(" Please examine your short-range scan.\""))
6274 # Decide if quadrant needs a Tholian; lighten up if skill is low
6275 if game.options & OPTION_THOLIAN:
6276 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6277 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6278 (game.skill > SKILL_GOOD and withprob(0.08)):
6279 game.tholian = coord()
6281 game.tholian.x = withprob(0.5) * (QUADSIZE-1)
6282 game.tholian.y = withprob(0.5) * (QUADSIZE-1)
6283 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6285 game.quad[game.tholian.x][game.tholian.y] = IHT
6286 game.enemies.append(loc=game.tholian,
6287 power=randrange(100, 500) + 25.0*game.skill)
6289 # Reserve unoccupied corners
6290 if game.quad[0][0]==IHDOT:
6291 game.quad[0][0] = 'X'
6292 if game.quad[0][QUADSIZE-1]==IHDOT:
6293 game.quad[0][QUADSIZE-1] = 'X'
6294 if game.quad[QUADSIZE-1][0]==IHDOT:
6295 game.quad[QUADSIZE-1][0] = 'X'
6296 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6297 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6298 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
6299 # Put in a few black holes
6300 for i in range(1, 3+1):
6303 # Take out X's in corners if Tholian present
6305 if game.quad[0][0]=='X':
6306 game.quad[0][0] = IHDOT
6307 if game.quad[0][QUADSIZE-1]=='X':
6308 game.quad[0][QUADSIZE-1] = IHDOT
6309 if game.quad[QUADSIZE-1][0]=='X':
6310 game.quad[QUADSIZE-1][0] = IHDOT
6311 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6312 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6315 # set the self-destruct password
6316 if game.options & OPTION_PLAIN:
6319 proutn(_("Please type in a secret password- "))
6322 if game.passwd != None:
6327 game.passwd += chr(ord('a')+randrange(26))
6329 # Code from sst.c begins here
6332 "SRSCAN": OPTION_TTY,
6333 "STATUS": OPTION_TTY,
6334 "REQUEST": OPTION_TTY,
6335 "LRSCAN": OPTION_TTY,
6348 "SENSORS": OPTION_PLANETS,
6349 "ORBIT": OPTION_PLANETS,
6350 "TRANSPORT": OPTION_PLANETS,
6351 "MINE": OPTION_PLANETS,
6352 "CRYSTALS": OPTION_PLANETS,
6353 "SHUTTLE": OPTION_PLANETS,
6354 "PLANETS": OPTION_PLANETS,
6359 "PROBE": OPTION_PROBE,
6361 "FREEZE": 0, # Synonym for SAVE
6367 "SOS": 0, # Synonym for MAYDAY
6368 "CALL": 0, # Synonym for MAYDAY
6375 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6378 # generate a list of legal commands
6380 proutn(_("LEGAL COMMANDS ARE:"))
6381 for key in commands:
6385 proutn("%-12s " % key)
6390 # browse on-line help
6391 # Give help on commands
6395 setwnd(prompt_window)
6396 proutn(_("Help on what command? "))
6398 setwnd(message_window)
6401 if citem in commands or citem == "ABBREV":
6410 fp = open(SSTDOC, "r")
6413 fp = open(DOC_NAME, "r")
6415 prout(_("Spock- \"Captain, that information is missing from the"))
6416 proutn(_(" computer. You need to find "))
6418 prout(_(" and put it in the"))
6419 proutn(_(" current directory or to "))
6423 # This used to continue: "You need to find SST.DOC and put
6424 # it in the current directory."
6428 linebuf = fp.readline()
6430 prout(_("Spock- \"Captain, there is no information on that command.\""))
6433 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6434 linebuf = linebuf[3:].strip()
6438 prout(_("Spock- \"Captain, I've found the following information:\""))
6440 while linebuf in fp:
6441 if "******" in linebuf:
6447 # command-interpretation loop
6450 setwnd(message_window)
6451 while True: # command loop
6453 while True: # get a command
6458 setwnd(prompt_window)
6462 if game.options & OPTION_CURSES:
6467 setwnd(message_window)
6469 candidates = filter(lambda x: x.startswith(citem.upper()),
6471 if len(candidates) == 1:
6474 elif candidates and not (game.options & OPTION_PLAIN):
6475 prout("Commands with that prefix: " + " ".join(candidates))
6479 if cmd == "SRSCAN": # srscan
6481 elif cmd == "STATUS": # status
6483 elif cmd == "REQUEST": # status request
6485 elif cmd == "LRSCAN": # long range scan
6486 lrscan(silent=False)
6487 elif cmd == "PHASERS": # phasers
6491 elif cmd == "TORPEDO": # photon torpedos
6495 elif cmd == "MOVE": # move under warp
6497 elif cmd == "SHIELDS": # shields
6498 doshield(shraise=False)
6501 game.shldchg = False
6502 elif cmd == "DOCK": # dock at starbase
6506 elif cmd == "DAMAGES": # damage reports
6508 elif cmd == "CHART": # chart
6510 elif cmd == "IMPULSE": # impulse
6512 elif cmd == "REST": # rest
6516 elif cmd == "WARP": # warp
6518 elif cmd == "SCORE": # score
6520 elif cmd == "SENSORS": # sensors
6522 elif cmd == "ORBIT": # orbit
6526 elif cmd == "TRANSPORT": # transport "beam"
6528 elif cmd == "MINE": # mine
6532 elif cmd == "CRYSTALS": # crystals
6536 elif cmd == "SHUTTLE": # shuttle
6540 elif cmd == "PLANETS": # Planet list
6542 elif cmd == "REPORT": # Game Report
6544 elif cmd == "COMPUTER": # use COMPUTER!
6546 elif cmd == "COMMANDS":
6548 elif cmd == "EMEXIT": # Emergency exit
6549 clrscr() # Hide screen
6550 freeze(True) # forced save
6551 raise SysExit,1 # And quick exit
6552 elif cmd == "PROBE":
6553 probe() # Launch probe
6556 elif cmd == "ABANDON": # Abandon Ship
6558 elif cmd == "DESTRUCT": # Self Destruct
6560 elif cmd == "SAVE": # Save Game
6563 if game.skill > SKILL_GOOD:
6564 prout(_("WARNING--Saved games produce no plaques!"))
6565 elif cmd == "DEATHRAY": # Try a desparation measure
6569 elif cmd == "DEBUGCMD": # What do we want for debug???
6571 elif cmd == "MAYDAY": # Call for help
6576 game.alldone = True # quit the game
6581 break # Game has ended
6582 if game.optime != 0.0:
6585 break # Events did us in
6586 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6589 if hitme and not game.justin:
6593 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6605 if cmd == IHR: s = _("Romulan")
6606 elif cmd == IHK: s = _("Klingon")
6607 elif cmd == IHC: s = _("Commander")
6608 elif cmd == IHS: s = _("Super-commander")
6609 elif cmd == IHSTAR: s = _("Star")
6610 elif cmd == IHP: s = _("Planet")
6611 elif cmd == IHB: s = _("Starbase")
6612 elif cmd == IHBLANK: s = _("Black hole")
6613 elif cmd == IHT: s = _("Tholian")
6614 elif cmd == IHWEB: s = _("Tholian web")
6615 elif cmd == IHQUEST: s = _("Stranger")
6616 elif cmd == IHW: s = _("Inhabited World")
6617 else: s = "Unknown??"
6620 def crmena(stars, enemy, loctype, w):
6621 # print an enemy and his location
6627 if loctype == "quadrant":
6628 buf = _("Quadrant ")
6629 elif loctype == "sector":
6634 # print our ship name
6635 if game.ship == IHE:
6637 elif game.ship == IHF:
6638 s = _("Faerie Queene")
6644 # print a line of stars
6645 prouts("******************************************************")
6649 return -avrage*math.log(1e-7 + randreal())
6651 def randplace(size):
6652 # choose a random location
6654 w.x = randrange(size)
6655 w.y = randrange(size)
6659 # Demand input for next scan
6664 # return IHEOL next time
6669 # Get a token from the user
6670 global inqueue, line, citem, aaitem
6674 # Read a line if nothing here
6677 if curwnd==prompt_window:
6679 setwnd(message_window)
6681 # Skip leading white space
6682 line = line.lstrip()
6684 inqueue = line.split()
6690 # From here on in it's all looking at the queue
6691 citem = inqueue.pop(0)
6695 aaitem = float(citem)
6700 citem = citem.lower()
6704 # yes-or-no confirmation
6713 proutn(_("Please answer with \"y\" or \"n\": "))
6716 # complain about unparseable input
6719 prout(_("Beg your pardon, Captain?"))
6722 # compares s to citem and returns true if it matches to the length of s
6723 return s.startswith(citem)
6726 # access to the internals for debugging
6727 proutn("Reset levels? ")
6729 if game.energy < game.inenrg:
6730 game.energy = game.inenrg
6731 game.shield = game.inshld
6732 game.torps = game.intorps
6733 game.lsupres = game.inlsr
6734 proutn("Reset damage? ")
6736 for i in range(NDEVICES):
6737 if game.damage[i] > 0.0:
6738 game.damage[i] = 0.0
6739 proutn("Toggle debug flag? ")
6743 prout("Debug output ON")
6745 prout("Debug output OFF")
6746 proutn("Cause selective damage? ")
6748 for i in range(NDEVICES):
6754 if key == IHALPHA and isit("y"):
6755 game.damage[i] = 10.0
6756 proutn("Examine/change events? ")
6761 FSNOVA: "Supernova ",
6764 FBATTAK: "Base Attack ",
6765 FCDBAS: "Base Destroy ",
6766 FSCMOVE: "SC Move ",
6767 FSCDBAS: "SC Base Destroy ",
6768 FDSPROB: "Probe Move ",
6769 FDISTR: "Distress Call ",
6770 FENSLV: "Enslavement ",
6771 FREPRO: "Klingon Build ",
6773 for i in range(1, NEVENTS):
6776 proutn("%.2f" % (scheduled(i)-game.state.date))
6777 if i == FENSLV or i == FREPRO:
6779 proutn(" in %s" % ev.quadrant)
6789 ev = schedule(i, aaitem)
6790 if i == FENSLV or i == FREPRO:
6792 proutn("In quadrant- ")
6794 # IHEOL says to leave coordinates as they are
6797 prout("Event %d canceled, no x coordinate." % (i))
6800 w.x = int(round(aaitem))
6803 prout("Event %d canceled, no y coordinate." % (i))
6806 w.y = int(round(aaitem))
6809 proutn("Induce supernova here? ")
6811 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6814 if __name__ == '__main__':
6816 global line, thing, game, idebug, iqengry
6817 game = citem = aaitem = inqueue = None
6823 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6824 # Disable curses mode until the game logic is working.
6825 # if os.getenv("TERM"):
6826 # game.options |= OPTION_CURSES | OPTION_SHOWME
6828 game.options |= OPTION_TTY
6829 seed = int(time.time())
6830 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6831 for (switch, val) in options:
6834 replayfp = open(val, "r")
6836 sys.stderr.write("sst: can't open replay file %s\n" % val)
6839 line = replayfp.readline().strip()
6840 (leader, key, seed) = line.split()
6842 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6843 line = replayfp.readline().strip()
6844 arguments += line.split()[2:]
6846 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6848 game.options |= OPTION_TTY
6849 game.options &=~ OPTION_CURSES
6850 elif switch == '-t':
6851 game.options |= OPTION_TTY
6852 game.options &=~ OPTION_CURSES
6853 elif switch == '-x':
6856 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6858 # where to save the input in case of bugs
6860 logfp = open("/usr/tmp/sst-input.log", "w")
6862 sys.stderr.write("sst: warning, can't open logfile\n")
6864 logfp.write("# seed %s\n" % seed)
6865 logfp.write("# options %s\n" % " ".join(arguments))
6872 while True: # Play a game
6873 setwnd(fullscreen_window)
6876 setup(needprompt=not inqueue)
6879 game.alldone = False
6885 if game.tourn and game.alldone:
6886 proutn(_("Do you want your score recorded?"))
6891 proutn(_("Do you want to play again? "))
6895 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6897 except KeyboardInterrupt: