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(enemy, look, 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
634 if enemy.type == IHR:
635 return False; # Romulans cannot escape!
637 # avoid intruding on another commander's territory
638 if enemy.type == IHC:
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 enemy.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, enemy.type, "sector", enemy.kloc)
653 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
654 # handle local matters related to escape
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(enemy):
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 mdist = int(dist1 + 0.5); # Nearest integer distance
729 # If SC, check with spy to see if should hi-tail it
730 if enemy.type==IHS and \
731 (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
735 # decide whether to advance, retreat, or hold position
736 forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
738 forces += 1000; # Good for enemy if shield is down!
739 if not damaged(DPHASER) or not damaged(DPHOTON):
740 if damaged(DPHASER): # phasers damaged
743 forces -= 0.2*(game.energy - 2500.0)
744 if damaged(DPHOTON): # photon torpedoes damaged
747 forces -= 50.0*game.torps
749 # phasers and photon tubes both out!
752 if forces <= 1000.0 and game.condition != "docked": # Typical situation
753 motion = ((forces + randreal(200))/150.0) - 5.0
755 if forces > 1000.0: # Very strong -- move in for kill
756 motion = (1.0-square(randreal()))*dist1 + 1.0
757 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
758 motion -= game.skill*(2.0-square(randreal()))
760 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
761 # don't move if no motion
764 # Limit motion according to skill
765 if abs(motion) > game.skill:
770 # calculate preferred number of steps
775 if motion > 0 and nsteps > mdist:
776 nsteps = mdist; # don't overshoot
777 if nsteps > QUADSIZE:
778 nsteps = QUADSIZE; # This shouldn't be necessary
780 nsteps = 1; # This shouldn't be necessary
782 proutn("NSTEPS = %d:" % nsteps)
783 # Compute preferred values of delta X and Y
784 mx = game.sector.x - enemy.kloc.x
785 my = game.sector.y - enemy.kloc.y
786 if 2.0 * abs(mx) < abs(my):
788 if 2.0 * abs(my) < abs(game.sector.x-enemy.kloc.x):
802 for ll in range(nsteps):
804 proutn(" %d" % (ll+1))
805 # Check if preferred position available
817 attempts = 0; # Settle mysterious hang problem
818 while attempts < 20 and not success:
820 if look.x < 0 or look.x >= QUADSIZE:
821 if motion < 0 and tryexit(enemy, look, irun):
823 if krawlx == mx or my == 0:
825 look.x = next.x + krawlx
827 elif look.y < 0 or look.y >= QUADSIZE:
828 if motion < 0 and tryexit(enemy, look, irun):
830 if krawly == my or mx == 0:
832 look.y = next.y + krawly
834 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
835 # See if enemy should ram ship
836 if game.quad[look.x][look.y] == game.ship and \
837 (enemy.type == IHC or enemy.type == IHS):
838 collision(rammed=True, enemy=enemy)
840 if krawlx != mx and my != 0:
841 look.x = next.x + krawlx
843 elif krawly != my and mx != 0:
844 look.y = next.y + krawly
847 break; # we have failed
858 # Put commander in place within same quadrant
859 game.quad[enemy.kloc.x][enemy.kloc.y] = IHDOT
860 game.quad[next.x][next.y] = enemy.type
861 if next != enemy.kloc:
864 enemy.kdist = enemy.kavgd = distance(game.sector, next)
865 if not damaged(DSRSENS) or game.condition == "docked":
868 proutn(_(" from Sector %s") % enemy.kloc)
869 if enemy.kdist < dist1:
870 proutn(_(" advances to "))
872 proutn(_(" retreats to "))
873 prout("Sector %s." % next)
876 # Klingon tactical movement
879 # Figure out which Klingon is the commander (or Supercommander)
882 for enemy in game.enemies:
883 if enemy.type == IHC:
886 for enemy in game.enemies:
887 if enemy.type == IHS:
890 # If skill level is high, move other Klingons and Romulans too!
891 # Move these last so they can base their actions on what the
893 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
894 for enemy in game.enemies:
895 if enemy.type in (IHK, IHR):
897 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
899 def movescom(iq, avoid):
900 # commander movement helper
901 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
902 game.state.galaxy[iq.x][iq.y].supernova or \
903 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
906 # Avoid quadrants with bases if we want to avoid Enterprise
907 for i in range(game.state.rembase):
908 if game.state.baseq[i] == iq:
910 if game.justin and not game.iscate:
913 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
914 game.state.kscmdr = iq
915 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
917 # SC has scooted, Remove him from current quadrant
923 for enemy in game.enemies:
924 if enemy.type == IHS:
928 if game.condition != "docked":
930 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
931 # check for a helpful planet
932 for i in range(game.inplan):
933 if game.state.planets[i].w == game.state.kscmdr and \
934 game.state.planets[i].crystals == "present":
936 game.state.planets[i].pclass = "destroyed"
937 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
940 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
941 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
942 prout(_(" by the Super-commander.\""))
944 return False; # looks good!
946 def supercommander():
947 # move the Super Commander
948 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
951 prout("== SUPERCOMMANDER")
952 # Decide on being active or passive
953 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 \
954 (game.state.date-game.indate) < 3.0)
955 if not game.iscate and avoid:
956 # compute move away from Enterprise
957 idelta = game.state.kscmdr-game.quadrant
958 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
960 idelta.x = game.state.kscmdr.y-game.quadrant.y
961 idelta.y = game.quadrant.x-game.state.kscmdr.x
963 # compute distances to starbases
964 if game.state.rembase <= 0:
968 sc = game.state.kscmdr
969 for i in range(game.state.rembase):
970 basetbl.append((i, distance(game.state.baseq[i], sc)))
971 if game.state.rembase > 1:
972 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
973 # look for nearest base without a commander, no Enterprise, and
974 # without too many Klingons, and not already under attack.
975 ifindit = iwhichb = 0
976 for i2 in range(game.state.rembase):
977 i = basetbl[i2][0]; # bug in original had it not finding nearest
978 ibq = game.state.baseq[i]
979 if ibq == game.quadrant or ibq == game.battle or \
980 game.state.galaxy[ibq.x][ibq.y].supernova or \
981 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
983 # if there is a commander, and no other base is appropriate,
984 # we will take the one with the commander
985 for j in range(game.state.remcom):
986 if ibq == game.state.kcmdr[j] and ifindit!= 2:
990 if j > game.state.remcom: # no commander -- use this one
995 return # Nothing suitable -- wait until next time
996 ibq = game.state.baseq[iwhichb]
997 # decide how to move toward base
998 idelta = ibq - game.state.kscmdr
999 # Maximum movement is 1 quadrant in either or both axes
1000 idelta = idelta.sgn()
1001 # try moving in both x and y directions
1002 # there was what looked like a bug in the Almy C code here,
1003 # but it might be this translation is just wrong.
1004 iq = game.state.kscmdr + idelta
1005 if movescom(iq, avoid):
1006 # failed -- try some other maneuvers
1007 if idelta.x==0 or idelta.y==0:
1008 # attempt angle move
1010 iq.y = game.state.kscmdr.y + 1
1011 if movescom(iq, avoid):
1012 iq.y = game.state.kscmdr.y - 1
1015 iq.x = game.state.kscmdr.x + 1
1016 if movescom(iq, avoid):
1017 iq.x = game.state.kscmdr.x - 1
1020 # try moving just in x or y
1021 iq.y = game.state.kscmdr.y
1022 if movescom(iq, avoid):
1023 iq.y = game.state.kscmdr.y + idelta.y
1024 iq.x = game.state.kscmdr.x
1027 if game.state.rembase == 0:
1030 for i in range(game.state.rembase):
1031 ibq = game.state.baseq[i]
1032 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1035 return # no, don't attack base!
1036 game.iseenit = False
1038 schedule(FSCDBAS, randreal(1.0, 3.0))
1039 if is_scheduled(FCDBAS):
1040 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1041 if not communicating():
1045 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1046 % game.state.kscmdr)
1047 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1048 proutn(_(" It can survive until stardate %d.\"") \
1049 % int(scheduled(FSCDBAS)))
1050 if not game.resting:
1052 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1055 game.resting = False
1056 game.optime = 0.0; # actually finished
1058 # Check for intelligence report
1061 (not communicating()) or \
1062 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1065 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1066 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1071 if not game.tholian or game.justin:
1073 if game.tholian.kloc.x == 0 and game.tholian.kloc.y == 0:
1074 idx = 0; idy = QUADSIZE-1
1075 elif game.tholian.kloc.x == 0 and game.tholian.kloc.y == QUADSIZE-1:
1076 idx = QUADSIZE-1; idy = QUADSIZE-1
1077 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == QUADSIZE-1:
1078 idx = QUADSIZE-1; idy = 0
1079 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == 0:
1082 # something is wrong!
1085 # do nothing if we are blocked
1086 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1088 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1089 if game.tholian.kloc.x != idx:
1091 im = math.fabs(idx - game.tholian.kloc.x)*1.0/(idx - game.tholian.kloc.x)
1092 while game.tholian.kloc.x != idx:
1093 game.tholian.kloc.x += im
1094 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1095 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1096 elif game.tholian.kloc.y != idy:
1098 im = math.fabs(idy - game.tholian.kloc.y)*1.0/(idy - game.tholian.kloc.y)
1099 while game.tholian.kloc.y != idy:
1100 game.tholian.kloc.y += im
1101 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1102 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1103 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHT
1104 #game.enemies[-1].kloc = game.tholian #FIXME
1105 # check to see if all holes plugged
1106 for i in range(QUADSIZE):
1107 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1109 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1111 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1113 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1115 # All plugged up -- Tholian splits
1116 game.quad[game.tholian.kloc.x][game.tholian.kloc.y]=IHWEB
1118 crmena(True, IHT, "sector", game.tholian)
1119 prout(_(" completes web."))
1120 game.tholian.move(None)
1123 # Code from battle.c begins here
1125 def doshield(shraise):
1126 # change shield status
1134 if isit("transfer"):
1138 if damaged(DSHIELD):
1139 prout(_("Shields damaged and down."))
1146 proutn(_("Do you wish to change shield energy? "))
1148 proutn(_("Energy to transfer to shields- "))
1150 elif damaged(DSHIELD):
1151 prout(_("Shields damaged and down."))
1154 proutn(_("Shields are up. Do you want them down? "))
1161 proutn(_("Shields are down. Do you want them up? "))
1167 if action == "SHUP": # raise shields
1169 prout(_("Shields already up."))
1173 if game.condition != "docked":
1175 prout(_("Shields raised."))
1176 if game.energy <= 0:
1178 prout(_("Shields raising uses up last of energy."))
1183 elif action == "SHDN":
1185 prout(_("Shields already down."))
1189 prout(_("Shields lowered."))
1192 elif action == "NRG":
1193 while scan() != IHREAL:
1195 proutn(_("Energy to transfer to shields- "))
1199 if aaitem > game.energy:
1200 prout(_("Insufficient ship energy."))
1203 if game.shield+aaitem >= game.inshld:
1204 prout(_("Shield energy maximized."))
1205 if game.shield+aaitem > game.inshld:
1206 prout(_("Excess energy requested returned to ship energy"))
1207 game.energy -= game.inshld-game.shield
1208 game.shield = game.inshld
1210 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1211 # Prevent shield drain loophole
1213 prout(_("Engineering to bridge--"))
1214 prout(_(" Scott here. Power circuit problem, Captain."))
1215 prout(_(" I can't drain the shields."))
1218 if game.shield+aaitem < 0:
1219 prout(_("All shield energy transferred to ship."))
1220 game.energy += game.shield
1223 proutn(_("Scotty- \""))
1225 prout(_("Transferring energy to shields.\""))
1227 prout(_("Draining energy from shields.\""))
1228 game.shield += aaitem
1229 game.energy -= aaitem
1233 # choose a device to damage, at random.
1235 # Quoth Eric Allman in the code of BSD-Trek:
1236 # "Under certain conditions you can get a critical hit. This
1237 # sort of hit damages devices. The probability that a given
1238 # device is damaged depends on the device. Well protected
1239 # devices (such as the computer, which is in the core of the
1240 # ship and has considerable redundancy) almost never get
1241 # damaged, whereas devices which are exposed (such as the
1242 # warp engines) or which are particularly delicate (such as
1243 # the transporter) have a much higher probability of being
1246 # This is one place where OPTION_PLAIN does not restore the
1247 # original behavior, which was equiprobable damage across
1248 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1249 # and have done with it. Also, in the original game, DNAVYS
1250 # and DCOMPTR were the same device.
1252 # Instead, we use a table of weights similar to the one from BSD Trek.
1253 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1254 # We don't have a cloaking device. The shuttle got the allocation
1255 # for the cloaking device, then we shaved a half-percent off
1256 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1259 105, # DSRSENS: short range scanners 10.5%
1260 105, # DLRSENS: long range scanners 10.5%
1261 120, # DPHASER: phasers 12.0%
1262 120, # DPHOTON: photon torpedoes 12.0%
1263 25, # DLIFSUP: life support 2.5%
1264 65, # DWARPEN: warp drive 6.5%
1265 70, # DIMPULS: impulse engines 6.5%
1266 145, # DSHIELD: deflector shields 14.5%
1267 30, # DRADIO: subspace radio 3.0%
1268 45, # DSHUTTL: shuttle 4.5%
1269 15, # DCOMPTR: computer 1.5%
1270 20, # NAVCOMP: navigation system 2.0%
1271 75, # DTRANSP: transporter 7.5%
1272 20, # DSHCTRL: high-speed shield controller 2.0%
1273 10, # DDRAY: death ray 1.0%
1274 30, # DDSP: deep-space probes 3.0%
1276 idx = randrange(1000) # weights must sum to 1000
1278 for (i, w) in enumerate(weights):
1282 return None; # we should never get here
1284 def collision(rammed, enemy):
1285 # collision handling
1286 prouts(_("***RED ALERT! RED ALERT!"))
1288 prout(_("***COLLISION IMMINENT."))
1292 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(enemy.type, 1.0)
1294 proutn(_(" rammed by "))
1297 crmena(False, enemy.type, "sector", enemy.kloc)
1299 proutn(_(" (original position)"))
1301 deadkl(enemy.kloc, enemy.type, game.sector)
1304 prout(_(" heavily damaged."))
1305 icas = randrange(10, 30)
1306 prout(_("***Sickbay reports %d casualties"), icas)
1308 game.state.crew -= icas
1310 # In the pre-SST2K version, all devices got equiprobably damaged,
1311 # which was silly. Instead, pick up to half the devices at
1312 # random according to our weighting table,
1314 ncrits = randrange(NDEVICES/2)
1315 for m in range(ncrits):
1317 if game.damage[dev] < 0:
1319 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1320 # Damage for at least time of travel!
1321 game.damage[dev] += game.optime + extradm
1323 prout(_("***Shields are down."))
1324 if game.state.remkl + game.state.remcom + game.state.nscrem:
1331 def torpedo(course, r, incoming, i, n):
1332 # let a photon torpedo fly
1335 ac = course + 0.25*r
1336 angle = (15.0-ac)*0.5235988
1337 bullseye = (15.0 - course)*0.5235988
1338 deltax = -math.sin(angle);
1339 deltay = math.cos(angle);
1340 x = incoming.x; y = incoming.y
1341 w = coord(); jw = coord()
1342 w.x = w.y = jw.x = jw.y = 0
1343 bigger = max(math.fabs(deltax), math.fabs(deltay))
1346 if not damaged(DSRSENS) or game.condition=="docked":
1347 setwnd(srscan_window)
1349 setwnd(message_window)
1350 # Loop to move a single torpedo
1351 for l in range(1, 15+1):
1356 if not VALID_SECTOR(w.x, w.y):
1358 iquad=game.quad[w.x][w.y]
1359 tracktorpedo(w, l, i, n, iquad)
1363 setwnd(message_window)
1364 if damaged(DSRSENS) and not game.condition=="docked":
1365 skip(1); # start new line after text track
1366 if iquad in (IHE, IHF): # Hit our ship
1368 proutn(_("Torpedo hits "))
1371 hit = 700.0 + randreal(100) - \
1372 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1373 newcnd(); # we're blown out of dock
1374 # We may be displaced.
1375 if game.landed or game.condition=="docked":
1376 return hit # Cheat if on a planet
1377 ang = angle + 2.5*(randreal()-0.5)
1378 temp = math.fabs(math.sin(ang))
1379 if math.fabs(math.cos(ang)) > temp:
1380 temp = math.fabs(math.cos(ang))
1381 xx = -math.sin(ang)/temp
1382 yy = math.cos(ang)/temp
1383 jw.x = int(w.x+xx+0.5)
1384 jw.y = int(w.y+yy+0.5)
1385 if not VALID_SECTOR(jw.x, jw.y):
1387 if game.quad[jw.x][jw.y]==IHBLANK:
1390 if game.quad[jw.x][jw.y]!=IHDOT:
1391 # can't move into object
1396 elif iquad in (IHC, IHS): # Hit a commander
1398 crmena(True, iquad, "sector", w)
1399 prout(_(" uses anti-photon device;"))
1400 prout(_(" torpedo neutralized."))
1402 elif iquad in (IHR, IHK): # Hit a regular enemy
1404 for enemy in game.enemies:
1405 if w == game.enemies[ll].kloc:
1407 kp = math.fabs(e.kpower)
1408 h1 = 700.0 + randrange(100) - \
1409 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1413 if enemy.kpower < 0:
1417 if enemy.kpower == 0:
1420 crmena(True, iquad, "sector", w)
1421 # If enemy damaged but not destroyed, try to displace
1422 ang = angle + 2.5*(randreal()-0.5)
1423 temp = math.fabs(math.sin(ang))
1424 if math.fabs(math.cos(ang)) > temp:
1425 temp = math.fabs(math.cos(ang))
1426 xx = -math.sin(ang)/temp
1427 yy = math.cos(ang)/temp
1430 if not VALID_SECTOR(jw.x, jw.y):
1431 prout(_(" damaged but not destroyed."))
1433 if game.quad[jw.x][jw.y]==IHBLANK:
1434 prout(_(" buffeted into black hole."))
1435 deadkl(w, iquad, jw)
1437 if game.quad[jw.x][jw.y]!=IHDOT:
1438 # can't move into object
1439 prout(_(" damaged but not destroyed."))
1441 proutn(_(" damaged--"))
1445 elif iquad == IHB: # Hit a base
1447 prout(_("***STARBASE DESTROYED.."))
1448 for ll in range(game.state.rembase):
1449 if game.state.baseq[ll] == game.quadrant:
1450 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1452 game.quad[w.x][w.y]=IHDOT
1453 game.state.rembase -= 1
1454 game.base.x=game.base.y=0
1455 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1456 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1457 game.state.basekl += 1
1460 elif iquad == IHP: # Hit a planet
1461 crmena(True, iquad, "sector", w)
1462 prout(_(" destroyed."))
1463 game.state.nplankl += 1
1464 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1465 game.iplnet.pclass = "destroyed"
1467 invalidate(game.plnet)
1468 game.quad[w.x][w.y] = IHDOT
1470 # captain perishes on planet
1473 elif iquad == IHW: # Hit an inhabited world -- very bad!
1474 crmena(True, iquad, "sector", w)
1475 prout(_(" destroyed."))
1476 game.state.nworldkl += 1
1477 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1478 game.iplnet.pclass = "destroyed"
1480 invalidate(game.plnet)
1481 game.quad[w.x][w.y] = IHDOT
1483 # captain perishes on planet
1485 prout(_("You have just destroyed an inhabited planet."))
1486 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1488 elif iquad == IHSTAR: # Hit a star
1492 crmena(True, IHSTAR, "sector", w)
1493 prout(_(" unaffected by photon blast."))
1495 elif iquad == IHQUEST: # Hit a thingy
1496 if not (game.options & OPTION_THINGY) or withprob(0.3):
1498 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1500 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1502 proutn(_("Mr. Spock-"))
1503 prouts(_(" \"Fascinating!\""))
1508 # Stas Sergeev added the possibility that
1509 # you can shove the Thingy and piss it off.
1510 # It then becomes an enemy and may fire at you.
1515 elif iquad == IHBLANK: # Black hole
1517 crmena(True, IHBLANK, "sector", w)
1518 prout(_(" swallows torpedo."))
1520 elif iquad == IHWEB: # hit the web
1522 prout(_("***Torpedo absorbed by Tholian web."))
1524 elif iquad == IHT: # Hit a Tholian
1525 h1 = 700.0 + randrange(100) - \
1526 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1529 game.quad[w.x][w.y] = IHDOT
1534 crmena(True, IHT, "sector", w)
1536 prout(_(" survives photon blast."))
1538 prout(_(" disappears."))
1539 game.tholian.move(None)
1540 game.quad[w.x][w.y] = IHWEB
1545 proutn("Don't know how to handle torpedo collision with ")
1546 crmena(True, iquad, "sector", w)
1550 if curwnd!=message_window:
1551 setwnd(message_window)
1553 game.quad[w.x][w.y]=IHDOT
1554 game.quad[jw.x][jw.y]=iquad
1555 prout(_(" displaced by blast to Sector %s ") % jw)
1556 for ll in range(len(game.enemies)):
1557 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector,game.enemies[ll].kloc)
1558 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1561 prout(_("Torpedo missed."))
1565 # critical-hit resolution
1566 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1568 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1569 proutn(_("***CRITICAL HIT--"))
1570 # Select devices and cause damage
1572 for loop1 in range(ncrit):
1575 # Cheat to prevent shuttle damage unless on ship
1576 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1579 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1580 game.damage[j] += extradm
1582 for (i, j) in enumerate(cdam):
1584 if skipcount % 3 == 2 and i < len(cdam)-1:
1589 prout(_(" damaged."))
1590 if damaged(DSHIELD) and game.shldup:
1591 prout(_("***Shields knocked down."))
1594 def attack(torps_ok):
1595 # bad guy attacks us
1596 # torps_ok == False forces use of phasers in an attack
1597 attempt = False; ihurt = False;
1598 hitmax=0.0; hittot=0.0; chgfac=1.0
1600 # game could be over at this point, check
1604 prout("=== ATTACK!")
1605 # Tholian gets to move before attacking
1608 # if you have just entered the RNZ, you'll get a warning
1609 if game.neutz: # The one chance not to be attacked
1612 # commanders get a chance to tac-move towards you
1613 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1615 # if no enemies remain after movement, we're done
1616 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1618 # set up partial hits if attack happens during shield status change
1619 pfac = 1.0/game.inshld
1621 chgfac = 0.25 + randreal(0.5)
1623 # message verbosity control
1624 if game.skill <= SKILL_FAIR:
1626 for enemy in game.enemies:
1627 if enemy.kpower < 0:
1628 continue; # too weak to attack
1629 # compute hit strength and diminish shield power
1631 # Increase chance of photon torpedos if docked or enemy energy is low
1632 if game.condition == "docked":
1634 if enemy.kpower < 500:
1636 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1638 # different enemies have different probabilities of throwing a torp
1639 usephasers = not torps_ok or \
1640 (enemy.type == IHK and r > 0.0005) or \
1641 (enemy.type==IHC and r > 0.015) or \
1642 (enemy.type==IHR and r > 0.3) or \
1643 (enemy.type==IHS and r > 0.07) or \
1644 (enemy.type==IHQUEST and r > 0.05)
1645 if usephasers: # Enemy uses phasers
1646 if game.condition == "docked":
1647 continue; # Don't waste the effort!
1648 attempt = True; # Attempt to attack
1649 dustfac = 0.8 + randreal(0.5)
1650 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1651 enemy.kpower *= 0.75
1652 else: # Enemy uses photon torpedo
1653 course = 1.90985*math.atan2(game.sector.y-enemy.kloc.y, enemy.kloc.x-game.sector.x)
1655 proutn(_("***TORPEDO INCOMING"))
1656 if not damaged(DSRSENS):
1658 crmena(False, enemy.type, where, enemy.kloc)
1661 r = (randreal()+randreal())*0.5 - 0.5
1662 r += 0.002*enemy.kpower*r
1663 hit = torpedo(course, r, enemy.kloc, 1, 1)
1664 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1665 finish(FWON); # Klingons did themselves in!
1666 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1667 return # Supernova or finished
1670 # incoming phaser or torpedo, shields may dissipate it
1671 if game.shldup or game.shldchg or game.condition=="docked":
1672 # shields will take hits
1673 propor = pfac * game.shield
1674 if game.condition =="docked":
1678 hitsh = propor*chgfac*hit+1.0
1680 if absorb > game.shield:
1681 absorb = game.shield
1682 game.shield -= absorb
1684 # taking a hit blasts us out of a starbase dock
1685 if game.condition == "docked":
1687 # but the shields may take care of it
1688 if propor > 0.1 and hit < 0.005*game.energy:
1690 # hit from this opponent got through shields, so take damage
1692 proutn(_("%d unit hit") % int(hit))
1693 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1694 proutn(_(" on the "))
1696 if not damaged(DSRSENS) and usephasers:
1698 crmena(False, enemy.type, where, enemy.kloc)
1700 # Decide if hit is critical
1706 if game.energy <= 0:
1707 # Returning home upon your shield, not with it...
1710 if not attempt and game.condition == "docked":
1711 prout(_("***Enemies decide against attacking your ship."))
1712 percent = 100.0*pfac*game.shield+0.5
1714 # Shields fully protect ship
1715 proutn(_("Enemy attack reduces shield strength to "))
1717 # Print message if starship suffered hit(s)
1719 proutn(_("Energy left %2d shields ") % int(game.energy))
1722 elif not damaged(DSHIELD):
1725 proutn(_("damaged, "))
1726 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1727 # Check if anyone was hurt
1728 if hitmax >= 200 or hittot >= 500:
1729 icas = randrange(hittot * 0.015)
1732 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1733 prout(_(" in that last attack.\""))
1735 game.state.crew -= icas
1736 # After attack, reset average distance to enemies
1737 for enemy in game.enemies:
1738 enemy.kavgd = enemy.kdist
1739 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1742 def deadkl(w, type, mv):
1743 # kill a Klingon, Tholian, Romulan, or Thingy
1744 # Added mv to allow enemy to "move" before dying
1745 crmena(True, type, "sector", mv)
1746 # Decide what kind of enemy it is and update appropriately
1748 # chalk up a Romulan
1749 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1751 game.state.nromrem -= 1
1755 elif type == IHQUEST:
1760 # Some type of a Klingon
1761 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1764 game.comhere = False
1765 for i in range(game.state.remcom):
1766 if game.state.kcmdr[i] == game.quadrant:
1768 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1769 game.state.kcmdr[game.state.remcom].x = 0
1770 game.state.kcmdr[game.state.remcom].y = 0
1771 game.state.remcom -= 1
1773 if game.state.remcom != 0:
1774 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1775 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1778 game.state.remkl -= 1
1780 game.state.nscrem -= 1
1782 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1786 # For each kind of enemy, finish message to player
1787 prout(_(" destroyed."))
1788 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1791 # Remove enemy ship from arrays describing local conditions
1792 for e in game.enemies:
1798 def targetcheck(x, y):
1799 # Return None if target is invalid
1800 if not VALID_SECTOR(x, y):
1803 deltx = 0.1*(y - game.sector.y)
1804 delty = 0.1*(x - game.sector.x)
1805 if deltx==0 and delty== 0:
1807 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1808 prout(_(" I recommend an immediate review of"))
1809 prout(_(" the Captain's psychological profile.\""))
1812 return 1.90985932*math.atan2(deltx, delty)
1815 # launch photon torpedo
1817 if damaged(DPHOTON):
1818 prout(_("Photon tubes damaged."))
1822 prout(_("No torpedoes left."))
1831 prout(_("%d torpedoes left.") % game.torps)
1832 proutn(_("Number of torpedoes to fire- "))
1834 else: # key == IHREAL {
1836 if n <= 0: # abort command
1841 prout(_("Maximum of 3 torpedoes per burst."))
1848 for i in range(1, n+1):
1850 if i==1 and key == IHEOL:
1851 break; # we will try prompting
1852 if i==2 and key == IHEOL:
1853 # direct all torpedoes at one target
1855 targ[i][1] = targ[1][1]
1856 targ[i][2] = targ[1][2]
1857 course[i] = course[1]
1869 course[i] = targetcheck(targ[i][1], targ[i][2])
1870 if course[i] == None:
1873 if i == 1 and key == IHEOL:
1874 # prompt for each one
1875 for i in range(1, n+1):
1876 proutn(_("Target sector for torpedo number %d- ") % i)
1881 targ[i][1] = int(aaitem-0.5)
1886 targ[i][2] = int(aaitem-0.5)
1888 course[i] = targetcheck(targ[i][1], targ[i][2])
1889 if course[i] == None:
1892 # Loop for moving <n> torpedoes
1894 if game.condition != "docked":
1896 r = (randreal()+randreal())*0.5 -0.5
1897 if math.fabs(r) >= 0.47:
1899 r *= randreal(1.2, 2.2)
1901 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1903 prouts(_("***TORPEDO MISFIRES."))
1906 prout(_(" Remainder of burst aborted."))
1908 prout(_("***Photon tubes damaged by misfire."))
1909 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1911 if game.shldup or game.condition == "docked":
1912 r *= 1.0 + 0.0001*game.shield
1913 torpedo(course[i], r, game.sector, i, n)
1914 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1916 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1920 # check for phasers overheating
1922 checkburn = (rpow-1500.0)*0.00038
1923 if withprob(checkburn):
1924 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1925 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1927 def checkshctrl(rpow):
1928 # check shield control
1931 prout(_("Shields lowered."))
1933 # Something bad has happened
1934 prouts(_("***RED ALERT! RED ALERT!"))
1936 hit = rpow*game.shield/game.inshld
1937 game.energy -= rpow+hit*0.8
1938 game.shield -= hit*0.2
1939 if game.energy <= 0.0:
1940 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1945 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1947 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1948 icas = randrange(hit*0.012)
1953 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1954 prout(_(" %d casualties so far.\"") % icas)
1956 game.state.crew -= icas
1958 prout(_("Phaser energy dispersed by shields."))
1959 prout(_("Enemy unaffected."))
1964 # register a phaser hit on Klingons and Romulans
1965 nenhr2 = game.nenhere; kk=0
1968 for (k, wham) in enumerate(hits):
1971 dustfac = randreal(0.9, 1.0)
1972 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1973 kpini = game.enemies[kk].kpower
1974 kp = math.fabs(kpini)
1975 if PHASEFAC*hit < kp:
1977 if game.enemies[kk].kpower < 0:
1978 game.enemies[kk].kpower -= -kp
1980 game.enemies[kk].kpower -= kp
1981 kpow = game.enemies[kk].kpower
1982 w = game.enemies[kk].kloc
1984 if not damaged(DSRSENS):
1986 proutn(_("%d unit hit on ") % int(hit))
1988 proutn(_("Very small hit on "))
1989 ienm = game.quad[w.x][w.y]
1992 crmena(False, ienm, "sector", w)
1996 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2000 kk -= 1 # don't do the increment
2002 else: # decide whether or not to emasculate klingon
2003 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2004 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2005 prout(_(" has just lost its firepower.\""))
2006 game.enemies[kk].kpower = -kpow
2013 kz = 0; k = 1; irec=0 # Cheating inhibitor
2014 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2018 # SR sensors and Computer are needed fopr automode
2019 if damaged(DSRSENS) or damaged(DCOMPTR):
2021 if game.condition == "docked":
2022 prout(_("Phasers can't be fired through base shields."))
2025 if damaged(DPHASER):
2026 prout(_("Phaser control damaged."))
2030 if damaged(DSHCTRL):
2031 prout(_("High speed shield control damaged."))
2034 if game.energy <= 200.0:
2035 prout(_("Insufficient energy to activate high-speed shield control."))
2038 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2040 # Original code so convoluted, I re-did it all
2041 # (That was Tom Almy talking about the C code, I think -- ESR)
2042 while automode=="NOTSET":
2047 prout(_("There is no enemy present to select."))
2050 automode="AUTOMATIC"
2054 elif isit("automatic"):
2055 if (not itarg) and game.nenhere != 0:
2056 automode = "FORCEMAN"
2059 prout(_("Energy will be expended into space."))
2060 automode = "AUTOMATIC"
2069 prout(_("Energy will be expended into space."))
2070 automode = "AUTOMATIC"
2072 automode = "FORCEMAN"
2074 automode = "AUTOMATIC"
2078 prout(_("Energy will be expended into space."))
2079 automode = "AUTOMATIC"
2081 automode = "FORCEMAN"
2083 proutn(_("Manual or automatic? "))
2088 if automode == "AUTOMATIC":
2089 if key == IHALPHA and isit("no"):
2092 if key != IHREAL and game.nenhere != 0:
2093 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2098 for i in range(game.nenhere):
2099 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2101 proutn(_("%d units required. ") % irec)
2103 proutn(_("Units to fire= "))
2109 proutn(_("Energy available= %.2f") % avail)
2112 if not rpow > avail:
2119 if key == IHALPHA and isit("no"):
2122 game.energy -= 200; # Go and do it!
2123 if checkshctrl(rpow):
2131 for i in range(game.nenhere):
2135 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2136 over = randreal(1.01, 1.06) * hits[i]
2138 powrem -= hits[i] + over
2139 if powrem <= 0 and temp < hits[i]:
2148 if extra > 0 and not game.alldone:
2150 proutn(_("*** Tholian web absorbs "))
2152 proutn(_("excess "))
2153 prout(_("phaser energy."))
2155 prout(_("%d expended on empty space.") % int(extra))
2156 elif automode == "FORCEMAN":
2159 if damaged(DCOMPTR):
2160 prout(_("Battle computer damaged, manual fire only."))
2163 prouts(_("---WORKING---"))
2165 prout(_("Short-range-sensors-damaged"))
2166 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2167 prout(_("Manual-fire-must-be-used"))
2169 elif automode == "MANUAL":
2171 for k in range(game.nenhere):
2172 aim = game.enemies[k].kloc
2173 ienm = game.quad[aim.x][aim.y]
2175 proutn(_("Energy available= %.2f") % (avail-0.006))
2179 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2180 (ienm == IHC or ienm == IHS):
2182 prout(_(" can't be located without short range scan."))
2185 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2190 if itarg and k > kz:
2191 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2194 if not damaged(DCOMPTR):
2199 proutn(_("units to fire at "))
2200 crmena(False, ienm, "sector", aim)
2203 if key == IHALPHA and isit("no"):
2211 if k==1: # Let me say I'm baffled by this
2220 # If total requested is too much, inform and start over
2222 prout(_("Available energy exceeded -- try again."))
2225 key = scan(); # scan for next value
2228 # zero energy -- abort
2231 if key == IHALPHA and isit("no"):
2236 game.energy -= 200.0
2237 if checkshctrl(rpow):
2241 # Say shield raised or malfunction, if necessary
2248 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2249 prouts(_(" CLICK CLICK POP . . ."))
2250 prout(_(" No response, sir!"))
2253 prout(_("Shields raised."))
2258 # Code from events,c begins here.
2260 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2261 # event of each type active at any given time. Mostly these means we can
2262 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2263 # BSD Trek, from which we swiped the idea, can have up to 5.
2265 def unschedule(evtype):
2266 # remove an event from the schedule
2267 game.future[evtype].date = FOREVER
2268 return game.future[evtype]
2270 def is_scheduled(evtype):
2271 # is an event of specified type scheduled
2272 return game.future[evtype].date != FOREVER
2274 def scheduled(evtype):
2275 # when will this event happen?
2276 return game.future[evtype].date
2278 def schedule(evtype, offset):
2279 # schedule an event of specified type
2280 game.future[evtype].date = game.state.date + offset
2281 return game.future[evtype]
2283 def postpone(evtype, offset):
2284 # postpone a scheduled event
2285 game.future[evtype].date += offset
2288 # rest period is interrupted by event
2291 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2293 game.resting = False
2299 # run through the event queue looking for things to do
2301 fintim = game.state.date + game.optime; yank=0
2302 ictbeam = False; istract = False
2303 w = coord(); hold = coord()
2304 ev = event(); ev2 = event()
2306 def tractorbeam(yank):
2307 # tractor beaming cases merge here
2309 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2313 prout(_(" caught in long range tractor beam--"))
2314 # If Kirk & Co. screwing around on planet, handle
2315 atover(True) # atover(true) is Grab
2318 if game.icraft: # Caught in Galileo?
2321 # Check to see if shuttle is aboard
2322 if game.iscraft == "offship":
2325 prout(_("Galileo, left on the planet surface, is captured"))
2326 prout(_("by aliens and made into a flying McDonald's."))
2327 game.damage[DSHUTTL] = -10
2328 game.iscraft = "removed"
2330 prout(_("Galileo, left on the planet surface, is well hidden."))
2332 game.quadrant = game.state.kscmdr
2334 game.quadrant = game.state.kcmdr[i]
2335 game.sector = randplace(QUADSIZE)
2337 prout(_(" is pulled to Quadrant %s, Sector %s") \
2338 % (game.quadrant, game.sector))
2340 prout(_("(Remainder of rest/repair period cancelled.)"))
2341 game.resting = False
2343 if not damaged(DSHIELD) and game.shield > 0:
2344 doshield(shraise=True) # raise shields
2345 game.shldchg = False
2347 prout(_("(Shields not currently useable.)"))
2349 # Adjust finish time to time of tractor beaming
2350 fintim = game.state.date+game.optime
2352 if game.state.remcom <= 0:
2355 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2358 # Code merges here for any commander destroying base
2359 # Not perfect, but will have to do
2360 # Handle case where base is in same quadrant as starship
2361 if game.battle == game.quadrant:
2362 game.state.chart[game.battle.x][game.battle.y].starbase = False
2363 game.quad[game.base.x][game.base.y] = IHDOT
2364 game.base.x=game.base.y=0
2367 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2368 elif game.state.rembase != 1 and communicating():
2369 # Get word via subspace radio
2372 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2373 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2375 prout(_("the Klingon Super-Commander"))
2377 prout(_("a Klingon Commander"))
2378 game.state.chart[game.battle.x][game.battle.y].starbase = False
2379 # Remove Starbase from galaxy
2380 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2381 for i in range(1, game.state.rembase+1):
2382 if game.state.baseq[i] == game.battle:
2383 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2384 game.state.rembase -= 1
2386 # reinstate a commander's base attack
2390 invalidate(game.battle)
2393 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2394 for i in range(1, NEVENTS):
2395 if i == FSNOVA: proutn("=== Supernova ")
2396 elif i == FTBEAM: proutn("=== T Beam ")
2397 elif i == FSNAP: proutn("=== Snapshot ")
2398 elif i == FBATTAK: proutn("=== Base Attack ")
2399 elif i == FCDBAS: proutn("=== Base Destroy ")
2400 elif i == FSCMOVE: proutn("=== SC Move ")
2401 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2402 elif i == FDSPROB: proutn("=== Probe Move ")
2403 elif i == FDISTR: proutn("=== Distress Call ")
2404 elif i == FENSLV: proutn("=== Enslavement ")
2405 elif i == FREPRO: proutn("=== Klingon Build ")
2407 prout("%.2f" % (scheduled(i)))
2410 radio_was_broken = damaged(DRADIO)
2413 # Select earliest extraneous event, evcode==0 if no events
2418 for l in range(1, NEVENTS):
2419 if game.future[l].date < datemin:
2422 prout("== Event %d fires" % evcode)
2423 datemin = game.future[l].date
2424 xtime = datemin-game.state.date
2425 game.state.date = datemin
2426 # Decrement Federation resources and recompute remaining time
2427 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2429 if game.state.remtime <=0:
2432 # Any crew left alive?
2433 if game.state.crew <=0:
2436 # Is life support adequate?
2437 if damaged(DLIFSUP) and game.condition != "docked":
2438 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2441 game.lsupres -= xtime
2442 if game.damage[DLIFSUP] <= xtime:
2443 game.lsupres = game.inlsr
2446 if game.condition == "docked":
2447 repair /= game.docfac
2448 # Don't fix Deathray here
2449 for l in range(NDEVICES):
2450 if game.damage[l] > 0.0 and l != DDRAY:
2451 if game.damage[l]-repair > 0.0:
2452 game.damage[l] -= repair
2454 game.damage[l] = 0.0
2455 # If radio repaired, update star chart and attack reports
2456 if radio_was_broken and not damaged(DRADIO):
2457 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2458 prout(_(" surveillance reports are coming in."))
2460 if not game.iseenit:
2464 prout(_(" The star chart is now up to date.\""))
2466 # Cause extraneous event EVCODE to occur
2467 game.optime -= xtime
2468 if evcode == FSNOVA: # Supernova
2471 schedule(FSNOVA, expran(0.5*game.intime))
2472 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2474 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2475 if game.state.nscrem == 0 or \
2476 ictbeam or istract or \
2477 game.condition=="docked" or game.isatb==1 or game.iscate:
2479 if game.ientesc or \
2480 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2481 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2482 (damaged(DSHIELD) and \
2483 (game.energy < 2500 or damaged(DPHASER)) and \
2484 (game.torps < 5 or damaged(DPHOTON))):
2486 istract = ictbeam = True
2487 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2490 elif evcode == FTBEAM: # Tractor beam
2491 if game.state.remcom == 0:
2494 i = randrange(game.state.remcom)
2495 yank = distance(game.state.kcmdr[i], game.quadrant)
2496 if istract or game.condition == "docked" or yank == 0:
2497 # Drats! Have to reschedule
2499 game.optime + expran(1.5*game.intime/game.state.remcom))
2503 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2504 game.snapsht = copy.deepcopy(game.state)
2505 game.state.snap = True
2506 schedule(FSNAP, expran(0.5 * game.intime))
2507 elif evcode == FBATTAK: # Commander attacks starbase
2508 if game.state.remcom==0 or game.state.rembase==0:
2514 for j in range(game.state.rembase):
2515 for k in range(game.state.remcom):
2516 if game.state.baseq[j] == game.state.kcmdr[k] and \
2517 not game.state.baseq[j] == game.quadrant and \
2518 not game.state.baseq[j] == game.state.kscmdr:
2522 if j>game.state.rembase:
2523 # no match found -- try later
2524 schedule(FBATTAK, expran(0.3*game.intime))
2527 # commander + starbase combination found -- launch attack
2528 game.battle = game.state.baseq[j]
2529 schedule(FCDBAS, randreal(1.0, 4.0))
2530 if game.isatb: # extra time if SC already attacking
2531 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2532 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2533 game.iseenit = False
2534 if not communicating():
2535 continue # No warning :-(
2539 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2540 prout(_(" reports that it is under attack and that it can"))
2541 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2544 elif evcode == FSCDBAS: # Supercommander destroys base
2547 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2548 continue # WAS RETURN!
2550 game.battle = game.state.kscmdr
2552 elif evcode == FCDBAS: # Commander succeeds in destroying base
2555 # find the lucky pair
2556 for i in range(game.state.remcom):
2557 if game.state.kcmdr[i] == game.battle:
2559 if i > game.state.remcom or game.state.rembase == 0 or \
2560 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2561 # No action to take after all
2562 invalidate(game.battle)
2565 elif evcode == FSCMOVE: # Supercommander moves
2566 schedule(FSCMOVE, 0.2777)
2567 if not game.ientesc and not istract and game.isatb != 1 and \
2568 (not game.iscate or not game.justin):
2570 elif evcode == FDSPROB: # Move deep space probe
2571 schedule(FDSPROB, 0.01)
2572 game.probex += game.probeinx
2573 game.probey += game.probeiny
2574 i = (int)(game.probex/QUADSIZE +0.05)
2575 j = (int)(game.probey/QUADSIZE + 0.05)
2576 if game.probec.x != i or game.probec.y != j:
2579 if not VALID_QUADRANT(i, j) or \
2580 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2581 # Left galaxy or ran into supernova
2585 proutn(_("Lt. Uhura- \"The deep space probe "))
2586 if not VALID_QUADRANT(j, i):
2587 proutn(_("has left the galaxy"))
2589 proutn(_("is no longer transmitting"))
2593 if not communicating():
2596 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2597 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2598 # Update star chart if Radio is working or have access to radio
2600 chp = game.state.chart[game.probec.x][game.probec.y]
2601 chp.klingons = pdest.klingons
2602 chp.starbase = pdest.starbase
2603 chp.stars = pdest.stars
2604 pdest.charted = True
2605 game.proben -= 1 # One less to travel
2606 if game.proben == 0 and game.isarmed and pdest.stars:
2607 # lets blow the sucker!
2608 supernova(True, game.probec)
2610 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2612 elif evcode == FDISTR: # inhabited system issues distress call
2614 # try a whole bunch of times to find something suitable
2615 for i in range(100):
2616 # need a quadrant which is not the current one,
2617 # which has some stars which are inhabited and
2618 # not already under attack, which is not
2619 # supernova'ed, and which has some Klingons in it
2620 w = randplace(GALSIZE)
2621 q = game.state.galaxy[w.x][w.y]
2622 if not (game.quadrant == w or q.planet == None or \
2623 not q.planet.inhabited or \
2624 q.supernova or q.status!="secure" or q.klingons<=0):
2627 # can't seem to find one; ignore this call
2629 prout("=== Couldn't find location for distress event.")
2631 # got one!! Schedule its enslavement
2632 ev = schedule(FENSLV, expran(game.intime))
2634 q.status = distressed
2636 # tell the captain about it if we can
2638 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2640 prout(_("by a Klingon invasion fleet."))
2643 elif evcode == FENSLV: # starsystem is enslaved
2644 ev = unschedule(FENSLV)
2645 # see if current distress call still active
2646 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2650 q.status = "enslaved"
2652 # play stork and schedule the first baby
2653 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2654 ev2.quadrant = ev.quadrant
2656 # report the disaster if we can
2658 prout(_("Uhura- We've lost contact with starsystem %s") % \
2660 prout(_("in Quadrant %s.\n") % ev.quadrant)
2661 elif evcode == FREPRO: # Klingon reproduces
2662 # If we ever switch to a real event queue, we'll need to
2663 # explicitly retrieve and restore the x and y.
2664 ev = schedule(FREPRO, expran(1.0 * game.intime))
2665 # see if current distress call still active
2666 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2670 if game.state.remkl >=MAXKLGAME:
2671 continue # full right now
2672 # reproduce one Klingon
2674 if game.klhere >= MAXKLQUAD:
2676 # this quadrant not ok, pick an adjacent one
2677 for i in range(w.x - 1, w.x + 2):
2678 for j in range(w.y - 1, w.y + 2):
2679 if not VALID_QUADRANT(i, j):
2681 q = game.state.galaxy[w.x][w.y]
2682 # check for this quad ok (not full & no snova)
2683 if q.klingons >= MAXKLQUAD or q.supernova:
2687 continue # search for eligible quadrant failed
2692 game.state.remkl += 1
2694 if game.quadrant == w:
2696 game.enemies.append(newkling())
2697 # recompute time left
2699 # report the disaster if we can
2701 if game.quadrant == w:
2702 prout(_("Spock- sensors indicate the Klingons have"))
2703 prout(_("launched a warship from %s.") % q.planet)
2705 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2706 if q.planet != None:
2707 proutn(_("near %s") % q.planet)
2708 prout(_("in Quadrant %s.") % w)
2717 proutn(_("How long? "))
2722 origTime = delay = aaitem
2725 if delay >= game.state.remtime or game.nenhere != 0:
2726 proutn(_("Are you sure? "))
2729 # Alternate resting periods (events) with attacks
2733 game.resting = False
2734 if not game.resting:
2735 prout(_("%d stardates left.") % int(game.state.remtime))
2737 temp = game.optime = delay
2739 rtime = randreal(1.0, 2.0)
2743 if game.optime < delay:
2752 # Repair Deathray if long rest at starbase
2753 if origTime-delay >= 9.99 and game.condition == "docked":
2754 game.damage[DDRAY] = 0.0
2755 # leave if quadrant supernovas
2756 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2758 game.resting = False
2761 # A nova occurs. It is the result of having a star hit with a
2762 # photon torpedo, or possibly of a probe warhead going off.
2763 # Stars that go nova cause stars which surround them to undergo
2764 # the same probabilistic process. Klingons next to them are
2765 # destroyed. And if the starship is next to it, it gets zapped.
2766 # If the zap is too much, it gets destroyed.
2770 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2771 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2773 # Wow! We've supernova'ed
2774 supernova(False, nov)
2776 # handle initial nova
2777 game.quad[nov.x][nov.y] = IHDOT
2778 crmena(False, IHSTAR, "sector", nov)
2780 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2781 game.state.starkl += 1
2782 # Set up queue to recursively trigger adjacent stars
2788 for offset.x in range(-1, 1+1):
2789 for offset.y in range(-1, 1+1):
2790 if offset.y==0 and offset.x==0:
2792 neighbor = start + offset
2793 if not VALID_SECTOR(neighbor.y, neighbor.x):
2795 iquad = game.quad[neighbor.x][neighbor.y]
2796 # Empty space ends reaction
2797 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2799 elif iquad == IHSTAR: # Affect another star
2801 # This star supernovas
2805 hits.append(neighbor)
2806 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2807 game.state.starkl += 1
2808 crmena(True, IHSTAR, "sector", neighbor)
2810 game.quad[neighbor.x][neighbor.y] = IHDOT
2812 elif iquad in (IHP, IHW): # Destroy planet
2813 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2815 game.state.nplankl += 1
2817 game.state.worldkl += 1
2818 crmena(True, iquad, "sector", neighbor)
2819 prout(_(" destroyed."))
2820 game.iplnet.pclass = "destroyed"
2822 invalidate(game.plnet)
2826 game.quad[neighbor.x][neighbor.y] = IHDOT
2827 elif iquad == IHB: # Destroy base
2828 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2829 for i in range(game.state.rembase):
2830 if game.state.baseq[i] == game.quadrant:
2832 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2833 game.state.rembase -= 1
2834 invalidate(game.base)
2835 game.state.basekl += 1
2837 crmena(True, IHB, "sector", neighbor)
2838 prout(_(" destroyed."))
2839 game.quad[neighbor.x][neighbor.y] = IHDOT
2840 elif iquad in (IHE, IHF): # Buffet ship
2841 prout(_("***Starship buffeted by nova."))
2843 if game.shield >= 2000.0:
2844 game.shield -= 2000.0
2846 diff = 2000.0 - game.shield
2850 prout(_("***Shields knocked out."))
2851 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2853 game.energy -= 2000.0
2854 if game.energy <= 0:
2857 # add in course nova contributes to kicking starship
2858 bump += (game.sector-hits[mm]).sgn()
2859 elif iquad == IHK: # kill klingon
2860 deadkl(neighbor, iquad, neighbor)
2861 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2862 for ll in range(game.nenhere):
2863 if game.enemies[ll].kloc == neighbor:
2865 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2866 if game.enemies[ll].kpower <= 0.0:
2867 deadkl(neighbor, iquad, neighbor)
2869 newc = neighbor + neighbor - hits[mm]
2870 crmena(True, iquad, "sector", neighbor)
2871 proutn(_(" damaged"))
2872 if not VALID_SECTOR(newc.x, newc.y):
2873 # can't leave quadrant
2876 iquad1 = game.quad[newc.x][newc.y]
2877 if iquad1 == IHBLANK:
2878 proutn(_(", blasted into "))
2879 crmena(False, IHBLANK, "sector", newc)
2881 deadkl(neighbor, iquad, newc)
2884 # can't move into something else
2887 proutn(_(", buffeted to Sector %s") % newc)
2888 game.quad[neighbor.x][neighbor.y] = IHDOT
2889 game.quad[newc.x][newc.y] = iquad
2890 game.enemies[ll].move(newc)
2891 # Starship affected by nova -- kick it away.
2892 game.dist = kount*0.1
2893 game.direc = course[3*(bump.x+1)+bump.y+2]
2894 if game.direc == 0.0:
2896 if game.dist == 0.0:
2898 game.optime = 10.0*game.dist/16.0
2900 prout(_("Force of nova displaces starship."))
2901 imove(novapush=True)
2902 game.optime = 10.0*game.dist/16.0
2905 def supernova(induced, w=None):
2906 # star goes supernova
2913 # Scheduled supernova -- select star
2914 # logic changed here so that we won't favor quadrants in top
2916 for nq.x in range(GALSIZE):
2917 for nq.y in range(GALSIZE):
2918 stars += game.state.galaxy[nq.x][nq.y].stars
2920 return # nothing to supernova exists
2921 num = randrange(stars) + 1
2922 for nq.x in range(GALSIZE):
2923 for nq.y in range(GALSIZE):
2924 num -= game.state.galaxy[nq.x][nq.y].stars
2930 proutn("=== Super nova here?")
2933 if not nq == game.quadrant or game.justin:
2934 # it isn't here, or we just entered (treat as enroute)
2937 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2938 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2941 # we are in the quadrant!
2942 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2943 for ns.x in range(QUADSIZE):
2944 for ns.y in range(QUADSIZE):
2945 if game.quad[ns.x][ns.y]==IHSTAR:
2952 prouts(_("***RED ALERT! RED ALERT!"))
2954 prout(_("***Incipient supernova detected at Sector %s") % ns)
2955 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2956 proutn(_("Emergency override attempts t"))
2957 prouts("***************")
2962 # destroy any Klingons in supernovaed quadrant
2963 kldead = game.state.galaxy[nq.x][nq.y].klingons
2964 game.state.galaxy[nq.x][nq.y].klingons = 0
2965 if nq == game.state.kscmdr:
2966 # did in the Supercommander!
2967 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2971 if game.state.remcom:
2972 maxloop = game.state.remcom
2973 for l in range(maxloop):
2974 if game.state.kcmdr[l] == nq:
2975 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
2976 invalidate(game.state.kcmdr[game.state.remcom])
2977 game.state.remcom -= 1
2979 if game.state.remcom==0:
2982 game.state.remkl -= kldead
2983 # destroy Romulans and planets in supernovaed quadrant
2984 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
2985 game.state.galaxy[nq.x][nq.y].romulans = 0
2986 game.state.nromrem -= nrmdead
2988 for loop in range(game.inplan):
2989 if game.state.planets[loop].w == nq:
2990 game.state.planets[loop].pclass = "destroyed"
2992 # Destroy any base in supernovaed quadrant
2993 if game.state.rembase:
2994 maxloop = game.state.rembase
2995 for loop in range(maxloop):
2996 if game.state.baseq[loop] == nq:
2997 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
2998 invalidate(game.state.baseq[game.state.rembase])
2999 game.state.rembase -= 1
3001 # If starship caused supernova, tally up destruction
3003 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3004 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3005 game.state.nplankl += npdead
3006 # mark supernova in galaxy and in star chart
3007 if game.quadrant == nq or communicating():
3008 game.state.galaxy[nq.x][nq.y].supernova = True
3009 # If supernova destroys last Klingons give special message
3010 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3013 prout(_("Lucky you!"))
3014 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3017 # if some Klingons remain, continue or die in supernova
3022 # Code from finish.c ends here.
3025 # self-destruct maneuver
3026 # Finish with a BANG!
3028 if damaged(DCOMPTR):
3029 prout(_("Computer damaged; cannot execute destruct sequence."))
3031 prouts(_("---WORKING---")); skip(1)
3032 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3033 prouts(" 10"); skip(1)
3034 prouts(" 9"); skip(1)
3035 prouts(" 8"); skip(1)
3036 prouts(" 7"); skip(1)
3037 prouts(" 6"); skip(1)
3039 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3041 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3043 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3047 if game.passwd != citem:
3048 prouts(_("PASSWORD-REJECTED;"))
3050 prouts(_("CONTINUITY-EFFECTED"))
3053 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3054 prouts(" 5"); skip(1)
3055 prouts(" 4"); skip(1)
3056 prouts(" 3"); skip(1)
3057 prouts(" 2"); skip(1)
3058 prouts(" 1"); skip(1)
3060 prouts(_("GOODBYE-CRUEL-WORLD"))
3068 prouts(_("********* Entropy of "))
3070 prouts(_(" maximized *********"))
3074 if game.nenhere != 0:
3075 whammo = 25.0 * game.energy
3077 while l <= game.nenhere:
3078 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3079 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3084 "Compute our rate of kils over time."
3085 elapsed = game.state.date - game.indate
3086 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3089 starting = (game.inkling + game.incom + game.inscom)
3090 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3091 return (starting - remaining)/elapsed
3095 badpt = 5.0*game.state.starkl + \
3097 10.0*game.state.nplankl + \
3098 300*game.state.nworldkl + \
3100 100.0*game.state.basekl +\
3102 if game.ship == IHF:
3104 elif game.ship == None:
3109 # end the game, with appropriate notfications
3113 prout(_("It is stardate %.1f.") % game.state.date)
3115 if ifin == FWON: # Game has been won
3116 if game.state.nromrem != 0:
3117 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3120 prout(_("You have smashed the Klingon invasion fleet and saved"))
3121 prout(_("the Federation."))
3126 badpt = 0.0 # Close enough!
3127 # killsPerDate >= RateMax
3128 if game.state.date-game.indate < 5.0 or \
3129 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3131 prout(_("In fact, you have done so well that Starfleet Command"))
3132 if game.skill == SKILL_NOVICE:
3133 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3134 elif game.skill == SKILL_FAIR:
3135 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3136 elif game.skill == SKILL_GOOD:
3137 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3138 elif game.skill == SKILL_EXPERT:
3139 prout(_("promotes you to Commodore Emeritus."))
3141 prout(_("Now that you think you're really good, try playing"))
3142 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3143 elif game.skill == SKILL_EMERITUS:
3145 proutn(_("Computer- "))
3146 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3148 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3150 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3152 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3154 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3156 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3158 prout(_("Now you can retire and write your own Star Trek game!"))
3160 elif game.skill >= SKILL_EXPERT:
3161 if game.thawed and not idebug:
3162 prout(_("You cannot get a citation, so..."))
3164 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3168 # Only grant long life if alive (original didn't!)
3170 prout(_("LIVE LONG AND PROSPER."))
3175 elif ifin == FDEPLETE: # Federation Resources Depleted
3176 prout(_("Your time has run out and the Federation has been"))
3177 prout(_("conquered. Your starship is now Klingon property,"))
3178 prout(_("and you are put on trial as a war criminal. On the"))
3179 proutn(_("basis of your record, you are "))
3180 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3181 prout(_("acquitted."))
3183 prout(_("LIVE LONG AND PROSPER."))
3185 prout(_("found guilty and"))
3186 prout(_("sentenced to death by slow torture."))
3190 elif ifin == FLIFESUP:
3191 prout(_("Your life support reserves have run out, and"))
3192 prout(_("you die of thirst, starvation, and asphyxiation."))
3193 prout(_("Your starship is a derelict in space."))
3195 prout(_("Your energy supply is exhausted."))
3197 prout(_("Your starship is a derelict in space."))
3198 elif ifin == FBATTLE:
3201 prout(_(" has been destroyed in battle."))
3203 prout(_("Dulce et decorum est pro patria mori."))
3205 prout(_("You have made three attempts to cross the negative energy"))
3206 prout(_("barrier which surrounds the galaxy."))
3208 prout(_("Your navigation is abominable."))
3211 prout(_("Your starship has been destroyed by a nova."))
3212 prout(_("That was a great shot."))
3214 elif ifin == FSNOVAED:
3217 prout(_(" has been fried by a supernova."))
3218 prout(_("...Not even cinders remain..."))
3219 elif ifin == FABANDN:
3220 prout(_("You have been captured by the Klingons. If you still"))
3221 prout(_("had a starbase to be returned to, you would have been"))
3222 prout(_("repatriated and given another chance. Since you have"))
3223 prout(_("no starbases, you will be mercilessly tortured to death."))
3224 elif ifin == FDILITHIUM:
3225 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3226 elif ifin == FMATERIALIZE:
3227 prout(_("Starbase was unable to re-materialize your starship."))
3228 prout(_("Sic transit gloria mundi"))
3229 elif ifin == FPHASER:
3232 prout(_(" has been cremated by its own phasers."))
3234 prout(_("You and your landing party have been"))
3235 prout(_("converted to energy, disipating through space."))
3236 elif ifin == FMINING:
3237 prout(_("You are left with your landing party on"))
3238 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3240 prout(_("They are very fond of \"Captain Kirk\" soup."))
3242 proutn(_("Without your leadership, the "))
3244 prout(_(" is destroyed."))
3245 elif ifin == FDPLANET:
3246 prout(_("You and your mining party perish."))
3248 prout(_("That was a great shot."))
3251 prout(_("The Galileo is instantly annihilated by the supernova."))
3252 prout(_("You and your mining party are atomized."))
3254 proutn(_("Mr. Spock takes command of the "))
3257 prout(_("joins the Romulans, reigning terror on the Federation."))
3258 elif ifin == FPNOVA:
3259 prout(_("You and your mining party are atomized."))
3261 proutn(_("Mr. Spock takes command of the "))
3264 prout(_("joins the Romulans, reigning terror on the Federation."))
3265 elif ifin == FSTRACTOR:
3266 prout(_("The shuttle craft Galileo is also caught,"))
3267 prout(_("and breaks up under the strain."))
3269 prout(_("Your debris is scattered for millions of miles."))
3270 proutn(_("Without your leadership, the "))
3272 prout(_(" is destroyed."))
3274 prout(_("The mutants attack and kill Spock."))
3275 prout(_("Your ship is captured by Klingons, and"))
3276 prout(_("your crew is put on display in a Klingon zoo."))
3277 elif ifin == FTRIBBLE:
3278 prout(_("Tribbles consume all remaining water,"))
3279 prout(_("food, and oxygen on your ship."))
3281 prout(_("You die of thirst, starvation, and asphyxiation."))
3282 prout(_("Your starship is a derelict in space."))
3284 prout(_("Your ship is drawn to the center of the black hole."))
3285 prout(_("You are crushed into extremely dense matter."))
3287 prout(_("Your last crew member has died."))
3288 if game.ship == IHF:
3290 elif game.ship == IHE:
3293 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3294 goodies = game.state.remres/game.inresor
3295 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3296 if goodies/baddies >= randreal(1.0, 1.5):
3297 prout(_("As a result of your actions, a treaty with the Klingon"))
3298 prout(_("Empire has been signed. The terms of the treaty are"))
3299 if goodies/baddies >= randreal(3.0):
3300 prout(_("favorable to the Federation."))
3302 prout(_("Congratulations!"))
3304 prout(_("highly unfavorable to the Federation."))
3306 prout(_("The Federation will be destroyed."))
3308 prout(_("Since you took the last Klingon with you, you are a"))
3309 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3310 prout(_("statue in your memory. Rest in peace, and try not"))
3311 prout(_("to think about pigeons."))
3316 # compute player's score
3317 timused = game.state.date - game.indate
3319 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3321 perdate = killrate()
3322 ithperd = 500*perdate + 0.5
3325 iwon = 100*game.skill
3326 if game.ship == IHE:
3328 elif game.ship == IHF:
3332 if not game.gamewon:
3333 game.state.nromrem = 0 # None captured if no win
3334 iscore = 10*(game.inkling - game.state.remkl) \
3335 + 50*(game.incom - game.state.remcom) \
3337 + 20*(game.inrom - game.state.nromrem) \
3338 + 200*(game.inscom - game.state.nscrem) \
3339 - game.state.nromrem \
3344 prout(_("Your score --"))
3345 if game.inrom - game.state.nromrem:
3346 prout(_("%6d Romulans destroyed %5d") %
3347 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3348 if game.state.nromrem:
3349 prout(_("%6d Romulans captured %5d") %
3350 (game.state.nromrem, game.state.nromrem))
3351 if game.inkling - game.state.remkl:
3352 prout(_("%6d ordinary Klingons destroyed %5d") %
3353 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3354 if game.incom - game.state.remcom:
3355 prout(_("%6d Klingon commanders destroyed %5d") %
3356 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3357 if game.inscom - game.state.nscrem:
3358 prout(_("%6d Super-Commander destroyed %5d") %
3359 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3361 prout(_("%6.2f Klingons per stardate %5d") %
3363 if game.state.starkl:
3364 prout(_("%6d stars destroyed by your action %5d") %
3365 (game.state.starkl, -5*game.state.starkl))
3366 if game.state.nplankl:
3367 prout(_("%6d planets destroyed by your action %5d") %
3368 (game.state.nplankl, -10*game.state.nplankl))
3369 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3370 prout(_("%6d inhabited planets destroyed by your action %5d") %
3371 (game.state.nplankl, -300*game.state.nworldkl))
3372 if game.state.basekl:
3373 prout(_("%6d bases destroyed by your action %5d") %
3374 (game.state.basekl, -100*game.state.basekl))
3376 prout(_("%6d calls for help from starbase %5d") %
3377 (game.nhelp, -45*game.nhelp))
3379 prout(_("%6d casualties incurred %5d") %
3380 (game.casual, -game.casual))
3382 prout(_("%6d crew abandoned in space %5d") %
3383 (game.abandoned, -3*game.abandoned))
3385 prout(_("%6d ship(s) lost or destroyed %5d") %
3386 (klship, -100*klship))
3388 prout(_("Penalty for getting yourself killed -200"))
3390 proutn(_("Bonus for winning "))
3391 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3392 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3393 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3394 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3395 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3396 prout(" %5d" % iwon)
3398 prout(_("TOTAL SCORE %5d") % iscore)
3401 # emit winner's commemmorative plaque
3404 proutn(_("File or device name for your plaque: "))
3407 fp = open(winner, "w")
3410 prout(_("Invalid name."))
3412 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3414 # The 38 below must be 64 for 132-column paper
3415 nskip = 38 - len(winner)/2
3416 fp.write("\n\n\n\n")
3417 # --------DRAW ENTERPRISE PICTURE.
3418 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3419 fp.write(" EEE E : : : E\n" )
3420 fp.write(" EE EEE E : : NCC-1701 : E\n")
3421 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3422 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3423 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3424 fp.write(" EEEEEEE EEEEE E E E E\n")
3425 fp.write(" EEE E E E E\n")
3426 fp.write(" E E E E\n")
3427 fp.write(" EEEEEEEEEEEEE E E\n")
3428 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3429 fp.write(" :E : EEEE E\n")
3430 fp.write(" .-E -:----- E\n")
3431 fp.write(" :E : E\n")
3432 fp.write(" EE : EEEEEEEE\n")
3433 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3435 fp.write(_(" U. S. S. ENTERPRISE\n"))
3436 fp.write("\n\n\n\n")
3437 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3439 fp.write(_(" Starfleet Command bestows to you\n"))
3441 fp.write("%*s%s\n\n" % (nskip, "", winner))
3442 fp.write(_(" the rank of\n\n"))
3443 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3445 if game.skill == SKILL_EXPERT:
3446 fp.write(_(" Expert level\n\n"))
3447 elif game.skill == SKILL_EMERITUS:
3448 fp.write(_("Emeritus level\n\n"))
3450 fp.write(_(" Cheat level\n\n"))
3451 timestring = ctime()
3452 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3453 (timestring+4, timestring+20, timestring+11))
3454 fp.write(_(" Your score: %d\n\n") % iscore)
3455 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3458 # Code from io.c begins here
3460 rows = linecount = 0 # for paging
3463 fullscreen_window = None
3464 srscan_window = None
3465 report_window = None
3466 status_window = None
3467 lrscan_window = None
3468 message_window = None
3469 prompt_window = None
3473 "wrap up, either normally or due to signal"
3474 if game.options & OPTION_CURSES:
3481 sys.stdout.write('\n')
3487 #setlocale(LC_ALL, "")
3488 #bindtextdomain(PACKAGE, LOCALEDIR)
3489 #textdomain(PACKAGE)
3490 if atexit.register(outro):
3491 sys.stderr.write("Unable to register outro(), exiting...\n")
3493 if not (game.options & OPTION_CURSES):
3494 ln_env = os.getenv("LINES")
3500 stdscr = curses.initscr()
3505 curses.start_color()
3506 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3507 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3508 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3509 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3510 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3511 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3512 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3513 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3515 global fullscreen_window, srscan_window, report_window, status_window
3516 global lrscan_window, message_window, prompt_window
3517 fullscreen_window = stdscr
3518 srscan_window = curses.newwin(12, 25, 0, 0)
3519 report_window = curses.newwin(11, 0, 1, 25)
3520 status_window = curses.newwin(10, 0, 1, 39)
3521 lrscan_window = curses.newwin(5, 0, 0, 64)
3522 message_window = curses.newwin(0, 0, 12, 0)
3523 prompt_window = curses.newwin(1, 0, rows-2, 0)
3524 message_window.scrollok(True)
3525 setwnd(fullscreen_window)
3529 "wait for user action -- OK to do nothing if on a TTY"
3530 if game.options & OPTION_CURSES:
3535 if game.skill > SKILL_FAIR:
3536 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3538 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3542 if game.skill > SKILL_FAIR:
3543 prompt = _("[CONTINUE?]")
3545 prompt = _("[PRESS ENTER TO CONTINUE]")
3547 if game.options & OPTION_CURSES:
3549 setwnd(prompt_window)
3550 prompt_window.wclear()
3551 prompt_window.addstr(prompt)
3552 prompt_window.getstr()
3553 prompt_window.clear()
3554 prompt_window.refresh()
3555 setwnd(message_window)
3558 sys.stdout.write('\n')
3561 for j in range(rows):
3562 sys.stdout.write('\n')
3566 "Skip i lines. Pause game if this would cause a scrolling event."
3567 for dummy in range(i):
3568 if game.options & OPTION_CURSES:
3569 (y, x) = curwnd.getyx()
3570 (my, mx) = curwnd.getmaxyx()
3571 if curwnd == message_window and y >= my - 3:
3579 if rows and linecount >= rows:
3582 sys.stdout.write('\n')
3585 "Utter a line with no following line feed."
3586 if game.options & OPTION_CURSES:
3590 sys.stdout.write(line)
3600 if not replayfp or replayfp.closed: # Don't slow down replays
3603 if game.options & OPTION_CURSES:
3607 if not replayfp or replayfp.closed:
3611 "Get a line of input."
3612 if game.options & OPTION_CURSES:
3613 line = curwnd.getstr() + "\n"
3616 if replayfp and not replayfp.closed:
3618 line = replayfp.readline()
3621 prout("*** Replay finished")
3624 elif line[0] != "#":
3627 line = raw_input() + "\n"
3633 "Change windows -- OK for this to be a no-op in tty mode."
3635 if game.options & OPTION_CURSES:
3637 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3640 "Clear to end of line -- can be a no-op in tty mode"
3641 if game.options & OPTION_CURSES:
3646 "Clear screen -- can be a no-op in tty mode."
3648 if game.options & OPTION_CURSES:
3654 def textcolor(color):
3655 "Set the current text color"
3656 if game.options & OPTION_CURSES:
3657 if color == DEFAULT:
3659 elif color == BLACK:
3660 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3662 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3663 elif color == GREEN:
3664 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3666 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3668 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3669 elif color == MAGENTA:
3670 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3671 elif color == BROWN:
3672 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3673 elif color == LIGHTGRAY:
3674 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3675 elif color == DARKGRAY:
3676 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3677 elif color == LIGHTBLUE:
3678 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3679 elif color == LIGHTGREEN:
3680 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3681 elif color == LIGHTCYAN:
3682 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3683 elif color == LIGHTRED:
3684 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3685 elif color == LIGHTMAGENTA:
3686 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3687 elif color == YELLOW:
3688 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3689 elif color == WHITE:
3690 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3693 "Set highlight video, if this is reasonable."
3694 if game.options & OPTION_CURSES:
3695 curwnd.attron(curses.A_REVERSE)
3698 # Things past this point have policy implications.
3702 "Hook to be called after moving to redraw maps."
3703 if game.options & OPTION_CURSES:
3706 setwnd(srscan_window)
3710 setwnd(status_window)
3711 status_window.clear()
3712 status_window.move(0, 0)
3713 setwnd(report_window)
3714 report_window.clear()
3715 report_window.move(0, 0)
3717 setwnd(lrscan_window)
3718 lrscan_window.clear()
3719 lrscan_window.move(0, 0)
3720 lrscan(silent=False)
3722 def put_srscan_sym(w, sym):
3723 "Emit symbol for short-range scan."
3724 srscan_window.move(w.x+1, w.y*2+2)
3725 srscan_window.addch(sym)
3726 srscan_window.refresh()
3729 "Enemy fall down, go boom."
3730 if game.options & OPTION_CURSES:
3732 setwnd(srscan_window)
3733 srscan_window.attron(curses.A_REVERSE)
3734 put_srscan_sym(w, game.quad[w.x][w.y])
3738 srscan_window.attroff(curses.A_REVERSE)
3739 put_srscan_sym(w, game.quad[w.x][w.y])
3740 curses.delay_output(500)
3741 setwnd(message_window)
3744 "Sound and visual effects for teleportation."
3745 if game.options & OPTION_CURSES:
3747 setwnd(message_window)
3749 prouts(" . . . . . ")
3750 if game.options & OPTION_CURSES:
3751 #curses.delay_output(1000)
3755 def tracktorpedo(w, l, i, n, iquad):
3756 "Torpedo-track animation."
3757 if not game.options & OPTION_CURSES:
3761 proutn(_("Track for torpedo number %d- ") % i)
3764 proutn(_("Torpedo track- "))
3767 proutn("%d - %d " % (w.x, w.y))
3769 if not damaged(DSRSENS) or game.condition=="docked":
3770 if i != 1 and l == 1:
3773 if (iquad==IHDOT) or (iquad==IHBLANK):
3774 put_srscan_sym(w, '+')
3778 put_srscan_sym(w, iquad)
3780 curwnd.attron(curses.A_REVERSE)
3781 put_srscan_sym(w, iquad)
3785 curwnd.attroff(curses.A_REVERSE)
3786 put_srscan_sym(w, iquad)
3788 proutn("%d - %d " % (w.x, w.y))
3791 "Display the current galaxy chart."
3792 if game.options & OPTION_CURSES:
3793 setwnd(message_window)
3794 message_window.clear()
3796 if game.options & OPTION_TTY:
3801 def prstat(txt, data):
3803 if game.options & OPTION_CURSES:
3805 setwnd(status_window)
3807 proutn(" " * (NSYM - len(txt)))
3810 if game.options & OPTION_CURSES:
3811 setwnd(report_window)
3813 # Code from moving.c begins here
3815 def imove(novapush):
3816 # movement execution for warp, impulse, supernova, and tractor-beam events
3817 w = coord(); final = coord()
3820 def no_quad_change():
3821 # No quadrant change -- compute new average enemy distances
3822 game.quad[game.sector.x][game.sector.y] = game.ship
3824 for m in range(game.nenhere):
3825 finald = distance(w, game.enemies[m].kloc)
3826 game.enemies[m].kavgd = 0.5 * (finald+game.enemies[m].kdist)
3827 game.enemies[m].kdist = finald
3828 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3829 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3831 for m in range(game.nenhere):
3832 game.enemies[m].kavgd = game.enemies[m].kdist
3835 setwnd(message_window)
3838 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3839 game.inorbit = False
3840 angle = ((15.0 - game.direc) * 0.5235988)
3841 deltax = -math.sin(angle)
3842 deltay = math.cos(angle)
3843 if math.fabs(deltax) > math.fabs(deltay):
3844 bigger = math.fabs(deltax)
3846 bigger = math.fabs(deltay)
3849 # If tractor beam is to occur, don't move full distance
3850 if game.state.date+game.optime >= scheduled(FTBEAM):
3852 game.condition = "red"
3853 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3854 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3855 # Move within the quadrant
3856 game.quad[game.sector.x][game.sector.y] = IHDOT
3859 n = int(10.0*game.dist*bigger+0.5)
3861 for m in range(1, n+1):
3866 if not VALID_SECTOR(w.x, w.y):
3867 # Leaving quadrant -- allow final enemy attack
3868 # Don't do it if being pushed by Nova
3869 if game.nenhere != 0 and not novapush:
3871 for m in range(game.nenhere):
3872 finald = distance(w, game.enemies[m].kloc)
3873 game.enemies[m].kavgd = 0.5 * (finald + game.enemies[m].kdist)
3875 # Stas Sergeev added the condition
3876 # that attacks only happen if Klingons
3877 # are present and your skill is good.
3879 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3883 # compute final position -- new quadrant and sector
3884 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3885 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3886 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3887 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3888 # check for edge of galaxy
3898 if w.x >= GALSIZE*QUADSIZE:
3899 w.x = (GALSIZE*QUADSIZE*2) - w.x
3901 if w.y >= GALSIZE*QUADSIZE:
3902 w.y = (GALSIZE*QUADSIZE*2) - w.y
3910 if game.nkinks == 3:
3911 # Three strikes -- you're out!
3915 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3916 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3917 prout(_("YOU WILL BE DESTROYED."))
3918 # Compute final position in new quadrant
3919 if trbeam: # Don't bother if we are to be beamed
3921 game.quadrant.x = w.x/QUADSIZE
3922 game.quadrant.y = w.y/QUADSIZE
3923 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3924 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3926 prout(_("Entering Quadrant %s.") % game.quadrant)
3927 game.quad[game.sector.x][game.sector.y] = game.ship
3929 if game.skill>SKILL_NOVICE:
3932 iquad = game.quad[w.x][w.y]
3934 # object encountered in flight path
3935 stopegy = 50.0*game.dist/game.optime
3936 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3937 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3939 for enemy in game.enemies:
3940 if enemy.kloc == game.sector:
3942 collision(rammed=False, enemy=enemy)
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: