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, type=None, loc=None, power=None):
424 self.kpower = power # enemy energy level
425 game.enemies.append(self)
427 if self.kloc.x is not None and self.kloc.y is not None:
428 game.quad[self.kloc.x][self.kloc.y] = IHDOT
431 game.quad[self.kloc.x][self.kloc.y] = self.type
432 self.kdist = self.kavgd = distance(game.sector, loc)
434 self.kloc = coord() # enemy sector location
435 self.kdist = self.kavgd = None
436 game.enemies.remove(self)
438 return "<%s=%f>" % (self.kloc, self.kpower) # For debugging
442 self.options = None # Game options
443 self.state = snapshot() # A snapshot structure
444 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
445 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
446 self.damage = [0.0] * NDEVICES # damage encountered
447 self.future = [] # future events
448 for i in range(NEVENTS):
449 self.future.append(event())
450 self.passwd = None; # Self Destruct password
452 self.quadrant = None # where we are in the large
453 self.sector = None # where we are in the small
454 self.tholian = None # Tholian enemy object
455 self.base = None # position of base in current quadrant
456 self.battle = None # base coordinates being attacked
457 self.plnet = None # location of planet in quadrant
458 self.probec = None # current probe quadrant
459 self.gamewon = False # Finished!
460 self.ididit = False # action taken -- allows enemy to attack
461 self.alive = False # we are alive (not killed)
462 self.justin = False # just entered quadrant
463 self.shldup = False # shields are up
464 self.shldchg = False # shield is changing (affects efficiency)
465 self.comhere = False # commander here
466 self.ishere = False # super-commander in quadrant
467 self.iscate = False # super commander is here
468 self.ientesc = False # attempted escape from supercommander
469 self.resting = False # rest time
470 self.icraft = False # Kirk in Galileo
471 self.landed = False # party on planet (true), on ship (false)
472 self.alldone = False # game is now finished
473 self.neutz = False # Romulan Neutral Zone
474 self.isarmed = False # probe is armed
475 self.inorbit = False # orbiting a planet
476 self.imine = False # mining
477 self.icrystl = False # dilithium crystals aboard
478 self.iseenit = False # seen base attack report
479 self.thawed = False # thawed game
480 self.condition = None # "green", "yellow", "red", "docked", "dead"
481 self.iscraft = None # "onship", "offship", "removed"
482 self.skill = None # Player skill level
483 self.inkling = 0 # initial number of klingons
484 self.inbase = 0 # initial number of bases
485 self.incom = 0 # initial number of commanders
486 self.inscom = 0 # initial number of commanders
487 self.inrom = 0 # initial number of commanders
488 self.instar = 0 # initial stars
489 self.intorps = 0 # initial/max torpedoes
490 self.torps = 0 # number of torpedoes
491 self.ship = 0 # ship type -- 'E' is Enterprise
492 self.abandoned = 0 # count of crew abandoned in space
493 self.length = 0 # length of game
494 self.klhere = 0 # klingons here
495 self.casual = 0 # causalties
496 self.nhelp = 0 # calls for help
497 self.nkinks = 0 # count of energy-barrier crossings
498 self.iplnet = None # planet # in quadrant
499 self.inplan = 0 # initial planets
500 self.irhere = 0 # Romulans in quadrant
501 self.isatb = 0 # =1 if super commander is attacking base
502 self.tourn = None # tournament number
503 self.proben = 0 # number of moves for probe
504 self.nprobes = 0 # number of probes available
505 self.inresor = 0.0 # initial resources
506 self.intime = 0.0 # initial time
507 self.inenrg = 0.0 # initial/max energy
508 self.inshld = 0.0 # initial/max shield
509 self.inlsr = 0.0 # initial life support resources
510 self.indate = 0.0 # initial date
511 self.energy = 0.0 # energy level
512 self.shield = 0.0 # shield level
513 self.warpfac = 0.0 # warp speed
514 self.wfacsq = 0.0 # squared warp factor
515 self.lsupres = 0.0 # life support reserves
516 self.dist = 0.0 # movement distance
517 self.direc = 0.0 # movement direction
518 self.optime = 0.0 # time taken by current operation
519 self.docfac = 0.0 # repair factor when docking (constant?)
520 self.damfac = 0.0 # damage factor
521 self.lastchart = 0.0 # time star chart was last updated
522 self.cryprob = 0.0 # probability that crystal will work
523 self.probex = 0.0 # location of probe
525 self.probeinx = 0.0 # probe x,y increment
526 self.probeiny = 0.0 #
527 self.height = 0.0 # height of orbit around planet
529 # Stas thinks this should be (C expression):
530 # game.state.remkl + game.state.remcom > 0 ?
531 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
532 # He says the existing expression is prone to divide-by-zero errors
533 # after killing the last klingon when score is shown -- perhaps also
534 # if the only remaining klingon is SCOM.
535 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
536 # From enumerated type 'feature'
557 # From enumerated type 'FINTYPE'
581 # From enumerated type 'COLORS'
600 # Log the results of pulling random numbers so we can check determinism.
606 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
609 def randrange(*args):
610 v = random.randrange(*args)
611 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
617 v *= args[0] # returns from [0, a1)
619 v = args[0] + v*args[1] # returns from [a1, a2)
620 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
623 # Code from ai.c begins here
625 def tryexit(look, ienm, loccom, irun):
626 # a bad guy attempts to bug out
628 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
629 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
630 if not VALID_QUADRANT(iq.x,iq.y) or \
631 game.state.galaxy[iq.x][iq.y].supernova or \
632 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
633 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
635 return False; # Romulans cannot escape!
637 # avoid intruding on another commander's territory
639 for n in range(game.state.remcom):
640 if game.state.kcmdr[n] == iq:
642 # refuse to leave if currently attacking starbase
643 if game.battle == game.quadrant:
645 # don't leave if over 1000 units of energy
646 if game.enemies[loccom].kpower > 1000.0:
648 # print escape message and move out of quadrant.
649 # we know this if either short or long range sensors are working
650 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
651 game.condition == docked:
652 crmena(True, ienm, "sector", game.enemies[loccom].kloc)
653 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
654 # handle local matters related to escape
655 game.enemies[loccom].move(None)
657 if game.condition != docked:
659 # Handle global matters related to escape
660 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
661 game.state.galaxy[iq.x][iq.y].klingons += 1
667 schedule(FSCMOVE, 0.2777)
671 for n in range(game.state.remcom):
672 if game.state.kcmdr[n] == game.quadrant:
673 game.state.kcmdr[n]=iq
676 return True; # success
679 # The bad-guy movement algorithm:
681 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
682 # If both are operating full strength, force is 1000. If both are damaged,
683 # force is -1000. Having shields down subtracts an additional 1000.
685 # 2. Enemy has forces equal to the energy of the attacker plus
686 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
687 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
689 # Attacker Initial energy levels (nominal):
690 # Klingon Romulan Commander Super-Commander
691 # Novice 400 700 1200
693 # Good 450 800 1300 1750
694 # Expert 475 850 1350 1875
695 # Emeritus 500 900 1400 2000
696 # VARIANCE 75 200 200 200
698 # Enemy vessels only move prior to their attack. In Novice - Good games
699 # only commanders move. In Expert games, all enemy vessels move if there
700 # is a commander present. In Emeritus games all enemy vessels move.
702 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
703 # forces are 1000 greater than Enterprise.
705 # Agressive action on average cuts the distance between the ship and
706 # the enemy to 1/4 the original.
708 # 4. At lower energy advantage, movement units are proportional to the
709 # advantage with a 650 advantage being to hold ground, 800 to move forward
710 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
712 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
713 # retreat, especially at high skill levels.
715 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
718 def movebaddy(com, loccom, ienm):
719 # tactical movement for the bad guys
720 next = coord(); look = coord()
722 # This should probably be just game.comhere + game.ishere
723 if game.skill >= SKILL_EXPERT:
724 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
726 nbaddys = game.comhere + game.ishere
728 dist1 = game.enemies[loccom].kdist
729 mdist = int(dist1 + 0.5); # Nearest integer distance
730 # If SC, check with spy to see if should hi-tail it
732 (game.enemies[loccom].kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
736 # decide whether to advance, retreat, or hold position
737 forces = game.enemies[loccom].kpower+100.0*len(game.enemies)+400*(nbaddys-1)
739 forces += 1000; # Good for enemy if shield is down!
740 if not damaged(DPHASER) or not damaged(DPHOTON):
741 if damaged(DPHASER): # phasers damaged
744 forces -= 0.2*(game.energy - 2500.0)
745 if damaged(DPHOTON): # photon torpedoes damaged
748 forces -= 50.0*game.torps
750 # phasers and photon tubes both out!
753 if forces <= 1000.0 and game.condition != "docked": # Typical situation
754 motion = ((forces + randreal(200))/150.0) - 5.0
756 if forces > 1000.0: # Very strong -- move in for kill
757 motion = (1.0-square(randreal()))*dist1 + 1.0
758 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
759 motion -= game.skill*(2.0-square(randreal()))
761 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
762 # don't move if no motion
765 # Limit motion according to skill
766 if abs(motion) > game.skill:
771 # calculate preferred number of steps
776 if motion > 0 and nsteps > mdist:
777 nsteps = mdist; # don't overshoot
778 if nsteps > QUADSIZE:
779 nsteps = QUADSIZE; # This shouldn't be necessary
781 nsteps = 1; # This shouldn't be necessary
783 proutn("NSTEPS = %d:" % nsteps)
784 # Compute preferred values of delta X and Y
785 mx = game.sector.x - com.x
786 my = game.sector.y - com.y
787 if 2.0 * abs(mx) < abs(my):
789 if 2.0 * abs(my) < abs(game.sector.x-com.x):
803 for ll in range(nsteps):
805 proutn(" %d" % (ll+1))
806 # Check if preferred position available
818 attempts = 0; # Settle mysterious hang problem
819 while attempts < 20 and not success:
821 if look.x < 0 or look.x >= QUADSIZE:
822 if motion < 0 and tryexit(look, ienm, loccom, irun):
824 if krawlx == mx or my == 0:
826 look.x = next.x + krawlx
828 elif look.y < 0 or look.y >= QUADSIZE:
829 if motion < 0 and tryexit(look, ienm, loccom, irun):
831 if krawly == my or mx == 0:
833 look.y = next.y + krawly
835 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
836 # See if we should ram ship
837 if game.quad[look.x][look.y] == game.ship and \
838 (ienm == IHC or ienm == IHS):
841 if krawlx != mx and my != 0:
842 look.x = next.x + krawlx
844 elif krawly != my and mx != 0:
845 look.y = next.y + krawly
848 break; # we have failed
860 # Put commander in place within same quadrant
861 game.quad[com.x][com.y] = IHDOT
862 game.quad[next.x][next.y] = ienm
865 game.enemies[loccom].kloc = next
866 game.enemies[loccom].kdist = game.enemies[loccom].kavgd = distance(game.sector, next)
867 if not damaged(DSRSENS) or game.condition == docked:
870 proutn(_(" from Sector %s") % com)
871 if game.enemies[loccom].kdist < dist1:
872 proutn(_(" advances to "))
874 proutn(_(" retreats to "))
875 prout("Sector %s." % next)
878 # Klingon tactical movement
881 # Figure out which Klingon is the commander (or Supercommander)
884 for (i, e) in enumerate(game.enemies):
885 if game.quad[e.kloc.x][e.kloc.y] == IHC:
886 movebaddy(e.kloc, i, IHC)
889 for (i, e) in enumerate(game.enemies):
890 if game.quad[e.kloc.x][e.kloc.y] == IHS:
891 movebaddy(e.kloc, i, IHS)
893 # If skill level is high, move other Klingons and Romulans too!
894 # Move these last so they can base their actions on what the
896 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
897 for (i, e) in enumerate(game.enemies):
898 if game.quad[e.kloc.x][e.kloc.y] in (IHK, IHR):
899 movebaddy(e.kloc, i, game.quad[e.kloc.x][e.kloc.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 e in game.enemies:
927 if game.quad[e.kloc.x][e.kloc.y] == IHS:
929 game.enemies[i].move(None)
931 if game.condition!=docked:
933 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
934 # check for a helpful planet
935 for i in range(game.inplan):
936 if game.state.planets[i].w == game.state.kscmdr and \
937 game.state.planets[i].crystals == "present":
939 game.state.planets[i].pclass = "destroyed"
940 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
943 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
944 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
945 prout(_(" by the Super-commander.\""))
947 return False; # looks good!
949 def supercommander():
950 # move the Super Commander
951 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
954 prout("== SUPERCOMMANDER")
955 # Decide on being active or passive
956 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 \
957 (game.state.date-game.indate) < 3.0)
958 if not game.iscate and avoid:
959 # compute move away from Enterprise
960 idelta = game.state.kscmdr-game.quadrant
961 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
963 idelta.x = game.state.kscmdr.y-game.quadrant.y
964 idelta.y = game.quadrant.x-game.state.kscmdr.x
966 # compute distances to starbases
967 if game.state.rembase <= 0:
971 sc = game.state.kscmdr
972 for i in range(game.state.rembase):
973 basetbl.append((i, distance(game.state.baseq[i], sc)))
974 if game.state.rembase > 1:
975 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
976 # look for nearest base without a commander, no Enterprise, and
977 # without too many Klingons, and not already under attack.
978 ifindit = iwhichb = 0
979 for i2 in range(game.state.rembase):
980 i = basetbl[i2][0]; # bug in original had it not finding nearest
981 ibq = game.state.baseq[i]
982 if ibq == game.quadrant or ibq == game.battle or \
983 game.state.galaxy[ibq.x][ibq.y].supernova or \
984 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
986 # if there is a commander, and no other base is appropriate,
987 # we will take the one with the commander
988 for j in range(game.state.remcom):
989 if ibq == game.state.kcmdr[j] and ifindit!= 2:
993 if j > game.state.remcom: # no commander -- use this one
998 return # Nothing suitable -- wait until next time
999 ibq = game.state.baseq[iwhichb]
1000 # decide how to move toward base
1001 idelta = ibq - game.state.kscmdr
1002 # Maximum movement is 1 quadrant in either or both axes
1003 idelta = idelta.sgn()
1004 # try moving in both x and y directions
1005 # there was what looked like a bug in the Almy C code here,
1006 # but it might be this translation is just wrong.
1007 iq = game.state.kscmdr + idelta
1008 if movescom(iq, avoid):
1009 # failed -- try some other maneuvers
1010 if idelta.x==0 or idelta.y==0:
1011 # attempt angle move
1013 iq.y = game.state.kscmdr.y + 1
1014 if movescom(iq, avoid):
1015 iq.y = game.state.kscmdr.y - 1
1018 iq.x = game.state.kscmdr.x + 1
1019 if movescom(iq, avoid):
1020 iq.x = game.state.kscmdr.x - 1
1023 # try moving just in x or y
1024 iq.y = game.state.kscmdr.y
1025 if movescom(iq, avoid):
1026 iq.y = game.state.kscmdr.y + idelta.y
1027 iq.x = game.state.kscmdr.x
1030 if game.state.rembase == 0:
1033 for i in range(game.state.rembase):
1034 ibq = game.state.baseq[i]
1035 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1038 return # no, don't attack base!
1039 game.iseenit = False
1041 schedule(FSCDBAS, randreal(1.0, 3.0))
1042 if is_scheduled(FCDBAS):
1043 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1044 if not communicating():
1048 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1049 % game.state.kscmdr)
1050 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1051 proutn(_(" It can survive until stardate %d.\"") \
1052 % int(scheduled(FSCDBAS)))
1053 if not game.resting:
1055 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1058 game.resting = False
1059 game.optime = 0.0; # actually finished
1061 # Check for intelligence report
1064 (not communicating()) or \
1065 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1068 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1069 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1074 if not game.tholian or game.justin:
1076 if game.tholian.kloc.x == 0 and game.tholian.kloc.y == 0:
1077 idx = 0; idy = QUADSIZE-1
1078 elif game.tholian.kloc.x == 0 and game.tholian.kloc.y == QUADSIZE-1:
1079 idx = QUADSIZE-1; idy = QUADSIZE-1
1080 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == QUADSIZE-1:
1081 idx = QUADSIZE-1; idy = 0
1082 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == 0:
1085 # something is wrong!
1088 # do nothing if we are blocked
1089 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1091 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1092 if game.tholian.kloc.x != idx:
1094 im = math.fabs(idx - game.tholian.kloc.x)*1.0/(idx - game.tholian.kloc.x)
1095 while game.tholian.kloc.x != idx:
1096 game.tholian.kloc.x += im
1097 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1098 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1099 elif game.tholian.kloc.y != idy:
1101 im = math.fabs(idy - game.tholian.kloc.y)*1.0/(idy - game.tholian.kloc.y)
1102 while game.tholian.kloc.y != idy:
1103 game.tholian.kloc.y += im
1104 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1105 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1106 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHT
1107 #game.enemies[-1].kloc = game.tholian #FIXME
1108 # check to see if all holes plugged
1109 for i in range(QUADSIZE):
1110 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1112 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1114 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1116 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1118 # All plugged up -- Tholian splits
1119 game.quad[game.tholian.kloc.x][game.tholian.kloc.y]=IHWEB
1121 crmena(True, IHT, "sector", game.tholian)
1122 prout(_(" completes web."))
1123 game.tholian.move(None)
1126 # Code from battle.c begins here
1128 def doshield(shraise):
1129 # change shield status
1137 if isit("transfer"):
1141 if damaged(DSHIELD):
1142 prout(_("Shields damaged and down."))
1149 proutn(_("Do you wish to change shield energy? "))
1151 proutn(_("Energy to transfer to shields- "))
1153 elif damaged(DSHIELD):
1154 prout(_("Shields damaged and down."))
1157 proutn(_("Shields are up. Do you want them down? "))
1164 proutn(_("Shields are down. Do you want them up? "))
1170 if action == "SHUP": # raise shields
1172 prout(_("Shields already up."))
1176 if game.condition != "docked":
1178 prout(_("Shields raised."))
1179 if game.energy <= 0:
1181 prout(_("Shields raising uses up last of energy."))
1186 elif action == "SHDN":
1188 prout(_("Shields already down."))
1192 prout(_("Shields lowered."))
1195 elif action == "NRG":
1196 while scan() != IHREAL:
1198 proutn(_("Energy to transfer to shields- "))
1202 if aaitem > game.energy:
1203 prout(_("Insufficient ship energy."))
1206 if game.shield+aaitem >= game.inshld:
1207 prout(_("Shield energy maximized."))
1208 if game.shield+aaitem > game.inshld:
1209 prout(_("Excess energy requested returned to ship energy"))
1210 game.energy -= game.inshld-game.shield
1211 game.shield = game.inshld
1213 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1214 # Prevent shield drain loophole
1216 prout(_("Engineering to bridge--"))
1217 prout(_(" Scott here. Power circuit problem, Captain."))
1218 prout(_(" I can't drain the shields."))
1221 if game.shield+aaitem < 0:
1222 prout(_("All shield energy transferred to ship."))
1223 game.energy += game.shield
1226 proutn(_("Scotty- \""))
1228 prout(_("Transferring energy to shields.\""))
1230 prout(_("Draining energy from shields.\""))
1231 game.shield += aaitem
1232 game.energy -= aaitem
1236 # choose a device to damage, at random.
1238 # Quoth Eric Allman in the code of BSD-Trek:
1239 # "Under certain conditions you can get a critical hit. This
1240 # sort of hit damages devices. The probability that a given
1241 # device is damaged depends on the device. Well protected
1242 # devices (such as the computer, which is in the core of the
1243 # ship and has considerable redundancy) almost never get
1244 # damaged, whereas devices which are exposed (such as the
1245 # warp engines) or which are particularly delicate (such as
1246 # the transporter) have a much higher probability of being
1249 # This is one place where OPTION_PLAIN does not restore the
1250 # original behavior, which was equiprobable damage across
1251 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1252 # and have done with it. Also, in the original game, DNAVYS
1253 # and DCOMPTR were the same device.
1255 # Instead, we use a table of weights similar to the one from BSD Trek.
1256 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1257 # We don't have a cloaking device. The shuttle got the allocation
1258 # for the cloaking device, then we shaved a half-percent off
1259 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1262 105, # DSRSENS: short range scanners 10.5%
1263 105, # DLRSENS: long range scanners 10.5%
1264 120, # DPHASER: phasers 12.0%
1265 120, # DPHOTON: photon torpedoes 12.0%
1266 25, # DLIFSUP: life support 2.5%
1267 65, # DWARPEN: warp drive 6.5%
1268 70, # DIMPULS: impulse engines 6.5%
1269 145, # DSHIELD: deflector shields 14.5%
1270 30, # DRADIO: subspace radio 3.0%
1271 45, # DSHUTTL: shuttle 4.5%
1272 15, # DCOMPTR: computer 1.5%
1273 20, # NAVCOMP: navigation system 2.0%
1274 75, # DTRANSP: transporter 7.5%
1275 20, # DSHCTRL: high-speed shield controller 2.0%
1276 10, # DDRAY: death ray 1.0%
1277 30, # DDSP: deep-space probes 3.0%
1279 idx = randrange(1000) # weights must sum to 1000
1281 for (i, w) in enumerate(weights):
1285 return None; # we should never get here
1287 def ram(ibumpd, ienm, w):
1288 # make our ship ram something
1289 prouts(_("***RED ALERT! RED ALERT!"))
1291 prout(_("***COLLISION IMMINENT."))
1295 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1297 proutn(_(" rammed by "))
1300 crmena(False, ienm, "sector", w)
1302 proutn(_(" (original position)"))
1304 deadkl(w, ienm, game.sector)
1307 prout(_(" heavily damaged."))
1308 icas = randrange(10, 30)
1309 prout(_("***Sickbay reports %d casualties"), icas)
1311 game.state.crew -= icas
1313 # In the pre-SST2K version, all devices got equiprobably damaged,
1314 # which was silly. Instead, pick up to half the devices at
1315 # random according to our weighting table,
1317 ncrits = randrange(NDEVICES/2)
1318 for m in range(ncrits):
1320 if game.damage[dev] < 0:
1322 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1323 # Damage for at least time of travel!
1324 game.damage[dev] += game.optime + extradm
1326 prout(_("***Shields are down."))
1327 if game.state.remkl + game.state.remcom + game.state.nscrem:
1334 def torpedo(course, r, incoming, i, n):
1335 # let a photon torpedo fly
1338 ac = course + 0.25*r
1339 angle = (15.0-ac)*0.5235988
1340 bullseye = (15.0 - course)*0.5235988
1341 deltax = -math.sin(angle);
1342 deltay = math.cos(angle);
1343 x = incoming.x; y = incoming.y
1344 w = coord(); jw = coord()
1345 w.x = w.y = jw.x = jw.y = 0
1346 bigger = max(math.fabs(deltax), math.fabs(deltay))
1349 if not damaged(DSRSENS) or game.condition=="docked":
1350 setwnd(srscan_window)
1352 setwnd(message_window)
1353 # Loop to move a single torpedo
1354 for l in range(1, 15+1):
1359 if not VALID_SECTOR(w.x, w.y):
1361 iquad=game.quad[w.x][w.y]
1362 tracktorpedo(w, l, i, n, iquad)
1366 setwnd(message_window)
1367 if damaged(DSRSENS) and not game.condition=="docked":
1368 skip(1); # start new line after text track
1369 if iquad in (IHE, IHF): # Hit our ship
1371 proutn(_("Torpedo hits "))
1374 hit = 700.0 + randreal(100) - \
1375 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1376 newcnd(); # we're blown out of dock
1377 # We may be displaced.
1378 if game.landed or game.condition=="docked":
1379 return hit # Cheat if on a planet
1380 ang = angle + 2.5*(randreal()-0.5)
1381 temp = math.fabs(math.sin(ang))
1382 if math.fabs(math.cos(ang)) > temp:
1383 temp = math.fabs(math.cos(ang))
1384 xx = -math.sin(ang)/temp
1385 yy = math.cos(ang)/temp
1386 jw.x = int(w.x+xx+0.5)
1387 jw.y = int(w.y+yy+0.5)
1388 if not VALID_SECTOR(jw.x, jw.y):
1390 if game.quad[jw.x][jw.y]==IHBLANK:
1393 if game.quad[jw.x][jw.y]!=IHDOT:
1394 # can't move into object
1399 elif iquad in (IHC, IHS): # Hit a commander
1401 crmena(True, iquad, "sector", w)
1402 prout(_(" uses anti-photon device;"))
1403 prout(_(" torpedo neutralized."))
1405 elif iquad in (IHR, IHK): # Hit a regular enemy
1407 for enemy in game.enemies:
1408 if w == game.enemies[ll].kloc:
1410 kp = math.fabs(e.kpower)
1411 h1 = 700.0 + randrange(100) - \
1412 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1416 if enemy.kpower < 0:
1420 if enemy.kpower == 0:
1423 crmena(True, iquad, "sector", w)
1424 # If enemy damaged but not destroyed, try to displace
1425 ang = angle + 2.5*(randreal()-0.5)
1426 temp = math.fabs(math.sin(ang))
1427 if math.fabs(math.cos(ang)) > temp:
1428 temp = math.fabs(math.cos(ang))
1429 xx = -math.sin(ang)/temp
1430 yy = math.cos(ang)/temp
1433 if not VALID_SECTOR(jw.x, jw.y):
1434 prout(_(" damaged but not destroyed."))
1436 if game.quad[jw.x][jw.y]==IHBLANK:
1437 prout(_(" buffeted into black hole."))
1438 deadkl(w, iquad, jw)
1440 if game.quad[jw.x][jw.y]!=IHDOT:
1441 # can't move into object
1442 prout(_(" damaged but not destroyed."))
1444 proutn(_(" damaged--"))
1448 elif iquad == IHB: # Hit a base
1450 prout(_("***STARBASE DESTROYED.."))
1451 for ll in range(game.state.rembase):
1452 if game.state.baseq[ll] == game.quadrant:
1453 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1455 game.quad[w.x][w.y]=IHDOT
1456 game.state.rembase -= 1
1457 game.base.x=game.base.y=0
1458 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1459 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1460 game.state.basekl += 1
1463 elif iquad == IHP: # Hit a planet
1464 crmena(True, iquad, "sector", w)
1465 prout(_(" destroyed."))
1466 game.state.nplankl += 1
1467 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1468 game.iplnet.pclass = "destroyed"
1470 invalidate(game.plnet)
1471 game.quad[w.x][w.y] = IHDOT
1473 # captain perishes on planet
1476 elif iquad == IHW: # Hit an inhabited world -- very bad!
1477 crmena(True, iquad, "sector", w)
1478 prout(_(" destroyed."))
1479 game.state.nworldkl += 1
1480 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1481 game.iplnet.pclass = "destroyed"
1483 invalidate(game.plnet)
1484 game.quad[w.x][w.y] = IHDOT
1486 # captain perishes on planet
1488 prout(_("You have just destroyed an inhabited planet."))
1489 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1491 elif iquad == IHSTAR: # Hit a star
1495 crmena(True, IHSTAR, "sector", w)
1496 prout(_(" unaffected by photon blast."))
1498 elif iquad == IHQUEST: # Hit a thingy
1499 if not (game.options & OPTION_THINGY) or withprob(0.3):
1501 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1503 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1505 proutn(_("Mr. Spock-"))
1506 prouts(_(" \"Fascinating!\""))
1511 # Stas Sergeev added the possibility that
1512 # you can shove the Thingy and piss it off.
1513 # It then becomes an enemy and may fire at you.
1518 elif iquad == IHBLANK: # Black hole
1520 crmena(True, IHBLANK, "sector", w)
1521 prout(_(" swallows torpedo."))
1523 elif iquad == IHWEB: # hit the web
1525 prout(_("***Torpedo absorbed by Tholian web."))
1527 elif iquad == IHT: # Hit a Tholian
1528 h1 = 700.0 + randrange(100) - \
1529 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1532 game.quad[w.x][w.y] = IHDOT
1537 crmena(True, IHT, "sector", w)
1539 prout(_(" survives photon blast."))
1541 prout(_(" disappears."))
1542 game.tholian.move(None)
1543 game.quad[w.x][w.y] = IHWEB
1548 proutn("Don't know how to handle torpedo collision with ")
1549 crmena(True, iquad, "sector", w)
1553 if curwnd!=message_window:
1554 setwnd(message_window)
1556 game.quad[w.x][w.y]=IHDOT
1557 game.quad[jw.x][jw.y]=iquad
1558 prout(_(" displaced by blast to Sector %s ") % jw)
1559 for ll in range(len(game.enemies)):
1560 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector,game.enemies[ll].kloc)
1561 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1564 prout(_("Torpedo missed."))
1568 # critical-hit resolution
1569 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1571 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1572 proutn(_("***CRITICAL HIT--"))
1573 # Select devices and cause damage
1575 for loop1 in range(ncrit):
1578 # Cheat to prevent shuttle damage unless on ship
1579 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1582 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1583 game.damage[j] += extradm
1585 for (i, j) in enumerate(cdam):
1587 if skipcount % 3 == 2 and i < len(cdam)-1:
1592 prout(_(" damaged."))
1593 if damaged(DSHIELD) and game.shldup:
1594 prout(_("***Shields knocked down."))
1597 def attack(torps_ok):
1598 # bad guy attacks us
1599 # torps_ok == False forces use of phasers in an attack
1600 attempt = False; ihurt = False;
1601 hitmax=0.0; hittot=0.0; chgfac=1.0
1603 # game could be over at this point, check
1607 prout("=== ATTACK!")
1608 # Tholian gets to move before attacking
1611 # if you have just entered the RNZ, you'll get a warning
1612 if game.neutz: # The one chance not to be attacked
1615 # commanders get a chance to tac-move towards you
1616 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1618 # if no enemies remain after movement, we're done
1619 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1621 # set up partial hits if attack happens during shield status change
1622 pfac = 1.0/game.inshld
1624 chgfac = 0.25 + randreal(0.5)
1626 # message verbosity control
1627 if game.skill <= SKILL_FAIR:
1629 for enemy in game.enemies:
1630 if enemy.kpower < 0:
1631 continue; # too weak to attack
1632 # compute hit strength and diminish shield power
1634 # Increase chance of photon torpedos if docked or enemy energy is low
1635 if game.condition == "docked":
1637 if enemy.kpower < 500:
1639 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1641 # different enemies have different probabilities of throwing a torp
1642 usephasers = not torps_ok or \
1643 (enemy.type == IHK and r > 0.0005) or \
1644 (enemy.type==IHC and r > 0.015) or \
1645 (enemy.type==IHR and r > 0.3) or \
1646 (enemy.type==IHS and r > 0.07) or \
1647 (enemy.type==IHQUEST and r > 0.05)
1648 if usephasers: # Enemy uses phasers
1649 if game.condition == "docked":
1650 continue; # Don't waste the effort!
1651 attempt = True; # Attempt to attack
1652 dustfac = 0.8 + randreal(0.5)
1653 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1654 enemy.kpower *= 0.75
1655 else: # Enemy uses photon torpedo
1656 course = 1.90985*math.atan2(game.sector.y-enemy.kloc.y, enemy.kloc.x-game.sector.x)
1658 proutn(_("***TORPEDO INCOMING"))
1659 if not damaged(DSRSENS):
1661 crmena(False, enemy.type, where, enemy.kloc)
1664 r = (randreal()+randreal())*0.5 - 0.5
1665 r += 0.002*enemy.kpower*r
1666 hit = torpedo(course, r, enemy.kloc, 1, 1)
1667 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1668 finish(FWON); # Klingons did themselves in!
1669 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1670 return # Supernova or finished
1673 # incoming phaser or torpedo, shields may dissipate it
1674 if game.shldup or game.shldchg or game.condition=="docked":
1675 # shields will take hits
1676 propor = pfac * game.shield
1677 if game.condition =="docked":
1681 hitsh = propor*chgfac*hit+1.0
1683 if absorb > game.shield:
1684 absorb = game.shield
1685 game.shield -= absorb
1687 # taking a hit blasts us out of a starbase dock
1688 if game.condition == "docked":
1690 # but the shields may take care of it
1691 if propor > 0.1 and hit < 0.005*game.energy:
1693 # hit from this opponent got through shields, so take damage
1695 proutn(_("%d unit hit") % int(hit))
1696 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1697 proutn(_(" on the "))
1699 if not damaged(DSRSENS) and usephasers:
1701 crmena(False, enemy.type, where, enemy.kloc)
1703 # Decide if hit is critical
1709 if game.energy <= 0:
1710 # Returning home upon your shield, not with it...
1713 if not attempt and game.condition == "docked":
1714 prout(_("***Enemies decide against attacking your ship."))
1715 percent = 100.0*pfac*game.shield+0.5
1717 # Shields fully protect ship
1718 proutn(_("Enemy attack reduces shield strength to "))
1720 # Print message if starship suffered hit(s)
1722 proutn(_("Energy left %2d shields ") % int(game.energy))
1725 elif not damaged(DSHIELD):
1728 proutn(_("damaged, "))
1729 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1730 # Check if anyone was hurt
1731 if hitmax >= 200 or hittot >= 500:
1732 icas = randrange(hittot * 0.015)
1735 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1736 prout(_(" in that last attack.\""))
1738 game.state.crew -= icas
1739 # After attack, reset average distance to enemies
1740 for enemy in game.enemies:
1741 enemy.kavgd = enemy.kdist
1742 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1745 def deadkl(w, type, mv):
1746 # kill a Klingon, Tholian, Romulan, or Thingy
1747 # Added mv to allow enemy to "move" before dying
1748 crmena(True, type, "sector", mv)
1749 # Decide what kind of enemy it is and update appropriately
1751 # chalk up a Romulan
1752 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1754 game.state.nromrem -= 1
1758 elif type == IHQUEST:
1763 # Some type of a Klingon
1764 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1767 game.comhere = False
1768 for i in range(game.state.remcom):
1769 if game.state.kcmdr[i] == game.quadrant:
1771 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1772 game.state.kcmdr[game.state.remcom].x = 0
1773 game.state.kcmdr[game.state.remcom].y = 0
1774 game.state.remcom -= 1
1776 if game.state.remcom != 0:
1777 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1778 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1781 game.state.remkl -= 1
1783 game.state.nscrem -= 1
1785 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1789 # For each kind of enemy, finish message to player
1790 prout(_(" destroyed."))
1791 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1794 # Remove enemy ship from arrays describing local conditions
1795 for e in game.enemies:
1801 def targetcheck(x, y):
1802 # Return None if target is invalid
1803 if not VALID_SECTOR(x, y):
1806 deltx = 0.1*(y - game.sector.y)
1807 delty = 0.1*(x - game.sector.x)
1808 if deltx==0 and delty== 0:
1810 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1811 prout(_(" I recommend an immediate review of"))
1812 prout(_(" the Captain's psychological profile.\""))
1815 return 1.90985932*math.atan2(deltx, delty)
1818 # launch photon torpedo
1820 if damaged(DPHOTON):
1821 prout(_("Photon tubes damaged."))
1825 prout(_("No torpedoes left."))
1834 prout(_("%d torpedoes left.") % game.torps)
1835 proutn(_("Number of torpedoes to fire- "))
1837 else: # key == IHREAL {
1839 if n <= 0: # abort command
1844 prout(_("Maximum of 3 torpedoes per burst."))
1851 for i in range(1, n+1):
1853 if i==1 and key == IHEOL:
1854 break; # we will try prompting
1855 if i==2 and key == IHEOL:
1856 # direct all torpedoes at one target
1858 targ[i][1] = targ[1][1]
1859 targ[i][2] = targ[1][2]
1860 course[i] = course[1]
1872 course[i] = targetcheck(targ[i][1], targ[i][2])
1873 if course[i] == None:
1876 if i == 1 and key == IHEOL:
1877 # prompt for each one
1878 for i in range(1, n+1):
1879 proutn(_("Target sector for torpedo number %d- ") % i)
1884 targ[i][1] = int(aaitem-0.5)
1889 targ[i][2] = int(aaitem-0.5)
1891 course[i] = targetcheck(targ[i][1], targ[i][2])
1892 if course[i] == None:
1895 # Loop for moving <n> torpedoes
1897 if game.condition != "docked":
1899 r = (randreal()+randreal())*0.5 -0.5
1900 if math.fabs(r) >= 0.47:
1902 r *= randreal(1.2, 2.2)
1904 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1906 prouts(_("***TORPEDO MISFIRES."))
1909 prout(_(" Remainder of burst aborted."))
1911 prout(_("***Photon tubes damaged by misfire."))
1912 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1914 if game.shldup or game.condition == "docked":
1915 r *= 1.0 + 0.0001*game.shield
1916 torpedo(course[i], r, game.sector, i, n)
1917 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1919 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1923 # check for phasers overheating
1925 checkburn = (rpow-1500.0)*0.00038
1926 if withprob(checkburn):
1927 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1928 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1930 def checkshctrl(rpow):
1931 # check shield control
1934 prout(_("Shields lowered."))
1936 # Something bad has happened
1937 prouts(_("***RED ALERT! RED ALERT!"))
1939 hit = rpow*game.shield/game.inshld
1940 game.energy -= rpow+hit*0.8
1941 game.shield -= hit*0.2
1942 if game.energy <= 0.0:
1943 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1948 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1950 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1951 icas = randrange(hit*0.012)
1956 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1957 prout(_(" %d casualties so far.\"") % icas)
1959 game.state.crew -= icas
1961 prout(_("Phaser energy dispersed by shields."))
1962 prout(_("Enemy unaffected."))
1967 # register a phaser hit on Klingons and Romulans
1968 nenhr2 = game.nenhere; kk=0
1971 for (k, wham) in enumerate(hits):
1974 dustfac = randreal(0.9, 1.0)
1975 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1976 kpini = game.enemies[kk].kpower
1977 kp = math.fabs(kpini)
1978 if PHASEFAC*hit < kp:
1980 if game.enemies[kk].kpower < 0:
1981 game.enemies[kk].kpower -= -kp
1983 game.enemies[kk].kpower -= kp
1984 kpow = game.enemies[kk].kpower
1985 w = game.enemies[kk].kloc
1987 if not damaged(DSRSENS):
1989 proutn(_("%d unit hit on ") % int(hit))
1991 proutn(_("Very small hit on "))
1992 ienm = game.quad[w.x][w.y]
1995 crmena(False, ienm, "sector", w)
1999 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2003 kk -= 1 # don't do the increment
2005 else: # decide whether or not to emasculate klingon
2006 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2007 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2008 prout(_(" has just lost its firepower.\""))
2009 game.enemies[kk].kpower = -kpow
2016 kz = 0; k = 1; irec=0 # Cheating inhibitor
2017 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2021 # SR sensors and Computer are needed fopr automode
2022 if damaged(DSRSENS) or damaged(DCOMPTR):
2024 if game.condition == "docked":
2025 prout(_("Phasers can't be fired through base shields."))
2028 if damaged(DPHASER):
2029 prout(_("Phaser control damaged."))
2033 if damaged(DSHCTRL):
2034 prout(_("High speed shield control damaged."))
2037 if game.energy <= 200.0:
2038 prout(_("Insufficient energy to activate high-speed shield control."))
2041 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2043 # Original code so convoluted, I re-did it all
2044 # (That was Tom Almy talking about the C code, I think -- ESR)
2045 while automode=="NOTSET":
2050 prout(_("There is no enemy present to select."))
2053 automode="AUTOMATIC"
2057 elif isit("automatic"):
2058 if (not itarg) and game.nenhere != 0:
2059 automode = "FORCEMAN"
2062 prout(_("Energy will be expended into space."))
2063 automode = "AUTOMATIC"
2072 prout(_("Energy will be expended into space."))
2073 automode = "AUTOMATIC"
2075 automode = "FORCEMAN"
2077 automode = "AUTOMATIC"
2081 prout(_("Energy will be expended into space."))
2082 automode = "AUTOMATIC"
2084 automode = "FORCEMAN"
2086 proutn(_("Manual or automatic? "))
2091 if automode == "AUTOMATIC":
2092 if key == IHALPHA and isit("no"):
2095 if key != IHREAL and game.nenhere != 0:
2096 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2101 for i in range(game.nenhere):
2102 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2104 proutn(_("%d units required. ") % irec)
2106 proutn(_("Units to fire= "))
2112 proutn(_("Energy available= %.2f") % avail)
2115 if not rpow > avail:
2122 if key == IHALPHA and isit("no"):
2125 game.energy -= 200; # Go and do it!
2126 if checkshctrl(rpow):
2134 for i in range(game.nenhere):
2138 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2139 over = randreal(1.01, 1.06) * hits[i]
2141 powrem -= hits[i] + over
2142 if powrem <= 0 and temp < hits[i]:
2151 if extra > 0 and not game.alldone:
2153 proutn(_("*** Tholian web absorbs "))
2155 proutn(_("excess "))
2156 prout(_("phaser energy."))
2158 prout(_("%d expended on empty space.") % int(extra))
2159 elif automode == "FORCEMAN":
2162 if damaged(DCOMPTR):
2163 prout(_("Battle computer damaged, manual fire only."))
2166 prouts(_("---WORKING---"))
2168 prout(_("Short-range-sensors-damaged"))
2169 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2170 prout(_("Manual-fire-must-be-used"))
2172 elif automode == "MANUAL":
2174 for k in range(game.nenhere):
2175 aim = game.enemies[k].kloc
2176 ienm = game.quad[aim.x][aim.y]
2178 proutn(_("Energy available= %.2f") % (avail-0.006))
2182 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2183 (ienm == IHC or ienm == IHS):
2185 prout(_(" can't be located without short range scan."))
2188 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2193 if itarg and k > kz:
2194 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2197 if not damaged(DCOMPTR):
2202 proutn(_("units to fire at "))
2203 crmena(False, ienm, "sector", aim)
2206 if key == IHALPHA and isit("no"):
2214 if k==1: # Let me say I'm baffled by this
2223 # If total requested is too much, inform and start over
2225 prout(_("Available energy exceeded -- try again."))
2228 key = scan(); # scan for next value
2231 # zero energy -- abort
2234 if key == IHALPHA and isit("no"):
2239 game.energy -= 200.0
2240 if checkshctrl(rpow):
2244 # Say shield raised or malfunction, if necessary
2251 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2252 prouts(_(" CLICK CLICK POP . . ."))
2253 prout(_(" No response, sir!"))
2256 prout(_("Shields raised."))
2261 # Code from events,c begins here.
2263 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2264 # event of each type active at any given time. Mostly these means we can
2265 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2266 # BSD Trek, from which we swiped the idea, can have up to 5.
2268 def unschedule(evtype):
2269 # remove an event from the schedule
2270 game.future[evtype].date = FOREVER
2271 return game.future[evtype]
2273 def is_scheduled(evtype):
2274 # is an event of specified type scheduled
2275 return game.future[evtype].date != FOREVER
2277 def scheduled(evtype):
2278 # when will this event happen?
2279 return game.future[evtype].date
2281 def schedule(evtype, offset):
2282 # schedule an event of specified type
2283 game.future[evtype].date = game.state.date + offset
2284 return game.future[evtype]
2286 def postpone(evtype, offset):
2287 # postpone a scheduled event
2288 game.future[evtype].date += offset
2291 # rest period is interrupted by event
2294 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2296 game.resting = False
2302 # run through the event queue looking for things to do
2304 fintim = game.state.date + game.optime; yank=0
2305 ictbeam = False; istract = False
2306 w = coord(); hold = coord()
2307 ev = event(); ev2 = event()
2309 def tractorbeam(yank):
2310 # tractor beaming cases merge here
2312 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2316 prout(_(" caught in long range tractor beam--"))
2317 # If Kirk & Co. screwing around on planet, handle
2318 atover(True) # atover(true) is Grab
2321 if game.icraft: # Caught in Galileo?
2324 # Check to see if shuttle is aboard
2325 if game.iscraft == "offship":
2328 prout(_("Galileo, left on the planet surface, is captured"))
2329 prout(_("by aliens and made into a flying McDonald's."))
2330 game.damage[DSHUTTL] = -10
2331 game.iscraft = "removed"
2333 prout(_("Galileo, left on the planet surface, is well hidden."))
2335 game.quadrant = game.state.kscmdr
2337 game.quadrant = game.state.kcmdr[i]
2338 game.sector = randplace(QUADSIZE)
2340 prout(_(" is pulled to Quadrant %s, Sector %s") \
2341 % (game.quadrant, game.sector))
2343 prout(_("(Remainder of rest/repair period cancelled.)"))
2344 game.resting = False
2346 if not damaged(DSHIELD) and game.shield > 0:
2347 doshield(shraise=True) # raise shields
2348 game.shldchg = False
2350 prout(_("(Shields not currently useable.)"))
2352 # Adjust finish time to time of tractor beaming
2353 fintim = game.state.date+game.optime
2355 if game.state.remcom <= 0:
2358 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2361 # Code merges here for any commander destroying base
2362 # Not perfect, but will have to do
2363 # Handle case where base is in same quadrant as starship
2364 if game.battle == game.quadrant:
2365 game.state.chart[game.battle.x][game.battle.y].starbase = False
2366 game.quad[game.base.x][game.base.y] = IHDOT
2367 game.base.x=game.base.y=0
2370 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2371 elif game.state.rembase != 1 and communicating():
2372 # Get word via subspace radio
2375 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2376 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2378 prout(_("the Klingon Super-Commander"))
2380 prout(_("a Klingon Commander"))
2381 game.state.chart[game.battle.x][game.battle.y].starbase = False
2382 # Remove Starbase from galaxy
2383 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2384 for i in range(1, game.state.rembase+1):
2385 if game.state.baseq[i] == game.battle:
2386 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2387 game.state.rembase -= 1
2389 # reinstate a commander's base attack
2393 invalidate(game.battle)
2396 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2397 for i in range(1, NEVENTS):
2398 if i == FSNOVA: proutn("=== Supernova ")
2399 elif i == FTBEAM: proutn("=== T Beam ")
2400 elif i == FSNAP: proutn("=== Snapshot ")
2401 elif i == FBATTAK: proutn("=== Base Attack ")
2402 elif i == FCDBAS: proutn("=== Base Destroy ")
2403 elif i == FSCMOVE: proutn("=== SC Move ")
2404 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2405 elif i == FDSPROB: proutn("=== Probe Move ")
2406 elif i == FDISTR: proutn("=== Distress Call ")
2407 elif i == FENSLV: proutn("=== Enslavement ")
2408 elif i == FREPRO: proutn("=== Klingon Build ")
2410 prout("%.2f" % (scheduled(i)))
2413 radio_was_broken = damaged(DRADIO)
2416 # Select earliest extraneous event, evcode==0 if no events
2421 for l in range(1, NEVENTS):
2422 if game.future[l].date < datemin:
2425 prout("== Event %d fires" % evcode)
2426 datemin = game.future[l].date
2427 xtime = datemin-game.state.date
2428 game.state.date = datemin
2429 # Decrement Federation resources and recompute remaining time
2430 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2432 if game.state.remtime <=0:
2435 # Any crew left alive?
2436 if game.state.crew <=0:
2439 # Is life support adequate?
2440 if damaged(DLIFSUP) and game.condition != "docked":
2441 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2444 game.lsupres -= xtime
2445 if game.damage[DLIFSUP] <= xtime:
2446 game.lsupres = game.inlsr
2449 if game.condition == "docked":
2450 repair /= game.docfac
2451 # Don't fix Deathray here
2452 for l in range(NDEVICES):
2453 if game.damage[l] > 0.0 and l != DDRAY:
2454 if game.damage[l]-repair > 0.0:
2455 game.damage[l] -= repair
2457 game.damage[l] = 0.0
2458 # If radio repaired, update star chart and attack reports
2459 if radio_was_broken and not damaged(DRADIO):
2460 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2461 prout(_(" surveillance reports are coming in."))
2463 if not game.iseenit:
2467 prout(_(" The star chart is now up to date.\""))
2469 # Cause extraneous event EVCODE to occur
2470 game.optime -= xtime
2471 if evcode == FSNOVA: # Supernova
2474 schedule(FSNOVA, expran(0.5*game.intime))
2475 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2477 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2478 if game.state.nscrem == 0 or \
2479 ictbeam or istract or \
2480 game.condition=="docked" or game.isatb==1 or game.iscate:
2482 if game.ientesc or \
2483 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2484 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2485 (damaged(DSHIELD) and \
2486 (game.energy < 2500 or damaged(DPHASER)) and \
2487 (game.torps < 5 or damaged(DPHOTON))):
2489 istract = ictbeam = True
2490 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2493 elif evcode == FTBEAM: # Tractor beam
2494 if game.state.remcom == 0:
2497 i = randrange(game.state.remcom)
2498 yank = distance(game.state.kcmdr[i], game.quadrant)
2499 if istract or game.condition == "docked" or yank == 0:
2500 # Drats! Have to reschedule
2502 game.optime + expran(1.5*game.intime/game.state.remcom))
2506 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2507 game.snapsht = copy.deepcopy(game.state)
2508 game.state.snap = True
2509 schedule(FSNAP, expran(0.5 * game.intime))
2510 elif evcode == FBATTAK: # Commander attacks starbase
2511 if game.state.remcom==0 or game.state.rembase==0:
2517 for j in range(game.state.rembase):
2518 for k in range(game.state.remcom):
2519 if game.state.baseq[j] == game.state.kcmdr[k] and \
2520 not game.state.baseq[j] == game.quadrant and \
2521 not game.state.baseq[j] == game.state.kscmdr:
2525 if j>game.state.rembase:
2526 # no match found -- try later
2527 schedule(FBATTAK, expran(0.3*game.intime))
2530 # commander + starbase combination found -- launch attack
2531 game.battle = game.state.baseq[j]
2532 schedule(FCDBAS, randreal(1.0, 4.0))
2533 if game.isatb: # extra time if SC already attacking
2534 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2535 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2536 game.iseenit = False
2537 if not communicating():
2538 continue # No warning :-(
2542 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2543 prout(_(" reports that it is under attack and that it can"))
2544 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2547 elif evcode == FSCDBAS: # Supercommander destroys base
2550 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2551 continue # WAS RETURN!
2553 game.battle = game.state.kscmdr
2555 elif evcode == FCDBAS: # Commander succeeds in destroying base
2558 # find the lucky pair
2559 for i in range(game.state.remcom):
2560 if game.state.kcmdr[i] == game.battle:
2562 if i > game.state.remcom or game.state.rembase == 0 or \
2563 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2564 # No action to take after all
2565 invalidate(game.battle)
2568 elif evcode == FSCMOVE: # Supercommander moves
2569 schedule(FSCMOVE, 0.2777)
2570 if not game.ientesc and not istract and game.isatb != 1 and \
2571 (not game.iscate or not game.justin):
2573 elif evcode == FDSPROB: # Move deep space probe
2574 schedule(FDSPROB, 0.01)
2575 game.probex += game.probeinx
2576 game.probey += game.probeiny
2577 i = (int)(game.probex/QUADSIZE +0.05)
2578 j = (int)(game.probey/QUADSIZE + 0.05)
2579 if game.probec.x != i or game.probec.y != j:
2582 if not VALID_QUADRANT(i, j) or \
2583 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2584 # Left galaxy or ran into supernova
2588 proutn(_("Lt. Uhura- \"The deep space probe "))
2589 if not VALID_QUADRANT(j, i):
2590 proutn(_("has left the galaxy"))
2592 proutn(_("is no longer transmitting"))
2596 if not communicating():
2599 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2600 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2601 # Update star chart if Radio is working or have access to radio
2603 chp = game.state.chart[game.probec.x][game.probec.y]
2604 chp.klingons = pdest.klingons
2605 chp.starbase = pdest.starbase
2606 chp.stars = pdest.stars
2607 pdest.charted = True
2608 game.proben -= 1 # One less to travel
2609 if game.proben == 0 and game.isarmed and pdest.stars:
2610 # lets blow the sucker!
2611 supernova(True, game.probec)
2613 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2615 elif evcode == FDISTR: # inhabited system issues distress call
2617 # try a whole bunch of times to find something suitable
2618 for i in range(100):
2619 # need a quadrant which is not the current one,
2620 # which has some stars which are inhabited and
2621 # not already under attack, which is not
2622 # supernova'ed, and which has some Klingons in it
2623 w = randplace(GALSIZE)
2624 q = game.state.galaxy[w.x][w.y]
2625 if not (game.quadrant == w or q.planet == None or \
2626 not q.planet.inhabited or \
2627 q.supernova or q.status!="secure" or q.klingons<=0):
2630 # can't seem to find one; ignore this call
2632 prout("=== Couldn't find location for distress event.")
2634 # got one!! Schedule its enslavement
2635 ev = schedule(FENSLV, expran(game.intime))
2637 q.status = distressed
2639 # tell the captain about it if we can
2641 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2643 prout(_("by a Klingon invasion fleet."))
2646 elif evcode == FENSLV: # starsystem is enslaved
2647 ev = unschedule(FENSLV)
2648 # see if current distress call still active
2649 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2653 q.status = "enslaved"
2655 # play stork and schedule the first baby
2656 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2657 ev2.quadrant = ev.quadrant
2659 # report the disaster if we can
2661 prout(_("Uhura- We've lost contact with starsystem %s") % \
2663 prout(_("in Quadrant %s.\n") % ev.quadrant)
2664 elif evcode == FREPRO: # Klingon reproduces
2665 # If we ever switch to a real event queue, we'll need to
2666 # explicitly retrieve and restore the x and y.
2667 ev = schedule(FREPRO, expran(1.0 * game.intime))
2668 # see if current distress call still active
2669 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2673 if game.state.remkl >=MAXKLGAME:
2674 continue # full right now
2675 # reproduce one Klingon
2677 if game.klhere >= MAXKLQUAD:
2679 # this quadrant not ok, pick an adjacent one
2680 for i in range(w.x - 1, w.x + 2):
2681 for j in range(w.y - 1, w.y + 2):
2682 if not VALID_QUADRANT(i, j):
2684 q = game.state.galaxy[w.x][w.y]
2685 # check for this quad ok (not full & no snova)
2686 if q.klingons >= MAXKLQUAD or q.supernova:
2690 continue # search for eligible quadrant failed
2695 game.state.remkl += 1
2697 if game.quadrant == w:
2699 game.enemies.append(newkling())
2700 # recompute time left
2702 # report the disaster if we can
2704 if game.quadrant == w:
2705 prout(_("Spock- sensors indicate the Klingons have"))
2706 prout(_("launched a warship from %s.") % q.planet)
2708 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2709 if q.planet != None:
2710 proutn(_("near %s") % q.planet)
2711 prout(_("in Quadrant %s.") % w)
2720 proutn(_("How long? "))
2725 origTime = delay = aaitem
2728 if delay >= game.state.remtime or game.nenhere != 0:
2729 proutn(_("Are you sure? "))
2732 # Alternate resting periods (events) with attacks
2736 game.resting = False
2737 if not game.resting:
2738 prout(_("%d stardates left.") % int(game.state.remtime))
2740 temp = game.optime = delay
2742 rtime = randreal(1.0, 2.0)
2746 if game.optime < delay:
2755 # Repair Deathray if long rest at starbase
2756 if origTime-delay >= 9.99 and game.condition == "docked":
2757 game.damage[DDRAY] = 0.0
2758 # leave if quadrant supernovas
2759 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2761 game.resting = False
2764 # A nova occurs. It is the result of having a star hit with a
2765 # photon torpedo, or possibly of a probe warhead going off.
2766 # Stars that go nova cause stars which surround them to undergo
2767 # the same probabilistic process. Klingons next to them are
2768 # destroyed. And if the starship is next to it, it gets zapped.
2769 # If the zap is too much, it gets destroyed.
2773 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2774 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2776 # Wow! We've supernova'ed
2777 supernova(False, nov)
2779 # handle initial nova
2780 game.quad[nov.x][nov.y] = IHDOT
2781 crmena(False, IHSTAR, "sector", nov)
2783 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2784 game.state.starkl += 1
2785 # Set up queue to recursively trigger adjacent stars
2791 for offset.x in range(-1, 1+1):
2792 for offset.y in range(-1, 1+1):
2793 if offset.y==0 and offset.x==0:
2795 neighbor = start + offset
2796 if not VALID_SECTOR(neighbor.y, neighbor.x):
2798 iquad = game.quad[neighbor.x][neighbor.y]
2799 # Empty space ends reaction
2800 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2802 elif iquad == IHSTAR: # Affect another star
2804 # This star supernovas
2808 hits.append(neighbor)
2809 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2810 game.state.starkl += 1
2811 crmena(True, IHSTAR, "sector", neighbor)
2813 game.quad[neighbor.x][neighbor.y] = IHDOT
2815 elif iquad in (IHP, IHW): # Destroy planet
2816 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2818 game.state.nplankl += 1
2820 game.state.worldkl += 1
2821 crmena(True, iquad, "sector", neighbor)
2822 prout(_(" destroyed."))
2823 game.iplnet.pclass = "destroyed"
2825 invalidate(game.plnet)
2829 game.quad[neighbor.x][neighbor.y] = IHDOT
2830 elif iquad == IHB: # Destroy base
2831 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2832 for i in range(game.state.rembase):
2833 if game.state.baseq[i] == game.quadrant:
2835 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2836 game.state.rembase -= 1
2837 invalidate(game.base)
2838 game.state.basekl += 1
2840 crmena(True, IHB, "sector", neighbor)
2841 prout(_(" destroyed."))
2842 game.quad[neighbor.x][neighbor.y] = IHDOT
2843 elif iquad in (IHE, IHF): # Buffet ship
2844 prout(_("***Starship buffeted by nova."))
2846 if game.shield >= 2000.0:
2847 game.shield -= 2000.0
2849 diff = 2000.0 - game.shield
2853 prout(_("***Shields knocked out."))
2854 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2856 game.energy -= 2000.0
2857 if game.energy <= 0:
2860 # add in course nova contributes to kicking starship
2861 bump += (game.sector-hits[mm]).sgn()
2862 elif iquad == IHK: # kill klingon
2863 deadkl(neighbor, iquad, neighbor)
2864 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2865 for ll in range(game.nenhere):
2866 if game.enemies[ll].kloc == neighbor:
2868 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2869 if game.enemies[ll].kpower <= 0.0:
2870 deadkl(neighbor, iquad, neighbor)
2872 newc = neighbor + neighbor - hits[mm]
2873 crmena(True, iquad, "sector", neighbor)
2874 proutn(_(" damaged"))
2875 if not VALID_SECTOR(newc.x, newc.y):
2876 # can't leave quadrant
2879 iquad1 = game.quad[newc.x][newc.y]
2880 if iquad1 == IHBLANK:
2881 proutn(_(", blasted into "))
2882 crmena(False, IHBLANK, "sector", newc)
2884 deadkl(neighbor, iquad, newc)
2887 # can't move into something else
2890 proutn(_(", buffeted to Sector %s") % newc)
2891 game.quad[neighbor.x][neighbor.y] = IHDOT
2892 game.quad[newc.x][newc.y] = iquad
2893 game.enemies[ll].move(newc)
2894 # Starship affected by nova -- kick it away.
2895 game.dist = kount*0.1
2896 game.direc = course[3*(bump.x+1)+bump.y+2]
2897 if game.direc == 0.0:
2899 if game.dist == 0.0:
2901 game.optime = 10.0*game.dist/16.0
2903 prout(_("Force of nova displaces starship."))
2904 imove(novapush=True)
2905 game.optime = 10.0*game.dist/16.0
2908 def supernova(induced, w=None):
2909 # star goes supernova
2916 # Scheduled supernova -- select star
2917 # logic changed here so that we won't favor quadrants in top
2919 for nq.x in range(GALSIZE):
2920 for nq.y in range(GALSIZE):
2921 stars += game.state.galaxy[nq.x][nq.y].stars
2923 return # nothing to supernova exists
2924 num = randrange(stars) + 1
2925 for nq.x in range(GALSIZE):
2926 for nq.y in range(GALSIZE):
2927 num -= game.state.galaxy[nq.x][nq.y].stars
2933 proutn("=== Super nova here?")
2936 if not nq == game.quadrant or game.justin:
2937 # it isn't here, or we just entered (treat as enroute)
2940 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2941 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2944 # we are in the quadrant!
2945 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2946 for ns.x in range(QUADSIZE):
2947 for ns.y in range(QUADSIZE):
2948 if game.quad[ns.x][ns.y]==IHSTAR:
2955 prouts(_("***RED ALERT! RED ALERT!"))
2957 prout(_("***Incipient supernova detected at Sector %s") % ns)
2958 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2959 proutn(_("Emergency override attempts t"))
2960 prouts("***************")
2965 # destroy any Klingons in supernovaed quadrant
2966 kldead = game.state.galaxy[nq.x][nq.y].klingons
2967 game.state.galaxy[nq.x][nq.y].klingons = 0
2968 if nq == game.state.kscmdr:
2969 # did in the Supercommander!
2970 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2974 if game.state.remcom:
2975 maxloop = game.state.remcom
2976 for l in range(maxloop):
2977 if game.state.kcmdr[l] == nq:
2978 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
2979 invalidate(game.state.kcmdr[game.state.remcom])
2980 game.state.remcom -= 1
2982 if game.state.remcom==0:
2985 game.state.remkl -= kldead
2986 # destroy Romulans and planets in supernovaed quadrant
2987 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
2988 game.state.galaxy[nq.x][nq.y].romulans = 0
2989 game.state.nromrem -= nrmdead
2991 for loop in range(game.inplan):
2992 if game.state.planets[loop].w == nq:
2993 game.state.planets[loop].pclass = "destroyed"
2995 # Destroy any base in supernovaed quadrant
2996 if game.state.rembase:
2997 maxloop = game.state.rembase
2998 for loop in range(maxloop):
2999 if game.state.baseq[loop] == nq:
3000 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3001 invalidate(game.state.baseq[game.state.rembase])
3002 game.state.rembase -= 1
3004 # If starship caused supernova, tally up destruction
3006 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3007 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3008 game.state.nplankl += npdead
3009 # mark supernova in galaxy and in star chart
3010 if game.quadrant == nq or communicating():
3011 game.state.galaxy[nq.x][nq.y].supernova = True
3012 # If supernova destroys last Klingons give special message
3013 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3016 prout(_("Lucky you!"))
3017 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3020 # if some Klingons remain, continue or die in supernova
3025 # Code from finish.c ends here.
3028 # self-destruct maneuver
3029 # Finish with a BANG!
3031 if damaged(DCOMPTR):
3032 prout(_("Computer damaged; cannot execute destruct sequence."))
3034 prouts(_("---WORKING---")); skip(1)
3035 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3036 prouts(" 10"); skip(1)
3037 prouts(" 9"); skip(1)
3038 prouts(" 8"); skip(1)
3039 prouts(" 7"); skip(1)
3040 prouts(" 6"); skip(1)
3042 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3044 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3046 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3050 if game.passwd != citem:
3051 prouts(_("PASSWORD-REJECTED;"))
3053 prouts(_("CONTINUITY-EFFECTED"))
3056 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3057 prouts(" 5"); skip(1)
3058 prouts(" 4"); skip(1)
3059 prouts(" 3"); skip(1)
3060 prouts(" 2"); skip(1)
3061 prouts(" 1"); skip(1)
3063 prouts(_("GOODBYE-CRUEL-WORLD"))
3071 prouts(_("********* Entropy of "))
3073 prouts(_(" maximized *********"))
3077 if game.nenhere != 0:
3078 whammo = 25.0 * game.energy
3080 while l <= game.nenhere:
3081 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3082 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3087 "Compute our rate of kils over time."
3088 elapsed = game.state.date - game.indate
3089 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3092 starting = (game.inkling + game.incom + game.inscom)
3093 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3094 return (starting - remaining)/elapsed
3098 badpt = 5.0*game.state.starkl + \
3100 10.0*game.state.nplankl + \
3101 300*game.state.nworldkl + \
3103 100.0*game.state.basekl +\
3105 if game.ship == IHF:
3107 elif game.ship == None:
3112 # end the game, with appropriate notfications
3116 prout(_("It is stardate %.1f.") % game.state.date)
3118 if ifin == FWON: # Game has been won
3119 if game.state.nromrem != 0:
3120 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3123 prout(_("You have smashed the Klingon invasion fleet and saved"))
3124 prout(_("the Federation."))
3129 badpt = 0.0 # Close enough!
3130 # killsPerDate >= RateMax
3131 if game.state.date-game.indate < 5.0 or \
3132 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3134 prout(_("In fact, you have done so well that Starfleet Command"))
3135 if game.skill == SKILL_NOVICE:
3136 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3137 elif game.skill == SKILL_FAIR:
3138 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3139 elif game.skill == SKILL_GOOD:
3140 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3141 elif game.skill == SKILL_EXPERT:
3142 prout(_("promotes you to Commodore Emeritus."))
3144 prout(_("Now that you think you're really good, try playing"))
3145 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3146 elif game.skill == SKILL_EMERITUS:
3148 proutn(_("Computer- "))
3149 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3151 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3153 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3155 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3157 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3159 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3161 prout(_("Now you can retire and write your own Star Trek game!"))
3163 elif game.skill >= SKILL_EXPERT:
3164 if game.thawed and not idebug:
3165 prout(_("You cannot get a citation, so..."))
3167 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3171 # Only grant long life if alive (original didn't!)
3173 prout(_("LIVE LONG AND PROSPER."))
3178 elif ifin == FDEPLETE: # Federation Resources Depleted
3179 prout(_("Your time has run out and the Federation has been"))
3180 prout(_("conquered. Your starship is now Klingon property,"))
3181 prout(_("and you are put on trial as a war criminal. On the"))
3182 proutn(_("basis of your record, you are "))
3183 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3184 prout(_("acquitted."))
3186 prout(_("LIVE LONG AND PROSPER."))
3188 prout(_("found guilty and"))
3189 prout(_("sentenced to death by slow torture."))
3193 elif ifin == FLIFESUP:
3194 prout(_("Your life support reserves have run out, and"))
3195 prout(_("you die of thirst, starvation, and asphyxiation."))
3196 prout(_("Your starship is a derelict in space."))
3198 prout(_("Your energy supply is exhausted."))
3200 prout(_("Your starship is a derelict in space."))
3201 elif ifin == FBATTLE:
3204 prout(_(" has been destroyed in battle."))
3206 prout(_("Dulce et decorum est pro patria mori."))
3208 prout(_("You have made three attempts to cross the negative energy"))
3209 prout(_("barrier which surrounds the galaxy."))
3211 prout(_("Your navigation is abominable."))
3214 prout(_("Your starship has been destroyed by a nova."))
3215 prout(_("That was a great shot."))
3217 elif ifin == FSNOVAED:
3220 prout(_(" has been fried by a supernova."))
3221 prout(_("...Not even cinders remain..."))
3222 elif ifin == FABANDN:
3223 prout(_("You have been captured by the Klingons. If you still"))
3224 prout(_("had a starbase to be returned to, you would have been"))
3225 prout(_("repatriated and given another chance. Since you have"))
3226 prout(_("no starbases, you will be mercilessly tortured to death."))
3227 elif ifin == FDILITHIUM:
3228 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3229 elif ifin == FMATERIALIZE:
3230 prout(_("Starbase was unable to re-materialize your starship."))
3231 prout(_("Sic transit gloria mundi"))
3232 elif ifin == FPHASER:
3235 prout(_(" has been cremated by its own phasers."))
3237 prout(_("You and your landing party have been"))
3238 prout(_("converted to energy, disipating through space."))
3239 elif ifin == FMINING:
3240 prout(_("You are left with your landing party on"))
3241 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3243 prout(_("They are very fond of \"Captain Kirk\" soup."))
3245 proutn(_("Without your leadership, the "))
3247 prout(_(" is destroyed."))
3248 elif ifin == FDPLANET:
3249 prout(_("You and your mining party perish."))
3251 prout(_("That was a great shot."))
3254 prout(_("The Galileo is instantly annihilated by the supernova."))
3255 prout(_("You and your mining party are atomized."))
3257 proutn(_("Mr. Spock takes command of the "))
3260 prout(_("joins the Romulans, reigning terror on the Federation."))
3261 elif ifin == FPNOVA:
3262 prout(_("You and your mining party are atomized."))
3264 proutn(_("Mr. Spock takes command of the "))
3267 prout(_("joins the Romulans, reigning terror on the Federation."))
3268 elif ifin == FSTRACTOR:
3269 prout(_("The shuttle craft Galileo is also caught,"))
3270 prout(_("and breaks up under the strain."))
3272 prout(_("Your debris is scattered for millions of miles."))
3273 proutn(_("Without your leadership, the "))
3275 prout(_(" is destroyed."))
3277 prout(_("The mutants attack and kill Spock."))
3278 prout(_("Your ship is captured by Klingons, and"))
3279 prout(_("your crew is put on display in a Klingon zoo."))
3280 elif ifin == FTRIBBLE:
3281 prout(_("Tribbles consume all remaining water,"))
3282 prout(_("food, and oxygen on your ship."))
3284 prout(_("You die of thirst, starvation, and asphyxiation."))
3285 prout(_("Your starship is a derelict in space."))
3287 prout(_("Your ship is drawn to the center of the black hole."))
3288 prout(_("You are crushed into extremely dense matter."))
3290 prout(_("Your last crew member has died."))
3291 if game.ship == IHF:
3293 elif game.ship == IHE:
3296 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3297 goodies = game.state.remres/game.inresor
3298 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3299 if goodies/baddies >= randreal(1.0, 1.5):
3300 prout(_("As a result of your actions, a treaty with the Klingon"))
3301 prout(_("Empire has been signed. The terms of the treaty are"))
3302 if goodies/baddies >= randreal(3.0):
3303 prout(_("favorable to the Federation."))
3305 prout(_("Congratulations!"))
3307 prout(_("highly unfavorable to the Federation."))
3309 prout(_("The Federation will be destroyed."))
3311 prout(_("Since you took the last Klingon with you, you are a"))
3312 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3313 prout(_("statue in your memory. Rest in peace, and try not"))
3314 prout(_("to think about pigeons."))
3319 # compute player's score
3320 timused = game.state.date - game.indate
3322 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3324 perdate = killrate()
3325 ithperd = 500*perdate + 0.5
3328 iwon = 100*game.skill
3329 if game.ship == IHE:
3331 elif game.ship == IHF:
3335 if not game.gamewon:
3336 game.state.nromrem = 0 # None captured if no win
3337 iscore = 10*(game.inkling - game.state.remkl) \
3338 + 50*(game.incom - game.state.remcom) \
3340 + 20*(game.inrom - game.state.nromrem) \
3341 + 200*(game.inscom - game.state.nscrem) \
3342 - game.state.nromrem \
3347 prout(_("Your score --"))
3348 if game.inrom - game.state.nromrem:
3349 prout(_("%6d Romulans destroyed %5d") %
3350 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3351 if game.state.nromrem:
3352 prout(_("%6d Romulans captured %5d") %
3353 (game.state.nromrem, game.state.nromrem))
3354 if game.inkling - game.state.remkl:
3355 prout(_("%6d ordinary Klingons destroyed %5d") %
3356 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3357 if game.incom - game.state.remcom:
3358 prout(_("%6d Klingon commanders destroyed %5d") %
3359 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3360 if game.inscom - game.state.nscrem:
3361 prout(_("%6d Super-Commander destroyed %5d") %
3362 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3364 prout(_("%6.2f Klingons per stardate %5d") %
3366 if game.state.starkl:
3367 prout(_("%6d stars destroyed by your action %5d") %
3368 (game.state.starkl, -5*game.state.starkl))
3369 if game.state.nplankl:
3370 prout(_("%6d planets destroyed by your action %5d") %
3371 (game.state.nplankl, -10*game.state.nplankl))
3372 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3373 prout(_("%6d inhabited planets destroyed by your action %5d") %
3374 (game.state.nplankl, -300*game.state.nworldkl))
3375 if game.state.basekl:
3376 prout(_("%6d bases destroyed by your action %5d") %
3377 (game.state.basekl, -100*game.state.basekl))
3379 prout(_("%6d calls for help from starbase %5d") %
3380 (game.nhelp, -45*game.nhelp))
3382 prout(_("%6d casualties incurred %5d") %
3383 (game.casual, -game.casual))
3385 prout(_("%6d crew abandoned in space %5d") %
3386 (game.abandoned, -3*game.abandoned))
3388 prout(_("%6d ship(s) lost or destroyed %5d") %
3389 (klship, -100*klship))
3391 prout(_("Penalty for getting yourself killed -200"))
3393 proutn(_("Bonus for winning "))
3394 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3395 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3396 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3397 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3398 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3399 prout(" %5d" % iwon)
3401 prout(_("TOTAL SCORE %5d") % iscore)
3404 # emit winner's commemmorative plaque
3407 proutn(_("File or device name for your plaque: "))
3410 fp = open(winner, "w")
3413 prout(_("Invalid name."))
3415 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3417 # The 38 below must be 64 for 132-column paper
3418 nskip = 38 - len(winner)/2
3419 fp.write("\n\n\n\n")
3420 # --------DRAW ENTERPRISE PICTURE.
3421 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3422 fp.write(" EEE E : : : E\n" )
3423 fp.write(" EE EEE E : : NCC-1701 : E\n")
3424 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3425 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3426 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3427 fp.write(" EEEEEEE EEEEE E E E E\n")
3428 fp.write(" EEE E E E E\n")
3429 fp.write(" E E E E\n")
3430 fp.write(" EEEEEEEEEEEEE E E\n")
3431 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3432 fp.write(" :E : EEEE E\n")
3433 fp.write(" .-E -:----- E\n")
3434 fp.write(" :E : E\n")
3435 fp.write(" EE : EEEEEEEE\n")
3436 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3438 fp.write(_(" U. S. S. ENTERPRISE\n"))
3439 fp.write("\n\n\n\n")
3440 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3442 fp.write(_(" Starfleet Command bestows to you\n"))
3444 fp.write("%*s%s\n\n" % (nskip, "", winner))
3445 fp.write(_(" the rank of\n\n"))
3446 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3448 if game.skill == SKILL_EXPERT:
3449 fp.write(_(" Expert level\n\n"))
3450 elif game.skill == SKILL_EMERITUS:
3451 fp.write(_("Emeritus level\n\n"))
3453 fp.write(_(" Cheat level\n\n"))
3454 timestring = ctime()
3455 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3456 (timestring+4, timestring+20, timestring+11))
3457 fp.write(_(" Your score: %d\n\n") % iscore)
3458 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3461 # Code from io.c begins here
3463 rows = linecount = 0 # for paging
3466 fullscreen_window = None
3467 srscan_window = None
3468 report_window = None
3469 status_window = None
3470 lrscan_window = None
3471 message_window = None
3472 prompt_window = None
3476 "wrap up, either normally or due to signal"
3477 if game.options & OPTION_CURSES:
3484 sys.stdout.write('\n')
3490 #setlocale(LC_ALL, "")
3491 #bindtextdomain(PACKAGE, LOCALEDIR)
3492 #textdomain(PACKAGE)
3493 if atexit.register(outro):
3494 sys.stderr.write("Unable to register outro(), exiting...\n")
3496 if not (game.options & OPTION_CURSES):
3497 ln_env = os.getenv("LINES")
3503 stdscr = curses.initscr()
3508 curses.start_color()
3509 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3510 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3511 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3512 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3513 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3514 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3515 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3516 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3518 global fullscreen_window, srscan_window, report_window, status_window
3519 global lrscan_window, message_window, prompt_window
3520 fullscreen_window = stdscr
3521 srscan_window = curses.newwin(12, 25, 0, 0)
3522 report_window = curses.newwin(11, 0, 1, 25)
3523 status_window = curses.newwin(10, 0, 1, 39)
3524 lrscan_window = curses.newwin(5, 0, 0, 64)
3525 message_window = curses.newwin(0, 0, 12, 0)
3526 prompt_window = curses.newwin(1, 0, rows-2, 0)
3527 message_window.scrollok(True)
3528 setwnd(fullscreen_window)
3532 "wait for user action -- OK to do nothing if on a TTY"
3533 if game.options & OPTION_CURSES:
3538 if game.skill > SKILL_FAIR:
3539 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3541 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3545 if game.skill > SKILL_FAIR:
3546 prompt = _("[CONTINUE?]")
3548 prompt = _("[PRESS ENTER TO CONTINUE]")
3550 if game.options & OPTION_CURSES:
3552 setwnd(prompt_window)
3553 prompt_window.wclear()
3554 prompt_window.addstr(prompt)
3555 prompt_window.getstr()
3556 prompt_window.clear()
3557 prompt_window.refresh()
3558 setwnd(message_window)
3561 sys.stdout.write('\n')
3564 for j in range(rows):
3565 sys.stdout.write('\n')
3569 "Skip i lines. Pause game if this would cause a scrolling event."
3570 for dummy in range(i):
3571 if game.options & OPTION_CURSES:
3572 (y, x) = curwnd.getyx()
3573 (my, mx) = curwnd.getmaxyx()
3574 if curwnd == message_window and y >= my - 3:
3582 if rows and linecount >= rows:
3585 sys.stdout.write('\n')
3588 "Utter a line with no following line feed."
3589 if game.options & OPTION_CURSES:
3593 sys.stdout.write(line)
3603 if not replayfp or replayfp.closed: # Don't slow down replays
3606 if game.options & OPTION_CURSES:
3610 if not replayfp or replayfp.closed:
3614 "Get a line of input."
3615 if game.options & OPTION_CURSES:
3616 line = curwnd.getstr() + "\n"
3619 if replayfp and not replayfp.closed:
3621 line = replayfp.readline()
3624 prout("*** Replay finished")
3627 elif line[0] != "#":
3632 logfp.write("$" + line + "\n")
3636 "Change windows -- OK for this to be a no-op in tty mode."
3638 if game.options & OPTION_CURSES:
3640 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3643 "Clear to end of line -- can be a no-op in tty mode"
3644 if game.options & OPTION_CURSES:
3649 "Clear screen -- can be a no-op in tty mode."
3651 if game.options & OPTION_CURSES:
3657 def textcolor(color):
3658 "Set the current text color"
3659 if game.options & OPTION_CURSES:
3660 if color == DEFAULT:
3662 elif color == BLACK:
3663 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3665 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3666 elif color == GREEN:
3667 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3669 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3671 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3672 elif color == MAGENTA:
3673 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3674 elif color == BROWN:
3675 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3676 elif color == LIGHTGRAY:
3677 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3678 elif color == DARKGRAY:
3679 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3680 elif color == LIGHTBLUE:
3681 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3682 elif color == LIGHTGREEN:
3683 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3684 elif color == LIGHTCYAN:
3685 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3686 elif color == LIGHTRED:
3687 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3688 elif color == LIGHTMAGENTA:
3689 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3690 elif color == YELLOW:
3691 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3692 elif color == WHITE:
3693 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3696 "Set highlight video, if this is reasonable."
3697 if game.options & OPTION_CURSES:
3698 curwnd.attron(curses.A_REVERSE)
3701 # Things past this point have policy implications.
3705 "Hook to be called after moving to redraw maps."
3706 if game.options & OPTION_CURSES:
3709 setwnd(srscan_window)
3713 setwnd(status_window)
3714 status_window.clear()
3715 status_window.move(0, 0)
3716 setwnd(report_window)
3717 report_window.clear()
3718 report_window.move(0, 0)
3720 setwnd(lrscan_window)
3721 lrscan_window.clear()
3722 lrscan_window.move(0, 0)
3723 lrscan(silent=False)
3725 def put_srscan_sym(w, sym):
3726 "Emit symbol for short-range scan."
3727 srscan_window.move(w.x+1, w.y*2+2)
3728 srscan_window.addch(sym)
3729 srscan_window.refresh()
3732 "Enemy fall down, go boom."
3733 if game.options & OPTION_CURSES:
3735 setwnd(srscan_window)
3736 srscan_window.attron(curses.A_REVERSE)
3737 put_srscan_sym(w, game.quad[w.x][w.y])
3741 srscan_window.attroff(curses.A_REVERSE)
3742 put_srscan_sym(w, game.quad[w.x][w.y])
3743 curses.delay_output(500)
3744 setwnd(message_window)
3747 "Sound and visual effects for teleportation."
3748 if game.options & OPTION_CURSES:
3750 setwnd(message_window)
3752 prouts(" . . . . . ")
3753 if game.options & OPTION_CURSES:
3754 #curses.delay_output(1000)
3758 def tracktorpedo(w, l, i, n, iquad):
3759 "Torpedo-track animation."
3760 if not game.options & OPTION_CURSES:
3764 proutn(_("Track for torpedo number %d- ") % i)
3767 proutn(_("Torpedo track- "))
3770 proutn("%d - %d " % (w.x, w.y))
3772 if not damaged(DSRSENS) or game.condition=="docked":
3773 if i != 1 and l == 1:
3776 if (iquad==IHDOT) or (iquad==IHBLANK):
3777 put_srscan_sym(w, '+')
3781 put_srscan_sym(w, iquad)
3783 curwnd.attron(curses.A_REVERSE)
3784 put_srscan_sym(w, iquad)
3788 curwnd.attroff(curses.A_REVERSE)
3789 put_srscan_sym(w, iquad)
3791 proutn("%d - %d " % (w.x, w.y))
3794 "Display the current galaxy chart."
3795 if game.options & OPTION_CURSES:
3796 setwnd(message_window)
3797 message_window.clear()
3799 if game.options & OPTION_TTY:
3804 def prstat(txt, data):
3806 if game.options & OPTION_CURSES:
3808 setwnd(status_window)
3810 proutn(" " * (NSYM - len(txt)))
3813 if game.options & OPTION_CURSES:
3814 setwnd(report_window)
3816 # Code from moving.c begins here
3818 def imove(novapush):
3819 # movement execution for warp, impulse, supernova, and tractor-beam events
3820 w = coord(); final = coord()
3823 def no_quad_change():
3824 # No quadrant change -- compute new average enemy distances
3825 game.quad[game.sector.x][game.sector.y] = game.ship
3827 for m in range(game.nenhere):
3828 finald = distance(w, game.enemies[m].kloc)
3829 game.enemies[m].kavgd = 0.5 * (finald+game.enemies[m].kdist)
3830 game.enemies[m].kdist = finald
3831 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3832 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3834 for m in range(game.nenhere):
3835 game.enemies[m].kavgd = game.enemies[m].kdist
3838 setwnd(message_window)
3841 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3842 game.inorbit = False
3843 angle = ((15.0 - game.direc) * 0.5235988)
3844 deltax = -math.sin(angle)
3845 deltay = math.cos(angle)
3846 if math.fabs(deltax) > math.fabs(deltay):
3847 bigger = math.fabs(deltax)
3849 bigger = math.fabs(deltay)
3852 # If tractor beam is to occur, don't move full distance
3853 if game.state.date+game.optime >= scheduled(FTBEAM):
3855 game.condition = "red"
3856 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3857 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3858 # Move within the quadrant
3859 game.quad[game.sector.x][game.sector.y] = IHDOT
3862 n = int(10.0*game.dist*bigger+0.5)
3864 for m in range(1, n+1):
3869 if not VALID_SECTOR(w.x, w.y):
3870 # Leaving quadrant -- allow final enemy attack
3871 # Don't do it if being pushed by Nova
3872 if game.nenhere != 0 and not novapush:
3874 for m in range(game.nenhere):
3875 finald = distance(w, game.enemies[m].kloc)
3876 game.enemies[m].kavgd = 0.5 * (finald + game.enemies[m].kdist)
3878 # Stas Sergeev added the condition
3879 # that attacks only happen if Klingons
3880 # are present and your skill is good.
3882 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3886 # compute final position -- new quadrant and sector
3887 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3888 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3889 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3890 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3891 # check for edge of galaxy
3901 if w.x >= GALSIZE*QUADSIZE:
3902 w.x = (GALSIZE*QUADSIZE*2) - w.x
3904 if w.y >= GALSIZE*QUADSIZE:
3905 w.y = (GALSIZE*QUADSIZE*2) - w.y
3913 if game.nkinks == 3:
3914 # Three strikes -- you're out!
3918 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3919 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3920 prout(_("YOU WILL BE DESTROYED."))
3921 # Compute final position in new quadrant
3922 if trbeam: # Don't bother if we are to be beamed
3924 game.quadrant.x = w.x/QUADSIZE
3925 game.quadrant.y = w.y/QUADSIZE
3926 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3927 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3929 prout(_("Entering Quadrant %s.") % game.quadrant)
3930 game.quad[game.sector.x][game.sector.y] = game.ship
3932 if game.skill>SKILL_NOVICE:
3935 iquad = game.quad[w.x][w.y]
3937 # object encountered in flight path
3938 stopegy = 50.0*game.dist/game.optime
3939 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3940 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3942 ram(False, iquad, game.sector)
3944 elif iquad == IHBLANK:
3946 prouts(_("***RED ALERT! RED ALERT!"))
3950 proutn(_(" pulled into black hole at Sector %s") % w)
3952 # Getting pulled into a black hole was certain
3953 # death in Almy's original. Stas Sergeev added a
3954 # possibility that you'll get timewarped instead.
3957 for m in range(NDEVICES):
3958 if game.damage[m]>0:
3960 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3961 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3971 proutn(_(" encounters Tholian web at %s;") % w)
3973 proutn(_(" blocked by object at %s;") % w)
3974 proutn(_("Emergency stop required "))
3975 prout(_("%2d units of energy.") % int(stopegy))
3976 game.energy -= stopegy
3977 final.x = x-deltax+0.5
3978 final.y = y-deltay+0.5
3980 if game.energy <= 0:
3986 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3993 # dock our ship at a starbase
3995 if game.condition == "docked" and verbose:
3996 prout(_("Already docked."))
3999 prout(_("You must first leave standard orbit."))
4001 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4003 prout(_(" not adjacent to base."))
4005 game.condition = "docked"
4009 if game.energy < game.inenrg:
4010 game.energy = game.inenrg
4011 game.shield = game.inshld
4012 game.torps = game.intorps
4013 game.lsupres = game.inlsr
4014 game.state.crew = FULLCREW
4015 if not damaged(DRADIO) and \
4016 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4017 # get attack report from base
4018 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4022 # This program originally required input in terms of a (clock)
4023 # direction and distance. Somewhere in history, it was changed to
4024 # cartesian coordinates. So we need to convert. Probably
4025 # "manual" input should still be done this way -- it's a real
4026 # pain if the computer isn't working! Manual mode is still confusing
4027 # because it involves giving x and y motions, yet the coordinates
4028 # are always displayed y - x, where +y is downward!
4030 def getcourse(isprobe, akey):
4031 # get course and distance
4033 dquad = copy.copy(game.quadrant)
4034 navmode = "unspecified"
4038 if game.landed and not isprobe:
4039 prout(_("Dummy! You can't leave standard orbit until you"))
4040 proutn(_("are back aboard the ship."))
4043 while navmode == "unspecified":
4044 if damaged(DNAVSYS):
4046 prout(_("Computer damaged; manual navigation only"))
4048 prout(_("Computer damaged; manual movement only"))
4053 if isprobe and akey != -1:
4054 # For probe launch, use pre-scanned value first time
4060 proutn(_("Manual or automatic- "))
4063 elif key == IHALPHA:
4068 elif isit("automatic"):
4069 navmode = "automatic"
4078 prout(_("(Manual navigation assumed.)"))
4080 prout(_("(Manual movement assumed.)"))
4083 if navmode == "automatic":
4086 proutn(_("Target quadrant or quadrant§or- "))
4088 proutn(_("Destination sector or quadrant§or- "))
4095 xi = int(round(aaitem))-1
4100 xj = int(round(aaitem))-1
4103 # both quadrant and sector specified
4104 xk = int(round(aaitem))-1
4109 xl = int(round(aaitem))-1
4115 # only one pair of numbers was specified
4117 # only quadrant specified -- go to center of dest quad
4120 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4122 # only sector specified
4126 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4133 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4135 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4136 # the actual deltas get computed here
4137 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4138 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4141 proutn(_("X and Y displacements- "))
4155 # Check for zero movement
4156 if deltax == 0 and deltay == 0:
4159 if itemp == "verbose" and not isprobe:
4161 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4162 # Course actually laid in.
4163 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4164 game.direc = math.atan2(deltax, deltay)*1.90985932
4165 if game.direc < 0.0:
4171 # move under impulse power
4173 if damaged(DIMPULS):
4176 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4178 if game.energy > 30.0:
4179 if not getcourse(isprobe=False, akey=0):
4181 power = 20.0 + 100.0*game.dist
4184 if power >= game.energy:
4185 # Insufficient power for trip
4187 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4188 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4189 if game.energy > 30:
4190 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4191 int(0.01 * (game.energy-20.0)-0.05))
4192 prout(_(" quadrants.\""))
4194 prout(_("quadrant. They are, therefore, useless.\""))
4197 # Make sure enough time is left for the trip
4198 game.optime = game.dist/0.095
4199 if game.optime >= game.state.remtime:
4200 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4201 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4202 proutn(_("we dare spend the time?\" "))
4205 # Activate impulse engines and pay the cost
4206 imove(novapush=False)
4210 power = 20.0 + 100.0*game.dist
4211 game.energy -= power
4212 game.optime = game.dist/0.095
4213 if game.energy <= 0:
4218 # move under warp drive
4219 blooey = False; twarp = False
4220 if not timewarp: # Not WARPX entry
4222 if game.damage[DWARPEN] > 10.0:
4225 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4227 if damaged(DWARPEN) and game.warpfac > 4.0:
4230 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4231 prout(_(" is repaired, I can only give you warp 4.\""))
4233 # Read in course and distance
4234 if not getcourse(isprobe=False, akey=0):
4236 # Make sure starship has enough energy for the trip
4237 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4238 if power >= game.energy:
4239 # Insufficient power for trip
4242 prout(_("Engineering to bridge--"))
4243 if not game.shldup or 0.5*power > game.energy:
4244 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4246 prout(_("We can't do it, Captain. We don't have enough energy."))
4248 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4251 prout(_("if you'll lower the shields."))
4255 prout(_("We haven't the energy to go that far with the shields up."))
4258 # Make sure enough time is left for the trip
4259 game.optime = 10.0*game.dist/game.wfacsq
4260 if game.optime >= 0.8*game.state.remtime:
4262 prout(_("First Officer Spock- \"Captain, I compute that such"))
4263 proutn(_(" a trip would require approximately %2.0f") %
4264 (100.0*game.optime/game.state.remtime))
4265 prout(_(" percent of our"))
4266 proutn(_(" remaining time. Are you sure this is wise?\" "))
4272 if game.warpfac > 6.0:
4273 # Decide if engine damage will occur
4274 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4275 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4276 if prob > randreal():
4278 game.dist = randreal(game.dist)
4279 # Decide if time warp will occur
4280 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4282 if idebug and game.warpfac==10 and not twarp:
4284 proutn("=== Force time warp? ")
4288 # If time warp or engine damage, check path
4289 # If it is obstructed, don't do warp or damage
4290 angle = ((15.0-game.direc)*0.5235998)
4291 deltax = -math.sin(angle)
4292 deltay = math.cos(angle)
4293 if math.fabs(deltax) > math.fabs(deltay):
4294 bigger = math.fabs(deltax)
4296 bigger = math.fabs(deltay)
4300 n = 10.0 * game.dist * bigger +0.5
4303 for l in range(1, n+1):
4308 if not VALID_SECTOR(ix, iy):
4310 if game.quad[ix][iy] != IHDOT:
4313 # Activate Warp Engines and pay the cost
4314 imove(novapush=False)
4317 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4318 if game.energy <= 0:
4320 game.optime = 10.0*game.dist/game.wfacsq
4324 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4326 prout(_("Engineering to bridge--"))
4327 prout(_(" Scott here. The warp engines are damaged."))
4328 prout(_(" We'll have to reduce speed to warp 4."))
4333 # change the warp factor
4339 proutn(_("Warp factor- "))
4344 if game.damage[DWARPEN] > 10.0:
4345 prout(_("Warp engines inoperative."))
4347 if damaged(DWARPEN) and aaitem > 4.0:
4348 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4349 prout(_(" but right now we can only go warp 4.\""))
4352 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4355 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4357 oldfac = game.warpfac
4358 game.warpfac = aaitem
4359 game.wfacsq=game.warpfac*game.warpfac
4360 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4361 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4364 if game.warpfac < 8.00:
4365 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4367 if game.warpfac == 10.0:
4368 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4370 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4374 # cope with being tossed out of quadrant by supernova or yanked by beam
4376 # is captain on planet?
4378 if damaged(DTRANSP):
4381 prout(_("Scotty rushes to the transporter controls."))
4383 prout(_("But with the shields up it's hopeless."))
4385 prouts(_("His desperate attempt to rescue you . . ."))
4390 prout(_("SUCCEEDS!"))
4393 proutn(_("The crystals mined were "))
4401 # Check to see if captain in shuttle craft
4406 # Inform captain of attempt to reach safety
4410 prouts(_("***RED ALERT! RED ALERT!"))
4414 prout(_(" has stopped in a quadrant containing"))
4415 prouts(_(" a supernova."))
4417 proutn(_("***Emergency automatic override attempts to hurl "))
4420 prout(_("safely out of quadrant."))
4421 if not damaged(DRADIO):
4422 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4423 # Try to use warp engines
4424 if damaged(DWARPEN):
4426 prout(_("Warp engines damaged."))
4429 game.warpfac = randreal(6.0, 8.0)
4430 game.wfacsq = game.warpfac * game.warpfac
4431 prout(_("Warp factor set to %d") % int(game.warpfac))
4432 power = 0.75*game.energy
4433 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4434 distreq = randreal(math.sqrt(2))
4435 if distreq < game.dist:
4437 game.optime = 10.0*game.dist/game.wfacsq
4438 game.direc = randreal(12) # How dumb!
4440 game.inorbit = False
4443 # This is bad news, we didn't leave quadrant.
4447 prout(_("Insufficient energy to leave quadrant."))
4450 # Repeat if another snova
4451 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4453 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4454 finish(FWON) # Snova killed remaining enemy.
4457 # let's do the time warp again
4458 prout(_("***TIME WARP ENTERED."))
4459 if game.state.snap and withprob(0.5):
4461 prout(_("You are traveling backwards in time %d stardates.") %
4462 int(game.state.date-game.snapsht.date))
4463 game.state = game.snapsht
4464 game.state.snap = False
4465 if game.state.remcom:
4466 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4467 schedule(FBATTAK, expran(0.3*game.intime))
4468 schedule(FSNOVA, expran(0.5*game.intime))
4469 # next snapshot will be sooner
4470 schedule(FSNAP, expran(0.25*game.state.remtime))
4472 if game.state.nscrem:
4473 schedule(FSCMOVE, 0.2777)
4477 invalidate(game.battle)
4479 # Make sure Galileo is consistant -- Snapshot may have been taken
4480 # when on planet, which would give us two Galileos!
4482 for l in range(game.inplan):
4483 if game.state.planets[l].known == "shuttle_down":
4485 if game.iscraft == "onship" and game.ship==IHE:
4486 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4487 game.iscraft = "offship"
4488 # Likewise, if in the original time the Galileo was abandoned, but
4489 # was on ship earlier, it would have vanished -- let's restore it.
4490 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4491 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4492 game.iscraft = "onship"
4494 # * There used to be code to do the actual reconstrction here,
4495 # * but the starchart is now part of the snapshotted galaxy state.
4497 prout(_("Spock has reconstructed a correct star chart from memory"))
4499 # Go forward in time
4500 game.optime = -0.5*game.intime*math.log(randreal())
4501 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4502 # cheat to make sure no tractor beams occur during time warp
4503 postpone(FTBEAM, game.optime)
4504 game.damage[DRADIO] += game.optime
4506 events() # Stas Sergeev added this -- do pending events
4509 # launch deep-space probe
4510 # New code to launch a deep space probe
4511 if game.nprobes == 0:
4514 if game.ship == IHE:
4515 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4517 prout(_("Ye Faerie Queene has no deep space probes."))
4522 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4524 if is_scheduled(FDSPROB):
4527 if damaged(DRADIO) and game.condition != "docked":
4528 prout(_("Spock- \"Records show the previous probe has not yet"))
4529 prout(_(" reached its destination.\""))
4531 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4535 # slow mode, so let Kirk know how many probes there are left
4536 if game.nprobes == 1:
4537 prout(_("1 probe left."))
4539 prout(_("%d probes left") % game.nprobes)
4540 proutn(_("Are you sure you want to fire a probe? "))
4543 game.isarmed = False
4544 if key == IHALPHA and citem == "armed":
4548 proutn(_("Arm NOVAMAX warhead? "))
4550 if not getcourse(isprobe=True, akey=key):
4553 angle = ((15.0 - game.direc) * 0.5235988)
4554 game.probeinx = -math.sin(angle)
4555 game.probeiny = math.cos(angle)
4556 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4557 bigger = math.fabs(game.probeinx)
4559 bigger = math.fabs(game.probeiny)
4560 game.probeiny /= bigger
4561 game.probeinx /= bigger
4562 game.proben = 10.0*game.dist*bigger +0.5
4563 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4564 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4565 game.probec = game.quadrant
4566 schedule(FDSPROB, 0.01) # Time to move one sector
4567 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4571 # Here's how the mayday code works:
4573 # First, the closest starbase is selected. If there is a a starbase
4574 # in your own quadrant, you are in good shape. This distance takes
4575 # quadrant distances into account only.
4577 # A magic number is computed based on the distance which acts as the
4578 # probability that you will be rematerialized. You get three tries.
4580 # When it is determined that you should be able to be rematerialized
4581 # (i.e., when the probability thing mentioned above comes up
4582 # positive), you are put into that quadrant (anywhere). Then, we try
4583 # to see if there is a spot adjacent to the star- base. If not, you
4584 # can't be rematerialized!!! Otherwise, it drops you there. It only
4585 # tries five times to find a spot to drop you. After that, it's your
4589 # yell for help from nearest starbase
4590 # There's more than one way to move in this game!
4593 # Test for conditions which prevent calling for help
4594 if game.condition == "docked":
4595 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4598 prout(_("Subspace radio damaged."))
4600 if game.state.rembase==0:
4601 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4604 proutn(_("You must be aboard the "))
4608 # OK -- call for help from nearest starbase
4611 # There's one in this quadrant
4612 ddist = distance(game.base, game.sector)
4615 for m in range(game.state.rembase):
4616 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4620 # Since starbase not in quadrant, set up new quadrant
4621 game.quadrant = game.state.baseq[line]
4623 # dematerialize starship
4624 game.quad[game.sector.x][game.sector.y]=IHDOT
4625 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4627 prout(_(" dematerializes."))
4629 for m in range(1, 5+1):
4630 w = game.base.scatter()
4631 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4632 # found one -- finish up
4635 if not is_valid(game.sector):
4636 prout(_("You have been lost in space..."))
4637 finish(FMATERIALIZE)
4639 # Give starbase three chances to rematerialize starship
4640 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4641 for m in range(1, 3+1):
4642 if m == 1: proutn(_("1st"))
4643 elif m == 2: proutn(_("2nd"))
4644 elif m == 3: proutn(_("3rd"))
4645 proutn(_(" attempt to re-materialize "))
4647 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4650 if randreal() > probf:
4653 curses.delay_output(500)
4656 game.quad[ix][iy]=IHQUEST
4659 setwnd(message_window)
4660 finish(FMATERIALIZE)
4662 game.quad[ix][iy]=game.ship
4664 prout(_("succeeds."))
4668 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4670 # Abandon Ship (the BSD-Trek description)
4672 # The ship is abandoned. If your current ship is the Faire
4673 # Queene, or if your shuttlecraft is dead, you're out of
4674 # luck. You need the shuttlecraft in order for the captain
4675 # (that's you!!) to escape.
4677 # Your crew can beam to an inhabited starsystem in the
4678 # quadrant, if there is one and if the transporter is working.
4679 # If there is no inhabited starsystem, or if the transporter
4680 # is out, they are left to die in outer space.
4682 # If there are no starbases left, you are captured by the
4683 # Klingons, who torture you mercilessly. However, if there
4684 # is at least one starbase, you are returned to the
4685 # Federation in a prisoner of war exchange. Of course, this
4686 # can't happen unless you have taken some prisoners.
4691 if game.condition=="docked":
4693 prout(_("You cannot abandon Ye Faerie Queene."))
4696 # Must take shuttle craft to exit
4697 if game.damage[DSHUTTL]==-1:
4698 prout(_("Ye Faerie Queene has no shuttle craft."))
4700 if game.damage[DSHUTTL]<0:
4701 prout(_("Shuttle craft now serving Big Macs."))
4703 if game.damage[DSHUTTL]>0:
4704 prout(_("Shuttle craft damaged."))
4707 prout(_("You must be aboard the ship."))
4709 if game.iscraft != "onship":
4710 prout(_("Shuttle craft not currently available."))
4712 # Print abandon ship messages
4714 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4716 prouts(_("***ALL HANDS ABANDON SHIP!"))
4718 prout(_("Captain and crew escape in shuttle craft."))
4719 if game.state.rembase==0:
4720 # Oops! no place to go...
4723 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4725 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4726 prout(_("Remainder of ship's complement beam down"))
4727 prout(_("to nearest habitable planet."))
4728 elif q.planet != None and not damaged(DTRANSP):
4729 prout(_("Remainder of ship's complement beam down to %s.") %
4732 prout(_("Entire crew of %d left to die in outer space.") %
4734 game.casual += game.state.crew
4735 game.abandoned += game.state.crew
4737 # If at least one base left, give 'em the Faerie Queene
4739 game.icrystl = False # crystals are lost
4740 game.nprobes = 0 # No probes
4741 prout(_("You are captured by Klingons and released to"))
4742 prout(_("the Federation in a prisoner-of-war exchange."))
4743 nb = randrange(game.state.rembase)
4744 # Set up quadrant and position FQ adjacient to base
4745 if not game.quadrant == game.state.baseq[nb]:
4746 game.quadrant = game.state.baseq[nb]
4747 game.sector.x = game.sector.y = 5
4750 # position next to base by trial and error
4751 game.quad[game.sector.x][game.sector.y] = IHDOT
4752 for l in range(QUADSIZE):
4753 game.sector = game.base.scatter()
4754 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4755 game.quad[game.sector.x][game.sector.y] == IHDOT:
4758 break # found a spot
4759 game.sector.x=QUADSIZE/2
4760 game.sector.y=QUADSIZE/2
4762 # Get new commission
4763 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4764 game.state.crew = FULLCREW
4765 prout(_("Starfleet puts you in command of another ship,"))
4766 prout(_("the Faerie Queene, which is antiquated but,"))
4767 prout(_("still useable."))
4769 prout(_("The dilithium crystals have been moved."))
4771 game.iscraft = "offship" # Galileo disappears
4773 game.condition="docked"
4774 for l in range(NDEVICES):
4775 game.damage[l] = 0.0
4776 game.damage[DSHUTTL] = -1
4777 game.energy = game.inenrg = 3000.0
4778 game.shield = game.inshld = 1250.0
4779 game.torps = game.intorps = 6
4780 game.lsupres=game.inlsr=3.0
4786 # Code from planets.c begins here.
4789 # abort a lengthy operation if an event interrupts it
4792 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4797 # report on (uninhabited) planets in the galaxy
4801 prout(_("Spock- \"Planet report follows, Captain.\""))
4803 for i in range(game.inplan):
4804 if game.state.planets[i].pclass == "destroyed":
4806 if (game.state.planets[i].known != "unknown" \
4807 and not game.state.planets[i].inhabited) \
4810 if idebug and game.state.planets[i].known=="unknown":
4811 proutn("(Unknown) ")
4812 proutn(_("Quadrant %s") % game.state.planets[i].w)
4813 proutn(_(" class "))
4814 proutn(game.state.planets[i].pclass)
4816 if game.state.planets[i].crystals != present:
4818 prout(_("dilithium crystals present."))
4819 if game.state.planets[i].known=="shuttle_down":
4820 prout(_(" Shuttle Craft Galileo on surface."))
4822 prout(_("No information available."))
4825 # enter standard orbit
4829 prout(_("Already in standard orbit."))
4831 if damaged(DWARPEN) and damaged(DIMPULS):
4832 prout(_("Both warp and impulse engines damaged."))
4834 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4836 prout(_(" not adjacent to planet."))
4839 game.optime = randreal(0.02, 0.05)
4840 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4844 game.height = randreal(1400, 8600)
4845 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4850 # examine planets in this quadrant
4851 if damaged(DSRSENS):
4852 if game.options & OPTION_TTY:
4853 prout(_("Short range sensors damaged."))
4855 if game.iplnet == None:
4856 if game.options & OPTION_TTY:
4857 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4859 if game.iplnet.known == "unknown":
4860 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4862 prout(_(" Planet at Sector %s is of class %s.") %
4863 (game.plnet, game.iplnet.pclass))
4864 if game.iplnet.known=="shuttle_down":
4865 prout(_(" Sensors show Galileo still on surface."))
4866 proutn(_(" Readings indicate"))
4867 if game.iplnet.crystals != "present":
4869 prout(_(" dilithium crystals present.\""))
4870 if game.iplnet.known == "unknown":
4871 game.iplnet.known = "known"
4872 elif game.iplnet.inhabited:
4873 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4874 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4877 # use the transporter
4881 if damaged(DTRANSP):
4882 prout(_("Transporter damaged."))
4883 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4885 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4889 if not game.inorbit:
4891 prout(_(" not in standard orbit."))
4894 prout(_("Impossible to transport through shields."))
4896 if game.iplnet.known=="unknown":
4897 prout(_("Spock- \"Captain, we have no information on this planet"))
4898 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4899 prout(_(" you may not go down.\""))
4901 if not game.landed and game.iplnet.crystals=="absent":
4902 prout(_("Spock- \"Captain, I fail to see the logic in"))
4903 prout(_(" exploring a planet with no dilithium crystals."))
4904 proutn(_(" Are you sure this is wise?\" "))
4908 if not (game.options & OPTION_PLAIN):
4909 nrgneed = 50 * game.skill + game.height / 100.0
4910 if nrgneed > game.energy:
4911 prout(_("Engineering to bridge--"))
4912 prout(_(" Captain, we don't have enough energy for transportation."))
4914 if not game.landed and nrgneed * 2 > game.energy:
4915 prout(_("Engineering to bridge--"))
4916 prout(_(" Captain, we have enough energy only to transport you down to"))
4917 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4918 if game.iplnet.known == "shuttle_down":
4919 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4920 proutn(_(" Are you sure this is wise?\" "))
4925 # Coming from planet
4926 if game.iplnet.known=="shuttle_down":
4927 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4931 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4932 prout(_("Landing party assembled, ready to beam up."))
4934 prout(_("Kirk whips out communicator..."))
4935 prouts(_("BEEP BEEP BEEP"))
4937 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4940 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4942 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4944 prout(_("Kirk- \"Energize.\""))
4947 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4950 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4952 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4955 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4956 game.landed = not game.landed
4957 game.energy -= nrgneed
4959 prout(_("Transport complete."))
4960 if game.landed and game.iplnet.known=="shuttle_down":
4961 prout(_("The shuttle craft Galileo is here!"))
4962 if not game.landed and game.imine:
4969 # strip-mine a world for dilithium
4973 prout(_("Mining party not on planet."))
4975 if game.iplnet.crystals == "mined":
4976 prout(_("This planet has already been strip-mined for dilithium."))
4978 elif game.iplnet.crystals == "absent":
4979 prout(_("No dilithium crystals on this planet."))
4982 prout(_("You've already mined enough crystals for this trip."))
4984 if game.icrystl and game.cryprob == 0.05:
4985 proutn(_("With all those fresh crystals aboard the "))
4988 prout(_("there's no reason to mine more at this time."))
4990 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4993 prout(_("Mining operation complete."))
4994 game.iplnet.crystals = "mined"
4995 game.imine = game.ididit = True
4998 # use dilithium crystals
5002 if not game.icrystl:
5003 prout(_("No dilithium crystals available."))
5005 if game.energy >= 1000:
5006 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5007 prout(_(" except when Condition Yellow exists."))
5009 prout(_("Spock- \"Captain, I must warn you that loading"))
5010 prout(_(" raw dilithium crystals into the ship's power"))
5011 prout(_(" system may risk a severe explosion."))
5012 proutn(_(" Are you sure this is wise?\" "))
5017 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5018 prout(_(" Mr. Spock and I will try it.\""))
5020 prout(_("Spock- \"Crystals in place, Sir."))
5021 prout(_(" Ready to activate circuit.\""))
5023 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5025 if with(game.cryprob):
5026 prouts(_(" \"Activating now! - - No good! It's***"))
5028 prouts(_("***RED ALERT! RED A*L********************************"))
5031 prouts(_("****************** KA-BOOM!!!! *******************"))
5035 game.energy += randreal(5000.0, 5500.0)
5036 prouts(_(" \"Activating now! - - "))
5037 prout(_("The instruments"))
5038 prout(_(" are going crazy, but I think it's"))
5039 prout(_(" going to work!! Congratulations, Sir!\""))
5044 # use shuttlecraft for planetary jaunt
5047 if damaged(DSHUTTL):
5048 if game.damage[DSHUTTL] == -1.0:
5049 if game.inorbit and game.iplnet.known == "shuttle_down":
5050 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5052 prout(_("Ye Faerie Queene had no shuttle craft."))
5053 elif game.damage[DSHUTTL] > 0:
5054 prout(_("The Galileo is damaged."))
5055 else: # game.damage[DSHUTTL] < 0
5056 prout(_("Shuttle craft is now serving Big Macs."))
5058 if not game.inorbit:
5060 prout(_(" not in standard orbit."))
5062 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5063 prout(_("Shuttle craft not currently available."))
5065 if not game.landed and game.iplnet.known=="shuttle_down":
5066 prout(_("You will have to beam down to retrieve the shuttle craft."))
5068 if game.shldup or game.condition == "docked":
5069 prout(_("Shuttle craft cannot pass through shields."))
5071 if game.iplnet.known=="unknown":
5072 prout(_("Spock- \"Captain, we have no information on this planet"))
5073 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5074 prout(_(" you may not fly down.\""))
5076 game.optime = 3.0e-5*game.height
5077 if game.optime >= 0.8*game.state.remtime:
5078 prout(_("First Officer Spock- \"Captain, I compute that such"))
5079 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5080 int(100*game.optime/game.state.remtime))
5081 prout(_("remaining time."))
5082 proutn(_("Are you sure this is wise?\" "))
5088 if game.iscraft == "onship":
5090 if not damaged(DTRANSP):
5091 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5095 proutn(_("Shuttle crew"))
5097 proutn(_("Rescue party"))
5098 prout(_(" boards Galileo and swoops toward planet surface."))
5099 game.iscraft = "offship"
5103 game.iplnet.known="shuttle_down"
5104 prout(_("Trip complete."))
5107 # Ready to go back to ship
5108 prout(_("You and your mining party board the"))
5109 prout(_("shuttle craft for the trip back to the Enterprise."))
5111 prouts(_("The short hop begins . . ."))
5113 game.iplnet.known="known"
5119 game.iscraft = "onship"
5125 prout(_("Trip complete."))
5130 prout(_("Mining party assembles in the hangar deck,"))
5131 prout(_("ready to board the shuttle craft \"Galileo\"."))
5133 prouts(_("The hangar doors open; the trip begins."))
5136 game.iscraft = "offship"
5139 game.iplnet.known = "shuttle_down"
5142 prout(_("Trip complete."))
5146 # use the big zapper
5150 if game.ship != IHE:
5151 prout(_("Ye Faerie Queene has no death ray."))
5154 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5157 prout(_("Death Ray is damaged."))
5159 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5160 prout(_(" is highly unpredictible. Considering the alternatives,"))
5161 proutn(_(" are you sure this is wise?\" "))
5164 prout(_("Spock- \"Acknowledged.\""))
5167 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5169 prout(_("Crew scrambles in emergency preparation."))
5170 prout(_("Spock and Scotty ready the death ray and"))
5171 prout(_("prepare to channel all ship's power to the device."))
5173 prout(_("Spock- \"Preparations complete, sir.\""))
5174 prout(_("Kirk- \"Engage!\""))
5176 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5179 if game.options & OPTION_PLAIN:
5183 prouts(_("Sulu- \"Captain! It's working!\""))
5185 while game.nenhere > 0:
5186 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.x][game.enemies[1].kloc.y],game.enemies[1].kloc)
5187 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5188 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5190 if (game.options & OPTION_PLAIN) == 0:
5191 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5193 prout(_(" is still operational.\""))
5195 prout(_(" has been rendered nonfunctional.\""))
5196 game.damage[DDRAY] = 39.95
5198 r = randreal() # Pick failure method
5200 prouts(_("Sulu- \"Captain! It's working!\""))
5202 prouts(_("***RED ALERT! RED ALERT!"))
5204 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5206 prouts(_("***RED ALERT! RED A*L********************************"))
5209 prouts(_("****************** KA-BOOM!!!! *******************"))
5214 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5216 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5218 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5219 prout(_(" have apparently been transformed into strange mutations."))
5220 prout(_(" Vulcans do not seem to be affected."))
5222 prout(_("Kirk- \"Raauch! Raauch!\""))
5227 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5229 proutn(_("Spock- \"I believe the word is"))
5230 prouts(_(" *ASTONISHING*"))
5231 prout(_(" Mr. Sulu."))
5232 for i in range(QUADSIZE):
5233 for j in range(QUADSIZE):
5234 if game.quad[i][j] == IHDOT:
5235 game.quad[i][j] = IHQUEST
5236 prout(_(" Captain, our quadrant is now infested with"))
5237 prouts(_(" - - - - - - *THINGS*."))
5239 prout(_(" I have no logical explanation.\""))
5241 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5243 prout(_("Scotty- \"There are so many tribbles down here"))
5244 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5248 # Code from reports.c begins here
5250 def attackreport(curt):
5251 # report status of bases under attack
5253 if is_scheduled(FCDBAS):
5254 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5255 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5256 elif game.isatb == 1:
5257 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5258 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5260 prout(_("No Starbase is currently under attack."))
5262 if is_scheduled(FCDBAS):
5263 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5265 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5269 # report on general game status
5271 s1 = "" and game.thawed and _("thawed ")
5272 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5273 s3 = (None, _("novice"). _("fair"),
5274 _("good"), _("expert"), _("emeritus"))[game.skill]
5275 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5276 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5277 prout(_("No plaque is allowed."))
5279 prout(_("This is tournament game %d.") % game.tourn)
5280 prout(_("Your secret password is \"%s\"") % game.passwd)
5281 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5282 (game.inkling + game.incom + game.inscom)))
5283 if game.incom - game.state.remcom:
5284 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5285 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5286 prout(_(", but no Commanders."))
5289 if game.skill > SKILL_FAIR:
5290 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5291 if game.state.rembase != game.inbase:
5293 if game.inbase-game.state.rembase==1:
5294 proutn(_("has been 1 base"))
5296 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5297 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5299 prout(_("There are %d bases.") % game.inbase)
5300 if communicating() or game.iseenit:
5301 # Don't report this if not seen and
5302 # either the radio is dead or not at base!
5306 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5308 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5309 if game.ship == IHE:
5310 proutn(_("You have "))
5312 proutn("%d" % (game.nprobes))
5315 proutn(_(" deep space probe"))
5319 if communicating() and is_scheduled(FDSPROB):
5321 proutn(_("An armed deep space probe is in "))
5323 proutn(_("A deep space probe is in "))
5324 prout("Quadrant %s." % game.probec)
5326 if game.cryprob <= .05:
5327 prout(_("Dilithium crystals aboard ship... not yet used."))
5331 while game.cryprob > ai:
5334 prout(_("Dilithium crystals have been used %d time%s.") % \
5335 (i, (_("s"), "")[i==1]))
5339 # long-range sensor scan
5340 if damaged(DLRSENS):
5341 # Now allow base's sensors if docked
5342 if game.condition != "docked":
5344 prout(_("LONG-RANGE SENSORS DAMAGED."))
5347 prout(_("Starbase's long-range scan"))
5349 prout(_("Long-range scan"))
5350 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5353 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5354 if not VALID_QUADRANT(x, y):
5358 if not damaged(DRADIO):
5359 game.state.galaxy[x][y].charted = True
5360 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5361 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5362 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5363 if not silent and game.state.galaxy[x][y].supernova:
5366 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5374 for i in range(NDEVICES):
5377 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5378 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5380 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5381 game.damage[i]+0.05,
5382 game.docfac*game.damage[i]+0.005))
5384 prout(_("All devices functional."))
5387 # update the chart in the Enterprise's computer from galaxy data
5388 game.lastchart = game.state.date
5389 for i in range(GALSIZE):
5390 for j in range(GALSIZE):
5391 if game.state.galaxy[i][j].charted:
5392 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5393 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5394 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5397 # display the star chart
5399 if (game.options & OPTION_AUTOSCAN):
5401 if not damaged(DRADIO):
5403 if game.lastchart < game.state.date and game.condition == "docked":
5404 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5407 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5408 if game.state.date > game.lastchart:
5409 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5410 prout(" 1 2 3 4 5 6 7 8")
5411 for i in range(GALSIZE):
5412 proutn("%d |" % (i+1))
5413 for j in range(GALSIZE):
5414 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5418 if game.state.galaxy[i][j].supernova:
5420 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5422 elif game.state.galaxy[i][j].charted:
5423 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5427 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5435 def sectscan(goodScan, i, j):
5436 # light up an individual dot in a sector
5437 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5438 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):
5439 if game.condition == "red": textcolor(RED)
5440 elif game.condition == "green": textcolor(GREEN)
5441 elif game.condition == "yellow": textcolor(YELLOW)
5442 elif game.condition == "docked": textcolor(CYAN)
5443 elif game.condition == "dead": textcolor(BROWN)
5444 if game.quad[i][j] != game.ship:
5446 proutn("%c " % game.quad[i][j])
5452 # print status report lines
5454 if not req or req == 1:
5455 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5456 % (game.state.date, game.state.remtime))
5457 if not req or req == 2:
5458 if game.condition != "docked":
5461 for t in range(NDEVICES):
5462 if game.damage[t]>0:
5464 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5465 if not req or req == 3:
5466 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5467 if not req or req == 4:
5468 if damaged(DLIFSUP):
5469 if game.condition == "docked":
5470 s = _("DAMAGED, Base provides")
5472 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5475 prstat(_("Life Support"), s)
5476 if not req or req == 5:
5477 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5478 if not req or req == 6:
5480 if game.icrystl and (game.options & OPTION_SHOWME):
5481 extra = _(" (have crystals)")
5482 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5483 if not req or req == 7:
5484 prstat(_("Torpedoes"), "%d" % (game.torps))
5485 if not req or req == 8:
5486 if damaged(DSHIELD):
5492 data = _(" %d%% %.1f units") \
5493 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5494 prstat(_("Shields"), s+data)
5495 if not req or req == 9:
5496 prstat(_("Klingons Left"), "%d" \
5497 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5498 if not req or req == 10:
5499 if game.options & OPTION_WORLDS:
5500 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5501 if plnet and plnet.inhabited:
5502 prstat(_("Major system"), plnet.name)
5504 prout(_("Sector is uninhabited"))
5505 elif not req or req == 11:
5506 attackreport(not req)
5509 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5510 while scan() == IHEOL:
5511 proutn(_("Information desired? "))
5513 if citem in requests:
5514 status(requests.index(citem))
5516 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5517 prout((" date, condition, position, lsupport, warpfactor,"))
5518 prout((" energy, torpedoes, shields, klingons, system, time."))
5523 if damaged(DSRSENS):
5524 # Allow base's sensors if docked
5525 if game.condition != "docked":
5526 prout(_(" S.R. SENSORS DAMAGED!"))
5529 prout(_(" [Using Base's sensors]"))
5531 prout(_(" Short-range scan"))
5532 if goodScan and not damaged(DRADIO):
5533 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5534 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5535 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5536 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5537 prout(" 1 2 3 4 5 6 7 8 9 10")
5538 if game.condition != "docked":
5540 for i in range(QUADSIZE):
5541 proutn("%2d " % (i+1))
5542 for j in range(QUADSIZE):
5543 sectscan(goodScan, i, j)
5548 # use computer to get estimated time of arrival for a warp jump
5549 w1 = coord(); w2 = coord()
5551 if damaged(DCOMPTR):
5552 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5555 if scan() != IHREAL:
5558 proutn(_("Destination quadrant and/or sector? "))
5562 w1.y = int(aaitem-0.5)
5563 if scan() != IHREAL:
5566 w1.x = int(aaitem-0.5)
5567 if scan() == IHREAL:
5568 w2.y = int(aaitem-0.5)
5569 if scan() != IHREAL:
5572 w2.x = int(aaitem-0.5)
5574 if game.quadrant.y>w1.x:
5578 if game.quadrant.x>w1.y:
5582 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5585 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5586 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5589 prout(_("Answer \"no\" if you don't know the value:"))
5592 proutn(_("Time or arrival date? "))
5595 if ttime > game.state.date:
5596 ttime -= game.state.date # Actually a star date
5597 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5598 if ttime <= 1e-10 or twarp > 10:
5599 prout(_("We'll never make it, sir."))
5606 proutn(_("Warp factor? "))
5610 if twarp<1.0 or twarp > 10.0:
5614 prout(_("Captain, certainly you can give me one of these."))
5617 ttime = (10.0*game.dist)/square(twarp)
5618 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5619 if tpower >= game.energy:
5620 prout(_("Insufficient energy, sir."))
5621 if not game.shldup or tpower > game.energy*2.0:
5624 proutn(_("New warp factor to try? "))
5625 if scan() == IHREAL:
5628 if twarp<1.0 or twarp > 10.0:
5636 prout(_("But if you lower your shields,"))
5637 proutn(_("remaining"))
5640 proutn(_("Remaining"))
5641 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5643 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5645 prout(_("Any warp speed is adequate."))
5647 prout(_("Minimum warp needed is %.2f,") % (twarp))
5648 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5649 if game.state.remtime < ttime:
5650 prout(_("Unfortunately, the Federation will be destroyed by then."))
5652 prout(_("You'll be taking risks at that speed, Captain"))
5653 if (game.isatb==1 and game.state.kscmdr == w1 and \
5654 scheduled(FSCDBAS)< ttime+game.state.date) or \
5655 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5656 prout(_("The starbase there will be destroyed by then."))
5657 proutn(_("New warp factor to try? "))
5658 if scan() == IHREAL:
5661 if twarp<1.0 or twarp > 10.0:
5670 # Code from setup.c begins here
5673 # issue a historically correct banner
5675 prout(_("-SUPER- STAR TREK"))
5677 # From the FORTRAN original
5678 # prout(_("Latest update-21 Sept 78"))
5684 citem = "emsave.trk"
5688 proutn(_("File name: "))
5694 if '.' not in citem:
5697 fp = open(citem, "wb")
5699 prout(_("Can't freeze game as file %s") % citem)
5701 cPickle.dump(game, fp)
5705 # retrieve saved game
5706 game.passwd[0] = '\0'
5709 proutn(_("File name: "))
5715 if '.' not in citem:
5718 fp = open(citem, "rb")
5720 prout(_("Can't thaw game in %s") % citem)
5722 game = cPickle.load(fp)
5726 # I used <http://www.memory-alpha.org> to find planets
5727 # with references in ST:TOS. Eath and the Alpha Centauri
5728 # Colony have been omitted.
5730 # Some planets marked Class G and P here will be displayed as class M
5731 # because of the way planets are generated. This is a known bug.
5734 _("Andoria (Fesoan)"), # several episodes
5735 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5736 _("Vulcan (T'Khasi)"), # many episodes
5737 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5738 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5739 _("Ardana"), # TOS: "The Cloud Minders"
5740 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5741 _("Gideon"), # TOS: "The Mark of Gideon"
5742 _("Aldebaran III"), # TOS: "The Deadly Years"
5743 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5744 _("Altair IV"), # TOS: "Amok Time
5745 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5746 _("Benecia"), # TOS: "The Conscience of the King"
5747 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5748 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5749 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5750 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5751 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5752 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5753 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5754 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5755 _("Ingraham B"), # TOS: "Operation: Annihilate"
5756 _("Janus IV"), # TOS: "The Devil in the Dark"
5757 _("Makus III"), # TOS: "The Galileo Seven"
5758 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5759 _("Omega IV"), # TOS: "The Omega Glory"
5760 _("Regulus V"), # TOS: "Amok Time
5761 _("Deneva"), # TOS: "Operation -- Annihilate!"
5762 # Worlds from BSD Trek
5763 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5764 _("Beta III"), # TOS: "The Return of the Archons"
5765 _("Triacus"), # TOS: "And the Children Shall Lead",
5766 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5768 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5769 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5770 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5771 # _("Izar"), # TOS: "Whom Gods Destroy"
5772 # _("Tiburon"), # TOS: "The Way to Eden"
5773 # _("Merak II"), # TOS: "The Cloud Minders"
5774 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5775 # _("Iotia"), # TOS: "A Piece of the Action"
5779 _("S. R. Sensors"), \
5780 _("L. R. Sensors"), \
5782 _("Photon Tubes"), \
5783 _("Life Support"), \
5784 _("Warp Engines"), \
5785 _("Impulse Engines"), \
5787 _("Subspace Radio"), \
5788 _("Shuttle Craft"), \
5790 _("Navigation System"), \
5792 _("Shield Control"), \
5797 def setup(needprompt):
5798 # prepare to play, set up cosmos
5800 # Decide how many of everything
5801 if choose(needprompt):
5802 return # frozen game
5803 # Prepare the Enterprise
5804 game.alldone = game.gamewon = False
5806 game.state.crew = FULLCREW
5807 game.energy = game.inenrg = 5000.0
5808 game.shield = game.inshld = 2500.0
5809 game.shldchg = False
5813 game.quadrant = randplace(GALSIZE)
5814 game.sector = randplace(QUADSIZE)
5815 game.torps = game.intorps = 10
5816 game.nprobes = randrange(2, 5)
5818 game.wfacsq = game.warpfac * game.warpfac
5819 for i in range(NDEVICES):
5820 game.damage[i] = 0.0
5821 # Set up assorted game parameters
5822 game.battle = coord()
5823 game.state.date = game.indate = 100.0 * randreal(20, 51)
5824 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5825 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5826 game.isatb = game.state.nplankl = 0
5827 game.state.starkl = game.state.basekl = 0
5828 game.iscraft = "onship"
5832 for i in range(GALSIZE):
5833 for j in range(GALSIZE):
5834 quad = game.state.galaxy[i][j]
5839 quad.starbase = False
5840 quad.supernova = False
5841 quad.status = "secure"
5842 # Initialize times for extraneous events
5843 schedule(FSNOVA, expran(0.5 * game.intime))
5844 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5845 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5846 schedule(FBATTAK, expran(0.3*game.intime))
5848 if game.state.nscrem:
5849 schedule(FSCMOVE, 0.2777)
5854 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5855 schedule(FDISTR, expran(1.0 + game.intime))
5860 # Starchart is functional but we've never seen it
5861 game.lastchart = FOREVER
5862 # Put stars in the galaxy
5864 for i in range(GALSIZE):
5865 for j in range(GALSIZE):
5866 k = randrange(1, QUADSIZE**2/10+1)
5868 game.state.galaxy[i][j].stars = k
5869 # Locate star bases in galaxy
5870 for i in range(game.inbase):
5873 w = randplace(GALSIZE)
5874 if not game.state.galaxy[w.x][w.y].starbase:
5877 # C version: for (j = i-1; j > 0; j--)
5878 # so it did them in the opposite order.
5879 for j in range(1, i):
5880 # Improved placement algorithm to spread out bases
5881 distq = w.distance(game.state.baseq[j])
5882 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5885 prout("=== Abandoning base #%d at %s" % (i, w))
5887 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5889 prout("=== Saving base #%d, close to #%d" % (i, j))
5892 game.state.baseq[i] = w
5893 game.state.galaxy[w.x][w.y].starbase = True
5894 game.state.chart[w.x][w.y].starbase = True
5895 # Position ordinary Klingon Battle Cruisers
5897 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5898 if klumper > MAXKLQUAD:
5902 klump = (1.0 - r*r)*klumper
5907 w = randplace(GALSIZE)
5908 if not game.state.galaxy[w.x][w.y].supernova and \
5909 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5911 game.state.galaxy[w.x][w.y].klingons += int(klump)
5914 # Position Klingon Commander Ships
5915 for i in range(1, game.incom+1):
5917 w = randplace(GALSIZE)
5918 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5919 not game.state.galaxy[w.x][w.y].supernova and \
5920 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5921 not w in game.state.kcmdr[:i]:
5923 game.state.galaxy[w.x][w.y].klingons += 1
5924 game.state.kcmdr[i] = w
5925 # Locate planets in galaxy
5926 for i in range(game.inplan):
5928 w = randplace(GALSIZE)
5929 if game.state.galaxy[w.x][w.y].planet == None:
5933 new.crystals = "absent"
5934 if (game.options & OPTION_WORLDS) and i < NINHAB:
5935 new.pclass = "M" # All inhabited planets are class M
5936 new.crystals = "absent"
5938 new.name = systnames[i]
5939 new.inhabited = True
5941 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5943 new.crystals = "present"
5944 new.known = "unknown"
5945 new.inhabited = False
5946 game.state.galaxy[w.x][w.y].planet = new
5947 game.state.planets.append(new)
5949 for i in range(game.state.nromrem):
5950 w = randplace(GALSIZE)
5951 game.state.galaxy[w.x][w.y].romulans += 1
5952 # Locate the Super Commander
5953 if game.state.nscrem > 0:
5955 w = randplace(GALSIZE)
5956 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
5958 game.state.kscmdr = w
5959 game.state.galaxy[w.x][w.y].klingons += 1
5960 # Place thing (in tournament game, we don't want one!)
5962 if game.tourn is None:
5963 thing = randplace(GALSIZE)
5965 game.state.snap = False
5966 if game.skill == SKILL_NOVICE:
5967 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5968 prout(_("a deadly Klingon invasion force. As captain of the United"))
5969 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5970 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5971 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5972 prout(_("your mission. As you proceed you may be given more time."))
5974 prout(_("You will have %d supporting starbases.") % (game.inbase))
5975 proutn(_("Starbase locations- "))
5977 prout(_("Stardate %d.") % int(game.state.date))
5979 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5980 prout(_("An unknown number of Romulans."))
5981 if game.state.nscrem:
5982 prout(_("And one (GULP) Super-Commander."))
5983 prout(_("%d stardates.") % int(game.intime))
5984 proutn(_("%d starbases in ") % game.inbase)
5985 for i in range(game.inbase):
5986 proutn(`game.state.baseq[i]`)
5989 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5990 proutn(_(" Sector %s") % game.sector)
5992 prout(_("Good Luck!"))
5993 if game.state.nscrem:
5994 prout(_(" YOU'LL NEED IT."))
5997 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
5999 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6002 def choose(needprompt):
6003 # choose your game type
6008 game.skill = SKILL_NONE
6010 if needprompt: # Can start with command line options
6011 proutn(_("Would you like a regular, tournament, or saved game? "))
6013 if len(citem)==0: # Try again
6015 if isit("tournament"):
6016 while scan() == IHEOL:
6017 proutn(_("Type in tournament number-"))
6020 continue # We don't want a blank entry
6021 game.tourn = int(round(aaitem))
6024 logfp.write("# random.seed(%d)\n" % aaitem)
6026 if isit("saved") or isit("frozen"):
6030 if game.passwd == None:
6032 if not game.alldone:
6033 game.thawed = True # No plaque if not finished
6039 proutn(_("What is \"%s\"?"), citem)
6041 while game.length==0 or game.skill==SKILL_NONE:
6042 if scan() == IHALPHA:
6045 elif isit("medium"):
6049 elif isit("novice"):
6050 game.skill = SKILL_NOVICE
6052 game.skill = SKILL_FAIR
6054 game.skill = SKILL_GOOD
6055 elif isit("expert"):
6056 game.skill = SKILL_EXPERT
6057 elif isit("emeritus"):
6058 game.skill = SKILL_EMERITUS
6060 proutn(_("What is \""))
6066 proutn(_("Would you like a Short, Medium, or Long game? "))
6067 elif game.skill == SKILL_NONE:
6068 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6069 # Choose game options -- added by ESR for SST2K
6070 if scan() != IHALPHA:
6072 proutn(_("Choose your game style (or just press enter): "))
6075 # Approximates the UT FORTRAN version.
6076 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6077 game.options |= OPTION_PLAIN
6079 # Approximates Tom Almy's version.
6080 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6081 game.options |= OPTION_ALMY
6085 proutn(_("What is \"%s\"?") % citem)
6087 if game.passwd == "debug":
6089 fputs("=== Debug mode enabled\n", sys.stdout)
6091 # Use parameters to generate initial values of things
6092 game.damfac = 0.5 * game.skill
6093 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6094 game.inbase = game.state.rembase
6096 if game.options & OPTION_PLANETS:
6097 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6098 if game.options & OPTION_WORLDS:
6099 game.inplan += int(NINHAB)
6100 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6101 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6102 game.state.remtime = 7.0 * game.length
6103 game.intime = game.state.remtime
6104 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6105 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6106 game.state.remcom = min(10, game.incom)
6107 game.incom = game.state.remcom
6108 game.state.remres = (game.inkling+4*game.incom)*game.intime
6109 game.inresor = game.state.remres
6110 if game.inkling > 50:
6111 game.state.rembase += 1
6112 game.inbase = game.state.rembase
6115 def dropin(iquad=None):
6116 # drop a feature on a random dot in the current quadrant
6119 w = randplace(QUADSIZE)
6120 if game.quad[w.x][w.y] == IHDOT:
6122 if iquad is not None:
6123 game.quad[w.x][w.y] = iquad
6127 # update our alert status
6128 game.condition = "green"
6129 if game.energy < 1000.0:
6130 game.condition = "yellow"
6131 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6132 game.condition = "red"
6134 game.condition="dead"
6137 # drop new Klingon into current quadrant
6138 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
6141 # set up a new state of quadrant, for when we enter or re-enter it
6145 game.comhere = False
6151 game.inorbit = False
6153 game.ientesc = False
6154 game.iseenit = False
6156 # Attempt to escape Super-commander, so tbeam back!
6159 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6160 # cope with supernova
6163 game.klhere = q.klingons
6164 game.irhere = q.romulans
6165 game.nenhere = game.klhere + game.irhere
6167 game.quad[game.sector.x][game.sector.y] = game.ship
6170 # Position ordinary Klingons
6171 for i in range(game.klhere):
6173 # If we need a commander, promote a Klingon
6174 for i in range(game.state.remcom):
6175 if game.state.kcmdr[i] == game.quadrant:
6176 e = game.enemies[game.klhere-1]
6177 game.quad[e.kloc.x][e.kloc.y] = IHC
6178 e.kpower = randreal(950,1350) + 50.0*game.skill
6181 # If we need a super-commander, promote a Klingon
6182 if game.quadrant == game.state.kscmdr:
6184 game.quad[e.kloc.x][e.kloc.y] = IHS
6185 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
6186 game.iscate = (game.state.remkl > 1)
6188 # Put in Romulans if needed
6189 for i in range(game.klhere, game.nenhere):
6190 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
6191 # If quadrant needs a starbase, put it in
6193 game.base = dropin(IHB)
6194 # If quadrant needs a planet, put it in
6196 game.iplnet = q.planet
6197 if not q.planet.inhabited:
6198 game.plnet = dropin(IHP)
6200 game.plnet = dropin(IHW)
6201 # Check for condition
6204 if game.irhere > 0 and game.klhere == 0:
6206 if not damaged(DRADIO):
6208 prout(_("LT. Uhura- \"Captain, an urgent message."))
6209 prout(_(" I'll put it on audio.\" CLICK"))
6211 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6212 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6214 # Put in THING if needed
6215 if thing == game.quadrant:
6216 enemy(symbol=IHQUEST, loc=dropin(),
6217 power=randreal(6000,6500.0)+250.0*game.skill)
6218 if not damaged(DSRSENS):
6220 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6221 prout(_(" Please examine your short-range scan.\""))
6222 # Decide if quadrant needs a Tholian; lighten up if skill is low
6223 if game.options & OPTION_THOLIAN:
6224 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6225 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6226 (game.skill > SKILL_GOOD and withprob(0.08)):
6229 w.x = withprob(0.5) * (QUADSIZE-1)
6230 w.y = withprob(0.5) * (QUADSIZE-1)
6231 if game.quad[w.x][w.y] == IHDOT:
6233 game.tholian = enemy(symbol=IHT, loc=w,
6234 power=randrange(100, 500) + 25.0*game.skill)
6235 # Reserve unoccupied corners
6236 if game.quad[0][0]==IHDOT:
6237 game.quad[0][0] = 'X'
6238 if game.quad[0][QUADSIZE-1]==IHDOT:
6239 game.quad[0][QUADSIZE-1] = 'X'
6240 if game.quad[QUADSIZE-1][0]==IHDOT:
6241 game.quad[QUADSIZE-1][0] = 'X'
6242 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6243 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6244 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
6245 # And finally the stars
6246 for i in range(q.stars):
6248 # Put in a few black holes
6249 for i in range(1, 3+1):
6252 # Take out X's in corners if Tholian present
6254 if game.quad[0][0]=='X':
6255 game.quad[0][0] = IHDOT
6256 if game.quad[0][QUADSIZE-1]=='X':
6257 game.quad[0][QUADSIZE-1] = IHDOT
6258 if game.quad[QUADSIZE-1][0]=='X':
6259 game.quad[QUADSIZE-1][0] = IHDOT
6260 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6261 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6264 # set the self-destruct password
6265 if game.options & OPTION_PLAIN:
6268 proutn(_("Please type in a secret password- "))
6271 if game.passwd != None:
6276 game.passwd += chr(ord('a')+randrange(26))
6278 # Code from sst.c begins here
6281 "SRSCAN": OPTION_TTY,
6282 "STATUS": OPTION_TTY,
6283 "REQUEST": OPTION_TTY,
6284 "LRSCAN": OPTION_TTY,
6297 "SENSORS": OPTION_PLANETS,
6298 "ORBIT": OPTION_PLANETS,
6299 "TRANSPORT": OPTION_PLANETS,
6300 "MINE": OPTION_PLANETS,
6301 "CRYSTALS": OPTION_PLANETS,
6302 "SHUTTLE": OPTION_PLANETS,
6303 "PLANETS": OPTION_PLANETS,
6308 "PROBE": OPTION_PROBE,
6310 "FREEZE": 0, # Synonym for SAVE
6316 "SOS": 0, # Synonym for MAYDAY
6317 "CALL": 0, # Synonym for MAYDAY
6324 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6327 # generate a list of legal commands
6329 proutn(_("LEGAL COMMANDS ARE:"))
6330 for key in commands:
6334 proutn("%-12s " % key)
6339 # browse on-line help
6340 # Give help on commands
6344 setwnd(prompt_window)
6345 proutn(_("Help on what command? "))
6347 setwnd(message_window)
6350 if citem in commands or citem == "ABBREV":
6359 fp = open(SSTDOC, "r")
6362 fp = open(DOC_NAME, "r")
6364 prout(_("Spock- \"Captain, that information is missing from the"))
6365 proutn(_(" computer. You need to find "))
6367 prout(_(" and put it in the"))
6368 proutn(_(" current directory or to "))
6372 # This used to continue: "You need to find SST.DOC and put
6373 # it in the current directory."
6377 linebuf = fp.readline()
6379 prout(_("Spock- \"Captain, there is no information on that command.\""))
6382 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6383 linebuf = linebuf[3:].strip()
6387 prout(_("Spock- \"Captain, I've found the following information:\""))
6389 while linebuf in fp:
6390 if "******" in linebuf:
6396 # command-interpretation loop
6399 setwnd(message_window)
6400 while True: # command loop
6402 while True: # get a command
6407 setwnd(prompt_window)
6411 if game.options & OPTION_CURSES:
6416 setwnd(message_window)
6418 candidates = filter(lambda x: x.startswith(citem.upper()),
6420 if len(candidates) == 1:
6423 elif candidates and not (game.options & OPTION_PLAIN):
6424 prout("Commands with that prefix: " + " ".join(candidates))
6428 if cmd == "SRSCAN": # srscan
6430 elif cmd == "STATUS": # status
6432 elif cmd == "REQUEST": # status request
6434 elif cmd == "LRSCAN": # long range scan
6435 lrscan(silent=False)
6436 elif cmd == "PHASERS": # phasers
6440 elif cmd == "TORPEDO": # photon torpedos
6444 elif cmd == "MOVE": # move under warp
6446 elif cmd == "SHIELDS": # shields
6447 doshield(shraise=False)
6450 game.shldchg = False
6451 elif cmd == "DOCK": # dock at starbase
6455 elif cmd == "DAMAGES": # damage reports
6457 elif cmd == "CHART": # chart
6459 elif cmd == "IMPULSE": # impulse
6461 elif cmd == "REST": # rest
6465 elif cmd == "WARP": # warp
6467 elif cmd == "SCORE": # score
6469 elif cmd == "SENSORS": # sensors
6471 elif cmd == "ORBIT": # orbit
6475 elif cmd == "TRANSPORT": # transport "beam"
6477 elif cmd == "MINE": # mine
6481 elif cmd == "CRYSTALS": # crystals
6485 elif cmd == "SHUTTLE": # shuttle
6489 elif cmd == "PLANETS": # Planet list
6491 elif cmd == "REPORT": # Game Report
6493 elif cmd == "COMPUTER": # use COMPUTER!
6495 elif cmd == "COMMANDS":
6497 elif cmd == "EMEXIT": # Emergency exit
6498 clrscr() # Hide screen
6499 freeze(True) # forced save
6500 raise SysExit,1 # And quick exit
6501 elif cmd == "PROBE":
6502 probe() # Launch probe
6505 elif cmd == "ABANDON": # Abandon Ship
6507 elif cmd == "DESTRUCT": # Self Destruct
6509 elif cmd == "SAVE": # Save Game
6512 if game.skill > SKILL_GOOD:
6513 prout(_("WARNING--Saved games produce no plaques!"))
6514 elif cmd == "DEATHRAY": # Try a desparation measure
6518 elif cmd == "DEBUGCMD": # What do we want for debug???
6520 elif cmd == "MAYDAY": # Call for help
6525 game.alldone = True # quit the game
6530 break # Game has ended
6531 if game.optime != 0.0:
6534 break # Events did us in
6535 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6538 if hitme and not game.justin:
6542 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6554 if cmd == IHR: s = _("Romulan")
6555 elif cmd == IHK: s = _("Klingon")
6556 elif cmd == IHC: s = _("Commander")
6557 elif cmd == IHS: s = _("Super-commander")
6558 elif cmd == IHSTAR: s = _("Star")
6559 elif cmd == IHP: s = _("Planet")
6560 elif cmd == IHB: s = _("Starbase")
6561 elif cmd == IHBLANK: s = _("Black hole")
6562 elif cmd == IHT: s = _("Tholian")
6563 elif cmd == IHWEB: s = _("Tholian web")
6564 elif cmd == IHQUEST: s = _("Stranger")
6565 elif cmd == IHW: s = _("Inhabited World")
6566 else: s = "Unknown??"
6569 def crmena(stars, enemy, loctype, w):
6570 # print an enemy and his location
6576 if loctype == "quadrant":
6577 buf = _("Quadrant ")
6578 elif loctype == "sector":
6583 # print our ship name
6584 if game.ship == IHE:
6586 elif game.ship == IHF:
6587 s = _("Faerie Queene")
6593 # print a line of stars
6594 prouts("******************************************************")
6598 return -avrage*math.log(1e-7 + randreal())
6600 def randplace(size):
6601 # choose a random location
6603 w.x = randrange(size)
6604 w.y = randrange(size)
6608 # Demand input for next scan
6613 # return IHEOL next time
6618 # Get a token from the user
6619 global inqueue, line, citem, aaitem
6623 # Read a line if nothing here
6626 if curwnd==prompt_window:
6628 setwnd(message_window)
6630 # Skip leading white space
6631 line = line.lstrip()
6633 inqueue = line.split()
6639 # From here on in it's all looking at the queue
6640 citem = inqueue.pop(0)
6644 aaitem = float(citem)
6649 citem = citem.lower()
6653 # yes-or-no confirmation
6662 proutn(_("Please answer with \"y\" or \"n\": "))
6665 # complain about unparseable input
6668 prout(_("Beg your pardon, Captain?"))
6671 # compares s to citem and returns true if it matches to the length of s
6672 return s.startswith(citem)
6675 # access to the internals for debugging
6676 proutn("Reset levels? ")
6678 if game.energy < game.inenrg:
6679 game.energy = game.inenrg
6680 game.shield = game.inshld
6681 game.torps = game.intorps
6682 game.lsupres = game.inlsr
6683 proutn("Reset damage? ")
6685 for i in range(NDEVICES):
6686 if game.damage[i] > 0.0:
6687 game.damage[i] = 0.0
6688 proutn("Toggle debug flag? ")
6692 prout("Debug output ON")
6694 prout("Debug output OFF")
6695 proutn("Cause selective damage? ")
6697 for i in range(NDEVICES):
6703 if key == IHALPHA and isit("y"):
6704 game.damage[i] = 10.0
6705 proutn("Examine/change events? ")
6710 FSNOVA: "Supernova ",
6713 FBATTAK: "Base Attack ",
6714 FCDBAS: "Base Destroy ",
6715 FSCMOVE: "SC Move ",
6716 FSCDBAS: "SC Base Destroy ",
6717 FDSPROB: "Probe Move ",
6718 FDISTR: "Distress Call ",
6719 FENSLV: "Enslavement ",
6720 FREPRO: "Klingon Build ",
6722 for i in range(1, NEVENTS):
6725 proutn("%.2f" % (scheduled(i)-game.state.date))
6726 if i == FENSLV or i == FREPRO:
6728 proutn(" in %s" % ev.quadrant)
6738 ev = schedule(i, aaitem)
6739 if i == FENSLV or i == FREPRO:
6741 proutn("In quadrant- ")
6743 # IHEOL says to leave coordinates as they are
6746 prout("Event %d canceled, no x coordinate." % (i))
6749 w.x = int(round(aaitem))
6752 prout("Event %d canceled, no y coordinate." % (i))
6755 w.y = int(round(aaitem))
6758 proutn("Induce supernova here? ")
6760 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6763 if __name__ == '__main__':
6765 global line, thing, game, idebug
6766 game = citem = aaitem = inqueue = None
6772 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6773 # Disable curses mode until the game logic is working.
6774 # if os.getenv("TERM"):
6775 # game.options |= OPTION_CURSES | OPTION_SHOWME
6777 game.options |= OPTION_TTY
6778 seed = int(time.time())
6779 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6780 for (switch, val) in options:
6783 replayfp = open(val, "r")
6785 sys.stderr.write("sst: can't open replay file %s\n" % val)
6788 line = replayfp.readline().strip()
6789 (leader, key, seed) = line.split()
6791 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6792 line = replayfp.readline().strip()
6793 arguments += line.split()[2:]
6795 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6797 game.options |= OPTION_TTY
6798 game.options &=~ OPTION_CURSES
6799 elif switch == '-t':
6800 game.options |= OPTION_TTY
6801 game.options &=~ OPTION_CURSES
6802 elif switch == '-x':
6805 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6807 # where to save the input in case of bugs
6809 logfp = open("/usr/tmp/sst-input.log", "w")
6811 sys.stderr.write("sst: warning, can't open logfile\n")
6813 logfp.write("# seed %s\n" % seed)
6814 logfp.write("# options %s\n" % " ".join(arguments))
6821 while True: # Play a game
6822 setwnd(fullscreen_window)
6825 setup(needprompt=not inqueue)
6828 game.alldone = False
6834 if game.tourn and game.alldone:
6835 proutn(_("Do you want your score recorded?"))
6840 proutn(_("Do you want to play again? "))
6844 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6846 except KeyboardInterrupt: