3 sst.py =-- Super Star Trek in Python
5 This code is a Python translation of a C translation of a FORTRAN original.
6 The FORTRANness still shows in many ways, notably the use of a lot of
7 parallel arrays where a more modern language would use structures
8 or objects. (However, 1-origin array indexing was fixed.)
12 SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON,
13 LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE
14 were in the original non-"super" version of UT FORTRAN Star Trek.
16 Tholians were not in the original. Dave is dubious about their merits.
17 (They are now controlled by OPTION_THOLIAN and turned off if the game
20 Planets and dilithium crystals were not in the original. Dave is OK
21 with this idea. (It's now controlled by OPTION_PLANETS and turned
22 off if the game type is "plain".)
24 Dave says the bit about the Galileo getting turned into a
25 McDonald's is "consistant with our original vision". (This has been
26 left permanently enabled, as it can only happen if OPTION_PLANETS
29 Dave also says the Space Thingy should not be preserved across saved
30 games, so you can't prove to others that you've seen it. He says it
31 shouldn't fire back, either. It should do nothing except scream and
32 disappear when hit by photon torpedos. It's OK that it may move
33 when attacked, but it didn't in the original. (Whether the Thingy
34 can fire back is now controlled by OPTION_THINGY and turned off if the
35 game type is "plain" or "almy". The no-save behavior has been restored.)
37 The Faerie Queen, black holes, and time warping were in the original.
39 Here are Tom Almy's changes:
41 In early 1997, I got the bright idea to look for references to
42 "Super Star Trek" on the World Wide Web. There weren't many hits,
43 but there was one that came up with 1979 Fortran sources! This
44 version had a few additional features that mine didn't have,
45 however mine had some feature it didn't have. So I merged its
46 features that I liked. I also took a peek at the DECUS version (a
47 port, less sources, to the PDP-10), and some other variations.
49 1, Compared to the original UT version, I've changed the "help" command to
50 "call" and the "terminate" command to "quit" to better match
51 user expectations. The DECUS version apparently made those changes
52 as well as changing "freeze" to "save". However I like "freeze".
53 (Both "freeze" and "save" work in SST2K.)
55 2. The experimental deathray originally had only a 5% chance of
56 success, but could be used repeatedly. I guess after a couple
57 years of use, it was less "experimental" because the 1979
58 version had a 70% success rate. However it was prone to breaking
59 after use. I upgraded the deathray, but kept the original set of
60 failure modes (great humor!). (Now controlled by OPTION_DEATHRAY
61 and turned off if game type is "plain".)
63 3. The 1979 version also mentions srscan and lrscan working when
64 docked (using the starbase's scanners), so I made some changes here
65 to do this (and indicating that fact to the player), and then realized
66 the base would have a subspace radio as well -- doing a Chart when docked
67 updates the star chart, and all radio reports will be heard. The Dock
68 command will also give a report if a base is under attack.
70 4. Tholian Web from the 1979 version. (Now controlled by
71 OPTION_THOLIAN and turned off if game type is "plain".)
73 5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING
74 and turned off if game type is "plain".)
76 6. Regular Klingons and Romulans can move in Expert and Emeritus games.
77 This code could use improvement. (Now controlled by OPTION_MVBADDY
78 and turned off if game type is "plain".)
80 7. The deep-space probe feature from the DECUS version. (Now controlled
81 by OPTION_PROBE and turned off if game type is "plain").
83 8. 'emexit' command from the 1979 version.
85 9. Bugfix: Klingon commander movements are no longer reported if long-range
88 10. Bugfix: Better base positioning at startup (more spread out).
89 That made sense to add because most people abort games with
92 In June 2002, I fixed two known bugs and a documentation typo.
93 In June 2004 I fixed a number of bugs involving: 1) parsing invalid
94 numbers, 2) manual phasers when SR scan is damaged and commander is
95 present, 3) time warping into the future, 4) hang when moving
96 klingons in crowded quadrants. (These fixes are in SST2K.)
98 Here are Stas Sergeev's changes:
100 1. The Space Thingy can be shoved, if you ram it, and can fire back if
101 fired upon. (Now controlled by OPTION_THINGY and turned off if game
102 type is "plain" or "almy".)
104 2. When you are docked, base covers you with an almost invincible shield.
105 (A commander can still ram you, or a Romulan can destroy the base,
106 or a SCom can even succeed with direct attack IIRC, but this rarely
107 happens.) (Now controlled by OPTION_BASE and turned off if game
108 type is "plain" or "almy".)
110 3. Ramming a black hole is no longer instant death. There is a
111 chance you might get timewarped instead. (Now controlled by
112 OPTION_BLKHOLE and turned off if game type is "plain" or "almy".)
114 4. The Tholian can be hit with phasers.
116 5. SCom can't escape from you if no more enemies remain
117 (without this, chasing SCom can take an eternity).
119 6. Probe target you enter is now the destination quadrant. Before I don't
120 remember what it was, but it was something I had difficulty using.
122 7. Secret password is now autogenerated.
124 8. "Plaque" is adjusted for A4 paper :-)
126 9. Phasers now tells you how much energy needed, but only if the computer
129 10. Planets are auto-scanned when you enter the quadrant.
131 11. Mining or using crystals in presense of enemy now yields an attack.
132 There are other minor adjustments to what yields an attack
135 12. "freeze" command reverts to "save", most people will understand this
136 better anyway. (SST2K recognizes both.)
138 13. Screen-oriented interface, with sensor scans always up. (SST2K
139 supports both screen-oriented and TTY modes.)
141 Eric Raymond's changes:
143 Mainly, I translated this C code out of FORTRAN into C -- created #defines
144 for a lot of magic numbers and refactored the heck out of it.
146 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
148 2. Status report now indicates when dilithium crystals are on board.
150 3. Per Dave Matuszek's remarks, Thingy state is never saved across games.
152 4. Added game option selection so you can play a close (but not bug-for-
153 bug identical) approximation of older versions.
155 5. Half the quadrants now have inhabited planets, from which one
156 cannot mine dilithium (there will still be the same additional number
157 of dilithium-bearing planets). Torpedoing an inhabited world is *bad*.
158 There is BSD-Trek-like logic for Klingons to attack and enslave
159 inhabited worlds, producing more ships (only is skill is 'good' or
160 better). (Controlled by OPTION_WORLDS and turned off if game
161 type is "plain" or "almy".)
163 6. User input is now logged so we can do regression testing.
165 7. More BSD-Trek features: You can now lose if your entire crew
166 dies in battle. When abandoning ship in a game with inhabited
167 worlds enabled, they must have one in the quadrant to beam down
168 to; otherwise they die in space and this counts heavily against
169 your score. Docking at a starbase replenishes your crew.
171 8. Still more BSD-Trek: we now have a weighted damage table.
172 Also, the nav subsystem (enabling automatic course
173 setting) can be damaged separately from the main computer (which
174 handles weapons targeting, ETA calculation, and self-destruct).
176 After these features were added, I translated this into Python and added
179 9. A long-range scan is done silently whenever you call CHART; thus
180 the LRSCAN command is no longer needed. (Controlled by OPTION_AUTOSCAN
181 and turned off if game type is "plain" or "almy".)
183 import os,sys,math,curses,time,atexit,readline,cPickle,random,getopt,copy
185 SSTDOC = "/usr/share/doc/sst/sst.doc"
188 # Stub to be replaced
189 def _(str): return str
193 NINHAB = (GALSIZE * GALSIZE / 2)
195 PLNETMAX = (NINHAB + MAXUNINHAB)
198 BASEMAX = (GALSIZE * GALSIZE / 12)
201 FULLCREW = 428 # BSD Trek was 387, that's wrong
204 # These functions hide the difference between 0-origin and 1-origin addressing.
205 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
206 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
208 def square(i): return ((i)*(i))
209 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
210 def invalidate(w): w.x = w.y = 0
211 def is_valid(w): return (w.x != 0 and w.y != 0)
213 # How to represent features
238 def __init__(self, x=None, y=None):
241 def invalidate(self):
242 self.x = self.y = None
244 return self.x != None and self.y != None
245 def __eq__(self, other):
246 return other != None and self.x == other.y and self.x == other.y
247 def __add__(self, other):
248 return coord(self.x+self.x, self.y+self.y)
249 def __sub__(self, other):
250 return coord(self.x-self.x, self.y-self.y)
251 def distance(self, other):
252 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
258 s.x = self.x / abs(self.x)
262 s.y = self.y / abs(self.y)
266 s.x = self.x + randrange(-1, 2)
267 s.y = self.y + randrange(-1, 2)
272 if self.x == None or self.y == None:
274 return "%s - %s" % (self.x+1, self.y+1)
279 self.name = None # string-valued if inhabited
280 self.w = coord() # quadrant located
281 self.pclass = None # could be ""M", "N", "O", or "destroyed"
282 self.crystals = "absent"# could be "mined", "present", "absent"
283 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
284 self.inhabited = False # is it inhabites?
295 self.supernova = None
297 self.status = None # Could be "secure", "distressed", "enslaved"
305 def fill2d(size, fillfun):
306 "Fill an empty list in 2D."
308 for i in range(size):
310 for j in range(size):
311 lst[i].append(fillfun(i, j))
316 self.snap = False # snapshot taken
317 self.crew = 0 # crew complement
318 self.remkl = 0 # remaining klingons
319 self.remcom = 0 # remaining commanders
320 self.nscrem = 0 # remaining super commanders
321 self.rembase = 0 # remaining bases
322 self.starkl = 0 # destroyed stars
323 self.basekl = 0 # destroyed bases
324 self.nromrem = 0 # Romulans remaining
325 self.nplankl = 0 # destroyed uninhabited planets
326 self.nworldkl = 0 # destroyed inhabited planets
327 self.planets = [] # Planet information
328 self.date = 0.0 # stardate
329 self.remres = 0 # remaining resources
330 self.remtime = 0 # remaining time
331 self.baseq = [] # Base quadrant coordinates
332 for i in range(BASEMAX):
333 self.baseq.append(coord())
334 self.kcmdr = [] # Commander quadrant coordinates
335 for i in range(QUADSIZE):
336 self.kcmdr.append(coord())
337 self.kscmdr = coord() # Supercommander quadrant coordinates
338 # the galaxy (subscript 0 not used)
339 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
340 # the starchart (subscript 0 not used)
341 self.chart = fill2d(GALSIZE, lambda i, j: page())
345 self.date = None # A real number
346 self.quadrant = None # A coord structure
349 OPTION_ALL = 0xffffffff
350 OPTION_TTY = 0x00000001 # old interface
351 OPTION_CURSES = 0x00000002 # new interface
352 OPTION_IOMODES = 0x00000003 # cover both interfaces
353 OPTION_PLANETS = 0x00000004 # planets and mining
354 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
355 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
356 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
357 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
358 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
359 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
360 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
361 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
362 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
363 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
364 OPTION_PLAIN = 0x01000000 # user chose plain game
365 OPTION_ALMY = 0x02000000 # user chose Almy variant
384 NDEVICES= 16 # Number of devices
393 def damaged(dev): return (game.damage[dev] != 0.0)
394 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
396 # Define future events
397 FSPY = 0 # Spy event happens always (no future[] entry)
398 # can cause SC to tractor beam Enterprise
399 FSNOVA = 1 # Supernova
400 FTBEAM = 2 # Commander tractor beams Enterprise
401 FSNAP = 3 # Snapshot for time warp
402 FBATTAK = 4 # Commander attacks base
403 FCDBAS = 5 # Commander destroys base
404 FSCMOVE = 6 # Supercommander moves (might attack base)
405 FSCDBAS = 7 # Supercommander destroys base
406 FDSPROB = 8 # Move deep space probe
407 FDISTR = 9 # Emit distress call from an inhabited world
408 FENSLV = 10 # Inhabited word is enslaved */
409 FREPRO = 11 # Klingons build a ship in an enslaved system
413 # abstract out the event handling -- underlying data structures will change
414 # when we implement stateful events
416 def findevent(evtype): return game.future[evtype]
420 self.options = None # Game options
421 self.state = snapshot() # A snapshot structure
422 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
423 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
424 self.kpower = [0.0]*(QUADSIZE**2) # enemy energy levels
425 self.kdist = [0.0]*(QUADSIZE**2) # enemy distances
426 self.kavgd = [0.0]*(QUADSIZE**2) # average distances
427 self.damage = [0.0] * NDEVICES # damage encountered
428 self.future = [] # future events
429 for i in range(NEVENTS):
430 self.future.append(event())
431 self.passwd = None; # Self Destruct password
432 self.ks = [] # enemy sector locations
433 for i in range(QUADSIZE**2):
434 self.ks.append(coord())
435 self.quadrant = None # where we are in the large
436 self.sector = None # where we are in the small
437 self.tholian = None # coordinates of Tholian
438 self.base = None # position of base in current quadrant
439 self.battle = None # base coordinates being attacked
440 self.plnet = None # location of planet in quadrant
441 self.probec = None # current probe quadrant
442 self.gamewon = False # Finished!
443 self.ididit = False # action taken -- allows enemy to attack
444 self.alive = False # we are alive (not killed)
445 self.justin = False # just entered quadrant
446 self.shldup = False # shields are up
447 self.shldchg = False # shield is changing (affects efficiency)
448 self.comhere = False # commander here
449 self.ishere = False # super-commander in quadrant
450 self.iscate = False # super commander is here
451 self.ientesc = False # attempted escape from supercommander
452 self.resting = False # rest time
453 self.icraft = False # Kirk in Galileo
454 self.landed = False # party on planet (true), on ship (false)
455 self.alldone = False # game is now finished
456 self.neutz = False # Romulan Neutral Zone
457 self.isarmed = False # probe is armed
458 self.inorbit = False # orbiting a planet
459 self.imine = False # mining
460 self.icrystl = False # dilithium crystals aboard
461 self.iseenit = False # seen base attack report
462 self.thawed = False # thawed game
463 self.condition = None # "green", "yellow", "red", "docked", "dead"
464 self.iscraft = None # "onship", "offship", "removed"
465 self.skill = None # Player skill level
466 self.inkling = 0 # initial number of klingons
467 self.inbase = 0 # initial number of bases
468 self.incom = 0 # initial number of commanders
469 self.inscom = 0 # initial number of commanders
470 self.inrom = 0 # initial number of commanders
471 self.instar = 0 # initial stars
472 self.intorps = 0 # initial/max torpedoes
473 self.torps = 0 # number of torpedoes
474 self.ship = 0 # ship type -- 'E' is Enterprise
475 self.abandoned = 0 # count of crew abandoned in space
476 self.length = 0 # length of game
477 self.klhere = 0 # klingons here
478 self.casual = 0 # causalties
479 self.nhelp = 0 # calls for help
480 self.nkinks = 0 # count of energy-barrier crossings
481 self.iplnet = None # planet # in quadrant
482 self.inplan = 0 # initial planets
483 self.nenhere = 0 # number of enemies in quadrant
484 self.irhere = 0 # Romulans in quadrant
485 self.isatb = 0 # =1 if super commander is attacking base
486 self.tourn = 0 # tournament number
487 self.proben = 0 # number of moves for probe
488 self.nprobes = 0 # number of probes available
489 self.inresor = 0.0 # initial resources
490 self.intime = 0.0 # initial time
491 self.inenrg = 0.0 # initial/max energy
492 self.inshld = 0.0 # initial/max shield
493 self.inlsr = 0.0 # initial life support resources
494 self.indate = 0.0 # initial date
495 self.energy = 0.0 # energy level
496 self.shield = 0.0 # shield level
497 self.warpfac = 0.0 # warp speed
498 self.wfacsq = 0.0 # squared warp factor
499 self.lsupres = 0.0 # life support reserves
500 self.dist = 0.0 # movement distance
501 self.direc = 0.0 # movement direction
502 self.optime = 0.0 # time taken by current operation
503 self.docfac = 0.0 # repair factor when docking (constant?)
504 self.damfac = 0.0 # damage factor
505 self.lastchart = 0.0 # time star chart was last updated
506 self.cryprob = 0.0 # probability that crystal will work
507 self.probex = 0.0 # location of probe
509 self.probeinx = 0.0 # probe x,y increment
510 self.probeiny = 0.0 #
511 self.height = 0.0 # height of orbit around planet
513 # Stas thinks this should be (C expression):
514 # game.state.remkl + game.state.remcom > 0 ?
515 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
516 # He says the existing expression is prone to divide-by-zero errors
517 # after killing the last klingon when score is shown -- perhaps also
518 # if the only remaining klingon is SCOM.
519 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
520 # From enumerated type 'feature'
541 # From enumerated type 'FINTYPE'
565 # From enumerated type 'COLORS'
584 # Log the results of pulling random numbers so we can check determinism.
590 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
593 def randrange(*args):
594 v = random.randrange(*args)
595 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
601 v *= args[0] # returns from [0, a1)
603 v = args[0] + v*args[1] # returns from [a1, a2)
604 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
607 # Code from ai.c begins here
609 def tryexit(look, ienm, loccom, irun):
610 # a bad guy attempts to bug out
612 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
613 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
614 if not VALID_QUADRANT(iq.x,iq.y) or \
615 game.state.galaxy[iq.x][iq.y].supernova or \
616 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
617 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
619 return False; # Romulans cannot escape!
621 # avoid intruding on another commander's territory
623 for n in range(game.state.remcom):
624 if game.state.kcmdr[n] == iq:
626 # refuse to leave if currently attacking starbase
627 if game.battle == game.quadrant:
629 # don't leave if over 1000 units of energy
630 if game.kpower[loccom] > 1000.0:
632 # print escape message and move out of quadrant.
633 # we know this if either short or long range sensors are working
634 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
635 game.condition == docked:
636 crmena(True, ienm, "sector", game.ks[loccom])
637 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
638 # handle local matters related to escape
639 game.quad[game.ks[loccom].x][game.ks[loccom].y] = IHDOT
640 game.ks[loccom] = game.ks[game.nenhere]
641 game.kavgd[loccom] = game.kavgd[game.nenhere]
642 game.kpower[loccom] = game.kpower[game.nenhere]
643 game.kdist[loccom] = game.kdist[game.nenhere]
646 if game.condition != docked:
648 # Handle global matters related to escape
649 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
650 game.state.galaxy[iq.x][iq.y].klingons += 1
656 schedule(FSCMOVE, 0.2777)
660 for n in range(game.state.remcom):
661 if game.state.kcmdr[n] == game.quadrant:
662 game.state.kcmdr[n]=iq
665 return True; # success
668 # The bad-guy movement algorithm:
670 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
671 # If both are operating full strength, force is 1000. If both are damaged,
672 # force is -1000. Having shields down subtracts an additional 1000.
674 # 2. Enemy has forces equal to the energy of the attacker plus
675 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
676 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
678 # Attacker Initial energy levels (nominal):
679 # Klingon Romulan Commander Super-Commander
680 # Novice 400 700 1200
682 # Good 450 800 1300 1750
683 # Expert 475 850 1350 1875
684 # Emeritus 500 900 1400 2000
685 # VARIANCE 75 200 200 200
687 # Enemy vessels only move prior to their attack. In Novice - Good games
688 # only commanders move. In Expert games, all enemy vessels move if there
689 # is a commander present. In Emeritus games all enemy vessels move.
691 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
692 # forces are 1000 greater than Enterprise.
694 # Agressive action on average cuts the distance between the ship and
695 # the enemy to 1/4 the original.
697 # 4. At lower energy advantage, movement units are proportional to the
698 # advantage with a 650 advantage being to hold ground, 800 to move forward
699 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
701 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
702 # retreat, especially at high skill levels.
704 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
707 def movebaddy(com, loccom, ienm):
708 # tactical movement for the bad guys
709 next = coord(); look = coord()
711 # This should probably be just game.comhere + game.ishere
712 if game.skill >= SKILL_EXPERT:
713 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
715 nbaddys = game.comhere + game.ishere
717 dist1 = game.kdist[loccom]
718 mdist = int(dist1 + 0.5); # Nearest integer distance
720 # If SC, check with spy to see if should hi-tail it
722 (game.kpower[loccom] <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
726 # decide whether to advance, retreat, or hold position
727 forces = game.kpower[loccom]+100.0*game.nenhere+400*(nbaddys-1)
729 forces += 1000; # Good for enemy if shield is down!
730 if not damaged(DPHASER) or not damaged(DPHOTON):
731 if damaged(DPHASER): # phasers damaged
734 forces -= 0.2*(game.energy - 2500.0)
735 if damaged(DPHOTON): # photon torpedoes damaged
738 forces -= 50.0*game.torps
740 # phasers and photon tubes both out!
743 if forces <= 1000.0 and game.condition != "docked": # Typical situation
744 motion = ((forces + randreal(200))/150.0) - 5.0
746 if forces > 1000.0: # Very strong -- move in for kill
747 motion = (1.0-square(randreal()))*dist1 + 1.0
748 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
749 motion -= game.skill*(2.0-square(randreal()))
751 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
752 # don't move if no motion
755 # Limit motion according to skill
756 if abs(motion) > game.skill:
761 # calculate preferred number of steps
766 if motion > 0 and nsteps > mdist:
767 nsteps = mdist; # don't overshoot
768 if nsteps > QUADSIZE:
769 nsteps = QUADSIZE; # This shouldn't be necessary
771 nsteps = 1; # This shouldn't be necessary
773 proutn("NSTEPS = %d:" % nsteps)
774 # Compute preferred values of delta X and Y
775 mx = game.sector.x - com.x
776 my = game.sector.y - com.y
777 if 2.0 * abs(mx) < abs(my):
779 if 2.0 * abs(my) < abs(game.sector.x-com.x):
793 for ll in range(nsteps):
795 proutn(" %d" % (ll+1))
796 # Check if preferred position available
808 attempts = 0; # Settle mysterious hang problem
809 while attempts < 20 and not success:
811 if look.x < 0 or look.x >= QUADSIZE:
812 if motion < 0 and tryexit(look, ienm, loccom, irun):
814 if krawlx == mx or my == 0:
816 look.x = next.x + krawlx
818 elif look.y < 0 or look.y >= QUADSIZE:
819 if motion < 0 and tryexit(look, ienm, loccom, irun):
821 if krawly == my or mx == 0:
823 look.y = next.y + krawly
825 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
826 # See if we should ram ship
827 if game.quad[look.x][look.y] == game.ship and \
828 (ienm == IHC or ienm == IHS):
831 if krawlx != mx and my != 0:
832 look.x = next.x + krawlx
834 elif krawly != my and mx != 0:
835 look.y = next.y + krawly
838 break; # we have failed
850 # Put commander in place within same quadrant
851 game.quad[com.x][com.y] = IHDOT
852 game.quad[next.x][next.y] = ienm
855 game.ks[loccom] = next
856 game.kdist[loccom] = game.kavgd[loccom] = distance(game.sector, next)
857 if not damaged(DSRSENS) or game.condition == docked:
860 proutn(_(" from Sector %s") % com)
861 if game.kdist[loccom] < dist1:
862 proutn(_(" advances to "))
864 proutn(_(" retreats to "))
865 prout("Sector %s." % next)
868 # Klingon tactical movement
871 # Figure out which Klingon is the commander (or Supercommander)
874 for i in range(game.nenhere):
876 if game.quad[w.x][w.y] == IHC:
880 for i in range(game.nenhere):
882 if game.quad[w.x][w.y] == IHS:
885 # If skill level is high, move other Klingons and Romulans too!
886 # Move these last so they can base their actions on what the
888 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
889 for i in range(game.nenhere):
891 if game.quad[w.x][w.y] == IHK or game.quad[w.x][w.y] == IHR:
892 movebaddy(w, i, game.quad[w.x][w.y])
895 def movescom(iq, avoid):
896 # commander movement helper
897 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
898 game.state.galaxy[iq.x][iq.y].supernova or \
899 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
902 # Avoid quadrants with bases if we want to avoid Enterprise
903 for i in range(game.state.rembase):
904 if game.state.baseq[i] == iq:
906 if game.justin and not game.iscate:
909 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
910 game.state.kscmdr = iq
911 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
913 # SC has scooted, Remove him from current quadrant
919 for i in range(game.nenhere):
920 if game.quad[game.ks[i].x][game.ks[i].y] == IHS:
922 game.quad[game.ks[i].x][game.ks[i].y] = IHDOT
923 game.ks[i] = game.ks[game.nenhere]
924 game.kdist[i] = game.kdist[game.nenhere]
925 game.kavgd[i] = game.kavgd[game.nenhere]
926 game.kpower[i] = game.kpower[game.nenhere]
929 if game.condition!=docked:
932 # check for a helpful planet
933 for i in range(game.inplan):
934 if game.state.planets[i].w == game.state.kscmdr and \
935 game.state.planets[i].crystals == "present":
937 game.state.planets[i].pclass = "destroyed"
938 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
941 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
942 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
943 prout(_(" by the Super-commander.\""))
945 return False; # looks good!
947 def supercommander():
948 # move the Super Commander
949 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
952 prout("== SUPERCOMMANDER")
953 # Decide on being active or passive
954 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 \
955 (game.state.date-game.indate) < 3.0)
956 if not game.iscate and avoid:
957 # compute move away from Enterprise
958 idelta = game.state.kscmdr-game.quadrant
959 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
961 idelta.x = game.state.kscmdr.y-game.quadrant.y
962 idelta.y = game.quadrant.x-game.state.kscmdr.x
964 # compute distances to starbases
965 if game.state.rembase <= 0:
969 sc = game.state.kscmdr
970 for i in range(game.state.rembase):
971 basetbl.append((i, distance(game.state.baseq[i], sc)))
972 if game.state.rembase > 1:
973 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
974 # look for nearest base without a commander, no Enterprise, and
975 # without too many Klingons, and not already under attack.
976 ifindit = iwhichb = 0
977 for i2 in range(game.state.rembase):
978 i = basetbl[i2][0]; # bug in original had it not finding nearest
979 ibq = game.state.baseq[i]
980 if ibq == game.quadrant or ibq == game.battle or \
981 game.state.galaxy[ibq.x][ibq.y].supernova or \
982 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
984 # if there is a commander, and no other base is appropriate,
985 # we will take the one with the commander
986 for j in range(game.state.remcom):
987 if ibq == game.state.kcmdr[j] and ifindit!= 2:
991 if j > game.state.remcom: # no commander -- use this one
996 return; # Nothing suitable -- wait until next time
997 ibq = game.state.baseq[iwhichb]
998 # decide how to move toward base
999 idelta = ibq - game.state.kscmdr
1000 # Maximum movement is 1 quadrant in either or both axes
1001 idelta = idelta.sgn()
1002 # try moving in both x and y directions
1003 # there was what looked like a bug in the Almy C code here,
1004 # but it might be this translation is just wrong.
1005 iq = game.state.kscmdr + idelta
1006 if movescom(iq, avoid):
1007 # failed -- try some other maneuvers
1008 if idelta.x==0 or idelta.y==0:
1009 # attempt angle move
1011 iq.y = game.state.kscmdr.y + 1
1012 if movescom(iq, avoid):
1013 iq.y = game.state.kscmdr.y - 1
1016 iq.x = game.state.kscmdr.x + 1
1017 if movescom(iq, avoid):
1018 iq.x = game.state.kscmdr.x - 1
1021 # try moving just in x or y
1022 iq.y = game.state.kscmdr.y
1023 if movescom(iq, avoid):
1024 iq.y = game.state.kscmdr.y + idelta.y
1025 iq.x = game.state.kscmdr.x
1028 if game.state.rembase == 0:
1031 for i in range(game.state.rembase):
1032 ibq = game.state.baseq[i]
1033 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1036 return; # no, don't attack base!
1037 game.iseenit = False
1039 schedule(FSCDBAS, randreal(1.0, 3.0))
1040 if is_scheduled(FCDBAS):
1041 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1042 if not communicating():
1043 return; # no warning
1046 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1047 % game.state.kscmdr)
1048 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1049 proutn(_(" It can survive until stardate %d.\"") \
1050 % int(scheduled(FSCDBAS)))
1051 if not game.resting:
1053 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1056 game.resting = False
1057 game.optime = 0.0; # actually finished
1059 # Check for intelligence report
1062 (not communicating()) or \
1063 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1066 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1067 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1072 if not game.tholian or game.justin:
1074 if game.tholian.x == 0 and game.tholian.y == 0:
1075 idx = 0; idy = QUADSIZE-1
1076 elif game.tholian.x == 0 and game.tholian.y == QUADSIZE-1:
1077 idx = QUADSIZE-1; idy = QUADSIZE-1
1078 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == QUADSIZE-1:
1079 idx = QUADSIZE-1; idy = 0
1080 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == 0:
1083 # something is wrong!
1086 # do nothing if we are blocked
1087 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1089 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1090 if game.tholian.x != idx:
1092 im = math.fabs(idx - game.tholian.x)*1.0/(idx - game.tholian.x)
1093 while game.tholian.x != idx:
1094 game.tholian.x += im
1095 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1096 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1097 elif game.tholian.y != idy:
1099 im = math.fabs(idy - game.tholian.y)*1.0/(idy - game.tholian.y)
1100 while game.tholian.y != idy:
1101 game.tholian.y += im
1102 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1103 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1104 game.quad[game.tholian.x][game.tholian.y] = IHT
1105 game.ks[game.nenhere] = game.tholian
1107 # check to see if all holes plugged
1108 for i in range(QUADSIZE):
1109 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1111 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1113 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1115 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1117 # All plugged up -- Tholian splits
1118 game.quad[game.tholian.x][game.tholian.y]=IHWEB
1120 crmena(True, IHT, "sector", game.tholian)
1121 prout(_(" completes web."))
1126 # Code from battle.c begins here
1128 def doshield(shraise):
1129 # change shield status
1137 if isit("transfer"):
1141 if damaged(DSHIELD):
1142 prout(_("Shields damaged and down."))
1149 proutn(_("Do you wish to change shield energy? "))
1151 proutn(_("Energy to transfer to shields- "))
1153 elif damaged(DSHIELD):
1154 prout(_("Shields damaged and down."))
1157 proutn(_("Shields are up. Do you want them down? "))
1164 proutn(_("Shields are down. Do you want them up? "))
1170 if action == "SHUP": # raise shields
1172 prout(_("Shields already up."))
1176 if game.condition != "docked":
1178 prout(_("Shields raised."))
1179 if game.energy <= 0:
1181 prout(_("Shields raising uses up last of energy."))
1186 elif action == "SHDN":
1188 prout(_("Shields already down."))
1192 prout(_("Shields lowered."))
1195 elif action == "NRG":
1196 while scan() != IHREAL:
1198 proutn(_("Energy to transfer to shields- "))
1202 if aaitem > game.energy:
1203 prout(_("Insufficient ship energy."))
1206 if game.shield+aaitem >= game.inshld:
1207 prout(_("Shield energy maximized."))
1208 if game.shield+aaitem > game.inshld:
1209 prout(_("Excess energy requested returned to ship energy"))
1210 game.energy -= game.inshld-game.shield
1211 game.shield = game.inshld
1213 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1214 # Prevent shield drain loophole
1216 prout(_("Engineering to bridge--"))
1217 prout(_(" Scott here. Power circuit problem, Captain."))
1218 prout(_(" I can't drain the shields."))
1221 if game.shield+aaitem < 0:
1222 prout(_("All shield energy transferred to ship."))
1223 game.energy += game.shield
1226 proutn(_("Scotty- \""))
1228 prout(_("Transferring energy to shields.\""))
1230 prout(_("Draining energy from shields.\""))
1231 game.shield += aaitem
1232 game.energy -= aaitem
1236 # choose a device to damage, at random.
1238 # Quoth Eric Allman in the code of BSD-Trek:
1239 # "Under certain conditions you can get a critical hit. This
1240 # sort of hit damages devices. The probability that a given
1241 # device is damaged depends on the device. Well protected
1242 # devices (such as the computer, which is in the core of the
1243 # ship and has considerable redundancy) almost never get
1244 # damaged, whereas devices which are exposed (such as the
1245 # warp engines) or which are particularly delicate (such as
1246 # the transporter) have a much higher probability of being
1249 # This is one place where OPTION_PLAIN does not restore the
1250 # original behavior, which was equiprobable damage across
1251 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1252 # and have done with it. Also, in the original game, DNAVYS
1253 # and DCOMPTR were the same device.
1255 # Instead, we use a table of weights similar to the one from BSD Trek.
1256 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1257 # We don't have a cloaking device. The shuttle got the allocation
1258 # for the cloaking device, then we shaved a half-percent off
1259 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1262 105, # DSRSENS: short range scanners 10.5%
1263 105, # DLRSENS: long range scanners 10.5%
1264 120, # DPHASER: phasers 12.0%
1265 120, # DPHOTON: photon torpedoes 12.0%
1266 25, # DLIFSUP: life support 2.5%
1267 65, # DWARPEN: warp drive 6.5%
1268 70, # DIMPULS: impulse engines 6.5%
1269 145, # DSHIELD: deflector shields 14.5%
1270 30, # DRADIO: subspace radio 3.0%
1271 45, # DSHUTTL: shuttle 4.5%
1272 15, # DCOMPTR: computer 1.5%
1273 20, # NAVCOMP: navigation system 2.0%
1274 75, # DTRANSP: transporter 7.5%
1275 20, # DSHCTRL: high-speed shield controller 2.0%
1276 10, # DDRAY: death ray 1.0%
1277 30, # DDSP: deep-space probes 3.0%
1279 idx = randrange(1000) # weights must sum to 1000
1281 for (i, w) in enumerate(weights):
1285 return None; # we should never get here
1287 def ram(ibumpd, ienm, w):
1288 # make our ship ram something
1289 prouts(_("***RED ALERT! RED ALERT!"))
1291 prout(_("***COLLISION IMMINENT."))
1295 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1297 proutn(_(" rammed by "))
1300 crmena(False, ienm, "sector", w)
1302 proutn(_(" (original position)"))
1304 deadkl(w, ienm, game.sector)
1307 prout(_(" heavily damaged."))
1308 icas = randrange(10, 30)
1309 prout(_("***Sickbay reports %d casualties"), icas)
1311 game.state.crew -= icas
1313 # In the pre-SST2K version, all devices got equiprobably damaged,
1314 # which was silly. Instead, pick up to half the devices at
1315 # random according to our weighting table,
1317 ncrits = randrange(NDEVICES/2)
1318 for m in range(ncrits):
1320 if game.damage[dev] < 0:
1322 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1323 # Damage for at least time of travel!
1324 game.damage[dev] += game.optime + extradm
1326 prout(_("***Shields are down."))
1327 if game.state.remkl + game.state.remcom + game.state.nscrem:
1334 def torpedo(course, r, incoming, i, n):
1335 # let a photon torpedo fly
1338 ac = course + 0.25*r
1339 angle = (15.0-ac)*0.5235988
1340 bullseye = (15.0 - course)*0.5235988
1341 deltax = -math.sin(angle);
1342 deltay = math.cos(angle);
1343 x = incoming.x; y = incoming.y
1344 w = coord(); jw = coord()
1345 w.x = w.y = jw.x = jw.y = 0
1346 bigger = max(math.fabs(deltax), math.fabs(deltay))
1349 if not damaged(DSRSENS) or game.condition=="docked":
1350 setwnd(srscan_window)
1352 setwnd(message_window)
1353 # Loop to move a single torpedo
1354 for l in range(1, 15+1):
1359 if not VALID_SECTOR(w.x, w.y):
1361 iquad=game.quad[w.x][w.y]
1362 tracktorpedo(w, l, i, n, iquad)
1366 setwnd(message_window)
1367 if damaged(DSRSENS) and not game.condition=="docked":
1368 skip(1); # start new line after text track
1369 if iquad in (IHE, IHF): # Hit our ship
1371 proutn(_("Torpedo hits "))
1374 hit = 700.0 + randreal(100) - \
1375 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1376 newcnd(); # we're blown out of dock
1377 # We may be displaced.
1378 if game.landed or game.condition=="docked":
1379 return hit # Cheat if on a planet
1380 ang = angle + 2.5*(randreal()-0.5)
1381 temp = math.fabs(math.sin(ang))
1382 if math.fabs(math.cos(ang)) > temp:
1383 temp = math.fabs(math.cos(ang))
1384 xx = -math.sin(ang)/temp
1385 yy = math.cos(ang)/temp
1388 if not VALID_SECTOR(jw.x, jw.y):
1390 if game.quad[jw.x][jw.y]==IHBLANK:
1393 if game.quad[jw.x][jw.y]!=IHDOT:
1394 # can't move into object
1399 elif iquad in (IHC, IHS): # Hit a commander
1401 crmena(True, iquad, "sector", w)
1402 prout(_(" uses anti-photon device;"))
1403 prout(_(" torpedo neutralized."))
1405 elif iquad in (IHR, IHK): # Hit a regular enemy
1407 for ll in range(game.nenhere):
1408 if w == game.ks[ll]:
1410 kp = math.fabs(game.kpower[ll])
1411 h1 = 700.0 + randrange(100) - \
1412 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1416 if game.kpower[ll] < 0:
1417 game.kpower[ll] -= -h1
1419 game.kpower[ll] -= h1
1420 if game.kpower[ll] == 0:
1423 crmena(True, iquad, "sector", w)
1424 # If enemy damaged but not destroyed, try to displace
1425 ang = angle + 2.5*(randreal()-0.5)
1426 temp = math.fabs(math.sin(ang))
1427 if math.fabs(math.cos(ang)) > temp:
1428 temp = math.fabs(math.cos(ang))
1429 xx = -math.sin(ang)/temp
1430 yy = math.cos(ang)/temp
1433 if not VALID_SECTOR(jw.x, jw.y):
1434 prout(_(" damaged but not destroyed."))
1436 if game.quad[jw.x][jw.y]==IHBLANK:
1437 prout(_(" buffeted into black hole."))
1438 deadkl(w, iquad, jw)
1440 if game.quad[jw.x][jw.y]!=IHDOT:
1441 # can't move into object
1442 prout(_(" damaged but not destroyed."))
1444 proutn(_(" damaged--"))
1448 elif iquad == IHB: # Hit a base
1450 prout(_("***STARBASE DESTROYED.."))
1451 for ll in range(game.state.rembase):
1452 if game.state.baseq[ll] == game.quadrant:
1453 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1455 game.quad[w.x][w.y]=IHDOT
1456 game.state.rembase -= 1
1457 game.base.x=game.base.y=0
1458 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1459 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1460 game.state.basekl += 1
1463 elif iquad == IHP: # Hit a planet
1464 crmena(True, iquad, "sector", w)
1465 prout(_(" destroyed."))
1466 game.state.nplankl += 1
1467 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1468 game.iplnet.pclass = "destroyed"
1470 invalidate(game.plnet)
1471 game.quad[w.x][w.y] = IHDOT
1473 # captain perishes on planet
1476 elif iquad == IHW: # Hit an inhabited world -- very bad!
1477 crmena(True, iquad, "sector", w)
1478 prout(_(" destroyed."))
1479 game.state.nworldkl += 1
1480 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1481 game.iplnet.pclass = "destroyed"
1483 invalidate(game.plnet)
1484 game.quad[w.x][w.y] = IHDOT
1486 # captain perishes on planet
1488 prout(_("You have just destroyed an inhabited planet."))
1489 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1491 elif iquad == IHSTAR: # Hit a star
1495 crmena(True, IHSTAR, "sector", w)
1496 prout(_(" unaffected by photon blast."))
1498 elif iquad == IHQUEST: # Hit a thingy
1499 if not (game.options & OPTION_THINGY) or withprob(0.3):
1501 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1503 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1505 proutn(_("Mr. Spock-"))
1506 prouts(_(" \"Fascinating!\""))
1511 # Stas Sergeev added the possibility that
1512 # you can shove the Thingy and piss it off.
1513 # It then becomes an enemy and may fire at you.
1519 elif iquad == IHBLANK: # Black hole
1521 crmena(True, IHBLANK, "sector", w)
1522 prout(_(" swallows torpedo."))
1524 elif iquad == IHWEB: # hit the web
1526 prout(_("***Torpedo absorbed by Tholian web."))
1528 elif iquad == IHT: # Hit a Tholian
1529 h1 = 700.0 + randrange(100) - \
1530 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1533 game.quad[w.x][w.y] = IHDOT
1538 crmena(True, IHT, "sector", w)
1540 prout(_(" survives photon blast."))
1542 prout(_(" disappears."))
1543 game.quad[w.x][w.y] = IHWEB
1550 proutn("Don't know how to handle torpedo collision with ")
1551 crmena(True, iquad, "sector", w)
1555 if curwnd!=message_window:
1556 setwnd(message_window)
1558 game.quad[w.x][w.y]=IHDOT
1559 game.quad[jw.x][jw.y]=iquad
1560 prout(_(" displaced by blast to Sector %s ") % jw)
1561 for ll in range(game.nenhere):
1562 game.kdist[ll] = game.kavgd[ll] = distance(game.sector,game.ks[ll])
1566 prout(_("Torpedo missed."))
1570 # critical-hit resolution
1571 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1573 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1574 proutn(_("***CRITICAL HIT--"))
1575 # Select devices and cause damage
1577 for loop1 in range(ncrit):
1580 # Cheat to prevent shuttle damage unless on ship
1581 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1584 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1585 game.damage[j] += extradm
1587 for (i, j) in enumerate(cdam):
1589 if skipcount % 3 == 2 and i < len(cdam)-1:
1594 prout(_(" damaged."))
1595 if damaged(DSHIELD) and game.shldup:
1596 prout(_("***Shields knocked down."))
1599 def attack(torps_ok):
1600 # bad guy attacks us
1601 # torps_ok == false forces use of phasers in an attack
1602 atackd = False; attempt = False; ihurt = False;
1603 hitmax=0.0; hittot=0.0; chgfac=1.0
1606 # game could be over at this point, check
1610 prout("=== ATTACK!")
1611 # Tholian gets to move before attacking
1614 # if you have just entered the RNZ, you'll get a warning
1615 if game.neutz: # The one chance not to be attacked
1618 # commanders get a chance to tac-move towards you
1619 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1621 # if no enemies remain after movement, we're done
1622 if game.nenhere==0 or (game.nenhere==1 and thing == game.quadrant and not iqengry):
1624 # set up partial hits if attack happens during shield status change
1625 pfac = 1.0/game.inshld
1627 chgfac = 0.25 + randreal(0.5)
1629 # message verbosity control
1630 if game.skill <= SKILL_FAIR:
1632 for loop in range(game.nenhere):
1633 if game.kpower[loop] < 0:
1634 continue; # too weak to attack
1635 # compute hit strength and diminish shield power
1637 # Increase chance of photon torpedos if docked or enemy energy low
1638 if game.condition == "docked":
1640 if game.kpower[loop] < 500:
1643 iquad = game.quad[jay.x][jay.y]
1644 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1646 # different enemies have different probabilities of throwing a torp
1647 usephasers = not torps_ok or \
1648 (iquad == IHK and r > 0.0005) or \
1649 (iquad==IHC and r > 0.015) or \
1650 (iquad==IHR and r > 0.3) or \
1651 (iquad==IHS and r > 0.07) or \
1652 (iquad==IHQUEST and r > 0.05)
1653 if usephasers: # Enemy uses phasers
1654 if game.condition == "docked":
1655 continue; # Don't waste the effort!
1656 attempt = True; # Attempt to attack
1657 dustfac = 0.8 + randreal(0.5)
1658 hit = game.kpower[loop]*math.pow(dustfac,game.kavgd[loop])
1659 game.kpower[loop] *= 0.75
1660 else: # Enemy uses photon torpedo
1661 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1663 proutn(_("***TORPEDO INCOMING"))
1664 if not damaged(DSRSENS):
1666 crmena(False, iquad, where, jay)
1669 r = (randreal()+randreal())*0.5 - 0.5
1670 r += 0.002*game.kpower[loop]*r
1671 hit = torpedo(course, r, jay, 1, 1)
1672 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1673 finish(FWON); # Klingons did themselves in!
1674 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1675 return; # Supernova or finished
1678 # incoming phaser or torpedo, shields may dissipate it
1679 if game.shldup or game.shldchg or game.condition=="docked":
1680 # shields will take hits
1681 propor = pfac * game.shield
1682 if game.condition =="docked":
1686 hitsh = propor*chgfac*hit+1.0
1688 if absorb > game.shield:
1689 absorb = game.shield
1690 game.shield -= absorb
1692 # taking a hit blasts us out of a starbase dock
1693 if game.condition == "docked":
1695 # but the shields may take care of it
1696 if propor > 0.1 and hit < 0.005*game.energy:
1698 # hit from this opponent got through shields, so take damage
1700 proutn(_("%d unit hit") % int(hit))
1701 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1702 proutn(_(" on the "))
1704 if not damaged(DSRSENS) and usephasers:
1706 crmena(False, iquad, where, jay)
1708 # Decide if hit is critical
1714 if game.energy <= 0:
1715 # Returning home upon your shield, not with it...
1718 if not attempt and game.condition == "docked":
1719 prout(_("***Enemies decide against attacking your ship."))
1722 percent = 100.0*pfac*game.shield+0.5
1724 # Shields fully protect ship
1725 proutn(_("Enemy attack reduces shield strength to "))
1727 # Print message if starship suffered hit(s)
1729 proutn(_("Energy left %2d shields ") % int(game.energy))
1732 elif not damaged(DSHIELD):
1735 proutn(_("damaged, "))
1736 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1737 # Check if anyone was hurt
1738 if hitmax >= 200 or hittot >= 500:
1739 icas = randrange(hittot * 0.015)
1742 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1743 prout(_(" in that last attack.\""))
1745 game.state.crew -= icas
1746 # After attack, reset average distance to enemies
1747 for loop in range(game.nenhere):
1748 game.kavgd[loop] = game.kdist[loop]
1752 def deadkl(w, type, mv):
1753 # kill a Klingon, Tholian, Romulan, or Thingy
1754 # Added mv to allow enemy to "move" before dying
1755 crmena(True, type, "sector", mv)
1756 # Decide what kind of enemy it is and update appropriately
1758 # chalk up a Romulan
1759 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1761 game.state.nromrem -= 1
1765 elif type == IHQUEST:
1771 # Some type of a Klingon
1772 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1775 game.comhere = False
1776 for i in range(game.state.remcom):
1777 if game.state.kcmdr[i] == game.quadrant:
1779 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1780 game.state.kcmdr[game.state.remcom].x = 0
1781 game.state.kcmdr[game.state.remcom].y = 0
1782 game.state.remcom -= 1
1784 if game.state.remcom != 0:
1785 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1787 game.state.remkl -= 1
1789 game.state.nscrem -= 1
1791 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1796 prout("*** Internal error, deadkl() called on %s\n" % type)
1797 # For each kind of enemy, finish message to player
1798 prout(_(" destroyed."))
1799 game.quad[w.x][w.y] = IHDOT
1800 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1803 # Remove enemy ship from arrays describing local conditions
1804 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1806 for i in range(game.nenhere):
1808 for j in range(i, game.nenhere):
1809 game.ks[j] = game.ks[j+1]
1810 game.kpower[j] = game.kpower[j+1]
1811 game.kavgd[j] = game.kdist[j] = game.kdist[j+1]
1812 game.ks[game.nenhere].x = 0
1813 game.ks[game.nenhere].y = 0
1814 game.kdist[game.nenhere] = 0
1815 game.kavgd[game.nenhere] = 0
1816 game.kpower[game.nenhere] = 0
1822 def targetcheck(x, y):
1823 # Return None if target is invalid
1824 if not VALID_SECTOR(x, y):
1827 deltx = 0.1*(y - game.sector.y)
1828 delty = 0.1*(x - game.sector.x)
1829 if deltx==0 and delty== 0:
1831 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1832 prout(_(" I recommend an immediate review of"))
1833 prout(_(" the Captain's psychological profile.\""))
1836 return 1.90985932*math.atan2(deltx, delty)
1839 # launch photon torpedo
1841 if damaged(DPHOTON):
1842 prout(_("Photon tubes damaged."))
1846 prout(_("No torpedoes left."))
1855 prout(_("%d torpedoes left.") % game.torps)
1856 proutn(_("Number of torpedoes to fire- "))
1858 else: # key == IHREAL {
1860 if n <= 0: # abort command
1865 prout(_("Maximum of 3 torpedoes per burst."))
1872 for i in range(1, n+1):
1874 if i==1 and key == IHEOL:
1875 break; # we will try prompting
1876 if i==2 and key == IHEOL:
1877 # direct all torpedoes at one target
1879 targ[i][1] = targ[1][1]
1880 targ[i][2] = targ[1][2]
1881 course[i] = course[1]
1893 course[i] = targetcheck(targ[i][1], targ[i][2])
1894 if course[i] == None:
1897 if i == 1 and key == IHEOL:
1898 # prompt for each one
1899 for i in range(1, n+1):
1900 proutn(_("Target sector for torpedo number %d- ") % i)
1905 targ[i][1] = int(aaitem-0.5)
1910 targ[i][2] = int(aaitem-0.5)
1912 course[i] = targetcheck(targ[i][1], targ[i][2])
1913 if course[i] == None:
1916 # Loop for moving <n> torpedoes
1918 if game.condition != "docked":
1920 r = (randreal()+randreal())*0.5 -0.5
1921 if math.fabs(r) >= 0.47:
1923 r *= randreal(1.2, 2.2)
1925 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1927 prouts(_("***TORPEDO MISFIRES."))
1930 prout(_(" Remainder of burst aborted."))
1932 prout(_("***Photon tubes damaged by misfire."))
1933 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1935 if game.shldup or game.condition == "docked":
1936 r *= 1.0 + 0.0001*game.shield
1937 torpedo(course[i], r, game.sector, i, n)
1938 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1940 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1944 # check for phasers overheating
1946 checkburn = (rpow-1500.0)*0.00038
1947 if withprob(checkburn):
1948 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1949 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1951 def checkshctrl(rpow):
1952 # check shield control
1955 prout(_("Shields lowered."))
1957 # Something bad has happened
1958 prouts(_("***RED ALERT! RED ALERT!"))
1960 hit = rpow*game.shield/game.inshld
1961 game.energy -= rpow+hit*0.8
1962 game.shield -= hit*0.2
1963 if game.energy <= 0.0:
1964 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1969 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1971 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1972 icas = randrange(hit*0.012)
1977 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1978 prout(_(" %d casualties so far.\"") % icas)
1980 game.state.crew -= icas
1982 prout(_("Phaser energy dispersed by shields."))
1983 prout(_("Enemy unaffected."))
1988 # register a phaser hit on Klingons and Romulans
1989 nenhr2 = game.nenhere; kk=0
1992 for (k, wham) in enumerate(hits):
1995 dustfac = randreal(0.9, 1.0)
1996 print type(wham), type(dustfac), type(game.kdist[kk]), "Foo!", game.kdist
1997 hit = wham*math.pow(dustfac,game.kdist[kk])
1999 kpini = game.kpower[kk]
2000 kp = math.fabs(kpini)
2001 if PHASEFAC*hit < kp:
2003 if game.kpower[kk] < 0:
2004 game.kpower[kk] -= -kp
2006 game.kpower[kk] -= kp
2007 kpow = game.kpower[kk]
2010 if not damaged(DSRSENS):
2012 proutn(_("%d unit hit on ") % int(hit))
2014 proutn(_("Very small hit on "))
2015 ienm = game.quad[w.x][w.y]
2019 crmena(False, ienm, "sector", w)
2023 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2027 kk -= 1 # don't do the increment
2029 else: # decide whether or not to emasculate klingon
2030 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2031 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2032 prout(_(" has just lost its firepower.\""))
2033 game.kpower[kk] = -kpow
2040 kz = 0; k = 1; irec=0 # Cheating inhibitor
2041 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2045 # SR sensors and Computer are needed fopr automode
2046 if damaged(DSRSENS) or damaged(DCOMPTR):
2048 if game.condition == "docked":
2049 prout(_("Phasers can't be fired through base shields."))
2052 if damaged(DPHASER):
2053 prout(_("Phaser control damaged."))
2057 if damaged(DSHCTRL):
2058 prout(_("High speed shield control damaged."))
2061 if game.energy <= 200.0:
2062 prout(_("Insufficient energy to activate high-speed shield control."))
2065 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2067 # Original code so convoluted, I re-did it all
2068 # (That was Tom Almy talking about the C code, I think -- ESR)
2069 while automode=="NOTSET":
2074 prout(_("There is no enemy present to select."))
2077 automode="AUTOMATIC"
2081 elif isit("automatic"):
2082 if (not itarg) and game.nenhere != 0:
2083 automode = "FORCEMAN"
2086 prout(_("Energy will be expended into space."))
2087 automode = "AUTOMATIC"
2096 prout(_("Energy will be expended into space."))
2097 automode = "AUTOMATIC"
2099 automode = "FORCEMAN"
2101 automode = "AUTOMATIC"
2105 prout(_("Energy will be expended into space."))
2106 automode = "AUTOMATIC"
2108 automode = "FORCEMAN"
2110 proutn(_("Manual or automatic? "))
2115 if automode == "AUTOMATIC":
2116 if key == IHALPHA and isit("no"):
2119 if key != IHREAL and game.nenhere != 0:
2120 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2125 for i in range(game.nenhere):
2126 irec += math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))*randreal(1.01, 1.06) + 1.0
2128 proutn(_("%d units required. ") % irec)
2130 proutn(_("Units to fire= "))
2136 proutn(_("Energy available= %.2f") % avail)
2139 if not rpow > avail:
2146 if key == IHALPHA and isit("no"):
2149 game.energy -= 200; # Go and do it!
2150 if checkshctrl(rpow):
2158 for i in range(game.nenhere):
2162 hits[i] = math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))
2163 over = randreal(1.01, 1.06) * hits[i]
2165 powrem -= hits[i] + over
2166 if powrem <= 0 and temp < hits[i]:
2175 if extra > 0 and not game.alldone:
2177 proutn(_("*** Tholian web absorbs "))
2179 proutn(_("excess "))
2180 prout(_("phaser energy."))
2182 prout(_("%d expended on empty space.") % int(extra))
2183 elif automode == "FORCEMAN":
2186 if damaged(DCOMPTR):
2187 prout(_("Battle computer damaged, manual fire only."))
2190 prouts(_("---WORKING---"))
2192 prout(_("Short-range-sensors-damaged"))
2193 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2194 prout(_("Manual-fire-must-be-used"))
2196 elif automode == "MANUAL":
2198 for k in range(game.nenhere):
2200 ienm = game.quad[aim.x][aim.y]
2202 proutn(_("Energy available= %.2f") % (avail-0.006))
2206 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2207 (ienm == IHC or ienm == IHS):
2209 prout(_(" can't be located without short range scan."))
2212 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2217 if itarg and k > kz:
2218 irec=(abs(game.kpower[k])/(PHASEFAC*math.pow(0.9,game.kdist[k]))) * randreal(1.01, 1.06) + 1.0
2221 if not damaged(DCOMPTR):
2226 proutn(_("units to fire at "))
2227 crmena(False, ienm, "sector", aim)
2230 if key == IHALPHA and isit("no"):
2238 if k==1: # Let me say I'm baffled by this
2247 # If total requested is too much, inform and start over
2249 prout(_("Available energy exceeded -- try again."))
2252 key = scan(); # scan for next value
2255 # zero energy -- abort
2258 if key == IHALPHA and isit("no"):
2263 game.energy -= 200.0
2264 if checkshctrl(rpow):
2268 # Say shield raised or malfunction, if necessary
2275 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2276 prouts(_(" CLICK CLICK POP . . ."))
2277 prout(_(" No response, sir!"))
2280 prout(_("Shields raised."))
2285 # Code from events,c begins here.
2287 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2288 # event of each type active at any given time. Mostly these means we can
2289 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2290 # BSD Trek, from which we swiped the idea, can have up to 5.
2292 def unschedule(evtype):
2293 # remove an event from the schedule
2294 game.future[evtype].date = FOREVER
2295 return game.future[evtype]
2297 def is_scheduled(evtype):
2298 # is an event of specified type scheduled
2299 return game.future[evtype].date != FOREVER
2301 def scheduled(evtype):
2302 # when will this event happen?
2303 return game.future[evtype].date
2305 def schedule(evtype, offset):
2306 # schedule an event of specified type
2307 game.future[evtype].date = game.state.date + offset
2308 return game.future[evtype]
2310 def postpone(evtype, offset):
2311 # postpone a scheduled event
2312 game.future[evtype].date += offset
2315 # rest period is interrupted by event
2318 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2320 game.resting = False
2326 # run through the event queue looking for things to do
2328 fintim = game.state.date + game.optime; yank=0
2329 ictbeam = False; istract = False
2330 w = coord(); hold = coord()
2331 ev = event(); ev2 = event()
2333 def tractorbeam(yank):
2334 # tractor beaming cases merge here
2336 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2340 prout(_(" caught in long range tractor beam--"))
2341 # If Kirk & Co. screwing around on planet, handle
2342 atover(True) # atover(true) is Grab
2345 if game.icraft: # Caught in Galileo?
2348 # Check to see if shuttle is aboard
2349 if game.iscraft == "offship":
2352 prout(_("Galileo, left on the planet surface, is captured"))
2353 prout(_("by aliens and made into a flying McDonald's."))
2354 game.damage[DSHUTTL] = -10
2355 game.iscraft = "removed"
2357 prout(_("Galileo, left on the planet surface, is well hidden."))
2359 game.quadrant = game.state.kscmdr
2361 game.quadrant = game.state.kcmdr[i]
2362 game.sector = randplace(QUADSIZE)
2364 prout(_(" is pulled to Quadrant %s, Sector %s") \
2365 % (game.quadrant, game.sector))
2367 prout(_("(Remainder of rest/repair period cancelled.)"))
2368 game.resting = False
2370 if not damaged(DSHIELD) and game.shield > 0:
2371 doshield(shraise=True) # raise shields
2372 game.shldchg = False
2374 prout(_("(Shields not currently useable.)"))
2376 # Adjust finish time to time of tractor beaming
2377 fintim = game.state.date+game.optime
2379 if game.state.remcom <= 0:
2382 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2385 # Code merges here for any commander destroying base
2386 # Not perfect, but will have to do
2387 # Handle case where base is in same quadrant as starship
2388 if game.battle == game.quadrant:
2389 game.state.chart[game.battle.x][game.battle.y].starbase = False
2390 game.quad[game.base.x][game.base.y] = IHDOT
2391 game.base.x=game.base.y=0
2394 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2395 elif game.state.rembase != 1 and communicating():
2396 # Get word via subspace radio
2399 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2400 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2402 prout(_("the Klingon Super-Commander"))
2404 prout(_("a Klingon Commander"))
2405 game.state.chart[game.battle.x][game.battle.y].starbase = False
2406 # Remove Starbase from galaxy
2407 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2408 for i in range(1, game.state.rembase+1):
2409 if game.state.baseq[i] == game.battle:
2410 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2411 game.state.rembase -= 1
2413 # reinstate a commander's base attack
2417 invalidate(game.battle)
2420 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2421 for i in range(1, NEVENTS):
2422 if i == FSNOVA: proutn("=== Supernova ")
2423 elif i == FTBEAM: proutn("=== T Beam ")
2424 elif i == FSNAP: proutn("=== Snapshot ")
2425 elif i == FBATTAK: proutn("=== Base Attack ")
2426 elif i == FCDBAS: proutn("=== Base Destroy ")
2427 elif i == FSCMOVE: proutn("=== SC Move ")
2428 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2429 elif i == FDSPROB: proutn("=== Probe Move ")
2430 elif i == FDISTR: proutn("=== Distress Call ")
2431 elif i == FENSLV: proutn("=== Enslavement ")
2432 elif i == FREPRO: proutn("=== Klingon Build ")
2434 prout("%.2f" % (scheduled(i)))
2437 radio_was_broken = damaged(DRADIO)
2440 # Select earliest extraneous event, evcode==0 if no events
2445 for l in range(1, NEVENTS):
2446 if game.future[l].date < datemin:
2449 prout("== Event %d fires" % evcode)
2450 datemin = game.future[l].date
2451 xtime = datemin-game.state.date
2452 game.state.date = datemin
2453 # Decrement Federation resources and recompute remaining time
2454 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2456 if game.state.remtime <=0:
2459 # Any crew left alive?
2460 if game.state.crew <=0:
2463 # Is life support adequate?
2464 if damaged(DLIFSUP) and game.condition != "docked":
2465 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2468 game.lsupres -= xtime
2469 if game.damage[DLIFSUP] <= xtime:
2470 game.lsupres = game.inlsr
2473 if game.condition == "docked":
2474 repair /= game.docfac
2475 # Don't fix Deathray here
2476 for l in range(NDEVICES):
2477 if game.damage[l] > 0.0 and l != DDRAY:
2478 if game.damage[l]-repair > 0.0:
2479 game.damage[l] -= repair
2481 game.damage[l] = 0.0
2482 # If radio repaired, update star chart and attack reports
2483 if radio_was_broken and not damaged(DRADIO):
2484 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2485 prout(_(" surveillance reports are coming in."))
2487 if not game.iseenit:
2491 prout(_(" The star chart is now up to date.\""))
2493 # Cause extraneous event EVCODE to occur
2494 game.optime -= xtime
2495 if evcode == FSNOVA: # Supernova
2498 schedule(FSNOVA, expran(0.5*game.intime))
2499 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2501 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2502 if game.state.nscrem == 0 or \
2503 ictbeam or istract or \
2504 game.condition=="docked" or game.isatb==1 or game.iscate:
2506 if game.ientesc or \
2507 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2508 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2509 (damaged(DSHIELD) and \
2510 (game.energy < 2500 or damaged(DPHASER)) and \
2511 (game.torps < 5 or damaged(DPHOTON))):
2513 istract = ictbeam = True
2514 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2517 elif evcode == FTBEAM: # Tractor beam
2518 if game.state.remcom == 0:
2521 i = randrange(game.state.remcom)
2522 yank = distance(game.state.kcmdr[i], game.quadrant)
2523 if istract or game.condition == "docked" or yank == 0:
2524 # Drats! Have to reschedule
2526 game.optime + expran(1.5*game.intime/game.state.remcom))
2530 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2531 game.snapsht = copy.deepcopy(game.state)
2532 game.state.snap = True
2533 schedule(FSNAP, expran(0.5 * game.intime))
2534 elif evcode == FBATTAK: # Commander attacks starbase
2535 if game.state.remcom==0 or game.state.rembase==0:
2541 for j in range(game.state.rembase):
2542 for k in range(game.state.remcom):
2543 if game.state.baseq[j] == game.state.kcmdr[k] and \
2544 not game.state.baseq[j] == game.quadrant and \
2545 not game.state.baseq[j] == game.state.kscmdr:
2549 if j>game.state.rembase:
2550 # no match found -- try later
2551 schedule(FBATTAK, expran(0.3*game.intime))
2554 # commander + starbase combination found -- launch attack
2555 game.battle = game.state.baseq[j]
2556 schedule(FCDBAS, randreal(1.0, 4.0))
2557 if game.isatb: # extra time if SC already attacking
2558 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2559 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2560 game.iseenit = False
2561 if not communicating():
2562 continue # No warning :-(
2566 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2567 prout(_(" reports that it is under attack and that it can"))
2568 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2571 elif evcode == FSCDBAS: # Supercommander destroys base
2574 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2575 continue # WAS RETURN!
2577 game.battle = game.state.kscmdr
2579 elif evcode == FCDBAS: # Commander succeeds in destroying base
2582 # find the lucky pair
2583 for i in range(game.state.remcom):
2584 if game.state.kcmdr[i] == game.battle:
2586 if i > game.state.remcom or game.state.rembase == 0 or \
2587 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2588 # No action to take after all
2589 invalidate(game.battle)
2592 elif evcode == FSCMOVE: # Supercommander moves
2593 schedule(FSCMOVE, 0.2777)
2594 if not game.ientesc and not istract and game.isatb != 1 and \
2595 (not game.iscate or not game.justin):
2597 elif evcode == FDSPROB: # Move deep space probe
2598 schedule(FDSPROB, 0.01)
2599 game.probex += game.probeinx
2600 game.probey += game.probeiny
2601 i = (int)(game.probex/QUADSIZE +0.05)
2602 j = (int)(game.probey/QUADSIZE + 0.05)
2603 if game.probec.x != i or game.probec.y != j:
2606 if not VALID_QUADRANT(i, j) or \
2607 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2608 # Left galaxy or ran into supernova
2612 proutn(_("Lt. Uhura- \"The deep space probe "))
2613 if not VALID_QUADRANT(j, i):
2614 proutn(_("has left the galaxy"))
2616 proutn(_("is no longer transmitting"))
2620 if not communicating():
2623 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2624 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2625 # Update star chart if Radio is working or have access to radio
2627 chp = game.state.chart[game.probec.x][game.probec.y]
2628 chp.klingons = pdest.klingons
2629 chp.starbase = pdest.starbase
2630 chp.stars = pdest.stars
2631 pdest.charted = True
2632 game.proben -= 1 # One less to travel
2633 if game.proben == 0 and game.isarmed and pdest.stars:
2634 # lets blow the sucker!
2635 supernova(True, game.probec)
2637 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2639 elif evcode == FDISTR: # inhabited system issues distress call
2641 # try a whole bunch of times to find something suitable
2642 for i in range(100):
2643 # need a quadrant which is not the current one,
2644 # which has some stars which are inhabited and
2645 # not already under attack, which is not
2646 # supernova'ed, and which has some Klingons in it
2647 w = randplace(GALSIZE)
2648 q = game.state.galaxy[w.x][w.y]
2649 if not (game.quadrant == w or q.planet == None or \
2650 not q.planet.inhabited or \
2651 q.supernova or q.status!="secure" or q.klingons<=0):
2654 # can't seem to find one; ignore this call
2656 prout("=== Couldn't find location for distress event.")
2658 # got one!! Schedule its enslavement
2659 ev = schedule(FENSLV, expran(game.intime))
2661 q.status = distressed
2663 # tell the captain about it if we can
2665 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2667 prout(_("by a Klingon invasion fleet."))
2670 elif evcode == FENSLV: # starsystem is enslaved
2671 ev = unschedule(FENSLV)
2672 # see if current distress call still active
2673 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2677 q.status = "enslaved"
2679 # play stork and schedule the first baby
2680 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2681 ev2.quadrant = ev.quadrant
2683 # report the disaster if we can
2685 prout(_("Uhura- We've lost contact with starsystem %s") % \
2687 prout(_("in Quadrant %s.\n") % ev.quadrant)
2688 elif evcode == FREPRO: # Klingon reproduces
2689 # If we ever switch to a real event queue, we'll need to
2690 # explicitly retrieve and restore the x and y.
2691 ev = schedule(FREPRO, expran(1.0 * game.intime))
2692 # see if current distress call still active
2693 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2697 if game.state.remkl >=MAXKLGAME:
2698 continue # full right now
2699 # reproduce one Klingon
2701 if game.klhere >= MAXKLQUAD:
2703 # this quadrant not ok, pick an adjacent one
2704 for i in range(w.x - 1, w.x + 2):
2705 for j in range(w.y - 1, w.y + 2):
2706 if not VALID_QUADRANT(i, j):
2708 q = game.state.galaxy[w.x][w.y]
2709 # check for this quad ok (not full & no snova)
2710 if q.klingons >= MAXKLQUAD or q.supernova:
2714 continue # search for eligible quadrant failed
2719 game.state.remkl += 1
2721 if game.quadrant == w:
2723 newkling(game.klhere)
2724 # recompute time left
2726 # report the disaster if we can
2728 if game.quadrant == w:
2729 prout(_("Spock- sensors indicate the Klingons have"))
2730 prout(_("launched a warship from %s.") % q.planet)
2732 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2733 if q.planet != None:
2734 proutn(_("near %s") % q.planet)
2735 prout(_("in Quadrant %s.") % w)
2744 proutn(_("How long? "))
2749 origTime = delay = aaitem
2752 if delay >= game.state.remtime or game.nenhere != 0:
2753 proutn(_("Are you sure? "))
2756 # Alternate resting periods (events) with attacks
2760 game.resting = False
2761 if not game.resting:
2762 prout(_("%d stardates left.") % int(game.state.remtime))
2764 temp = game.optime = delay
2766 rtime = randreal(1.0, 2.0)
2770 if game.optime < delay:
2779 # Repair Deathray if long rest at starbase
2780 if origTime-delay >= 9.99 and game.condition == "docked":
2781 game.damage[DDRAY] = 0.0
2782 # leave if quadrant supernovas
2783 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2785 game.resting = False
2788 # A nova occurs. It is the result of having a star hit with a
2789 # photon torpedo, or possibly of a probe warhead going off.
2790 # Stars that go nova cause stars which surround them to undergo
2791 # the same probabilistic process. Klingons next to them are
2792 # destroyed. And if the starship is next to it, it gets zapped.
2793 # If the zap is too much, it gets destroyed.
2797 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2798 newc = coord(); scratch = coord()
2800 # Wow! We've supernova'ed
2801 supernova(False, nov)
2803 # handle initial nova
2804 game.quad[nov.x][nov.y] = IHDOT
2805 crmena(False, IHSTAR, "sector", nov)
2807 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2808 game.state.starkl += 1
2810 # Set up stack to recursively trigger adjacent stars
2811 bot = top = top2 = 1
2817 for mm in range(bot, top+1):
2818 for nn in range(1, 3+1): # nn,j represents coordinates around current
2819 for j in range(1, 3+1):
2822 scratch.x = hits[mm][1]+nn-2
2823 scratch.y = hits[mm][2]+j-2
2824 if not VALID_SECTOR(scratch.y, scratch.x):
2826 iquad = game.quad[scratch.x][scratch.y]
2827 # Empty space ends reaction
2828 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2830 elif iquad == IHSTAR: # Affect another star
2832 # This star supernovas
2833 scratch = supernova(False)
2836 hits[top2][1]=scratch.x
2837 hits[top2][2]=scratch.y
2838 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2839 game.state.starkl += 1
2840 crmena(True, IHSTAR, "sector", scratch)
2842 game.quad[scratch.x][scratch.y] = IHDOT
2843 elif iquad == IHP: # Destroy planet
2844 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2845 game.state.nplankl += 1
2846 crmena(True, IHP, "sector", scratch)
2847 prout(_(" destroyed."))
2848 game.iplnet.pclass = "destroyed"
2850 invalidate(game.plnet)
2854 game.quad[scratch.x][scratch.y] = IHDOT
2855 elif iquad == IHB: # Destroy base
2856 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2857 for i in range(game.state.rembase):
2858 if game.state.baseq[i] == game.quadrant:
2860 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2861 game.state.rembase -= 1
2862 invalidate(game.base)
2863 game.state.basekl += 1
2865 crmena(True, IHB, "sector", scratch)
2866 prout(_(" destroyed."))
2867 game.quad[scratch.x][scratch.y] = IHDOT
2868 elif iquad in (IHE, IHF): # Buffet ship
2869 prout(_("***Starship buffeted by nova."))
2871 if game.shield >= 2000.0:
2872 game.shield -= 2000.0
2874 diff = 2000.0 - game.shield
2878 prout(_("***Shields knocked out."))
2879 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2881 game.energy -= 2000.0
2882 if game.energy <= 0:
2885 # add in course nova contributes to kicking starship
2886 icx += game.sector.x-hits[mm][1]
2887 icy += game.sector.y-hits[mm][2]
2889 elif iquad == IHK: # kill klingon
2890 deadkl(scratch,iquad, scratch)
2891 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2892 for ll in range(game.nenhere):
2893 if game.ks[ll] == scratch:
2895 game.kpower[ll] -= 800.0 # If firepower is lost, die
2896 if game.kpower[ll] <= 0.0:
2897 deadkl(scratch, iquad, scratch)
2899 newc.x = scratch.x + scratch.x - hits[mm][1]
2900 newc.y = scratch.y + scratch.y - hits[mm][2]
2901 crmena(True, iquad, "sector", scratch)
2902 proutn(_(" damaged"))
2903 if not VALID_SECTOR(newc.x, newc.y):
2904 # can't leave quadrant
2907 iquad1 = game.quad[newc.x][newc.y]
2908 if iquad1 == IHBLANK:
2909 proutn(_(", blasted into "))
2910 crmena(False, IHBLANK, "sector", newc)
2912 deadkl(scratch, iquad, newc)
2915 # can't move into something else
2918 proutn(_(", buffeted to Sector %s") % newc)
2919 game.quad[scratch.x][scratch.y] = IHDOT
2920 game.quad[newc.x][newc.y] = iquad
2922 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc)
2931 # Starship affected by nova -- kick it away.
2932 game.dist = kount*0.1
2935 game.direc = course[3*(icx+1)+icy+2]
2936 if game.direc == 0.0:
2938 if game.dist == 0.0:
2940 game.optime = 10.0*game.dist/16.0
2942 prout(_("Force of nova displaces starship."))
2943 imove(novapush=True)
2944 game.optime = 10.0*game.dist/16.0
2947 def supernova(induced, w=None):
2948 # star goes supernova
2955 # Scheduled supernova -- select star
2956 # logic changed here so that we won't favor quadrants in top
2958 for nq.x in range(GALSIZE):
2959 for nq.y in range(GALSIZE):
2960 stars += game.state.galaxy[nq.x][nq.y].stars
2962 return # nothing to supernova exists
2963 num = randrange(stars) + 1
2964 for nq.x in range(GALSIZE):
2965 for nq.y in range(GALSIZE):
2966 num -= game.state.galaxy[nq.x][nq.y].stars
2972 proutn("=== Super nova here?")
2975 if not nq == game.quadrant or game.justin:
2976 # it isn't here, or we just entered (treat as enroute)
2979 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2980 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2983 # we are in the quadrant!
2984 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2985 for ns.x in range(QUADSIZE):
2986 for ns.y in range(QUADSIZE):
2987 if game.quad[ns.x][ns.y]==IHSTAR:
2994 prouts(_("***RED ALERT! RED ALERT!"))
2996 prout(_("***Incipient supernova detected at Sector %s") % ns)
2997 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2998 proutn(_("Emergency override attempts t"))
2999 prouts("***************")
3004 # destroy any Klingons in supernovaed quadrant
3005 kldead = game.state.galaxy[nq.x][nq.y].klingons
3006 game.state.galaxy[nq.x][nq.y].klingons = 0
3007 if nq == game.state.kscmdr:
3008 # did in the Supercommander!
3009 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
3013 if game.state.remcom:
3014 maxloop = game.state.remcom
3015 for l in range(maxloop):
3016 if game.state.kcmdr[l] == nq:
3017 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
3018 invalidate(game.state.kcmdr[game.state.remcom])
3019 game.state.remcom -= 1
3021 if game.state.remcom==0:
3024 game.state.remkl -= kldead
3025 # destroy Romulans and planets in supernovaed quadrant
3026 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
3027 game.state.galaxy[nq.x][nq.y].romulans = 0
3028 game.state.nromrem -= nrmdead
3030 for loop in range(game.inplan):
3031 if game.state.planets[loop].w == nq:
3032 game.state.planets[loop].pclass = "destroyed"
3034 # Destroy any base in supernovaed quadrant
3035 if game.state.rembase:
3036 maxloop = game.state.rembase
3037 for loop in range(maxloop):
3038 if game.state.baseq[loop] == nq:
3039 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3040 invalidate(game.state.baseq[game.state.rembase])
3041 game.state.rembase -= 1
3043 # If starship caused supernova, tally up destruction
3045 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3046 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3047 game.state.nplankl += npdead
3048 # mark supernova in galaxy and in star chart
3049 if game.quadrant == nq or communicating():
3050 game.state.galaxy[nq.x][nq.y].supernova = True
3051 # If supernova destroys last Klingons give special message
3052 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3055 prout(_("Lucky you!"))
3056 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3059 # if some Klingons remain, continue or die in supernova
3064 # Code from finish.c ends here.
3067 # self-destruct maneuver
3068 # Finish with a BANG!
3070 if damaged(DCOMPTR):
3071 prout(_("Computer damaged; cannot execute destruct sequence."))
3073 prouts(_("---WORKING---")); skip(1)
3074 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3075 prouts(" 10"); skip(1)
3076 prouts(" 9"); skip(1)
3077 prouts(" 8"); skip(1)
3078 prouts(" 7"); skip(1)
3079 prouts(" 6"); skip(1)
3081 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3083 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3085 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3089 if game.passwd != citem:
3090 prouts(_("PASSWORD-REJECTED;"))
3092 prouts(_("CONTINUITY-EFFECTED"))
3095 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3096 prouts(" 5"); skip(1)
3097 prouts(" 4"); skip(1)
3098 prouts(" 3"); skip(1)
3099 prouts(" 2"); skip(1)
3100 prouts(" 1"); skip(1)
3102 prouts(_("GOODBYE-CRUEL-WORLD"))
3110 prouts(_("********* Entropy of "))
3112 prouts(_(" maximized *********"))
3116 if game.nenhere != 0:
3117 whammo = 25.0 * game.energy
3119 while l <= game.nenhere:
3120 if game.kpower[l]*game.kdist[l] <= whammo:
3121 deadkl(game.ks[l], game.quad[game.ks[l].x][game.ks[l].y], game.ks[l])
3126 "Compute our rate of kils over time."
3127 elapsed = game.state.date - game.indate
3128 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3131 starting = (game.inkling + game.incom + game.inscom)
3132 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3133 return (starting - remaining)/elapsed
3137 badpt = 5.0*game.state.starkl + \
3139 10.0*game.state.nplankl + \
3140 300*game.state.nworldkl + \
3142 100.0*game.state.basekl +\
3144 if game.ship == IHF:
3146 elif game.ship == None:
3151 # end the game, with appropriate notfications
3155 prout(_("It is stardate %.1f.") % game.state.date)
3157 if ifin == FWON: # Game has been won
3158 if game.state.nromrem != 0:
3159 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3162 prout(_("You have smashed the Klingon invasion fleet and saved"))
3163 prout(_("the Federation."))
3168 badpt = 0.0 # Close enough!
3169 # killsPerDate >= RateMax
3170 if game.state.date-game.indate < 5.0 or \
3171 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3173 prout(_("In fact, you have done so well that Starfleet Command"))
3174 if game.skill == SKILL_NOVICE:
3175 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3176 elif game.skill == SKILL_FAIR:
3177 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3178 elif game.skill == SKILL_GOOD:
3179 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3180 elif game.skill == SKILL_EXPERT:
3181 prout(_("promotes you to Commodore Emeritus."))
3183 prout(_("Now that you think you're really good, try playing"))
3184 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3185 elif game.skill == SKILL_EMERITUS:
3187 proutn(_("Computer- "))
3188 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3190 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3192 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3194 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3196 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3198 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3200 prout(_("Now you can retire and write your own Star Trek game!"))
3202 elif game.skill >= SKILL_EXPERT:
3203 if game.thawed and not idebug:
3204 prout(_("You cannot get a citation, so..."))
3206 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3210 # Only grant long life if alive (original didn't!)
3212 prout(_("LIVE LONG AND PROSPER."))
3217 elif ifin == FDEPLETE: # Federation Resources Depleted
3218 prout(_("Your time has run out and the Federation has been"))
3219 prout(_("conquered. Your starship is now Klingon property,"))
3220 prout(_("and you are put on trial as a war criminal. On the"))
3221 proutn(_("basis of your record, you are "))
3222 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3223 prout(_("acquitted."))
3225 prout(_("LIVE LONG AND PROSPER."))
3227 prout(_("found guilty and"))
3228 prout(_("sentenced to death by slow torture."))
3232 elif ifin == FLIFESUP:
3233 prout(_("Your life support reserves have run out, and"))
3234 prout(_("you die of thirst, starvation, and asphyxiation."))
3235 prout(_("Your starship is a derelict in space."))
3237 prout(_("Your energy supply is exhausted."))
3239 prout(_("Your starship is a derelict in space."))
3240 elif ifin == FBATTLE:
3243 prout(_("has been destroyed in battle."))
3245 prout(_("Dulce et decorum est pro patria mori."))
3247 prout(_("You have made three attempts to cross the negative energy"))
3248 prout(_("barrier which surrounds the galaxy."))
3250 prout(_("Your navigation is abominable."))
3253 prout(_("Your starship has been destroyed by a nova."))
3254 prout(_("That was a great shot."))
3256 elif ifin == FSNOVAED:
3259 prout(_(" has been fried by a supernova."))
3260 prout(_("...Not even cinders remain..."))
3261 elif ifin == FABANDN:
3262 prout(_("You have been captured by the Klingons. If you still"))
3263 prout(_("had a starbase to be returned to, you would have been"))
3264 prout(_("repatriated and given another chance. Since you have"))
3265 prout(_("no starbases, you will be mercilessly tortured to death."))
3266 elif ifin == FDILITHIUM:
3267 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3268 elif ifin == FMATERIALIZE:
3269 prout(_("Starbase was unable to re-materialize your starship."))
3270 prout(_("Sic transit gloria mundi"))
3271 elif ifin == FPHASER:
3274 prout(_(" has been cremated by its own phasers."))
3276 prout(_("You and your landing party have been"))
3277 prout(_("converted to energy, disipating through space."))
3278 elif ifin == FMINING:
3279 prout(_("You are left with your landing party on"))
3280 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3282 prout(_("They are very fond of \"Captain Kirk\" soup."))
3284 proutn(_("Without your leadership, the "))
3286 prout(_(" is destroyed."))
3287 elif ifin == FDPLANET:
3288 prout(_("You and your mining party perish."))
3290 prout(_("That was a great shot."))
3293 prout(_("The Galileo is instantly annihilated by the supernova."))
3294 prout(_("You and your mining party are atomized."))
3296 proutn(_("Mr. Spock takes command of the "))
3299 prout(_("joins the Romulans, reigning terror on the Federation."))
3300 elif ifin == FPNOVA:
3301 prout(_("You and your mining party are atomized."))
3303 proutn(_("Mr. Spock takes command of the "))
3306 prout(_("joins the Romulans, reigning terror on the Federation."))
3307 elif ifin == FSTRACTOR:
3308 prout(_("The shuttle craft Galileo is also caught,"))
3309 prout(_("and breaks up under the strain."))
3311 prout(_("Your debris is scattered for millions of miles."))
3312 proutn(_("Without your leadership, the "))
3314 prout(_(" is destroyed."))
3316 prout(_("The mutants attack and kill Spock."))
3317 prout(_("Your ship is captured by Klingons, and"))
3318 prout(_("your crew is put on display in a Klingon zoo."))
3319 elif ifin == FTRIBBLE:
3320 prout(_("Tribbles consume all remaining water,"))
3321 prout(_("food, and oxygen on your ship."))
3323 prout(_("You die of thirst, starvation, and asphyxiation."))
3324 prout(_("Your starship is a derelict in space."))
3326 prout(_("Your ship is drawn to the center of the black hole."))
3327 prout(_("You are crushed into extremely dense matter."))
3329 prout(_("Your last crew member has died."))
3330 if game.ship == IHF:
3332 elif game.ship == IHE:
3335 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3336 goodies = game.state.remres/game.inresor
3337 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3338 if goodies/baddies >= randreal(1.0, 1.5):
3339 prout(_("As a result of your actions, a treaty with the Klingon"))
3340 prout(_("Empire has been signed. The terms of the treaty are"))
3341 if goodies/baddies >= randreal(3.0):
3342 prout(_("favorable to the Federation."))
3344 prout(_("Congratulations!"))
3346 prout(_("highly unfavorable to the Federation."))
3348 prout(_("The Federation will be destroyed."))
3350 prout(_("Since you took the last Klingon with you, you are a"))
3351 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3352 prout(_("statue in your memory. Rest in peace, and try not"))
3353 prout(_("to think about pigeons."))
3358 # compute player's score
3359 timused = game.state.date - game.indate
3361 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3363 perdate = killrate()
3364 ithperd = 500*perdate + 0.5
3367 iwon = 100*game.skill
3368 if game.ship == IHE:
3370 elif game.ship == IHF:
3374 if not game.gamewon:
3375 game.state.nromrem = 0 # None captured if no win
3376 iscore = 10*(game.inkling - game.state.remkl) \
3377 + 50*(game.incom - game.state.remcom) \
3379 + 20*(game.inrom - game.state.nromrem) \
3380 + 200*(game.inscom - game.state.nscrem) \
3381 - game.state.nromrem \
3386 prout(_("Your score --"))
3387 if game.inrom - game.state.nromrem:
3388 prout(_("%6d Romulans destroyed %5d") %
3389 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3390 if game.state.nromrem:
3391 prout(_("%6d Romulans captured %5d") %
3392 (game.state.nromrem, game.state.nromrem))
3393 if game.inkling - game.state.remkl:
3394 prout(_("%6d ordinary Klingons destroyed %5d") %
3395 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3396 if game.incom - game.state.remcom:
3397 prout(_("%6d Klingon commanders destroyed %5d") %
3398 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3399 if game.inscom - game.state.nscrem:
3400 prout(_("%6d Super-Commander destroyed %5d") %
3401 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3403 prout(_("%6.2f Klingons per stardate %5d") %
3405 if game.state.starkl:
3406 prout(_("%6d stars destroyed by your action %5d") %
3407 (game.state.starkl, -5*game.state.starkl))
3408 if game.state.nplankl:
3409 prout(_("%6d planets destroyed by your action %5d") %
3410 (game.state.nplankl, -10*game.state.nplankl))
3411 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3412 prout(_("%6d inhabited planets destroyed by your action %5d") %
3413 (game.state.nplankl, -300*game.state.nworldkl))
3414 if game.state.basekl:
3415 prout(_("%6d bases destroyed by your action %5d") %
3416 (game.state.basekl, -100*game.state.basekl))
3418 prout(_("%6d calls for help from starbase %5d") %
3419 (game.nhelp, -45*game.nhelp))
3421 prout(_("%6d casualties incurred %5d") %
3422 (game.casual, -game.casual))
3424 prout(_("%6d crew abandoned in space %5d") %
3425 (game.abandoned, -3*game.abandoned))
3427 prout(_("%6d ship(s) lost or destroyed %5d") %
3428 (klship, -100*klship))
3430 prout(_("Penalty for getting yourself killed -200"))
3432 proutn(_("Bonus for winning "))
3433 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3434 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3435 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3436 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3437 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3438 prout(" %5d" % iwon)
3440 prout(_("TOTAL SCORE %5d") % iscore)
3443 # emit winner's commemmorative plaque
3446 proutn(_("File or device name for your plaque: "))
3449 fp = open(winner, "w")
3452 prout(_("Invalid name."))
3454 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3456 # The 38 below must be 64 for 132-column paper
3457 nskip = 38 - len(winner)/2
3458 fp.write("\n\n\n\n")
3459 # --------DRAW ENTERPRISE PICTURE.
3460 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3461 fp.write(" EEE E : : : E\n" )
3462 fp.write(" EE EEE E : : NCC-1701 : E\n")
3463 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3464 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3465 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3466 fp.write(" EEEEEEE EEEEE E E E E\n")
3467 fp.write(" EEE E E E E\n")
3468 fp.write(" E E E E\n")
3469 fp.write(" EEEEEEEEEEEEE E E\n")
3470 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3471 fp.write(" :E : EEEE E\n")
3472 fp.write(" .-E -:----- E\n")
3473 fp.write(" :E : E\n")
3474 fp.write(" EE : EEEEEEEE\n")
3475 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3477 fp.write(_(" U. S. S. ENTERPRISE\n"))
3478 fp.write("\n\n\n\n")
3479 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3481 fp.write(_(" Starfleet Command bestows to you\n"))
3483 fp.write("%*s%s\n\n" % (nskip, "", winner))
3484 fp.write(_(" the rank of\n\n"))
3485 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3487 if game.skill == SKILL_EXPERT:
3488 fp.write(_(" Expert level\n\n"))
3489 elif game.skill == SKILL_EMERITUS:
3490 fp.write(_("Emeritus level\n\n"))
3492 fp.write(_(" Cheat level\n\n"))
3493 timestring = ctime()
3494 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3495 (timestring+4, timestring+20, timestring+11))
3496 fp.write(_(" Your score: %d\n\n") % iscore)
3497 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3500 # Code from io.c begins here
3502 rows = linecount = 0 # for paging
3505 fullscreen_window = None
3506 srscan_window = None
3507 report_window = None
3508 status_window = None
3509 lrscan_window = None
3510 message_window = None
3511 prompt_window = None
3515 "wrap up, either normally or due to signal"
3516 if game.options & OPTION_CURSES:
3523 sys.stdout.write('\n')
3529 #setlocale(LC_ALL, "")
3530 #bindtextdomain(PACKAGE, LOCALEDIR)
3531 #textdomain(PACKAGE)
3532 if atexit.register(outro):
3533 sys.stderr.write("Unable to register outro(), exiting...\n")
3535 if not (game.options & OPTION_CURSES):
3536 ln_env = os.getenv("LINES")
3542 stdscr = curses.initscr()
3547 curses.start_color()
3548 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3549 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3550 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3551 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3552 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3553 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3554 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3555 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3557 global fullscreen_window, srscan_window, report_window, status_window
3558 global lrscan_window, message_window, prompt_window
3559 fullscreen_window = stdscr
3560 srscan_window = curses.newwin(12, 25, 0, 0)
3561 report_window = curses.newwin(11, 0, 1, 25)
3562 status_window = curses.newwin(10, 0, 1, 39)
3563 lrscan_window = curses.newwin(5, 0, 0, 64)
3564 message_window = curses.newwin(0, 0, 12, 0)
3565 prompt_window = curses.newwin(1, 0, rows-2, 0)
3566 message_window.scrollok(True)
3567 setwnd(fullscreen_window)
3571 "wait for user action -- OK to do nothing if on a TTY"
3572 if game.options & OPTION_CURSES:
3577 if game.skill > SKILL_FAIR:
3578 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3580 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3584 if game.skill > SKILL_FAIR:
3585 prompt = _("[CONTINUE?]")
3587 prompt = _("[PRESS ENTER TO CONTINUE]")
3589 if game.options & OPTION_CURSES:
3591 setwnd(prompt_window)
3592 prompt_window.wclear()
3593 prompt_window.addstr(prompt)
3594 prompt_window.getstr()
3595 prompt_window.clear()
3596 prompt_window.refresh()
3597 setwnd(message_window)
3600 sys.stdout.write('\n')
3603 for j in range(rows):
3604 sys.stdout.write('\n')
3608 "Skip i lines. Pause game if this would cause a scrolling event."
3609 for dummy in range(i):
3610 if game.options & OPTION_CURSES:
3611 (y, x) = curwnd.getyx()
3612 (my, mx) = curwnd.getmaxyx()
3613 if curwnd == message_window and y >= my - 3:
3621 if rows and linecount >= rows:
3624 sys.stdout.write('\n')
3627 "Utter a line with no following line feed."
3628 if game.options & OPTION_CURSES:
3632 sys.stdout.write(line)
3642 if not replayfp or replayfp.closed: # Don't slow down replays
3645 if game.options & OPTION_CURSES:
3649 if not replayfp or replayfp.closed:
3653 "Get a line of input."
3654 if game.options & OPTION_CURSES:
3655 line = curwnd.getstr() + "\n"
3658 if replayfp and not replayfp.closed:
3660 line = replayfp.readline()
3663 prout("*** Replay finished")
3666 elif line[0] != "#":
3671 logfp.write(line + "\n")
3675 "Change windows -- OK for this to be a no-op in tty mode."
3677 if game.options & OPTION_CURSES:
3679 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3682 "Clear to end of line -- can be a no-op in tty mode"
3683 if game.options & OPTION_CURSES:
3688 "Clear screen -- can be a no-op in tty mode."
3690 if game.options & OPTION_CURSES:
3696 def textcolor(color):
3697 "Set the current text color"
3698 if game.options & OPTION_CURSES:
3699 if color == DEFAULT:
3701 elif color == BLACK:
3702 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3704 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3705 elif color == GREEN:
3706 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3708 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3710 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3711 elif color == MAGENTA:
3712 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3713 elif color == BROWN:
3714 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3715 elif color == LIGHTGRAY:
3716 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3717 elif color == DARKGRAY:
3718 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3719 elif color == LIGHTBLUE:
3720 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3721 elif color == LIGHTGREEN:
3722 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3723 elif color == LIGHTCYAN:
3724 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3725 elif color == LIGHTRED:
3726 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3727 elif color == LIGHTMAGENTA:
3728 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3729 elif color == YELLOW:
3730 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3731 elif color == WHITE:
3732 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3735 "Set highlight video, if this is reasonable."
3736 if game.options & OPTION_CURSES:
3737 curwnd.attron(curses.A_REVERSE)
3740 # Things past this point have policy implications.
3744 "Hook to be called after moving to redraw maps."
3745 if game.options & OPTION_CURSES:
3748 setwnd(srscan_window)
3752 setwnd(status_window)
3753 status_window.clear()
3754 status_window.move(0, 0)
3755 setwnd(report_window)
3756 report_window.clear()
3757 report_window.move(0, 0)
3759 setwnd(lrscan_window)
3760 lrscan_window.clear()
3761 lrscan_window.move(0, 0)
3762 lrscan(silent=False)
3764 def put_srscan_sym(w, sym):
3765 "Emit symbol for short-range scan."
3766 srscan_window.move(w.x+1, w.y*2+2)
3767 srscan_window.addch(sym)
3768 srscan_window.refresh()
3771 "Enemy fall down, go boom."
3772 if game.options & OPTION_CURSES:
3774 setwnd(srscan_window)
3775 srscan_window.attron(curses.A_REVERSE)
3776 put_srscan_sym(w, game.quad[w.x][w.y])
3780 srscan_window.attroff(curses.A_REVERSE)
3781 put_srscan_sym(w, game.quad[w.x][w.y])
3782 curses.delay_output(500)
3783 setwnd(message_window)
3786 "Sound and visual effects for teleportation."
3787 if game.options & OPTION_CURSES:
3789 setwnd(message_window)
3791 prouts(" . . . . . ")
3792 if game.options & OPTION_CURSES:
3793 #curses.delay_output(1000)
3797 def tracktorpedo(w, l, i, n, iquad):
3798 "Torpedo-track animation."
3799 if not game.options & OPTION_CURSES:
3803 proutn(_("Track for torpedo number %d- ") % i)
3806 proutn(_("Torpedo track- "))
3809 proutn("%d - %d " % (w.x, w.y))
3811 if not damaged(DSRSENS) or game.condition=="docked":
3812 if i != 1 and l == 1:
3815 if (iquad==IHDOT) or (iquad==IHBLANK):
3816 put_srscan_sym(w, '+')
3820 put_srscan_sym(w, iquad)
3822 curwnd.attron(curses.A_REVERSE)
3823 put_srscan_sym(w, iquad)
3827 curwnd.attroff(curses.A_REVERSE)
3828 put_srscan_sym(w, iquad)
3830 proutn("%d - %d " % (w.x, w.y))
3833 "Display the current galaxy chart."
3834 if game.options & OPTION_CURSES:
3835 setwnd(message_window)
3836 message_window.clear()
3838 if game.options & OPTION_TTY:
3843 def prstat(txt, data):
3845 if game.options & OPTION_CURSES:
3847 setwnd(status_window)
3849 proutn(" " * (NSYM - len(txt)))
3852 if game.options & OPTION_CURSES:
3853 setwnd(report_window)
3855 # Code from moving.c begins here
3857 def imove(novapush):
3858 # movement execution for warp, impulse, supernova, and tractor-beam events
3859 w = coord(); final = coord()
3862 def no_quad_change():
3863 # No quadrant change -- compute new average enemy distances
3864 game.quad[game.sector.x][game.sector.y] = game.ship
3866 for m in range(game.nenhere):
3867 finald = distance(w, game.ks[m])
3868 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3869 game.kdist[m] = finald
3871 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3873 for m in range(game.nenhere):
3874 game.kavgd[m] = game.kdist[m]
3877 setwnd(message_window)
3880 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3881 game.inorbit = False
3882 angle = ((15.0 - game.direc) * 0.5235988)
3883 deltax = -math.sin(angle)
3884 deltay = math.cos(angle)
3885 if math.fabs(deltax) > math.fabs(deltay):
3886 bigger = math.fabs(deltax)
3888 bigger = math.fabs(deltay)
3891 # If tractor beam is to occur, don't move full distance
3892 if game.state.date+game.optime >= scheduled(FTBEAM):
3894 game.condition = "red"
3895 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3896 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3897 # Move within the quadrant
3898 game.quad[game.sector.x][game.sector.y] = IHDOT
3901 n = int(10.0*game.dist*bigger+0.5)
3903 for m in range(1, n+1):
3908 if not VALID_SECTOR(w.x, w.y):
3909 # Leaving quadrant -- allow final enemy attack
3910 # Don't do it if being pushed by Nova
3911 if game.nenhere != 0 and not novapush:
3913 for m in range(game.nenhere):
3914 finald = distance(w, game.ks[m])
3915 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
3917 # Stas Sergeev added the condition
3918 # that attacks only happen if Klingons
3919 # are present and your skill is good.
3921 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3925 # compute final position -- new quadrant and sector
3926 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3927 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3928 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3929 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3930 # check for edge of galaxy
3940 if w.x >= GALSIZE*QUADSIZE:
3941 w.x = (GALSIZE*QUADSIZE*2) - w.x
3943 if w.y >= GALSIZE*QUADSIZE:
3944 w.y = (GALSIZE*QUADSIZE*2) - w.y
3952 if game.nkinks == 3:
3953 # Three strikes -- you're out!
3957 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3958 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3959 prout(_("YOU WILL BE DESTROYED."))
3960 # Compute final position in new quadrant
3961 if trbeam: # Don't bother if we are to be beamed
3963 game.quadrant.x = w.x/QUADSIZE
3964 game.quadrant.y = w.y/QUADSIZE
3965 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3966 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3968 prout(_("Entering Quadrant %s.") % game.quadrant)
3969 game.quad[game.sector.x][game.sector.y] = game.ship
3971 if game.skill>SKILL_NOVICE:
3974 iquad = game.quad[w.x][w.y]
3976 # object encountered in flight path
3977 stopegy = 50.0*game.dist/game.optime
3978 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3979 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3981 ram(False, iquad, game.sector)
3983 elif iquad == IHBLANK:
3985 prouts(_("***RED ALERT! RED ALERT!"))
3989 proutn(_(" pulled into black hole at Sector %s") % w)
3991 # Getting pulled into a black hole was certain
3992 # death in Almy's original. Stas Sergeev added a
3993 # possibility that you'll get timewarped instead.
3996 for m in range(NDEVICES):
3997 if game.damage[m]>0:
3999 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
4000 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
4010 proutn(_(" encounters Tholian web at %s;") % w)
4012 proutn(_(" blocked by object at %s;") % w)
4013 proutn(_("Emergency stop required "))
4014 prout(_("%2d units of energy.") % int(stopegy))
4015 game.energy -= stopegy
4016 final.x = x-deltax+0.5
4017 final.y = y-deltay+0.5
4019 if game.energy <= 0:
4025 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4032 # dock our ship at a starbase
4034 if game.condition == "docked" and verbose:
4035 prout(_("Already docked."))
4038 prout(_("You must first leave standard orbit."))
4040 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4042 prout(_(" not adjacent to base."))
4044 game.condition = "docked"
4048 if game.energy < game.inenrg:
4049 game.energy = game.inenrg
4050 game.shield = game.inshld
4051 game.torps = game.intorps
4052 game.lsupres = game.inlsr
4053 game.state.crew = FULLCREW
4054 if not damaged(DRADIO) and \
4055 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4056 # get attack report from base
4057 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4061 # This program originally required input in terms of a (clock)
4062 # direction and distance. Somewhere in history, it was changed to
4063 # cartesian coordinates. So we need to convert. Probably
4064 # "manual" input should still be done this way -- it's a real
4065 # pain if the computer isn't working! Manual mode is still confusing
4066 # because it involves giving x and y motions, yet the coordinates
4067 # are always displayed y - x, where +y is downward!
4069 def getcourse(isprobe, akey):
4070 # get course and distance
4072 dquad = copy.copy(game.quadrant)
4073 navmode = "unspecified"
4077 if game.landed and not isprobe:
4078 prout(_("Dummy! You can't leave standard orbit until you"))
4079 proutn(_("are back aboard the ship."))
4082 while navmode == "unspecified":
4083 if damaged(DNAVSYS):
4085 prout(_("Computer damaged; manual navigation only"))
4087 prout(_("Computer damaged; manual movement only"))
4092 if isprobe and akey != -1:
4093 # For probe launch, use pre-scanned value first time
4099 proutn(_("Manual or automatic- "))
4102 elif key == IHALPHA:
4107 elif isit("automatic"):
4108 navmode = "automatic"
4117 prout(_("(Manual navigation assumed.)"))
4119 prout(_("(Manual movement assumed.)"))
4122 if navmode == "automatic":
4125 proutn(_("Target quadrant or quadrant§or- "))
4127 proutn(_("Destination sector or quadrant§or- "))
4134 xi = int(round(aaitem))-1
4139 xj = int(round(aaitem))-1
4142 # both quadrant and sector specified
4143 xk = int(round(aaitem))-1
4148 xl = int(round(aaitem))-1
4154 # only one pair of numbers was specified
4156 # only quadrant specified -- go to center of dest quad
4159 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4161 # only sector specified
4165 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4172 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4174 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4175 # the actual deltas get computed here
4176 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4177 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4180 proutn(_("X and Y displacements- "))
4194 # Check for zero movement
4195 if deltax == 0 and deltay == 0:
4198 if itemp == "verbose" and not isprobe:
4200 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4201 # Course actually laid in.
4202 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4203 game.direc = math.atan2(deltax, deltay)*1.90985932
4204 if game.direc < 0.0:
4210 # move under impulse power
4212 if damaged(DIMPULS):
4215 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4217 if game.energy > 30.0:
4218 if not getcourse(isprobe=False, akey=0):
4220 power = 20.0 + 100.0*game.dist
4223 if power >= game.energy:
4224 # Insufficient power for trip
4226 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4227 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4228 if game.energy > 30:
4229 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4230 int(0.01 * (game.energy-20.0)-0.05))
4231 prout(_(" quadrants.\""))
4233 prout(_("quadrant. They are, therefore, useless.\""))
4236 # Make sure enough time is left for the trip
4237 game.optime = game.dist/0.095
4238 if game.optime >= game.state.remtime:
4239 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4240 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4241 proutn(_("we dare spend the time?\" "))
4244 # Activate impulse engines and pay the cost
4245 imove(novapush=False)
4249 power = 20.0 + 100.0*game.dist
4250 game.energy -= power
4251 game.optime = game.dist/0.095
4252 if game.energy <= 0:
4257 # move under warp drive
4258 blooey = False; twarp = False
4259 if not timewarp: # Not WARPX entry
4261 if game.damage[DWARPEN] > 10.0:
4264 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4266 if damaged(DWARPEN) and game.warpfac > 4.0:
4269 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4270 prout(_(" is repaired, I can only give you warp 4.\""))
4272 # Read in course and distance
4273 if not getcourse(isprobe=False, akey=0):
4275 # Make sure starship has enough energy for the trip
4276 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4277 if power >= game.energy:
4278 # Insufficient power for trip
4281 prout(_("Engineering to bridge--"))
4282 if not game.shldup or 0.5*power > game.energy:
4283 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4285 prout(_("We can't do it, Captain. We don't have enough energy."))
4287 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4290 prout(_("if you'll lower the shields."))
4294 prout(_("We haven't the energy to go that far with the shields up."))
4297 # Make sure enough time is left for the trip
4298 game.optime = 10.0*game.dist/game.wfacsq
4299 if game.optime >= 0.8*game.state.remtime:
4301 prout(_("First Officer Spock- \"Captain, I compute that such"))
4302 proutn(_(" a trip would require approximately %2.0f") %
4303 (100.0*game.optime/game.state.remtime))
4304 prout(_(" percent of our"))
4305 proutn(_(" remaining time. Are you sure this is wise?\" "))
4311 if game.warpfac > 6.0:
4312 # Decide if engine damage will occur
4313 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4314 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4315 if prob > randreal():
4317 game.dist = randreal(game.dist)
4318 # Decide if time warp will occur
4319 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4321 if idebug and game.warpfac==10 and not twarp:
4323 proutn("=== Force time warp? ")
4327 # If time warp or engine damage, check path
4328 # If it is obstructed, don't do warp or damage
4329 angle = ((15.0-game.direc)*0.5235998)
4330 deltax = -math.sin(angle)
4331 deltay = math.cos(angle)
4332 if math.fabs(deltax) > math.fabs(deltay):
4333 bigger = math.fabs(deltax)
4335 bigger = math.fabs(deltay)
4339 n = 10.0 * game.dist * bigger +0.5
4342 for l in range(1, n+1):
4347 if not VALID_SECTOR(ix, iy):
4349 if game.quad[ix][iy] != IHDOT:
4352 # Activate Warp Engines and pay the cost
4353 imove(novapush=False)
4356 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4357 if game.energy <= 0:
4359 game.optime = 10.0*game.dist/game.wfacsq
4363 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4365 prout(_("Engineering to bridge--"))
4366 prout(_(" Scott here. The warp engines are damaged."))
4367 prout(_(" We'll have to reduce speed to warp 4."))
4372 # change the warp factor
4378 proutn(_("Warp factor- "))
4383 if game.damage[DWARPEN] > 10.0:
4384 prout(_("Warp engines inoperative."))
4386 if damaged(DWARPEN) and aaitem > 4.0:
4387 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4388 prout(_(" but right now we can only go warp 4.\""))
4391 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4394 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4396 oldfac = game.warpfac
4397 game.warpfac = aaitem
4398 game.wfacsq=game.warpfac*game.warpfac
4399 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4400 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4403 if game.warpfac < 8.00:
4404 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4406 if game.warpfac == 10.0:
4407 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4409 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4413 # cope with being tossed out of quadrant by supernova or yanked by beam
4415 # is captain on planet?
4417 if damaged(DTRANSP):
4420 prout(_("Scotty rushes to the transporter controls."))
4422 prout(_("But with the shields up it's hopeless."))
4424 prouts(_("His desperate attempt to rescue you . . ."))
4429 prout(_("SUCCEEDS!"))
4432 proutn(_("The crystals mined were "))
4440 # Check to see if captain in shuttle craft
4445 # Inform captain of attempt to reach safety
4449 prouts(_("***RED ALERT! RED ALERT!"))
4453 prout(_(" has stopped in a quadrant containing"))
4454 prouts(_(" a supernova."))
4456 proutn(_("***Emergency automatic override attempts to hurl "))
4459 prout(_("safely out of quadrant."))
4460 if not damaged(DRADIO):
4461 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4462 # Try to use warp engines
4463 if damaged(DWARPEN):
4465 prout(_("Warp engines damaged."))
4468 game.warpfac = randreal(6.0, 8.0)
4469 game.wfacsq = game.warpfac * game.warpfac
4470 prout(_("Warp factor set to %d") % int(game.warpfac))
4471 power = 0.75*game.energy
4472 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4473 distreq = randreal(math.sqrt(2))
4474 if distreq < game.dist:
4476 game.optime = 10.0*game.dist/game.wfacsq
4477 game.direc = randreal(12) # How dumb!
4479 game.inorbit = False
4482 # This is bad news, we didn't leave quadrant.
4486 prout(_("Insufficient energy to leave quadrant."))
4489 # Repeat if another snova
4490 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4492 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4493 finish(FWON) # Snova killed remaining enemy.
4496 # let's do the time warp again
4497 prout(_("***TIME WARP ENTERED."))
4498 if game.state.snap and withprob(0.5):
4500 prout(_("You are traveling backwards in time %d stardates.") %
4501 int(game.state.date-game.snapsht.date))
4502 game.state = game.snapsht
4503 game.state.snap = False
4504 if game.state.remcom:
4505 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4506 schedule(FBATTAK, expran(0.3*game.intime))
4507 schedule(FSNOVA, expran(0.5*game.intime))
4508 # next snapshot will be sooner
4509 schedule(FSNAP, expran(0.25*game.state.remtime))
4511 if game.state.nscrem:
4512 schedule(FSCMOVE, 0.2777)
4516 invalidate(game.battle)
4518 # Make sure Galileo is consistant -- Snapshot may have been taken
4519 # when on planet, which would give us two Galileos!
4521 for l in range(game.inplan):
4522 if game.state.planets[l].known == "shuttle_down":
4524 if game.iscraft == "onship" and game.ship==IHE:
4525 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4526 game.iscraft = "offship"
4527 # Likewise, if in the original time the Galileo was abandoned, but
4528 # was on ship earlier, it would have vanished -- let's restore it.
4529 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4530 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4531 game.iscraft = "onship"
4533 # * There used to be code to do the actual reconstrction here,
4534 # * but the starchart is now part of the snapshotted galaxy state.
4536 prout(_("Spock has reconstructed a correct star chart from memory"))
4538 # Go forward in time
4539 game.optime = -0.5*game.intime*math.log(randreal())
4540 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4541 # cheat to make sure no tractor beams occur during time warp
4542 postpone(FTBEAM, game.optime)
4543 game.damage[DRADIO] += game.optime
4545 events() # Stas Sergeev added this -- do pending events
4548 # launch deep-space probe
4549 # New code to launch a deep space probe
4550 if game.nprobes == 0:
4553 if game.ship == IHE:
4554 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4556 prout(_("Ye Faerie Queene has no deep space probes."))
4561 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4563 if is_scheduled(FDSPROB):
4566 if damaged(DRADIO) and game.condition != "docked":
4567 prout(_("Spock- \"Records show the previous probe has not yet"))
4568 prout(_(" reached its destination.\""))
4570 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4574 # slow mode, so let Kirk know how many probes there are left
4575 if game.nprobes == 1:
4576 prout(_("1 probe left."))
4578 prout(_("%d probes left") % game.nprobes)
4579 proutn(_("Are you sure you want to fire a probe? "))
4582 game.isarmed = False
4583 if key == IHALPHA and citem == "armed":
4587 proutn(_("Arm NOVAMAX warhead? "))
4589 if not getcourse(isprobe=True, akey=key):
4592 angle = ((15.0 - game.direc) * 0.5235988)
4593 game.probeinx = -math.sin(angle)
4594 game.probeiny = math.cos(angle)
4595 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4596 bigger = math.fabs(game.probeinx)
4598 bigger = math.fabs(game.probeiny)
4599 game.probeiny /= bigger
4600 game.probeinx /= bigger
4601 game.proben = 10.0*game.dist*bigger +0.5
4602 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4603 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4604 game.probec = game.quadrant
4605 schedule(FDSPROB, 0.01) # Time to move one sector
4606 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4610 # Here's how the mayday code works:
4612 # First, the closest starbase is selected. If there is a a starbase
4613 # in your own quadrant, you are in good shape. This distance takes
4614 # quadrant distances into account only.
4616 # A magic number is computed based on the distance which acts as the
4617 # probability that you will be rematerialized. You get three tries.
4619 # When it is determined that you should be able to be rematerialized
4620 # (i.e., when the probability thing mentioned above comes up
4621 # positive), you are put into that quadrant (anywhere). Then, we try
4622 # to see if there is a spot adjacent to the star- base. If not, you
4623 # can't be rematerialized!!! Otherwise, it drops you there. It only
4624 # tries five times to find a spot to drop you. After that, it's your
4628 # yell for help from nearest starbase
4629 # There's more than one way to move in this game!
4632 # Test for conditions which prevent calling for help
4633 if game.condition == "docked":
4634 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4637 prout(_("Subspace radio damaged."))
4639 if game.state.rembase==0:
4640 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4643 proutn(_("You must be aboard the "))
4647 # OK -- call for help from nearest starbase
4650 # There's one in this quadrant
4651 ddist = distance(game.base, game.sector)
4654 for m in range(game.state.rembase):
4655 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4659 # Since starbase not in quadrant, set up new quadrant
4660 game.quadrant = game.state.baseq[line]
4662 # dematerialize starship
4663 game.quad[game.sector.x][game.sector.y]=IHDOT
4664 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4666 prout(_(" dematerializes."))
4668 for m in range(1, 5+1):
4669 w = game.base.scatter()
4670 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4671 # found one -- finish up
4674 if not is_valid(game.sector):
4675 prout(_("You have been lost in space..."))
4676 finish(FMATERIALIZE)
4678 # Give starbase three chances to rematerialize starship
4679 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4680 for m in range(1, 3+1):
4681 if m == 1: proutn(_("1st"))
4682 elif m == 2: proutn(_("2nd"))
4683 elif m == 3: proutn(_("3rd"))
4684 proutn(_(" attempt to re-materialize "))
4686 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4689 if randreal() > probf:
4692 curses.delay_output(500)
4695 game.quad[ix][iy]=IHQUEST
4698 setwnd(message_window)
4699 finish(FMATERIALIZE)
4701 game.quad[ix][iy]=game.ship
4703 prout(_("succeeds."))
4707 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4709 # Abandon Ship (the BSD-Trek description)
4711 # The ship is abandoned. If your current ship is the Faire
4712 # Queene, or if your shuttlecraft is dead, you're out of
4713 # luck. You need the shuttlecraft in order for the captain
4714 # (that's you!!) to escape.
4716 # Your crew can beam to an inhabited starsystem in the
4717 # quadrant, if there is one and if the transporter is working.
4718 # If there is no inhabited starsystem, or if the transporter
4719 # is out, they are left to die in outer space.
4721 # If there are no starbases left, you are captured by the
4722 # Klingons, who torture you mercilessly. However, if there
4723 # is at least one starbase, you are returned to the
4724 # Federation in a prisoner of war exchange. Of course, this
4725 # can't happen unless you have taken some prisoners.
4730 if game.condition=="docked":
4732 prout(_("You cannot abandon Ye Faerie Queene."))
4735 # Must take shuttle craft to exit
4736 if game.damage[DSHUTTL]==-1:
4737 prout(_("Ye Faerie Queene has no shuttle craft."))
4739 if game.damage[DSHUTTL]<0:
4740 prout(_("Shuttle craft now serving Big Macs."))
4742 if game.damage[DSHUTTL]>0:
4743 prout(_("Shuttle craft damaged."))
4746 prout(_("You must be aboard the ship."))
4748 if game.iscraft != "onship":
4749 prout(_("Shuttle craft not currently available."))
4751 # Print abandon ship messages
4753 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4755 prouts(_("***ALL HANDS ABANDON SHIP!"))
4757 prout(_("Captain and crew escape in shuttle craft."))
4758 if game.state.rembase==0:
4759 # Oops! no place to go...
4762 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4764 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4765 prout(_("Remainder of ship's complement beam down"))
4766 prout(_("to nearest habitable planet."))
4767 elif q.planet != None and not damaged(DTRANSP):
4768 prout(_("Remainder of ship's complement beam down to %s.") %
4771 prout(_("Entire crew of %d left to die in outer space.") %
4773 game.casual += game.state.crew
4774 game.abandoned += game.state.crew
4776 # If at least one base left, give 'em the Faerie Queene
4778 game.icrystl = False # crystals are lost
4779 game.nprobes = 0 # No probes
4780 prout(_("You are captured by Klingons and released to"))
4781 prout(_("the Federation in a prisoner-of-war exchange."))
4782 nb = randrange(game.state.rembase)
4783 # Set up quadrant and position FQ adjacient to base
4784 if not game.quadrant == game.state.baseq[nb]:
4785 game.quadrant = game.state.baseq[nb]
4786 game.sector.x = game.sector.y = 5
4789 # position next to base by trial and error
4790 game.quad[game.sector.x][game.sector.y] = IHDOT
4791 for l in range(QUADSIZE):
4792 game.sector = game.base.scatter()
4793 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4794 game.quad[game.sector.x][game.sector.y] == IHDOT:
4797 break # found a spot
4798 game.sector.x=QUADSIZE/2
4799 game.sector.y=QUADSIZE/2
4801 # Get new commission
4802 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4803 game.state.crew = FULLCREW
4804 prout(_("Starfleet puts you in command of another ship,"))
4805 prout(_("the Faerie Queene, which is antiquated but,"))
4806 prout(_("still useable."))
4808 prout(_("The dilithium crystals have been moved."))
4810 game.iscraft = "offship" # Galileo disappears
4812 game.condition="docked"
4813 for l in range(NDEVICES):
4814 game.damage[l] = 0.0
4815 game.damage[DSHUTTL] = -1
4816 game.energy = game.inenrg = 3000.0
4817 game.shield = game.inshld = 1250.0
4818 game.torps = game.intorps = 6
4819 game.lsupres=game.inlsr=3.0
4825 # Code from planets.c begins here.
4828 # abort a lengthy operation if an event interrupts it
4831 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4836 # report on (uninhabited) planets in the galaxy
4840 prout(_("Spock- \"Planet report follows, Captain.\""))
4842 for i in range(game.inplan):
4843 if game.state.planets[i].pclass == "destroyed":
4845 if (game.state.planets[i].known != "unknown" \
4846 and not game.state.planets[i].inhabited) \
4849 if idebug and game.state.planets[i].known=="unknown":
4850 proutn("(Unknown) ")
4851 proutn(_("Quadrant %s") % game.state.planets[i].w)
4852 proutn(_(" class "))
4853 proutn(game.state.planets[i].pclass)
4855 if game.state.planets[i].crystals != present:
4857 prout(_("dilithium crystals present."))
4858 if game.state.planets[i].known=="shuttle_down":
4859 prout(_(" Shuttle Craft Galileo on surface."))
4861 prout(_("No information available."))
4864 # enter standard orbit
4868 prout(_("Already in standard orbit."))
4870 if damaged(DWARPEN) and damaged(DIMPULS):
4871 prout(_("Both warp and impulse engines damaged."))
4873 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4875 prout(_(" not adjacent to planet."))
4878 game.optime = randreal(0.02, 0.05)
4879 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4883 game.height = randreal(1400, 8600)
4884 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4889 # examine planets in this quadrant
4890 if damaged(DSRSENS):
4891 if game.options & OPTION_TTY:
4892 prout(_("Short range sensors damaged."))
4894 if game.iplnet == None:
4895 if game.options & OPTION_TTY:
4896 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4898 if game.iplnet.known == "unknown":
4899 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4901 prout(_(" Planet at Sector %s is of class %s.") %
4902 (game.plnet, game.iplnet.pclass))
4903 if game.iplnet.known=="shuttle_down":
4904 prout(_(" Sensors show Galileo still on surface."))
4905 proutn(_(" Readings indicate"))
4906 if game.iplnet.crystals != "present":
4908 prout(_(" dilithium crystals present.\""))
4909 if game.iplnet.known == "unknown":
4910 game.iplnet.known = "known"
4911 elif game.iplnet.inhabited:
4912 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4913 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4916 # use the transporter
4920 if damaged(DTRANSP):
4921 prout(_("Transporter damaged."))
4922 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4924 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4928 if not game.inorbit:
4930 prout(_(" not in standard orbit."))
4933 prout(_("Impossible to transport through shields."))
4935 if game.iplnet.known=="unknown":
4936 prout(_("Spock- \"Captain, we have no information on this planet"))
4937 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4938 prout(_(" you may not go down.\""))
4940 if not game.landed and game.iplnet.crystals=="absent":
4941 prout(_("Spock- \"Captain, I fail to see the logic in"))
4942 prout(_(" exploring a planet with no dilithium crystals."))
4943 proutn(_(" Are you sure this is wise?\" "))
4947 if not (game.options & OPTION_PLAIN):
4948 nrgneed = 50 * game.skill + game.height / 100.0
4949 if nrgneed > game.energy:
4950 prout(_("Engineering to bridge--"))
4951 prout(_(" Captain, we don't have enough energy for transportation."))
4953 if not game.landed and nrgneed * 2 > game.energy:
4954 prout(_("Engineering to bridge--"))
4955 prout(_(" Captain, we have enough energy only to transport you down to"))
4956 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4957 if game.iplnet.known == "shuttle_down":
4958 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4959 proutn(_(" Are you sure this is wise?\" "))
4964 # Coming from planet
4965 if game.iplnet.known=="shuttle_down":
4966 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4970 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4971 prout(_("Landing party assembled, ready to beam up."))
4973 prout(_("Kirk whips out communicator..."))
4974 prouts(_("BEEP BEEP BEEP"))
4976 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4979 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4981 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4983 prout(_("Kirk- \"Energize.\""))
4986 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4989 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4991 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4994 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4995 game.landed = not game.landed
4996 game.energy -= nrgneed
4998 prout(_("Transport complete."))
4999 if game.landed and game.iplnet.known=="shuttle_down":
5000 prout(_("The shuttle craft Galileo is here!"))
5001 if not game.landed and game.imine:
5008 # strip-mine a world for dilithium
5012 prout(_("Mining party not on planet."))
5014 if game.iplnet.crystals == "mined":
5015 prout(_("This planet has already been strip-mined for dilithium."))
5017 elif game.iplnet.crystals == "absent":
5018 prout(_("No dilithium crystals on this planet."))
5021 prout(_("You've already mined enough crystals for this trip."))
5023 if game.icrystl and game.cryprob == 0.05:
5024 proutn(_("With all those fresh crystals aboard the "))
5027 prout(_("there's no reason to mine more at this time."))
5029 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
5032 prout(_("Mining operation complete."))
5033 game.iplnet.crystals = "mined"
5034 game.imine = game.ididit = True
5037 # use dilithium crystals
5041 if not game.icrystl:
5042 prout(_("No dilithium crystals available."))
5044 if game.energy >= 1000:
5045 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5046 prout(_(" except when Condition Yellow exists."))
5048 prout(_("Spock- \"Captain, I must warn you that loading"))
5049 prout(_(" raw dilithium crystals into the ship's power"))
5050 prout(_(" system may risk a severe explosion."))
5051 proutn(_(" Are you sure this is wise?\" "))
5056 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5057 prout(_(" Mr. Spock and I will try it.\""))
5059 prout(_("Spock- \"Crystals in place, Sir."))
5060 prout(_(" Ready to activate circuit.\""))
5062 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5064 if with(game.cryprob):
5065 prouts(_(" \"Activating now! - - No good! It's***"))
5067 prouts(_("***RED ALERT! RED A*L********************************"))
5070 prouts(_("****************** KA-BOOM!!!! *******************"))
5074 game.energy += randreal(5000.0, 5500.0)
5075 prouts(_(" \"Activating now! - - "))
5076 prout(_("The instruments"))
5077 prout(_(" are going crazy, but I think it's"))
5078 prout(_(" going to work!! Congratulations, Sir!\""))
5083 # use shuttlecraft for planetary jaunt
5086 if damaged(DSHUTTL):
5087 if game.damage[DSHUTTL] == -1.0:
5088 if game.inorbit and game.iplnet.known == "shuttle_down":
5089 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5091 prout(_("Ye Faerie Queene had no shuttle craft."))
5092 elif game.damage[DSHUTTL] > 0:
5093 prout(_("The Galileo is damaged."))
5094 else: # game.damage[DSHUTTL] < 0
5095 prout(_("Shuttle craft is now serving Big Macs."))
5097 if not game.inorbit:
5099 prout(_(" not in standard orbit."))
5101 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5102 prout(_("Shuttle craft not currently available."))
5104 if not game.landed and game.iplnet.known=="shuttle_down":
5105 prout(_("You will have to beam down to retrieve the shuttle craft."))
5107 if game.shldup or game.condition == "docked":
5108 prout(_("Shuttle craft cannot pass through shields."))
5110 if game.iplnet.known=="unknown":
5111 prout(_("Spock- \"Captain, we have no information on this planet"))
5112 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5113 prout(_(" you may not fly down.\""))
5115 game.optime = 3.0e-5*game.height
5116 if game.optime >= 0.8*game.state.remtime:
5117 prout(_("First Officer Spock- \"Captain, I compute that such"))
5118 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5119 int(100*game.optime/game.state.remtime))
5120 prout(_("remaining time."))
5121 proutn(_("Are you sure this is wise?\" "))
5127 if game.iscraft == "onship":
5129 if not damaged(DTRANSP):
5130 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5134 proutn(_("Shuttle crew"))
5136 proutn(_("Rescue party"))
5137 prout(_(" boards Galileo and swoops toward planet surface."))
5138 game.iscraft = "offship"
5142 game.iplnet.known="shuttle_down"
5143 prout(_("Trip complete."))
5146 # Ready to go back to ship
5147 prout(_("You and your mining party board the"))
5148 prout(_("shuttle craft for the trip back to the Enterprise."))
5150 prouts(_("The short hop begins . . ."))
5152 game.iplnet.known="known"
5158 game.iscraft = "onship"
5164 prout(_("Trip complete."))
5169 prout(_("Mining party assembles in the hangar deck,"))
5170 prout(_("ready to board the shuttle craft \"Galileo\"."))
5172 prouts(_("The hangar doors open; the trip begins."))
5175 game.iscraft = "offship"
5178 game.iplnet.known = "shuttle_down"
5181 prout(_("Trip complete."))
5185 # use the big zapper
5189 if game.ship != IHE:
5190 prout(_("Ye Faerie Queene has no death ray."))
5193 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5196 prout(_("Death Ray is damaged."))
5198 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5199 prout(_(" is highly unpredictible. Considering the alternatives,"))
5200 proutn(_(" are you sure this is wise?\" "))
5203 prout(_("Spock- \"Acknowledged.\""))
5206 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5208 prout(_("Crew scrambles in emergency preparation."))
5209 prout(_("Spock and Scotty ready the death ray and"))
5210 prout(_("prepare to channel all ship's power to the device."))
5212 prout(_("Spock- \"Preparations complete, sir.\""))
5213 prout(_("Kirk- \"Engage!\""))
5215 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5218 if game.options & OPTION_PLAIN:
5222 prouts(_("Sulu- \"Captain! It's working!\""))
5224 while game.nenhere > 0:
5225 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5226 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5227 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5229 if (game.options & OPTION_PLAIN) == 0:
5230 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5232 prout(_(" is still operational.\""))
5234 prout(_(" has been rendered nonfunctional.\""))
5235 game.damage[DDRAY] = 39.95
5237 r = randreal() # Pick failure method
5239 prouts(_("Sulu- \"Captain! It's working!\""))
5241 prouts(_("***RED ALERT! RED ALERT!"))
5243 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5245 prouts(_("***RED ALERT! RED A*L********************************"))
5248 prouts(_("****************** KA-BOOM!!!! *******************"))
5253 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5255 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5257 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5258 prout(_(" have apparently been transformed into strange mutations."))
5259 prout(_(" Vulcans do not seem to be affected."))
5261 prout(_("Kirk- \"Raauch! Raauch!\""))
5266 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5268 proutn(_("Spock- \"I believe the word is"))
5269 prouts(_(" *ASTONISHING*"))
5270 prout(_(" Mr. Sulu."))
5271 for i in range(QUADSIZE):
5272 for j in range(QUADSIZE):
5273 if game.quad[i][j] == IHDOT:
5274 game.quad[i][j] = IHQUEST
5275 prout(_(" Captain, our quadrant is now infested with"))
5276 prouts(_(" - - - - - - *THINGS*."))
5278 prout(_(" I have no logical explanation.\""))
5280 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5282 prout(_("Scotty- \"There are so many tribbles down here"))
5283 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5287 # Code from reports.c begins here
5289 def attackreport(curt):
5290 # report status of bases under attack
5292 if is_scheduled(FCDBAS):
5293 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5294 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5295 elif game.isatb == 1:
5296 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5297 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5299 prout(_("No Starbase is currently under attack."))
5301 if is_scheduled(FCDBAS):
5302 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5304 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5308 # report on general game status
5310 s1 = "" and game.thawed and _("thawed ")
5311 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5312 s3 = (None, _("novice"). _("fair"),
5313 _("good"), _("expert"), _("emeritus"))[game.skill]
5314 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5315 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5316 prout(_("No plaque is allowed."))
5318 prout(_("This is tournament game %d.") % game.tourn)
5319 prout(_("Your secret password is \"%s\"") % game.passwd)
5320 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5321 (game.inkling + game.incom + game.inscom)))
5322 if game.incom - game.state.remcom:
5323 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5324 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5325 prout(_(", but no Commanders."))
5328 if game.skill > SKILL_FAIR:
5329 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5330 if game.state.rembase != game.inbase:
5332 if game.inbase-game.state.rembase==1:
5333 proutn(_("has been 1 base"))
5335 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5336 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5338 prout(_("There are %d bases.") % game.inbase)
5339 if communicating() or game.iseenit:
5340 # Don't report this if not seen and
5341 # either the radio is dead or not at base!
5345 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5347 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5348 if game.ship == IHE:
5349 proutn(_("You have "))
5351 proutn("%d" % (game.nprobes))
5354 proutn(_(" deep space probe"))
5358 if communicating() and is_scheduled(FDSPROB):
5360 proutn(_("An armed deep space probe is in "))
5362 proutn(_("A deep space probe is in "))
5363 prout("Quadrant %s." % game.probec)
5365 if game.cryprob <= .05:
5366 prout(_("Dilithium crystals aboard ship... not yet used."))
5370 while game.cryprob > ai:
5373 prout(_("Dilithium crystals have been used %d time%s.") % \
5374 (i, (_("s"), "")[i==1]))
5378 # long-range sensor scan
5379 if damaged(DLRSENS):
5380 # Now allow base's sensors if docked
5381 if game.condition != "docked":
5383 prout(_("LONG-RANGE SENSORS DAMAGED."))
5386 prout(_("Starbase's long-range scan"))
5388 prout(_("Long-range scan"))
5389 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5392 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5393 if not VALID_QUADRANT(x, y):
5397 if not damaged(DRADIO):
5398 game.state.galaxy[x][y].charted = True
5399 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5400 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5401 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5402 if not silent and game.state.galaxy[x][y].supernova:
5405 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5413 for i in range(NDEVICES):
5416 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5417 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5419 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5420 game.damage[i]+0.05,
5421 game.docfac*game.damage[i]+0.005))
5423 prout(_("All devices functional."))
5426 # update the chart in the Enterprise's computer from galaxy data
5427 game.lastchart = game.state.date
5428 for i in range(GALSIZE):
5429 for j in range(GALSIZE):
5430 if game.state.galaxy[i][j].charted:
5431 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5432 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5433 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5436 # display the star chart
5438 if (game.options & OPTION_AUTOSCAN):
5440 if not damaged(DRADIO):
5442 if game.lastchart < game.state.date and game.condition == "docked":
5443 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5446 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5447 if game.state.date > game.lastchart:
5448 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5449 prout(" 1 2 3 4 5 6 7 8")
5450 for i in range(GALSIZE):
5451 proutn("%d |" % (i+1))
5452 for j in range(GALSIZE):
5453 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5457 if game.state.galaxy[i][j].supernova:
5459 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5461 elif game.state.galaxy[i][j].charted:
5462 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5466 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5474 def sectscan(goodScan, i, j):
5475 # light up an individual dot in a sector
5476 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5477 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):
5478 if game.condition == "red": textcolor(RED)
5479 elif game.condition == "green": textcolor(GREEN)
5480 elif game.condition == "yellow": textcolor(YELLOW)
5481 elif game.condition == "docked": textcolor(CYAN)
5482 elif game.condition == "dead": textcolor(BROWN)
5483 if game.quad[i][j] != game.ship:
5485 proutn("%c " % game.quad[i][j])
5491 # print status report lines
5493 if not req or req == 1:
5494 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5495 % (game.state.date, game.state.remtime))
5496 if not req or req == 2:
5497 if game.condition != "docked":
5500 for t in range(NDEVICES):
5501 if game.damage[t]>0:
5503 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5504 if not req or req == 3:
5505 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5506 if not req or req == 4:
5507 if damaged(DLIFSUP):
5508 if game.condition == "docked":
5509 s = _("DAMAGED, Base provides")
5511 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5514 prstat(_("Life Support"), s)
5515 if not req or req == 5:
5516 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5517 if not req or req == 6:
5519 if game.icrystl and (game.options & OPTION_SHOWME):
5520 extra = _(" (have crystals)")
5521 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5522 if not req or req == 7:
5523 prstat(_("Torpedoes"), "%d" % (game.torps))
5524 if not req or req == 8:
5525 if damaged(DSHIELD):
5531 data = _(" %d%% %.1f units") \
5532 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5533 prstat(_("Shields"), s+data)
5534 if not req or req == 9:
5535 prstat(_("Klingons Left"), "%d" \
5536 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5537 if not req or req == 10:
5538 if game.options & OPTION_WORLDS:
5539 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5540 if plnet and plnet.inhabited:
5541 prstat(_("Major system"), plnet.name)
5543 prout(_("Sector is uninhabited"))
5544 elif not req or req == 11:
5545 attackreport(not req)
5548 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5549 while scan() == IHEOL:
5550 proutn(_("Information desired? "))
5552 if citem in requests:
5553 status(requests.index(citem))
5555 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5556 prout((" date, condition, position, lsupport, warpfactor,"))
5557 prout((" energy, torpedoes, shields, klingons, system, time."))
5562 if damaged(DSRSENS):
5563 # Allow base's sensors if docked
5564 if game.condition != "docked":
5565 prout(_(" S.R. SENSORS DAMAGED!"))
5568 prout(_(" [Using Base's sensors]"))
5570 prout(_(" Short-range scan"))
5571 if goodScan and not damaged(DRADIO):
5572 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5573 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5574 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5575 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5576 prout(" 1 2 3 4 5 6 7 8 9 10")
5577 if game.condition != "docked":
5579 for i in range(QUADSIZE):
5580 proutn("%2d " % (i+1))
5581 for j in range(QUADSIZE):
5582 sectscan(goodScan, i, j)
5587 # use computer to get estimated time of arrival for a warp jump
5588 w1 = coord(); w2 = coord()
5590 if damaged(DCOMPTR):
5591 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5594 if scan() != IHREAL:
5597 proutn(_("Destination quadrant and/or sector? "))
5601 w1.y = int(aaitem-0.5)
5602 if scan() != IHREAL:
5605 w1.x = int(aaitem-0.5)
5606 if scan() == IHREAL:
5607 w2.y = int(aaitem-0.5)
5608 if scan() != IHREAL:
5611 w2.x = int(aaitem-0.5)
5613 if game.quadrant.y>w1.x:
5617 if game.quadrant.x>w1.y:
5621 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5624 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5625 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5628 prout(_("Answer \"no\" if you don't know the value:"))
5631 proutn(_("Time or arrival date? "))
5634 if ttime > game.state.date:
5635 ttime -= game.state.date # Actually a star date
5636 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5637 if ttime <= 1e-10 or twarp > 10:
5638 prout(_("We'll never make it, sir."))
5645 proutn(_("Warp factor? "))
5649 if twarp<1.0 or twarp > 10.0:
5653 prout(_("Captain, certainly you can give me one of these."))
5656 ttime = (10.0*game.dist)/square(twarp)
5657 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5658 if tpower >= game.energy:
5659 prout(_("Insufficient energy, sir."))
5660 if not game.shldup or tpower > game.energy*2.0:
5663 proutn(_("New warp factor to try? "))
5664 if scan() == IHREAL:
5667 if twarp<1.0 or twarp > 10.0:
5675 prout(_("But if you lower your shields,"))
5676 proutn(_("remaining"))
5679 proutn(_("Remaining"))
5680 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5682 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5684 prout(_("Any warp speed is adequate."))
5686 prout(_("Minimum warp needed is %.2f,") % (twarp))
5687 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5688 if game.state.remtime < ttime:
5689 prout(_("Unfortunately, the Federation will be destroyed by then."))
5691 prout(_("You'll be taking risks at that speed, Captain"))
5692 if (game.isatb==1 and game.state.kscmdr == w1 and \
5693 scheduled(FSCDBAS)< ttime+game.state.date) or \
5694 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5695 prout(_("The starbase there will be destroyed by then."))
5696 proutn(_("New warp factor to try? "))
5697 if scan() == IHREAL:
5700 if twarp<1.0 or twarp > 10.0:
5709 # Code from setup.c begins here
5712 # issue a historically correct banner
5714 prout(_("-SUPER- STAR TREK"))
5716 # From the FORTRAN original
5717 # prout(_("Latest update-21 Sept 78"))
5723 citem = "emsave.trk"
5727 proutn(_("File name: "))
5733 if '.' not in citem:
5736 fp = open(citem, "wb")
5738 prout(_("Can't freeze game as file %s") % citem)
5740 cPickle.dump(game, fp)
5744 # retrieve saved game
5745 game.passwd[0] = '\0'
5748 proutn(_("File name: "))
5754 if '.' not in citem:
5757 fp = open(citem, "rb")
5759 prout(_("Can't thaw game in %s") % citem)
5761 game = cPickle.load(fp)
5765 # I used <http://www.memory-alpha.org> to find planets
5766 # with references in ST:TOS. Eath and the Alpha Centauri
5767 # Colony have been omitted.
5769 # Some planets marked Class G and P here will be displayed as class M
5770 # because of the way planets are generated. This is a known bug.
5773 _("Andoria (Fesoan)"), # several episodes
5774 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5775 _("Vulcan (T'Khasi)"), # many episodes
5776 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5777 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5778 _("Ardana"), # TOS: "The Cloud Minders"
5779 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5780 _("Gideon"), # TOS: "The Mark of Gideon"
5781 _("Aldebaran III"), # TOS: "The Deadly Years"
5782 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5783 _("Altair IV"), # TOS: "Amok Time
5784 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5785 _("Benecia"), # TOS: "The Conscience of the King"
5786 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5787 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5788 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5789 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5790 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5791 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5792 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5793 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5794 _("Ingraham B"), # TOS: "Operation: Annihilate"
5795 _("Janus IV"), # TOS: "The Devil in the Dark"
5796 _("Makus III"), # TOS: "The Galileo Seven"
5797 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5798 _("Omega IV"), # TOS: "The Omega Glory"
5799 _("Regulus V"), # TOS: "Amok Time
5800 _("Deneva"), # TOS: "Operation -- Annihilate!"
5801 # Worlds from BSD Trek
5802 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5803 _("Beta III"), # TOS: "The Return of the Archons"
5804 _("Triacus"), # TOS: "And the Children Shall Lead",
5805 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5807 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5808 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5809 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5810 # _("Izar"), # TOS: "Whom Gods Destroy"
5811 # _("Tiburon"), # TOS: "The Way to Eden"
5812 # _("Merak II"), # TOS: "The Cloud Minders"
5813 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5814 # _("Iotia"), # TOS: "A Piece of the Action"
5818 _("S. R. Sensors"), \
5819 _("L. R. Sensors"), \
5821 _("Photon Tubes"), \
5822 _("Life Support"), \
5823 _("Warp Engines"), \
5824 _("Impulse Engines"), \
5826 _("Subspace Radio"), \
5827 _("Shuttle Craft"), \
5829 _("Navigation System"), \
5831 _("Shield Control"), \
5836 def setup(needprompt):
5837 # prepare to play, set up cosmos
5839 # Decide how many of everything
5840 if choose(needprompt):
5841 return # frozen game
5842 # Prepare the Enterprise
5843 game.alldone = game.gamewon = False
5845 game.state.crew = FULLCREW
5846 game.energy = game.inenrg = 5000.0
5847 game.shield = game.inshld = 2500.0
5848 game.shldchg = False
5852 game.quadrant = randplace(GALSIZE)
5853 game.sector = randplace(QUADSIZE)
5854 game.torps = game.intorps = 10
5855 game.nprobes = randrange(2, 5)
5857 game.wfacsq = game.warpfac * game.warpfac
5858 for i in range(NDEVICES):
5859 game.damage[i] = 0.0
5860 # Set up assorted game parameters
5861 game.battle = coord()
5862 game.state.date = game.indate = 100.0 * randreal(20, 51)
5863 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5864 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5865 game.isatb = game.state.nplankl = 0
5866 game.state.starkl = game.state.basekl = 0
5867 game.iscraft = "onship"
5871 for i in range(GALSIZE):
5872 for j in range(GALSIZE):
5873 quad = game.state.galaxy[i][j]
5878 quad.starbase = False
5879 quad.supernova = False
5880 quad.status = "secure"
5881 # Initialize times for extraneous events
5882 schedule(FSNOVA, expran(0.5 * game.intime))
5883 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5884 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5885 schedule(FBATTAK, expran(0.3*game.intime))
5887 if game.state.nscrem:
5888 schedule(FSCMOVE, 0.2777)
5893 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5894 schedule(FDISTR, expran(1.0 + game.intime))
5899 # Starchart is functional but we've never seen it
5900 game.lastchart = FOREVER
5901 # Put stars in the galaxy
5903 for i in range(GALSIZE):
5904 for j in range(GALSIZE):
5905 k = randrange(1, QUADSIZE**2/10+1)
5907 game.state.galaxy[i][j].stars = k
5908 # Locate star bases in galaxy
5909 for i in range(game.inbase):
5912 w = randplace(GALSIZE)
5913 if not game.state.galaxy[w.x][w.y].starbase:
5916 # C version: for (j = i-1; j > 0; j--)
5917 # so it did them in the opposite order.
5918 for j in range(1, i):
5919 # Improved placement algorithm to spread out bases
5920 distq = w.distance(game.state.baseq[j])
5921 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5924 prout("=== Abandoning base #%d at %s" % (i, w))
5926 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5928 prout("=== Saving base #%d, close to #%d" % (i, j))
5931 game.state.baseq[i] = w
5932 game.state.galaxy[w.x][w.y].starbase = True
5933 game.state.chart[w.x][w.y].starbase = True
5934 # Position ordinary Klingon Battle Cruisers
5936 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5937 if klumper > MAXKLQUAD:
5941 klump = (1.0 - r*r)*klumper
5946 w = randplace(GALSIZE)
5947 if not game.state.galaxy[w.x][w.y].supernova and \
5948 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5950 game.state.galaxy[w.x][w.y].klingons += int(klump)
5953 # Position Klingon Commander Ships
5954 for i in range(1, game.incom+1):
5956 w = randplace(GALSIZE)
5957 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5958 not game.state.galaxy[w.x][w.y].supernova and \
5959 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5960 not w in game.state.kcmdr[:i]:
5962 game.state.galaxy[w.x][w.y].klingons += 1
5963 game.state.kcmdr[i] = w
5964 # Locate planets in galaxy
5965 for i in range(game.inplan):
5967 w = randplace(GALSIZE)
5968 if game.state.galaxy[w.x][w.y].planet == None:
5972 new.crystals = "absent"
5973 if (game.options & OPTION_WORLDS) and i < NINHAB:
5974 new.pclass = "M" # All inhabited planets are class M
5975 new.crystals = "absent"
5977 new.name = systnames[i]
5978 new.inhabited = True
5980 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5982 new.crystals = "present"
5983 new.known = "unknown"
5984 new.inhabited = False
5985 game.state.galaxy[w.x][w.y].planet = new
5986 game.state.planets.append(new)
5988 for i in range(game.state.nromrem):
5989 w = randplace(GALSIZE)
5990 game.state.galaxy[w.x][w.y].romulans += 1
5991 # Locate the Super Commander
5992 if game.state.nscrem > 0:
5994 w = randplace(GALSIZE)
5995 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
5997 game.state.kscmdr = w
5998 game.state.galaxy[w.x][w.y].klingons += 1
5999 # Place thing (in tournament game, thingx == -1, don't want one!)
6002 thing = randplace(GALSIZE)
6004 game.state.snap = False
6005 if game.skill == SKILL_NOVICE:
6006 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6007 prout(_("a deadly Klingon invasion force. As captain of the United"))
6008 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6009 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6010 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6011 prout(_("your mission. As you proceed you may be given more time."))
6013 prout(_("You will have %d supporting starbases.") % (game.inbase))
6014 proutn(_("Starbase locations- "))
6016 prout(_("Stardate %d.") % int(game.state.date))
6018 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6019 prout(_("An unknown number of Romulans."))
6020 if game.state.nscrem:
6021 prout(_("And one (GULP) Super-Commander."))
6022 prout(_("%d stardates.") % int(game.intime))
6023 proutn(_("%d starbases in ") % game.inbase)
6024 for i in range(game.inbase):
6025 proutn(`game.state.baseq[i]`)
6028 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6029 proutn(_(" Sector %s") % game.sector)
6031 prout(_("Good Luck!"))
6032 if game.state.nscrem:
6033 prout(_(" YOU'LL NEED IT."))
6036 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
6038 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6041 def choose(needprompt):
6042 # choose your game type
6047 game.skill = SKILL_NONE
6049 if needprompt: # Can start with command line options
6050 proutn(_("Would you like a regular, tournament, or saved game? "))
6052 if len(citem)==0: # Try again
6054 if isit("tournament"):
6055 while scan() == IHEOL:
6056 proutn(_("Type in tournament number-"))
6059 continue # We don't want a blank entry
6060 game.tourn = int(round(aaitem))
6063 logfp.write("# random.seed(%d)\n" % aaitem)
6065 if isit("saved") or isit("frozen"):
6069 if game.passwd == None:
6071 if not game.alldone:
6072 game.thawed = True # No plaque if not finished
6078 proutn(_("What is \"%s\"?"), citem)
6080 while game.length==0 or game.skill==SKILL_NONE:
6081 if scan() == IHALPHA:
6084 elif isit("medium"):
6088 elif isit("novice"):
6089 game.skill = SKILL_NOVICE
6091 game.skill = SKILL_FAIR
6093 game.skill = SKILL_GOOD
6094 elif isit("expert"):
6095 game.skill = SKILL_EXPERT
6096 elif isit("emeritus"):
6097 game.skill = SKILL_EMERITUS
6099 proutn(_("What is \""))
6105 proutn(_("Would you like a Short, Medium, or Long game? "))
6106 elif game.skill == SKILL_NONE:
6107 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6108 # Choose game options -- added by ESR for SST2K
6109 if scan() != IHALPHA:
6111 proutn(_("Choose your game style (or just press enter): "))
6114 # Approximates the UT FORTRAN version.
6115 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6116 game.options |= OPTION_PLAIN
6118 # Approximates Tom Almy's version.
6119 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6120 game.options |= OPTION_ALMY
6124 proutn(_("What is \"%s\"?") % citem)
6126 if game.passwd == "debug":
6128 fputs("=== Debug mode enabled\n", sys.stdout)
6130 # Use parameters to generate initial values of things
6131 game.damfac = 0.5 * game.skill
6132 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6133 game.inbase = game.state.rembase
6135 if game.options & OPTION_PLANETS:
6136 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6137 if game.options & OPTION_WORLDS:
6138 game.inplan += int(NINHAB)
6139 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6140 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6141 game.state.remtime = 7.0 * game.length
6142 game.intime = game.state.remtime
6143 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6144 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6145 game.state.remcom = min(10, game.incom)
6146 game.incom = game.state.remcom
6147 game.state.remres = (game.inkling+4*game.incom)*game.intime
6148 game.inresor = game.state.remres
6149 if game.inkling > 50:
6150 game.state.rembase += 1
6151 game.inbase = game.state.rembase
6155 # drop a feature on a random dot in the current quadrant
6158 w = randplace(QUADSIZE)
6159 if game.quad[w.x][w.y] == IHDOT:
6161 game.quad[w.x][w.y] = iquad
6165 # update our alert status
6166 game.condition = "green"
6167 if game.energy < 1000.0:
6168 game.condition = "yellow"
6169 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6170 game.condition = "red"
6172 game.condition="dead"
6175 # drop new Klingon into current quadrant
6178 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6179 game.kpower[i] = randreal(300, 450) + 25.0*game.skill
6183 # set up a new state of quadrant, for when we enter or re-enter it
6187 game.comhere = False
6193 game.inorbit = False
6195 game.ientesc = False
6198 game.iseenit = False
6200 # Attempt to escape Super-commander, so tbeam back!
6203 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6204 # cope with supernova
6207 game.klhere = q.klingons
6208 game.irhere = q.romulans
6209 game.nenhere = game.klhere + game.irhere
6211 game.quad[game.sector.x][game.sector.y] = game.ship
6213 # Position ordinary Klingons
6214 for i in range(game.klhere):
6216 # If we need a commander, promote a Klingon
6217 for i in range(game.state.remcom):
6218 if game.state.kcmdr[i] == game.quadrant:
6219 game.quad[game.ks[i].x][game.ks[i].y] = IHC
6220 game.kpower[game.klhere] = randreal(950,1350) + 50.0*game.skill
6223 # If we need a super-commander, promote a Klingon
6224 if game.quadrant == game.state.kscmdr:
6225 game.quad[w.x][w.y] = IHS
6226 game.kpower[0] = randreal(1175.0, 1575.0) + 125.0*game.skill
6227 game.iscate = (game.state.remkl > 1)
6229 # Put in Romulans if needed
6230 for i in range(game.klhere, game.nenhere):
6233 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6234 game.kpower[i] = randreal(400.0, 850.0) + 50.0*game.skill
6235 # If quadrant needs a starbase, put it in
6237 game.base = dropin(IHB)
6238 # If quadrant needs a planet, put it in
6240 game.iplnet = q.planet
6241 if not q.planet.inhabited:
6242 game.plnet = dropin(IHP)
6244 game.plnet = dropin(IHW)
6245 # Check for condition
6247 # And finally the stars
6248 for i in range(q.stars):
6251 if game.irhere > 0 and game.klhere == 0:
6253 if not damaged(DRADIO):
6255 prout(_("LT. Uhura- \"Captain, an urgent message."))
6256 prout(_(" I'll put it on audio.\" CLICK"))
6258 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6259 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6261 # Put in THING if needed
6263 if thing == game.quadrant:
6265 thing = randplace(GALSIZE)
6267 game.ks[game.nenhere] = w
6268 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6269 distance(game.sector, w)
6270 game.kpower[game.nenhere] = randreal(6000,6500.0)+250.0*game.skill
6271 if not damaged(DSRSENS):
6273 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6274 prout(_(" Please examine your short-range scan.\""))
6275 # Decide if quadrant needs a Tholian; lighten up if skill is low
6276 if game.options & OPTION_THOLIAN:
6277 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6278 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6279 (game.skill > SKILL_GOOD and withprob(0.08)):
6280 game.tholian = coord()
6282 game.tholian.x = withprob(0.5) * (QUADSIZE-1)
6283 game.tholian.y = withprob(0.5) * (QUADSIZE-1)
6284 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6286 game.quad[game.tholian.x][game.tholian.y] = IHT
6288 game.ks[game.nenhere] = game.tholian
6289 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6290 distance(game.sector, game.tholian)
6291 game.kpower[game.nenhere] = randrange(100, 500) + 25.0*game.skill
6292 # Reserve unoccupied corners
6293 if game.quad[0][0]==IHDOT:
6294 game.quad[0][0] = 'X'
6295 if game.quad[0][QUADSIZE-1]==IHDOT:
6296 game.quad[0][QUADSIZE-1] = 'X'
6297 if game.quad[QUADSIZE-1][0]==IHDOT:
6298 game.quad[QUADSIZE-1][0] = 'X'
6299 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6300 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6302 # Put in a few black holes
6303 for i in range(1, 3+1):
6306 # Take out X's in corners if Tholian present
6308 if game.quad[0][0]=='X':
6309 game.quad[0][0] = IHDOT
6310 if game.quad[0][QUADSIZE-1]=='X':
6311 game.quad[0][QUADSIZE-1] = IHDOT
6312 if game.quad[QUADSIZE-1][0]=='X':
6313 game.quad[QUADSIZE-1][0] = IHDOT
6314 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6315 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6318 # sort Klingons by distance from us
6319 # The author liked bubble sort. So we will use it. :-(
6320 if game.nenhere-(thing==game.quadrant)-(game.tholian!=None) < 2:
6324 for j in range(game.nenhere-1):
6325 if game.kdist[j] > game.kdist[j+1]:
6328 game.kdist[j] = game.kdist[j+1]
6331 game.kavgd[j] = game.kavgd[j+1]
6334 game.ks[j].x = game.ks[j+1].x
6337 game.ks[j].y = game.ks[j+1].y
6340 game.kpower[j] = game.kpower[j+1]
6341 game.kpower[j+1] = t
6346 # set the self-destruct password
6347 if game.options & OPTION_PLAIN:
6350 proutn(_("Please type in a secret password- "))
6353 if game.passwd != None:
6358 game.passwd += chr(ord('a')+randrange(26))
6360 # Code from sst.c begins here
6363 "SRSCAN": OPTION_TTY,
6364 "STATUS": OPTION_TTY,
6365 "REQUEST": OPTION_TTY,
6366 "LRSCAN": OPTION_TTY,
6379 "SENSORS": OPTION_PLANETS,
6380 "ORBIT": OPTION_PLANETS,
6381 "TRANSPORT": OPTION_PLANETS,
6382 "MINE": OPTION_PLANETS,
6383 "CRYSTALS": OPTION_PLANETS,
6384 "SHUTTLE": OPTION_PLANETS,
6385 "PLANETS": OPTION_PLANETS,
6390 "PROBE": OPTION_PROBE,
6392 "FREEZE": 0, # Synonym for SAVE
6398 "SOS": 0, # Synonym for MAYDAY
6399 "CALL": 0, # Synonym for MAYDAY
6406 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6409 # generate a list of legal commands
6411 proutn(_("LEGAL COMMANDS ARE:"))
6412 for key in commands:
6416 proutn("%-12s " % key)
6421 # browse on-line help
6422 # Give help on commands
6426 setwnd(prompt_window)
6427 proutn(_("Help on what command? "))
6429 setwnd(message_window)
6432 if citem in commands or citem == "ABBREV":
6441 fp = open(SSTDOC, "r")
6444 fp = open(DOC_NAME, "r")
6446 prout(_("Spock- \"Captain, that information is missing from the"))
6447 proutn(_(" computer. You need to find "))
6449 prout(_(" and put it in the"))
6450 proutn(_(" current directory or to "))
6454 # This used to continue: "You need to find SST.DOC and put
6455 # it in the current directory."
6459 linebuf = fp.readline()
6461 prout(_("Spock- \"Captain, there is no information on that command.\""))
6464 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6465 linebuf = linebuf[3:].strip()
6469 prout(_("Spock- \"Captain, I've found the following information:\""))
6471 while linebuf in fp:
6472 if "******" in linebuf:
6478 # command-interpretation loop
6481 setwnd(message_window)
6482 while True: # command loop
6484 while True: # get a command
6489 setwnd(prompt_window)
6493 if game.options & OPTION_CURSES:
6498 setwnd(message_window)
6500 candidates = filter(lambda x: x.startswith(citem.upper()),
6502 if len(candidates) == 1:
6505 elif candidates and not (game.options & OPTION_PLAIN):
6506 prout("Commands with that prefix: " + " ".join(candidates))
6510 if cmd == "SRSCAN": # srscan
6512 elif cmd == "STATUS": # status
6514 elif cmd == "REQUEST": # status request
6516 elif cmd == "LRSCAN": # long range scan
6517 lrscan(silent=False)
6518 elif cmd == "PHASERS": # phasers
6522 elif cmd == "TORPEDO": # photon torpedos
6526 elif cmd == "MOVE": # move under warp
6528 elif cmd == "SHIELDS": # shields
6529 doshield(shraise=False)
6532 game.shldchg = False
6533 elif cmd == "DOCK": # dock at starbase
6537 elif cmd == "DAMAGES": # damage reports
6539 elif cmd == "CHART": # chart
6541 elif cmd == "IMPULSE": # impulse
6543 elif cmd == "REST": # rest
6547 elif cmd == "WARP": # warp
6549 elif cmd == "SCORE": # score
6551 elif cmd == "SENSORS": # sensors
6553 elif cmd == "ORBIT": # orbit
6557 elif cmd == "TRANSPORT": # transport "beam"
6559 elif cmd == "MINE": # mine
6563 elif cmd == "CRYSTALS": # crystals
6567 elif cmd == "SHUTTLE": # shuttle
6571 elif cmd == "PLANETS": # Planet list
6573 elif cmd == "REPORT": # Game Report
6575 elif cmd == "COMPUTER": # use COMPUTER!
6577 elif cmd == "COMMANDS":
6579 elif cmd == "EMEXIT": # Emergency exit
6580 clrscr() # Hide screen
6581 freeze(True) # forced save
6582 raise SysExit,1 # And quick exit
6583 elif cmd == "PROBE":
6584 probe() # Launch probe
6587 elif cmd == "ABANDON": # Abandon Ship
6589 elif cmd == "DESTRUCT": # Self Destruct
6591 elif cmd == "SAVE": # Save Game
6594 if game.skill > SKILL_GOOD:
6595 prout(_("WARNING--Saved games produce no plaques!"))
6596 elif cmd == "DEATHRAY": # Try a desparation measure
6600 elif cmd == "DEBUGCMD": # What do we want for debug???
6602 elif cmd == "MAYDAY": # Call for help
6607 game.alldone = True # quit the game
6612 break # Game has ended
6613 if game.optime != 0.0:
6616 break # Events did us in
6617 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6620 if hitme and not game.justin:
6624 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6636 if cmd == IHR: s = _("Romulan")
6637 elif cmd == IHK: s = _("Klingon")
6638 elif cmd == IHC: s = _("Commander")
6639 elif cmd == IHS: s = _("Super-commander")
6640 elif cmd == IHSTAR: s = _("Star")
6641 elif cmd == IHP: s = _("Planet")
6642 elif cmd == IHB: s = _("Starbase")
6643 elif cmd == IHBLANK: s = _("Black hole")
6644 elif cmd == IHT: s = _("Tholian")
6645 elif cmd == IHWEB: s = _("Tholian web")
6646 elif cmd == IHQUEST: s = _("Stranger")
6647 elif cmd == IHW: s = _("Inhabited World")
6648 else: s = "Unknown??"
6651 def crmena(stars, enemy, loctype, w):
6652 # print an enemy and his location
6658 if loctype == "quadrant":
6659 buf = _("Quadrant ")
6660 elif loctype == "sector":
6665 # print our ship name
6666 if game.ship == IHE:
6668 elif game.ship == IHF:
6669 s = _("Faerie Queene")
6675 # print a line of stars
6676 prouts("******************************************************")
6680 return -avrage*math.log(1e-7 + randreal())
6682 def randplace(size):
6683 # choose a random location
6685 w.x = randrange(size)
6686 w.y = randrange(size)
6690 # Demand input for next scan
6695 # return IHEOL next time
6700 # Get a token from the user
6701 global inqueue, line, citem, aaitem
6705 # Read a line if nothing here
6708 if curwnd==prompt_window:
6710 setwnd(message_window)
6712 # Skip leading white space
6713 line = line.lstrip()
6715 inqueue = line.split()
6721 # From here on in it's all looking at the queue
6722 citem = inqueue.pop(0)
6726 aaitem = float(citem)
6731 citem = citem.lower()
6735 # yes-or-no confirmation
6744 proutn(_("Please answer with \"y\" or \"n\": "))
6747 # complain about unparseable input
6750 prout(_("Beg your pardon, Captain?"))
6753 # compares s to citem and returns true if it matches to the length of s
6754 return s.startswith(citem)
6757 # access to the internals for debugging
6758 proutn("Reset levels? ")
6760 if game.energy < game.inenrg:
6761 game.energy = game.inenrg
6762 game.shield = game.inshld
6763 game.torps = game.intorps
6764 game.lsupres = game.inlsr
6765 proutn("Reset damage? ")
6767 for i in range(NDEVICES):
6768 if game.damage[i] > 0.0:
6769 game.damage[i] = 0.0
6770 proutn("Toggle debug flag? ")
6774 prout("Debug output ON")
6776 prout("Debug output OFF")
6777 proutn("Cause selective damage? ")
6779 for i in range(NDEVICES):
6785 if key == IHALPHA and isit("y"):
6786 game.damage[i] = 10.0
6787 proutn("Examine/change events? ")
6792 FSNOVA: "Supernova ",
6795 FBATTAK: "Base Attack ",
6796 FCDBAS: "Base Destroy ",
6797 FSCMOVE: "SC Move ",
6798 FSCDBAS: "SC Base Destroy ",
6799 FDSPROB: "Probe Move ",
6800 FDISTR: "Distress Call ",
6801 FENSLV: "Enslavement ",
6802 FREPRO: "Klingon Build ",
6804 for i in range(1, NEVENTS):
6807 proutn("%.2f" % (scheduled(i)-game.state.date))
6808 if i == FENSLV or i == FREPRO:
6810 proutn(" in %s" % ev.quadrant)
6820 ev = schedule(i, aaitem)
6821 if i == FENSLV or i == FREPRO:
6823 proutn("In quadrant- ")
6825 # IHEOL says to leave coordinates as they are
6828 prout("Event %d canceled, no x coordinate." % (i))
6831 w.x = int(round(aaitem))
6834 prout("Event %d canceled, no y coordinate." % (i))
6837 w.y = int(round(aaitem))
6840 proutn("Induce supernova here? ")
6842 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6845 if __name__ == '__main__':
6847 global line, thing, game, idebug, iqengry
6848 game = citem = aaitem = inqueue = None
6854 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6855 # Disable curses mode until the game logic is working.
6856 # if os.getenv("TERM"):
6857 # game.options |= OPTION_CURSES | OPTION_SHOWME
6859 game.options |= OPTION_TTY
6860 seed = int(time.time())
6861 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6862 for (switch, val) in options:
6865 replayfp = open(val, "r")
6867 sys.stderr.write("sst: can't open replay file %s\n" % val)
6870 line = replayfp.readline().strip()
6871 (leader, key, seed) = line.split()
6873 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6874 line = replayfp.readline().strip()
6875 arguments += line.split()[2:]
6877 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6879 game.options |= OPTION_TTY
6880 game.options &=~ OPTION_CURSES
6881 elif switch == '-t':
6882 game.options |= OPTION_TTY
6883 game.options &=~ OPTION_CURSES
6884 elif switch == '-x':
6887 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6889 # where to save the input in case of bugs
6891 logfp = open("/usr/tmp/sst-input.log", "w")
6893 sys.stderr.write("sst: warning, can't open logfile\n")
6895 logfp.write("# seed %s\n" % seed)
6896 logfp.write("# options %s\n" % " ".join(arguments))
6903 while True: # Play a game
6904 setwnd(fullscreen_window)
6907 setup(needprompt=not inqueue)
6910 game.alldone = False
6916 if game.tourn and game.alldone:
6917 proutn(_("Do you want your score recorded?"))
6922 proutn(_("Do you want to play again? "))
6926 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6928 except KeyboardInterrupt: