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 return ((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem))/(game.state.date-game.indate)
3096 badpt = 5.0*game.state.starkl + \
3098 10.0*game.state.nplankl + \
3099 300*game.state.nworldkl + \
3101 100.0*game.state.basekl +\
3103 if game.ship == IHF:
3105 elif game.ship == None:
3110 # end the game, with appropriate notfications
3114 prout(_("It is stardate %.1f.") % game.state.date)
3116 if ifin == FWON: # Game has been won
3117 if game.state.nromrem != 0:
3118 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3121 prout(_("You have smashed the Klingon invasion fleet and saved"))
3122 prout(_("the Federation."))
3127 badpt = 0.0 # Close enough!
3128 # killsPerDate >= RateMax
3129 if game.state.date-game.indate < 5.0 or \
3130 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3132 prout(_("In fact, you have done so well that Starfleet Command"))
3133 if game.skill == SKILL_NOVICE:
3134 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3135 elif game.skill == SKILL_FAIR:
3136 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3137 elif game.skill == SKILL_GOOD:
3138 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3139 elif game.skill == SKILL_EXPERT:
3140 prout(_("promotes you to Commodore Emeritus."))
3142 prout(_("Now that you think you're really good, try playing"))
3143 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3144 elif game.skill == SKILL_EMERITUS:
3146 proutn(_("Computer- "))
3147 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3149 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3151 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3153 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3155 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3157 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3159 prout(_("Now you can retire and write your own Star Trek game!"))
3161 elif game.skill >= SKILL_EXPERT:
3162 if game.thawed and not idebug:
3163 prout(_("You cannot get a citation, so..."))
3165 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3169 # Only grant long life if alive (original didn't!)
3171 prout(_("LIVE LONG AND PROSPER."))
3176 elif ifin == FDEPLETE: # Federation Resources Depleted
3177 prout(_("Your time has run out and the Federation has been"))
3178 prout(_("conquered. Your starship is now Klingon property,"))
3179 prout(_("and you are put on trial as a war criminal. On the"))
3180 proutn(_("basis of your record, you are "))
3181 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3182 prout(_("acquitted."))
3184 prout(_("LIVE LONG AND PROSPER."))
3186 prout(_("found guilty and"))
3187 prout(_("sentenced to death by slow torture."))
3191 elif ifin == FLIFESUP:
3192 prout(_("Your life support reserves have run out, and"))
3193 prout(_("you die of thirst, starvation, and asphyxiation."))
3194 prout(_("Your starship is a derelict in space."))
3196 prout(_("Your energy supply is exhausted."))
3198 prout(_("Your starship is a derelict in space."))
3199 elif ifin == FBATTLE:
3202 prout(_("has been destroyed in battle."))
3204 prout(_("Dulce et decorum est pro patria mori."))
3206 prout(_("You have made three attempts to cross the negative energy"))
3207 prout(_("barrier which surrounds the galaxy."))
3209 prout(_("Your navigation is abominable."))
3212 prout(_("Your starship has been destroyed by a nova."))
3213 prout(_("That was a great shot."))
3215 elif ifin == FSNOVAED:
3218 prout(_(" has been fried by a supernova."))
3219 prout(_("...Not even cinders remain..."))
3220 elif ifin == FABANDN:
3221 prout(_("You have been captured by the Klingons. If you still"))
3222 prout(_("had a starbase to be returned to, you would have been"))
3223 prout(_("repatriated and given another chance. Since you have"))
3224 prout(_("no starbases, you will be mercilessly tortured to death."))
3225 elif ifin == FDILITHIUM:
3226 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3227 elif ifin == FMATERIALIZE:
3228 prout(_("Starbase was unable to re-materialize your starship."))
3229 prout(_("Sic transit gloria mundi"))
3230 elif ifin == FPHASER:
3233 prout(_(" has been cremated by its own phasers."))
3235 prout(_("You and your landing party have been"))
3236 prout(_("converted to energy, disipating through space."))
3237 elif ifin == FMINING:
3238 prout(_("You are left with your landing party on"))
3239 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3241 prout(_("They are very fond of \"Captain Kirk\" soup."))
3243 proutn(_("Without your leadership, the "))
3245 prout(_(" is destroyed."))
3246 elif ifin == FDPLANET:
3247 prout(_("You and your mining party perish."))
3249 prout(_("That was a great shot."))
3252 prout(_("The Galileo is instantly annihilated by the supernova."))
3253 prout(_("You and your mining party are atomized."))
3255 proutn(_("Mr. Spock takes command of the "))
3258 prout(_("joins the Romulans, reigning terror on the Federation."))
3259 elif ifin == FPNOVA:
3260 prout(_("You and your mining party are atomized."))
3262 proutn(_("Mr. Spock takes command of the "))
3265 prout(_("joins the Romulans, reigning terror on the Federation."))
3266 elif ifin == FSTRACTOR:
3267 prout(_("The shuttle craft Galileo is also caught,"))
3268 prout(_("and breaks up under the strain."))
3270 prout(_("Your debris is scattered for millions of miles."))
3271 proutn(_("Without your leadership, the "))
3273 prout(_(" is destroyed."))
3275 prout(_("The mutants attack and kill Spock."))
3276 prout(_("Your ship is captured by Klingons, and"))
3277 prout(_("your crew is put on display in a Klingon zoo."))
3278 elif ifin == FTRIBBLE:
3279 prout(_("Tribbles consume all remaining water,"))
3280 prout(_("food, and oxygen on your ship."))
3282 prout(_("You die of thirst, starvation, and asphyxiation."))
3283 prout(_("Your starship is a derelict in space."))
3285 prout(_("Your ship is drawn to the center of the black hole."))
3286 prout(_("You are crushed into extremely dense matter."))
3288 prout(_("Your last crew member has died."))
3289 if game.ship == IHF:
3291 elif game.ship == IHE:
3294 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3295 goodies = game.state.remres/game.inresor
3296 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3297 if goodies/baddies >= 1.0+0.5*random.random():
3298 prout(_("As a result of your actions, a treaty with the Klingon"))
3299 prout(_("Empire has been signed. The terms of the treaty are"))
3300 if goodies/baddies >= 3.0+random.random():
3301 prout(_("favorable to the Federation."))
3303 prout(_("Congratulations!"))
3305 prout(_("highly unfavorable to the Federation."))
3307 prout(_("The Federation will be destroyed."))
3309 prout(_("Since you took the last Klingon with you, you are a"))
3310 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3311 prout(_("statue in your memory. Rest in peace, and try not"))
3312 prout(_("to think about pigeons."))
3317 # compute player's score
3318 timused = game.state.date - game.indate
3320 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3322 perdate = killrate()
3323 ithperd = 500*perdate + 0.5
3326 iwon = 100*game.skill
3327 if game.ship == IHE:
3329 elif game.ship == IHF:
3333 if not game.gamewon:
3334 game.state.nromrem = 0 # None captured if no win
3335 iscore = 10*(game.inkling - game.state.remkl) \
3336 + 50*(game.incom - game.state.remcom) \
3338 + 20*(game.inrom - game.state.nromrem) \
3339 + 200*(game.inscom - game.state.nscrem) \
3340 - game.state.nromrem \
3345 prout(_("Your score --"))
3346 if game.inrom - game.state.nromrem:
3347 prout(_("%6d Romulans destroyed %5d") %
3348 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3349 if game.state.nromrem:
3350 prout(_("%6d Romulans captured %5d") %
3351 (game.state.nromrem, game.state.nromrem))
3352 if game.inkling - game.state.remkl:
3353 prout(_("%6d ordinary Klingons destroyed %5d") %
3354 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3355 if game.incom - game.state.remcom:
3356 prout(_("%6d Klingon commanders destroyed %5d") %
3357 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3358 if game.inscom - game.state.nscrem:
3359 prout(_("%6d Super-Commander destroyed %5d") %
3360 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3362 prout(_("%6.2f Klingons per stardate %5d") %
3364 if game.state.starkl:
3365 prout(_("%6d stars destroyed by your action %5d") %
3366 (game.state.starkl, -5*game.state.starkl))
3367 if game.state.nplankl:
3368 prout(_("%6d planets destroyed by your action %5d") %
3369 (game.state.nplankl, -10*game.state.nplankl))
3370 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3371 prout(_("%6d inhabited planets destroyed by your action %5d") %
3372 (game.state.nplankl, -300*game.state.nworldkl))
3373 if game.state.basekl:
3374 prout(_("%6d bases destroyed by your action %5d") %
3375 (game.state.basekl, -100*game.state.basekl))
3377 prout(_("%6d calls for help from starbase %5d") %
3378 (game.nhelp, -45*game.nhelp))
3380 prout(_("%6d casualties incurred %5d") %
3381 (game.casual, -game.casual))
3383 prout(_("%6d crew abandoned in space %5d") %
3384 (game.abandoned, -3*game.abandoned))
3386 prout(_("%6d ship(s) lost or destroyed %5d") %
3387 (klship, -100*klship))
3389 prout(_("Penalty for getting yourself killed -200"))
3391 proutn(_("Bonus for winning "))
3392 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3393 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3394 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3395 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3396 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3397 prout(" %5d" % iwon)
3399 prout(_("TOTAL SCORE %5d") % iscore)
3402 # emit winner's commemmorative plaque
3405 proutn(_("File or device name for your plaque: "))
3408 fp = open(winner, "w")
3411 prout(_("Invalid name."))
3413 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3415 # The 38 below must be 64 for 132-column paper
3416 nskip = 38 - len(winner)/2
3417 fp.write("\n\n\n\n")
3418 # --------DRAW ENTERPRISE PICTURE.
3419 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3420 fp.write(" EEE E : : : E\n" )
3421 fp.write(" EE EEE E : : NCC-1701 : E\n")
3422 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3423 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3424 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3425 fp.write(" EEEEEEE EEEEE E E E E\n")
3426 fp.write(" EEE E E E E\n")
3427 fp.write(" E E E E\n")
3428 fp.write(" EEEEEEEEEEEEE E E\n")
3429 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3430 fp.write(" :E : EEEE E\n")
3431 fp.write(" .-E -:----- E\n")
3432 fp.write(" :E : E\n")
3433 fp.write(" EE : EEEEEEEE\n")
3434 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3436 fp.write(_(" U. S. S. ENTERPRISE\n"))
3437 fp.write("\n\n\n\n")
3438 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3440 fp.write(_(" Starfleet Command bestows to you\n"))
3442 fp.write("%*s%s\n\n" % (nskip, "", winner))
3443 fp.write(_(" the rank of\n\n"))
3444 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3446 if game.skill == SKILL_EXPERT:
3447 fp.write(_(" Expert level\n\n"))
3448 elif game.skill == SKILL_EMERITUS:
3449 fp.write(_("Emeritus level\n\n"))
3451 fp.write(_(" Cheat level\n\n"))
3452 timestring = ctime()
3453 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3454 (timestring+4, timestring+20, timestring+11))
3455 fp.write(_(" Your score: %d\n\n") % iscore)
3456 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3459 # Code from io.c begins here
3461 rows = linecount = 0 # for paging
3464 fullscreen_window = None
3465 srscan_window = None
3466 report_window = None
3467 status_window = None
3468 lrscan_window = None
3469 message_window = None
3470 prompt_window = None
3474 "wrap up, either normally or due to signal"
3475 if game.options & OPTION_CURSES:
3482 sys.stdout.write('\n')
3488 #setlocale(LC_ALL, "")
3489 #bindtextdomain(PACKAGE, LOCALEDIR)
3490 #textdomain(PACKAGE)
3491 if atexit.register(outro):
3492 sys.stderr.write("Unable to register outro(), exiting...\n")
3494 if not (game.options & OPTION_CURSES):
3495 ln_env = os.getenv("LINES")
3501 stdscr = curses.initscr()
3506 curses.start_color()
3507 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3508 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3509 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3510 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3511 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3512 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3513 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3514 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3516 global fullscreen_window, srscan_window, report_window, status_window
3517 global lrscan_window, message_window, prompt_window
3518 fullscreen_window = stdscr
3519 srscan_window = curses.newwin(12, 25, 0, 0)
3520 report_window = curses.newwin(11, 0, 1, 25)
3521 status_window = curses.newwin(10, 0, 1, 39)
3522 lrscan_window = curses.newwin(5, 0, 0, 64)
3523 message_window = curses.newwin(0, 0, 12, 0)
3524 prompt_window = curses.newwin(1, 0, rows-2, 0)
3525 message_window.scrollok(True)
3526 setwnd(fullscreen_window)
3530 "wait for user action -- OK to do nothing if on a TTY"
3531 if game.options & OPTION_CURSES:
3536 if game.skill > SKILL_FAIR:
3537 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3539 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3543 if game.skill > SKILL_FAIR:
3544 prompt = _("[CONTINUE?]")
3546 prompt = _("[PRESS ENTER TO CONTINUE]")
3548 if game.options & OPTION_CURSES:
3550 setwnd(prompt_window)
3551 prompt_window.wclear()
3552 prompt_window.addstr(prompt)
3553 prompt_window.getstr()
3554 prompt_window.clear()
3555 prompt_window.refresh()
3556 setwnd(message_window)
3559 sys.stdout.write('\n')
3562 for j in range(rows):
3563 sys.stdout.write('\n')
3567 "Skip i lines. Pause game if this would cause a scrolling event."
3568 for dummy in range(i):
3569 if game.options & OPTION_CURSES:
3570 (y, x) = curwnd.getyx()
3571 (my, mx) = curwnd.getmaxyx()
3572 if curwnd == message_window and y >= my - 3:
3580 if rows and linecount >= rows:
3583 sys.stdout.write('\n')
3586 "Utter a line with no following line feed."
3587 if game.options & OPTION_CURSES:
3591 sys.stdout.write(line)
3603 if game.options & OPTION_CURSES:
3610 "Get a line of input."
3611 if game.options & OPTION_CURSES:
3612 line = curwnd.getstr() + "\n"
3615 if replayfp and not replayfp.closed:
3616 line = replayfp.readline()
3620 logfp.write(line + "\n")
3624 "Change windows -- OK for this to be a no-op in tty mode."
3626 if game.options & OPTION_CURSES:
3628 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3631 "Clear to end of line -- can be a no-op in tty mode"
3632 if game.options & OPTION_CURSES:
3637 "Clear screen -- can be a no-op in tty mode."
3639 if game.options & OPTION_CURSES:
3645 def textcolor(color):
3646 "Set the current text color"
3647 if game.options & OPTION_CURSES:
3648 if color == DEFAULT:
3650 elif color == BLACK:
3651 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3653 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3654 elif color == GREEN:
3655 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3657 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3659 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3660 elif color == MAGENTA:
3661 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3662 elif color == BROWN:
3663 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3664 elif color == LIGHTGRAY:
3665 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3666 elif color == DARKGRAY:
3667 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3668 elif color == LIGHTBLUE:
3669 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3670 elif color == LIGHTGREEN:
3671 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3672 elif color == LIGHTCYAN:
3673 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3674 elif color == LIGHTRED:
3675 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3676 elif color == LIGHTMAGENTA:
3677 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3678 elif color == YELLOW:
3679 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3680 elif color == WHITE:
3681 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3684 "Set highlight video, if this is reasonable."
3685 if game.options & OPTION_CURSES:
3686 curwnd.attron(curses.A_REVERSE)
3689 # Things past this point have policy implications.
3693 "Hook to be called after moving to redraw maps."
3694 if game.options & OPTION_CURSES:
3697 setwnd(srscan_window)
3701 setwnd(status_window)
3702 status_window.clear()
3703 status_window.move(0, 0)
3704 setwnd(report_window)
3705 report_window.clear()
3706 report_window.move(0, 0)
3708 setwnd(lrscan_window)
3709 lrscan_window.clear()
3710 lrscan_window.move(0, 0)
3713 def put_srscan_sym(w, sym):
3714 "Emit symbol for short-range scan."
3715 srscan_window.move(w.x+1, w.y*2+2)
3716 srscan_window.addch(sym)
3717 srscan_window.refresh()
3720 "Enemy fall down, go boom."
3721 if game.options & OPTION_CURSES:
3723 setwnd(srscan_window)
3724 srscan_window.attron(curses.A_REVERSE)
3725 put_srscan_sym(w, game.quad[w.x][w.y])
3729 srscan_window.attroff(curses.A_REVERSE)
3730 put_srscan_sym(w, game.quad[w.x][w.y])
3731 curses.delay_output(500)
3732 setwnd(message_window)
3735 "Sound and visual effects for teleportation."
3736 if game.options & OPTION_CURSES:
3738 setwnd(message_window)
3740 prouts(" . . . . . ")
3741 if game.options & OPTION_CURSES:
3742 #curses.delay_output(1000)
3746 def tracktorpedo(w, l, i, n, iquad):
3747 "Torpedo-track animation."
3748 if not game.options & OPTION_CURSES:
3752 proutn(_("Track for torpedo number %d- ") % i)
3755 proutn(_("Torpedo track- "))
3758 proutn("%d - %d " % (w.x, w.y))
3760 if not damaged(DSRSENS) or game.condition=="docked":
3761 if i != 1 and l == 1:
3764 if (iquad==IHDOT) or (iquad==IHBLANK):
3765 put_srscan_sym(w, '+')
3769 put_srscan_sym(w, iquad)
3771 curwnd.attron(curses.A_REVERSE)
3772 put_srscan_sym(w, iquad)
3776 curwnd.attroff(curses.A_REVERSE)
3777 put_srscan_sym(w, iquad)
3779 proutn("%d - %d " % (w.x, w.y))
3782 "Display the current galaxy chart."
3783 if game.options & OPTION_CURSES:
3784 setwnd(message_window)
3785 message_window.clear()
3787 if game.options & OPTION_TTY:
3792 def prstat(txt, data):
3794 if game.options & OPTION_CURSES:
3796 setwnd(status_window)
3798 proutn(" " * (NSYM - len(txt)))
3801 if game.options & OPTION_CURSES:
3802 setwnd(report_window)
3804 # Code from moving.c begins here
3806 def imove(novapush):
3807 # movement execution for warp, impulse, supernova, and tractor-beam events
3808 w = coord(); final = coord()
3811 def no_quad_change():
3812 # No quadrant change -- compute new average enemy distances
3813 game.quad[game.sector.x][game.sector.y] = game.ship
3815 for m in range(game.nenhere):
3816 finald = distance(w, game.ks[m])
3817 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3818 game.kdist[m] = finald
3820 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3822 for m in range(game.nenhere):
3823 game.kavgd[m] = game.kdist[m]
3826 setwnd(message_window)
3829 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3830 game.inorbit = False
3831 angle = ((15.0 - game.direc) * 0.5235988)
3832 deltax = -math.sin(angle)
3833 deltay = math.cos(angle)
3834 if math.fabs(deltax) > math.fabs(deltay):
3835 bigger = math.fabs(deltax)
3837 bigger = math.fabs(deltay)
3840 # If tractor beam is to occur, don't move full distance
3841 if game.state.date+game.optime >= scheduled(FTBEAM):
3843 game.condition = "red"
3844 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3845 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3846 # Move within the quadrant
3847 game.quad[game.sector.x][game.sector.y] = IHDOT
3850 n = int(10.0*game.dist*bigger+0.5)
3852 for m in range(1, n+1):
3857 if not VALID_SECTOR(w.x, w.y):
3858 # Leaving quadrant -- allow final enemy attack
3859 # Don't do it if being pushed by Nova
3860 if game.nenhere != 0 and not novapush:
3862 for m in range(game.nenhere):
3863 finald = distance(w, game.ks[m])
3864 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
3866 # Stas Sergeev added the condition
3867 # that attacks only happen if Klingons
3868 # are present and your skill is good.
3870 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3874 # compute final position -- new quadrant and sector
3875 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3876 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3877 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3878 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3879 # check for edge of galaxy
3889 if w.x >= GALSIZE*QUADSIZE:
3890 w.x = (GALSIZE*QUADSIZE*2) - w.x
3892 if w.y >= GALSIZE*QUADSIZE:
3893 w.y = (GALSIZE*QUADSIZE*2) - w.y
3901 if game.nkinks == 3:
3902 # Three strikes -- you're out!
3906 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3907 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3908 prout(_("YOU WILL BE DESTROYED."))
3909 # Compute final position in new quadrant
3910 if trbeam: # Don't bother if we are to be beamed
3912 game.quadrant.x = w.x/QUADSIZE
3913 game.quadrant.y = w.y/QUADSIZE
3914 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3915 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3917 prout(_("Entering Quadrant %s.") % game.quadrant)
3918 game.quad[game.sector.x][game.sector.y] = game.ship
3920 if game.skill>SKILL_NOVICE:
3923 iquad = game.quad[w.x][w.y]
3925 # object encountered in flight path
3926 stopegy = 50.0*game.dist/game.optime
3927 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3928 if iquad in (IHT, IHK, OHC, IHS, IHR, IHQUEST):
3930 ram(False, iquad, game.sector)
3932 elif iquad == IHBLANK:
3934 prouts(_("***RED ALERT! RED ALERT!"))
3938 proutn(_(" pulled into black hole at Sector %s") % w)
3940 # Getting pulled into a black hole was certain
3941 # death in Almy's original. Stas Sergeev added a
3942 # possibility that you'll get timewarped instead.
3945 for m in range(NDEVICES):
3946 if game.damage[m]>0:
3948 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3949 if (game.options & OPTION_BLKHOLE) and random.random()>probf:
3959 proutn(_(" encounters Tholian web at %s;") % w)
3961 proutn(_(" blocked by object at %s;") % w)
3962 proutn(_("Emergency stop required "))
3963 prout(_("%2d units of energy.") % int(stopegy))
3964 game.energy -= stopegy
3965 final.x = x-deltax+0.5
3966 final.y = y-deltay+0.5
3968 if game.energy <= 0:
3974 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3981 # dock our ship at a starbase
3983 if game.condition == "docked" and verbose:
3984 prout(_("Already docked."))
3987 prout(_("You must first leave standard orbit."))
3989 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
3991 prout(_(" not adjacent to base."))
3993 game.condition = "docked"
3997 if game.energy < game.inenrg:
3998 game.energy = game.inenrg
3999 game.shield = game.inshld
4000 game.torps = game.intorps
4001 game.lsupres = game.inlsr
4002 game.state.crew = FULLCREW
4003 if not damaged(DRADIO) and \
4004 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4005 # get attack report from base
4006 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4010 # This program originally required input in terms of a (clock)
4011 # direction and distance. Somewhere in history, it was changed to
4012 # cartesian coordinates. So we need to convert. Probably
4013 # "manual" input should still be done this way -- it's a real
4014 # pain if the computer isn't working! Manual mode is still confusing
4015 # because it involves giving x and y motions, yet the coordinates
4016 # are always displayed y - x, where +y is downward!
4018 def getcourse(isprobe, akey):
4019 # get course and distance
4021 dquad = copy.copy(game.quadrant)
4022 navmode = "unspecified"
4026 if game.landed and not isprobe:
4027 prout(_("Dummy! You can't leave standard orbit until you"))
4028 proutn(_("are back aboard the ship."))
4031 while navmode == "unspecified":
4032 if damaged(DNAVSYS):
4034 prout(_("Computer damaged; manual navigation only"))
4036 prout(_("Computer damaged; manual movement only"))
4041 if isprobe and akey != -1:
4042 # For probe launch, use pre-scanned value first time
4048 proutn(_("Manual or automatic- "))
4051 elif key == IHALPHA:
4056 elif isit("automatic"):
4057 navmode = "automatic"
4066 prout(_("(Manual navigation assumed.)"))
4068 prout(_("(Manual movement assumed.)"))
4071 if navmode == "automatic":
4074 proutn(_("Target quadrant or quadrant§or- "))
4076 proutn(_("Destination sector or quadrant§or- "))
4083 xi = int(round(aaitem))-1
4088 xj = int(round(aaitem))-1
4091 # both quadrant and sector specified
4092 xk = int(round(aaitem))-1
4097 xl = int(round(aaitem))-1
4103 # only one pair of numbers was specified
4105 # only quadrant specified -- go to center of dest quad
4108 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4110 # only sector specified
4114 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4121 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4123 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4124 # the actual deltas get computed here
4125 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4126 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4129 proutn(_("X and Y displacements- "))
4143 # Check for zero movement
4144 if deltax == 0 and deltay == 0:
4147 if itemp == "verbose" and not isprobe:
4149 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4150 # Course actually laid in.
4151 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4152 game.direc = math.atan2(deltax, deltay)*1.90985932
4153 if game.direc < 0.0:
4159 # move under impulse power
4161 if damaged(DIMPULS):
4164 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4166 if game.energy > 30.0:
4167 if not getcourse(isprobe=False, akey=0):
4169 power = 20.0 + 100.0*game.dist
4172 if power >= game.energy:
4173 # Insufficient power for trip
4175 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4176 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4177 if game.energy > 30:
4178 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4179 int(0.01 * (game.energy-20.0)-0.05))
4180 prout(_(" quadrants.\""))
4182 prout(_("quadrant. They are, therefore, useless.\""))
4185 # Make sure enough time is left for the trip
4186 game.optime = game.dist/0.095
4187 if game.optime >= game.state.remtime:
4188 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4189 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4190 proutn(_("we dare spend the time?\" "))
4193 # Activate impulse engines and pay the cost
4194 imove(novapush=False)
4198 power = 20.0 + 100.0*game.dist
4199 game.energy -= power
4200 game.optime = game.dist/0.095
4201 if game.energy <= 0:
4206 # move under warp drive
4207 blooey = False; twarp = False
4208 if not timewarp: # Not WARPX entry
4210 if game.damage[DWARPEN] > 10.0:
4213 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4215 if damaged(DWARPEN) and game.warpfac > 4.0:
4218 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4219 prout(_(" is repaired, I can only give you warp 4.\""))
4221 # Read in course and distance
4222 if not getcourse(isprobe=False, akey=0):
4224 # Make sure starship has enough energy for the trip
4225 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4226 if power >= game.energy:
4227 # Insufficient power for trip
4230 prout(_("Engineering to bridge--"))
4231 if not game.shldup or 0.5*power > game.energy:
4232 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4234 prout(_("We can't do it, Captain. We don't have enough energy."))
4236 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4239 prout(_("if you'll lower the shields."))
4243 prout(_("We haven't the energy to go that far with the shields up."))
4246 # Make sure enough time is left for the trip
4247 game.optime = 10.0*game.dist/game.wfacsq
4248 if game.optime >= 0.8*game.state.remtime:
4250 prout(_("First Officer Spock- \"Captain, I compute that such"))
4251 proutn(_(" a trip would require approximately %2.0f") %
4252 (100.0*game.optime/game.state.remtime))
4253 prout(_(" percent of our"))
4254 proutn(_(" remaining time. Are you sure this is wise?\" "))
4260 if game.warpfac > 6.0:
4261 # Decide if engine damage will occur
4262 prob = game.dist*(6.0-game.warpfac)*(6.0-game.warpfac)/66.666666666
4263 if prob > random.random():
4265 game.dist = random.random()*game.dist
4266 # Decide if time warp will occur
4267 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > random.random():
4269 if idebug and game.warpfac==10 and not twarp:
4271 proutn("=== Force time warp? ")
4275 # If time warp or engine damage, check path
4276 # If it is obstructed, don't do warp or damage
4277 angle = ((15.0-game.direc)*0.5235998)
4278 deltax = -math.sin(angle)
4279 deltay = math.cos(angle)
4280 if math.fabs(deltax) > math.fabs(deltay):
4281 bigger = math.fabs(deltax)
4283 bigger = math.fabs(deltay)
4287 n = 10.0 * game.dist * bigger +0.5
4290 for l in range(1, n+1):
4295 if not VALID_SECTOR(ix, iy):
4297 if game.quad[ix][iy] != IHDOT:
4300 # Activate Warp Engines and pay the cost
4301 imove(novapush=False)
4304 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4305 if game.energy <= 0:
4307 game.optime = 10.0*game.dist/game.wfacsq
4311 game.damage[DWARPEN] = game.damfac*(3.0*random.random()+1.0)
4313 prout(_("Engineering to bridge--"))
4314 prout(_(" Scott here. The warp engines are damaged."))
4315 prout(_(" We'll have to reduce speed to warp 4."))
4320 # change the warp factor
4326 proutn(_("Warp factor- "))
4331 if game.damage[DWARPEN] > 10.0:
4332 prout(_("Warp engines inoperative."))
4334 if damaged(DWARPEN) and aaitem > 4.0:
4335 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4336 prout(_(" but right now we can only go warp 4.\""))
4339 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4342 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4344 oldfac = game.warpfac
4345 game.warpfac = aaitem
4346 game.wfacsq=game.warpfac*game.warpfac
4347 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4348 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4351 if game.warpfac < 8.00:
4352 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4354 if game.warpfac == 10.0:
4355 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4357 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4361 # cope with being tossed out of quadrant by supernova or yanked by beam
4363 # is captain on planet?
4365 if damaged(DTRANSP):
4368 prout(_("Scotty rushes to the transporter controls."))
4370 prout(_("But with the shields up it's hopeless."))
4372 prouts(_("His desperate attempt to rescue you . . ."))
4373 if random.random() <= 0.5:
4377 prout(_("SUCCEEDS!"))
4380 proutn(_("The crystals mined were "))
4381 if random.random() <= 0.25:
4388 # Check to see if captain in shuttle craft
4393 # Inform captain of attempt to reach safety
4397 prouts(_("***RED ALERT! RED ALERT!"))
4401 prout(_(" has stopped in a quadrant containing"))
4402 prouts(_(" a supernova."))
4404 proutn(_("***Emergency automatic override attempts to hurl "))
4407 prout(_("safely out of quadrant."))
4408 if not damaged(DRADIO):
4409 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4410 # Try to use warp engines
4411 if damaged(DWARPEN):
4413 prout(_("Warp engines damaged."))
4416 game.warpfac = 6.0+2.0*random.random()
4417 game.wfacsq = game.warpfac * game.warpfac
4418 prout(_("Warp factor set to %d") % int(game.warpfac))
4419 power = 0.75*game.energy
4420 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4421 distreq = 1.4142+random.random()
4422 if distreq < game.dist:
4424 game.optime = 10.0*game.dist/game.wfacsq
4425 game.direc = 12.0*random.random() # How dumb!
4427 game.inorbit = False
4430 # This is bad news, we didn't leave quadrant.
4434 prout(_("Insufficient energy to leave quadrant."))
4437 # Repeat if another snova
4438 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4440 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4441 finish(FWON) # Snova killed remaining enemy.
4444 # let's do the time warp again
4445 prout(_("***TIME WARP ENTERED."))
4446 if game.state.snap and random.random() < 0.5:
4448 prout(_("You are traveling backwards in time %d stardates.") %
4449 int(game.state.date-game.snapsht.date))
4450 game.state = game.snapsht
4451 game.state.snap = False
4452 if game.state.remcom:
4453 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4454 schedule(FBATTAK, expran(0.3*game.intime))
4455 schedule(FSNOVA, expran(0.5*game.intime))
4456 # next snapshot will be sooner
4457 schedule(FSNAP, expran(0.25*game.state.remtime))
4459 if game.state.nscrem:
4460 schedule(FSCMOVE, 0.2777)
4464 invalidate(game.battle)
4466 # Make sure Galileo is consistant -- Snapshot may have been taken
4467 # when on planet, which would give us two Galileos!
4469 for l in range(game.inplan):
4470 if game.state.planets[l].known == "shuttle_down":
4472 if game.iscraft == "onship" and game.ship==IHE:
4473 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4474 game.iscraft = "offship"
4475 # Likewise, if in the original time the Galileo was abandoned, but
4476 # was on ship earlier, it would have vanished -- let's restore it.
4477 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4478 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4479 game.iscraft = "onship"
4481 # * There used to be code to do the actual reconstrction here,
4482 # * but the starchart is now part of the snapshotted galaxy state.
4484 prout(_("Spock has reconstructed a correct star chart from memory"))
4486 # Go forward in time
4487 game.optime = -0.5*game.intime*math.log(random.random())
4488 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4489 # cheat to make sure no tractor beams occur during time warp
4490 postpone(FTBEAM, game.optime)
4491 game.damage[DRADIO] += game.optime
4493 events() # Stas Sergeev added this -- do pending events
4496 # launch deep-space probe
4497 # New code to launch a deep space probe
4498 if game.nprobes == 0:
4501 if game.ship == IHE:
4502 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4504 prout(_("Ye Faerie Queene has no deep space probes."))
4509 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4511 if is_scheduled(FDSPROB):
4514 if damaged(DRADIO) and game.condition != "docked":
4515 prout(_("Spock- \"Records show the previous probe has not yet"))
4516 prout(_(" reached its destination.\""))
4518 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4522 # slow mode, so let Kirk know how many probes there are left
4523 if game.nprobes == 1:
4524 prout(_("1 probe left."))
4526 prout(_("%d probes left") % game.nprobes)
4527 proutn(_("Are you sure you want to fire a probe? "))
4530 game.isarmed = False
4531 if key == IHALPHA and citem == "armed":
4535 proutn(_("Arm NOVAMAX warhead? "))
4537 if not getcourse(isprobe=True, akey=key):
4540 angle = ((15.0 - game.direc) * 0.5235988)
4541 game.probeinx = -math.sin(angle)
4542 game.probeiny = math.cos(angle)
4543 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4544 bigger = math.fabs(game.probeinx)
4546 bigger = math.fabs(game.probeiny)
4547 game.probeiny /= bigger
4548 game.probeinx /= bigger
4549 game.proben = 10.0*game.dist*bigger +0.5
4550 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4551 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4552 game.probec = game.quadrant
4553 schedule(FDSPROB, 0.01) # Time to move one sector
4554 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4558 # Here's how the mayday code works:
4560 # First, the closest starbase is selected. If there is a a starbase
4561 # in your own quadrant, you are in good shape. This distance takes
4562 # quadrant distances into account only.
4564 # A magic number is computed based on the distance which acts as the
4565 # probability that you will be rematerialized. You get three tries.
4567 # When it is determined that you should be able to be rematerialized
4568 # (i.e., when the probability thing mentioned above comes up
4569 # positive), you are put into that quadrant (anywhere). Then, we try
4570 # to see if there is a spot adjacent to the star- base. If not, you
4571 # can't be rematerialized!!! Otherwise, it drops you there. It only
4572 # tries five times to find a spot to drop you. After that, it's your
4576 # yell for help from nearest starbase
4577 # There's more than one way to move in this game!
4580 # Test for conditions which prevent calling for help
4581 if game.condition == "docked":
4582 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4585 prout(_("Subspace radio damaged."))
4587 if game.state.rembase==0:
4588 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4591 proutn(_("You must be aboard the "))
4595 # OK -- call for help from nearest starbase
4598 # There's one in this quadrant
4599 ddist = distance(game.base, game.sector)
4602 for m in range(game.state.rembase):
4603 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4607 # Since starbase not in quadrant, set up new quadrant
4608 game.quadrant = game.state.baseq[line]
4610 # dematerialize starship
4611 game.quad[game.sector.x][game.sector.y]=IHDOT
4612 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4614 prout(_(" dematerializes."))
4616 for m in range(1, 5+1):
4617 ix = game.base.x+3.0*random.random()-1
4618 iy = game.base.y+3.0*random.random()-1
4619 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4620 # found one -- finish up
4624 if not is_valid(game.sector):
4625 prout(_("You have been lost in space..."))
4626 finish(FMATERIALIZE)
4628 # Give starbase three chances to rematerialize starship
4629 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4630 for m in range(1, 3+1):
4631 if m == 1: proutn(_("1st"))
4632 elif m == 2: proutn(_("2nd"))
4633 elif m == 3: proutn(_("3rd"))
4634 proutn(_(" attempt to re-materialize "))
4636 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4639 if random.random() > probf:
4642 curses.delay_output(500)
4645 game.quad[ix][iy]=IHQUEST
4648 setwnd(message_window)
4649 finish(FMATERIALIZE)
4651 game.quad[ix][iy]=game.ship
4653 prout(_("succeeds."))
4657 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4659 # Abandon Ship (the BSD-Trek description)
4661 # The ship is abandoned. If your current ship is the Faire
4662 # Queene, or if your shuttlecraft is dead, you're out of
4663 # luck. You need the shuttlecraft in order for the captain
4664 # (that's you!!) to escape.
4666 # Your crew can beam to an inhabited starsystem in the
4667 # quadrant, if there is one and if the transporter is working.
4668 # If there is no inhabited starsystem, or if the transporter
4669 # is out, they are left to die in outer space.
4671 # If there are no starbases left, you are captured by the
4672 # Klingons, who torture you mercilessly. However, if there
4673 # is at least one starbase, you are returned to the
4674 # Federation in a prisoner of war exchange. Of course, this
4675 # can't happen unless you have taken some prisoners.
4680 if game.condition=="docked":
4682 prout(_("You cannot abandon Ye Faerie Queene."))
4685 # Must take shuttle craft to exit
4686 if game.damage[DSHUTTL]==-1:
4687 prout(_("Ye Faerie Queene has no shuttle craft."))
4689 if game.damage[DSHUTTL]<0:
4690 prout(_("Shuttle craft now serving Big Macs."))
4692 if game.damage[DSHUTTL]>0:
4693 prout(_("Shuttle craft damaged."))
4696 prout(_("You must be aboard the ship."))
4698 if game.iscraft != "onship":
4699 prout(_("Shuttle craft not currently available."))
4701 # Print abandon ship messages
4703 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4705 prouts(_("***ALL HANDS ABANDON SHIP!"))
4707 prout(_("Captain and crew escape in shuttle craft."))
4708 if game.state.rembase==0:
4709 # Oops! no place to go...
4712 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4714 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4715 prout(_("Remainder of ship's complement beam down"))
4716 prout(_("to nearest habitable planet."))
4717 elif q.planet != None and not damaged(DTRANSP):
4718 prout(_("Remainder of ship's complement beam down to %s.") %
4721 prout(_("Entire crew of %d left to die in outer space.") %
4723 game.casual += game.state.crew
4724 game.abandoned += game.state.crew
4726 # If at least one base left, give 'em the Faerie Queene
4728 game.icrystl = False # crystals are lost
4729 game.nprobes = 0 # No probes
4730 prout(_("You are captured by Klingons and released to"))
4731 prout(_("the Federation in a prisoner-of-war exchange."))
4732 nb = random.random()*game.state.rembase+1
4733 # Set up quadrant and position FQ adjacient to base
4734 if not game.quadrant == game.state.baseq[nb]:
4735 game.quadrant = game.state.baseq[nb]
4736 game.sector.x = game.sector.y = 5
4739 # position next to base by trial and error
4740 game.quad[game.sector.x][game.sector.y] = IHDOT
4741 for l in range(QUADSIZE):
4742 game.sector.x = 3.0*random.random() - 1.0 + game.base.x
4743 game.sector.y = 3.0*random.random() - 1.0 + game.base.y
4744 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4745 game.quad[game.sector.x][game.sector.y] == IHDOT:
4748 break # found a spot
4749 game.sector.x=QUADSIZE/2
4750 game.sector.y=QUADSIZE/2
4752 # Get new commission
4753 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4754 game.state.crew = FULLCREW
4755 prout(_("Starfleet puts you in command of another ship,"))
4756 prout(_("the Faerie Queene, which is antiquated but,"))
4757 prout(_("still useable."))
4759 prout(_("The dilithium crystals have been moved."))
4761 game.iscraft = "offship" # Galileo disappears
4763 game.condition="docked"
4764 for l in range(NDEVICES):
4765 game.damage[l] = 0.0
4766 game.damage[DSHUTTL] = -1
4767 game.energy = game.inenrg = 3000.0
4768 game.shield = game.inshld = 1250.0
4769 game.torps = game.intorps = 6
4770 game.lsupres=game.inlsr=3.0
4776 # Code from planets.c begins here.
4779 # abort a lengthy operation if an event interrupts it
4782 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4787 # report on (uninhabited) planets in the galaxy
4791 prout(_("Spock- \"Planet report follows, Captain.\""))
4793 for i in range(game.inplan):
4794 if game.state.planets[i].pclass == "destroyed":
4796 if (game.state.planets[i].known != "unknown" \
4797 and not game.state.planets[i].inhabited) \
4800 if idebug and game.state.planets[i].known=="unknown":
4801 proutn("(Unknown) ")
4802 proutn(_("Quadrant %s") % game.state.planets[i].w)
4803 proutn(_(" class "))
4804 proutn(game.state.planets[i].pclass)
4806 if game.state.planets[i].crystals != present:
4808 prout(_("dilithium crystals present."))
4809 if game.state.planets[i].known=="shuttle_down":
4810 prout(_(" Shuttle Craft Galileo on surface."))
4812 prout(_("No information available."))
4815 # enter standard orbit
4819 prout(_("Already in standard orbit."))
4821 if damaged(DWARPEN) and damaged(DIMPULS):
4822 prout(_("Both warp and impulse engines damaged."))
4824 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4826 prout(_(" not adjacent to planet."))
4829 game.optime = 0.02+0.03*random.random()
4830 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4834 game.height = (1400.0+7200.0*random.random())
4835 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4840 # examine planets in this quadrant
4841 if damaged(DSRSENS):
4842 if game.options & OPTION_TTY:
4843 prout(_("Short range sensors damaged."))
4845 if game.iplnet == None:
4846 if game.options & OPTION_TTY:
4847 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4849 if game.iplnet.known == "unknown":
4850 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4852 prout(_(" Planet at Sector %s is of class %s.") %
4853 (game.plnet, game.iplnet.pclass))
4854 if game.iplnet.known=="shuttle_down":
4855 prout(_(" Sensors show Galileo still on surface."))
4856 proutn(_(" Readings indicate"))
4857 if game.iplnet.crystals != "present":
4859 prout(_(" dilithium crystals present.\""))
4860 if game.iplnet.known == "unknown":
4861 game.iplnet.known = "known"
4862 elif game.iplnet.inhabited:
4863 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4864 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4867 # use the transporter
4871 if damaged(DTRANSP):
4872 prout(_("Transporter damaged."))
4873 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4875 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4879 if not game.inorbit:
4881 prout(_(" not in standard orbit."))
4884 prout(_("Impossible to transport through shields."))
4886 if game.iplnet.known=="unknown":
4887 prout(_("Spock- \"Captain, we have no information on this planet"))
4888 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4889 prout(_(" you may not go down.\""))
4891 if not game.landed and game.iplnet.crystals=="absent":
4892 prout(_("Spock- \"Captain, I fail to see the logic in"))
4893 prout(_(" exploring a planet with no dilithium crystals."))
4894 proutn(_(" Are you sure this is wise?\" "))
4898 if not (game.options & OPTION_PLAIN):
4899 nrgneed = 50 * game.skill + game.height / 100.0
4900 if nrgneed > game.energy:
4901 prout(_("Engineering to bridge--"))
4902 prout(_(" Captain, we don't have enough energy for transportation."))
4904 if not game.landed and nrgneed * 2 > game.energy:
4905 prout(_("Engineering to bridge--"))
4906 prout(_(" Captain, we have enough energy only to transport you down to"))
4907 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4908 if game.iplnet.known == "shuttle_down":
4909 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4910 proutn(_(" Are you sure this is wise?\" "))
4915 # Coming from planet
4916 if game.iplnet.known=="shuttle_down":
4917 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4921 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4922 prout(_("Landing party assembled, ready to beam up."))
4924 prout(_("Kirk whips out communicator..."))
4925 prouts(_("BEEP BEEP BEEP"))
4927 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4930 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4932 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4934 prout(_("Kirk- \"Energize.\""))
4937 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4939 if random.random() > 0.98:
4940 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4942 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4945 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4946 game.landed = not game.landed
4947 game.energy -= nrgneed
4949 prout(_("Transport complete."))
4950 if game.landed and game.iplnet.known=="shuttle_down":
4951 prout(_("The shuttle craft Galileo is here!"))
4952 if not game.landed and game.imine:
4959 # strip-mine a world for dilithium
4963 prout(_("Mining party not on planet."))
4965 if game.iplnet.crystals == "mined":
4966 prout(_("This planet has already been strip-mined for dilithium."))
4968 elif game.iplnet.crystals == "absent":
4969 prout(_("No dilithium crystals on this planet."))
4972 prout(_("You've already mined enough crystals for this trip."))
4974 if game.icrystl and game.cryprob == 0.05:
4975 proutn(_("With all those fresh crystals aboard the "))
4978 prout(_("there's no reason to mine more at this time."))
4980 game.optime = (0.1+0.2*random.random())*(ord(game.iplnet.pclass)-ord("M"))
4983 prout(_("Mining operation complete."))
4984 game.iplnet.crystals = "mined"
4985 game.imine = game.ididit = True
4988 # use dilithium crystals
4992 if not game.icrystl:
4993 prout(_("No dilithium crystals available."))
4995 if game.energy >= 1000:
4996 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4997 prout(_(" except when Condition Yellow exists."))
4999 prout(_("Spock- \"Captain, I must warn you that loading"))
5000 prout(_(" raw dilithium crystals into the ship's power"))
5001 prout(_(" system may risk a severe explosion."))
5002 proutn(_(" Are you sure this is wise?\" "))
5007 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5008 prout(_(" Mr. Spock and I will try it.\""))
5010 prout(_("Spock- \"Crystals in place, Sir."))
5011 prout(_(" Ready to activate circuit.\""))
5013 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5015 if random.random() <= game.cryprob:
5016 prouts(_(" \"Activating now! - - No good! It's***"))
5018 prouts(_("***RED ALERT! RED A*L********************************"))
5021 prouts(_("****************** KA-BOOM!!!! *******************"))
5025 game.energy += 5000.0*(1.0 + 0.9*random.random())
5026 prouts(_(" \"Activating now! - - "))
5027 prout(_("The instruments"))
5028 prout(_(" are going crazy, but I think it's"))
5029 prout(_(" going to work!! Congratulations, Sir!\""))
5034 # use shuttlecraft for planetary jaunt
5037 if damaged(DSHUTTL):
5038 if game.damage[DSHUTTL] == -1.0:
5039 if game.inorbit and game.iplnet.known == "shuttle_down":
5040 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5042 prout(_("Ye Faerie Queene had no shuttle craft."))
5043 elif game.damage[DSHUTTL] > 0:
5044 prout(_("The Galileo is damaged."))
5045 else: # game.damage[DSHUTTL] < 0
5046 prout(_("Shuttle craft is now serving Big Macs."))
5048 if not game.inorbit:
5050 prout(_(" not in standard orbit."))
5052 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5053 prout(_("Shuttle craft not currently available."))
5055 if not game.landed and game.iplnet.known=="shuttle_down":
5056 prout(_("You will have to beam down to retrieve the shuttle craft."))
5058 if game.shldup or game.condition == "docked":
5059 prout(_("Shuttle craft cannot pass through shields."))
5061 if game.iplnet.known=="unknown":
5062 prout(_("Spock- \"Captain, we have no information on this planet"))
5063 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5064 prout(_(" you may not fly down.\""))
5066 game.optime = 3.0e-5*game.height
5067 if game.optime >= 0.8*game.state.remtime:
5068 prout(_("First Officer Spock- \"Captain, I compute that such"))
5069 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5070 int(100*game.optime/game.state.remtime))
5071 prout(_("remaining time."))
5072 proutn(_("Are you sure this is wise?\" "))
5078 if game.iscraft == "onship":
5080 if not damaged(DTRANSP):
5081 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5085 proutn(_("Shuttle crew"))
5087 proutn(_("Rescue party"))
5088 prout(_(" boards Galileo and swoops toward planet surface."))
5089 game.iscraft = "offship"
5093 game.iplnet.known="shuttle_down"
5094 prout(_("Trip complete."))
5097 # Ready to go back to ship
5098 prout(_("You and your mining party board the"))
5099 prout(_("shuttle craft for the trip back to the Enterprise."))
5101 prouts(_("The short hop begins . . ."))
5103 game.iplnet.known="known"
5109 game.iscraft = "onship"
5115 prout(_("Trip complete."))
5120 prout(_("Mining party assembles in the hangar deck,"))
5121 prout(_("ready to board the shuttle craft \"Galileo\"."))
5123 prouts(_("The hangar doors open; the trip begins."))
5126 game.iscraft = "offship"
5129 game.iplnet.known = "shuttle_down"
5132 prout(_("Trip complete."))
5136 # use the big zapper
5141 if game.ship != IHE:
5142 prout(_("Ye Faerie Queene has no death ray."))
5145 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5148 prout(_("Death Ray is damaged."))
5150 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5151 prout(_(" is highly unpredictible. Considering the alternatives,"))
5152 proutn(_(" are you sure this is wise?\" "))
5155 prout(_("Spock- \"Acknowledged.\""))
5158 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5160 prout(_("Crew scrambles in emergency preparation."))
5161 prout(_("Spock and Scotty ready the death ray and"))
5162 prout(_("prepare to channel all ship's power to the device."))
5164 prout(_("Spock- \"Preparations complete, sir.\""))
5165 prout(_("Kirk- \"Engage!\""))
5167 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5170 if game.options & OPTION_PLAIN:
5173 prouts(_("Sulu- \"Captain! It's working!\""))
5175 while game.nenhere > 0:
5176 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5177 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5178 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5180 if (game.options & OPTION_PLAIN) == 0:
5181 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5182 if random.random() <= 0.05:
5183 prout(_(" is still operational.\""))
5185 prout(_(" has been rendered nonfunctional.\""))
5186 game.damage[DDRAY] = 39.95
5188 r = random.random() # Pick failure method
5190 prouts(_("Sulu- \"Captain! It's working!\""))
5192 prouts(_("***RED ALERT! RED ALERT!"))
5194 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5196 prouts(_("***RED ALERT! RED A*L********************************"))
5199 prouts(_("****************** KA-BOOM!!!! *******************"))
5204 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5206 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5208 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5209 prout(_(" have apparently been transformed into strange mutations."))
5210 prout(_(" Vulcans do not seem to be affected."))
5212 prout(_("Kirk- \"Raauch! Raauch!\""))
5217 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5219 proutn(_("Spock- \"I believe the word is"))
5220 prouts(_(" *ASTONISHING*"))
5221 prout(_(" Mr. Sulu."))
5222 for i in range(QUADSIZE):
5223 for j in range(QUADSIZE):
5224 if game.quad[i][j] == IHDOT:
5225 game.quad[i][j] = IHQUEST
5226 prout(_(" Captain, our quadrant is now infested with"))
5227 prouts(_(" - - - - - - *THINGS*."))
5229 prout(_(" I have no logical explanation.\""))
5231 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5233 prout(_("Scotty- \"There are so many tribbles down here"))
5234 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5238 # Code from reports.c begins here
5240 def attackreport(curt):
5241 # report status of bases under attack
5243 if is_scheduled(FCDBAS):
5244 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5245 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5246 elif game.isatb == 1:
5247 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5248 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5250 prout(_("No Starbase is currently under attack."))
5252 if is_scheduled(FCDBAS):
5253 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5255 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5259 # report on general game status
5261 s1 = "" and game.thawed and _("thawed ")
5262 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5263 s3 = (None, _("novice"). _("fair"),
5264 _("good"), _("expert"), _("emeritus"))[game.skill]
5265 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5266 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5267 prout(_("No plaque is allowed."))
5269 prout(_("This is tournament game %d.") % game.tourn)
5270 prout(_("Your secret password is \"%s\"") % game.passwd)
5271 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5272 (game.inkling + game.incom + game.inscom)))
5273 if game.incom - game.state.remcom:
5274 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5275 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5276 prout(_(", but no Commanders."))
5279 if game.skill > SKILL_FAIR:
5280 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5281 if game.state.rembase != game.inbase:
5283 if game.inbase-game.state.rembase==1:
5284 proutn(_("has been 1 base"))
5286 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5287 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5289 prout(_("There are %d bases.") % game.inbase)
5290 if communicating() or game.iseenit:
5291 # Don't report this if not seen and
5292 # either the radio is dead or not at base!
5296 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5298 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5299 if game.ship == IHE:
5300 proutn(_("You have "))
5302 proutn("%d" % (game.nprobes))
5305 proutn(_(" deep space probe"))
5309 if communicating() and is_scheduled(FDSPROB):
5311 proutn(_("An armed deep space probe is in "))
5313 proutn(_("A deep space probe is in "))
5314 prout("Quadrant %s." % game.probec)
5316 if game.cryprob <= .05:
5317 prout(_("Dilithium crystals aboard ship... not yet used."))
5321 while game.cryprob > ai:
5324 prout(_("Dilithium crystals have been used %d time%s.") % \
5325 (i, (_("s"), "")[i==1]))
5329 # long-range sensor scan
5330 if damaged(DLRSENS):
5331 # Now allow base's sensors if docked
5332 if game.condition != "docked":
5333 prout(_("LONG-RANGE SENSORS DAMAGED."))
5335 prout(_("Starbase's long-range scan"))
5337 prout(_("Long-range scan"))
5338 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5340 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5341 if not VALID_QUADRANT(x, y):
5344 if not damaged(DRADIO):
5345 game.state.galaxy[x][y].charted = True
5346 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5347 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5348 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5349 if game.state.galaxy[x][y].supernova:
5352 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5360 for i in range(NDEVICES):
5363 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5364 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5366 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5367 game.damage[i]+0.05,
5368 game.docfac*game.damage[i]+0.005))
5370 prout(_("All devices functional."))
5373 # update the chart in the Enterprise's computer from galaxy data
5374 game.lastchart = game.state.date
5375 for i in range(GALSIZE):
5376 for j in range(GALSIZE):
5377 if game.state.galaxy[i][j].charted:
5378 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5379 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5380 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5383 # display the star chart
5385 if not damaged(DRADIO):
5387 if game.lastchart < game.state.date and game.condition == "docked":
5388 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5391 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5392 if game.state.date > game.lastchart:
5393 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5394 prout(" 1 2 3 4 5 6 7 8")
5395 for i in range(GALSIZE):
5396 proutn("%d |" % (i+1))
5397 for j in range(GALSIZE):
5398 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5402 if game.state.galaxy[i][j].supernova:
5404 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5406 elif game.state.galaxy[i][j].charted:
5407 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5411 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5419 def sectscan(goodScan, i, j):
5420 # light up an individual dot in a sector
5421 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5422 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):
5423 if game.condition == "red": textcolor(RED)
5424 elif game.condition == "green": textcolor(GREEN)
5425 elif game.condition == "yellow": textcolor(YELLOW)
5426 elif game.condition == "docked": textcolor(CYAN)
5427 elif game.condition == "dead": textcolor(BROWN)
5428 if game.quad[i][j] != game.ship:
5430 proutn("%c " % game.quad[i][j])
5436 # print status report lines
5438 if not req or req == 1:
5439 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5440 % (game.state.date, game.state.remtime))
5441 if not req or req == 2:
5442 if game.condition != "docked":
5445 for t in range(NDEVICES):
5446 if game.damage[t]>0:
5448 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5449 if not req or req == 3:
5450 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5451 if not req or req == 4:
5452 if damaged(DLIFSUP):
5453 if game.condition == "docked":
5454 s = _("DAMAGED, Base provides")
5456 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5459 prstat(_("Life Support"), s)
5460 if not req or req == 5:
5461 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5462 if not req or req == 6:
5464 if game.icrystl and (game.options & OPTION_SHOWME):
5465 extra = _(" (have crystals)")
5466 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5467 if not req or req == 7:
5468 prstat(_("Torpedoes"), "%d" % (game.torps))
5469 if not req or req == 8:
5470 if damaged(DSHIELD):
5476 data = _(" %d%% %.1f units") \
5477 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5478 prstat(_("Shields"), s+data)
5479 if not req or req == 9:
5480 prstat(_("Klingons Left"), "%d" \
5481 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5482 if not req or req == 10:
5483 if game.options & OPTION_WORLDS:
5484 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5485 if plnet and plnet.inhabited:
5486 prstat(_("Major system"), plnet.name)
5488 prout(_("Sector is uninhabited"))
5489 elif not req or req == 11:
5490 attackreport(not req)
5493 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5494 while scan() == IHEOL:
5495 proutn(_("Information desired? "))
5497 if citem in requests:
5498 status(requests.index(citem))
5500 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5501 prout((" date, condition, position, lsupport, warpfactor,"))
5502 prout((" energy, torpedoes, shields, klingons, system, time."))
5507 if damaged(DSRSENS):
5508 # Allow base's sensors if docked
5509 if game.condition != "docked":
5510 prout(_(" S.R. SENSORS DAMAGED!"))
5513 prout(_(" [Using Base's sensors]"))
5515 prout(_(" Short-range scan"))
5516 if goodScan and not damaged(DRADIO):
5517 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5518 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5519 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5520 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5521 prout(" 1 2 3 4 5 6 7 8 9 10")
5522 if game.condition != "docked":
5524 for i in range(QUADSIZE):
5525 proutn("%2d " % (i+1))
5526 for j in range(QUADSIZE):
5527 sectscan(goodScan, i, j)
5532 # use computer to get estimated time of arrival for a warp jump
5533 w1 = coord(); w2 = coord()
5535 if damaged(DCOMPTR):
5536 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5539 if scan() != IHREAL:
5542 proutn(_("Destination quadrant and/or sector? "))
5546 w1.y = int(aaitem-0.5)
5547 if scan() != IHREAL:
5550 w1.x = int(aaitem-0.5)
5551 if scan() == IHREAL:
5552 w2.y = int(aaitem-0.5)
5553 if scan() != IHREAL:
5556 w2.x = int(aaitem-0.5)
5558 if game.quadrant.y>w1.x:
5562 if game.quadrant.x>w1.y:
5566 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5569 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5570 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5573 prout(_("Answer \"no\" if you don't know the value:"))
5576 proutn(_("Time or arrival date? "))
5579 if ttime > game.state.date:
5580 ttime -= game.state.date # Actually a star date
5581 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5582 if ttime <= 1e-10 or twarp > 10:
5583 prout(_("We'll never make it, sir."))
5590 proutn(_("Warp factor? "))
5594 if twarp<1.0 or twarp > 10.0:
5598 prout(_("Captain, certainly you can give me one of these."))
5601 ttime = (10.0*game.dist)/square(twarp)
5602 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5603 if tpower >= game.energy:
5604 prout(_("Insufficient energy, sir."))
5605 if not game.shldup or tpower > game.energy*2.0:
5608 proutn(_("New warp factor to try? "))
5609 if scan() == IHREAL:
5612 if twarp<1.0 or twarp > 10.0:
5620 prout(_("But if you lower your shields,"))
5621 proutn(_("remaining"))
5624 proutn(_("Remaining"))
5625 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5627 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5629 prout(_("Any warp speed is adequate."))
5631 prout(_("Minimum warp needed is %.2f,") % (twarp))
5632 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5633 if game.state.remtime < ttime:
5634 prout(_("Unfortunately, the Federation will be destroyed by then."))
5636 prout(_("You'll be taking risks at that speed, Captain"))
5637 if (game.isatb==1 and game.state.kscmdr == w1 and \
5638 scheduled(FSCDBAS)< ttime+game.state.date) or \
5639 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5640 prout(_("The starbase there will be destroyed by then."))
5641 proutn(_("New warp factor to try? "))
5642 if scan() == IHREAL:
5645 if twarp<1.0 or twarp > 10.0:
5654 #ifdef BSD_BUG_FOR_BUG
5655 # A visual scan is made in a particular direction of three sectors
5656 # in the general direction specified. This takes time, and
5657 # Klingons can attack you, so it should be done only when sensors
5658 # are out. Code swiped from BSD-Trek. Not presently used, as we
5659 # automatically display all adjacent sectors on the short-range
5660 # scan even when short-range sensors are out.
5662 # This struct[] has the delta x, delta y for particular directions
5680 if scan() != IHREAL:
5682 proutn(_("Direction? "))
5686 if aaitem < 0.0 or aaitem > 360.0:
5688 co = (aaitem + 22) / 45
5690 ix = game.sector.x + v.x
5691 iy = game.sector.y + v.y
5692 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5695 co = game.quad[ix][iy]
5696 printf("%d,%d %c " % (ix+1, iy+1, co))
5698 ix = game.sector.x + v.x
5699 iy = game.sector.y + v.y
5700 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5703 co = game.quad[ix][iy]
5704 printf("%c " % (co))
5706 ix = game.sector.x + v.x
5707 iy = game.sector.y + v.y
5708 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5711 co = game.quad[ix][iy]
5712 prout("%c %d,%d\n" % (co, ix+1, iy+1))
5717 # Code from setup.c begins here
5720 # issue a historically correct banner
5722 prout(_("-SUPER- STAR TREK"))
5724 #ifdef __HISTORICAL__
5725 # prout(_("Latest update-21 Sept 78"))
5727 #endif __HISTORICAL__
5732 citem = "emsave.trk"
5736 proutn(_("File name: "))
5742 if '.' not in citem:
5745 fp = open(citem, "wb")
5747 prout(_("Can't freeze game as file %s") % citem)
5749 cPickle.dump(game, fp)
5753 # retrieve saved game
5754 game.passwd[0] = '\0'
5757 proutn(_("File name: "))
5763 if '.' not in citem:
5766 fp = open(citem, "rb")
5768 prout(_("Can't thaw game in %s") % citem)
5770 game = cPickle.load(fp)
5774 # I used <http://www.memory-alpha.org> to find planets
5775 # with references in ST:TOS. Eath and the Alpha Centauri
5776 # Colony have been omitted.
5778 # Some planets marked Class G and P here will be displayed as class M
5779 # because of the way planets are generated. This is a known bug.
5782 _("Andoria (Fesoan)"), # several episodes
5783 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5784 _("Vulcan (T'Khasi)"), # many episodes
5785 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5786 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5787 _("Ardana"), # TOS: "The Cloud Minders"
5788 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5789 _("Gideon"), # TOS: "The Mark of Gideon"
5790 _("Aldebaran III"), # TOS: "The Deadly Years"
5791 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5792 _("Altair IV"), # TOS: "Amok Time
5793 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5794 _("Benecia"), # TOS: "The Conscience of the King"
5795 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5796 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5797 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5798 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5799 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5800 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5801 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5802 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5803 _("Ingraham B"), # TOS: "Operation: Annihilate"
5804 _("Janus IV"), # TOS: "The Devil in the Dark"
5805 _("Makus III"), # TOS: "The Galileo Seven"
5806 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5807 _("Omega IV"), # TOS: "The Omega Glory"
5808 _("Regulus V"), # TOS: "Amok Time
5809 _("Deneva"), # TOS: "Operation -- Annihilate!"
5810 # Worlds from BSD Trek
5811 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5812 _("Beta III"), # TOS: "The Return of the Archons"
5813 _("Triacus"), # TOS: "And the Children Shall Lead",
5814 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5816 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5817 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5818 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5819 # _("Izar"), # TOS: "Whom Gods Destroy"
5820 # _("Tiburon"), # TOS: "The Way to Eden"
5821 # _("Merak II"), # TOS: "The Cloud Minders"
5822 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5823 # _("Iotia"), # TOS: "A Piece of the Action"
5827 _("S. R. Sensors"), \
5828 _("L. R. Sensors"), \
5830 _("Photon Tubes"), \
5831 _("Life Support"), \
5832 _("Warp Engines"), \
5833 _("Impulse Engines"), \
5835 _("Subspace Radio"), \
5836 _("Shuttle Craft"), \
5838 _("Navigation System"), \
5840 _("Shield Control"), \
5845 def setup(needprompt):
5846 # prepare to play, set up cosmos
5848 # Decide how many of everything
5849 if choose(needprompt):
5850 return # frozen game
5851 # Prepare the Enterprise
5852 game.alldone = game.gamewon = False
5854 game.state.crew = FULLCREW
5855 game.energy = game.inenrg = 5000.0
5856 game.shield = game.inshld = 2500.0
5857 game.shldchg = False
5861 game.quadrant = randplace(GALSIZE)
5862 game.sector = randplace(QUADSIZE)
5863 game.torps = game.intorps = 10
5864 game.nprobes = int(3.0*random.random() + 2.0) # Give them 2-4 of these
5866 game.wfacsq = game.warpfac * game.warpfac
5867 for i in range(NDEVICES):
5868 game.damage[i] = 0.0
5869 # Set up assorted game parameters
5870 game.battle = coord()
5871 game.state.date = game.indate = 100.0*int(31.0*random.random()+20.0)
5872 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5873 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5874 game.isatb = game.state.nplankl = 0
5875 game.state.starkl = game.state.basekl = 0
5876 game.iscraft = "onship"
5880 for i in range(GALSIZE):
5881 for j in range(GALSIZE):
5882 quad = game.state.galaxy[i][j]
5887 quad.starbase = False
5888 quad.supernova = False
5889 quad.status = "secure"
5890 # Initialize times for extraneous events
5891 schedule(FSNOVA, expran(0.5 * game.intime))
5892 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5893 schedule(FSNAP, 1.0 + random.random()) # Force an early snapshot
5894 schedule(FBATTAK, expran(0.3*game.intime))
5896 if game.state.nscrem:
5897 schedule(FSCMOVE, 0.2777)
5902 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5903 schedule(FDISTR, expran(1.0 + game.intime))
5908 # Starchart is functional but we've never seen it
5909 game.lastchart = FOREVER
5910 # Put stars in the galaxy
5912 for i in range(GALSIZE):
5913 for j in range(GALSIZE):
5914 k = int(random.random()*9.0 + 1.0)
5916 game.state.galaxy[i][j].stars = k
5917 # Locate star bases in galaxy
5918 for i in range(game.inbase):
5921 w = randplace(GALSIZE)
5922 if not game.state.galaxy[w.x][w.y].starbase:
5925 # C version: for (j = i-1; j > 0; j--)
5926 # so it did them in the opposite order.
5927 for j in range(1, i):
5928 # Improved placement algorithm to spread out bases
5929 distq = w.distance(game.state.baseq[j])
5930 if distq < 6.0*(BASEMAX+1-game.inbase) and random.random() < 0.75:
5933 prout("=== Abandoning base #%d at %s" % (i, w))
5935 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5937 prout("=== Saving base #%d, close to #%d" % (i, j))
5940 game.state.baseq[i] = w
5941 game.state.galaxy[w.x][w.y].starbase = True
5942 game.state.chart[w.x][w.y].starbase = True
5943 # Position ordinary Klingon Battle Cruisers
5945 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5946 if klumper > MAXKLQUAD:
5950 klump = (1.0 - r*r)*klumper
5955 w = randplace(GALSIZE)
5956 if not game.state.galaxy[w.x][w.y].supernova and \
5957 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5959 game.state.galaxy[w.x][w.y].klingons += int(klump)
5962 # Position Klingon Commander Ships
5963 for i in range(1, game.incom+1):
5965 w = randplace(GALSIZE)
5966 if (game.state.galaxy[w.x][w.y].klingons or random.random()>=0.75) and \
5967 not game.state.galaxy[w.x][w.y].supernova and \
5968 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5969 not w in game.state.kcmdr[:i]:
5971 game.state.galaxy[w.x][w.y].klingons += 1
5972 game.state.kcmdr[i] = w
5973 # Locate planets in galaxy
5974 for i in range(game.inplan):
5976 w = randplace(GALSIZE)
5977 if game.state.galaxy[w.x][w.y].planet == None:
5981 new.crystals = "absent"
5982 if (game.options & OPTION_WORLDS) and i < NINHAB:
5983 new.pclass = "M" # All inhabited planets are class M
5984 new.crystals = "absent"
5986 new.name = systnames[i]
5987 new.inhabited = True
5989 new.pclass = ("M", "N", "O")[random.randint(0, 2)]
5990 if random.random()*1.5: # 1 in 3 chance of crystals
5991 new.crystals = "present"
5992 new.known = "unknown"
5993 new.inhabited = False
5994 game.state.galaxy[w.x][w.y].planet = new
5995 game.state.planets.append(new)
5997 for i in range(game.state.nromrem):
5998 w = randplace(GALSIZE)
5999 game.state.galaxy[w.x][w.y].romulans += 1
6000 # Locate the Super Commander
6001 if game.state.nscrem > 0:
6003 w = randplace(GALSIZE)
6004 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
6006 game.state.kscmdr = w
6007 game.state.galaxy[w.x][w.y].klingons += 1
6008 # Place thing (in tournament game, thingx == -1, don't want one!)
6011 thing = randplace(GALSIZE)
6013 game.state.snap = False
6014 if game.skill == SKILL_NOVICE:
6015 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6016 prout(_("a deadly Klingon invasion force. As captain of the United"))
6017 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6018 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6019 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6020 prout(_("your mission. As you proceed you may be given more time."))
6022 prout(_("You will have %d supporting starbases.") % (game.inbase))
6023 proutn(_("Starbase locations- "))
6025 prout(_("Stardate %d.") % int(game.state.date))
6027 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6028 prout(_("An unknown number of Romulans."))
6029 if game.state.nscrem:
6030 prout(_("And one (GULP) Super-Commander."))
6031 prout(_("%d stardates.") % int(game.intime))
6032 proutn(_("%d starbases in ") % game.inbase)
6033 for i in range(game.inbase):
6034 proutn(`game.state.baseq[i]`)
6037 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6038 proutn(_(" Sector %s") % game.sector)
6040 prout(_("Good Luck!"))
6041 if game.state.nscrem:
6042 prout(_(" YOU'LL NEED IT."))
6045 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
6047 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6050 def choose(needprompt):
6051 # choose your game type
6056 game.skill = SKILL_NONE
6058 if needprompt: # Can start with command line options
6059 proutn(_("Would you like a regular, tournament, or saved game? "))
6061 if len(citem)==0: # Try again
6063 if isit("tournament"):
6064 while scan() == IHEOL:
6065 proutn(_("Type in tournament number-"))
6068 continue # We don't want a blank entry
6069 game.tourn = int(round(aaitem))
6072 if isit("saved") or isit("frozen"):
6076 if game.passwd == None:
6078 if not game.alldone:
6079 game.thawed = True # No plaque if not finished
6085 proutn(_("What is \"%s\"?"), citem)
6087 while game.length==0 or game.skill==SKILL_NONE:
6088 if scan() == IHALPHA:
6091 elif isit("medium"):
6095 elif isit("novice"):
6096 game.skill = SKILL_NOVICE
6098 game.skill = SKILL_FAIR
6100 game.skill = SKILL_GOOD
6101 elif isit("expert"):
6102 game.skill = SKILL_EXPERT
6103 elif isit("emeritus"):
6104 game.skill = SKILL_EMERITUS
6106 proutn(_("What is \""))
6112 proutn(_("Would you like a Short, Medium, or Long game? "))
6113 elif game.skill == SKILL_NONE:
6114 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6115 # Choose game options -- added by ESR for SST2K
6116 if scan() != IHALPHA:
6118 proutn(_("Choose your game style (or just press enter): "))
6121 # Approximates the UT FORTRAN version.
6122 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6123 game.options |= OPTION_PLAIN
6125 # Approximates Tom Almy's version.
6126 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6127 game.options |= OPTION_ALMY
6131 proutn(_("What is \"%s\"?") % citem)
6133 if game.passwd == "debug":
6135 fputs("=== Debug mode enabled\n", sys.stdout)
6137 # Use parameters to generate initial values of things
6138 game.damfac = 0.5 * game.skill
6139 game.state.rembase = random.randint(BASEMIN, BASEMAX)
6140 game.inbase = game.state.rembase
6142 if game.options & OPTION_PLANETS:
6143 game.inplan += int((MAXUNINHAB/2) + (MAXUNINHAB/2+1)*random.random())
6144 if game.options & OPTION_WORLDS:
6145 game.inplan += int(NINHAB)
6146 game.state.nromrem = game.inrom = int((2.0+random.random())*game.skill)
6147 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6148 game.state.remtime = 7.0 * game.length
6149 game.intime = game.state.remtime
6150 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*random.random())*game.skill*0.1+.15)
6151 game.incom = int(game.skill + 0.0625*game.inkling*random.random())
6152 game.state.remcom = min(10, game.incom)
6153 game.incom = game.state.remcom
6154 game.state.remres = (game.inkling+4*game.incom)*game.intime
6155 game.inresor = game.state.remres
6156 if game.inkling > 50:
6157 game.state.rembase += 1
6158 game.inbase = game.state.rembase
6162 # drop a feature on a random dot in the current quadrant
6165 w = randplace(QUADSIZE)
6166 if game.quad[w.x][w.y] == IHDOT:
6168 game.quad[w.x][w.y] = iquad
6172 # update our alert status
6173 game.condition = "green"
6174 if game.energy < 1000.0:
6175 game.condition = "yellow"
6176 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6177 game.condition = "red"
6179 game.condition="dead"
6182 # drop new Klingon into current quadrant
6185 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6186 game.kpower[i] = random.random()*150.0 +300.0 +25.0*game.skill
6190 # set up a new state of quadrant, for when we enter or re-enter it
6194 game.comhere = False
6200 game.inorbit = False
6202 game.ientesc = False
6205 game.iseenit = False
6207 # Attempt to escape Super-commander, so tbeam back!
6210 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6211 # cope with supernova
6214 game.klhere = q.klingons
6215 game.irhere = q.romulans
6216 game.nenhere = game.klhere + game.irhere
6218 game.quad[game.sector.x][game.sector.y] = game.ship
6220 w.x = w.y = 0 # quiet a gcc warning
6221 # Position ordinary Klingons
6222 for i in range(game.klhere):
6224 # If we need a commander, promote a Klingon
6225 for i in range(game.state.remcom):
6226 if game.state.kcmdr[i] == game.quadrant:
6229 if i <= game.state.remcom:
6230 game.quad[w.x][w.y] = IHC
6231 game.kpower[game.klhere] = 950.0+400.0*random.random()+50.0*game.skill
6233 # If we need a super-commander, promote a Klingon
6234 if game.quadrant == game.state.kscmdr:
6235 game.quad[game.ks[0].x][game.ks[0].y] = IHS
6236 game.kpower[1] = 1175.0 + 400.0*random.random() + 125.0*game.skill
6237 game.iscate = (game.state.remkl > 1)
6239 # Put in Romulans if needed
6240 for i in range(game.klhere, game.nenhere):
6243 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6244 game.kpower[i] = random.random()*400.0 + 450.0 + 50.0*game.skill
6245 # If quadrant needs a starbase, put it in
6247 game.base = dropin(IHB)
6248 # If quadrant needs a planet, put it in
6250 game.iplnet = q.planet
6251 if not q.planet.inhabited:
6252 game.plnet = dropin(IHP)
6254 game.plnet = dropin(IHW)
6255 # Check for condition
6257 # And finally the stars
6258 for i in range(q.stars):
6262 if game.irhere > 0 and game.klhere == 0:
6264 if not damaged(DRADIO):
6266 prout(_("LT. Uhura- \"Captain, an urgent message."))
6267 prout(_(" I'll put it on audio.\" CLICK"))
6269 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6270 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6272 # Put in THING if needed
6274 if thing == game.quadrant:
6276 thing = randplace(GALSIZE)
6278 game.ks[game.nenhere] = w
6279 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6280 distance(game.sector, w)
6281 game.kpower[game.nenhere] = random.random()*6000.0 +500.0 +250.0*game.skill
6282 if not damaged(DSRSENS):
6284 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6285 prout(_(" Please examine your short-range scan.\""))
6286 # Decide if quadrant needs a Tholian; lighten up if skill is low
6287 if game.options & OPTION_THOLIAN:
6288 if (game.skill < SKILL_GOOD and random.random() <= 0.02) or \
6289 (game.skill == SKILL_GOOD and random.random() <= 0.05) or \
6290 (game.skill > SKILL_GOOD and random.random() <= 0.08):
6291 game.tholian = coord()
6293 game.tholian.x = random.choice((0, QUADSIZE-1))
6294 game.tholian.y = random.choice((0, QUADSIZE-1))
6295 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6297 game.quad[game.tholian.x][game.tholian.y] = IHT
6299 game.ks[game.nenhere] = game.tholian
6300 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6301 distance(game.sector, game.tholian)
6302 game.kpower[game.nenhere] = random.random()*400.0 +100.0 +25.0*game.skill
6303 # Reserve unoccupied corners
6304 if game.quad[0][0]==IHDOT:
6305 game.quad[0][0] = 'X'
6306 if game.quad[0][QUADSIZE-1]==IHDOT:
6307 game.quad[0][QUADSIZE-1] = 'X'
6308 if game.quad[QUADSIZE-1][0]==IHDOT:
6309 game.quad[QUADSIZE-1][0] = 'X'
6310 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6311 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6313 # Put in a few black holes
6314 for i in range(1, 3+1):
6315 if random.random() > 0.5:
6317 # Take out X's in corners if Tholian present
6319 if game.quad[0][0]=='X':
6320 game.quad[0][0] = IHDOT
6321 if game.quad[0][QUADSIZE-1]=='X':
6322 game.quad[0][QUADSIZE-1] = IHDOT
6323 if game.quad[QUADSIZE-1][0]=='X':
6324 game.quad[QUADSIZE-1][0] = IHDOT
6325 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6326 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6329 # sort Klingons by distance from us
6330 # The author liked bubble sort. So we will use it. :-(
6331 if game.nenhere-(thing==game.quadrant)-(game.tholian!=None) < 2:
6335 for j in range(game.nenhere):
6336 if game.kdist[j] > game.kdist[j+1]:
6339 game.kdist[j] = game.kdist[j+1]
6342 game.kavgd[j] = game.kavgd[j+1]
6345 game.ks[j].x = game.ks[j+1].x
6348 game.ks[j].y = game.ks[j+1].y
6351 game.kpower[j] = game.kpower[j+1]
6352 game.kpower[j+1] = t
6357 # set the self-destruct password
6358 if game.options & OPTION_PLAIN:
6361 proutn(_("Please type in a secret password- "))
6364 if game.passwd != None:
6369 game.passwd += chr(97+int(random.random()*25))
6371 # Code from sst.c begins here
6374 "SRSCAN": OPTION_TTY,
6375 "STATUS": OPTION_TTY,
6376 "REQUEST": OPTION_TTY,
6377 "LRSCAN": OPTION_TTY,
6390 "SENSORS": OPTION_PLANETS,
6391 "ORBIT": OPTION_PLANETS,
6392 "TRANSPORT": OPTION_PLANETS,
6393 "MINE": OPTION_PLANETS,
6394 "CRYSTALS": OPTION_PLANETS,
6395 "SHUTTLE": OPTION_PLANETS,
6396 "PLANETS": OPTION_PLANETS,
6401 "PROBE": OPTION_PROBE,
6403 "FREEZE": 0, # Synonym for SAVE
6409 "SOS": 0, # Synonym for MAYDAY
6410 "CALL": 0, # Synonym for MAYDAY
6417 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6420 # generate a list of legal commands
6422 proutn(_("LEGAL COMMANDS ARE:"))
6423 for key in commands:
6427 proutn("%-12s " % key)
6432 # browse on-line help
6433 # Give help on commands
6437 setwnd(prompt_window)
6438 proutn(_("Help on what command? "))
6440 setwnd(message_window)
6443 if citem in commands or citem == "ABBREV":
6452 fp = open(SSTDOC, "r")
6455 fp = open(DOC_NAME, "r")
6457 prout(_("Spock- \"Captain, that information is missing from the"))
6458 proutn(_(" computer. You need to find "))
6460 prout(_(" and put it in the"))
6461 proutn(_(" current directory or to "))
6465 # This used to continue: "You need to find SST.DOC and put
6466 # it in the current directory."
6470 linebuf = fp.readline()
6472 prout(_("Spock- \"Captain, there is no information on that command.\""))
6475 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6476 linebuf = linebuf[3:].strip()
6480 prout(_("Spock- \"Captain, I've found the following information:\""))
6482 while linebuf in fp:
6483 if "******" in linebuf:
6489 # command-interpretation loop
6492 setwnd(message_window)
6493 while True: # command loop
6495 while True: # get a command
6500 setwnd(prompt_window)
6504 if game.options & OPTION_CURSES:
6509 setwnd(message_window)
6511 candidates = filter(lambda x: x.startswith(citem.upper()),
6513 if len(candidates) == 1:
6516 elif candidates and not (game.options & OPTION_PLAIN):
6517 prout("Commands with that prefix: " + " ".join(candidates))
6521 if cmd == "SRSCAN": # srscan
6523 elif cmd == "STATUS": # status
6525 elif cmd == "REQUEST": # status request
6527 elif cmd == "LRSCAN": # long range scan
6529 elif cmd == "PHASERS": # phasers
6533 elif cmd == "TORPEDO": # photon torpedos
6537 elif cmd == "MOVE": # move under warp
6539 elif cmd == "SHIELDS": # shields
6540 doshield(shraise=False)
6543 game.shldchg = False
6544 elif cmd == "DOCK": # dock at starbase
6548 elif cmd == "DAMAGES": # damage reports
6550 elif cmd == "CHART": # chart
6552 elif cmd == "IMPULSE": # impulse
6554 elif cmd == "REST": # rest
6558 elif cmd == "WARP": # warp
6560 elif cmd == "SCORE": # score
6562 elif cmd == "SENSORS": # sensors
6564 elif cmd == "ORBIT": # orbit
6568 elif cmd == "TRANSPORT": # transport "beam"
6570 elif cmd == "MINE": # mine
6574 elif cmd == "CRYSTALS": # crystals
6578 elif cmd == "SHUTTLE": # shuttle
6582 elif cmd == "PLANETS": # Planet list
6584 elif cmd == "REPORT": # Game Report
6586 elif cmd == "COMPUTER": # use COMPUTER!
6588 elif cmd == "COMMANDS":
6590 elif cmd == "EMEXIT": # Emergency exit
6591 clrscr() # Hide screen
6592 freeze(True) # forced save
6593 os.exit(1) # And quick exit
6594 elif cmd == "PROBE":
6595 probe() # Launch probe
6598 elif cmd == "ABANDON": # Abandon Ship
6600 elif cmd == "DESTRUCT": # Self Destruct
6602 elif cmd == "SAVE": # Save Game
6605 if game.skill > SKILL_GOOD:
6606 prout(_("WARNING--Saved games produce no plaques!"))
6607 elif cmd == "DEATHRAY": # Try a desparation measure
6611 elif cmd == "DEBUGCMD": # What do we want for debug???
6613 elif cmd == "MAYDAY": # Call for help
6618 game.alldone = True # quit the game
6621 elif cmd == "SEED": # set random-number seed
6624 seed = int(round(aaitem))
6625 #ifdef BSD_BUG_FOR_BUG
6626 # elif cmd == "VISUAL":
6627 # visual() # perform visual scan
6631 break # Game has ended
6632 if game.optime != 0.0:
6635 break # Events did us in
6636 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6639 if hitme and not game.justin:
6643 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6655 if cmd == IHR: s = _("Romulan")
6656 elif cmd == IHK: s = _("Klingon")
6657 elif cmd == IHC: s = _("Commander")
6658 elif cmd == IHS: s = _("Super-commander")
6659 elif cmd == IHSTAR: s = _("Star")
6660 elif cmd == IHP: s = _("Planet")
6661 elif cmd == IHB: s = _("Starbase")
6662 elif cmd == IHBLANK: s = _("Black hole")
6663 elif cmd == IHT: s = _("Tholian")
6664 elif cmd == IHWEB: s = _("Tholian web")
6665 elif cmd == IHQUEST: s = _("Stranger")
6666 elif cmd == IHW: s = _("Inhabited World")
6667 else: s = "Unknown??"
6670 def crmena(stars, enemy, loctype, w):
6671 # print an enemy and his location
6677 if loctype == "quadrant":
6678 buf = _("Quadrant ")
6679 elif loctype == "sector":
6684 # print our ship name
6685 if game.ship == IHE:
6687 elif game.ship == IHF:
6688 s = _("Faerie Queene")
6694 # print a line of stars
6695 prouts("******************************************************")
6699 return -avrage*math.log(1e-7 + random.random())
6701 def randplace(size):
6702 # choose a random location
6704 w.x = random.randint(0, size-1)
6705 w.y = random.randint(0, size-1)
6709 # Demand input for next scan
6714 # return IHEOL next time
6719 # Get a token from the user
6720 global inqueue, line, citem, aaitem
6724 # Read a line if nothing here
6727 if curwnd==prompt_window:
6729 setwnd(message_window)
6731 # Skip leading white space
6732 line = line.lstrip()
6734 inqueue = line.split()
6740 # From here on in it's all looking at the queue
6741 citem = inqueue.pop(0)
6745 aaitem = float(citem)
6750 citem = citem.lower()
6754 # yes-or-no confirmation
6763 proutn(_("Please answer with \"y\" or \"n\": "))
6766 # complain about unparseable input
6769 prout(_("Beg your pardon, Captain?"))
6772 # compares s to citem and returns true if it matches to the length of s
6773 return s.startswith(citem)
6776 # access to the internals for debugging
6777 proutn("Reset levels? ")
6779 if game.energy < game.inenrg:
6780 game.energy = game.inenrg
6781 game.shield = game.inshld
6782 game.torps = game.intorps
6783 game.lsupres = game.inlsr
6784 proutn("Reset damage? ")
6786 for i in range(NDEVICES):
6787 if game.damage[i] > 0.0:
6788 game.damage[i] = 0.0
6789 proutn("Toggle debug flag? ")
6793 prout("Debug output ON")
6795 prout("Debug output OFF")
6796 proutn("Cause selective damage? ")
6798 for i in range(NDEVICES):
6804 if key == IHALPHA and isit("y"):
6805 game.damage[i] = 10.0
6806 proutn("Examine/change events? ")
6811 FSNOVA: "Supernova ",
6814 FBATTAK: "Base Attack ",
6815 FCDBAS: "Base Destroy ",
6816 FSCMOVE: "SC Move ",
6817 FSCDBAS: "SC Base Destroy ",
6818 FDSPROB: "Probe Move ",
6819 FDISTR: "Distress Call ",
6820 FENSLV: "Enslavement ",
6821 FREPRO: "Klingon Build ",
6823 for i in range(1, NEVENTS):
6826 proutn("%.2f" % (scheduled(i)-game.state.date))
6827 if i == FENSLV or i == FREPRO:
6829 proutn(" in %s" % ev.quadrant)
6839 ev = schedule(i, aaitem)
6840 if i == FENSLV or i == FREPRO:
6842 proutn("In quadrant- ")
6844 # IHEOL says to leave coordinates as they are
6847 prout("Event %d canceled, no x coordinate." % (i))
6850 w.x = int(round(aaitem))
6853 prout("Event %d canceled, no y coordinate." % (i))
6856 w.y = int(round(aaitem))
6859 proutn("Induce supernova here? ")
6861 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6864 if __name__ == '__main__':
6865 global line, thing, game, idebug, iqengry
6866 game = citem = aaitem = inqueue = None
6872 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY)
6873 # Disable curses mode until the game logic is working.
6874 # if os.getenv("TERM"):
6875 # game.options |= OPTION_CURSES | OPTION_SHOWME
6877 game.options |= OPTION_TTY
6879 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6880 for (switch, val) in options:
6883 replayfp = open(optarg, "r")
6885 sys.stderr.write("sst: can't open replay file %s\n" % optarg)
6887 line = replayfp.readline().strip()
6889 (key, seed) = line.split()
6892 sys.stderr.write("sst: replay file %s is ill-formed\n"%optarg)
6894 game.options |= OPTION_TTY
6895 game.options &=~ OPTION_CURSES
6896 elif switch == '-t':
6897 game.options |= OPTION_TTY
6898 game.options &=~ OPTION_CURSES
6899 elif switch == '-x':
6902 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6904 # where to save the input in case of bugs
6906 logfp = open("/usr/tmp/sst-input.log", "w")
6908 sys.stderr.write("sst: warning, can't open logfile\n")
6911 logfp.write("seed %d\n" % (seed))
6918 while True: # Play a game
6919 setwnd(fullscreen_window)
6922 setup(needprompt=not inqueue)
6925 game.alldone = False
6931 if game.tourn and game.alldone:
6932 proutn(_("Do you want your score recorded?"))
6936 proutn(_("Do you want to play again? "))
6940 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))