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
205 # These functions hide the difference between 0-origin and 1-origin addressing.
206 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
207 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
209 def square(i): return ((i)*(i))
210 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
211 def invalidate(w): w.x = w.y = 0
212 def is_valid(w): return (w.x != 0 and w.y != 0)
214 # How to represent features
239 def __init__(self, x=None, y=None):
242 def invalidate(self):
243 self.x = self.y = None
245 return self.x != None and self.y != None
246 def __eq__(self, other):
247 return other != None and self.x == other.y and self.x == other.y
248 def __add__(self, other):
249 return coord(self.x+self.x, self.y+self.y)
250 def __sub__(self, other):
251 return coord(self.x-self.x, self.y-self.y)
252 def distance(self, other):
253 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
259 s.x = self.x / abs(self.x)
263 s.y = self.y / abs(self.y)
267 s.x = self.x + randrange(-1, 2)
268 s.y = self.y + randrange(-1, 2)
273 if self.x == None or self.y == None:
275 return "%s - %s" % (self.x+1, self.y+1)
280 self.name = None # string-valued if inhabited
281 self.w = coord() # quadrant located
282 self.pclass = None # could be ""M", "N", "O", or "destroyed"
283 self.crystals = "absent"# could be "mined", "present", "absent"
284 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
285 self.inhabited = False # is it inhabites?
296 self.supernova = None
298 self.status = None # Could be "secure", "distressed", "enslaved"
306 def fill2d(size, fillfun):
307 "Fill an empty list in 2D."
309 for i in range(size):
311 for j in range(size):
312 lst[i].append(fillfun(i, j))
317 self.snap = False # snapshot taken
318 self.crew = 0 # crew complement
319 self.remkl = 0 # remaining klingons
320 self.remcom = 0 # remaining commanders
321 self.nscrem = 0 # remaining super commanders
322 self.rembase = 0 # remaining bases
323 self.starkl = 0 # destroyed stars
324 self.basekl = 0 # destroyed bases
325 self.nromrem = 0 # Romulans remaining
326 self.nplankl = 0 # destroyed uninhabited planets
327 self.nworldkl = 0 # destroyed inhabited planets
328 self.planets = [] # Planet information
329 self.date = 0.0 # stardate
330 self.remres = 0 # remaining resources
331 self.remtime = 0 # remaining time
332 self.baseq = [] # Base quadrant coordinates
333 for i in range(BASEMAX):
334 self.baseq.append(coord())
335 self.kcmdr = [] # Commander quadrant coordinates
336 for i in range(QUADSIZE):
337 self.kcmdr.append(coord())
338 self.kscmdr = coord() # Supercommander quadrant coordinates
339 # the galaxy (subscript 0 not used)
340 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
341 # the starchart (subscript 0 not used)
342 self.chart = fill2d(GALSIZE, lambda i, j: page())
346 self.date = None # A real number
347 self.quadrant = None # A coord structure
350 OPTION_ALL = 0xffffffff
351 OPTION_TTY = 0x00000001 # old interface
352 OPTION_CURSES = 0x00000002 # new interface
353 OPTION_IOMODES = 0x00000003 # cover both interfaces
354 OPTION_PLANETS = 0x00000004 # planets and mining
355 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
356 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
357 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
358 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
359 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
360 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
361 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
362 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
363 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
364 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
365 OPTION_PLAIN = 0x01000000 # user chose plain game
366 OPTION_ALMY = 0x02000000 # user chose Almy variant
385 NDEVICES= 16 # Number of devices
394 def damaged(dev): return (game.damage[dev] != 0.0)
395 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
397 # Define future events
398 FSPY = 0 # Spy event happens always (no future[] entry)
399 # can cause SC to tractor beam Enterprise
400 FSNOVA = 1 # Supernova
401 FTBEAM = 2 # Commander tractor beams Enterprise
402 FSNAP = 3 # Snapshot for time warp
403 FBATTAK = 4 # Commander attacks base
404 FCDBAS = 5 # Commander destroys base
405 FSCMOVE = 6 # Supercommander moves (might attack base)
406 FSCDBAS = 7 # Supercommander destroys base
407 FDSPROB = 8 # Move deep space probe
408 FDISTR = 9 # Emit distress call from an inhabited world
409 FENSLV = 10 # Inhabited word is enslaved */
410 FREPRO = 11 # Klingons build a ship in an enslaved system
414 # abstract out the event handling -- underlying data structures will change
415 # when we implement stateful events
417 def findevent(evtype): return game.future[evtype]
420 def __init__(self, type=None, loc=None, power=None):
425 self.kpower = power # enemy energy level
426 game.enemies.append(self)
428 motion = (loc != self.kloc)
429 if self.kloc.x is not None and self.kloc.y is not None:
430 game.quad[self.kloc.x][self.kloc.y] = IHDOT
433 game.quad[self.kloc.x][self.kloc.y] = self.type
434 self.kdist = self.kavgd = distance(game.sector, loc)
436 self.kloc = coord() # enemy sector location
437 self.kdist = self.kavgd = None
438 game.enemies.remove(self)
441 return "<%s=%f>" % (self.kloc, self.kpower) # For debugging
445 self.options = None # Game options
446 self.state = snapshot() # A snapshot structure
447 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
448 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
449 self.damage = [0.0] * NDEVICES # damage encountered
450 self.future = [] # future events
451 for i in range(NEVENTS):
452 self.future.append(event())
453 self.passwd = None; # Self Destruct password
455 self.quadrant = None # where we are in the large
456 self.sector = None # where we are in the small
457 self.tholian = None # Tholian enemy object
458 self.base = None # position of base in current quadrant
459 self.battle = None # base coordinates being attacked
460 self.plnet = None # location of planet in quadrant
461 self.probec = None # current probe quadrant
462 self.gamewon = False # Finished!
463 self.ididit = False # action taken -- allows enemy to attack
464 self.alive = False # we are alive (not killed)
465 self.justin = False # just entered quadrant
466 self.shldup = False # shields are up
467 self.shldchg = False # shield is changing (affects efficiency)
468 self.comhere = False # commander here
469 self.ishere = False # super-commander in quadrant
470 self.iscate = False # super commander is here
471 self.ientesc = False # attempted escape from supercommander
472 self.resting = False # rest time
473 self.icraft = False # Kirk in Galileo
474 self.landed = False # party on planet (true), on ship (false)
475 self.alldone = False # game is now finished
476 self.neutz = False # Romulan Neutral Zone
477 self.isarmed = False # probe is armed
478 self.inorbit = False # orbiting a planet
479 self.imine = False # mining
480 self.icrystl = False # dilithium crystals aboard
481 self.iseenit = False # seen base attack report
482 self.thawed = False # thawed game
483 self.condition = None # "green", "yellow", "red", "docked", "dead"
484 self.iscraft = None # "onship", "offship", "removed"
485 self.skill = None # Player skill level
486 self.inkling = 0 # initial number of klingons
487 self.inbase = 0 # initial number of bases
488 self.incom = 0 # initial number of commanders
489 self.inscom = 0 # initial number of commanders
490 self.inrom = 0 # initial number of commanders
491 self.instar = 0 # initial stars
492 self.intorps = 0 # initial/max torpedoes
493 self.torps = 0 # number of torpedoes
494 self.ship = 0 # ship type -- 'E' is Enterprise
495 self.abandoned = 0 # count of crew abandoned in space
496 self.length = 0 # length of game
497 self.klhere = 0 # klingons here
498 self.casual = 0 # causalties
499 self.nhelp = 0 # calls for help
500 self.nkinks = 0 # count of energy-barrier crossings
501 self.iplnet = None # planet # in quadrant
502 self.inplan = 0 # initial planets
503 self.irhere = 0 # Romulans in quadrant
504 self.isatb = 0 # =1 if super commander is attacking base
505 self.tourn = None # tournament number
506 self.proben = 0 # number of moves for probe
507 self.nprobes = 0 # number of probes available
508 self.inresor = 0.0 # initial resources
509 self.intime = 0.0 # initial time
510 self.inenrg = 0.0 # initial/max energy
511 self.inshld = 0.0 # initial/max shield
512 self.inlsr = 0.0 # initial life support resources
513 self.indate = 0.0 # initial date
514 self.energy = 0.0 # energy level
515 self.shield = 0.0 # shield level
516 self.warpfac = 0.0 # warp speed
517 self.wfacsq = 0.0 # squared warp factor
518 self.lsupres = 0.0 # life support reserves
519 self.dist = 0.0 # movement distance
520 self.direc = 0.0 # movement direction
521 self.optime = 0.0 # time taken by current operation
522 self.docfac = 0.0 # repair factor when docking (constant?)
523 self.damfac = 0.0 # damage factor
524 self.lastchart = 0.0 # time star chart was last updated
525 self.cryprob = 0.0 # probability that crystal will work
526 self.probex = 0.0 # location of probe
528 self.probeinx = 0.0 # probe x,y increment
529 self.probeiny = 0.0 #
530 self.height = 0.0 # height of orbit around planet
532 # Stas thinks this should be (C expression):
533 # game.state.remkl + game.state.remcom > 0 ?
534 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
535 # He says the existing expression is prone to divide-by-zero errors
536 # after killing the last klingon when score is shown -- perhaps also
537 # if the only remaining klingon is SCOM.
538 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
539 # From enumerated type 'feature'
560 # From enumerated type 'FINTYPE'
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(enemy, look, 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
618 if enemy.type == IHR:
619 return False; # Romulans cannot escape!
621 # avoid intruding on another commander's territory
622 if enemy.type == IHC:
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 enemy.kpower > 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, enemy.type, "sector", enemy.kloc)
637 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
638 # handle local matters related to escape
641 if game.condition != "docked":
643 # Handle global matters related to escape
644 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
645 game.state.galaxy[iq.x][iq.y].klingons += 1
651 schedule(FSCMOVE, 0.2777)
655 for n in range(game.state.remcom):
656 if game.state.kcmdr[n] == game.quadrant:
657 game.state.kcmdr[n]=iq
660 return True; # success
663 # The bad-guy movement algorithm:
665 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
666 # If both are operating full strength, force is 1000. If both are damaged,
667 # force is -1000. Having shields down subtracts an additional 1000.
669 # 2. Enemy has forces equal to the energy of the attacker plus
670 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
671 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
673 # Attacker Initial energy levels (nominal):
674 # Klingon Romulan Commander Super-Commander
675 # Novice 400 700 1200
677 # Good 450 800 1300 1750
678 # Expert 475 850 1350 1875
679 # Emeritus 500 900 1400 2000
680 # VARIANCE 75 200 200 200
682 # Enemy vessels only move prior to their attack. In Novice - Good games
683 # only commanders move. In Expert games, all enemy vessels move if there
684 # is a commander present. In Emeritus games all enemy vessels move.
686 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
687 # forces are 1000 greater than Enterprise.
689 # Agressive action on average cuts the distance between the ship and
690 # the enemy to 1/4 the original.
692 # 4. At lower energy advantage, movement units are proportional to the
693 # advantage with a 650 advantage being to hold ground, 800 to move forward
694 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
696 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
697 # retreat, especially at high skill levels.
699 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
702 def movebaddy(enemy):
703 # tactical movement for the bad guys
704 next = coord(); look = coord()
706 # This should probably be just game.comhere + game.ishere
707 if game.skill >= SKILL_EXPERT:
708 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
710 nbaddys = game.comhere + game.ishere
712 mdist = int(dist1 + 0.5); # Nearest integer distance
713 # If SC, check with spy to see if should hi-tail it
714 if enemy.type==IHS and \
715 (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
719 # decide whether to advance, retreat, or hold position
720 forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
722 forces += 1000; # Good for enemy if shield is down!
723 if not damaged(DPHASER) or not damaged(DPHOTON):
724 if damaged(DPHASER): # phasers damaged
727 forces -= 0.2*(game.energy - 2500.0)
728 if damaged(DPHOTON): # photon torpedoes damaged
731 forces -= 50.0*game.torps
733 # phasers and photon tubes both out!
736 if forces <= 1000.0 and game.condition != "docked": # Typical situation
737 motion = ((forces + randreal(200))/150.0) - 5.0
739 if forces > 1000.0: # Very strong -- move in for kill
740 motion = (1.0-square(randreal()))*dist1 + 1.0
741 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
742 motion -= game.skill*(2.0-square(randreal()))
744 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
745 # don't move if no motion
748 # Limit motion according to skill
749 if abs(motion) > game.skill:
754 # calculate preferred number of steps
759 if motion > 0 and nsteps > mdist:
760 nsteps = mdist; # don't overshoot
761 if nsteps > QUADSIZE:
762 nsteps = QUADSIZE; # This shouldn't be necessary
764 nsteps = 1; # This shouldn't be necessary
766 proutn("NSTEPS = %d:" % nsteps)
767 # Compute preferred values of delta X and Y
768 m = game.sector - enemy.kloc
769 if 2.0 * abs(m.x) < abs(m.y):
771 if 2.0 * abs(m.y) < abs(game.sector.x-enemy.kloc.x):
785 for ll in range(nsteps):
787 proutn(" %d" % (ll+1))
788 # Check if preferred position available
799 attempts = 0; # Settle mysterious hang problem
800 while attempts < 20 and not success:
802 if look.x < 0 or look.x >= QUADSIZE:
803 if motion < 0 and tryexit(enemy, look, irun):
805 if krawlx == m.x or m.y == 0:
807 look.x = next.x + krawlx
809 elif look.y < 0 or look.y >= QUADSIZE:
810 if motion < 0 and tryexit(enemy, look, irun):
812 if krawly == m.y or m.x == 0:
814 look.y = next.y + krawly
816 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
817 # See if enemy should ram ship
818 if game.quad[look.x][look.y] == game.ship and \
819 (enemy.type == IHC or enemy.type == IHS):
820 collision(rammed=True, enemy=enemy)
822 if krawlx != m.x and m.y != 0:
823 look.x = next.x + krawlx
825 elif krawly != m.y and m.x != 0:
826 look.y = next.y + krawly
829 break; # we have failed
841 if not damaged(DSRSENS) or game.condition == "docked":
844 proutn(_(" from Sector %s") % enemy.kloc)
845 if enemy.kdist < dist1:
846 proutn(_(" advances to "))
848 proutn(_(" retreats to "))
849 prout("Sector %s." % next)
852 # Klingon tactical movement
855 # Figure out which Klingon is the commander (or Supercommander)
858 for enemy in game.enemies:
859 if enemy.type == IHC:
862 for enemy in game.enemies:
863 if enemy.type == IHS:
866 # If skill level is high, move other Klingons and Romulans too!
867 # Move these last so they can base their actions on what the
869 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
870 for enemy in game.enemies:
871 if enemy.type in (IHK, IHR):
873 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
875 def movescom(iq, avoid):
876 # commander movement helper
877 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
878 game.state.galaxy[iq.x][iq.y].supernova or \
879 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
882 # Avoid quadrants with bases if we want to avoid Enterprise
883 for i in range(game.state.rembase):
884 if game.state.baseq[i] == iq:
886 if game.justin and not game.iscate:
889 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
890 game.state.kscmdr = iq
891 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
893 # SC has scooted, Remove him from current quadrant
899 for enemy in game.enemies:
900 if enemy.type == IHS:
904 if game.condition != "docked":
906 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
907 # check for a helpful planet
908 for i in range(game.inplan):
909 if game.state.planets[i].w == game.state.kscmdr and \
910 game.state.planets[i].crystals == "present":
912 game.state.planets[i].pclass = "destroyed"
913 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
916 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
917 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
918 prout(_(" by the Super-commander.\""))
920 return False; # looks good!
922 def supercommander():
923 # move the Super Commander
924 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
927 prout("== SUPERCOMMANDER")
928 # Decide on being active or passive
929 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 \
930 (game.state.date-game.indate) < 3.0)
931 if not game.iscate and avoid:
932 # compute move away from Enterprise
933 idelta = game.state.kscmdr-game.quadrant
934 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
936 idelta.x = game.state.kscmdr.y-game.quadrant.y
937 idelta.y = game.quadrant.x-game.state.kscmdr.x
939 # compute distances to starbases
940 if game.state.rembase <= 0:
944 sc = game.state.kscmdr
945 for i in range(game.state.rembase):
946 basetbl.append((i, distance(game.state.baseq[i], sc)))
947 if game.state.rembase > 1:
948 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
949 # look for nearest base without a commander, no Enterprise, and
950 # without too many Klingons, and not already under attack.
951 ifindit = iwhichb = 0
952 for i2 in range(game.state.rembase):
953 i = basetbl[i2][0]; # bug in original had it not finding nearest
954 ibq = game.state.baseq[i]
955 if ibq == game.quadrant or ibq == game.battle or \
956 game.state.galaxy[ibq.x][ibq.y].supernova or \
957 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
959 # if there is a commander, and no other base is appropriate,
960 # we will take the one with the commander
961 for j in range(game.state.remcom):
962 if ibq == game.state.kcmdr[j] and ifindit!= 2:
966 if j > game.state.remcom: # no commander -- use this one
971 return # Nothing suitable -- wait until next time
972 ibq = game.state.baseq[iwhichb]
973 # decide how to move toward base
974 idelta = ibq - game.state.kscmdr
975 # Maximum movement is 1 quadrant in either or both axes
976 idelta = idelta.sgn()
977 # try moving in both x and y directions
978 # there was what looked like a bug in the Almy C code here,
979 # but it might be this translation is just wrong.
980 iq = game.state.kscmdr + idelta
981 if movescom(iq, avoid):
982 # failed -- try some other maneuvers
983 if idelta.x==0 or idelta.y==0:
986 iq.y = game.state.kscmdr.y + 1
987 if movescom(iq, avoid):
988 iq.y = game.state.kscmdr.y - 1
991 iq.x = game.state.kscmdr.x + 1
992 if movescom(iq, avoid):
993 iq.x = game.state.kscmdr.x - 1
996 # try moving just in x or y
997 iq.y = game.state.kscmdr.y
998 if movescom(iq, avoid):
999 iq.y = game.state.kscmdr.y + idelta.y
1000 iq.x = game.state.kscmdr.x
1003 if game.state.rembase == 0:
1006 for i in range(game.state.rembase):
1007 ibq = game.state.baseq[i]
1008 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1011 return # no, don't attack base!
1012 game.iseenit = False
1014 schedule(FSCDBAS, randreal(1.0, 3.0))
1015 if is_scheduled(FCDBAS):
1016 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1017 if not communicating():
1021 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1022 % game.state.kscmdr)
1023 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1024 proutn(_(" It can survive until stardate %d.\"") \
1025 % int(scheduled(FSCDBAS)))
1026 if not game.resting:
1028 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1031 game.resting = False
1032 game.optime = 0.0; # actually finished
1034 # Check for intelligence report
1037 (not communicating()) or \
1038 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1041 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1042 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1047 if not game.tholian or game.justin:
1049 if game.tholian.kloc.x == 0 and game.tholian.kloc.y == 0:
1050 idx = 0; idy = QUADSIZE-1
1051 elif game.tholian.kloc.x == 0 and game.tholian.kloc.y == QUADSIZE-1:
1052 idx = QUADSIZE-1; idy = QUADSIZE-1
1053 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == QUADSIZE-1:
1054 idx = QUADSIZE-1; idy = 0
1055 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == 0:
1058 # something is wrong!
1061 # do nothing if we are blocked
1062 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1064 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1065 if game.tholian.kloc.x != idx:
1067 im = math.fabs(idx - game.tholian.kloc.x)*1.0/(idx - game.tholian.kloc.x)
1068 while game.tholian.kloc.x != idx:
1069 game.tholian.kloc.x += im
1070 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1071 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1072 elif game.tholian.kloc.y != idy:
1074 im = math.fabs(idy - game.tholian.kloc.y)*1.0/(idy - game.tholian.kloc.y)
1075 while game.tholian.kloc.y != idy:
1076 game.tholian.kloc.y += im
1077 if game.quad[game.tholian.kloc.x][game.tholian.kloc.y]==IHDOT:
1078 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHWEB
1079 game.quad[game.tholian.kloc.x][game.tholian.kloc.y] = IHT
1080 #game.enemies[-1].kloc = game.tholian #FIXME
1081 # check to see if all holes plugged
1082 for i in range(QUADSIZE):
1083 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1085 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1087 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1089 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1091 # All plugged up -- Tholian splits
1092 game.quad[game.tholian.kloc.x][game.tholian.kloc.y]=IHWEB
1094 crmena(True, IHT, "sector", game.tholian)
1095 prout(_(" completes web."))
1096 game.tholian.move(None)
1099 # Code from battle.c begins here
1101 def doshield(shraise):
1102 # change shield status
1110 if isit("transfer"):
1114 if damaged(DSHIELD):
1115 prout(_("Shields damaged and down."))
1122 proutn(_("Do you wish to change shield energy? "))
1124 proutn(_("Energy to transfer to shields- "))
1126 elif damaged(DSHIELD):
1127 prout(_("Shields damaged and down."))
1130 proutn(_("Shields are up. Do you want them down? "))
1137 proutn(_("Shields are down. Do you want them up? "))
1143 if action == "SHUP": # raise shields
1145 prout(_("Shields already up."))
1149 if game.condition != "docked":
1151 prout(_("Shields raised."))
1152 if game.energy <= 0:
1154 prout(_("Shields raising uses up last of energy."))
1159 elif action == "SHDN":
1161 prout(_("Shields already down."))
1165 prout(_("Shields lowered."))
1168 elif action == "NRG":
1169 while scan() != IHREAL:
1171 proutn(_("Energy to transfer to shields- "))
1175 if aaitem > game.energy:
1176 prout(_("Insufficient ship energy."))
1179 if game.shield+aaitem >= game.inshld:
1180 prout(_("Shield energy maximized."))
1181 if game.shield+aaitem > game.inshld:
1182 prout(_("Excess energy requested returned to ship energy"))
1183 game.energy -= game.inshld-game.shield
1184 game.shield = game.inshld
1186 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1187 # Prevent shield drain loophole
1189 prout(_("Engineering to bridge--"))
1190 prout(_(" Scott here. Power circuit problem, Captain."))
1191 prout(_(" I can't drain the shields."))
1194 if game.shield+aaitem < 0:
1195 prout(_("All shield energy transferred to ship."))
1196 game.energy += game.shield
1199 proutn(_("Scotty- \""))
1201 prout(_("Transferring energy to shields.\""))
1203 prout(_("Draining energy from shields.\""))
1204 game.shield += aaitem
1205 game.energy -= aaitem
1209 # choose a device to damage, at random.
1211 # Quoth Eric Allman in the code of BSD-Trek:
1212 # "Under certain conditions you can get a critical hit. This
1213 # sort of hit damages devices. The probability that a given
1214 # device is damaged depends on the device. Well protected
1215 # devices (such as the computer, which is in the core of the
1216 # ship and has considerable redundancy) almost never get
1217 # damaged, whereas devices which are exposed (such as the
1218 # warp engines) or which are particularly delicate (such as
1219 # the transporter) have a much higher probability of being
1222 # This is one place where OPTION_PLAIN does not restore the
1223 # original behavior, which was equiprobable damage across
1224 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1225 # and have done with it. Also, in the original game, DNAVYS
1226 # and DCOMPTR were the same device.
1228 # Instead, we use a table of weights similar to the one from BSD Trek.
1229 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1230 # We don't have a cloaking device. The shuttle got the allocation
1231 # for the cloaking device, then we shaved a half-percent off
1232 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1235 105, # DSRSENS: short range scanners 10.5%
1236 105, # DLRSENS: long range scanners 10.5%
1237 120, # DPHASER: phasers 12.0%
1238 120, # DPHOTON: photon torpedoes 12.0%
1239 25, # DLIFSUP: life support 2.5%
1240 65, # DWARPEN: warp drive 6.5%
1241 70, # DIMPULS: impulse engines 6.5%
1242 145, # DSHIELD: deflector shields 14.5%
1243 30, # DRADIO: subspace radio 3.0%
1244 45, # DSHUTTL: shuttle 4.5%
1245 15, # DCOMPTR: computer 1.5%
1246 20, # NAVCOMP: navigation system 2.0%
1247 75, # DTRANSP: transporter 7.5%
1248 20, # DSHCTRL: high-speed shield controller 2.0%
1249 10, # DDRAY: death ray 1.0%
1250 30, # DDSP: deep-space probes 3.0%
1252 idx = randrange(1000) # weights must sum to 1000
1254 for (i, w) in enumerate(weights):
1258 return None; # we should never get here
1260 def collision(rammed, enemy):
1261 # collision handling
1262 prouts(_("***RED ALERT! RED ALERT!"))
1264 prout(_("***COLLISION IMMINENT."))
1268 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(enemy.type, 1.0)
1270 proutn(_(" rammed by "))
1273 crmena(False, enemy.type, "sector", enemy.kloc)
1275 proutn(_(" (original position)"))
1277 deadkl(enemy.kloc, enemy.type, game.sector)
1280 prout(_(" heavily damaged."))
1281 icas = randrange(10, 30)
1282 prout(_("***Sickbay reports %d casualties"), icas)
1284 game.state.crew -= icas
1286 # In the pre-SST2K version, all devices got equiprobably damaged,
1287 # which was silly. Instead, pick up to half the devices at
1288 # random according to our weighting table,
1290 ncrits = randrange(NDEVICES/2)
1291 for m in range(ncrits):
1293 if game.damage[dev] < 0:
1295 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1296 # Damage for at least time of travel!
1297 game.damage[dev] += game.optime + extradm
1299 prout(_("***Shields are down."))
1300 if game.state.remkl + game.state.remcom + game.state.nscrem:
1307 def torpedo(course, dispersion, origin, number, nburst):
1308 # let a photon torpedo fly
1311 ac = course + 0.25*dispersion
1312 angle = (15.0-ac)*0.5235988
1313 bullseye = (15.0 - course)*0.5235988
1314 deltax = -math.sin(angle);
1315 deltay = math.cos(angle);
1316 x = origin.x; y = origin.y
1317 w = coord(); jw = coord()
1318 w.x = w.y = jw.x = jw.y = 0
1319 bigger = max(math.fabs(deltax), math.fabs(deltay))
1322 if not damaged(DSRSENS) or game.condition=="docked":
1323 setwnd(srscan_window)
1325 setwnd(message_window)
1326 # Loop to move a single torpedo
1327 for step in range(1, 15+1):
1332 if not VALID_SECTOR(w.x, w.y):
1334 iquad=game.quad[w.x][w.y]
1335 tracktorpedo(w, step, number, nburst, iquad)
1339 setwnd(message_window)
1340 if damaged(DSRSENS) and not game.condition=="docked":
1341 skip(1); # start new line after text track
1342 if iquad in (IHE, IHF): # Hit our ship
1344 proutn(_("Torpedo hits "))
1347 hit = 700.0 + randreal(100) - \
1348 1000.0 * distance(w, origin) * math.fabs(math.sin(bullseye-angle))
1349 newcnd(); # we're blown out of dock
1350 # We may be displaced.
1351 if game.landed or game.condition=="docked":
1352 return hit # Cheat if on a planet
1353 ang = angle + 2.5*(randreal()-0.5)
1354 temp = math.fabs(math.sin(ang))
1355 if math.fabs(math.cos(ang)) > temp:
1356 temp = math.fabs(math.cos(ang))
1357 xx = -math.sin(ang)/temp
1358 yy = math.cos(ang)/temp
1359 jw.x = int(w.x+xx+0.5)
1360 jw.y = int(w.y+yy+0.5)
1361 if not VALID_SECTOR(jw.x, jw.y):
1363 if game.quad[jw.x][jw.y]==IHBLANK:
1366 if game.quad[jw.x][jw.y]!=IHDOT:
1367 # can't move into object
1372 elif iquad in (IHC, IHS): # Hit a commander
1374 crmena(True, iquad, "sector", w)
1375 prout(_(" uses anti-photon device;"))
1376 prout(_(" torpedo neutralized."))
1378 elif iquad in (IHR, IHK): # Hit a regular enemy
1380 for enemy in game.enemies:
1381 if w == game.enemies[ll].kloc:
1383 kp = math.fabs(e.kpower)
1384 h1 = 700.0 + randrange(100) - \
1385 1000.0 * distance(w, origin) * math.fabs(math.sin(bullseye-angle))
1389 if enemy.kpower < 0:
1393 if enemy.kpower == 0:
1396 crmena(True, iquad, "sector", w)
1397 # If enemy damaged but not destroyed, try to displace
1398 ang = angle + 2.5*(randreal()-0.5)
1399 temp = math.fabs(math.sin(ang))
1400 if math.fabs(math.cos(ang)) > temp:
1401 temp = math.fabs(math.cos(ang))
1402 xx = -math.sin(ang)/temp
1403 yy = math.cos(ang)/temp
1404 jw.x = int(w.x+xx+0.5)
1405 jw.y = int(w.y+yy+0.5)
1406 if not VALID_SECTOR(jw.x, jw.y):
1407 prout(_(" damaged but not destroyed."))
1409 if game.quad[jw.x][jw.y]==IHBLANK:
1410 prout(_(" buffeted into black hole."))
1411 deadkl(w, iquad, jw)
1413 if game.quad[jw.x][jw.y]!=IHDOT:
1414 # can't move into object
1415 prout(_(" damaged but not destroyed."))
1417 proutn(_(" damaged--"))
1421 elif iquad == IHB: # Hit a base
1423 prout(_("***STARBASE DESTROYED.."))
1424 for ll in range(game.state.rembase):
1425 if game.state.baseq[ll] == game.quadrant:
1426 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1428 game.quad[w.x][w.y]=IHDOT
1429 game.state.rembase -= 1
1430 game.base.x=game.base.y=0
1431 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1432 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1433 game.state.basekl += 1
1436 elif iquad == IHP: # Hit a planet
1437 crmena(True, iquad, "sector", w)
1438 prout(_(" destroyed."))
1439 game.state.nplankl += 1
1440 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1441 game.iplnet.pclass = "destroyed"
1443 invalidate(game.plnet)
1444 game.quad[w.x][w.y] = IHDOT
1446 # captain perishes on planet
1449 elif iquad == IHW: # Hit an inhabited world -- very bad!
1450 crmena(True, iquad, "sector", w)
1451 prout(_(" destroyed."))
1452 game.state.nworldkl += 1
1453 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1454 game.iplnet.pclass = "destroyed"
1456 invalidate(game.plnet)
1457 game.quad[w.x][w.y] = IHDOT
1459 # captain perishes on planet
1461 prout(_("You have just destroyed an inhabited planet."))
1462 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1464 elif iquad == IHSTAR: # Hit a star
1468 crmena(True, IHSTAR, "sector", w)
1469 prout(_(" unaffected by photon blast."))
1471 elif iquad == IHQUEST: # Hit a thingy
1472 if not (game.options & OPTION_THINGY) or withprob(0.3):
1474 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1476 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1478 proutn(_("Mr. Spock-"))
1479 prouts(_(" \"Fascinating!\""))
1484 # Stas Sergeev added the possibility that
1485 # you can shove the Thingy and piss it off.
1486 # It then becomes an enemy and may fire at you.
1491 elif iquad == IHBLANK: # Black hole
1493 crmena(True, IHBLANK, "sector", w)
1494 prout(_(" swallows torpedo."))
1496 elif iquad == IHWEB: # hit the web
1498 prout(_("***Torpedo absorbed by Tholian web."))
1500 elif iquad == IHT: # Hit a Tholian
1501 h1 = 700.0 + randrange(100) - \
1502 1000.0 * distance(w, origin) * math.fabs(math.sin(bullseye-angle))
1505 game.quad[w.x][w.y] = IHDOT
1510 crmena(True, IHT, "sector", w)
1512 prout(_(" survives photon blast."))
1514 prout(_(" disappears."))
1515 game.tholian.move(None)
1516 game.quad[w.x][w.y] = IHWEB
1521 proutn("Don't know how to handle torpedo collision with ")
1522 crmena(True, iquad, "sector", w)
1526 if curwnd!=message_window:
1527 setwnd(message_window)
1529 game.quad[w.x][w.y]=IHDOT
1530 game.quad[jw.x][jw.y]=iquad
1531 prout(_(" displaced by blast to Sector %s ") % jw)
1532 for ll in range(len(game.enemies)):
1533 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector,game.enemies[ll].kloc)
1534 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1537 prout(_("Torpedo missed."))
1541 # critical-hit resolution
1542 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1544 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1545 proutn(_("***CRITICAL HIT--"))
1546 # Select devices and cause damage
1548 for loop1 in range(ncrit):
1551 # Cheat to prevent shuttle damage unless on ship
1552 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1555 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1556 game.damage[j] += extradm
1558 for (i, j) in enumerate(cdam):
1560 if skipcount % 3 == 2 and i < len(cdam)-1:
1565 prout(_(" damaged."))
1566 if damaged(DSHIELD) and game.shldup:
1567 prout(_("***Shields knocked down."))
1570 def attack(torps_ok):
1571 # bad guy attacks us
1572 # torps_ok == False forces use of phasers in an attack
1573 attempt = False; ihurt = False;
1574 hitmax=0.0; hittot=0.0; chgfac=1.0
1576 # game could be over at this point, check
1580 prout("=== ATTACK!")
1581 # Tholian gets to move before attacking
1584 # if you have just entered the RNZ, you'll get a warning
1585 if game.neutz: # The one chance not to be attacked
1588 # commanders get a chance to tac-move towards you
1589 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1591 # if no enemies remain after movement, we're done
1592 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1594 # set up partial hits if attack happens during shield status change
1595 pfac = 1.0/game.inshld
1597 chgfac = 0.25 + randreal(0.5)
1599 # message verbosity control
1600 if game.skill <= SKILL_FAIR:
1602 for enemy in game.enemies:
1603 if enemy.kpower < 0:
1604 continue; # too weak to attack
1605 # compute hit strength and diminish shield power
1607 # Increase chance of photon torpedos if docked or enemy energy is low
1608 if game.condition == "docked":
1610 if enemy.kpower < 500:
1612 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1614 # different enemies have different probabilities of throwing a torp
1615 usephasers = not torps_ok or \
1616 (enemy.type == IHK and r > 0.0005) or \
1617 (enemy.type==IHC and r > 0.015) or \
1618 (enemy.type==IHR and r > 0.3) or \
1619 (enemy.type==IHS and r > 0.07) or \
1620 (enemy.type==IHQUEST and r > 0.05)
1621 if usephasers: # Enemy uses phasers
1622 if game.condition == "docked":
1623 continue; # Don't waste the effort!
1624 attempt = True; # Attempt to attack
1625 dustfac = 0.8 + randreal(0.5)
1626 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1627 enemy.kpower *= 0.75
1628 else: # Enemy uses photon torpedo
1629 course = 1.90985*math.atan2(game.sector.y-enemy.kloc.y, enemy.kloc.x-game.sector.x)
1631 proutn(_("***TORPEDO INCOMING"))
1632 if not damaged(DSRSENS):
1634 crmena(False, enemy.type, where, enemy.kloc)
1637 dispersion = (randreal()+randreal())*0.5 - 0.5
1638 dispersion += 0.002*enemy.kpower*dispersion
1639 hit = torpedo(course, dispersion, origin=enemy.kloc, number=1, nburst=1)
1640 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1641 finish(FWON); # Klingons did themselves in!
1642 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1643 return # Supernova or finished
1646 # incoming phaser or torpedo, shields may dissipate it
1647 if game.shldup or game.shldchg or game.condition=="docked":
1648 # shields will take hits
1649 propor = pfac * game.shield
1650 if game.condition =="docked":
1654 hitsh = propor*chgfac*hit+1.0
1656 if absorb > game.shield:
1657 absorb = game.shield
1658 game.shield -= absorb
1660 # taking a hit blasts us out of a starbase dock
1661 if game.condition == "docked":
1663 # but the shields may take care of it
1664 if propor > 0.1 and hit < 0.005*game.energy:
1666 # hit from this opponent got through shields, so take damage
1668 proutn(_("%d unit hit") % int(hit))
1669 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1670 proutn(_(" on the "))
1672 if not damaged(DSRSENS) and usephasers:
1674 crmena(False, enemy.type, where, enemy.kloc)
1676 # Decide if hit is critical
1682 if game.energy <= 0:
1683 # Returning home upon your shield, not with it...
1686 if not attempt and game.condition == "docked":
1687 prout(_("***Enemies decide against attacking your ship."))
1688 percent = 100.0*pfac*game.shield+0.5
1690 # Shields fully protect ship
1691 proutn(_("Enemy attack reduces shield strength to "))
1693 # Print message if starship suffered hit(s)
1695 proutn(_("Energy left %2d shields ") % int(game.energy))
1698 elif not damaged(DSHIELD):
1701 proutn(_("damaged, "))
1702 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1703 # Check if anyone was hurt
1704 if hitmax >= 200 or hittot >= 500:
1705 icas = randrange(int(hittot * 0.015))
1708 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1709 prout(_(" in that last attack.\""))
1711 game.state.crew -= icas
1712 # After attack, reset average distance to enemies
1713 for enemy in game.enemies:
1714 enemy.kavgd = enemy.kdist
1715 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1718 def deadkl(w, type, mv):
1719 # kill a Klingon, Tholian, Romulan, or Thingy
1720 # Added mv to allow enemy to "move" before dying
1721 crmena(True, type, "sector", mv)
1722 # Decide what kind of enemy it is and update appropriately
1724 # chalk up a Romulan
1725 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1727 game.state.nromrem -= 1
1731 elif type == IHQUEST:
1736 # Some type of a Klingon
1737 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1740 game.comhere = False
1741 for i in range(game.state.remcom):
1742 if game.state.kcmdr[i] == game.quadrant:
1744 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1745 game.state.kcmdr[game.state.remcom].x = 0
1746 game.state.kcmdr[game.state.remcom].y = 0
1747 game.state.remcom -= 1
1749 if game.state.remcom != 0:
1750 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1751 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1754 game.state.remkl -= 1
1756 game.state.nscrem -= 1
1758 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1762 # For each kind of enemy, finish message to player
1763 prout(_(" destroyed."))
1764 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1767 # Remove enemy ship from arrays describing local conditions
1768 for e in game.enemies:
1775 # Return None if target is invalid
1776 if not VALID_SECTOR(w.x, w.y):
1779 deltx = 0.1*(w.y - game.sector.y)
1780 delty = 0.1*(w.x - game.sector.x)
1781 if deltx==0 and delty== 0:
1783 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1784 prout(_(" I recommend an immediate review of"))
1785 prout(_(" the Captain's psychological profile.\""))
1788 return 1.90985932*math.atan2(deltx, delty)
1791 # launch photon torpedo
1793 if damaged(DPHOTON):
1794 prout(_("Photon tubes damaged."))
1798 prout(_("No torpedoes left."))
1807 prout(_("%d torpedoes left.") % game.torps)
1809 proutn(_("Number of torpedoes to fire- "))
1811 else: # key == IHREAL {
1813 if n <= 0: # abort command
1818 prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
1826 for i in range(MAXBURST):
1827 targ.append(coord())
1830 if i==0 and key == IHEOL:
1831 break; # we will try prompting
1832 if i==1 and key == IHEOL:
1833 # direct all torpedoes at one target
1836 course[i] = course[0]
1848 course[i] = targetcheck(targ[i])
1849 if course[i] == None:
1852 if i == 1 and key == IHEOL:
1853 # prompt for each one
1855 proutn(_("Target sector for torpedo number %d- ") % (i+1))
1860 targ[i].x = int(aaitem-0.5)
1865 targ[i].y = int(aaitem-0.5)
1867 course[i] = targetcheck(targ[i])
1868 if course[i] == None:
1871 # Loop for moving <n> torpedoes
1873 if game.condition != "docked":
1875 dispersion = (randreal()+randreal())*0.5 -0.5
1876 if math.fabs(dispersion) >= 0.47:
1878 dispersion *= randreal(1.2, 2.2)
1880 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1882 prouts(_("***TORPEDO MISFIRES."))
1885 prout(_(" Remainder of burst aborted."))
1887 prout(_("***Photon tubes damaged by misfire."))
1888 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1890 if game.shldup or game.condition == "docked":
1891 dispersion *= 1.0 + 0.0001*game.shield
1892 torpedo(course[i], dispersion, origin=game.sector, number=i, nburst=n)
1893 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1895 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1899 # check for phasers overheating
1901 checkburn = (rpow-1500.0)*0.00038
1902 if withprob(checkburn):
1903 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1904 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1906 def checkshctrl(rpow):
1907 # check shield control
1910 prout(_("Shields lowered."))
1912 # Something bad has happened
1913 prouts(_("***RED ALERT! RED ALERT!"))
1915 hit = rpow*game.shield/game.inshld
1916 game.energy -= rpow+hit*0.8
1917 game.shield -= hit*0.2
1918 if game.energy <= 0.0:
1919 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1924 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1926 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1927 icas = randrange(int(hit*0.012))
1932 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1933 prout(_(" %d casualties so far.\"") % icas)
1935 game.state.crew -= icas
1937 prout(_("Phaser energy dispersed by shields."))
1938 prout(_("Enemy unaffected."))
1943 # register a phaser hit on Klingons and Romulans
1944 nenhr2 = game.nenhere; kk=0
1947 for (k, wham) in enumerate(hits):
1950 dustfac = randreal(0.9, 1.0)
1951 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1952 kpini = game.enemies[kk].kpower
1953 kp = math.fabs(kpini)
1954 if PHASEFAC*hit < kp:
1956 if game.enemies[kk].kpower < 0:
1957 game.enemies[kk].kpower -= -kp
1959 game.enemies[kk].kpower -= kp
1960 kpow = game.enemies[kk].kpower
1961 w = game.enemies[kk].kloc
1963 if not damaged(DSRSENS):
1965 proutn(_("%d unit hit on ") % int(hit))
1967 proutn(_("Very small hit on "))
1968 ienm = game.quad[w.x][w.y]
1971 crmena(False, ienm, "sector", w)
1975 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1979 kk -= 1 # don't do the increment
1981 else: # decide whether or not to emasculate klingon
1982 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
1983 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
1984 prout(_(" has just lost its firepower.\""))
1985 game.enemies[kk].kpower = -kpow
1992 kz = 0; k = 1; irec=0 # Cheating inhibitor
1993 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
1997 # SR sensors and Computer are needed fopr automode
1998 if damaged(DSRSENS) or damaged(DCOMPTR):
2000 if game.condition == "docked":
2001 prout(_("Phasers can't be fired through base shields."))
2004 if damaged(DPHASER):
2005 prout(_("Phaser control damaged."))
2009 if damaged(DSHCTRL):
2010 prout(_("High speed shield control damaged."))
2013 if game.energy <= 200.0:
2014 prout(_("Insufficient energy to activate high-speed shield control."))
2017 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2019 # Original code so convoluted, I re-did it all
2020 # (That was Tom Almy talking about the C code, I think -- ESR)
2021 while automode=="NOTSET":
2026 prout(_("There is no enemy present to select."))
2029 automode="AUTOMATIC"
2033 elif isit("automatic"):
2034 if (not itarg) and game.nenhere != 0:
2035 automode = "FORCEMAN"
2038 prout(_("Energy will be expended into space."))
2039 automode = "AUTOMATIC"
2048 prout(_("Energy will be expended into space."))
2049 automode = "AUTOMATIC"
2051 automode = "FORCEMAN"
2053 automode = "AUTOMATIC"
2057 prout(_("Energy will be expended into space."))
2058 automode = "AUTOMATIC"
2060 automode = "FORCEMAN"
2062 proutn(_("Manual or automatic? "))
2067 if automode == "AUTOMATIC":
2068 if key == IHALPHA and isit("no"):
2071 if key != IHREAL and game.nenhere != 0:
2072 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2077 for i in range(game.nenhere):
2078 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2080 proutn(_("%d units required. ") % irec)
2082 proutn(_("Units to fire= "))
2088 proutn(_("Energy available= %.2f") % avail)
2091 if not rpow > avail:
2098 if key == IHALPHA and isit("no"):
2101 game.energy -= 200; # Go and do it!
2102 if checkshctrl(rpow):
2110 for i in range(game.nenhere):
2114 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2115 over = randreal(1.01, 1.06) * hits[i]
2117 powrem -= hits[i] + over
2118 if powrem <= 0 and temp < hits[i]:
2127 if extra > 0 and not game.alldone:
2129 proutn(_("*** Tholian web absorbs "))
2131 proutn(_("excess "))
2132 prout(_("phaser energy."))
2134 prout(_("%d expended on empty space.") % int(extra))
2135 elif automode == "FORCEMAN":
2138 if damaged(DCOMPTR):
2139 prout(_("Battle computer damaged, manual fire only."))
2142 prouts(_("---WORKING---"))
2144 prout(_("Short-range-sensors-damaged"))
2145 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2146 prout(_("Manual-fire-must-be-used"))
2148 elif automode == "MANUAL":
2150 for k in range(game.nenhere):
2151 aim = game.enemies[k].kloc
2152 ienm = game.quad[aim.x][aim.y]
2154 proutn(_("Energy available= %.2f") % (avail-0.006))
2158 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2159 (ienm == IHC or ienm == IHS):
2161 prout(_(" can't be located without short range scan."))
2164 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2169 if itarg and k > kz:
2170 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2173 if not damaged(DCOMPTR):
2178 proutn(_("units to fire at "))
2179 crmena(False, ienm, "sector", aim)
2182 if key == IHALPHA and isit("no"):
2190 if k==1: # Let me say I'm baffled by this
2199 # If total requested is too much, inform and start over
2201 prout(_("Available energy exceeded -- try again."))
2204 key = scan(); # scan for next value
2207 # zero energy -- abort
2210 if key == IHALPHA and isit("no"):
2215 game.energy -= 200.0
2216 if checkshctrl(rpow):
2220 # Say shield raised or malfunction, if necessary
2227 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2228 prouts(_(" CLICK CLICK POP . . ."))
2229 prout(_(" No response, sir!"))
2232 prout(_("Shields raised."))
2237 # Code from events,c begins here.
2239 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2240 # event of each type active at any given time. Mostly these means we can
2241 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2242 # BSD Trek, from which we swiped the idea, can have up to 5.
2244 def unschedule(evtype):
2245 # remove an event from the schedule
2246 game.future[evtype].date = FOREVER
2247 return game.future[evtype]
2249 def is_scheduled(evtype):
2250 # is an event of specified type scheduled
2251 return game.future[evtype].date != FOREVER
2253 def scheduled(evtype):
2254 # when will this event happen?
2255 return game.future[evtype].date
2257 def schedule(evtype, offset):
2258 # schedule an event of specified type
2259 game.future[evtype].date = game.state.date + offset
2260 return game.future[evtype]
2262 def postpone(evtype, offset):
2263 # postpone a scheduled event
2264 game.future[evtype].date += offset
2267 # rest period is interrupted by event
2270 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2272 game.resting = False
2278 # run through the event queue looking for things to do
2280 fintim = game.state.date + game.optime; yank=0
2281 ictbeam = False; istract = False
2282 w = coord(); hold = coord()
2283 ev = event(); ev2 = event()
2285 def tractorbeam(yank):
2286 # tractor beaming cases merge here
2288 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2292 prout(_(" caught in long range tractor beam--"))
2293 # If Kirk & Co. screwing around on planet, handle
2294 atover(True) # atover(true) is Grab
2297 if game.icraft: # Caught in Galileo?
2300 # Check to see if shuttle is aboard
2301 if game.iscraft == "offship":
2304 prout(_("Galileo, left on the planet surface, is captured"))
2305 prout(_("by aliens and made into a flying McDonald's."))
2306 game.damage[DSHUTTL] = -10
2307 game.iscraft = "removed"
2309 prout(_("Galileo, left on the planet surface, is well hidden."))
2311 game.quadrant = game.state.kscmdr
2313 game.quadrant = game.state.kcmdr[i]
2314 game.sector = randplace(QUADSIZE)
2316 prout(_(" is pulled to Quadrant %s, Sector %s") \
2317 % (game.quadrant, game.sector))
2319 prout(_("(Remainder of rest/repair period cancelled.)"))
2320 game.resting = False
2322 if not damaged(DSHIELD) and game.shield > 0:
2323 doshield(shraise=True) # raise shields
2324 game.shldchg = False
2326 prout(_("(Shields not currently useable.)"))
2328 # Adjust finish time to time of tractor beaming
2329 fintim = game.state.date+game.optime
2330 attack(torps_ok=False)
2331 if game.state.remcom <= 0:
2334 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2337 # Code merges here for any commander destroying base
2338 # Not perfect, but will have to do
2339 # Handle case where base is in same quadrant as starship
2340 if game.battle == game.quadrant:
2341 game.state.chart[game.battle.x][game.battle.y].starbase = False
2342 game.quad[game.base.x][game.base.y] = IHDOT
2343 game.base.x=game.base.y=0
2346 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2347 elif game.state.rembase != 1 and communicating():
2348 # Get word via subspace radio
2351 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2352 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2354 prout(_("the Klingon Super-Commander"))
2356 prout(_("a Klingon Commander"))
2357 game.state.chart[game.battle.x][game.battle.y].starbase = False
2358 # Remove Starbase from galaxy
2359 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2360 for i in range(1, game.state.rembase+1):
2361 if game.state.baseq[i] == game.battle:
2362 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2363 game.state.rembase -= 1
2365 # reinstate a commander's base attack
2369 invalidate(game.battle)
2372 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2373 for i in range(1, NEVENTS):
2374 if i == FSNOVA: proutn("=== Supernova ")
2375 elif i == FTBEAM: proutn("=== T Beam ")
2376 elif i == FSNAP: proutn("=== Snapshot ")
2377 elif i == FBATTAK: proutn("=== Base Attack ")
2378 elif i == FCDBAS: proutn("=== Base Destroy ")
2379 elif i == FSCMOVE: proutn("=== SC Move ")
2380 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2381 elif i == FDSPROB: proutn("=== Probe Move ")
2382 elif i == FDISTR: proutn("=== Distress Call ")
2383 elif i == FENSLV: proutn("=== Enslavement ")
2384 elif i == FREPRO: proutn("=== Klingon Build ")
2386 prout("%.2f" % (scheduled(i)))
2389 radio_was_broken = damaged(DRADIO)
2392 # Select earliest extraneous event, evcode==0 if no events
2397 for l in range(1, NEVENTS):
2398 if game.future[l].date < datemin:
2401 prout("== Event %d fires" % evcode)
2402 datemin = game.future[l].date
2403 xtime = datemin-game.state.date
2404 game.state.date = datemin
2405 # Decrement Federation resources and recompute remaining time
2406 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2408 if game.state.remtime <=0:
2411 # Any crew left alive?
2412 if game.state.crew <=0:
2415 # Is life support adequate?
2416 if damaged(DLIFSUP) and game.condition != "docked":
2417 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2420 game.lsupres -= xtime
2421 if game.damage[DLIFSUP] <= xtime:
2422 game.lsupres = game.inlsr
2425 if game.condition == "docked":
2426 repair /= game.docfac
2427 # Don't fix Deathray here
2428 for l in range(NDEVICES):
2429 if game.damage[l] > 0.0 and l != DDRAY:
2430 if game.damage[l]-repair > 0.0:
2431 game.damage[l] -= repair
2433 game.damage[l] = 0.0
2434 # If radio repaired, update star chart and attack reports
2435 if radio_was_broken and not damaged(DRADIO):
2436 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2437 prout(_(" surveillance reports are coming in."))
2439 if not game.iseenit:
2443 prout(_(" The star chart is now up to date.\""))
2445 # Cause extraneous event EVCODE to occur
2446 game.optime -= xtime
2447 if evcode == FSNOVA: # Supernova
2450 schedule(FSNOVA, expran(0.5*game.intime))
2451 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2453 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2454 if game.state.nscrem == 0 or \
2455 ictbeam or istract or \
2456 game.condition=="docked" or game.isatb==1 or game.iscate:
2458 if game.ientesc or \
2459 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2460 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2461 (damaged(DSHIELD) and \
2462 (game.energy < 2500 or damaged(DPHASER)) and \
2463 (game.torps < 5 or damaged(DPHOTON))):
2465 istract = ictbeam = True
2466 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2469 elif evcode == FTBEAM: # Tractor beam
2470 if game.state.remcom == 0:
2473 i = randrange(game.state.remcom)
2474 yank = distance(game.state.kcmdr[i], game.quadrant)
2475 if istract or game.condition == "docked" or yank == 0:
2476 # Drats! Have to reschedule
2478 game.optime + expran(1.5*game.intime/game.state.remcom))
2482 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2483 game.snapsht = copy.deepcopy(game.state)
2484 game.state.snap = True
2485 schedule(FSNAP, expran(0.5 * game.intime))
2486 elif evcode == FBATTAK: # Commander attacks starbase
2487 if game.state.remcom==0 or game.state.rembase==0:
2493 for j in range(game.state.rembase):
2494 for k in range(game.state.remcom):
2495 if game.state.baseq[j] == game.state.kcmdr[k] and \
2496 not game.state.baseq[j] == game.quadrant and \
2497 not game.state.baseq[j] == game.state.kscmdr:
2501 if j>game.state.rembase:
2502 # no match found -- try later
2503 schedule(FBATTAK, expran(0.3*game.intime))
2506 # commander + starbase combination found -- launch attack
2507 game.battle = game.state.baseq[j]
2508 schedule(FCDBAS, randreal(1.0, 4.0))
2509 if game.isatb: # extra time if SC already attacking
2510 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2511 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2512 game.iseenit = False
2513 if not communicating():
2514 continue # No warning :-(
2518 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2519 prout(_(" reports that it is under attack and that it can"))
2520 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2523 elif evcode == FSCDBAS: # Supercommander destroys base
2526 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2527 continue # WAS RETURN!
2529 game.battle = game.state.kscmdr
2531 elif evcode == FCDBAS: # Commander succeeds in destroying base
2534 # find the lucky pair
2535 for i in range(game.state.remcom):
2536 if game.state.kcmdr[i] == game.battle:
2538 if i > game.state.remcom or game.state.rembase == 0 or \
2539 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2540 # No action to take after all
2541 invalidate(game.battle)
2544 elif evcode == FSCMOVE: # Supercommander moves
2545 schedule(FSCMOVE, 0.2777)
2546 if not game.ientesc and not istract and game.isatb != 1 and \
2547 (not game.iscate or not game.justin):
2549 elif evcode == FDSPROB: # Move deep space probe
2550 schedule(FDSPROB, 0.01)
2551 game.probex += game.probeinx
2552 game.probey += game.probeiny
2553 i = (int)(game.probex/QUADSIZE +0.05)
2554 j = (int)(game.probey/QUADSIZE + 0.05)
2555 if game.probec.x != i or game.probec.y != j:
2558 if not VALID_QUADRANT(i, j) or \
2559 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2560 # Left galaxy or ran into supernova
2564 proutn(_("Lt. Uhura- \"The deep space probe "))
2565 if not VALID_QUADRANT(j, i):
2566 proutn(_("has left the galaxy"))
2568 proutn(_("is no longer transmitting"))
2572 if not communicating():
2575 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2576 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2577 # Update star chart if Radio is working or have access to radio
2579 chp = game.state.chart[game.probec.x][game.probec.y]
2580 chp.klingons = pdest.klingons
2581 chp.starbase = pdest.starbase
2582 chp.stars = pdest.stars
2583 pdest.charted = True
2584 game.proben -= 1 # One less to travel
2585 if game.proben == 0 and game.isarmed and pdest.stars:
2586 # lets blow the sucker!
2587 supernova(True, game.probec)
2589 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2591 elif evcode == FDISTR: # inhabited system issues distress call
2593 # try a whole bunch of times to find something suitable
2594 for i in range(100):
2595 # need a quadrant which is not the current one,
2596 # which has some stars which are inhabited and
2597 # not already under attack, which is not
2598 # supernova'ed, and which has some Klingons in it
2599 w = randplace(GALSIZE)
2600 q = game.state.galaxy[w.x][w.y]
2601 if not (game.quadrant == w or q.planet == None or \
2602 not q.planet.inhabited or \
2603 q.supernova or q.status!="secure" or q.klingons<=0):
2606 # can't seem to find one; ignore this call
2608 prout("=== Couldn't find location for distress event.")
2610 # got one!! Schedule its enslavement
2611 ev = schedule(FENSLV, expran(game.intime))
2613 q.status = distressed
2615 # tell the captain about it if we can
2617 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2619 prout(_("by a Klingon invasion fleet."))
2622 elif evcode == FENSLV: # starsystem is enslaved
2623 ev = unschedule(FENSLV)
2624 # see if current distress call still active
2625 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2629 q.status = "enslaved"
2631 # play stork and schedule the first baby
2632 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2633 ev2.quadrant = ev.quadrant
2635 # report the disaster if we can
2637 prout(_("Uhura- We've lost contact with starsystem %s") % \
2639 prout(_("in Quadrant %s.\n") % ev.quadrant)
2640 elif evcode == FREPRO: # Klingon reproduces
2641 # If we ever switch to a real event queue, we'll need to
2642 # explicitly retrieve and restore the x and y.
2643 ev = schedule(FREPRO, expran(1.0 * game.intime))
2644 # see if current distress call still active
2645 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2649 if game.state.remkl >=MAXKLGAME:
2650 continue # full right now
2651 # reproduce one Klingon
2653 if game.klhere >= MAXKLQUAD:
2655 # this quadrant not ok, pick an adjacent one
2656 for i in range(w.x - 1, w.x + 2):
2657 for j in range(w.y - 1, w.y + 2):
2658 if not VALID_QUADRANT(i, j):
2660 q = game.state.galaxy[w.x][w.y]
2661 # check for this quad ok (not full & no snova)
2662 if q.klingons >= MAXKLQUAD or q.supernova:
2666 continue # search for eligible quadrant failed
2671 game.state.remkl += 1
2673 if game.quadrant == w:
2675 game.enemies.append(newkling())
2676 # recompute time left
2678 # report the disaster if we can
2680 if game.quadrant == w:
2681 prout(_("Spock- sensors indicate the Klingons have"))
2682 prout(_("launched a warship from %s.") % q.planet)
2684 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2685 if q.planet != None:
2686 proutn(_("near %s") % q.planet)
2687 prout(_("in Quadrant %s.") % w)
2696 proutn(_("How long? "))
2701 origTime = delay = aaitem
2704 if delay >= game.state.remtime or game.nenhere != 0:
2705 proutn(_("Are you sure? "))
2708 # Alternate resting periods (events) with attacks
2712 game.resting = False
2713 if not game.resting:
2714 prout(_("%d stardates left.") % int(game.state.remtime))
2716 temp = game.optime = delay
2718 rtime = randreal(1.0, 2.0)
2722 if game.optime < delay:
2723 attack(torps_ok=False)
2731 # Repair Deathray if long rest at starbase
2732 if origTime-delay >= 9.99 and game.condition == "docked":
2733 game.damage[DDRAY] = 0.0
2734 # leave if quadrant supernovas
2735 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2737 game.resting = False
2740 # A nova occurs. It is the result of having a star hit with a
2741 # photon torpedo, or possibly of a probe warhead going off.
2742 # Stars that go nova cause stars which surround them to undergo
2743 # the same probabilistic process. Klingons next to them are
2744 # destroyed. And if the starship is next to it, it gets zapped.
2745 # If the zap is too much, it gets destroyed.
2749 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2750 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2752 # Wow! We've supernova'ed
2753 supernova(False, nov)
2755 # handle initial nova
2756 game.quad[nov.x][nov.y] = IHDOT
2757 crmena(False, IHSTAR, "sector", nov)
2759 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2760 game.state.starkl += 1
2761 # Set up queue to recursively trigger adjacent stars
2767 for offset.x in range(-1, 1+1):
2768 for offset.y in range(-1, 1+1):
2769 if offset.y==0 and offset.x==0:
2771 neighbor = start + offset
2772 if not VALID_SECTOR(neighbor.y, neighbor.x):
2774 iquad = game.quad[neighbor.x][neighbor.y]
2775 # Empty space ends reaction
2776 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2778 elif iquad == IHSTAR: # Affect another star
2780 # This star supernovas
2784 hits.append(neighbor)
2785 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2786 game.state.starkl += 1
2787 crmena(True, IHSTAR, "sector", neighbor)
2789 game.quad[neighbor.x][neighbor.y] = IHDOT
2791 elif iquad in (IHP, IHW): # Destroy planet
2792 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2794 game.state.nplankl += 1
2796 game.state.worldkl += 1
2797 crmena(True, iquad, "sector", neighbor)
2798 prout(_(" destroyed."))
2799 game.iplnet.pclass = "destroyed"
2801 invalidate(game.plnet)
2805 game.quad[neighbor.x][neighbor.y] = IHDOT
2806 elif iquad == IHB: # Destroy base
2807 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2808 for i in range(game.state.rembase):
2809 if game.state.baseq[i] == game.quadrant:
2811 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2812 game.state.rembase -= 1
2813 invalidate(game.base)
2814 game.state.basekl += 1
2816 crmena(True, IHB, "sector", neighbor)
2817 prout(_(" destroyed."))
2818 game.quad[neighbor.x][neighbor.y] = IHDOT
2819 elif iquad in (IHE, IHF): # Buffet ship
2820 prout(_("***Starship buffeted by nova."))
2822 if game.shield >= 2000.0:
2823 game.shield -= 2000.0
2825 diff = 2000.0 - game.shield
2829 prout(_("***Shields knocked out."))
2830 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2832 game.energy -= 2000.0
2833 if game.energy <= 0:
2836 # add in course nova contributes to kicking starship
2837 bump += (game.sector-hits[mm]).sgn()
2838 elif iquad == IHK: # kill klingon
2839 deadkl(neighbor, iquad, neighbor)
2840 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2841 for ll in range(game.nenhere):
2842 if game.enemies[ll].kloc == neighbor:
2844 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2845 if game.enemies[ll].kpower <= 0.0:
2846 deadkl(neighbor, iquad, neighbor)
2848 newc = neighbor + neighbor - hits[mm]
2849 crmena(True, iquad, "sector", neighbor)
2850 proutn(_(" damaged"))
2851 if not VALID_SECTOR(newc.x, newc.y):
2852 # can't leave quadrant
2855 iquad1 = game.quad[newc.x][newc.y]
2856 if iquad1 == IHBLANK:
2857 proutn(_(", blasted into "))
2858 crmena(False, IHBLANK, "sector", newc)
2860 deadkl(neighbor, iquad, newc)
2863 # can't move into something else
2866 proutn(_(", buffeted to Sector %s") % newc)
2867 game.quad[neighbor.x][neighbor.y] = IHDOT
2868 game.quad[newc.x][newc.y] = iquad
2869 game.enemies[ll].move(newc)
2870 # Starship affected by nova -- kick it away.
2871 game.dist = kount*0.1
2872 game.direc = course[3*(bump.x+1)+bump.y+2]
2873 if game.direc == 0.0:
2875 if game.dist == 0.0:
2877 game.optime = 10.0*game.dist/16.0
2879 prout(_("Force of nova displaces starship."))
2880 imove(novapush=True)
2881 game.optime = 10.0*game.dist/16.0
2884 def supernova(induced, w=None):
2885 # star goes supernova
2892 # Scheduled supernova -- select star
2893 # logic changed here so that we won't favor quadrants in top
2895 for nq.x in range(GALSIZE):
2896 for nq.y in range(GALSIZE):
2897 stars += game.state.galaxy[nq.x][nq.y].stars
2899 return # nothing to supernova exists
2900 num = randrange(stars) + 1
2901 for nq.x in range(GALSIZE):
2902 for nq.y in range(GALSIZE):
2903 num -= game.state.galaxy[nq.x][nq.y].stars
2909 proutn("=== Super nova here?")
2912 if not nq == game.quadrant or game.justin:
2913 # it isn't here, or we just entered (treat as enroute)
2916 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2917 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2920 # we are in the quadrant!
2921 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2922 for ns.x in range(QUADSIZE):
2923 for ns.y in range(QUADSIZE):
2924 if game.quad[ns.x][ns.y]==IHSTAR:
2931 prouts(_("***RED ALERT! RED ALERT!"))
2933 prout(_("***Incipient supernova detected at Sector %s") % ns)
2934 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2935 proutn(_("Emergency override attempts t"))
2936 prouts("***************")
2941 # destroy any Klingons in supernovaed quadrant
2942 kldead = game.state.galaxy[nq.x][nq.y].klingons
2943 game.state.galaxy[nq.x][nq.y].klingons = 0
2944 if nq == game.state.kscmdr:
2945 # did in the Supercommander!
2946 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2950 if game.state.remcom:
2951 maxloop = game.state.remcom
2952 for l in range(maxloop):
2953 if game.state.kcmdr[l] == nq:
2954 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
2955 invalidate(game.state.kcmdr[game.state.remcom])
2956 game.state.remcom -= 1
2958 if game.state.remcom==0:
2961 game.state.remkl -= kldead
2962 # destroy Romulans and planets in supernovaed quadrant
2963 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
2964 game.state.galaxy[nq.x][nq.y].romulans = 0
2965 game.state.nromrem -= nrmdead
2967 for loop in range(game.inplan):
2968 if game.state.planets[loop].w == nq:
2969 game.state.planets[loop].pclass = "destroyed"
2971 # Destroy any base in supernovaed quadrant
2972 if game.state.rembase:
2973 maxloop = game.state.rembase
2974 for loop in range(maxloop):
2975 if game.state.baseq[loop] == nq:
2976 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
2977 invalidate(game.state.baseq[game.state.rembase])
2978 game.state.rembase -= 1
2980 # If starship caused supernova, tally up destruction
2982 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
2983 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
2984 game.state.nplankl += npdead
2985 # mark supernova in galaxy and in star chart
2986 if game.quadrant == nq or communicating():
2987 game.state.galaxy[nq.x][nq.y].supernova = True
2988 # If supernova destroys last Klingons give special message
2989 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
2992 prout(_("Lucky you!"))
2993 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
2996 # if some Klingons remain, continue or die in supernova
3001 # Code from finish.c ends here.
3004 # self-destruct maneuver
3005 # Finish with a BANG!
3007 if damaged(DCOMPTR):
3008 prout(_("Computer damaged; cannot execute destruct sequence."))
3010 prouts(_("---WORKING---")); skip(1)
3011 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3012 prouts(" 10"); skip(1)
3013 prouts(" 9"); skip(1)
3014 prouts(" 8"); skip(1)
3015 prouts(" 7"); skip(1)
3016 prouts(" 6"); skip(1)
3018 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3020 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3022 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3026 if game.passwd != citem:
3027 prouts(_("PASSWORD-REJECTED;"))
3029 prouts(_("CONTINUITY-EFFECTED"))
3032 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3033 prouts(" 5"); skip(1)
3034 prouts(" 4"); skip(1)
3035 prouts(" 3"); skip(1)
3036 prouts(" 2"); skip(1)
3037 prouts(" 1"); skip(1)
3039 prouts(_("GOODBYE-CRUEL-WORLD"))
3047 prouts(_("********* Entropy of "))
3049 prouts(_(" maximized *********"))
3053 if game.nenhere != 0:
3054 whammo = 25.0 * game.energy
3056 while l <= game.nenhere:
3057 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3058 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3063 "Compute our rate of kils over time."
3064 elapsed = game.state.date - game.indate
3065 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3068 starting = (game.inkling + game.incom + game.inscom)
3069 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3070 return (starting - remaining)/elapsed
3074 badpt = 5.0*game.state.starkl + \
3076 10.0*game.state.nplankl + \
3077 300*game.state.nworldkl + \
3079 100.0*game.state.basekl +\
3081 if game.ship == IHF:
3083 elif game.ship == None:
3088 # end the game, with appropriate notfications
3092 prout(_("It is stardate %.1f.") % game.state.date)
3094 if ifin == FWON: # Game has been won
3095 if game.state.nromrem != 0:
3096 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3099 prout(_("You have smashed the Klingon invasion fleet and saved"))
3100 prout(_("the Federation."))
3105 badpt = 0.0 # Close enough!
3106 # killsPerDate >= RateMax
3107 if game.state.date-game.indate < 5.0 or \
3108 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3110 prout(_("In fact, you have done so well that Starfleet Command"))
3111 if game.skill == SKILL_NOVICE:
3112 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3113 elif game.skill == SKILL_FAIR:
3114 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3115 elif game.skill == SKILL_GOOD:
3116 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3117 elif game.skill == SKILL_EXPERT:
3118 prout(_("promotes you to Commodore Emeritus."))
3120 prout(_("Now that you think you're really good, try playing"))
3121 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3122 elif game.skill == SKILL_EMERITUS:
3124 proutn(_("Computer- "))
3125 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3127 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3129 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3131 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3133 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3135 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3137 prout(_("Now you can retire and write your own Star Trek game!"))
3139 elif game.skill >= SKILL_EXPERT:
3140 if game.thawed and not idebug:
3141 prout(_("You cannot get a citation, so..."))
3143 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3147 # Only grant long life if alive (original didn't!)
3149 prout(_("LIVE LONG AND PROSPER."))
3154 elif ifin == FDEPLETE: # Federation Resources Depleted
3155 prout(_("Your time has run out and the Federation has been"))
3156 prout(_("conquered. Your starship is now Klingon property,"))
3157 prout(_("and you are put on trial as a war criminal. On the"))
3158 proutn(_("basis of your record, you are "))
3159 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3160 prout(_("acquitted."))
3162 prout(_("LIVE LONG AND PROSPER."))
3164 prout(_("found guilty and"))
3165 prout(_("sentenced to death by slow torture."))
3169 elif ifin == FLIFESUP:
3170 prout(_("Your life support reserves have run out, and"))
3171 prout(_("you die of thirst, starvation, and asphyxiation."))
3172 prout(_("Your starship is a derelict in space."))
3174 prout(_("Your energy supply is exhausted."))
3176 prout(_("Your starship is a derelict in space."))
3177 elif ifin == FBATTLE:
3180 prout(_(" has been destroyed in battle."))
3182 prout(_("Dulce et decorum est pro patria mori."))
3184 prout(_("You have made three attempts to cross the negative energy"))
3185 prout(_("barrier which surrounds the galaxy."))
3187 prout(_("Your navigation is abominable."))
3190 prout(_("Your starship has been destroyed by a nova."))
3191 prout(_("That was a great shot."))
3193 elif ifin == FSNOVAED:
3196 prout(_(" has been fried by a supernova."))
3197 prout(_("...Not even cinders remain..."))
3198 elif ifin == FABANDN:
3199 prout(_("You have been captured by the Klingons. If you still"))
3200 prout(_("had a starbase to be returned to, you would have been"))
3201 prout(_("repatriated and given another chance. Since you have"))
3202 prout(_("no starbases, you will be mercilessly tortured to death."))
3203 elif ifin == FDILITHIUM:
3204 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3205 elif ifin == FMATERIALIZE:
3206 prout(_("Starbase was unable to re-materialize your starship."))
3207 prout(_("Sic transit gloria mundi"))
3208 elif ifin == FPHASER:
3211 prout(_(" has been cremated by its own phasers."))
3213 prout(_("You and your landing party have been"))
3214 prout(_("converted to energy, disipating through space."))
3215 elif ifin == FMINING:
3216 prout(_("You are left with your landing party on"))
3217 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3219 prout(_("They are very fond of \"Captain Kirk\" soup."))
3221 proutn(_("Without your leadership, the "))
3223 prout(_(" is destroyed."))
3224 elif ifin == FDPLANET:
3225 prout(_("You and your mining party perish."))
3227 prout(_("That was a great shot."))
3230 prout(_("The Galileo is instantly annihilated by the supernova."))
3231 prout(_("You and your mining party are atomized."))
3233 proutn(_("Mr. Spock takes command of the "))
3236 prout(_("joins the Romulans, reigning terror on the Federation."))
3237 elif ifin == FPNOVA:
3238 prout(_("You and your mining party are atomized."))
3240 proutn(_("Mr. Spock takes command of the "))
3243 prout(_("joins the Romulans, reigning terror on the Federation."))
3244 elif ifin == FSTRACTOR:
3245 prout(_("The shuttle craft Galileo is also caught,"))
3246 prout(_("and breaks up under the strain."))
3248 prout(_("Your debris is scattered for millions of miles."))
3249 proutn(_("Without your leadership, the "))
3251 prout(_(" is destroyed."))
3253 prout(_("The mutants attack and kill Spock."))
3254 prout(_("Your ship is captured by Klingons, and"))
3255 prout(_("your crew is put on display in a Klingon zoo."))
3256 elif ifin == FTRIBBLE:
3257 prout(_("Tribbles consume all remaining water,"))
3258 prout(_("food, and oxygen on your ship."))
3260 prout(_("You die of thirst, starvation, and asphyxiation."))
3261 prout(_("Your starship is a derelict in space."))
3263 prout(_("Your ship is drawn to the center of the black hole."))
3264 prout(_("You are crushed into extremely dense matter."))
3266 prout(_("Your last crew member has died."))
3267 if game.ship == IHF:
3269 elif game.ship == IHE:
3272 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3273 goodies = game.state.remres/game.inresor
3274 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3275 if goodies/baddies >= randreal(1.0, 1.5):
3276 prout(_("As a result of your actions, a treaty with the Klingon"))
3277 prout(_("Empire has been signed. The terms of the treaty are"))
3278 if goodies/baddies >= randreal(3.0):
3279 prout(_("favorable to the Federation."))
3281 prout(_("Congratulations!"))
3283 prout(_("highly unfavorable to the Federation."))
3285 prout(_("The Federation will be destroyed."))
3287 prout(_("Since you took the last Klingon with you, you are a"))
3288 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3289 prout(_("statue in your memory. Rest in peace, and try not"))
3290 prout(_("to think about pigeons."))
3295 # compute player's score
3296 timused = game.state.date - game.indate
3298 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3300 perdate = killrate()
3301 ithperd = 500*perdate + 0.5
3304 iwon = 100*game.skill
3305 if game.ship == IHE:
3307 elif game.ship == IHF:
3311 if not game.gamewon:
3312 game.state.nromrem = 0 # None captured if no win
3313 iscore = 10*(game.inkling - game.state.remkl) \
3314 + 50*(game.incom - game.state.remcom) \
3316 + 20*(game.inrom - game.state.nromrem) \
3317 + 200*(game.inscom - game.state.nscrem) \
3318 - game.state.nromrem \
3323 prout(_("Your score --"))
3324 if game.inrom - game.state.nromrem:
3325 prout(_("%6d Romulans destroyed %5d") %
3326 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3327 if game.state.nromrem:
3328 prout(_("%6d Romulans captured %5d") %
3329 (game.state.nromrem, game.state.nromrem))
3330 if game.inkling - game.state.remkl:
3331 prout(_("%6d ordinary Klingons destroyed %5d") %
3332 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3333 if game.incom - game.state.remcom:
3334 prout(_("%6d Klingon commanders destroyed %5d") %
3335 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3336 if game.inscom - game.state.nscrem:
3337 prout(_("%6d Super-Commander destroyed %5d") %
3338 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3340 prout(_("%6.2f Klingons per stardate %5d") %
3342 if game.state.starkl:
3343 prout(_("%6d stars destroyed by your action %5d") %
3344 (game.state.starkl, -5*game.state.starkl))
3345 if game.state.nplankl:
3346 prout(_("%6d planets destroyed by your action %5d") %
3347 (game.state.nplankl, -10*game.state.nplankl))
3348 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3349 prout(_("%6d inhabited planets destroyed by your action %5d") %
3350 (game.state.nplankl, -300*game.state.nworldkl))
3351 if game.state.basekl:
3352 prout(_("%6d bases destroyed by your action %5d") %
3353 (game.state.basekl, -100*game.state.basekl))
3355 prout(_("%6d calls for help from starbase %5d") %
3356 (game.nhelp, -45*game.nhelp))
3358 prout(_("%6d casualties incurred %5d") %
3359 (game.casual, -game.casual))
3361 prout(_("%6d crew abandoned in space %5d") %
3362 (game.abandoned, -3*game.abandoned))
3364 prout(_("%6d ship(s) lost or destroyed %5d") %
3365 (klship, -100*klship))
3367 prout(_("Penalty for getting yourself killed -200"))
3369 proutn(_("Bonus for winning "))
3370 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3371 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3372 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3373 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3374 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3375 prout(" %5d" % iwon)
3377 prout(_("TOTAL SCORE %5d") % iscore)
3380 # emit winner's commemmorative plaque
3383 proutn(_("File or device name for your plaque: "))
3386 fp = open(winner, "w")
3389 prout(_("Invalid name."))
3391 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3393 # The 38 below must be 64 for 132-column paper
3394 nskip = 38 - len(winner)/2
3395 fp.write("\n\n\n\n")
3396 # --------DRAW ENTERPRISE PICTURE.
3397 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3398 fp.write(" EEE E : : : E\n" )
3399 fp.write(" EE EEE E : : NCC-1701 : E\n")
3400 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3401 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3402 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3403 fp.write(" EEEEEEE EEEEE E E E E\n")
3404 fp.write(" EEE E E E E\n")
3405 fp.write(" E E E E\n")
3406 fp.write(" EEEEEEEEEEEEE E E\n")
3407 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3408 fp.write(" :E : EEEE E\n")
3409 fp.write(" .-E -:----- E\n")
3410 fp.write(" :E : E\n")
3411 fp.write(" EE : EEEEEEEE\n")
3412 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3414 fp.write(_(" U. S. S. ENTERPRISE\n"))
3415 fp.write("\n\n\n\n")
3416 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3418 fp.write(_(" Starfleet Command bestows to you\n"))
3420 fp.write("%*s%s\n\n" % (nskip, "", winner))
3421 fp.write(_(" the rank of\n\n"))
3422 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3424 if game.skill == SKILL_EXPERT:
3425 fp.write(_(" Expert level\n\n"))
3426 elif game.skill == SKILL_EMERITUS:
3427 fp.write(_("Emeritus level\n\n"))
3429 fp.write(_(" Cheat level\n\n"))
3430 timestring = ctime()
3431 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3432 (timestring+4, timestring+20, timestring+11))
3433 fp.write(_(" Your score: %d\n\n") % iscore)
3434 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3437 # Code from io.c begins here
3439 rows = linecount = 0 # for paging
3442 fullscreen_window = None
3443 srscan_window = None
3444 report_window = None
3445 status_window = None
3446 lrscan_window = None
3447 message_window = None
3448 prompt_window = None
3452 "wrap up, either normally or due to signal"
3453 if game.options & OPTION_CURSES:
3460 sys.stdout.write('\n')
3466 #setlocale(LC_ALL, "")
3467 #bindtextdomain(PACKAGE, LOCALEDIR)
3468 #textdomain(PACKAGE)
3469 if atexit.register(outro):
3470 sys.stderr.write("Unable to register outro(), exiting...\n")
3472 if not (game.options & OPTION_CURSES):
3473 ln_env = os.getenv("LINES")
3479 stdscr = curses.initscr()
3484 curses.start_color()
3485 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3486 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3487 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3488 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3489 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3490 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3491 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3492 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3494 global fullscreen_window, srscan_window, report_window, status_window
3495 global lrscan_window, message_window, prompt_window
3496 (rows, columns) = stdscr.getmaxyx()
3497 fullscreen_window = stdscr
3498 srscan_window = curses.newwin(12, 25, 0, 0)
3499 report_window = curses.newwin(11, 0, 1, 25)
3500 status_window = curses.newwin(10, 0, 1, 39)
3501 lrscan_window = curses.newwin(5, 0, 0, 64)
3502 message_window = curses.newwin(0, 0, 12, 0)
3503 prompt_window = curses.newwin(1, 0, rows-2, 0)
3504 message_window.scrollok(True)
3505 setwnd(fullscreen_window)
3508 def textcolor(color):
3509 "Set text foreground color. Presently a stub."
3513 "Wrap up I/O. Presently a stub."
3517 "Wait for user action -- OK to do nothing if on a TTY"
3518 if game.options & OPTION_CURSES:
3523 if game.skill > SKILL_FAIR:
3524 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3526 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3530 if game.skill > SKILL_FAIR:
3531 prompt = _("[CONTINUE?]")
3533 prompt = _("[PRESS ENTER TO CONTINUE]")
3535 if game.options & OPTION_CURSES:
3537 setwnd(prompt_window)
3538 prompt_window.wclear()
3539 prompt_window.addstr(prompt)
3540 prompt_window.getstr()
3541 prompt_window.clear()
3542 prompt_window.refresh()
3543 setwnd(message_window)
3546 sys.stdout.write('\n')
3549 for j in range(rows):
3550 sys.stdout.write('\n')
3554 "Skip i lines. Pause game if this would cause a scrolling event."
3555 for dummy in range(i):
3556 if game.options & OPTION_CURSES:
3557 (y, x) = curwnd.getyx()
3558 (my, mx) = curwnd.getmaxyx()
3559 if curwnd == message_window and y >= my - 3:
3567 if rows and linecount >= rows:
3570 sys.stdout.write('\n')
3573 "Utter a line with no following line feed."
3574 if game.options & OPTION_CURSES:
3578 sys.stdout.write(line)
3588 if not replayfp or replayfp.closed: # Don't slow down replays
3591 if game.options & OPTION_CURSES:
3595 if not replayfp or replayfp.closed:
3599 "Get a line of input."
3600 if game.options & OPTION_CURSES:
3601 line = curwnd.getstr() + "\n"
3604 if replayfp and not replayfp.closed:
3606 line = replayfp.readline()
3609 prout("*** Replay finished")
3612 elif line[0] != "#":
3615 line = raw_input() + "\n"
3621 "Change windows -- OK for this to be a no-op in tty mode."
3623 if game.options & OPTION_CURSES:
3625 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3628 "Clear to end of line -- can be a no-op in tty mode"
3629 if game.options & OPTION_CURSES:
3634 "Clear screen -- can be a no-op in tty mode."
3636 if game.options & OPTION_CURSES:
3643 "Set highlight video, if this is reasonable."
3644 if game.options & OPTION_CURSES:
3645 curwnd.attron(curses.A_REVERSE)
3648 # Things past this point have policy implications.
3652 "Hook to be called after moving to redraw maps."
3653 if game.options & OPTION_CURSES:
3656 setwnd(srscan_window)
3660 setwnd(status_window)
3661 status_window.clear()
3662 status_window.move(0, 0)
3663 setwnd(report_window)
3664 report_window.clear()
3665 report_window.move(0, 0)
3667 setwnd(lrscan_window)
3668 lrscan_window.clear()
3669 lrscan_window.move(0, 0)
3670 lrscan(silent=False)
3672 def put_srscan_sym(w, sym):
3673 "Emit symbol for short-range scan."
3674 srscan_window.move(w.x+1, w.y*2+2)
3675 srscan_window.addch(sym)
3676 srscan_window.refresh()
3679 "Enemy fall down, go boom."
3680 if game.options & OPTION_CURSES:
3682 setwnd(srscan_window)
3683 srscan_window.attron(curses.A_REVERSE)
3684 put_srscan_sym(w, game.quad[w.x][w.y])
3688 srscan_window.attroff(curses.A_REVERSE)
3689 put_srscan_sym(w, game.quad[w.x][w.y])
3690 curses.delay_output(500)
3691 setwnd(message_window)
3694 "Sound and visual effects for teleportation."
3695 if game.options & OPTION_CURSES:
3697 setwnd(message_window)
3699 prouts(" . . . . . ")
3700 if game.options & OPTION_CURSES:
3701 #curses.delay_output(1000)
3705 def tracktorpedo(w, step, i, n, iquad):
3706 "Torpedo-track animation."
3707 if not game.options & OPTION_CURSES:
3711 proutn(_("Track for torpedo number %d- ") % i)
3714 proutn(_("Torpedo track- "))
3715 elif step==4 or step==9:
3719 if not damaged(DSRSENS) or game.condition=="docked":
3720 if i != 0 and step == 1:
3723 if (iquad==IHDOT) or (iquad==IHBLANK):
3724 put_srscan_sym(w, '+')
3728 put_srscan_sym(w, iquad)
3730 curwnd.attron(curses.A_REVERSE)
3731 put_srscan_sym(w, iquad)
3735 curwnd.attroff(curses.A_REVERSE)
3736 put_srscan_sym(w, iquad)
3741 "Display the current galaxy chart."
3742 if game.options & OPTION_CURSES:
3743 setwnd(message_window)
3744 message_window.clear()
3746 if game.options & OPTION_TTY:
3751 def prstat(txt, data):
3753 if game.options & OPTION_CURSES:
3755 setwnd(status_window)
3757 proutn(" " * (NSYM - len(txt)))
3760 if game.options & OPTION_CURSES:
3761 setwnd(report_window)
3763 # Code from moving.c begins here
3765 def imove(novapush):
3766 # movement execution for warp, impulse, supernova, and tractor-beam events
3767 w = coord(); final = coord()
3770 def no_quad_change():
3771 # No quadrant change -- compute new average enemy distances
3772 game.quad[game.sector.x][game.sector.y] = game.ship
3774 for m in range(game.nenhere):
3775 finald = distance(w, game.enemies[m].kloc)
3776 game.enemies[m].kavgd = 0.5 * (finald+game.enemies[m].kdist)
3777 game.enemies[m].kdist = finald
3778 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3779 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3780 attack(torps_ok=False)
3781 for m in range(game.nenhere):
3782 game.enemies[m].kavgd = game.enemies[m].kdist
3785 setwnd(message_window)
3788 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3789 game.inorbit = False
3790 angle = ((15.0 - game.direc) * 0.5235988)
3791 deltax = -math.sin(angle)
3792 deltay = math.cos(angle)
3793 if math.fabs(deltax) > math.fabs(deltay):
3794 bigger = math.fabs(deltax)
3796 bigger = math.fabs(deltay)
3799 # If tractor beam is to occur, don't move full distance
3800 if game.state.date+game.optime >= scheduled(FTBEAM):
3802 game.condition = "red"
3803 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3804 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3805 # Move within the quadrant
3806 game.quad[game.sector.x][game.sector.y] = IHDOT
3809 n = int(10.0*game.dist*bigger+0.5)
3811 for m in range(1, n+1):
3816 if not VALID_SECTOR(w.x, w.y):
3817 # Leaving quadrant -- allow final enemy attack
3818 # Don't do it if being pushed by Nova
3819 if game.nenhere != 0 and not novapush:
3821 for m in range(game.nenhere):
3822 finald = distance(w, game.enemies[m].kloc)
3823 game.enemies[m].kavgd = 0.5 * (finald + game.enemies[m].kdist)
3825 # Stas Sergeev added the condition
3826 # that attacks only happen if Klingons
3827 # are present and your skill is good.
3829 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3830 attack(torps_ok=False)
3833 # compute final position -- new quadrant and sector
3834 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3835 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3836 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3837 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3838 # check for edge of galaxy
3848 if w.x >= GALSIZE*QUADSIZE:
3849 w.x = (GALSIZE*QUADSIZE*2) - w.x
3851 if w.y >= GALSIZE*QUADSIZE:
3852 w.y = (GALSIZE*QUADSIZE*2) - w.y
3860 if game.nkinks == 3:
3861 # Three strikes -- you're out!
3865 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3866 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3867 prout(_("YOU WILL BE DESTROYED."))
3868 # Compute final position in new quadrant
3869 if trbeam: # Don't bother if we are to be beamed
3871 game.quadrant.x = w.x/QUADSIZE
3872 game.quadrant.y = w.y/QUADSIZE
3873 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3874 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3876 prout(_("Entering Quadrant %s.") % game.quadrant)
3877 game.quad[game.sector.x][game.sector.y] = game.ship
3879 if game.skill>SKILL_NOVICE:
3880 attack(torps_ok=False)
3882 iquad = game.quad[w.x][w.y]
3884 # object encountered in flight path
3885 stopegy = 50.0*game.dist/game.optime
3886 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3887 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3889 for enemy in game.enemies:
3890 if enemy.kloc == game.sector:
3892 collision(rammed=False, enemy=enemy)
3894 elif iquad == IHBLANK:
3896 prouts(_("***RED ALERT! RED ALERT!"))
3900 proutn(_(" pulled into black hole at Sector %s") % w)
3902 # Getting pulled into a black hole was certain
3903 # death in Almy's original. Stas Sergeev added a
3904 # possibility that you'll get timewarped instead.
3907 for m in range(NDEVICES):
3908 if game.damage[m]>0:
3910 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3911 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3921 proutn(_(" encounters Tholian web at %s;") % w)
3923 proutn(_(" blocked by object at %s;") % w)
3924 proutn(_("Emergency stop required "))
3925 prout(_("%2d units of energy.") % int(stopegy))
3926 game.energy -= stopegy
3927 final.x = x-deltax+0.5
3928 final.y = y-deltay+0.5
3930 if game.energy <= 0:
3936 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3943 # dock our ship at a starbase
3945 if game.condition == "docked" and verbose:
3946 prout(_("Already docked."))
3949 prout(_("You must first leave standard orbit."))
3951 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
3953 prout(_(" not adjacent to base."))
3955 game.condition = "docked"
3959 if game.energy < game.inenrg:
3960 game.energy = game.inenrg
3961 game.shield = game.inshld
3962 game.torps = game.intorps
3963 game.lsupres = game.inlsr
3964 game.state.crew = FULLCREW
3965 if not damaged(DRADIO) and \
3966 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
3967 # get attack report from base
3968 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
3972 # This program originally required input in terms of a (clock)
3973 # direction and distance. Somewhere in history, it was changed to
3974 # cartesian coordinates. So we need to convert. Probably
3975 # "manual" input should still be done this way -- it's a real
3976 # pain if the computer isn't working! Manual mode is still confusing
3977 # because it involves giving x and y motions, yet the coordinates
3978 # are always displayed y - x, where +y is downward!
3980 def getcourse(isprobe, akey):
3981 # get course and distance
3983 dquad = copy.copy(game.quadrant)
3984 navmode = "unspecified"
3988 if game.landed and not isprobe:
3989 prout(_("Dummy! You can't leave standard orbit until you"))
3990 proutn(_("are back aboard the ship."))
3993 while navmode == "unspecified":
3994 if damaged(DNAVSYS):
3996 prout(_("Computer damaged; manual navigation only"))
3998 prout(_("Computer damaged; manual movement only"))
4003 if isprobe and akey != -1:
4004 # For probe launch, use pre-scanned value first time
4010 proutn(_("Manual or automatic- "))
4013 elif key == IHALPHA:
4018 elif isit("automatic"):
4019 navmode = "automatic"
4028 prout(_("(Manual navigation assumed.)"))
4030 prout(_("(Manual movement assumed.)"))
4033 if navmode == "automatic":
4036 proutn(_("Target quadrant or quadrant§or- "))
4038 proutn(_("Destination sector or quadrant§or- "))
4045 xi = int(round(aaitem))-1
4050 xj = int(round(aaitem))-1
4053 # both quadrant and sector specified
4054 xk = int(round(aaitem))-1
4059 xl = int(round(aaitem))-1
4065 # only one pair of numbers was specified
4067 # only quadrant specified -- go to center of dest quad
4070 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4072 # only sector specified
4076 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4083 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4085 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4086 # the actual deltas get computed here
4087 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4088 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4091 proutn(_("X and Y displacements- "))
4105 # Check for zero movement
4106 if deltax == 0 and deltay == 0:
4109 if itemp == "verbose" and not isprobe:
4111 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4112 # Course actually laid in.
4113 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4114 game.direc = math.atan2(deltax, deltay)*1.90985932
4115 if game.direc < 0.0:
4121 # move under impulse power
4123 if damaged(DIMPULS):
4126 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4128 if game.energy > 30.0:
4129 if not getcourse(isprobe=False, akey=0):
4131 power = 20.0 + 100.0*game.dist
4134 if power >= game.energy:
4135 # Insufficient power for trip
4137 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4138 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4139 if game.energy > 30:
4140 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4141 int(0.01 * (game.energy-20.0)-0.05))
4142 prout(_(" quadrants.\""))
4144 prout(_("quadrant. They are, therefore, useless.\""))
4147 # Make sure enough time is left for the trip
4148 game.optime = game.dist/0.095
4149 if game.optime >= game.state.remtime:
4150 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4151 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4152 proutn(_("we dare spend the time?\" "))
4155 # Activate impulse engines and pay the cost
4156 imove(novapush=False)
4160 power = 20.0 + 100.0*game.dist
4161 game.energy -= power
4162 game.optime = game.dist/0.095
4163 if game.energy <= 0:
4168 # move under warp drive
4169 blooey = False; twarp = False
4170 if not timewarp: # Not WARPX entry
4172 if game.damage[DWARPEN] > 10.0:
4175 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4177 if damaged(DWARPEN) and game.warpfac > 4.0:
4180 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4181 prout(_(" is repaired, I can only give you warp 4.\""))
4183 # Read in course and distance
4184 if not getcourse(isprobe=False, akey=0):
4186 # Make sure starship has enough energy for the trip
4187 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4188 if power >= game.energy:
4189 # Insufficient power for trip
4192 prout(_("Engineering to bridge--"))
4193 if not game.shldup or 0.5*power > game.energy:
4194 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4196 prout(_("We can't do it, Captain. We don't have enough energy."))
4198 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4201 prout(_("if you'll lower the shields."))
4205 prout(_("We haven't the energy to go that far with the shields up."))
4208 # Make sure enough time is left for the trip
4209 game.optime = 10.0*game.dist/game.wfacsq
4210 if game.optime >= 0.8*game.state.remtime:
4212 prout(_("First Officer Spock- \"Captain, I compute that such"))
4213 proutn(_(" a trip would require approximately %2.0f") %
4214 (100.0*game.optime/game.state.remtime))
4215 prout(_(" percent of our"))
4216 proutn(_(" remaining time. Are you sure this is wise?\" "))
4222 if game.warpfac > 6.0:
4223 # Decide if engine damage will occur
4224 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4225 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4226 if prob > randreal():
4228 game.dist = randreal(game.dist)
4229 # Decide if time warp will occur
4230 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4232 if idebug and game.warpfac==10 and not twarp:
4234 proutn("=== Force time warp? ")
4238 # If time warp or engine damage, check path
4239 # If it is obstructed, don't do warp or damage
4240 angle = ((15.0-game.direc)*0.5235998)
4241 deltax = -math.sin(angle)
4242 deltay = math.cos(angle)
4243 if math.fabs(deltax) > math.fabs(deltay):
4244 bigger = math.fabs(deltax)
4246 bigger = math.fabs(deltay)
4250 n = 10.0 * game.dist * bigger +0.5
4253 for l in range(1, n+1):
4258 if not VALID_SECTOR(ix, iy):
4260 if game.quad[ix][iy] != IHDOT:
4263 # Activate Warp Engines and pay the cost
4264 imove(novapush=False)
4267 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4268 if game.energy <= 0:
4270 game.optime = 10.0*game.dist/game.wfacsq
4274 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4276 prout(_("Engineering to bridge--"))
4277 prout(_(" Scott here. The warp engines are damaged."))
4278 prout(_(" We'll have to reduce speed to warp 4."))
4283 # change the warp factor
4289 proutn(_("Warp factor- "))
4294 if game.damage[DWARPEN] > 10.0:
4295 prout(_("Warp engines inoperative."))
4297 if damaged(DWARPEN) and aaitem > 4.0:
4298 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4299 prout(_(" but right now we can only go warp 4.\""))
4302 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4305 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4307 oldfac = game.warpfac
4308 game.warpfac = aaitem
4309 game.wfacsq=game.warpfac*game.warpfac
4310 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4311 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4314 if game.warpfac < 8.00:
4315 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4317 if game.warpfac == 10.0:
4318 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4320 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4324 # cope with being tossed out of quadrant by supernova or yanked by beam
4326 # is captain on planet?
4328 if damaged(DTRANSP):
4331 prout(_("Scotty rushes to the transporter controls."))
4333 prout(_("But with the shields up it's hopeless."))
4335 prouts(_("His desperate attempt to rescue you . . ."))
4340 prout(_("SUCCEEDS!"))
4343 proutn(_("The crystals mined were "))
4351 # Check to see if captain in shuttle craft
4356 # Inform captain of attempt to reach safety
4360 prouts(_("***RED ALERT! RED ALERT!"))
4364 prout(_(" has stopped in a quadrant containing"))
4365 prouts(_(" a supernova."))
4367 proutn(_("***Emergency automatic override attempts to hurl "))
4370 prout(_("safely out of quadrant."))
4371 if not damaged(DRADIO):
4372 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4373 # Try to use warp engines
4374 if damaged(DWARPEN):
4376 prout(_("Warp engines damaged."))
4379 game.warpfac = randreal(6.0, 8.0)
4380 game.wfacsq = game.warpfac * game.warpfac
4381 prout(_("Warp factor set to %d") % int(game.warpfac))
4382 power = 0.75*game.energy
4383 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4384 distreq = randreal(math.sqrt(2))
4385 if distreq < game.dist:
4387 game.optime = 10.0*game.dist/game.wfacsq
4388 game.direc = randreal(12) # How dumb!
4390 game.inorbit = False
4393 # This is bad news, we didn't leave quadrant.
4397 prout(_("Insufficient energy to leave quadrant."))
4400 # Repeat if another snova
4401 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4403 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4404 finish(FWON) # Snova killed remaining enemy.
4407 # let's do the time warp again
4408 prout(_("***TIME WARP ENTERED."))
4409 if game.state.snap and withprob(0.5):
4411 prout(_("You are traveling backwards in time %d stardates.") %
4412 int(game.state.date-game.snapsht.date))
4413 game.state = game.snapsht
4414 game.state.snap = False
4415 if game.state.remcom:
4416 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4417 schedule(FBATTAK, expran(0.3*game.intime))
4418 schedule(FSNOVA, expran(0.5*game.intime))
4419 # next snapshot will be sooner
4420 schedule(FSNAP, expran(0.25*game.state.remtime))
4422 if game.state.nscrem:
4423 schedule(FSCMOVE, 0.2777)
4427 invalidate(game.battle)
4429 # Make sure Galileo is consistant -- Snapshot may have been taken
4430 # when on planet, which would give us two Galileos!
4432 for l in range(game.inplan):
4433 if game.state.planets[l].known == "shuttle_down":
4435 if game.iscraft == "onship" and game.ship==IHE:
4436 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4437 game.iscraft = "offship"
4438 # Likewise, if in the original time the Galileo was abandoned, but
4439 # was on ship earlier, it would have vanished -- let's restore it.
4440 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4441 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4442 game.iscraft = "onship"
4444 # * There used to be code to do the actual reconstrction here,
4445 # * but the starchart is now part of the snapshotted galaxy state.
4447 prout(_("Spock has reconstructed a correct star chart from memory"))
4449 # Go forward in time
4450 game.optime = -0.5*game.intime*math.log(randreal())
4451 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4452 # cheat to make sure no tractor beams occur during time warp
4453 postpone(FTBEAM, game.optime)
4454 game.damage[DRADIO] += game.optime
4456 events() # Stas Sergeev added this -- do pending events
4459 # launch deep-space probe
4460 # New code to launch a deep space probe
4461 if game.nprobes == 0:
4464 if game.ship == IHE:
4465 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4467 prout(_("Ye Faerie Queene has no deep space probes."))
4472 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4474 if is_scheduled(FDSPROB):
4477 if damaged(DRADIO) and game.condition != "docked":
4478 prout(_("Spock- \"Records show the previous probe has not yet"))
4479 prout(_(" reached its destination.\""))
4481 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4485 # slow mode, so let Kirk know how many probes there are left
4486 if game.nprobes == 1:
4487 prout(_("1 probe left."))
4489 prout(_("%d probes left") % game.nprobes)
4490 proutn(_("Are you sure you want to fire a probe? "))
4493 game.isarmed = False
4494 if key == IHALPHA and citem == "armed":
4498 proutn(_("Arm NOVAMAX warhead? "))
4500 if not getcourse(isprobe=True, akey=key):
4503 angle = ((15.0 - game.direc) * 0.5235988)
4504 game.probeinx = -math.sin(angle)
4505 game.probeiny = math.cos(angle)
4506 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4507 bigger = math.fabs(game.probeinx)
4509 bigger = math.fabs(game.probeiny)
4510 game.probeiny /= bigger
4511 game.probeinx /= bigger
4512 game.proben = 10.0*game.dist*bigger +0.5
4513 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4514 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4515 game.probec = game.quadrant
4516 schedule(FDSPROB, 0.01) # Time to move one sector
4517 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4521 # Here's how the mayday code works:
4523 # First, the closest starbase is selected. If there is a a starbase
4524 # in your own quadrant, you are in good shape. This distance takes
4525 # quadrant distances into account only.
4527 # A magic number is computed based on the distance which acts as the
4528 # probability that you will be rematerialized. You get three tries.
4530 # When it is determined that you should be able to be rematerialized
4531 # (i.e., when the probability thing mentioned above comes up
4532 # positive), you are put into that quadrant (anywhere). Then, we try
4533 # to see if there is a spot adjacent to the star- base. If not, you
4534 # can't be rematerialized!!! Otherwise, it drops you there. It only
4535 # tries five times to find a spot to drop you. After that, it's your
4539 # yell for help from nearest starbase
4540 # There's more than one way to move in this game!
4543 # Test for conditions which prevent calling for help
4544 if game.condition == "docked":
4545 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4548 prout(_("Subspace radio damaged."))
4550 if game.state.rembase==0:
4551 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4554 proutn(_("You must be aboard the "))
4558 # OK -- call for help from nearest starbase
4561 # There's one in this quadrant
4562 ddist = distance(game.base, game.sector)
4565 for m in range(game.state.rembase):
4566 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4570 # Since starbase not in quadrant, set up new quadrant
4571 game.quadrant = game.state.baseq[line]
4573 # dematerialize starship
4574 game.quad[game.sector.x][game.sector.y]=IHDOT
4575 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4577 prout(_(" dematerializes."))
4579 for m in range(1, 5+1):
4580 w = game.base.scatter()
4581 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4582 # found one -- finish up
4585 if not is_valid(game.sector):
4586 prout(_("You have been lost in space..."))
4587 finish(FMATERIALIZE)
4589 # Give starbase three chances to rematerialize starship
4590 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4591 for m in range(1, 3+1):
4592 if m == 1: proutn(_("1st"))
4593 elif m == 2: proutn(_("2nd"))
4594 elif m == 3: proutn(_("3rd"))
4595 proutn(_(" attempt to re-materialize "))
4597 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4600 if randreal() > probf:
4603 curses.delay_output(500)
4606 game.quad[ix][iy]=IHQUEST
4609 setwnd(message_window)
4610 finish(FMATERIALIZE)
4612 game.quad[ix][iy]=game.ship
4614 prout(_("succeeds."))
4618 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4620 # Abandon Ship (the BSD-Trek description)
4622 # The ship is abandoned. If your current ship is the Faire
4623 # Queene, or if your shuttlecraft is dead, you're out of
4624 # luck. You need the shuttlecraft in order for the captain
4625 # (that's you!!) to escape.
4627 # Your crew can beam to an inhabited starsystem in the
4628 # quadrant, if there is one and if the transporter is working.
4629 # If there is no inhabited starsystem, or if the transporter
4630 # is out, they are left to die in outer space.
4632 # If there are no starbases left, you are captured by the
4633 # Klingons, who torture you mercilessly. However, if there
4634 # is at least one starbase, you are returned to the
4635 # Federation in a prisoner of war exchange. Of course, this
4636 # can't happen unless you have taken some prisoners.
4641 if game.condition=="docked":
4643 prout(_("You cannot abandon Ye Faerie Queene."))
4646 # Must take shuttle craft to exit
4647 if game.damage[DSHUTTL]==-1:
4648 prout(_("Ye Faerie Queene has no shuttle craft."))
4650 if game.damage[DSHUTTL]<0:
4651 prout(_("Shuttle craft now serving Big Macs."))
4653 if game.damage[DSHUTTL]>0:
4654 prout(_("Shuttle craft damaged."))
4657 prout(_("You must be aboard the ship."))
4659 if game.iscraft != "onship":
4660 prout(_("Shuttle craft not currently available."))
4662 # Print abandon ship messages
4664 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4666 prouts(_("***ALL HANDS ABANDON SHIP!"))
4668 prout(_("Captain and crew escape in shuttle craft."))
4669 if game.state.rembase==0:
4670 # Oops! no place to go...
4673 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4675 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4676 prout(_("Remainder of ship's complement beam down"))
4677 prout(_("to nearest habitable planet."))
4678 elif q.planet != None and not damaged(DTRANSP):
4679 prout(_("Remainder of ship's complement beam down to %s.") %
4682 prout(_("Entire crew of %d left to die in outer space.") %
4684 game.casual += game.state.crew
4685 game.abandoned += game.state.crew
4687 # If at least one base left, give 'em the Faerie Queene
4689 game.icrystl = False # crystals are lost
4690 game.nprobes = 0 # No probes
4691 prout(_("You are captured by Klingons and released to"))
4692 prout(_("the Federation in a prisoner-of-war exchange."))
4693 nb = randrange(game.state.rembase)
4694 # Set up quadrant and position FQ adjacient to base
4695 if not game.quadrant == game.state.baseq[nb]:
4696 game.quadrant = game.state.baseq[nb]
4697 game.sector.x = game.sector.y = 5
4700 # position next to base by trial and error
4701 game.quad[game.sector.x][game.sector.y] = IHDOT
4702 for l in range(QUADSIZE):
4703 game.sector = game.base.scatter()
4704 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4705 game.quad[game.sector.x][game.sector.y] == IHDOT:
4708 break # found a spot
4709 game.sector.x=QUADSIZE/2
4710 game.sector.y=QUADSIZE/2
4712 # Get new commission
4713 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4714 game.state.crew = FULLCREW
4715 prout(_("Starfleet puts you in command of another ship,"))
4716 prout(_("the Faerie Queene, which is antiquated but,"))
4717 prout(_("still useable."))
4719 prout(_("The dilithium crystals have been moved."))
4721 game.iscraft = "offship" # Galileo disappears
4723 game.condition="docked"
4724 for l in range(NDEVICES):
4725 game.damage[l] = 0.0
4726 game.damage[DSHUTTL] = -1
4727 game.energy = game.inenrg = 3000.0
4728 game.shield = game.inshld = 1250.0
4729 game.torps = game.intorps = 6
4730 game.lsupres=game.inlsr=3.0
4736 # Code from planets.c begins here.
4739 # abort a lengthy operation if an event interrupts it
4742 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4747 # report on (uninhabited) planets in the galaxy
4751 prout(_("Spock- \"Planet report follows, Captain.\""))
4753 for i in range(game.inplan):
4754 if game.state.planets[i].pclass == "destroyed":
4756 if (game.state.planets[i].known != "unknown" \
4757 and not game.state.planets[i].inhabited) \
4760 if idebug and game.state.planets[i].known=="unknown":
4761 proutn("(Unknown) ")
4762 proutn(_("Quadrant %s") % game.state.planets[i].w)
4763 proutn(_(" class "))
4764 proutn(game.state.planets[i].pclass)
4766 if game.state.planets[i].crystals != present:
4768 prout(_("dilithium crystals present."))
4769 if game.state.planets[i].known=="shuttle_down":
4770 prout(_(" Shuttle Craft Galileo on surface."))
4772 prout(_("No information available."))
4775 # enter standard orbit
4779 prout(_("Already in standard orbit."))
4781 if damaged(DWARPEN) and damaged(DIMPULS):
4782 prout(_("Both warp and impulse engines damaged."))
4784 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4786 prout(_(" not adjacent to planet."))
4789 game.optime = randreal(0.02, 0.05)
4790 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4794 game.height = randreal(1400, 8600)
4795 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4800 # examine planets in this quadrant
4801 if damaged(DSRSENS):
4802 if game.options & OPTION_TTY:
4803 prout(_("Short range sensors damaged."))
4805 if game.iplnet == None:
4806 if game.options & OPTION_TTY:
4807 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4809 if game.iplnet.known == "unknown":
4810 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4812 prout(_(" Planet at Sector %s is of class %s.") %
4813 (game.plnet, game.iplnet.pclass))
4814 if game.iplnet.known=="shuttle_down":
4815 prout(_(" Sensors show Galileo still on surface."))
4816 proutn(_(" Readings indicate"))
4817 if game.iplnet.crystals != "present":
4819 prout(_(" dilithium crystals present.\""))
4820 if game.iplnet.known == "unknown":
4821 game.iplnet.known = "known"
4822 elif game.iplnet.inhabited:
4823 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4824 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4827 # use the transporter
4831 if damaged(DTRANSP):
4832 prout(_("Transporter damaged."))
4833 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4835 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4839 if not game.inorbit:
4841 prout(_(" not in standard orbit."))
4844 prout(_("Impossible to transport through shields."))
4846 if game.iplnet.known=="unknown":
4847 prout(_("Spock- \"Captain, we have no information on this planet"))
4848 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4849 prout(_(" you may not go down.\""))
4851 if not game.landed and game.iplnet.crystals=="absent":
4852 prout(_("Spock- \"Captain, I fail to see the logic in"))
4853 prout(_(" exploring a planet with no dilithium crystals."))
4854 proutn(_(" Are you sure this is wise?\" "))
4858 if not (game.options & OPTION_PLAIN):
4859 nrgneed = 50 * game.skill + game.height / 100.0
4860 if nrgneed > game.energy:
4861 prout(_("Engineering to bridge--"))
4862 prout(_(" Captain, we don't have enough energy for transportation."))
4864 if not game.landed and nrgneed * 2 > game.energy:
4865 prout(_("Engineering to bridge--"))
4866 prout(_(" Captain, we have enough energy only to transport you down to"))
4867 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4868 if game.iplnet.known == "shuttle_down":
4869 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4870 proutn(_(" Are you sure this is wise?\" "))
4875 # Coming from planet
4876 if game.iplnet.known=="shuttle_down":
4877 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4881 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4882 prout(_("Landing party assembled, ready to beam up."))
4884 prout(_("Kirk whips out communicator..."))
4885 prouts(_("BEEP BEEP BEEP"))
4887 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4890 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4892 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4894 prout(_("Kirk- \"Energize.\""))
4897 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4900 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4902 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4905 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4906 game.landed = not game.landed
4907 game.energy -= nrgneed
4909 prout(_("Transport complete."))
4910 if game.landed and game.iplnet.known=="shuttle_down":
4911 prout(_("The shuttle craft Galileo is here!"))
4912 if not game.landed and game.imine:
4919 # strip-mine a world for dilithium
4923 prout(_("Mining party not on planet."))
4925 if game.iplnet.crystals == "mined":
4926 prout(_("This planet has already been strip-mined for dilithium."))
4928 elif game.iplnet.crystals == "absent":
4929 prout(_("No dilithium crystals on this planet."))
4932 prout(_("You've already mined enough crystals for this trip."))
4934 if game.icrystl and game.cryprob == 0.05:
4935 proutn(_("With all those fresh crystals aboard the "))
4938 prout(_("there's no reason to mine more at this time."))
4940 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4943 prout(_("Mining operation complete."))
4944 game.iplnet.crystals = "mined"
4945 game.imine = game.ididit = True
4948 # use dilithium crystals
4952 if not game.icrystl:
4953 prout(_("No dilithium crystals available."))
4955 if game.energy >= 1000:
4956 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4957 prout(_(" except when Condition Yellow exists."))
4959 prout(_("Spock- \"Captain, I must warn you that loading"))
4960 prout(_(" raw dilithium crystals into the ship's power"))
4961 prout(_(" system may risk a severe explosion."))
4962 proutn(_(" Are you sure this is wise?\" "))
4967 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
4968 prout(_(" Mr. Spock and I will try it.\""))
4970 prout(_("Spock- \"Crystals in place, Sir."))
4971 prout(_(" Ready to activate circuit.\""))
4973 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
4975 if with(game.cryprob):
4976 prouts(_(" \"Activating now! - - No good! It's***"))
4978 prouts(_("***RED ALERT! RED A*L********************************"))
4981 prouts(_("****************** KA-BOOM!!!! *******************"))
4985 game.energy += randreal(5000.0, 5500.0)
4986 prouts(_(" \"Activating now! - - "))
4987 prout(_("The instruments"))
4988 prout(_(" are going crazy, but I think it's"))
4989 prout(_(" going to work!! Congratulations, Sir!\""))
4994 # use shuttlecraft for planetary jaunt
4997 if damaged(DSHUTTL):
4998 if game.damage[DSHUTTL] == -1.0:
4999 if game.inorbit and game.iplnet.known == "shuttle_down":
5000 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5002 prout(_("Ye Faerie Queene had no shuttle craft."))
5003 elif game.damage[DSHUTTL] > 0:
5004 prout(_("The Galileo is damaged."))
5005 else: # game.damage[DSHUTTL] < 0
5006 prout(_("Shuttle craft is now serving Big Macs."))
5008 if not game.inorbit:
5010 prout(_(" not in standard orbit."))
5012 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5013 prout(_("Shuttle craft not currently available."))
5015 if not game.landed and game.iplnet.known=="shuttle_down":
5016 prout(_("You will have to beam down to retrieve the shuttle craft."))
5018 if game.shldup or game.condition == "docked":
5019 prout(_("Shuttle craft cannot pass through shields."))
5021 if game.iplnet.known=="unknown":
5022 prout(_("Spock- \"Captain, we have no information on this planet"))
5023 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5024 prout(_(" you may not fly down.\""))
5026 game.optime = 3.0e-5*game.height
5027 if game.optime >= 0.8*game.state.remtime:
5028 prout(_("First Officer Spock- \"Captain, I compute that such"))
5029 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5030 int(100*game.optime/game.state.remtime))
5031 prout(_("remaining time."))
5032 proutn(_("Are you sure this is wise?\" "))
5038 if game.iscraft == "onship":
5040 if not damaged(DTRANSP):
5041 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5045 proutn(_("Shuttle crew"))
5047 proutn(_("Rescue party"))
5048 prout(_(" boards Galileo and swoops toward planet surface."))
5049 game.iscraft = "offship"
5053 game.iplnet.known="shuttle_down"
5054 prout(_("Trip complete."))
5057 # Ready to go back to ship
5058 prout(_("You and your mining party board the"))
5059 prout(_("shuttle craft for the trip back to the Enterprise."))
5061 prouts(_("The short hop begins . . ."))
5063 game.iplnet.known="known"
5069 game.iscraft = "onship"
5075 prout(_("Trip complete."))
5080 prout(_("Mining party assembles in the hangar deck,"))
5081 prout(_("ready to board the shuttle craft \"Galileo\"."))
5083 prouts(_("The hangar doors open; the trip begins."))
5086 game.iscraft = "offship"
5089 game.iplnet.known = "shuttle_down"
5092 prout(_("Trip complete."))
5096 # use the big zapper
5100 if game.ship != IHE:
5101 prout(_("Ye Faerie Queene has no death ray."))
5104 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5107 prout(_("Death Ray is damaged."))
5109 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5110 prout(_(" is highly unpredictible. Considering the alternatives,"))
5111 proutn(_(" are you sure this is wise?\" "))
5114 prout(_("Spock- \"Acknowledged.\""))
5117 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5119 prout(_("Crew scrambles in emergency preparation."))
5120 prout(_("Spock and Scotty ready the death ray and"))
5121 prout(_("prepare to channel all ship's power to the device."))
5123 prout(_("Spock- \"Preparations complete, sir.\""))
5124 prout(_("Kirk- \"Engage!\""))
5126 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5129 if game.options & OPTION_PLAIN:
5133 prouts(_("Sulu- \"Captain! It's working!\""))
5135 while game.nenhere > 0:
5136 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.x][game.enemies[1].kloc.y],game.enemies[1].kloc)
5137 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5138 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5140 if (game.options & OPTION_PLAIN) == 0:
5141 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5143 prout(_(" is still operational.\""))
5145 prout(_(" has been rendered nonfunctional.\""))
5146 game.damage[DDRAY] = 39.95
5148 r = randreal() # Pick failure method
5150 prouts(_("Sulu- \"Captain! It's working!\""))
5152 prouts(_("***RED ALERT! RED ALERT!"))
5154 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5156 prouts(_("***RED ALERT! RED A*L********************************"))
5159 prouts(_("****************** KA-BOOM!!!! *******************"))
5164 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5166 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5168 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5169 prout(_(" have apparently been transformed into strange mutations."))
5170 prout(_(" Vulcans do not seem to be affected."))
5172 prout(_("Kirk- \"Raauch! Raauch!\""))
5177 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5179 proutn(_("Spock- \"I believe the word is"))
5180 prouts(_(" *ASTONISHING*"))
5181 prout(_(" Mr. Sulu."))
5182 for i in range(QUADSIZE):
5183 for j in range(QUADSIZE):
5184 if game.quad[i][j] == IHDOT:
5185 game.quad[i][j] = IHQUEST
5186 prout(_(" Captain, our quadrant is now infested with"))
5187 prouts(_(" - - - - - - *THINGS*."))
5189 prout(_(" I have no logical explanation.\""))
5191 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5193 prout(_("Scotty- \"There are so many tribbles down here"))
5194 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5198 # Code from reports.c begins here
5200 def attackreport(curt):
5201 # report status of bases under attack
5203 if is_scheduled(FCDBAS):
5204 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5205 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5206 elif game.isatb == 1:
5207 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5208 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5210 prout(_("No Starbase is currently under attack."))
5212 if is_scheduled(FCDBAS):
5213 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5215 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5219 # report on general game status
5221 s1 = "" and game.thawed and _("thawed ")
5222 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5223 s3 = (None, _("novice"). _("fair"),
5224 _("good"), _("expert"), _("emeritus"))[game.skill]
5225 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5226 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5227 prout(_("No plaque is allowed."))
5229 prout(_("This is tournament game %d.") % game.tourn)
5230 prout(_("Your secret password is \"%s\"") % game.passwd)
5231 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5232 (game.inkling + game.incom + game.inscom)))
5233 if game.incom - game.state.remcom:
5234 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5235 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5236 prout(_(", but no Commanders."))
5239 if game.skill > SKILL_FAIR:
5240 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5241 if game.state.rembase != game.inbase:
5243 if game.inbase-game.state.rembase==1:
5244 proutn(_("has been 1 base"))
5246 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5247 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5249 prout(_("There are %d bases.") % game.inbase)
5250 if communicating() or game.iseenit:
5251 # Don't report this if not seen and
5252 # either the radio is dead or not at base!
5256 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5258 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5259 if game.ship == IHE:
5260 proutn(_("You have "))
5262 proutn("%d" % (game.nprobes))
5265 proutn(_(" deep space probe"))
5269 if communicating() and is_scheduled(FDSPROB):
5271 proutn(_("An armed deep space probe is in "))
5273 proutn(_("A deep space probe is in "))
5274 prout("Quadrant %s." % game.probec)
5276 if game.cryprob <= .05:
5277 prout(_("Dilithium crystals aboard ship... not yet used."))
5281 while game.cryprob > ai:
5284 prout(_("Dilithium crystals have been used %d time%s.") % \
5285 (i, (_("s"), "")[i==1]))
5289 # long-range sensor scan
5290 if damaged(DLRSENS):
5291 # Now allow base's sensors if docked
5292 if game.condition != "docked":
5294 prout(_("LONG-RANGE SENSORS DAMAGED."))
5297 prout(_("Starbase's long-range scan"))
5299 prout(_("Long-range scan"))
5300 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5303 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5304 if not VALID_QUADRANT(x, y):
5308 if not damaged(DRADIO):
5309 game.state.galaxy[x][y].charted = True
5310 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5311 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5312 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5313 if not silent and game.state.galaxy[x][y].supernova:
5316 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5324 for i in range(NDEVICES):
5327 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5328 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5330 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5331 game.damage[i]+0.05,
5332 game.docfac*game.damage[i]+0.005))
5334 prout(_("All devices functional."))
5337 # update the chart in the Enterprise's computer from galaxy data
5338 game.lastchart = game.state.date
5339 for i in range(GALSIZE):
5340 for j in range(GALSIZE):
5341 if game.state.galaxy[i][j].charted:
5342 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5343 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5344 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5347 # display the star chart
5349 if (game.options & OPTION_AUTOSCAN):
5351 if not damaged(DRADIO):
5353 if game.lastchart < game.state.date and game.condition == "docked":
5354 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5357 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5358 if game.state.date > game.lastchart:
5359 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5360 prout(" 1 2 3 4 5 6 7 8")
5361 for i in range(GALSIZE):
5362 proutn("%d |" % (i+1))
5363 for j in range(GALSIZE):
5364 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5368 if game.state.galaxy[i][j].supernova:
5370 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5372 elif game.state.galaxy[i][j].charted:
5373 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5377 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5385 def sectscan(goodScan, i, j):
5386 # light up an individual dot in a sector
5387 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5388 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):
5389 if game.condition == "red": textcolor("red")
5390 elif game.condition == "green": textcolor("green")
5391 elif game.condition == "yellow": textcolor("yellow")
5392 elif game.condition == "docked": textcolor("cyan")
5393 elif game.condition == "dead": textcolor("brown")
5394 if game.quad[i][j] != game.ship:
5396 proutn("%c " % game.quad[i][j])
5402 # print status report lines
5404 if not req or req == 1:
5405 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5406 % (game.state.date, game.state.remtime))
5407 if not req or req == 2:
5408 if game.condition != "docked":
5411 for t in range(NDEVICES):
5412 if game.damage[t]>0:
5414 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5415 if not req or req == 3:
5416 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5417 if not req or req == 4:
5418 if damaged(DLIFSUP):
5419 if game.condition == "docked":
5420 s = _("DAMAGED, Base provides")
5422 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5425 prstat(_("Life Support"), s)
5426 if not req or req == 5:
5427 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5428 if not req or req == 6:
5430 if game.icrystl and (game.options & OPTION_SHOWME):
5431 extra = _(" (have crystals)")
5432 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5433 if not req or req == 7:
5434 prstat(_("Torpedoes"), "%d" % (game.torps))
5435 if not req or req == 8:
5436 if damaged(DSHIELD):
5442 data = _(" %d%% %.1f units") \
5443 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5444 prstat(_("Shields"), s+data)
5445 if not req or req == 9:
5446 prstat(_("Klingons Left"), "%d" \
5447 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5448 if not req or req == 10:
5449 if game.options & OPTION_WORLDS:
5450 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5451 if plnet and plnet.inhabited:
5452 prstat(_("Major system"), plnet.name)
5454 prout(_("Sector is uninhabited"))
5455 elif not req or req == 11:
5456 attackreport(not req)
5459 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5460 while scan() == IHEOL:
5461 proutn(_("Information desired? "))
5463 if citem in requests:
5464 status(requests.index(citem))
5466 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5467 prout((" date, condition, position, lsupport, warpfactor,"))
5468 prout((" energy, torpedoes, shields, klingons, system, time."))
5473 if damaged(DSRSENS):
5474 # Allow base's sensors if docked
5475 if game.condition != "docked":
5476 prout(_(" S.R. SENSORS DAMAGED!"))
5479 prout(_(" [Using Base's sensors]"))
5481 prout(_(" Short-range scan"))
5482 if goodScan and not damaged(DRADIO):
5483 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5484 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5485 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5486 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5487 prout(" 1 2 3 4 5 6 7 8 9 10")
5488 if game.condition != "docked":
5490 for i in range(QUADSIZE):
5491 proutn("%2d " % (i+1))
5492 for j in range(QUADSIZE):
5493 sectscan(goodScan, i, j)
5498 # use computer to get estimated time of arrival for a warp jump
5499 w1 = coord(); w2 = coord()
5501 if damaged(DCOMPTR):
5502 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5505 if scan() != IHREAL:
5508 proutn(_("Destination quadrant and/or sector? "))
5512 w1.y = int(aaitem-0.5)
5513 if scan() != IHREAL:
5516 w1.x = int(aaitem-0.5)
5517 if scan() == IHREAL:
5518 w2.y = int(aaitem-0.5)
5519 if scan() != IHREAL:
5522 w2.x = int(aaitem-0.5)
5524 if game.quadrant.y>w1.x:
5528 if game.quadrant.x>w1.y:
5532 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5535 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5536 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5539 prout(_("Answer \"no\" if you don't know the value:"))
5542 proutn(_("Time or arrival date? "))
5545 if ttime > game.state.date:
5546 ttime -= game.state.date # Actually a star date
5547 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5548 if ttime <= 1e-10 or twarp > 10:
5549 prout(_("We'll never make it, sir."))
5556 proutn(_("Warp factor? "))
5560 if twarp<1.0 or twarp > 10.0:
5564 prout(_("Captain, certainly you can give me one of these."))
5567 ttime = (10.0*game.dist)/square(twarp)
5568 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5569 if tpower >= game.energy:
5570 prout(_("Insufficient energy, sir."))
5571 if not game.shldup or tpower > game.energy*2.0:
5574 proutn(_("New warp factor to try? "))
5575 if scan() == IHREAL:
5578 if twarp<1.0 or twarp > 10.0:
5586 prout(_("But if you lower your shields,"))
5587 proutn(_("remaining"))
5590 proutn(_("Remaining"))
5591 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5593 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5595 prout(_("Any warp speed is adequate."))
5597 prout(_("Minimum warp needed is %.2f,") % (twarp))
5598 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5599 if game.state.remtime < ttime:
5600 prout(_("Unfortunately, the Federation will be destroyed by then."))
5602 prout(_("You'll be taking risks at that speed, Captain"))
5603 if (game.isatb==1 and game.state.kscmdr == w1 and \
5604 scheduled(FSCDBAS)< ttime+game.state.date) or \
5605 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5606 prout(_("The starbase there will be destroyed by then."))
5607 proutn(_("New warp factor to try? "))
5608 if scan() == IHREAL:
5611 if twarp<1.0 or twarp > 10.0:
5620 # Code from setup.c begins here
5623 # issue a historically correct banner
5625 prout(_("-SUPER- STAR TREK"))
5627 # From the FORTRAN original
5628 # prout(_("Latest update-21 Sept 78"))
5634 citem = "emsave.trk"
5638 proutn(_("File name: "))
5644 if '.' not in citem:
5647 fp = open(citem, "wb")
5649 prout(_("Can't freeze game as file %s") % citem)
5651 cPickle.dump(game, fp)
5655 # retrieve saved game
5656 game.passwd[0] = '\0'
5659 proutn(_("File name: "))
5665 if '.' not in citem:
5668 fp = open(citem, "rb")
5670 prout(_("Can't thaw game in %s") % citem)
5672 game = cPickle.load(fp)
5676 # I used <http://www.memory-alpha.org> to find planets
5677 # with references in ST:TOS. Eath and the Alpha Centauri
5678 # Colony have been omitted.
5680 # Some planets marked Class G and P here will be displayed as class M
5681 # because of the way planets are generated. This is a known bug.
5684 _("Andoria (Fesoan)"), # several episodes
5685 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5686 _("Vulcan (T'Khasi)"), # many episodes
5687 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5688 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5689 _("Ardana"), # TOS: "The Cloud Minders"
5690 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5691 _("Gideon"), # TOS: "The Mark of Gideon"
5692 _("Aldebaran III"), # TOS: "The Deadly Years"
5693 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5694 _("Altair IV"), # TOS: "Amok Time
5695 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5696 _("Benecia"), # TOS: "The Conscience of the King"
5697 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5698 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5699 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5700 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5701 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5702 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5703 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5704 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5705 _("Ingraham B"), # TOS: "Operation: Annihilate"
5706 _("Janus IV"), # TOS: "The Devil in the Dark"
5707 _("Makus III"), # TOS: "The Galileo Seven"
5708 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5709 _("Omega IV"), # TOS: "The Omega Glory"
5710 _("Regulus V"), # TOS: "Amok Time
5711 _("Deneva"), # TOS: "Operation -- Annihilate!"
5712 # Worlds from BSD Trek
5713 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5714 _("Beta III"), # TOS: "The Return of the Archons"
5715 _("Triacus"), # TOS: "And the Children Shall Lead",
5716 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5718 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5719 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5720 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5721 # _("Izar"), # TOS: "Whom Gods Destroy"
5722 # _("Tiburon"), # TOS: "The Way to Eden"
5723 # _("Merak II"), # TOS: "The Cloud Minders"
5724 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5725 # _("Iotia"), # TOS: "A Piece of the Action"
5729 _("S. R. Sensors"), \
5730 _("L. R. Sensors"), \
5732 _("Photon Tubes"), \
5733 _("Life Support"), \
5734 _("Warp Engines"), \
5735 _("Impulse Engines"), \
5737 _("Subspace Radio"), \
5738 _("Shuttle Craft"), \
5740 _("Navigation System"), \
5742 _("Shield Control"), \
5747 def setup(needprompt):
5748 # prepare to play, set up cosmos
5750 # Decide how many of everything
5751 if choose(needprompt):
5752 return # frozen game
5753 # Prepare the Enterprise
5754 game.alldone = game.gamewon = False
5756 game.state.crew = FULLCREW
5757 game.energy = game.inenrg = 5000.0
5758 game.shield = game.inshld = 2500.0
5759 game.shldchg = False
5763 game.quadrant = randplace(GALSIZE)
5764 game.sector = randplace(QUADSIZE)
5765 game.torps = game.intorps = 10
5766 game.nprobes = randrange(2, 5)
5768 game.wfacsq = game.warpfac * game.warpfac
5769 for i in range(NDEVICES):
5770 game.damage[i] = 0.0
5771 # Set up assorted game parameters
5772 game.battle = coord()
5773 game.state.date = game.indate = 100.0 * randreal(20, 51)
5774 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5775 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5776 game.isatb = game.state.nplankl = 0
5777 game.state.starkl = game.state.basekl = 0
5778 game.iscraft = "onship"
5782 for i in range(GALSIZE):
5783 for j in range(GALSIZE):
5784 quad = game.state.galaxy[i][j]
5789 quad.starbase = False
5790 quad.supernova = False
5791 quad.status = "secure"
5792 # Initialize times for extraneous events
5793 schedule(FSNOVA, expran(0.5 * game.intime))
5794 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5795 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5796 schedule(FBATTAK, expran(0.3*game.intime))
5798 if game.state.nscrem:
5799 schedule(FSCMOVE, 0.2777)
5804 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5805 schedule(FDISTR, expran(1.0 + game.intime))
5810 # Starchart is functional but we've never seen it
5811 game.lastchart = FOREVER
5812 # Put stars in the galaxy
5814 for i in range(GALSIZE):
5815 for j in range(GALSIZE):
5816 k = randrange(1, QUADSIZE**2/10+1)
5818 game.state.galaxy[i][j].stars = k
5819 # Locate star bases in galaxy
5820 for i in range(game.inbase):
5823 w = randplace(GALSIZE)
5824 if not game.state.galaxy[w.x][w.y].starbase:
5827 # C version: for (j = i-1; j > 0; j--)
5828 # so it did them in the opposite order.
5829 for j in range(1, i):
5830 # Improved placement algorithm to spread out bases
5831 distq = w.distance(game.state.baseq[j])
5832 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5835 prout("=== Abandoning base #%d at %s" % (i, w))
5837 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5839 prout("=== Saving base #%d, close to #%d" % (i, j))
5842 game.state.baseq[i] = w
5843 game.state.galaxy[w.x][w.y].starbase = True
5844 game.state.chart[w.x][w.y].starbase = True
5845 # Position ordinary Klingon Battle Cruisers
5847 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5848 if klumper > MAXKLQUAD:
5852 klump = (1.0 - r*r)*klumper
5857 w = randplace(GALSIZE)
5858 if not game.state.galaxy[w.x][w.y].supernova and \
5859 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5861 game.state.galaxy[w.x][w.y].klingons += int(klump)
5864 # Position Klingon Commander Ships
5865 for i in range(1, game.incom+1):
5867 w = randplace(GALSIZE)
5868 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5869 not game.state.galaxy[w.x][w.y].supernova and \
5870 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5871 not w in game.state.kcmdr[:i]:
5873 game.state.galaxy[w.x][w.y].klingons += 1
5874 game.state.kcmdr[i] = w
5875 # Locate planets in galaxy
5876 for i in range(game.inplan):
5878 w = randplace(GALSIZE)
5879 if game.state.galaxy[w.x][w.y].planet == None:
5883 new.crystals = "absent"
5884 if (game.options & OPTION_WORLDS) and i < NINHAB:
5885 new.pclass = "M" # All inhabited planets are class M
5886 new.crystals = "absent"
5888 new.name = systnames[i]
5889 new.inhabited = True
5891 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5893 new.crystals = "present"
5894 new.known = "unknown"
5895 new.inhabited = False
5896 game.state.galaxy[w.x][w.y].planet = new
5897 game.state.planets.append(new)
5899 for i in range(game.state.nromrem):
5900 w = randplace(GALSIZE)
5901 game.state.galaxy[w.x][w.y].romulans += 1
5902 # Locate the Super Commander
5903 if game.state.nscrem > 0:
5905 w = randplace(GALSIZE)
5906 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
5908 game.state.kscmdr = w
5909 game.state.galaxy[w.x][w.y].klingons += 1
5910 # Place thing (in tournament game, we don't want one!)
5912 if game.tourn is None:
5913 thing = randplace(GALSIZE)
5915 game.state.snap = False
5916 if game.skill == SKILL_NOVICE:
5917 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5918 prout(_("a deadly Klingon invasion force. As captain of the United"))
5919 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5920 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5921 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5922 prout(_("your mission. As you proceed you may be given more time."))
5924 prout(_("You will have %d supporting starbases.") % (game.inbase))
5925 proutn(_("Starbase locations- "))
5927 prout(_("Stardate %d.") % int(game.state.date))
5929 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5930 prout(_("An unknown number of Romulans."))
5931 if game.state.nscrem:
5932 prout(_("And one (GULP) Super-Commander."))
5933 prout(_("%d stardates.") % int(game.intime))
5934 proutn(_("%d starbases in ") % game.inbase)
5935 for i in range(game.inbase):
5936 proutn(`game.state.baseq[i]`)
5939 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5940 proutn(_(" Sector %s") % game.sector)
5942 prout(_("Good Luck!"))
5943 if game.state.nscrem:
5944 prout(_(" YOU'LL NEED IT."))
5947 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
5949 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5950 attack(torps_ok=False)
5952 def choose(needprompt):
5953 # choose your game type
5958 game.skill = SKILL_NONE
5960 if needprompt: # Can start with command line options
5961 proutn(_("Would you like a regular, tournament, or saved game? "))
5963 if len(citem)==0: # Try again
5965 if isit("tournament"):
5966 while scan() == IHEOL:
5967 proutn(_("Type in tournament number-"))
5970 continue # We don't want a blank entry
5971 game.tourn = int(round(aaitem))
5974 logfp.write("# random.seed(%d)\n" % aaitem)
5976 if isit("saved") or isit("frozen"):
5980 if game.passwd == None:
5982 if not game.alldone:
5983 game.thawed = True # No plaque if not finished
5989 proutn(_("What is \"%s\"?"), citem)
5991 while game.length==0 or game.skill==SKILL_NONE:
5992 if scan() == IHALPHA:
5995 elif isit("medium"):
5999 elif isit("novice"):
6000 game.skill = SKILL_NOVICE
6002 game.skill = SKILL_FAIR
6004 game.skill = SKILL_GOOD
6005 elif isit("expert"):
6006 game.skill = SKILL_EXPERT
6007 elif isit("emeritus"):
6008 game.skill = SKILL_EMERITUS
6010 proutn(_("What is \""))
6016 proutn(_("Would you like a Short, Medium, or Long game? "))
6017 elif game.skill == SKILL_NONE:
6018 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6019 # Choose game options -- added by ESR for SST2K
6020 if scan() != IHALPHA:
6022 proutn(_("Choose your game style (or just press enter): "))
6025 # Approximates the UT FORTRAN version.
6026 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6027 game.options |= OPTION_PLAIN
6029 # Approximates Tom Almy's version.
6030 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6031 game.options |= OPTION_ALMY
6035 proutn(_("What is \"%s\"?") % citem)
6037 if game.passwd == "debug":
6039 fputs("=== Debug mode enabled\n", sys.stdout)
6041 # Use parameters to generate initial values of things
6042 game.damfac = 0.5 * game.skill
6043 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6044 game.inbase = game.state.rembase
6046 if game.options & OPTION_PLANETS:
6047 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6048 if game.options & OPTION_WORLDS:
6049 game.inplan += int(NINHAB)
6050 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6051 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6052 game.state.remtime = 7.0 * game.length
6053 game.intime = game.state.remtime
6054 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6055 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6056 game.state.remcom = min(10, game.incom)
6057 game.incom = game.state.remcom
6058 game.state.remres = (game.inkling+4*game.incom)*game.intime
6059 game.inresor = game.state.remres
6060 if game.inkling > 50:
6061 game.state.rembase += 1
6062 game.inbase = game.state.rembase
6065 def dropin(iquad=None):
6066 # drop a feature on a random dot in the current quadrant
6069 w = randplace(QUADSIZE)
6070 if game.quad[w.x][w.y] == IHDOT:
6072 if iquad is not None:
6073 game.quad[w.x][w.y] = iquad
6077 # update our alert status
6078 game.condition = "green"
6079 if game.energy < 1000.0:
6080 game.condition = "yellow"
6081 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6082 game.condition = "red"
6084 game.condition="dead"
6087 # drop new Klingon into current quadrant
6088 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
6091 # set up a new state of quadrant, for when we enter or re-enter it
6095 game.comhere = False
6101 game.inorbit = False
6103 game.ientesc = False
6104 game.iseenit = False
6106 # Attempt to escape Super-commander, so tbeam back!
6109 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6110 # cope with supernova
6113 game.klhere = q.klingons
6114 game.irhere = q.romulans
6115 game.nenhere = game.klhere + game.irhere
6117 game.quad[game.sector.x][game.sector.y] = game.ship
6120 # Position ordinary Klingons
6121 for i in range(game.klhere):
6123 # If we need a commander, promote a Klingon
6124 for i in range(game.state.remcom):
6125 if game.state.kcmdr[i] == game.quadrant:
6126 e = game.enemies[game.klhere-1]
6127 game.quad[e.kloc.x][e.kloc.y] = IHC
6128 e.kpower = randreal(950,1350) + 50.0*game.skill
6131 # If we need a super-commander, promote a Klingon
6132 if game.quadrant == game.state.kscmdr:
6134 game.quad[e.kloc.x][e.kloc.y] = IHS
6135 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
6136 game.iscate = (game.state.remkl > 1)
6138 # Put in Romulans if needed
6139 for i in range(game.klhere, game.nenhere):
6140 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
6141 # If quadrant needs a starbase, put it in
6143 game.base = dropin(IHB)
6144 # If quadrant needs a planet, put it in
6146 game.iplnet = q.planet
6147 if not q.planet.inhabited:
6148 game.plnet = dropin(IHP)
6150 game.plnet = dropin(IHW)
6151 # Check for condition
6154 if game.irhere > 0 and game.klhere == 0:
6156 if not damaged(DRADIO):
6158 prout(_("LT. Uhura- \"Captain, an urgent message."))
6159 prout(_(" I'll put it on audio.\" CLICK"))
6161 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6162 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6164 # Put in THING if needed
6165 if thing == game.quadrant:
6166 enemy(type=IHQUEST, loc=dropin(),
6167 power=randreal(6000,6500.0)+250.0*game.skill)
6168 if not damaged(DSRSENS):
6170 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6171 prout(_(" Please examine your short-range scan.\""))
6172 # Decide if quadrant needs a Tholian; lighten up if skill is low
6173 if game.options & OPTION_THOLIAN:
6174 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6175 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6176 (game.skill > SKILL_GOOD and withprob(0.08)):
6179 w.x = withprob(0.5) * (QUADSIZE-1)
6180 w.y = withprob(0.5) * (QUADSIZE-1)
6181 if game.quad[w.x][w.y] == IHDOT:
6183 game.tholian = enemy(type=IHT, loc=w,
6184 power=randrange(100, 500) + 25.0*game.skill)
6185 # Reserve unoccupied corners
6186 if game.quad[0][0]==IHDOT:
6187 game.quad[0][0] = 'X'
6188 if game.quad[0][QUADSIZE-1]==IHDOT:
6189 game.quad[0][QUADSIZE-1] = 'X'
6190 if game.quad[QUADSIZE-1][0]==IHDOT:
6191 game.quad[QUADSIZE-1][0] = 'X'
6192 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6193 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6194 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
6195 # And finally the stars
6196 for i in range(q.stars):
6198 # Put in a few black holes
6199 for i in range(1, 3+1):
6202 # Take out X's in corners if Tholian present
6204 if game.quad[0][0]=='X':
6205 game.quad[0][0] = IHDOT
6206 if game.quad[0][QUADSIZE-1]=='X':
6207 game.quad[0][QUADSIZE-1] = IHDOT
6208 if game.quad[QUADSIZE-1][0]=='X':
6209 game.quad[QUADSIZE-1][0] = IHDOT
6210 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6211 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6214 # set the self-destruct password
6215 if game.options & OPTION_PLAIN:
6218 proutn(_("Please type in a secret password- "))
6221 if game.passwd != None:
6226 game.passwd += chr(ord('a')+randrange(26))
6228 # Code from sst.c begins here
6231 "SRSCAN": OPTION_TTY,
6232 "STATUS": OPTION_TTY,
6233 "REQUEST": OPTION_TTY,
6234 "LRSCAN": OPTION_TTY,
6247 "SENSORS": OPTION_PLANETS,
6248 "ORBIT": OPTION_PLANETS,
6249 "TRANSPORT": OPTION_PLANETS,
6250 "MINE": OPTION_PLANETS,
6251 "CRYSTALS": OPTION_PLANETS,
6252 "SHUTTLE": OPTION_PLANETS,
6253 "PLANETS": OPTION_PLANETS,
6258 "PROBE": OPTION_PROBE,
6260 "FREEZE": 0, # Synonym for SAVE
6266 "SOS": 0, # Synonym for MAYDAY
6267 "CALL": 0, # Synonym for MAYDAY
6274 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6277 # generate a list of legal commands
6279 proutn(_("LEGAL COMMANDS ARE:"))
6280 for key in commands:
6284 proutn("%-12s " % key)
6289 # browse on-line help
6290 # Give help on commands
6294 setwnd(prompt_window)
6295 proutn(_("Help on what command? "))
6297 setwnd(message_window)
6300 if citem in commands or citem == "ABBREV":
6309 fp = open(SSTDOC, "r")
6312 fp = open(DOC_NAME, "r")
6314 prout(_("Spock- \"Captain, that information is missing from the"))
6315 proutn(_(" computer. You need to find "))
6317 prout(_(" and put it in the"))
6318 proutn(_(" current directory or to "))
6322 # This used to continue: "You need to find SST.DOC and put
6323 # it in the current directory."
6327 linebuf = fp.readline()
6329 prout(_("Spock- \"Captain, there is no information on that command.\""))
6332 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6333 linebuf = linebuf[3:].strip()
6337 prout(_("Spock- \"Captain, I've found the following information:\""))
6339 while linebuf in fp:
6340 if "******" in linebuf:
6346 # command-interpretation loop
6349 setwnd(message_window)
6350 while True: # command loop
6352 while True: # get a command
6357 setwnd(prompt_window)
6361 if game.options & OPTION_CURSES:
6366 setwnd(message_window)
6368 candidates = filter(lambda x: x.startswith(citem.upper()),
6370 if len(candidates) == 1:
6373 elif candidates and not (game.options & OPTION_PLAIN):
6374 prout("Commands with that prefix: " + " ".join(candidates))
6378 if cmd == "SRSCAN": # srscan
6380 elif cmd == "STATUS": # status
6382 elif cmd == "REQUEST": # status request
6384 elif cmd == "LRSCAN": # long range scan
6385 lrscan(silent=False)
6386 elif cmd == "PHASERS": # phasers
6390 elif cmd == "TORPEDO": # photon torpedos
6394 elif cmd == "MOVE": # move under warp
6396 elif cmd == "SHIELDS": # shields
6397 doshield(shraise=False)
6400 game.shldchg = False
6401 elif cmd == "DOCK": # dock at starbase
6404 attack(torps_ok=False)
6405 elif cmd == "DAMAGES": # damage reports
6407 elif cmd == "CHART": # chart
6409 elif cmd == "IMPULSE": # impulse
6411 elif cmd == "REST": # rest
6415 elif cmd == "WARP": # warp
6417 elif cmd == "SCORE": # score
6419 elif cmd == "SENSORS": # sensors
6421 elif cmd == "ORBIT": # orbit
6425 elif cmd == "TRANSPORT": # transport "beam"
6427 elif cmd == "MINE": # mine
6431 elif cmd == "CRYSTALS": # crystals
6435 elif cmd == "SHUTTLE": # shuttle
6439 elif cmd == "PLANETS": # Planet list
6441 elif cmd == "REPORT": # Game Report
6443 elif cmd == "COMPUTER": # use COMPUTER!
6445 elif cmd == "COMMANDS":
6447 elif cmd == "EMEXIT": # Emergency exit
6448 clrscr() # Hide screen
6449 freeze(True) # forced save
6450 raise SysExit,1 # And quick exit
6451 elif cmd == "PROBE":
6452 probe() # Launch probe
6455 elif cmd == "ABANDON": # Abandon Ship
6457 elif cmd == "DESTRUCT": # Self Destruct
6459 elif cmd == "SAVE": # Save Game
6462 if game.skill > SKILL_GOOD:
6463 prout(_("WARNING--Saved games produce no plaques!"))
6464 elif cmd == "DEATHRAY": # Try a desparation measure
6468 elif cmd == "DEBUGCMD": # What do we want for debug???
6470 elif cmd == "MAYDAY": # Call for help
6475 game.alldone = True # quit the game
6480 break # Game has ended
6481 if game.optime != 0.0:
6484 break # Events did us in
6485 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6488 if hitme and not game.justin:
6489 attack(torps_ok=True)
6492 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6504 if cmd == IHR: s = _("Romulan")
6505 elif cmd == IHK: s = _("Klingon")
6506 elif cmd == IHC: s = _("Commander")
6507 elif cmd == IHS: s = _("Super-commander")
6508 elif cmd == IHSTAR: s = _("Star")
6509 elif cmd == IHP: s = _("Planet")
6510 elif cmd == IHB: s = _("Starbase")
6511 elif cmd == IHBLANK: s = _("Black hole")
6512 elif cmd == IHT: s = _("Tholian")
6513 elif cmd == IHWEB: s = _("Tholian web")
6514 elif cmd == IHQUEST: s = _("Stranger")
6515 elif cmd == IHW: s = _("Inhabited World")
6516 else: s = "Unknown??"
6519 def crmena(stars, enemy, loctype, w):
6520 # print an enemy and his location
6526 if loctype == "quadrant":
6527 buf = _("Quadrant ")
6528 elif loctype == "sector":
6533 # print our ship name
6534 if game.ship == IHE:
6536 elif game.ship == IHF:
6537 s = _("Faerie Queene")
6543 # print a line of stars
6544 prouts("******************************************************")
6548 return -avrage*math.log(1e-7 + randreal())
6550 def randplace(size):
6551 # choose a random location
6553 w.x = randrange(size)
6554 w.y = randrange(size)
6558 # Demand input for next scan
6563 # return IHEOL next time
6568 # Get a token from the user
6569 global inqueue, line, citem, aaitem
6573 # Read a line if nothing here
6576 if curwnd==prompt_window:
6578 setwnd(message_window)
6580 # Skip leading white space
6581 line = line.lstrip()
6583 inqueue = line.split()
6589 # From here on in it's all looking at the queue
6590 citem = inqueue.pop(0)
6594 aaitem = float(citem)
6599 citem = citem.lower()
6603 # yes-or-no confirmation
6612 proutn(_("Please answer with \"y\" or \"n\": "))
6615 # complain about unparseable input
6618 prout(_("Beg your pardon, Captain?"))
6621 # compares s to citem and returns true if it matches to the length of s
6622 return s.startswith(citem)
6625 # access to the internals for debugging
6626 proutn("Reset levels? ")
6628 if game.energy < game.inenrg:
6629 game.energy = game.inenrg
6630 game.shield = game.inshld
6631 game.torps = game.intorps
6632 game.lsupres = game.inlsr
6633 proutn("Reset damage? ")
6635 for i in range(NDEVICES):
6636 if game.damage[i] > 0.0:
6637 game.damage[i] = 0.0
6638 proutn("Toggle debug flag? ")
6642 prout("Debug output ON")
6644 prout("Debug output OFF")
6645 proutn("Cause selective damage? ")
6647 for i in range(NDEVICES):
6653 if key == IHALPHA and isit("y"):
6654 game.damage[i] = 10.0
6655 proutn("Examine/change events? ")
6660 FSNOVA: "Supernova ",
6663 FBATTAK: "Base Attack ",
6664 FCDBAS: "Base Destroy ",
6665 FSCMOVE: "SC Move ",
6666 FSCDBAS: "SC Base Destroy ",
6667 FDSPROB: "Probe Move ",
6668 FDISTR: "Distress Call ",
6669 FENSLV: "Enslavement ",
6670 FREPRO: "Klingon Build ",
6672 for i in range(1, NEVENTS):
6675 proutn("%.2f" % (scheduled(i)-game.state.date))
6676 if i == FENSLV or i == FREPRO:
6678 proutn(" in %s" % ev.quadrant)
6688 ev = schedule(i, aaitem)
6689 if i == FENSLV or i == FREPRO:
6691 proutn("In quadrant- ")
6693 # IHEOL says to leave coordinates as they are
6696 prout("Event %d canceled, no x coordinate." % (i))
6699 w.x = int(round(aaitem))
6702 prout("Event %d canceled, no y coordinate." % (i))
6705 w.y = int(round(aaitem))
6708 proutn("Induce supernova here? ")
6710 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6713 if __name__ == '__main__':
6715 global line, thing, game, idebug
6716 game = citem = aaitem = inqueue = None
6722 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6723 # Disable curses mode until the game logic is working.
6724 # if os.getenv("TERM"):
6725 # game.options |= OPTION_CURSES | OPTION_SHOWME
6727 game.options |= OPTION_TTY
6728 seed = int(time.time())
6729 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6730 for (switch, val) in options:
6733 replayfp = open(val, "r")
6735 sys.stderr.write("sst: can't open replay file %s\n" % val)
6738 line = replayfp.readline().strip()
6739 (leader, key, seed) = line.split()
6741 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6742 line = replayfp.readline().strip()
6743 arguments += line.split()[2:]
6745 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6747 game.options |= OPTION_TTY
6748 game.options &=~ OPTION_CURSES
6749 elif switch == '-t':
6750 game.options |= OPTION_TTY
6751 game.options &=~ OPTION_CURSES
6752 elif switch == '-x':
6755 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6757 # where to save the input in case of bugs
6759 logfp = open("/usr/tmp/sst-input.log", "w")
6761 sys.stderr.write("sst: warning, can't open logfile\n")
6763 logfp.write("# seed %s\n" % seed)
6764 logfp.write("# options %s\n" % " ".join(arguments))
6772 while True: # Play a game
6773 setwnd(fullscreen_window)
6776 setup(needprompt=not inqueue)
6779 game.alldone = False
6785 if game.tourn and game.alldone:
6786 proutn(_("Do you want your score recorded?"))
6791 proutn(_("Do you want to play again? "))
6795 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6799 except KeyboardInterrupt: