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
206 # These functions hide the difference between 0-origin and 1-origin addressing.
207 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
208 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
210 # How to represent features
235 def __init__(self, x=None, y=None):
238 def invalidate(self):
239 self.x = self.y = None
241 return self.x != None and self.y != None
242 def __eq__(self, other):
243 return other != None and self.x == other.y and self.x == other.y
244 def __add__(self, other):
245 return coord(self.x+self.x, self.y+self.y)
246 def __sub__(self, other):
247 return coord(self.x-other.x, self.y-other.y)
248 def __mul__(self, other):
249 return coord(self.x*other, self.y*other)
250 def __rmul__(self, other):
251 return coord(self.x*other, self.y*other)
252 def __div__(self, other):
253 return coord(self.x/other, self.y/other)
254 def __rdiv__(self, other):
255 return coord(self.x/other, self.y/other)
256 def snaptogrid(self):
257 return coord(int(round(self.x)), int(round(self.y)))
258 def distance(self, other=None):
259 if not other: other = coord(0, 0)
260 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
261 def bearing(self, other=None):
262 if not other: other = coord(0, 0)
263 return 1.90985*math.atan2(self.x-other.x, self.y-other.y)
269 s.x = self.x / abs(self.x)
273 s.y = self.y / abs(self.y)
277 s.x = self.x + randrange(-1, 2)
278 s.y = self.y + randrange(-1, 2)
283 if self.x == None or self.y == None:
285 return "%s - %s" % (self.x+1, self.y+1)
290 self.name = None # string-valued if inhabited
291 self.quadrant = coord() # quadrant located
292 self.pclass = None # could be ""M", "N", "O", or "destroyed"
293 self.crystals = "absent"# could be "mined", "present", "absent"
294 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
295 self.inhabited = False # is it inhabites?
303 self.starbase = False
306 self.supernova = False
308 self.status = "secure" # Could be "secure", "distressed", "enslaved"
316 def fill2d(size, fillfun):
317 "Fill an empty list in 2D."
319 for i in range(size):
321 for j in range(size):
322 lst[i].append(fillfun(i, j))
327 self.snap = False # snapshot taken
328 self.crew = 0 # crew complement
329 self.remkl = 0 # remaining klingons
330 self.nscrem = 0 # remaining super commanders
331 self.starkl = 0 # destroyed stars
332 self.basekl = 0 # destroyed bases
333 self.nromrem = 0 # Romulans remaining
334 self.nplankl = 0 # destroyed uninhabited planets
335 self.nworldkl = 0 # destroyed inhabited planets
336 self.planets = [] # Planet information
337 self.date = 0.0 # stardate
338 self.remres = 0 # remaining resources
339 self.remtime = 0 # remaining time
340 self.baseq = [] # Base quadrant coordinates
341 self.kcmdr = [] # Commander quadrant coordinates
342 self.kscmdr = coord() # Supercommander quadrant coordinates
343 # the galaxy (subscript 0 not used)
344 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
345 # the starchart (subscript 0 not used)
346 self.chart = fill2d(GALSIZE, lambda i, j: page())
350 self.date = None # A real number
351 self.quadrant = None # A coord structure
354 OPTION_ALL = 0xffffffff
355 OPTION_TTY = 0x00000001 # old interface
356 OPTION_CURSES = 0x00000002 # new interface
357 OPTION_IOMODES = 0x00000003 # cover both interfaces
358 OPTION_PLANETS = 0x00000004 # planets and mining
359 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
360 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
361 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
362 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
363 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
364 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
365 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
366 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
367 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
368 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
369 OPTION_PLAIN = 0x01000000 # user chose plain game
370 OPTION_ALMY = 0x02000000 # user chose Almy variant
389 NDEVICES= 16 # Number of devices
398 def damaged(dev): return (game.damage[dev] != 0.0)
399 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
401 # Define future events
402 FSPY = 0 # Spy event happens always (no future[] entry)
403 # can cause SC to tractor beam Enterprise
404 FSNOVA = 1 # Supernova
405 FTBEAM = 2 # Commander tractor beams Enterprise
406 FSNAP = 3 # Snapshot for time warp
407 FBATTAK = 4 # Commander attacks base
408 FCDBAS = 5 # Commander destroys base
409 FSCMOVE = 6 # Supercommander moves (might attack base)
410 FSCDBAS = 7 # Supercommander destroys base
411 FDSPROB = 8 # Move deep space probe
412 FDISTR = 9 # Emit distress call from an inhabited world
413 FENSLV = 10 # Inhabited word is enslaved */
414 FREPRO = 11 # Klingons build a ship in an enslaved system
418 # abstract out the event handling -- underlying data structures will change
419 # when we implement stateful events
421 def findevent(evtype): return game.future[evtype]
424 def __init__(self, type=None, loc=None, power=None):
429 self.kpower = power # enemy energy level
430 game.enemies.append(self)
432 motion = (loc != self.kloc)
433 if self.kloc.x is not None and self.kloc.y is not None:
436 game.quad[self.kloc.x][self.kloc.y] = IHWEB
438 game.quad[self.kloc.x][self.kloc.y] = IHDOT
440 self.kloc = copy.copy(loc)
441 game.quad[self.kloc.x][self.kloc.y] = self.type
442 self.kdist = self.kavgd = (game.sector - loc).distance()
445 self.kdist = self.kavgd = None
446 game.enemies.remove(self)
449 return "<%s,%s.%f>" % (self.type, self.kloc, self.kpower) # For debugging
453 self.options = None # Game options
454 self.state = snapshot() # A snapshot structure
455 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
456 self.quad = None # contents of our quadrant
457 self.damage = [0.0] * NDEVICES # damage encountered
458 self.future = [] # future events
459 for i in range(NEVENTS):
460 self.future.append(event())
461 self.passwd = None; # Self Destruct password
463 self.quadrant = None # where we are in the large
464 self.sector = None # where we are in the small
465 self.tholian = None # Tholian enemy object
466 self.base = None # position of base in current quadrant
467 self.battle = None # base coordinates being attacked
468 self.plnet = None # location of planet in quadrant
469 self.probec = None # current probe quadrant
470 self.gamewon = False # Finished!
471 self.ididit = False # action taken -- allows enemy to attack
472 self.alive = False # we are alive (not killed)
473 self.justin = False # just entered quadrant
474 self.shldup = False # shields are up
475 self.shldchg = False # shield is changing (affects efficiency)
476 self.iscate = False # super commander is here
477 self.ientesc = False # attempted escape from supercommander
478 self.resting = False # rest time
479 self.icraft = False # Kirk in Galileo
480 self.landed = False # party on planet (true), on ship (false)
481 self.alldone = False # game is now finished
482 self.neutz = False # Romulan Neutral Zone
483 self.isarmed = False # probe is armed
484 self.inorbit = False # orbiting a planet
485 self.imine = False # mining
486 self.icrystl = False # dilithium crystals aboard
487 self.iseenit = False # seen base attack report
488 self.thawed = False # thawed game
489 self.condition = None # "green", "yellow", "red", "docked", "dead"
490 self.iscraft = None # "onship", "offship", "removed"
491 self.skill = None # Player skill level
492 self.inkling = 0 # initial number of klingons
493 self.inbase = 0 # initial number of bases
494 self.incom = 0 # initial number of commanders
495 self.inscom = 0 # initial number of commanders
496 self.inrom = 0 # initial number of commanders
497 self.instar = 0 # initial stars
498 self.intorps = 0 # initial/max torpedoes
499 self.torps = 0 # number of torpedoes
500 self.ship = 0 # ship type -- 'E' is Enterprise
501 self.abandoned = 0 # count of crew abandoned in space
502 self.length = 0 # length of game
503 self.klhere = 0 # klingons here
504 self.casual = 0 # causalties
505 self.nhelp = 0 # calls for help
506 self.nkinks = 0 # count of energy-barrier crossings
507 self.iplnet = None # planet # in quadrant
508 self.inplan = 0 # initial planets
509 self.irhere = 0 # Romulans in quadrant
510 self.isatb = 0 # =1 if super commander is attacking base
511 self.tourn = None # tournament number
512 self.proben = 0 # number of moves for probe
513 self.nprobes = 0 # number of probes available
514 self.inresor = 0.0 # initial resources
515 self.intime = 0.0 # initial time
516 self.inenrg = 0.0 # initial/max energy
517 self.inshld = 0.0 # initial/max shield
518 self.inlsr = 0.0 # initial life support resources
519 self.indate = 0.0 # initial date
520 self.energy = 0.0 # energy level
521 self.shield = 0.0 # shield level
522 self.warpfac = 0.0 # warp speed
523 self.wfacsq = 0.0 # squared warp factor
524 self.lsupres = 0.0 # life support reserves
525 self.dist = 0.0 # movement distance
526 self.direc = 0.0 # movement direction
527 self.optime = 0.0 # time taken by current operation
528 self.docfac = 0.0 # repair factor when docking (constant?)
529 self.damfac = 0.0 # damage factor
530 self.lastchart = 0.0 # time star chart was last updated
531 self.cryprob = 0.0 # probability that crystal will work
532 self.probex = 0.0 # location of probe
534 self.probeinx = 0.0 # probe x,y increment
535 self.probeiny = 0.0 #
536 self.height = 0.0 # height of orbit around planet
538 # Stas thinks this should be (C expression):
539 # game.state.remkl + len(game.state.kcmdr) > 0 ?
540 # game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr)) : 99
541 # He says the existing expression is prone to divide-by-zero errors
542 # after killing the last klingon when score is shown -- perhaps also
543 # if the only remaining klingon is SCOM.
544 game.state.remtime = game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr))
545 # From enumerated type 'feature'
566 # From enumerated type 'FINTYPE'
590 # Log the results of pulling random numbers so we can check determinism.
596 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
599 def randrange(*args):
600 v = random.randrange(*args)
601 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
607 v *= args[0] # returns from [0, args[0])
609 v = args[0] + v*(args[1]-args[0]) # returns from [args[0], args[1])
610 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
613 # Code from ai.c begins here
616 "Would this quadrant welcome another Klingon?"
617 return VALID_QUADRANT(iq.x,iq.y) and \
618 not game.state.galaxy[iq.x][iq.y].supernova or \
619 game.state.galaxy[iq.x][iq.y].klingons < MAXKLQUAD
622 def tryexit(enemy, look, irun):
623 "A bad guy attempts to bug out."
625 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
626 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
627 if not welcoming(iq):
629 if enemy.type == IHR:
630 return False; # Romulans cannot escape!
632 # avoid intruding on another commander's territory
633 if enemy.type == IHC:
634 if iq in game.state.kcmdr:
636 # refuse to leave if currently attacking starbase
637 if game.battle == game.quadrant:
639 # don't leave if over 1000 units of energy
640 if enemy.kpower > 1000.0:
642 # emit escape message and move out of quadrant.
643 # we know this if either short or long range sensors are working
644 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
645 game.condition == "docked":
646 crmena(True, enemy.type, "sector", enemy.kloc)
647 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
648 # handle local matters related to escape
651 if game.condition != "docked":
653 # Handle global matters related to escape
654 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
655 game.state.galaxy[iq.x][iq.y].klingons += 1
660 schedule(FSCMOVE, 0.2777)
664 for cmdr in game.state.kcmdr:
665 if cmdr == game.quadrant:
666 game.state.kcmdr[n] = iq
668 return True; # success
671 # The bad-guy movement algorithm:
673 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
674 # If both are operating full strength, force is 1000. If both are damaged,
675 # force is -1000. Having shields down subtracts an additional 1000.
677 # 2. Enemy has forces equal to the energy of the attacker plus
678 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
679 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
681 # Attacker Initial energy levels (nominal):
682 # Klingon Romulan Commander Super-Commander
683 # Novice 400 700 1200
685 # Good 450 800 1300 1750
686 # Expert 475 850 1350 1875
687 # Emeritus 500 900 1400 2000
688 # VARIANCE 75 200 200 200
690 # Enemy vessels only move prior to their attack. In Novice - Good games
691 # only commanders move. In Expert games, all enemy vessels move if there
692 # is a commander present. In Emeritus games all enemy vessels move.
694 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
695 # forces are 1000 greater than Enterprise.
697 # Agressive action on average cuts the distance between the ship and
698 # the enemy to 1/4 the original.
700 # 4. At lower energy advantage, movement units are proportional to the
701 # advantage with a 650 advantage being to hold ground, 800 to move forward
702 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
704 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
705 # retreat, especially at high skill levels.
707 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
710 def movebaddy(enemy):
711 "Tactical movement for the bad guys."
712 next = coord(); look = coord()
714 # This should probably be just (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
715 if game.skill >= SKILL_EXPERT:
716 nbaddys = (((game.quadrant in game.state.kcmdr)*2 + (game.state.kscmdr==game.quadrant)*2+game.klhere*1.23+game.irhere*1.5)/2.0)
718 nbaddys = (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
720 mdist = int(dist1 + 0.5); # Nearest integer distance
721 # If SC, check with spy to see if should hi-tail it
722 if enemy.type==IHS and \
723 (enemy.kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
727 # decide whether to advance, retreat, or hold position
728 forces = enemy.kpower+100.0*len(game.enemies)+400*(nbaddys-1)
730 forces += 1000; # Good for enemy if shield is down!
731 if not damaged(DPHASER) or not damaged(DPHOTON):
732 if damaged(DPHASER): # phasers damaged
735 forces -= 0.2*(game.energy - 2500.0)
736 if damaged(DPHOTON): # photon torpedoes damaged
739 forces -= 50.0*game.torps
741 # phasers and photon tubes both out!
744 if forces <= 1000.0 and game.condition != "docked": # Typical situation
745 motion = ((forces + randreal(200))/150.0) - 5.0
747 if forces > 1000.0: # Very strong -- move in for kill
748 motion = (1.0 - randreal())**2 * dist1 + 1.0
749 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
750 motion -= game.skill*(2.0-randreal()**2)
752 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
753 # don't move if no motion
756 # Limit motion according to skill
757 if abs(motion) > game.skill:
762 # calculate preferred number of steps
767 if motion > 0 and nsteps > mdist:
768 nsteps = mdist; # don't overshoot
769 if nsteps > QUADSIZE:
770 nsteps = QUADSIZE; # This shouldn't be necessary
772 nsteps = 1; # This shouldn't be necessary
774 proutn("NSTEPS = %d:" % nsteps)
775 # Compute preferred values of delta X and Y
776 m = game.sector - enemy.kloc
777 if 2.0 * abs(m.x) < abs(m.y):
779 if 2.0 * abs(m.y) < abs(game.sector.x-enemy.kloc.x):
793 for ll in range(nsteps):
795 proutn(" %d" % (ll+1))
796 # Check if preferred position available
807 attempts = 0; # Settle mysterious hang problem
808 while attempts < 20 and not success:
810 if look.x < 0 or look.x >= QUADSIZE:
811 if motion < 0 and tryexit(enemy, look, irun):
813 if krawlx == m.x or m.y == 0:
815 look.x = next.x + krawlx
817 elif look.y < 0 or look.y >= QUADSIZE:
818 if motion < 0 and tryexit(enemy, look, irun):
820 if krawly == m.y or m.x == 0:
822 look.y = next.y + krawly
824 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
825 # See if enemy should ram ship
826 if game.quad[look.x][look.y] == game.ship and \
827 (enemy.type == IHC or enemy.type == IHS):
828 collision(rammed=True, enemy=enemy)
830 if krawlx != m.x and m.y != 0:
831 look.x = next.x + krawlx
833 elif krawly != m.y and m.x != 0:
834 look.y = next.y + krawly
837 break; # we have failed
849 if not damaged(DSRSENS) or game.condition == "docked":
852 proutn(_(" from Sector %s") % enemy.kloc)
853 if enemy.kdist < dist1:
854 proutn(_(" advances to "))
856 proutn(_(" retreats to "))
857 prout("Sector %s." % next)
860 "Sequence Klingon tactical movement."
863 # Figure out which Klingon is the commander (or Supercommander)
865 if game.quadrant in game.state.kcmdr:
866 for enemy in game.enemies:
867 if enemy.type == IHC:
869 if game.state.kscmdr==game.quadrant:
870 for enemy in game.enemies:
871 if enemy.type == IHS:
874 # If skill level is high, move other Klingons and Romulans too!
875 # Move these last so they can base their actions on what the
877 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
878 for enemy in game.enemies:
879 if enemy.type in (IHK, IHR):
881 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
883 def movescom(iq, avoid):
884 "Commander movement helper."
885 # Avoid quadrants with bases if we want to avoid Enterprise
886 if not welcoming(iq) or (avoid and iq in game.state.baseq):
888 if game.justin and not game.iscate:
891 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
892 game.state.kscmdr = iq
893 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
894 if game.state.kscmdr==game.quadrant:
895 # SC has scooted, Remove him from current quadrant
900 for enemy in game.enemies:
901 if enemy.type == IHS:
905 if game.condition != "docked":
907 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
908 # check for a helpful planet
909 for i in range(game.inplan):
910 if game.state.planets[i].quadrant == game.state.kscmdr and \
911 game.state.planets[i].crystals == "present":
913 game.state.planets[i].pclass = "destroyed"
914 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
917 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
918 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
919 prout(_(" by the Super-commander.\""))
921 return False; # looks good!
923 def supercommander():
924 "Move the Super Commander."
925 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
928 prout("== SUPERCOMMANDER")
929 # Decide on being active or passive
930 avoid = ((game.incom - len(game.state.kcmdr) + game.inkling - game.state.remkl)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) or \
931 (game.state.date-game.indate) < 3.0)
932 if not game.iscate and avoid:
933 # compute move away from Enterprise
934 idelta = game.state.kscmdr-game.quadrant
935 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
937 idelta.x = game.state.kscmdr.y-game.quadrant.y
938 idelta.y = game.quadrant.x-game.state.kscmdr.x
940 # compute distances to starbases
941 if not game.state.baseq:
945 sc = game.state.kscmdr
946 for base in game.state.baseq:
947 basetbl.append((i, (base - sc).distance()))
948 if game.state.baseq > 1:
949 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
950 # look for nearest base without a commander, no Enterprise, and
951 # without too many Klingons, and not already under attack.
952 ifindit = iwhichb = 0
953 for (i2, base) in enumerate(game.state.baseq):
954 i = basetbl[i2][0]; # bug in original had it not finding nearest
955 if base==game.quadrant or base==game.battle or not welcoming(base):
957 # if there is a commander, and no other base is appropriate,
958 # we will take the one with the commander
959 for cmdr in game.state.kcmdr:
960 if base == cmdr and ifindit != 2:
964 else: # no commander -- use this one
969 return # Nothing suitable -- wait until next time
970 ibq = game.state.baseq[iwhichb]
971 # decide how to move toward base
972 idelta = ibq - game.state.kscmdr
973 # Maximum movement is 1 quadrant in either or both axes
974 idelta = idelta.sgn()
975 # try moving in both x and y directions
976 # there was what looked like a bug in the Almy C code here,
977 # but it might be this translation is just wrong.
978 iq = game.state.kscmdr + idelta
979 if movescom(iq, avoid):
980 # failed -- try some other maneuvers
981 if idelta.x==0 or idelta.y==0:
984 iq.y = game.state.kscmdr.y + 1
985 if movescom(iq, avoid):
986 iq.y = game.state.kscmdr.y - 1
989 iq.x = game.state.kscmdr.x + 1
990 if movescom(iq, avoid):
991 iq.x = game.state.kscmdr.x - 1
994 # try moving just in x or y
995 iq.y = game.state.kscmdr.y
996 if movescom(iq, avoid):
997 iq.y = game.state.kscmdr.y + idelta.y
998 iq.x = game.state.kscmdr.x
1001 if len(game.state.baseq) == 0:
1004 for (i, ibq) in enumerate(game.state.baseq):
1005 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1008 return # no, don't attack base!
1009 game.iseenit = False
1011 schedule(FSCDBAS, randreal(1.0, 3.0))
1012 if is_scheduled(FCDBAS):
1013 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1014 if not communicating():
1018 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1019 % game.state.kscmdr)
1020 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1021 proutn(_(" It can survive until stardate %d.\"") \
1022 % int(scheduled(FSCDBAS)))
1023 if not game.resting:
1025 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1028 game.resting = False
1029 game.optime = 0.0; # actually finished
1031 # Check for intelligence report
1034 (not communicating()) or \
1035 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1038 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1039 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1044 if not game.tholian or game.justin:
1047 if game.tholian.kloc.x == 0 and game.tholian.kloc.y == 0:
1048 id.x = 0; id.y = QUADSIZE-1
1049 elif game.tholian.kloc.x == 0 and game.tholian.kloc.y == QUADSIZE-1:
1050 id.x = QUADSIZE-1; id.y = QUADSIZE-1
1051 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == QUADSIZE-1:
1052 id.x = QUADSIZE-1; id.y = 0
1053 elif game.tholian.kloc.x == QUADSIZE-1 and game.tholian.kloc.y == 0:
1056 # something is wrong!
1057 game.tholian.move(None)
1058 prout("***Internal error: Tholian in a bad spot.")
1060 # do nothing if we are blocked
1061 if game.quad[id.x][id.y] not in (IHDOT, IHWEB):
1063 here = copy.copy(game.tholian.kloc)
1064 delta = (id - game.tholian.kloc).sgn()
1066 while here.x != id.x:
1068 if game.quad[here.x][here.y]==IHDOT:
1069 game.tholian.move(here)
1071 while here.y != id.y:
1073 if game.quad[here.x][here.y]==IHDOT:
1074 game.tholian.move(here)
1075 # check to see if all holes plugged
1076 for i in range(QUADSIZE):
1077 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1079 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1081 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1083 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1085 # All plugged up -- Tholian splits
1086 game.quad[game.tholian.kloc.x][game.tholian.kloc.y]=IHWEB
1088 crmena(True, IHT, "sector", game.tholian)
1089 prout(_(" completes web."))
1090 game.tholian.move(None)
1093 # Code from battle.c begins here
1095 def doshield(shraise):
1096 "Change shield status."
1102 key = scanner.next()
1104 if scanner.sees("transfer"):
1107 if damaged(DSHIELD):
1108 prout(_("Shields damaged and down."))
1110 if scanner.sees("up"):
1112 elif scanner.sees("down"):
1115 proutn(_("Do you wish to change shield energy? "))
1117 proutn(_("Energy to transfer to shields- "))
1119 elif damaged(DSHIELD):
1120 prout(_("Shields damaged and down."))
1123 proutn(_("Shields are up. Do you want them down? "))
1130 proutn(_("Shields are down. Do you want them up? "))
1136 if action == "SHUP": # raise shields
1138 prout(_("Shields already up."))
1142 if game.condition != "docked":
1144 prout(_("Shields raised."))
1145 if game.energy <= 0:
1147 prout(_("Shields raising uses up last of energy."))
1152 elif action == "SHDN":
1154 prout(_("Shields already down."))
1158 prout(_("Shields lowered."))
1161 elif action == "NRG":
1162 while scanner.next() != IHREAL:
1164 proutn(_("Energy to transfer to shields- "))
1166 if scanner.real == 0:
1168 if scanner.real > game.energy:
1169 prout(_("Insufficient ship energy."))
1172 if game.shield+scanner.real >= game.inshld:
1173 prout(_("Shield energy maximized."))
1174 if game.shield+scanner.real > game.inshld:
1175 prout(_("Excess energy requested returned to ship energy"))
1176 game.energy -= game.inshld-game.shield
1177 game.shield = game.inshld
1179 if scanner.real < 0.0 and game.energy-scanner.real > game.inenrg:
1180 # Prevent shield drain loophole
1182 prout(_("Engineering to bridge--"))
1183 prout(_(" Scott here. Power circuit problem, Captain."))
1184 prout(_(" I can't drain the shields."))
1187 if game.shield+scanner.real < 0:
1188 prout(_("All shield energy transferred to ship."))
1189 game.energy += game.shield
1192 proutn(_("Scotty- \""))
1193 if scanner.real > 0:
1194 prout(_("Transferring energy to shields.\""))
1196 prout(_("Draining energy from shields.\""))
1197 game.shield += scanner.real
1198 game.energy -= scanner.real
1202 # choose a device to damage, at random.
1204 # Quoth Eric Allman in the code of BSD-Trek:
1205 # "Under certain conditions you can get a critical hit. This
1206 # sort of hit damages devices. The probability that a given
1207 # device is damaged depends on the device. Well protected
1208 # devices (such as the computer, which is in the core of the
1209 # ship and has considerable redundancy) almost never get
1210 # damaged, whereas devices which are exposed (such as the
1211 # warp engines) or which are particularly delicate (such as
1212 # the transporter) have a much higher probability of being
1215 # This is one place where OPTION_PLAIN does not restore the
1216 # original behavior, which was equiprobable damage across
1217 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1218 # and have done with it. Also, in the original game, DNAVYS
1219 # and DCOMPTR were the same device.
1221 # Instead, we use a table of weights similar to the one from BSD Trek.
1222 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1223 # We don't have a cloaking device. The shuttle got the allocation
1224 # for the cloaking device, then we shaved a half-percent off
1225 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1228 105, # DSRSENS: short range scanners 10.5%
1229 105, # DLRSENS: long range scanners 10.5%
1230 120, # DPHASER: phasers 12.0%
1231 120, # DPHOTON: photon torpedoes 12.0%
1232 25, # DLIFSUP: life support 2.5%
1233 65, # DWARPEN: warp drive 6.5%
1234 70, # DIMPULS: impulse engines 6.5%
1235 145, # DSHIELD: deflector shields 14.5%
1236 30, # DRADIO: subspace radio 3.0%
1237 45, # DSHUTTL: shuttle 4.5%
1238 15, # DCOMPTR: computer 1.5%
1239 20, # NAVCOMP: navigation system 2.0%
1240 75, # DTRANSP: transporter 7.5%
1241 20, # DSHCTRL: high-speed shield controller 2.0%
1242 10, # DDRAY: death ray 1.0%
1243 30, # DDSP: deep-space probes 3.0%
1245 idx = randrange(1000) # weights must sum to 1000
1247 for (i, w) in enumerate(weights):
1251 return None; # we should never get here
1253 def collision(rammed, enemy):
1254 "Collision handling fot rammong events."
1255 prouts(_("***RED ALERT! RED ALERT!"))
1257 prout(_("***COLLISION IMMINENT."))
1261 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(enemy.type, 1.0)
1263 proutn(_(" rammed by "))
1266 crmena(False, enemy.type, "sector", enemy.kloc)
1268 proutn(_(" (original position)"))
1270 deadkl(enemy.kloc, enemy.type, game.sector)
1273 prout(_(" heavily damaged."))
1274 icas = randrange(10, 30)
1275 prout(_("***Sickbay reports %d casualties"), icas)
1277 game.state.crew -= icas
1279 # In the pre-SST2K version, all devices got equiprobably damaged,
1280 # which was silly. Instead, pick up to half the devices at
1281 # random according to our weighting table,
1283 ncrits = randrange(NDEVICES/2)
1284 for m in range(ncrits):
1286 if game.damage[dev] < 0:
1288 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1289 # Damage for at least time of travel!
1290 game.damage[dev] += game.optime + extradm
1292 prout(_("***Shields are down."))
1293 if game.state.remkl + len(game.state.kcmdr) + game.state.nscrem:
1300 def torpedo(course, dispersion, origin, number, nburst):
1301 "Let a photon torpedo fly"
1304 ac = course + 0.25*dispersion
1305 angle = (15.0-ac)*0.5235988
1306 bullseye = (15.0 - course)*0.5235988
1307 deltax = -math.sin(angle);
1308 deltay = math.cos(angle);
1309 x = origin.x; y = origin.y
1310 w = coord(); jw = coord()
1311 w.x = w.y = jw.x = jw.y = 0
1312 bigger = max(math.fabs(deltax), math.fabs(deltay))
1315 if not damaged(DSRSENS) or game.condition=="docked":
1316 setwnd(srscan_window)
1318 setwnd(message_window)
1319 # Loop to move a single torpedo
1320 for step in range(1, 15+1):
1325 if not VALID_SECTOR(w.x, w.y):
1327 iquad=game.quad[w.x][w.y]
1328 tracktorpedo(origin, w, step, number, nburst, iquad)
1332 setwnd(message_window)
1333 if damaged(DSRSENS) and not game.condition=="docked":
1334 skip(1); # start new line after text track
1335 if iquad in (IHE, IHF): # Hit our ship
1337 proutn(_("Torpedo hits "))
1340 hit = 700.0 + randreal(100) - \
1341 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1342 newcnd(); # we're blown out of dock
1343 # We may be displaced.
1344 if game.landed or game.condition=="docked":
1345 return hit # Cheat if on a planet
1346 ang = angle + 2.5*(randreal()-0.5)
1347 temp = math.fabs(math.sin(ang))
1348 if math.fabs(math.cos(ang)) > temp:
1349 temp = math.fabs(math.cos(ang))
1350 xx = -math.sin(ang)/temp
1351 yy = math.cos(ang)/temp
1352 jw.x = int(w.x+xx+0.5)
1353 jw.y = int(w.y+yy+0.5)
1354 if not VALID_SECTOR(jw.x, jw.y):
1356 if game.quad[jw.x][jw.y]==IHBLANK:
1359 if game.quad[jw.x][jw.y]!=IHDOT:
1360 # can't move into object
1365 elif iquad in (IHC, IHS): # Hit a commander
1367 crmena(True, iquad, "sector", w)
1368 prout(_(" uses anti-photon device;"))
1369 prout(_(" torpedo neutralized."))
1371 elif iquad in (IHR, IHK): # Hit a regular enemy
1373 for enemy in game.enemies:
1374 if w == game.enemies[ll].kloc:
1376 kp = math.fabs(e.kpower)
1377 h1 = 700.0 + randrange(100) - \
1378 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1382 if enemy.kpower < 0:
1386 if enemy.kpower == 0:
1389 crmena(True, iquad, "sector", w)
1390 # If enemy damaged but not destroyed, try to displace
1391 ang = angle + 2.5*(randreal()-0.5)
1392 temp = math.fabs(math.sin(ang))
1393 if math.fabs(math.cos(ang)) > temp:
1394 temp = math.fabs(math.cos(ang))
1395 xx = -math.sin(ang)/temp
1396 yy = math.cos(ang)/temp
1397 jw.x = int(w.x+xx+0.5)
1398 jw.y = int(w.y+yy+0.5)
1399 if not VALID_SECTOR(jw.x, jw.y):
1400 prout(_(" damaged but not destroyed."))
1402 if game.quad[jw.x][jw.y]==IHBLANK:
1403 prout(_(" buffeted into black hole."))
1404 deadkl(w, iquad, jw)
1406 if game.quad[jw.x][jw.y]!=IHDOT:
1407 # can't move into object
1408 prout(_(" damaged but not destroyed."))
1410 proutn(_(" damaged--"))
1414 elif iquad == IHB: # Hit a base
1416 prout(_("***STARBASE DESTROYED.."))
1417 game.state.baseq = filter(lambda x: x != game.quadrant, game.state.baseq)
1418 game.quad[w.x][w.y]=IHDOT
1419 game.base.invalidate()
1420 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1421 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1422 game.state.basekl += 1
1425 elif iquad == IHP: # Hit a planet
1426 crmena(True, iquad, "sector", w)
1427 prout(_(" destroyed."))
1428 game.state.nplankl += 1
1429 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1430 game.iplnet.pclass = "destroyed"
1432 game.plnet.invalidate()
1433 game.quad[w.x][w.y] = IHDOT
1435 # captain perishes on planet
1438 elif iquad == IHW: # Hit an inhabited world -- very bad!
1439 crmena(True, iquad, "sector", w)
1440 prout(_(" destroyed."))
1441 game.state.nworldkl += 1
1442 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1443 game.iplnet.pclass = "destroyed"
1445 game.plnet.invalidate()
1446 game.quad[w.x][w.y] = IHDOT
1448 # captain perishes on planet
1450 prout(_("You have just destroyed an inhabited planet."))
1451 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1453 elif iquad == IHSTAR: # Hit a star
1457 crmena(True, IHSTAR, "sector", w)
1458 prout(_(" unaffected by photon blast."))
1460 elif iquad == IHQUEST: # Hit a thingy
1461 if not (game.options & OPTION_THINGY) or withprob(0.3):
1463 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1465 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1467 proutn(_("Mr. Spock-"))
1468 prouts(_(" \"Fascinating!\""))
1473 # Stas Sergeev added the possibility that
1474 # you can shove the Thingy and piss it off.
1475 # It then becomes an enemy and may fire at you.
1480 elif iquad == IHBLANK: # Black hole
1482 crmena(True, IHBLANK, "sector", w)
1483 prout(_(" swallows torpedo."))
1485 elif iquad == IHWEB: # hit the web
1487 prout(_("***Torpedo absorbed by Tholian web."))
1489 elif iquad == IHT: # Hit a Tholian
1490 h1 = 700.0 + randrange(100) - \
1491 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1494 game.quad[w.x][w.y] = IHDOT
1499 crmena(True, IHT, "sector", w)
1501 prout(_(" survives photon blast."))
1503 prout(_(" disappears."))
1504 game.tholian.move(None)
1505 game.quad[w.x][w.y] = IHWEB
1510 proutn("Don't know how to handle torpedo collision with ")
1511 crmena(True, iquad, "sector", w)
1515 if curwnd!=message_window:
1516 setwnd(message_window)
1518 game.quad[w.x][w.y]=IHDOT
1519 game.quad[jw.x][jw.y]=iquad
1520 prout(_(" displaced by blast to Sector %s ") % jw)
1521 for ll in range(len(game.enemies)):
1522 game.enemies[ll].kdist = game.enemies[ll].kavgd = (game.sector-game.enemies[ll].kloc).distance()
1523 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1526 prout(_("Torpedo missed."))
1530 "Critical-hit resolution."
1531 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1533 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1534 proutn(_("***CRITICAL HIT--"))
1535 # Select devices and cause damage
1537 for loop1 in range(ncrit):
1540 # Cheat to prevent shuttle damage unless on ship
1541 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1544 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1545 game.damage[j] += extradm
1547 for (i, j) in enumerate(cdam):
1549 if skipcount % 3 == 2 and i < len(cdam)-1:
1554 prout(_(" damaged."))
1555 if damaged(DSHIELD) and game.shldup:
1556 prout(_("***Shields knocked down."))
1559 def attack(torps_ok):
1560 # bad guy attacks us
1561 # torps_ok == False forces use of phasers in an attack
1562 attempt = False; ihurt = False;
1563 hitmax=0.0; hittot=0.0; chgfac=1.0
1565 # game could be over at this point, check
1569 prout("=== ATTACK!")
1570 # Tholian gets to move before attacking
1573 # if you have just entered the RNZ, you'll get a warning
1574 if game.neutz: # The one chance not to be attacked
1577 # commanders get a chance to tac-move towards you
1578 if (((game.quadrant in game.state.kcmdr or game.state.kscmdr==game.quadrant) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1580 # if no enemies remain after movement, we're done
1581 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1583 # set up partial hits if attack happens during shield status change
1584 pfac = 1.0/game.inshld
1586 chgfac = 0.25 + randreal(0.5)
1588 # message verbosity control
1589 if game.skill <= SKILL_FAIR:
1591 for enemy in game.enemies:
1592 if enemy.kpower < 0:
1593 continue; # too weak to attack
1594 # compute hit strength and diminish shield power
1596 # Increase chance of photon torpedos if docked or enemy energy is low
1597 if game.condition == "docked":
1599 if enemy.kpower < 500:
1601 if enemy.type==IHT or (enemy.type==IHQUEST and not thing.angry):
1603 # different enemies have different probabilities of throwing a torp
1604 usephasers = not torps_ok or \
1605 (enemy.type == IHK and r > 0.0005) or \
1606 (enemy.type==IHC and r > 0.015) or \
1607 (enemy.type==IHR and r > 0.3) or \
1608 (enemy.type==IHS and r > 0.07) or \
1609 (enemy.type==IHQUEST and r > 0.05)
1610 if usephasers: # Enemy uses phasers
1611 if game.condition == "docked":
1612 continue; # Don't waste the effort!
1613 attempt = True; # Attempt to attack
1614 dustfac = randreal(0.8, 0.85)
1615 hit = enemy.kpower*math.pow(dustfac,enemy.kavgd)
1616 enemy.kpower *= 0.75
1617 else: # Enemy uses photon torpedo
1618 #course2 = (enemy.kloc-game.sector).bearing()
1619 course = 1.90985*math.atan2(game.sector.y-enemy.kloc.y, enemy.kloc.x-game.sector.x)
1621 proutn(_("***TORPEDO INCOMING"))
1622 if not damaged(DSRSENS):
1624 crmena(False, enemy.type, where, enemy.kloc)
1627 dispersion = (randreal()+randreal())*0.5 - 0.5
1628 dispersion += 0.002*enemy.kpower*dispersion
1629 hit = torpedo(course, dispersion, origin=enemy.kloc, number=1, nburst=1)
1630 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1631 finish(FWON); # Klingons did themselves in!
1632 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1633 return # Supernova or finished
1636 # incoming phaser or torpedo, shields may dissipate it
1637 if game.shldup or game.shldchg or game.condition=="docked":
1638 # shields will take hits
1639 propor = pfac * game.shield
1640 if game.condition =="docked":
1644 hitsh = propor*chgfac*hit+1.0
1646 if absorb > game.shield:
1647 absorb = game.shield
1648 game.shield -= absorb
1650 # taking a hit blasts us out of a starbase dock
1651 if game.condition == "docked":
1653 # but the shields may take care of it
1654 if propor > 0.1 and hit < 0.005*game.energy:
1656 # hit from this opponent got through shields, so take damage
1658 proutn(_("%d unit hit") % int(hit))
1659 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1660 proutn(_(" on the "))
1662 if not damaged(DSRSENS) and usephasers:
1664 crmena(False, enemy.type, where, enemy.kloc)
1666 # Decide if hit is critical
1672 if game.energy <= 0:
1673 # Returning home upon your shield, not with it...
1676 if not attempt and game.condition == "docked":
1677 prout(_("***Enemies decide against attacking your ship."))
1678 percent = 100.0*pfac*game.shield+0.5
1680 # Shields fully protect ship
1681 proutn(_("Enemy attack reduces shield strength to "))
1683 # Emit message if starship suffered hit(s)
1685 proutn(_("Energy left %2d shields ") % int(game.energy))
1688 elif not damaged(DSHIELD):
1691 proutn(_("damaged, "))
1692 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1693 # Check if anyone was hurt
1694 if hitmax >= 200 or hittot >= 500:
1695 icas = randrange(int(hittot * 0.015))
1698 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1699 prout(_(" in that last attack.\""))
1701 game.state.crew -= icas
1702 # After attack, reset average distance to enemies
1703 for enemy in game.enemies:
1704 enemy.kavgd = enemy.kdist
1705 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1708 def deadkl(w, type, mv):
1709 "Kill a Klingon, Tholian, Romulan, or Thingy."
1710 # Added mv to allow enemy to "move" before dying
1711 crmena(True, type, "sector", mv)
1712 # Decide what kind of enemy it is and update appropriately
1714 # chalk up a Romulan
1715 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1717 game.state.nromrem -= 1
1721 elif type == IHQUEST:
1726 # Some type of a Klingon
1727 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1730 game.state.kcmdr.remove(game.quadrant)
1732 if game.state.kcmdr:
1733 schedule(FTBEAM, expran(1.0*game.incom/len(game.state.kcmdr)))
1734 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1737 game.state.remkl -= 1
1739 game.state.nscrem -= 1
1740 game.state.kscmdr.invalidate()
1745 # For each kind of enemy, finish message to player
1746 prout(_(" destroyed."))
1747 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1750 # Remove enemy ship from arrays describing local conditions
1751 for e in game.enemies:
1758 "Return None if target is invalid, otherwise return a course angle."
1759 if not VALID_SECTOR(w.x, w.y):
1762 delta = 0.1*(w - game.sector)
1763 if delta.x==0 and delta.y== 0:
1765 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1766 prout(_(" I recommend an immediate review of"))
1767 prout(_(" the Captain's psychological profile.\""))
1770 return delta.bearing()
1773 "Launch photon torpedo."
1774 course = [0.0] * MAXBURST
1776 if damaged(DPHOTON):
1777 prout(_("Photon tubes damaged."))
1781 prout(_("No torpedoes left."))
1784 # First, get torpedo count
1787 if scanner.token == IHALPHA:
1790 elif scanner.token == IHEOL or not scanner.waiting():
1791 prout(_("%d torpedoes left.") % game.torps)
1793 proutn(_("Number of torpedoes to fire- "))
1794 continue # Go back around to get a number
1795 else: # key == IHREAL
1797 if n <= 0: # abort command
1802 prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
1805 scanner.chew() # User requested more torps than available
1806 continue # Go back around
1807 break # All is good, go to next stage
1811 key = scanner.next()
1812 if i==0 and key == IHEOL:
1813 break; # no coordinate waiting, we will try prompting
1814 if i==1 and key == IHEOL:
1815 # direct all torpedoes at one target
1817 target.append(targets[0])
1818 course.append(course[0])
1822 target.append(scanner.getcoord())
1823 if target[-1] == None:
1825 course.append(targetcheck(target[1]))
1826 if course[i] == None:
1830 # prompt for each one
1832 proutn(_("Target sector for torpedo number %d- ") % (i+1))
1834 target.append(scanner.getcoord())
1835 if target[-1] == None:
1837 course.append(targetcheck(target[-1]))
1838 if course[-1] == None:
1841 # Loop for moving <n> torpedoes
1843 if game.condition != "docked":
1845 dispersion = (randreal()+randreal())*0.5 -0.5
1846 if math.fabs(dispersion) >= 0.47:
1848 dispersion *= randreal(1.2, 2.2)
1850 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1852 prouts(_("***TORPEDO MISFIRES."))
1855 prout(_(" Remainder of burst aborted."))
1857 prout(_("***Photon tubes damaged by misfire."))
1858 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1860 if game.shldup or game.condition == "docked":
1861 dispersion *= 1.0 + 0.0001*game.shield
1862 torpedo(course[i], dispersion, origin=game.sector, number=i, nburst=n)
1863 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1865 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1869 "Check for phasers overheating."
1871 checkburn = (rpow-1500.0)*0.00038
1872 if withprob(checkburn):
1873 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1874 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1876 def checkshctrl(rpow):
1877 "Check shield control."
1880 prout(_("Shields lowered."))
1882 # Something bad has happened
1883 prouts(_("***RED ALERT! RED ALERT!"))
1885 hit = rpow*game.shield/game.inshld
1886 game.energy -= rpow+hit*0.8
1887 game.shield -= hit*0.2
1888 if game.energy <= 0.0:
1889 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1894 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1896 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1897 icas = randrange(int(hit*0.012))
1902 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1903 prout(_(" %d casualties so far.\"") % icas)
1905 game.state.crew -= icas
1907 prout(_("Phaser energy dispersed by shields."))
1908 prout(_("Enemy unaffected."))
1913 "Register a phaser hit on Klingons and Romulans."
1914 nenhr2 = len(game.enemies); kk=0
1917 for (k, wham) in enumerate(hits):
1920 dustfac = randreal(0.9, 1.0)
1921 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1922 kpini = game.enemies[kk].kpower
1923 kp = math.fabs(kpini)
1924 if PHASEFAC*hit < kp:
1926 if game.enemies[kk].kpower < 0:
1927 game.enemies[kk].kpower -= -kp
1929 game.enemies[kk].kpower -= kp
1930 kpow = game.enemies[kk].kpower
1931 w = game.enemies[kk].kloc
1933 if not damaged(DSRSENS):
1935 proutn(_("%d unit hit on ") % int(hit))
1937 proutn(_("Very small hit on "))
1938 ienm = game.quad[w.x][w.y]
1941 crmena(False, ienm, "sector", w)
1945 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1949 kk -= 1 # don't do the increment
1951 else: # decide whether or not to emasculate klingon
1952 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
1953 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
1954 prout(_(" has just lost its firepower.\""))
1955 game.enemies[kk].kpower = -kpow
1960 "Fire phasers at bad guys."
1962 kz = 0; k = 1; irec=0 # Cheating inhibitor
1963 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
1967 # SR sensors and Computer are needed for automode
1968 if damaged(DSRSENS) or damaged(DCOMPTR):
1970 if game.condition == "docked":
1971 prout(_("Phasers can't be fired through base shields."))
1974 if damaged(DPHASER):
1975 prout(_("Phaser control damaged."))
1979 if damaged(DSHCTRL):
1980 prout(_("High speed shield control damaged."))
1983 if game.energy <= 200.0:
1984 prout(_("Insufficient energy to activate high-speed shield control."))
1987 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
1989 # Original code so convoluted, I re-did it all
1990 # (That was Tom Almy talking about the C code, I think -- ESR)
1991 while automode=="NOTSET":
1994 if scanner.sees("manual"):
1995 if len(game.enemies)==0:
1996 prout(_("There is no enemy present to select."))
1999 automode="AUTOMATIC"
2002 key = scanner.next()
2003 elif scanner.sees("automatic"):
2004 if (not itarg) and len(game.enemies) != 0:
2005 automode = "FORCEMAN"
2007 if len(game.enemies)==0:
2008 prout(_("Energy will be expended into space."))
2009 automode = "AUTOMATIC"
2010 key = scanner.next()
2011 elif scanner.sees("no"):
2017 if len(game.enemies)==0:
2018 prout(_("Energy will be expended into space."))
2019 automode = "AUTOMATIC"
2021 automode = "FORCEMAN"
2023 automode = "AUTOMATIC"
2026 if len(game.enemies)==0:
2027 prout(_("Energy will be expended into space."))
2028 automode = "AUTOMATIC"
2030 automode = "FORCEMAN"
2032 proutn(_("Manual or automatic? "))
2037 if automode == "AUTOMATIC":
2038 if key == IHALPHA and scanner.sees("no"):
2040 key = scanner.next()
2041 if key != IHREAL and len(game.enemies) != 0:
2042 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2047 for i in range(len(game.enemies)):
2048 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2050 proutn(_("%d units required. ") % irec)
2052 proutn(_("Units to fire= "))
2053 key = scanner.next()
2058 proutn(_("Energy available= %.2f") % avail)
2061 if not rpow > avail:
2068 if key == IHALPHA and scanner.sees("no"):
2071 game.energy -= 200; # Go and do it!
2072 if checkshctrl(rpow):
2077 if len(game.enemies):
2080 for i in range(len(game.enemies)):
2084 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2085 over = randreal(1.01, 1.06) * hits[i]
2087 powrem -= hits[i] + over
2088 if powrem <= 0 and temp < hits[i]:
2097 if extra > 0 and not game.alldone:
2099 proutn(_("*** Tholian web absorbs "))
2100 if len(game.enemies)>0:
2101 proutn(_("excess "))
2102 prout(_("phaser energy."))
2104 prout(_("%d expended on empty space.") % int(extra))
2105 elif automode == "FORCEMAN":
2108 if damaged(DCOMPTR):
2109 prout(_("Battle computer damaged, manual fire only."))
2112 prouts(_("---WORKING---"))
2114 prout(_("Short-range-sensors-damaged"))
2115 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2116 prout(_("Manual-fire-must-be-used"))
2118 elif automode == "MANUAL":
2120 for k in range(len(game.enemies)):
2121 aim = game.enemies[k].kloc
2122 ienm = game.quad[aim.x][aim.y]
2124 proutn(_("Energy available= %.2f") % (avail-0.006))
2128 if damaged(DSRSENS) and \
2129 not game.sector.distance(aim)<2**0.5 and ienm in (IHC, IHS):
2131 prout(_(" can't be located without short range scan."))
2134 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2139 if itarg and k > kz:
2140 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2143 if not damaged(DCOMPTR):
2148 proutn(_("units to fire at "))
2149 crmena(False, ienm, "sector", aim)
2151 key = scanner.next()
2152 if key == IHALPHA and scanner.sees("no"):
2154 key = scanner.next()
2160 if k==1: # Let me say I'm baffled by this
2163 if scanner.real < 0:
2167 hits[k] = scanner.real
2168 rpow += scanner.real
2169 # If total requested is too much, inform and start over
2171 prout(_("Available energy exceeded -- try again."))
2174 key = scanner.next(); # scan for next value
2177 # zero energy -- abort
2180 if key == IHALPHA and scanner.sees("no"):
2185 game.energy -= 200.0
2186 if checkshctrl(rpow):
2190 # Say shield raised or malfunction, if necessary
2197 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2198 prouts(_(" CLICK CLICK POP . . ."))
2199 prout(_(" No response, sir!"))
2202 prout(_("Shields raised."))
2207 # Code from events,c begins here.
2209 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2210 # event of each type active at any given time. Mostly these means we can
2211 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2212 # BSD Trek, from which we swiped the idea, can have up to 5.
2214 def unschedule(evtype):
2215 "Remove an event from the schedule."
2216 game.future[evtype].date = FOREVER
2217 return game.future[evtype]
2219 def is_scheduled(evtype):
2220 "Is an event of specified type scheduled."
2221 return game.future[evtype].date != FOREVER
2223 def scheduled(evtype):
2224 "When will this event happen?"
2225 return game.future[evtype].date
2227 def schedule(evtype, offset):
2228 "Schedule an event of specified type."
2229 game.future[evtype].date = game.state.date + offset
2230 return game.future[evtype]
2232 def postpone(evtype, offset):
2233 "Postpone a scheduled event."
2234 game.future[evtype].date += offset
2237 "Rest period is interrupted by event."
2240 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2242 game.resting = False
2248 "Run through the event queue looking for things to do."
2250 fintim = game.state.date + game.optime; yank=0
2251 ictbeam = False; istract = False
2252 w = coord(); hold = coord()
2253 ev = event(); ev2 = event()
2255 def tractorbeam(yank):
2256 "Tractor-beaming cases merge here."
2258 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2262 prout(_(" caught in long range tractor beam--"))
2263 # If Kirk & Co. screwing around on planet, handle
2264 atover(True) # atover(true) is Grab
2267 if game.icraft: # Caught in Galileo?
2270 # Check to see if shuttle is aboard
2271 if game.iscraft == "offship":
2274 prout(_("Galileo, left on the planet surface, is captured"))
2275 prout(_("by aliens and made into a flying McDonald's."))
2276 game.damage[DSHUTTL] = -10
2277 game.iscraft = "removed"
2279 prout(_("Galileo, left on the planet surface, is well hidden."))
2281 game.quadrant = game.state.kscmdr
2283 game.quadrant = game.state.kcmdr[i]
2284 game.sector = randplace(QUADSIZE)
2286 prout(_(" is pulled to Quadrant %s, Sector %s") \
2287 % (game.quadrant, game.sector))
2289 prout(_("(Remainder of rest/repair period cancelled.)"))
2290 game.resting = False
2292 if not damaged(DSHIELD) and game.shield > 0:
2293 doshield(shraise=True) # raise shields
2294 game.shldchg = False
2296 prout(_("(Shields not currently useable.)"))
2298 # Adjust finish time to time of tractor beaming
2299 fintim = game.state.date+game.optime
2300 attack(torps_ok=False)
2301 if not game.state.kcmdr:
2304 schedule(FTBEAM, game.optime+expran(1.5*game.intime/len(game.state.kcmdr)))
2307 "Code merges here for any commander destroying a starbase."
2308 # Not perfect, but will have to do
2309 # Handle case where base is in same quadrant as starship
2310 if game.battle == game.quadrant:
2311 game.state.chart[game.battle.x][game.battle.y].starbase = False
2312 game.quad[game.base.x][game.base.y] = IHDOT
2313 game.base.invalidate()
2316 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2317 elif game.state.baseq and communicating():
2318 # Get word via subspace radio
2321 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2322 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2324 prout(_("the Klingon Super-Commander"))
2326 prout(_("a Klingon Commander"))
2327 game.state.chart[game.battle.x][game.battle.y].starbase = False
2328 # Remove Starbase from galaxy
2329 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2330 game.state.baseq = filter(lambda x: x != game.battle, game.state.baseq)
2332 # reinstate a commander's base attack
2336 game.battle.invalidate()
2338 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2339 for i in range(1, NEVENTS):
2340 if i == FSNOVA: proutn("=== Supernova ")
2341 elif i == FTBEAM: proutn("=== T Beam ")
2342 elif i == FSNAP: proutn("=== Snapshot ")
2343 elif i == FBATTAK: proutn("=== Base Attack ")
2344 elif i == FCDBAS: proutn("=== Base Destroy ")
2345 elif i == FSCMOVE: proutn("=== SC Move ")
2346 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2347 elif i == FDSPROB: proutn("=== Probe Move ")
2348 elif i == FDISTR: proutn("=== Distress Call ")
2349 elif i == FENSLV: proutn("=== Enslavement ")
2350 elif i == FREPRO: proutn("=== Klingon Build ")
2352 prout("%.2f" % (scheduled(i)))
2355 radio_was_broken = damaged(DRADIO)
2358 # Select earliest extraneous event, evcode==0 if no events
2363 for l in range(1, NEVENTS):
2364 if game.future[l].date < datemin:
2367 prout("== Event %d fires" % evcode)
2368 datemin = game.future[l].date
2369 xtime = datemin-game.state.date
2370 game.state.date = datemin
2371 # Decrement Federation resources and recompute remaining time
2372 game.state.remres -= (game.state.remkl+4*len(game.state.kcmdr))*xtime
2374 if game.state.remtime <=0:
2377 # Any crew left alive?
2378 if game.state.crew <=0:
2381 # Is life support adequate?
2382 if damaged(DLIFSUP) and game.condition != "docked":
2383 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2386 game.lsupres -= xtime
2387 if game.damage[DLIFSUP] <= xtime:
2388 game.lsupres = game.inlsr
2391 if game.condition == "docked":
2392 repair /= game.docfac
2393 # Don't fix Deathray here
2394 for l in range(NDEVICES):
2395 if game.damage[l] > 0.0 and l != DDRAY:
2396 if game.damage[l]-repair > 0.0:
2397 game.damage[l] -= repair
2399 game.damage[l] = 0.0
2400 # If radio repaired, update star chart and attack reports
2401 if radio_was_broken and not damaged(DRADIO):
2402 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2403 prout(_(" surveillance reports are coming in."))
2405 if not game.iseenit:
2409 prout(_(" The star chart is now up to date.\""))
2411 # Cause extraneous event EVCODE to occur
2412 game.optime -= xtime
2413 if evcode == FSNOVA: # Supernova
2416 schedule(FSNOVA, expran(0.5*game.intime))
2417 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2419 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2420 if game.state.nscrem == 0 or \
2421 ictbeam or istract or \
2422 game.condition=="docked" or game.isatb==1 or game.iscate:
2424 if game.ientesc or \
2425 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2426 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2427 (damaged(DSHIELD) and \
2428 (game.energy < 2500 or damaged(DPHASER)) and \
2429 (game.torps < 5 or damaged(DPHOTON))):
2431 istract = ictbeam = True
2432 tractorbeam((game.state.kscmdr-game.quadrant).distance())
2435 elif evcode == FTBEAM: # Tractor beam
2436 if not game.state.kcmdr:
2439 i = randrange(len(game.state.kcmdr))
2440 yank = (game.state.kcmdr[i]-game.quadrant).distance()
2441 if istract or game.condition == "docked" or yank == 0:
2442 # Drats! Have to reschedule
2444 game.optime + expran(1.5*game.intime/len(game.state.kcmdr)))
2448 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2449 game.snapsht = copy.deepcopy(game.state)
2450 game.state.snap = True
2451 schedule(FSNAP, expran(0.5 * game.intime))
2452 elif evcode == FBATTAK: # Commander attacks starbase
2453 if not game.state.kcmdr or not game.state.baseq:
2459 for ibq in game.state.baseq:
2460 for cmdr in game.state.kcmdr:
2461 if ibq == cmdr and ibq != game.quadrant and ibq != game.state.kscmdr:
2464 # no match found -- try later
2465 schedule(FBATTAK, expran(0.3*game.intime))
2468 # commander + starbase combination found -- launch attack
2469 game.battle = game.state.baseq[j]
2470 schedule(FCDBAS, randreal(1.0, 4.0))
2471 if game.isatb: # extra time if SC already attacking
2472 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2473 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2474 game.iseenit = False
2475 if not communicating():
2476 continue # No warning :-(
2480 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2481 prout(_(" reports that it is under attack and that it can"))
2482 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2485 elif evcode == FSCDBAS: # Supercommander destroys base
2488 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2489 continue # WAS RETURN!
2491 game.battle = game.state.kscmdr
2493 elif evcode == FCDBAS: # Commander succeeds in destroying base
2496 if not game.state.baseq() \
2497 or not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2498 game.battle.invalidate()
2500 # find the lucky pair
2501 for cmdr in game.state.kcmdr:
2502 if cmdr == game.battle:
2505 # No action to take after all
2508 elif evcode == FSCMOVE: # Supercommander moves
2509 schedule(FSCMOVE, 0.2777)
2510 if not game.ientesc and not istract and game.isatb != 1 and \
2511 (not game.iscate or not game.justin):
2513 elif evcode == FDSPROB: # Move deep space probe
2514 schedule(FDSPROB, 0.01)
2515 game.probex += game.probeinx
2516 game.probey += game.probeiny
2517 i = (int)(game.probex/QUADSIZE +0.05)
2518 j = (int)(game.probey/QUADSIZE + 0.05)
2519 if game.probec.x != i or game.probec.y != j:
2522 if not VALID_QUADRANT(i, j) or \
2523 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2524 # Left galaxy or ran into supernova
2528 proutn(_("Lt. Uhura- \"The deep space probe "))
2529 if not VALID_QUADRANT(j, i):
2530 proutn(_("has left the galaxy"))
2532 proutn(_("is no longer transmitting"))
2536 if not communicating():
2539 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2540 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2541 # Update star chart if Radio is working or have access to radio
2543 chp = game.state.chart[game.probec.x][game.probec.y]
2544 chp.klingons = pdest.klingons
2545 chp.starbase = pdest.starbase
2546 chp.stars = pdest.stars
2547 pdest.charted = True
2548 game.proben -= 1 # One less to travel
2549 if game.proben == 0 and game.isarmed and pdest.stars:
2550 # lets blow the sucker!
2551 supernova(True, game.probec)
2553 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2555 elif evcode == FDISTR: # inhabited system issues distress call
2557 # try a whole bunch of times to find something suitable
2558 for i in range(100):
2559 # need a quadrant which is not the current one,
2560 # which has some stars which are inhabited and
2561 # not already under attack, which is not
2562 # supernova'ed, and which has some Klingons in it
2563 w = randplace(GALSIZE)
2564 q = game.state.galaxy[w.x][w.y]
2565 if not (game.quadrant == w or q.planet == None or \
2566 not q.planet.inhabited or \
2567 q.supernova or q.status!="secure" or q.klingons<=0):
2570 # can't seem to find one; ignore this call
2572 prout("=== Couldn't find location for distress event.")
2574 # got one!! Schedule its enslavement
2575 ev = schedule(FENSLV, expran(game.intime))
2577 q.status = distressed
2579 # tell the captain about it if we can
2581 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2583 prout(_("by a Klingon invasion fleet."))
2586 elif evcode == FENSLV: # starsystem is enslaved
2587 ev = unschedule(FENSLV)
2588 # see if current distress call still active
2589 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2593 q.status = "enslaved"
2595 # play stork and schedule the first baby
2596 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2597 ev2.quadrant = ev.quadrant
2599 # report the disaster if we can
2601 prout(_("Uhura- We've lost contact with starsystem %s") % \
2603 prout(_("in Quadrant %s.\n") % ev.quadrant)
2604 elif evcode == FREPRO: # Klingon reproduces
2605 # If we ever switch to a real event queue, we'll need to
2606 # explicitly retrieve and restore the x and y.
2607 ev = schedule(FREPRO, expran(1.0 * game.intime))
2608 # see if current distress call still active
2609 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2613 if game.state.remkl >=MAXKLGAME:
2614 continue # full right now
2615 # reproduce one Klingon
2617 if game.klhere >= MAXKLQUAD:
2619 # this quadrant not ok, pick an adjacent one
2620 for i in range(w.x - 1, w.x + 2):
2621 for j in range(w.y - 1, w.y + 2):
2622 if not VALID_QUADRANT(i, j):
2624 q = game.state.galaxy[w.x][w.y]
2625 # check for this quad ok (not full & no snova)
2626 if q.klingons >= MAXKLQUAD or q.supernova:
2630 continue # search for eligible quadrant failed
2635 game.state.remkl += 1
2637 if game.quadrant == w:
2639 game.enemies.append(newkling())
2640 # recompute time left
2642 # report the disaster if we can
2644 if game.quadrant == w:
2645 prout(_("Spock- sensors indicate the Klingons have"))
2646 prout(_("launched a warship from %s.") % q.planet)
2648 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2649 if q.planet != None:
2650 proutn(_("near %s") % q.planet)
2651 prout(_("in Quadrant %s.") % w)
2657 key = scanner.next()
2660 proutn(_("How long? "))
2665 origTime = delay = scanner.real
2668 if delay >= game.state.remtime or len(game.enemies) != 0:
2669 proutn(_("Are you sure? "))
2672 # Alternate resting periods (events) with attacks
2676 game.resting = False
2677 if not game.resting:
2678 prout(_("%d stardates left.") % int(game.state.remtime))
2680 temp = game.optime = delay
2681 if len(game.enemies):
2682 rtime = randreal(1.0, 2.0)
2686 if game.optime < delay:
2687 attack(torps_ok=False)
2695 # Repair Deathray if long rest at starbase
2696 if origTime-delay >= 9.99 and game.condition == "docked":
2697 game.damage[DDRAY] = 0.0
2698 # leave if quadrant supernovas
2699 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2701 game.resting = False
2704 # A nova occurs. It is the result of having a star hit with a
2705 # photon torpedo, or possibly of a probe warhead going off.
2706 # Stars that go nova cause stars which surround them to undergo
2707 # the same probabilistic process. Klingons next to them are
2708 # destroyed. And if the starship is next to it, it gets zapped.
2709 # If the zap is too much, it gets destroyed.
2713 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2714 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2716 # Wow! We've supernova'ed
2717 supernova(False, nov)
2719 # handle initial nova
2720 game.quad[nov.x][nov.y] = IHDOT
2721 crmena(False, IHSTAR, "sector", nov)
2723 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2724 game.state.starkl += 1
2725 # Set up queue to recursively trigger adjacent stars
2731 for offset.x in range(-1, 1+1):
2732 for offset.y in range(-1, 1+1):
2733 if offset.y==0 and offset.x==0:
2735 neighbor = start + offset
2736 if not VALID_SECTOR(neighbor.y, neighbor.x):
2738 iquad = game.quad[neighbor.x][neighbor.y]
2739 # Empty space ends reaction
2740 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2742 elif iquad == IHSTAR: # Affect another star
2744 # This star supernovas
2748 hits.append(neighbor)
2749 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2750 game.state.starkl += 1
2751 crmena(True, IHSTAR, "sector", neighbor)
2753 game.quad[neighbor.x][neighbor.y] = IHDOT
2755 elif iquad in (IHP, IHW): # Destroy planet
2756 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2758 game.state.nplankl += 1
2760 game.state.worldkl += 1
2761 crmena(True, iquad, "sector", neighbor)
2762 prout(_(" destroyed."))
2763 game.iplnet.pclass = "destroyed"
2765 game.plnet.invalidate()
2769 game.quad[neighbor.x][neighbor.y] = IHDOT
2770 elif iquad == IHB: # Destroy base
2771 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2772 game.state.baseq = filter(lambda x: x!= game.quadrant, game.state.baseq)
2773 game.base.invalidate()
2774 game.state.basekl += 1
2776 crmena(True, IHB, "sector", neighbor)
2777 prout(_(" destroyed."))
2778 game.quad[neighbor.x][neighbor.y] = IHDOT
2779 elif iquad in (IHE, IHF): # Buffet ship
2780 prout(_("***Starship buffeted by nova."))
2782 if game.shield >= 2000.0:
2783 game.shield -= 2000.0
2785 diff = 2000.0 - game.shield
2789 prout(_("***Shields knocked out."))
2790 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2792 game.energy -= 2000.0
2793 if game.energy <= 0:
2796 # add in course nova contributes to kicking starship
2797 bump += (game.sector-hits[mm]).sgn()
2798 elif iquad == IHK: # kill klingon
2799 deadkl(neighbor, iquad, neighbor)
2800 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2801 for ll in range(len(game.enemies)):
2802 if game.enemies[ll].kloc == neighbor:
2804 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2805 if game.enemies[ll].kpower <= 0.0:
2806 deadkl(neighbor, iquad, neighbor)
2808 newc = neighbor + neighbor - hits[mm]
2809 crmena(True, iquad, "sector", neighbor)
2810 proutn(_(" damaged"))
2811 if not VALID_SECTOR(newc.x, newc.y):
2812 # can't leave quadrant
2815 iquad1 = game.quad[newc.x][newc.y]
2816 if iquad1 == IHBLANK:
2817 proutn(_(", blasted into "))
2818 crmena(False, IHBLANK, "sector", newc)
2820 deadkl(neighbor, iquad, newc)
2823 # can't move into something else
2826 proutn(_(", buffeted to Sector %s") % newc)
2827 game.quad[neighbor.x][neighbor.y] = IHDOT
2828 game.quad[newc.x][newc.y] = iquad
2829 game.enemies[ll].move(newc)
2830 # Starship affected by nova -- kick it away.
2831 game.dist = kount*0.1
2832 game.direc = course[3*(bump.x+1)+bump.y+2]
2833 if game.direc == 0.0:
2835 if game.dist == 0.0:
2837 game.optime = 10.0*game.dist/16.0
2839 prout(_("Force of nova displaces starship."))
2840 imove(novapush=True)
2841 game.optime = 10.0*game.dist/16.0
2844 def supernova(induced, w=None):
2845 "Star goes supernova."
2852 # Scheduled supernova -- select star
2853 # logic changed here so that we won't favor quadrants in top
2855 for nq.x in range(GALSIZE):
2856 for nq.y in range(GALSIZE):
2857 stars += game.state.galaxy[nq.x][nq.y].stars
2859 return # nothing to supernova exists
2860 num = randrange(stars) + 1
2861 for nq.x in range(GALSIZE):
2862 for nq.y in range(GALSIZE):
2863 num -= game.state.galaxy[nq.x][nq.y].stars
2869 proutn("=== Super nova here?")
2872 if not nq == game.quadrant or game.justin:
2873 # it isn't here, or we just entered (treat as enroute)
2876 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2877 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2880 # we are in the quadrant!
2881 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2882 for ns.x in range(QUADSIZE):
2883 for ns.y in range(QUADSIZE):
2884 if game.quad[ns.x][ns.y]==IHSTAR:
2891 prouts(_("***RED ALERT! RED ALERT!"))
2893 prout(_("***Incipient supernova detected at Sector %s") % ns)
2894 if (ns.x-game.sector.x)**2 + (ns.y-game.sector.y)**2 <= 2.1:
2895 proutn(_("Emergency override attempts t"))
2896 prouts("***************")
2900 # destroy any Klingons in supernovaed quadrant
2901 kldead = game.state.galaxy[nq.x][nq.y].klingons
2902 game.state.galaxy[nq.x][nq.y].klingons = 0
2903 if nq == game.state.kscmdr:
2904 # did in the Supercommander!
2905 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2909 survivors = filter(lambda w: w != nq, game.state.kcmdr)
2910 comkills = len(game.state.kcmdr) - len(survivors)
2911 game.state.kcmdr = survivors
2913 if not game.state.kcmdr:
2915 game.state.remkl -= kldead
2916 # destroy Romulans and planets in supernovaed quadrant
2917 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
2918 game.state.galaxy[nq.x][nq.y].romulans = 0
2919 game.state.nromrem -= nrmdead
2921 for loop in range(game.inplan):
2922 if game.state.planets[loop].quadrant == nq:
2923 game.state.planets[loop].pclass = "destroyed"
2925 # Destroy any base in supernovaed quadrant
2926 game.state.baseq = filter(lambda x: x != nq, game.state.baseq)
2927 # If starship caused supernova, tally up destruction
2929 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
2930 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
2931 game.state.nplankl += npdead
2932 # mark supernova in galaxy and in star chart
2933 if game.quadrant == nq or communicating():
2934 game.state.galaxy[nq.x][nq.y].supernova = True
2935 # If supernova destroys last Klingons give special message
2936 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0 and not nq == game.quadrant:
2939 prout(_("Lucky you!"))
2940 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
2943 # if some Klingons remain, continue or die in supernova
2948 # Code from finish.c ends here.
2951 "Self-destruct maneuver. Finish with a BANG!"
2953 if damaged(DCOMPTR):
2954 prout(_("Computer damaged; cannot execute destruct sequence."))
2956 prouts(_("---WORKING---")); skip(1)
2957 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
2958 prouts(" 10"); skip(1)
2959 prouts(" 9"); skip(1)
2960 prouts(" 8"); skip(1)
2961 prouts(" 7"); skip(1)
2962 prouts(" 6"); skip(1)
2964 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
2966 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
2968 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
2972 if game.passwd != scanner.token:
2973 prouts(_("PASSWORD-REJECTED;"))
2975 prouts(_("CONTINUITY-EFFECTED"))
2978 prouts(_("PASSWORD-ACCEPTED")); skip(1)
2979 prouts(" 5"); skip(1)
2980 prouts(" 4"); skip(1)
2981 prouts(" 3"); skip(1)
2982 prouts(" 2"); skip(1)
2983 prouts(" 1"); skip(1)
2985 prouts(_("GOODBYE-CRUEL-WORLD"))
2993 prouts(_("********* Entropy of "))
2995 prouts(_(" maximized *********"))
2999 if len(game.enemies) != 0:
3000 whammo = 25.0 * game.energy
3002 while l <= len(game.enemies):
3003 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3004 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3009 "Compute our rate of kils over time."
3010 elapsed = game.state.date - game.indate
3011 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3014 starting = (game.inkling + game.incom + game.inscom)
3015 remaining = (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)
3016 return (starting - remaining)/elapsed
3020 badpt = 5.0*game.state.starkl + \
3022 10.0*game.state.nplankl + \
3023 300*game.state.nworldkl + \
3025 100.0*game.state.basekl +\
3027 if game.ship == IHF:
3029 elif game.ship == None:
3034 # end the game, with appropriate notfications
3038 prout(_("It is stardate %.1f.") % game.state.date)
3040 if ifin == FWON: # Game has been won
3041 if game.state.nromrem != 0:
3042 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3045 prout(_("You have smashed the Klingon invasion fleet and saved"))
3046 prout(_("the Federation."))
3051 badpt = 0.0 # Close enough!
3052 # killsPerDate >= RateMax
3053 if game.state.date-game.indate < 5.0 or \
3054 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3056 prout(_("In fact, you have done so well that Starfleet Command"))
3057 if game.skill == SKILL_NOVICE:
3058 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3059 elif game.skill == SKILL_FAIR:
3060 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3061 elif game.skill == SKILL_GOOD:
3062 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3063 elif game.skill == SKILL_EXPERT:
3064 prout(_("promotes you to Commodore Emeritus."))
3066 prout(_("Now that you think you're really good, try playing"))
3067 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3068 elif game.skill == SKILL_EMERITUS:
3070 proutn(_("Computer- "))
3071 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3073 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3075 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3077 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3079 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3081 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3083 prout(_("Now you can retire and write your own Star Trek game!"))
3085 elif game.skill >= SKILL_EXPERT:
3086 if game.thawed and not idebug:
3087 prout(_("You cannot get a citation, so..."))
3089 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3093 # Only grant long life if alive (original didn't!)
3095 prout(_("LIVE LONG AND PROSPER."))
3100 elif ifin == FDEPLETE: # Federation Resources Depleted
3101 prout(_("Your time has run out and the Federation has been"))
3102 prout(_("conquered. Your starship is now Klingon property,"))
3103 prout(_("and you are put on trial as a war criminal. On the"))
3104 proutn(_("basis of your record, you are "))
3105 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3106 prout(_("acquitted."))
3108 prout(_("LIVE LONG AND PROSPER."))
3110 prout(_("found guilty and"))
3111 prout(_("sentenced to death by slow torture."))
3115 elif ifin == FLIFESUP:
3116 prout(_("Your life support reserves have run out, and"))
3117 prout(_("you die of thirst, starvation, and asphyxiation."))
3118 prout(_("Your starship is a derelict in space."))
3120 prout(_("Your energy supply is exhausted."))
3122 prout(_("Your starship is a derelict in space."))
3123 elif ifin == FBATTLE:
3126 prout(_(" has been destroyed in battle."))
3128 prout(_("Dulce et decorum est pro patria mori."))
3130 prout(_("You have made three attempts to cross the negative energy"))
3131 prout(_("barrier which surrounds the galaxy."))
3133 prout(_("Your navigation is abominable."))
3136 prout(_("Your starship has been destroyed by a nova."))
3137 prout(_("That was a great shot."))
3139 elif ifin == FSNOVAED:
3142 prout(_(" has been fried by a supernova."))
3143 prout(_("...Not even cinders remain..."))
3144 elif ifin == FABANDN:
3145 prout(_("You have been captured by the Klingons. If you still"))
3146 prout(_("had a starbase to be returned to, you would have been"))
3147 prout(_("repatriated and given another chance. Since you have"))
3148 prout(_("no starbases, you will be mercilessly tortured to death."))
3149 elif ifin == FDILITHIUM:
3150 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3151 elif ifin == FMATERIALIZE:
3152 prout(_("Starbase was unable to re-materialize your starship."))
3153 prout(_("Sic transit gloria mundi"))
3154 elif ifin == FPHASER:
3157 prout(_(" has been cremated by its own phasers."))
3159 prout(_("You and your landing party have been"))
3160 prout(_("converted to energy, disipating through space."))
3161 elif ifin == FMINING:
3162 prout(_("You are left with your landing party on"))
3163 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3165 prout(_("They are very fond of \"Captain Kirk\" soup."))
3167 proutn(_("Without your leadership, the "))
3169 prout(_(" is destroyed."))
3170 elif ifin == FDPLANET:
3171 prout(_("You and your mining party perish."))
3173 prout(_("That was a great shot."))
3176 prout(_("The Galileo is instantly annihilated by the supernova."))
3177 prout(_("You and your mining party are atomized."))
3179 proutn(_("Mr. Spock takes command of the "))
3182 prout(_("joins the Romulans, reigning terror on the Federation."))
3183 elif ifin == FPNOVA:
3184 prout(_("You and your mining party are atomized."))
3186 proutn(_("Mr. Spock takes command of the "))
3189 prout(_("joins the Romulans, reigning terror on the Federation."))
3190 elif ifin == FSTRACTOR:
3191 prout(_("The shuttle craft Galileo is also caught,"))
3192 prout(_("and breaks up under the strain."))
3194 prout(_("Your debris is scattered for millions of miles."))
3195 proutn(_("Without your leadership, the "))
3197 prout(_(" is destroyed."))
3199 prout(_("The mutants attack and kill Spock."))
3200 prout(_("Your ship is captured by Klingons, and"))
3201 prout(_("your crew is put on display in a Klingon zoo."))
3202 elif ifin == FTRIBBLE:
3203 prout(_("Tribbles consume all remaining water,"))
3204 prout(_("food, and oxygen on your ship."))
3206 prout(_("You die of thirst, starvation, and asphyxiation."))
3207 prout(_("Your starship is a derelict in space."))
3209 prout(_("Your ship is drawn to the center of the black hole."))
3210 prout(_("You are crushed into extremely dense matter."))
3212 prout(_("Your last crew member has died."))
3213 if game.ship == IHF:
3215 elif game.ship == IHE:
3218 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0:
3219 goodies = game.state.remres/game.inresor
3220 baddies = (game.state.remkl + 2.0*len(game.state.kcmdr))/(game.inkling+2.0*game.incom)
3221 if goodies/baddies >= randreal(1.0, 1.5):
3222 prout(_("As a result of your actions, a treaty with the Klingon"))
3223 prout(_("Empire has been signed. The terms of the treaty are"))
3224 if goodies/baddies >= randreal(3.0):
3225 prout(_("favorable to the Federation."))
3227 prout(_("Congratulations!"))
3229 prout(_("highly unfavorable to the Federation."))
3231 prout(_("The Federation will be destroyed."))
3233 prout(_("Since you took the last Klingon with you, you are a"))
3234 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3235 prout(_("statue in your memory. Rest in peace, and try not"))
3236 prout(_("to think about pigeons."))
3241 "Compute player's score."
3242 timused = game.state.date - game.indate
3244 if (timused == 0 or (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0) and timused < 5.0:
3246 perdate = killrate()
3247 ithperd = 500*perdate + 0.5
3250 iwon = 100*game.skill
3251 if game.ship == IHE:
3253 elif game.ship == IHF:
3257 if not game.gamewon:
3258 game.state.nromrem = 0 # None captured if no win
3259 iscore = 10*(game.inkling - game.state.remkl) \
3260 + 50*(game.incom - len(game.state.kcmdr)) \
3262 + 20*(game.inrom - game.state.nromrem) \
3263 + 200*(game.inscom - game.state.nscrem) \
3264 - game.state.nromrem \
3269 prout(_("Your score --"))
3270 if game.inrom - game.state.nromrem:
3271 prout(_("%6d Romulans destroyed %5d") %
3272 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3273 if game.state.nromrem:
3274 prout(_("%6d Romulans captured %5d") %
3275 (game.state.nromrem, game.state.nromrem))
3276 if game.inkling - game.state.remkl:
3277 prout(_("%6d ordinary Klingons destroyed %5d") %
3278 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3279 if game.incom - len(game.state.kcmdr):
3280 prout(_("%6d Klingon commanders destroyed %5d") %
3281 (game.incom - len(game.state.kcmdr), 50*(game.incom - len(game.state.kcmdr))))
3282 if game.inscom - game.state.nscrem:
3283 prout(_("%6d Super-Commander destroyed %5d") %
3284 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3286 prout(_("%6.2f Klingons per stardate %5d") %
3288 if game.state.starkl:
3289 prout(_("%6d stars destroyed by your action %5d") %
3290 (game.state.starkl, -5*game.state.starkl))
3291 if game.state.nplankl:
3292 prout(_("%6d planets destroyed by your action %5d") %
3293 (game.state.nplankl, -10*game.state.nplankl))
3294 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3295 prout(_("%6d inhabited planets destroyed by your action %5d") %
3296 (game.state.nplankl, -300*game.state.nworldkl))
3297 if game.state.basekl:
3298 prout(_("%6d bases destroyed by your action %5d") %
3299 (game.state.basekl, -100*game.state.basekl))
3301 prout(_("%6d calls for help from starbase %5d") %
3302 (game.nhelp, -45*game.nhelp))
3304 prout(_("%6d casualties incurred %5d") %
3305 (game.casual, -game.casual))
3307 prout(_("%6d crew abandoned in space %5d") %
3308 (game.abandoned, -3*game.abandoned))
3310 prout(_("%6d ship(s) lost or destroyed %5d") %
3311 (klship, -100*klship))
3313 prout(_("Penalty for getting yourself killed -200"))
3315 proutn(_("Bonus for winning "))
3316 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3317 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3318 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3319 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3320 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3321 prout(" %5d" % iwon)
3323 prout(_("TOTAL SCORE %5d") % iscore)
3326 "Emit winner's commemmorative plaque."
3329 proutn(_("File or device name for your plaque: "))
3332 fp = open(winner, "w")
3335 prout(_("Invalid name."))
3337 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3339 # The 38 below must be 64 for 132-column paper
3340 nskip = 38 - len(winner)/2
3341 fp.write("\n\n\n\n")
3342 # --------DRAW ENTERPRISE PICTURE.
3343 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3344 fp.write(" EEE E : : : E\n" )
3345 fp.write(" EE EEE E : : NCC-1701 : E\n")
3346 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3347 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3348 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3349 fp.write(" EEEEEEE EEEEE E E E E\n")
3350 fp.write(" EEE E E E E\n")
3351 fp.write(" E E E E\n")
3352 fp.write(" EEEEEEEEEEEEE E E\n")
3353 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3354 fp.write(" :E : EEEE E\n")
3355 fp.write(" .-E -:----- E\n")
3356 fp.write(" :E : E\n")
3357 fp.write(" EE : EEEEEEEE\n")
3358 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3360 fp.write(_(" U. S. S. ENTERPRISE\n"))
3361 fp.write("\n\n\n\n")
3362 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3364 fp.write(_(" Starfleet Command bestows to you\n"))
3366 fp.write("%*s%s\n\n" % (nskip, "", winner))
3367 fp.write(_(" the rank of\n\n"))
3368 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3370 if game.skill == SKILL_EXPERT:
3371 fp.write(_(" Expert level\n\n"))
3372 elif game.skill == SKILL_EMERITUS:
3373 fp.write(_("Emeritus level\n\n"))
3375 fp.write(_(" Cheat level\n\n"))
3376 timestring = ctime()
3377 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3378 (timestring+4, timestring+20, timestring+11))
3379 fp.write(_(" Your score: %d\n\n") % iscore)
3380 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3383 # Code from io.c begins here
3385 rows = linecount = 0 # for paging
3388 fullscreen_window = None
3389 srscan_window = None
3390 report_window = None
3391 status_window = None
3392 lrscan_window = None
3393 message_window = None
3394 prompt_window = None
3398 "Wrap up, either normally or due to signal"
3399 if game.options & OPTION_CURSES:
3406 sys.stdout.write('\n')
3412 #setlocale(LC_ALL, "")
3413 #bindtextdomain(PACKAGE, LOCALEDIR)
3414 #textdomain(PACKAGE)
3415 if atexit.register(outro):
3416 sys.stderr.write("Unable to register outro(), exiting...\n")
3418 if not (game.options & OPTION_CURSES):
3419 ln_env = os.getenv("LINES")
3425 stdscr = curses.initscr()
3430 curses.start_color()
3431 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3432 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3433 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3434 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3435 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3436 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3437 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3438 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3440 global fullscreen_window, srscan_window, report_window, status_window
3441 global lrscan_window, message_window, prompt_window
3442 (rows, columns) = stdscr.getmaxyx()
3443 fullscreen_window = stdscr
3444 srscan_window = curses.newwin(12, 25, 0, 0)
3445 report_window = curses.newwin(11, 0, 1, 25)
3446 status_window = curses.newwin(10, 0, 1, 39)
3447 lrscan_window = curses.newwin(5, 0, 0, 64)
3448 message_window = curses.newwin(0, 0, 12, 0)
3449 prompt_window = curses.newwin(1, 0, rows-2, 0)
3450 message_window.scrollok(True)
3451 setwnd(fullscreen_window)
3454 def textcolor(color):
3455 "Set text foreground color. Presently a stub."
3459 "Wrap up I/O. Presently a stub."
3463 "Wait for user action -- OK to do nothing if on a TTY"
3464 if game.options & OPTION_CURSES:
3469 if game.skill > SKILL_FAIR:
3470 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3472 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3476 if game.skill > SKILL_FAIR:
3477 prompt = _("[CONTINUE?]")
3479 prompt = _("[PRESS ENTER TO CONTINUE]")
3481 if game.options & OPTION_CURSES:
3483 setwnd(prompt_window)
3484 prompt_window.wclear()
3485 prompt_window.addstr(prompt)
3486 prompt_window.getstr()
3487 prompt_window.clear()
3488 prompt_window.refresh()
3489 setwnd(message_window)
3492 sys.stdout.write('\n')
3495 for j in range(rows):
3496 sys.stdout.write('\n')
3500 "Skip i lines. Pause game if this would cause a scrolling event."
3501 for dummy in range(i):
3502 if game.options & OPTION_CURSES:
3503 (y, x) = curwnd.getyx()
3504 (my, mx) = curwnd.getmaxyx()
3505 if curwnd == message_window and y >= my - 3:
3513 if rows and linecount >= rows:
3516 sys.stdout.write('\n')
3519 "Utter a line with no following line feed."
3520 if game.options & OPTION_CURSES:
3524 sys.stdout.write(line)
3534 if not replayfp or replayfp.closed: # Don't slow down replays
3537 if game.options & OPTION_CURSES:
3541 if not replayfp or replayfp.closed:
3545 "Get a line of input."
3546 if game.options & OPTION_CURSES:
3547 line = curwnd.getstr() + "\n"
3550 if replayfp and not replayfp.closed:
3552 line = replayfp.readline()
3555 prout("*** Replay finished")
3558 elif line[0] != "#":
3561 line = raw_input() + "\n"
3567 "Change windows -- OK for this to be a no-op in tty mode."
3569 if game.options & OPTION_CURSES:
3571 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3574 "Clear to end of line -- can be a no-op in tty mode"
3575 if game.options & OPTION_CURSES:
3580 "Clear screen -- can be a no-op in tty mode."
3582 if game.options & OPTION_CURSES:
3589 "Set highlight video, if this is reasonable."
3590 if game.options & OPTION_CURSES:
3591 curwnd.attron(curses.A_REVERSE)
3594 # Things past this point have policy implications.
3598 "Hook to be called after moving to redraw maps."
3599 if game.options & OPTION_CURSES:
3602 setwnd(srscan_window)
3606 setwnd(status_window)
3607 status_window.clear()
3608 status_window.move(0, 0)
3609 setwnd(report_window)
3610 report_window.clear()
3611 report_window.move(0, 0)
3613 setwnd(lrscan_window)
3614 lrscan_window.clear()
3615 lrscan_window.move(0, 0)
3616 lrscan(silent=False)
3618 def put_srscan_sym(w, sym):
3619 "Emit symbol for short-range scan."
3620 srscan_window.move(w.x+1, w.y*2+2)
3621 srscan_window.addch(sym)
3622 srscan_window.refresh()
3625 "Enemy fall down, go boom."
3626 if game.options & OPTION_CURSES:
3628 setwnd(srscan_window)
3629 srscan_window.attron(curses.A_REVERSE)
3630 put_srscan_sym(w, game.quad[w.x][w.y])
3634 srscan_window.attroff(curses.A_REVERSE)
3635 put_srscan_sym(w, game.quad[w.x][w.y])
3636 curses.delay_output(500)
3637 setwnd(message_window)
3640 "Sound and visual effects for teleportation."
3641 if game.options & OPTION_CURSES:
3643 setwnd(message_window)
3645 prouts(" . . . . . ")
3646 if game.options & OPTION_CURSES:
3647 #curses.delay_output(1000)
3651 def tracktorpedo(origin, w, step, i, n, iquad):
3652 "Torpedo-track animation."
3653 if not game.options & OPTION_CURSES:
3657 proutn(_("Track for %s torpedo number %d- ") % (game.quad[origin.x][origin.y],i+1))
3660 proutn(_("Torpedo track- "))
3661 elif step==4 or step==9:
3665 if not damaged(DSRSENS) or game.condition=="docked":
3666 if i != 0 and step == 1:
3669 if (iquad==IHDOT) or (iquad==IHBLANK):
3670 put_srscan_sym(w, '+')
3674 put_srscan_sym(w, iquad)
3676 curwnd.attron(curses.A_REVERSE)
3677 put_srscan_sym(w, iquad)
3681 curwnd.attroff(curses.A_REVERSE)
3682 put_srscan_sym(w, iquad)
3687 "Display the current galaxy chart."
3688 if game.options & OPTION_CURSES:
3689 setwnd(message_window)
3690 message_window.clear()
3692 if game.options & OPTION_TTY:
3697 def prstat(txt, data):
3699 if game.options & OPTION_CURSES:
3701 setwnd(status_window)
3703 proutn(" " * (NSYM - len(txt)))
3706 if game.options & OPTION_CURSES:
3707 setwnd(report_window)
3709 # Code from moving.c begins here
3711 def imove(novapush):
3712 "Movement execution for warp, impulse, supernova, and tractor-beam events."
3713 w = coord(); final = coord()
3716 def no_quad_change():
3717 # No quadrant change -- compute new average enemy distances
3718 game.quad[game.sector.x][game.sector.y] = game.ship
3720 for enemy in game.enemies:
3721 finald = (w-enemy.kloc).distance()
3722 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3723 enemy.kdist = finald
3724 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3725 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3726 attack(torps_ok=False)
3727 for enemy in game.enemies:
3728 enemy.kavgd = enemy.kdist
3731 setwnd(message_window)
3734 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3735 game.inorbit = False
3736 angle = ((15.0 - game.direc) * 0.5235988)
3737 deltax = -math.sin(angle)
3738 deltay = math.cos(angle)
3739 if math.fabs(deltax) > math.fabs(deltay):
3740 bigger = math.fabs(deltax)
3742 bigger = math.fabs(deltay)
3745 # If tractor beam is to occur, don't move full distance
3746 if game.state.date+game.optime >= scheduled(FTBEAM):
3748 game.condition = "red"
3749 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3750 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3751 # Move within the quadrant
3752 game.quad[game.sector.x][game.sector.y] = IHDOT
3755 n = int(10.0*game.dist*bigger+0.5)
3757 for m in range(1, n+1):
3762 if not VALID_SECTOR(w.x, w.y):
3763 # Leaving quadrant -- allow final enemy attack
3764 # Don't do it if being pushed by Nova
3765 if len(game.enemies) != 0 and not novapush:
3767 for enemy in game.enemies:
3768 finald = (w - enemy.kloc).distance()
3769 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3771 # Stas Sergeev added the condition
3772 # that attacks only happen if Klingons
3773 # are present and your skill is good.
3775 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3776 attack(torps_ok=False)
3779 # compute final position -- new quadrant and sector
3780 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3781 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3782 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3783 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3784 # check for edge of galaxy
3794 if w.x >= GALSIZE*QUADSIZE:
3795 w.x = (GALSIZE*QUADSIZE*2) - w.x
3797 if w.y >= GALSIZE*QUADSIZE:
3798 w.y = (GALSIZE*QUADSIZE*2) - w.y
3806 if game.nkinks == 3:
3807 # Three strikes -- you're out!
3811 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3812 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3813 prout(_("YOU WILL BE DESTROYED."))
3814 # Compute final position in new quadrant
3815 if trbeam: # Don't bother if we are to be beamed
3817 game.quadrant.x = w.x/QUADSIZE
3818 game.quadrant.y = w.y/QUADSIZE
3819 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3820 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3822 prout(_("Entering Quadrant %s.") % game.quadrant)
3823 game.quad[game.sector.x][game.sector.y] = game.ship
3825 if game.skill>SKILL_NOVICE:
3826 attack(torps_ok=False)
3828 iquad = game.quad[w.x][w.y]
3830 # object encountered in flight path
3831 stopegy = 50.0*game.dist/game.optime
3832 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3833 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3835 for enemy in game.enemies:
3836 if enemy.kloc == game.sector:
3838 collision(rammed=False, enemy=enemy)
3840 elif iquad == IHBLANK:
3842 prouts(_("***RED ALERT! RED ALERT!"))
3846 proutn(_(" pulled into black hole at Sector %s") % w)
3848 # Getting pulled into a black hole was certain
3849 # death in Almy's original. Stas Sergeev added a
3850 # possibility that you'll get timewarped instead.
3853 for m in range(NDEVICES):
3854 if game.damage[m]>0:
3856 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3857 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3867 prout(_(" encounters Tholian web at %s;") % w)
3869 prout(_(" blocked by object at %s;") % w)
3870 proutn(_("Emergency stop required "))
3871 prout(_("%2d units of energy.") % int(stopegy))
3872 game.energy -= stopegy
3873 final.x = int(round(deltax))
3874 final.y = int(round(deltay))
3876 if game.energy <= 0:
3882 game.dist = (game.sector - w).distance() / (QUADSIZE * 1.0)
3889 "Dock our ship at a starbase."
3891 if game.condition == "docked" and verbose:
3892 prout(_("Already docked."))
3895 prout(_("You must first leave standard orbit."))
3897 if not game.base.is_valid() or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
3899 prout(_(" not adjacent to base."))
3901 game.condition = "docked"
3905 if game.energy < game.inenrg:
3906 game.energy = game.inenrg
3907 game.shield = game.inshld
3908 game.torps = game.intorps
3909 game.lsupres = game.inlsr
3910 game.state.crew = FULLCREW
3911 if not damaged(DRADIO) and \
3912 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
3913 # get attack report from base
3914 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
3918 # This program originally required input in terms of a (clock)
3919 # direction and distance. Somewhere in history, it was changed to
3920 # cartesian coordinates. So we need to convert. Probably
3921 # "manual" input should still be done this way -- it's a real
3922 # pain if the computer isn't working! Manual mode is still confusing
3923 # because it involves giving x and y motions, yet the coordinates
3924 # are always displayed y - x, where +y is downward!
3926 def getcourse(isprobe, akey):
3927 "Get a course and distance from the user."
3929 dquad = copy.copy(game.quadrant)
3930 navmode = "unspecified"
3934 if game.landed and not isprobe:
3935 prout(_("Dummy! You can't leave standard orbit until you"))
3936 proutn(_("are back aboard the ship."))
3939 while navmode == "unspecified":
3940 if damaged(DNAVSYS):
3942 prout(_("Computer damaged; manual navigation only"))
3944 prout(_("Computer damaged; manual movement only"))
3949 if isprobe and akey != -1:
3950 # For probe launch, use pre-scanned value first time
3954 key = scanner.next()
3956 proutn(_("Manual or automatic- "))
3959 elif key == IHALPHA:
3960 if scanner.sees("manual"):
3962 key = scanner.next()
3964 elif scanner.sees("automatic"):
3965 navmode = "automatic"
3966 key = scanner.next()
3974 prout(_("(Manual navigation assumed.)"))
3976 prout(_("(Manual movement assumed.)"))
3979 if navmode == "automatic":
3982 proutn(_("Target quadrant or quadrant§or- "))
3984 proutn(_("Destination sector or quadrant§or- "))
3987 key = scanner.next()
3991 xi = int(round(scanner.real))-1
3992 key = scanner.next()
3996 xj = int(round(scanner.real))-1
3997 key = scanner.next()
3999 # both quadrant and sector specified
4000 xk = int(round(scanner.real))-1
4001 key = scanner.next()
4005 xl = int(round(scanner.real))-1
4011 # only one pair of numbers was specified
4013 # only quadrant specified -- go to center of dest quad
4016 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4018 # only sector specified
4022 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4029 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4031 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4032 # the actual deltas get computed here
4034 delta.x = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4035 delta.y = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4038 proutn(_("X and Y displacements- "))
4041 key = scanner.next()
4046 delta.x = scanner.real
4047 key = scanner.next()
4051 delta.y = scanner.real
4052 # Check for zero movement
4053 if delta.x == 0 and delta.y == 0:
4056 if itemp == "verbose" and not isprobe:
4058 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4059 # Course actually laid in.
4060 game.dist = delta.distance()
4061 game.direc = delta.bearing()
4062 if game.direc < 0.0:
4068 "Move under impulse power."
4070 if damaged(DIMPULS):
4073 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4075 if game.energy > 30.0:
4076 if not getcourse(isprobe=False, akey=0):
4078 power = 20.0 + 100.0*game.dist
4081 if power >= game.energy:
4082 # Insufficient power for trip
4084 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4085 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4086 if game.energy > 30:
4087 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4088 int(0.01 * (game.energy-20.0)-0.05))
4089 prout(_(" quadrants.\""))
4091 prout(_("quadrant. They are, therefore, useless.\""))
4094 # Make sure enough time is left for the trip
4095 game.optime = game.dist/0.095
4096 if game.optime >= game.state.remtime:
4097 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4098 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4099 proutn(_("we dare spend the time?\" "))
4102 # Activate impulse engines and pay the cost
4103 imove(novapush=False)
4107 power = 20.0 + 100.0*game.dist
4108 game.energy -= power
4109 game.optime = game.dist/0.095
4110 if game.energy <= 0:
4115 "ove under warp drive."
4116 blooey = False; twarp = False
4117 if not timewarp: # Not WARPX entry
4119 if game.damage[DWARPEN] > 10.0:
4122 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4124 if damaged(DWARPEN) and game.warpfac > 4.0:
4127 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4128 prout(_(" is repaired, I can only give you warp 4.\""))
4130 # Read in course and distance
4131 if not getcourse(isprobe=False, akey=0):
4133 # Make sure starship has enough energy for the trip
4134 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4135 if power >= game.energy:
4136 # Insufficient power for trip
4139 prout(_("Engineering to bridge--"))
4140 if not game.shldup or 0.5*power > game.energy:
4141 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4143 prout(_("We can't do it, Captain. We don't have enough energy."))
4145 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4148 prout(_("if you'll lower the shields."))
4152 prout(_("We haven't the energy to go that far with the shields up."))
4155 # Make sure enough time is left for the trip
4156 game.optime = 10.0*game.dist/game.wfacsq
4157 if game.optime >= 0.8*game.state.remtime:
4159 prout(_("First Officer Spock- \"Captain, I compute that such"))
4160 proutn(_(" a trip would require approximately %2.0f") %
4161 (100.0*game.optime/game.state.remtime))
4162 prout(_(" percent of our"))
4163 proutn(_(" remaining time. Are you sure this is wise?\" "))
4169 if game.warpfac > 6.0:
4170 # Decide if engine damage will occur
4171 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4172 prob = game.dist*(6.0-game.warpfac)**2/66.666666666
4173 if prob > randreal():
4175 game.dist = randreal(game.dist)
4176 # Decide if time warp will occur
4177 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4179 if idebug and game.warpfac==10 and not twarp:
4181 proutn("=== Force time warp? ")
4185 # If time warp or engine damage, check path
4186 # If it is obstructed, don't do warp or damage
4187 angle = ((15.0-game.direc)*0.5235998)
4188 deltax = -math.sin(angle)
4189 deltay = math.cos(angle)
4190 if math.fabs(deltax) > math.fabs(deltay):
4191 bigger = math.fabs(deltax)
4193 bigger = math.fabs(deltay)
4197 n = 10.0 * game.dist * bigger +0.5
4200 for l in range(1, n+1):
4205 if not VALID_SECTOR(ix, iy):
4207 if game.quad[ix][iy] != IHDOT:
4210 # Activate Warp Engines and pay the cost
4211 imove(novapush=False)
4214 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4215 if game.energy <= 0:
4217 game.optime = 10.0*game.dist/game.wfacsq
4221 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4223 prout(_("Engineering to bridge--"))
4224 prout(_(" Scott here. The warp engines are damaged."))
4225 prout(_(" We'll have to reduce speed to warp 4."))
4230 "Change the warp factor."
4236 proutn(_("Warp factor- "))
4241 if game.damage[DWARPEN] > 10.0:
4242 prout(_("Warp engines inoperative."))
4244 if damaged(DWARPEN) and scanner.real > 4.0:
4245 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4246 prout(_(" but right now we can only go warp 4.\""))
4248 if scanner.real > 10.0:
4249 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4251 if scanner.real < 1.0:
4252 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4254 oldfac = game.warpfac
4255 game.warpfac = scanner.real
4256 game.wfacsq=game.warpfac*game.warpfac
4257 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4258 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4261 if game.warpfac < 8.00:
4262 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4264 if game.warpfac == 10.0:
4265 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4267 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4271 "Cope with being tossed out of quadrant by supernova or yanked by beam."
4273 # is captain on planet?
4275 if damaged(DTRANSP):
4278 prout(_("Scotty rushes to the transporter controls."))
4280 prout(_("But with the shields up it's hopeless."))
4282 prouts(_("His desperate attempt to rescue you . . ."))
4287 prout(_("SUCCEEDS!"))
4290 proutn(_("The crystals mined were "))
4298 # Check to see if captain in shuttle craft
4303 # Inform captain of attempt to reach safety
4307 prouts(_("***RED ALERT! RED ALERT!"))
4311 prout(_(" has stopped in a quadrant containing"))
4312 prouts(_(" a supernova."))
4314 proutn(_("***Emergency automatic override attempts to hurl "))
4317 prout(_("safely out of quadrant."))
4318 if not damaged(DRADIO):
4319 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4320 # Try to use warp engines
4321 if damaged(DWARPEN):
4323 prout(_("Warp engines damaged."))
4326 game.warpfac = randreal(6.0, 8.0)
4327 game.wfacsq = game.warpfac * game.warpfac
4328 prout(_("Warp factor set to %d") % int(game.warpfac))
4329 power = 0.75*game.energy
4330 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4331 distreq = randreal(math.sqrt(2))
4332 if distreq < game.dist:
4334 game.optime = 10.0*game.dist/game.wfacsq
4335 game.direc = randreal(12) # How dumb!
4337 game.inorbit = False
4340 # This is bad news, we didn't leave quadrant.
4344 prout(_("Insufficient energy to leave quadrant."))
4347 # Repeat if another snova
4348 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4350 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
4351 finish(FWON) # Snova killed remaining enemy.
4354 "Let's do the time warp again."
4355 prout(_("***TIME WARP ENTERED."))
4356 if game.state.snap and withprob(0.5):
4358 prout(_("You are traveling backwards in time %d stardates.") %
4359 int(game.state.date-game.snapsht.date))
4360 game.state = game.snapsht
4361 game.state.snap = False
4362 if len(game.state.kcmdr):
4363 schedule(FTBEAM, expran(game.intime/len(game.state.kcmdr)))
4364 schedule(FBATTAK, expran(0.3*game.intime))
4365 schedule(FSNOVA, expran(0.5*game.intime))
4366 # next snapshot will be sooner
4367 schedule(FSNAP, expran(0.25*game.state.remtime))
4369 if game.state.nscrem:
4370 schedule(FSCMOVE, 0.2777)
4374 game.battle.invalidate()
4376 # Make sure Galileo is consistant -- Snapshot may have been taken
4377 # when on planet, which would give us two Galileos!
4379 for l in range(game.inplan):
4380 if game.state.planets[l].known == "shuttle_down":
4382 if game.iscraft == "onship" and game.ship==IHE:
4383 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4384 game.iscraft = "offship"
4385 # Likewise, if in the original time the Galileo was abandoned, but
4386 # was on ship earlier, it would have vanished -- let's restore it.
4387 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4388 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4389 game.iscraft = "onship"
4390 # There used to be code to do the actual reconstrction here,
4391 # but the starchart is now part of the snapshotted galaxy state.
4392 prout(_("Spock has reconstructed a correct star chart from memory"))
4394 # Go forward in time
4395 game.optime = -0.5*game.intime*math.log(randreal())
4396 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4397 # cheat to make sure no tractor beams occur during time warp
4398 postpone(FTBEAM, game.optime)
4399 game.damage[DRADIO] += game.optime
4401 events() # Stas Sergeev added this -- do pending events
4404 "Launch deep-space probe."
4405 # New code to launch a deep space probe
4406 if game.nprobes == 0:
4409 if game.ship == IHE:
4410 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4412 prout(_("Ye Faerie Queene has no deep space probes."))
4417 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4419 if is_scheduled(FDSPROB):
4422 if damaged(DRADIO) and game.condition != "docked":
4423 prout(_("Spock- \"Records show the previous probe has not yet"))
4424 prout(_(" reached its destination.\""))
4426 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4428 key = scanner.next()
4430 # slow mode, so let Kirk know how many probes there are left
4431 if game.nprobes == 1:
4432 prout(_("1 probe left."))
4434 prout(_("%d probes left") % game.nprobes)
4435 proutn(_("Are you sure you want to fire a probe? "))
4438 game.isarmed = False
4439 if key == IHALPHA and scanner.token == "armed":
4441 key = scanner.next()
4443 proutn(_("Arm NOVAMAX warhead? "))
4445 if not getcourse(isprobe=True, akey=key):
4448 angle = ((15.0 - game.direc) * 0.5235988)
4449 game.probeinx = -math.sin(angle)
4450 game.probeiny = math.cos(angle)
4451 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4452 bigger = math.fabs(game.probeinx)
4454 bigger = math.fabs(game.probeiny)
4455 game.probeiny /= bigger
4456 game.probeinx /= bigger
4457 game.proben = 10.0*game.dist*bigger +0.5
4458 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4459 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4460 game.probec = game.quadrant
4461 schedule(FDSPROB, 0.01) # Time to move one sector
4462 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4466 # Here's how the mayday code works:
4468 # First, the closest starbase is selected. If there is a a starbase
4469 # in your own quadrant, you are in good shape. This distance takes
4470 # quadrant distances into account only.
4472 # A magic number is computed based on the distance which acts as the
4473 # probability that you will be rematerialized. You get three tries.
4475 # When it is determined that you should be able to be rematerialized
4476 # (i.e., when the probability thing mentioned above comes up
4477 # positive), you are put into that quadrant (anywhere). Then, we try
4478 # to see if there is a spot adjacent to the star- base. If not, you
4479 # can't be rematerialized!!! Otherwise, it drops you there. It only
4480 # tries five times to find a spot to drop you. After that, it's your
4484 "Yell for help from nearest starbase."
4485 # There's more than one way to move in this game!
4487 # Test for conditions which prevent calling for help
4488 if game.condition == "docked":
4489 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4492 prout(_("Subspace radio damaged."))
4494 if not game.state.baseq:
4495 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4498 proutn(_("You must be aboard the "))
4502 # OK -- call for help from nearest starbase
4505 # There's one in this quadrant
4506 ddist = (game.base - game.sector).distance()
4509 for ibq in game.state.baseq:
4510 xdist = QUADSIZE * (ibq - game.quadrant).distance()
4513 # Since starbase not in quadrant, set up new quadrant
4516 # dematerialize starship
4517 game.quad[game.sector.x][game.sector.y]=IHDOT
4518 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4520 prout(_(" dematerializes."))
4522 for m in range(1, 5+1):
4523 w = game.base.scatter()
4524 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4525 # found one -- finish up
4528 if not game.sector.is_valid():
4529 prout(_("You have been lost in space..."))
4530 finish(FMATERIALIZE)
4532 # Give starbase three chances to rematerialize starship
4533 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4534 for m in range(1, 3+1):
4535 if m == 1: proutn(_("1st"))
4536 elif m == 2: proutn(_("2nd"))
4537 elif m == 3: proutn(_("3rd"))
4538 proutn(_(" attempt to re-materialize "))
4540 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4543 if randreal() > probf:
4546 curses.delay_output(500)
4549 game.quad[ix][iy]=IHQUEST
4552 setwnd(message_window)
4553 finish(FMATERIALIZE)
4555 game.quad[ix][iy]=game.ship
4557 prout(_("succeeds."))
4561 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4563 # Abandon Ship (the BSD-Trek description)
4565 # The ship is abandoned. If your current ship is the Faire
4566 # Queene, or if your shuttlecraft is dead, you're out of
4567 # luck. You need the shuttlecraft in order for the captain
4568 # (that's you!!) to escape.
4570 # Your crew can beam to an inhabited starsystem in the
4571 # quadrant, if there is one and if the transporter is working.
4572 # If there is no inhabited starsystem, or if the transporter
4573 # is out, they are left to die in outer space.
4575 # If there are no starbases left, you are captured by the
4576 # Klingons, who torture you mercilessly. However, if there
4577 # is at least one starbase, you are returned to the
4578 # Federation in a prisoner of war exchange. Of course, this
4579 # can't happen unless you have taken some prisoners.
4584 if game.condition=="docked":
4586 prout(_("You cannot abandon Ye Faerie Queene."))
4589 # Must take shuttle craft to exit
4590 if game.damage[DSHUTTL]==-1:
4591 prout(_("Ye Faerie Queene has no shuttle craft."))
4593 if game.damage[DSHUTTL]<0:
4594 prout(_("Shuttle craft now serving Big Macs."))
4596 if game.damage[DSHUTTL]>0:
4597 prout(_("Shuttle craft damaged."))
4600 prout(_("You must be aboard the ship."))
4602 if game.iscraft != "onship":
4603 prout(_("Shuttle craft not currently available."))
4605 # Emit abandon ship messages
4607 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4609 prouts(_("***ALL HANDS ABANDON SHIP!"))
4611 prout(_("Captain and crew escape in shuttle craft."))
4612 if not game.state.baseq:
4613 # Oops! no place to go...
4616 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4618 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4619 prout(_("Remainder of ship's complement beam down"))
4620 prout(_("to nearest habitable planet."))
4621 elif q.planet != None and not damaged(DTRANSP):
4622 prout(_("Remainder of ship's complement beam down to %s.") %
4625 prout(_("Entire crew of %d left to die in outer space.") %
4627 game.casual += game.state.crew
4628 game.abandoned += game.state.crew
4630 # If at least one base left, give 'em the Faerie Queene
4632 game.icrystl = False # crystals are lost
4633 game.nprobes = 0 # No probes
4634 prout(_("You are captured by Klingons and released to"))
4635 prout(_("the Federation in a prisoner-of-war exchange."))
4636 nb = randrange(len(game.state.baseq))
4637 # Set up quadrant and position FQ adjacient to base
4638 if not game.quadrant == game.state.baseq[nb]:
4639 game.quadrant = game.state.baseq[nb]
4640 game.sector.x = game.sector.y = 5
4643 # position next to base by trial and error
4644 game.quad[game.sector.x][game.sector.y] = IHDOT
4645 for l in range(QUADSIZE):
4646 game.sector = game.base.scatter()
4647 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4648 game.quad[game.sector.x][game.sector.y] == IHDOT:
4651 break # found a spot
4652 game.sector.x=QUADSIZE/2
4653 game.sector.y=QUADSIZE/2
4655 # Get new commission
4656 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4657 game.state.crew = FULLCREW
4658 prout(_("Starfleet puts you in command of another ship,"))
4659 prout(_("the Faerie Queene, which is antiquated but,"))
4660 prout(_("still useable."))
4662 prout(_("The dilithium crystals have been moved."))
4664 game.iscraft = "offship" # Galileo disappears
4666 game.condition="docked"
4667 for l in range(NDEVICES):
4668 game.damage[l] = 0.0
4669 game.damage[DSHUTTL] = -1
4670 game.energy = game.inenrg = 3000.0
4671 game.shield = game.inshld = 1250.0
4672 game.torps = game.intorps = 6
4673 game.lsupres=game.inlsr=3.0
4679 # Code from planets.c begins here.
4682 "Abort a lengthy operation if an event interrupts it."
4685 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4690 "Report on (uninhabited) planets in the galaxy."
4694 prout(_("Spock- \"Planet report follows, Captain.\""))
4696 for i in range(game.inplan):
4697 if game.state.planets[i].pclass == "destroyed":
4699 if (game.state.planets[i].known != "unknown" \
4700 and not game.state.planets[i].inhabited) \
4703 if idebug and game.state.planets[i].known=="unknown":
4704 proutn("(Unknown) ")
4705 proutn(_("Quadrant %s") % game.state.planets[i].quadrant)
4706 proutn(_(" class "))
4707 proutn(game.state.planets[i].pclass)
4709 if game.state.planets[i].crystals != present:
4711 prout(_("dilithium crystals present."))
4712 if game.state.planets[i].known=="shuttle_down":
4713 prout(_(" Shuttle Craft Galileo on surface."))
4715 prout(_("No information available."))
4718 "Enter standard orbit."
4722 prout(_("Already in standard orbit."))
4724 if damaged(DWARPEN) and damaged(DIMPULS):
4725 prout(_("Both warp and impulse engines damaged."))
4727 if not game.plnet.is_valid():
4728 prout("There is no planet in this sector.")
4730 if abs(game.sector.x-game.plnet.x)>1 or abs(game.sector.y-game.plnet.y)>1:
4732 prout(_(" not adjacent to planet."))
4735 game.optime = randreal(0.02, 0.05)
4736 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4740 game.height = randreal(1400, 8600)
4741 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4746 "Examine planets in this quadrant."
4747 if damaged(DSRSENS):
4748 if game.options & OPTION_TTY:
4749 prout(_("Short range sensors damaged."))
4751 if game.iplnet == None:
4752 if game.options & OPTION_TTY:
4753 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4755 if game.iplnet.known == "unknown":
4756 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4758 prout(_(" Planet at Sector %s is of class %s.") %
4759 (game.plnet, game.iplnet.pclass))
4760 if game.iplnet.known=="shuttle_down":
4761 prout(_(" Sensors show Galileo still on surface."))
4762 proutn(_(" Readings indicate"))
4763 if game.iplnet.crystals != "present":
4765 prout(_(" dilithium crystals present.\""))
4766 if game.iplnet.known == "unknown":
4767 game.iplnet.known = "known"
4768 elif game.iplnet.inhabited:
4769 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4770 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4773 "Use the transporter."
4777 if damaged(DTRANSP):
4778 prout(_("Transporter damaged."))
4779 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4781 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4785 if not game.inorbit:
4787 prout(_(" not in standard orbit."))
4790 prout(_("Impossible to transport through shields."))
4792 if game.iplnet.known=="unknown":
4793 prout(_("Spock- \"Captain, we have no information on this planet"))
4794 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4795 prout(_(" you may not go down.\""))
4797 if not game.landed and game.iplnet.crystals=="absent":
4798 prout(_("Spock- \"Captain, I fail to see the logic in"))
4799 prout(_(" exploring a planet with no dilithium crystals."))
4800 proutn(_(" Are you sure this is wise?\" "))
4804 if not (game.options & OPTION_PLAIN):
4805 nrgneed = 50 * game.skill + game.height / 100.0
4806 if nrgneed > game.energy:
4807 prout(_("Engineering to bridge--"))
4808 prout(_(" Captain, we don't have enough energy for transportation."))
4810 if not game.landed and nrgneed * 2 > game.energy:
4811 prout(_("Engineering to bridge--"))
4812 prout(_(" Captain, we have enough energy only to transport you down to"))
4813 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4814 if game.iplnet.known == "shuttle_down":
4815 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4816 proutn(_(" Are you sure this is wise?\" "))
4821 # Coming from planet
4822 if game.iplnet.known=="shuttle_down":
4823 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4827 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4828 prout(_("Landing party assembled, ready to beam up."))
4830 prout(_("Kirk whips out communicator..."))
4831 prouts(_("BEEP BEEP BEEP"))
4833 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4836 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4838 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4840 prout(_("Kirk- \"Energize.\""))
4843 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4846 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4848 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4851 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4852 game.landed = not game.landed
4853 game.energy -= nrgneed
4855 prout(_("Transport complete."))
4856 if game.landed and game.iplnet.known=="shuttle_down":
4857 prout(_("The shuttle craft Galileo is here!"))
4858 if not game.landed and game.imine:
4865 "Strip-mine a world for dilithium."
4869 prout(_("Mining party not on planet."))
4871 if game.iplnet.crystals == "mined":
4872 prout(_("This planet has already been strip-mined for dilithium."))
4874 elif game.iplnet.crystals == "absent":
4875 prout(_("No dilithium crystals on this planet."))
4878 prout(_("You've already mined enough crystals for this trip."))
4880 if game.icrystl and game.cryprob == 0.05:
4881 proutn(_("With all those fresh crystals aboard the "))
4884 prout(_("there's no reason to mine more at this time."))
4886 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4889 prout(_("Mining operation complete."))
4890 game.iplnet.crystals = "mined"
4891 game.imine = game.ididit = True
4894 "Use dilithium crystals."
4898 if not game.icrystl:
4899 prout(_("No dilithium crystals available."))
4901 if game.energy >= 1000:
4902 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4903 prout(_(" except when Condition Yellow exists."))
4905 prout(_("Spock- \"Captain, I must warn you that loading"))
4906 prout(_(" raw dilithium crystals into the ship's power"))
4907 prout(_(" system may risk a severe explosion."))
4908 proutn(_(" Are you sure this is wise?\" "))
4913 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
4914 prout(_(" Mr. Spock and I will try it.\""))
4916 prout(_("Spock- \"Crystals in place, Sir."))
4917 prout(_(" Ready to activate circuit.\""))
4919 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
4921 if with(game.cryprob):
4922 prouts(_(" \"Activating now! - - No good! It's***"))
4924 prouts(_("***RED ALERT! RED A*L********************************"))
4927 prouts(_("****************** KA-BOOM!!!! *******************"))
4931 game.energy += randreal(5000.0, 5500.0)
4932 prouts(_(" \"Activating now! - - "))
4933 prout(_("The instruments"))
4934 prout(_(" are going crazy, but I think it's"))
4935 prout(_(" going to work!! Congratulations, Sir!\""))
4940 "Use shuttlecraft for planetary jaunt."
4943 if damaged(DSHUTTL):
4944 if game.damage[DSHUTTL] == -1.0:
4945 if game.inorbit and game.iplnet.known == "shuttle_down":
4946 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
4948 prout(_("Ye Faerie Queene had no shuttle craft."))
4949 elif game.damage[DSHUTTL] > 0:
4950 prout(_("The Galileo is damaged."))
4951 else: # game.damage[DSHUTTL] < 0
4952 prout(_("Shuttle craft is now serving Big Macs."))
4954 if not game.inorbit:
4956 prout(_(" not in standard orbit."))
4958 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
4959 prout(_("Shuttle craft not currently available."))
4961 if not game.landed and game.iplnet.known=="shuttle_down":
4962 prout(_("You will have to beam down to retrieve the shuttle craft."))
4964 if game.shldup or game.condition == "docked":
4965 prout(_("Shuttle craft cannot pass through shields."))
4967 if game.iplnet.known=="unknown":
4968 prout(_("Spock- \"Captain, we have no information on this planet"))
4969 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4970 prout(_(" you may not fly down.\""))
4972 game.optime = 3.0e-5*game.height
4973 if game.optime >= 0.8*game.state.remtime:
4974 prout(_("First Officer Spock- \"Captain, I compute that such"))
4975 proutn(_(" a maneuver would require approximately %2d%% of our") % \
4976 int(100*game.optime/game.state.remtime))
4977 prout(_("remaining time."))
4978 proutn(_("Are you sure this is wise?\" "))
4984 if game.iscraft == "onship":
4986 if not damaged(DTRANSP):
4987 proutn(_("Spock- \"Would you rather use the transporter?\" "))
4991 proutn(_("Shuttle crew"))
4993 proutn(_("Rescue party"))
4994 prout(_(" boards Galileo and swoops toward planet surface."))
4995 game.iscraft = "offship"
4999 game.iplnet.known="shuttle_down"
5000 prout(_("Trip complete."))
5003 # Ready to go back to ship
5004 prout(_("You and your mining party board the"))
5005 prout(_("shuttle craft for the trip back to the Enterprise."))
5007 prouts(_("The short hop begins . . ."))
5009 game.iplnet.known="known"
5015 game.iscraft = "onship"
5021 prout(_("Trip complete."))
5024 # Kirk on ship and so is Galileo
5025 prout(_("Mining party assembles in the hangar deck,"))
5026 prout(_("ready to board the shuttle craft \"Galileo\"."))
5028 prouts(_("The hangar doors open; the trip begins."))
5031 game.iscraft = "offship"
5034 game.iplnet.known = "shuttle_down"
5037 prout(_("Trip complete."))
5041 "Use the big zapper."
5045 if game.ship != IHE:
5046 prout(_("Ye Faerie Queene has no death ray."))
5048 if len(game.enemies)==0:
5049 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5052 prout(_("Death Ray is damaged."))
5054 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5055 prout(_(" is highly unpredictible. Considering the alternatives,"))
5056 proutn(_(" are you sure this is wise?\" "))
5059 prout(_("Spock- \"Acknowledged.\""))
5062 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5064 prout(_("Crew scrambles in emergency preparation."))
5065 prout(_("Spock and Scotty ready the death ray and"))
5066 prout(_("prepare to channel all ship's power to the device."))
5068 prout(_("Spock- \"Preparations complete, sir.\""))
5069 prout(_("Kirk- \"Engage!\""))
5071 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5074 if game.options & OPTION_PLAIN:
5078 prouts(_("Sulu- \"Captain! It's working!\""))
5080 while len(game.enemies) > 0:
5081 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.x][game.enemies[1].kloc.y],game.enemies[1].kloc)
5082 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5083 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) == 0:
5085 if (game.options & OPTION_PLAIN) == 0:
5086 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5088 prout(_(" is still operational.\""))
5090 prout(_(" has been rendered nonfunctional.\""))
5091 game.damage[DDRAY] = 39.95
5093 r = randreal() # Pick failure method
5095 prouts(_("Sulu- \"Captain! It's working!\""))
5097 prouts(_("***RED ALERT! RED ALERT!"))
5099 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5101 prouts(_("***RED ALERT! RED A*L********************************"))
5104 prouts(_("****************** KA-BOOM!!!! *******************"))
5109 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5111 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5113 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5114 prout(_(" have apparently been transformed into strange mutations."))
5115 prout(_(" Vulcans do not seem to be affected."))
5117 prout(_("Kirk- \"Raauch! Raauch!\""))
5122 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5124 proutn(_("Spock- \"I believe the word is"))
5125 prouts(_(" *ASTONISHING*"))
5126 prout(_(" Mr. Sulu."))
5127 for i in range(QUADSIZE):
5128 for j in range(QUADSIZE):
5129 if game.quad[i][j] == IHDOT:
5130 game.quad[i][j] = IHQUEST
5131 prout(_(" Captain, our quadrant is now infested with"))
5132 prouts(_(" - - - - - - *THINGS*."))
5134 prout(_(" I have no logical explanation.\""))
5136 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5138 prout(_("Scotty- \"There are so many tribbles down here"))
5139 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5143 # Code from reports.c begins here
5145 def attackreport(curt):
5146 "eport status of bases under attack."
5148 if is_scheduled(FCDBAS):
5149 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5150 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5151 elif game.isatb == 1:
5152 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5153 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5155 prout(_("No Starbase is currently under attack."))
5157 if is_scheduled(FCDBAS):
5158 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5160 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5164 # report on general game status
5166 s1 = "" and game.thawed and _("thawed ")
5167 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5168 s3 = (None, _("novice"). _("fair"),
5169 _("good"), _("expert"), _("emeritus"))[game.skill]
5170 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5171 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5172 prout(_("No plaque is allowed."))
5174 prout(_("This is tournament game %d.") % game.tourn)
5175 prout(_("Your secret password is \"%s\"") % game.passwd)
5176 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)),
5177 (game.inkling + game.incom + game.inscom)))
5178 if game.incom - len(game.state.kcmdr):
5179 prout(_(", including %d Commander%s.") % (game.incom - len(game.state.kcmdr), (_("s"), "")[(game.incom - len(game.state.kcmdr))==1]))
5180 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5181 prout(_(", but no Commanders."))
5184 if game.skill > SKILL_FAIR:
5185 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5186 if len(game.state.baseq) != game.inbase:
5188 if game.inbase-len(game.state.baseq)==1:
5189 proutn(_("has been 1 base"))
5191 proutn(_("have been %d bases") % (game.inbase-len(game.state.baseq)))
5192 prout(_(" destroyed, %d remaining.") % len(game.state.baseq))
5194 prout(_("There are %d bases.") % game.inbase)
5195 if communicating() or game.iseenit:
5196 # Don't report this if not seen and
5197 # either the radio is dead or not at base!
5201 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5203 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5204 if game.ship == IHE:
5205 proutn(_("You have "))
5207 proutn("%d" % (game.nprobes))
5210 proutn(_(" deep space probe"))
5214 if communicating() and is_scheduled(FDSPROB):
5216 proutn(_("An armed deep space probe is in "))
5218 proutn(_("A deep space probe is in "))
5219 prout("Quadrant %s." % game.probec)
5221 if game.cryprob <= .05:
5222 prout(_("Dilithium crystals aboard ship... not yet used."))
5226 while game.cryprob > ai:
5229 prout(_("Dilithium crystals have been used %d time%s.") % \
5230 (i, (_("s"), "")[i==1]))
5234 "Long-range sensor scan."
5235 if damaged(DLRSENS):
5236 # Now allow base's sensors if docked
5237 if game.condition != "docked":
5239 prout(_("LONG-RANGE SENSORS DAMAGED."))
5242 prout(_("Starbase's long-range scan"))
5244 prout(_("Long-range scan"))
5245 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5248 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5249 if not VALID_QUADRANT(x, y):
5253 if not damaged(DRADIO):
5254 game.state.galaxy[x][y].charted = True
5255 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5256 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5257 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5258 if not silent and game.state.galaxy[x][y].supernova:
5261 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5269 for i in range(NDEVICES):
5272 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5273 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5275 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5276 game.damage[i]+0.05,
5277 game.docfac*game.damage[i]+0.005))
5279 prout(_("All devices functional."))
5282 "Update the chart in the Enterprise's computer from galaxy data."
5283 game.lastchart = game.state.date
5284 for i in range(GALSIZE):
5285 for j in range(GALSIZE):
5286 if game.state.galaxy[i][j].charted:
5287 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5288 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5289 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5292 "Display the star chart."
5294 if (game.options & OPTION_AUTOSCAN):
5296 if not damaged(DRADIO):
5298 if game.lastchart < game.state.date and game.condition == "docked":
5299 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5301 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5302 if game.state.date > game.lastchart:
5303 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5304 prout(" 1 2 3 4 5 6 7 8")
5305 for i in range(GALSIZE):
5306 proutn("%d |" % (i+1))
5307 for j in range(GALSIZE):
5308 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5312 if game.state.galaxy[i][j].supernova:
5314 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5316 elif game.state.galaxy[i][j].charted:
5317 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5321 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5329 def sectscan(goodScan, i, j):
5330 "Light up an individual dot in a sector."
5331 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5332 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):
5333 if game.condition == "red": textcolor("red")
5334 elif game.condition == "green": textcolor("green")
5335 elif game.condition == "yellow": textcolor("yellow")
5336 elif game.condition == "docked": textcolor("cyan")
5337 elif game.condition == "dead": textcolor("brown")
5338 if game.quad[i][j] != game.ship:
5340 proutn("%c " % game.quad[i][j])
5346 "Emit status report lines"
5347 if not req or req == 1:
5348 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5349 % (game.state.date, game.state.remtime))
5350 if not req or req == 2:
5351 if game.condition != "docked":
5354 for t in range(NDEVICES):
5355 if game.damage[t]>0:
5357 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5358 if not req or req == 3:
5359 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5360 if not req or req == 4:
5361 if damaged(DLIFSUP):
5362 if game.condition == "docked":
5363 s = _("DAMAGED, Base provides")
5365 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5368 prstat(_("Life Support"), s)
5369 if not req or req == 5:
5370 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5371 if not req or req == 6:
5373 if game.icrystl and (game.options & OPTION_SHOWME):
5374 extra = _(" (have crystals)")
5375 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5376 if not req or req == 7:
5377 prstat(_("Torpedoes"), "%d" % (game.torps))
5378 if not req or req == 8:
5379 if damaged(DSHIELD):
5385 data = _(" %d%% %.1f units") \
5386 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5387 prstat(_("Shields"), s+data)
5388 if not req or req == 9:
5389 prstat(_("Klingons Left"), "%d" \
5390 % (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem))
5391 if not req or req == 10:
5392 if game.options & OPTION_WORLDS:
5393 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5394 if plnet and plnet.inhabited:
5395 prstat(_("Major system"), plnet.name)
5397 prout(_("Sector is uninhabited"))
5398 elif not req or req == 11:
5399 attackreport(not req)
5402 "Request specified status data, a historical relic from slow TTYs."
5403 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5404 while scanner.next() == IHEOL:
5405 proutn(_("Information desired? "))
5407 if scanner.token in requests:
5408 status(requests.index(scanner.token))
5410 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5411 prout((" date, condition, position, lsupport, warpfactor,"))
5412 prout((" energy, torpedoes, shields, klingons, system, time."))
5417 if damaged(DSRSENS):
5418 # Allow base's sensors if docked
5419 if game.condition != "docked":
5420 prout(_(" S.R. SENSORS DAMAGED!"))
5423 prout(_(" [Using Base's sensors]"))
5425 prout(_(" Short-range scan"))
5426 if goodScan and not damaged(DRADIO):
5427 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5428 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5429 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5430 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5431 prout(" 1 2 3 4 5 6 7 8 9 10")
5432 if game.condition != "docked":
5434 for i in range(QUADSIZE):
5435 proutn("%2d " % (i+1))
5436 for j in range(QUADSIZE):
5437 sectscan(goodScan, i, j)
5441 "Use computer to get estimated time of arrival for a warp jump."
5442 w1 = coord(); w2 = coord()
5444 if damaged(DCOMPTR):
5445 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5448 if scanner.next() != IHREAL:
5451 proutn(_("Destination quadrant and/or sector? "))
5452 if scanner.next()!=IHREAL:
5455 w1.y = int(scanner.real-0.5)
5456 if scanner.next() != IHREAL:
5459 w1.x = int(scanner.real-0.5)
5460 if scanner.next() == IHREAL:
5461 w2.y = int(scanner.real-0.5)
5462 if scanner.next() != IHREAL:
5465 w2.x = int(scanner.real-0.5)
5467 if game.quadrant.y>w1.x:
5471 if game.quadrant.x>w1.y:
5475 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5478 game.dist = math.sqrt((w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))**2+
5479 (w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x))**2)
5482 prout(_("Answer \"no\" if you don't know the value:"))
5485 proutn(_("Time or arrival date? "))
5486 if scanner.next()==IHREAL:
5487 ttime = scanner.real
5488 if ttime > game.state.date:
5489 ttime -= game.state.date # Actually a star date
5490 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5491 if ttime <= 1e-10 or twarp > 10:
5492 prout(_("We'll never make it, sir."))
5499 proutn(_("Warp factor? "))
5500 if scanner.next()== IHREAL:
5502 twarp = scanner.real
5503 if twarp<1.0 or twarp > 10.0:
5507 prout(_("Captain, certainly you can give me one of these."))
5510 ttime = (10.0*game.dist)/twarp**2
5511 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5512 if tpower >= game.energy:
5513 prout(_("Insufficient energy, sir."))
5514 if not game.shldup or tpower > game.energy*2.0:
5517 proutn(_("New warp factor to try? "))
5518 if scanner.next() == IHREAL:
5520 twarp = scanner.real
5521 if twarp<1.0 or twarp > 10.0:
5529 prout(_("But if you lower your shields,"))
5530 proutn(_("remaining"))
5533 proutn(_("Remaining"))
5534 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5536 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5538 prout(_("Any warp speed is adequate."))
5540 prout(_("Minimum warp needed is %.2f,") % (twarp))
5541 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5542 if game.state.remtime < ttime:
5543 prout(_("Unfortunately, the Federation will be destroyed by then."))
5545 prout(_("You'll be taking risks at that speed, Captain"))
5546 if (game.isatb==1 and game.state.kscmdr == w1 and \
5547 scheduled(FSCDBAS)< ttime+game.state.date) or \
5548 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5549 prout(_("The starbase there will be destroyed by then."))
5550 proutn(_("New warp factor to try? "))
5551 if scanner.next() == IHREAL:
5553 twarp = scanner.real
5554 if twarp<1.0 or twarp > 10.0:
5563 # Code from setup.c begins here
5566 "Issue a historically correct banner."
5568 prout(_("-SUPER- STAR TREK"))
5570 # From the FORTRAN original
5571 # prout(_("Latest update-21 Sept 78"))
5577 scanner.token = "emsave.trk"
5579 key = scanner.next()
5581 proutn(_("File name: "))
5582 key = scanner.next()
5587 if '.' not in scanner.token:
5588 scanner.token += ".trk"
5590 fp = open(scanner.token, "wb")
5592 prout(_("Can't freeze game as file %s") % scanner.token)
5594 cPickle.dump(game, fp)
5598 "Retrieve saved game."
5599 game.passwd[0] = '\0'
5600 key = scanner.next()
5602 proutn(_("File name: "))
5603 key = scanner.next()
5608 if '.' not in scanner.token:
5609 scanner.token += ".trk"
5611 fp = open(scanner.token, "rb")
5613 prout(_("Can't thaw game in %s") % scanner.token)
5615 game = cPickle.load(fp)
5619 # I used <http://www.memory-alpha.org> to find planets
5620 # with references in ST:TOS. Eath and the Alpha Centauri
5621 # Colony have been omitted.
5623 # Some planets marked Class G and P here will be displayed as class M
5624 # because of the way planets are generated. This is a known bug.
5627 _("Andoria (Fesoan)"), # several episodes
5628 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5629 _("Vulcan (T'Khasi)"), # many episodes
5630 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5631 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5632 _("Ardana"), # TOS: "The Cloud Minders"
5633 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5634 _("Gideon"), # TOS: "The Mark of Gideon"
5635 _("Aldebaran III"), # TOS: "The Deadly Years"
5636 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5637 _("Altair IV"), # TOS: "Amok Time
5638 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5639 _("Benecia"), # TOS: "The Conscience of the King"
5640 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5641 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5642 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5643 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5644 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5645 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5646 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5647 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5648 _("Ingraham B"), # TOS: "Operation: Annihilate"
5649 _("Janus IV"), # TOS: "The Devil in the Dark"
5650 _("Makus III"), # TOS: "The Galileo Seven"
5651 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5652 _("Omega IV"), # TOS: "The Omega Glory"
5653 _("Regulus V"), # TOS: "Amok Time
5654 _("Deneva"), # TOS: "Operation -- Annihilate!"
5655 # Worlds from BSD Trek
5656 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5657 _("Beta III"), # TOS: "The Return of the Archons"
5658 _("Triacus"), # TOS: "And the Children Shall Lead",
5659 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5661 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5662 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5663 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5664 # _("Izar"), # TOS: "Whom Gods Destroy"
5665 # _("Tiburon"), # TOS: "The Way to Eden"
5666 # _("Merak II"), # TOS: "The Cloud Minders"
5667 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5668 # _("Iotia"), # TOS: "A Piece of the Action"
5672 _("S. R. Sensors"), \
5673 _("L. R. Sensors"), \
5675 _("Photon Tubes"), \
5676 _("Life Support"), \
5677 _("Warp Engines"), \
5678 _("Impulse Engines"), \
5680 _("Subspace Radio"), \
5681 _("Shuttle Craft"), \
5683 _("Navigation System"), \
5685 _("Shield Control"), \
5691 "Prepare to play, set up cosmos."
5693 # Decide how many of everything
5695 return # frozen game
5696 # Prepare the Enterprise
5697 game.alldone = game.gamewon = False
5699 game.state.crew = FULLCREW
5700 game.energy = game.inenrg = 5000.0
5701 game.shield = game.inshld = 2500.0
5702 game.shldchg = False
5706 game.quadrant = randplace(GALSIZE)
5707 game.sector = randplace(QUADSIZE)
5708 game.torps = game.intorps = 10
5709 game.nprobes = randrange(2, 5)
5711 game.wfacsq = game.warpfac * game.warpfac
5712 for i in range(NDEVICES):
5713 game.damage[i] = 0.0
5714 # Set up assorted game parameters
5715 game.battle = coord()
5716 game.state.date = game.indate = 100.0 * randreal(20, 51)
5717 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5718 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5719 game.isatb = game.state.nplankl = 0
5720 game.state.starkl = game.state.basekl = 0
5721 game.iscraft = "onship"
5725 # Starchart is functional but we've never seen it
5726 game.lastchart = FOREVER
5727 # Put stars in the galaxy
5729 for i in range(GALSIZE):
5730 for j in range(GALSIZE):
5731 k = randrange(1, QUADSIZE**2/10+1)
5733 game.state.galaxy[i][j].stars = k
5734 # Locate star bases in galaxy
5735 for i in range(game.inbase):
5738 w = randplace(GALSIZE)
5739 if not game.state.galaxy[w.x][w.y].starbase:
5742 # C version: for (j = i-1; j > 0; j--)
5743 # so it did them in the opposite order.
5744 for j in range(1, i):
5745 # Improved placement algorithm to spread out bases
5746 distq = (w - game.state.baseq[j]).distance()
5747 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5750 prout("=== Abandoning base #%d at %s" % (i, w))
5752 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5754 prout("=== Saving base #%d, close to #%d" % (i, j))
5757 game.state.baseq.append(w)
5758 game.state.galaxy[w.x][w.y].starbase = game.state.chart[w.x][w.y].starbase = True
5759 # Position ordinary Klingon Battle Cruisers
5761 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5762 if klumper > MAXKLQUAD:
5766 klump = (1.0 - r*r)*klumper
5771 w = randplace(GALSIZE)
5772 if not game.state.galaxy[w.x][w.y].supernova and \
5773 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5775 game.state.galaxy[w.x][w.y].klingons += int(klump)
5778 # Position Klingon Commander Ships
5779 for i in range(game.incom):
5781 w = randplace(GALSIZE)
5782 if not welcoming(w) or w in game.state.kcmdr:
5784 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)):
5786 game.state.galaxy[w.x][w.y].klingons += 1
5787 game.state.kcmdr.append(w)
5788 # Locate planets in galaxy
5789 for i in range(game.inplan):
5791 w = randplace(GALSIZE)
5792 if game.state.galaxy[w.x][w.y].planet == None:
5796 new.crystals = "absent"
5797 if (game.options & OPTION_WORLDS) and i < NINHAB:
5798 new.pclass = "M" # All inhabited planets are class M
5799 new.crystals = "absent"
5801 new.name = systnames[i]
5802 new.inhabited = True
5804 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5806 new.crystals = "present"
5807 new.known = "unknown"
5808 new.inhabited = False
5809 game.state.galaxy[w.x][w.y].planet = new
5810 game.state.planets.append(new)
5812 for i in range(game.state.nromrem):
5813 w = randplace(GALSIZE)
5814 game.state.galaxy[w.x][w.y].romulans += 1
5815 # Place the Super-Commander if needed
5816 if game.state.nscrem > 0:
5818 w = randplace(GALSIZE)
5821 game.state.kscmdr = w
5822 game.state.galaxy[w.x][w.y].klingons += 1
5823 # Initialize times for extraneous events
5824 schedule(FSNOVA, expran(0.5 * game.intime))
5825 schedule(FTBEAM, expran(1.5 * (game.intime / len(game.state.kcmdr))))
5826 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5827 schedule(FBATTAK, expran(0.3*game.intime))
5829 if game.state.nscrem:
5830 schedule(FSCMOVE, 0.2777)
5835 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5836 schedule(FDISTR, expran(1.0 + game.intime))
5841 # Place thing (in tournament game, we don't want one!)
5843 if game.tourn is None:
5844 thing = randplace(GALSIZE)
5846 game.state.snap = False
5847 if game.skill == SKILL_NOVICE:
5848 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5849 prout(_("a deadly Klingon invasion force. As captain of the United"))
5850 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5851 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5852 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5853 prout(_("your mission. As you proceed you may be given more time."))
5855 prout(_("You will have %d supporting starbases.") % (game.inbase))
5856 proutn(_("Starbase locations- "))
5858 prout(_("Stardate %d.") % int(game.state.date))
5860 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5861 prout(_("An unknown number of Romulans."))
5862 if game.state.nscrem:
5863 prout(_("And one (GULP) Super-Commander."))
5864 prout(_("%d stardates.") % int(game.intime))
5865 proutn(_("%d starbases in ") % game.inbase)
5866 for i in range(game.inbase):
5867 proutn(`game.state.baseq[i]`)
5870 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5871 proutn(_(" Sector %s") % game.sector)
5873 prout(_("Good Luck!"))
5874 if game.state.nscrem:
5875 prout(_(" YOU'LL NEED IT."))
5878 if len(game.enemies) - (thing == game.quadrant) - (game.tholian != None):
5880 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5881 attack(torps_ok=False)
5884 "Choose your game type."
5889 game.skill = SKILL_NONE
5891 if not scanner.inqueue: # Can start with command line options
5892 proutn(_("Would you like a regular, tournament, or saved game? "))
5894 if len(scanner.token)==0: # Try again
5896 if scanner.sees("tournament"):
5897 while scanner.next() == IHEOL:
5898 proutn(_("Type in tournament number-"))
5899 if scanner.real == 0:
5901 continue # We don't want a blank entry
5902 game.tourn = int(round(scanner.real))
5903 random.seed(scanner.real)
5905 logfp.write("# random.seed(%d)\n" % scanner.real)
5907 if scanner.sees("saved") or scanner.sees("frozen"):
5911 if game.passwd == None:
5913 if not game.alldone:
5914 game.thawed = True # No plaque if not finished
5918 if scanner.sees("regular"):
5920 proutn(_("What is \"%s\"?") % scanner.token)
5922 while game.length==0 or game.skill==SKILL_NONE:
5923 if scanner.next() == IHALPHA:
5924 if scanner.sees("short"):
5926 elif scanner.sees("medium"):
5928 elif scanner.sees("long"):
5930 elif scanner.sees("novice"):
5931 game.skill = SKILL_NOVICE
5932 elif scanner.sees("fair"):
5933 game.skill = SKILL_FAIR
5934 elif scanner.sees("good"):
5935 game.skill = SKILL_GOOD
5936 elif scanner.sees("expert"):
5937 game.skill = SKILL_EXPERT
5938 elif scanner.sees("emeritus"):
5939 game.skill = SKILL_EMERITUS
5941 proutn(_("What is \""))
5942 proutn(scanner.token)
5947 proutn(_("Would you like a Short, Medium, or Long game? "))
5948 elif game.skill == SKILL_NONE:
5949 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
5950 # Choose game options -- added by ESR for SST2K
5951 if scanner.next() != IHALPHA:
5953 proutn(_("Choose your game style (or just press enter): "))
5955 if scanner.sees("plain"):
5956 # Approximates the UT FORTRAN version.
5957 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5958 game.options |= OPTION_PLAIN
5959 elif scanner.sees("almy"):
5960 # Approximates Tom Almy's version.
5961 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5962 game.options |= OPTION_ALMY
5963 elif scanner.sees("fancy"):
5965 elif len(scanner.token):
5966 proutn(_("What is \"%s\"?") % scanner.token)
5968 if game.passwd == "debug":
5970 prout("=== Debug mode enabled.")
5971 # Use parameters to generate initial values of things
5972 game.damfac = 0.5 * game.skill
5973 game.inbase = randrange(BASEMIN, BASEMAX+1)
5975 if game.options & OPTION_PLANETS:
5976 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
5977 if game.options & OPTION_WORLDS:
5978 game.inplan += int(NINHAB)
5979 game.state.nromrem = game.inrom = randrange(2 *game.skill)
5980 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
5981 game.state.remtime = 7.0 * game.length
5982 game.intime = game.state.remtime
5983 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
5984 game.incom = min(MINCMDR, int(game.skill + 0.0625*game.inkling*randreal()))
5985 game.state.remres = (game.inkling+4*game.incom)*game.intime
5986 game.inresor = game.state.remres
5987 if game.inkling > 50:
5988 game.state.inbase += 1
5991 def dropin(iquad=None):
5992 "Drop a feature on a random dot in the current quadrant."
5995 w = randplace(QUADSIZE)
5996 if game.quad[w.x][w.y] == IHDOT:
5998 if iquad is not None:
5999 game.quad[w.x][w.y] = iquad
6003 "Update our alert status."
6004 game.condition = "green"
6005 if game.energy < 1000.0:
6006 game.condition = "yellow"
6007 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6008 game.condition = "red"
6010 game.condition="dead"
6013 "Drop new Klingon into current quadrant."
6014 return enemy(IHK, loc=dropin(), power=randreal(300,450)+25.0*game.skill)
6017 "Set up a new state of quadrant, for when we enter or re-enter it."
6024 game.inorbit = False
6026 game.ientesc = False
6027 game.iseenit = False
6028 # Create a blank quadrant
6029 game.quad = fill2d(QUADSIZE, lambda i, j: IHDOT)
6031 # Attempt to escape Super-commander, so tbeam back!
6034 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6035 # cope with supernova
6038 game.klhere = q.klingons
6039 game.irhere = q.romulans
6041 game.quad[game.sector.x][game.sector.y] = game.ship
6044 # Position ordinary Klingons
6045 for i in range(game.klhere):
6047 # If we need a commander, promote a Klingon
6048 for cmdr in game.state.kcmdr:
6049 if cmdr == game.quadrant:
6050 e = game.enemies[game.klhere-1]
6051 game.quad[e.kloc.x][e.kloc.y] = IHC
6052 e.kpower = randreal(950,1350) + 50.0*game.skill
6054 # If we need a super-commander, promote a Klingon
6055 if game.quadrant == game.state.kscmdr:
6057 game.quad[e.kloc.x][e.kloc.y] = IHS
6058 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
6059 game.iscate = (game.state.remkl > 1)
6060 # Put in Romulans if needed
6061 for i in range(q.romulans):
6062 enemy(IHR, loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
6063 # If quadrant needs a starbase, put it in
6065 game.base = dropin(IHB)
6066 # If quadrant needs a planet, put it in
6068 game.iplnet = q.planet
6069 if not q.planet.inhabited:
6070 game.plnet = dropin(IHP)
6072 game.plnet = dropin(IHW)
6073 # Check for condition
6076 if game.irhere > 0 and game.klhere == 0:
6078 if not damaged(DRADIO):
6080 prout(_("LT. Uhura- \"Captain, an urgent message."))
6081 prout(_(" I'll put it on audio.\" CLICK"))
6083 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6084 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6086 # Put in THING if needed
6087 if thing == game.quadrant:
6088 enemy(type=IHQUEST, loc=dropin(),
6089 power=randreal(6000,6500.0)+250.0*game.skill)
6090 if not damaged(DSRSENS):
6092 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6093 prout(_(" Please examine your short-range scan.\""))
6094 # Decide if quadrant needs a Tholian; lighten up if skill is low
6095 if game.options & OPTION_THOLIAN:
6096 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6097 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6098 (game.skill > SKILL_GOOD and withprob(0.08)):
6101 w.x = withprob(0.5) * (QUADSIZE-1)
6102 w.y = withprob(0.5) * (QUADSIZE-1)
6103 if game.quad[w.x][w.y] == IHDOT:
6105 game.tholian = enemy(type=IHT, loc=w,
6106 power=randrange(100, 500) + 25.0*game.skill)
6107 # Reserve unoccupied corners
6108 if game.quad[0][0]==IHDOT:
6109 game.quad[0][0] = 'X'
6110 if game.quad[0][QUADSIZE-1]==IHDOT:
6111 game.quad[0][QUADSIZE-1] = 'X'
6112 if game.quad[QUADSIZE-1][0]==IHDOT:
6113 game.quad[QUADSIZE-1][0] = 'X'
6114 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6115 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6116 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
6117 # And finally the stars
6118 for i in range(q.stars):
6120 # Put in a few black holes
6121 for i in range(1, 3+1):
6124 # Take out X's in corners if Tholian present
6126 if game.quad[0][0]=='X':
6127 game.quad[0][0] = IHDOT
6128 if game.quad[0][QUADSIZE-1]=='X':
6129 game.quad[0][QUADSIZE-1] = IHDOT
6130 if game.quad[QUADSIZE-1][0]=='X':
6131 game.quad[QUADSIZE-1][0] = IHDOT
6132 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6133 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6136 "Set the self-destruct password."
6137 if game.options & OPTION_PLAIN:
6140 proutn(_("Please type in a secret password- "))
6142 game.passwd = scanner.token
6143 if game.passwd != None:
6148 game.passwd += chr(ord('a')+randrange(26))
6150 # Code from sst.c begins here
6153 "SRSCAN": OPTION_TTY,
6154 "STATUS": OPTION_TTY,
6155 "REQUEST": OPTION_TTY,
6156 "LRSCAN": OPTION_TTY,
6169 "SENSORS": OPTION_PLANETS,
6170 "ORBIT": OPTION_PLANETS,
6171 "TRANSPORT": OPTION_PLANETS,
6172 "MINE": OPTION_PLANETS,
6173 "CRYSTALS": OPTION_PLANETS,
6174 "SHUTTLE": OPTION_PLANETS,
6175 "PLANETS": OPTION_PLANETS,
6180 "PROBE": OPTION_PROBE,
6182 "FREEZE": 0, # Synonym for SAVE
6188 "SOS": 0, # Synonym for MAYDAY
6189 "CALL": 0, # Synonym for MAYDAY
6194 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6197 "Generate a list of legal commands."
6199 proutn(_("LEGAL COMMANDS ARE:"))
6200 for key in commands:
6204 proutn("%-12s " % key)
6209 "Browse on-line help."
6210 key = scanner.next()
6213 setwnd(prompt_window)
6214 proutn(_("Help on what command? "))
6215 key = scanner.next()
6216 setwnd(message_window)
6219 if scanner.token in commands or scanner.token == "ABBREV":
6226 cmd = scanner.token.upper()
6228 fp = open(SSTDOC, "r")
6231 fp = open(DOC_NAME, "r")
6233 prout(_("Spock- \"Captain, that information is missing from the"))
6234 proutn(_(" computer. You need to find "))
6236 prout(_(" and put it in the"))
6237 proutn(_(" current directory or to "))
6241 # This used to continue: "You need to find SST.DOC and put
6242 # it in the current directory."
6246 linebuf = fp.readline()
6248 prout(_("Spock- \"Captain, there is no information on that command.\""))
6251 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6252 linebuf = linebuf[3:].strip()
6256 prout(_("Spock- \"Captain, I've found the following information:\""))
6258 while linebuf in fp:
6259 if "******" in linebuf:
6265 "Command-interpretation loop."
6268 setwnd(message_window)
6269 while True: # command loop
6271 while True: # get a command
6276 setwnd(prompt_window)
6279 if scanner.next() == IHEOL:
6280 if game.options & OPTION_CURSES:
6283 elif scanner.token == "":
6287 setwnd(message_window)
6289 candidates = filter(lambda x: x.startswith(scanner.token.upper()),
6291 if len(candidates) == 1:
6294 elif candidates and not (game.options & OPTION_PLAIN):
6295 prout("Commands with prefix '%s': %s" % (scanner.token, " ".join(candidates)))
6299 if cmd == "SRSCAN": # srscan
6301 elif cmd == "STATUS": # status
6303 elif cmd == "REQUEST": # status request
6305 elif cmd == "LRSCAN": # long range scan
6306 lrscan(silent=False)
6307 elif cmd == "PHASERS": # phasers
6311 elif cmd == "TORPEDO": # photon torpedos
6315 elif cmd == "MOVE": # move under warp
6317 elif cmd == "SHIELDS": # shields
6318 doshield(shraise=False)
6321 game.shldchg = False
6322 elif cmd == "DOCK": # dock at starbase
6325 attack(torps_ok=False)
6326 elif cmd == "DAMAGES": # damage reports
6328 elif cmd == "CHART": # chart
6330 elif cmd == "IMPULSE": # impulse
6332 elif cmd == "REST": # rest
6336 elif cmd == "WARP": # warp
6338 elif cmd == "SCORE": # score
6340 elif cmd == "SENSORS": # sensors
6342 elif cmd == "ORBIT": # orbit
6346 elif cmd == "TRANSPORT": # transport "beam"
6348 elif cmd == "MINE": # mine
6352 elif cmd == "CRYSTALS": # crystals
6356 elif cmd == "SHUTTLE": # shuttle
6360 elif cmd == "PLANETS": # Planet list
6362 elif cmd == "REPORT": # Game Report
6364 elif cmd == "COMPUTER": # use COMPUTER!
6366 elif cmd == "COMMANDS":
6368 elif cmd == "EMEXIT": # Emergency exit
6369 clrscr() # Hide screen
6370 freeze(True) # forced save
6371 raise SysExit,1 # And quick exit
6372 elif cmd == "PROBE":
6373 probe() # Launch probe
6376 elif cmd == "ABANDON": # Abandon Ship
6378 elif cmd == "DESTRUCT": # Self Destruct
6380 elif cmd == "SAVE": # Save Game
6383 if game.skill > SKILL_GOOD:
6384 prout(_("WARNING--Saved games produce no plaques!"))
6385 elif cmd == "DEATHRAY": # Try a desparation measure
6389 elif cmd == "DEBUGCMD": # What do we want for debug???
6391 elif cmd == "MAYDAY": # Call for help
6396 game.alldone = True # quit the game
6401 break # Game has ended
6402 if game.optime != 0.0:
6405 break # Events did us in
6406 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6409 if hitme and not game.justin:
6410 attack(torps_ok=True)
6413 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6424 "Emit the name of an enemy or feature."
6425 if cmd == IHR: s = _("Romulan")
6426 elif cmd == IHK: s = _("Klingon")
6427 elif cmd == IHC: s = _("Commander")
6428 elif cmd == IHS: s = _("Super-commander")
6429 elif cmd == IHSTAR: s = _("Star")
6430 elif cmd == IHP: s = _("Planet")
6431 elif cmd == IHB: s = _("Starbase")
6432 elif cmd == IHBLANK: s = _("Black hole")
6433 elif cmd == IHT: s = _("Tholian")
6434 elif cmd == IHWEB: s = _("Tholian web")
6435 elif cmd == IHQUEST: s = _("Stranger")
6436 elif cmd == IHW: s = _("Inhabited World")
6437 else: s = "Unknown??"
6440 def crmena(stars, enemy, loctype, w):
6441 "Emit the name of an enemy and his location."
6447 if loctype == "quadrant":
6448 buf = _("Quadrant ")
6449 elif loctype == "sector":
6454 "Emit our ship name."
6455 if game.ship == IHE:
6457 elif game.ship == IHF:
6458 s = _("Faerie Queene")
6464 "Emit a line of stars"
6465 prouts("******************************************************")
6469 return -avrage*math.log(1e-7 + randreal())
6471 def randplace(size):
6472 "Choose a random location."
6474 w.x = randrange(size)
6475 w.y = randrange(size)
6485 # Get a token from the user
6488 # Fill the token quue if nothing here
6489 while not self.inqueue:
6491 if curwnd==prompt_window:
6493 setwnd(message_window)
6497 # Skip leading white space
6498 line = line.lstrip()
6502 self.inqueue = line.lstrip().split() + [IHEOL]
6503 # From here on in it's all looking at the queue
6504 self.token = self.inqueue.pop(0)
6505 if self.token == IHEOL:
6509 self.real = float(self.token)
6515 self.token = self.token.lower()
6519 def push(self, tok):
6520 self.inqueue.append(tok)
6524 # Demand input for next scan
6526 self.real = self.token = None
6528 # return IHEOL next time
6529 self.inqueue = [IHEOL]
6530 self.real = self.token = None
6532 # compares s to item and returns true if it matches to the length of s
6533 return s.startswith(self.token)
6535 # Round token value to nearest integer
6536 return int(round(scanner.real))
6540 if scanner.type != IHREAL:
6543 s.x = scanner.int()-1
6545 if scanner.type != IHREAL:
6548 s.y = scanner.int()-1
6552 "Yes-or-no confirmation."
6557 if scanner.token == 'y':
6559 if scanner.token == 'n':
6561 proutn(_("Please answer with \"y\" or \"n\": "))
6564 "Complain about unparseable input."
6567 prout(_("Beg your pardon, Captain?"))
6570 "Access to the internals for debugging."
6571 proutn("Reset levels? ")
6573 if game.energy < game.inenrg:
6574 game.energy = game.inenrg
6575 game.shield = game.inshld
6576 game.torps = game.intorps
6577 game.lsupres = game.inlsr
6578 proutn("Reset damage? ")
6580 for i in range(NDEVICES):
6581 if game.damage[i] > 0.0:
6582 game.damage[i] = 0.0
6583 proutn("Toggle debug flag? ")
6587 prout("Debug output ON")
6589 prout("Debug output OFF")
6590 proutn("Cause selective damage? ")
6592 for i in range(NDEVICES):
6597 key = scanner.next()
6598 if key == IHALPHA and scanner.sees("y"):
6599 game.damage[i] = 10.0
6600 proutn("Examine/change events? ")
6605 FSNOVA: "Supernova ",
6608 FBATTAK: "Base Attack ",
6609 FCDBAS: "Base Destroy ",
6610 FSCMOVE: "SC Move ",
6611 FSCDBAS: "SC Base Destroy ",
6612 FDSPROB: "Probe Move ",
6613 FDISTR: "Distress Call ",
6614 FENSLV: "Enslavement ",
6615 FREPRO: "Klingon Build ",
6617 for i in range(1, NEVENTS):
6620 proutn("%.2f" % (scheduled(i)-game.state.date))
6621 if i == FENSLV or i == FREPRO:
6623 proutn(" in %s" % ev.quadrant)
6628 key = scanner.next()
6633 ev = schedule(i, scanner.real)
6634 if i == FENSLV or i == FREPRO:
6636 proutn("In quadrant- ")
6637 key = scanner.next()
6638 # IHEOL says to leave coordinates as they are
6641 prout("Event %d canceled, no x coordinate." % (i))
6644 w.x = int(round(scanner.real))
6645 key = scanner.next()
6647 prout("Event %d canceled, no y coordinate." % (i))
6650 w.y = int(round(scanner.real))
6653 proutn("Induce supernova here? ")
6655 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6658 if __name__ == '__main__':
6660 global line, thing, game, idebug
6666 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6667 # Disable curses mode until the game logic is working.
6668 # if os.getenv("TERM"):
6669 # game.options |= OPTION_CURSES | OPTION_SHOWME
6671 game.options |= OPTION_TTY
6672 seed = int(time.time())
6673 (options, arguments) = getopt.getopt(sys.argv[1:], "r:s:tx")
6674 for (switch, val) in options:
6677 replayfp = open(val, "r")
6679 sys.stderr.write("sst: can't open replay file %s\n" % val)
6682 line = replayfp.readline().strip()
6683 (leader, key, seed) = line.split()
6685 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6686 line = replayfp.readline().strip()
6687 arguments += line.split()[2:]
6689 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6691 game.options |= OPTION_TTY
6692 game.options &=~ OPTION_CURSES
6693 elif switch == '-s':
6695 elif switch == '-t':
6696 game.options |= OPTION_TTY
6697 game.options &=~ OPTION_CURSES
6698 elif switch == '-x':
6701 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6703 # where to save the input in case of bugs
6705 logfp = open("/usr/tmp/sst-input.log", "w")
6707 sys.stderr.write("sst: warning, can't open logfile\n")
6709 logfp.write("# seed %s\n" % seed)
6710 logfp.write("# options %s\n" % " ".join(arguments))
6712 scanner = sstscanner()
6713 map(scanner.push, arguments)
6716 while True: # Play a game
6717 setwnd(fullscreen_window)
6723 game.alldone = False
6729 if game.tourn and game.alldone:
6730 proutn(_("Do you want your score recorded?"))
6735 proutn(_("Do you want to play again? "))
6739 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6743 except KeyboardInterrupt: