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 import os,sys,math,curses,time,atexit,readline,cPickle,random,getopt,copy
178 SSTDOC = "/usr/share/doc/sst/sst.doc"
181 # Stub to be replaced
182 def _(str): return str
186 NINHAB = (GALSIZE * GALSIZE / 2)
188 PLNETMAX = (NINHAB + MAXUNINHAB)
191 BASEMAX = (GALSIZE * GALSIZE / 12)
194 FULLCREW = 428 # BSD Trek was 387, that's wrong
197 # These functions hide the difference between 0-origin and 1-origin addressing.
198 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
199 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
201 def square(i): return ((i)*(i))
202 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
203 def invalidate(w): w.x = w.y = 0
204 def is_valid(w): return (w.x != 0 and w.y != 0)
206 # How to represent features
231 def __init__(self, x=None, y=None):
234 def invalidate(self):
235 self.x = self.y = None
237 return self.x != None and self.y != None
238 def __eq__(self, other):
239 return other != None and self.x == other.y and self.x == other.y
240 def __add__(self, other):
241 return coord(self.x+self.x, self.y+self.y)
242 def __sub__(self, other):
243 return coord(self.x-self.x, self.y-self.y)
244 def distance(self, other):
245 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
251 s.x = self.x / abs(self.x)
255 s.y = self.y / abs(self.y)
260 return "%s - %s" % (self.x+1, self.y+1)
265 self.name = None # string-valued if inhabited
266 self.w = coord() # quadrant located
267 self.pclass = None # could be ""M", "N", "O", or "destroyed"
268 self.crystals = "absent"# could be "mined", "present", "absent"
269 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
270 self.inhabited = False # is it inhabites?
281 self.supernova = None
283 self.status = None # Could be "secure", "distressed", "enslaved"
291 def fill2d(size, fillfun):
292 "Fill an empty list in 2D."
294 for i in range(size):
296 for j in range(size):
297 lst[i].append(fillfun(i, j))
302 self.snap = False # snapshot taken
303 self.crew = 0 # crew complement
304 self.remkl = 0 # remaining klingons
305 self.remcom = 0 # remaining commanders
306 self.nscrem = 0 # remaining super commanders
307 self.rembase = 0 # remaining bases
308 self.starkl = 0 # destroyed stars
309 self.basekl = 0 # destroyed bases
310 self.nromrem = 0 # Romulans remaining
311 self.nplankl = 0 # destroyed uninhabited planets
312 self.nworldkl = 0 # destroyed inhabited planets
313 self.planets = [] # Planet information
314 self.date = 0.0 # stardate
315 self.remres = 0 # remaining resources
316 self.remtime = 0 # remaining time
317 self.baseq = [] # Base quadrant coordinates
318 for i in range(BASEMAX):
319 self.baseq.append(coord())
320 self.kcmdr = [] # Commander quadrant coordinates
321 for i in range(QUADSIZE):
322 self.kcmdr.append(coord())
323 self.kscmdr = coord() # Supercommander quadrant coordinates
324 # the galaxy (subscript 0 not used)
325 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
326 # the starchart (subscript 0 not used)
327 self.chart = fill2d(GALSIZE, lambda i, j: page())
331 self.date = None # A real number
332 self.quadrant = None # A coord structure
335 OPTION_ALL = 0xffffffff
336 OPTION_TTY = 0x00000001 # old interface
337 OPTION_CURSES = 0x00000002 # new interface
338 OPTION_IOMODES = 0x00000003 # cover both interfaces
339 OPTION_PLANETS = 0x00000004 # planets and mining
340 OPTION_THOLIAN = 0x00000008 # Tholians and their webs
341 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back
342 OPTION_PROBE = 0x00000020 # deep-space probes
343 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
344 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise
345 OPTION_MVBADDY = 0x00000100 # more enemies can move
346 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you
347 OPTION_BASE = 0x00000400 # bases have good shields
348 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds
349 OPTION_PLAIN = 0x01000000 # user chose plain game
350 OPTION_ALMY = 0x02000000 # user chose Almy variant
369 NDEVICES= 16 # Number of devices
378 def damaged(dev): return (game.damage[dev] != 0.0)
379 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
381 # Define future events
382 FSPY = 0 # Spy event happens always (no future[] entry)
383 # can cause SC to tractor beam Enterprise
384 FSNOVA = 1 # Supernova
385 FTBEAM = 2 # Commander tractor beams Enterprise
386 FSNAP = 3 # Snapshot for time warp
387 FBATTAK = 4 # Commander attacks base
388 FCDBAS = 5 # Commander destroys base
389 FSCMOVE = 6 # Supercommander moves (might attack base)
390 FSCDBAS = 7 # Supercommander destroys base
391 FDSPROB = 8 # Move deep space probe
392 FDISTR = 9 # Emit distress call from an inhabited world
393 FENSLV = 10 # Inhabited word is enslaved */
394 FREPRO = 11 # Klingons build a ship in an enslaved system
398 # abstract out the event handling -- underlying data structures will change
399 # when we implement stateful events
401 def findevent(evtype): return game.future[evtype]
405 self.options = None # Game options
406 self.state = snapshot() # A snapshot structure
407 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
408 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
409 self.kpower = fill2d(QUADSIZE, lambda i, j: 0.0) # enemy energy levels
410 self.kdist = fill2d(QUADSIZE, lambda i, j: 0.0) # enemy distances
411 self.kavgd = fill2d(QUADSIZE, lambda i, j: 0.0) # average distances
412 self.damage = [0.0] * NDEVICES # damage encountered
413 self.future = [] # future events
414 for i in range(NEVENTS):
415 self.future.append(event())
416 self.passwd = None; # Self Destruct password
417 self.ks = fill2d(QUADSIZE, lambda i, j: coord()) # enemy sector locations
418 self.quadrant = None # where we are in the large
419 self.sector = None # where we are in the small
420 self.tholian = None # coordinates of Tholian
421 self.base = None # position of base in current quadrant
422 self.battle = None # base coordinates being attacked
423 self.plnet = None # location of planet in quadrant
424 self.probec = None # current probe quadrant
425 self.gamewon = False # Finished!
426 self.ididit = False # action taken -- allows enemy to attack
427 self.alive = False # we are alive (not killed)
428 self.justin = False # just entered quadrant
429 self.shldup = False # shields are up
430 self.shldchg = False # shield is changing (affects efficiency)
431 self.comhere = False # commander here
432 self.ishere = False # super-commander in quadrant
433 self.iscate = False # super commander is here
434 self.ientesc = False # attempted escape from supercommander
435 self.resting = False # rest time
436 self.icraft = False # Kirk in Galileo
437 self.landed = False # party on planet (true), on ship (false)
438 self.alldone = False # game is now finished
439 self.neutz = False # Romulan Neutral Zone
440 self.isarmed = False # probe is armed
441 self.inorbit = False # orbiting a planet
442 self.imine = False # mining
443 self.icrystl = False # dilithium crystals aboard
444 self.iseenit = False # seen base attack report
445 self.thawed = False # thawed game
446 self.condition = None # "green", "yellow", "red", "docked", "dead"
447 self.iscraft = None # "onship", "offship", "removed"
448 self.skill = None # Player skill level
449 self.inkling = 0 # initial number of klingons
450 self.inbase = 0 # initial number of bases
451 self.incom = 0 # initial number of commanders
452 self.inscom = 0 # initial number of commanders
453 self.inrom = 0 # initial number of commanders
454 self.instar = 0 # initial stars
455 self.intorps = 0 # initial/max torpedoes
456 self.torps = 0 # number of torpedoes
457 self.ship = 0 # ship type -- 'E' is Enterprise
458 self.abandoned = 0 # count of crew abandoned in space
459 self.length = 0 # length of game
460 self.klhere = 0 # klingons here
461 self.casual = 0 # causalties
462 self.nhelp = 0 # calls for help
463 self.nkinks = 0 # count of energy-barrier crossings
464 self.iplnet = None # planet # in quadrant
465 self.inplan = 0 # initial planets
466 self.nenhere = 0 # number of enemies in quadrant
467 self.irhere = 0 # Romulans in quadrant
468 self.isatb = 0 # =1 if super commander is attacking base
469 self.tourn = 0 # tournament number
470 self.proben = 0 # number of moves for probe
471 self.nprobes = 0 # number of probes available
472 self.inresor = 0.0 # initial resources
473 self.intime = 0.0 # initial time
474 self.inenrg = 0.0 # initial/max energy
475 self.inshld = 0.0 # initial/max shield
476 self.inlsr = 0.0 # initial life support resources
477 self.indate = 0.0 # initial date
478 self.energy = 0.0 # energy level
479 self.shield = 0.0 # shield level
480 self.warpfac = 0.0 # warp speed
481 self.wfacsq = 0.0 # squared warp factor
482 self.lsupres = 0.0 # life support reserves
483 self.dist = 0.0 # movement distance
484 self.direc = 0.0 # movement direction
485 self.optime = 0.0 # time taken by current operation
486 self.docfac = 0.0 # repair factor when docking (constant?)
487 self.damfac = 0.0 # damage factor
488 self.lastchart = 0.0 # time star chart was last updated
489 self.cryprob = 0.0 # probability that crystal will work
490 self.probex = 0.0 # location of probe
492 self.probeinx = 0.0 # probe x,y increment
493 self.probeiny = 0.0 #
494 self.height = 0.0 # height of orbit around planet
496 # Stas thinks this should be (C expression):
497 # game.state.remkl + game.state.remcom > 0 ?
498 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
499 # He says the existing expression is prone to divide-by-zero errors
500 # after killing the last klingon when score is shown -- perhaps also
501 # if the only remaining klingon is SCOM.
502 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
503 # From enumerated type 'feature'
524 # From enumerated type 'FINTYPE'
548 # From enumerated type 'COLORS'
567 # Code from ai.c begins here
569 def tryexit(look, ienm, loccom, irun):
570 # a bad guy attempts to bug out
572 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
573 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
574 if not VALID_QUADRANT(iq.x,iq.y) or \
575 game.state.galaxy[iq.x][iq.y].supernova or \
576 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
577 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
579 return False; # Romulans cannot escape!
581 # avoid intruding on another commander's territory
583 for n in range(game.state.remcom):
584 if game.state.kcmdr[n] == iq:
586 # refuse to leave if currently attacking starbase
587 if game.battle == game.quadrant:
589 # don't leave if over 1000 units of energy
590 if game.kpower[loccom] > 1000.0:
592 # print escape message and move out of quadrant.
593 # we know this if either short or long range sensors are working
594 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
595 game.condition == docked:
596 crmena(True, ienm, "sector", game.ks[loccom])
597 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
598 # handle local matters related to escape
599 game.quad[game.ks[loccom].x][game.ks[loccom].y] = IHDOT
600 game.ks[loccom] = game.ks[game.nenhere]
601 game.kavgd[loccom] = game.kavgd[game.nenhere]
602 game.kpower[loccom] = game.kpower[game.nenhere]
603 game.kdist[loccom] = game.kdist[game.nenhere]
606 if game.condition != docked:
608 # Handle global matters related to escape
609 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
610 game.state.galaxy[iq.x][iq.y].klingons += 1
616 schedule(FSCMOVE, 0.2777)
620 for n in range(game.state.remcom):
621 if game.state.kcmdr[n] == game.quadrant:
622 game.state.kcmdr[n]=iq
625 return True; # success
628 # The bad-guy movement algorithm:
630 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
631 # If both are operating full strength, force is 1000. If both are damaged,
632 # force is -1000. Having shields down subtracts an additional 1000.
634 # 2. Enemy has forces equal to the energy of the attacker plus
635 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
636 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
638 # Attacker Initial energy levels (nominal):
639 # Klingon Romulan Commander Super-Commander
640 # Novice 400 700 1200
642 # Good 450 800 1300 1750
643 # Expert 475 850 1350 1875
644 # Emeritus 500 900 1400 2000
645 # VARIANCE 75 200 200 200
647 # Enemy vessels only move prior to their attack. In Novice - Good games
648 # only commanders move. In Expert games, all enemy vessels move if there
649 # is a commander present. In Emeritus games all enemy vessels move.
651 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
652 # forces are 1000 greater than Enterprise.
654 # Agressive action on average cuts the distance between the ship and
655 # the enemy to 1/4 the original.
657 # 4. At lower energy advantage, movement units are proportional to the
658 # advantage with a 650 advantage being to hold ground, 800 to move forward
659 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
661 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
662 # retreat, especially at high skill levels.
664 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
667 def movebaddy(com, loccom, ienm):
668 # tactical movement for the bad guys
669 next = coord(); look = coord()
671 # This should probably be just game.comhere + game.ishere
672 if game.skill >= SKILL_EXPERT:
673 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
675 nbaddys = game.comhere + game.ishere
677 dist1 = game.kdist[loccom]
678 mdist = int(dist1 + 0.5); # Nearest integer distance
680 # If SC, check with spy to see if should hi-tail it
682 (game.kpower[loccom] <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
686 # decide whether to advance, retreat, or hold position
687 forces = game.kpower[loccom]+100.0*game.nenhere+400*(nbaddys-1)
689 forces += 1000; # Good for enemy if shield is down!
690 if not damaged(DPHASER) or not damaged(DPHOTON):
691 if damaged(DPHASER): # phasers damaged
694 forces -= 0.2*(game.energy - 2500.0)
695 if damaged(DPHOTON): # photon torpedoes damaged
698 forces -= 50.0*game.torps
700 # phasers and photon tubes both out!
703 if forces <= 1000.0 and game.condition != "docked": # Typical situation
704 motion = ((forces+200.0*random.random())/150.0) - 5.0
706 if forces > 1000.0: # Very strong -- move in for kill
707 motion = (1.0-square(random.random()))*dist1 + 1.0
708 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
709 motion -= game.skill*(2.0-square(random.random()))
711 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
712 # don't move if no motion
715 # Limit motion according to skill
716 if abs(motion) > game.skill:
721 # calculate preferred number of steps
726 if motion > 0 and nsteps > mdist:
727 nsteps = mdist; # don't overshoot
728 if nsteps > QUADSIZE:
729 nsteps = QUADSIZE; # This shouldn't be necessary
731 nsteps = 1; # This shouldn't be necessary
733 proutn("NSTEPS = %d:" % nsteps)
734 # Compute preferred values of delta X and Y
735 mx = game.sector.x - com.x
736 my = game.sector.y - com.y
737 if 2.0 * abs(mx) < abs(my):
739 if 2.0 * abs(my) < abs(game.sector.x-com.x):
753 for ll in range(nsteps):
755 proutn(" %d" % (ll+1))
756 # Check if preferred position available
768 attempts = 0; # Settle mysterious hang problem
769 while attempts < 20 and not success:
771 if look.x < 0 or look.x >= QUADSIZE:
772 if motion < 0 and tryexit(look, ienm, loccom, irun):
774 if krawlx == mx or my == 0:
776 look.x = next.x + krawlx
778 elif look.y < 0 or look.y >= QUADSIZE:
779 if motion < 0 and tryexit(look, ienm, loccom, irun):
781 if krawly == my or mx == 0:
783 look.y = next.y + krawly
785 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
786 # See if we should ram ship
787 if game.quad[look.x][look.y] == game.ship and \
788 (ienm == IHC or ienm == IHS):
791 if krawlx != mx and my != 0:
792 look.x = next.x + krawlx
794 elif krawly != my and mx != 0:
795 look.y = next.y + krawly
798 break; # we have failed
810 # Put commander in place within same quadrant
811 game.quad[com.x][com.y] = IHDOT
812 game.quad[next.x][next.y] = ienm
815 game.ks[loccom] = next
816 game.kdist[loccom] = game.kavgd[loccom] = distance(game.sector, next)
817 if not damaged(DSRSENS) or game.condition == docked:
820 proutn(_(" from Sector %s") % com)
821 if game.kdist[loccom] < dist1:
822 proutn(_(" advances to "))
824 proutn(_(" retreats to "))
825 prout("Sector %s." % next)
828 # Klingon tactical movement
831 # Figure out which Klingon is the commander (or Supercommander)
834 for i in range(game.nenhere):
836 if game.quad[w.x][w.y] == IHC:
840 for i in range(game.nenhere):
842 if game.quad[w.x][w.y] == IHS:
845 # If skill level is high, move other Klingons and Romulans too!
846 # Move these last so they can base their actions on what the
848 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
849 for i in range(game.nenhere):
851 if game.quad[w.x][w.y] == IHK or game.quad[w.x][w.y] == IHR:
852 movebaddy(w, i, game.quad[w.x][w.y])
855 def movescom(iq, avoid):
856 # commander movement helper
857 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
858 game.state.galaxy[iq.x][iq.y].supernova or \
859 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
862 # Avoid quadrants with bases if we want to avoid Enterprise
863 for i in range(game.state.rembase):
864 if game.state.baseq[i] == iq:
866 if game.justin and not game.iscate:
869 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
870 game.state.kscmdr = iq
871 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
873 # SC has scooted, Remove him from current quadrant
879 for i in range(game.nenhere):
880 if game.quad[game.ks[i].x][game.ks[i].y] == IHS:
882 game.quad[game.ks[i].x][game.ks[i].y] = IHDOT
883 game.ks[i] = game.ks[game.nenhere]
884 game.kdist[i] = game.kdist[game.nenhere]
885 game.kavgd[i] = game.kavgd[game.nenhere]
886 game.kpower[i] = game.kpower[game.nenhere]
889 if game.condition!=docked:
892 # check for a helpful planet
893 for i in range(game.inplan):
894 if game.state.planets[i].w == game.state.kscmdr and \
895 game.state.planets[i].crystals == "present":
897 game.state.planets[i].pclass = "destroyed"
898 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
901 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
902 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
903 prout(_(" by the Super-commander.\""))
905 return False; # looks good!
907 def supercommander():
908 # move the Super Commander
909 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
912 prout("== SUPERCOMMANDER")
913 # Decide on being active or passive
914 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 \
915 (game.state.date-game.indate) < 3.0)
916 if not game.iscate and avoid:
917 # compute move away from Enterprise
918 idelta = game.state.kscmdr-game.quadrant
919 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
921 idelta.x = game.state.kscmdr.y-game.quadrant.y
922 idelta.y = game.quadrant.x-game.state.kscmdr.x
924 # compute distances to starbases
925 if game.state.rembase <= 0:
929 sc = game.state.kscmdr
930 for i in range(game.state.rembase):
931 basetbl.append((i, distance(game.state.baseq[i], sc)))
932 if game.state.rembase > 1:
933 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
934 # look for nearest base without a commander, no Enterprise, and
935 # without too many Klingons, and not already under attack.
936 ifindit = iwhichb = 0
937 for i2 in range(game.state.rembase):
938 i = basetbl[i2][0]; # bug in original had it not finding nearest
939 ibq = game.state.baseq[i]
940 if ibq == game.quadrant or ibq == game.battle or \
941 game.state.galaxy[ibq.x][ibq.y].supernova or \
942 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
944 # if there is a commander, and no other base is appropriate,
945 # we will take the one with the commander
946 for j in range(game.state.remcom):
947 if ibq == game.state.kcmdr[j] and ifindit!= 2:
951 if j > game.state.remcom: # no commander -- use this one
956 return; # Nothing suitable -- wait until next time
957 ibq = game.state.baseq[iwhichb]
958 # decide how to move toward base
959 idelta = ibq - game.state.kscmdr
960 # Maximum movement is 1 quadrant in either or both axes
961 idelta = idelta.sgn()
962 # try moving in both x and y directions
963 # there was what looked like a bug in the Almy C code here,
964 # but it might be this translation is just wrong.
965 iq = game.state.kscmdr + idelta
966 if movescom(iq, avoid):
967 # failed -- try some other maneuvers
968 if idelta.x==0 or idelta.y==0:
971 iq.y = game.state.kscmdr.y + 1
972 if movescom(iq, avoid):
973 iq.y = game.state.kscmdr.y - 1
976 iq.x = game.state.kscmdr.x + 1
977 if movescom(iq, avoid):
978 iq.x = game.state.kscmdr.x - 1
981 # try moving just in x or y
982 iq.y = game.state.kscmdr.y
983 if movescom(iq, avoid):
984 iq.y = game.state.kscmdr.y + idelta.y
985 iq.x = game.state.kscmdr.x
988 if game.state.rembase == 0:
991 for i in range(game.state.rembase):
992 ibq = game.state.baseq[i]
993 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
996 return; # no, don't attack base!
999 schedule(FSCDBAS, 1.0 +2.0*random.random())
1000 if is_scheduled(FCDBAS):
1001 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1002 if not communicating():
1003 return; # no warning
1006 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1007 % game.state.kscmdr)
1008 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1009 proutn(_(" It can survive until stardate %d.\"") \
1010 % int(scheduled(FSCDBAS)))
1011 if not game.resting:
1013 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1016 game.resting = False
1017 game.optime = 0.0; # actually finished
1019 # Check for intelligence report
1021 (random.random() > 0.2 or \
1022 (not communicating()) or \
1023 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1026 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1027 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1032 if not game.tholian or game.justin:
1034 if game.tholian.x == 0 and game.tholian.y == 0:
1035 idx = 0; idy = QUADSIZE-1
1036 elif game.tholian.x == 0 and game.tholian.y == QUADSIZE-1:
1037 idx = QUADSIZE-1; idy = QUADSIZE-1
1038 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == QUADSIZE-1:
1039 idx = QUADSIZE-1; idy = 0
1040 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == 0:
1043 # something is wrong!
1046 # do nothing if we are blocked
1047 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1049 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1050 if game.tholian.x != idx:
1052 im = math.fabs(idx - game.tholian.x)*1.0/(idx - game.tholian.x)
1053 while game.tholian.x != idx:
1054 game.tholian.x += im
1055 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1056 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1057 elif game.tholian.y != idy:
1059 im = math.fabs(idy - game.tholian.y)*1.0/(idy - game.tholian.y)
1060 while game.tholian.y != idy:
1061 game.tholian.y += im
1062 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1063 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1064 game.quad[game.tholian.x][game.tholian.y] = IHT
1065 game.ks[game.nenhere] = game.tholian
1067 # check to see if all holes plugged
1068 for i in range(QUADSIZE):
1069 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1071 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1073 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1075 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1077 # All plugged up -- Tholian splits
1078 game.quad[game.tholian.x][game.tholian.y]=IHWEB
1080 crmena(True, IHT, "sector", game.tholian)
1081 prout(_(" completes web."))
1086 # Code from battle.c begins here
1088 def doshield(shraise):
1089 # change shield status
1097 if isit("transfer"):
1101 if damaged(DSHIELD):
1102 prout(_("Shields damaged and down."))
1109 proutn(_("Do you wish to change shield energy? "))
1111 proutn(_("Energy to transfer to shields- "))
1113 elif damaged(DSHIELD):
1114 prout(_("Shields damaged and down."))
1117 proutn(_("Shields are up. Do you want them down? "))
1124 proutn(_("Shields are down. Do you want them up? "))
1130 if action == "SHUP": # raise shields
1132 prout(_("Shields already up."))
1136 if game.condition != "docked":
1138 prout(_("Shields raised."))
1139 if game.energy <= 0:
1141 prout(_("Shields raising uses up last of energy."))
1146 elif action == "SHDN":
1148 prout(_("Shields already down."))
1152 prout(_("Shields lowered."))
1155 elif action == "NRG":
1156 while scan() != IHREAL:
1158 proutn(_("Energy to transfer to shields- "))
1162 if aaitem > game.energy:
1163 prout(_("Insufficient ship energy."))
1166 if game.shield+aaitem >= game.inshld:
1167 prout(_("Shield energy maximized."))
1168 if game.shield+aaitem > game.inshld:
1169 prout(_("Excess energy requested returned to ship energy"))
1170 game.energy -= game.inshld-game.shield
1171 game.shield = game.inshld
1173 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1174 # Prevent shield drain loophole
1176 prout(_("Engineering to bridge--"))
1177 prout(_(" Scott here. Power circuit problem, Captain."))
1178 prout(_(" I can't drain the shields."))
1181 if game.shield+aaitem < 0:
1182 prout(_("All shield energy transferred to ship."))
1183 game.energy += game.shield
1186 proutn(_("Scotty- \""))
1188 prout(_("Transferring energy to shields.\""))
1190 prout(_("Draining energy from shields.\""))
1191 game.shield += aaitem
1192 game.energy -= aaitem
1196 # choose a device to damage, at random.
1198 # Quoth Eric Allman in the code of BSD-Trek:
1199 # "Under certain conditions you can get a critical hit. This
1200 # sort of hit damages devices. The probability that a given
1201 # device is damaged depends on the device. Well protected
1202 # devices (such as the computer, which is in the core of the
1203 # ship and has considerable redundancy) almost never get
1204 # damaged, whereas devices which are exposed (such as the
1205 # warp engines) or which are particularly delicate (such as
1206 # the transporter) have a much higher probability of being
1209 # This is one place where OPTION_PLAIN does not restore the
1210 # original behavior, which was equiprobable damage across
1211 # all devices. If we wanted that, we'd return NDEVICES*random.random()
1212 # and have done with it. Also, in the original game, DNAVYS
1213 # and DCOMPTR were the same device.
1215 # Instead, we use a table of weights similar to the one from BSD Trek.
1216 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1217 # We don't have a cloaking device. The shuttle got the allocation
1218 # for the cloaking device, then we shaved a half-percent off
1219 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1222 105, # DSRSENS: short range scanners 10.5%
1223 105, # DLRSENS: long range scanners 10.5%
1224 120, # DPHASER: phasers 12.0%
1225 120, # DPHOTON: photon torpedoes 12.0%
1226 25, # DLIFSUP: life support 2.5%
1227 65, # DWARPEN: warp drive 6.5%
1228 70, # DIMPULS: impulse engines 6.5%
1229 145, # DSHIELD: deflector shields 14.5%
1230 30, # DRADIO: subspace radio 3.0%
1231 45, # DSHUTTL: shuttle 4.5%
1232 15, # DCOMPTR: computer 1.5%
1233 20, # NAVCOMP: navigation system 2.0%
1234 75, # DTRANSP: transporter 7.5%
1235 20, # DSHCTRL: high-speed shield controller 2.0%
1236 10, # DDRAY: death ray 1.0%
1237 30, # DDSP: deep-space probes 3.0%
1239 idx = random.random() * 1000.0 # weights must sum to 1000
1241 for (i, w) in enumerate(weights):
1245 return None; # we should never get here
1247 def ram(ibumpd, ienm, w):
1248 # make our ship ram something
1249 prouts(_("***RED ALERT! RED ALERT!"))
1251 prout(_("***COLLISION IMMINENT."))
1255 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1257 proutn(_(" rammed by "))
1260 crmena(False, ienm, sector, w)
1262 proutn(_(" (original position)"))
1264 deadkl(w, ienm, game.sector)
1267 prout(_(" heavily damaged."))
1268 icas = 10 + random.randrange(20)
1269 prout(_("***Sickbay reports %d casualties"), icas)
1271 game.state.crew -= icas
1273 # In the pre-SST2K version, all devices got equiprobably damaged,
1274 # which was silly. Instead, pick up to half the devices at
1275 # random according to our weighting table,
1277 ncrits = random.randrange(NDEVICES/2)
1278 for m in range(ncrits):
1280 if game.damage[dev] < 0:
1282 extradm = (10.0*hardness*random.random()+1.0)*game.damfac
1283 # Damage for at least time of travel!
1284 game.damage[dev] += game.optime + extradm
1286 prout(_("***Shields are down."))
1287 if game.state.remkl + game.state.remcom + game.state.nscrem:
1294 def torpedo(course, r, incoming, i, n):
1295 # let a photon torpedo fly
1298 ac = course + 0.25*r
1299 angle = (15.0-ac)*0.5235988
1300 bullseye = (15.0 - course)*0.5235988
1301 deltax = -math.sin(angle);
1302 deltay = math.cos(angle);
1303 x = incoming.x; y = incoming.y
1304 w = coord(); jw = coord()
1305 w.x = w.y = jw.x = jw.y = 0
1306 bigger = max(math.fabs(deltax), math.fabs(deltay))
1309 if not damaged(DSRSENS) or game.condition=="docked":
1310 setwnd(srscan_window)
1312 setwnd(message_window)
1313 # Loop to move a single torpedo
1314 for l in range(1, 15+1):
1319 if not VALID_SECTOR(w.x, w.y):
1321 iquad=game.quad[w.x][w.y]
1322 tracktorpedo(w, l, i, n, iquad)
1326 setwnd(message_window)
1327 if damaged(DSRSENS) and not game.condition=="docked":
1328 skip(1); # start new line after text track
1329 if iquad in (IHE, IHF): # Hit our ship
1331 proutn(_("Torpedo hits "))
1334 hit = 700.0 + 100.0*random.random() - \
1335 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1336 newcnd(); # we're blown out of dock
1337 # We may be displaced.
1338 if game.landed or game.condition=="docked":
1339 return hit # Cheat if on a planet
1340 ang = angle + 2.5*(random.random()-0.5)
1341 temp = math.fabs(math.sin(ang))
1342 if math.fabs(math.cos(ang)) > temp:
1343 temp = math.fabs(math.cos(ang))
1344 xx = -math.sin(ang)/temp
1345 yy = math.cos(ang)/temp
1348 if not VALID_SECTOR(jw.x, jw.y):
1350 if game.quad[jw.x][jw.y]==IHBLANK:
1353 if game.quad[jw.x][jw.y]!=IHDOT:
1354 # can't move into object
1359 elif iquad in (IHC, IHS): # Hit a commander
1360 if random.random() <= 0.05:
1361 crmena(True, iquad, sector, w)
1362 prout(_(" uses anti-photon device;"))
1363 prout(_(" torpedo neutralized."))
1365 elif iquad in (IHR, IHK): # Hit a regular enemy
1367 for ll in range(game.nenhere):
1368 if w == game.ks[ll]:
1370 kp = math.fabs(game.kpower[ll])
1371 h1 = 700.0 + 100.0*random.random() - \
1372 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1376 if game.kpower[ll] < 0:
1377 game.kpower[ll] -= -h1
1379 game.kpower[ll] -= h1
1380 if game.kpower[ll] == 0:
1383 crmena(True, iquad, "sector", w)
1384 # If enemy damaged but not destroyed, try to displace
1385 ang = angle + 2.5*(random.random()-0.5)
1386 temp = math.fabs(math.sin(ang))
1387 if math.fabs(math.cos(ang)) > temp:
1388 temp = math.fabs(math.cos(ang))
1389 xx = -math.sin(ang)/temp
1390 yy = math.cos(ang)/temp
1393 if not VALID_SECTOR(jw.x, jw.y):
1394 prout(_(" damaged but not destroyed."))
1396 if game.quad[jw.x][jw.y]==IHBLANK:
1397 prout(_(" buffeted into black hole."))
1398 deadkl(w, iquad, jw)
1400 if game.quad[jw.x][jw.y]!=IHDOT:
1401 # can't move into object
1402 prout(_(" damaged but not destroyed."))
1404 proutn(_(" damaged--"))
1408 elif iquad == IHB: # Hit a base
1410 prout(_("***STARBASE DESTROYED.."))
1411 for ll in range(game.state.rembase):
1412 if game.state.baseq[ll] == game.quadrant:
1413 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1415 game.quad[w.x][w.y]=IHDOT
1416 game.state.rembase -= 1
1417 game.base.x=game.base.y=0
1418 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1419 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1420 game.state.basekl += 1
1423 elif iquad == IHP: # Hit a planet
1424 crmena(True, iquad, sector, w)
1425 prout(_(" destroyed."))
1426 game.state.nplankl += 1
1427 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1428 game.iplnet.pclass = "destroyed"
1430 invalidate(game.plnet)
1431 game.quad[w.x][w.y] = IHDOT
1433 # captain perishes on planet
1436 elif iquad == IHW: # Hit an inhabited world -- very bad!
1437 crmena(True, iquad, sector, w)
1438 prout(_(" destroyed."))
1439 game.state.nworldkl += 1
1440 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1441 game.iplnet.pclass = "destroyed"
1443 invalidate(game.plnet)
1444 game.quad[w.x][w.y] = IHDOT
1446 # captain perishes on planet
1448 prout(_("You have just destroyed an inhabited planet."))
1449 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1451 elif iquad == IHSTAR: # Hit a star
1452 if random.random() > 0.10:
1455 crmena(True, IHSTAR, sector, w)
1456 prout(_(" unaffected by photon blast."))
1458 elif iquad == IHQUEST: # Hit a thingy
1459 if not (game.options & OPTION_THINGY) or random.random()>0.7:
1461 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1463 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1465 proutn(_("Mr. Spock-"))
1466 prouts(_(" \"Fascinating!\""))
1471 # Stas Sergeev added the possibility that
1472 # you can shove the Thingy and piss it off.
1473 # It then becomes an enemy and may fire at you.
1479 elif iquad == IHBLANK: # Black hole
1481 crmena(True, IHBLANK, sector, w)
1482 prout(_(" swallows torpedo."))
1484 elif iquad == IHWEB: # hit the web
1486 prout(_("***Torpedo absorbed by Tholian web."))
1488 elif iquad == IHT: # Hit a Tholian
1489 h1 = 700.0 + 100.0*random.random() - \
1490 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1493 game.quad[w.x][w.y] = IHDOT
1498 crmena(True, IHT, sector, w)
1499 if random.random() > 0.05:
1500 prout(_(" survives photon blast."))
1502 prout(_(" disappears."))
1503 game.quad[w.x][w.y] = IHWEB
1510 proutn("Don't know how to handle torpedo collision with ")
1511 crmena(True, iquad, sector, w)
1515 if curwnd!=message_window:
1516 setwnd(message_window)
1518 game.quad[w.x][w.y]=IHDOT
1519 game.quad[jw.x][jw.y]=iquad
1520 prout(_(" displaced by blast to Sector %s ") % jw)
1521 for ll in range(game.nenhere):
1522 game.kdist[ll] = game.kavgd[ll] = distance(game.sector,game.ks[ll])
1526 prout(_("Torpedo missed."))
1530 # critical-hit resolution
1532 # a critical hit occured
1533 if hit < (275.0-25.0*game.skill)*(1.0+0.5*random.random()):
1535 ncrit = 1.0 + hit/(500.0+100.0*random.random())
1536 proutn(_("***CRITICAL HIT--"))
1537 # Select devices and cause damage
1539 for loop1 in range(ncrit):
1542 # Cheat to prevent shuttle damage unless on ship
1543 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1546 extradm = (hit*game.damfac)/(ncrit*(75.0+25.0*random.random()))
1547 game.damage[j] += extradm
1549 for loop2 in range(loop1):
1550 if j == cdam[loop2]:
1559 prout(_(" damaged."))
1560 if damaged(DSHIELD) and game.shldup:
1561 prout(_("***Shields knocked down."))
1564 def attack(torps_ok):
1565 # bad guy attacks us
1566 # torps_ok == false forces use of phasers in an attack
1567 atackd = False; attempt = False; ihurt = False;
1568 hitmax=0.0; hittot=0.0; chgfac=1.0
1571 # game could be over at this point, check
1575 prout("=== ATTACK!")
1576 # Tholian gets to move before attacking
1579 # if you have just entered the RNZ, you'll get a warning
1580 if game.neutz: # The one chance not to be attacked
1583 # commanders get a chance to tac-move towards you
1584 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1586 # if no enemies remain after movement, we're done
1587 if game.nenhere==0 or (game.nenhere==1 and thing == game.quadrant and not iqengry):
1589 # set up partial hits if attack happens during shield status change
1590 pfac = 1.0/game.inshld
1592 chgfac = 0.25+0.5*random.random()
1594 # message verbosity control
1595 if game.skill <= SKILL_FAIR:
1597 for loop in range(game.nenhere):
1598 if game.kpower[loop] < 0:
1599 continue; # too weak to attack
1600 # compute hit strength and diminish shield power
1602 # Increase chance of photon torpedos if docked or enemy energy low
1603 if game.condition == "docked":
1605 if game.kpower[loop] < 500:
1608 iquad = game.quad[jay.x][jay.y]
1609 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1611 # different enemies have different probabilities of throwing a torp
1612 usephasers = not torps_ok or \
1613 (iquad == IHK and r > 0.0005) or \
1614 (iquad==IHC and r > 0.015) or \
1615 (iquad==IHR and r > 0.3) or \
1616 (iquad==IHS and r > 0.07) or \
1617 (iquad==IHQUEST and r > 0.05)
1618 if usephasers: # Enemy uses phasers
1619 if game.condition == "docked":
1620 continue; # Don't waste the effort!
1621 attempt = True; # Attempt to attack
1622 dustfac = 0.8+0.05*random.random()
1623 hit = game.kpower[loop]*math.pow(dustfac,game.kavgd[loop])
1624 game.kpower[loop] *= 0.75
1625 else: # Enemy uses photon torpedo
1626 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1628 proutn(_("***TORPEDO INCOMING"))
1629 if not damaged(DSRSENS):
1631 crmena(False, iquad, where, jay)
1634 r = (random.random()+random.random())*0.5 -0.5
1635 r += 0.002*game.kpower[loop]*r
1636 hit = torpedo(course, r, jay, 1, 1)
1637 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1638 finish(FWON); # Klingons did themselves in!
1639 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1640 return; # Supernova or finished
1643 # incoming phaser or torpedo, shields may dissipate it
1644 if game.shldup or game.shldchg or game.condition=="docked":
1645 # shields will take hits
1646 propor = pfac * game.shield
1647 if game.condition =="docked":
1651 hitsh = propor*chgfac*hit+1.0
1653 if absorb > game.shield:
1654 absorb = game.shield
1655 game.shield -= absorb
1657 # taking a hit blasts us out of a starbase dock
1658 if game.condition == "docked":
1660 # but the shields may take care of it
1661 if propor > 0.1 and hit < 0.005*game.energy:
1663 # hit from this opponent got through shields, so take damage
1665 proutn(_("%d unit hit") % int(hit))
1666 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1667 proutn(_(" on the "))
1669 if not damaged(DSRSENS) and usephasers:
1671 crmena(False, iquad, where, jay)
1673 # Decide if hit is critical
1679 if game.energy <= 0:
1680 # Returning home upon your shield, not with it...
1683 if not attempt and game.condition == "docked":
1684 prout(_("***Enemies decide against attacking your ship."))
1687 percent = 100.0*pfac*game.shield+0.5
1689 # Shields fully protect ship
1690 proutn(_("Enemy attack reduces shield strength to "))
1692 # Print message if starship suffered hit(s)
1694 proutn(_("Energy left %2d shields ") % int(game.energy))
1697 elif not damaged(DSHIELD):
1700 proutn(_("damaged, "))
1701 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1702 # Check if anyone was hurt
1703 if hitmax >= 200 or hittot >= 500:
1704 icas= hittot*random.random()*0.015
1707 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1708 prout(_(" in that last attack.\""))
1710 game.state.crew -= icas
1711 # After attack, reset average distance to enemies
1712 for loop in range(game.nenhere):
1713 game.kavgd[loop] = game.kdist[loop]
1717 def deadkl(w, type, mv):
1718 # kill a Klingon, Tholian, Romulan, or Thingy
1719 # Added mv to allow enemy to "move" before dying
1720 crmena(True, type, sector, mv)
1721 # Decide what kind of enemy it is and update appropriately
1723 # chalk up a Romulan
1724 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1726 game.state.nromrem -= 1
1730 elif type == IHQUEST:
1736 # Some type of a Klingon
1737 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1740 game.comhere = False
1741 for i in range(game.state.remcom):
1742 if game.state.kcmdr[i] == game.quadrant:
1744 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1745 game.state.kcmdr[game.state.remcom].x = 0
1746 game.state.kcmdr[game.state.remcom].y = 0
1747 game.state.remcom -= 1
1749 if game.state.remcom != 0:
1750 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1752 game.state.remkl -= 1
1754 game.state.nscrem -= 1
1756 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1761 prout("*** Internal error, deadkl() called on %s\n" % type)
1762 # For each kind of enemy, finish message to player
1763 prout(_(" destroyed."))
1764 game.quad[w.x][w.y] = IHDOT
1765 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1768 # Remove enemy ship from arrays describing local conditions
1769 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1771 for i in range(game.nenhere):
1773 for j in range(i, game.nenhere):
1774 game.ks[j] = game.ks[j+1]
1775 game.kpower[j] = game.kpower[j+1]
1776 game.kavgd[j] = game.kdist[j] = game.kdist[j+1]
1777 game.ks[game.nenhere].x = 0
1778 game.ks[game.nenhere].y = 0
1779 game.kdist[game.nenhere] = 0
1780 game.kavgd[game.nenhere] = 0
1781 game.kpower[game.nenhere] = 0
1787 def targetcheck(x, y):
1788 # Return None if target is invalid
1789 if not VALID_SECTOR(x, y):
1792 deltx = 0.1*(y - game.sector.y)
1793 delty = 0.1*(x - game.sector.x)
1794 if deltx==0 and delty== 0:
1796 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1797 prout(_(" I recommend an immediate review of"))
1798 prout(_(" the Captain's psychological profile.\""))
1801 return 1.90985932*math.atan2(deltx, delty)
1804 # launch photon torpedo
1806 if damaged(DPHOTON):
1807 prout(_("Photon tubes damaged."))
1811 prout(_("No torpedoes left."))
1820 prout(_("%d torpedoes left.") % game.torps)
1821 proutn(_("Number of torpedoes to fire- "))
1823 else: # key == IHREAL {
1825 if n <= 0: # abort command
1830 prout(_("Maximum of 3 torpedoes per burst."))
1837 for i in range(1, n+1):
1839 if i==1 and key == IHEOL:
1840 break; # we will try prompting
1841 if i==2 and key == IHEOL:
1842 # direct all torpedoes at one target
1844 targ[i][1] = targ[1][1]
1845 targ[i][2] = targ[1][2]
1846 course[i] = course[1]
1858 course[i] = targetcheck(targ[i][1], targ[i][2])
1859 if course[i] == None:
1862 if i == 1 and key == IHEOL:
1863 # prompt for each one
1864 for i in range(1, n+1):
1865 proutn(_("Target sector for torpedo number %d- ") % i)
1870 targ[i][1] = int(aaitem-0.5)
1875 targ[i][2] = int(aaitem-0.5)
1877 course[i] = targetcheck(targ[i][1], targ[i][2])
1878 if course[i] == None:
1881 # Loop for moving <n> torpedoes
1882 for i in range(1, n+1):
1883 if game.condition != "docked":
1885 r = (random.random()+random.random())*0.5 -0.5
1886 if math.fabs(r) >= 0.47:
1888 r = (random.random()+1.2) * r
1890 prouts(_("***TORPEDO NUMBER %d MISFIRES") % i)
1892 prouts(_("***TORPEDO MISFIRES."))
1895 prout(_(" Remainder of burst aborted."))
1896 if random.random() <= 0.2:
1897 prout(_("***Photon tubes damaged by misfire."))
1898 game.damage[DPHOTON] = game.damfac*(1.0+2.0*random.random())
1900 if game.shldup or game.condition == "docked":
1901 r *= 1.0 + 0.0001*game.shield
1902 torpedo(course[i], r, game.sector, i, n)
1903 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1905 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1909 # check for phasers overheating
1911 chekbrn = (rpow-1500.)*0.00038
1912 if random.random() <= chekbrn:
1913 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1914 game.damage[DPHASER] = game.damfac*(1.0 + random.random()) * (1.0+chekbrn)
1916 def checkshctrl(rpow):
1917 # check shield control
1919 if random.random() < 0.998:
1920 prout(_("Shields lowered."))
1922 # Something bad has happened
1923 prouts(_("***RED ALERT! RED ALERT!"))
1925 hit = rpow*game.shield/game.inshld
1926 game.energy -= rpow+hit*0.8
1927 game.shield -= hit*0.2
1928 if game.energy <= 0.0:
1929 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1934 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1936 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1937 icas = hit*random.random()*0.012
1942 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1943 prout(_(" %d casualties so far.\"") % icas)
1945 game.state.crew -= icas
1947 prout(_("Phaser energy dispersed by shields."))
1948 prout(_("Enemy unaffected."))
1953 # register a phaser hit on Klingons and Romulans
1954 nenhr2 = game.nenhere; kk=1
1957 for k in range(nenhr2):
1961 dustfac = 0.9 + 0.01*random.random()
1962 hit = wham*math.pow(dustfac,game.kdist[kk])
1963 kpini = game.kpower[kk]
1964 kp = math.fabs(kpini)
1965 if PHASEFAC*hit < kp:
1967 if game.kpower[kk] < 0:
1968 game.kpower[kk] -= -kp
1970 game.kpower[kk] -= kp
1971 kpow = game.kpower[kk]
1974 if not damaged(DSRSENS):
1976 proutn(_("%d unit hit on ") % int(hit))
1978 proutn(_("Very small hit on "))
1979 ienm = game.quad[w.x][w.y]
1983 crmena(False, ienm, "sector", w)
1987 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1991 kk -= 1; # don't do the increment
1992 else: # decide whether or not to emasculate klingon
1993 if kpow > 0 and random.random() >= 0.9 and \
1994 kpow <= ((0.4 + 0.4*random.random())*kpini):
1995 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s") % w)
1996 prout(_(" has just lost its firepower.\""))
1997 game.kpower[kk] = -kpow
2004 kz = 0; k = 1; irec=0 # Cheating inhibitor
2005 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2009 # SR sensors and Computer are needed fopr automode
2010 if damaged(DSRSENS) or damaged(DCOMPTR):
2012 if game.condition == "docked":
2013 prout(_("Phasers can't be fired through base shields."))
2016 if damaged(DPHASER):
2017 prout(_("Phaser control damaged."))
2021 if damaged(DSHCTRL):
2022 prout(_("High speed shield control damaged."))
2025 if game.energy <= 200.0:
2026 prout(_("Insufficient energy to activate high-speed shield control."))
2029 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2031 # Original code so convoluted, I re-did it all
2032 # (That was Tom Almy talking about the C code, I think -- ESR)
2033 while automode=="NOTSET":
2038 prout(_("There is no enemy present to select."))
2041 automode="AUTOMATIC"
2045 elif isit("automatic"):
2046 if (not itarg) and game.nenhere != 0:
2047 automode = "FORCEMAN"
2050 prout(_("Energy will be expended into space."))
2051 automode = "AUTOMATIC"
2060 prout(_("Energy will be expended into space."))
2061 automode = "AUTOMATIC"
2063 automode = "FORCEMAN"
2065 automode = "AUTOMATIC"
2069 prout(_("Energy will be expended into space."))
2070 automode = "AUTOMATIC"
2072 automode = "FORCEMAN"
2074 proutn(_("Manual or automatic? "))
2079 if automode == "AUTOMATIC":
2080 if key == IHALPHA and isit("no"):
2083 if key != IHREAL and game.nenhere != 0:
2084 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2089 for i in range(game.nenhere):
2090 irec += math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))*(1.01+0.05*random.random()) + 1.0
2092 proutn(_("%d units required. ") % irec)
2094 proutn(_("Units to fire= "))
2100 proutn(_("Energy available= %.2f") % avail)
2103 if not rpow > avail:
2110 if key == IHALPHA and isit("no"):
2113 game.energy -= 200; # Go and do it!
2114 if checkshctrl(rpow):
2122 for i in range(game.nenhere):
2126 hits[i] = math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))
2127 over = (0.01 + 0.05*random.random())*hits[i]
2129 powrem -= hits[i] + over
2130 if powrem <= 0 and temp < hits[i]:
2139 if extra > 0 and not game.alldone:
2141 proutn(_("*** Tholian web absorbs "))
2143 proutn(_("excess "))
2144 prout(_("phaser energy."))
2146 prout(_("%d expended on empty space.") % int(extra))
2147 elif automode == "FORCEMAN":
2150 if damaged(DCOMPTR):
2151 prout(_("Battle computer damaged, manual fire only."))
2154 prouts(_("---WORKING---"))
2156 prout(_("Short-range-sensors-damaged"))
2157 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2158 prout(_("Manual-fire-must-be-used"))
2160 elif automode == "MANUAL":
2162 for k in range(game.nenhere):
2164 ienm = game.quad[aim.x][aim.y]
2166 proutn(_("Energy available= %.2f") % (avail-0.006))
2170 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2171 (ienm == IHC or ienm == IHS):
2173 prout(_(" can't be located without short range scan."))
2176 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2181 if itarg and k > kz:
2182 irec=(abs(game.kpower[k])/(PHASEFAC*math.pow(0.9,game.kdist[k]))) * (1.01+0.05*random.random()) + 1.0
2185 if not damaged(DCOMPTR):
2190 proutn(_("units to fire at "))
2191 crmena(False, ienm, sector, aim)
2194 if key == IHALPHA and isit("no"):
2202 if k==1: # Let me say I'm baffled by this
2211 # If total requested is too much, inform and start over
2213 prout(_("Available energy exceeded -- try again."))
2216 key = scan(); # scan for next value
2219 # zero energy -- abort
2222 if key == IHALPHA and isit("no"):
2227 game.energy -= 200.0
2228 if checkshctrl(rpow):
2232 # Say shield raised or malfunction, if necessary
2238 if random.random() >= 0.99:
2239 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2240 prouts(_(" CLICK CLICK POP . . ."))
2241 prout(_(" No response, sir!"))
2244 prout(_("Shields raised."))
2249 # Code from events,c begins here.
2251 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2252 # event of each type active at any given time. Mostly these means we can
2253 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2254 # BSD Trek, from which we swiped the idea, can have up to 5.
2256 def unschedule(evtype):
2257 # remove an event from the schedule
2258 game.future[evtype].date = FOREVER
2259 return game.future[evtype]
2261 def is_scheduled(evtype):
2262 # is an event of specified type scheduled
2263 return game.future[evtype].date != FOREVER
2265 def scheduled(evtype):
2266 # when will this event happen?
2267 return game.future[evtype].date
2269 def schedule(evtype, offset):
2270 # schedule an event of specified type
2271 game.future[evtype].date = game.state.date + offset
2272 return game.future[evtype]
2274 def postpone(evtype, offset):
2275 # postpone a scheduled event
2276 game.future[evtype].date += offset
2279 # rest period is interrupted by event
2282 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2284 game.resting = False
2290 # run through the event queue looking for things to do
2292 fintim = game.state.date + game.optime; yank=0
2293 ictbeam = False; istract = False
2294 w = coord(); hold = coord()
2295 ev = event(); ev2 = event()
2297 def tractorbeam(yank):
2298 # tractor beaming cases merge here
2300 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2304 prout(_(" caught in long range tractor beam--"))
2305 # If Kirk & Co. screwing around on planet, handle
2306 atover(True) # atover(true) is Grab
2309 if game.icraft: # Caught in Galileo?
2312 # Check to see if shuttle is aboard
2313 if game.iscraft == "offship":
2315 if random.random() > 0.5:
2316 prout(_("Galileo, left on the planet surface, is captured"))
2317 prout(_("by aliens and made into a flying McDonald's."))
2318 game.damage[DSHUTTL] = -10
2319 game.iscraft = "removed"
2321 prout(_("Galileo, left on the planet surface, is well hidden."))
2323 game.quadrant = game.state.kscmdr
2325 game.quadrant = game.state.kcmdr[i]
2326 game.sector = randplace(QUADSIZE)
2328 prout(_(" is pulled to Quadrant %s, Sector %s") \
2329 % (game.quadrant, game.sector))
2331 prout(_("(Remainder of rest/repair period cancelled.)"))
2332 game.resting = False
2334 if not damaged(DSHIELD) and game.shield > 0:
2335 doshield(shraise=True) # raise shields
2336 game.shldchg = False
2338 prout(_("(Shields not currently useable.)"))
2340 # Adjust finish time to time of tractor beaming
2341 fintim = game.state.date+game.optime
2343 if game.state.remcom <= 0:
2346 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2349 # Code merges here for any commander destroying base
2350 # Not perfect, but will have to do
2351 # Handle case where base is in same quadrant as starship
2352 if game.battle == game.quadrant:
2353 game.state.chart[game.battle.x][game.battle.y].starbase = False
2354 game.quad[game.base.x][game.base.y] = IHDOT
2355 game.base.x=game.base.y=0
2358 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2359 elif game.state.rembase != 1 and communicating():
2360 # Get word via subspace radio
2363 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2364 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2366 prout(_("the Klingon Super-Commander"))
2368 prout(_("a Klingon Commander"))
2369 game.state.chart[game.battle.x][game.battle.y].starbase = False
2370 # Remove Starbase from galaxy
2371 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2372 for i in range(1, game.state.rembase+1):
2373 if game.state.baseq[i] == game.battle:
2374 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2375 game.state.rembase -= 1
2377 # reinstate a commander's base attack
2381 invalidate(game.battle)
2384 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2385 for i in range(1, NEVENTS):
2386 if i == FSNOVA: proutn("=== Supernova ")
2387 elif i == FTBEAM: proutn("=== T Beam ")
2388 elif i == FSNAP: proutn("=== Snapshot ")
2389 elif i == FBATTAK: proutn("=== Base Attack ")
2390 elif i == FCDBAS: proutn("=== Base Destroy ")
2391 elif i == FSCMOVE: proutn("=== SC Move ")
2392 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2393 elif i == FDSPROB: proutn("=== Probe Move ")
2394 elif i == FDISTR: proutn("=== Distress Call ")
2395 elif i == FENSLV: proutn("=== Enslavement ")
2396 elif i == FREPRO: proutn("=== Klingon Build ")
2398 prout("%.2f" % (scheduled(i)))
2401 radio_was_broken = damaged(DRADIO)
2404 # Select earliest extraneous event, evcode==0 if no events
2409 for l in range(1, NEVENTS):
2410 if game.future[l].date < datemin:
2413 prout("== Event %d fires" % evcode)
2414 datemin = game.future[l].date
2415 xtime = datemin-game.state.date
2416 game.state.date = datemin
2417 # Decrement Federation resources and recompute remaining time
2418 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2420 if game.state.remtime <=0:
2423 # Any crew left alive?
2424 if game.state.crew <=0:
2427 # Is life support adequate?
2428 if damaged(DLIFSUP) and game.condition != "docked":
2429 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2432 game.lsupres -= xtime
2433 if game.damage[DLIFSUP] <= xtime:
2434 game.lsupres = game.inlsr
2437 if game.condition == "docked":
2438 repair /= game.docfac
2439 # Don't fix Deathray here
2440 for l in range(NDEVICES):
2441 if game.damage[l] > 0.0 and l != DDRAY:
2442 if game.damage[l]-repair > 0.0:
2443 game.damage[l] -= repair
2445 game.damage[l] = 0.0
2446 # If radio repaired, update star chart and attack reports
2447 if radio_was_broken and not damaged(DRADIO):
2448 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2449 prout(_(" surveillance reports are coming in."))
2451 if not game.iseenit:
2455 prout(_(" The star chart is now up to date.\""))
2457 # Cause extraneous event EVCODE to occur
2458 game.optime -= xtime
2459 if evcode == FSNOVA: # Supernova
2462 schedule(FSNOVA, expran(0.5*game.intime))
2463 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2465 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2466 if game.state.nscrem == 0 or \
2467 ictbeam or istract or \
2468 game.condition=="docked" or game.isatb==1 or game.iscate:
2470 if game.ientesc or \
2471 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2472 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2473 (damaged(DSHIELD) and \
2474 (game.energy < 2500 or damaged(DPHASER)) and \
2475 (game.torps < 5 or damaged(DPHOTON))):
2477 istract = ictbeam = True
2478 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2481 elif evcode == FTBEAM: # Tractor beam
2482 if game.state.remcom == 0:
2485 i = random.randrange(game.state.remcom)
2486 yank = distance(game.state.kcmdr[i], game.quadrant)
2487 if istract or game.condition == "docked" or yank == 0:
2488 # Drats! Have to reschedule
2490 game.optime + expran(1.5*game.intime/game.state.remcom))
2494 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2495 game.snapsht = copy.deepcopy(game.state)
2496 game.state.snap = True
2497 schedule(FSNAP, expran(0.5 * game.intime))
2498 elif evcode == FBATTAK: # Commander attacks starbase
2499 if game.state.remcom==0 or game.state.rembase==0:
2505 for j in range(game.state.rembase):
2506 for k in range(game.state.remcom):
2507 if game.state.baseq[j] == game.state.kcmdr[k] and \
2508 not game.state.baseq[j] == game.quadrant and \
2509 not game.state.baseq[j] == game.state.kscmdr:
2513 if j>game.state.rembase:
2514 # no match found -- try later
2515 schedule(FBATTAK, expran(0.3*game.intime))
2518 # commander + starbase combination found -- launch attack
2519 game.battle = game.state.baseq[j]
2520 schedule(FCDBAS, 1.0+3.0*random.random())
2521 if game.isatb: # extra time if SC already attacking
2522 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2523 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2524 game.iseenit = False
2525 if not communicating():
2526 continue # No warning :-(
2530 proutn(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2531 prout(_(" reports that it is under attack and that it can"))
2532 proutn(_(" hold out only until stardate %d") % (int(scheduled(FCDBAS))))
2536 elif evcode == FSCDBAS: # Supercommander destroys base
2539 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2540 continue # WAS RETURN!
2542 game.battle = game.state.kscmdr
2544 elif evcode == FCDBAS: # Commander succeeds in destroying base
2547 # find the lucky pair
2548 for i in range(game.state.remcom):
2549 if game.state.kcmdr[i] == game.battle:
2551 if i > game.state.remcom or game.state.rembase == 0 or \
2552 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2553 # No action to take after all
2554 invalidate(game.battle)
2557 elif evcode == FSCMOVE: # Supercommander moves
2558 schedule(FSCMOVE, 0.2777)
2559 if not game.ientesc and not istract and game.isatb != 1 and \
2560 (not game.iscate or not game.justin):
2562 elif evcode == FDSPROB: # Move deep space probe
2563 schedule(FDSPROB, 0.01)
2564 game.probex += game.probeinx
2565 game.probey += game.probeiny
2566 i = (int)(game.probex/QUADSIZE +0.05)
2567 j = (int)(game.probey/QUADSIZE + 0.05)
2568 if game.probec.x != i or game.probec.y != j:
2571 if not VALID_QUADRANT(i, j) or \
2572 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2573 # Left galaxy or ran into supernova
2577 proutn(_("Lt. Uhura- \"The deep space probe "))
2578 if not VALID_QUADRANT(j, i):
2579 proutn(_("has left the galaxy"))
2581 proutn(_("is no longer transmitting"))
2585 if not communicating():
2588 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2589 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2590 # Update star chart if Radio is working or have access to radio
2592 chp = game.state.chart[game.probec.x][game.probec.y]
2593 chp.klingons = pdest.klingons
2594 chp.starbase = pdest.starbase
2595 chp.stars = pdest.stars
2596 pdest.charted = True
2597 game.proben -= 1 # One less to travel
2598 if game.proben == 0 and game.isarmed and pdest.stars:
2599 # lets blow the sucker!
2600 supernova(True, game.probec)
2602 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2604 elif evcode == FDISTR: # inhabited system issues distress call
2606 # try a whole bunch of times to find something suitable
2607 for i in range(100):
2608 # need a quadrant which is not the current one,
2609 # which has some stars which are inhabited and
2610 # not already under attack, which is not
2611 # supernova'ed, and which has some Klingons in it
2612 w = randplace(GALSIZE)
2613 q = game.state.galaxy[w.x][w.y]
2614 if not (game.quadrant == w or q.planet == None or \
2615 not q.planet.inhabited or \
2616 q.supernova or q.status!="secure" or q.klingons<=0):
2619 # can't seem to find one; ignore this call
2621 prout("=== Couldn't find location for distress event.")
2623 # got one!! Schedule its enslavement
2624 ev = schedule(FENSLV, expran(game.intime))
2626 q.status = distressed
2628 # tell the captain about it if we can
2630 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2632 prout(_("by a Klingon invasion fleet."))
2635 elif evcode == FENSLV: # starsystem is enslaved
2636 ev = unschedule(FENSLV)
2637 # see if current distress call still active
2638 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2642 q.status = "enslaved"
2644 # play stork and schedule the first baby
2645 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2646 ev2.quadrant = ev.quadrant
2648 # report the disaster if we can
2650 prout(_("Uhura- We've lost contact with starsystem %s") % \
2652 prout(_("in Quadrant %s.\n") % ev.quadrant)
2653 elif evcode == FREPRO: # Klingon reproduces
2654 # If we ever switch to a real event queue, we'll need to
2655 # explicitly retrieve and restore the x and y.
2656 ev = schedule(FREPRO, expran(1.0 * game.intime))
2657 # see if current distress call still active
2658 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2662 if game.state.remkl >=MAXKLGAME:
2663 continue # full right now
2664 # reproduce one Klingon
2666 if game.klhere >= MAXKLQUAD:
2668 # this quadrant not ok, pick an adjacent one
2669 for i in range(w.x - 1, w.x + 2):
2670 for j in range(w.y - 1, w.y + 2):
2671 if not VALID_QUADRANT(i, j):
2673 q = game.state.galaxy[w.x][w.y]
2674 # check for this quad ok (not full & no snova)
2675 if q.klingons >= MAXKLQUAD or q.supernova:
2679 continue # search for eligible quadrant failed
2684 game.state.remkl += 1
2686 if game.quadrant == w:
2688 newkling(game.klhere)
2689 # recompute time left
2691 # report the disaster if we can
2693 if game.quadrant == w:
2694 prout(_("Spock- sensors indicate the Klingons have"))
2695 prout(_("launched a warship from %s.") % q.planet)
2697 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2698 if q.planet != None:
2699 proutn(_("near %s") % q.planet)
2700 prout(_("in Quadrant %s.") % w)
2709 proutn(_("How long? "))
2714 origTime = delay = aaitem
2717 if delay >= game.state.remtime or game.nenhere != 0:
2718 proutn(_("Are you sure? "))
2721 # Alternate resting periods (events) with attacks
2725 game.resting = False
2726 if not game.resting:
2727 prout(_("%d stardates left.") % int(game.state.remtime))
2729 temp = game.optime = delay
2731 rtime = 1.0 + random.random()
2735 if game.optime < delay:
2744 # Repair Deathray if long rest at starbase
2745 if origTime-delay >= 9.99 and game.condition == "docked":
2746 game.damage[DDRAY] = 0.0
2747 # leave if quadrant supernovas
2748 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2750 game.resting = False
2753 # A nova occurs. It is the result of having a star hit with a
2754 # photon torpedo, or possibly of a probe warhead going off.
2755 # Stars that go nova cause stars which surround them to undergo
2756 # the same probabilistic process. Klingons next to them are
2757 # destroyed. And if the starship is next to it, it gets zapped.
2758 # If the zap is too much, it gets destroyed.
2762 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2763 newc = coord(); scratch = coord()
2764 if random.random() < 0.05:
2765 # Wow! We've supernova'ed
2766 supernova(False, nov)
2768 # handle initial nova
2769 game.quad[nov.x][nov.y] = IHDOT
2770 crmena(False, IHSTAR, sector, nov)
2772 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2773 game.state.starkl += 1
2775 # Set up stack to recursively trigger adjacent stars
2776 bot = top = top2 = 1
2782 for mm in range(bot, top+1):
2783 for nn in range(1, 3+1): # nn,j represents coordinates around current
2784 for j in range(1, 3+1):
2787 scratch.x = hits[mm][1]+nn-2
2788 scratch.y = hits[mm][2]+j-2
2789 if not VALID_SECTOR(scratch.y, scratch.x):
2791 iquad = game.quad[scratch.x][scratch.y]
2792 # Empty space ends reaction
2793 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2795 elif iquad == IHSTAR: # Affect another star
2796 if random.random() < 0.05:
2797 # This star supernovas
2798 scratch = supernova(False)
2801 hits[top2][1]=scratch.x
2802 hits[top2][2]=scratch.y
2803 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2804 game.state.starkl += 1
2805 crmena(True, IHSTAR, sector, scratch)
2807 game.quad[scratch.x][scratch.y] = IHDOT
2808 elif iquad == IHP: # Destroy planet
2809 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2810 game.state.nplankl += 1
2811 crmena(True, IHP, sector, scratch)
2812 prout(_(" destroyed."))
2813 game.iplnet.pclass = "destroyed"
2815 invalidate(game.plnet)
2819 game.quad[scratch.x][scratch.y] = IHDOT
2820 elif iquad == IHB: # Destroy base
2821 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2822 for i in range(game.state.rembase):
2823 if game.state.baseq[i] == game.quadrant:
2825 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2826 game.state.rembase -= 1
2827 invalidate(game.base)
2828 game.state.basekl += 1
2830 crmena(True, IHB, sector, scratch)
2831 prout(_(" destroyed."))
2832 game.quad[scratch.x][scratch.y] = IHDOT
2833 elif iquad in (IHE, IHF): # Buffet ship
2834 prout(_("***Starship buffeted by nova."))
2836 if game.shield >= 2000.0:
2837 game.shield -= 2000.0
2839 diff = 2000.0 - game.shield
2843 prout(_("***Shields knocked out."))
2844 game.damage[DSHIELD] += 0.005*game.damfac*random.random()*diff
2846 game.energy -= 2000.0
2847 if game.energy <= 0:
2850 # add in course nova contributes to kicking starship
2851 icx += game.sector.x-hits[mm][1]
2852 icy += game.sector.y-hits[mm][2]
2854 elif iquad == IHK: # kill klingon
2855 deadkl(scratch,iquad, scratch)
2856 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2857 for ll in range(game.nenhere):
2858 if game.ks[ll] == scratch:
2860 game.kpower[ll] -= 800.0 # If firepower is lost, die
2861 if game.kpower[ll] <= 0.0:
2862 deadkl(scratch, iquad, scratch)
2864 newc.x = scratch.x + scratch.x - hits[mm][1]
2865 newc.y = scratch.y + scratch.y - hits[mm][2]
2866 crmena(True, iquad, sector, scratch)
2867 proutn(_(" damaged"))
2868 if not VALID_SECTOR(newc.x, newc.y):
2869 # can't leave quadrant
2872 iquad1 = game.quad[newc.x][newc.y]
2873 if iquad1 == IHBLANK:
2874 proutn(_(", blasted into "))
2875 crmena(False, IHBLANK, sector, newc)
2877 deadkl(scratch, iquad, newc)
2880 # can't move into something else
2883 proutn(_(", buffeted to Sector %s") % newc)
2884 game.quad[scratch.x][scratch.y] = IHDOT
2885 game.quad[newc.x][newc.y] = iquad
2887 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc)
2896 # Starship affected by nova -- kick it away.
2897 game.dist = kount*0.1
2900 game.direc = course[3*(icx+1)+icy+2]
2901 if game.direc == 0.0:
2903 if game.dist == 0.0:
2905 game.optime = 10.0*game.dist/16.0
2907 prout(_("Force of nova displaces starship."))
2908 imove(novapush=True)
2909 game.optime = 10.0*game.dist/16.0
2912 def supernova(induced, w=None):
2913 # star goes supernova
2920 # Scheduled supernova -- select star
2921 # logic changed here so that we won't favor quadrants in top
2923 for nq.x in range(GALSIZE):
2924 for nq.y in range(GALSIZE):
2925 stars += game.state.galaxy[nq.x][nq.y].stars
2927 return # nothing to supernova exists
2928 num = random.randrange(stars) + 1
2929 for nq.x in range(GALSIZE):
2930 for nq.y in range(GALSIZE):
2931 num -= game.state.galaxy[nq.x][nq.y].stars
2937 proutn("=== Super nova here?")
2940 if not nq == game.quadrant or game.justin:
2941 # it isn't here, or we just entered (treat as enroute)
2944 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2945 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2948 # we are in the quadrant!
2949 num = random.randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2950 for ns.x in range(QUADSIZE):
2951 for ns.y in range(QUADSIZE):
2952 if game.quad[ns.x][ns.y]==IHSTAR:
2959 prouts(_("***RED ALERT! RED ALERT!"))
2961 prout(_("***Incipient supernova detected at Sector %s") % ns)
2962 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2963 proutn(_("Emergency override attempts t"))
2964 prouts("***************")
2969 # destroy any Klingons in supernovaed quadrant
2970 kldead = game.state.galaxy[nq.x][nq.y].klingons
2971 game.state.galaxy[nq.x][nq.y].klingons = 0
2972 if nq == game.state.kscmdr:
2973 # did in the Supercommander!
2974 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2978 if game.state.remcom:
2979 maxloop = game.state.remcom
2980 for l in range(maxloop):
2981 if game.state.kcmdr[l] == nq:
2982 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
2983 invalidate(game.state.kcmdr[game.state.remcom])
2984 game.state.remcom -= 1
2986 if game.state.remcom==0:
2989 game.state.remkl -= kldead
2990 # destroy Romulans and planets in supernovaed quadrant
2991 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
2992 game.state.galaxy[nq.x][nq.y].romulans = 0
2993 game.state.nromrem -= nrmdead
2995 for loop in range(game.inplan):
2996 if game.state.planets[loop].w == nq:
2997 game.state.planets[loop].pclass = "destroyed"
2999 # Destroy any base in supernovaed quadrant
3000 if game.state.rembase:
3001 maxloop = game.state.rembase
3002 for loop in range(maxloop):
3003 if game.state.baseq[loop] == nq:
3004 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3005 invalidate(game.state.baseq[game.state.rembase])
3006 game.state.rembase -= 1
3008 # If starship caused supernova, tally up destruction
3010 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3011 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3012 game.state.nplankl += npdead
3013 # mark supernova in galaxy and in star chart
3014 if game.quadrant == nq or communicating():
3015 game.state.galaxy[nq.x][nq.y].supernova = True
3016 # If supernova destroys last Klingons give special message
3017 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3020 prout(_("Lucky you!"))
3021 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3024 # if some Klingons remain, continue or die in supernova
3029 # Code from finish.c ends here.
3032 # self-destruct maneuver
3033 # Finish with a BANG!
3035 if damaged(DCOMPTR):
3036 prout(_("Computer damaged; cannot execute destruct sequence."))
3038 prouts(_("---WORKING---")); skip(1)
3039 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3040 prouts(" 10"); skip(1)
3041 prouts(" 9"); skip(1)
3042 prouts(" 8"); skip(1)
3043 prouts(" 7"); skip(1)
3044 prouts(" 6"); skip(1)
3046 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3048 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3050 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3054 if game.passwd != citem:
3055 prouts(_("PASSWORD-REJECTED;"))
3057 prouts(_("CONTINUITY-EFFECTED"))
3060 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3061 prouts(" 5"); skip(1)
3062 prouts(" 4"); skip(1)
3063 prouts(" 3"); skip(1)
3064 prouts(" 2"); skip(1)
3065 prouts(" 1"); skip(1)
3066 if random.random() < 0.15:
3067 prouts(_("GOODBYE-CRUEL-WORLD"))
3075 prouts(_("********* Entropy of "))
3077 prouts(_(" maximized *********"))
3081 if game.nenhere != 0:
3082 whammo = 25.0 * game.energy
3084 while l <= game.nenhere:
3085 if game.kpower[l]*game.kdist[l] <= whammo:
3086 deadkl(game.ks[l], game.quad[game.ks[l].x][game.ks[l].y], game.ks[l])
3091 "Compute our rate of kils over time."
3092 elapsed = game.state.date - game.indate
3093 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3096 starting = (game.inkling + game.incom + game.inscom)
3097 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3098 return (starting - remaining)/elapsed
3102 badpt = 5.0*game.state.starkl + \
3104 10.0*game.state.nplankl + \
3105 300*game.state.nworldkl + \
3107 100.0*game.state.basekl +\
3109 if game.ship == IHF:
3111 elif game.ship == None:
3116 # end the game, with appropriate notfications
3120 prout(_("It is stardate %.1f.") % game.state.date)
3122 if ifin == FWON: # Game has been won
3123 if game.state.nromrem != 0:
3124 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3127 prout(_("You have smashed the Klingon invasion fleet and saved"))
3128 prout(_("the Federation."))
3133 badpt = 0.0 # Close enough!
3134 # killsPerDate >= RateMax
3135 if game.state.date-game.indate < 5.0 or \
3136 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3138 prout(_("In fact, you have done so well that Starfleet Command"))
3139 if game.skill == SKILL_NOVICE:
3140 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3141 elif game.skill == SKILL_FAIR:
3142 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3143 elif game.skill == SKILL_GOOD:
3144 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3145 elif game.skill == SKILL_EXPERT:
3146 prout(_("promotes you to Commodore Emeritus."))
3148 prout(_("Now that you think you're really good, try playing"))
3149 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3150 elif game.skill == SKILL_EMERITUS:
3152 proutn(_("Computer- "))
3153 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3155 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3157 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3159 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3161 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3163 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3165 prout(_("Now you can retire and write your own Star Trek game!"))
3167 elif game.skill >= SKILL_EXPERT:
3168 if game.thawed and not idebug:
3169 prout(_("You cannot get a citation, so..."))
3171 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3175 # Only grant long life if alive (original didn't!)
3177 prout(_("LIVE LONG AND PROSPER."))
3182 elif ifin == FDEPLETE: # Federation Resources Depleted
3183 prout(_("Your time has run out and the Federation has been"))
3184 prout(_("conquered. Your starship is now Klingon property,"))
3185 prout(_("and you are put on trial as a war criminal. On the"))
3186 proutn(_("basis of your record, you are "))
3187 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3188 prout(_("acquitted."))
3190 prout(_("LIVE LONG AND PROSPER."))
3192 prout(_("found guilty and"))
3193 prout(_("sentenced to death by slow torture."))
3197 elif ifin == FLIFESUP:
3198 prout(_("Your life support reserves have run out, and"))
3199 prout(_("you die of thirst, starvation, and asphyxiation."))
3200 prout(_("Your starship is a derelict in space."))
3202 prout(_("Your energy supply is exhausted."))
3204 prout(_("Your starship is a derelict in space."))
3205 elif ifin == FBATTLE:
3208 prout(_("has been destroyed in battle."))
3210 prout(_("Dulce et decorum est pro patria mori."))
3212 prout(_("You have made three attempts to cross the negative energy"))
3213 prout(_("barrier which surrounds the galaxy."))
3215 prout(_("Your navigation is abominable."))
3218 prout(_("Your starship has been destroyed by a nova."))
3219 prout(_("That was a great shot."))
3221 elif ifin == FSNOVAED:
3224 prout(_(" has been fried by a supernova."))
3225 prout(_("...Not even cinders remain..."))
3226 elif ifin == FABANDN:
3227 prout(_("You have been captured by the Klingons. If you still"))
3228 prout(_("had a starbase to be returned to, you would have been"))
3229 prout(_("repatriated and given another chance. Since you have"))
3230 prout(_("no starbases, you will be mercilessly tortured to death."))
3231 elif ifin == FDILITHIUM:
3232 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3233 elif ifin == FMATERIALIZE:
3234 prout(_("Starbase was unable to re-materialize your starship."))
3235 prout(_("Sic transit gloria mundi"))
3236 elif ifin == FPHASER:
3239 prout(_(" has been cremated by its own phasers."))
3241 prout(_("You and your landing party have been"))
3242 prout(_("converted to energy, disipating through space."))
3243 elif ifin == FMINING:
3244 prout(_("You are left with your landing party on"))
3245 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3247 prout(_("They are very fond of \"Captain Kirk\" soup."))
3249 proutn(_("Without your leadership, the "))
3251 prout(_(" is destroyed."))
3252 elif ifin == FDPLANET:
3253 prout(_("You and your mining party perish."))
3255 prout(_("That was a great shot."))
3258 prout(_("The Galileo is instantly annihilated by the supernova."))
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 == FPNOVA:
3266 prout(_("You and your mining party are atomized."))
3268 proutn(_("Mr. Spock takes command of the "))
3271 prout(_("joins the Romulans, reigning terror on the Federation."))
3272 elif ifin == FSTRACTOR:
3273 prout(_("The shuttle craft Galileo is also caught,"))
3274 prout(_("and breaks up under the strain."))
3276 prout(_("Your debris is scattered for millions of miles."))
3277 proutn(_("Without your leadership, the "))
3279 prout(_(" is destroyed."))
3281 prout(_("The mutants attack and kill Spock."))
3282 prout(_("Your ship is captured by Klingons, and"))
3283 prout(_("your crew is put on display in a Klingon zoo."))
3284 elif ifin == FTRIBBLE:
3285 prout(_("Tribbles consume all remaining water,"))
3286 prout(_("food, and oxygen on your ship."))
3288 prout(_("You die of thirst, starvation, and asphyxiation."))
3289 prout(_("Your starship is a derelict in space."))
3291 prout(_("Your ship is drawn to the center of the black hole."))
3292 prout(_("You are crushed into extremely dense matter."))
3294 prout(_("Your last crew member has died."))
3295 if game.ship == IHF:
3297 elif game.ship == IHE:
3300 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3301 goodies = game.state.remres/game.inresor
3302 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3303 if goodies/baddies >= 1.0+0.5*random.random():
3304 prout(_("As a result of your actions, a treaty with the Klingon"))
3305 prout(_("Empire has been signed. The terms of the treaty are"))
3306 if goodies/baddies >= 3.0+random.random():
3307 prout(_("favorable to the Federation."))
3309 prout(_("Congratulations!"))
3311 prout(_("highly unfavorable to the Federation."))
3313 prout(_("The Federation will be destroyed."))
3315 prout(_("Since you took the last Klingon with you, you are a"))
3316 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3317 prout(_("statue in your memory. Rest in peace, and try not"))
3318 prout(_("to think about pigeons."))
3323 # compute player's score
3324 timused = game.state.date - game.indate
3326 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3328 perdate = killrate()
3329 ithperd = 500*perdate + 0.5
3332 iwon = 100*game.skill
3333 if game.ship == IHE:
3335 elif game.ship == IHF:
3339 if not game.gamewon:
3340 game.state.nromrem = 0 # None captured if no win
3341 iscore = 10*(game.inkling - game.state.remkl) \
3342 + 50*(game.incom - game.state.remcom) \
3344 + 20*(game.inrom - game.state.nromrem) \
3345 + 200*(game.inscom - game.state.nscrem) \
3346 - game.state.nromrem \
3351 prout(_("Your score --"))
3352 if game.inrom - game.state.nromrem:
3353 prout(_("%6d Romulans destroyed %5d") %
3354 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3355 if game.state.nromrem:
3356 prout(_("%6d Romulans captured %5d") %
3357 (game.state.nromrem, game.state.nromrem))
3358 if game.inkling - game.state.remkl:
3359 prout(_("%6d ordinary Klingons destroyed %5d") %
3360 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3361 if game.incom - game.state.remcom:
3362 prout(_("%6d Klingon commanders destroyed %5d") %
3363 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3364 if game.inscom - game.state.nscrem:
3365 prout(_("%6d Super-Commander destroyed %5d") %
3366 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3368 prout(_("%6.2f Klingons per stardate %5d") %
3370 if game.state.starkl:
3371 prout(_("%6d stars destroyed by your action %5d") %
3372 (game.state.starkl, -5*game.state.starkl))
3373 if game.state.nplankl:
3374 prout(_("%6d planets destroyed by your action %5d") %
3375 (game.state.nplankl, -10*game.state.nplankl))
3376 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3377 prout(_("%6d inhabited planets destroyed by your action %5d") %
3378 (game.state.nplankl, -300*game.state.nworldkl))
3379 if game.state.basekl:
3380 prout(_("%6d bases destroyed by your action %5d") %
3381 (game.state.basekl, -100*game.state.basekl))
3383 prout(_("%6d calls for help from starbase %5d") %
3384 (game.nhelp, -45*game.nhelp))
3386 prout(_("%6d casualties incurred %5d") %
3387 (game.casual, -game.casual))
3389 prout(_("%6d crew abandoned in space %5d") %
3390 (game.abandoned, -3*game.abandoned))
3392 prout(_("%6d ship(s) lost or destroyed %5d") %
3393 (klship, -100*klship))
3395 prout(_("Penalty for getting yourself killed -200"))
3397 proutn(_("Bonus for winning "))
3398 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3399 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3400 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3401 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3402 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3403 prout(" %5d" % iwon)
3405 prout(_("TOTAL SCORE %5d") % iscore)
3408 # emit winner's commemmorative plaque
3411 proutn(_("File or device name for your plaque: "))
3414 fp = open(winner, "w")
3417 prout(_("Invalid name."))
3419 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3421 # The 38 below must be 64 for 132-column paper
3422 nskip = 38 - len(winner)/2
3423 fp.write("\n\n\n\n")
3424 # --------DRAW ENTERPRISE PICTURE.
3425 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3426 fp.write(" EEE E : : : E\n" )
3427 fp.write(" EE EEE E : : NCC-1701 : E\n")
3428 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3429 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3430 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3431 fp.write(" EEEEEEE EEEEE E E E E\n")
3432 fp.write(" EEE E E E E\n")
3433 fp.write(" E E E E\n")
3434 fp.write(" EEEEEEEEEEEEE E E\n")
3435 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3436 fp.write(" :E : EEEE E\n")
3437 fp.write(" .-E -:----- E\n")
3438 fp.write(" :E : E\n")
3439 fp.write(" EE : EEEEEEEE\n")
3440 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3442 fp.write(_(" U. S. S. ENTERPRISE\n"))
3443 fp.write("\n\n\n\n")
3444 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3446 fp.write(_(" Starfleet Command bestows to you\n"))
3448 fp.write("%*s%s\n\n" % (nskip, "", winner))
3449 fp.write(_(" the rank of\n\n"))
3450 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3452 if game.skill == SKILL_EXPERT:
3453 fp.write(_(" Expert level\n\n"))
3454 elif game.skill == SKILL_EMERITUS:
3455 fp.write(_("Emeritus level\n\n"))
3457 fp.write(_(" Cheat level\n\n"))
3458 timestring = ctime()
3459 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3460 (timestring+4, timestring+20, timestring+11))
3461 fp.write(_(" Your score: %d\n\n") % iscore)
3462 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3465 # Code from io.c begins here
3467 rows = linecount = 0 # for paging
3470 fullscreen_window = None
3471 srscan_window = None
3472 report_window = None
3473 status_window = None
3474 lrscan_window = None
3475 message_window = None
3476 prompt_window = None
3480 "wrap up, either normally or due to signal"
3481 if game.options & OPTION_CURSES:
3488 sys.stdout.write('\n')
3494 #setlocale(LC_ALL, "")
3495 #bindtextdomain(PACKAGE, LOCALEDIR)
3496 #textdomain(PACKAGE)
3497 if atexit.register(outro):
3498 sys.stderr.write("Unable to register outro(), exiting...\n")
3500 if not (game.options & OPTION_CURSES):
3501 ln_env = os.getenv("LINES")
3507 stdscr = curses.initscr()
3512 curses.start_color()
3513 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3514 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3515 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3516 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3517 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3518 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3519 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3520 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3522 global fullscreen_window, srscan_window, report_window, status_window
3523 global lrscan_window, message_window, prompt_window
3524 fullscreen_window = stdscr
3525 srscan_window = curses.newwin(12, 25, 0, 0)
3526 report_window = curses.newwin(11, 0, 1, 25)
3527 status_window = curses.newwin(10, 0, 1, 39)
3528 lrscan_window = curses.newwin(5, 0, 0, 64)
3529 message_window = curses.newwin(0, 0, 12, 0)
3530 prompt_window = curses.newwin(1, 0, rows-2, 0)
3531 message_window.scrollok(True)
3532 setwnd(fullscreen_window)
3536 "wait for user action -- OK to do nothing if on a TTY"
3537 if game.options & OPTION_CURSES:
3542 if game.skill > SKILL_FAIR:
3543 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3545 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3549 if game.skill > SKILL_FAIR:
3550 prompt = _("[CONTINUE?]")
3552 prompt = _("[PRESS ENTER TO CONTINUE]")
3554 if game.options & OPTION_CURSES:
3556 setwnd(prompt_window)
3557 prompt_window.wclear()
3558 prompt_window.addstr(prompt)
3559 prompt_window.getstr()
3560 prompt_window.clear()
3561 prompt_window.refresh()
3562 setwnd(message_window)
3565 sys.stdout.write('\n')
3568 for j in range(rows):
3569 sys.stdout.write('\n')
3573 "Skip i lines. Pause game if this would cause a scrolling event."
3574 for dummy in range(i):
3575 if game.options & OPTION_CURSES:
3576 (y, x) = curwnd.getyx()
3577 (my, mx) = curwnd.getmaxyx()
3578 if curwnd == message_window and y >= my - 3:
3586 if rows and linecount >= rows:
3589 sys.stdout.write('\n')
3592 "Utter a line with no following line feed."
3593 if game.options & OPTION_CURSES:
3597 sys.stdout.write(line)
3609 if game.options & OPTION_CURSES:
3616 "Get a line of input."
3617 if game.options & OPTION_CURSES:
3618 line = curwnd.getstr() + "\n"
3621 if replayfp and not replayfp.closed:
3622 line = replayfp.readline()
3624 prout("*** Replay finished")
3627 line = raw_input("COMMAND> ")
3629 logfp.write(line + "\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)
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.ks[m])
3826 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3827 game.kdist[m] = finald
3829 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3831 for m in range(game.nenhere):
3832 game.kavgd[m] = game.kdist[m]
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.ks[m])
3873 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
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 ram(False, iquad, game.sector)
3941 elif iquad == IHBLANK:
3943 prouts(_("***RED ALERT! RED ALERT!"))
3947 proutn(_(" pulled into black hole at Sector %s") % w)
3949 # Getting pulled into a black hole was certain
3950 # death in Almy's original. Stas Sergeev added a
3951 # possibility that you'll get timewarped instead.
3954 for m in range(NDEVICES):
3955 if game.damage[m]>0:
3957 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3958 if (game.options & OPTION_BLKHOLE) and random.random()>probf:
3968 proutn(_(" encounters Tholian web at %s;") % w)
3970 proutn(_(" blocked by object at %s;") % w)
3971 proutn(_("Emergency stop required "))
3972 prout(_("%2d units of energy.") % int(stopegy))
3973 game.energy -= stopegy
3974 final.x = x-deltax+0.5
3975 final.y = y-deltay+0.5
3977 if game.energy <= 0:
3983 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3990 # dock our ship at a starbase
3992 if game.condition == "docked" and verbose:
3993 prout(_("Already docked."))
3996 prout(_("You must first leave standard orbit."))
3998 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4000 prout(_(" not adjacent to base."))
4002 game.condition = "docked"
4006 if game.energy < game.inenrg:
4007 game.energy = game.inenrg
4008 game.shield = game.inshld
4009 game.torps = game.intorps
4010 game.lsupres = game.inlsr
4011 game.state.crew = FULLCREW
4012 if not damaged(DRADIO) and \
4013 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4014 # get attack report from base
4015 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4019 # This program originally required input in terms of a (clock)
4020 # direction and distance. Somewhere in history, it was changed to
4021 # cartesian coordinates. So we need to convert. Probably
4022 # "manual" input should still be done this way -- it's a real
4023 # pain if the computer isn't working! Manual mode is still confusing
4024 # because it involves giving x and y motions, yet the coordinates
4025 # are always displayed y - x, where +y is downward!
4027 def getcourse(isprobe, akey):
4028 # get course and distance
4030 dquad = copy.copy(game.quadrant)
4031 navmode = "unspecified"
4035 if game.landed and not isprobe:
4036 prout(_("Dummy! You can't leave standard orbit until you"))
4037 proutn(_("are back aboard the ship."))
4040 while navmode == "unspecified":
4041 if damaged(DNAVSYS):
4043 prout(_("Computer damaged; manual navigation only"))
4045 prout(_("Computer damaged; manual movement only"))
4050 if isprobe and akey != -1:
4051 # For probe launch, use pre-scanned value first time
4057 proutn(_("Manual or automatic- "))
4060 elif key == IHALPHA:
4065 elif isit("automatic"):
4066 navmode = "automatic"
4075 prout(_("(Manual navigation assumed.)"))
4077 prout(_("(Manual movement assumed.)"))
4080 if navmode == "automatic":
4083 proutn(_("Target quadrant or quadrant§or- "))
4085 proutn(_("Destination sector or quadrant§or- "))
4092 xi = int(round(aaitem))-1
4097 xj = int(round(aaitem))-1
4100 # both quadrant and sector specified
4101 xk = int(round(aaitem))-1
4106 xl = int(round(aaitem))-1
4112 # only one pair of numbers was specified
4114 # only quadrant specified -- go to center of dest quad
4117 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4119 # only sector specified
4123 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4130 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4132 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4133 # the actual deltas get computed here
4134 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4135 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4138 proutn(_("X and Y displacements- "))
4152 # Check for zero movement
4153 if deltax == 0 and deltay == 0:
4156 if itemp == "verbose" and not isprobe:
4158 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4159 # Course actually laid in.
4160 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4161 game.direc = math.atan2(deltax, deltay)*1.90985932
4162 if game.direc < 0.0:
4168 # move under impulse power
4170 if damaged(DIMPULS):
4173 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4175 if game.energy > 30.0:
4176 if not getcourse(isprobe=False, akey=0):
4178 power = 20.0 + 100.0*game.dist
4181 if power >= game.energy:
4182 # Insufficient power for trip
4184 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4185 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4186 if game.energy > 30:
4187 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4188 int(0.01 * (game.energy-20.0)-0.05))
4189 prout(_(" quadrants.\""))
4191 prout(_("quadrant. They are, therefore, useless.\""))
4194 # Make sure enough time is left for the trip
4195 game.optime = game.dist/0.095
4196 if game.optime >= game.state.remtime:
4197 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4198 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4199 proutn(_("we dare spend the time?\" "))
4202 # Activate impulse engines and pay the cost
4203 imove(novapush=False)
4207 power = 20.0 + 100.0*game.dist
4208 game.energy -= power
4209 game.optime = game.dist/0.095
4210 if game.energy <= 0:
4215 # move under warp drive
4216 blooey = False; twarp = False
4217 if not timewarp: # Not WARPX entry
4219 if game.damage[DWARPEN] > 10.0:
4222 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4224 if damaged(DWARPEN) and game.warpfac > 4.0:
4227 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4228 prout(_(" is repaired, I can only give you warp 4.\""))
4230 # Read in course and distance
4231 if not getcourse(isprobe=False, akey=0):
4233 # Make sure starship has enough energy for the trip
4234 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4235 if power >= game.energy:
4236 # Insufficient power for trip
4239 prout(_("Engineering to bridge--"))
4240 if not game.shldup or 0.5*power > game.energy:
4241 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4243 prout(_("We can't do it, Captain. We don't have enough energy."))
4245 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4248 prout(_("if you'll lower the shields."))
4252 prout(_("We haven't the energy to go that far with the shields up."))
4255 # Make sure enough time is left for the trip
4256 game.optime = 10.0*game.dist/game.wfacsq
4257 if game.optime >= 0.8*game.state.remtime:
4259 prout(_("First Officer Spock- \"Captain, I compute that such"))
4260 proutn(_(" a trip would require approximately %2.0f") %
4261 (100.0*game.optime/game.state.remtime))
4262 prout(_(" percent of our"))
4263 proutn(_(" remaining time. Are you sure this is wise?\" "))
4269 if game.warpfac > 6.0:
4270 # Decide if engine damage will occur
4271 prob = game.dist*(6.0-game.warpfac)*(6.0-game.warpfac)/66.666666666
4272 if prob > random.random():
4274 game.dist = random.random()*game.dist
4275 # Decide if time warp will occur
4276 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > random.random():
4278 if idebug and game.warpfac==10 and not twarp:
4280 proutn("=== Force time warp? ")
4284 # If time warp or engine damage, check path
4285 # If it is obstructed, don't do warp or damage
4286 angle = ((15.0-game.direc)*0.5235998)
4287 deltax = -math.sin(angle)
4288 deltay = math.cos(angle)
4289 if math.fabs(deltax) > math.fabs(deltay):
4290 bigger = math.fabs(deltax)
4292 bigger = math.fabs(deltay)
4296 n = 10.0 * game.dist * bigger +0.5
4299 for l in range(1, n+1):
4304 if not VALID_SECTOR(ix, iy):
4306 if game.quad[ix][iy] != IHDOT:
4309 # Activate Warp Engines and pay the cost
4310 imove(novapush=False)
4313 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4314 if game.energy <= 0:
4316 game.optime = 10.0*game.dist/game.wfacsq
4320 game.damage[DWARPEN] = game.damfac*(3.0*random.random()+1.0)
4322 prout(_("Engineering to bridge--"))
4323 prout(_(" Scott here. The warp engines are damaged."))
4324 prout(_(" We'll have to reduce speed to warp 4."))
4329 # change the warp factor
4335 proutn(_("Warp factor- "))
4340 if game.damage[DWARPEN] > 10.0:
4341 prout(_("Warp engines inoperative."))
4343 if damaged(DWARPEN) and aaitem > 4.0:
4344 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4345 prout(_(" but right now we can only go warp 4.\""))
4348 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4351 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4353 oldfac = game.warpfac
4354 game.warpfac = aaitem
4355 game.wfacsq=game.warpfac*game.warpfac
4356 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4357 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4360 if game.warpfac < 8.00:
4361 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4363 if game.warpfac == 10.0:
4364 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4366 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4370 # cope with being tossed out of quadrant by supernova or yanked by beam
4372 # is captain on planet?
4374 if damaged(DTRANSP):
4377 prout(_("Scotty rushes to the transporter controls."))
4379 prout(_("But with the shields up it's hopeless."))
4381 prouts(_("His desperate attempt to rescue you . . ."))
4382 if random.random() <= 0.5:
4386 prout(_("SUCCEEDS!"))
4389 proutn(_("The crystals mined were "))
4390 if random.random() <= 0.25:
4397 # Check to see if captain in shuttle craft
4402 # Inform captain of attempt to reach safety
4406 prouts(_("***RED ALERT! RED ALERT!"))
4410 prout(_(" has stopped in a quadrant containing"))
4411 prouts(_(" a supernova."))
4413 proutn(_("***Emergency automatic override attempts to hurl "))
4416 prout(_("safely out of quadrant."))
4417 if not damaged(DRADIO):
4418 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4419 # Try to use warp engines
4420 if damaged(DWARPEN):
4422 prout(_("Warp engines damaged."))
4425 game.warpfac = 6.0+2.0*random.random()
4426 game.wfacsq = game.warpfac * game.warpfac
4427 prout(_("Warp factor set to %d") % int(game.warpfac))
4428 power = 0.75*game.energy
4429 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4430 distreq = 1.4142+random.random()
4431 if distreq < game.dist:
4433 game.optime = 10.0*game.dist/game.wfacsq
4434 game.direc = 12.0*random.random() # How dumb!
4436 game.inorbit = False
4439 # This is bad news, we didn't leave quadrant.
4443 prout(_("Insufficient energy to leave quadrant."))
4446 # Repeat if another snova
4447 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4449 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4450 finish(FWON) # Snova killed remaining enemy.
4453 # let's do the time warp again
4454 prout(_("***TIME WARP ENTERED."))
4455 if game.state.snap and random.random() < 0.5:
4457 prout(_("You are traveling backwards in time %d stardates.") %
4458 int(game.state.date-game.snapsht.date))
4459 game.state = game.snapsht
4460 game.state.snap = False
4461 if game.state.remcom:
4462 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4463 schedule(FBATTAK, expran(0.3*game.intime))
4464 schedule(FSNOVA, expran(0.5*game.intime))
4465 # next snapshot will be sooner
4466 schedule(FSNAP, expran(0.25*game.state.remtime))
4468 if game.state.nscrem:
4469 schedule(FSCMOVE, 0.2777)
4473 invalidate(game.battle)
4475 # Make sure Galileo is consistant -- Snapshot may have been taken
4476 # when on planet, which would give us two Galileos!
4478 for l in range(game.inplan):
4479 if game.state.planets[l].known == "shuttle_down":
4481 if game.iscraft == "onship" and game.ship==IHE:
4482 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4483 game.iscraft = "offship"
4484 # Likewise, if in the original time the Galileo was abandoned, but
4485 # was on ship earlier, it would have vanished -- let's restore it.
4486 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4487 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4488 game.iscraft = "onship"
4490 # * There used to be code to do the actual reconstrction here,
4491 # * but the starchart is now part of the snapshotted galaxy state.
4493 prout(_("Spock has reconstructed a correct star chart from memory"))
4495 # Go forward in time
4496 game.optime = -0.5*game.intime*math.log(random.random())
4497 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4498 # cheat to make sure no tractor beams occur during time warp
4499 postpone(FTBEAM, game.optime)
4500 game.damage[DRADIO] += game.optime
4502 events() # Stas Sergeev added this -- do pending events
4505 # launch deep-space probe
4506 # New code to launch a deep space probe
4507 if game.nprobes == 0:
4510 if game.ship == IHE:
4511 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4513 prout(_("Ye Faerie Queene has no deep space probes."))
4518 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4520 if is_scheduled(FDSPROB):
4523 if damaged(DRADIO) and game.condition != "docked":
4524 prout(_("Spock- \"Records show the previous probe has not yet"))
4525 prout(_(" reached its destination.\""))
4527 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4531 # slow mode, so let Kirk know how many probes there are left
4532 if game.nprobes == 1:
4533 prout(_("1 probe left."))
4535 prout(_("%d probes left") % game.nprobes)
4536 proutn(_("Are you sure you want to fire a probe? "))
4539 game.isarmed = False
4540 if key == IHALPHA and citem == "armed":
4544 proutn(_("Arm NOVAMAX warhead? "))
4546 if not getcourse(isprobe=True, akey=key):
4549 angle = ((15.0 - game.direc) * 0.5235988)
4550 game.probeinx = -math.sin(angle)
4551 game.probeiny = math.cos(angle)
4552 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4553 bigger = math.fabs(game.probeinx)
4555 bigger = math.fabs(game.probeiny)
4556 game.probeiny /= bigger
4557 game.probeinx /= bigger
4558 game.proben = 10.0*game.dist*bigger +0.5
4559 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4560 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4561 game.probec = game.quadrant
4562 schedule(FDSPROB, 0.01) # Time to move one sector
4563 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4567 # Here's how the mayday code works:
4569 # First, the closest starbase is selected. If there is a a starbase
4570 # in your own quadrant, you are in good shape. This distance takes
4571 # quadrant distances into account only.
4573 # A magic number is computed based on the distance which acts as the
4574 # probability that you will be rematerialized. You get three tries.
4576 # When it is determined that you should be able to be rematerialized
4577 # (i.e., when the probability thing mentioned above comes up
4578 # positive), you are put into that quadrant (anywhere). Then, we try
4579 # to see if there is a spot adjacent to the star- base. If not, you
4580 # can't be rematerialized!!! Otherwise, it drops you there. It only
4581 # tries five times to find a spot to drop you. After that, it's your
4585 # yell for help from nearest starbase
4586 # There's more than one way to move in this game!
4589 # Test for conditions which prevent calling for help
4590 if game.condition == "docked":
4591 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4594 prout(_("Subspace radio damaged."))
4596 if game.state.rembase==0:
4597 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4600 proutn(_("You must be aboard the "))
4604 # OK -- call for help from nearest starbase
4607 # There's one in this quadrant
4608 ddist = distance(game.base, game.sector)
4611 for m in range(game.state.rembase):
4612 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4616 # Since starbase not in quadrant, set up new quadrant
4617 game.quadrant = game.state.baseq[line]
4619 # dematerialize starship
4620 game.quad[game.sector.x][game.sector.y]=IHDOT
4621 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4623 prout(_(" dematerializes."))
4625 for m in range(1, 5+1):
4626 ix = game.base.x+3.0*random.random()-1
4627 iy = game.base.y+3.0*random.random()-1
4628 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4629 # found one -- finish up
4633 if not is_valid(game.sector):
4634 prout(_("You have been lost in space..."))
4635 finish(FMATERIALIZE)
4637 # Give starbase three chances to rematerialize starship
4638 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4639 for m in range(1, 3+1):
4640 if m == 1: proutn(_("1st"))
4641 elif m == 2: proutn(_("2nd"))
4642 elif m == 3: proutn(_("3rd"))
4643 proutn(_(" attempt to re-materialize "))
4645 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4648 if random.random() > probf:
4651 curses.delay_output(500)
4654 game.quad[ix][iy]=IHQUEST
4657 setwnd(message_window)
4658 finish(FMATERIALIZE)
4660 game.quad[ix][iy]=game.ship
4662 prout(_("succeeds."))
4666 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4668 # Abandon Ship (the BSD-Trek description)
4670 # The ship is abandoned. If your current ship is the Faire
4671 # Queene, or if your shuttlecraft is dead, you're out of
4672 # luck. You need the shuttlecraft in order for the captain
4673 # (that's you!!) to escape.
4675 # Your crew can beam to an inhabited starsystem in the
4676 # quadrant, if there is one and if the transporter is working.
4677 # If there is no inhabited starsystem, or if the transporter
4678 # is out, they are left to die in outer space.
4680 # If there are no starbases left, you are captured by the
4681 # Klingons, who torture you mercilessly. However, if there
4682 # is at least one starbase, you are returned to the
4683 # Federation in a prisoner of war exchange. Of course, this
4684 # can't happen unless you have taken some prisoners.
4689 if game.condition=="docked":
4691 prout(_("You cannot abandon Ye Faerie Queene."))
4694 # Must take shuttle craft to exit
4695 if game.damage[DSHUTTL]==-1:
4696 prout(_("Ye Faerie Queene has no shuttle craft."))
4698 if game.damage[DSHUTTL]<0:
4699 prout(_("Shuttle craft now serving Big Macs."))
4701 if game.damage[DSHUTTL]>0:
4702 prout(_("Shuttle craft damaged."))
4705 prout(_("You must be aboard the ship."))
4707 if game.iscraft != "onship":
4708 prout(_("Shuttle craft not currently available."))
4710 # Print abandon ship messages
4712 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4714 prouts(_("***ALL HANDS ABANDON SHIP!"))
4716 prout(_("Captain and crew escape in shuttle craft."))
4717 if game.state.rembase==0:
4718 # Oops! no place to go...
4721 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4723 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4724 prout(_("Remainder of ship's complement beam down"))
4725 prout(_("to nearest habitable planet."))
4726 elif q.planet != None and not damaged(DTRANSP):
4727 prout(_("Remainder of ship's complement beam down to %s.") %
4730 prout(_("Entire crew of %d left to die in outer space.") %
4732 game.casual += game.state.crew
4733 game.abandoned += game.state.crew
4735 # If at least one base left, give 'em the Faerie Queene
4737 game.icrystl = False # crystals are lost
4738 game.nprobes = 0 # No probes
4739 prout(_("You are captured by Klingons and released to"))
4740 prout(_("the Federation in a prisoner-of-war exchange."))
4741 nb = random.random()*game.state.rembase+1
4742 # Set up quadrant and position FQ adjacient to base
4743 if not game.quadrant == game.state.baseq[nb]:
4744 game.quadrant = game.state.baseq[nb]
4745 game.sector.x = game.sector.y = 5
4748 # position next to base by trial and error
4749 game.quad[game.sector.x][game.sector.y] = IHDOT
4750 for l in range(QUADSIZE):
4751 game.sector.x = 3.0*random.random() - 1.0 + game.base.x
4752 game.sector.y = 3.0*random.random() - 1.0 + game.base.y
4753 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4754 game.quad[game.sector.x][game.sector.y] == IHDOT:
4757 break # found a spot
4758 game.sector.x=QUADSIZE/2
4759 game.sector.y=QUADSIZE/2
4761 # Get new commission
4762 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4763 game.state.crew = FULLCREW
4764 prout(_("Starfleet puts you in command of another ship,"))
4765 prout(_("the Faerie Queene, which is antiquated but,"))
4766 prout(_("still useable."))
4768 prout(_("The dilithium crystals have been moved."))
4770 game.iscraft = "offship" # Galileo disappears
4772 game.condition="docked"
4773 for l in range(NDEVICES):
4774 game.damage[l] = 0.0
4775 game.damage[DSHUTTL] = -1
4776 game.energy = game.inenrg = 3000.0
4777 game.shield = game.inshld = 1250.0
4778 game.torps = game.intorps = 6
4779 game.lsupres=game.inlsr=3.0
4785 # Code from planets.c begins here.
4788 # abort a lengthy operation if an event interrupts it
4791 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4796 # report on (uninhabited) planets in the galaxy
4800 prout(_("Spock- \"Planet report follows, Captain.\""))
4802 for i in range(game.inplan):
4803 if game.state.planets[i].pclass == "destroyed":
4805 if (game.state.planets[i].known != "unknown" \
4806 and not game.state.planets[i].inhabited) \
4809 if idebug and game.state.planets[i].known=="unknown":
4810 proutn("(Unknown) ")
4811 proutn(_("Quadrant %s") % game.state.planets[i].w)
4812 proutn(_(" class "))
4813 proutn(game.state.planets[i].pclass)
4815 if game.state.planets[i].crystals != present:
4817 prout(_("dilithium crystals present."))
4818 if game.state.planets[i].known=="shuttle_down":
4819 prout(_(" Shuttle Craft Galileo on surface."))
4821 prout(_("No information available."))
4824 # enter standard orbit
4828 prout(_("Already in standard orbit."))
4830 if damaged(DWARPEN) and damaged(DIMPULS):
4831 prout(_("Both warp and impulse engines damaged."))
4833 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4835 prout(_(" not adjacent to planet."))
4838 game.optime = 0.02+0.03*random.random()
4839 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4843 game.height = (1400.0+7200.0*random.random())
4844 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4849 # examine planets in this quadrant
4850 if damaged(DSRSENS):
4851 if game.options & OPTION_TTY:
4852 prout(_("Short range sensors damaged."))
4854 if game.iplnet == None:
4855 if game.options & OPTION_TTY:
4856 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4858 if game.iplnet.known == "unknown":
4859 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4861 prout(_(" Planet at Sector %s is of class %s.") %
4862 (game.plnet, game.iplnet.pclass))
4863 if game.iplnet.known=="shuttle_down":
4864 prout(_(" Sensors show Galileo still on surface."))
4865 proutn(_(" Readings indicate"))
4866 if game.iplnet.crystals != "present":
4868 prout(_(" dilithium crystals present.\""))
4869 if game.iplnet.known == "unknown":
4870 game.iplnet.known = "known"
4871 elif game.iplnet.inhabited:
4872 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4873 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4876 # use the transporter
4880 if damaged(DTRANSP):
4881 prout(_("Transporter damaged."))
4882 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4884 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4888 if not game.inorbit:
4890 prout(_(" not in standard orbit."))
4893 prout(_("Impossible to transport through shields."))
4895 if game.iplnet.known=="unknown":
4896 prout(_("Spock- \"Captain, we have no information on this planet"))
4897 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4898 prout(_(" you may not go down.\""))
4900 if not game.landed and game.iplnet.crystals=="absent":
4901 prout(_("Spock- \"Captain, I fail to see the logic in"))
4902 prout(_(" exploring a planet with no dilithium crystals."))
4903 proutn(_(" Are you sure this is wise?\" "))
4907 if not (game.options & OPTION_PLAIN):
4908 nrgneed = 50 * game.skill + game.height / 100.0
4909 if nrgneed > game.energy:
4910 prout(_("Engineering to bridge--"))
4911 prout(_(" Captain, we don't have enough energy for transportation."))
4913 if not game.landed and nrgneed * 2 > game.energy:
4914 prout(_("Engineering to bridge--"))
4915 prout(_(" Captain, we have enough energy only to transport you down to"))
4916 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4917 if game.iplnet.known == "shuttle_down":
4918 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4919 proutn(_(" Are you sure this is wise?\" "))
4924 # Coming from planet
4925 if game.iplnet.known=="shuttle_down":
4926 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4930 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4931 prout(_("Landing party assembled, ready to beam up."))
4933 prout(_("Kirk whips out communicator..."))
4934 prouts(_("BEEP BEEP BEEP"))
4936 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4939 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4941 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4943 prout(_("Kirk- \"Energize.\""))
4946 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4948 if random.random() > 0.98:
4949 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4951 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4954 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4955 game.landed = not game.landed
4956 game.energy -= nrgneed
4958 prout(_("Transport complete."))
4959 if game.landed and game.iplnet.known=="shuttle_down":
4960 prout(_("The shuttle craft Galileo is here!"))
4961 if not game.landed and game.imine:
4968 # strip-mine a world for dilithium
4972 prout(_("Mining party not on planet."))
4974 if game.iplnet.crystals == "mined":
4975 prout(_("This planet has already been strip-mined for dilithium."))
4977 elif game.iplnet.crystals == "absent":
4978 prout(_("No dilithium crystals on this planet."))
4981 prout(_("You've already mined enough crystals for this trip."))
4983 if game.icrystl and game.cryprob == 0.05:
4984 proutn(_("With all those fresh crystals aboard the "))
4987 prout(_("there's no reason to mine more at this time."))
4989 game.optime = (0.1+0.2*random.random())*(ord(game.iplnet.pclass)-ord("M"))
4992 prout(_("Mining operation complete."))
4993 game.iplnet.crystals = "mined"
4994 game.imine = game.ididit = True
4997 # use dilithium crystals
5001 if not game.icrystl:
5002 prout(_("No dilithium crystals available."))
5004 if game.energy >= 1000:
5005 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5006 prout(_(" except when Condition Yellow exists."))
5008 prout(_("Spock- \"Captain, I must warn you that loading"))
5009 prout(_(" raw dilithium crystals into the ship's power"))
5010 prout(_(" system may risk a severe explosion."))
5011 proutn(_(" Are you sure this is wise?\" "))
5016 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5017 prout(_(" Mr. Spock and I will try it.\""))
5019 prout(_("Spock- \"Crystals in place, Sir."))
5020 prout(_(" Ready to activate circuit.\""))
5022 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5024 if random.random() <= game.cryprob:
5025 prouts(_(" \"Activating now! - - No good! It's***"))
5027 prouts(_("***RED ALERT! RED A*L********************************"))
5030 prouts(_("****************** KA-BOOM!!!! *******************"))
5034 game.energy += 5000.0*(1.0 + 0.9*random.random())
5035 prouts(_(" \"Activating now! - - "))
5036 prout(_("The instruments"))
5037 prout(_(" are going crazy, but I think it's"))
5038 prout(_(" going to work!! Congratulations, Sir!\""))
5043 # use shuttlecraft for planetary jaunt
5046 if damaged(DSHUTTL):
5047 if game.damage[DSHUTTL] == -1.0:
5048 if game.inorbit and game.iplnet.known == "shuttle_down":
5049 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5051 prout(_("Ye Faerie Queene had no shuttle craft."))
5052 elif game.damage[DSHUTTL] > 0:
5053 prout(_("The Galileo is damaged."))
5054 else: # game.damage[DSHUTTL] < 0
5055 prout(_("Shuttle craft is now serving Big Macs."))
5057 if not game.inorbit:
5059 prout(_(" not in standard orbit."))
5061 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5062 prout(_("Shuttle craft not currently available."))
5064 if not game.landed and game.iplnet.known=="shuttle_down":
5065 prout(_("You will have to beam down to retrieve the shuttle craft."))
5067 if game.shldup or game.condition == "docked":
5068 prout(_("Shuttle craft cannot pass through shields."))
5070 if game.iplnet.known=="unknown":
5071 prout(_("Spock- \"Captain, we have no information on this planet"))
5072 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5073 prout(_(" you may not fly down.\""))
5075 game.optime = 3.0e-5*game.height
5076 if game.optime >= 0.8*game.state.remtime:
5077 prout(_("First Officer Spock- \"Captain, I compute that such"))
5078 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5079 int(100*game.optime/game.state.remtime))
5080 prout(_("remaining time."))
5081 proutn(_("Are you sure this is wise?\" "))
5087 if game.iscraft == "onship":
5089 if not damaged(DTRANSP):
5090 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5094 proutn(_("Shuttle crew"))
5096 proutn(_("Rescue party"))
5097 prout(_(" boards Galileo and swoops toward planet surface."))
5098 game.iscraft = "offship"
5102 game.iplnet.known="shuttle_down"
5103 prout(_("Trip complete."))
5106 # Ready to go back to ship
5107 prout(_("You and your mining party board the"))
5108 prout(_("shuttle craft for the trip back to the Enterprise."))
5110 prouts(_("The short hop begins . . ."))
5112 game.iplnet.known="known"
5118 game.iscraft = "onship"
5124 prout(_("Trip complete."))
5129 prout(_("Mining party assembles in the hangar deck,"))
5130 prout(_("ready to board the shuttle craft \"Galileo\"."))
5132 prouts(_("The hangar doors open; the trip begins."))
5135 game.iscraft = "offship"
5138 game.iplnet.known = "shuttle_down"
5141 prout(_("Trip complete."))
5145 # 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:
5182 prouts(_("Sulu- \"Captain! It's working!\""))
5184 while game.nenhere > 0:
5185 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5186 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5187 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5189 if (game.options & OPTION_PLAIN) == 0:
5190 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5191 if random.random() <= 0.05:
5192 prout(_(" is still operational.\""))
5194 prout(_(" has been rendered nonfunctional.\""))
5195 game.damage[DDRAY] = 39.95
5197 r = random.random() # Pick failure method
5199 prouts(_("Sulu- \"Captain! It's working!\""))
5201 prouts(_("***RED ALERT! RED ALERT!"))
5203 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5205 prouts(_("***RED ALERT! RED A*L********************************"))
5208 prouts(_("****************** KA-BOOM!!!! *******************"))
5213 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5215 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5217 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5218 prout(_(" have apparently been transformed into strange mutations."))
5219 prout(_(" Vulcans do not seem to be affected."))
5221 prout(_("Kirk- \"Raauch! Raauch!\""))
5226 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5228 proutn(_("Spock- \"I believe the word is"))
5229 prouts(_(" *ASTONISHING*"))
5230 prout(_(" Mr. Sulu."))
5231 for i in range(QUADSIZE):
5232 for j in range(QUADSIZE):
5233 if game.quad[i][j] == IHDOT:
5234 game.quad[i][j] = IHQUEST
5235 prout(_(" Captain, our quadrant is now infested with"))
5236 prouts(_(" - - - - - - *THINGS*."))
5238 prout(_(" I have no logical explanation.\""))
5240 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5242 prout(_("Scotty- \"There are so many tribbles down here"))
5243 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5247 # Code from reports.c begins here
5249 def attackreport(curt):
5250 # report status of bases under attack
5252 if is_scheduled(FCDBAS):
5253 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5254 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5255 elif game.isatb == 1:
5256 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5257 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5259 prout(_("No Starbase is currently under attack."))
5261 if is_scheduled(FCDBAS):
5262 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5264 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5268 # report on general game status
5270 s1 = "" and game.thawed and _("thawed ")
5271 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5272 s3 = (None, _("novice"). _("fair"),
5273 _("good"), _("expert"), _("emeritus"))[game.skill]
5274 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5275 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5276 prout(_("No plaque is allowed."))
5278 prout(_("This is tournament game %d.") % game.tourn)
5279 prout(_("Your secret password is \"%s\"") % game.passwd)
5280 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5281 (game.inkling + game.incom + game.inscom)))
5282 if game.incom - game.state.remcom:
5283 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5284 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5285 prout(_(", but no Commanders."))
5288 if game.skill > SKILL_FAIR:
5289 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5290 if game.state.rembase != game.inbase:
5292 if game.inbase-game.state.rembase==1:
5293 proutn(_("has been 1 base"))
5295 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5296 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5298 prout(_("There are %d bases.") % game.inbase)
5299 if communicating() or game.iseenit:
5300 # Don't report this if not seen and
5301 # either the radio is dead or not at base!
5305 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5307 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5308 if game.ship == IHE:
5309 proutn(_("You have "))
5311 proutn("%d" % (game.nprobes))
5314 proutn(_(" deep space probe"))
5318 if communicating() and is_scheduled(FDSPROB):
5320 proutn(_("An armed deep space probe is in "))
5322 proutn(_("A deep space probe is in "))
5323 prout("Quadrant %s." % game.probec)
5325 if game.cryprob <= .05:
5326 prout(_("Dilithium crystals aboard ship... not yet used."))
5330 while game.cryprob > ai:
5333 prout(_("Dilithium crystals have been used %d time%s.") % \
5334 (i, (_("s"), "")[i==1]))
5338 # long-range sensor scan
5339 if damaged(DLRSENS):
5340 # Now allow base's sensors if docked
5341 if game.condition != "docked":
5342 prout(_("LONG-RANGE SENSORS DAMAGED."))
5344 prout(_("Starbase's long-range scan"))
5346 prout(_("Long-range scan"))
5347 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5349 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5350 if not VALID_QUADRANT(x, y):
5353 if not damaged(DRADIO):
5354 game.state.galaxy[x][y].charted = True
5355 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5356 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5357 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5358 if game.state.galaxy[x][y].supernova:
5361 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5369 for i in range(NDEVICES):
5372 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5373 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5375 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5376 game.damage[i]+0.05,
5377 game.docfac*game.damage[i]+0.005))
5379 prout(_("All devices functional."))
5382 # update the chart in the Enterprise's computer from galaxy data
5383 game.lastchart = game.state.date
5384 for i in range(GALSIZE):
5385 for j in range(GALSIZE):
5386 if game.state.galaxy[i][j].charted:
5387 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5388 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5389 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5392 # display the star chart
5394 if not damaged(DRADIO):
5396 if game.lastchart < game.state.date and game.condition == "docked":
5397 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5400 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5401 if game.state.date > game.lastchart:
5402 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5403 prout(" 1 2 3 4 5 6 7 8")
5404 for i in range(GALSIZE):
5405 proutn("%d |" % (i+1))
5406 for j in range(GALSIZE):
5407 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5411 if game.state.galaxy[i][j].supernova:
5413 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5415 elif game.state.galaxy[i][j].charted:
5416 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5420 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5428 def sectscan(goodScan, i, j):
5429 # light up an individual dot in a sector
5430 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5431 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):
5432 if game.condition == "red": textcolor(RED)
5433 elif game.condition == "green": textcolor(GREEN)
5434 elif game.condition == "yellow": textcolor(YELLOW)
5435 elif game.condition == "docked": textcolor(CYAN)
5436 elif game.condition == "dead": textcolor(BROWN)
5437 if game.quad[i][j] != game.ship:
5439 proutn("%c " % game.quad[i][j])
5445 # print status report lines
5447 if not req or req == 1:
5448 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5449 % (game.state.date, game.state.remtime))
5450 if not req or req == 2:
5451 if game.condition != "docked":
5454 for t in range(NDEVICES):
5455 if game.damage[t]>0:
5457 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5458 if not req or req == 3:
5459 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5460 if not req or req == 4:
5461 if damaged(DLIFSUP):
5462 if game.condition == "docked":
5463 s = _("DAMAGED, Base provides")
5465 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5468 prstat(_("Life Support"), s)
5469 if not req or req == 5:
5470 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5471 if not req or req == 6:
5473 if game.icrystl and (game.options & OPTION_SHOWME):
5474 extra = _(" (have crystals)")
5475 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5476 if not req or req == 7:
5477 prstat(_("Torpedoes"), "%d" % (game.torps))
5478 if not req or req == 8:
5479 if damaged(DSHIELD):
5485 data = _(" %d%% %.1f units") \
5486 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5487 prstat(_("Shields"), s+data)
5488 if not req or req == 9:
5489 prstat(_("Klingons Left"), "%d" \
5490 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5491 if not req or req == 10:
5492 if game.options & OPTION_WORLDS:
5493 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5494 if plnet and plnet.inhabited:
5495 prstat(_("Major system"), plnet.name)
5497 prout(_("Sector is uninhabited"))
5498 elif not req or req == 11:
5499 attackreport(not req)
5502 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5503 while scan() == IHEOL:
5504 proutn(_("Information desired? "))
5506 if citem in requests:
5507 status(requests.index(citem))
5509 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5510 prout((" date, condition, position, lsupport, warpfactor,"))
5511 prout((" energy, torpedoes, shields, klingons, system, time."))
5516 if damaged(DSRSENS):
5517 # Allow base's sensors if docked
5518 if game.condition != "docked":
5519 prout(_(" S.R. SENSORS DAMAGED!"))
5522 prout(_(" [Using Base's sensors]"))
5524 prout(_(" Short-range scan"))
5525 if goodScan and not damaged(DRADIO):
5526 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5527 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5528 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5529 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5530 prout(" 1 2 3 4 5 6 7 8 9 10")
5531 if game.condition != "docked":
5533 for i in range(QUADSIZE):
5534 proutn("%2d " % (i+1))
5535 for j in range(QUADSIZE):
5536 sectscan(goodScan, i, j)
5541 # use computer to get estimated time of arrival for a warp jump
5542 w1 = coord(); w2 = coord()
5544 if damaged(DCOMPTR):
5545 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5548 if scan() != IHREAL:
5551 proutn(_("Destination quadrant and/or sector? "))
5555 w1.y = int(aaitem-0.5)
5556 if scan() != IHREAL:
5559 w1.x = int(aaitem-0.5)
5560 if scan() == IHREAL:
5561 w2.y = int(aaitem-0.5)
5562 if scan() != IHREAL:
5565 w2.x = int(aaitem-0.5)
5567 if game.quadrant.y>w1.x:
5571 if game.quadrant.x>w1.y:
5575 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5578 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5579 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5582 prout(_("Answer \"no\" if you don't know the value:"))
5585 proutn(_("Time or arrival date? "))
5588 if ttime > game.state.date:
5589 ttime -= game.state.date # Actually a star date
5590 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5591 if ttime <= 1e-10 or twarp > 10:
5592 prout(_("We'll never make it, sir."))
5599 proutn(_("Warp factor? "))
5603 if twarp<1.0 or twarp > 10.0:
5607 prout(_("Captain, certainly you can give me one of these."))
5610 ttime = (10.0*game.dist)/square(twarp)
5611 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5612 if tpower >= game.energy:
5613 prout(_("Insufficient energy, sir."))
5614 if not game.shldup or tpower > game.energy*2.0:
5617 proutn(_("New warp factor to try? "))
5618 if scan() == IHREAL:
5621 if twarp<1.0 or twarp > 10.0:
5629 prout(_("But if you lower your shields,"))
5630 proutn(_("remaining"))
5633 proutn(_("Remaining"))
5634 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5636 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5638 prout(_("Any warp speed is adequate."))
5640 prout(_("Minimum warp needed is %.2f,") % (twarp))
5641 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5642 if game.state.remtime < ttime:
5643 prout(_("Unfortunately, the Federation will be destroyed by then."))
5645 prout(_("You'll be taking risks at that speed, Captain"))
5646 if (game.isatb==1 and game.state.kscmdr == w1 and \
5647 scheduled(FSCDBAS)< ttime+game.state.date) or \
5648 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5649 prout(_("The starbase there will be destroyed by then."))
5650 proutn(_("New warp factor to try? "))
5651 if scan() == IHREAL:
5654 if twarp<1.0 or twarp > 10.0:
5663 #ifdef BSD_BUG_FOR_BUG
5664 # A visual scan is made in a particular direction of three sectors
5665 # in the general direction specified. This takes time, and
5666 # Klingons can attack you, so it should be done only when sensors
5667 # are out. Code swiped from BSD-Trek. Not presently used, as we
5668 # automatically display all adjacent sectors on the short-range
5669 # scan even when short-range sensors are out.
5671 # This struct[] has the delta x, delta y for particular directions
5689 if scan() != IHREAL:
5691 proutn(_("Direction? "))
5695 if aaitem < 0.0 or aaitem > 360.0:
5697 co = (aaitem + 22) / 45
5699 ix = game.sector.x + v.x
5700 iy = game.sector.y + v.y
5701 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5704 co = game.quad[ix][iy]
5705 printf("%d,%d %c " % (ix+1, iy+1, co))
5707 ix = game.sector.x + v.x
5708 iy = game.sector.y + v.y
5709 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5712 co = game.quad[ix][iy]
5713 printf("%c " % (co))
5715 ix = game.sector.x + v.x
5716 iy = game.sector.y + v.y
5717 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5720 co = game.quad[ix][iy]
5721 prout("%c %d,%d\n" % (co, ix+1, iy+1))
5726 # Code from setup.c begins here
5729 # issue a historically correct banner
5731 prout(_("-SUPER- STAR TREK"))
5733 #ifdef __HISTORICAL__
5734 # prout(_("Latest update-21 Sept 78"))
5736 #endif __HISTORICAL__
5741 citem = "emsave.trk"
5745 proutn(_("File name: "))
5751 if '.' not in citem:
5754 fp = open(citem, "wb")
5756 prout(_("Can't freeze game as file %s") % citem)
5758 cPickle.dump(game, fp)
5762 # retrieve saved game
5763 game.passwd[0] = '\0'
5766 proutn(_("File name: "))
5772 if '.' not in citem:
5775 fp = open(citem, "rb")
5777 prout(_("Can't thaw game in %s") % citem)
5779 game = cPickle.load(fp)
5783 # I used <http://www.memory-alpha.org> to find planets
5784 # with references in ST:TOS. Eath and the Alpha Centauri
5785 # Colony have been omitted.
5787 # Some planets marked Class G and P here will be displayed as class M
5788 # because of the way planets are generated. This is a known bug.
5791 _("Andoria (Fesoan)"), # several episodes
5792 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5793 _("Vulcan (T'Khasi)"), # many episodes
5794 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5795 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5796 _("Ardana"), # TOS: "The Cloud Minders"
5797 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5798 _("Gideon"), # TOS: "The Mark of Gideon"
5799 _("Aldebaran III"), # TOS: "The Deadly Years"
5800 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5801 _("Altair IV"), # TOS: "Amok Time
5802 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5803 _("Benecia"), # TOS: "The Conscience of the King"
5804 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5805 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5806 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5807 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5808 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5809 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5810 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5811 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5812 _("Ingraham B"), # TOS: "Operation: Annihilate"
5813 _("Janus IV"), # TOS: "The Devil in the Dark"
5814 _("Makus III"), # TOS: "The Galileo Seven"
5815 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5816 _("Omega IV"), # TOS: "The Omega Glory"
5817 _("Regulus V"), # TOS: "Amok Time
5818 _("Deneva"), # TOS: "Operation -- Annihilate!"
5819 # Worlds from BSD Trek
5820 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5821 _("Beta III"), # TOS: "The Return of the Archons"
5822 _("Triacus"), # TOS: "And the Children Shall Lead",
5823 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5825 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5826 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5827 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5828 # _("Izar"), # TOS: "Whom Gods Destroy"
5829 # _("Tiburon"), # TOS: "The Way to Eden"
5830 # _("Merak II"), # TOS: "The Cloud Minders"
5831 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5832 # _("Iotia"), # TOS: "A Piece of the Action"
5836 _("S. R. Sensors"), \
5837 _("L. R. Sensors"), \
5839 _("Photon Tubes"), \
5840 _("Life Support"), \
5841 _("Warp Engines"), \
5842 _("Impulse Engines"), \
5844 _("Subspace Radio"), \
5845 _("Shuttle Craft"), \
5847 _("Navigation System"), \
5849 _("Shield Control"), \
5854 def setup(needprompt):
5855 # prepare to play, set up cosmos
5857 # Decide how many of everything
5858 if choose(needprompt):
5859 return # frozen game
5860 # Prepare the Enterprise
5861 game.alldone = game.gamewon = False
5863 game.state.crew = FULLCREW
5864 game.energy = game.inenrg = 5000.0
5865 game.shield = game.inshld = 2500.0
5866 game.shldchg = False
5870 game.quadrant = randplace(GALSIZE)
5871 game.sector = randplace(QUADSIZE)
5872 game.torps = game.intorps = 10
5873 game.nprobes = int(3.0*random.random() + 2.0) # Give them 2-4 of these
5875 game.wfacsq = game.warpfac * game.warpfac
5876 for i in range(NDEVICES):
5877 game.damage[i] = 0.0
5878 # Set up assorted game parameters
5879 game.battle = coord()
5880 game.state.date = game.indate = 100.0*int(31.0*random.random()+20.0)
5881 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5882 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5883 game.isatb = game.state.nplankl = 0
5884 game.state.starkl = game.state.basekl = 0
5885 game.iscraft = "onship"
5889 for i in range(GALSIZE):
5890 for j in range(GALSIZE):
5891 quad = game.state.galaxy[i][j]
5896 quad.starbase = False
5897 quad.supernova = False
5898 quad.status = "secure"
5899 # Initialize times for extraneous events
5900 schedule(FSNOVA, expran(0.5 * game.intime))
5901 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5902 schedule(FSNAP, 1.0 + random.random()) # Force an early snapshot
5903 schedule(FBATTAK, expran(0.3*game.intime))
5905 if game.state.nscrem:
5906 schedule(FSCMOVE, 0.2777)
5911 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5912 schedule(FDISTR, expran(1.0 + game.intime))
5917 # Starchart is functional but we've never seen it
5918 game.lastchart = FOREVER
5919 # Put stars in the galaxy
5921 for i in range(GALSIZE):
5922 for j in range(GALSIZE):
5923 k = int(random.random()*9.0 + 1.0)
5925 game.state.galaxy[i][j].stars = k
5926 # Locate star bases in galaxy
5927 for i in range(game.inbase):
5930 w = randplace(GALSIZE)
5931 if not game.state.galaxy[w.x][w.y].starbase:
5934 # C version: for (j = i-1; j > 0; j--)
5935 # so it did them in the opposite order.
5936 for j in range(1, i):
5937 # Improved placement algorithm to spread out bases
5938 distq = w.distance(game.state.baseq[j])
5939 if distq < 6.0*(BASEMAX+1-game.inbase) and random.random() < 0.75:
5942 prout("=== Abandoning base #%d at %s" % (i, w))
5944 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5946 prout("=== Saving base #%d, close to #%d" % (i, j))
5949 game.state.baseq[i] = w
5950 game.state.galaxy[w.x][w.y].starbase = True
5951 game.state.chart[w.x][w.y].starbase = True
5952 # Position ordinary Klingon Battle Cruisers
5954 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5955 if klumper > MAXKLQUAD:
5959 klump = (1.0 - r*r)*klumper
5964 w = randplace(GALSIZE)
5965 if not game.state.galaxy[w.x][w.y].supernova and \
5966 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5968 game.state.galaxy[w.x][w.y].klingons += int(klump)
5971 # Position Klingon Commander Ships
5972 for i in range(1, game.incom+1):
5974 w = randplace(GALSIZE)
5975 if (game.state.galaxy[w.x][w.y].klingons or random.random()>=0.75) and \
5976 not game.state.galaxy[w.x][w.y].supernova and \
5977 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5978 not w in game.state.kcmdr[:i]:
5980 game.state.galaxy[w.x][w.y].klingons += 1
5981 game.state.kcmdr[i] = w
5982 # Locate planets in galaxy
5983 for i in range(game.inplan):
5985 w = randplace(GALSIZE)
5986 if game.state.galaxy[w.x][w.y].planet == None:
5990 new.crystals = "absent"
5991 if (game.options & OPTION_WORLDS) and i < NINHAB:
5992 new.pclass = "M" # All inhabited planets are class M
5993 new.crystals = "absent"
5995 new.name = systnames[i]
5996 new.inhabited = True
5998 new.pclass = ("M", "N", "O")[random.randint(0, 2)]
5999 if random.random()*1.5: # 1 in 3 chance of crystals
6000 new.crystals = "present"
6001 new.known = "unknown"
6002 new.inhabited = False
6003 game.state.galaxy[w.x][w.y].planet = new
6004 game.state.planets.append(new)
6006 for i in range(game.state.nromrem):
6007 w = randplace(GALSIZE)
6008 game.state.galaxy[w.x][w.y].romulans += 1
6009 # Locate the Super Commander
6010 if game.state.nscrem > 0:
6012 w = randplace(GALSIZE)
6013 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
6015 game.state.kscmdr = w
6016 game.state.galaxy[w.x][w.y].klingons += 1
6017 # Place thing (in tournament game, thingx == -1, don't want one!)
6020 thing = randplace(GALSIZE)
6022 game.state.snap = False
6023 if game.skill == SKILL_NOVICE:
6024 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6025 prout(_("a deadly Klingon invasion force. As captain of the United"))
6026 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6027 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6028 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6029 prout(_("your mission. As you proceed you may be given more time."))
6031 prout(_("You will have %d supporting starbases.") % (game.inbase))
6032 proutn(_("Starbase locations- "))
6034 prout(_("Stardate %d.") % int(game.state.date))
6036 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6037 prout(_("An unknown number of Romulans."))
6038 if game.state.nscrem:
6039 prout(_("And one (GULP) Super-Commander."))
6040 prout(_("%d stardates.") % int(game.intime))
6041 proutn(_("%d starbases in ") % game.inbase)
6042 for i in range(game.inbase):
6043 proutn(`game.state.baseq[i]`)
6046 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6047 proutn(_(" Sector %s") % game.sector)
6049 prout(_("Good Luck!"))
6050 if game.state.nscrem:
6051 prout(_(" YOU'LL NEED IT."))
6054 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
6056 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6059 def choose(needprompt):
6060 # choose your game type
6065 game.skill = SKILL_NONE
6067 if needprompt: # Can start with command line options
6068 proutn(_("Would you like a regular, tournament, or saved game? "))
6070 if len(citem)==0: # Try again
6072 if isit("tournament"):
6073 while scan() == IHEOL:
6074 proutn(_("Type in tournament number-"))
6077 continue # We don't want a blank entry
6078 game.tourn = int(round(aaitem))
6081 if isit("saved") or isit("frozen"):
6085 if game.passwd == None:
6087 if not game.alldone:
6088 game.thawed = True # No plaque if not finished
6094 proutn(_("What is \"%s\"?"), citem)
6096 while game.length==0 or game.skill==SKILL_NONE:
6097 if scan() == IHALPHA:
6100 elif isit("medium"):
6104 elif isit("novice"):
6105 game.skill = SKILL_NOVICE
6107 game.skill = SKILL_FAIR
6109 game.skill = SKILL_GOOD
6110 elif isit("expert"):
6111 game.skill = SKILL_EXPERT
6112 elif isit("emeritus"):
6113 game.skill = SKILL_EMERITUS
6115 proutn(_("What is \""))
6121 proutn(_("Would you like a Short, Medium, or Long game? "))
6122 elif game.skill == SKILL_NONE:
6123 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6124 # Choose game options -- added by ESR for SST2K
6125 if scan() != IHALPHA:
6127 proutn(_("Choose your game style (or just press enter): "))
6130 # Approximates the UT FORTRAN version.
6131 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6132 game.options |= OPTION_PLAIN
6134 # Approximates Tom Almy's version.
6135 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6136 game.options |= OPTION_ALMY
6140 proutn(_("What is \"%s\"?") % citem)
6142 if game.passwd == "debug":
6144 fputs("=== Debug mode enabled\n", sys.stdout)
6146 # Use parameters to generate initial values of things
6147 game.damfac = 0.5 * game.skill
6148 game.state.rembase = random.randint(BASEMIN, BASEMAX)
6149 game.inbase = game.state.rembase
6151 if game.options & OPTION_PLANETS:
6152 game.inplan += int((MAXUNINHAB/2) + (MAXUNINHAB/2+1)*random.random())
6153 if game.options & OPTION_WORLDS:
6154 game.inplan += int(NINHAB)
6155 game.state.nromrem = game.inrom = int((2.0+random.random())*game.skill)
6156 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6157 game.state.remtime = 7.0 * game.length
6158 game.intime = game.state.remtime
6159 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*random.random())*game.skill*0.1+.15)
6160 game.incom = int(game.skill + 0.0625*game.inkling*random.random())
6161 game.state.remcom = min(10, game.incom)
6162 game.incom = game.state.remcom
6163 game.state.remres = (game.inkling+4*game.incom)*game.intime
6164 game.inresor = game.state.remres
6165 if game.inkling > 50:
6166 game.state.rembase += 1
6167 game.inbase = game.state.rembase
6171 # drop a feature on a random dot in the current quadrant
6174 w = randplace(QUADSIZE)
6175 if game.quad[w.x][w.y] == IHDOT:
6177 game.quad[w.x][w.y] = iquad
6181 # update our alert status
6182 game.condition = "green"
6183 if game.energy < 1000.0:
6184 game.condition = "yellow"
6185 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6186 game.condition = "red"
6188 game.condition="dead"
6191 # drop new Klingon into current quadrant
6194 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6195 game.kpower[i] = random.random()*150.0 +300.0 +25.0*game.skill
6199 # set up a new state of quadrant, for when we enter or re-enter it
6203 game.comhere = False
6209 game.inorbit = False
6211 game.ientesc = False
6214 game.iseenit = False
6216 # Attempt to escape Super-commander, so tbeam back!
6219 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6220 # cope with supernova
6223 game.klhere = q.klingons
6224 game.irhere = q.romulans
6225 game.nenhere = game.klhere + game.irhere
6227 game.quad[game.sector.x][game.sector.y] = game.ship
6229 w.x = w.y = 0 # quiet a gcc warning
6230 # Position ordinary Klingons
6231 for i in range(game.klhere):
6233 # If we need a commander, promote a Klingon
6234 for i in range(game.state.remcom):
6235 if game.state.kcmdr[i] == game.quadrant:
6238 if i <= game.state.remcom:
6239 game.quad[w.x][w.y] = IHC
6240 game.kpower[game.klhere] = 950.0+400.0*random.random()+50.0*game.skill
6242 # If we need a super-commander, promote a Klingon
6243 if game.quadrant == game.state.kscmdr:
6244 game.quad[game.ks[0].x][game.ks[0].y] = IHS
6245 game.kpower[1] = 1175.0 + 400.0*random.random() + 125.0*game.skill
6246 game.iscate = (game.state.remkl > 1)
6248 # Put in Romulans if needed
6249 for i in range(game.klhere, game.nenhere):
6252 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6253 game.kpower[i] = random.random()*400.0 + 450.0 + 50.0*game.skill
6254 # If quadrant needs a starbase, put it in
6256 game.base = dropin(IHB)
6257 # If quadrant needs a planet, put it in
6259 game.iplnet = q.planet
6260 if not q.planet.inhabited:
6261 game.plnet = dropin(IHP)
6263 game.plnet = dropin(IHW)
6264 # Check for condition
6266 # And finally the stars
6267 for i in range(q.stars):
6271 if game.irhere > 0 and game.klhere == 0:
6273 if not damaged(DRADIO):
6275 prout(_("LT. Uhura- \"Captain, an urgent message."))
6276 prout(_(" I'll put it on audio.\" CLICK"))
6278 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6279 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6281 # Put in THING if needed
6283 if thing == game.quadrant:
6285 thing = randplace(GALSIZE)
6287 game.ks[game.nenhere] = w
6288 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6289 distance(game.sector, w)
6290 game.kpower[game.nenhere] = random.random()*6000.0 +500.0 +250.0*game.skill
6291 if not damaged(DSRSENS):
6293 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6294 prout(_(" Please examine your short-range scan.\""))
6295 # Decide if quadrant needs a Tholian; lighten up if skill is low
6296 if game.options & OPTION_THOLIAN:
6297 if (game.skill < SKILL_GOOD and random.random() <= 0.02) or \
6298 (game.skill == SKILL_GOOD and random.random() <= 0.05) or \
6299 (game.skill > SKILL_GOOD and random.random() <= 0.08):
6300 game.tholian = coord()
6302 game.tholian.x = random.choice((0, QUADSIZE-1))
6303 game.tholian.y = random.choice((0, QUADSIZE-1))
6304 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6306 game.quad[game.tholian.x][game.tholian.y] = IHT
6308 game.ks[game.nenhere] = game.tholian
6309 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6310 distance(game.sector, game.tholian)
6311 game.kpower[game.nenhere] = random.random()*400.0 +100.0 +25.0*game.skill
6312 # Reserve unoccupied corners
6313 if game.quad[0][0]==IHDOT:
6314 game.quad[0][0] = 'X'
6315 if game.quad[0][QUADSIZE-1]==IHDOT:
6316 game.quad[0][QUADSIZE-1] = 'X'
6317 if game.quad[QUADSIZE-1][0]==IHDOT:
6318 game.quad[QUADSIZE-1][0] = 'X'
6319 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6320 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6322 # Put in a few black holes
6323 for i in range(1, 3+1):
6324 if random.random() > 0.5:
6326 # Take out X's in corners if Tholian present
6328 if game.quad[0][0]=='X':
6329 game.quad[0][0] = IHDOT
6330 if game.quad[0][QUADSIZE-1]=='X':
6331 game.quad[0][QUADSIZE-1] = IHDOT
6332 if game.quad[QUADSIZE-1][0]=='X':
6333 game.quad[QUADSIZE-1][0] = IHDOT
6334 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6335 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6338 # sort Klingons by distance from us
6339 # The author liked bubble sort. So we will use it. :-(
6340 if game.nenhere-(thing==game.quadrant)-(game.tholian!=None) < 2:
6344 for j in range(game.nenhere):
6345 if game.kdist[j] > game.kdist[j+1]:
6348 game.kdist[j] = game.kdist[j+1]
6351 game.kavgd[j] = game.kavgd[j+1]
6354 game.ks[j].x = game.ks[j+1].x
6357 game.ks[j].y = game.ks[j+1].y
6360 game.kpower[j] = game.kpower[j+1]
6361 game.kpower[j+1] = t
6366 # set the self-destruct password
6367 if game.options & OPTION_PLAIN:
6370 proutn(_("Please type in a secret password- "))
6373 if game.passwd != None:
6378 game.passwd += chr(97+int(random.random()*25))
6380 # Code from sst.c begins here
6383 "SRSCAN": OPTION_TTY,
6384 "STATUS": OPTION_TTY,
6385 "REQUEST": OPTION_TTY,
6386 "LRSCAN": OPTION_TTY,
6399 "SENSORS": OPTION_PLANETS,
6400 "ORBIT": OPTION_PLANETS,
6401 "TRANSPORT": OPTION_PLANETS,
6402 "MINE": OPTION_PLANETS,
6403 "CRYSTALS": OPTION_PLANETS,
6404 "SHUTTLE": OPTION_PLANETS,
6405 "PLANETS": OPTION_PLANETS,
6410 "PROBE": OPTION_PROBE,
6412 "FREEZE": 0, # Synonym for SAVE
6418 "SOS": 0, # Synonym for MAYDAY
6419 "CALL": 0, # Synonym for MAYDAY
6426 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6429 # generate a list of legal commands
6431 proutn(_("LEGAL COMMANDS ARE:"))
6432 for key in commands:
6436 proutn("%-12s " % key)
6441 # browse on-line help
6442 # Give help on commands
6446 setwnd(prompt_window)
6447 proutn(_("Help on what command? "))
6449 setwnd(message_window)
6452 if citem in commands or citem == "ABBREV":
6461 fp = open(SSTDOC, "r")
6464 fp = open(DOC_NAME, "r")
6466 prout(_("Spock- \"Captain, that information is missing from the"))
6467 proutn(_(" computer. You need to find "))
6469 prout(_(" and put it in the"))
6470 proutn(_(" current directory or to "))
6474 # This used to continue: "You need to find SST.DOC and put
6475 # it in the current directory."
6479 linebuf = fp.readline()
6481 prout(_("Spock- \"Captain, there is no information on that command.\""))
6484 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6485 linebuf = linebuf[3:].strip()
6489 prout(_("Spock- \"Captain, I've found the following information:\""))
6491 while linebuf in fp:
6492 if "******" in linebuf:
6498 # command-interpretation loop
6501 setwnd(message_window)
6502 while True: # command loop
6504 while True: # get a command
6509 setwnd(prompt_window)
6512 if game.options & OPTION_CURSES:
6517 setwnd(message_window)
6519 candidates = filter(lambda x: x.startswith(citem.upper()),
6521 if len(candidates) == 1:
6524 elif candidates and not (game.options & OPTION_PLAIN):
6525 prout("Commands with that prefix: " + " ".join(candidates))
6529 if cmd == "SRSCAN": # srscan
6531 elif cmd == "STATUS": # status
6533 elif cmd == "REQUEST": # status request
6535 elif cmd == "LRSCAN": # long range scan
6537 elif cmd == "PHASERS": # phasers
6541 elif cmd == "TORPEDO": # photon torpedos
6545 elif cmd == "MOVE": # move under warp
6547 elif cmd == "SHIELDS": # shields
6548 doshield(shraise=False)
6551 game.shldchg = False
6552 elif cmd == "DOCK": # dock at starbase
6556 elif cmd == "DAMAGES": # damage reports
6558 elif cmd == "CHART": # chart
6560 elif cmd == "IMPULSE": # impulse
6562 elif cmd == "REST": # rest
6566 elif cmd == "WARP": # warp
6568 elif cmd == "SCORE": # score
6570 elif cmd == "SENSORS": # sensors
6572 elif cmd == "ORBIT": # orbit
6576 elif cmd == "TRANSPORT": # transport "beam"
6578 elif cmd == "MINE": # mine
6582 elif cmd == "CRYSTALS": # crystals
6586 elif cmd == "SHUTTLE": # shuttle
6590 elif cmd == "PLANETS": # Planet list
6592 elif cmd == "REPORT": # Game Report
6594 elif cmd == "COMPUTER": # use COMPUTER!
6596 elif cmd == "COMMANDS":
6598 elif cmd == "EMEXIT": # Emergency exit
6599 clrscr() # Hide screen
6600 freeze(True) # forced save
6601 raise SysExit,1 # And quick exit
6602 elif cmd == "PROBE":
6603 probe() # Launch probe
6606 elif cmd == "ABANDON": # Abandon Ship
6608 elif cmd == "DESTRUCT": # Self Destruct
6610 elif cmd == "SAVE": # Save Game
6613 if game.skill > SKILL_GOOD:
6614 prout(_("WARNING--Saved games produce no plaques!"))
6615 elif cmd == "DEATHRAY": # Try a desparation measure
6619 elif cmd == "DEBUGCMD": # What do we want for debug???
6621 elif cmd == "MAYDAY": # Call for help
6626 game.alldone = True # quit the game
6629 #ifdef BSD_BUG_FOR_BUG
6630 # elif cmd == "VISUAL":
6631 # visual() # perform visual scan
6635 break # Game has ended
6636 if game.optime != 0.0:
6639 break # Events did us in
6640 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6643 if hitme and not game.justin:
6647 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6659 if cmd == IHR: s = _("Romulan")
6660 elif cmd == IHK: s = _("Klingon")
6661 elif cmd == IHC: s = _("Commander")
6662 elif cmd == IHS: s = _("Super-commander")
6663 elif cmd == IHSTAR: s = _("Star")
6664 elif cmd == IHP: s = _("Planet")
6665 elif cmd == IHB: s = _("Starbase")
6666 elif cmd == IHBLANK: s = _("Black hole")
6667 elif cmd == IHT: s = _("Tholian")
6668 elif cmd == IHWEB: s = _("Tholian web")
6669 elif cmd == IHQUEST: s = _("Stranger")
6670 elif cmd == IHW: s = _("Inhabited World")
6671 else: s = "Unknown??"
6674 def crmena(stars, enemy, loctype, w):
6675 # print an enemy and his location
6681 if loctype == "quadrant":
6682 buf = _("Quadrant ")
6683 elif loctype == "sector":
6688 # print our ship name
6689 if game.ship == IHE:
6691 elif game.ship == IHF:
6692 s = _("Faerie Queene")
6698 # print a line of stars
6699 prouts("******************************************************")
6703 return -avrage*math.log(1e-7 + random.random())
6705 def randplace(size):
6706 # choose a random location
6708 w.x = random.randint(0, size-1)
6709 w.y = random.randint(0, size-1)
6713 # Demand input for next scan
6718 # return IHEOL next time
6723 # Get a token from the user
6724 global inqueue, line, citem, aaitem
6728 # Read a line if nothing here
6731 if curwnd==prompt_window:
6733 setwnd(message_window)
6735 # Skip leading white space
6736 line = line.lstrip()
6738 inqueue = line.split()
6744 # From here on in it's all looking at the queue
6745 citem = inqueue.pop(0)
6749 aaitem = float(citem)
6754 citem = citem.lower()
6758 # yes-or-no confirmation
6767 proutn(_("Please answer with \"y\" or \"n\": "))
6770 # complain about unparseable input
6773 prout(_("Beg your pardon, Captain?"))
6776 # compares s to citem and returns true if it matches to the length of s
6777 return s.startswith(citem)
6780 # access to the internals for debugging
6781 proutn("Reset levels? ")
6783 if game.energy < game.inenrg:
6784 game.energy = game.inenrg
6785 game.shield = game.inshld
6786 game.torps = game.intorps
6787 game.lsupres = game.inlsr
6788 proutn("Reset damage? ")
6790 for i in range(NDEVICES):
6791 if game.damage[i] > 0.0:
6792 game.damage[i] = 0.0
6793 proutn("Toggle debug flag? ")
6797 prout("Debug output ON")
6799 prout("Debug output OFF")
6800 proutn("Cause selective damage? ")
6802 for i in range(NDEVICES):
6808 if key == IHALPHA and isit("y"):
6809 game.damage[i] = 10.0
6810 proutn("Examine/change events? ")
6815 FSNOVA: "Supernova ",
6818 FBATTAK: "Base Attack ",
6819 FCDBAS: "Base Destroy ",
6820 FSCMOVE: "SC Move ",
6821 FSCDBAS: "SC Base Destroy ",
6822 FDSPROB: "Probe Move ",
6823 FDISTR: "Distress Call ",
6824 FENSLV: "Enslavement ",
6825 FREPRO: "Klingon Build ",
6827 for i in range(1, NEVENTS):
6830 proutn("%.2f" % (scheduled(i)-game.state.date))
6831 if i == FENSLV or i == FREPRO:
6833 proutn(" in %s" % ev.quadrant)
6843 ev = schedule(i, aaitem)
6844 if i == FENSLV or i == FREPRO:
6846 proutn("In quadrant- ")
6848 # IHEOL says to leave coordinates as they are
6851 prout("Event %d canceled, no x coordinate." % (i))
6854 w.x = int(round(aaitem))
6857 prout("Event %d canceled, no y coordinate." % (i))
6860 w.y = int(round(aaitem))
6863 proutn("Induce supernova here? ")
6865 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6868 if __name__ == '__main__':
6869 global line, thing, game, idebug, iqengry
6870 game = citem = aaitem = inqueue = None
6876 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY)
6877 # Disable curses mode until the game logic is working.
6878 # if os.getenv("TERM"):
6879 # game.options |= OPTION_CURSES | OPTION_SHOWME
6881 game.options |= OPTION_TTY
6883 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6884 for (switch, val) in options:
6887 replayfp = open(val, "r")
6889 sys.stderr.write("sst: can't open replay file %s\n" % val)
6891 line = replayfp.readline().strip()
6893 (key, seed) = line.split()
6895 sys.stderr.write("sst2k: seed set to %d\n" % seed)
6897 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6899 game.options |= OPTION_TTY
6900 game.options &=~ OPTION_CURSES
6901 elif switch == '-t':
6902 game.options |= OPTION_TTY
6903 game.options &=~ OPTION_CURSES
6904 elif switch == '-x':
6907 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6909 # where to save the input in case of bugs
6911 logfp = open("/usr/tmp/sst-input.log", "w")
6913 sys.stderr.write("sst: warning, can't open logfile\n")
6916 logfp.write("seed %d\n" % (seed))
6923 while True: # Play a game
6924 setwnd(fullscreen_window)
6927 setup(needprompt=not inqueue)
6930 game.alldone = False
6936 if game.tourn and game.alldone:
6937 proutn(_("Do you want your score recorded?"))
6942 proutn(_("Do you want to play again? "))
6946 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))