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 # How to represent features
234 def __init__(self, x=None, y=None):
237 def invalidate(self):
238 self.x = self.y = None
240 return self.x != None and self.y != None
241 def __eq__(self, other):
242 return other != None and self.x == other.y and self.x == other.y
243 def __add__(self, other):
244 return coord(self.x+self.x, self.y+self.y)
245 def __sub__(self, other):
246 return coord(self.x-other.x, self.y-other.y)
247 def __mul__(self, other):
248 return coord(self.x*other, self.y*other)
249 def __rmul__(self, other):
250 return coord(self.x*other, self.y*other)
251 def distance(self, other=None):
252 if not other: other = coord(0, 0)
253 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
254 def bearing(self, other=None):
255 if not other: other = coord(0, 0)
256 return 1.90985*math.atan2(self.x-other.x, self.y-other.y)
262 s.x = self.x / abs(self.x)
266 s.y = self.y / abs(self.y)
270 s.x = self.x + randrange(-1, 2)
271 s.y = self.y + randrange(-1, 2)
276 if self.x == None or self.y == None:
278 return "%s - %s" % (self.x+1, self.y+1)
283 self.name = None # string-valued if inhabited
284 self.w = coord() # quadrant located
285 self.pclass = None # could be ""M", "N", "O", or "destroyed"
286 self.crystals = "absent"# could be "mined", "present", "absent"
287 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
288 self.inhabited = False # is it inhabites?
299 self.supernova = None
301 self.status = None # Could be "secure", "distressed", "enslaved"
309 def fill2d(size, fillfun):
310 "Fill an empty list in 2D."
312 for i in range(size):
314 for j in range(size):
315 lst[i].append(fillfun(i, j))
320 self.snap = False # snapshot taken
321 self.crew = 0 # crew complement
322 self.remkl = 0 # remaining klingons
323 self.remcom = 0 # remaining commanders
324 self.nscrem = 0 # remaining super commanders
325 self.rembase = 0 # remaining bases
326 self.starkl = 0 # destroyed stars
327 self.basekl = 0 # destroyed bases
328 self.nromrem = 0 # Romulans remaining
329 self.nplankl = 0 # destroyed uninhabited planets
330 self.nworldkl = 0 # destroyed inhabited planets
331 self.planets = [] # Planet information
332 self.date = 0.0 # stardate
333 self.remres = 0 # remaining resources
334 self.remtime = 0 # remaining time
335 self.baseq = [] # Base quadrant coordinates
336 for i in range(BASEMAX):
337 self.baseq.append(coord())
338 self.kcmdr = [] # Commander quadrant coordinates
339 for i in range(QUADSIZE):
340 self.kcmdr.append(coord())
341 self.kscmdr = coord() # Supercommander quadrant coordinates
342 # the galaxy (subscript 0 not used)
343 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
344 # the starchart (subscript 0 not used)
345 self.chart = fill2d(GALSIZE, lambda i, j: page())
349 self.date = None # A real number
350 self.quadrant = None # A coord structure
353 OPTION_ALL = 0xffffffff
354 OPTION_TTY = 0x00000001 # old interface
355 OPTION_CURSES = 0x00000002 # new interface
356 OPTION_IOMODES = 0x00000003 # cover both interfaces
357 OPTION_PLANETS = 0x00000004 # planets and mining
358 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
359 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
360 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
361 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
362 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
363 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
364 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
365 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
366 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
367 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
368 OPTION_PLAIN = 0x01000000 # user chose plain game
369 OPTION_ALMY = 0x02000000 # user chose Almy variant
388 NDEVICES= 16 # Number of devices
397 def damaged(dev): return (game.damage[dev] != 0.0)
398 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
400 # Define future events
401 FSPY = 0 # Spy event happens always (no future[] entry)
402 # can cause SC to tractor beam Enterprise
403 FSNOVA = 1 # Supernova
404 FTBEAM = 2 # Commander tractor beams Enterprise
405 FSNAP = 3 # Snapshot for time warp
406 FBATTAK = 4 # Commander attacks base
407 FCDBAS = 5 # Commander destroys base
408 FSCMOVE = 6 # Supercommander moves (might attack base)
409 FSCDBAS = 7 # Supercommander destroys base
410 FDSPROB = 8 # Move deep space probe
411 FDISTR = 9 # Emit distress call from an inhabited world
412 FENSLV = 10 # Inhabited word is enslaved */
413 FREPRO = 11 # Klingons build a ship in an enslaved system
417 # abstract out the event handling -- underlying data structures will change
418 # when we implement stateful events
420 def findevent(evtype): return game.future[evtype]
423 def __init__(self, type=None, loc=None, power=None):
428 self.kpower = power # enemy energy level
429 game.enemies.append(self)
431 motion = (loc != self.kloc)
432 if self.kloc.x is not None and self.kloc.y is not None:
435 game.quad[self.kloc.x][self.kloc.y] = IHWEB
437 game.quad[self.kloc.x][self.kloc.y] = IHDOT
439 self.kloc = copy.copy(loc)
440 game.quad[self.kloc.x][self.kloc.y] = self.type
441 self.kdist = self.kavgd = (game.sector - loc).distance()
444 self.kdist = self.kavgd = None
445 game.enemies.remove(self)
448 return "<%s=%f>" % (self.kloc, self.kpower) # For debugging
452 self.options = None # Game options
453 self.state = snapshot() # A snapshot structure
454 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
455 self.quad = None # contents of our quadrant
456 self.damage = [0.0] * NDEVICES # damage encountered
457 self.future = [] # future events
458 for i in range(NEVENTS):
459 self.future.append(event())
460 self.passwd = None; # Self Destruct password
462 self.quadrant = None # where we are in the large
463 self.sector = None # where we are in the small
464 self.tholian = None # Tholian enemy object
465 self.base = None # position of base in current quadrant
466 self.battle = None # base coordinates being attacked
467 self.plnet = None # location of planet in quadrant
468 self.probec = None # current probe quadrant
469 self.gamewon = False # Finished!
470 self.ididit = False # action taken -- allows enemy to attack
471 self.alive = False # we are alive (not killed)
472 self.justin = False # just entered quadrant
473 self.shldup = False # shields are up
474 self.shldchg = False # shield is changing (affects efficiency)
475 self.comhere = False # commander here
476 self.ishere = False # super-commander in quadrant
477 self.iscate = False # super commander is here
478 self.ientesc = False # attempted escape from supercommander
479 self.resting = False # rest time
480 self.icraft = False # Kirk in Galileo
481 self.landed = False # party on planet (true), on ship (false)
482 self.alldone = False # game is now finished
483 self.neutz = False # Romulan Neutral Zone
484 self.isarmed = False # probe is armed
485 self.inorbit = False # orbiting a planet
486 self.imine = False # mining
487 self.icrystl = False # dilithium crystals aboard
488 self.iseenit = False # seen base attack report
489 self.thawed = False # thawed game
490 self.condition = None # "green", "yellow", "red", "docked", "dead"
491 self.iscraft = None # "onship", "offship", "removed"
492 self.skill = None # Player skill level
493 self.inkling = 0 # initial number of klingons
494 self.inbase = 0 # initial number of bases
495 self.incom = 0 # initial number of commanders
496 self.inscom = 0 # initial number of commanders
497 self.inrom = 0 # initial number of commanders
498 self.instar = 0 # initial stars
499 self.intorps = 0 # initial/max torpedoes
500 self.torps = 0 # number of torpedoes
501 self.ship = 0 # ship type -- 'E' is Enterprise
502 self.abandoned = 0 # count of crew abandoned in space
503 self.length = 0 # length of game
504 self.klhere = 0 # klingons here
505 self.casual = 0 # causalties
506 self.nhelp = 0 # calls for help
507 self.nkinks = 0 # count of energy-barrier crossings
508 self.iplnet = None # planet # in quadrant
509 self.inplan = 0 # initial planets
510 self.irhere = 0 # Romulans in quadrant
511 self.isatb = 0 # =1 if super commander is attacking base
512 self.tourn = None # tournament number
513 self.proben = 0 # number of moves for probe
514 self.nprobes = 0 # number of probes available
515 self.inresor = 0.0 # initial resources
516 self.intime = 0.0 # initial time
517 self.inenrg = 0.0 # initial/max energy
518 self.inshld = 0.0 # initial/max shield
519 self.inlsr = 0.0 # initial life support resources
520 self.indate = 0.0 # initial date
521 self.energy = 0.0 # energy level
522 self.shield = 0.0 # shield level
523 self.warpfac = 0.0 # warp speed
524 self.wfacsq = 0.0 # squared warp factor
525 self.lsupres = 0.0 # life support reserves
526 self.dist = 0.0 # movement distance
527 self.direc = 0.0 # movement direction
528 self.optime = 0.0 # time taken by current operation
529 self.docfac = 0.0 # repair factor when docking (constant?)
530 self.damfac = 0.0 # damage factor
531 self.lastchart = 0.0 # time star chart was last updated
532 self.cryprob = 0.0 # probability that crystal will work
533 self.probex = 0.0 # location of probe
535 self.probeinx = 0.0 # probe x,y increment
536 self.probeiny = 0.0 #
537 self.height = 0.0 # height of orbit around planet
539 # Stas thinks this should be (C expression):
540 # game.state.remkl + game.state.remcom > 0 ?
541 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
542 # He says the existing expression is prone to divide-by-zero errors
543 # after killing the last klingon when score is shown -- perhaps also
544 # if the only remaining klingon is SCOM.
545 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
546 # From enumerated type 'feature'
567 # From enumerated type 'FINTYPE'
591 # Log the results of pulling random numbers so we can check determinism.
597 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
600 def randrange(*args):
601 v = random.randrange(*args)
602 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
608 v *= args[0] # returns from [0, args[0])
610 v = args[0] + v*(args[1]-args[0]) # returns from [args[0], args[1])
611 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
614 # Code from ai.c begins here
616 def tryexit(enemy, look, irun):
617 # a bad guy attempts to bug out
619 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
620 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
621 if not VALID_QUADRANT(iq.x,iq.y) or \
622 game.state.galaxy[iq.x][iq.y].supernova or \
623 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
624 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
625 if enemy.type == IHR:
626 return False; # Romulans cannot escape!
628 # avoid intruding on another commander's territory
629 if enemy.type == IHC:
630 for n in range(game.state.remcom):
631 if game.state.kcmdr[n] == iq:
633 # refuse to leave if currently attacking starbase
634 if game.battle == game.quadrant:
636 # don't leave if over 1000 units of energy
637 if enemy.kpower > 1000.0:
639 # print escape message and move out of quadrant.
640 # we know this if either short or long range sensors are working
641 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
642 game.condition == "docked":
643 crmena(True, enemy.type, "sector", enemy.kloc)
644 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
645 # handle local matters related to escape
648 if game.condition != "docked":
650 # Handle global matters related to escape
651 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
652 game.state.galaxy[iq.x][iq.y].klingons += 1
658 schedule(FSCMOVE, 0.2777)
662 for n in range(game.state.remcom):
663 if game.state.kcmdr[n] == game.quadrant:
664 game.state.kcmdr[n]=iq
667 return True; # success
670 # The bad-guy movement algorithm:
672 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
673 # If both are operating full strength, force is 1000. If both are damaged,
674 # force is -1000. Having shields down subtracts an additional 1000.
676 # 2. Enemy has forces equal to the energy of the attacker plus
677 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
678 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
680 # Attacker Initial energy levels (nominal):
681 # Klingon Romulan Commander Super-Commander
682 # Novice 400 700 1200
684 # Good 450 800 1300 1750
685 # Expert 475 850 1350 1875
686 # Emeritus 500 900 1400 2000
687 # VARIANCE 75 200 200 200
689 # Enemy vessels only move prior to their attack. In Novice - Good games
690 # only commanders move. In Expert games, all enemy vessels move if there
691 # is a commander present. In Emeritus games all enemy vessels move.
693 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
694 # forces are 1000 greater than Enterprise.
696 # Agressive action on average cuts the distance between the ship and
697 # the enemy to 1/4 the original.
699 # 4. At lower energy advantage, movement units are proportional to the
700 # advantage with a 650 advantage being to hold ground, 800 to move forward
701 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
703 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
704 # retreat, especially at high skill levels.
706 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
709 def movebaddy(enemy):
710 # tactical movement for the bad guys
711 next = coord(); look = coord()
713 # This should probably be just game.comhere + game.ishere
714 if game.skill >= SKILL_EXPERT:
715 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
717 nbaddys = game.comhere + game.ishere
719 mdist = int(dist1 + 0.5); # Nearest integer distance
720 # If SC, check with spy to see if should hi-tail it
721 if enemy.type==IHS and \
722 (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
726 # decide whether to advance, retreat, or hold position
727 forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
729 forces += 1000; # Good for enemy if shield is down!
730 if not damaged(DPHASER) or not damaged(DPHOTON):
731 if damaged(DPHASER): # phasers damaged
734 forces -= 0.2*(game.energy - 2500.0)
735 if damaged(DPHOTON): # photon torpedoes damaged
738 forces -= 50.0*game.torps
740 # phasers and photon tubes both out!
743 if forces <= 1000.0 and game.condition != "docked": # Typical situation
744 motion = ((forces + randreal(200))/150.0) - 5.0
746 if forces > 1000.0: # Very strong -- move in for kill
747 motion = (1.0 - randreal())**2 * dist1 + 1.0
748 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
749 motion -= game.skill*(2.0-randreal()**2)
751 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
752 # don't move if no motion
755 # Limit motion according to skill
756 if abs(motion) > game.skill:
761 # calculate preferred number of steps
766 if motion > 0 and nsteps > mdist:
767 nsteps = mdist; # don't overshoot
768 if nsteps > QUADSIZE:
769 nsteps = QUADSIZE; # This shouldn't be necessary
771 nsteps = 1; # This shouldn't be necessary
773 proutn("NSTEPS = %d:" % nsteps)
774 # Compute preferred values of delta X and Y
775 m = game.sector - enemy.kloc
776 if 2.0 * abs(m.x) < abs(m.y):
778 if 2.0 * abs(m.y) < abs(game.sector.x-enemy.kloc.x):
792 for ll in range(nsteps):
794 proutn(" %d" % (ll+1))
795 # Check if preferred position available
806 attempts = 0; # Settle mysterious hang problem
807 while attempts < 20 and not success:
809 if look.x < 0 or look.x >= QUADSIZE:
810 if motion < 0 and tryexit(enemy, look, irun):
812 if krawlx == m.x or m.y == 0:
814 look.x = next.x + krawlx
816 elif look.y < 0 or look.y >= QUADSIZE:
817 if motion < 0 and tryexit(enemy, look, irun):
819 if krawly == m.y or m.x == 0:
821 look.y = next.y + krawly
823 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
824 # See if enemy should ram ship
825 if game.quad[look.x][look.y] == game.ship and \
826 (enemy.type == IHC or enemy.type == IHS):
827 collision(rammed=True, enemy=enemy)
829 if krawlx != m.x and m.y != 0:
830 look.x = next.x + krawlx
832 elif krawly != m.y and m.x != 0:
833 look.y = next.y + krawly
836 break; # we have failed
848 if not damaged(DSRSENS) or game.condition == "docked":
851 proutn(_(" from Sector %s") % enemy.kloc)
852 if enemy.kdist < dist1:
853 proutn(_(" advances to "))
855 proutn(_(" retreats to "))
856 prout("Sector %s." % next)
859 # Klingon tactical movement
862 # Figure out which Klingon is the commander (or Supercommander)
865 for enemy in game.enemies:
866 if enemy.type == IHC:
869 for enemy in game.enemies:
870 if enemy.type == IHS:
873 # If skill level is high, move other Klingons and Romulans too!
874 # Move these last so they can base their actions on what the
876 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
877 for enemy in game.enemies:
878 if enemy.type in (IHK, IHR):
880 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
882 def movescom(iq, avoid):
883 # commander movement helper
884 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
885 game.state.galaxy[iq.x][iq.y].supernova or \
886 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
889 # Avoid quadrants with bases if we want to avoid Enterprise
890 for i in range(game.state.rembase):
891 if game.state.baseq[i] == iq:
893 if game.justin and not game.iscate:
896 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
897 game.state.kscmdr = iq
898 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
900 # SC has scooted, Remove him from current quadrant
906 for enemy in game.enemies:
907 if enemy.type == IHS:
911 if game.condition != "docked":
913 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
914 # check for a helpful planet
915 for i in range(game.inplan):
916 if game.state.planets[i].w == game.state.kscmdr and \
917 game.state.planets[i].crystals == "present":
919 game.state.planets[i].pclass = "destroyed"
920 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
923 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
924 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
925 prout(_(" by the Super-commander.\""))
927 return False; # looks good!
929 def supercommander():
930 # move the Super Commander
931 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
934 prout("== SUPERCOMMANDER")
935 # Decide on being active or passive
936 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 \
937 (game.state.date-game.indate) < 3.0)
938 if not game.iscate and avoid:
939 # compute move away from Enterprise
940 idelta = game.state.kscmdr-game.quadrant
941 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
943 idelta.x = game.state.kscmdr.y-game.quadrant.y
944 idelta.y = game.quadrant.x-game.state.kscmdr.x
946 # compute distances to starbases
947 if game.state.rembase <= 0:
951 sc = game.state.kscmdr
952 for i in range(game.state.rembase):
953 basetbl.append((i, (game.state.baseq[i] - sc).distance()))
954 if game.state.rembase > 1:
955 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
956 # look for nearest base without a commander, no Enterprise, and
957 # without too many Klingons, and not already under attack.
958 ifindit = iwhichb = 0
959 for i2 in range(game.state.rembase):
960 i = basetbl[i2][0]; # bug in original had it not finding nearest
961 ibq = game.state.baseq[i]
962 if ibq == game.quadrant or ibq == game.battle or \
963 game.state.galaxy[ibq.x][ibq.y].supernova or \
964 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
966 # if there is a commander, and no other base is appropriate,
967 # we will take the one with the commander
968 for j in range(game.state.remcom):
969 if ibq == game.state.kcmdr[j] and ifindit!= 2:
973 if j > game.state.remcom: # no commander -- use this one
978 return # Nothing suitable -- wait until next time
979 ibq = game.state.baseq[iwhichb]
980 # decide how to move toward base
981 idelta = ibq - game.state.kscmdr
982 # Maximum movement is 1 quadrant in either or both axes
983 idelta = idelta.sgn()
984 # try moving in both x and y directions
985 # there was what looked like a bug in the Almy C code here,
986 # but it might be this translation is just wrong.
987 iq = game.state.kscmdr + idelta
988 if movescom(iq, avoid):
989 # failed -- try some other maneuvers
990 if idelta.x==0 or idelta.y==0:
993 iq.y = game.state.kscmdr.y + 1
994 if movescom(iq, avoid):
995 iq.y = game.state.kscmdr.y - 1
998 iq.x = game.state.kscmdr.x + 1
999 if movescom(iq, avoid):
1000 iq.x = game.state.kscmdr.x - 1
1003 # try moving just in x or y
1004 iq.y = game.state.kscmdr.y
1005 if movescom(iq, avoid):
1006 iq.y = game.state.kscmdr.y + idelta.y
1007 iq.x = game.state.kscmdr.x
1010 if game.state.rembase == 0:
1013 for i in range(game.state.rembase):
1014 ibq = game.state.baseq[i]
1015 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1018 return # no, don't attack base!
1019 game.iseenit = False
1021 schedule(FSCDBAS, randreal(1.0, 3.0))
1022 if is_scheduled(FCDBAS):
1023 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1024 if not communicating():
1028 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1029 % game.state.kscmdr)
1030 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1031 proutn(_(" It can survive until stardate %d.\"") \
1032 % int(scheduled(FSCDBAS)))
1033 if not game.resting:
1035 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1038 game.resting = False
1039 game.optime = 0.0; # actually finished
1041 # Check for intelligence report
1044 (not communicating()) or \
1045 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1048 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1049 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1054 if not game.tholian or game.justin:
1057 if game.tholian.kloc.x == 0 and game.tholian.kloc.y == 0:
1058 id.x = 0; id.y = QUADSIZE-1
1059 elif game.tholian.kloc.x == 0 and game.tholian.kloc.y == QUADSIZE-1:
1060 id.x = QUADSIZE-1; id.y = QUADSIZE-1
1061 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == QUADSIZE-1:
1062 id.x = QUADSIZE-1; id.y = 0
1063 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == 0:
1066 # something is wrong!
1067 game.tholian.move(None)
1068 prout("***Internal error: Tholian in a bad spot.")
1070 # do nothing if we are blocked
1071 if game.quad[id.x][id.y] not in (IHDOT, IHWEB):
1073 here = copy.copy(game.tholian.kloc)
1074 delta = (id - game.tholian.kloc).sgn()
1076 while here.x != id.x:
1077 #print "Moving in X", delta
1079 if game.quad[here.x][here.y]==IHDOT:
1080 game.tholian.move(here)
1082 while here.y != id.y:
1083 #print "Moving in Y", delta
1085 if game.quad[here.x][here.y]==IHDOT:
1086 game.tholian.move(here)
1087 # check to see if all holes plugged
1088 for i in range(QUADSIZE):
1089 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1091 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1093 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1095 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1097 # All plugged up -- Tholian splits
1098 game.quad[game.tholian.kloc.x][game.tholian.kloc.y]=IHWEB
1100 crmena(True, IHT, "sector", game.tholian)
1101 prout(_(" completes web."))
1102 game.tholian.move(None)
1103 print "Tholian movement ends"
1106 # Code from battle.c begins here
1108 def doshield(shraise):
1109 # change shield status
1115 key = scanner.next()
1117 if scanner.sees("transfer"):
1120 if damaged(DSHIELD):
1121 prout(_("Shields damaged and down."))
1123 if scanner.sees("up"):
1125 elif scanner.sees("down"):
1128 proutn(_("Do you wish to change shield energy? "))
1130 proutn(_("Energy to transfer to shields- "))
1132 elif damaged(DSHIELD):
1133 prout(_("Shields damaged and down."))
1136 proutn(_("Shields are up. Do you want them down? "))
1143 proutn(_("Shields are down. Do you want them up? "))
1149 if action == "SHUP": # raise shields
1151 prout(_("Shields already up."))
1155 if game.condition != "docked":
1157 prout(_("Shields raised."))
1158 if game.energy <= 0:
1160 prout(_("Shields raising uses up last of energy."))
1165 elif action == "SHDN":
1167 prout(_("Shields already down."))
1171 prout(_("Shields lowered."))
1174 elif action == "NRG":
1175 while scanner.next() != IHREAL:
1177 proutn(_("Energy to transfer to shields- "))
1179 if scanner.real == 0:
1181 if scanner.real > game.energy:
1182 prout(_("Insufficient ship energy."))
1185 if game.shield+scanner.real >= game.inshld:
1186 prout(_("Shield energy maximized."))
1187 if game.shield+scanner.real > game.inshld:
1188 prout(_("Excess energy requested returned to ship energy"))
1189 game.energy -= game.inshld-game.shield
1190 game.shield = game.inshld
1192 if scanner.real < 0.0 and game.energy-scanner.real > game.inenrg:
1193 # Prevent shield drain loophole
1195 prout(_("Engineering to bridge--"))
1196 prout(_(" Scott here. Power circuit problem, Captain."))
1197 prout(_(" I can't drain the shields."))
1200 if game.shield+scanner.real < 0:
1201 prout(_("All shield energy transferred to ship."))
1202 game.energy += game.shield
1205 proutn(_("Scotty- \""))
1206 if scanner.real > 0:
1207 prout(_("Transferring energy to shields.\""))
1209 prout(_("Draining energy from shields.\""))
1210 game.shield += scanner.real
1211 game.energy -= scanner.real
1215 # choose a device to damage, at random.
1217 # Quoth Eric Allman in the code of BSD-Trek:
1218 # "Under certain conditions you can get a critical hit. This
1219 # sort of hit damages devices. The probability that a given
1220 # device is damaged depends on the device. Well protected
1221 # devices (such as the computer, which is in the core of the
1222 # ship and has considerable redundancy) almost never get
1223 # damaged, whereas devices which are exposed (such as the
1224 # warp engines) or which are particularly delicate (such as
1225 # the transporter) have a much higher probability of being
1228 # This is one place where OPTION_PLAIN does not restore the
1229 # original behavior, which was equiprobable damage across
1230 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1231 # and have done with it. Also, in the original game, DNAVYS
1232 # and DCOMPTR were the same device.
1234 # Instead, we use a table of weights similar to the one from BSD Trek.
1235 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1236 # We don't have a cloaking device. The shuttle got the allocation
1237 # for the cloaking device, then we shaved a half-percent off
1238 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1241 105, # DSRSENS: short range scanners 10.5%
1242 105, # DLRSENS: long range scanners 10.5%
1243 120, # DPHASER: phasers 12.0%
1244 120, # DPHOTON: photon torpedoes 12.0%
1245 25, # DLIFSUP: life support 2.5%
1246 65, # DWARPEN: warp drive 6.5%
1247 70, # DIMPULS: impulse engines 6.5%
1248 145, # DSHIELD: deflector shields 14.5%
1249 30, # DRADIO: subspace radio 3.0%
1250 45, # DSHUTTL: shuttle 4.5%
1251 15, # DCOMPTR: computer 1.5%
1252 20, # NAVCOMP: navigation system 2.0%
1253 75, # DTRANSP: transporter 7.5%
1254 20, # DSHCTRL: high-speed shield controller 2.0%
1255 10, # DDRAY: death ray 1.0%
1256 30, # DDSP: deep-space probes 3.0%
1258 idx = randrange(1000) # weights must sum to 1000
1260 for (i, w) in enumerate(weights):
1264 return None; # we should never get here
1266 def collision(rammed, enemy):
1267 # collision handling
1268 prouts(_("***RED ALERT! RED ALERT!"))
1270 prout(_("***COLLISION IMMINENT."))
1274 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(enemy.type, 1.0)
1276 proutn(_(" rammed by "))
1279 crmena(False, enemy.type, "sector", enemy.kloc)
1281 proutn(_(" (original position)"))
1283 deadkl(enemy.kloc, enemy.type, game.sector)
1286 prout(_(" heavily damaged."))
1287 icas = randrange(10, 30)
1288 prout(_("***Sickbay reports %d casualties"), icas)
1290 game.state.crew -= icas
1292 # In the pre-SST2K version, all devices got equiprobably damaged,
1293 # which was silly. Instead, pick up to half the devices at
1294 # random according to our weighting table,
1296 ncrits = randrange(NDEVICES/2)
1297 for m in range(ncrits):
1299 if game.damage[dev] < 0:
1301 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1302 # Damage for at least time of travel!
1303 game.damage[dev] += game.optime + extradm
1305 prout(_("***Shields are down."))
1306 if game.state.remkl + game.state.remcom + game.state.nscrem:
1313 def torpedo(course, dispersion, origin, number, nburst):
1314 # let a photon torpedo fly
1317 ac = course + 0.25*dispersion
1318 angle = (15.0-ac)*0.5235988
1319 bullseye = (15.0 - course)*0.5235988
1320 deltax = -math.sin(angle);
1321 deltay = math.cos(angle);
1322 x = origin.x; y = origin.y
1323 w = coord(); jw = coord()
1324 w.x = w.y = jw.x = jw.y = 0
1325 bigger = max(math.fabs(deltax), math.fabs(deltay))
1328 if not damaged(DSRSENS) or game.condition=="docked":
1329 setwnd(srscan_window)
1331 setwnd(message_window)
1332 # Loop to move a single torpedo
1333 for step in range(1, 15+1):
1338 if not VALID_SECTOR(w.x, w.y):
1340 iquad=game.quad[w.x][w.y]
1341 tracktorpedo(origin, w, step, number, nburst, iquad)
1345 setwnd(message_window)
1346 if damaged(DSRSENS) and not game.condition=="docked":
1347 skip(1); # start new line after text track
1348 if iquad in (IHE, IHF): # Hit our ship
1350 proutn(_("Torpedo hits "))
1353 hit = 700.0 + randreal(100) - \
1354 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1355 newcnd(); # we're blown out of dock
1356 # We may be displaced.
1357 if game.landed or game.condition=="docked":
1358 return hit # Cheat if on a planet
1359 ang = angle + 2.5*(randreal()-0.5)
1360 temp = math.fabs(math.sin(ang))
1361 if math.fabs(math.cos(ang)) > temp:
1362 temp = math.fabs(math.cos(ang))
1363 xx = -math.sin(ang)/temp
1364 yy = math.cos(ang)/temp
1365 jw.x = int(w.x+xx+0.5)
1366 jw.y = int(w.y+yy+0.5)
1367 if not VALID_SECTOR(jw.x, jw.y):
1369 if game.quad[jw.x][jw.y]==IHBLANK:
1372 if game.quad[jw.x][jw.y]!=IHDOT:
1373 # can't move into object
1378 elif iquad in (IHC, IHS): # Hit a commander
1380 crmena(True, iquad, "sector", w)
1381 prout(_(" uses anti-photon device;"))
1382 prout(_(" torpedo neutralized."))
1384 elif iquad in (IHR, IHK): # Hit a regular enemy
1386 for enemy in game.enemies:
1387 if w == game.enemies[ll].kloc:
1389 kp = math.fabs(e.kpower)
1390 h1 = 700.0 + randrange(100) - \
1391 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1395 if enemy.kpower < 0:
1399 if enemy.kpower == 0:
1402 crmena(True, iquad, "sector", w)
1403 # If enemy damaged but not destroyed, try to displace
1404 ang = angle + 2.5*(randreal()-0.5)
1405 temp = math.fabs(math.sin(ang))
1406 if math.fabs(math.cos(ang)) > temp:
1407 temp = math.fabs(math.cos(ang))
1408 xx = -math.sin(ang)/temp
1409 yy = math.cos(ang)/temp
1410 jw.x = int(w.x+xx+0.5)
1411 jw.y = int(w.y+yy+0.5)
1412 if not VALID_SECTOR(jw.x, jw.y):
1413 prout(_(" damaged but not destroyed."))
1415 if game.quad[jw.x][jw.y]==IHBLANK:
1416 prout(_(" buffeted into black hole."))
1417 deadkl(w, iquad, jw)
1419 if game.quad[jw.x][jw.y]!=IHDOT:
1420 # can't move into object
1421 prout(_(" damaged but not destroyed."))
1423 proutn(_(" damaged--"))
1427 elif iquad == IHB: # Hit a base
1429 prout(_("***STARBASE DESTROYED.."))
1430 for ll in range(game.state.rembase):
1431 if game.state.baseq[ll] == game.quadrant:
1432 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1434 game.quad[w.x][w.y]=IHDOT
1435 game.state.rembase -= 1
1436 game.base.x=game.base.y=0
1437 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1438 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1439 game.state.basekl += 1
1442 elif iquad == IHP: # Hit a planet
1443 crmena(True, iquad, "sector", w)
1444 prout(_(" destroyed."))
1445 game.state.nplankl += 1
1446 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1447 game.iplnet.pclass = "destroyed"
1449 game.plnet.invalidate()
1450 game.quad[w.x][w.y] = IHDOT
1452 # captain perishes on planet
1455 elif iquad == IHW: # Hit an inhabited world -- very bad!
1456 crmena(True, iquad, "sector", w)
1457 prout(_(" destroyed."))
1458 game.state.nworldkl += 1
1459 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1460 game.iplnet.pclass = "destroyed"
1462 game.plnet.invalidate()
1463 game.quad[w.x][w.y] = IHDOT
1465 # captain perishes on planet
1467 prout(_("You have just destroyed an inhabited planet."))
1468 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1470 elif iquad == IHSTAR: # Hit a star
1474 crmena(True, IHSTAR, "sector", w)
1475 prout(_(" unaffected by photon blast."))
1477 elif iquad == IHQUEST: # Hit a thingy
1478 if not (game.options & OPTION_THINGY) or withprob(0.3):
1480 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1482 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1484 proutn(_("Mr. Spock-"))
1485 prouts(_(" \"Fascinating!\""))
1490 # Stas Sergeev added the possibility that
1491 # you can shove the Thingy and piss it off.
1492 # It then becomes an enemy and may fire at you.
1497 elif iquad == IHBLANK: # Black hole
1499 crmena(True, IHBLANK, "sector", w)
1500 prout(_(" swallows torpedo."))
1502 elif iquad == IHWEB: # hit the web
1504 prout(_("***Torpedo absorbed by Tholian web."))
1506 elif iquad == IHT: # Hit a Tholian
1507 h1 = 700.0 + randrange(100) - \
1508 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1511 game.quad[w.x][w.y] = IHDOT
1516 crmena(True, IHT, "sector", w)
1518 prout(_(" survives photon blast."))
1520 prout(_(" disappears."))
1521 game.tholian.move(None)
1522 game.quad[w.x][w.y] = IHWEB
1527 proutn("Don't know how to handle torpedo collision with ")
1528 crmena(True, iquad, "sector", w)
1532 if curwnd!=message_window:
1533 setwnd(message_window)
1535 game.quad[w.x][w.y]=IHDOT
1536 game.quad[jw.x][jw.y]=iquad
1537 prout(_(" displaced by blast to Sector %s ") % jw)
1538 for ll in range(len(game.enemies)):
1539 game.enemies[ll].kdist = game.enemies[ll].kavgd = (game.sector-game.enemies[ll].kloc).distance()
1540 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1543 prout(_("Torpedo missed."))
1547 # critical-hit resolution
1548 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1550 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1551 proutn(_("***CRITICAL HIT--"))
1552 # Select devices and cause damage
1554 for loop1 in range(ncrit):
1557 # Cheat to prevent shuttle damage unless on ship
1558 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1561 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1562 game.damage[j] += extradm
1564 for (i, j) in enumerate(cdam):
1566 if skipcount % 3 == 2 and i < len(cdam)-1:
1571 prout(_(" damaged."))
1572 if damaged(DSHIELD) and game.shldup:
1573 prout(_("***Shields knocked down."))
1576 def attack(torps_ok):
1577 # bad guy attacks us
1578 # torps_ok == False forces use of phasers in an attack
1579 attempt = False; ihurt = False;
1580 hitmax=0.0; hittot=0.0; chgfac=1.0
1582 # game could be over at this point, check
1586 prout("=== ATTACK!")
1587 # Tholian gets to move before attacking
1590 # if you have just entered the RNZ, you'll get a warning
1591 if game.neutz: # The one chance not to be attacked
1594 # commanders get a chance to tac-move towards you
1595 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1597 # if no enemies remain after movement, we're done
1598 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1600 # set up partial hits if attack happens during shield status change
1601 pfac = 1.0/game.inshld
1603 chgfac = 0.25 + randreal(0.5)
1605 # message verbosity control
1606 if game.skill <= SKILL_FAIR:
1608 for enemy in game.enemies:
1609 if enemy.kpower < 0:
1610 continue; # too weak to attack
1611 # compute hit strength and diminish shield power
1613 # Increase chance of photon torpedos if docked or enemy energy is low
1614 if game.condition == "docked":
1616 if enemy.kpower < 500:
1618 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1620 # different enemies have different probabilities of throwing a torp
1621 usephasers = not torps_ok or \
1622 (enemy.type == IHK and r > 0.0005) or \
1623 (enemy.type==IHC and r > 0.015) or \
1624 (enemy.type==IHR and r > 0.3) or \
1625 (enemy.type==IHS and r > 0.07) or \
1626 (enemy.type==IHQUEST and r > 0.05)
1627 if usephasers: # Enemy uses phasers
1628 if game.condition == "docked":
1629 continue; # Don't waste the effort!
1630 attempt = True; # Attempt to attack
1631 dustfac = randreal(0.8, 0.85)
1632 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1633 enemy.kpower *= 0.75
1634 else: # Enemy uses photon torpedo
1635 #course2 = (enemy.kloc-game.sector).bearing()
1636 course = 1.90985*math.atan2(game.sector.y-enemy.kloc.y, enemy.kloc.x-game.sector.x)
1638 proutn(_("***TORPEDO INCOMING"))
1639 if not damaged(DSRSENS):
1641 crmena(False, enemy.type, where, enemy.kloc)
1644 dispersion = (randreal()+randreal())*0.5 - 0.5
1645 dispersion += 0.002*enemy.kpower*dispersion
1646 hit = torpedo(course, dispersion, origin=enemy.kloc, number=1, nburst=1)
1647 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1648 finish(FWON); # Klingons did themselves in!
1649 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1650 return # Supernova or finished
1653 # incoming phaser or torpedo, shields may dissipate it
1654 if game.shldup or game.shldchg or game.condition=="docked":
1655 # shields will take hits
1656 propor = pfac * game.shield
1657 if game.condition =="docked":
1661 hitsh = propor*chgfac*hit+1.0
1663 if absorb > game.shield:
1664 absorb = game.shield
1665 game.shield -= absorb
1667 # taking a hit blasts us out of a starbase dock
1668 if game.condition == "docked":
1670 # but the shields may take care of it
1671 if propor > 0.1 and hit < 0.005*game.energy:
1673 # hit from this opponent got through shields, so take damage
1675 proutn(_("%d unit hit") % int(hit))
1676 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1677 proutn(_(" on the "))
1679 if not damaged(DSRSENS) and usephasers:
1681 crmena(False, enemy.type, where, enemy.kloc)
1683 # Decide if hit is critical
1689 if game.energy <= 0:
1690 # Returning home upon your shield, not with it...
1693 if not attempt and game.condition == "docked":
1694 prout(_("***Enemies decide against attacking your ship."))
1695 percent = 100.0*pfac*game.shield+0.5
1697 # Shields fully protect ship
1698 proutn(_("Enemy attack reduces shield strength to "))
1700 # Print message if starship suffered hit(s)
1702 proutn(_("Energy left %2d shields ") % int(game.energy))
1705 elif not damaged(DSHIELD):
1708 proutn(_("damaged, "))
1709 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1710 # Check if anyone was hurt
1711 if hitmax >= 200 or hittot >= 500:
1712 icas = randrange(int(hittot * 0.015))
1715 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1716 prout(_(" in that last attack.\""))
1718 game.state.crew -= icas
1719 # After attack, reset average distance to enemies
1720 for enemy in game.enemies:
1721 enemy.kavgd = enemy.kdist
1722 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1725 def deadkl(w, type, mv):
1726 # kill a Klingon, Tholian, Romulan, or Thingy
1727 # Added mv to allow enemy to "move" before dying
1728 crmena(True, type, "sector", mv)
1729 # Decide what kind of enemy it is and update appropriately
1731 # chalk up a Romulan
1732 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1734 game.state.nromrem -= 1
1738 elif type == IHQUEST:
1743 # Some type of a Klingon
1744 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1747 game.comhere = False
1748 for i in range(game.state.remcom):
1749 if game.state.kcmdr[i] == game.quadrant:
1751 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1752 game.state.kcmdr[game.state.remcom].x = 0
1753 game.state.kcmdr[game.state.remcom].y = 0
1754 game.state.remcom -= 1
1756 if game.state.remcom != 0:
1757 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1758 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1761 game.state.remkl -= 1
1763 game.state.nscrem -= 1
1765 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1769 # For each kind of enemy, finish message to player
1770 prout(_(" destroyed."))
1771 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1774 # Remove enemy ship from arrays describing local conditions
1775 for e in game.enemies:
1782 # Return None if target is invalid, otherwise return a course angle
1783 if not VALID_SECTOR(w.x, w.y):
1786 delta = 0.1*(w - game.sector)
1787 if delta.x==0 and delta.y== 0:
1789 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1790 prout(_(" I recommend an immediate review of"))
1791 prout(_(" the Captain's psychological profile.\""))
1794 return delta.bearing()
1797 # launch photon torpedo
1798 course = [0.0] * MAXBURST
1800 if damaged(DPHOTON):
1801 prout(_("Photon tubes damaged."))
1805 prout(_("No torpedoes left."))
1808 key = scanner.next()
1814 prout(_("%d torpedoes left.") % game.torps)
1816 proutn(_("Number of torpedoes to fire- "))
1817 key = scanner.next()
1818 else: # key == IHREAL
1820 if n <= 0: # abort command
1825 prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
1833 for i in range(MAXBURST):
1834 targ.append(coord())
1836 key = scanner.next()
1837 if i==0 and key == IHEOL:
1838 break; # we will try prompting
1839 if i==1 and key == IHEOL:
1840 # direct all torpedoes at one target
1843 course[i] = course[0]
1849 targ[i].x = scanner.int()
1850 key = scanner.next()
1854 targ[i].y = scanner.int()
1855 course[i] = targetcheck(targ[i])
1856 if course[i] == None:
1859 if i == 0 and key == IHEOL:
1860 # prompt for each one
1862 proutn(_("Target sector for torpedo number %d- ") % (i+1))
1863 key = scanner.next()
1867 targ[i].x = scanner.int()
1868 key = scanner.next()
1872 targ[i].y = scanner.int()
1874 course[i] = targetcheck(targ[i])
1875 if course[i] == None:
1878 # Loop for moving <n> torpedoes
1880 if game.condition != "docked":
1882 dispersion = (randreal()+randreal())*0.5 -0.5
1883 if math.fabs(dispersion) >= 0.47:
1885 dispersion *= randreal(1.2, 2.2)
1887 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1889 prouts(_("***TORPEDO MISFIRES."))
1892 prout(_(" Remainder of burst aborted."))
1894 prout(_("***Photon tubes damaged by misfire."))
1895 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1897 if game.shldup or game.condition == "docked":
1898 dispersion *= 1.0 + 0.0001*game.shield
1899 torpedo(course[i], dispersion, origin=game.sector, number=i, nburst=n)
1900 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1902 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1906 # check for phasers overheating
1908 checkburn = (rpow-1500.0)*0.00038
1909 if withprob(checkburn):
1910 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1911 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1913 def checkshctrl(rpow):
1914 # check shield control
1917 prout(_("Shields lowered."))
1919 # Something bad has happened
1920 prouts(_("***RED ALERT! RED ALERT!"))
1922 hit = rpow*game.shield/game.inshld
1923 game.energy -= rpow+hit*0.8
1924 game.shield -= hit*0.2
1925 if game.energy <= 0.0:
1926 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1931 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1933 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1934 icas = randrange(int(hit*0.012))
1939 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1940 prout(_(" %d casualties so far.\"") % icas)
1942 game.state.crew -= icas
1944 prout(_("Phaser energy dispersed by shields."))
1945 prout(_("Enemy unaffected."))
1950 # register a phaser hit on Klingons and Romulans
1951 nenhr2 = len(game.enemies); kk=0
1954 print "Hits are:", hits
1955 for (k, wham) in enumerate(hits):
1958 dustfac = randreal(0.9, 1.0)
1959 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1960 kpini = game.enemies[kk].kpower
1961 kp = math.fabs(kpini)
1962 if PHASEFAC*hit < kp:
1964 if game.enemies[kk].kpower < 0:
1965 game.enemies[kk].kpower -= -kp
1967 game.enemies[kk].kpower -= kp
1968 kpow = game.enemies[kk].kpower
1969 w = game.enemies[kk].kloc
1971 if not damaged(DSRSENS):
1973 proutn(_("%d unit hit on ") % int(hit))
1975 proutn(_("Very small hit on "))
1976 ienm = game.quad[w.x][w.y]
1979 crmena(False, ienm, "sector", w)
1983 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1987 kk -= 1 # don't do the increment
1989 else: # decide whether or not to emasculate klingon
1990 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
1991 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
1992 prout(_(" has just lost its firepower.\""))
1993 game.enemies[kk].kpower = -kpow
2000 kz = 0; k = 1; irec=0 # Cheating inhibitor
2001 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2005 # SR sensors and Computer are needed for automode
2006 if damaged(DSRSENS) or damaged(DCOMPTR):
2008 if game.condition == "docked":
2009 prout(_("Phasers can't be fired through base shields."))
2012 if damaged(DPHASER):
2013 prout(_("Phaser control damaged."))
2017 if damaged(DSHCTRL):
2018 prout(_("High speed shield control damaged."))
2021 if game.energy <= 200.0:
2022 prout(_("Insufficient energy to activate high-speed shield control."))
2025 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2027 # Original code so convoluted, I re-did it all
2028 # (That was Tom Almy talking about the C code, I think -- ESR)
2029 while automode=="NOTSET":
2032 if scanner.sees("manual"):
2033 if len(game.enemies)==0:
2034 prout(_("There is no enemy present to select."))
2037 automode="AUTOMATIC"
2040 key = scanner.next()
2041 elif scanner.sees("automatic"):
2042 if (not itarg) and len(game.enemies) != 0:
2043 automode = "FORCEMAN"
2045 if len(game.enemies)==0:
2046 prout(_("Energy will be expended into space."))
2047 automode = "AUTOMATIC"
2048 key = scanner.next()
2049 elif scanner.sees("no"):
2055 if len(game.enemies)==0:
2056 prout(_("Energy will be expended into space."))
2057 automode = "AUTOMATIC"
2059 automode = "FORCEMAN"
2061 automode = "AUTOMATIC"
2064 if len(game.enemies)==0:
2065 prout(_("Energy will be expended into space."))
2066 automode = "AUTOMATIC"
2068 automode = "FORCEMAN"
2070 proutn(_("Manual or automatic? "))
2075 if automode == "AUTOMATIC":
2076 if key == IHALPHA and scanner.sees("no"):
2078 key = scanner.next()
2079 if key != IHREAL and len(game.enemies) != 0:
2080 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2085 for i in range(len(game.enemies)):
2086 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2088 proutn(_("%d units required. ") % irec)
2090 proutn(_("Units to fire= "))
2091 key = scanner.next()
2096 proutn(_("Energy available= %.2f") % avail)
2099 if not rpow > avail:
2106 if key == IHALPHA and scanner.sees("no"):
2109 game.energy -= 200; # Go and do it!
2110 if checkshctrl(rpow):
2115 if len(game.enemies):
2118 for i in range(len(game.enemies)):
2122 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2123 over = randreal(1.01, 1.06) * hits[i]
2125 powrem -= hits[i] + over
2126 if powrem <= 0 and temp < hits[i]:
2135 if extra > 0 and not game.alldone:
2137 proutn(_("*** Tholian web absorbs "))
2138 if len(game.enemies)>0:
2139 proutn(_("excess "))
2140 prout(_("phaser energy."))
2142 prout(_("%d expended on empty space.") % int(extra))
2143 elif automode == "FORCEMAN":
2146 if damaged(DCOMPTR):
2147 prout(_("Battle computer damaged, manual fire only."))
2150 prouts(_("---WORKING---"))
2152 prout(_("Short-range-sensors-damaged"))
2153 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2154 prout(_("Manual-fire-must-be-used"))
2156 elif automode == "MANUAL":
2158 for k in range(len(game.enemies)):
2159 aim = game.enemies[k].kloc
2160 ienm = game.quad[aim.x][aim.y]
2162 proutn(_("Energy available= %.2f") % (avail-0.006))
2166 if damaged(DSRSENS) and \
2167 not game.sector.distance(aim)<2**0.5 and ienm in (IHC, IHS):
2169 prout(_(" can't be located without short range scan."))
2172 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2177 if itarg and k > kz:
2178 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2181 if not damaged(DCOMPTR):
2186 proutn(_("units to fire at "))
2187 crmena(False, ienm, "sector", aim)
2189 key = scanner.next()
2190 if key == IHALPHA and scanner.sees("no"):
2192 key = scanner.next()
2198 if k==1: # Let me say I'm baffled by this
2201 if scanner.real < 0:
2205 hits[k] = scanner.real
2206 rpow += scanner.real
2207 # If total requested is too much, inform and start over
2209 prout(_("Available energy exceeded -- try again."))
2212 key = scanner.next(); # scan for next value
2215 # zero energy -- abort
2218 if key == IHALPHA and scanner.sees("no"):
2223 game.energy -= 200.0
2224 if checkshctrl(rpow):
2228 # Say shield raised or malfunction, if necessary
2235 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2236 prouts(_(" CLICK CLICK POP . . ."))
2237 prout(_(" No response, sir!"))
2240 prout(_("Shields raised."))
2245 # Code from events,c begins here.
2247 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2248 # event of each type active at any given time. Mostly these means we can
2249 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2250 # BSD Trek, from which we swiped the idea, can have up to 5.
2252 def unschedule(evtype):
2253 # remove an event from the schedule
2254 game.future[evtype].date = FOREVER
2255 return game.future[evtype]
2257 def is_scheduled(evtype):
2258 # is an event of specified type scheduled
2259 return game.future[evtype].date != FOREVER
2261 def scheduled(evtype):
2262 # when will this event happen?
2263 return game.future[evtype].date
2265 def schedule(evtype, offset):
2266 # schedule an event of specified type
2267 game.future[evtype].date = game.state.date + offset
2268 return game.future[evtype]
2270 def postpone(evtype, offset):
2271 # postpone a scheduled event
2272 game.future[evtype].date += offset
2275 # rest period is interrupted by event
2278 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2280 game.resting = False
2286 # run through the event queue looking for things to do
2288 fintim = game.state.date + game.optime; yank=0
2289 ictbeam = False; istract = False
2290 w = coord(); hold = coord()
2291 ev = event(); ev2 = event()
2293 def tractorbeam(yank):
2294 # tractor beaming cases merge here
2296 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2300 prout(_(" caught in long range tractor beam--"))
2301 # If Kirk & Co. screwing around on planet, handle
2302 atover(True) # atover(true) is Grab
2305 if game.icraft: # Caught in Galileo?
2308 # Check to see if shuttle is aboard
2309 if game.iscraft == "offship":
2312 prout(_("Galileo, left on the planet surface, is captured"))
2313 prout(_("by aliens and made into a flying McDonald's."))
2314 game.damage[DSHUTTL] = -10
2315 game.iscraft = "removed"
2317 prout(_("Galileo, left on the planet surface, is well hidden."))
2319 game.quadrant = game.state.kscmdr
2321 game.quadrant = game.state.kcmdr[i]
2322 game.sector = randplace(QUADSIZE)
2324 prout(_(" is pulled to Quadrant %s, Sector %s") \
2325 % (game.quadrant, game.sector))
2327 prout(_("(Remainder of rest/repair period cancelled.)"))
2328 game.resting = False
2330 if not damaged(DSHIELD) and game.shield > 0:
2331 doshield(shraise=True) # raise shields
2332 game.shldchg = False
2334 prout(_("(Shields not currently useable.)"))
2336 # Adjust finish time to time of tractor beaming
2337 fintim = game.state.date+game.optime
2338 attack(torps_ok=False)
2339 if game.state.remcom <= 0:
2342 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2345 # Code merges here for any commander destroying base
2346 # Not perfect, but will have to do
2347 # Handle case where base is in same quadrant as starship
2348 if game.battle == game.quadrant:
2349 game.state.chart[game.battle.x][game.battle.y].starbase = False
2350 game.quad[game.base.x][game.base.y] = IHDOT
2351 game.base.x=game.base.y=0
2354 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2355 elif game.state.rembase != 1 and communicating():
2356 # Get word via subspace radio
2359 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2360 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2362 prout(_("the Klingon Super-Commander"))
2364 prout(_("a Klingon Commander"))
2365 game.state.chart[game.battle.x][game.battle.y].starbase = False
2366 # Remove Starbase from galaxy
2367 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2368 for i in range(1, game.state.rembase+1):
2369 if game.state.baseq[i] == game.battle:
2370 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2371 game.state.rembase -= 1
2373 # reinstate a commander's base attack
2377 game.battle.invalidate()
2380 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2381 for i in range(1, NEVENTS):
2382 if i == FSNOVA: proutn("=== Supernova ")
2383 elif i == FTBEAM: proutn("=== T Beam ")
2384 elif i == FSNAP: proutn("=== Snapshot ")
2385 elif i == FBATTAK: proutn("=== Base Attack ")
2386 elif i == FCDBAS: proutn("=== Base Destroy ")
2387 elif i == FSCMOVE: proutn("=== SC Move ")
2388 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2389 elif i == FDSPROB: proutn("=== Probe Move ")
2390 elif i == FDISTR: proutn("=== Distress Call ")
2391 elif i == FENSLV: proutn("=== Enslavement ")
2392 elif i == FREPRO: proutn("=== Klingon Build ")
2394 prout("%.2f" % (scheduled(i)))
2397 radio_was_broken = damaged(DRADIO)
2400 # Select earliest extraneous event, evcode==0 if no events
2405 for l in range(1, NEVENTS):
2406 if game.future[l].date < datemin:
2409 prout("== Event %d fires" % evcode)
2410 datemin = game.future[l].date
2411 xtime = datemin-game.state.date
2412 game.state.date = datemin
2413 # Decrement Federation resources and recompute remaining time
2414 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2416 if game.state.remtime <=0:
2419 # Any crew left alive?
2420 if game.state.crew <=0:
2423 # Is life support adequate?
2424 if damaged(DLIFSUP) and game.condition != "docked":
2425 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2428 game.lsupres -= xtime
2429 if game.damage[DLIFSUP] <= xtime:
2430 game.lsupres = game.inlsr
2433 if game.condition == "docked":
2434 repair /= game.docfac
2435 # Don't fix Deathray here
2436 for l in range(NDEVICES):
2437 if game.damage[l] > 0.0 and l != DDRAY:
2438 if game.damage[l]-repair > 0.0:
2439 game.damage[l] -= repair
2441 game.damage[l] = 0.0
2442 # If radio repaired, update star chart and attack reports
2443 if radio_was_broken and not damaged(DRADIO):
2444 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2445 prout(_(" surveillance reports are coming in."))
2447 if not game.iseenit:
2451 prout(_(" The star chart is now up to date.\""))
2453 # Cause extraneous event EVCODE to occur
2454 game.optime -= xtime
2455 if evcode == FSNOVA: # Supernova
2458 schedule(FSNOVA, expran(0.5*game.intime))
2459 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2461 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2462 if game.state.nscrem == 0 or \
2463 ictbeam or istract or \
2464 game.condition=="docked" or game.isatb==1 or game.iscate:
2466 if game.ientesc or \
2467 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2468 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2469 (damaged(DSHIELD) and \
2470 (game.energy < 2500 or damaged(DPHASER)) and \
2471 (game.torps < 5 or damaged(DPHOTON))):
2473 istract = ictbeam = True
2474 tractorbeam((game.state.kscmdr-game.quadrant).distance())
2477 elif evcode == FTBEAM: # Tractor beam
2478 if game.state.remcom == 0:
2481 i = randrange(game.state.remcom)
2482 yank = (game.state.kcmdr[i]-game.quadrant).distance()
2483 if istract or game.condition == "docked" or yank == 0:
2484 # Drats! Have to reschedule
2486 game.optime + expran(1.5*game.intime/game.state.remcom))
2490 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2491 game.snapsht = copy.deepcopy(game.state)
2492 game.state.snap = True
2493 schedule(FSNAP, expran(0.5 * game.intime))
2494 elif evcode == FBATTAK: # Commander attacks starbase
2495 if game.state.remcom==0 or game.state.rembase==0:
2501 for j in range(game.state.rembase):
2502 for k in range(game.state.remcom):
2503 if game.state.baseq[j] == game.state.kcmdr[k] and \
2504 not game.state.baseq[j] == game.quadrant and \
2505 not game.state.baseq[j] == game.state.kscmdr:
2509 if j>game.state.rembase:
2510 # no match found -- try later
2511 schedule(FBATTAK, expran(0.3*game.intime))
2514 # commander + starbase combination found -- launch attack
2515 game.battle = game.state.baseq[j]
2516 schedule(FCDBAS, randreal(1.0, 4.0))
2517 if game.isatb: # extra time if SC already attacking
2518 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2519 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2520 game.iseenit = False
2521 if not communicating():
2522 continue # No warning :-(
2526 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2527 prout(_(" reports that it is under attack and that it can"))
2528 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2531 elif evcode == FSCDBAS: # Supercommander destroys base
2534 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2535 continue # WAS RETURN!
2537 game.battle = game.state.kscmdr
2539 elif evcode == FCDBAS: # Commander succeeds in destroying base
2542 # find the lucky pair
2543 for i in range(game.state.remcom):
2544 if game.state.kcmdr[i] == game.battle:
2546 if i > game.state.remcom or game.state.rembase == 0 or \
2547 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2548 # No action to take after all
2549 game.battle.invalidate()
2552 elif evcode == FSCMOVE: # Supercommander moves
2553 schedule(FSCMOVE, 0.2777)
2554 if not game.ientesc and not istract and game.isatb != 1 and \
2555 (not game.iscate or not game.justin):
2557 elif evcode == FDSPROB: # Move deep space probe
2558 schedule(FDSPROB, 0.01)
2559 game.probex += game.probeinx
2560 game.probey += game.probeiny
2561 i = (int)(game.probex/QUADSIZE +0.05)
2562 j = (int)(game.probey/QUADSIZE + 0.05)
2563 if game.probec.x != i or game.probec.y != j:
2566 if not VALID_QUADRANT(i, j) or \
2567 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2568 # Left galaxy or ran into supernova
2572 proutn(_("Lt. Uhura- \"The deep space probe "))
2573 if not VALID_QUADRANT(j, i):
2574 proutn(_("has left the galaxy"))
2576 proutn(_("is no longer transmitting"))
2580 if not communicating():
2583 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2584 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2585 # Update star chart if Radio is working or have access to radio
2587 chp = game.state.chart[game.probec.x][game.probec.y]
2588 chp.klingons = pdest.klingons
2589 chp.starbase = pdest.starbase
2590 chp.stars = pdest.stars
2591 pdest.charted = True
2592 game.proben -= 1 # One less to travel
2593 if game.proben == 0 and game.isarmed and pdest.stars:
2594 # lets blow the sucker!
2595 supernova(True, game.probec)
2597 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2599 elif evcode == FDISTR: # inhabited system issues distress call
2601 # try a whole bunch of times to find something suitable
2602 for i in range(100):
2603 # need a quadrant which is not the current one,
2604 # which has some stars which are inhabited and
2605 # not already under attack, which is not
2606 # supernova'ed, and which has some Klingons in it
2607 w = randplace(GALSIZE)
2608 q = game.state.galaxy[w.x][w.y]
2609 if not (game.quadrant == w or q.planet == None or \
2610 not q.planet.inhabited or \
2611 q.supernova or q.status!="secure" or q.klingons<=0):
2614 # can't seem to find one; ignore this call
2616 prout("=== Couldn't find location for distress event.")
2618 # got one!! Schedule its enslavement
2619 ev = schedule(FENSLV, expran(game.intime))
2621 q.status = distressed
2623 # tell the captain about it if we can
2625 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2627 prout(_("by a Klingon invasion fleet."))
2630 elif evcode == FENSLV: # starsystem is enslaved
2631 ev = unschedule(FENSLV)
2632 # see if current distress call still active
2633 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2637 q.status = "enslaved"
2639 # play stork and schedule the first baby
2640 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2641 ev2.quadrant = ev.quadrant
2643 # report the disaster if we can
2645 prout(_("Uhura- We've lost contact with starsystem %s") % \
2647 prout(_("in Quadrant %s.\n") % ev.quadrant)
2648 elif evcode == FREPRO: # Klingon reproduces
2649 # If we ever switch to a real event queue, we'll need to
2650 # explicitly retrieve and restore the x and y.
2651 ev = schedule(FREPRO, expran(1.0 * game.intime))
2652 # see if current distress call still active
2653 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2657 if game.state.remkl >=MAXKLGAME:
2658 continue # full right now
2659 # reproduce one Klingon
2661 if game.klhere >= MAXKLQUAD:
2663 # this quadrant not ok, pick an adjacent one
2664 for i in range(w.x - 1, w.x + 2):
2665 for j in range(w.y - 1, w.y + 2):
2666 if not VALID_QUADRANT(i, j):
2668 q = game.state.galaxy[w.x][w.y]
2669 # check for this quad ok (not full & no snova)
2670 if q.klingons >= MAXKLQUAD or q.supernova:
2674 continue # search for eligible quadrant failed
2679 game.state.remkl += 1
2681 if game.quadrant == w:
2683 game.enemies.append(newkling())
2684 # recompute time left
2686 # report the disaster if we can
2688 if game.quadrant == w:
2689 prout(_("Spock- sensors indicate the Klingons have"))
2690 prout(_("launched a warship from %s.") % q.planet)
2692 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2693 if q.planet != None:
2694 proutn(_("near %s") % q.planet)
2695 prout(_("in Quadrant %s.") % w)
2701 key = scanner.next()
2704 proutn(_("How long? "))
2709 origTime = delay = scanner.real
2712 if delay >= game.state.remtime or len(game.enemies) != 0:
2713 proutn(_("Are you sure? "))
2716 # Alternate resting periods (events) with attacks
2720 game.resting = False
2721 if not game.resting:
2722 prout(_("%d stardates left.") % int(game.state.remtime))
2724 temp = game.optime = delay
2725 if len(game.enemies):
2726 rtime = randreal(1.0, 2.0)
2730 if game.optime < delay:
2731 attack(torps_ok=False)
2739 # Repair Deathray if long rest at starbase
2740 if origTime-delay >= 9.99 and game.condition == "docked":
2741 game.damage[DDRAY] = 0.0
2742 # leave if quadrant supernovas
2743 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2745 game.resting = False
2748 # A nova occurs. It is the result of having a star hit with a
2749 # photon torpedo, or possibly of a probe warhead going off.
2750 # Stars that go nova cause stars which surround them to undergo
2751 # the same probabilistic process. Klingons next to them are
2752 # destroyed. And if the starship is next to it, it gets zapped.
2753 # If the zap is too much, it gets destroyed.
2757 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2758 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2760 # Wow! We've supernova'ed
2761 supernova(False, nov)
2763 # handle initial nova
2764 game.quad[nov.x][nov.y] = IHDOT
2765 crmena(False, IHSTAR, "sector", nov)
2767 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2768 game.state.starkl += 1
2769 # Set up queue to recursively trigger adjacent stars
2775 for offset.x in range(-1, 1+1):
2776 for offset.y in range(-1, 1+1):
2777 if offset.y==0 and offset.x==0:
2779 neighbor = start + offset
2780 if not VALID_SECTOR(neighbor.y, neighbor.x):
2782 iquad = game.quad[neighbor.x][neighbor.y]
2783 # Empty space ends reaction
2784 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2786 elif iquad == IHSTAR: # Affect another star
2788 # This star supernovas
2792 hits.append(neighbor)
2793 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2794 game.state.starkl += 1
2795 crmena(True, IHSTAR, "sector", neighbor)
2797 game.quad[neighbor.x][neighbor.y] = IHDOT
2799 elif iquad in (IHP, IHW): # Destroy planet
2800 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2802 game.state.nplankl += 1
2804 game.state.worldkl += 1
2805 crmena(True, iquad, "sector", neighbor)
2806 prout(_(" destroyed."))
2807 game.iplnet.pclass = "destroyed"
2809 game.plnet.invalidate()
2813 game.quad[neighbor.x][neighbor.y] = IHDOT
2814 elif iquad == IHB: # Destroy base
2815 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2816 for i in range(game.state.rembase):
2817 if game.state.baseq[i] == game.quadrant:
2819 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2820 game.state.rembase -= 1
2821 game.base.invalidate()
2822 game.state.basekl += 1
2824 crmena(True, IHB, "sector", neighbor)
2825 prout(_(" destroyed."))
2826 game.quad[neighbor.x][neighbor.y] = IHDOT
2827 elif iquad in (IHE, IHF): # Buffet ship
2828 prout(_("***Starship buffeted by nova."))
2830 if game.shield >= 2000.0:
2831 game.shield -= 2000.0
2833 diff = 2000.0 - game.shield
2837 prout(_("***Shields knocked out."))
2838 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2840 game.energy -= 2000.0
2841 if game.energy <= 0:
2844 # add in course nova contributes to kicking starship
2845 bump += (game.sector-hits[mm]).sgn()
2846 elif iquad == IHK: # kill klingon
2847 deadkl(neighbor, iquad, neighbor)
2848 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2849 for ll in range(len(game.enemies)):
2850 if game.enemies[ll].kloc == neighbor:
2852 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2853 if game.enemies[ll].kpower <= 0.0:
2854 deadkl(neighbor, iquad, neighbor)
2856 newc = neighbor + neighbor - hits[mm]
2857 crmena(True, iquad, "sector", neighbor)
2858 proutn(_(" damaged"))
2859 if not VALID_SECTOR(newc.x, newc.y):
2860 # can't leave quadrant
2863 iquad1 = game.quad[newc.x][newc.y]
2864 if iquad1 == IHBLANK:
2865 proutn(_(", blasted into "))
2866 crmena(False, IHBLANK, "sector", newc)
2868 deadkl(neighbor, iquad, newc)
2871 # can't move into something else
2874 proutn(_(", buffeted to Sector %s") % newc)
2875 game.quad[neighbor.x][neighbor.y] = IHDOT
2876 game.quad[newc.x][newc.y] = iquad
2877 game.enemies[ll].move(newc)
2878 # Starship affected by nova -- kick it away.
2879 game.dist = kount*0.1
2880 game.direc = course[3*(bump.x+1)+bump.y+2]
2881 if game.direc == 0.0:
2883 if game.dist == 0.0:
2885 game.optime = 10.0*game.dist/16.0
2887 prout(_("Force of nova displaces starship."))
2888 imove(novapush=True)
2889 game.optime = 10.0*game.dist/16.0
2892 def supernova(induced, w=None):
2893 # star goes supernova
2900 # Scheduled supernova -- select star
2901 # logic changed here so that we won't favor quadrants in top
2903 for nq.x in range(GALSIZE):
2904 for nq.y in range(GALSIZE):
2905 stars += game.state.galaxy[nq.x][nq.y].stars
2907 return # nothing to supernova exists
2908 num = randrange(stars) + 1
2909 for nq.x in range(GALSIZE):
2910 for nq.y in range(GALSIZE):
2911 num -= game.state.galaxy[nq.x][nq.y].stars
2917 proutn("=== Super nova here?")
2920 if not nq == game.quadrant or game.justin:
2921 # it isn't here, or we just entered (treat as enroute)
2924 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2925 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2928 # we are in the quadrant!
2929 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2930 for ns.x in range(QUADSIZE):
2931 for ns.y in range(QUADSIZE):
2932 if game.quad[ns.x][ns.y]==IHSTAR:
2939 prouts(_("***RED ALERT! RED ALERT!"))
2941 prout(_("***Incipient supernova detected at Sector %s") % ns)
2942 if (ns.x-game.sector.x)**2 + (ns.y-game.sector.y)**2 <= 2.1:
2943 proutn(_("Emergency override attempts t"))
2944 prouts("***************")
2948 # destroy any Klingons in supernovaed quadrant
2949 kldead = game.state.galaxy[nq.x][nq.y].klingons
2950 game.state.galaxy[nq.x][nq.y].klingons = 0
2951 if nq == game.state.kscmdr:
2952 # did in the Supercommander!
2953 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2957 survivors = filter(lambda w: w != nq, game.state.kcmdr)
2958 comkills = len(game.state.kcmdr) - len(survivors)
2959 game.state.kcmdr = survivors
2961 game.state.remcom -= comkills
2962 if game.state.remcom==0:
2964 game.state.remkl -= kldead
2965 # destroy Romulans and planets in supernovaed quadrant
2966 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
2967 game.state.galaxy[nq.x][nq.y].romulans = 0
2968 game.state.nromrem -= nrmdead
2970 for loop in range(game.inplan):
2971 if game.state.planets[loop].w == nq:
2972 game.state.planets[loop].pclass = "destroyed"
2974 # Destroy any base in supernovaed quadrant
2975 game.state.baseq = filter(lambda x: x != nq, game.state.baseq)
2976 game.state.rembase = len(game.state.baseq)
2977 # If starship caused supernova, tally up destruction
2979 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
2980 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
2981 game.state.nplankl += npdead
2982 # mark supernova in galaxy and in star chart
2983 if game.quadrant == nq or communicating():
2984 game.state.galaxy[nq.x][nq.y].supernova = True
2985 # If supernova destroys last Klingons give special message
2986 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
2989 prout(_("Lucky you!"))
2990 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
2993 # if some Klingons remain, continue or die in supernova
2998 # Code from finish.c ends here.
3001 # self-destruct maneuver
3002 # Finish with a BANG!
3004 if damaged(DCOMPTR):
3005 prout(_("Computer damaged; cannot execute destruct sequence."))
3007 prouts(_("---WORKING---")); skip(1)
3008 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3009 prouts(" 10"); skip(1)
3010 prouts(" 9"); skip(1)
3011 prouts(" 8"); skip(1)
3012 prouts(" 7"); skip(1)
3013 prouts(" 6"); skip(1)
3015 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3017 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3019 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3023 if game.passwd != scanner.token:
3024 prouts(_("PASSWORD-REJECTED;"))
3026 prouts(_("CONTINUITY-EFFECTED"))
3029 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3030 prouts(" 5"); skip(1)
3031 prouts(" 4"); skip(1)
3032 prouts(" 3"); skip(1)
3033 prouts(" 2"); skip(1)
3034 prouts(" 1"); skip(1)
3036 prouts(_("GOODBYE-CRUEL-WORLD"))
3044 prouts(_("********* Entropy of "))
3046 prouts(_(" maximized *********"))
3050 if len(game.enemies) != 0:
3051 whammo = 25.0 * game.energy
3053 while l <= len(game.enemies):
3054 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3055 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3060 "Compute our rate of kils over time."
3061 elapsed = game.state.date - game.indate
3062 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3065 starting = (game.inkling + game.incom + game.inscom)
3066 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3067 return (starting - remaining)/elapsed
3071 badpt = 5.0*game.state.starkl + \
3073 10.0*game.state.nplankl + \
3074 300*game.state.nworldkl + \
3076 100.0*game.state.basekl +\
3078 if game.ship == IHF:
3080 elif game.ship == None:
3085 # end the game, with appropriate notfications
3089 prout(_("It is stardate %.1f.") % game.state.date)
3091 if ifin == FWON: # Game has been won
3092 if game.state.nromrem != 0:
3093 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3096 prout(_("You have smashed the Klingon invasion fleet and saved"))
3097 prout(_("the Federation."))
3102 badpt = 0.0 # Close enough!
3103 # killsPerDate >= RateMax
3104 if game.state.date-game.indate < 5.0 or \
3105 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3107 prout(_("In fact, you have done so well that Starfleet Command"))
3108 if game.skill == SKILL_NOVICE:
3109 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3110 elif game.skill == SKILL_FAIR:
3111 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3112 elif game.skill == SKILL_GOOD:
3113 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3114 elif game.skill == SKILL_EXPERT:
3115 prout(_("promotes you to Commodore Emeritus."))
3117 prout(_("Now that you think you're really good, try playing"))
3118 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3119 elif game.skill == SKILL_EMERITUS:
3121 proutn(_("Computer- "))
3122 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3124 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3126 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3128 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3130 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3132 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3134 prout(_("Now you can retire and write your own Star Trek game!"))
3136 elif game.skill >= SKILL_EXPERT:
3137 if game.thawed and not idebug:
3138 prout(_("You cannot get a citation, so..."))
3140 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3144 # Only grant long life if alive (original didn't!)
3146 prout(_("LIVE LONG AND PROSPER."))
3151 elif ifin == FDEPLETE: # Federation Resources Depleted
3152 prout(_("Your time has run out and the Federation has been"))
3153 prout(_("conquered. Your starship is now Klingon property,"))
3154 prout(_("and you are put on trial as a war criminal. On the"))
3155 proutn(_("basis of your record, you are "))
3156 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3157 prout(_("acquitted."))
3159 prout(_("LIVE LONG AND PROSPER."))
3161 prout(_("found guilty and"))
3162 prout(_("sentenced to death by slow torture."))
3166 elif ifin == FLIFESUP:
3167 prout(_("Your life support reserves have run out, and"))
3168 prout(_("you die of thirst, starvation, and asphyxiation."))
3169 prout(_("Your starship is a derelict in space."))
3171 prout(_("Your energy supply is exhausted."))
3173 prout(_("Your starship is a derelict in space."))
3174 elif ifin == FBATTLE:
3177 prout(_(" has been destroyed in battle."))
3179 prout(_("Dulce et decorum est pro patria mori."))
3181 prout(_("You have made three attempts to cross the negative energy"))
3182 prout(_("barrier which surrounds the galaxy."))
3184 prout(_("Your navigation is abominable."))
3187 prout(_("Your starship has been destroyed by a nova."))
3188 prout(_("That was a great shot."))
3190 elif ifin == FSNOVAED:
3193 prout(_(" has been fried by a supernova."))
3194 prout(_("...Not even cinders remain..."))
3195 elif ifin == FABANDN:
3196 prout(_("You have been captured by the Klingons. If you still"))
3197 prout(_("had a starbase to be returned to, you would have been"))
3198 prout(_("repatriated and given another chance. Since you have"))
3199 prout(_("no starbases, you will be mercilessly tortured to death."))
3200 elif ifin == FDILITHIUM:
3201 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3202 elif ifin == FMATERIALIZE:
3203 prout(_("Starbase was unable to re-materialize your starship."))
3204 prout(_("Sic transit gloria mundi"))
3205 elif ifin == FPHASER:
3208 prout(_(" has been cremated by its own phasers."))
3210 prout(_("You and your landing party have been"))
3211 prout(_("converted to energy, disipating through space."))
3212 elif ifin == FMINING:
3213 prout(_("You are left with your landing party on"))
3214 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3216 prout(_("They are very fond of \"Captain Kirk\" soup."))
3218 proutn(_("Without your leadership, the "))
3220 prout(_(" is destroyed."))
3221 elif ifin == FDPLANET:
3222 prout(_("You and your mining party perish."))
3224 prout(_("That was a great shot."))
3227 prout(_("The Galileo is instantly annihilated by the supernova."))
3228 prout(_("You and your mining party are atomized."))
3230 proutn(_("Mr. Spock takes command of the "))
3233 prout(_("joins the Romulans, reigning terror on the Federation."))
3234 elif ifin == FPNOVA:
3235 prout(_("You and your mining party are atomized."))
3237 proutn(_("Mr. Spock takes command of the "))
3240 prout(_("joins the Romulans, reigning terror on the Federation."))
3241 elif ifin == FSTRACTOR:
3242 prout(_("The shuttle craft Galileo is also caught,"))
3243 prout(_("and breaks up under the strain."))
3245 prout(_("Your debris is scattered for millions of miles."))
3246 proutn(_("Without your leadership, the "))
3248 prout(_(" is destroyed."))
3250 prout(_("The mutants attack and kill Spock."))
3251 prout(_("Your ship is captured by Klingons, and"))
3252 prout(_("your crew is put on display in a Klingon zoo."))
3253 elif ifin == FTRIBBLE:
3254 prout(_("Tribbles consume all remaining water,"))
3255 prout(_("food, and oxygen on your ship."))
3257 prout(_("You die of thirst, starvation, and asphyxiation."))
3258 prout(_("Your starship is a derelict in space."))
3260 prout(_("Your ship is drawn to the center of the black hole."))
3261 prout(_("You are crushed into extremely dense matter."))
3263 prout(_("Your last crew member has died."))
3264 if game.ship == IHF:
3266 elif game.ship == IHE:
3269 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3270 goodies = game.state.remres/game.inresor
3271 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3272 if goodies/baddies >= randreal(1.0, 1.5):
3273 prout(_("As a result of your actions, a treaty with the Klingon"))
3274 prout(_("Empire has been signed. The terms of the treaty are"))
3275 if goodies/baddies >= randreal(3.0):
3276 prout(_("favorable to the Federation."))
3278 prout(_("Congratulations!"))
3280 prout(_("highly unfavorable to the Federation."))
3282 prout(_("The Federation will be destroyed."))
3284 prout(_("Since you took the last Klingon with you, you are a"))
3285 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3286 prout(_("statue in your memory. Rest in peace, and try not"))
3287 prout(_("to think about pigeons."))
3292 # compute player's score
3293 timused = game.state.date - game.indate
3295 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3297 perdate = killrate()
3298 ithperd = 500*perdate + 0.5
3301 iwon = 100*game.skill
3302 if game.ship == IHE:
3304 elif game.ship == IHF:
3308 if not game.gamewon:
3309 game.state.nromrem = 0 # None captured if no win
3310 iscore = 10*(game.inkling - game.state.remkl) \
3311 + 50*(game.incom - game.state.remcom) \
3313 + 20*(game.inrom - game.state.nromrem) \
3314 + 200*(game.inscom - game.state.nscrem) \
3315 - game.state.nromrem \
3320 prout(_("Your score --"))
3321 if game.inrom - game.state.nromrem:
3322 prout(_("%6d Romulans destroyed %5d") %
3323 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3324 if game.state.nromrem:
3325 prout(_("%6d Romulans captured %5d") %
3326 (game.state.nromrem, game.state.nromrem))
3327 if game.inkling - game.state.remkl:
3328 prout(_("%6d ordinary Klingons destroyed %5d") %
3329 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3330 if game.incom - game.state.remcom:
3331 prout(_("%6d Klingon commanders destroyed %5d") %
3332 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3333 if game.inscom - game.state.nscrem:
3334 prout(_("%6d Super-Commander destroyed %5d") %
3335 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3337 prout(_("%6.2f Klingons per stardate %5d") %
3339 if game.state.starkl:
3340 prout(_("%6d stars destroyed by your action %5d") %
3341 (game.state.starkl, -5*game.state.starkl))
3342 if game.state.nplankl:
3343 prout(_("%6d planets destroyed by your action %5d") %
3344 (game.state.nplankl, -10*game.state.nplankl))
3345 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3346 prout(_("%6d inhabited planets destroyed by your action %5d") %
3347 (game.state.nplankl, -300*game.state.nworldkl))
3348 if game.state.basekl:
3349 prout(_("%6d bases destroyed by your action %5d") %
3350 (game.state.basekl, -100*game.state.basekl))
3352 prout(_("%6d calls for help from starbase %5d") %
3353 (game.nhelp, -45*game.nhelp))
3355 prout(_("%6d casualties incurred %5d") %
3356 (game.casual, -game.casual))
3358 prout(_("%6d crew abandoned in space %5d") %
3359 (game.abandoned, -3*game.abandoned))
3361 prout(_("%6d ship(s) lost or destroyed %5d") %
3362 (klship, -100*klship))
3364 prout(_("Penalty for getting yourself killed -200"))
3366 proutn(_("Bonus for winning "))
3367 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3368 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3369 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3370 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3371 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3372 prout(" %5d" % iwon)
3374 prout(_("TOTAL SCORE %5d") % iscore)
3377 # emit winner's commemmorative plaque
3380 proutn(_("File or device name for your plaque: "))
3383 fp = open(winner, "w")
3386 prout(_("Invalid name."))
3388 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3390 # The 38 below must be 64 for 132-column paper
3391 nskip = 38 - len(winner)/2
3392 fp.write("\n\n\n\n")
3393 # --------DRAW ENTERPRISE PICTURE.
3394 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3395 fp.write(" EEE E : : : E\n" )
3396 fp.write(" EE EEE E : : NCC-1701 : E\n")
3397 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3398 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3399 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3400 fp.write(" EEEEEEE EEEEE E E E E\n")
3401 fp.write(" EEE E E E E\n")
3402 fp.write(" E E E E\n")
3403 fp.write(" EEEEEEEEEEEEE E E\n")
3404 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3405 fp.write(" :E : EEEE E\n")
3406 fp.write(" .-E -:----- E\n")
3407 fp.write(" :E : E\n")
3408 fp.write(" EE : EEEEEEEE\n")
3409 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3411 fp.write(_(" U. S. S. ENTERPRISE\n"))
3412 fp.write("\n\n\n\n")
3413 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3415 fp.write(_(" Starfleet Command bestows to you\n"))
3417 fp.write("%*s%s\n\n" % (nskip, "", winner))
3418 fp.write(_(" the rank of\n\n"))
3419 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3421 if game.skill == SKILL_EXPERT:
3422 fp.write(_(" Expert level\n\n"))
3423 elif game.skill == SKILL_EMERITUS:
3424 fp.write(_("Emeritus level\n\n"))
3426 fp.write(_(" Cheat level\n\n"))
3427 timestring = ctime()
3428 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3429 (timestring+4, timestring+20, timestring+11))
3430 fp.write(_(" Your score: %d\n\n") % iscore)
3431 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3434 # Code from io.c begins here
3436 rows = linecount = 0 # for paging
3439 fullscreen_window = None
3440 srscan_window = None
3441 report_window = None
3442 status_window = None
3443 lrscan_window = None
3444 message_window = None
3445 prompt_window = None
3449 "wrap up, either normally or due to signal"
3450 if game.options & OPTION_CURSES:
3457 sys.stdout.write('\n')
3463 #setlocale(LC_ALL, "")
3464 #bindtextdomain(PACKAGE, LOCALEDIR)
3465 #textdomain(PACKAGE)
3466 if atexit.register(outro):
3467 sys.stderr.write("Unable to register outro(), exiting...\n")
3469 if not (game.options & OPTION_CURSES):
3470 ln_env = os.getenv("LINES")
3476 stdscr = curses.initscr()
3481 curses.start_color()
3482 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3483 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3484 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3485 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3486 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3487 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3488 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3489 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3491 global fullscreen_window, srscan_window, report_window, status_window
3492 global lrscan_window, message_window, prompt_window
3493 (rows, columns) = stdscr.getmaxyx()
3494 fullscreen_window = stdscr
3495 srscan_window = curses.newwin(12, 25, 0, 0)
3496 report_window = curses.newwin(11, 0, 1, 25)
3497 status_window = curses.newwin(10, 0, 1, 39)
3498 lrscan_window = curses.newwin(5, 0, 0, 64)
3499 message_window = curses.newwin(0, 0, 12, 0)
3500 prompt_window = curses.newwin(1, 0, rows-2, 0)
3501 message_window.scrollok(True)
3502 setwnd(fullscreen_window)
3505 def textcolor(color):
3506 "Set text foreground color. Presently a stub."
3510 "Wrap up I/O. Presently a stub."
3514 "Wait for user action -- OK to do nothing if on a TTY"
3515 if game.options & OPTION_CURSES:
3520 if game.skill > SKILL_FAIR:
3521 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3523 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3527 if game.skill > SKILL_FAIR:
3528 prompt = _("[CONTINUE?]")
3530 prompt = _("[PRESS ENTER TO CONTINUE]")
3532 if game.options & OPTION_CURSES:
3534 setwnd(prompt_window)
3535 prompt_window.wclear()
3536 prompt_window.addstr(prompt)
3537 prompt_window.getstr()
3538 prompt_window.clear()
3539 prompt_window.refresh()
3540 setwnd(message_window)
3543 sys.stdout.write('\n')
3546 for j in range(rows):
3547 sys.stdout.write('\n')
3551 "Skip i lines. Pause game if this would cause a scrolling event."
3552 for dummy in range(i):
3553 if game.options & OPTION_CURSES:
3554 (y, x) = curwnd.getyx()
3555 (my, mx) = curwnd.getmaxyx()
3556 if curwnd == message_window and y >= my - 3:
3564 if rows and linecount >= rows:
3567 sys.stdout.write('\n')
3570 "Utter a line with no following line feed."
3571 if game.options & OPTION_CURSES:
3575 sys.stdout.write(line)
3585 if not replayfp or replayfp.closed: # Don't slow down replays
3588 if game.options & OPTION_CURSES:
3592 if not replayfp or replayfp.closed:
3596 "Get a line of input."
3597 if game.options & OPTION_CURSES:
3598 line = curwnd.getstr() + "\n"
3601 if replayfp and not replayfp.closed:
3603 line = replayfp.readline()
3606 prout("*** Replay finished")
3609 elif line[0] != "#":
3612 line = raw_input() + "\n"
3618 "Change windows -- OK for this to be a no-op in tty mode."
3620 if game.options & OPTION_CURSES:
3622 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3625 "Clear to end of line -- can be a no-op in tty mode"
3626 if game.options & OPTION_CURSES:
3631 "Clear screen -- can be a no-op in tty mode."
3633 if game.options & OPTION_CURSES:
3640 "Set highlight video, if this is reasonable."
3641 if game.options & OPTION_CURSES:
3642 curwnd.attron(curses.A_REVERSE)
3645 # Things past this point have policy implications.
3649 "Hook to be called after moving to redraw maps."
3650 if game.options & OPTION_CURSES:
3653 setwnd(srscan_window)
3657 setwnd(status_window)
3658 status_window.clear()
3659 status_window.move(0, 0)
3660 setwnd(report_window)
3661 report_window.clear()
3662 report_window.move(0, 0)
3664 setwnd(lrscan_window)
3665 lrscan_window.clear()
3666 lrscan_window.move(0, 0)
3667 lrscan(silent=False)
3669 def put_srscan_sym(w, sym):
3670 "Emit symbol for short-range scan."
3671 srscan_window.move(w.x+1, w.y*2+2)
3672 srscan_window.addch(sym)
3673 srscan_window.refresh()
3676 "Enemy fall down, go boom."
3677 if game.options & OPTION_CURSES:
3679 setwnd(srscan_window)
3680 srscan_window.attron(curses.A_REVERSE)
3681 put_srscan_sym(w, game.quad[w.x][w.y])
3685 srscan_window.attroff(curses.A_REVERSE)
3686 put_srscan_sym(w, game.quad[w.x][w.y])
3687 curses.delay_output(500)
3688 setwnd(message_window)
3691 "Sound and visual effects for teleportation."
3692 if game.options & OPTION_CURSES:
3694 setwnd(message_window)
3696 prouts(" . . . . . ")
3697 if game.options & OPTION_CURSES:
3698 #curses.delay_output(1000)
3702 def tracktorpedo(origin, w, step, i, n, iquad):
3703 "Torpedo-track animation."
3704 if not game.options & OPTION_CURSES:
3708 proutn(_("Track for %s torpedo number %d- ") % (game.quad[origin.x][origin.y],i+1))
3711 proutn(_("Torpedo track- "))
3712 elif step==4 or step==9:
3716 if not damaged(DSRSENS) or game.condition=="docked":
3717 if i != 0 and step == 1:
3720 if (iquad==IHDOT) or (iquad==IHBLANK):
3721 put_srscan_sym(w, '+')
3725 put_srscan_sym(w, iquad)
3727 curwnd.attron(curses.A_REVERSE)
3728 put_srscan_sym(w, iquad)
3732 curwnd.attroff(curses.A_REVERSE)
3733 put_srscan_sym(w, iquad)
3738 "Display the current galaxy chart."
3739 if game.options & OPTION_CURSES:
3740 setwnd(message_window)
3741 message_window.clear()
3743 if game.options & OPTION_TTY:
3748 def prstat(txt, data):
3750 if game.options & OPTION_CURSES:
3752 setwnd(status_window)
3754 proutn(" " * (NSYM - len(txt)))
3757 if game.options & OPTION_CURSES:
3758 setwnd(report_window)
3760 # Code from moving.c begins here
3762 def imove(novapush):
3763 # movement execution for warp, impulse, supernova, and tractor-beam events
3764 w = coord(); final = coord()
3767 def no_quad_change():
3768 # No quadrant change -- compute new average enemy distances
3769 game.quad[game.sector.x][game.sector.y] = game.ship
3771 for enemy in game.enemies:
3772 finald = (w-enemy.kloc).distance()
3773 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3774 enemy.kdist = finald
3775 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3776 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3777 attack(torps_ok=False)
3778 for enemy in game.enemies:
3779 enemy.kavgd = enemy.kdist
3782 setwnd(message_window)
3785 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3786 game.inorbit = False
3787 angle = ((15.0 - game.direc) * 0.5235988)
3788 deltax = -math.sin(angle)
3789 deltay = math.cos(angle)
3790 if math.fabs(deltax) > math.fabs(deltay):
3791 bigger = math.fabs(deltax)
3793 bigger = math.fabs(deltay)
3796 # If tractor beam is to occur, don't move full distance
3797 if game.state.date+game.optime >= scheduled(FTBEAM):
3799 game.condition = "red"
3800 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3801 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3802 # Move within the quadrant
3803 game.quad[game.sector.x][game.sector.y] = IHDOT
3806 n = int(10.0*game.dist*bigger+0.5)
3808 for m in range(1, n+1):
3813 if not VALID_SECTOR(w.x, w.y):
3814 # Leaving quadrant -- allow final enemy attack
3815 # Don't do it if being pushed by Nova
3816 if len(game.enemies) != 0 and not novapush:
3818 for enemy in game.enemies:
3819 finald = (w - enemy.kloc).distance()
3820 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3822 # Stas Sergeev added the condition
3823 # that attacks only happen if Klingons
3824 # are present and your skill is good.
3826 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3827 attack(torps_ok=False)
3830 # compute final position -- new quadrant and sector
3831 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3832 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3833 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3834 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3835 # check for edge of galaxy
3845 if w.x >= GALSIZE*QUADSIZE:
3846 w.x = (GALSIZE*QUADSIZE*2) - w.x
3848 if w.y >= GALSIZE*QUADSIZE:
3849 w.y = (GALSIZE*QUADSIZE*2) - w.y
3857 if game.nkinks == 3:
3858 # Three strikes -- you're out!
3862 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3863 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3864 prout(_("YOU WILL BE DESTROYED."))
3865 # Compute final position in new quadrant
3866 if trbeam: # Don't bother if we are to be beamed
3868 game.quadrant.x = w.x/QUADSIZE
3869 game.quadrant.y = w.y/QUADSIZE
3870 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3871 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3873 prout(_("Entering Quadrant %s.") % game.quadrant)
3874 game.quad[game.sector.x][game.sector.y] = game.ship
3876 if game.skill>SKILL_NOVICE:
3877 attack(torps_ok=False)
3879 iquad = game.quad[w.x][w.y]
3881 # object encountered in flight path
3882 stopegy = 50.0*game.dist/game.optime
3883 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3884 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3886 for enemy in game.enemies:
3887 if enemy.kloc == game.sector:
3889 collision(rammed=False, enemy=enemy)
3891 elif iquad == IHBLANK:
3893 prouts(_("***RED ALERT! RED ALERT!"))
3897 proutn(_(" pulled into black hole at Sector %s") % w)
3899 # Getting pulled into a black hole was certain
3900 # death in Almy's original. Stas Sergeev added a
3901 # possibility that you'll get timewarped instead.
3904 for m in range(NDEVICES):
3905 if game.damage[m]>0:
3907 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3908 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3918 proutn(_(" encounters Tholian web at %s;") % w)
3920 proutn(_(" blocked by object at %s;") % w)
3921 proutn(_("Emergency stop required "))
3922 prout(_("%2d units of energy.") % int(stopegy))
3923 game.energy -= stopegy
3924 final.x = x-deltax+0.5
3925 final.y = y-deltay+0.5
3927 if game.energy <= 0:
3933 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3940 # dock our ship at a starbase
3942 if game.condition == "docked" and verbose:
3943 prout(_("Already docked."))
3946 prout(_("You must first leave standard orbit."))
3948 if not game.base.is_valid() or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
3950 prout(_(" not adjacent to base."))
3952 game.condition = "docked"
3956 if game.energy < game.inenrg:
3957 game.energy = game.inenrg
3958 game.shield = game.inshld
3959 game.torps = game.intorps
3960 game.lsupres = game.inlsr
3961 game.state.crew = FULLCREW
3962 if not damaged(DRADIO) and \
3963 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
3964 # get attack report from base
3965 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
3969 # This program originally required input in terms of a (clock)
3970 # direction and distance. Somewhere in history, it was changed to
3971 # cartesian coordinates. So we need to convert. Probably
3972 # "manual" input should still be done this way -- it's a real
3973 # pain if the computer isn't working! Manual mode is still confusing
3974 # because it involves giving x and y motions, yet the coordinates
3975 # are always displayed y - x, where +y is downward!
3977 def getcourse(isprobe, akey):
3978 # get course and distance
3980 dquad = copy.copy(game.quadrant)
3981 navmode = "unspecified"
3985 if game.landed and not isprobe:
3986 prout(_("Dummy! You can't leave standard orbit until you"))
3987 proutn(_("are back aboard the ship."))
3990 while navmode == "unspecified":
3991 if damaged(DNAVSYS):
3993 prout(_("Computer damaged; manual navigation only"))
3995 prout(_("Computer damaged; manual movement only"))
4000 if isprobe and akey != -1:
4001 # For probe launch, use pre-scanned value first time
4005 key = scanner.next()
4007 proutn(_("Manual or automatic- "))
4010 elif key == IHALPHA:
4011 if scanner.sees("manual"):
4013 key = scanner.next()
4015 elif scanner.sees("automatic"):
4016 navmode = "automatic"
4017 key = scanner.next()
4025 prout(_("(Manual navigation assumed.)"))
4027 prout(_("(Manual movement assumed.)"))
4030 if navmode == "automatic":
4033 proutn(_("Target quadrant or quadrant§or- "))
4035 proutn(_("Destination sector or quadrant§or- "))
4038 key = scanner.next()
4042 xi = int(round(scanner.real))-1
4043 key = scanner.next()
4047 xj = int(round(scanner.real))-1
4048 key = scanner.next()
4050 # both quadrant and sector specified
4051 xk = int(round(scanner.real))-1
4052 key = scanner.next()
4056 xl = int(round(scanner.real))-1
4062 # only one pair of numbers was specified
4064 # only quadrant specified -- go to center of dest quad
4067 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4069 # only sector specified
4073 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4080 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4082 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4083 # the actual deltas get computed here
4085 delta.x = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4086 delta.y = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4089 proutn(_("X and Y displacements- "))
4092 key = scanner.next()
4097 delta.x = scanner.real
4098 key = scanner.next()
4102 delta.y = scanner.real
4103 # Check for zero movement
4104 if delta.x == 0 and delta.y == 0:
4107 if itemp == "verbose" and not isprobe:
4109 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4110 # Course actually laid in.
4111 game.dist = delta.distance()
4112 game.direc = delta.bearing()
4113 if game.direc < 0.0:
4119 # move under impulse power
4121 if damaged(DIMPULS):
4124 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4126 if game.energy > 30.0:
4127 if not getcourse(isprobe=False, akey=0):
4129 power = 20.0 + 100.0*game.dist
4132 if power >= game.energy:
4133 # Insufficient power for trip
4135 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4136 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4137 if game.energy > 30:
4138 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4139 int(0.01 * (game.energy-20.0)-0.05))
4140 prout(_(" quadrants.\""))
4142 prout(_("quadrant. They are, therefore, useless.\""))
4145 # Make sure enough time is left for the trip
4146 game.optime = game.dist/0.095
4147 if game.optime >= game.state.remtime:
4148 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4149 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4150 proutn(_("we dare spend the time?\" "))
4153 # Activate impulse engines and pay the cost
4154 imove(novapush=False)
4158 power = 20.0 + 100.0*game.dist
4159 game.energy -= power
4160 game.optime = game.dist/0.095
4161 if game.energy <= 0:
4166 # move under warp drive
4167 blooey = False; twarp = False
4168 if not timewarp: # Not WARPX entry
4170 if game.damage[DWARPEN] > 10.0:
4173 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4175 if damaged(DWARPEN) and game.warpfac > 4.0:
4178 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4179 prout(_(" is repaired, I can only give you warp 4.\""))
4181 # Read in course and distance
4182 if not getcourse(isprobe=False, akey=0):
4184 # Make sure starship has enough energy for the trip
4185 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4186 if power >= game.energy:
4187 # Insufficient power for trip
4190 prout(_("Engineering to bridge--"))
4191 if not game.shldup or 0.5*power > game.energy:
4192 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4194 prout(_("We can't do it, Captain. We don't have enough energy."))
4196 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4199 prout(_("if you'll lower the shields."))
4203 prout(_("We haven't the energy to go that far with the shields up."))
4206 # Make sure enough time is left for the trip
4207 game.optime = 10.0*game.dist/game.wfacsq
4208 if game.optime >= 0.8*game.state.remtime:
4210 prout(_("First Officer Spock- \"Captain, I compute that such"))
4211 proutn(_(" a trip would require approximately %2.0f") %
4212 (100.0*game.optime/game.state.remtime))
4213 prout(_(" percent of our"))
4214 proutn(_(" remaining time. Are you sure this is wise?\" "))
4220 if game.warpfac > 6.0:
4221 # Decide if engine damage will occur
4222 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4223 prob = game.dist*(6.0-game.warpfac)**2/66.666666666
4224 if prob > randreal():
4226 game.dist = randreal(game.dist)
4227 # Decide if time warp will occur
4228 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4230 if idebug and game.warpfac==10 and not twarp:
4232 proutn("=== Force time warp? ")
4236 # If time warp or engine damage, check path
4237 # If it is obstructed, don't do warp or damage
4238 angle = ((15.0-game.direc)*0.5235998)
4239 deltax = -math.sin(angle)
4240 deltay = math.cos(angle)
4241 if math.fabs(deltax) > math.fabs(deltay):
4242 bigger = math.fabs(deltax)
4244 bigger = math.fabs(deltay)
4248 n = 10.0 * game.dist * bigger +0.5
4251 for l in range(1, n+1):
4256 if not VALID_SECTOR(ix, iy):
4258 if game.quad[ix][iy] != IHDOT:
4261 # Activate Warp Engines and pay the cost
4262 imove(novapush=False)
4265 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4266 if game.energy <= 0:
4268 game.optime = 10.0*game.dist/game.wfacsq
4272 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4274 prout(_("Engineering to bridge--"))
4275 prout(_(" Scott here. The warp engines are damaged."))
4276 prout(_(" We'll have to reduce speed to warp 4."))
4281 # change the warp factor
4287 proutn(_("Warp factor- "))
4292 if game.damage[DWARPEN] > 10.0:
4293 prout(_("Warp engines inoperative."))
4295 if damaged(DWARPEN) and scanner.real > 4.0:
4296 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4297 prout(_(" but right now we can only go warp 4.\""))
4299 if scanner.real > 10.0:
4300 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4302 if scanner.real < 1.0:
4303 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4305 oldfac = game.warpfac
4306 game.warpfac = scanner.real
4307 game.wfacsq=game.warpfac*game.warpfac
4308 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4309 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4312 if game.warpfac < 8.00:
4313 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4315 if game.warpfac == 10.0:
4316 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4318 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4322 # cope with being tossed out of quadrant by supernova or yanked by beam
4324 # is captain on planet?
4326 if damaged(DTRANSP):
4329 prout(_("Scotty rushes to the transporter controls."))
4331 prout(_("But with the shields up it's hopeless."))
4333 prouts(_("His desperate attempt to rescue you . . ."))
4338 prout(_("SUCCEEDS!"))
4341 proutn(_("The crystals mined were "))
4349 # Check to see if captain in shuttle craft
4354 # Inform captain of attempt to reach safety
4358 prouts(_("***RED ALERT! RED ALERT!"))
4362 prout(_(" has stopped in a quadrant containing"))
4363 prouts(_(" a supernova."))
4365 proutn(_("***Emergency automatic override attempts to hurl "))
4368 prout(_("safely out of quadrant."))
4369 if not damaged(DRADIO):
4370 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4371 # Try to use warp engines
4372 if damaged(DWARPEN):
4374 prout(_("Warp engines damaged."))
4377 game.warpfac = randreal(6.0, 8.0)
4378 game.wfacsq = game.warpfac * game.warpfac
4379 prout(_("Warp factor set to %d") % int(game.warpfac))
4380 power = 0.75*game.energy
4381 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4382 distreq = randreal(math.sqrt(2))
4383 if distreq < game.dist:
4385 game.optime = 10.0*game.dist/game.wfacsq
4386 game.direc = randreal(12) # How dumb!
4388 game.inorbit = False
4391 # This is bad news, we didn't leave quadrant.
4395 prout(_("Insufficient energy to leave quadrant."))
4398 # Repeat if another snova
4399 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4401 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4402 finish(FWON) # Snova killed remaining enemy.
4405 # let's do the time warp again
4406 prout(_("***TIME WARP ENTERED."))
4407 if game.state.snap and withprob(0.5):
4409 prout(_("You are traveling backwards in time %d stardates.") %
4410 int(game.state.date-game.snapsht.date))
4411 game.state = game.snapsht
4412 game.state.snap = False
4413 if game.state.remcom:
4414 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4415 schedule(FBATTAK, expran(0.3*game.intime))
4416 schedule(FSNOVA, expran(0.5*game.intime))
4417 # next snapshot will be sooner
4418 schedule(FSNAP, expran(0.25*game.state.remtime))
4420 if game.state.nscrem:
4421 schedule(FSCMOVE, 0.2777)
4425 game.battle.invalidate()
4427 # Make sure Galileo is consistant -- Snapshot may have been taken
4428 # when on planet, which would give us two Galileos!
4430 for l in range(game.inplan):
4431 if game.state.planets[l].known == "shuttle_down":
4433 if game.iscraft == "onship" and game.ship==IHE:
4434 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4435 game.iscraft = "offship"
4436 # Likewise, if in the original time the Galileo was abandoned, but
4437 # was on ship earlier, it would have vanished -- let's restore it.
4438 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4439 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4440 game.iscraft = "onship"
4442 # * There used to be code to do the actual reconstrction here,
4443 # * but the starchart is now part of the snapshotted galaxy state.
4445 prout(_("Spock has reconstructed a correct star chart from memory"))
4447 # Go forward in time
4448 game.optime = -0.5*game.intime*math.log(randreal())
4449 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4450 # cheat to make sure no tractor beams occur during time warp
4451 postpone(FTBEAM, game.optime)
4452 game.damage[DRADIO] += game.optime
4454 events() # Stas Sergeev added this -- do pending events
4457 # launch deep-space probe
4458 # New code to launch a deep space probe
4459 if game.nprobes == 0:
4462 if game.ship == IHE:
4463 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4465 prout(_("Ye Faerie Queene has no deep space probes."))
4470 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4472 if is_scheduled(FDSPROB):
4475 if damaged(DRADIO) and game.condition != "docked":
4476 prout(_("Spock- \"Records show the previous probe has not yet"))
4477 prout(_(" reached its destination.\""))
4479 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4481 key = scanner.next()
4483 # slow mode, so let Kirk know how many probes there are left
4484 if game.nprobes == 1:
4485 prout(_("1 probe left."))
4487 prout(_("%d probes left") % game.nprobes)
4488 proutn(_("Are you sure you want to fire a probe? "))
4491 game.isarmed = False
4492 if key == IHALPHA and scanner.token == "armed":
4494 key = scanner.next()
4496 proutn(_("Arm NOVAMAX warhead? "))
4498 if not getcourse(isprobe=True, akey=key):
4501 angle = ((15.0 - game.direc) * 0.5235988)
4502 game.probeinx = -math.sin(angle)
4503 game.probeiny = math.cos(angle)
4504 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4505 bigger = math.fabs(game.probeinx)
4507 bigger = math.fabs(game.probeiny)
4508 game.probeiny /= bigger
4509 game.probeinx /= bigger
4510 game.proben = 10.0*game.dist*bigger +0.5
4511 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4512 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4513 game.probec = game.quadrant
4514 schedule(FDSPROB, 0.01) # Time to move one sector
4515 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4519 # Here's how the mayday code works:
4521 # First, the closest starbase is selected. If there is a a starbase
4522 # in your own quadrant, you are in good shape. This distance takes
4523 # quadrant distances into account only.
4525 # A magic number is computed based on the distance which acts as the
4526 # probability that you will be rematerialized. You get three tries.
4528 # When it is determined that you should be able to be rematerialized
4529 # (i.e., when the probability thing mentioned above comes up
4530 # positive), you are put into that quadrant (anywhere). Then, we try
4531 # to see if there is a spot adjacent to the star- base. If not, you
4532 # can't be rematerialized!!! Otherwise, it drops you there. It only
4533 # tries five times to find a spot to drop you. After that, it's your
4537 # yell for help from nearest starbase
4538 # There's more than one way to move in this game!
4541 # Test for conditions which prevent calling for help
4542 if game.condition == "docked":
4543 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4546 prout(_("Subspace radio damaged."))
4548 if game.state.rembase==0:
4549 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4552 proutn(_("You must be aboard the "))
4556 # OK -- call for help from nearest starbase
4559 # There's one in this quadrant
4560 ddist = (game.base - game.sector).distance()
4563 for m in range(game.state.rembase):
4564 xdist = QUADSIZE * (game.state.baseq[m] - game.quadrant).distance()
4568 # Since starbase not in quadrant, set up new quadrant
4569 game.quadrant = game.state.baseq[line]
4571 # dematerialize starship
4572 game.quad[game.sector.x][game.sector.y]=IHDOT
4573 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4575 prout(_(" dematerializes."))
4577 for m in range(1, 5+1):
4578 w = game.base.scatter()
4579 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4580 # found one -- finish up
4583 if not game.sector.is_valid():
4584 prout(_("You have been lost in space..."))
4585 finish(FMATERIALIZE)
4587 # Give starbase three chances to rematerialize starship
4588 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4589 for m in range(1, 3+1):
4590 if m == 1: proutn(_("1st"))
4591 elif m == 2: proutn(_("2nd"))
4592 elif m == 3: proutn(_("3rd"))
4593 proutn(_(" attempt to re-materialize "))
4595 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4598 if randreal() > probf:
4601 curses.delay_output(500)
4604 game.quad[ix][iy]=IHQUEST
4607 setwnd(message_window)
4608 finish(FMATERIALIZE)
4610 game.quad[ix][iy]=game.ship
4612 prout(_("succeeds."))
4616 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4618 # Abandon Ship (the BSD-Trek description)
4620 # The ship is abandoned. If your current ship is the Faire
4621 # Queene, or if your shuttlecraft is dead, you're out of
4622 # luck. You need the shuttlecraft in order for the captain
4623 # (that's you!!) to escape.
4625 # Your crew can beam to an inhabited starsystem in the
4626 # quadrant, if there is one and if the transporter is working.
4627 # If there is no inhabited starsystem, or if the transporter
4628 # is out, they are left to die in outer space.
4630 # If there are no starbases left, you are captured by the
4631 # Klingons, who torture you mercilessly. However, if there
4632 # is at least one starbase, you are returned to the
4633 # Federation in a prisoner of war exchange. Of course, this
4634 # can't happen unless you have taken some prisoners.
4639 if game.condition=="docked":
4641 prout(_("You cannot abandon Ye Faerie Queene."))
4644 # Must take shuttle craft to exit
4645 if game.damage[DSHUTTL]==-1:
4646 prout(_("Ye Faerie Queene has no shuttle craft."))
4648 if game.damage[DSHUTTL]<0:
4649 prout(_("Shuttle craft now serving Big Macs."))
4651 if game.damage[DSHUTTL]>0:
4652 prout(_("Shuttle craft damaged."))
4655 prout(_("You must be aboard the ship."))
4657 if game.iscraft != "onship":
4658 prout(_("Shuttle craft not currently available."))
4660 # Print abandon ship messages
4662 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4664 prouts(_("***ALL HANDS ABANDON SHIP!"))
4666 prout(_("Captain and crew escape in shuttle craft."))
4667 if game.state.rembase==0:
4668 # Oops! no place to go...
4671 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4673 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4674 prout(_("Remainder of ship's complement beam down"))
4675 prout(_("to nearest habitable planet."))
4676 elif q.planet != None and not damaged(DTRANSP):
4677 prout(_("Remainder of ship's complement beam down to %s.") %
4680 prout(_("Entire crew of %d left to die in outer space.") %
4682 game.casual += game.state.crew
4683 game.abandoned += game.state.crew
4685 # If at least one base left, give 'em the Faerie Queene
4687 game.icrystl = False # crystals are lost
4688 game.nprobes = 0 # No probes
4689 prout(_("You are captured by Klingons and released to"))
4690 prout(_("the Federation in a prisoner-of-war exchange."))
4691 nb = randrange(game.state.rembase)
4692 # Set up quadrant and position FQ adjacient to base
4693 if not game.quadrant == game.state.baseq[nb]:
4694 game.quadrant = game.state.baseq[nb]
4695 game.sector.x = game.sector.y = 5
4698 # position next to base by trial and error
4699 game.quad[game.sector.x][game.sector.y] = IHDOT
4700 for l in range(QUADSIZE):
4701 game.sector = game.base.scatter()
4702 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4703 game.quad[game.sector.x][game.sector.y] == IHDOT:
4706 break # found a spot
4707 game.sector.x=QUADSIZE/2
4708 game.sector.y=QUADSIZE/2
4710 # Get new commission
4711 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4712 game.state.crew = FULLCREW
4713 prout(_("Starfleet puts you in command of another ship,"))
4714 prout(_("the Faerie Queene, which is antiquated but,"))
4715 prout(_("still useable."))
4717 prout(_("The dilithium crystals have been moved."))
4719 game.iscraft = "offship" # Galileo disappears
4721 game.condition="docked"
4722 for l in range(NDEVICES):
4723 game.damage[l] = 0.0
4724 game.damage[DSHUTTL] = -1
4725 game.energy = game.inenrg = 3000.0
4726 game.shield = game.inshld = 1250.0
4727 game.torps = game.intorps = 6
4728 game.lsupres=game.inlsr=3.0
4734 # Code from planets.c begins here.
4737 # abort a lengthy operation if an event interrupts it
4740 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4745 # report on (uninhabited) planets in the galaxy
4749 prout(_("Spock- \"Planet report follows, Captain.\""))
4751 for i in range(game.inplan):
4752 if game.state.planets[i].pclass == "destroyed":
4754 if (game.state.planets[i].known != "unknown" \
4755 and not game.state.planets[i].inhabited) \
4758 if idebug and game.state.planets[i].known=="unknown":
4759 proutn("(Unknown) ")
4760 proutn(_("Quadrant %s") % game.state.planets[i].w)
4761 proutn(_(" class "))
4762 proutn(game.state.planets[i].pclass)
4764 if game.state.planets[i].crystals != present:
4766 prout(_("dilithium crystals present."))
4767 if game.state.planets[i].known=="shuttle_down":
4768 prout(_(" Shuttle Craft Galileo on surface."))
4770 prout(_("No information available."))
4773 # enter standard orbit
4777 prout(_("Already in standard orbit."))
4779 if damaged(DWARPEN) and damaged(DIMPULS):
4780 prout(_("Both warp and impulse engines damaged."))
4782 if not game.plnet.is_valid() or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4784 prout(_(" not adjacent to planet."))
4787 game.optime = randreal(0.02, 0.05)
4788 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4792 game.height = randreal(1400, 8600)
4793 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4798 # examine planets in this quadrant
4799 if damaged(DSRSENS):
4800 if game.options & OPTION_TTY:
4801 prout(_("Short range sensors damaged."))
4803 if game.iplnet == None:
4804 if game.options & OPTION_TTY:
4805 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4807 if game.iplnet.known == "unknown":
4808 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4810 prout(_(" Planet at Sector %s is of class %s.") %
4811 (game.plnet, game.iplnet.pclass))
4812 if game.iplnet.known=="shuttle_down":
4813 prout(_(" Sensors show Galileo still on surface."))
4814 proutn(_(" Readings indicate"))
4815 if game.iplnet.crystals != "present":
4817 prout(_(" dilithium crystals present.\""))
4818 if game.iplnet.known == "unknown":
4819 game.iplnet.known = "known"
4820 elif game.iplnet.inhabited:
4821 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4822 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4825 # use the transporter
4829 if damaged(DTRANSP):
4830 prout(_("Transporter damaged."))
4831 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4833 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4837 if not game.inorbit:
4839 prout(_(" not in standard orbit."))
4842 prout(_("Impossible to transport through shields."))
4844 if game.iplnet.known=="unknown":
4845 prout(_("Spock- \"Captain, we have no information on this planet"))
4846 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4847 prout(_(" you may not go down.\""))
4849 if not game.landed and game.iplnet.crystals=="absent":
4850 prout(_("Spock- \"Captain, I fail to see the logic in"))
4851 prout(_(" exploring a planet with no dilithium crystals."))
4852 proutn(_(" Are you sure this is wise?\" "))
4856 if not (game.options & OPTION_PLAIN):
4857 nrgneed = 50 * game.skill + game.height / 100.0
4858 if nrgneed > game.energy:
4859 prout(_("Engineering to bridge--"))
4860 prout(_(" Captain, we don't have enough energy for transportation."))
4862 if not game.landed and nrgneed * 2 > game.energy:
4863 prout(_("Engineering to bridge--"))
4864 prout(_(" Captain, we have enough energy only to transport you down to"))
4865 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4866 if game.iplnet.known == "shuttle_down":
4867 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4868 proutn(_(" Are you sure this is wise?\" "))
4873 # Coming from planet
4874 if game.iplnet.known=="shuttle_down":
4875 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4879 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4880 prout(_("Landing party assembled, ready to beam up."))
4882 prout(_("Kirk whips out communicator..."))
4883 prouts(_("BEEP BEEP BEEP"))
4885 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4888 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4890 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4892 prout(_("Kirk- \"Energize.\""))
4895 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4898 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4900 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4903 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4904 game.landed = not game.landed
4905 game.energy -= nrgneed
4907 prout(_("Transport complete."))
4908 if game.landed and game.iplnet.known=="shuttle_down":
4909 prout(_("The shuttle craft Galileo is here!"))
4910 if not game.landed and game.imine:
4917 # strip-mine a world for dilithium
4921 prout(_("Mining party not on planet."))
4923 if game.iplnet.crystals == "mined":
4924 prout(_("This planet has already been strip-mined for dilithium."))
4926 elif game.iplnet.crystals == "absent":
4927 prout(_("No dilithium crystals on this planet."))
4930 prout(_("You've already mined enough crystals for this trip."))
4932 if game.icrystl and game.cryprob == 0.05:
4933 proutn(_("With all those fresh crystals aboard the "))
4936 prout(_("there's no reason to mine more at this time."))
4938 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4941 prout(_("Mining operation complete."))
4942 game.iplnet.crystals = "mined"
4943 game.imine = game.ididit = True
4946 # use dilithium crystals
4950 if not game.icrystl:
4951 prout(_("No dilithium crystals available."))
4953 if game.energy >= 1000:
4954 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4955 prout(_(" except when Condition Yellow exists."))
4957 prout(_("Spock- \"Captain, I must warn you that loading"))
4958 prout(_(" raw dilithium crystals into the ship's power"))
4959 prout(_(" system may risk a severe explosion."))
4960 proutn(_(" Are you sure this is wise?\" "))
4965 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
4966 prout(_(" Mr. Spock and I will try it.\""))
4968 prout(_("Spock- \"Crystals in place, Sir."))
4969 prout(_(" Ready to activate circuit.\""))
4971 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
4973 if with(game.cryprob):
4974 prouts(_(" \"Activating now! - - No good! It's***"))
4976 prouts(_("***RED ALERT! RED A*L********************************"))
4979 prouts(_("****************** KA-BOOM!!!! *******************"))
4983 game.energy += randreal(5000.0, 5500.0)
4984 prouts(_(" \"Activating now! - - "))
4985 prout(_("The instruments"))
4986 prout(_(" are going crazy, but I think it's"))
4987 prout(_(" going to work!! Congratulations, Sir!\""))
4992 # use shuttlecraft for planetary jaunt
4995 if damaged(DSHUTTL):
4996 if game.damage[DSHUTTL] == -1.0:
4997 if game.inorbit and game.iplnet.known == "shuttle_down":
4998 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5000 prout(_("Ye Faerie Queene had no shuttle craft."))
5001 elif game.damage[DSHUTTL] > 0:
5002 prout(_("The Galileo is damaged."))
5003 else: # game.damage[DSHUTTL] < 0
5004 prout(_("Shuttle craft is now serving Big Macs."))
5006 if not game.inorbit:
5008 prout(_(" not in standard orbit."))
5010 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5011 prout(_("Shuttle craft not currently available."))
5013 if not game.landed and game.iplnet.known=="shuttle_down":
5014 prout(_("You will have to beam down to retrieve the shuttle craft."))
5016 if game.shldup or game.condition == "docked":
5017 prout(_("Shuttle craft cannot pass through shields."))
5019 if game.iplnet.known=="unknown":
5020 prout(_("Spock- \"Captain, we have no information on this planet"))
5021 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5022 prout(_(" you may not fly down.\""))
5024 game.optime = 3.0e-5*game.height
5025 if game.optime >= 0.8*game.state.remtime:
5026 prout(_("First Officer Spock- \"Captain, I compute that such"))
5027 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5028 int(100*game.optime/game.state.remtime))
5029 prout(_("remaining time."))
5030 proutn(_("Are you sure this is wise?\" "))
5036 if game.iscraft == "onship":
5038 if not damaged(DTRANSP):
5039 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5043 proutn(_("Shuttle crew"))
5045 proutn(_("Rescue party"))
5046 prout(_(" boards Galileo and swoops toward planet surface."))
5047 game.iscraft = "offship"
5051 game.iplnet.known="shuttle_down"
5052 prout(_("Trip complete."))
5055 # Ready to go back to ship
5056 prout(_("You and your mining party board the"))
5057 prout(_("shuttle craft for the trip back to the Enterprise."))
5059 prouts(_("The short hop begins . . ."))
5061 game.iplnet.known="known"
5067 game.iscraft = "onship"
5073 prout(_("Trip complete."))
5078 prout(_("Mining party assembles in the hangar deck,"))
5079 prout(_("ready to board the shuttle craft \"Galileo\"."))
5081 prouts(_("The hangar doors open; the trip begins."))
5084 game.iscraft = "offship"
5087 game.iplnet.known = "shuttle_down"
5090 prout(_("Trip complete."))
5094 # use the big zapper
5098 if game.ship != IHE:
5099 prout(_("Ye Faerie Queene has no death ray."))
5101 if len(game.enemies)==0:
5102 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5105 prout(_("Death Ray is damaged."))
5107 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5108 prout(_(" is highly unpredictible. Considering the alternatives,"))
5109 proutn(_(" are you sure this is wise?\" "))
5112 prout(_("Spock- \"Acknowledged.\""))
5115 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5117 prout(_("Crew scrambles in emergency preparation."))
5118 prout(_("Spock and Scotty ready the death ray and"))
5119 prout(_("prepare to channel all ship's power to the device."))
5121 prout(_("Spock- \"Preparations complete, sir.\""))
5122 prout(_("Kirk- \"Engage!\""))
5124 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5127 if game.options & OPTION_PLAIN:
5131 prouts(_("Sulu- \"Captain! It's working!\""))
5133 while len(game.enemies) > 0:
5134 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.x][game.enemies[1].kloc.y],game.enemies[1].kloc)
5135 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5136 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5138 if (game.options & OPTION_PLAIN) == 0:
5139 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5141 prout(_(" is still operational.\""))
5143 prout(_(" has been rendered nonfunctional.\""))
5144 game.damage[DDRAY] = 39.95
5146 r = randreal() # Pick failure method
5148 prouts(_("Sulu- \"Captain! It's working!\""))
5150 prouts(_("***RED ALERT! RED ALERT!"))
5152 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5154 prouts(_("***RED ALERT! RED A*L********************************"))
5157 prouts(_("****************** KA-BOOM!!!! *******************"))
5162 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5164 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5166 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5167 prout(_(" have apparently been transformed into strange mutations."))
5168 prout(_(" Vulcans do not seem to be affected."))
5170 prout(_("Kirk- \"Raauch! Raauch!\""))
5175 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5177 proutn(_("Spock- \"I believe the word is"))
5178 prouts(_(" *ASTONISHING*"))
5179 prout(_(" Mr. Sulu."))
5180 for i in range(QUADSIZE):
5181 for j in range(QUADSIZE):
5182 if game.quad[i][j] == IHDOT:
5183 game.quad[i][j] = IHQUEST
5184 prout(_(" Captain, our quadrant is now infested with"))
5185 prouts(_(" - - - - - - *THINGS*."))
5187 prout(_(" I have no logical explanation.\""))
5189 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5191 prout(_("Scotty- \"There are so many tribbles down here"))
5192 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5196 # Code from reports.c begins here
5198 def attackreport(curt):
5199 # report status of bases under attack
5201 if is_scheduled(FCDBAS):
5202 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5203 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5204 elif game.isatb == 1:
5205 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5206 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5208 prout(_("No Starbase is currently under attack."))
5210 if is_scheduled(FCDBAS):
5211 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5213 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5217 # report on general game status
5219 s1 = "" and game.thawed and _("thawed ")
5220 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5221 s3 = (None, _("novice"). _("fair"),
5222 _("good"), _("expert"), _("emeritus"))[game.skill]
5223 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5224 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5225 prout(_("No plaque is allowed."))
5227 prout(_("This is tournament game %d.") % game.tourn)
5228 prout(_("Your secret password is \"%s\"") % game.passwd)
5229 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5230 (game.inkling + game.incom + game.inscom)))
5231 if game.incom - game.state.remcom:
5232 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5233 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5234 prout(_(", but no Commanders."))
5237 if game.skill > SKILL_FAIR:
5238 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5239 if game.state.rembase != game.inbase:
5241 if game.inbase-game.state.rembase==1:
5242 proutn(_("has been 1 base"))
5244 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5245 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5247 prout(_("There are %d bases.") % game.inbase)
5248 if communicating() or game.iseenit:
5249 # Don't report this if not seen and
5250 # either the radio is dead or not at base!
5254 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5256 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5257 if game.ship == IHE:
5258 proutn(_("You have "))
5260 proutn("%d" % (game.nprobes))
5263 proutn(_(" deep space probe"))
5267 if communicating() and is_scheduled(FDSPROB):
5269 proutn(_("An armed deep space probe is in "))
5271 proutn(_("A deep space probe is in "))
5272 prout("Quadrant %s." % game.probec)
5274 if game.cryprob <= .05:
5275 prout(_("Dilithium crystals aboard ship... not yet used."))
5279 while game.cryprob > ai:
5282 prout(_("Dilithium crystals have been used %d time%s.") % \
5283 (i, (_("s"), "")[i==1]))
5287 # long-range sensor scan
5288 if damaged(DLRSENS):
5289 # Now allow base's sensors if docked
5290 if game.condition != "docked":
5292 prout(_("LONG-RANGE SENSORS DAMAGED."))
5295 prout(_("Starbase's long-range scan"))
5297 prout(_("Long-range scan"))
5298 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5301 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5302 if not VALID_QUADRANT(x, y):
5306 if not damaged(DRADIO):
5307 game.state.galaxy[x][y].charted = True
5308 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5309 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5310 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5311 if not silent and game.state.galaxy[x][y].supernova:
5314 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5322 for i in range(NDEVICES):
5325 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5326 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5328 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5329 game.damage[i]+0.05,
5330 game.docfac*game.damage[i]+0.005))
5332 prout(_("All devices functional."))
5335 # update the chart in the Enterprise's computer from galaxy data
5336 game.lastchart = game.state.date
5337 for i in range(GALSIZE):
5338 for j in range(GALSIZE):
5339 if game.state.galaxy[i][j].charted:
5340 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5341 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5342 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5345 # display the star chart
5347 if (game.options & OPTION_AUTOSCAN):
5349 if not damaged(DRADIO):
5351 if game.lastchart < game.state.date and game.condition == "docked":
5352 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5355 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5356 if game.state.date > game.lastchart:
5357 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5358 prout(" 1 2 3 4 5 6 7 8")
5359 for i in range(GALSIZE):
5360 proutn("%d |" % (i+1))
5361 for j in range(GALSIZE):
5362 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5366 if game.state.galaxy[i][j].supernova:
5368 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5370 elif game.state.galaxy[i][j].charted:
5371 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5375 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5383 def sectscan(goodScan, i, j):
5384 # light up an individual dot in a sector
5385 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5386 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):
5387 if game.condition == "red": textcolor("red")
5388 elif game.condition == "green": textcolor("green")
5389 elif game.condition == "yellow": textcolor("yellow")
5390 elif game.condition == "docked": textcolor("cyan")
5391 elif game.condition == "dead": textcolor("brown")
5392 if game.quad[i][j] != game.ship:
5394 proutn("%c " % game.quad[i][j])
5400 # print status report lines
5402 if not req or req == 1:
5403 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5404 % (game.state.date, game.state.remtime))
5405 if not req or req == 2:
5406 if game.condition != "docked":
5409 for t in range(NDEVICES):
5410 if game.damage[t]>0:
5412 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5413 if not req or req == 3:
5414 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5415 if not req or req == 4:
5416 if damaged(DLIFSUP):
5417 if game.condition == "docked":
5418 s = _("DAMAGED, Base provides")
5420 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5423 prstat(_("Life Support"), s)
5424 if not req or req == 5:
5425 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5426 if not req or req == 6:
5428 if game.icrystl and (game.options & OPTION_SHOWME):
5429 extra = _(" (have crystals)")
5430 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5431 if not req or req == 7:
5432 prstat(_("Torpedoes"), "%d" % (game.torps))
5433 if not req or req == 8:
5434 if damaged(DSHIELD):
5440 data = _(" %d%% %.1f units") \
5441 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5442 prstat(_("Shields"), s+data)
5443 if not req or req == 9:
5444 prstat(_("Klingons Left"), "%d" \
5445 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5446 if not req or req == 10:
5447 if game.options & OPTION_WORLDS:
5448 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5449 if plnet and plnet.inhabited:
5450 prstat(_("Major system"), plnet.name)
5452 prout(_("Sector is uninhabited"))
5453 elif not req or req == 11:
5454 attackreport(not req)
5457 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5458 while scanner.next() == IHEOL:
5459 proutn(_("Information desired? "))
5461 if scanner.token in requests:
5462 status(requests.index(scanner.token))
5464 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5465 prout((" date, condition, position, lsupport, warpfactor,"))
5466 prout((" energy, torpedoes, shields, klingons, system, time."))
5471 if damaged(DSRSENS):
5472 # Allow base's sensors if docked
5473 if game.condition != "docked":
5474 prout(_(" S.R. SENSORS DAMAGED!"))
5477 prout(_(" [Using Base's sensors]"))
5479 prout(_(" Short-range scan"))
5480 if goodScan and not damaged(DRADIO):
5481 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5482 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5483 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5484 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5485 prout(" 1 2 3 4 5 6 7 8 9 10")
5486 if game.condition != "docked":
5488 for i in range(QUADSIZE):
5489 proutn("%2d " % (i+1))
5490 for j in range(QUADSIZE):
5491 sectscan(goodScan, i, j)
5495 # use computer to get estimated time of arrival for a warp jump
5496 w1 = coord(); w2 = coord()
5498 if damaged(DCOMPTR):
5499 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5502 if scanner.next() != IHREAL:
5505 proutn(_("Destination quadrant and/or sector? "))
5506 if scanner.next()!=IHREAL:
5509 w1.y = int(scanner.real-0.5)
5510 if scanner.next() != IHREAL:
5513 w1.x = int(scanner.real-0.5)
5514 if scanner.next() == IHREAL:
5515 w2.y = int(scanner.real-0.5)
5516 if scanner.next() != IHREAL:
5519 w2.x = int(scanner.real-0.5)
5521 if game.quadrant.y>w1.x:
5525 if game.quadrant.x>w1.y:
5529 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5532 game.dist = math.sqrt((w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))**2+
5533 (w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x))**2)
5536 prout(_("Answer \"no\" if you don't know the value:"))
5539 proutn(_("Time or arrival date? "))
5540 if scanner.next()==IHREAL:
5541 ttime = scanner.real
5542 if ttime > game.state.date:
5543 ttime -= game.state.date # Actually a star date
5544 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5545 if ttime <= 1e-10 or twarp > 10:
5546 prout(_("We'll never make it, sir."))
5553 proutn(_("Warp factor? "))
5554 if scanner.next()== IHREAL:
5556 twarp = scanner.real
5557 if twarp<1.0 or twarp > 10.0:
5561 prout(_("Captain, certainly you can give me one of these."))
5564 ttime = (10.0*game.dist)/twarp**2
5565 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5566 if tpower >= game.energy:
5567 prout(_("Insufficient energy, sir."))
5568 if not game.shldup or tpower > game.energy*2.0:
5571 proutn(_("New warp factor to try? "))
5572 if scanner.next() == IHREAL:
5574 twarp = scanner.real
5575 if twarp<1.0 or twarp > 10.0:
5583 prout(_("But if you lower your shields,"))
5584 proutn(_("remaining"))
5587 proutn(_("Remaining"))
5588 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5590 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5592 prout(_("Any warp speed is adequate."))
5594 prout(_("Minimum warp needed is %.2f,") % (twarp))
5595 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5596 if game.state.remtime < ttime:
5597 prout(_("Unfortunately, the Federation will be destroyed by then."))
5599 prout(_("You'll be taking risks at that speed, Captain"))
5600 if (game.isatb==1 and game.state.kscmdr == w1 and \
5601 scheduled(FSCDBAS)< ttime+game.state.date) or \
5602 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5603 prout(_("The starbase there will be destroyed by then."))
5604 proutn(_("New warp factor to try? "))
5605 if scanner.next() == IHREAL:
5607 twarp = scanner.real
5608 if twarp<1.0 or twarp > 10.0:
5617 # Code from setup.c begins here
5620 # issue a historically correct banner
5622 prout(_("-SUPER- STAR TREK"))
5624 # From the FORTRAN original
5625 # prout(_("Latest update-21 Sept 78"))
5631 scanner.token = "emsave.trk"
5633 key = scanner.next()
5635 proutn(_("File name: "))
5636 key = scanner.next()
5641 if '.' not in scanner.token:
5642 scanner.token += ".trk"
5644 fp = open(scanner.token, "wb")
5646 prout(_("Can't freeze game as file %s") % scanner.token)
5648 cPickle.dump(game, fp)
5652 # retrieve saved game
5653 game.passwd[0] = '\0'
5654 key = scanner.next()
5656 proutn(_("File name: "))
5657 key = scanner.next()
5662 if '.' not in scanner.token:
5663 scanner.token += ".trk"
5665 fp = open(scanner.token, "rb")
5667 prout(_("Can't thaw game in %s") % scanner.token)
5669 game = cPickle.load(fp)
5673 # I used <http://www.memory-alpha.org> to find planets
5674 # with references in ST:TOS. Eath and the Alpha Centauri
5675 # Colony have been omitted.
5677 # Some planets marked Class G and P here will be displayed as class M
5678 # because of the way planets are generated. This is a known bug.
5681 _("Andoria (Fesoan)"), # several episodes
5682 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5683 _("Vulcan (T'Khasi)"), # many episodes
5684 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5685 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5686 _("Ardana"), # TOS: "The Cloud Minders"
5687 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5688 _("Gideon"), # TOS: "The Mark of Gideon"
5689 _("Aldebaran III"), # TOS: "The Deadly Years"
5690 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5691 _("Altair IV"), # TOS: "Amok Time
5692 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5693 _("Benecia"), # TOS: "The Conscience of the King"
5694 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5695 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5696 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5697 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5698 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5699 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5700 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5701 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5702 _("Ingraham B"), # TOS: "Operation: Annihilate"
5703 _("Janus IV"), # TOS: "The Devil in the Dark"
5704 _("Makus III"), # TOS: "The Galileo Seven"
5705 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5706 _("Omega IV"), # TOS: "The Omega Glory"
5707 _("Regulus V"), # TOS: "Amok Time
5708 _("Deneva"), # TOS: "Operation -- Annihilate!"
5709 # Worlds from BSD Trek
5710 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5711 _("Beta III"), # TOS: "The Return of the Archons"
5712 _("Triacus"), # TOS: "And the Children Shall Lead",
5713 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5715 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5716 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5717 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5718 # _("Izar"), # TOS: "Whom Gods Destroy"
5719 # _("Tiburon"), # TOS: "The Way to Eden"
5720 # _("Merak II"), # TOS: "The Cloud Minders"
5721 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5722 # _("Iotia"), # TOS: "A Piece of the Action"
5726 _("S. R. Sensors"), \
5727 _("L. R. Sensors"), \
5729 _("Photon Tubes"), \
5730 _("Life Support"), \
5731 _("Warp Engines"), \
5732 _("Impulse Engines"), \
5734 _("Subspace Radio"), \
5735 _("Shuttle Craft"), \
5737 _("Navigation System"), \
5739 _("Shield Control"), \
5745 # prepare to play, set up cosmos
5747 # Decide how many of everything
5749 return # frozen game
5750 # Prepare the Enterprise
5751 game.alldone = game.gamewon = False
5753 game.state.crew = FULLCREW
5754 game.energy = game.inenrg = 5000.0
5755 game.shield = game.inshld = 2500.0
5756 game.shldchg = False
5760 game.quadrant = randplace(GALSIZE)
5761 game.sector = randplace(QUADSIZE)
5762 game.torps = game.intorps = 10
5763 game.nprobes = randrange(2, 5)
5765 game.wfacsq = game.warpfac * game.warpfac
5766 for i in range(NDEVICES):
5767 game.damage[i] = 0.0
5768 # Set up assorted game parameters
5769 game.battle = coord()
5770 game.state.date = game.indate = 100.0 * randreal(20, 51)
5771 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5772 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5773 game.isatb = game.state.nplankl = 0
5774 game.state.starkl = game.state.basekl = 0
5775 game.iscraft = "onship"
5779 for i in range(GALSIZE):
5780 for j in range(GALSIZE):
5781 quad = game.state.galaxy[i][j]
5786 quad.starbase = False
5787 quad.supernova = False
5788 quad.status = "secure"
5789 # Initialize times for extraneous events
5790 schedule(FSNOVA, expran(0.5 * game.intime))
5791 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5792 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5793 schedule(FBATTAK, expran(0.3*game.intime))
5795 if game.state.nscrem:
5796 schedule(FSCMOVE, 0.2777)
5801 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5802 schedule(FDISTR, expran(1.0 + game.intime))
5807 # Starchart is functional but we've never seen it
5808 game.lastchart = FOREVER
5809 # Put stars in the galaxy
5811 for i in range(GALSIZE):
5812 for j in range(GALSIZE):
5813 k = randrange(1, QUADSIZE**2/10+1)
5815 game.state.galaxy[i][j].stars = k
5816 # Locate star bases in galaxy
5817 for i in range(game.inbase):
5820 w = randplace(GALSIZE)
5821 if not game.state.galaxy[w.x][w.y].starbase:
5824 # C version: for (j = i-1; j > 0; j--)
5825 # so it did them in the opposite order.
5826 for j in range(1, i):
5827 # Improved placement algorithm to spread out bases
5828 distq = (w - game.state.baseq[j]).distance()
5829 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5832 prout("=== Abandoning base #%d at %s" % (i, w))
5834 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5836 prout("=== Saving base #%d, close to #%d" % (i, j))
5839 game.state.baseq[i] = w
5840 game.state.galaxy[w.x][w.y].starbase = True
5841 game.state.chart[w.x][w.y].starbase = True
5842 # Position ordinary Klingon Battle Cruisers
5844 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5845 if klumper > MAXKLQUAD:
5849 klump = (1.0 - r*r)*klumper
5854 w = randplace(GALSIZE)
5855 if not game.state.galaxy[w.x][w.y].supernova and \
5856 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5858 game.state.galaxy[w.x][w.y].klingons += int(klump)
5861 # Position Klingon Commander Ships
5862 for i in range(game.incom):
5864 w = randplace(GALSIZE)
5865 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5866 not game.state.galaxy[w.x][w.y].supernova and \
5867 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5868 not w in game.state.kcmdr[:i]:
5870 game.state.galaxy[w.x][w.y].klingons += 1
5871 game.state.kcmdr[i] = w
5872 # Locate planets in galaxy
5873 for i in range(game.inplan):
5875 w = randplace(GALSIZE)
5876 if game.state.galaxy[w.x][w.y].planet == None:
5880 new.crystals = "absent"
5881 if (game.options & OPTION_WORLDS) and i < NINHAB:
5882 new.pclass = "M" # All inhabited planets are class M
5883 new.crystals = "absent"
5885 new.name = systnames[i]
5886 new.inhabited = True
5888 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5890 new.crystals = "present"
5891 new.known = "unknown"
5892 new.inhabited = False
5893 game.state.galaxy[w.x][w.y].planet = new
5894 game.state.planets.append(new)
5896 for i in range(game.state.nromrem):
5897 w = randplace(GALSIZE)
5898 game.state.galaxy[w.x][w.y].romulans += 1
5899 # Locate the Super Commander
5900 if game.state.nscrem > 0:
5902 w = randplace(GALSIZE)
5903 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
5905 game.state.kscmdr = w
5906 game.state.galaxy[w.x][w.y].klingons += 1
5907 # Place thing (in tournament game, we don't want one!)
5909 if game.tourn is None:
5910 thing = randplace(GALSIZE)
5912 game.state.snap = False
5913 if game.skill == SKILL_NOVICE:
5914 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5915 prout(_("a deadly Klingon invasion force. As captain of the United"))
5916 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5917 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5918 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5919 prout(_("your mission. As you proceed you may be given more time."))
5921 prout(_("You will have %d supporting starbases.") % (game.inbase))
5922 proutn(_("Starbase locations- "))
5924 prout(_("Stardate %d.") % int(game.state.date))
5926 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5927 prout(_("An unknown number of Romulans."))
5928 if game.state.nscrem:
5929 prout(_("And one (GULP) Super-Commander."))
5930 prout(_("%d stardates.") % int(game.intime))
5931 proutn(_("%d starbases in ") % game.inbase)
5932 for i in range(game.inbase):
5933 proutn(`game.state.baseq[i]`)
5936 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5937 proutn(_(" Sector %s") % game.sector)
5939 prout(_("Good Luck!"))
5940 if game.state.nscrem:
5941 prout(_(" YOU'LL NEED IT."))
5944 if len(game.enemies) - (thing == game.quadrant) - (game.tholian != None):
5946 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5947 attack(torps_ok=False)
5950 # choose your game type
5955 game.skill = SKILL_NONE
5957 if not scanner.inqueue: # Can start with command line options
5958 proutn(_("Would you like a regular, tournament, or saved game? "))
5960 if len(scanner.token)==0: # Try again
5962 if scanner.sees("tournament"):
5963 while scanner.next() == IHEOL:
5964 proutn(_("Type in tournament number-"))
5965 if scanner.real == 0:
5967 continue # We don't want a blank entry
5968 game.tourn = int(round(scanner.real))
5969 random.seed(scanner.real)
5971 logfp.write("# random.seed(%d)\n" % scanner.real)
5973 if scanner.sees("saved") or scanner.sees("frozen"):
5977 if game.passwd == None:
5979 if not game.alldone:
5980 game.thawed = True # No plaque if not finished
5984 if scanner.sees("regular"):
5986 proutn(_("What is \"%s\"?") % scanner.token)
5988 while game.length==0 or game.skill==SKILL_NONE:
5989 if scanner.next() == IHALPHA:
5990 if scanner.sees("short"):
5992 elif scanner.sees("medium"):
5994 elif scanner.sees("long"):
5996 elif scanner.sees("novice"):
5997 game.skill = SKILL_NOVICE
5998 elif scanner.sees("fair"):
5999 game.skill = SKILL_FAIR
6000 elif scanner.sees("good"):
6001 game.skill = SKILL_GOOD
6002 elif scanner.sees("expert"):
6003 game.skill = SKILL_EXPERT
6004 elif scanner.sees("emeritus"):
6005 game.skill = SKILL_EMERITUS
6007 proutn(_("What is \""))
6008 proutn(scanner.token)
6013 proutn(_("Would you like a Short, Medium, or Long game? "))
6014 elif game.skill == SKILL_NONE:
6015 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6016 # Choose game options -- added by ESR for SST2K
6017 if scanner.next() != IHALPHA:
6019 proutn(_("Choose your game style (or just press enter): "))
6021 if scanner.sees("plain"):
6022 # Approximates the UT FORTRAN version.
6023 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6024 game.options |= OPTION_PLAIN
6025 elif scanner.sees("almy"):
6026 # Approximates Tom Almy's version.
6027 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6028 game.options |= OPTION_ALMY
6029 elif scanner.sees("fancy"):
6031 elif len(scanner.token):
6032 proutn(_("What is \"%s\"?") % scanner.token)
6034 if game.passwd == "debug":
6036 fputs("=== Debug mode enabled\n", sys.stdout)
6038 # Use parameters to generate initial values of things
6039 game.damfac = 0.5 * game.skill
6040 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6041 game.inbase = game.state.rembase
6043 if game.options & OPTION_PLANETS:
6044 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6045 if game.options & OPTION_WORLDS:
6046 game.inplan += int(NINHAB)
6047 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6048 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6049 game.state.remtime = 7.0 * game.length
6050 game.intime = game.state.remtime
6051 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6052 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6053 game.state.remcom = min(10, game.incom)
6054 game.incom = game.state.remcom
6055 game.state.remres = (game.inkling+4*game.incom)*game.intime
6056 game.inresor = game.state.remres
6057 if game.inkling > 50:
6058 game.state.rembase += 1
6059 game.inbase = game.state.rembase
6062 def dropin(iquad=None):
6063 # drop a feature on a random dot in the current quadrant
6066 w = randplace(QUADSIZE)
6067 if game.quad[w.x][w.y] == IHDOT:
6069 if iquad is not None:
6070 game.quad[w.x][w.y] = iquad
6074 # update our alert status
6075 game.condition = "green"
6076 if game.energy < 1000.0:
6077 game.condition = "yellow"
6078 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6079 game.condition = "red"
6081 game.condition="dead"
6084 # drop new Klingon into current quadrant
6085 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
6088 # set up a new state of quadrant, for when we enter or re-enter it
6092 game.comhere = False
6097 game.inorbit = False
6099 game.ientesc = False
6100 game.iseenit = False
6101 # Create a blank quadrant
6102 game.quad = fill2d(QUADSIZE, lambda i, j: IHDOT)
6104 # Attempt to escape Super-commander, so tbeam back!
6107 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6108 # cope with supernova
6111 game.klhere = q.klingons
6112 game.irhere = q.romulans
6114 game.quad[game.sector.x][game.sector.y] = game.ship
6117 # Position ordinary Klingons
6118 for i in range(game.klhere):
6120 # If we need a commander, promote a Klingon
6121 for i in range(game.state.remcom):
6122 if game.state.kcmdr[i] == game.quadrant:
6123 e = game.enemies[game.klhere-1]
6124 game.quad[e.kloc.x][e.kloc.y] = IHC
6125 e.kpower = randreal(950,1350) + 50.0*game.skill
6128 # If we need a super-commander, promote a Klingon
6129 if game.quadrant == game.state.kscmdr:
6131 game.quad[e.kloc.x][e.kloc.y] = IHS
6132 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
6133 game.iscate = (game.state.remkl > 1)
6135 # Put in Romulans if needed
6136 for i in range(game.klhere, len(game.enemies)):
6137 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
6138 # If quadrant needs a starbase, put it in
6140 game.base = dropin(IHB)
6141 # If quadrant needs a planet, put it in
6143 game.iplnet = q.planet
6144 if not q.planet.inhabited:
6145 game.plnet = dropin(IHP)
6147 game.plnet = dropin(IHW)
6148 # Check for condition
6151 if game.irhere > 0 and game.klhere == 0:
6153 if not damaged(DRADIO):
6155 prout(_("LT. Uhura- \"Captain, an urgent message."))
6156 prout(_(" I'll put it on audio.\" CLICK"))
6158 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6159 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6161 # Put in THING if needed
6162 if thing == game.quadrant:
6163 enemy(type=IHQUEST, loc=dropin(),
6164 power=randreal(6000,6500.0)+250.0*game.skill)
6165 if not damaged(DSRSENS):
6167 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6168 prout(_(" Please examine your short-range scan.\""))
6169 # Decide if quadrant needs a Tholian; lighten up if skill is low
6170 if game.options & OPTION_THOLIAN:
6171 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6172 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6173 (game.skill > SKILL_GOOD and withprob(0.08)):
6176 w.x = withprob(0.5) * (QUADSIZE-1)
6177 w.y = withprob(0.5) * (QUADSIZE-1)
6178 if game.quad[w.x][w.y] == IHDOT:
6180 game.tholian = enemy(type=IHT, loc=w,
6181 power=randrange(100, 500) + 25.0*game.skill)
6182 # Reserve unoccupied corners
6183 if game.quad[0][0]==IHDOT:
6184 game.quad[0][0] = 'X'
6185 if game.quad[0][QUADSIZE-1]==IHDOT:
6186 game.quad[0][QUADSIZE-1] = 'X'
6187 if game.quad[QUADSIZE-1][0]==IHDOT:
6188 game.quad[QUADSIZE-1][0] = 'X'
6189 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6190 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6191 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
6192 # And finally the stars
6193 for i in range(q.stars):
6195 # Put in a few black holes
6196 for i in range(1, 3+1):
6199 # Take out X's in corners if Tholian present
6201 if game.quad[0][0]=='X':
6202 game.quad[0][0] = IHDOT
6203 if game.quad[0][QUADSIZE-1]=='X':
6204 game.quad[0][QUADSIZE-1] = IHDOT
6205 if game.quad[QUADSIZE-1][0]=='X':
6206 game.quad[QUADSIZE-1][0] = IHDOT
6207 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6208 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6211 # set the self-destruct password
6212 if game.options & OPTION_PLAIN:
6215 proutn(_("Please type in a secret password- "))
6217 game.passwd = scanner.token
6218 if game.passwd != None:
6223 game.passwd += chr(ord('a')+randrange(26))
6225 # Code from sst.c begins here
6228 "SRSCAN": OPTION_TTY,
6229 "STATUS": OPTION_TTY,
6230 "REQUEST": OPTION_TTY,
6231 "LRSCAN": OPTION_TTY,
6244 "SENSORS": OPTION_PLANETS,
6245 "ORBIT": OPTION_PLANETS,
6246 "TRANSPORT": OPTION_PLANETS,
6247 "MINE": OPTION_PLANETS,
6248 "CRYSTALS": OPTION_PLANETS,
6249 "SHUTTLE": OPTION_PLANETS,
6250 "PLANETS": OPTION_PLANETS,
6255 "PROBE": OPTION_PROBE,
6257 "FREEZE": 0, # Synonym for SAVE
6263 "SOS": 0, # Synonym for MAYDAY
6264 "CALL": 0, # Synonym for MAYDAY
6271 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6274 # generate a list of legal commands
6276 proutn(_("LEGAL COMMANDS ARE:"))
6277 for key in commands:
6281 proutn("%-12s " % key)
6286 # browse on-line help
6287 # Give help on commands
6288 key = scanner.next()
6291 setwnd(prompt_window)
6292 proutn(_("Help on what command? "))
6293 key = scanner.next()
6294 setwnd(message_window)
6297 if scanner.token in commands or scanner.token == "ABBREV":
6304 cmd = scanner.token.upper()
6306 fp = open(SSTDOC, "r")
6309 fp = open(DOC_NAME, "r")
6311 prout(_("Spock- \"Captain, that information is missing from the"))
6312 proutn(_(" computer. You need to find "))
6314 prout(_(" and put it in the"))
6315 proutn(_(" current directory or to "))
6319 # This used to continue: "You need to find SST.DOC and put
6320 # it in the current directory."
6324 linebuf = fp.readline()
6326 prout(_("Spock- \"Captain, there is no information on that command.\""))
6329 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6330 linebuf = linebuf[3:].strip()
6334 prout(_("Spock- \"Captain, I've found the following information:\""))
6336 while linebuf in fp:
6337 if "******" in linebuf:
6343 # command-interpretation loop
6346 setwnd(message_window)
6347 while True: # command loop
6349 while True: # get a command
6354 setwnd(prompt_window)
6357 if scanner.next() == IHEOL:
6358 if game.options & OPTION_CURSES:
6361 elif scanner.token == "":
6365 setwnd(message_window)
6367 candidates = filter(lambda x: x.startswith(scanner.token.upper()),
6369 if len(candidates) == 1:
6372 elif candidates and not (game.options & OPTION_PLAIN):
6373 prout("Commands with prefix '%s': %s" % (scanner.token, " ".join(candidates)))
6377 if cmd == "SRSCAN": # srscan
6379 elif cmd == "STATUS": # status
6381 elif cmd == "REQUEST": # status request
6383 elif cmd == "LRSCAN": # long range scan
6384 lrscan(silent=False)
6385 elif cmd == "PHASERS": # phasers
6389 elif cmd == "TORPEDO": # photon torpedos
6393 elif cmd == "MOVE": # move under warp
6395 elif cmd == "SHIELDS": # shields
6396 doshield(shraise=False)
6399 game.shldchg = False
6400 elif cmd == "DOCK": # dock at starbase
6403 attack(torps_ok=False)
6404 elif cmd == "DAMAGES": # damage reports
6406 elif cmd == "CHART": # chart
6408 elif cmd == "IMPULSE": # impulse
6410 elif cmd == "REST": # rest
6414 elif cmd == "WARP": # warp
6416 elif cmd == "SCORE": # score
6418 elif cmd == "SENSORS": # sensors
6420 elif cmd == "ORBIT": # orbit
6424 elif cmd == "TRANSPORT": # transport "beam"
6426 elif cmd == "MINE": # mine
6430 elif cmd == "CRYSTALS": # crystals
6434 elif cmd == "SHUTTLE": # shuttle
6438 elif cmd == "PLANETS": # Planet list
6440 elif cmd == "REPORT": # Game Report
6442 elif cmd == "COMPUTER": # use COMPUTER!
6444 elif cmd == "COMMANDS":
6446 elif cmd == "EMEXIT": # Emergency exit
6447 clrscr() # Hide screen
6448 freeze(True) # forced save
6449 raise SysExit,1 # And quick exit
6450 elif cmd == "PROBE":
6451 probe() # Launch probe
6454 elif cmd == "ABANDON": # Abandon Ship
6456 elif cmd == "DESTRUCT": # Self Destruct
6458 elif cmd == "SAVE": # Save Game
6461 if game.skill > SKILL_GOOD:
6462 prout(_("WARNING--Saved games produce no plaques!"))
6463 elif cmd == "DEATHRAY": # Try a desparation measure
6467 elif cmd == "DEBUGCMD": # What do we want for debug???
6469 elif cmd == "MAYDAY": # Call for help
6474 game.alldone = True # quit the game
6479 break # Game has ended
6480 if game.optime != 0.0:
6483 break # Events did us in
6484 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6487 if hitme and not game.justin:
6488 attack(torps_ok=True)
6491 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6503 if cmd == IHR: s = _("Romulan")
6504 elif cmd == IHK: s = _("Klingon")
6505 elif cmd == IHC: s = _("Commander")
6506 elif cmd == IHS: s = _("Super-commander")
6507 elif cmd == IHSTAR: s = _("Star")
6508 elif cmd == IHP: s = _("Planet")
6509 elif cmd == IHB: s = _("Starbase")
6510 elif cmd == IHBLANK: s = _("Black hole")
6511 elif cmd == IHT: s = _("Tholian")
6512 elif cmd == IHWEB: s = _("Tholian web")
6513 elif cmd == IHQUEST: s = _("Stranger")
6514 elif cmd == IHW: s = _("Inhabited World")
6515 else: s = "Unknown??"
6518 def crmena(stars, enemy, loctype, w):
6519 # print an enemy and his location
6525 if loctype == "quadrant":
6526 buf = _("Quadrant ")
6527 elif loctype == "sector":
6532 # print our ship name
6533 if game.ship == IHE:
6535 elif game.ship == IHF:
6536 s = _("Faerie Queene")
6542 # print a line of stars
6543 prouts("******************************************************")
6547 return -avrage*math.log(1e-7 + randreal())
6549 def randplace(size):
6550 # choose a random location
6552 w.x = randrange(size)
6553 w.y = randrange(size)
6563 # Get a token from the user
6566 # Fill the token quue if nothing here
6567 while not self.inqueue:
6569 if curwnd==prompt_window:
6571 setwnd(message_window)
6575 # Skip leading white space
6576 line = line.lstrip()
6580 self.inqueue = line.lstrip().split() + [IHEOL]
6581 # From here on in it's all looking at the queue
6582 self.token = self.inqueue.pop(0)
6583 if self.token == IHEOL:
6587 self.real = float(self.token)
6593 self.token = self.token.lower()
6597 def push(self, toklist):
6598 self.inqueue += toklist
6600 # Demand input for next scan
6602 self.real = self.token = None
6604 # return IHEOL next time
6606 self.real = self.token = None
6608 # compares s to item and returns true if it matches to the length of s
6609 return s.startswith(self.token)
6611 # Round token value to nearest integer
6612 return int(round(scanner.real))
6615 # yes-or-no confirmation
6620 if scanner.token == 'y':
6622 if scanner.token == 'n':
6624 proutn(_("Please answer with \"y\" or \"n\": "))
6627 # complain about unparseable input
6630 prout(_("Beg your pardon, Captain?"))
6634 # access to the internals for debugging
6635 proutn("Reset levels? ")
6637 if game.energy < game.inenrg:
6638 game.energy = game.inenrg
6639 game.shield = game.inshld
6640 game.torps = game.intorps
6641 game.lsupres = game.inlsr
6642 proutn("Reset damage? ")
6644 for i in range(NDEVICES):
6645 if game.damage[i] > 0.0:
6646 game.damage[i] = 0.0
6647 proutn("Toggle debug flag? ")
6651 prout("Debug output ON")
6653 prout("Debug output OFF")
6654 proutn("Cause selective damage? ")
6656 for i in range(NDEVICES):
6661 key = scanner.next()
6662 if key == IHALPHA and scanner.sees("y"):
6663 game.damage[i] = 10.0
6664 proutn("Examine/change events? ")
6669 FSNOVA: "Supernova ",
6672 FBATTAK: "Base Attack ",
6673 FCDBAS: "Base Destroy ",
6674 FSCMOVE: "SC Move ",
6675 FSCDBAS: "SC Base Destroy ",
6676 FDSPROB: "Probe Move ",
6677 FDISTR: "Distress Call ",
6678 FENSLV: "Enslavement ",
6679 FREPRO: "Klingon Build ",
6681 for i in range(1, NEVENTS):
6684 proutn("%.2f" % (scheduled(i)-game.state.date))
6685 if i == FENSLV or i == FREPRO:
6687 proutn(" in %s" % ev.quadrant)
6692 key = scanner.next()
6697 ev = schedule(i, scanner.real)
6698 if i == FENSLV or i == FREPRO:
6700 proutn("In quadrant- ")
6701 key = scanner.next()
6702 # IHEOL says to leave coordinates as they are
6705 prout("Event %d canceled, no x coordinate." % (i))
6708 w.x = int(round(scanner.real))
6709 key = scanner.next()
6711 prout("Event %d canceled, no y coordinate." % (i))
6714 w.y = int(round(scanner.real))
6717 proutn("Induce supernova here? ")
6719 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6722 if __name__ == '__main__':
6724 global line, thing, game, idebug
6730 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6731 # Disable curses mode until the game logic is working.
6732 # if os.getenv("TERM"):
6733 # game.options |= OPTION_CURSES | OPTION_SHOWME
6735 game.options |= OPTION_TTY
6736 seed = int(time.time())
6737 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6738 for (switch, val) in options:
6741 replayfp = open(val, "r")
6743 sys.stderr.write("sst: can't open replay file %s\n" % val)
6746 line = replayfp.readline().strip()
6747 (leader, key, seed) = line.split()
6749 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6750 line = replayfp.readline().strip()
6751 arguments += line.split()[2:]
6753 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6755 game.options |= OPTION_TTY
6756 game.options &=~ OPTION_CURSES
6757 elif switch == '-t':
6758 game.options |= OPTION_TTY
6759 game.options &=~ OPTION_CURSES
6760 elif switch == '-x':
6763 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6765 # where to save the input in case of bugs
6767 logfp = open("/usr/tmp/sst-input.log", "w")
6769 sys.stderr.write("sst: warning, can't open logfile\n")
6771 logfp.write("# seed %s\n" % seed)
6772 logfp.write("# options %s\n" % " ".join(arguments))
6774 scanner = sstscanner()
6775 scanner.push(arguments)
6778 while True: # Play a game
6779 setwnd(fullscreen_window)
6785 game.alldone = False
6791 if game.tourn and game.alldone:
6792 proutn(_("Do you want your score recorded?"))
6797 proutn(_("Do you want to play again? "))
6801 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6805 except KeyboardInterrupt: