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)
259 s.x = self.x + randrange(-1, 2)
260 s.y = self.y + randrange(-1, 2)
265 return "%s - %s" % (self.x+1, self.y+1)
270 self.name = None # string-valued if inhabited
271 self.w = coord() # quadrant located
272 self.pclass = None # could be ""M", "N", "O", or "destroyed"
273 self.crystals = "absent"# could be "mined", "present", "absent"
274 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
275 self.inhabited = False # is it inhabites?
286 self.supernova = None
288 self.status = None # Could be "secure", "distressed", "enslaved"
296 def fill2d(size, fillfun):
297 "Fill an empty list in 2D."
299 for i in range(size):
301 for j in range(size):
302 lst[i].append(fillfun(i, j))
307 self.snap = False # snapshot taken
308 self.crew = 0 # crew complement
309 self.remkl = 0 # remaining klingons
310 self.remcom = 0 # remaining commanders
311 self.nscrem = 0 # remaining super commanders
312 self.rembase = 0 # remaining bases
313 self.starkl = 0 # destroyed stars
314 self.basekl = 0 # destroyed bases
315 self.nromrem = 0 # Romulans remaining
316 self.nplankl = 0 # destroyed uninhabited planets
317 self.nworldkl = 0 # destroyed inhabited planets
318 self.planets = [] # Planet information
319 self.date = 0.0 # stardate
320 self.remres = 0 # remaining resources
321 self.remtime = 0 # remaining time
322 self.baseq = [] # Base quadrant coordinates
323 for i in range(BASEMAX):
324 self.baseq.append(coord())
325 self.kcmdr = [] # Commander quadrant coordinates
326 for i in range(QUADSIZE):
327 self.kcmdr.append(coord())
328 self.kscmdr = coord() # Supercommander quadrant coordinates
329 # the galaxy (subscript 0 not used)
330 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
331 # the starchart (subscript 0 not used)
332 self.chart = fill2d(GALSIZE, lambda i, j: page())
336 self.date = None # A real number
337 self.quadrant = None # A coord structure
340 OPTION_ALL = 0xffffffff
341 OPTION_TTY = 0x00000001 # old interface
342 OPTION_CURSES = 0x00000002 # new interface
343 OPTION_IOMODES = 0x00000003 # cover both interfaces
344 OPTION_PLANETS = 0x00000004 # planets and mining
345 OPTION_THOLIAN = 0x00000008 # Tholians and their webs
346 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back
347 OPTION_PROBE = 0x00000020 # deep-space probes
348 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
349 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise
350 OPTION_MVBADDY = 0x00000100 # more enemies can move
351 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you
352 OPTION_BASE = 0x00000400 # bases have good shields
353 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds
354 OPTION_PLAIN = 0x01000000 # user chose plain game
355 OPTION_ALMY = 0x02000000 # user chose Almy variant
374 NDEVICES= 16 # Number of devices
383 def damaged(dev): return (game.damage[dev] != 0.0)
384 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
386 # Define future events
387 FSPY = 0 # Spy event happens always (no future[] entry)
388 # can cause SC to tractor beam Enterprise
389 FSNOVA = 1 # Supernova
390 FTBEAM = 2 # Commander tractor beams Enterprise
391 FSNAP = 3 # Snapshot for time warp
392 FBATTAK = 4 # Commander attacks base
393 FCDBAS = 5 # Commander destroys base
394 FSCMOVE = 6 # Supercommander moves (might attack base)
395 FSCDBAS = 7 # Supercommander destroys base
396 FDSPROB = 8 # Move deep space probe
397 FDISTR = 9 # Emit distress call from an inhabited world
398 FENSLV = 10 # Inhabited word is enslaved */
399 FREPRO = 11 # Klingons build a ship in an enslaved system
403 # abstract out the event handling -- underlying data structures will change
404 # when we implement stateful events
406 def findevent(evtype): return game.future[evtype]
410 self.options = None # Game options
411 self.state = snapshot() # A snapshot structure
412 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
413 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
414 self.kpower = fill2d(QUADSIZE, lambda i, j: 0.0) # enemy energy levels
415 self.kdist = fill2d(QUADSIZE, lambda i, j: 0.0) # enemy distances
416 self.kavgd = fill2d(QUADSIZE, lambda i, j: 0.0) # average distances
417 self.damage = [0.0] * NDEVICES # damage encountered
418 self.future = [] # future events
419 for i in range(NEVENTS):
420 self.future.append(event())
421 self.passwd = None; # Self Destruct password
422 self.ks = fill2d(QUADSIZE, lambda i, j: coord()) # enemy sector locations
423 self.quadrant = None # where we are in the large
424 self.sector = None # where we are in the small
425 self.tholian = None # coordinates of Tholian
426 self.base = None # position of base in current quadrant
427 self.battle = None # base coordinates being attacked
428 self.plnet = None # location of planet in quadrant
429 self.probec = None # current probe quadrant
430 self.gamewon = False # Finished!
431 self.ididit = False # action taken -- allows enemy to attack
432 self.alive = False # we are alive (not killed)
433 self.justin = False # just entered quadrant
434 self.shldup = False # shields are up
435 self.shldchg = False # shield is changing (affects efficiency)
436 self.comhere = False # commander here
437 self.ishere = False # super-commander in quadrant
438 self.iscate = False # super commander is here
439 self.ientesc = False # attempted escape from supercommander
440 self.resting = False # rest time
441 self.icraft = False # Kirk in Galileo
442 self.landed = False # party on planet (true), on ship (false)
443 self.alldone = False # game is now finished
444 self.neutz = False # Romulan Neutral Zone
445 self.isarmed = False # probe is armed
446 self.inorbit = False # orbiting a planet
447 self.imine = False # mining
448 self.icrystl = False # dilithium crystals aboard
449 self.iseenit = False # seen base attack report
450 self.thawed = False # thawed game
451 self.condition = None # "green", "yellow", "red", "docked", "dead"
452 self.iscraft = None # "onship", "offship", "removed"
453 self.skill = None # Player skill level
454 self.inkling = 0 # initial number of klingons
455 self.inbase = 0 # initial number of bases
456 self.incom = 0 # initial number of commanders
457 self.inscom = 0 # initial number of commanders
458 self.inrom = 0 # initial number of commanders
459 self.instar = 0 # initial stars
460 self.intorps = 0 # initial/max torpedoes
461 self.torps = 0 # number of torpedoes
462 self.ship = 0 # ship type -- 'E' is Enterprise
463 self.abandoned = 0 # count of crew abandoned in space
464 self.length = 0 # length of game
465 self.klhere = 0 # klingons here
466 self.casual = 0 # causalties
467 self.nhelp = 0 # calls for help
468 self.nkinks = 0 # count of energy-barrier crossings
469 self.iplnet = None # planet # in quadrant
470 self.inplan = 0 # initial planets
471 self.nenhere = 0 # number of enemies in quadrant
472 self.irhere = 0 # Romulans in quadrant
473 self.isatb = 0 # =1 if super commander is attacking base
474 self.tourn = 0 # tournament number
475 self.proben = 0 # number of moves for probe
476 self.nprobes = 0 # number of probes available
477 self.inresor = 0.0 # initial resources
478 self.intime = 0.0 # initial time
479 self.inenrg = 0.0 # initial/max energy
480 self.inshld = 0.0 # initial/max shield
481 self.inlsr = 0.0 # initial life support resources
482 self.indate = 0.0 # initial date
483 self.energy = 0.0 # energy level
484 self.shield = 0.0 # shield level
485 self.warpfac = 0.0 # warp speed
486 self.wfacsq = 0.0 # squared warp factor
487 self.lsupres = 0.0 # life support reserves
488 self.dist = 0.0 # movement distance
489 self.direc = 0.0 # movement direction
490 self.optime = 0.0 # time taken by current operation
491 self.docfac = 0.0 # repair factor when docking (constant?)
492 self.damfac = 0.0 # damage factor
493 self.lastchart = 0.0 # time star chart was last updated
494 self.cryprob = 0.0 # probability that crystal will work
495 self.probex = 0.0 # location of probe
497 self.probeinx = 0.0 # probe x,y increment
498 self.probeiny = 0.0 #
499 self.height = 0.0 # height of orbit around planet
501 # Stas thinks this should be (C expression):
502 # game.state.remkl + game.state.remcom > 0 ?
503 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
504 # He says the existing expression is prone to divide-by-zero errors
505 # after killing the last klingon when score is shown -- perhaps also
506 # if the only remaining klingon is SCOM.
507 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
508 # From enumerated type 'feature'
529 # From enumerated type 'FINTYPE'
553 # From enumerated type 'COLORS'
572 # Log the results of pulling random numbers so we can check determinism.
578 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
581 def randrange(*args):
582 v = random.randrange(*args)
583 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
589 v *= args[0] # returns from [0, a1)
591 v = args[0] + v*args[1] # returns from [a1, a2)
592 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
595 # Code from ai.c begins here
597 def tryexit(look, ienm, loccom, irun):
598 # a bad guy attempts to bug out
600 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
601 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
602 if not VALID_QUADRANT(iq.x,iq.y) or \
603 game.state.galaxy[iq.x][iq.y].supernova or \
604 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
605 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
607 return False; # Romulans cannot escape!
609 # avoid intruding on another commander's territory
611 for n in range(game.state.remcom):
612 if game.state.kcmdr[n] == iq:
614 # refuse to leave if currently attacking starbase
615 if game.battle == game.quadrant:
617 # don't leave if over 1000 units of energy
618 if game.kpower[loccom] > 1000.0:
620 # print escape message and move out of quadrant.
621 # we know this if either short or long range sensors are working
622 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
623 game.condition == docked:
624 crmena(True, ienm, "sector", game.ks[loccom])
625 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
626 # handle local matters related to escape
627 game.quad[game.ks[loccom].x][game.ks[loccom].y] = IHDOT
628 game.ks[loccom] = game.ks[game.nenhere]
629 game.kavgd[loccom] = game.kavgd[game.nenhere]
630 game.kpower[loccom] = game.kpower[game.nenhere]
631 game.kdist[loccom] = game.kdist[game.nenhere]
634 if game.condition != docked:
636 # Handle global matters related to escape
637 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
638 game.state.galaxy[iq.x][iq.y].klingons += 1
644 schedule(FSCMOVE, 0.2777)
648 for n in range(game.state.remcom):
649 if game.state.kcmdr[n] == game.quadrant:
650 game.state.kcmdr[n]=iq
653 return True; # success
656 # The bad-guy movement algorithm:
658 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
659 # If both are operating full strength, force is 1000. If both are damaged,
660 # force is -1000. Having shields down subtracts an additional 1000.
662 # 2. Enemy has forces equal to the energy of the attacker plus
663 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
664 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
666 # Attacker Initial energy levels (nominal):
667 # Klingon Romulan Commander Super-Commander
668 # Novice 400 700 1200
670 # Good 450 800 1300 1750
671 # Expert 475 850 1350 1875
672 # Emeritus 500 900 1400 2000
673 # VARIANCE 75 200 200 200
675 # Enemy vessels only move prior to their attack. In Novice - Good games
676 # only commanders move. In Expert games, all enemy vessels move if there
677 # is a commander present. In Emeritus games all enemy vessels move.
679 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
680 # forces are 1000 greater than Enterprise.
682 # Agressive action on average cuts the distance between the ship and
683 # the enemy to 1/4 the original.
685 # 4. At lower energy advantage, movement units are proportional to the
686 # advantage with a 650 advantage being to hold ground, 800 to move forward
687 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
689 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
690 # retreat, especially at high skill levels.
692 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
695 def movebaddy(com, loccom, ienm):
696 # tactical movement for the bad guys
697 next = coord(); look = coord()
699 # This should probably be just game.comhere + game.ishere
700 if game.skill >= SKILL_EXPERT:
701 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
703 nbaddys = game.comhere + game.ishere
705 dist1 = game.kdist[loccom]
706 mdist = int(dist1 + 0.5); # Nearest integer distance
708 # If SC, check with spy to see if should hi-tail it
710 (game.kpower[loccom] <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
714 # decide whether to advance, retreat, or hold position
715 forces = game.kpower[loccom]+100.0*game.nenhere+400*(nbaddys-1)
717 forces += 1000; # Good for enemy if shield is down!
718 if not damaged(DPHASER) or not damaged(DPHOTON):
719 if damaged(DPHASER): # phasers damaged
722 forces -= 0.2*(game.energy - 2500.0)
723 if damaged(DPHOTON): # photon torpedoes damaged
726 forces -= 50.0*game.torps
728 # phasers and photon tubes both out!
731 if forces <= 1000.0 and game.condition != "docked": # Typical situation
732 motion = ((forces + randreal(200))/150.0) - 5.0
734 if forces > 1000.0: # Very strong -- move in for kill
735 motion = (1.0-square(randreal()))*dist1 + 1.0
736 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
737 motion -= game.skill*(2.0-square(randreal()))
739 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
740 # don't move if no motion
743 # Limit motion according to skill
744 if abs(motion) > game.skill:
749 # calculate preferred number of steps
754 if motion > 0 and nsteps > mdist:
755 nsteps = mdist; # don't overshoot
756 if nsteps > QUADSIZE:
757 nsteps = QUADSIZE; # This shouldn't be necessary
759 nsteps = 1; # This shouldn't be necessary
761 proutn("NSTEPS = %d:" % nsteps)
762 # Compute preferred values of delta X and Y
763 mx = game.sector.x - com.x
764 my = game.sector.y - com.y
765 if 2.0 * abs(mx) < abs(my):
767 if 2.0 * abs(my) < abs(game.sector.x-com.x):
781 for ll in range(nsteps):
783 proutn(" %d" % (ll+1))
784 # Check if preferred position available
796 attempts = 0; # Settle mysterious hang problem
797 while attempts < 20 and not success:
799 if look.x < 0 or look.x >= QUADSIZE:
800 if motion < 0 and tryexit(look, ienm, loccom, irun):
802 if krawlx == mx or my == 0:
804 look.x = next.x + krawlx
806 elif look.y < 0 or look.y >= QUADSIZE:
807 if motion < 0 and tryexit(look, ienm, loccom, irun):
809 if krawly == my or mx == 0:
811 look.y = next.y + krawly
813 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
814 # See if we should ram ship
815 if game.quad[look.x][look.y] == game.ship and \
816 (ienm == IHC or ienm == IHS):
819 if krawlx != mx and my != 0:
820 look.x = next.x + krawlx
822 elif krawly != my and mx != 0:
823 look.y = next.y + krawly
826 break; # we have failed
838 # Put commander in place within same quadrant
839 game.quad[com.x][com.y] = IHDOT
840 game.quad[next.x][next.y] = ienm
843 game.ks[loccom] = next
844 game.kdist[loccom] = game.kavgd[loccom] = distance(game.sector, next)
845 if not damaged(DSRSENS) or game.condition == docked:
848 proutn(_(" from Sector %s") % com)
849 if game.kdist[loccom] < dist1:
850 proutn(_(" advances to "))
852 proutn(_(" retreats to "))
853 prout("Sector %s." % next)
856 # Klingon tactical movement
859 # Figure out which Klingon is the commander (or Supercommander)
862 for i in range(game.nenhere):
864 if game.quad[w.x][w.y] == IHC:
868 for i in range(game.nenhere):
870 if game.quad[w.x][w.y] == IHS:
873 # If skill level is high, move other Klingons and Romulans too!
874 # Move these last so they can base their actions on what the
876 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
877 for i in range(game.nenhere):
879 if game.quad[w.x][w.y] == IHK or game.quad[w.x][w.y] == IHR:
880 movebaddy(w, i, game.quad[w.x][w.y])
883 def movescom(iq, avoid):
884 # commander movement helper
885 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
886 game.state.galaxy[iq.x][iq.y].supernova or \
887 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
890 # Avoid quadrants with bases if we want to avoid Enterprise
891 for i in range(game.state.rembase):
892 if game.state.baseq[i] == iq:
894 if game.justin and not game.iscate:
897 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
898 game.state.kscmdr = iq
899 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
901 # SC has scooted, Remove him from current quadrant
907 for i in range(game.nenhere):
908 if game.quad[game.ks[i].x][game.ks[i].y] == IHS:
910 game.quad[game.ks[i].x][game.ks[i].y] = IHDOT
911 game.ks[i] = game.ks[game.nenhere]
912 game.kdist[i] = game.kdist[game.nenhere]
913 game.kavgd[i] = game.kavgd[game.nenhere]
914 game.kpower[i] = game.kpower[game.nenhere]
917 if game.condition!=docked:
920 # check for a helpful planet
921 for i in range(game.inplan):
922 if game.state.planets[i].w == game.state.kscmdr and \
923 game.state.planets[i].crystals == "present":
925 game.state.planets[i].pclass = "destroyed"
926 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
929 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
930 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
931 prout(_(" by the Super-commander.\""))
933 return False; # looks good!
935 def supercommander():
936 # move the Super Commander
937 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
940 prout("== SUPERCOMMANDER")
941 # Decide on being active or passive
942 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 \
943 (game.state.date-game.indate) < 3.0)
944 if not game.iscate and avoid:
945 # compute move away from Enterprise
946 idelta = game.state.kscmdr-game.quadrant
947 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
949 idelta.x = game.state.kscmdr.y-game.quadrant.y
950 idelta.y = game.quadrant.x-game.state.kscmdr.x
952 # compute distances to starbases
953 if game.state.rembase <= 0:
957 sc = game.state.kscmdr
958 for i in range(game.state.rembase):
959 basetbl.append((i, distance(game.state.baseq[i], sc)))
960 if game.state.rembase > 1:
961 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
962 # look for nearest base without a commander, no Enterprise, and
963 # without too many Klingons, and not already under attack.
964 ifindit = iwhichb = 0
965 for i2 in range(game.state.rembase):
966 i = basetbl[i2][0]; # bug in original had it not finding nearest
967 ibq = game.state.baseq[i]
968 if ibq == game.quadrant or ibq == game.battle or \
969 game.state.galaxy[ibq.x][ibq.y].supernova or \
970 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
972 # if there is a commander, and no other base is appropriate,
973 # we will take the one with the commander
974 for j in range(game.state.remcom):
975 if ibq == game.state.kcmdr[j] and ifindit!= 2:
979 if j > game.state.remcom: # no commander -- use this one
984 return; # Nothing suitable -- wait until next time
985 ibq = game.state.baseq[iwhichb]
986 # decide how to move toward base
987 idelta = ibq - game.state.kscmdr
988 # Maximum movement is 1 quadrant in either or both axes
989 idelta = idelta.sgn()
990 # try moving in both x and y directions
991 # there was what looked like a bug in the Almy C code here,
992 # but it might be this translation is just wrong.
993 iq = game.state.kscmdr + idelta
994 if movescom(iq, avoid):
995 # failed -- try some other maneuvers
996 if idelta.x==0 or idelta.y==0:
999 iq.y = game.state.kscmdr.y + 1
1000 if movescom(iq, avoid):
1001 iq.y = game.state.kscmdr.y - 1
1004 iq.x = game.state.kscmdr.x + 1
1005 if movescom(iq, avoid):
1006 iq.x = game.state.kscmdr.x - 1
1009 # try moving just in x or y
1010 iq.y = game.state.kscmdr.y
1011 if movescom(iq, avoid):
1012 iq.y = game.state.kscmdr.y + idelta.y
1013 iq.x = game.state.kscmdr.x
1016 if game.state.rembase == 0:
1019 for i in range(game.state.rembase):
1020 ibq = game.state.baseq[i]
1021 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1024 return; # no, don't attack base!
1025 game.iseenit = False
1027 schedule(FSCDBAS, randreal(1.0, 3.0))
1028 if is_scheduled(FCDBAS):
1029 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1030 if not communicating():
1031 return; # no warning
1034 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1035 % game.state.kscmdr)
1036 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1037 proutn(_(" It can survive until stardate %d.\"") \
1038 % int(scheduled(FSCDBAS)))
1039 if not game.resting:
1041 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1044 game.resting = False
1045 game.optime = 0.0; # actually finished
1047 # Check for intelligence report
1050 (not communicating()) or \
1051 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1054 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1055 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1060 if not game.tholian or game.justin:
1062 if game.tholian.x == 0 and game.tholian.y == 0:
1063 idx = 0; idy = QUADSIZE-1
1064 elif game.tholian.x == 0 and game.tholian.y == QUADSIZE-1:
1065 idx = QUADSIZE-1; idy = QUADSIZE-1
1066 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == QUADSIZE-1:
1067 idx = QUADSIZE-1; idy = 0
1068 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == 0:
1071 # something is wrong!
1074 # do nothing if we are blocked
1075 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1077 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1078 if game.tholian.x != idx:
1080 im = math.fabs(idx - game.tholian.x)*1.0/(idx - game.tholian.x)
1081 while game.tholian.x != idx:
1082 game.tholian.x += im
1083 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1084 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1085 elif game.tholian.y != idy:
1087 im = math.fabs(idy - game.tholian.y)*1.0/(idy - game.tholian.y)
1088 while game.tholian.y != idy:
1089 game.tholian.y += im
1090 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1091 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1092 game.quad[game.tholian.x][game.tholian.y] = IHT
1093 game.ks[game.nenhere] = game.tholian
1095 # check to see if all holes plugged
1096 for i in range(QUADSIZE):
1097 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1099 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1101 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1103 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1105 # All plugged up -- Tholian splits
1106 game.quad[game.tholian.x][game.tholian.y]=IHWEB
1108 crmena(True, IHT, "sector", game.tholian)
1109 prout(_(" completes web."))
1114 # Code from battle.c begins here
1116 def doshield(shraise):
1117 # change shield status
1125 if isit("transfer"):
1129 if damaged(DSHIELD):
1130 prout(_("Shields damaged and down."))
1137 proutn(_("Do you wish to change shield energy? "))
1139 proutn(_("Energy to transfer to shields- "))
1141 elif damaged(DSHIELD):
1142 prout(_("Shields damaged and down."))
1145 proutn(_("Shields are up. Do you want them down? "))
1152 proutn(_("Shields are down. Do you want them up? "))
1158 if action == "SHUP": # raise shields
1160 prout(_("Shields already up."))
1164 if game.condition != "docked":
1166 prout(_("Shields raised."))
1167 if game.energy <= 0:
1169 prout(_("Shields raising uses up last of energy."))
1174 elif action == "SHDN":
1176 prout(_("Shields already down."))
1180 prout(_("Shields lowered."))
1183 elif action == "NRG":
1184 while scan() != IHREAL:
1186 proutn(_("Energy to transfer to shields- "))
1190 if aaitem > game.energy:
1191 prout(_("Insufficient ship energy."))
1194 if game.shield+aaitem >= game.inshld:
1195 prout(_("Shield energy maximized."))
1196 if game.shield+aaitem > game.inshld:
1197 prout(_("Excess energy requested returned to ship energy"))
1198 game.energy -= game.inshld-game.shield
1199 game.shield = game.inshld
1201 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1202 # Prevent shield drain loophole
1204 prout(_("Engineering to bridge--"))
1205 prout(_(" Scott here. Power circuit problem, Captain."))
1206 prout(_(" I can't drain the shields."))
1209 if game.shield+aaitem < 0:
1210 prout(_("All shield energy transferred to ship."))
1211 game.energy += game.shield
1214 proutn(_("Scotty- \""))
1216 prout(_("Transferring energy to shields.\""))
1218 prout(_("Draining energy from shields.\""))
1219 game.shield += aaitem
1220 game.energy -= aaitem
1224 # choose a device to damage, at random.
1226 # Quoth Eric Allman in the code of BSD-Trek:
1227 # "Under certain conditions you can get a critical hit. This
1228 # sort of hit damages devices. The probability that a given
1229 # device is damaged depends on the device. Well protected
1230 # devices (such as the computer, which is in the core of the
1231 # ship and has considerable redundancy) almost never get
1232 # damaged, whereas devices which are exposed (such as the
1233 # warp engines) or which are particularly delicate (such as
1234 # the transporter) have a much higher probability of being
1237 # This is one place where OPTION_PLAIN does not restore the
1238 # original behavior, which was equiprobable damage across
1239 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1240 # and have done with it. Also, in the original game, DNAVYS
1241 # and DCOMPTR were the same device.
1243 # Instead, we use a table of weights similar to the one from BSD Trek.
1244 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1245 # We don't have a cloaking device. The shuttle got the allocation
1246 # for the cloaking device, then we shaved a half-percent off
1247 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1250 105, # DSRSENS: short range scanners 10.5%
1251 105, # DLRSENS: long range scanners 10.5%
1252 120, # DPHASER: phasers 12.0%
1253 120, # DPHOTON: photon torpedoes 12.0%
1254 25, # DLIFSUP: life support 2.5%
1255 65, # DWARPEN: warp drive 6.5%
1256 70, # DIMPULS: impulse engines 6.5%
1257 145, # DSHIELD: deflector shields 14.5%
1258 30, # DRADIO: subspace radio 3.0%
1259 45, # DSHUTTL: shuttle 4.5%
1260 15, # DCOMPTR: computer 1.5%
1261 20, # NAVCOMP: navigation system 2.0%
1262 75, # DTRANSP: transporter 7.5%
1263 20, # DSHCTRL: high-speed shield controller 2.0%
1264 10, # DDRAY: death ray 1.0%
1265 30, # DDSP: deep-space probes 3.0%
1267 idx = randrange(1000) # weights must sum to 1000
1269 for (i, w) in enumerate(weights):
1273 return None; # we should never get here
1275 def ram(ibumpd, ienm, w):
1276 # make our ship ram something
1277 prouts(_("***RED ALERT! RED ALERT!"))
1279 prout(_("***COLLISION IMMINENT."))
1283 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1285 proutn(_(" rammed by "))
1288 crmena(False, ienm, sector, w)
1290 proutn(_(" (original position)"))
1292 deadkl(w, ienm, game.sector)
1295 prout(_(" heavily damaged."))
1296 icas = randrange(10, 30)
1297 prout(_("***Sickbay reports %d casualties"), icas)
1299 game.state.crew -= icas
1301 # In the pre-SST2K version, all devices got equiprobably damaged,
1302 # which was silly. Instead, pick up to half the devices at
1303 # random according to our weighting table,
1305 ncrits = randrange(NDEVICES/2)
1306 for m in range(ncrits):
1308 if game.damage[dev] < 0:
1310 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1311 # Damage for at least time of travel!
1312 game.damage[dev] += game.optime + extradm
1314 prout(_("***Shields are down."))
1315 if game.state.remkl + game.state.remcom + game.state.nscrem:
1322 def torpedo(course, r, incoming, i, n):
1323 # let a photon torpedo fly
1326 ac = course + 0.25*r
1327 angle = (15.0-ac)*0.5235988
1328 bullseye = (15.0 - course)*0.5235988
1329 deltax = -math.sin(angle);
1330 deltay = math.cos(angle);
1331 x = incoming.x; y = incoming.y
1332 w = coord(); jw = coord()
1333 w.x = w.y = jw.x = jw.y = 0
1334 bigger = max(math.fabs(deltax), math.fabs(deltay))
1337 if not damaged(DSRSENS) or game.condition=="docked":
1338 setwnd(srscan_window)
1340 setwnd(message_window)
1341 # Loop to move a single torpedo
1342 for l in range(1, 15+1):
1347 if not VALID_SECTOR(w.x, w.y):
1349 iquad=game.quad[w.x][w.y]
1350 tracktorpedo(w, l, i, n, iquad)
1354 setwnd(message_window)
1355 if damaged(DSRSENS) and not game.condition=="docked":
1356 skip(1); # start new line after text track
1357 if iquad in (IHE, IHF): # Hit our ship
1359 proutn(_("Torpedo hits "))
1362 hit = 700.0 + randreal(100) - \
1363 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1364 newcnd(); # we're blown out of dock
1365 # We may be displaced.
1366 if game.landed or game.condition=="docked":
1367 return hit # Cheat if on a planet
1368 ang = angle + 2.5*(randreal()-0.5)
1369 temp = math.fabs(math.sin(ang))
1370 if math.fabs(math.cos(ang)) > temp:
1371 temp = math.fabs(math.cos(ang))
1372 xx = -math.sin(ang)/temp
1373 yy = math.cos(ang)/temp
1376 if not VALID_SECTOR(jw.x, jw.y):
1378 if game.quad[jw.x][jw.y]==IHBLANK:
1381 if game.quad[jw.x][jw.y]!=IHDOT:
1382 # can't move into object
1387 elif iquad in (IHC, IHS): # Hit a commander
1389 crmena(True, iquad, sector, w)
1390 prout(_(" uses anti-photon device;"))
1391 prout(_(" torpedo neutralized."))
1393 elif iquad in (IHR, IHK): # Hit a regular enemy
1395 for ll in range(game.nenhere):
1396 if w == game.ks[ll]:
1398 kp = math.fabs(game.kpower[ll])
1399 h1 = 700.0 + randrange(100) - \
1400 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1404 if game.kpower[ll] < 0:
1405 game.kpower[ll] -= -h1
1407 game.kpower[ll] -= h1
1408 if game.kpower[ll] == 0:
1411 crmena(True, iquad, "sector", w)
1412 # If enemy damaged but not destroyed, try to displace
1413 ang = angle + 2.5*(randreal()-0.5)
1414 temp = math.fabs(math.sin(ang))
1415 if math.fabs(math.cos(ang)) > temp:
1416 temp = math.fabs(math.cos(ang))
1417 xx = -math.sin(ang)/temp
1418 yy = math.cos(ang)/temp
1421 if not VALID_SECTOR(jw.x, jw.y):
1422 prout(_(" damaged but not destroyed."))
1424 if game.quad[jw.x][jw.y]==IHBLANK:
1425 prout(_(" buffeted into black hole."))
1426 deadkl(w, iquad, jw)
1428 if game.quad[jw.x][jw.y]!=IHDOT:
1429 # can't move into object
1430 prout(_(" damaged but not destroyed."))
1432 proutn(_(" damaged--"))
1436 elif iquad == IHB: # Hit a base
1438 prout(_("***STARBASE DESTROYED.."))
1439 for ll in range(game.state.rembase):
1440 if game.state.baseq[ll] == game.quadrant:
1441 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1443 game.quad[w.x][w.y]=IHDOT
1444 game.state.rembase -= 1
1445 game.base.x=game.base.y=0
1446 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1447 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1448 game.state.basekl += 1
1451 elif iquad == IHP: # Hit a planet
1452 crmena(True, iquad, sector, w)
1453 prout(_(" destroyed."))
1454 game.state.nplankl += 1
1455 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1456 game.iplnet.pclass = "destroyed"
1458 invalidate(game.plnet)
1459 game.quad[w.x][w.y] = IHDOT
1461 # captain perishes on planet
1464 elif iquad == IHW: # Hit an inhabited world -- very bad!
1465 crmena(True, iquad, sector, w)
1466 prout(_(" destroyed."))
1467 game.state.nworldkl += 1
1468 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1469 game.iplnet.pclass = "destroyed"
1471 invalidate(game.plnet)
1472 game.quad[w.x][w.y] = IHDOT
1474 # captain perishes on planet
1476 prout(_("You have just destroyed an inhabited planet."))
1477 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1479 elif iquad == IHSTAR: # Hit a star
1483 crmena(True, IHSTAR, sector, w)
1484 prout(_(" unaffected by photon blast."))
1486 elif iquad == IHQUEST: # Hit a thingy
1487 if not (game.options & OPTION_THINGY) or withprob(0.3):
1489 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1491 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1493 proutn(_("Mr. Spock-"))
1494 prouts(_(" \"Fascinating!\""))
1499 # Stas Sergeev added the possibility that
1500 # you can shove the Thingy and piss it off.
1501 # It then becomes an enemy and may fire at you.
1507 elif iquad == IHBLANK: # Black hole
1509 crmena(True, IHBLANK, sector, w)
1510 prout(_(" swallows torpedo."))
1512 elif iquad == IHWEB: # hit the web
1514 prout(_("***Torpedo absorbed by Tholian web."))
1516 elif iquad == IHT: # Hit a Tholian
1517 h1 = 700.0 + randrange(100) - \
1518 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1521 game.quad[w.x][w.y] = IHDOT
1526 crmena(True, IHT, sector, w)
1528 prout(_(" survives photon blast."))
1530 prout(_(" disappears."))
1531 game.quad[w.x][w.y] = IHWEB
1538 proutn("Don't know how to handle torpedo collision with ")
1539 crmena(True, iquad, sector, w)
1543 if curwnd!=message_window:
1544 setwnd(message_window)
1546 game.quad[w.x][w.y]=IHDOT
1547 game.quad[jw.x][jw.y]=iquad
1548 prout(_(" displaced by blast to Sector %s ") % jw)
1549 for ll in range(game.nenhere):
1550 game.kdist[ll] = game.kavgd[ll] = distance(game.sector,game.ks[ll])
1554 prout(_("Torpedo missed."))
1558 # critical-hit resolution
1560 # a critical hit occured
1561 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1563 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1564 proutn(_("***CRITICAL HIT--"))
1565 # Select devices and cause damage
1567 for loop1 in range(ncrit):
1570 # Cheat to prevent shuttle damage unless on ship
1571 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1574 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1575 game.damage[j] += extradm
1577 for loop2 in range(loop1):
1578 if j == cdam[loop2]:
1587 prout(_(" damaged."))
1588 if damaged(DSHIELD) and game.shldup:
1589 prout(_("***Shields knocked down."))
1592 def attack(torps_ok):
1593 # bad guy attacks us
1594 # torps_ok == false forces use of phasers in an attack
1595 atackd = False; attempt = False; ihurt = False;
1596 hitmax=0.0; hittot=0.0; chgfac=1.0
1599 # game could be over at this point, check
1603 prout("=== ATTACK!")
1604 # Tholian gets to move before attacking
1607 # if you have just entered the RNZ, you'll get a warning
1608 if game.neutz: # The one chance not to be attacked
1611 # commanders get a chance to tac-move towards you
1612 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1614 # if no enemies remain after movement, we're done
1615 if game.nenhere==0 or (game.nenhere==1 and thing == game.quadrant and not iqengry):
1617 # set up partial hits if attack happens during shield status change
1618 pfac = 1.0/game.inshld
1620 chgfac = 0.25 + randreal(0.5)
1622 # message verbosity control
1623 if game.skill <= SKILL_FAIR:
1625 for loop in range(game.nenhere):
1626 if game.kpower[loop] < 0:
1627 continue; # too weak to attack
1628 # compute hit strength and diminish shield power
1630 # Increase chance of photon torpedos if docked or enemy energy low
1631 if game.condition == "docked":
1633 if game.kpower[loop] < 500:
1636 iquad = game.quad[jay.x][jay.y]
1637 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1639 # different enemies have different probabilities of throwing a torp
1640 usephasers = not torps_ok or \
1641 (iquad == IHK and r > 0.0005) or \
1642 (iquad==IHC and r > 0.015) or \
1643 (iquad==IHR and r > 0.3) or \
1644 (iquad==IHS and r > 0.07) or \
1645 (iquad==IHQUEST and r > 0.05)
1646 if usephasers: # Enemy uses phasers
1647 if game.condition == "docked":
1648 continue; # Don't waste the effort!
1649 attempt = True; # Attempt to attack
1650 dustfac = 0.8 + randreal(0.5)
1651 hit = game.kpower[loop]*math.pow(dustfac,game.kavgd[loop])
1652 game.kpower[loop] *= 0.75
1653 else: # Enemy uses photon torpedo
1654 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1656 proutn(_("***TORPEDO INCOMING"))
1657 if not damaged(DSRSENS):
1659 crmena(False, iquad, where, jay)
1662 r = (randreal()+randreal())*0.5 - 0.5
1663 r += 0.002*game.kpower[loop]*r
1664 hit = torpedo(course, r, jay, 1, 1)
1665 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1666 finish(FWON); # Klingons did themselves in!
1667 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1668 return; # Supernova or finished
1671 # incoming phaser or torpedo, shields may dissipate it
1672 if game.shldup or game.shldchg or game.condition=="docked":
1673 # shields will take hits
1674 propor = pfac * game.shield
1675 if game.condition =="docked":
1679 hitsh = propor*chgfac*hit+1.0
1681 if absorb > game.shield:
1682 absorb = game.shield
1683 game.shield -= absorb
1685 # taking a hit blasts us out of a starbase dock
1686 if game.condition == "docked":
1688 # but the shields may take care of it
1689 if propor > 0.1 and hit < 0.005*game.energy:
1691 # hit from this opponent got through shields, so take damage
1693 proutn(_("%d unit hit") % int(hit))
1694 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1695 proutn(_(" on the "))
1697 if not damaged(DSRSENS) and usephasers:
1699 crmena(False, iquad, where, jay)
1701 # Decide if hit is critical
1707 if game.energy <= 0:
1708 # Returning home upon your shield, not with it...
1711 if not attempt and game.condition == "docked":
1712 prout(_("***Enemies decide against attacking your ship."))
1715 percent = 100.0*pfac*game.shield+0.5
1717 # Shields fully protect ship
1718 proutn(_("Enemy attack reduces shield strength to "))
1720 # Print message if starship suffered hit(s)
1722 proutn(_("Energy left %2d shields ") % int(game.energy))
1725 elif not damaged(DSHIELD):
1728 proutn(_("damaged, "))
1729 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1730 # Check if anyone was hurt
1731 if hitmax >= 200 or hittot >= 500:
1732 icas = randrange(hittot * 0.015)
1735 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1736 prout(_(" in that last attack.\""))
1738 game.state.crew -= icas
1739 # After attack, reset average distance to enemies
1740 for loop in range(game.nenhere):
1741 game.kavgd[loop] = game.kdist[loop]
1745 def deadkl(w, type, mv):
1746 # kill a Klingon, Tholian, Romulan, or Thingy
1747 # Added mv to allow enemy to "move" before dying
1748 crmena(True, type, sector, mv)
1749 # Decide what kind of enemy it is and update appropriately
1751 # chalk up a Romulan
1752 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1754 game.state.nromrem -= 1
1758 elif type == IHQUEST:
1764 # Some type of a Klingon
1765 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1768 game.comhere = False
1769 for i in range(game.state.remcom):
1770 if game.state.kcmdr[i] == game.quadrant:
1772 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1773 game.state.kcmdr[game.state.remcom].x = 0
1774 game.state.kcmdr[game.state.remcom].y = 0
1775 game.state.remcom -= 1
1777 if game.state.remcom != 0:
1778 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1780 game.state.remkl -= 1
1782 game.state.nscrem -= 1
1784 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1789 prout("*** Internal error, deadkl() called on %s\n" % type)
1790 # For each kind of enemy, finish message to player
1791 prout(_(" destroyed."))
1792 game.quad[w.x][w.y] = IHDOT
1793 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1796 # Remove enemy ship from arrays describing local conditions
1797 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1799 for i in range(game.nenhere):
1801 for j in range(i, game.nenhere):
1802 game.ks[j] = game.ks[j+1]
1803 game.kpower[j] = game.kpower[j+1]
1804 game.kavgd[j] = game.kdist[j] = game.kdist[j+1]
1805 game.ks[game.nenhere].x = 0
1806 game.ks[game.nenhere].y = 0
1807 game.kdist[game.nenhere] = 0
1808 game.kavgd[game.nenhere] = 0
1809 game.kpower[game.nenhere] = 0
1815 def targetcheck(x, y):
1816 # Return None if target is invalid
1817 if not VALID_SECTOR(x, y):
1820 deltx = 0.1*(y - game.sector.y)
1821 delty = 0.1*(x - game.sector.x)
1822 if deltx==0 and delty== 0:
1824 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1825 prout(_(" I recommend an immediate review of"))
1826 prout(_(" the Captain's psychological profile.\""))
1829 return 1.90985932*math.atan2(deltx, delty)
1832 # launch photon torpedo
1834 if damaged(DPHOTON):
1835 prout(_("Photon tubes damaged."))
1839 prout(_("No torpedoes left."))
1848 prout(_("%d torpedoes left.") % game.torps)
1849 proutn(_("Number of torpedoes to fire- "))
1851 else: # key == IHREAL {
1853 if n <= 0: # abort command
1858 prout(_("Maximum of 3 torpedoes per burst."))
1865 for i in range(1, n+1):
1867 if i==1 and key == IHEOL:
1868 break; # we will try prompting
1869 if i==2 and key == IHEOL:
1870 # direct all torpedoes at one target
1872 targ[i][1] = targ[1][1]
1873 targ[i][2] = targ[1][2]
1874 course[i] = course[1]
1886 course[i] = targetcheck(targ[i][1], targ[i][2])
1887 if course[i] == None:
1890 if i == 1 and key == IHEOL:
1891 # prompt for each one
1892 for i in range(1, n+1):
1893 proutn(_("Target sector for torpedo number %d- ") % i)
1898 targ[i][1] = int(aaitem-0.5)
1903 targ[i][2] = int(aaitem-0.5)
1905 course[i] = targetcheck(targ[i][1], targ[i][2])
1906 if course[i] == None:
1909 # Loop for moving <n> torpedoes
1911 if game.condition != "docked":
1913 r = (randreal()+randreal())*0.5 -0.5
1914 if math.fabs(r) >= 0.47:
1916 r *= randreal(1.2, 2.2)
1918 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1920 prouts(_("***TORPEDO MISFIRES."))
1923 prout(_(" Remainder of burst aborted."))
1925 prout(_("***Photon tubes damaged by misfire."))
1926 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1928 if game.shldup or game.condition == "docked":
1929 r *= 1.0 + 0.0001*game.shield
1930 torpedo(course[i], r, game.sector, i, n)
1931 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1933 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1937 # check for phasers overheating
1939 checkburn = (rpow-1500.0)*0.00038
1940 if withprob(checkburn):
1941 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1942 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1944 def checkshctrl(rpow):
1945 # check shield control
1948 prout(_("Shields lowered."))
1950 # Something bad has happened
1951 prouts(_("***RED ALERT! RED ALERT!"))
1953 hit = rpow*game.shield/game.inshld
1954 game.energy -= rpow+hit*0.8
1955 game.shield -= hit*0.2
1956 if game.energy <= 0.0:
1957 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1962 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1964 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1965 icas = randrange(hit*0.012)
1970 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1971 prout(_(" %d casualties so far.\"") % icas)
1973 game.state.crew -= icas
1975 prout(_("Phaser energy dispersed by shields."))
1976 prout(_("Enemy unaffected."))
1981 # register a phaser hit on Klingons and Romulans
1982 nenhr2 = game.nenhere; kk=1
1985 for k in range(nenhr2):
1989 dustfac = randreal(0.9, 1.0)
1990 hit = wham*math.pow(dustfac,game.kdist[kk])
1991 kpini = game.kpower[kk]
1992 kp = math.fabs(kpini)
1993 if PHASEFAC*hit < kp:
1995 if game.kpower[kk] < 0:
1996 game.kpower[kk] -= -kp
1998 game.kpower[kk] -= kp
1999 kpow = game.kpower[kk]
2002 if not damaged(DSRSENS):
2004 proutn(_("%d unit hit on ") % int(hit))
2006 proutn(_("Very small hit on "))
2007 ienm = game.quad[w.x][w.y]
2011 crmena(False, ienm, "sector", w)
2015 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2019 kk -= 1; # don't do the increment
2020 else: # decide whether or not to emasculate klingon
2021 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2022 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2023 prout(_(" has just lost its firepower.\""))
2024 game.kpower[kk] = -kpow
2031 kz = 0; k = 1; irec=0 # Cheating inhibitor
2032 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2036 # SR sensors and Computer are needed fopr automode
2037 if damaged(DSRSENS) or damaged(DCOMPTR):
2039 if game.condition == "docked":
2040 prout(_("Phasers can't be fired through base shields."))
2043 if damaged(DPHASER):
2044 prout(_("Phaser control damaged."))
2048 if damaged(DSHCTRL):
2049 prout(_("High speed shield control damaged."))
2052 if game.energy <= 200.0:
2053 prout(_("Insufficient energy to activate high-speed shield control."))
2056 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2058 # Original code so convoluted, I re-did it all
2059 # (That was Tom Almy talking about the C code, I think -- ESR)
2060 while automode=="NOTSET":
2065 prout(_("There is no enemy present to select."))
2068 automode="AUTOMATIC"
2072 elif isit("automatic"):
2073 if (not itarg) and game.nenhere != 0:
2074 automode = "FORCEMAN"
2077 prout(_("Energy will be expended into space."))
2078 automode = "AUTOMATIC"
2087 prout(_("Energy will be expended into space."))
2088 automode = "AUTOMATIC"
2090 automode = "FORCEMAN"
2092 automode = "AUTOMATIC"
2096 prout(_("Energy will be expended into space."))
2097 automode = "AUTOMATIC"
2099 automode = "FORCEMAN"
2101 proutn(_("Manual or automatic? "))
2106 if automode == "AUTOMATIC":
2107 if key == IHALPHA and isit("no"):
2110 if key != IHREAL and game.nenhere != 0:
2111 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2116 for i in range(game.nenhere):
2117 irec += math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))*randreal(1.01, 1.06) + 1.0
2119 proutn(_("%d units required. ") % irec)
2121 proutn(_("Units to fire= "))
2127 proutn(_("Energy available= %.2f") % avail)
2130 if not rpow > avail:
2137 if key == IHALPHA and isit("no"):
2140 game.energy -= 200; # Go and do it!
2141 if checkshctrl(rpow):
2149 for i in range(game.nenhere):
2153 hits[i] = math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))
2154 over = randreal(1.01, 1.06) * hits[i]
2156 powrem -= hits[i] + over
2157 if powrem <= 0 and temp < hits[i]:
2166 if extra > 0 and not game.alldone:
2168 proutn(_("*** Tholian web absorbs "))
2170 proutn(_("excess "))
2171 prout(_("phaser energy."))
2173 prout(_("%d expended on empty space.") % int(extra))
2174 elif automode == "FORCEMAN":
2177 if damaged(DCOMPTR):
2178 prout(_("Battle computer damaged, manual fire only."))
2181 prouts(_("---WORKING---"))
2183 prout(_("Short-range-sensors-damaged"))
2184 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2185 prout(_("Manual-fire-must-be-used"))
2187 elif automode == "MANUAL":
2189 for k in range(game.nenhere):
2191 ienm = game.quad[aim.x][aim.y]
2193 proutn(_("Energy available= %.2f") % (avail-0.006))
2197 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2198 (ienm == IHC or ienm == IHS):
2200 prout(_(" can't be located without short range scan."))
2203 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2208 if itarg and k > kz:
2209 irec=(abs(game.kpower[k])/(PHASEFAC*math.pow(0.9,game.kdist[k]))) * randreal(1.01, 1.06) + 1.0
2212 if not damaged(DCOMPTR):
2217 proutn(_("units to fire at "))
2218 crmena(False, ienm, sector, aim)
2221 if key == IHALPHA and isit("no"):
2229 if k==1: # Let me say I'm baffled by this
2238 # If total requested is too much, inform and start over
2240 prout(_("Available energy exceeded -- try again."))
2243 key = scan(); # scan for next value
2246 # zero energy -- abort
2249 if key == IHALPHA and isit("no"):
2254 game.energy -= 200.0
2255 if checkshctrl(rpow):
2259 # Say shield raised or malfunction, if necessary
2266 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2267 prouts(_(" CLICK CLICK POP . . ."))
2268 prout(_(" No response, sir!"))
2271 prout(_("Shields raised."))
2276 # Code from events,c begins here.
2278 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2279 # event of each type active at any given time. Mostly these means we can
2280 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2281 # BSD Trek, from which we swiped the idea, can have up to 5.
2283 def unschedule(evtype):
2284 # remove an event from the schedule
2285 game.future[evtype].date = FOREVER
2286 return game.future[evtype]
2288 def is_scheduled(evtype):
2289 # is an event of specified type scheduled
2290 return game.future[evtype].date != FOREVER
2292 def scheduled(evtype):
2293 # when will this event happen?
2294 return game.future[evtype].date
2296 def schedule(evtype, offset):
2297 # schedule an event of specified type
2298 game.future[evtype].date = game.state.date + offset
2299 return game.future[evtype]
2301 def postpone(evtype, offset):
2302 # postpone a scheduled event
2303 game.future[evtype].date += offset
2306 # rest period is interrupted by event
2309 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2311 game.resting = False
2317 # run through the event queue looking for things to do
2319 fintim = game.state.date + game.optime; yank=0
2320 ictbeam = False; istract = False
2321 w = coord(); hold = coord()
2322 ev = event(); ev2 = event()
2324 def tractorbeam(yank):
2325 # tractor beaming cases merge here
2327 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2331 prout(_(" caught in long range tractor beam--"))
2332 # If Kirk & Co. screwing around on planet, handle
2333 atover(True) # atover(true) is Grab
2336 if game.icraft: # Caught in Galileo?
2339 # Check to see if shuttle is aboard
2340 if game.iscraft == "offship":
2343 prout(_("Galileo, left on the planet surface, is captured"))
2344 prout(_("by aliens and made into a flying McDonald's."))
2345 game.damage[DSHUTTL] = -10
2346 game.iscraft = "removed"
2348 prout(_("Galileo, left on the planet surface, is well hidden."))
2350 game.quadrant = game.state.kscmdr
2352 game.quadrant = game.state.kcmdr[i]
2353 game.sector = randplace(QUADSIZE)
2355 prout(_(" is pulled to Quadrant %s, Sector %s") \
2356 % (game.quadrant, game.sector))
2358 prout(_("(Remainder of rest/repair period cancelled.)"))
2359 game.resting = False
2361 if not damaged(DSHIELD) and game.shield > 0:
2362 doshield(shraise=True) # raise shields
2363 game.shldchg = False
2365 prout(_("(Shields not currently useable.)"))
2367 # Adjust finish time to time of tractor beaming
2368 fintim = game.state.date+game.optime
2370 if game.state.remcom <= 0:
2373 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2376 # Code merges here for any commander destroying base
2377 # Not perfect, but will have to do
2378 # Handle case where base is in same quadrant as starship
2379 if game.battle == game.quadrant:
2380 game.state.chart[game.battle.x][game.battle.y].starbase = False
2381 game.quad[game.base.x][game.base.y] = IHDOT
2382 game.base.x=game.base.y=0
2385 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2386 elif game.state.rembase != 1 and communicating():
2387 # Get word via subspace radio
2390 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2391 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2393 prout(_("the Klingon Super-Commander"))
2395 prout(_("a Klingon Commander"))
2396 game.state.chart[game.battle.x][game.battle.y].starbase = False
2397 # Remove Starbase from galaxy
2398 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2399 for i in range(1, game.state.rembase+1):
2400 if game.state.baseq[i] == game.battle:
2401 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2402 game.state.rembase -= 1
2404 # reinstate a commander's base attack
2408 invalidate(game.battle)
2411 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2412 for i in range(1, NEVENTS):
2413 if i == FSNOVA: proutn("=== Supernova ")
2414 elif i == FTBEAM: proutn("=== T Beam ")
2415 elif i == FSNAP: proutn("=== Snapshot ")
2416 elif i == FBATTAK: proutn("=== Base Attack ")
2417 elif i == FCDBAS: proutn("=== Base Destroy ")
2418 elif i == FSCMOVE: proutn("=== SC Move ")
2419 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2420 elif i == FDSPROB: proutn("=== Probe Move ")
2421 elif i == FDISTR: proutn("=== Distress Call ")
2422 elif i == FENSLV: proutn("=== Enslavement ")
2423 elif i == FREPRO: proutn("=== Klingon Build ")
2425 prout("%.2f" % (scheduled(i)))
2428 radio_was_broken = damaged(DRADIO)
2431 # Select earliest extraneous event, evcode==0 if no events
2436 for l in range(1, NEVENTS):
2437 if game.future[l].date < datemin:
2440 prout("== Event %d fires" % evcode)
2441 datemin = game.future[l].date
2442 xtime = datemin-game.state.date
2443 game.state.date = datemin
2444 # Decrement Federation resources and recompute remaining time
2445 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2447 if game.state.remtime <=0:
2450 # Any crew left alive?
2451 if game.state.crew <=0:
2454 # Is life support adequate?
2455 if damaged(DLIFSUP) and game.condition != "docked":
2456 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2459 game.lsupres -= xtime
2460 if game.damage[DLIFSUP] <= xtime:
2461 game.lsupres = game.inlsr
2464 if game.condition == "docked":
2465 repair /= game.docfac
2466 # Don't fix Deathray here
2467 for l in range(NDEVICES):
2468 if game.damage[l] > 0.0 and l != DDRAY:
2469 if game.damage[l]-repair > 0.0:
2470 game.damage[l] -= repair
2472 game.damage[l] = 0.0
2473 # If radio repaired, update star chart and attack reports
2474 if radio_was_broken and not damaged(DRADIO):
2475 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2476 prout(_(" surveillance reports are coming in."))
2478 if not game.iseenit:
2482 prout(_(" The star chart is now up to date.\""))
2484 # Cause extraneous event EVCODE to occur
2485 game.optime -= xtime
2486 if evcode == FSNOVA: # Supernova
2489 schedule(FSNOVA, expran(0.5*game.intime))
2490 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2492 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2493 if game.state.nscrem == 0 or \
2494 ictbeam or istract or \
2495 game.condition=="docked" or game.isatb==1 or game.iscate:
2497 if game.ientesc or \
2498 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2499 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2500 (damaged(DSHIELD) and \
2501 (game.energy < 2500 or damaged(DPHASER)) and \
2502 (game.torps < 5 or damaged(DPHOTON))):
2504 istract = ictbeam = True
2505 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2508 elif evcode == FTBEAM: # Tractor beam
2509 if game.state.remcom == 0:
2512 i = randrange(game.state.remcom)
2513 yank = distance(game.state.kcmdr[i], game.quadrant)
2514 if istract or game.condition == "docked" or yank == 0:
2515 # Drats! Have to reschedule
2517 game.optime + expran(1.5*game.intime/game.state.remcom))
2521 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2522 game.snapsht = copy.deepcopy(game.state)
2523 game.state.snap = True
2524 schedule(FSNAP, expran(0.5 * game.intime))
2525 elif evcode == FBATTAK: # Commander attacks starbase
2526 if game.state.remcom==0 or game.state.rembase==0:
2532 for j in range(game.state.rembase):
2533 for k in range(game.state.remcom):
2534 if game.state.baseq[j] == game.state.kcmdr[k] and \
2535 not game.state.baseq[j] == game.quadrant and \
2536 not game.state.baseq[j] == game.state.kscmdr:
2540 if j>game.state.rembase:
2541 # no match found -- try later
2542 schedule(FBATTAK, expran(0.3*game.intime))
2545 # commander + starbase combination found -- launch attack
2546 game.battle = game.state.baseq[j]
2547 schedule(FCDBAS, randreal(1.0, 4.0))
2548 if game.isatb: # extra time if SC already attacking
2549 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2550 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2551 game.iseenit = False
2552 if not communicating():
2553 continue # No warning :-(
2557 proutn(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2558 prout(_(" reports that it is under attack and that it can"))
2559 proutn(_(" hold out only until stardate %d") % (int(scheduled(FCDBAS))))
2563 elif evcode == FSCDBAS: # Supercommander destroys base
2566 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2567 continue # WAS RETURN!
2569 game.battle = game.state.kscmdr
2571 elif evcode == FCDBAS: # Commander succeeds in destroying base
2574 # find the lucky pair
2575 for i in range(game.state.remcom):
2576 if game.state.kcmdr[i] == game.battle:
2578 if i > game.state.remcom or game.state.rembase == 0 or \
2579 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2580 # No action to take after all
2581 invalidate(game.battle)
2584 elif evcode == FSCMOVE: # Supercommander moves
2585 schedule(FSCMOVE, 0.2777)
2586 if not game.ientesc and not istract and game.isatb != 1 and \
2587 (not game.iscate or not game.justin):
2589 elif evcode == FDSPROB: # Move deep space probe
2590 schedule(FDSPROB, 0.01)
2591 game.probex += game.probeinx
2592 game.probey += game.probeiny
2593 i = (int)(game.probex/QUADSIZE +0.05)
2594 j = (int)(game.probey/QUADSIZE + 0.05)
2595 if game.probec.x != i or game.probec.y != j:
2598 if not VALID_QUADRANT(i, j) or \
2599 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2600 # Left galaxy or ran into supernova
2604 proutn(_("Lt. Uhura- \"The deep space probe "))
2605 if not VALID_QUADRANT(j, i):
2606 proutn(_("has left the galaxy"))
2608 proutn(_("is no longer transmitting"))
2612 if not communicating():
2615 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2616 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2617 # Update star chart if Radio is working or have access to radio
2619 chp = game.state.chart[game.probec.x][game.probec.y]
2620 chp.klingons = pdest.klingons
2621 chp.starbase = pdest.starbase
2622 chp.stars = pdest.stars
2623 pdest.charted = True
2624 game.proben -= 1 # One less to travel
2625 if game.proben == 0 and game.isarmed and pdest.stars:
2626 # lets blow the sucker!
2627 supernova(True, game.probec)
2629 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2631 elif evcode == FDISTR: # inhabited system issues distress call
2633 # try a whole bunch of times to find something suitable
2634 for i in range(100):
2635 # need a quadrant which is not the current one,
2636 # which has some stars which are inhabited and
2637 # not already under attack, which is not
2638 # supernova'ed, and which has some Klingons in it
2639 w = randplace(GALSIZE)
2640 q = game.state.galaxy[w.x][w.y]
2641 if not (game.quadrant == w or q.planet == None or \
2642 not q.planet.inhabited or \
2643 q.supernova or q.status!="secure" or q.klingons<=0):
2646 # can't seem to find one; ignore this call
2648 prout("=== Couldn't find location for distress event.")
2650 # got one!! Schedule its enslavement
2651 ev = schedule(FENSLV, expran(game.intime))
2653 q.status = distressed
2655 # tell the captain about it if we can
2657 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2659 prout(_("by a Klingon invasion fleet."))
2662 elif evcode == FENSLV: # starsystem is enslaved
2663 ev = unschedule(FENSLV)
2664 # see if current distress call still active
2665 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2669 q.status = "enslaved"
2671 # play stork and schedule the first baby
2672 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2673 ev2.quadrant = ev.quadrant
2675 # report the disaster if we can
2677 prout(_("Uhura- We've lost contact with starsystem %s") % \
2679 prout(_("in Quadrant %s.\n") % ev.quadrant)
2680 elif evcode == FREPRO: # Klingon reproduces
2681 # If we ever switch to a real event queue, we'll need to
2682 # explicitly retrieve and restore the x and y.
2683 ev = schedule(FREPRO, expran(1.0 * game.intime))
2684 # see if current distress call still active
2685 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2689 if game.state.remkl >=MAXKLGAME:
2690 continue # full right now
2691 # reproduce one Klingon
2693 if game.klhere >= MAXKLQUAD:
2695 # this quadrant not ok, pick an adjacent one
2696 for i in range(w.x - 1, w.x + 2):
2697 for j in range(w.y - 1, w.y + 2):
2698 if not VALID_QUADRANT(i, j):
2700 q = game.state.galaxy[w.x][w.y]
2701 # check for this quad ok (not full & no snova)
2702 if q.klingons >= MAXKLQUAD or q.supernova:
2706 continue # search for eligible quadrant failed
2711 game.state.remkl += 1
2713 if game.quadrant == w:
2715 newkling(game.klhere)
2716 # recompute time left
2718 # report the disaster if we can
2720 if game.quadrant == w:
2721 prout(_("Spock- sensors indicate the Klingons have"))
2722 prout(_("launched a warship from %s.") % q.planet)
2724 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2725 if q.planet != None:
2726 proutn(_("near %s") % q.planet)
2727 prout(_("in Quadrant %s.") % w)
2736 proutn(_("How long? "))
2741 origTime = delay = aaitem
2744 if delay >= game.state.remtime or game.nenhere != 0:
2745 proutn(_("Are you sure? "))
2748 # Alternate resting periods (events) with attacks
2752 game.resting = False
2753 if not game.resting:
2754 prout(_("%d stardates left.") % int(game.state.remtime))
2756 temp = game.optime = delay
2758 rtime = randreal(1.0, 2.0)
2762 if game.optime < delay:
2771 # Repair Deathray if long rest at starbase
2772 if origTime-delay >= 9.99 and game.condition == "docked":
2773 game.damage[DDRAY] = 0.0
2774 # leave if quadrant supernovas
2775 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2777 game.resting = False
2780 # A nova occurs. It is the result of having a star hit with a
2781 # photon torpedo, or possibly of a probe warhead going off.
2782 # Stars that go nova cause stars which surround them to undergo
2783 # the same probabilistic process. Klingons next to them are
2784 # destroyed. And if the starship is next to it, it gets zapped.
2785 # If the zap is too much, it gets destroyed.
2789 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2790 newc = coord(); scratch = coord()
2792 # Wow! We've supernova'ed
2793 supernova(False, nov)
2795 # handle initial nova
2796 game.quad[nov.x][nov.y] = IHDOT
2797 crmena(False, IHSTAR, sector, nov)
2799 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2800 game.state.starkl += 1
2802 # Set up stack to recursively trigger adjacent stars
2803 bot = top = top2 = 1
2809 for mm in range(bot, top+1):
2810 for nn in range(1, 3+1): # nn,j represents coordinates around current
2811 for j in range(1, 3+1):
2814 scratch.x = hits[mm][1]+nn-2
2815 scratch.y = hits[mm][2]+j-2
2816 if not VALID_SECTOR(scratch.y, scratch.x):
2818 iquad = game.quad[scratch.x][scratch.y]
2819 # Empty space ends reaction
2820 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2822 elif iquad == IHSTAR: # Affect another star
2824 # This star supernovas
2825 scratch = supernova(False)
2828 hits[top2][1]=scratch.x
2829 hits[top2][2]=scratch.y
2830 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2831 game.state.starkl += 1
2832 crmena(True, IHSTAR, sector, scratch)
2834 game.quad[scratch.x][scratch.y] = IHDOT
2835 elif iquad == IHP: # Destroy planet
2836 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2837 game.state.nplankl += 1
2838 crmena(True, IHP, sector, scratch)
2839 prout(_(" destroyed."))
2840 game.iplnet.pclass = "destroyed"
2842 invalidate(game.plnet)
2846 game.quad[scratch.x][scratch.y] = IHDOT
2847 elif iquad == IHB: # Destroy base
2848 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2849 for i in range(game.state.rembase):
2850 if game.state.baseq[i] == game.quadrant:
2852 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2853 game.state.rembase -= 1
2854 invalidate(game.base)
2855 game.state.basekl += 1
2857 crmena(True, IHB, sector, scratch)
2858 prout(_(" destroyed."))
2859 game.quad[scratch.x][scratch.y] = IHDOT
2860 elif iquad in (IHE, IHF): # Buffet ship
2861 prout(_("***Starship buffeted by nova."))
2863 if game.shield >= 2000.0:
2864 game.shield -= 2000.0
2866 diff = 2000.0 - game.shield
2870 prout(_("***Shields knocked out."))
2871 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2873 game.energy -= 2000.0
2874 if game.energy <= 0:
2877 # add in course nova contributes to kicking starship
2878 icx += game.sector.x-hits[mm][1]
2879 icy += game.sector.y-hits[mm][2]
2881 elif iquad == IHK: # kill klingon
2882 deadkl(scratch,iquad, scratch)
2883 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2884 for ll in range(game.nenhere):
2885 if game.ks[ll] == scratch:
2887 game.kpower[ll] -= 800.0 # If firepower is lost, die
2888 if game.kpower[ll] <= 0.0:
2889 deadkl(scratch, iquad, scratch)
2891 newc.x = scratch.x + scratch.x - hits[mm][1]
2892 newc.y = scratch.y + scratch.y - hits[mm][2]
2893 crmena(True, iquad, sector, scratch)
2894 proutn(_(" damaged"))
2895 if not VALID_SECTOR(newc.x, newc.y):
2896 # can't leave quadrant
2899 iquad1 = game.quad[newc.x][newc.y]
2900 if iquad1 == IHBLANK:
2901 proutn(_(", blasted into "))
2902 crmena(False, IHBLANK, sector, newc)
2904 deadkl(scratch, iquad, newc)
2907 # can't move into something else
2910 proutn(_(", buffeted to Sector %s") % newc)
2911 game.quad[scratch.x][scratch.y] = IHDOT
2912 game.quad[newc.x][newc.y] = iquad
2914 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc)
2923 # Starship affected by nova -- kick it away.
2924 game.dist = kount*0.1
2927 game.direc = course[3*(icx+1)+icy+2]
2928 if game.direc == 0.0:
2930 if game.dist == 0.0:
2932 game.optime = 10.0*game.dist/16.0
2934 prout(_("Force of nova displaces starship."))
2935 imove(novapush=True)
2936 game.optime = 10.0*game.dist/16.0
2939 def supernova(induced, w=None):
2940 # star goes supernova
2947 # Scheduled supernova -- select star
2948 # logic changed here so that we won't favor quadrants in top
2950 for nq.x in range(GALSIZE):
2951 for nq.y in range(GALSIZE):
2952 stars += game.state.galaxy[nq.x][nq.y].stars
2954 return # nothing to supernova exists
2955 num = randrange(stars) + 1
2956 for nq.x in range(GALSIZE):
2957 for nq.y in range(GALSIZE):
2958 num -= game.state.galaxy[nq.x][nq.y].stars
2964 proutn("=== Super nova here?")
2967 if not nq == game.quadrant or game.justin:
2968 # it isn't here, or we just entered (treat as enroute)
2971 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2972 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2975 # we are in the quadrant!
2976 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2977 for ns.x in range(QUADSIZE):
2978 for ns.y in range(QUADSIZE):
2979 if game.quad[ns.x][ns.y]==IHSTAR:
2986 prouts(_("***RED ALERT! RED ALERT!"))
2988 prout(_("***Incipient supernova detected at Sector %s") % ns)
2989 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2990 proutn(_("Emergency override attempts t"))
2991 prouts("***************")
2996 # destroy any Klingons in supernovaed quadrant
2997 kldead = game.state.galaxy[nq.x][nq.y].klingons
2998 game.state.galaxy[nq.x][nq.y].klingons = 0
2999 if nq == game.state.kscmdr:
3000 # did in the Supercommander!
3001 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
3005 if game.state.remcom:
3006 maxloop = game.state.remcom
3007 for l in range(maxloop):
3008 if game.state.kcmdr[l] == nq:
3009 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
3010 invalidate(game.state.kcmdr[game.state.remcom])
3011 game.state.remcom -= 1
3013 if game.state.remcom==0:
3016 game.state.remkl -= kldead
3017 # destroy Romulans and planets in supernovaed quadrant
3018 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
3019 game.state.galaxy[nq.x][nq.y].romulans = 0
3020 game.state.nromrem -= nrmdead
3022 for loop in range(game.inplan):
3023 if game.state.planets[loop].w == nq:
3024 game.state.planets[loop].pclass = "destroyed"
3026 # Destroy any base in supernovaed quadrant
3027 if game.state.rembase:
3028 maxloop = game.state.rembase
3029 for loop in range(maxloop):
3030 if game.state.baseq[loop] == nq:
3031 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3032 invalidate(game.state.baseq[game.state.rembase])
3033 game.state.rembase -= 1
3035 # If starship caused supernova, tally up destruction
3037 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3038 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3039 game.state.nplankl += npdead
3040 # mark supernova in galaxy and in star chart
3041 if game.quadrant == nq or communicating():
3042 game.state.galaxy[nq.x][nq.y].supernova = True
3043 # If supernova destroys last Klingons give special message
3044 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3047 prout(_("Lucky you!"))
3048 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3051 # if some Klingons remain, continue or die in supernova
3056 # Code from finish.c ends here.
3059 # self-destruct maneuver
3060 # Finish with a BANG!
3062 if damaged(DCOMPTR):
3063 prout(_("Computer damaged; cannot execute destruct sequence."))
3065 prouts(_("---WORKING---")); skip(1)
3066 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3067 prouts(" 10"); skip(1)
3068 prouts(" 9"); skip(1)
3069 prouts(" 8"); skip(1)
3070 prouts(" 7"); skip(1)
3071 prouts(" 6"); skip(1)
3073 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3075 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3077 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3081 if game.passwd != citem:
3082 prouts(_("PASSWORD-REJECTED;"))
3084 prouts(_("CONTINUITY-EFFECTED"))
3087 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3088 prouts(" 5"); skip(1)
3089 prouts(" 4"); skip(1)
3090 prouts(" 3"); skip(1)
3091 prouts(" 2"); skip(1)
3092 prouts(" 1"); skip(1)
3094 prouts(_("GOODBYE-CRUEL-WORLD"))
3102 prouts(_("********* Entropy of "))
3104 prouts(_(" maximized *********"))
3108 if game.nenhere != 0:
3109 whammo = 25.0 * game.energy
3111 while l <= game.nenhere:
3112 if game.kpower[l]*game.kdist[l] <= whammo:
3113 deadkl(game.ks[l], game.quad[game.ks[l].x][game.ks[l].y], game.ks[l])
3118 "Compute our rate of kils over time."
3119 elapsed = game.state.date - game.indate
3120 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3123 starting = (game.inkling + game.incom + game.inscom)
3124 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3125 return (starting - remaining)/elapsed
3129 badpt = 5.0*game.state.starkl + \
3131 10.0*game.state.nplankl + \
3132 300*game.state.nworldkl + \
3134 100.0*game.state.basekl +\
3136 if game.ship == IHF:
3138 elif game.ship == None:
3143 # end the game, with appropriate notfications
3147 prout(_("It is stardate %.1f.") % game.state.date)
3149 if ifin == FWON: # Game has been won
3150 if game.state.nromrem != 0:
3151 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3154 prout(_("You have smashed the Klingon invasion fleet and saved"))
3155 prout(_("the Federation."))
3160 badpt = 0.0 # Close enough!
3161 # killsPerDate >= RateMax
3162 if game.state.date-game.indate < 5.0 or \
3163 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3165 prout(_("In fact, you have done so well that Starfleet Command"))
3166 if game.skill == SKILL_NOVICE:
3167 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3168 elif game.skill == SKILL_FAIR:
3169 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3170 elif game.skill == SKILL_GOOD:
3171 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3172 elif game.skill == SKILL_EXPERT:
3173 prout(_("promotes you to Commodore Emeritus."))
3175 prout(_("Now that you think you're really good, try playing"))
3176 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3177 elif game.skill == SKILL_EMERITUS:
3179 proutn(_("Computer- "))
3180 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3182 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3184 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3186 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3188 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3190 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3192 prout(_("Now you can retire and write your own Star Trek game!"))
3194 elif game.skill >= SKILL_EXPERT:
3195 if game.thawed and not idebug:
3196 prout(_("You cannot get a citation, so..."))
3198 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3202 # Only grant long life if alive (original didn't!)
3204 prout(_("LIVE LONG AND PROSPER."))
3209 elif ifin == FDEPLETE: # Federation Resources Depleted
3210 prout(_("Your time has run out and the Federation has been"))
3211 prout(_("conquered. Your starship is now Klingon property,"))
3212 prout(_("and you are put on trial as a war criminal. On the"))
3213 proutn(_("basis of your record, you are "))
3214 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3215 prout(_("acquitted."))
3217 prout(_("LIVE LONG AND PROSPER."))
3219 prout(_("found guilty and"))
3220 prout(_("sentenced to death by slow torture."))
3224 elif ifin == FLIFESUP:
3225 prout(_("Your life support reserves have run out, and"))
3226 prout(_("you die of thirst, starvation, and asphyxiation."))
3227 prout(_("Your starship is a derelict in space."))
3229 prout(_("Your energy supply is exhausted."))
3231 prout(_("Your starship is a derelict in space."))
3232 elif ifin == FBATTLE:
3235 prout(_("has been destroyed in battle."))
3237 prout(_("Dulce et decorum est pro patria mori."))
3239 prout(_("You have made three attempts to cross the negative energy"))
3240 prout(_("barrier which surrounds the galaxy."))
3242 prout(_("Your navigation is abominable."))
3245 prout(_("Your starship has been destroyed by a nova."))
3246 prout(_("That was a great shot."))
3248 elif ifin == FSNOVAED:
3251 prout(_(" has been fried by a supernova."))
3252 prout(_("...Not even cinders remain..."))
3253 elif ifin == FABANDN:
3254 prout(_("You have been captured by the Klingons. If you still"))
3255 prout(_("had a starbase to be returned to, you would have been"))
3256 prout(_("repatriated and given another chance. Since you have"))
3257 prout(_("no starbases, you will be mercilessly tortured to death."))
3258 elif ifin == FDILITHIUM:
3259 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3260 elif ifin == FMATERIALIZE:
3261 prout(_("Starbase was unable to re-materialize your starship."))
3262 prout(_("Sic transit gloria mundi"))
3263 elif ifin == FPHASER:
3266 prout(_(" has been cremated by its own phasers."))
3268 prout(_("You and your landing party have been"))
3269 prout(_("converted to energy, disipating through space."))
3270 elif ifin == FMINING:
3271 prout(_("You are left with your landing party on"))
3272 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3274 prout(_("They are very fond of \"Captain Kirk\" soup."))
3276 proutn(_("Without your leadership, the "))
3278 prout(_(" is destroyed."))
3279 elif ifin == FDPLANET:
3280 prout(_("You and your mining party perish."))
3282 prout(_("That was a great shot."))
3285 prout(_("The Galileo is instantly annihilated by the supernova."))
3286 prout(_("You and your mining party are atomized."))
3288 proutn(_("Mr. Spock takes command of the "))
3291 prout(_("joins the Romulans, reigning terror on the Federation."))
3292 elif ifin == FPNOVA:
3293 prout(_("You and your mining party are atomized."))
3295 proutn(_("Mr. Spock takes command of the "))
3298 prout(_("joins the Romulans, reigning terror on the Federation."))
3299 elif ifin == FSTRACTOR:
3300 prout(_("The shuttle craft Galileo is also caught,"))
3301 prout(_("and breaks up under the strain."))
3303 prout(_("Your debris is scattered for millions of miles."))
3304 proutn(_("Without your leadership, the "))
3306 prout(_(" is destroyed."))
3308 prout(_("The mutants attack and kill Spock."))
3309 prout(_("Your ship is captured by Klingons, and"))
3310 prout(_("your crew is put on display in a Klingon zoo."))
3311 elif ifin == FTRIBBLE:
3312 prout(_("Tribbles consume all remaining water,"))
3313 prout(_("food, and oxygen on your ship."))
3315 prout(_("You die of thirst, starvation, and asphyxiation."))
3316 prout(_("Your starship is a derelict in space."))
3318 prout(_("Your ship is drawn to the center of the black hole."))
3319 prout(_("You are crushed into extremely dense matter."))
3321 prout(_("Your last crew member has died."))
3322 if game.ship == IHF:
3324 elif game.ship == IHE:
3327 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3328 goodies = game.state.remres/game.inresor
3329 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3330 if goodies/baddies >= randreal(1.0, 1.5):
3331 prout(_("As a result of your actions, a treaty with the Klingon"))
3332 prout(_("Empire has been signed. The terms of the treaty are"))
3333 if goodies/baddies >= randreal(3.0):
3334 prout(_("favorable to the Federation."))
3336 prout(_("Congratulations!"))
3338 prout(_("highly unfavorable to the Federation."))
3340 prout(_("The Federation will be destroyed."))
3342 prout(_("Since you took the last Klingon with you, you are a"))
3343 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3344 prout(_("statue in your memory. Rest in peace, and try not"))
3345 prout(_("to think about pigeons."))
3350 # compute player's score
3351 timused = game.state.date - game.indate
3353 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3355 perdate = killrate()
3356 ithperd = 500*perdate + 0.5
3359 iwon = 100*game.skill
3360 if game.ship == IHE:
3362 elif game.ship == IHF:
3366 if not game.gamewon:
3367 game.state.nromrem = 0 # None captured if no win
3368 iscore = 10*(game.inkling - game.state.remkl) \
3369 + 50*(game.incom - game.state.remcom) \
3371 + 20*(game.inrom - game.state.nromrem) \
3372 + 200*(game.inscom - game.state.nscrem) \
3373 - game.state.nromrem \
3378 prout(_("Your score --"))
3379 if game.inrom - game.state.nromrem:
3380 prout(_("%6d Romulans destroyed %5d") %
3381 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3382 if game.state.nromrem:
3383 prout(_("%6d Romulans captured %5d") %
3384 (game.state.nromrem, game.state.nromrem))
3385 if game.inkling - game.state.remkl:
3386 prout(_("%6d ordinary Klingons destroyed %5d") %
3387 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3388 if game.incom - game.state.remcom:
3389 prout(_("%6d Klingon commanders destroyed %5d") %
3390 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3391 if game.inscom - game.state.nscrem:
3392 prout(_("%6d Super-Commander destroyed %5d") %
3393 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3395 prout(_("%6.2f Klingons per stardate %5d") %
3397 if game.state.starkl:
3398 prout(_("%6d stars destroyed by your action %5d") %
3399 (game.state.starkl, -5*game.state.starkl))
3400 if game.state.nplankl:
3401 prout(_("%6d planets destroyed by your action %5d") %
3402 (game.state.nplankl, -10*game.state.nplankl))
3403 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3404 prout(_("%6d inhabited planets destroyed by your action %5d") %
3405 (game.state.nplankl, -300*game.state.nworldkl))
3406 if game.state.basekl:
3407 prout(_("%6d bases destroyed by your action %5d") %
3408 (game.state.basekl, -100*game.state.basekl))
3410 prout(_("%6d calls for help from starbase %5d") %
3411 (game.nhelp, -45*game.nhelp))
3413 prout(_("%6d casualties incurred %5d") %
3414 (game.casual, -game.casual))
3416 prout(_("%6d crew abandoned in space %5d") %
3417 (game.abandoned, -3*game.abandoned))
3419 prout(_("%6d ship(s) lost or destroyed %5d") %
3420 (klship, -100*klship))
3422 prout(_("Penalty for getting yourself killed -200"))
3424 proutn(_("Bonus for winning "))
3425 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3426 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3427 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3428 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3429 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3430 prout(" %5d" % iwon)
3432 prout(_("TOTAL SCORE %5d") % iscore)
3435 # emit winner's commemmorative plaque
3438 proutn(_("File or device name for your plaque: "))
3441 fp = open(winner, "w")
3444 prout(_("Invalid name."))
3446 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3448 # The 38 below must be 64 for 132-column paper
3449 nskip = 38 - len(winner)/2
3450 fp.write("\n\n\n\n")
3451 # --------DRAW ENTERPRISE PICTURE.
3452 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3453 fp.write(" EEE E : : : E\n" )
3454 fp.write(" EE EEE E : : NCC-1701 : E\n")
3455 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3456 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3457 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3458 fp.write(" EEEEEEE EEEEE E E E E\n")
3459 fp.write(" EEE E E E E\n")
3460 fp.write(" E E E E\n")
3461 fp.write(" EEEEEEEEEEEEE E E\n")
3462 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3463 fp.write(" :E : EEEE E\n")
3464 fp.write(" .-E -:----- E\n")
3465 fp.write(" :E : E\n")
3466 fp.write(" EE : EEEEEEEE\n")
3467 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3469 fp.write(_(" U. S. S. ENTERPRISE\n"))
3470 fp.write("\n\n\n\n")
3471 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3473 fp.write(_(" Starfleet Command bestows to you\n"))
3475 fp.write("%*s%s\n\n" % (nskip, "", winner))
3476 fp.write(_(" the rank of\n\n"))
3477 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3479 if game.skill == SKILL_EXPERT:
3480 fp.write(_(" Expert level\n\n"))
3481 elif game.skill == SKILL_EMERITUS:
3482 fp.write(_("Emeritus level\n\n"))
3484 fp.write(_(" Cheat level\n\n"))
3485 timestring = ctime()
3486 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3487 (timestring+4, timestring+20, timestring+11))
3488 fp.write(_(" Your score: %d\n\n") % iscore)
3489 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3492 # Code from io.c begins here
3494 rows = linecount = 0 # for paging
3497 fullscreen_window = None
3498 srscan_window = None
3499 report_window = None
3500 status_window = None
3501 lrscan_window = None
3502 message_window = None
3503 prompt_window = None
3507 "wrap up, either normally or due to signal"
3508 if game.options & OPTION_CURSES:
3515 sys.stdout.write('\n')
3521 #setlocale(LC_ALL, "")
3522 #bindtextdomain(PACKAGE, LOCALEDIR)
3523 #textdomain(PACKAGE)
3524 if atexit.register(outro):
3525 sys.stderr.write("Unable to register outro(), exiting...\n")
3527 if not (game.options & OPTION_CURSES):
3528 ln_env = os.getenv("LINES")
3534 stdscr = curses.initscr()
3539 curses.start_color()
3540 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3541 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3542 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3543 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3544 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3545 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3546 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3547 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3549 global fullscreen_window, srscan_window, report_window, status_window
3550 global lrscan_window, message_window, prompt_window
3551 fullscreen_window = stdscr
3552 srscan_window = curses.newwin(12, 25, 0, 0)
3553 report_window = curses.newwin(11, 0, 1, 25)
3554 status_window = curses.newwin(10, 0, 1, 39)
3555 lrscan_window = curses.newwin(5, 0, 0, 64)
3556 message_window = curses.newwin(0, 0, 12, 0)
3557 prompt_window = curses.newwin(1, 0, rows-2, 0)
3558 message_window.scrollok(True)
3559 setwnd(fullscreen_window)
3563 "wait for user action -- OK to do nothing if on a TTY"
3564 if game.options & OPTION_CURSES:
3569 if game.skill > SKILL_FAIR:
3570 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3572 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3576 if game.skill > SKILL_FAIR:
3577 prompt = _("[CONTINUE?]")
3579 prompt = _("[PRESS ENTER TO CONTINUE]")
3581 if game.options & OPTION_CURSES:
3583 setwnd(prompt_window)
3584 prompt_window.wclear()
3585 prompt_window.addstr(prompt)
3586 prompt_window.getstr()
3587 prompt_window.clear()
3588 prompt_window.refresh()
3589 setwnd(message_window)
3592 sys.stdout.write('\n')
3595 for j in range(rows):
3596 sys.stdout.write('\n')
3600 "Skip i lines. Pause game if this would cause a scrolling event."
3601 for dummy in range(i):
3602 if game.options & OPTION_CURSES:
3603 (y, x) = curwnd.getyx()
3604 (my, mx) = curwnd.getmaxyx()
3605 if curwnd == message_window and y >= my - 3:
3613 if rows and linecount >= rows:
3616 sys.stdout.write('\n')
3619 "Utter a line with no following line feed."
3620 if game.options & OPTION_CURSES:
3624 sys.stdout.write(line)
3636 if game.options & OPTION_CURSES:
3643 "Get a line of input."
3644 if game.options & OPTION_CURSES:
3645 line = curwnd.getstr() + "\n"
3648 if replayfp and not replayfp.closed:
3650 line = replayfp.readline()
3652 prout("*** Replay finished")
3655 elif line[0] != "#":
3658 line = raw_input("COMMAND> ")
3660 logfp.write(line + "\n")
3664 "Change windows -- OK for this to be a no-op in tty mode."
3666 if game.options & OPTION_CURSES:
3668 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3671 "Clear to end of line -- can be a no-op in tty mode"
3672 if game.options & OPTION_CURSES:
3677 "Clear screen -- can be a no-op in tty mode."
3679 if game.options & OPTION_CURSES:
3685 def textcolor(color):
3686 "Set the current text color"
3687 if game.options & OPTION_CURSES:
3688 if color == DEFAULT:
3690 elif color == BLACK:
3691 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3693 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3694 elif color == GREEN:
3695 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3697 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3699 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3700 elif color == MAGENTA:
3701 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3702 elif color == BROWN:
3703 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3704 elif color == LIGHTGRAY:
3705 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3706 elif color == DARKGRAY:
3707 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3708 elif color == LIGHTBLUE:
3709 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3710 elif color == LIGHTGREEN:
3711 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3712 elif color == LIGHTCYAN:
3713 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3714 elif color == LIGHTRED:
3715 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3716 elif color == LIGHTMAGENTA:
3717 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3718 elif color == YELLOW:
3719 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3720 elif color == WHITE:
3721 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3724 "Set highlight video, if this is reasonable."
3725 if game.options & OPTION_CURSES:
3726 curwnd.attron(curses.A_REVERSE)
3729 # Things past this point have policy implications.
3733 "Hook to be called after moving to redraw maps."
3734 if game.options & OPTION_CURSES:
3737 setwnd(srscan_window)
3741 setwnd(status_window)
3742 status_window.clear()
3743 status_window.move(0, 0)
3744 setwnd(report_window)
3745 report_window.clear()
3746 report_window.move(0, 0)
3748 setwnd(lrscan_window)
3749 lrscan_window.clear()
3750 lrscan_window.move(0, 0)
3753 def put_srscan_sym(w, sym):
3754 "Emit symbol for short-range scan."
3755 srscan_window.move(w.x+1, w.y*2+2)
3756 srscan_window.addch(sym)
3757 srscan_window.refresh()
3760 "Enemy fall down, go boom."
3761 if game.options & OPTION_CURSES:
3763 setwnd(srscan_window)
3764 srscan_window.attron(curses.A_REVERSE)
3765 put_srscan_sym(w, game.quad[w.x][w.y])
3769 srscan_window.attroff(curses.A_REVERSE)
3770 put_srscan_sym(w, game.quad[w.x][w.y])
3771 curses.delay_output(500)
3772 setwnd(message_window)
3775 "Sound and visual effects for teleportation."
3776 if game.options & OPTION_CURSES:
3778 setwnd(message_window)
3780 prouts(" . . . . . ")
3781 if game.options & OPTION_CURSES:
3782 #curses.delay_output(1000)
3786 def tracktorpedo(w, l, i, n, iquad):
3787 "Torpedo-track animation."
3788 if not game.options & OPTION_CURSES:
3792 proutn(_("Track for torpedo number %d- ") % i)
3795 proutn(_("Torpedo track- "))
3798 proutn("%d - %d " % (w.x, w.y))
3800 if not damaged(DSRSENS) or game.condition=="docked":
3801 if i != 1 and l == 1:
3804 if (iquad==IHDOT) or (iquad==IHBLANK):
3805 put_srscan_sym(w, '+')
3809 put_srscan_sym(w, iquad)
3811 curwnd.attron(curses.A_REVERSE)
3812 put_srscan_sym(w, iquad)
3816 curwnd.attroff(curses.A_REVERSE)
3817 put_srscan_sym(w, iquad)
3819 proutn("%d - %d " % (w.x, w.y))
3822 "Display the current galaxy chart."
3823 if game.options & OPTION_CURSES:
3824 setwnd(message_window)
3825 message_window.clear()
3827 if game.options & OPTION_TTY:
3832 def prstat(txt, data):
3834 if game.options & OPTION_CURSES:
3836 setwnd(status_window)
3838 proutn(" " * (NSYM - len(txt)))
3841 if game.options & OPTION_CURSES:
3842 setwnd(report_window)
3844 # Code from moving.c begins here
3846 def imove(novapush):
3847 # movement execution for warp, impulse, supernova, and tractor-beam events
3848 w = coord(); final = coord()
3851 def no_quad_change():
3852 # No quadrant change -- compute new average enemy distances
3853 game.quad[game.sector.x][game.sector.y] = game.ship
3855 for m in range(game.nenhere):
3856 finald = distance(w, game.ks[m])
3857 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3858 game.kdist[m] = finald
3860 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3862 for m in range(game.nenhere):
3863 game.kavgd[m] = game.kdist[m]
3866 setwnd(message_window)
3869 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3870 game.inorbit = False
3871 angle = ((15.0 - game.direc) * 0.5235988)
3872 deltax = -math.sin(angle)
3873 deltay = math.cos(angle)
3874 if math.fabs(deltax) > math.fabs(deltay):
3875 bigger = math.fabs(deltax)
3877 bigger = math.fabs(deltay)
3880 # If tractor beam is to occur, don't move full distance
3881 if game.state.date+game.optime >= scheduled(FTBEAM):
3883 game.condition = "red"
3884 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3885 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3886 # Move within the quadrant
3887 game.quad[game.sector.x][game.sector.y] = IHDOT
3890 n = int(10.0*game.dist*bigger+0.5)
3892 for m in range(1, n+1):
3897 if not VALID_SECTOR(w.x, w.y):
3898 # Leaving quadrant -- allow final enemy attack
3899 # Don't do it if being pushed by Nova
3900 if game.nenhere != 0 and not novapush:
3902 for m in range(game.nenhere):
3903 finald = distance(w, game.ks[m])
3904 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
3906 # Stas Sergeev added the condition
3907 # that attacks only happen if Klingons
3908 # are present and your skill is good.
3910 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3914 # compute final position -- new quadrant and sector
3915 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3916 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3917 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3918 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3919 # check for edge of galaxy
3929 if w.x >= GALSIZE*QUADSIZE:
3930 w.x = (GALSIZE*QUADSIZE*2) - w.x
3932 if w.y >= GALSIZE*QUADSIZE:
3933 w.y = (GALSIZE*QUADSIZE*2) - w.y
3941 if game.nkinks == 3:
3942 # Three strikes -- you're out!
3946 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3947 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3948 prout(_("YOU WILL BE DESTROYED."))
3949 # Compute final position in new quadrant
3950 if trbeam: # Don't bother if we are to be beamed
3952 game.quadrant.x = w.x/QUADSIZE
3953 game.quadrant.y = w.y/QUADSIZE
3954 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3955 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3957 prout(_("Entering Quadrant %s.") % game.quadrant)
3958 game.quad[game.sector.x][game.sector.y] = game.ship
3960 if game.skill>SKILL_NOVICE:
3963 iquad = game.quad[w.x][w.y]
3965 # object encountered in flight path
3966 stopegy = 50.0*game.dist/game.optime
3967 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3968 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3970 ram(False, iquad, game.sector)
3972 elif iquad == IHBLANK:
3974 prouts(_("***RED ALERT! RED ALERT!"))
3978 proutn(_(" pulled into black hole at Sector %s") % w)
3980 # Getting pulled into a black hole was certain
3981 # death in Almy's original. Stas Sergeev added a
3982 # possibility that you'll get timewarped instead.
3985 for m in range(NDEVICES):
3986 if game.damage[m]>0:
3988 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3989 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3999 proutn(_(" encounters Tholian web at %s;") % w)
4001 proutn(_(" blocked by object at %s;") % w)
4002 proutn(_("Emergency stop required "))
4003 prout(_("%2d units of energy.") % int(stopegy))
4004 game.energy -= stopegy
4005 final.x = x-deltax+0.5
4006 final.y = y-deltay+0.5
4008 if game.energy <= 0:
4014 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4021 # dock our ship at a starbase
4023 if game.condition == "docked" and verbose:
4024 prout(_("Already docked."))
4027 prout(_("You must first leave standard orbit."))
4029 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4031 prout(_(" not adjacent to base."))
4033 game.condition = "docked"
4037 if game.energy < game.inenrg:
4038 game.energy = game.inenrg
4039 game.shield = game.inshld
4040 game.torps = game.intorps
4041 game.lsupres = game.inlsr
4042 game.state.crew = FULLCREW
4043 if not damaged(DRADIO) and \
4044 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4045 # get attack report from base
4046 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4050 # This program originally required input in terms of a (clock)
4051 # direction and distance. Somewhere in history, it was changed to
4052 # cartesian coordinates. So we need to convert. Probably
4053 # "manual" input should still be done this way -- it's a real
4054 # pain if the computer isn't working! Manual mode is still confusing
4055 # because it involves giving x and y motions, yet the coordinates
4056 # are always displayed y - x, where +y is downward!
4058 def getcourse(isprobe, akey):
4059 # get course and distance
4061 dquad = copy.copy(game.quadrant)
4062 navmode = "unspecified"
4066 if game.landed and not isprobe:
4067 prout(_("Dummy! You can't leave standard orbit until you"))
4068 proutn(_("are back aboard the ship."))
4071 while navmode == "unspecified":
4072 if damaged(DNAVSYS):
4074 prout(_("Computer damaged; manual navigation only"))
4076 prout(_("Computer damaged; manual movement only"))
4081 if isprobe and akey != -1:
4082 # For probe launch, use pre-scanned value first time
4088 proutn(_("Manual or automatic- "))
4091 elif key == IHALPHA:
4096 elif isit("automatic"):
4097 navmode = "automatic"
4106 prout(_("(Manual navigation assumed.)"))
4108 prout(_("(Manual movement assumed.)"))
4111 if navmode == "automatic":
4114 proutn(_("Target quadrant or quadrant§or- "))
4116 proutn(_("Destination sector or quadrant§or- "))
4123 xi = int(round(aaitem))-1
4128 xj = int(round(aaitem))-1
4131 # both quadrant and sector specified
4132 xk = int(round(aaitem))-1
4137 xl = int(round(aaitem))-1
4143 # only one pair of numbers was specified
4145 # only quadrant specified -- go to center of dest quad
4148 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4150 # only sector specified
4154 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4161 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4163 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4164 # the actual deltas get computed here
4165 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4166 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4169 proutn(_("X and Y displacements- "))
4183 # Check for zero movement
4184 if deltax == 0 and deltay == 0:
4187 if itemp == "verbose" and not isprobe:
4189 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4190 # Course actually laid in.
4191 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4192 game.direc = math.atan2(deltax, deltay)*1.90985932
4193 if game.direc < 0.0:
4199 # move under impulse power
4201 if damaged(DIMPULS):
4204 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4206 if game.energy > 30.0:
4207 if not getcourse(isprobe=False, akey=0):
4209 power = 20.0 + 100.0*game.dist
4212 if power >= game.energy:
4213 # Insufficient power for trip
4215 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4216 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4217 if game.energy > 30:
4218 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4219 int(0.01 * (game.energy-20.0)-0.05))
4220 prout(_(" quadrants.\""))
4222 prout(_("quadrant. They are, therefore, useless.\""))
4225 # Make sure enough time is left for the trip
4226 game.optime = game.dist/0.095
4227 if game.optime >= game.state.remtime:
4228 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4229 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4230 proutn(_("we dare spend the time?\" "))
4233 # Activate impulse engines and pay the cost
4234 imove(novapush=False)
4238 power = 20.0 + 100.0*game.dist
4239 game.energy -= power
4240 game.optime = game.dist/0.095
4241 if game.energy <= 0:
4246 # move under warp drive
4247 blooey = False; twarp = False
4248 if not timewarp: # Not WARPX entry
4250 if game.damage[DWARPEN] > 10.0:
4253 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4255 if damaged(DWARPEN) and game.warpfac > 4.0:
4258 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4259 prout(_(" is repaired, I can only give you warp 4.\""))
4261 # Read in course and distance
4262 if not getcourse(isprobe=False, akey=0):
4264 # Make sure starship has enough energy for the trip
4265 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4266 if power >= game.energy:
4267 # Insufficient power for trip
4270 prout(_("Engineering to bridge--"))
4271 if not game.shldup or 0.5*power > game.energy:
4272 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4274 prout(_("We can't do it, Captain. We don't have enough energy."))
4276 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4279 prout(_("if you'll lower the shields."))
4283 prout(_("We haven't the energy to go that far with the shields up."))
4286 # Make sure enough time is left for the trip
4287 game.optime = 10.0*game.dist/game.wfacsq
4288 if game.optime >= 0.8*game.state.remtime:
4290 prout(_("First Officer Spock- \"Captain, I compute that such"))
4291 proutn(_(" a trip would require approximately %2.0f") %
4292 (100.0*game.optime/game.state.remtime))
4293 prout(_(" percent of our"))
4294 proutn(_(" remaining time. Are you sure this is wise?\" "))
4300 if game.warpfac > 6.0:
4301 # Decide if engine damage will occur
4302 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4303 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4304 if prob > randreal():
4306 game.dist = randreal(game.dist)
4307 # Decide if time warp will occur
4308 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4310 if idebug and game.warpfac==10 and not twarp:
4312 proutn("=== Force time warp? ")
4316 # If time warp or engine damage, check path
4317 # If it is obstructed, don't do warp or damage
4318 angle = ((15.0-game.direc)*0.5235998)
4319 deltax = -math.sin(angle)
4320 deltay = math.cos(angle)
4321 if math.fabs(deltax) > math.fabs(deltay):
4322 bigger = math.fabs(deltax)
4324 bigger = math.fabs(deltay)
4328 n = 10.0 * game.dist * bigger +0.5
4331 for l in range(1, n+1):
4336 if not VALID_SECTOR(ix, iy):
4338 if game.quad[ix][iy] != IHDOT:
4341 # Activate Warp Engines and pay the cost
4342 imove(novapush=False)
4345 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4346 if game.energy <= 0:
4348 game.optime = 10.0*game.dist/game.wfacsq
4352 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4354 prout(_("Engineering to bridge--"))
4355 prout(_(" Scott here. The warp engines are damaged."))
4356 prout(_(" We'll have to reduce speed to warp 4."))
4361 # change the warp factor
4367 proutn(_("Warp factor- "))
4372 if game.damage[DWARPEN] > 10.0:
4373 prout(_("Warp engines inoperative."))
4375 if damaged(DWARPEN) and aaitem > 4.0:
4376 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4377 prout(_(" but right now we can only go warp 4.\""))
4380 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4383 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4385 oldfac = game.warpfac
4386 game.warpfac = aaitem
4387 game.wfacsq=game.warpfac*game.warpfac
4388 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4389 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4392 if game.warpfac < 8.00:
4393 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4395 if game.warpfac == 10.0:
4396 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4398 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4402 # cope with being tossed out of quadrant by supernova or yanked by beam
4404 # is captain on planet?
4406 if damaged(DTRANSP):
4409 prout(_("Scotty rushes to the transporter controls."))
4411 prout(_("But with the shields up it's hopeless."))
4413 prouts(_("His desperate attempt to rescue you . . ."))
4418 prout(_("SUCCEEDS!"))
4421 proutn(_("The crystals mined were "))
4429 # Check to see if captain in shuttle craft
4434 # Inform captain of attempt to reach safety
4438 prouts(_("***RED ALERT! RED ALERT!"))
4442 prout(_(" has stopped in a quadrant containing"))
4443 prouts(_(" a supernova."))
4445 proutn(_("***Emergency automatic override attempts to hurl "))
4448 prout(_("safely out of quadrant."))
4449 if not damaged(DRADIO):
4450 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4451 # Try to use warp engines
4452 if damaged(DWARPEN):
4454 prout(_("Warp engines damaged."))
4457 game.warpfac = randreal(6.0, 8.0)
4458 game.wfacsq = game.warpfac * game.warpfac
4459 prout(_("Warp factor set to %d") % int(game.warpfac))
4460 power = 0.75*game.energy
4461 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4462 distreq = randreal(math.sqrt(2))
4463 if distreq < game.dist:
4465 game.optime = 10.0*game.dist/game.wfacsq
4466 game.direc = randreal(12) # How dumb!
4468 game.inorbit = False
4471 # This is bad news, we didn't leave quadrant.
4475 prout(_("Insufficient energy to leave quadrant."))
4478 # Repeat if another snova
4479 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4481 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4482 finish(FWON) # Snova killed remaining enemy.
4485 # let's do the time warp again
4486 prout(_("***TIME WARP ENTERED."))
4487 if game.state.snap and withprob(0.5):
4489 prout(_("You are traveling backwards in time %d stardates.") %
4490 int(game.state.date-game.snapsht.date))
4491 game.state = game.snapsht
4492 game.state.snap = False
4493 if game.state.remcom:
4494 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4495 schedule(FBATTAK, expran(0.3*game.intime))
4496 schedule(FSNOVA, expran(0.5*game.intime))
4497 # next snapshot will be sooner
4498 schedule(FSNAP, expran(0.25*game.state.remtime))
4500 if game.state.nscrem:
4501 schedule(FSCMOVE, 0.2777)
4505 invalidate(game.battle)
4507 # Make sure Galileo is consistant -- Snapshot may have been taken
4508 # when on planet, which would give us two Galileos!
4510 for l in range(game.inplan):
4511 if game.state.planets[l].known == "shuttle_down":
4513 if game.iscraft == "onship" and game.ship==IHE:
4514 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4515 game.iscraft = "offship"
4516 # Likewise, if in the original time the Galileo was abandoned, but
4517 # was on ship earlier, it would have vanished -- let's restore it.
4518 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4519 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4520 game.iscraft = "onship"
4522 # * There used to be code to do the actual reconstrction here,
4523 # * but the starchart is now part of the snapshotted galaxy state.
4525 prout(_("Spock has reconstructed a correct star chart from memory"))
4527 # Go forward in time
4528 game.optime = -0.5*game.intime*math.log(randreal())
4529 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4530 # cheat to make sure no tractor beams occur during time warp
4531 postpone(FTBEAM, game.optime)
4532 game.damage[DRADIO] += game.optime
4534 events() # Stas Sergeev added this -- do pending events
4537 # launch deep-space probe
4538 # New code to launch a deep space probe
4539 if game.nprobes == 0:
4542 if game.ship == IHE:
4543 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4545 prout(_("Ye Faerie Queene has no deep space probes."))
4550 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4552 if is_scheduled(FDSPROB):
4555 if damaged(DRADIO) and game.condition != "docked":
4556 prout(_("Spock- \"Records show the previous probe has not yet"))
4557 prout(_(" reached its destination.\""))
4559 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4563 # slow mode, so let Kirk know how many probes there are left
4564 if game.nprobes == 1:
4565 prout(_("1 probe left."))
4567 prout(_("%d probes left") % game.nprobes)
4568 proutn(_("Are you sure you want to fire a probe? "))
4571 game.isarmed = False
4572 if key == IHALPHA and citem == "armed":
4576 proutn(_("Arm NOVAMAX warhead? "))
4578 if not getcourse(isprobe=True, akey=key):
4581 angle = ((15.0 - game.direc) * 0.5235988)
4582 game.probeinx = -math.sin(angle)
4583 game.probeiny = math.cos(angle)
4584 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4585 bigger = math.fabs(game.probeinx)
4587 bigger = math.fabs(game.probeiny)
4588 game.probeiny /= bigger
4589 game.probeinx /= bigger
4590 game.proben = 10.0*game.dist*bigger +0.5
4591 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4592 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4593 game.probec = game.quadrant
4594 schedule(FDSPROB, 0.01) # Time to move one sector
4595 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4599 # Here's how the mayday code works:
4601 # First, the closest starbase is selected. If there is a a starbase
4602 # in your own quadrant, you are in good shape. This distance takes
4603 # quadrant distances into account only.
4605 # A magic number is computed based on the distance which acts as the
4606 # probability that you will be rematerialized. You get three tries.
4608 # When it is determined that you should be able to be rematerialized
4609 # (i.e., when the probability thing mentioned above comes up
4610 # positive), you are put into that quadrant (anywhere). Then, we try
4611 # to see if there is a spot adjacent to the star- base. If not, you
4612 # can't be rematerialized!!! Otherwise, it drops you there. It only
4613 # tries five times to find a spot to drop you. After that, it's your
4617 # yell for help from nearest starbase
4618 # There's more than one way to move in this game!
4621 # Test for conditions which prevent calling for help
4622 if game.condition == "docked":
4623 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4626 prout(_("Subspace radio damaged."))
4628 if game.state.rembase==0:
4629 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4632 proutn(_("You must be aboard the "))
4636 # OK -- call for help from nearest starbase
4639 # There's one in this quadrant
4640 ddist = distance(game.base, game.sector)
4643 for m in range(game.state.rembase):
4644 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4648 # Since starbase not in quadrant, set up new quadrant
4649 game.quadrant = game.state.baseq[line]
4651 # dematerialize starship
4652 game.quad[game.sector.x][game.sector.y]=IHDOT
4653 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4655 prout(_(" dematerializes."))
4657 for m in range(1, 5+1):
4658 w = game.base.scatter()
4659 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4660 # found one -- finish up
4663 if not is_valid(game.sector):
4664 prout(_("You have been lost in space..."))
4665 finish(FMATERIALIZE)
4667 # Give starbase three chances to rematerialize starship
4668 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4669 for m in range(1, 3+1):
4670 if m == 1: proutn(_("1st"))
4671 elif m == 2: proutn(_("2nd"))
4672 elif m == 3: proutn(_("3rd"))
4673 proutn(_(" attempt to re-materialize "))
4675 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4678 if randreal() > probf:
4681 curses.delay_output(500)
4684 game.quad[ix][iy]=IHQUEST
4687 setwnd(message_window)
4688 finish(FMATERIALIZE)
4690 game.quad[ix][iy]=game.ship
4692 prout(_("succeeds."))
4696 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4698 # Abandon Ship (the BSD-Trek description)
4700 # The ship is abandoned. If your current ship is the Faire
4701 # Queene, or if your shuttlecraft is dead, you're out of
4702 # luck. You need the shuttlecraft in order for the captain
4703 # (that's you!!) to escape.
4705 # Your crew can beam to an inhabited starsystem in the
4706 # quadrant, if there is one and if the transporter is working.
4707 # If there is no inhabited starsystem, or if the transporter
4708 # is out, they are left to die in outer space.
4710 # If there are no starbases left, you are captured by the
4711 # Klingons, who torture you mercilessly. However, if there
4712 # is at least one starbase, you are returned to the
4713 # Federation in a prisoner of war exchange. Of course, this
4714 # can't happen unless you have taken some prisoners.
4719 if game.condition=="docked":
4721 prout(_("You cannot abandon Ye Faerie Queene."))
4724 # Must take shuttle craft to exit
4725 if game.damage[DSHUTTL]==-1:
4726 prout(_("Ye Faerie Queene has no shuttle craft."))
4728 if game.damage[DSHUTTL]<0:
4729 prout(_("Shuttle craft now serving Big Macs."))
4731 if game.damage[DSHUTTL]>0:
4732 prout(_("Shuttle craft damaged."))
4735 prout(_("You must be aboard the ship."))
4737 if game.iscraft != "onship":
4738 prout(_("Shuttle craft not currently available."))
4740 # Print abandon ship messages
4742 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4744 prouts(_("***ALL HANDS ABANDON SHIP!"))
4746 prout(_("Captain and crew escape in shuttle craft."))
4747 if game.state.rembase==0:
4748 # Oops! no place to go...
4751 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4753 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4754 prout(_("Remainder of ship's complement beam down"))
4755 prout(_("to nearest habitable planet."))
4756 elif q.planet != None and not damaged(DTRANSP):
4757 prout(_("Remainder of ship's complement beam down to %s.") %
4760 prout(_("Entire crew of %d left to die in outer space.") %
4762 game.casual += game.state.crew
4763 game.abandoned += game.state.crew
4765 # If at least one base left, give 'em the Faerie Queene
4767 game.icrystl = False # crystals are lost
4768 game.nprobes = 0 # No probes
4769 prout(_("You are captured by Klingons and released to"))
4770 prout(_("the Federation in a prisoner-of-war exchange."))
4771 nb = randrange(game.state.rembase)
4772 # Set up quadrant and position FQ adjacient to base
4773 if not game.quadrant == game.state.baseq[nb]:
4774 game.quadrant = game.state.baseq[nb]
4775 game.sector.x = game.sector.y = 5
4778 # position next to base by trial and error
4779 game.quad[game.sector.x][game.sector.y] = IHDOT
4780 for l in range(QUADSIZE):
4781 game.sector = game.base.scatter()
4782 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4783 game.quad[game.sector.x][game.sector.y] == IHDOT:
4786 break # found a spot
4787 game.sector.x=QUADSIZE/2
4788 game.sector.y=QUADSIZE/2
4790 # Get new commission
4791 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4792 game.state.crew = FULLCREW
4793 prout(_("Starfleet puts you in command of another ship,"))
4794 prout(_("the Faerie Queene, which is antiquated but,"))
4795 prout(_("still useable."))
4797 prout(_("The dilithium crystals have been moved."))
4799 game.iscraft = "offship" # Galileo disappears
4801 game.condition="docked"
4802 for l in range(NDEVICES):
4803 game.damage[l] = 0.0
4804 game.damage[DSHUTTL] = -1
4805 game.energy = game.inenrg = 3000.0
4806 game.shield = game.inshld = 1250.0
4807 game.torps = game.intorps = 6
4808 game.lsupres=game.inlsr=3.0
4814 # Code from planets.c begins here.
4817 # abort a lengthy operation if an event interrupts it
4820 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4825 # report on (uninhabited) planets in the galaxy
4829 prout(_("Spock- \"Planet report follows, Captain.\""))
4831 for i in range(game.inplan):
4832 if game.state.planets[i].pclass == "destroyed":
4834 if (game.state.planets[i].known != "unknown" \
4835 and not game.state.planets[i].inhabited) \
4838 if idebug and game.state.planets[i].known=="unknown":
4839 proutn("(Unknown) ")
4840 proutn(_("Quadrant %s") % game.state.planets[i].w)
4841 proutn(_(" class "))
4842 proutn(game.state.planets[i].pclass)
4844 if game.state.planets[i].crystals != present:
4846 prout(_("dilithium crystals present."))
4847 if game.state.planets[i].known=="shuttle_down":
4848 prout(_(" Shuttle Craft Galileo on surface."))
4850 prout(_("No information available."))
4853 # enter standard orbit
4857 prout(_("Already in standard orbit."))
4859 if damaged(DWARPEN) and damaged(DIMPULS):
4860 prout(_("Both warp and impulse engines damaged."))
4862 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4864 prout(_(" not adjacent to planet."))
4867 game.optime = randreal(0.02, 0.05)
4868 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4872 game.height = randreal(1400, 8600)
4873 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4878 # examine planets in this quadrant
4879 if damaged(DSRSENS):
4880 if game.options & OPTION_TTY:
4881 prout(_("Short range sensors damaged."))
4883 if game.iplnet == None:
4884 if game.options & OPTION_TTY:
4885 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4887 if game.iplnet.known == "unknown":
4888 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4890 prout(_(" Planet at Sector %s is of class %s.") %
4891 (game.plnet, game.iplnet.pclass))
4892 if game.iplnet.known=="shuttle_down":
4893 prout(_(" Sensors show Galileo still on surface."))
4894 proutn(_(" Readings indicate"))
4895 if game.iplnet.crystals != "present":
4897 prout(_(" dilithium crystals present.\""))
4898 if game.iplnet.known == "unknown":
4899 game.iplnet.known = "known"
4900 elif game.iplnet.inhabited:
4901 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4902 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4905 # use the transporter
4909 if damaged(DTRANSP):
4910 prout(_("Transporter damaged."))
4911 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4913 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4917 if not game.inorbit:
4919 prout(_(" not in standard orbit."))
4922 prout(_("Impossible to transport through shields."))
4924 if game.iplnet.known=="unknown":
4925 prout(_("Spock- \"Captain, we have no information on this planet"))
4926 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4927 prout(_(" you may not go down.\""))
4929 if not game.landed and game.iplnet.crystals=="absent":
4930 prout(_("Spock- \"Captain, I fail to see the logic in"))
4931 prout(_(" exploring a planet with no dilithium crystals."))
4932 proutn(_(" Are you sure this is wise?\" "))
4936 if not (game.options & OPTION_PLAIN):
4937 nrgneed = 50 * game.skill + game.height / 100.0
4938 if nrgneed > game.energy:
4939 prout(_("Engineering to bridge--"))
4940 prout(_(" Captain, we don't have enough energy for transportation."))
4942 if not game.landed and nrgneed * 2 > game.energy:
4943 prout(_("Engineering to bridge--"))
4944 prout(_(" Captain, we have enough energy only to transport you down to"))
4945 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4946 if game.iplnet.known == "shuttle_down":
4947 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4948 proutn(_(" Are you sure this is wise?\" "))
4953 # Coming from planet
4954 if game.iplnet.known=="shuttle_down":
4955 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4959 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4960 prout(_("Landing party assembled, ready to beam up."))
4962 prout(_("Kirk whips out communicator..."))
4963 prouts(_("BEEP BEEP BEEP"))
4965 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4968 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4970 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4972 prout(_("Kirk- \"Energize.\""))
4975 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4978 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4980 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4983 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4984 game.landed = not game.landed
4985 game.energy -= nrgneed
4987 prout(_("Transport complete."))
4988 if game.landed and game.iplnet.known=="shuttle_down":
4989 prout(_("The shuttle craft Galileo is here!"))
4990 if not game.landed and game.imine:
4997 # strip-mine a world for dilithium
5001 prout(_("Mining party not on planet."))
5003 if game.iplnet.crystals == "mined":
5004 prout(_("This planet has already been strip-mined for dilithium."))
5006 elif game.iplnet.crystals == "absent":
5007 prout(_("No dilithium crystals on this planet."))
5010 prout(_("You've already mined enough crystals for this trip."))
5012 if game.icrystl and game.cryprob == 0.05:
5013 proutn(_("With all those fresh crystals aboard the "))
5016 prout(_("there's no reason to mine more at this time."))
5018 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
5021 prout(_("Mining operation complete."))
5022 game.iplnet.crystals = "mined"
5023 game.imine = game.ididit = True
5026 # use dilithium crystals
5030 if not game.icrystl:
5031 prout(_("No dilithium crystals available."))
5033 if game.energy >= 1000:
5034 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5035 prout(_(" except when Condition Yellow exists."))
5037 prout(_("Spock- \"Captain, I must warn you that loading"))
5038 prout(_(" raw dilithium crystals into the ship's power"))
5039 prout(_(" system may risk a severe explosion."))
5040 proutn(_(" Are you sure this is wise?\" "))
5045 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5046 prout(_(" Mr. Spock and I will try it.\""))
5048 prout(_("Spock- \"Crystals in place, Sir."))
5049 prout(_(" Ready to activate circuit.\""))
5051 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5053 if with(game.cryprob):
5054 prouts(_(" \"Activating now! - - No good! It's***"))
5056 prouts(_("***RED ALERT! RED A*L********************************"))
5059 prouts(_("****************** KA-BOOM!!!! *******************"))
5063 game.energy += randreal(5000.0, 5500.0)
5064 prouts(_(" \"Activating now! - - "))
5065 prout(_("The instruments"))
5066 prout(_(" are going crazy, but I think it's"))
5067 prout(_(" going to work!! Congratulations, Sir!\""))
5072 # use shuttlecraft for planetary jaunt
5075 if damaged(DSHUTTL):
5076 if game.damage[DSHUTTL] == -1.0:
5077 if game.inorbit and game.iplnet.known == "shuttle_down":
5078 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5080 prout(_("Ye Faerie Queene had no shuttle craft."))
5081 elif game.damage[DSHUTTL] > 0:
5082 prout(_("The Galileo is damaged."))
5083 else: # game.damage[DSHUTTL] < 0
5084 prout(_("Shuttle craft is now serving Big Macs."))
5086 if not game.inorbit:
5088 prout(_(" not in standard orbit."))
5090 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5091 prout(_("Shuttle craft not currently available."))
5093 if not game.landed and game.iplnet.known=="shuttle_down":
5094 prout(_("You will have to beam down to retrieve the shuttle craft."))
5096 if game.shldup or game.condition == "docked":
5097 prout(_("Shuttle craft cannot pass through shields."))
5099 if game.iplnet.known=="unknown":
5100 prout(_("Spock- \"Captain, we have no information on this planet"))
5101 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5102 prout(_(" you may not fly down.\""))
5104 game.optime = 3.0e-5*game.height
5105 if game.optime >= 0.8*game.state.remtime:
5106 prout(_("First Officer Spock- \"Captain, I compute that such"))
5107 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5108 int(100*game.optime/game.state.remtime))
5109 prout(_("remaining time."))
5110 proutn(_("Are you sure this is wise?\" "))
5116 if game.iscraft == "onship":
5118 if not damaged(DTRANSP):
5119 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5123 proutn(_("Shuttle crew"))
5125 proutn(_("Rescue party"))
5126 prout(_(" boards Galileo and swoops toward planet surface."))
5127 game.iscraft = "offship"
5131 game.iplnet.known="shuttle_down"
5132 prout(_("Trip complete."))
5135 # Ready to go back to ship
5136 prout(_("You and your mining party board the"))
5137 prout(_("shuttle craft for the trip back to the Enterprise."))
5139 prouts(_("The short hop begins . . ."))
5141 game.iplnet.known="known"
5147 game.iscraft = "onship"
5153 prout(_("Trip complete."))
5158 prout(_("Mining party assembles in the hangar deck,"))
5159 prout(_("ready to board the shuttle craft \"Galileo\"."))
5161 prouts(_("The hangar doors open; the trip begins."))
5164 game.iscraft = "offship"
5167 game.iplnet.known = "shuttle_down"
5170 prout(_("Trip complete."))
5174 # use the big zapper
5178 if game.ship != IHE:
5179 prout(_("Ye Faerie Queene has no death ray."))
5182 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5185 prout(_("Death Ray is damaged."))
5187 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5188 prout(_(" is highly unpredictible. Considering the alternatives,"))
5189 proutn(_(" are you sure this is wise?\" "))
5192 prout(_("Spock- \"Acknowledged.\""))
5195 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5197 prout(_("Crew scrambles in emergency preparation."))
5198 prout(_("Spock and Scotty ready the death ray and"))
5199 prout(_("prepare to channel all ship's power to the device."))
5201 prout(_("Spock- \"Preparations complete, sir.\""))
5202 prout(_("Kirk- \"Engage!\""))
5204 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5207 if game.options & OPTION_PLAIN:
5211 prouts(_("Sulu- \"Captain! It's working!\""))
5213 while game.nenhere > 0:
5214 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5215 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5216 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5218 if (game.options & OPTION_PLAIN) == 0:
5219 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5221 prout(_(" is still operational.\""))
5223 prout(_(" has been rendered nonfunctional.\""))
5224 game.damage[DDRAY] = 39.95
5226 r = randreal() # Pick failure method
5228 prouts(_("Sulu- \"Captain! It's working!\""))
5230 prouts(_("***RED ALERT! RED ALERT!"))
5232 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5234 prouts(_("***RED ALERT! RED A*L********************************"))
5237 prouts(_("****************** KA-BOOM!!!! *******************"))
5242 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5244 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5246 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5247 prout(_(" have apparently been transformed into strange mutations."))
5248 prout(_(" Vulcans do not seem to be affected."))
5250 prout(_("Kirk- \"Raauch! Raauch!\""))
5255 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5257 proutn(_("Spock- \"I believe the word is"))
5258 prouts(_(" *ASTONISHING*"))
5259 prout(_(" Mr. Sulu."))
5260 for i in range(QUADSIZE):
5261 for j in range(QUADSIZE):
5262 if game.quad[i][j] == IHDOT:
5263 game.quad[i][j] = IHQUEST
5264 prout(_(" Captain, our quadrant is now infested with"))
5265 prouts(_(" - - - - - - *THINGS*."))
5267 prout(_(" I have no logical explanation.\""))
5269 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5271 prout(_("Scotty- \"There are so many tribbles down here"))
5272 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5276 # Code from reports.c begins here
5278 def attackreport(curt):
5279 # report status of bases under attack
5281 if is_scheduled(FCDBAS):
5282 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5283 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5284 elif game.isatb == 1:
5285 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5286 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5288 prout(_("No Starbase is currently under attack."))
5290 if is_scheduled(FCDBAS):
5291 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5293 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5297 # report on general game status
5299 s1 = "" and game.thawed and _("thawed ")
5300 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5301 s3 = (None, _("novice"). _("fair"),
5302 _("good"), _("expert"), _("emeritus"))[game.skill]
5303 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5304 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5305 prout(_("No plaque is allowed."))
5307 prout(_("This is tournament game %d.") % game.tourn)
5308 prout(_("Your secret password is \"%s\"") % game.passwd)
5309 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5310 (game.inkling + game.incom + game.inscom)))
5311 if game.incom - game.state.remcom:
5312 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5313 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5314 prout(_(", but no Commanders."))
5317 if game.skill > SKILL_FAIR:
5318 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5319 if game.state.rembase != game.inbase:
5321 if game.inbase-game.state.rembase==1:
5322 proutn(_("has been 1 base"))
5324 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5325 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5327 prout(_("There are %d bases.") % game.inbase)
5328 if communicating() or game.iseenit:
5329 # Don't report this if not seen and
5330 # either the radio is dead or not at base!
5334 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5336 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5337 if game.ship == IHE:
5338 proutn(_("You have "))
5340 proutn("%d" % (game.nprobes))
5343 proutn(_(" deep space probe"))
5347 if communicating() and is_scheduled(FDSPROB):
5349 proutn(_("An armed deep space probe is in "))
5351 proutn(_("A deep space probe is in "))
5352 prout("Quadrant %s." % game.probec)
5354 if game.cryprob <= .05:
5355 prout(_("Dilithium crystals aboard ship... not yet used."))
5359 while game.cryprob > ai:
5362 prout(_("Dilithium crystals have been used %d time%s.") % \
5363 (i, (_("s"), "")[i==1]))
5367 # long-range sensor scan
5368 if damaged(DLRSENS):
5369 # Now allow base's sensors if docked
5370 if game.condition != "docked":
5371 prout(_("LONG-RANGE SENSORS DAMAGED."))
5373 prout(_("Starbase's long-range scan"))
5375 prout(_("Long-range scan"))
5376 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5378 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5379 if not VALID_QUADRANT(x, y):
5382 if not damaged(DRADIO):
5383 game.state.galaxy[x][y].charted = True
5384 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5385 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5386 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5387 if game.state.galaxy[x][y].supernova:
5390 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5398 for i in range(NDEVICES):
5401 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5402 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5404 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5405 game.damage[i]+0.05,
5406 game.docfac*game.damage[i]+0.005))
5408 prout(_("All devices functional."))
5411 # update the chart in the Enterprise's computer from galaxy data
5412 game.lastchart = game.state.date
5413 for i in range(GALSIZE):
5414 for j in range(GALSIZE):
5415 if game.state.galaxy[i][j].charted:
5416 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5417 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5418 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5421 # display the star chart
5423 if not damaged(DRADIO):
5425 if game.lastchart < game.state.date and game.condition == "docked":
5426 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5429 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5430 if game.state.date > game.lastchart:
5431 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5432 prout(" 1 2 3 4 5 6 7 8")
5433 for i in range(GALSIZE):
5434 proutn("%d |" % (i+1))
5435 for j in range(GALSIZE):
5436 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5440 if game.state.galaxy[i][j].supernova:
5442 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5444 elif game.state.galaxy[i][j].charted:
5445 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5449 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5457 def sectscan(goodScan, i, j):
5458 # light up an individual dot in a sector
5459 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5460 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):
5461 if game.condition == "red": textcolor(RED)
5462 elif game.condition == "green": textcolor(GREEN)
5463 elif game.condition == "yellow": textcolor(YELLOW)
5464 elif game.condition == "docked": textcolor(CYAN)
5465 elif game.condition == "dead": textcolor(BROWN)
5466 if game.quad[i][j] != game.ship:
5468 proutn("%c " % game.quad[i][j])
5474 # print status report lines
5476 if not req or req == 1:
5477 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5478 % (game.state.date, game.state.remtime))
5479 if not req or req == 2:
5480 if game.condition != "docked":
5483 for t in range(NDEVICES):
5484 if game.damage[t]>0:
5486 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5487 if not req or req == 3:
5488 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5489 if not req or req == 4:
5490 if damaged(DLIFSUP):
5491 if game.condition == "docked":
5492 s = _("DAMAGED, Base provides")
5494 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5497 prstat(_("Life Support"), s)
5498 if not req or req == 5:
5499 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5500 if not req or req == 6:
5502 if game.icrystl and (game.options & OPTION_SHOWME):
5503 extra = _(" (have crystals)")
5504 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5505 if not req or req == 7:
5506 prstat(_("Torpedoes"), "%d" % (game.torps))
5507 if not req or req == 8:
5508 if damaged(DSHIELD):
5514 data = _(" %d%% %.1f units") \
5515 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5516 prstat(_("Shields"), s+data)
5517 if not req or req == 9:
5518 prstat(_("Klingons Left"), "%d" \
5519 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5520 if not req or req == 10:
5521 if game.options & OPTION_WORLDS:
5522 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5523 if plnet and plnet.inhabited:
5524 prstat(_("Major system"), plnet.name)
5526 prout(_("Sector is uninhabited"))
5527 elif not req or req == 11:
5528 attackreport(not req)
5531 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5532 while scan() == IHEOL:
5533 proutn(_("Information desired? "))
5535 if citem in requests:
5536 status(requests.index(citem))
5538 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5539 prout((" date, condition, position, lsupport, warpfactor,"))
5540 prout((" energy, torpedoes, shields, klingons, system, time."))
5545 if damaged(DSRSENS):
5546 # Allow base's sensors if docked
5547 if game.condition != "docked":
5548 prout(_(" S.R. SENSORS DAMAGED!"))
5551 prout(_(" [Using Base's sensors]"))
5553 prout(_(" Short-range scan"))
5554 if goodScan and not damaged(DRADIO):
5555 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5556 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5557 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5558 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5559 prout(" 1 2 3 4 5 6 7 8 9 10")
5560 if game.condition != "docked":
5562 for i in range(QUADSIZE):
5563 proutn("%2d " % (i+1))
5564 for j in range(QUADSIZE):
5565 sectscan(goodScan, i, j)
5570 # use computer to get estimated time of arrival for a warp jump
5571 w1 = coord(); w2 = coord()
5573 if damaged(DCOMPTR):
5574 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5577 if scan() != IHREAL:
5580 proutn(_("Destination quadrant and/or sector? "))
5584 w1.y = int(aaitem-0.5)
5585 if scan() != IHREAL:
5588 w1.x = int(aaitem-0.5)
5589 if scan() == IHREAL:
5590 w2.y = int(aaitem-0.5)
5591 if scan() != IHREAL:
5594 w2.x = int(aaitem-0.5)
5596 if game.quadrant.y>w1.x:
5600 if game.quadrant.x>w1.y:
5604 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5607 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5608 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5611 prout(_("Answer \"no\" if you don't know the value:"))
5614 proutn(_("Time or arrival date? "))
5617 if ttime > game.state.date:
5618 ttime -= game.state.date # Actually a star date
5619 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5620 if ttime <= 1e-10 or twarp > 10:
5621 prout(_("We'll never make it, sir."))
5628 proutn(_("Warp factor? "))
5632 if twarp<1.0 or twarp > 10.0:
5636 prout(_("Captain, certainly you can give me one of these."))
5639 ttime = (10.0*game.dist)/square(twarp)
5640 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5641 if tpower >= game.energy:
5642 prout(_("Insufficient energy, sir."))
5643 if not game.shldup or tpower > game.energy*2.0:
5646 proutn(_("New warp factor to try? "))
5647 if scan() == IHREAL:
5650 if twarp<1.0 or twarp > 10.0:
5658 prout(_("But if you lower your shields,"))
5659 proutn(_("remaining"))
5662 proutn(_("Remaining"))
5663 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5665 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5667 prout(_("Any warp speed is adequate."))
5669 prout(_("Minimum warp needed is %.2f,") % (twarp))
5670 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5671 if game.state.remtime < ttime:
5672 prout(_("Unfortunately, the Federation will be destroyed by then."))
5674 prout(_("You'll be taking risks at that speed, Captain"))
5675 if (game.isatb==1 and game.state.kscmdr == w1 and \
5676 scheduled(FSCDBAS)< ttime+game.state.date) or \
5677 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5678 prout(_("The starbase there will be destroyed by then."))
5679 proutn(_("New warp factor to try? "))
5680 if scan() == IHREAL:
5683 if twarp<1.0 or twarp > 10.0:
5692 # Code from setup.c begins here
5695 # issue a historically correct banner
5697 prout(_("-SUPER- STAR TREK"))
5699 # From the FORTRAN original
5700 # prout(_("Latest update-21 Sept 78"))
5706 citem = "emsave.trk"
5710 proutn(_("File name: "))
5716 if '.' not in citem:
5719 fp = open(citem, "wb")
5721 prout(_("Can't freeze game as file %s") % citem)
5723 cPickle.dump(game, fp)
5727 # retrieve saved game
5728 game.passwd[0] = '\0'
5731 proutn(_("File name: "))
5737 if '.' not in citem:
5740 fp = open(citem, "rb")
5742 prout(_("Can't thaw game in %s") % citem)
5744 game = cPickle.load(fp)
5748 # I used <http://www.memory-alpha.org> to find planets
5749 # with references in ST:TOS. Eath and the Alpha Centauri
5750 # Colony have been omitted.
5752 # Some planets marked Class G and P here will be displayed as class M
5753 # because of the way planets are generated. This is a known bug.
5756 _("Andoria (Fesoan)"), # several episodes
5757 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5758 _("Vulcan (T'Khasi)"), # many episodes
5759 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5760 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5761 _("Ardana"), # TOS: "The Cloud Minders"
5762 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5763 _("Gideon"), # TOS: "The Mark of Gideon"
5764 _("Aldebaran III"), # TOS: "The Deadly Years"
5765 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5766 _("Altair IV"), # TOS: "Amok Time
5767 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5768 _("Benecia"), # TOS: "The Conscience of the King"
5769 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5770 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5771 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5772 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5773 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5774 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5775 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5776 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5777 _("Ingraham B"), # TOS: "Operation: Annihilate"
5778 _("Janus IV"), # TOS: "The Devil in the Dark"
5779 _("Makus III"), # TOS: "The Galileo Seven"
5780 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5781 _("Omega IV"), # TOS: "The Omega Glory"
5782 _("Regulus V"), # TOS: "Amok Time
5783 _("Deneva"), # TOS: "Operation -- Annihilate!"
5784 # Worlds from BSD Trek
5785 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5786 _("Beta III"), # TOS: "The Return of the Archons"
5787 _("Triacus"), # TOS: "And the Children Shall Lead",
5788 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5790 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5791 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5792 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5793 # _("Izar"), # TOS: "Whom Gods Destroy"
5794 # _("Tiburon"), # TOS: "The Way to Eden"
5795 # _("Merak II"), # TOS: "The Cloud Minders"
5796 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5797 # _("Iotia"), # TOS: "A Piece of the Action"
5801 _("S. R. Sensors"), \
5802 _("L. R. Sensors"), \
5804 _("Photon Tubes"), \
5805 _("Life Support"), \
5806 _("Warp Engines"), \
5807 _("Impulse Engines"), \
5809 _("Subspace Radio"), \
5810 _("Shuttle Craft"), \
5812 _("Navigation System"), \
5814 _("Shield Control"), \
5819 def setup(needprompt):
5820 # prepare to play, set up cosmos
5822 # Decide how many of everything
5823 if choose(needprompt):
5824 return # frozen game
5825 # Prepare the Enterprise
5826 game.alldone = game.gamewon = False
5828 game.state.crew = FULLCREW
5829 game.energy = game.inenrg = 5000.0
5830 game.shield = game.inshld = 2500.0
5831 game.shldchg = False
5835 game.quadrant = randplace(GALSIZE)
5836 game.sector = randplace(QUADSIZE)
5837 game.torps = game.intorps = 10
5838 game.nprobes = randrange(2, 5)
5840 game.wfacsq = game.warpfac * game.warpfac
5841 for i in range(NDEVICES):
5842 game.damage[i] = 0.0
5843 # Set up assorted game parameters
5844 game.battle = coord()
5845 game.state.date = game.indate = 100.0 * randreal(20, 51)
5846 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5847 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5848 game.isatb = game.state.nplankl = 0
5849 game.state.starkl = game.state.basekl = 0
5850 game.iscraft = "onship"
5854 for i in range(GALSIZE):
5855 for j in range(GALSIZE):
5856 quad = game.state.galaxy[i][j]
5861 quad.starbase = False
5862 quad.supernova = False
5863 quad.status = "secure"
5864 # Initialize times for extraneous events
5865 schedule(FSNOVA, expran(0.5 * game.intime))
5866 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5867 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5868 schedule(FBATTAK, expran(0.3*game.intime))
5870 if game.state.nscrem:
5871 schedule(FSCMOVE, 0.2777)
5876 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5877 schedule(FDISTR, expran(1.0 + game.intime))
5882 # Starchart is functional but we've never seen it
5883 game.lastchart = FOREVER
5884 # Put stars in the galaxy
5886 for i in range(GALSIZE):
5887 for j in range(GALSIZE):
5888 k = randrange(1, QUADSIZE**2/10+1)
5890 game.state.galaxy[i][j].stars = k
5891 # Locate star bases in galaxy
5892 for i in range(game.inbase):
5895 w = randplace(GALSIZE)
5896 if not game.state.galaxy[w.x][w.y].starbase:
5899 # C version: for (j = i-1; j > 0; j--)
5900 # so it did them in the opposite order.
5901 for j in range(1, i):
5902 # Improved placement algorithm to spread out bases
5903 distq = w.distance(game.state.baseq[j])
5904 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5907 prout("=== Abandoning base #%d at %s" % (i, w))
5909 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5911 prout("=== Saving base #%d, close to #%d" % (i, j))
5914 game.state.baseq[i] = w
5915 game.state.galaxy[w.x][w.y].starbase = True
5916 game.state.chart[w.x][w.y].starbase = True
5917 # Position ordinary Klingon Battle Cruisers
5919 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5920 if klumper > MAXKLQUAD:
5924 klump = (1.0 - r*r)*klumper
5929 w = randplace(GALSIZE)
5930 if not game.state.galaxy[w.x][w.y].supernova and \
5931 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5933 game.state.galaxy[w.x][w.y].klingons += int(klump)
5936 # Position Klingon Commander Ships
5937 for i in range(1, game.incom+1):
5939 w = randplace(GALSIZE)
5940 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5941 not game.state.galaxy[w.x][w.y].supernova and \
5942 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5943 not w in game.state.kcmdr[:i]:
5945 game.state.galaxy[w.x][w.y].klingons += 1
5946 game.state.kcmdr[i] = w
5947 # Locate planets in galaxy
5948 for i in range(game.inplan):
5950 w = randplace(GALSIZE)
5951 if game.state.galaxy[w.x][w.y].planet == None:
5955 new.crystals = "absent"
5956 if (game.options & OPTION_WORLDS) and i < NINHAB:
5957 new.pclass = "M" # All inhabited planets are class M
5958 new.crystals = "absent"
5960 new.name = systnames[i]
5961 new.inhabited = True
5963 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5965 new.crystals = "present"
5966 new.known = "unknown"
5967 new.inhabited = False
5968 game.state.galaxy[w.x][w.y].planet = new
5969 game.state.planets.append(new)
5971 for i in range(game.state.nromrem):
5972 w = randplace(GALSIZE)
5973 game.state.galaxy[w.x][w.y].romulans += 1
5974 # Locate the Super Commander
5975 if game.state.nscrem > 0:
5977 w = randplace(GALSIZE)
5978 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
5980 game.state.kscmdr = w
5981 game.state.galaxy[w.x][w.y].klingons += 1
5982 # Place thing (in tournament game, thingx == -1, don't want one!)
5985 thing = randplace(GALSIZE)
5987 game.state.snap = False
5988 if game.skill == SKILL_NOVICE:
5989 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5990 prout(_("a deadly Klingon invasion force. As captain of the United"))
5991 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5992 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5993 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5994 prout(_("your mission. As you proceed you may be given more time."))
5996 prout(_("You will have %d supporting starbases.") % (game.inbase))
5997 proutn(_("Starbase locations- "))
5999 prout(_("Stardate %d.") % int(game.state.date))
6001 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6002 prout(_("An unknown number of Romulans."))
6003 if game.state.nscrem:
6004 prout(_("And one (GULP) Super-Commander."))
6005 prout(_("%d stardates.") % int(game.intime))
6006 proutn(_("%d starbases in ") % game.inbase)
6007 for i in range(game.inbase):
6008 proutn(`game.state.baseq[i]`)
6011 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6012 proutn(_(" Sector %s") % game.sector)
6014 prout(_("Good Luck!"))
6015 if game.state.nscrem:
6016 prout(_(" YOU'LL NEED IT."))
6019 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
6021 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6024 def choose(needprompt):
6025 # choose your game type
6030 game.skill = SKILL_NONE
6032 if needprompt: # Can start with command line options
6033 proutn(_("Would you like a regular, tournament, or saved game? "))
6035 if len(citem)==0: # Try again
6037 if isit("tournament"):
6038 while scan() == IHEOL:
6039 proutn(_("Type in tournament number-"))
6042 continue # We don't want a blank entry
6043 game.tourn = int(round(aaitem))
6046 logfp.write("# random.seed(%d)\n" % aaitem)
6048 if isit("saved") or isit("frozen"):
6052 if game.passwd == None:
6054 if not game.alldone:
6055 game.thawed = True # No plaque if not finished
6061 proutn(_("What is \"%s\"?"), citem)
6063 while game.length==0 or game.skill==SKILL_NONE:
6064 if scan() == IHALPHA:
6067 elif isit("medium"):
6071 elif isit("novice"):
6072 game.skill = SKILL_NOVICE
6074 game.skill = SKILL_FAIR
6076 game.skill = SKILL_GOOD
6077 elif isit("expert"):
6078 game.skill = SKILL_EXPERT
6079 elif isit("emeritus"):
6080 game.skill = SKILL_EMERITUS
6082 proutn(_("What is \""))
6088 proutn(_("Would you like a Short, Medium, or Long game? "))
6089 elif game.skill == SKILL_NONE:
6090 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6091 # Choose game options -- added by ESR for SST2K
6092 if scan() != IHALPHA:
6094 proutn(_("Choose your game style (or just press enter): "))
6097 # Approximates the UT FORTRAN version.
6098 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6099 game.options |= OPTION_PLAIN
6101 # Approximates Tom Almy's version.
6102 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6103 game.options |= OPTION_ALMY
6107 proutn(_("What is \"%s\"?") % citem)
6109 if game.passwd == "debug":
6111 fputs("=== Debug mode enabled\n", sys.stdout)
6113 # Use parameters to generate initial values of things
6114 game.damfac = 0.5 * game.skill
6115 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6116 game.inbase = game.state.rembase
6118 if game.options & OPTION_PLANETS:
6119 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6120 if game.options & OPTION_WORLDS:
6121 game.inplan += int(NINHAB)
6122 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6123 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6124 game.state.remtime = 7.0 * game.length
6125 game.intime = game.state.remtime
6126 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6127 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6128 game.state.remcom = min(10, game.incom)
6129 game.incom = game.state.remcom
6130 game.state.remres = (game.inkling+4*game.incom)*game.intime
6131 game.inresor = game.state.remres
6132 if game.inkling > 50:
6133 game.state.rembase += 1
6134 game.inbase = game.state.rembase
6138 # drop a feature on a random dot in the current quadrant
6141 w = randplace(QUADSIZE)
6142 if game.quad[w.x][w.y] == IHDOT:
6144 game.quad[w.x][w.y] = iquad
6148 # update our alert status
6149 game.condition = "green"
6150 if game.energy < 1000.0:
6151 game.condition = "yellow"
6152 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6153 game.condition = "red"
6155 game.condition="dead"
6158 # drop new Klingon into current quadrant
6161 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6162 game.kpower[i] = randreal(300, 450) + 25.0*game.skill
6166 # set up a new state of quadrant, for when we enter or re-enter it
6170 game.comhere = False
6176 game.inorbit = False
6178 game.ientesc = False
6181 game.iseenit = False
6183 # Attempt to escape Super-commander, so tbeam back!
6186 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6187 # cope with supernova
6190 game.klhere = q.klingons
6191 game.irhere = q.romulans
6192 game.nenhere = game.klhere + game.irhere
6194 game.quad[game.sector.x][game.sector.y] = game.ship
6196 w.x = w.y = 0 # quiet a gcc warning
6197 # Position ordinary Klingons
6198 for i in range(game.klhere):
6200 # If we need a commander, promote a Klingon
6201 for i in range(game.state.remcom):
6202 if game.state.kcmdr[i] == game.quadrant:
6205 if i <= game.state.remcom:
6206 game.quad[w.x][w.y] = IHC
6207 game.kpower[game.klhere] = randreal(950, 1350) + 50.0*game.skill
6209 # If we need a super-commander, promote a Klingon
6210 if game.quadrant == game.state.kscmdr:
6211 game.quad[game.ks[0].x][game.ks[0].y] = IHS
6212 game.kpower[0] = randreal(1175.0, 1575.0) + 125.0*game.skill
6213 game.iscate = (game.state.remkl > 1)
6215 # Put in Romulans if needed
6216 for i in range(game.klhere, game.nenhere):
6219 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6220 game.kpower[i] = randreal(400.0, 850.0) + 50.0*game.skill
6221 # If quadrant needs a starbase, put it in
6223 game.base = dropin(IHB)
6224 # If quadrant needs a planet, put it in
6226 game.iplnet = q.planet
6227 if not q.planet.inhabited:
6228 game.plnet = dropin(IHP)
6230 game.plnet = dropin(IHW)
6231 # Check for condition
6233 # And finally the stars
6234 for i in range(q.stars):
6238 if game.irhere > 0 and game.klhere == 0:
6240 if not damaged(DRADIO):
6242 prout(_("LT. Uhura- \"Captain, an urgent message."))
6243 prout(_(" I'll put it on audio.\" CLICK"))
6245 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6246 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6248 # Put in THING if needed
6250 if thing == game.quadrant:
6252 thing = randplace(GALSIZE)
6254 game.ks[game.nenhere] = w
6255 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6256 distance(game.sector, w)
6257 game.kpower[game.nenhere] = randreal(6000,6500.0)+250.0*game.skill
6258 if not damaged(DSRSENS):
6260 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6261 prout(_(" Please examine your short-range scan.\""))
6262 # Decide if quadrant needs a Tholian; lighten up if skill is low
6263 if game.options & OPTION_THOLIAN:
6264 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6265 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6266 (game.skill > SKILL_GOOD and withprob(0.08)):
6267 game.tholian = coord()
6269 game.tholian.x = withprob(0.5) * (QUADSIZE-1)
6270 game.tholian.y = withprob(0.5) * (QUADSIZE-1)
6271 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6273 game.quad[game.tholian.x][game.tholian.y] = IHT
6275 game.ks[game.nenhere] = game.tholian
6276 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6277 distance(game.sector, game.tholian)
6278 game.kpower[game.nenhere] = randrange(100, 500) + 25.0*game.skill
6279 # Reserve unoccupied corners
6280 if game.quad[0][0]==IHDOT:
6281 game.quad[0][0] = 'X'
6282 if game.quad[0][QUADSIZE-1]==IHDOT:
6283 game.quad[0][QUADSIZE-1] = 'X'
6284 if game.quad[QUADSIZE-1][0]==IHDOT:
6285 game.quad[QUADSIZE-1][0] = 'X'
6286 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6287 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6289 # Put in a few black holes
6290 for i in range(1, 3+1):
6293 # Take out X's in corners if Tholian present
6295 if game.quad[0][0]=='X':
6296 game.quad[0][0] = IHDOT
6297 if game.quad[0][QUADSIZE-1]=='X':
6298 game.quad[0][QUADSIZE-1] = IHDOT
6299 if game.quad[QUADSIZE-1][0]=='X':
6300 game.quad[QUADSIZE-1][0] = IHDOT
6301 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6302 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6305 # sort Klingons by distance from us
6306 # The author liked bubble sort. So we will use it. :-(
6307 if game.nenhere-(thing==game.quadrant)-(game.tholian!=None) < 2:
6311 for j in range(game.nenhere):
6312 if game.kdist[j] > game.kdist[j+1]:
6315 game.kdist[j] = game.kdist[j+1]
6318 game.kavgd[j] = game.kavgd[j+1]
6321 game.ks[j].x = game.ks[j+1].x
6324 game.ks[j].y = game.ks[j+1].y
6327 game.kpower[j] = game.kpower[j+1]
6328 game.kpower[j+1] = t
6333 # set the self-destruct password
6334 if game.options & OPTION_PLAIN:
6337 proutn(_("Please type in a secret password- "))
6340 if game.passwd != None:
6345 game.passwd += chr(ord('a')+randrange(26))
6347 # Code from sst.c begins here
6350 "SRSCAN": OPTION_TTY,
6351 "STATUS": OPTION_TTY,
6352 "REQUEST": OPTION_TTY,
6353 "LRSCAN": OPTION_TTY,
6366 "SENSORS": OPTION_PLANETS,
6367 "ORBIT": OPTION_PLANETS,
6368 "TRANSPORT": OPTION_PLANETS,
6369 "MINE": OPTION_PLANETS,
6370 "CRYSTALS": OPTION_PLANETS,
6371 "SHUTTLE": OPTION_PLANETS,
6372 "PLANETS": OPTION_PLANETS,
6377 "PROBE": OPTION_PROBE,
6379 "FREEZE": 0, # Synonym for SAVE
6385 "SOS": 0, # Synonym for MAYDAY
6386 "CALL": 0, # Synonym for MAYDAY
6393 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6396 # generate a list of legal commands
6398 proutn(_("LEGAL COMMANDS ARE:"))
6399 for key in commands:
6403 proutn("%-12s " % key)
6408 # browse on-line help
6409 # Give help on commands
6413 setwnd(prompt_window)
6414 proutn(_("Help on what command? "))
6416 setwnd(message_window)
6419 if citem in commands or citem == "ABBREV":
6428 fp = open(SSTDOC, "r")
6431 fp = open(DOC_NAME, "r")
6433 prout(_("Spock- \"Captain, that information is missing from the"))
6434 proutn(_(" computer. You need to find "))
6436 prout(_(" and put it in the"))
6437 proutn(_(" current directory or to "))
6441 # This used to continue: "You need to find SST.DOC and put
6442 # it in the current directory."
6446 linebuf = fp.readline()
6448 prout(_("Spock- \"Captain, there is no information on that command.\""))
6451 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6452 linebuf = linebuf[3:].strip()
6456 prout(_("Spock- \"Captain, I've found the following information:\""))
6458 while linebuf in fp:
6459 if "******" in linebuf:
6465 # command-interpretation loop
6468 setwnd(message_window)
6469 while True: # command loop
6471 while True: # get a command
6476 setwnd(prompt_window)
6479 if game.options & OPTION_CURSES:
6484 setwnd(message_window)
6486 candidates = filter(lambda x: x.startswith(citem.upper()),
6488 if len(candidates) == 1:
6491 elif candidates and not (game.options & OPTION_PLAIN):
6492 prout("Commands with that prefix: " + " ".join(candidates))
6496 if cmd == "SRSCAN": # srscan
6498 elif cmd == "STATUS": # status
6500 elif cmd == "REQUEST": # status request
6502 elif cmd == "LRSCAN": # long range scan
6504 elif cmd == "PHASERS": # phasers
6508 elif cmd == "TORPEDO": # photon torpedos
6512 elif cmd == "MOVE": # move under warp
6514 elif cmd == "SHIELDS": # shields
6515 doshield(shraise=False)
6518 game.shldchg = False
6519 elif cmd == "DOCK": # dock at starbase
6523 elif cmd == "DAMAGES": # damage reports
6525 elif cmd == "CHART": # chart
6527 elif cmd == "IMPULSE": # impulse
6529 elif cmd == "REST": # rest
6533 elif cmd == "WARP": # warp
6535 elif cmd == "SCORE": # score
6537 elif cmd == "SENSORS": # sensors
6539 elif cmd == "ORBIT": # orbit
6543 elif cmd == "TRANSPORT": # transport "beam"
6545 elif cmd == "MINE": # mine
6549 elif cmd == "CRYSTALS": # crystals
6553 elif cmd == "SHUTTLE": # shuttle
6557 elif cmd == "PLANETS": # Planet list
6559 elif cmd == "REPORT": # Game Report
6561 elif cmd == "COMPUTER": # use COMPUTER!
6563 elif cmd == "COMMANDS":
6565 elif cmd == "EMEXIT": # Emergency exit
6566 clrscr() # Hide screen
6567 freeze(True) # forced save
6568 raise SysExit,1 # And quick exit
6569 elif cmd == "PROBE":
6570 probe() # Launch probe
6573 elif cmd == "ABANDON": # Abandon Ship
6575 elif cmd == "DESTRUCT": # Self Destruct
6577 elif cmd == "SAVE": # Save Game
6580 if game.skill > SKILL_GOOD:
6581 prout(_("WARNING--Saved games produce no plaques!"))
6582 elif cmd == "DEATHRAY": # Try a desparation measure
6586 elif cmd == "DEBUGCMD": # What do we want for debug???
6588 elif cmd == "MAYDAY": # Call for help
6593 game.alldone = True # quit the game
6598 break # Game has ended
6599 if game.optime != 0.0:
6602 break # Events did us in
6603 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6606 if hitme and not game.justin:
6610 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6622 if cmd == IHR: s = _("Romulan")
6623 elif cmd == IHK: s = _("Klingon")
6624 elif cmd == IHC: s = _("Commander")
6625 elif cmd == IHS: s = _("Super-commander")
6626 elif cmd == IHSTAR: s = _("Star")
6627 elif cmd == IHP: s = _("Planet")
6628 elif cmd == IHB: s = _("Starbase")
6629 elif cmd == IHBLANK: s = _("Black hole")
6630 elif cmd == IHT: s = _("Tholian")
6631 elif cmd == IHWEB: s = _("Tholian web")
6632 elif cmd == IHQUEST: s = _("Stranger")
6633 elif cmd == IHW: s = _("Inhabited World")
6634 else: s = "Unknown??"
6637 def crmena(stars, enemy, loctype, w):
6638 # print an enemy and his location
6644 if loctype == "quadrant":
6645 buf = _("Quadrant ")
6646 elif loctype == "sector":
6651 # print our ship name
6652 if game.ship == IHE:
6654 elif game.ship == IHF:
6655 s = _("Faerie Queene")
6661 # print a line of stars
6662 prouts("******************************************************")
6666 return -avrage*math.log(1e-7 + randreal())
6668 def randplace(size):
6669 # choose a random location
6671 w.x = randrange(size)
6672 w.y = randrange(size)
6676 # Demand input for next scan
6681 # return IHEOL next time
6686 # Get a token from the user
6687 global inqueue, line, citem, aaitem
6691 # Read a line if nothing here
6694 if curwnd==prompt_window:
6696 setwnd(message_window)
6698 # Skip leading white space
6699 line = line.lstrip()
6701 inqueue = line.split()
6707 # From here on in it's all looking at the queue
6708 citem = inqueue.pop(0)
6712 aaitem = float(citem)
6717 citem = citem.lower()
6721 # yes-or-no confirmation
6730 proutn(_("Please answer with \"y\" or \"n\": "))
6733 # complain about unparseable input
6736 prout(_("Beg your pardon, Captain?"))
6739 # compares s to citem and returns true if it matches to the length of s
6740 return s.startswith(citem)
6743 # access to the internals for debugging
6744 proutn("Reset levels? ")
6746 if game.energy < game.inenrg:
6747 game.energy = game.inenrg
6748 game.shield = game.inshld
6749 game.torps = game.intorps
6750 game.lsupres = game.inlsr
6751 proutn("Reset damage? ")
6753 for i in range(NDEVICES):
6754 if game.damage[i] > 0.0:
6755 game.damage[i] = 0.0
6756 proutn("Toggle debug flag? ")
6760 prout("Debug output ON")
6762 prout("Debug output OFF")
6763 proutn("Cause selective damage? ")
6765 for i in range(NDEVICES):
6771 if key == IHALPHA and isit("y"):
6772 game.damage[i] = 10.0
6773 proutn("Examine/change events? ")
6778 FSNOVA: "Supernova ",
6781 FBATTAK: "Base Attack ",
6782 FCDBAS: "Base Destroy ",
6783 FSCMOVE: "SC Move ",
6784 FSCDBAS: "SC Base Destroy ",
6785 FDSPROB: "Probe Move ",
6786 FDISTR: "Distress Call ",
6787 FENSLV: "Enslavement ",
6788 FREPRO: "Klingon Build ",
6790 for i in range(1, NEVENTS):
6793 proutn("%.2f" % (scheduled(i)-game.state.date))
6794 if i == FENSLV or i == FREPRO:
6796 proutn(" in %s" % ev.quadrant)
6806 ev = schedule(i, aaitem)
6807 if i == FENSLV or i == FREPRO:
6809 proutn("In quadrant- ")
6811 # IHEOL says to leave coordinates as they are
6814 prout("Event %d canceled, no x coordinate." % (i))
6817 w.x = int(round(aaitem))
6820 prout("Event %d canceled, no y coordinate." % (i))
6823 w.y = int(round(aaitem))
6826 proutn("Induce supernova here? ")
6828 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6831 if __name__ == '__main__':
6832 global line, thing, game, idebug, iqengry
6833 game = citem = aaitem = inqueue = None
6839 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY)
6840 # Disable curses mode until the game logic is working.
6841 # if os.getenv("TERM"):
6842 # game.options |= OPTION_CURSES | OPTION_SHOWME
6844 game.options |= OPTION_TTY
6845 seed = int(time.time())
6846 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6847 for (switch, val) in options:
6850 replayfp = open(val, "r")
6852 sys.stderr.write("sst: can't open replay file %s\n" % val)
6855 line = replayfp.readline().strip()
6856 (leader, key, seed) = line.split()
6858 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6859 line = replayfp.readline().strip()
6860 arguments += line.split()[2:]
6862 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6864 game.options |= OPTION_TTY
6865 game.options &=~ OPTION_CURSES
6866 elif switch == '-t':
6867 game.options |= OPTION_TTY
6868 game.options &=~ OPTION_CURSES
6869 elif switch == '-x':
6872 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6874 # where to save the input in case of bugs
6876 logfp = open("/usr/tmp/sst-input.log", "w")
6878 sys.stderr.write("sst: warning, can't open logfile\n")
6880 logfp.write("# seed %s\n" % seed)
6881 logfp.write("# options %s\n" % " ".join(arguments))
6888 while True: # Play a game
6889 setwnd(fullscreen_window)
6892 setup(needprompt=not inqueue)
6895 game.alldone = False
6901 if game.tourn and game.alldone:
6902 proutn(_("Do you want your score recorded?"))
6907 proutn(_("Do you want to play again? "))
6911 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))