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
1572 # a critical hit occured
1573 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1575 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1576 proutn(_("***CRITICAL HIT--"))
1577 # Select devices and cause damage
1579 for loop1 in range(ncrit):
1582 # Cheat to prevent shuttle damage unless on ship
1583 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1586 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1587 game.damage[j] += extradm
1589 for loop2 in range(loop1):
1590 if j == cdam[loop2]:
1599 prout(_(" damaged."))
1600 if damaged(DSHIELD) and game.shldup:
1601 prout(_("***Shields knocked down."))
1604 def attack(torps_ok):
1605 # bad guy attacks us
1606 # torps_ok == false forces use of phasers in an attack
1607 atackd = False; attempt = False; ihurt = False;
1608 hitmax=0.0; hittot=0.0; chgfac=1.0
1611 # game could be over at this point, check
1615 prout("=== ATTACK!")
1616 # Tholian gets to move before attacking
1619 # if you have just entered the RNZ, you'll get a warning
1620 if game.neutz: # The one chance not to be attacked
1623 # commanders get a chance to tac-move towards you
1624 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1626 # if no enemies remain after movement, we're done
1627 if game.nenhere==0 or (game.nenhere==1 and thing == game.quadrant and not iqengry):
1629 # set up partial hits if attack happens during shield status change
1630 pfac = 1.0/game.inshld
1632 chgfac = 0.25 + randreal(0.5)
1634 # message verbosity control
1635 if game.skill <= SKILL_FAIR:
1637 for loop in range(game.nenhere):
1638 if game.kpower[loop] < 0:
1639 continue; # too weak to attack
1640 # compute hit strength and diminish shield power
1642 # Increase chance of photon torpedos if docked or enemy energy low
1643 if game.condition == "docked":
1645 if game.kpower[loop] < 500:
1648 iquad = game.quad[jay.x][jay.y]
1649 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1651 # different enemies have different probabilities of throwing a torp
1652 usephasers = not torps_ok or \
1653 (iquad == IHK and r > 0.0005) or \
1654 (iquad==IHC and r > 0.015) or \
1655 (iquad==IHR and r > 0.3) or \
1656 (iquad==IHS and r > 0.07) or \
1657 (iquad==IHQUEST and r > 0.05)
1658 if usephasers: # Enemy uses phasers
1659 if game.condition == "docked":
1660 continue; # Don't waste the effort!
1661 attempt = True; # Attempt to attack
1662 dustfac = 0.8 + randreal(0.5)
1663 hit = game.kpower[loop]*math.pow(dustfac,game.kavgd[loop])
1664 game.kpower[loop] *= 0.75
1665 else: # Enemy uses photon torpedo
1666 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1668 proutn(_("***TORPEDO INCOMING"))
1669 if not damaged(DSRSENS):
1671 crmena(False, iquad, where, jay)
1674 r = (randreal()+randreal())*0.5 - 0.5
1675 r += 0.002*game.kpower[loop]*r
1676 hit = torpedo(course, r, jay, 1, 1)
1677 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1678 finish(FWON); # Klingons did themselves in!
1679 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1680 return; # Supernova or finished
1683 # incoming phaser or torpedo, shields may dissipate it
1684 if game.shldup or game.shldchg or game.condition=="docked":
1685 # shields will take hits
1686 propor = pfac * game.shield
1687 if game.condition =="docked":
1691 hitsh = propor*chgfac*hit+1.0
1693 if absorb > game.shield:
1694 absorb = game.shield
1695 game.shield -= absorb
1697 # taking a hit blasts us out of a starbase dock
1698 if game.condition == "docked":
1700 # but the shields may take care of it
1701 if propor > 0.1 and hit < 0.005*game.energy:
1703 # hit from this opponent got through shields, so take damage
1705 proutn(_("%d unit hit") % int(hit))
1706 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1707 proutn(_(" on the "))
1709 if not damaged(DSRSENS) and usephasers:
1711 crmena(False, iquad, where, jay)
1713 # Decide if hit is critical
1719 if game.energy <= 0:
1720 # Returning home upon your shield, not with it...
1723 if not attempt and game.condition == "docked":
1724 prout(_("***Enemies decide against attacking your ship."))
1727 percent = 100.0*pfac*game.shield+0.5
1729 # Shields fully protect ship
1730 proutn(_("Enemy attack reduces shield strength to "))
1732 # Print message if starship suffered hit(s)
1734 proutn(_("Energy left %2d shields ") % int(game.energy))
1737 elif not damaged(DSHIELD):
1740 proutn(_("damaged, "))
1741 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1742 # Check if anyone was hurt
1743 if hitmax >= 200 or hittot >= 500:
1744 icas = randrange(hittot * 0.015)
1747 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1748 prout(_(" in that last attack.\""))
1750 game.state.crew -= icas
1751 # After attack, reset average distance to enemies
1752 for loop in range(game.nenhere):
1753 game.kavgd[loop] = game.kdist[loop]
1757 def deadkl(w, type, mv):
1758 # kill a Klingon, Tholian, Romulan, or Thingy
1759 # Added mv to allow enemy to "move" before dying
1760 crmena(True, type, "sector", mv)
1761 # Decide what kind of enemy it is and update appropriately
1763 # chalk up a Romulan
1764 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1766 game.state.nromrem -= 1
1770 elif type == IHQUEST:
1776 # Some type of a Klingon
1777 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1780 game.comhere = False
1781 for i in range(game.state.remcom):
1782 if game.state.kcmdr[i] == game.quadrant:
1784 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1785 game.state.kcmdr[game.state.remcom].x = 0
1786 game.state.kcmdr[game.state.remcom].y = 0
1787 game.state.remcom -= 1
1789 if game.state.remcom != 0:
1790 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1792 game.state.remkl -= 1
1794 game.state.nscrem -= 1
1796 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1801 prout("*** Internal error, deadkl() called on %s\n" % type)
1802 # For each kind of enemy, finish message to player
1803 prout(_(" destroyed."))
1804 game.quad[w.x][w.y] = IHDOT
1805 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1808 # Remove enemy ship from arrays describing local conditions
1809 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1811 for i in range(game.nenhere):
1813 for j in range(i, game.nenhere):
1814 game.ks[j] = game.ks[j+1]
1815 game.kpower[j] = game.kpower[j+1]
1816 game.kavgd[j] = game.kdist[j] = game.kdist[j+1]
1817 game.ks[game.nenhere].x = 0
1818 game.ks[game.nenhere].y = 0
1819 game.kdist[game.nenhere] = 0
1820 game.kavgd[game.nenhere] = 0
1821 game.kpower[game.nenhere] = 0
1827 def targetcheck(x, y):
1828 # Return None if target is invalid
1829 if not VALID_SECTOR(x, y):
1832 deltx = 0.1*(y - game.sector.y)
1833 delty = 0.1*(x - game.sector.x)
1834 if deltx==0 and delty== 0:
1836 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1837 prout(_(" I recommend an immediate review of"))
1838 prout(_(" the Captain's psychological profile.\""))
1841 return 1.90985932*math.atan2(deltx, delty)
1844 # launch photon torpedo
1846 if damaged(DPHOTON):
1847 prout(_("Photon tubes damaged."))
1851 prout(_("No torpedoes left."))
1860 prout(_("%d torpedoes left.") % game.torps)
1861 proutn(_("Number of torpedoes to fire- "))
1863 else: # key == IHREAL {
1865 if n <= 0: # abort command
1870 prout(_("Maximum of 3 torpedoes per burst."))
1877 for i in range(1, n+1):
1879 if i==1 and key == IHEOL:
1880 break; # we will try prompting
1881 if i==2 and key == IHEOL:
1882 # direct all torpedoes at one target
1884 targ[i][1] = targ[1][1]
1885 targ[i][2] = targ[1][2]
1886 course[i] = course[1]
1898 course[i] = targetcheck(targ[i][1], targ[i][2])
1899 if course[i] == None:
1902 if i == 1 and key == IHEOL:
1903 # prompt for each one
1904 for i in range(1, n+1):
1905 proutn(_("Target sector for torpedo number %d- ") % i)
1910 targ[i][1] = int(aaitem-0.5)
1915 targ[i][2] = int(aaitem-0.5)
1917 course[i] = targetcheck(targ[i][1], targ[i][2])
1918 if course[i] == None:
1921 # Loop for moving <n> torpedoes
1923 if game.condition != "docked":
1925 r = (randreal()+randreal())*0.5 -0.5
1926 if math.fabs(r) >= 0.47:
1928 r *= randreal(1.2, 2.2)
1930 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1932 prouts(_("***TORPEDO MISFIRES."))
1935 prout(_(" Remainder of burst aborted."))
1937 prout(_("***Photon tubes damaged by misfire."))
1938 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1940 if game.shldup or game.condition == "docked":
1941 r *= 1.0 + 0.0001*game.shield
1942 torpedo(course[i], r, game.sector, i, n)
1943 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1945 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1949 # check for phasers overheating
1951 checkburn = (rpow-1500.0)*0.00038
1952 if withprob(checkburn):
1953 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1954 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1956 def checkshctrl(rpow):
1957 # check shield control
1960 prout(_("Shields lowered."))
1962 # Something bad has happened
1963 prouts(_("***RED ALERT! RED ALERT!"))
1965 hit = rpow*game.shield/game.inshld
1966 game.energy -= rpow+hit*0.8
1967 game.shield -= hit*0.2
1968 if game.energy <= 0.0:
1969 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1974 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1976 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1977 icas = randrange(hit*0.012)
1982 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1983 prout(_(" %d casualties so far.\"") % icas)
1985 game.state.crew -= icas
1987 prout(_("Phaser energy dispersed by shields."))
1988 prout(_("Enemy unaffected."))
1993 # register a phaser hit on Klingons and Romulans
1994 nenhr2 = game.nenhere; kk=0
1997 for (k, wham) in enumerate(hits):
2000 dustfac = randreal(0.9, 1.0)
2001 print type(wham), type(dustfac), type(game.kdist[kk]), "Foo!", game.kdist
2002 hit = wham*math.pow(dustfac,game.kdist[kk])
2004 kpini = game.kpower[kk]
2005 kp = math.fabs(kpini)
2006 if PHASEFAC*hit < kp:
2008 if game.kpower[kk] < 0:
2009 game.kpower[kk] -= -kp
2011 game.kpower[kk] -= kp
2012 kpow = game.kpower[kk]
2015 if not damaged(DSRSENS):
2017 proutn(_("%d unit hit on ") % int(hit))
2019 proutn(_("Very small hit on "))
2020 ienm = game.quad[w.x][w.y]
2024 crmena(False, ienm, "sector", w)
2028 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2032 kk -= 1 # don't do the increment
2034 else: # decide whether or not to emasculate klingon
2035 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2036 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2037 prout(_(" has just lost its firepower.\""))
2038 game.kpower[kk] = -kpow
2045 kz = 0; k = 1; irec=0 # Cheating inhibitor
2046 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2050 # SR sensors and Computer are needed fopr automode
2051 if damaged(DSRSENS) or damaged(DCOMPTR):
2053 if game.condition == "docked":
2054 prout(_("Phasers can't be fired through base shields."))
2057 if damaged(DPHASER):
2058 prout(_("Phaser control damaged."))
2062 if damaged(DSHCTRL):
2063 prout(_("High speed shield control damaged."))
2066 if game.energy <= 200.0:
2067 prout(_("Insufficient energy to activate high-speed shield control."))
2070 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2072 # Original code so convoluted, I re-did it all
2073 # (That was Tom Almy talking about the C code, I think -- ESR)
2074 while automode=="NOTSET":
2079 prout(_("There is no enemy present to select."))
2082 automode="AUTOMATIC"
2086 elif isit("automatic"):
2087 if (not itarg) and game.nenhere != 0:
2088 automode = "FORCEMAN"
2091 prout(_("Energy will be expended into space."))
2092 automode = "AUTOMATIC"
2101 prout(_("Energy will be expended into space."))
2102 automode = "AUTOMATIC"
2104 automode = "FORCEMAN"
2106 automode = "AUTOMATIC"
2110 prout(_("Energy will be expended into space."))
2111 automode = "AUTOMATIC"
2113 automode = "FORCEMAN"
2115 proutn(_("Manual or automatic? "))
2120 if automode == "AUTOMATIC":
2121 if key == IHALPHA and isit("no"):
2124 if key != IHREAL and game.nenhere != 0:
2125 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2130 for i in range(game.nenhere):
2131 irec += math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))*randreal(1.01, 1.06) + 1.0
2133 proutn(_("%d units required. ") % irec)
2135 proutn(_("Units to fire= "))
2141 proutn(_("Energy available= %.2f") % avail)
2144 if not rpow > avail:
2151 if key == IHALPHA and isit("no"):
2154 game.energy -= 200; # Go and do it!
2155 if checkshctrl(rpow):
2163 for i in range(game.nenhere):
2167 hits[i] = math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))
2168 over = randreal(1.01, 1.06) * hits[i]
2170 powrem -= hits[i] + over
2171 if powrem <= 0 and temp < hits[i]:
2180 if extra > 0 and not game.alldone:
2182 proutn(_("*** Tholian web absorbs "))
2184 proutn(_("excess "))
2185 prout(_("phaser energy."))
2187 prout(_("%d expended on empty space.") % int(extra))
2188 elif automode == "FORCEMAN":
2191 if damaged(DCOMPTR):
2192 prout(_("Battle computer damaged, manual fire only."))
2195 prouts(_("---WORKING---"))
2197 prout(_("Short-range-sensors-damaged"))
2198 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2199 prout(_("Manual-fire-must-be-used"))
2201 elif automode == "MANUAL":
2203 for k in range(game.nenhere):
2205 ienm = game.quad[aim.x][aim.y]
2207 proutn(_("Energy available= %.2f") % (avail-0.006))
2211 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2212 (ienm == IHC or ienm == IHS):
2214 prout(_(" can't be located without short range scan."))
2217 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2222 if itarg and k > kz:
2223 irec=(abs(game.kpower[k])/(PHASEFAC*math.pow(0.9,game.kdist[k]))) * randreal(1.01, 1.06) + 1.0
2226 if not damaged(DCOMPTR):
2231 proutn(_("units to fire at "))
2232 crmena(False, ienm, "sector", aim)
2235 if key == IHALPHA and isit("no"):
2243 if k==1: # Let me say I'm baffled by this
2252 # If total requested is too much, inform and start over
2254 prout(_("Available energy exceeded -- try again."))
2257 key = scan(); # scan for next value
2260 # zero energy -- abort
2263 if key == IHALPHA and isit("no"):
2268 game.energy -= 200.0
2269 if checkshctrl(rpow):
2273 # Say shield raised or malfunction, if necessary
2280 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2281 prouts(_(" CLICK CLICK POP . . ."))
2282 prout(_(" No response, sir!"))
2285 prout(_("Shields raised."))
2290 # Code from events,c begins here.
2292 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2293 # event of each type active at any given time. Mostly these means we can
2294 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2295 # BSD Trek, from which we swiped the idea, can have up to 5.
2297 def unschedule(evtype):
2298 # remove an event from the schedule
2299 game.future[evtype].date = FOREVER
2300 return game.future[evtype]
2302 def is_scheduled(evtype):
2303 # is an event of specified type scheduled
2304 return game.future[evtype].date != FOREVER
2306 def scheduled(evtype):
2307 # when will this event happen?
2308 return game.future[evtype].date
2310 def schedule(evtype, offset):
2311 # schedule an event of specified type
2312 game.future[evtype].date = game.state.date + offset
2313 return game.future[evtype]
2315 def postpone(evtype, offset):
2316 # postpone a scheduled event
2317 game.future[evtype].date += offset
2320 # rest period is interrupted by event
2323 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2325 game.resting = False
2331 # run through the event queue looking for things to do
2333 fintim = game.state.date + game.optime; yank=0
2334 ictbeam = False; istract = False
2335 w = coord(); hold = coord()
2336 ev = event(); ev2 = event()
2338 def tractorbeam(yank):
2339 # tractor beaming cases merge here
2341 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2345 prout(_(" caught in long range tractor beam--"))
2346 # If Kirk & Co. screwing around on planet, handle
2347 atover(True) # atover(true) is Grab
2350 if game.icraft: # Caught in Galileo?
2353 # Check to see if shuttle is aboard
2354 if game.iscraft == "offship":
2357 prout(_("Galileo, left on the planet surface, is captured"))
2358 prout(_("by aliens and made into a flying McDonald's."))
2359 game.damage[DSHUTTL] = -10
2360 game.iscraft = "removed"
2362 prout(_("Galileo, left on the planet surface, is well hidden."))
2364 game.quadrant = game.state.kscmdr
2366 game.quadrant = game.state.kcmdr[i]
2367 game.sector = randplace(QUADSIZE)
2369 prout(_(" is pulled to Quadrant %s, Sector %s") \
2370 % (game.quadrant, game.sector))
2372 prout(_("(Remainder of rest/repair period cancelled.)"))
2373 game.resting = False
2375 if not damaged(DSHIELD) and game.shield > 0:
2376 doshield(shraise=True) # raise shields
2377 game.shldchg = False
2379 prout(_("(Shields not currently useable.)"))
2381 # Adjust finish time to time of tractor beaming
2382 fintim = game.state.date+game.optime
2384 if game.state.remcom <= 0:
2387 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2390 # Code merges here for any commander destroying base
2391 # Not perfect, but will have to do
2392 # Handle case where base is in same quadrant as starship
2393 if game.battle == game.quadrant:
2394 game.state.chart[game.battle.x][game.battle.y].starbase = False
2395 game.quad[game.base.x][game.base.y] = IHDOT
2396 game.base.x=game.base.y=0
2399 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2400 elif game.state.rembase != 1 and communicating():
2401 # Get word via subspace radio
2404 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2405 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2407 prout(_("the Klingon Super-Commander"))
2409 prout(_("a Klingon Commander"))
2410 game.state.chart[game.battle.x][game.battle.y].starbase = False
2411 # Remove Starbase from galaxy
2412 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2413 for i in range(1, game.state.rembase+1):
2414 if game.state.baseq[i] == game.battle:
2415 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2416 game.state.rembase -= 1
2418 # reinstate a commander's base attack
2422 invalidate(game.battle)
2425 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2426 for i in range(1, NEVENTS):
2427 if i == FSNOVA: proutn("=== Supernova ")
2428 elif i == FTBEAM: proutn("=== T Beam ")
2429 elif i == FSNAP: proutn("=== Snapshot ")
2430 elif i == FBATTAK: proutn("=== Base Attack ")
2431 elif i == FCDBAS: proutn("=== Base Destroy ")
2432 elif i == FSCMOVE: proutn("=== SC Move ")
2433 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2434 elif i == FDSPROB: proutn("=== Probe Move ")
2435 elif i == FDISTR: proutn("=== Distress Call ")
2436 elif i == FENSLV: proutn("=== Enslavement ")
2437 elif i == FREPRO: proutn("=== Klingon Build ")
2439 prout("%.2f" % (scheduled(i)))
2442 radio_was_broken = damaged(DRADIO)
2445 # Select earliest extraneous event, evcode==0 if no events
2450 for l in range(1, NEVENTS):
2451 if game.future[l].date < datemin:
2454 prout("== Event %d fires" % evcode)
2455 datemin = game.future[l].date
2456 xtime = datemin-game.state.date
2457 game.state.date = datemin
2458 # Decrement Federation resources and recompute remaining time
2459 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2461 if game.state.remtime <=0:
2464 # Any crew left alive?
2465 if game.state.crew <=0:
2468 # Is life support adequate?
2469 if damaged(DLIFSUP) and game.condition != "docked":
2470 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2473 game.lsupres -= xtime
2474 if game.damage[DLIFSUP] <= xtime:
2475 game.lsupres = game.inlsr
2478 if game.condition == "docked":
2479 repair /= game.docfac
2480 # Don't fix Deathray here
2481 for l in range(NDEVICES):
2482 if game.damage[l] > 0.0 and l != DDRAY:
2483 if game.damage[l]-repair > 0.0:
2484 game.damage[l] -= repair
2486 game.damage[l] = 0.0
2487 # If radio repaired, update star chart and attack reports
2488 if radio_was_broken and not damaged(DRADIO):
2489 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2490 prout(_(" surveillance reports are coming in."))
2492 if not game.iseenit:
2496 prout(_(" The star chart is now up to date.\""))
2498 # Cause extraneous event EVCODE to occur
2499 game.optime -= xtime
2500 if evcode == FSNOVA: # Supernova
2503 schedule(FSNOVA, expran(0.5*game.intime))
2504 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2506 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2507 if game.state.nscrem == 0 or \
2508 ictbeam or istract or \
2509 game.condition=="docked" or game.isatb==1 or game.iscate:
2511 if game.ientesc or \
2512 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2513 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2514 (damaged(DSHIELD) and \
2515 (game.energy < 2500 or damaged(DPHASER)) and \
2516 (game.torps < 5 or damaged(DPHOTON))):
2518 istract = ictbeam = True
2519 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2522 elif evcode == FTBEAM: # Tractor beam
2523 if game.state.remcom == 0:
2526 i = randrange(game.state.remcom)
2527 yank = distance(game.state.kcmdr[i], game.quadrant)
2528 if istract or game.condition == "docked" or yank == 0:
2529 # Drats! Have to reschedule
2531 game.optime + expran(1.5*game.intime/game.state.remcom))
2535 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2536 game.snapsht = copy.deepcopy(game.state)
2537 game.state.snap = True
2538 schedule(FSNAP, expran(0.5 * game.intime))
2539 elif evcode == FBATTAK: # Commander attacks starbase
2540 if game.state.remcom==0 or game.state.rembase==0:
2546 for j in range(game.state.rembase):
2547 for k in range(game.state.remcom):
2548 if game.state.baseq[j] == game.state.kcmdr[k] and \
2549 not game.state.baseq[j] == game.quadrant and \
2550 not game.state.baseq[j] == game.state.kscmdr:
2554 if j>game.state.rembase:
2555 # no match found -- try later
2556 schedule(FBATTAK, expran(0.3*game.intime))
2559 # commander + starbase combination found -- launch attack
2560 game.battle = game.state.baseq[j]
2561 schedule(FCDBAS, randreal(1.0, 4.0))
2562 if game.isatb: # extra time if SC already attacking
2563 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2564 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2565 game.iseenit = False
2566 if not communicating():
2567 continue # No warning :-(
2571 proutn(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2572 prout(_(" reports that it is under attack and that it can"))
2573 proutn(_(" hold out only until stardate %d") % (int(scheduled(FCDBAS))))
2577 elif evcode == FSCDBAS: # Supercommander destroys base
2580 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2581 continue # WAS RETURN!
2583 game.battle = game.state.kscmdr
2585 elif evcode == FCDBAS: # Commander succeeds in destroying base
2588 # find the lucky pair
2589 for i in range(game.state.remcom):
2590 if game.state.kcmdr[i] == game.battle:
2592 if i > game.state.remcom or game.state.rembase == 0 or \
2593 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2594 # No action to take after all
2595 invalidate(game.battle)
2598 elif evcode == FSCMOVE: # Supercommander moves
2599 schedule(FSCMOVE, 0.2777)
2600 if not game.ientesc and not istract and game.isatb != 1 and \
2601 (not game.iscate or not game.justin):
2603 elif evcode == FDSPROB: # Move deep space probe
2604 schedule(FDSPROB, 0.01)
2605 game.probex += game.probeinx
2606 game.probey += game.probeiny
2607 i = (int)(game.probex/QUADSIZE +0.05)
2608 j = (int)(game.probey/QUADSIZE + 0.05)
2609 if game.probec.x != i or game.probec.y != j:
2612 if not VALID_QUADRANT(i, j) or \
2613 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2614 # Left galaxy or ran into supernova
2618 proutn(_("Lt. Uhura- \"The deep space probe "))
2619 if not VALID_QUADRANT(j, i):
2620 proutn(_("has left the galaxy"))
2622 proutn(_("is no longer transmitting"))
2626 if not communicating():
2629 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2630 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2631 # Update star chart if Radio is working or have access to radio
2633 chp = game.state.chart[game.probec.x][game.probec.y]
2634 chp.klingons = pdest.klingons
2635 chp.starbase = pdest.starbase
2636 chp.stars = pdest.stars
2637 pdest.charted = True
2638 game.proben -= 1 # One less to travel
2639 if game.proben == 0 and game.isarmed and pdest.stars:
2640 # lets blow the sucker!
2641 supernova(True, game.probec)
2643 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2645 elif evcode == FDISTR: # inhabited system issues distress call
2647 # try a whole bunch of times to find something suitable
2648 for i in range(100):
2649 # need a quadrant which is not the current one,
2650 # which has some stars which are inhabited and
2651 # not already under attack, which is not
2652 # supernova'ed, and which has some Klingons in it
2653 w = randplace(GALSIZE)
2654 q = game.state.galaxy[w.x][w.y]
2655 if not (game.quadrant == w or q.planet == None or \
2656 not q.planet.inhabited or \
2657 q.supernova or q.status!="secure" or q.klingons<=0):
2660 # can't seem to find one; ignore this call
2662 prout("=== Couldn't find location for distress event.")
2664 # got one!! Schedule its enslavement
2665 ev = schedule(FENSLV, expran(game.intime))
2667 q.status = distressed
2669 # tell the captain about it if we can
2671 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2673 prout(_("by a Klingon invasion fleet."))
2676 elif evcode == FENSLV: # starsystem is enslaved
2677 ev = unschedule(FENSLV)
2678 # see if current distress call still active
2679 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2683 q.status = "enslaved"
2685 # play stork and schedule the first baby
2686 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2687 ev2.quadrant = ev.quadrant
2689 # report the disaster if we can
2691 prout(_("Uhura- We've lost contact with starsystem %s") % \
2693 prout(_("in Quadrant %s.\n") % ev.quadrant)
2694 elif evcode == FREPRO: # Klingon reproduces
2695 # If we ever switch to a real event queue, we'll need to
2696 # explicitly retrieve and restore the x and y.
2697 ev = schedule(FREPRO, expran(1.0 * game.intime))
2698 # see if current distress call still active
2699 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2703 if game.state.remkl >=MAXKLGAME:
2704 continue # full right now
2705 # reproduce one Klingon
2707 if game.klhere >= MAXKLQUAD:
2709 # this quadrant not ok, pick an adjacent one
2710 for i in range(w.x - 1, w.x + 2):
2711 for j in range(w.y - 1, w.y + 2):
2712 if not VALID_QUADRANT(i, j):
2714 q = game.state.galaxy[w.x][w.y]
2715 # check for this quad ok (not full & no snova)
2716 if q.klingons >= MAXKLQUAD or q.supernova:
2720 continue # search for eligible quadrant failed
2725 game.state.remkl += 1
2727 if game.quadrant == w:
2729 newkling(game.klhere)
2730 # recompute time left
2732 # report the disaster if we can
2734 if game.quadrant == w:
2735 prout(_("Spock- sensors indicate the Klingons have"))
2736 prout(_("launched a warship from %s.") % q.planet)
2738 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2739 if q.planet != None:
2740 proutn(_("near %s") % q.planet)
2741 prout(_("in Quadrant %s.") % w)
2750 proutn(_("How long? "))
2755 origTime = delay = aaitem
2758 if delay >= game.state.remtime or game.nenhere != 0:
2759 proutn(_("Are you sure? "))
2762 # Alternate resting periods (events) with attacks
2766 game.resting = False
2767 if not game.resting:
2768 prout(_("%d stardates left.") % int(game.state.remtime))
2770 temp = game.optime = delay
2772 rtime = randreal(1.0, 2.0)
2776 if game.optime < delay:
2785 # Repair Deathray if long rest at starbase
2786 if origTime-delay >= 9.99 and game.condition == "docked":
2787 game.damage[DDRAY] = 0.0
2788 # leave if quadrant supernovas
2789 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2791 game.resting = False
2794 # A nova occurs. It is the result of having a star hit with a
2795 # photon torpedo, or possibly of a probe warhead going off.
2796 # Stars that go nova cause stars which surround them to undergo
2797 # the same probabilistic process. Klingons next to them are
2798 # destroyed. And if the starship is next to it, it gets zapped.
2799 # If the zap is too much, it gets destroyed.
2803 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2804 newc = coord(); scratch = coord()
2806 # Wow! We've supernova'ed
2807 supernova(False, nov)
2809 # handle initial nova
2810 game.quad[nov.x][nov.y] = IHDOT
2811 crmena(False, IHSTAR, "sector", nov)
2813 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2814 game.state.starkl += 1
2816 # Set up stack to recursively trigger adjacent stars
2817 bot = top = top2 = 1
2823 for mm in range(bot, top+1):
2824 for nn in range(1, 3+1): # nn,j represents coordinates around current
2825 for j in range(1, 3+1):
2828 scratch.x = hits[mm][1]+nn-2
2829 scratch.y = hits[mm][2]+j-2
2830 if not VALID_SECTOR(scratch.y, scratch.x):
2832 iquad = game.quad[scratch.x][scratch.y]
2833 # Empty space ends reaction
2834 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2836 elif iquad == IHSTAR: # Affect another star
2838 # This star supernovas
2839 scratch = supernova(False)
2842 hits[top2][1]=scratch.x
2843 hits[top2][2]=scratch.y
2844 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2845 game.state.starkl += 1
2846 crmena(True, IHSTAR, "sector", scratch)
2848 game.quad[scratch.x][scratch.y] = IHDOT
2849 elif iquad == IHP: # Destroy planet
2850 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2851 game.state.nplankl += 1
2852 crmena(True, IHP, "sector", scratch)
2853 prout(_(" destroyed."))
2854 game.iplnet.pclass = "destroyed"
2856 invalidate(game.plnet)
2860 game.quad[scratch.x][scratch.y] = IHDOT
2861 elif iquad == IHB: # Destroy base
2862 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2863 for i in range(game.state.rembase):
2864 if game.state.baseq[i] == game.quadrant:
2866 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2867 game.state.rembase -= 1
2868 invalidate(game.base)
2869 game.state.basekl += 1
2871 crmena(True, IHB, "sector", scratch)
2872 prout(_(" destroyed."))
2873 game.quad[scratch.x][scratch.y] = IHDOT
2874 elif iquad in (IHE, IHF): # Buffet ship
2875 prout(_("***Starship buffeted by nova."))
2877 if game.shield >= 2000.0:
2878 game.shield -= 2000.0
2880 diff = 2000.0 - game.shield
2884 prout(_("***Shields knocked out."))
2885 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2887 game.energy -= 2000.0
2888 if game.energy <= 0:
2891 # add in course nova contributes to kicking starship
2892 icx += game.sector.x-hits[mm][1]
2893 icy += game.sector.y-hits[mm][2]
2895 elif iquad == IHK: # kill klingon
2896 deadkl(scratch,iquad, scratch)
2897 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2898 for ll in range(game.nenhere):
2899 if game.ks[ll] == scratch:
2901 game.kpower[ll] -= 800.0 # If firepower is lost, die
2902 if game.kpower[ll] <= 0.0:
2903 deadkl(scratch, iquad, scratch)
2905 newc.x = scratch.x + scratch.x - hits[mm][1]
2906 newc.y = scratch.y + scratch.y - hits[mm][2]
2907 crmena(True, iquad, "sector", scratch)
2908 proutn(_(" damaged"))
2909 if not VALID_SECTOR(newc.x, newc.y):
2910 # can't leave quadrant
2913 iquad1 = game.quad[newc.x][newc.y]
2914 if iquad1 == IHBLANK:
2915 proutn(_(", blasted into "))
2916 crmena(False, IHBLANK, "sector", newc)
2918 deadkl(scratch, iquad, newc)
2921 # can't move into something else
2924 proutn(_(", buffeted to Sector %s") % newc)
2925 game.quad[scratch.x][scratch.y] = IHDOT
2926 game.quad[newc.x][newc.y] = iquad
2928 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc)
2937 # Starship affected by nova -- kick it away.
2938 game.dist = kount*0.1
2941 game.direc = course[3*(icx+1)+icy+2]
2942 if game.direc == 0.0:
2944 if game.dist == 0.0:
2946 game.optime = 10.0*game.dist/16.0
2948 prout(_("Force of nova displaces starship."))
2949 imove(novapush=True)
2950 game.optime = 10.0*game.dist/16.0
2953 def supernova(induced, w=None):
2954 # star goes supernova
2961 # Scheduled supernova -- select star
2962 # logic changed here so that we won't favor quadrants in top
2964 for nq.x in range(GALSIZE):
2965 for nq.y in range(GALSIZE):
2966 stars += game.state.galaxy[nq.x][nq.y].stars
2968 return # nothing to supernova exists
2969 num = randrange(stars) + 1
2970 for nq.x in range(GALSIZE):
2971 for nq.y in range(GALSIZE):
2972 num -= game.state.galaxy[nq.x][nq.y].stars
2978 proutn("=== Super nova here?")
2981 if not nq == game.quadrant or game.justin:
2982 # it isn't here, or we just entered (treat as enroute)
2985 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2986 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2989 # we are in the quadrant!
2990 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2991 for ns.x in range(QUADSIZE):
2992 for ns.y in range(QUADSIZE):
2993 if game.quad[ns.x][ns.y]==IHSTAR:
3000 prouts(_("***RED ALERT! RED ALERT!"))
3002 prout(_("***Incipient supernova detected at Sector %s") % ns)
3003 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
3004 proutn(_("Emergency override attempts t"))
3005 prouts("***************")
3010 # destroy any Klingons in supernovaed quadrant
3011 kldead = game.state.galaxy[nq.x][nq.y].klingons
3012 game.state.galaxy[nq.x][nq.y].klingons = 0
3013 if nq == game.state.kscmdr:
3014 # did in the Supercommander!
3015 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
3019 if game.state.remcom:
3020 maxloop = game.state.remcom
3021 for l in range(maxloop):
3022 if game.state.kcmdr[l] == nq:
3023 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
3024 invalidate(game.state.kcmdr[game.state.remcom])
3025 game.state.remcom -= 1
3027 if game.state.remcom==0:
3030 game.state.remkl -= kldead
3031 # destroy Romulans and planets in supernovaed quadrant
3032 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
3033 game.state.galaxy[nq.x][nq.y].romulans = 0
3034 game.state.nromrem -= nrmdead
3036 for loop in range(game.inplan):
3037 if game.state.planets[loop].w == nq:
3038 game.state.planets[loop].pclass = "destroyed"
3040 # Destroy any base in supernovaed quadrant
3041 if game.state.rembase:
3042 maxloop = game.state.rembase
3043 for loop in range(maxloop):
3044 if game.state.baseq[loop] == nq:
3045 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3046 invalidate(game.state.baseq[game.state.rembase])
3047 game.state.rembase -= 1
3049 # If starship caused supernova, tally up destruction
3051 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3052 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3053 game.state.nplankl += npdead
3054 # mark supernova in galaxy and in star chart
3055 if game.quadrant == nq or communicating():
3056 game.state.galaxy[nq.x][nq.y].supernova = True
3057 # If supernova destroys last Klingons give special message
3058 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3061 prout(_("Lucky you!"))
3062 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3065 # if some Klingons remain, continue or die in supernova
3070 # Code from finish.c ends here.
3073 # self-destruct maneuver
3074 # Finish with a BANG!
3076 if damaged(DCOMPTR):
3077 prout(_("Computer damaged; cannot execute destruct sequence."))
3079 prouts(_("---WORKING---")); skip(1)
3080 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3081 prouts(" 10"); skip(1)
3082 prouts(" 9"); skip(1)
3083 prouts(" 8"); skip(1)
3084 prouts(" 7"); skip(1)
3085 prouts(" 6"); skip(1)
3087 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3089 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3091 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3095 if game.passwd != citem:
3096 prouts(_("PASSWORD-REJECTED;"))
3098 prouts(_("CONTINUITY-EFFECTED"))
3101 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3102 prouts(" 5"); skip(1)
3103 prouts(" 4"); skip(1)
3104 prouts(" 3"); skip(1)
3105 prouts(" 2"); skip(1)
3106 prouts(" 1"); skip(1)
3108 prouts(_("GOODBYE-CRUEL-WORLD"))
3116 prouts(_("********* Entropy of "))
3118 prouts(_(" maximized *********"))
3122 if game.nenhere != 0:
3123 whammo = 25.0 * game.energy
3125 while l <= game.nenhere:
3126 if game.kpower[l]*game.kdist[l] <= whammo:
3127 deadkl(game.ks[l], game.quad[game.ks[l].x][game.ks[l].y], game.ks[l])
3132 "Compute our rate of kils over time."
3133 elapsed = game.state.date - game.indate
3134 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3137 starting = (game.inkling + game.incom + game.inscom)
3138 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3139 return (starting - remaining)/elapsed
3143 badpt = 5.0*game.state.starkl + \
3145 10.0*game.state.nplankl + \
3146 300*game.state.nworldkl + \
3148 100.0*game.state.basekl +\
3150 if game.ship == IHF:
3152 elif game.ship == None:
3157 # end the game, with appropriate notfications
3161 prout(_("It is stardate %.1f.") % game.state.date)
3163 if ifin == FWON: # Game has been won
3164 if game.state.nromrem != 0:
3165 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3168 prout(_("You have smashed the Klingon invasion fleet and saved"))
3169 prout(_("the Federation."))
3174 badpt = 0.0 # Close enough!
3175 # killsPerDate >= RateMax
3176 if game.state.date-game.indate < 5.0 or \
3177 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3179 prout(_("In fact, you have done so well that Starfleet Command"))
3180 if game.skill == SKILL_NOVICE:
3181 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3182 elif game.skill == SKILL_FAIR:
3183 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3184 elif game.skill == SKILL_GOOD:
3185 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3186 elif game.skill == SKILL_EXPERT:
3187 prout(_("promotes you to Commodore Emeritus."))
3189 prout(_("Now that you think you're really good, try playing"))
3190 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3191 elif game.skill == SKILL_EMERITUS:
3193 proutn(_("Computer- "))
3194 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3196 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3198 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3200 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3202 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3204 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3206 prout(_("Now you can retire and write your own Star Trek game!"))
3208 elif game.skill >= SKILL_EXPERT:
3209 if game.thawed and not idebug:
3210 prout(_("You cannot get a citation, so..."))
3212 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3216 # Only grant long life if alive (original didn't!)
3218 prout(_("LIVE LONG AND PROSPER."))
3223 elif ifin == FDEPLETE: # Federation Resources Depleted
3224 prout(_("Your time has run out and the Federation has been"))
3225 prout(_("conquered. Your starship is now Klingon property,"))
3226 prout(_("and you are put on trial as a war criminal. On the"))
3227 proutn(_("basis of your record, you are "))
3228 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3229 prout(_("acquitted."))
3231 prout(_("LIVE LONG AND PROSPER."))
3233 prout(_("found guilty and"))
3234 prout(_("sentenced to death by slow torture."))
3238 elif ifin == FLIFESUP:
3239 prout(_("Your life support reserves have run out, and"))
3240 prout(_("you die of thirst, starvation, and asphyxiation."))
3241 prout(_("Your starship is a derelict in space."))
3243 prout(_("Your energy supply is exhausted."))
3245 prout(_("Your starship is a derelict in space."))
3246 elif ifin == FBATTLE:
3249 prout(_("has been destroyed in battle."))
3251 prout(_("Dulce et decorum est pro patria mori."))
3253 prout(_("You have made three attempts to cross the negative energy"))
3254 prout(_("barrier which surrounds the galaxy."))
3256 prout(_("Your navigation is abominable."))
3259 prout(_("Your starship has been destroyed by a nova."))
3260 prout(_("That was a great shot."))
3262 elif ifin == FSNOVAED:
3265 prout(_(" has been fried by a supernova."))
3266 prout(_("...Not even cinders remain..."))
3267 elif ifin == FABANDN:
3268 prout(_("You have been captured by the Klingons. If you still"))
3269 prout(_("had a starbase to be returned to, you would have been"))
3270 prout(_("repatriated and given another chance. Since you have"))
3271 prout(_("no starbases, you will be mercilessly tortured to death."))
3272 elif ifin == FDILITHIUM:
3273 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3274 elif ifin == FMATERIALIZE:
3275 prout(_("Starbase was unable to re-materialize your starship."))
3276 prout(_("Sic transit gloria mundi"))
3277 elif ifin == FPHASER:
3280 prout(_(" has been cremated by its own phasers."))
3282 prout(_("You and your landing party have been"))
3283 prout(_("converted to energy, disipating through space."))
3284 elif ifin == FMINING:
3285 prout(_("You are left with your landing party on"))
3286 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3288 prout(_("They are very fond of \"Captain Kirk\" soup."))
3290 proutn(_("Without your leadership, the "))
3292 prout(_(" is destroyed."))
3293 elif ifin == FDPLANET:
3294 prout(_("You and your mining party perish."))
3296 prout(_("That was a great shot."))
3299 prout(_("The Galileo is instantly annihilated by the supernova."))
3300 prout(_("You and your mining party are atomized."))
3302 proutn(_("Mr. Spock takes command of the "))
3305 prout(_("joins the Romulans, reigning terror on the Federation."))
3306 elif ifin == FPNOVA:
3307 prout(_("You and your mining party are atomized."))
3309 proutn(_("Mr. Spock takes command of the "))
3312 prout(_("joins the Romulans, reigning terror on the Federation."))
3313 elif ifin == FSTRACTOR:
3314 prout(_("The shuttle craft Galileo is also caught,"))
3315 prout(_("and breaks up under the strain."))
3317 prout(_("Your debris is scattered for millions of miles."))
3318 proutn(_("Without your leadership, the "))
3320 prout(_(" is destroyed."))
3322 prout(_("The mutants attack and kill Spock."))
3323 prout(_("Your ship is captured by Klingons, and"))
3324 prout(_("your crew is put on display in a Klingon zoo."))
3325 elif ifin == FTRIBBLE:
3326 prout(_("Tribbles consume all remaining water,"))
3327 prout(_("food, and oxygen on your ship."))
3329 prout(_("You die of thirst, starvation, and asphyxiation."))
3330 prout(_("Your starship is a derelict in space."))
3332 prout(_("Your ship is drawn to the center of the black hole."))
3333 prout(_("You are crushed into extremely dense matter."))
3335 prout(_("Your last crew member has died."))
3336 if game.ship == IHF:
3338 elif game.ship == IHE:
3341 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3342 goodies = game.state.remres/game.inresor
3343 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3344 if goodies/baddies >= randreal(1.0, 1.5):
3345 prout(_("As a result of your actions, a treaty with the Klingon"))
3346 prout(_("Empire has been signed. The terms of the treaty are"))
3347 if goodies/baddies >= randreal(3.0):
3348 prout(_("favorable to the Federation."))
3350 prout(_("Congratulations!"))
3352 prout(_("highly unfavorable to the Federation."))
3354 prout(_("The Federation will be destroyed."))
3356 prout(_("Since you took the last Klingon with you, you are a"))
3357 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3358 prout(_("statue in your memory. Rest in peace, and try not"))
3359 prout(_("to think about pigeons."))
3364 # compute player's score
3365 timused = game.state.date - game.indate
3367 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3369 perdate = killrate()
3370 ithperd = 500*perdate + 0.5
3373 iwon = 100*game.skill
3374 if game.ship == IHE:
3376 elif game.ship == IHF:
3380 if not game.gamewon:
3381 game.state.nromrem = 0 # None captured if no win
3382 iscore = 10*(game.inkling - game.state.remkl) \
3383 + 50*(game.incom - game.state.remcom) \
3385 + 20*(game.inrom - game.state.nromrem) \
3386 + 200*(game.inscom - game.state.nscrem) \
3387 - game.state.nromrem \
3392 prout(_("Your score --"))
3393 if game.inrom - game.state.nromrem:
3394 prout(_("%6d Romulans destroyed %5d") %
3395 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3396 if game.state.nromrem:
3397 prout(_("%6d Romulans captured %5d") %
3398 (game.state.nromrem, game.state.nromrem))
3399 if game.inkling - game.state.remkl:
3400 prout(_("%6d ordinary Klingons destroyed %5d") %
3401 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3402 if game.incom - game.state.remcom:
3403 prout(_("%6d Klingon commanders destroyed %5d") %
3404 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3405 if game.inscom - game.state.nscrem:
3406 prout(_("%6d Super-Commander destroyed %5d") %
3407 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3409 prout(_("%6.2f Klingons per stardate %5d") %
3411 if game.state.starkl:
3412 prout(_("%6d stars destroyed by your action %5d") %
3413 (game.state.starkl, -5*game.state.starkl))
3414 if game.state.nplankl:
3415 prout(_("%6d planets destroyed by your action %5d") %
3416 (game.state.nplankl, -10*game.state.nplankl))
3417 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3418 prout(_("%6d inhabited planets destroyed by your action %5d") %
3419 (game.state.nplankl, -300*game.state.nworldkl))
3420 if game.state.basekl:
3421 prout(_("%6d bases destroyed by your action %5d") %
3422 (game.state.basekl, -100*game.state.basekl))
3424 prout(_("%6d calls for help from starbase %5d") %
3425 (game.nhelp, -45*game.nhelp))
3427 prout(_("%6d casualties incurred %5d") %
3428 (game.casual, -game.casual))
3430 prout(_("%6d crew abandoned in space %5d") %
3431 (game.abandoned, -3*game.abandoned))
3433 prout(_("%6d ship(s) lost or destroyed %5d") %
3434 (klship, -100*klship))
3436 prout(_("Penalty for getting yourself killed -200"))
3438 proutn(_("Bonus for winning "))
3439 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3440 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3441 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3442 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3443 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3444 prout(" %5d" % iwon)
3446 prout(_("TOTAL SCORE %5d") % iscore)
3449 # emit winner's commemmorative plaque
3452 proutn(_("File or device name for your plaque: "))
3455 fp = open(winner, "w")
3458 prout(_("Invalid name."))
3460 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3462 # The 38 below must be 64 for 132-column paper
3463 nskip = 38 - len(winner)/2
3464 fp.write("\n\n\n\n")
3465 # --------DRAW ENTERPRISE PICTURE.
3466 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3467 fp.write(" EEE E : : : E\n" )
3468 fp.write(" EE EEE E : : NCC-1701 : E\n")
3469 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3470 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3471 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3472 fp.write(" EEEEEEE EEEEE E E E E\n")
3473 fp.write(" EEE E E E E\n")
3474 fp.write(" E E E E\n")
3475 fp.write(" EEEEEEEEEEEEE E E\n")
3476 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3477 fp.write(" :E : EEEE E\n")
3478 fp.write(" .-E -:----- E\n")
3479 fp.write(" :E : E\n")
3480 fp.write(" EE : EEEEEEEE\n")
3481 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3483 fp.write(_(" U. S. S. ENTERPRISE\n"))
3484 fp.write("\n\n\n\n")
3485 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3487 fp.write(_(" Starfleet Command bestows to you\n"))
3489 fp.write("%*s%s\n\n" % (nskip, "", winner))
3490 fp.write(_(" the rank of\n\n"))
3491 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3493 if game.skill == SKILL_EXPERT:
3494 fp.write(_(" Expert level\n\n"))
3495 elif game.skill == SKILL_EMERITUS:
3496 fp.write(_("Emeritus level\n\n"))
3498 fp.write(_(" Cheat level\n\n"))
3499 timestring = ctime()
3500 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3501 (timestring+4, timestring+20, timestring+11))
3502 fp.write(_(" Your score: %d\n\n") % iscore)
3503 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3506 # Code from io.c begins here
3508 rows = linecount = 0 # for paging
3511 fullscreen_window = None
3512 srscan_window = None
3513 report_window = None
3514 status_window = None
3515 lrscan_window = None
3516 message_window = None
3517 prompt_window = None
3521 "wrap up, either normally or due to signal"
3522 if game.options & OPTION_CURSES:
3529 sys.stdout.write('\n')
3535 #setlocale(LC_ALL, "")
3536 #bindtextdomain(PACKAGE, LOCALEDIR)
3537 #textdomain(PACKAGE)
3538 if atexit.register(outro):
3539 sys.stderr.write("Unable to register outro(), exiting...\n")
3541 if not (game.options & OPTION_CURSES):
3542 ln_env = os.getenv("LINES")
3548 stdscr = curses.initscr()
3553 curses.start_color()
3554 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3555 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3556 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3557 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3558 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3559 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3560 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3561 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3563 global fullscreen_window, srscan_window, report_window, status_window
3564 global lrscan_window, message_window, prompt_window
3565 fullscreen_window = stdscr
3566 srscan_window = curses.newwin(12, 25, 0, 0)
3567 report_window = curses.newwin(11, 0, 1, 25)
3568 status_window = curses.newwin(10, 0, 1, 39)
3569 lrscan_window = curses.newwin(5, 0, 0, 64)
3570 message_window = curses.newwin(0, 0, 12, 0)
3571 prompt_window = curses.newwin(1, 0, rows-2, 0)
3572 message_window.scrollok(True)
3573 setwnd(fullscreen_window)
3577 "wait for user action -- OK to do nothing if on a TTY"
3578 if game.options & OPTION_CURSES:
3583 if game.skill > SKILL_FAIR:
3584 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3586 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3590 if game.skill > SKILL_FAIR:
3591 prompt = _("[CONTINUE?]")
3593 prompt = _("[PRESS ENTER TO CONTINUE]")
3595 if game.options & OPTION_CURSES:
3597 setwnd(prompt_window)
3598 prompt_window.wclear()
3599 prompt_window.addstr(prompt)
3600 prompt_window.getstr()
3601 prompt_window.clear()
3602 prompt_window.refresh()
3603 setwnd(message_window)
3606 sys.stdout.write('\n')
3609 for j in range(rows):
3610 sys.stdout.write('\n')
3614 "Skip i lines. Pause game if this would cause a scrolling event."
3615 for dummy in range(i):
3616 if game.options & OPTION_CURSES:
3617 (y, x) = curwnd.getyx()
3618 (my, mx) = curwnd.getmaxyx()
3619 if curwnd == message_window and y >= my - 3:
3627 if rows and linecount >= rows:
3630 sys.stdout.write('\n')
3633 "Utter a line with no following line feed."
3634 if game.options & OPTION_CURSES:
3638 sys.stdout.write(line)
3648 if not replayfp or replayfp.closed: # Don't slow down replays
3651 if game.options & OPTION_CURSES:
3655 if not replayfp or replayfp.closed:
3659 "Get a line of input."
3660 if game.options & OPTION_CURSES:
3661 line = curwnd.getstr() + "\n"
3664 if replayfp and not replayfp.closed:
3666 line = replayfp.readline()
3669 prout("*** Replay finished")
3672 elif line[0] != "#":
3677 logfp.write(line + "\n")
3681 "Change windows -- OK for this to be a no-op in tty mode."
3683 if game.options & OPTION_CURSES:
3685 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3688 "Clear to end of line -- can be a no-op in tty mode"
3689 if game.options & OPTION_CURSES:
3694 "Clear screen -- can be a no-op in tty mode."
3696 if game.options & OPTION_CURSES:
3702 def textcolor(color):
3703 "Set the current text color"
3704 if game.options & OPTION_CURSES:
3705 if color == DEFAULT:
3707 elif color == BLACK:
3708 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3710 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3711 elif color == GREEN:
3712 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3714 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3716 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3717 elif color == MAGENTA:
3718 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3719 elif color == BROWN:
3720 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3721 elif color == LIGHTGRAY:
3722 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3723 elif color == DARKGRAY:
3724 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3725 elif color == LIGHTBLUE:
3726 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3727 elif color == LIGHTGREEN:
3728 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3729 elif color == LIGHTCYAN:
3730 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3731 elif color == LIGHTRED:
3732 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3733 elif color == LIGHTMAGENTA:
3734 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3735 elif color == YELLOW:
3736 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3737 elif color == WHITE:
3738 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3741 "Set highlight video, if this is reasonable."
3742 if game.options & OPTION_CURSES:
3743 curwnd.attron(curses.A_REVERSE)
3746 # Things past this point have policy implications.
3750 "Hook to be called after moving to redraw maps."
3751 if game.options & OPTION_CURSES:
3754 setwnd(srscan_window)
3758 setwnd(status_window)
3759 status_window.clear()
3760 status_window.move(0, 0)
3761 setwnd(report_window)
3762 report_window.clear()
3763 report_window.move(0, 0)
3765 setwnd(lrscan_window)
3766 lrscan_window.clear()
3767 lrscan_window.move(0, 0)
3768 lrscan(silent=False)
3770 def put_srscan_sym(w, sym):
3771 "Emit symbol for short-range scan."
3772 srscan_window.move(w.x+1, w.y*2+2)
3773 srscan_window.addch(sym)
3774 srscan_window.refresh()
3777 "Enemy fall down, go boom."
3778 if game.options & OPTION_CURSES:
3780 setwnd(srscan_window)
3781 srscan_window.attron(curses.A_REVERSE)
3782 put_srscan_sym(w, game.quad[w.x][w.y])
3786 srscan_window.attroff(curses.A_REVERSE)
3787 put_srscan_sym(w, game.quad[w.x][w.y])
3788 curses.delay_output(500)
3789 setwnd(message_window)
3792 "Sound and visual effects for teleportation."
3793 if game.options & OPTION_CURSES:
3795 setwnd(message_window)
3797 prouts(" . . . . . ")
3798 if game.options & OPTION_CURSES:
3799 #curses.delay_output(1000)
3803 def tracktorpedo(w, l, i, n, iquad):
3804 "Torpedo-track animation."
3805 if not game.options & OPTION_CURSES:
3809 proutn(_("Track for torpedo number %d- ") % i)
3812 proutn(_("Torpedo track- "))
3815 proutn("%d - %d " % (w.x, w.y))
3817 if not damaged(DSRSENS) or game.condition=="docked":
3818 if i != 1 and l == 1:
3821 if (iquad==IHDOT) or (iquad==IHBLANK):
3822 put_srscan_sym(w, '+')
3826 put_srscan_sym(w, iquad)
3828 curwnd.attron(curses.A_REVERSE)
3829 put_srscan_sym(w, iquad)
3833 curwnd.attroff(curses.A_REVERSE)
3834 put_srscan_sym(w, iquad)
3836 proutn("%d - %d " % (w.x, w.y))
3839 "Display the current galaxy chart."
3840 if game.options & OPTION_CURSES:
3841 setwnd(message_window)
3842 message_window.clear()
3844 if game.options & OPTION_TTY:
3849 def prstat(txt, data):
3851 if game.options & OPTION_CURSES:
3853 setwnd(status_window)
3855 proutn(" " * (NSYM - len(txt)))
3858 if game.options & OPTION_CURSES:
3859 setwnd(report_window)
3861 # Code from moving.c begins here
3863 def imove(novapush):
3864 # movement execution for warp, impulse, supernova, and tractor-beam events
3865 w = coord(); final = coord()
3868 def no_quad_change():
3869 # No quadrant change -- compute new average enemy distances
3870 game.quad[game.sector.x][game.sector.y] = game.ship
3872 for m in range(game.nenhere):
3873 finald = distance(w, game.ks[m])
3874 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3875 game.kdist[m] = finald
3877 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3879 for m in range(game.nenhere):
3880 game.kavgd[m] = game.kdist[m]
3883 setwnd(message_window)
3886 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3887 game.inorbit = False
3888 angle = ((15.0 - game.direc) * 0.5235988)
3889 deltax = -math.sin(angle)
3890 deltay = math.cos(angle)
3891 if math.fabs(deltax) > math.fabs(deltay):
3892 bigger = math.fabs(deltax)
3894 bigger = math.fabs(deltay)
3897 # If tractor beam is to occur, don't move full distance
3898 if game.state.date+game.optime >= scheduled(FTBEAM):
3900 game.condition = "red"
3901 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3902 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3903 # Move within the quadrant
3904 game.quad[game.sector.x][game.sector.y] = IHDOT
3907 n = int(10.0*game.dist*bigger+0.5)
3909 for m in range(1, n+1):
3914 if not VALID_SECTOR(w.x, w.y):
3915 # Leaving quadrant -- allow final enemy attack
3916 # Don't do it if being pushed by Nova
3917 if game.nenhere != 0 and not novapush:
3919 for m in range(game.nenhere):
3920 finald = distance(w, game.ks[m])
3921 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
3923 # Stas Sergeev added the condition
3924 # that attacks only happen if Klingons
3925 # are present and your skill is good.
3927 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3931 # compute final position -- new quadrant and sector
3932 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3933 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3934 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3935 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3936 # check for edge of galaxy
3946 if w.x >= GALSIZE*QUADSIZE:
3947 w.x = (GALSIZE*QUADSIZE*2) - w.x
3949 if w.y >= GALSIZE*QUADSIZE:
3950 w.y = (GALSIZE*QUADSIZE*2) - w.y
3958 if game.nkinks == 3:
3959 # Three strikes -- you're out!
3963 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3964 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3965 prout(_("YOU WILL BE DESTROYED."))
3966 # Compute final position in new quadrant
3967 if trbeam: # Don't bother if we are to be beamed
3969 game.quadrant.x = w.x/QUADSIZE
3970 game.quadrant.y = w.y/QUADSIZE
3971 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3972 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3974 prout(_("Entering Quadrant %s.") % game.quadrant)
3975 game.quad[game.sector.x][game.sector.y] = game.ship
3977 if game.skill>SKILL_NOVICE:
3980 iquad = game.quad[w.x][w.y]
3982 # object encountered in flight path
3983 stopegy = 50.0*game.dist/game.optime
3984 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3985 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3987 ram(False, iquad, game.sector)
3989 elif iquad == IHBLANK:
3991 prouts(_("***RED ALERT! RED ALERT!"))
3995 proutn(_(" pulled into black hole at Sector %s") % w)
3997 # Getting pulled into a black hole was certain
3998 # death in Almy's original. Stas Sergeev added a
3999 # possibility that you'll get timewarped instead.
4002 for m in range(NDEVICES):
4003 if game.damage[m]>0:
4005 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
4006 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
4016 proutn(_(" encounters Tholian web at %s;") % w)
4018 proutn(_(" blocked by object at %s;") % w)
4019 proutn(_("Emergency stop required "))
4020 prout(_("%2d units of energy.") % int(stopegy))
4021 game.energy -= stopegy
4022 final.x = x-deltax+0.5
4023 final.y = y-deltay+0.5
4025 if game.energy <= 0:
4031 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4038 # dock our ship at a starbase
4040 if game.condition == "docked" and verbose:
4041 prout(_("Already docked."))
4044 prout(_("You must first leave standard orbit."))
4046 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4048 prout(_(" not adjacent to base."))
4050 game.condition = "docked"
4054 if game.energy < game.inenrg:
4055 game.energy = game.inenrg
4056 game.shield = game.inshld
4057 game.torps = game.intorps
4058 game.lsupres = game.inlsr
4059 game.state.crew = FULLCREW
4060 if not damaged(DRADIO) and \
4061 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4062 # get attack report from base
4063 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4067 # This program originally required input in terms of a (clock)
4068 # direction and distance. Somewhere in history, it was changed to
4069 # cartesian coordinates. So we need to convert. Probably
4070 # "manual" input should still be done this way -- it's a real
4071 # pain if the computer isn't working! Manual mode is still confusing
4072 # because it involves giving x and y motions, yet the coordinates
4073 # are always displayed y - x, where +y is downward!
4075 def getcourse(isprobe, akey):
4076 # get course and distance
4078 dquad = copy.copy(game.quadrant)
4079 navmode = "unspecified"
4083 if game.landed and not isprobe:
4084 prout(_("Dummy! You can't leave standard orbit until you"))
4085 proutn(_("are back aboard the ship."))
4088 while navmode == "unspecified":
4089 if damaged(DNAVSYS):
4091 prout(_("Computer damaged; manual navigation only"))
4093 prout(_("Computer damaged; manual movement only"))
4098 if isprobe and akey != -1:
4099 # For probe launch, use pre-scanned value first time
4105 proutn(_("Manual or automatic- "))
4108 elif key == IHALPHA:
4113 elif isit("automatic"):
4114 navmode = "automatic"
4123 prout(_("(Manual navigation assumed.)"))
4125 prout(_("(Manual movement assumed.)"))
4128 if navmode == "automatic":
4131 proutn(_("Target quadrant or quadrant§or- "))
4133 proutn(_("Destination sector or quadrant§or- "))
4140 xi = int(round(aaitem))-1
4145 xj = int(round(aaitem))-1
4148 # both quadrant and sector specified
4149 xk = int(round(aaitem))-1
4154 xl = int(round(aaitem))-1
4160 # only one pair of numbers was specified
4162 # only quadrant specified -- go to center of dest quad
4165 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4167 # only sector specified
4171 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4178 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4180 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4181 # the actual deltas get computed here
4182 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4183 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4186 proutn(_("X and Y displacements- "))
4200 # Check for zero movement
4201 if deltax == 0 and deltay == 0:
4204 if itemp == "verbose" and not isprobe:
4206 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4207 # Course actually laid in.
4208 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4209 game.direc = math.atan2(deltax, deltay)*1.90985932
4210 if game.direc < 0.0:
4216 # move under impulse power
4218 if damaged(DIMPULS):
4221 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4223 if game.energy > 30.0:
4224 if not getcourse(isprobe=False, akey=0):
4226 power = 20.0 + 100.0*game.dist
4229 if power >= game.energy:
4230 # Insufficient power for trip
4232 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4233 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4234 if game.energy > 30:
4235 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4236 int(0.01 * (game.energy-20.0)-0.05))
4237 prout(_(" quadrants.\""))
4239 prout(_("quadrant. They are, therefore, useless.\""))
4242 # Make sure enough time is left for the trip
4243 game.optime = game.dist/0.095
4244 if game.optime >= game.state.remtime:
4245 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4246 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4247 proutn(_("we dare spend the time?\" "))
4250 # Activate impulse engines and pay the cost
4251 imove(novapush=False)
4255 power = 20.0 + 100.0*game.dist
4256 game.energy -= power
4257 game.optime = game.dist/0.095
4258 if game.energy <= 0:
4263 # move under warp drive
4264 blooey = False; twarp = False
4265 if not timewarp: # Not WARPX entry
4267 if game.damage[DWARPEN] > 10.0:
4270 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4272 if damaged(DWARPEN) and game.warpfac > 4.0:
4275 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4276 prout(_(" is repaired, I can only give you warp 4.\""))
4278 # Read in course and distance
4279 if not getcourse(isprobe=False, akey=0):
4281 # Make sure starship has enough energy for the trip
4282 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4283 if power >= game.energy:
4284 # Insufficient power for trip
4287 prout(_("Engineering to bridge--"))
4288 if not game.shldup or 0.5*power > game.energy:
4289 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4291 prout(_("We can't do it, Captain. We don't have enough energy."))
4293 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4296 prout(_("if you'll lower the shields."))
4300 prout(_("We haven't the energy to go that far with the shields up."))
4303 # Make sure enough time is left for the trip
4304 game.optime = 10.0*game.dist/game.wfacsq
4305 if game.optime >= 0.8*game.state.remtime:
4307 prout(_("First Officer Spock- \"Captain, I compute that such"))
4308 proutn(_(" a trip would require approximately %2.0f") %
4309 (100.0*game.optime/game.state.remtime))
4310 prout(_(" percent of our"))
4311 proutn(_(" remaining time. Are you sure this is wise?\" "))
4317 if game.warpfac > 6.0:
4318 # Decide if engine damage will occur
4319 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4320 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4321 if prob > randreal():
4323 game.dist = randreal(game.dist)
4324 # Decide if time warp will occur
4325 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4327 if idebug and game.warpfac==10 and not twarp:
4329 proutn("=== Force time warp? ")
4333 # If time warp or engine damage, check path
4334 # If it is obstructed, don't do warp or damage
4335 angle = ((15.0-game.direc)*0.5235998)
4336 deltax = -math.sin(angle)
4337 deltay = math.cos(angle)
4338 if math.fabs(deltax) > math.fabs(deltay):
4339 bigger = math.fabs(deltax)
4341 bigger = math.fabs(deltay)
4345 n = 10.0 * game.dist * bigger +0.5
4348 for l in range(1, n+1):
4353 if not VALID_SECTOR(ix, iy):
4355 if game.quad[ix][iy] != IHDOT:
4358 # Activate Warp Engines and pay the cost
4359 imove(novapush=False)
4362 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4363 if game.energy <= 0:
4365 game.optime = 10.0*game.dist/game.wfacsq
4369 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4371 prout(_("Engineering to bridge--"))
4372 prout(_(" Scott here. The warp engines are damaged."))
4373 prout(_(" We'll have to reduce speed to warp 4."))
4378 # change the warp factor
4384 proutn(_("Warp factor- "))
4389 if game.damage[DWARPEN] > 10.0:
4390 prout(_("Warp engines inoperative."))
4392 if damaged(DWARPEN) and aaitem > 4.0:
4393 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4394 prout(_(" but right now we can only go warp 4.\""))
4397 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4400 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4402 oldfac = game.warpfac
4403 game.warpfac = aaitem
4404 game.wfacsq=game.warpfac*game.warpfac
4405 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4406 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4409 if game.warpfac < 8.00:
4410 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4412 if game.warpfac == 10.0:
4413 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4415 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4419 # cope with being tossed out of quadrant by supernova or yanked by beam
4421 # is captain on planet?
4423 if damaged(DTRANSP):
4426 prout(_("Scotty rushes to the transporter controls."))
4428 prout(_("But with the shields up it's hopeless."))
4430 prouts(_("His desperate attempt to rescue you . . ."))
4435 prout(_("SUCCEEDS!"))
4438 proutn(_("The crystals mined were "))
4446 # Check to see if captain in shuttle craft
4451 # Inform captain of attempt to reach safety
4455 prouts(_("***RED ALERT! RED ALERT!"))
4459 prout(_(" has stopped in a quadrant containing"))
4460 prouts(_(" a supernova."))
4462 proutn(_("***Emergency automatic override attempts to hurl "))
4465 prout(_("safely out of quadrant."))
4466 if not damaged(DRADIO):
4467 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4468 # Try to use warp engines
4469 if damaged(DWARPEN):
4471 prout(_("Warp engines damaged."))
4474 game.warpfac = randreal(6.0, 8.0)
4475 game.wfacsq = game.warpfac * game.warpfac
4476 prout(_("Warp factor set to %d") % int(game.warpfac))
4477 power = 0.75*game.energy
4478 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4479 distreq = randreal(math.sqrt(2))
4480 if distreq < game.dist:
4482 game.optime = 10.0*game.dist/game.wfacsq
4483 game.direc = randreal(12) # How dumb!
4485 game.inorbit = False
4488 # This is bad news, we didn't leave quadrant.
4492 prout(_("Insufficient energy to leave quadrant."))
4495 # Repeat if another snova
4496 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4498 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4499 finish(FWON) # Snova killed remaining enemy.
4502 # let's do the time warp again
4503 prout(_("***TIME WARP ENTERED."))
4504 if game.state.snap and withprob(0.5):
4506 prout(_("You are traveling backwards in time %d stardates.") %
4507 int(game.state.date-game.snapsht.date))
4508 game.state = game.snapsht
4509 game.state.snap = False
4510 if game.state.remcom:
4511 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4512 schedule(FBATTAK, expran(0.3*game.intime))
4513 schedule(FSNOVA, expran(0.5*game.intime))
4514 # next snapshot will be sooner
4515 schedule(FSNAP, expran(0.25*game.state.remtime))
4517 if game.state.nscrem:
4518 schedule(FSCMOVE, 0.2777)
4522 invalidate(game.battle)
4524 # Make sure Galileo is consistant -- Snapshot may have been taken
4525 # when on planet, which would give us two Galileos!
4527 for l in range(game.inplan):
4528 if game.state.planets[l].known == "shuttle_down":
4530 if game.iscraft == "onship" and game.ship==IHE:
4531 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4532 game.iscraft = "offship"
4533 # Likewise, if in the original time the Galileo was abandoned, but
4534 # was on ship earlier, it would have vanished -- let's restore it.
4535 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4536 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4537 game.iscraft = "onship"
4539 # * There used to be code to do the actual reconstrction here,
4540 # * but the starchart is now part of the snapshotted galaxy state.
4542 prout(_("Spock has reconstructed a correct star chart from memory"))
4544 # Go forward in time
4545 game.optime = -0.5*game.intime*math.log(randreal())
4546 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4547 # cheat to make sure no tractor beams occur during time warp
4548 postpone(FTBEAM, game.optime)
4549 game.damage[DRADIO] += game.optime
4551 events() # Stas Sergeev added this -- do pending events
4554 # launch deep-space probe
4555 # New code to launch a deep space probe
4556 if game.nprobes == 0:
4559 if game.ship == IHE:
4560 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4562 prout(_("Ye Faerie Queene has no deep space probes."))
4567 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4569 if is_scheduled(FDSPROB):
4572 if damaged(DRADIO) and game.condition != "docked":
4573 prout(_("Spock- \"Records show the previous probe has not yet"))
4574 prout(_(" reached its destination.\""))
4576 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4580 # slow mode, so let Kirk know how many probes there are left
4581 if game.nprobes == 1:
4582 prout(_("1 probe left."))
4584 prout(_("%d probes left") % game.nprobes)
4585 proutn(_("Are you sure you want to fire a probe? "))
4588 game.isarmed = False
4589 if key == IHALPHA and citem == "armed":
4593 proutn(_("Arm NOVAMAX warhead? "))
4595 if not getcourse(isprobe=True, akey=key):
4598 angle = ((15.0 - game.direc) * 0.5235988)
4599 game.probeinx = -math.sin(angle)
4600 game.probeiny = math.cos(angle)
4601 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4602 bigger = math.fabs(game.probeinx)
4604 bigger = math.fabs(game.probeiny)
4605 game.probeiny /= bigger
4606 game.probeinx /= bigger
4607 game.proben = 10.0*game.dist*bigger +0.5
4608 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4609 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4610 game.probec = game.quadrant
4611 schedule(FDSPROB, 0.01) # Time to move one sector
4612 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4616 # Here's how the mayday code works:
4618 # First, the closest starbase is selected. If there is a a starbase
4619 # in your own quadrant, you are in good shape. This distance takes
4620 # quadrant distances into account only.
4622 # A magic number is computed based on the distance which acts as the
4623 # probability that you will be rematerialized. You get three tries.
4625 # When it is determined that you should be able to be rematerialized
4626 # (i.e., when the probability thing mentioned above comes up
4627 # positive), you are put into that quadrant (anywhere). Then, we try
4628 # to see if there is a spot adjacent to the star- base. If not, you
4629 # can't be rematerialized!!! Otherwise, it drops you there. It only
4630 # tries five times to find a spot to drop you. After that, it's your
4634 # yell for help from nearest starbase
4635 # There's more than one way to move in this game!
4638 # Test for conditions which prevent calling for help
4639 if game.condition == "docked":
4640 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4643 prout(_("Subspace radio damaged."))
4645 if game.state.rembase==0:
4646 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4649 proutn(_("You must be aboard the "))
4653 # OK -- call for help from nearest starbase
4656 # There's one in this quadrant
4657 ddist = distance(game.base, game.sector)
4660 for m in range(game.state.rembase):
4661 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4665 # Since starbase not in quadrant, set up new quadrant
4666 game.quadrant = game.state.baseq[line]
4668 # dematerialize starship
4669 game.quad[game.sector.x][game.sector.y]=IHDOT
4670 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4672 prout(_(" dematerializes."))
4674 for m in range(1, 5+1):
4675 w = game.base.scatter()
4676 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4677 # found one -- finish up
4680 if not is_valid(game.sector):
4681 prout(_("You have been lost in space..."))
4682 finish(FMATERIALIZE)
4684 # Give starbase three chances to rematerialize starship
4685 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4686 for m in range(1, 3+1):
4687 if m == 1: proutn(_("1st"))
4688 elif m == 2: proutn(_("2nd"))
4689 elif m == 3: proutn(_("3rd"))
4690 proutn(_(" attempt to re-materialize "))
4692 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4695 if randreal() > probf:
4698 curses.delay_output(500)
4701 game.quad[ix][iy]=IHQUEST
4704 setwnd(message_window)
4705 finish(FMATERIALIZE)
4707 game.quad[ix][iy]=game.ship
4709 prout(_("succeeds."))
4713 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4715 # Abandon Ship (the BSD-Trek description)
4717 # The ship is abandoned. If your current ship is the Faire
4718 # Queene, or if your shuttlecraft is dead, you're out of
4719 # luck. You need the shuttlecraft in order for the captain
4720 # (that's you!!) to escape.
4722 # Your crew can beam to an inhabited starsystem in the
4723 # quadrant, if there is one and if the transporter is working.
4724 # If there is no inhabited starsystem, or if the transporter
4725 # is out, they are left to die in outer space.
4727 # If there are no starbases left, you are captured by the
4728 # Klingons, who torture you mercilessly. However, if there
4729 # is at least one starbase, you are returned to the
4730 # Federation in a prisoner of war exchange. Of course, this
4731 # can't happen unless you have taken some prisoners.
4736 if game.condition=="docked":
4738 prout(_("You cannot abandon Ye Faerie Queene."))
4741 # Must take shuttle craft to exit
4742 if game.damage[DSHUTTL]==-1:
4743 prout(_("Ye Faerie Queene has no shuttle craft."))
4745 if game.damage[DSHUTTL]<0:
4746 prout(_("Shuttle craft now serving Big Macs."))
4748 if game.damage[DSHUTTL]>0:
4749 prout(_("Shuttle craft damaged."))
4752 prout(_("You must be aboard the ship."))
4754 if game.iscraft != "onship":
4755 prout(_("Shuttle craft not currently available."))
4757 # Print abandon ship messages
4759 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4761 prouts(_("***ALL HANDS ABANDON SHIP!"))
4763 prout(_("Captain and crew escape in shuttle craft."))
4764 if game.state.rembase==0:
4765 # Oops! no place to go...
4768 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4770 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4771 prout(_("Remainder of ship's complement beam down"))
4772 prout(_("to nearest habitable planet."))
4773 elif q.planet != None and not damaged(DTRANSP):
4774 prout(_("Remainder of ship's complement beam down to %s.") %
4777 prout(_("Entire crew of %d left to die in outer space.") %
4779 game.casual += game.state.crew
4780 game.abandoned += game.state.crew
4782 # If at least one base left, give 'em the Faerie Queene
4784 game.icrystl = False # crystals are lost
4785 game.nprobes = 0 # No probes
4786 prout(_("You are captured by Klingons and released to"))
4787 prout(_("the Federation in a prisoner-of-war exchange."))
4788 nb = randrange(game.state.rembase)
4789 # Set up quadrant and position FQ adjacient to base
4790 if not game.quadrant == game.state.baseq[nb]:
4791 game.quadrant = game.state.baseq[nb]
4792 game.sector.x = game.sector.y = 5
4795 # position next to base by trial and error
4796 game.quad[game.sector.x][game.sector.y] = IHDOT
4797 for l in range(QUADSIZE):
4798 game.sector = game.base.scatter()
4799 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4800 game.quad[game.sector.x][game.sector.y] == IHDOT:
4803 break # found a spot
4804 game.sector.x=QUADSIZE/2
4805 game.sector.y=QUADSIZE/2
4807 # Get new commission
4808 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4809 game.state.crew = FULLCREW
4810 prout(_("Starfleet puts you in command of another ship,"))
4811 prout(_("the Faerie Queene, which is antiquated but,"))
4812 prout(_("still useable."))
4814 prout(_("The dilithium crystals have been moved."))
4816 game.iscraft = "offship" # Galileo disappears
4818 game.condition="docked"
4819 for l in range(NDEVICES):
4820 game.damage[l] = 0.0
4821 game.damage[DSHUTTL] = -1
4822 game.energy = game.inenrg = 3000.0
4823 game.shield = game.inshld = 1250.0
4824 game.torps = game.intorps = 6
4825 game.lsupres=game.inlsr=3.0
4831 # Code from planets.c begins here.
4834 # abort a lengthy operation if an event interrupts it
4837 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4842 # report on (uninhabited) planets in the galaxy
4846 prout(_("Spock- \"Planet report follows, Captain.\""))
4848 for i in range(game.inplan):
4849 if game.state.planets[i].pclass == "destroyed":
4851 if (game.state.planets[i].known != "unknown" \
4852 and not game.state.planets[i].inhabited) \
4855 if idebug and game.state.planets[i].known=="unknown":
4856 proutn("(Unknown) ")
4857 proutn(_("Quadrant %s") % game.state.planets[i].w)
4858 proutn(_(" class "))
4859 proutn(game.state.planets[i].pclass)
4861 if game.state.planets[i].crystals != present:
4863 prout(_("dilithium crystals present."))
4864 if game.state.planets[i].known=="shuttle_down":
4865 prout(_(" Shuttle Craft Galileo on surface."))
4867 prout(_("No information available."))
4870 # enter standard orbit
4874 prout(_("Already in standard orbit."))
4876 if damaged(DWARPEN) and damaged(DIMPULS):
4877 prout(_("Both warp and impulse engines damaged."))
4879 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4881 prout(_(" not adjacent to planet."))
4884 game.optime = randreal(0.02, 0.05)
4885 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4889 game.height = randreal(1400, 8600)
4890 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4895 # examine planets in this quadrant
4896 if damaged(DSRSENS):
4897 if game.options & OPTION_TTY:
4898 prout(_("Short range sensors damaged."))
4900 if game.iplnet == None:
4901 if game.options & OPTION_TTY:
4902 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4904 if game.iplnet.known == "unknown":
4905 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4907 prout(_(" Planet at Sector %s is of class %s.") %
4908 (game.plnet, game.iplnet.pclass))
4909 if game.iplnet.known=="shuttle_down":
4910 prout(_(" Sensors show Galileo still on surface."))
4911 proutn(_(" Readings indicate"))
4912 if game.iplnet.crystals != "present":
4914 prout(_(" dilithium crystals present.\""))
4915 if game.iplnet.known == "unknown":
4916 game.iplnet.known = "known"
4917 elif game.iplnet.inhabited:
4918 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4919 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4922 # use the transporter
4926 if damaged(DTRANSP):
4927 prout(_("Transporter damaged."))
4928 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4930 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4934 if not game.inorbit:
4936 prout(_(" not in standard orbit."))
4939 prout(_("Impossible to transport through shields."))
4941 if game.iplnet.known=="unknown":
4942 prout(_("Spock- \"Captain, we have no information on this planet"))
4943 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4944 prout(_(" you may not go down.\""))
4946 if not game.landed and game.iplnet.crystals=="absent":
4947 prout(_("Spock- \"Captain, I fail to see the logic in"))
4948 prout(_(" exploring a planet with no dilithium crystals."))
4949 proutn(_(" Are you sure this is wise?\" "))
4953 if not (game.options & OPTION_PLAIN):
4954 nrgneed = 50 * game.skill + game.height / 100.0
4955 if nrgneed > game.energy:
4956 prout(_("Engineering to bridge--"))
4957 prout(_(" Captain, we don't have enough energy for transportation."))
4959 if not game.landed and nrgneed * 2 > game.energy:
4960 prout(_("Engineering to bridge--"))
4961 prout(_(" Captain, we have enough energy only to transport you down to"))
4962 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4963 if game.iplnet.known == "shuttle_down":
4964 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4965 proutn(_(" Are you sure this is wise?\" "))
4970 # Coming from planet
4971 if game.iplnet.known=="shuttle_down":
4972 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4976 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4977 prout(_("Landing party assembled, ready to beam up."))
4979 prout(_("Kirk whips out communicator..."))
4980 prouts(_("BEEP BEEP BEEP"))
4982 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4985 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4987 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4989 prout(_("Kirk- \"Energize.\""))
4992 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4995 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4997 prout(_("Scotty- \"Oh my God! I've lost them.\""))
5000 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
5001 game.landed = not game.landed
5002 game.energy -= nrgneed
5004 prout(_("Transport complete."))
5005 if game.landed and game.iplnet.known=="shuttle_down":
5006 prout(_("The shuttle craft Galileo is here!"))
5007 if not game.landed and game.imine:
5014 # strip-mine a world for dilithium
5018 prout(_("Mining party not on planet."))
5020 if game.iplnet.crystals == "mined":
5021 prout(_("This planet has already been strip-mined for dilithium."))
5023 elif game.iplnet.crystals == "absent":
5024 prout(_("No dilithium crystals on this planet."))
5027 prout(_("You've already mined enough crystals for this trip."))
5029 if game.icrystl and game.cryprob == 0.05:
5030 proutn(_("With all those fresh crystals aboard the "))
5033 prout(_("there's no reason to mine more at this time."))
5035 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
5038 prout(_("Mining operation complete."))
5039 game.iplnet.crystals = "mined"
5040 game.imine = game.ididit = True
5043 # use dilithium crystals
5047 if not game.icrystl:
5048 prout(_("No dilithium crystals available."))
5050 if game.energy >= 1000:
5051 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5052 prout(_(" except when Condition Yellow exists."))
5054 prout(_("Spock- \"Captain, I must warn you that loading"))
5055 prout(_(" raw dilithium crystals into the ship's power"))
5056 prout(_(" system may risk a severe explosion."))
5057 proutn(_(" Are you sure this is wise?\" "))
5062 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5063 prout(_(" Mr. Spock and I will try it.\""))
5065 prout(_("Spock- \"Crystals in place, Sir."))
5066 prout(_(" Ready to activate circuit.\""))
5068 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5070 if with(game.cryprob):
5071 prouts(_(" \"Activating now! - - No good! It's***"))
5073 prouts(_("***RED ALERT! RED A*L********************************"))
5076 prouts(_("****************** KA-BOOM!!!! *******************"))
5080 game.energy += randreal(5000.0, 5500.0)
5081 prouts(_(" \"Activating now! - - "))
5082 prout(_("The instruments"))
5083 prout(_(" are going crazy, but I think it's"))
5084 prout(_(" going to work!! Congratulations, Sir!\""))
5089 # use shuttlecraft for planetary jaunt
5092 if damaged(DSHUTTL):
5093 if game.damage[DSHUTTL] == -1.0:
5094 if game.inorbit and game.iplnet.known == "shuttle_down":
5095 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5097 prout(_("Ye Faerie Queene had no shuttle craft."))
5098 elif game.damage[DSHUTTL] > 0:
5099 prout(_("The Galileo is damaged."))
5100 else: # game.damage[DSHUTTL] < 0
5101 prout(_("Shuttle craft is now serving Big Macs."))
5103 if not game.inorbit:
5105 prout(_(" not in standard orbit."))
5107 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5108 prout(_("Shuttle craft not currently available."))
5110 if not game.landed and game.iplnet.known=="shuttle_down":
5111 prout(_("You will have to beam down to retrieve the shuttle craft."))
5113 if game.shldup or game.condition == "docked":
5114 prout(_("Shuttle craft cannot pass through shields."))
5116 if game.iplnet.known=="unknown":
5117 prout(_("Spock- \"Captain, we have no information on this planet"))
5118 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5119 prout(_(" you may not fly down.\""))
5121 game.optime = 3.0e-5*game.height
5122 if game.optime >= 0.8*game.state.remtime:
5123 prout(_("First Officer Spock- \"Captain, I compute that such"))
5124 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5125 int(100*game.optime/game.state.remtime))
5126 prout(_("remaining time."))
5127 proutn(_("Are you sure this is wise?\" "))
5133 if game.iscraft == "onship":
5135 if not damaged(DTRANSP):
5136 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5140 proutn(_("Shuttle crew"))
5142 proutn(_("Rescue party"))
5143 prout(_(" boards Galileo and swoops toward planet surface."))
5144 game.iscraft = "offship"
5148 game.iplnet.known="shuttle_down"
5149 prout(_("Trip complete."))
5152 # Ready to go back to ship
5153 prout(_("You and your mining party board the"))
5154 prout(_("shuttle craft for the trip back to the Enterprise."))
5156 prouts(_("The short hop begins . . ."))
5158 game.iplnet.known="known"
5164 game.iscraft = "onship"
5170 prout(_("Trip complete."))
5175 prout(_("Mining party assembles in the hangar deck,"))
5176 prout(_("ready to board the shuttle craft \"Galileo\"."))
5178 prouts(_("The hangar doors open; the trip begins."))
5181 game.iscraft = "offship"
5184 game.iplnet.known = "shuttle_down"
5187 prout(_("Trip complete."))
5191 # use the big zapper
5195 if game.ship != IHE:
5196 prout(_("Ye Faerie Queene has no death ray."))
5199 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5202 prout(_("Death Ray is damaged."))
5204 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5205 prout(_(" is highly unpredictible. Considering the alternatives,"))
5206 proutn(_(" are you sure this is wise?\" "))
5209 prout(_("Spock- \"Acknowledged.\""))
5212 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5214 prout(_("Crew scrambles in emergency preparation."))
5215 prout(_("Spock and Scotty ready the death ray and"))
5216 prout(_("prepare to channel all ship's power to the device."))
5218 prout(_("Spock- \"Preparations complete, sir.\""))
5219 prout(_("Kirk- \"Engage!\""))
5221 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5224 if game.options & OPTION_PLAIN:
5228 prouts(_("Sulu- \"Captain! It's working!\""))
5230 while game.nenhere > 0:
5231 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5232 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5233 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5235 if (game.options & OPTION_PLAIN) == 0:
5236 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5238 prout(_(" is still operational.\""))
5240 prout(_(" has been rendered nonfunctional.\""))
5241 game.damage[DDRAY] = 39.95
5243 r = randreal() # Pick failure method
5245 prouts(_("Sulu- \"Captain! It's working!\""))
5247 prouts(_("***RED ALERT! RED ALERT!"))
5249 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5251 prouts(_("***RED ALERT! RED A*L********************************"))
5254 prouts(_("****************** KA-BOOM!!!! *******************"))
5259 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5261 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5263 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5264 prout(_(" have apparently been transformed into strange mutations."))
5265 prout(_(" Vulcans do not seem to be affected."))
5267 prout(_("Kirk- \"Raauch! Raauch!\""))
5272 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5274 proutn(_("Spock- \"I believe the word is"))
5275 prouts(_(" *ASTONISHING*"))
5276 prout(_(" Mr. Sulu."))
5277 for i in range(QUADSIZE):
5278 for j in range(QUADSIZE):
5279 if game.quad[i][j] == IHDOT:
5280 game.quad[i][j] = IHQUEST
5281 prout(_(" Captain, our quadrant is now infested with"))
5282 prouts(_(" - - - - - - *THINGS*."))
5284 prout(_(" I have no logical explanation.\""))
5286 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5288 prout(_("Scotty- \"There are so many tribbles down here"))
5289 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5293 # Code from reports.c begins here
5295 def attackreport(curt):
5296 # report status of bases under attack
5298 if is_scheduled(FCDBAS):
5299 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5300 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5301 elif game.isatb == 1:
5302 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5303 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5305 prout(_("No Starbase is currently under attack."))
5307 if is_scheduled(FCDBAS):
5308 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5310 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5314 # report on general game status
5316 s1 = "" and game.thawed and _("thawed ")
5317 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5318 s3 = (None, _("novice"). _("fair"),
5319 _("good"), _("expert"), _("emeritus"))[game.skill]
5320 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5321 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5322 prout(_("No plaque is allowed."))
5324 prout(_("This is tournament game %d.") % game.tourn)
5325 prout(_("Your secret password is \"%s\"") % game.passwd)
5326 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5327 (game.inkling + game.incom + game.inscom)))
5328 if game.incom - game.state.remcom:
5329 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5330 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5331 prout(_(", but no Commanders."))
5334 if game.skill > SKILL_FAIR:
5335 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5336 if game.state.rembase != game.inbase:
5338 if game.inbase-game.state.rembase==1:
5339 proutn(_("has been 1 base"))
5341 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5342 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5344 prout(_("There are %d bases.") % game.inbase)
5345 if communicating() or game.iseenit:
5346 # Don't report this if not seen and
5347 # either the radio is dead or not at base!
5351 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5353 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5354 if game.ship == IHE:
5355 proutn(_("You have "))
5357 proutn("%d" % (game.nprobes))
5360 proutn(_(" deep space probe"))
5364 if communicating() and is_scheduled(FDSPROB):
5366 proutn(_("An armed deep space probe is in "))
5368 proutn(_("A deep space probe is in "))
5369 prout("Quadrant %s." % game.probec)
5371 if game.cryprob <= .05:
5372 prout(_("Dilithium crystals aboard ship... not yet used."))
5376 while game.cryprob > ai:
5379 prout(_("Dilithium crystals have been used %d time%s.") % \
5380 (i, (_("s"), "")[i==1]))
5384 # long-range sensor scan
5385 if damaged(DLRSENS):
5386 # Now allow base's sensors if docked
5387 if game.condition != "docked":
5389 prout(_("LONG-RANGE SENSORS DAMAGED."))
5392 prout(_("Starbase's long-range scan"))
5394 prout(_("Long-range scan"))
5395 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5398 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5399 if not VALID_QUADRANT(x, y):
5403 if not damaged(DRADIO):
5404 game.state.galaxy[x][y].charted = True
5405 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5406 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5407 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5408 if not silent and game.state.galaxy[x][y].supernova:
5411 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5419 for i in range(NDEVICES):
5422 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5423 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5425 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5426 game.damage[i]+0.05,
5427 game.docfac*game.damage[i]+0.005))
5429 prout(_("All devices functional."))
5432 # update the chart in the Enterprise's computer from galaxy data
5433 game.lastchart = game.state.date
5434 for i in range(GALSIZE):
5435 for j in range(GALSIZE):
5436 if game.state.galaxy[i][j].charted:
5437 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5438 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5439 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5442 # display the star chart
5444 if (game.options & OPTION_AUTOSCAN):
5446 if not damaged(DRADIO):
5448 if game.lastchart < game.state.date and game.condition == "docked":
5449 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5452 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5453 if game.state.date > game.lastchart:
5454 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5455 prout(" 1 2 3 4 5 6 7 8")
5456 for i in range(GALSIZE):
5457 proutn("%d |" % (i+1))
5458 for j in range(GALSIZE):
5459 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5463 if game.state.galaxy[i][j].supernova:
5465 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5467 elif game.state.galaxy[i][j].charted:
5468 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5472 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5480 def sectscan(goodScan, i, j):
5481 # light up an individual dot in a sector
5482 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5483 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):
5484 if game.condition == "red": textcolor(RED)
5485 elif game.condition == "green": textcolor(GREEN)
5486 elif game.condition == "yellow": textcolor(YELLOW)
5487 elif game.condition == "docked": textcolor(CYAN)
5488 elif game.condition == "dead": textcolor(BROWN)
5489 if game.quad[i][j] != game.ship:
5491 proutn("%c " % game.quad[i][j])
5497 # print status report lines
5499 if not req or req == 1:
5500 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5501 % (game.state.date, game.state.remtime))
5502 if not req or req == 2:
5503 if game.condition != "docked":
5506 for t in range(NDEVICES):
5507 if game.damage[t]>0:
5509 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5510 if not req or req == 3:
5511 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5512 if not req or req == 4:
5513 if damaged(DLIFSUP):
5514 if game.condition == "docked":
5515 s = _("DAMAGED, Base provides")
5517 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5520 prstat(_("Life Support"), s)
5521 if not req or req == 5:
5522 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5523 if not req or req == 6:
5525 if game.icrystl and (game.options & OPTION_SHOWME):
5526 extra = _(" (have crystals)")
5527 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5528 if not req or req == 7:
5529 prstat(_("Torpedoes"), "%d" % (game.torps))
5530 if not req or req == 8:
5531 if damaged(DSHIELD):
5537 data = _(" %d%% %.1f units") \
5538 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5539 prstat(_("Shields"), s+data)
5540 if not req or req == 9:
5541 prstat(_("Klingons Left"), "%d" \
5542 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5543 if not req or req == 10:
5544 if game.options & OPTION_WORLDS:
5545 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5546 if plnet and plnet.inhabited:
5547 prstat(_("Major system"), plnet.name)
5549 prout(_("Sector is uninhabited"))
5550 elif not req or req == 11:
5551 attackreport(not req)
5554 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5555 while scan() == IHEOL:
5556 proutn(_("Information desired? "))
5558 if citem in requests:
5559 status(requests.index(citem))
5561 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5562 prout((" date, condition, position, lsupport, warpfactor,"))
5563 prout((" energy, torpedoes, shields, klingons, system, time."))
5568 if damaged(DSRSENS):
5569 # Allow base's sensors if docked
5570 if game.condition != "docked":
5571 prout(_(" S.R. SENSORS DAMAGED!"))
5574 prout(_(" [Using Base's sensors]"))
5576 prout(_(" Short-range scan"))
5577 if goodScan and not damaged(DRADIO):
5578 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5579 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5580 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5581 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5582 prout(" 1 2 3 4 5 6 7 8 9 10")
5583 if game.condition != "docked":
5585 for i in range(QUADSIZE):
5586 proutn("%2d " % (i+1))
5587 for j in range(QUADSIZE):
5588 sectscan(goodScan, i, j)
5593 # use computer to get estimated time of arrival for a warp jump
5594 w1 = coord(); w2 = coord()
5596 if damaged(DCOMPTR):
5597 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5600 if scan() != IHREAL:
5603 proutn(_("Destination quadrant and/or sector? "))
5607 w1.y = int(aaitem-0.5)
5608 if scan() != IHREAL:
5611 w1.x = int(aaitem-0.5)
5612 if scan() == IHREAL:
5613 w2.y = int(aaitem-0.5)
5614 if scan() != IHREAL:
5617 w2.x = int(aaitem-0.5)
5619 if game.quadrant.y>w1.x:
5623 if game.quadrant.x>w1.y:
5627 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5630 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5631 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5634 prout(_("Answer \"no\" if you don't know the value:"))
5637 proutn(_("Time or arrival date? "))
5640 if ttime > game.state.date:
5641 ttime -= game.state.date # Actually a star date
5642 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5643 if ttime <= 1e-10 or twarp > 10:
5644 prout(_("We'll never make it, sir."))
5651 proutn(_("Warp factor? "))
5655 if twarp<1.0 or twarp > 10.0:
5659 prout(_("Captain, certainly you can give me one of these."))
5662 ttime = (10.0*game.dist)/square(twarp)
5663 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5664 if tpower >= game.energy:
5665 prout(_("Insufficient energy, sir."))
5666 if not game.shldup or tpower > game.energy*2.0:
5669 proutn(_("New warp factor to try? "))
5670 if scan() == IHREAL:
5673 if twarp<1.0 or twarp > 10.0:
5681 prout(_("But if you lower your shields,"))
5682 proutn(_("remaining"))
5685 proutn(_("Remaining"))
5686 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5688 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5690 prout(_("Any warp speed is adequate."))
5692 prout(_("Minimum warp needed is %.2f,") % (twarp))
5693 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5694 if game.state.remtime < ttime:
5695 prout(_("Unfortunately, the Federation will be destroyed by then."))
5697 prout(_("You'll be taking risks at that speed, Captain"))
5698 if (game.isatb==1 and game.state.kscmdr == w1 and \
5699 scheduled(FSCDBAS)< ttime+game.state.date) or \
5700 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5701 prout(_("The starbase there will be destroyed by then."))
5702 proutn(_("New warp factor to try? "))
5703 if scan() == IHREAL:
5706 if twarp<1.0 or twarp > 10.0:
5715 # Code from setup.c begins here
5718 # issue a historically correct banner
5720 prout(_("-SUPER- STAR TREK"))
5722 # From the FORTRAN original
5723 # prout(_("Latest update-21 Sept 78"))
5729 citem = "emsave.trk"
5733 proutn(_("File name: "))
5739 if '.' not in citem:
5742 fp = open(citem, "wb")
5744 prout(_("Can't freeze game as file %s") % citem)
5746 cPickle.dump(game, fp)
5750 # retrieve saved game
5751 game.passwd[0] = '\0'
5754 proutn(_("File name: "))
5760 if '.' not in citem:
5763 fp = open(citem, "rb")
5765 prout(_("Can't thaw game in %s") % citem)
5767 game = cPickle.load(fp)
5771 # I used <http://www.memory-alpha.org> to find planets
5772 # with references in ST:TOS. Eath and the Alpha Centauri
5773 # Colony have been omitted.
5775 # Some planets marked Class G and P here will be displayed as class M
5776 # because of the way planets are generated. This is a known bug.
5779 _("Andoria (Fesoan)"), # several episodes
5780 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5781 _("Vulcan (T'Khasi)"), # many episodes
5782 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5783 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5784 _("Ardana"), # TOS: "The Cloud Minders"
5785 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5786 _("Gideon"), # TOS: "The Mark of Gideon"
5787 _("Aldebaran III"), # TOS: "The Deadly Years"
5788 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5789 _("Altair IV"), # TOS: "Amok Time
5790 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5791 _("Benecia"), # TOS: "The Conscience of the King"
5792 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5793 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5794 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5795 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5796 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5797 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5798 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5799 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5800 _("Ingraham B"), # TOS: "Operation: Annihilate"
5801 _("Janus IV"), # TOS: "The Devil in the Dark"
5802 _("Makus III"), # TOS: "The Galileo Seven"
5803 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5804 _("Omega IV"), # TOS: "The Omega Glory"
5805 _("Regulus V"), # TOS: "Amok Time
5806 _("Deneva"), # TOS: "Operation -- Annihilate!"
5807 # Worlds from BSD Trek
5808 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5809 _("Beta III"), # TOS: "The Return of the Archons"
5810 _("Triacus"), # TOS: "And the Children Shall Lead",
5811 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5813 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5814 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5815 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5816 # _("Izar"), # TOS: "Whom Gods Destroy"
5817 # _("Tiburon"), # TOS: "The Way to Eden"
5818 # _("Merak II"), # TOS: "The Cloud Minders"
5819 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5820 # _("Iotia"), # TOS: "A Piece of the Action"
5824 _("S. R. Sensors"), \
5825 _("L. R. Sensors"), \
5827 _("Photon Tubes"), \
5828 _("Life Support"), \
5829 _("Warp Engines"), \
5830 _("Impulse Engines"), \
5832 _("Subspace Radio"), \
5833 _("Shuttle Craft"), \
5835 _("Navigation System"), \
5837 _("Shield Control"), \
5842 def setup(needprompt):
5843 # prepare to play, set up cosmos
5845 # Decide how many of everything
5846 if choose(needprompt):
5847 return # frozen game
5848 # Prepare the Enterprise
5849 game.alldone = game.gamewon = False
5851 game.state.crew = FULLCREW
5852 game.energy = game.inenrg = 5000.0
5853 game.shield = game.inshld = 2500.0
5854 game.shldchg = False
5858 game.quadrant = randplace(GALSIZE)
5859 game.sector = randplace(QUADSIZE)
5860 game.torps = game.intorps = 10
5861 game.nprobes = randrange(2, 5)
5863 game.wfacsq = game.warpfac * game.warpfac
5864 for i in range(NDEVICES):
5865 game.damage[i] = 0.0
5866 # Set up assorted game parameters
5867 game.battle = coord()
5868 game.state.date = game.indate = 100.0 * randreal(20, 51)
5869 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5870 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5871 game.isatb = game.state.nplankl = 0
5872 game.state.starkl = game.state.basekl = 0
5873 game.iscraft = "onship"
5877 for i in range(GALSIZE):
5878 for j in range(GALSIZE):
5879 quad = game.state.galaxy[i][j]
5884 quad.starbase = False
5885 quad.supernova = False
5886 quad.status = "secure"
5887 # Initialize times for extraneous events
5888 schedule(FSNOVA, expran(0.5 * game.intime))
5889 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5890 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5891 schedule(FBATTAK, expran(0.3*game.intime))
5893 if game.state.nscrem:
5894 schedule(FSCMOVE, 0.2777)
5899 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5900 schedule(FDISTR, expran(1.0 + game.intime))
5905 # Starchart is functional but we've never seen it
5906 game.lastchart = FOREVER
5907 # Put stars in the galaxy
5909 for i in range(GALSIZE):
5910 for j in range(GALSIZE):
5911 k = randrange(1, QUADSIZE**2/10+1)
5913 game.state.galaxy[i][j].stars = k
5914 # Locate star bases in galaxy
5915 for i in range(game.inbase):
5918 w = randplace(GALSIZE)
5919 if not game.state.galaxy[w.x][w.y].starbase:
5922 # C version: for (j = i-1; j > 0; j--)
5923 # so it did them in the opposite order.
5924 for j in range(1, i):
5925 # Improved placement algorithm to spread out bases
5926 distq = w.distance(game.state.baseq[j])
5927 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5930 prout("=== Abandoning base #%d at %s" % (i, w))
5932 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5934 prout("=== Saving base #%d, close to #%d" % (i, j))
5937 game.state.baseq[i] = w
5938 game.state.galaxy[w.x][w.y].starbase = True
5939 game.state.chart[w.x][w.y].starbase = True
5940 # Position ordinary Klingon Battle Cruisers
5942 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5943 if klumper > MAXKLQUAD:
5947 klump = (1.0 - r*r)*klumper
5952 w = randplace(GALSIZE)
5953 if not game.state.galaxy[w.x][w.y].supernova and \
5954 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5956 game.state.galaxy[w.x][w.y].klingons += int(klump)
5959 # Position Klingon Commander Ships
5960 for i in range(1, game.incom+1):
5962 w = randplace(GALSIZE)
5963 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5964 not game.state.galaxy[w.x][w.y].supernova and \
5965 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5966 not w in game.state.kcmdr[:i]:
5968 game.state.galaxy[w.x][w.y].klingons += 1
5969 game.state.kcmdr[i] = w
5970 # Locate planets in galaxy
5971 for i in range(game.inplan):
5973 w = randplace(GALSIZE)
5974 if game.state.galaxy[w.x][w.y].planet == None:
5978 new.crystals = "absent"
5979 if (game.options & OPTION_WORLDS) and i < NINHAB:
5980 new.pclass = "M" # All inhabited planets are class M
5981 new.crystals = "absent"
5983 new.name = systnames[i]
5984 new.inhabited = True
5986 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5988 new.crystals = "present"
5989 new.known = "unknown"
5990 new.inhabited = False
5991 game.state.galaxy[w.x][w.y].planet = new
5992 game.state.planets.append(new)
5994 for i in range(game.state.nromrem):
5995 w = randplace(GALSIZE)
5996 game.state.galaxy[w.x][w.y].romulans += 1
5997 # Locate the Super Commander
5998 if game.state.nscrem > 0:
6000 w = randplace(GALSIZE)
6001 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
6003 game.state.kscmdr = w
6004 game.state.galaxy[w.x][w.y].klingons += 1
6005 # Place thing (in tournament game, thingx == -1, don't want one!)
6008 thing = randplace(GALSIZE)
6010 game.state.snap = False
6011 if game.skill == SKILL_NOVICE:
6012 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6013 prout(_("a deadly Klingon invasion force. As captain of the United"))
6014 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6015 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6016 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6017 prout(_("your mission. As you proceed you may be given more time."))
6019 prout(_("You will have %d supporting starbases.") % (game.inbase))
6020 proutn(_("Starbase locations- "))
6022 prout(_("Stardate %d.") % int(game.state.date))
6024 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6025 prout(_("An unknown number of Romulans."))
6026 if game.state.nscrem:
6027 prout(_("And one (GULP) Super-Commander."))
6028 prout(_("%d stardates.") % int(game.intime))
6029 proutn(_("%d starbases in ") % game.inbase)
6030 for i in range(game.inbase):
6031 proutn(`game.state.baseq[i]`)
6034 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6035 proutn(_(" Sector %s") % game.sector)
6037 prout(_("Good Luck!"))
6038 if game.state.nscrem:
6039 prout(_(" YOU'LL NEED IT."))
6042 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
6044 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6047 def choose(needprompt):
6048 # choose your game type
6053 game.skill = SKILL_NONE
6055 if needprompt: # Can start with command line options
6056 proutn(_("Would you like a regular, tournament, or saved game? "))
6058 if len(citem)==0: # Try again
6060 if isit("tournament"):
6061 while scan() == IHEOL:
6062 proutn(_("Type in tournament number-"))
6065 continue # We don't want a blank entry
6066 game.tourn = int(round(aaitem))
6069 logfp.write("# random.seed(%d)\n" % aaitem)
6071 if isit("saved") or isit("frozen"):
6075 if game.passwd == None:
6077 if not game.alldone:
6078 game.thawed = True # No plaque if not finished
6084 proutn(_("What is \"%s\"?"), citem)
6086 while game.length==0 or game.skill==SKILL_NONE:
6087 if scan() == IHALPHA:
6090 elif isit("medium"):
6094 elif isit("novice"):
6095 game.skill = SKILL_NOVICE
6097 game.skill = SKILL_FAIR
6099 game.skill = SKILL_GOOD
6100 elif isit("expert"):
6101 game.skill = SKILL_EXPERT
6102 elif isit("emeritus"):
6103 game.skill = SKILL_EMERITUS
6105 proutn(_("What is \""))
6111 proutn(_("Would you like a Short, Medium, or Long game? "))
6112 elif game.skill == SKILL_NONE:
6113 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6114 # Choose game options -- added by ESR for SST2K
6115 if scan() != IHALPHA:
6117 proutn(_("Choose your game style (or just press enter): "))
6120 # Approximates the UT FORTRAN version.
6121 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6122 game.options |= OPTION_PLAIN
6124 # Approximates Tom Almy's version.
6125 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6126 game.options |= OPTION_ALMY
6130 proutn(_("What is \"%s\"?") % citem)
6132 if game.passwd == "debug":
6134 fputs("=== Debug mode enabled\n", sys.stdout)
6136 # Use parameters to generate initial values of things
6137 game.damfac = 0.5 * game.skill
6138 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6139 game.inbase = game.state.rembase
6141 if game.options & OPTION_PLANETS:
6142 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6143 if game.options & OPTION_WORLDS:
6144 game.inplan += int(NINHAB)
6145 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6146 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6147 game.state.remtime = 7.0 * game.length
6148 game.intime = game.state.remtime
6149 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6150 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6151 game.state.remcom = min(10, game.incom)
6152 game.incom = game.state.remcom
6153 game.state.remres = (game.inkling+4*game.incom)*game.intime
6154 game.inresor = game.state.remres
6155 if game.inkling > 50:
6156 game.state.rembase += 1
6157 game.inbase = game.state.rembase
6161 # drop a feature on a random dot in the current quadrant
6164 w = randplace(QUADSIZE)
6165 if game.quad[w.x][w.y] == IHDOT:
6167 game.quad[w.x][w.y] = iquad
6171 # update our alert status
6172 game.condition = "green"
6173 if game.energy < 1000.0:
6174 game.condition = "yellow"
6175 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6176 game.condition = "red"
6178 game.condition="dead"
6181 # drop new Klingon into current quadrant
6184 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6185 game.kpower[i] = randreal(300, 450) + 25.0*game.skill
6189 # set up a new state of quadrant, for when we enter or re-enter it
6193 game.comhere = False
6199 game.inorbit = False
6201 game.ientesc = False
6204 game.iseenit = False
6206 # Attempt to escape Super-commander, so tbeam back!
6209 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6210 # cope with supernova
6213 game.klhere = q.klingons
6214 game.irhere = q.romulans
6215 game.nenhere = game.klhere + game.irhere
6217 game.quad[game.sector.x][game.sector.y] = game.ship
6219 # Position ordinary Klingons
6220 for i in range(game.klhere):
6222 # If we need a commander, promote a Klingon
6223 for i in range(game.state.remcom):
6224 if game.state.kcmdr[i] == game.quadrant:
6225 game.quad[game.ks[i].x][game.ks[i].y] = IHC
6226 game.kpower[game.klhere] = randreal(950,1350) + 50.0*game.skill
6229 # If we need a super-commander, promote a Klingon
6230 if game.quadrant == game.state.kscmdr:
6231 game.quad[w.x][w.y] = IHS
6232 game.kpower[0] = randreal(1175.0, 1575.0) + 125.0*game.skill
6233 game.iscate = (game.state.remkl > 1)
6235 # Put in Romulans if needed
6236 for i in range(game.klhere, game.nenhere):
6239 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6240 game.kpower[i] = randreal(400.0, 850.0) + 50.0*game.skill
6241 # If quadrant needs a starbase, put it in
6243 game.base = dropin(IHB)
6244 # If quadrant needs a planet, put it in
6246 game.iplnet = q.planet
6247 if not q.planet.inhabited:
6248 game.plnet = dropin(IHP)
6250 game.plnet = dropin(IHW)
6251 # Check for condition
6253 # And finally the stars
6254 for i in range(q.stars):
6257 if game.irhere > 0 and game.klhere == 0:
6259 if not damaged(DRADIO):
6261 prout(_("LT. Uhura- \"Captain, an urgent message."))
6262 prout(_(" I'll put it on audio.\" CLICK"))
6264 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6265 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6267 # Put in THING if needed
6269 if thing == game.quadrant:
6271 thing = randplace(GALSIZE)
6273 game.ks[game.nenhere] = w
6274 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6275 distance(game.sector, w)
6276 game.kpower[game.nenhere] = randreal(6000,6500.0)+250.0*game.skill
6277 if not damaged(DSRSENS):
6279 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6280 prout(_(" Please examine your short-range scan.\""))
6281 # Decide if quadrant needs a Tholian; lighten up if skill is low
6282 if game.options & OPTION_THOLIAN:
6283 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6284 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6285 (game.skill > SKILL_GOOD and withprob(0.08)):
6286 game.tholian = coord()
6288 game.tholian.x = withprob(0.5) * (QUADSIZE-1)
6289 game.tholian.y = withprob(0.5) * (QUADSIZE-1)
6290 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6292 game.quad[game.tholian.x][game.tholian.y] = IHT
6294 game.ks[game.nenhere] = game.tholian
6295 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6296 distance(game.sector, game.tholian)
6297 game.kpower[game.nenhere] = randrange(100, 500) + 25.0*game.skill
6298 # Reserve unoccupied corners
6299 if game.quad[0][0]==IHDOT:
6300 game.quad[0][0] = 'X'
6301 if game.quad[0][QUADSIZE-1]==IHDOT:
6302 game.quad[0][QUADSIZE-1] = 'X'
6303 if game.quad[QUADSIZE-1][0]==IHDOT:
6304 game.quad[QUADSIZE-1][0] = 'X'
6305 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6306 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6308 # Put in a few black holes
6309 for i in range(1, 3+1):
6312 # Take out X's in corners if Tholian present
6314 if game.quad[0][0]=='X':
6315 game.quad[0][0] = IHDOT
6316 if game.quad[0][QUADSIZE-1]=='X':
6317 game.quad[0][QUADSIZE-1] = IHDOT
6318 if game.quad[QUADSIZE-1][0]=='X':
6319 game.quad[QUADSIZE-1][0] = IHDOT
6320 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6321 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6324 # sort Klingons by distance from us
6325 # The author liked bubble sort. So we will use it. :-(
6326 if game.nenhere-(thing==game.quadrant)-(game.tholian!=None) < 2:
6330 for j in range(game.nenhere-1):
6331 if game.kdist[j] > game.kdist[j+1]:
6334 game.kdist[j] = game.kdist[j+1]
6337 game.kavgd[j] = game.kavgd[j+1]
6340 game.ks[j].x = game.ks[j+1].x
6343 game.ks[j].y = game.ks[j+1].y
6346 game.kpower[j] = game.kpower[j+1]
6347 game.kpower[j+1] = t
6352 # set the self-destruct password
6353 if game.options & OPTION_PLAIN:
6356 proutn(_("Please type in a secret password- "))
6359 if game.passwd != None:
6364 game.passwd += chr(ord('a')+randrange(26))
6366 # Code from sst.c begins here
6369 "SRSCAN": OPTION_TTY,
6370 "STATUS": OPTION_TTY,
6371 "REQUEST": OPTION_TTY,
6372 "LRSCAN": OPTION_TTY,
6385 "SENSORS": OPTION_PLANETS,
6386 "ORBIT": OPTION_PLANETS,
6387 "TRANSPORT": OPTION_PLANETS,
6388 "MINE": OPTION_PLANETS,
6389 "CRYSTALS": OPTION_PLANETS,
6390 "SHUTTLE": OPTION_PLANETS,
6391 "PLANETS": OPTION_PLANETS,
6396 "PROBE": OPTION_PROBE,
6398 "FREEZE": 0, # Synonym for SAVE
6404 "SOS": 0, # Synonym for MAYDAY
6405 "CALL": 0, # Synonym for MAYDAY
6412 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6415 # generate a list of legal commands
6417 proutn(_("LEGAL COMMANDS ARE:"))
6418 for key in commands:
6422 proutn("%-12s " % key)
6427 # browse on-line help
6428 # Give help on commands
6432 setwnd(prompt_window)
6433 proutn(_("Help on what command? "))
6435 setwnd(message_window)
6438 if citem in commands or citem == "ABBREV":
6447 fp = open(SSTDOC, "r")
6450 fp = open(DOC_NAME, "r")
6452 prout(_("Spock- \"Captain, that information is missing from the"))
6453 proutn(_(" computer. You need to find "))
6455 prout(_(" and put it in the"))
6456 proutn(_(" current directory or to "))
6460 # This used to continue: "You need to find SST.DOC and put
6461 # it in the current directory."
6465 linebuf = fp.readline()
6467 prout(_("Spock- \"Captain, there is no information on that command.\""))
6470 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6471 linebuf = linebuf[3:].strip()
6475 prout(_("Spock- \"Captain, I've found the following information:\""))
6477 while linebuf in fp:
6478 if "******" in linebuf:
6484 # command-interpretation loop
6487 setwnd(message_window)
6488 while True: # command loop
6490 while True: # get a command
6495 setwnd(prompt_window)
6499 if game.options & OPTION_CURSES:
6504 setwnd(message_window)
6506 candidates = filter(lambda x: x.startswith(citem.upper()),
6508 if len(candidates) == 1:
6511 elif candidates and not (game.options & OPTION_PLAIN):
6512 prout("Commands with that prefix: " + " ".join(candidates))
6516 if cmd == "SRSCAN": # srscan
6518 elif cmd == "STATUS": # status
6520 elif cmd == "REQUEST": # status request
6522 elif cmd == "LRSCAN": # long range scan
6523 lrscan(silent=False)
6524 elif cmd == "PHASERS": # phasers
6528 elif cmd == "TORPEDO": # photon torpedos
6532 elif cmd == "MOVE": # move under warp
6534 elif cmd == "SHIELDS": # shields
6535 doshield(shraise=False)
6538 game.shldchg = False
6539 elif cmd == "DOCK": # dock at starbase
6543 elif cmd == "DAMAGES": # damage reports
6545 elif cmd == "CHART": # chart
6547 elif cmd == "IMPULSE": # impulse
6549 elif cmd == "REST": # rest
6553 elif cmd == "WARP": # warp
6555 elif cmd == "SCORE": # score
6557 elif cmd == "SENSORS": # sensors
6559 elif cmd == "ORBIT": # orbit
6563 elif cmd == "TRANSPORT": # transport "beam"
6565 elif cmd == "MINE": # mine
6569 elif cmd == "CRYSTALS": # crystals
6573 elif cmd == "SHUTTLE": # shuttle
6577 elif cmd == "PLANETS": # Planet list
6579 elif cmd == "REPORT": # Game Report
6581 elif cmd == "COMPUTER": # use COMPUTER!
6583 elif cmd == "COMMANDS":
6585 elif cmd == "EMEXIT": # Emergency exit
6586 clrscr() # Hide screen
6587 freeze(True) # forced save
6588 raise SysExit,1 # And quick exit
6589 elif cmd == "PROBE":
6590 probe() # Launch probe
6593 elif cmd == "ABANDON": # Abandon Ship
6595 elif cmd == "DESTRUCT": # Self Destruct
6597 elif cmd == "SAVE": # Save Game
6600 if game.skill > SKILL_GOOD:
6601 prout(_("WARNING--Saved games produce no plaques!"))
6602 elif cmd == "DEATHRAY": # Try a desparation measure
6606 elif cmd == "DEBUGCMD": # What do we want for debug???
6608 elif cmd == "MAYDAY": # Call for help
6613 game.alldone = True # quit the game
6618 break # Game has ended
6619 if game.optime != 0.0:
6622 break # Events did us in
6623 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6626 if hitme and not game.justin:
6630 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6642 if cmd == IHR: s = _("Romulan")
6643 elif cmd == IHK: s = _("Klingon")
6644 elif cmd == IHC: s = _("Commander")
6645 elif cmd == IHS: s = _("Super-commander")
6646 elif cmd == IHSTAR: s = _("Star")
6647 elif cmd == IHP: s = _("Planet")
6648 elif cmd == IHB: s = _("Starbase")
6649 elif cmd == IHBLANK: s = _("Black hole")
6650 elif cmd == IHT: s = _("Tholian")
6651 elif cmd == IHWEB: s = _("Tholian web")
6652 elif cmd == IHQUEST: s = _("Stranger")
6653 elif cmd == IHW: s = _("Inhabited World")
6654 else: s = "Unknown??"
6657 def crmena(stars, enemy, loctype, w):
6658 # print an enemy and his location
6664 if loctype == "quadrant":
6665 buf = _("Quadrant ")
6666 elif loctype == "sector":
6671 # print our ship name
6672 if game.ship == IHE:
6674 elif game.ship == IHF:
6675 s = _("Faerie Queene")
6681 # print a line of stars
6682 prouts("******************************************************")
6686 return -avrage*math.log(1e-7 + randreal())
6688 def randplace(size):
6689 # choose a random location
6691 w.x = randrange(size)
6692 w.y = randrange(size)
6696 # Demand input for next scan
6701 # return IHEOL next time
6706 # Get a token from the user
6707 global inqueue, line, citem, aaitem
6711 # Read a line if nothing here
6714 if curwnd==prompt_window:
6716 setwnd(message_window)
6718 # Skip leading white space
6719 line = line.lstrip()
6721 inqueue = line.split()
6727 # From here on in it's all looking at the queue
6728 citem = inqueue.pop(0)
6732 aaitem = float(citem)
6737 citem = citem.lower()
6741 # yes-or-no confirmation
6750 proutn(_("Please answer with \"y\" or \"n\": "))
6753 # complain about unparseable input
6756 prout(_("Beg your pardon, Captain?"))
6759 # compares s to citem and returns true if it matches to the length of s
6760 return s.startswith(citem)
6763 # access to the internals for debugging
6764 proutn("Reset levels? ")
6766 if game.energy < game.inenrg:
6767 game.energy = game.inenrg
6768 game.shield = game.inshld
6769 game.torps = game.intorps
6770 game.lsupres = game.inlsr
6771 proutn("Reset damage? ")
6773 for i in range(NDEVICES):
6774 if game.damage[i] > 0.0:
6775 game.damage[i] = 0.0
6776 proutn("Toggle debug flag? ")
6780 prout("Debug output ON")
6782 prout("Debug output OFF")
6783 proutn("Cause selective damage? ")
6785 for i in range(NDEVICES):
6791 if key == IHALPHA and isit("y"):
6792 game.damage[i] = 10.0
6793 proutn("Examine/change events? ")
6798 FSNOVA: "Supernova ",
6801 FBATTAK: "Base Attack ",
6802 FCDBAS: "Base Destroy ",
6803 FSCMOVE: "SC Move ",
6804 FSCDBAS: "SC Base Destroy ",
6805 FDSPROB: "Probe Move ",
6806 FDISTR: "Distress Call ",
6807 FENSLV: "Enslavement ",
6808 FREPRO: "Klingon Build ",
6810 for i in range(1, NEVENTS):
6813 proutn("%.2f" % (scheduled(i)-game.state.date))
6814 if i == FENSLV or i == FREPRO:
6816 proutn(" in %s" % ev.quadrant)
6826 ev = schedule(i, aaitem)
6827 if i == FENSLV or i == FREPRO:
6829 proutn("In quadrant- ")
6831 # IHEOL says to leave coordinates as they are
6834 prout("Event %d canceled, no x coordinate." % (i))
6837 w.x = int(round(aaitem))
6840 prout("Event %d canceled, no y coordinate." % (i))
6843 w.y = int(round(aaitem))
6846 proutn("Induce supernova here? ")
6848 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6851 if __name__ == '__main__':
6853 global line, thing, game, idebug, iqengry
6854 game = citem = aaitem = inqueue = None
6860 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6861 # Disable curses mode until the game logic is working.
6862 # if os.getenv("TERM"):
6863 # game.options |= OPTION_CURSES | OPTION_SHOWME
6865 game.options |= OPTION_TTY
6866 seed = int(time.time())
6867 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6868 for (switch, val) in options:
6871 replayfp = open(val, "r")
6873 sys.stderr.write("sst: can't open replay file %s\n" % val)
6876 line = replayfp.readline().strip()
6877 (leader, key, seed) = line.split()
6879 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6880 line = replayfp.readline().strip()
6881 arguments += line.split()[2:]
6883 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6885 game.options |= OPTION_TTY
6886 game.options &=~ OPTION_CURSES
6887 elif switch == '-t':
6888 game.options |= OPTION_TTY
6889 game.options &=~ OPTION_CURSES
6890 elif switch == '-x':
6893 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6895 # where to save the input in case of bugs
6897 logfp = open("/usr/tmp/sst-input.log", "w")
6899 sys.stderr.write("sst: warning, can't open logfile\n")
6901 logfp.write("# seed %s\n" % seed)
6902 logfp.write("# options %s\n" % " ".join(arguments))
6909 while True: # Play a game
6910 setwnd(fullscreen_window)
6913 setup(needprompt=not inqueue)
6916 game.alldone = False
6922 if game.tourn and game.alldone:
6923 proutn(_("Do you want your score recorded?"))
6928 proutn(_("Do you want to play again? "))
6932 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6934 except KeyboardInterrupt: