3 sst.py =-- Super Star Trek in Python
5 This code is a Python translation of a C translation of a FORTRAN original.
6 The FORTRANness still shows in many ways, notably the use of a lot of
7 parallel arrays where a more modern language would use structures
8 or objects. (However, 1-origin array indexing was fixed.)
12 SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON,
13 LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE
14 were in the original non-"super" version of UT FORTRAN Star Trek.
16 Tholians were not in the original. Dave is dubious about their merits.
17 (They are now controlled by OPTION_THOLIAN and turned off if the game
20 Planets and dilithium crystals were not in the original. Dave is OK
21 with this idea. (It's now controlled by OPTION_PLANETS and turned
22 off if the game type is "plain".)
24 Dave says the bit about the Galileo getting turned into a
25 McDonald's is "consistant with our original vision". (This has been
26 left permanently enabled, as it can only happen if OPTION_PLANETS
29 Dave also says the Space Thingy should not be preserved across saved
30 games, so you can't prove to others that you've seen it. He says it
31 shouldn't fire back, either. It should do nothing except scream and
32 disappear when hit by photon torpedos. It's OK that it may move
33 when attacked, but it didn't in the original. (Whether the Thingy
34 can fire back is now controlled by OPTION_THINGY and turned off if the
35 game type is "plain" or "almy". The no-save behavior has been restored.)
37 The Faerie Queen, black holes, and time warping were in the original.
39 Here are Tom Almy's changes:
41 In early 1997, I got the bright idea to look for references to
42 "Super Star Trek" on the World Wide Web. There weren't many hits,
43 but there was one that came up with 1979 Fortran sources! This
44 version had a few additional features that mine didn't have,
45 however mine had some feature it didn't have. So I merged its
46 features that I liked. I also took a peek at the DECUS version (a
47 port, less sources, to the PDP-10), and some other variations.
49 1, Compared to the original UT version, I've changed the "help" command to
50 "call" and the "terminate" command to "quit" to better match
51 user expectations. The DECUS version apparently made those changes
52 as well as changing "freeze" to "save". However I like "freeze".
53 (Both "freeze" and "save" work in SST2K.)
55 2. The experimental deathray originally had only a 5% chance of
56 success, but could be used repeatedly. I guess after a couple
57 years of use, it was less "experimental" because the 1979
58 version had a 70% success rate. However it was prone to breaking
59 after use. I upgraded the deathray, but kept the original set of
60 failure modes (great humor!). (Now controlled by OPTION_DEATHRAY
61 and turned off if game type is "plain".)
63 3. The 1979 version also mentions srscan and lrscan working when
64 docked (using the starbase's scanners), so I made some changes here
65 to do this (and indicating that fact to the player), and then realized
66 the base would have a subspace radio as well -- doing a Chart when docked
67 updates the star chart, and all radio reports will be heard. The Dock
68 command will also give a report if a base is under attack.
70 4. Tholian Web from the 1979 version. (Now controlled by
71 OPTION_THOLIAN and turned off if game type is "plain".)
73 5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING
74 and turned off if game type is "plain".)
76 6. Regular Klingons and Romulans can move in Expert and Emeritus games.
77 This code could use improvement. (Now controlled by OPTION_MVBADDY
78 and turned off if game type is "plain".)
80 7. The deep-space probe feature from the DECUS version. (Now controlled
81 by OPTION_PROBE and turned off if game type is "plain").
83 8. 'emexit' command from the 1979 version.
85 9. Bugfix: Klingon commander movements are no longer reported if long-range
88 10. Bugfix: Better base positioning at startup (more spread out).
89 That made sense to add because most people abort games with
92 In June 2002, I fixed two known bugs and a documentation typo.
93 In June 2004 I fixed a number of bugs involving: 1) parsing invalid
94 numbers, 2) manual phasers when SR scan is damaged and commander is
95 present, 3) time warping into the future, 4) hang when moving
96 klingons in crowded quadrants. (These fixes are in SST2K.)
98 Here are Stas Sergeev's changes:
100 1. The Space Thingy can be shoved, if you ram it, and can fire back if
101 fired upon. (Now controlled by OPTION_THINGY and turned off if game
102 type is "plain" or "almy".)
104 2. When you are docked, base covers you with an almost invincible shield.
105 (A commander can still ram you, or a Romulan can destroy the base,
106 or a SCom can even succeed with direct attack IIRC, but this rarely
107 happens.) (Now controlled by OPTION_BASE and turned off if game
108 type is "plain" or "almy".)
110 3. Ramming a black hole is no longer instant death. There is a
111 chance you might get timewarped instead. (Now controlled by
112 OPTION_BLKHOLE and turned off if game type is "plain" or "almy".)
114 4. The Tholian can be hit with phasers.
116 5. SCom can't escape from you if no more enemies remain
117 (without this, chasing SCom can take an eternity).
119 6. Probe target you enter is now the destination quadrant. Before I don't
120 remember what it was, but it was something I had difficulty using.
122 7. Secret password is now autogenerated.
124 8. "Plaque" is adjusted for A4 paper :-)
126 9. Phasers now tells you how much energy needed, but only if the computer
129 10. Planets are auto-scanned when you enter the quadrant.
131 11. Mining or using crystals in presense of enemy now yields an attack.
132 There are other minor adjustments to what yields an attack
135 12. "freeze" command reverts to "save", most people will understand this
136 better anyway. (SST2K recognizes both.)
138 13. Screen-oriented interface, with sensor scans always up. (SST2K
139 supports both screen-oriented and TTY modes.)
141 Eric Raymond's changes:
143 Mainly, I translated this C code out of FORTRAN into C -- created #defines
144 for a lot of magic numbers and refactored the heck out of it.
146 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
148 2. Status report now indicates when dilithium crystals are on board.
150 3. Per Dave Matuszek's remarks, Thingy state is never saved across games.
152 4. Added game option selection so you can play a close (but not bug-for-
153 bug identical) approximation of older versions.
155 5. Half the quadrants now have inhabited planets, from which one
156 cannot mine dilithium (there will still be the same additional number
157 of dilithium-bearing planets). Torpedoing an inhabited world is *bad*.
158 There is BSD-Trek-like logic for Klingons to attack and enslave
159 inhabited worlds, producing more ships (only is skill is 'good' or
160 better). (Controlled by OPTION_WORLDS and turned off if game
161 type is "plain" or "almy".)
163 6. User input is now logged so we can do regression testing.
165 7. More BSD-Trek features: You can now lose if your entire crew
166 dies in battle. When abandoning ship in a game with inhabited
167 worlds enabled, they must have one in the quadrant to beam down
168 to; otherwise they die in space and this counts heavily against
169 your score. Docking at a starbase replenishes your crew.
171 8. Still more BSD-Trek: we now have a weighted damage table.
172 Also, the nav subsystem (enabling automatic course
173 setting) can be damaged separately from the main computer (which
174 handles weapons targeting, ETA calculation, and self-destruct).
176 After these features were added, I translated this into Python and added
179 9. A long-range scan is done silently whenever you call CHART; thus
180 the LRSCAN command is no longer needed. (Controlled by OPTION_AUTOSCAN
181 and turned off if game type is "plain" or "almy".)
183 import os,sys,math,curses,time,atexit,readline,cPickle,random,getopt,copy
185 SSTDOC = "/usr/share/doc/sst/sst.doc"
188 # Stub to be replaced
189 def _(str): return str
193 NINHAB = (GALSIZE * GALSIZE / 2)
195 PLNETMAX = (NINHAB + MAXUNINHAB)
198 BASEMAX = (GALSIZE * GALSIZE / 12)
201 FULLCREW = 428 # BSD Trek was 387, that's wrong
204 # These functions hide the difference between 0-origin and 1-origin addressing.
205 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
206 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
208 def square(i): return ((i)*(i))
209 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
210 def invalidate(w): w.x = w.y = 0
211 def is_valid(w): return (w.x != 0 and w.y != 0)
213 # How to represent features
238 def __init__(self, x=None, y=None):
241 def invalidate(self):
242 self.x = self.y = None
244 return self.x != None and self.y != None
245 def __eq__(self, other):
246 return other != None and self.x == other.y and self.x == other.y
247 def __add__(self, other):
248 return coord(self.x+self.x, self.y+self.y)
249 def __sub__(self, other):
250 return coord(self.x-self.x, self.y-self.y)
251 def distance(self, other):
252 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
258 s.x = self.x / abs(self.x)
262 s.y = self.y / abs(self.y)
266 s.x = self.x + randrange(-1, 2)
267 s.y = self.y + randrange(-1, 2)
272 if self.x == None or self.y == None:
274 return "%s - %s" % (self.x+1, self.y+1)
279 self.name = None # string-valued if inhabited
280 self.w = coord() # quadrant located
281 self.pclass = None # could be ""M", "N", "O", or "destroyed"
282 self.crystals = "absent"# could be "mined", "present", "absent"
283 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
284 self.inhabited = False # is it inhabites?
295 self.supernova = None
297 self.status = None # Could be "secure", "distressed", "enslaved"
305 def fill2d(size, fillfun):
306 "Fill an empty list in 2D."
308 for i in range(size):
310 for j in range(size):
311 lst[i].append(fillfun(i, j))
316 self.snap = False # snapshot taken
317 self.crew = 0 # crew complement
318 self.remkl = 0 # remaining klingons
319 self.remcom = 0 # remaining commanders
320 self.nscrem = 0 # remaining super commanders
321 self.rembase = 0 # remaining bases
322 self.starkl = 0 # destroyed stars
323 self.basekl = 0 # destroyed bases
324 self.nromrem = 0 # Romulans remaining
325 self.nplankl = 0 # destroyed uninhabited planets
326 self.nworldkl = 0 # destroyed inhabited planets
327 self.planets = [] # Planet information
328 self.date = 0.0 # stardate
329 self.remres = 0 # remaining resources
330 self.remtime = 0 # remaining time
331 self.baseq = [] # Base quadrant coordinates
332 for i in range(BASEMAX):
333 self.baseq.append(coord())
334 self.kcmdr = [] # Commander quadrant coordinates
335 for i in range(QUADSIZE):
336 self.kcmdr.append(coord())
337 self.kscmdr = coord() # Supercommander quadrant coordinates
338 # the galaxy (subscript 0 not used)
339 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
340 # the starchart (subscript 0 not used)
341 self.chart = fill2d(GALSIZE, lambda i, j: page())
345 self.date = None # A real number
346 self.quadrant = None # A coord structure
349 OPTION_ALL = 0xffffffff
350 OPTION_TTY = 0x00000001 # old interface
351 OPTION_CURSES = 0x00000002 # new interface
352 OPTION_IOMODES = 0x00000003 # cover both interfaces
353 OPTION_PLANETS = 0x00000004 # planets and mining
354 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
355 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
356 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
357 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
358 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
359 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
360 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
361 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
362 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
363 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
364 OPTION_PLAIN = 0x01000000 # user chose plain game
365 OPTION_ALMY = 0x02000000 # user chose Almy variant
384 NDEVICES= 16 # Number of devices
393 def damaged(dev): return (game.damage[dev] != 0.0)
394 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
396 # Define future events
397 FSPY = 0 # Spy event happens always (no future[] entry)
398 # can cause SC to tractor beam Enterprise
399 FSNOVA = 1 # Supernova
400 FTBEAM = 2 # Commander tractor beams Enterprise
401 FSNAP = 3 # Snapshot for time warp
402 FBATTAK = 4 # Commander attacks base
403 FCDBAS = 5 # Commander destroys base
404 FSCMOVE = 6 # Supercommander moves (might attack base)
405 FSCDBAS = 7 # Supercommander destroys base
406 FDSPROB = 8 # Move deep space probe
407 FDISTR = 9 # Emit distress call from an inhabited world
408 FENSLV = 10 # Inhabited word is enslaved */
409 FREPRO = 11 # Klingons build a ship in an enslaved system
413 # abstract out the event handling -- underlying data structures will change
414 # when we implement stateful events
416 def findevent(evtype): return game.future[evtype]
419 def __init__(self, loc=None, power=None):
423 self.kloc = coord() # enemy sector location
424 self.kpower = power # enemy energy levels
425 self.kdist = self.kavgd = distance(game.sector, e.kloc)
427 return "<%s=%f>" % (self.kloc, self.kpower) # For debugging
431 self.options = None # Game options
432 self.state = snapshot() # A snapshot structure
433 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
434 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
435 self.damage = [0.0] * NDEVICES # damage encountered
436 self.future = [] # future events
437 for i in range(NEVENTS):
438 self.future.append(event())
439 self.passwd = None; # Self Destruct password
441 self.quadrant = None # where we are in the large
442 self.sector = None # where we are in the small
443 self.tholian = None # coordinates of Tholian
444 self.base = None # position of base in current quadrant
445 self.battle = None # base coordinates being attacked
446 self.plnet = None # location of planet in quadrant
447 self.probec = None # current probe quadrant
448 self.gamewon = False # Finished!
449 self.ididit = False # action taken -- allows enemy to attack
450 self.alive = False # we are alive (not killed)
451 self.justin = False # just entered quadrant
452 self.shldup = False # shields are up
453 self.shldchg = False # shield is changing (affects efficiency)
454 self.comhere = False # commander here
455 self.ishere = False # super-commander in quadrant
456 self.iscate = False # super commander is here
457 self.ientesc = False # attempted escape from supercommander
458 self.resting = False # rest time
459 self.icraft = False # Kirk in Galileo
460 self.landed = False # party on planet (true), on ship (false)
461 self.alldone = False # game is now finished
462 self.neutz = False # Romulan Neutral Zone
463 self.isarmed = False # probe is armed
464 self.inorbit = False # orbiting a planet
465 self.imine = False # mining
466 self.icrystl = False # dilithium crystals aboard
467 self.iseenit = False # seen base attack report
468 self.thawed = False # thawed game
469 self.condition = None # "green", "yellow", "red", "docked", "dead"
470 self.iscraft = None # "onship", "offship", "removed"
471 self.skill = None # Player skill level
472 self.inkling = 0 # initial number of klingons
473 self.inbase = 0 # initial number of bases
474 self.incom = 0 # initial number of commanders
475 self.inscom = 0 # initial number of commanders
476 self.inrom = 0 # initial number of commanders
477 self.instar = 0 # initial stars
478 self.intorps = 0 # initial/max torpedoes
479 self.torps = 0 # number of torpedoes
480 self.ship = 0 # ship type -- 'E' is Enterprise
481 self.abandoned = 0 # count of crew abandoned in space
482 self.length = 0 # length of game
483 self.klhere = 0 # klingons here
484 self.casual = 0 # causalties
485 self.nhelp = 0 # calls for help
486 self.nkinks = 0 # count of energy-barrier crossings
487 self.iplnet = None # planet # in quadrant
488 self.inplan = 0 # initial planets
489 self.nenhere = 0 # number of enemies in quadrant
490 self.irhere = 0 # Romulans in quadrant
491 self.isatb = 0 # =1 if super commander is attacking base
492 self.tourn = None # tournament number
493 self.proben = 0 # number of moves for probe
494 self.nprobes = 0 # number of probes available
495 self.inresor = 0.0 # initial resources
496 self.intime = 0.0 # initial time
497 self.inenrg = 0.0 # initial/max energy
498 self.inshld = 0.0 # initial/max shield
499 self.inlsr = 0.0 # initial life support resources
500 self.indate = 0.0 # initial date
501 self.energy = 0.0 # energy level
502 self.shield = 0.0 # shield level
503 self.warpfac = 0.0 # warp speed
504 self.wfacsq = 0.0 # squared warp factor
505 self.lsupres = 0.0 # life support reserves
506 self.dist = 0.0 # movement distance
507 self.direc = 0.0 # movement direction
508 self.optime = 0.0 # time taken by current operation
509 self.docfac = 0.0 # repair factor when docking (constant?)
510 self.damfac = 0.0 # damage factor
511 self.lastchart = 0.0 # time star chart was last updated
512 self.cryprob = 0.0 # probability that crystal will work
513 self.probex = 0.0 # location of probe
515 self.probeinx = 0.0 # probe x,y increment
516 self.probeiny = 0.0 #
517 self.height = 0.0 # height of orbit around planet
519 # Stas thinks this should be (C expression):
520 # game.state.remkl + game.state.remcom > 0 ?
521 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
522 # He says the existing expression is prone to divide-by-zero errors
523 # after killing the last klingon when score is shown -- perhaps also
524 # if the only remaining klingon is SCOM.
525 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
526 # From enumerated type 'feature'
547 # From enumerated type 'FINTYPE'
571 # From enumerated type 'COLORS'
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, a1)
609 v = args[0] + v*args[1] # returns from [a1, a2)
610 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
613 # Code from ai.c begins here
615 def tryexit(look, ienm, loccom, irun):
616 # a bad guy attempts to bug out
618 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
619 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
620 if not VALID_QUADRANT(iq.x,iq.y) or \
621 game.state.galaxy[iq.x][iq.y].supernova or \
622 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
623 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
625 return False; # Romulans cannot escape!
627 # avoid intruding on another commander's territory
629 for n in range(game.state.remcom):
630 if game.state.kcmdr[n] == iq:
632 # refuse to leave if currently attacking starbase
633 if game.battle == game.quadrant:
635 # don't leave if over 1000 units of energy
636 if game.enemies[loccom].kpower > 1000.0:
638 # print escape message and move out of quadrant.
639 # we know this if either short or long range sensors are working
640 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
641 game.condition == docked:
642 crmena(True, ienm, "sector", game.enemies[loccom].kloc)
643 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
644 # handle local matters related to escape
645 game.quad[game.enemies[loccom].kloc.x][game.enemies[loccom].kloc.y] = IHDOT
646 game.enemies[loccom].kloc = game.enemies[game.nenhere].kloc
647 game.enemies[loccom].kavgd = game.enemies[game.nenhere].kavgd
648 game.enemies[loccom].kpower = game.enemies[game.nenhere].kpower
649 game.enemies[loccom].kdist = game.enemies[game.nenhere].kdist
652 if game.condition != docked:
654 # Handle global matters related to escape
655 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
656 game.state.galaxy[iq.x][iq.y].klingons += 1
662 schedule(FSCMOVE, 0.2777)
666 for n in range(game.state.remcom):
667 if game.state.kcmdr[n] == game.quadrant:
668 game.state.kcmdr[n]=iq
671 return True; # success
674 # The bad-guy movement algorithm:
676 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
677 # If both are operating full strength, force is 1000. If both are damaged,
678 # force is -1000. Having shields down subtracts an additional 1000.
680 # 2. Enemy has forces equal to the energy of the attacker plus
681 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
682 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
684 # Attacker Initial energy levels (nominal):
685 # Klingon Romulan Commander Super-Commander
686 # Novice 400 700 1200
688 # Good 450 800 1300 1750
689 # Expert 475 850 1350 1875
690 # Emeritus 500 900 1400 2000
691 # VARIANCE 75 200 200 200
693 # Enemy vessels only move prior to their attack. In Novice - Good games
694 # only commanders move. In Expert games, all enemy vessels move if there
695 # is a commander present. In Emeritus games all enemy vessels move.
697 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
698 # forces are 1000 greater than Enterprise.
700 # Agressive action on average cuts the distance between the ship and
701 # the enemy to 1/4 the original.
703 # 4. At lower energy advantage, movement units are proportional to the
704 # advantage with a 650 advantage being to hold ground, 800 to move forward
705 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
707 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
708 # retreat, especially at high skill levels.
710 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
713 def movebaddy(com, loccom, ienm):
714 # tactical movement for the bad guys
715 next = coord(); look = coord()
717 # This should probably be just game.comhere + game.ishere
718 if game.skill >= SKILL_EXPERT:
719 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
721 nbaddys = game.comhere + game.ishere
723 dist1 = game.enemies[loccom].kdist
724 mdist = int(dist1 + 0.5); # Nearest integer distance
726 # If SC, check with spy to see if should hi-tail it
728 (game.enemies[loccom].kpower <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
732 # decide whether to advance, retreat, or hold position
733 forces = game.enemies[loccom].kpower+100.0*game.nenhere+400*(nbaddys-1)
735 forces += 1000; # Good for enemy if shield is down!
736 if not damaged(DPHASER) or not damaged(DPHOTON):
737 if damaged(DPHASER): # phasers damaged
740 forces -= 0.2*(game.energy - 2500.0)
741 if damaged(DPHOTON): # photon torpedoes damaged
744 forces -= 50.0*game.torps
746 # phasers and photon tubes both out!
749 if forces <= 1000.0 and game.condition != "docked": # Typical situation
750 motion = ((forces + randreal(200))/150.0) - 5.0
752 if forces > 1000.0: # Very strong -- move in for kill
753 motion = (1.0-square(randreal()))*dist1 + 1.0
754 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
755 motion -= game.skill*(2.0-square(randreal()))
757 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
758 # don't move if no motion
761 # Limit motion according to skill
762 if abs(motion) > game.skill:
767 # calculate preferred number of steps
772 if motion > 0 and nsteps > mdist:
773 nsteps = mdist; # don't overshoot
774 if nsteps > QUADSIZE:
775 nsteps = QUADSIZE; # This shouldn't be necessary
777 nsteps = 1; # This shouldn't be necessary
779 proutn("NSTEPS = %d:" % nsteps)
780 # Compute preferred values of delta X and Y
781 mx = game.sector.x - com.x
782 my = game.sector.y - com.y
783 if 2.0 * abs(mx) < abs(my):
785 if 2.0 * abs(my) < abs(game.sector.x-com.x):
799 for ll in range(nsteps):
801 proutn(" %d" % (ll+1))
802 # Check if preferred position available
814 attempts = 0; # Settle mysterious hang problem
815 while attempts < 20 and not success:
817 if look.x < 0 or look.x >= QUADSIZE:
818 if motion < 0 and tryexit(look, ienm, loccom, irun):
820 if krawlx == mx or my == 0:
822 look.x = next.x + krawlx
824 elif look.y < 0 or look.y >= QUADSIZE:
825 if motion < 0 and tryexit(look, ienm, loccom, irun):
827 if krawly == my or mx == 0:
829 look.y = next.y + krawly
831 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
832 # See if we should ram ship
833 if game.quad[look.x][look.y] == game.ship and \
834 (ienm == IHC or ienm == IHS):
837 if krawlx != mx and my != 0:
838 look.x = next.x + krawlx
840 elif krawly != my and mx != 0:
841 look.y = next.y + krawly
844 break; # we have failed
856 # Put commander in place within same quadrant
857 game.quad[com.x][com.y] = IHDOT
858 game.quad[next.x][next.y] = ienm
861 game.enemies[loccom].kloc = next
862 game.enemies[loccom].kdist = game.enemies[loccom].kavgd = distance(game.sector, next)
863 if not damaged(DSRSENS) or game.condition == docked:
866 proutn(_(" from Sector %s") % com)
867 if game.enemies[loccom].kdist < dist1:
868 proutn(_(" advances to "))
870 proutn(_(" retreats to "))
871 prout("Sector %s." % next)
874 # Klingon tactical movement
877 # Figure out which Klingon is the commander (or Supercommander)
880 for i in range(game.nenhere):
881 w = game.enemies[i].kloc
882 if game.quad[w.x][w.y] == IHC:
886 for i in range(game.nenhere):
887 w = game.enemies[i].kloc
888 if game.quad[w.x][w.y] == IHS:
891 # If skill level is high, move other Klingons and Romulans too!
892 # Move these last so they can base their actions on what the
894 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
895 for i in range(game.nenhere):
896 w = game.enemies[i].kloc
897 if game.quad[w.x][w.y] == IHK or game.quad[w.x][w.y] == IHR:
898 movebaddy(w, i, game.quad[w.x][w.y])
901 def movescom(iq, avoid):
902 # commander movement helper
903 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
904 game.state.galaxy[iq.x][iq.y].supernova or \
905 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
908 # Avoid quadrants with bases if we want to avoid Enterprise
909 for i in range(game.state.rembase):
910 if game.state.baseq[i] == iq:
912 if game.justin and not game.iscate:
915 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
916 game.state.kscmdr = iq
917 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
919 # SC has scooted, Remove him from current quadrant
925 for i in range(game.nenhere):
926 if game.quad[game.enemies[i].kloc.x][game.enemies[i].kloc.y] == IHS:
928 game.quad[game.enemies[i].kloc.x][game.enemies[i].kloc.y] = IHDOT
929 game.enemies[i].kloc = game.enemies[game.nenhere].kloc
930 game.enemies[i].kdist = game.enemies[game.nenhere].kdist
931 game.enemies[i].kavgd = game.enemies[game.nenhere].kavgd
932 game.enemies[i].kpower = game.enemies[game.nenhere].kpower
935 if game.condition!=docked:
938 # check for a helpful planet
939 for i in range(game.inplan):
940 if game.state.planets[i].w == game.state.kscmdr and \
941 game.state.planets[i].crystals == "present":
943 game.state.planets[i].pclass = "destroyed"
944 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = None
947 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
948 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
949 prout(_(" by the Super-commander.\""))
951 return False; # looks good!
953 def supercommander():
954 # move the Super Commander
955 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
958 prout("== SUPERCOMMANDER")
959 # Decide on being active or passive
960 avoid = ((game.incom - game.state.remcom + game.inkling - game.state.remkl)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) or \
961 (game.state.date-game.indate) < 3.0)
962 if not game.iscate and avoid:
963 # compute move away from Enterprise
964 idelta = game.state.kscmdr-game.quadrant
965 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
967 idelta.x = game.state.kscmdr.y-game.quadrant.y
968 idelta.y = game.quadrant.x-game.state.kscmdr.x
970 # compute distances to starbases
971 if game.state.rembase <= 0:
975 sc = game.state.kscmdr
976 for i in range(game.state.rembase):
977 basetbl.append((i, distance(game.state.baseq[i], sc)))
978 if game.state.rembase > 1:
979 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
980 # look for nearest base without a commander, no Enterprise, and
981 # without too many Klingons, and not already under attack.
982 ifindit = iwhichb = 0
983 for i2 in range(game.state.rembase):
984 i = basetbl[i2][0]; # bug in original had it not finding nearest
985 ibq = game.state.baseq[i]
986 if ibq == game.quadrant or ibq == game.battle or \
987 game.state.galaxy[ibq.x][ibq.y].supernova or \
988 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
990 # if there is a commander, and no other base is appropriate,
991 # we will take the one with the commander
992 for j in range(game.state.remcom):
993 if ibq == game.state.kcmdr[j] and ifindit!= 2:
997 if j > game.state.remcom: # no commander -- use this one
1002 return; # Nothing suitable -- wait until next time
1003 ibq = game.state.baseq[iwhichb]
1004 # decide how to move toward base
1005 idelta = ibq - game.state.kscmdr
1006 # Maximum movement is 1 quadrant in either or both axes
1007 idelta = idelta.sgn()
1008 # try moving in both x and y directions
1009 # there was what looked like a bug in the Almy C code here,
1010 # but it might be this translation is just wrong.
1011 iq = game.state.kscmdr + idelta
1012 if movescom(iq, avoid):
1013 # failed -- try some other maneuvers
1014 if idelta.x==0 or idelta.y==0:
1015 # attempt angle move
1017 iq.y = game.state.kscmdr.y + 1
1018 if movescom(iq, avoid):
1019 iq.y = game.state.kscmdr.y - 1
1022 iq.x = game.state.kscmdr.x + 1
1023 if movescom(iq, avoid):
1024 iq.x = game.state.kscmdr.x - 1
1027 # try moving just in x or y
1028 iq.y = game.state.kscmdr.y
1029 if movescom(iq, avoid):
1030 iq.y = game.state.kscmdr.y + idelta.y
1031 iq.x = game.state.kscmdr.x
1034 if game.state.rembase == 0:
1037 for i in range(game.state.rembase):
1038 ibq = game.state.baseq[i]
1039 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
1042 return; # no, don't attack base!
1043 game.iseenit = False
1045 schedule(FSCDBAS, randreal(1.0, 3.0))
1046 if is_scheduled(FCDBAS):
1047 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
1048 if not communicating():
1049 return; # no warning
1052 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1053 % game.state.kscmdr)
1054 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1055 proutn(_(" It can survive until stardate %d.\"") \
1056 % int(scheduled(FSCDBAS)))
1057 if not game.resting:
1059 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1062 game.resting = False
1063 game.optime = 0.0; # actually finished
1065 # Check for intelligence report
1068 (not communicating()) or \
1069 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1072 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1073 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1078 if not game.tholian or game.justin:
1080 if game.tholian.x == 0 and game.tholian.y == 0:
1081 idx = 0; idy = QUADSIZE-1
1082 elif game.tholian.x == 0 and game.tholian.y == QUADSIZE-1:
1083 idx = QUADSIZE-1; idy = QUADSIZE-1
1084 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == QUADSIZE-1:
1085 idx = QUADSIZE-1; idy = 0
1086 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == 0:
1089 # something is wrong!
1092 # do nothing if we are blocked
1093 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1095 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1096 if game.tholian.x != idx:
1098 im = math.fabs(idx - game.tholian.x)*1.0/(idx - game.tholian.x)
1099 while game.tholian.x != idx:
1100 game.tholian.x += im
1101 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1102 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1103 elif game.tholian.y != idy:
1105 im = math.fabs(idy - game.tholian.y)*1.0/(idy - game.tholian.y)
1106 while game.tholian.y != idy:
1107 game.tholian.y += im
1108 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1109 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1110 game.quad[game.tholian.x][game.tholian.y] = IHT
1111 game.enemies[game.nenhere].kloc = game.tholian
1113 # check to see if all holes plugged
1114 for i in range(QUADSIZE):
1115 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1117 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1119 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1121 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1123 # All plugged up -- Tholian splits
1124 game.quad[game.tholian.x][game.tholian.y]=IHWEB
1126 crmena(True, IHT, "sector", game.tholian)
1127 prout(_(" completes web."))
1132 # Code from battle.c begins here
1134 def doshield(shraise):
1135 # change shield status
1143 if isit("transfer"):
1147 if damaged(DSHIELD):
1148 prout(_("Shields damaged and down."))
1155 proutn(_("Do you wish to change shield energy? "))
1157 proutn(_("Energy to transfer to shields- "))
1159 elif damaged(DSHIELD):
1160 prout(_("Shields damaged and down."))
1163 proutn(_("Shields are up. Do you want them down? "))
1170 proutn(_("Shields are down. Do you want them up? "))
1176 if action == "SHUP": # raise shields
1178 prout(_("Shields already up."))
1182 if game.condition != "docked":
1184 prout(_("Shields raised."))
1185 if game.energy <= 0:
1187 prout(_("Shields raising uses up last of energy."))
1192 elif action == "SHDN":
1194 prout(_("Shields already down."))
1198 prout(_("Shields lowered."))
1201 elif action == "NRG":
1202 while scan() != IHREAL:
1204 proutn(_("Energy to transfer to shields- "))
1208 if aaitem > game.energy:
1209 prout(_("Insufficient ship energy."))
1212 if game.shield+aaitem >= game.inshld:
1213 prout(_("Shield energy maximized."))
1214 if game.shield+aaitem > game.inshld:
1215 prout(_("Excess energy requested returned to ship energy"))
1216 game.energy -= game.inshld-game.shield
1217 game.shield = game.inshld
1219 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1220 # Prevent shield drain loophole
1222 prout(_("Engineering to bridge--"))
1223 prout(_(" Scott here. Power circuit problem, Captain."))
1224 prout(_(" I can't drain the shields."))
1227 if game.shield+aaitem < 0:
1228 prout(_("All shield energy transferred to ship."))
1229 game.energy += game.shield
1232 proutn(_("Scotty- \""))
1234 prout(_("Transferring energy to shields.\""))
1236 prout(_("Draining energy from shields.\""))
1237 game.shield += aaitem
1238 game.energy -= aaitem
1242 # choose a device to damage, at random.
1244 # Quoth Eric Allman in the code of BSD-Trek:
1245 # "Under certain conditions you can get a critical hit. This
1246 # sort of hit damages devices. The probability that a given
1247 # device is damaged depends on the device. Well protected
1248 # devices (such as the computer, which is in the core of the
1249 # ship and has considerable redundancy) almost never get
1250 # damaged, whereas devices which are exposed (such as the
1251 # warp engines) or which are particularly delicate (such as
1252 # the transporter) have a much higher probability of being
1255 # This is one place where OPTION_PLAIN does not restore the
1256 # original behavior, which was equiprobable damage across
1257 # all devices. If we wanted that, we'd return randrange(NDEVICES)
1258 # and have done with it. Also, in the original game, DNAVYS
1259 # and DCOMPTR were the same device.
1261 # Instead, we use a table of weights similar to the one from BSD Trek.
1262 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1263 # We don't have a cloaking device. The shuttle got the allocation
1264 # for the cloaking device, then we shaved a half-percent off
1265 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1268 105, # DSRSENS: short range scanners 10.5%
1269 105, # DLRSENS: long range scanners 10.5%
1270 120, # DPHASER: phasers 12.0%
1271 120, # DPHOTON: photon torpedoes 12.0%
1272 25, # DLIFSUP: life support 2.5%
1273 65, # DWARPEN: warp drive 6.5%
1274 70, # DIMPULS: impulse engines 6.5%
1275 145, # DSHIELD: deflector shields 14.5%
1276 30, # DRADIO: subspace radio 3.0%
1277 45, # DSHUTTL: shuttle 4.5%
1278 15, # DCOMPTR: computer 1.5%
1279 20, # NAVCOMP: navigation system 2.0%
1280 75, # DTRANSP: transporter 7.5%
1281 20, # DSHCTRL: high-speed shield controller 2.0%
1282 10, # DDRAY: death ray 1.0%
1283 30, # DDSP: deep-space probes 3.0%
1285 idx = randrange(1000) # weights must sum to 1000
1287 for (i, w) in enumerate(weights):
1291 return None; # we should never get here
1293 def ram(ibumpd, ienm, w):
1294 # make our ship ram something
1295 prouts(_("***RED ALERT! RED ALERT!"))
1297 prout(_("***COLLISION IMMINENT."))
1301 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1303 proutn(_(" rammed by "))
1306 crmena(False, ienm, "sector", w)
1308 proutn(_(" (original position)"))
1310 deadkl(w, ienm, game.sector)
1313 prout(_(" heavily damaged."))
1314 icas = randrange(10, 30)
1315 prout(_("***Sickbay reports %d casualties"), icas)
1317 game.state.crew -= icas
1319 # In the pre-SST2K version, all devices got equiprobably damaged,
1320 # which was silly. Instead, pick up to half the devices at
1321 # random according to our weighting table,
1323 ncrits = randrange(NDEVICES/2)
1324 for m in range(ncrits):
1326 if game.damage[dev] < 0:
1328 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1329 # Damage for at least time of travel!
1330 game.damage[dev] += game.optime + extradm
1332 prout(_("***Shields are down."))
1333 if game.state.remkl + game.state.remcom + game.state.nscrem:
1340 def torpedo(course, r, incoming, i, n):
1341 # let a photon torpedo fly
1344 ac = course + 0.25*r
1345 angle = (15.0-ac)*0.5235988
1346 bullseye = (15.0 - course)*0.5235988
1347 deltax = -math.sin(angle);
1348 deltay = math.cos(angle);
1349 x = incoming.x; y = incoming.y
1350 w = coord(); jw = coord()
1351 w.x = w.y = jw.x = jw.y = 0
1352 bigger = max(math.fabs(deltax), math.fabs(deltay))
1355 if not damaged(DSRSENS) or game.condition=="docked":
1356 setwnd(srscan_window)
1358 setwnd(message_window)
1359 # Loop to move a single torpedo
1360 for l in range(1, 15+1):
1365 if not VALID_SECTOR(w.x, w.y):
1367 iquad=game.quad[w.x][w.y]
1368 tracktorpedo(w, l, i, n, iquad)
1372 setwnd(message_window)
1373 if damaged(DSRSENS) and not game.condition=="docked":
1374 skip(1); # start new line after text track
1375 if iquad in (IHE, IHF): # Hit our ship
1377 proutn(_("Torpedo hits "))
1380 hit = 700.0 + randreal(100) - \
1381 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1382 newcnd(); # we're blown out of dock
1383 # We may be displaced.
1384 if game.landed or game.condition=="docked":
1385 return hit # Cheat if on a planet
1386 ang = angle + 2.5*(randreal()-0.5)
1387 temp = math.fabs(math.sin(ang))
1388 if math.fabs(math.cos(ang)) > temp:
1389 temp = math.fabs(math.cos(ang))
1390 xx = -math.sin(ang)/temp
1391 yy = math.cos(ang)/temp
1394 if not VALID_SECTOR(jw.x, jw.y):
1396 if game.quad[jw.x][jw.y]==IHBLANK:
1399 if game.quad[jw.x][jw.y]!=IHDOT:
1400 # can't move into object
1405 elif iquad in (IHC, IHS): # Hit a commander
1407 crmena(True, iquad, "sector", w)
1408 prout(_(" uses anti-photon device;"))
1409 prout(_(" torpedo neutralized."))
1411 elif iquad in (IHR, IHK): # Hit a regular enemy
1413 for ll in range(game.nenhere):
1414 if w == game.enemies[ll].kloc:
1416 kp = math.fabs(game.enemies[ll].kpower)
1417 h1 = 700.0 + randrange(100) - \
1418 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1422 if game.enemies[ll].kpower < 0:
1423 game.enemies[ll].kpower -= -h1
1425 game.enemies[ll].kpower -= h1
1426 if game.enemies[ll].kpower == 0:
1429 crmena(True, iquad, "sector", w)
1430 # If enemy damaged but not destroyed, try to displace
1431 ang = angle + 2.5*(randreal()-0.5)
1432 temp = math.fabs(math.sin(ang))
1433 if math.fabs(math.cos(ang)) > temp:
1434 temp = math.fabs(math.cos(ang))
1435 xx = -math.sin(ang)/temp
1436 yy = math.cos(ang)/temp
1439 if not VALID_SECTOR(jw.x, jw.y):
1440 prout(_(" damaged but not destroyed."))
1442 if game.quad[jw.x][jw.y]==IHBLANK:
1443 prout(_(" buffeted into black hole."))
1444 deadkl(w, iquad, jw)
1446 if game.quad[jw.x][jw.y]!=IHDOT:
1447 # can't move into object
1448 prout(_(" damaged but not destroyed."))
1450 proutn(_(" damaged--"))
1451 game.enemies[ll].kloc = jw
1454 elif iquad == IHB: # Hit a base
1456 prout(_("***STARBASE DESTROYED.."))
1457 for ll in range(game.state.rembase):
1458 if game.state.baseq[ll] == game.quadrant:
1459 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1461 game.quad[w.x][w.y]=IHDOT
1462 game.state.rembase -= 1
1463 game.base.x=game.base.y=0
1464 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1465 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1466 game.state.basekl += 1
1469 elif iquad == IHP: # Hit a planet
1470 crmena(True, iquad, "sector", w)
1471 prout(_(" destroyed."))
1472 game.state.nplankl += 1
1473 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1474 game.iplnet.pclass = "destroyed"
1476 invalidate(game.plnet)
1477 game.quad[w.x][w.y] = IHDOT
1479 # captain perishes on planet
1482 elif iquad == IHW: # Hit an inhabited world -- very bad!
1483 crmena(True, iquad, "sector", w)
1484 prout(_(" destroyed."))
1485 game.state.nworldkl += 1
1486 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
1487 game.iplnet.pclass = "destroyed"
1489 invalidate(game.plnet)
1490 game.quad[w.x][w.y] = IHDOT
1492 # captain perishes on planet
1494 prout(_("You have just destroyed an inhabited planet."))
1495 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1497 elif iquad == IHSTAR: # Hit a star
1501 crmena(True, IHSTAR, "sector", w)
1502 prout(_(" unaffected by photon blast."))
1504 elif iquad == IHQUEST: # Hit a thingy
1505 if not (game.options & OPTION_THINGY) or withprob(0.3):
1507 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1509 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1511 proutn(_("Mr. Spock-"))
1512 prouts(_(" \"Fascinating!\""))
1517 # Stas Sergeev added the possibility that
1518 # you can shove the Thingy and piss it off.
1519 # It then becomes an enemy and may fire at you.
1525 elif iquad == IHBLANK: # Black hole
1527 crmena(True, IHBLANK, "sector", w)
1528 prout(_(" swallows torpedo."))
1530 elif iquad == IHWEB: # hit the web
1532 prout(_("***Torpedo absorbed by Tholian web."))
1534 elif iquad == IHT: # Hit a Tholian
1535 h1 = 700.0 + randrange(100) - \
1536 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1539 game.quad[w.x][w.y] = IHDOT
1544 crmena(True, IHT, "sector", w)
1546 prout(_(" survives photon blast."))
1548 prout(_(" disappears."))
1549 game.quad[w.x][w.y] = IHWEB
1556 proutn("Don't know how to handle torpedo collision with ")
1557 crmena(True, iquad, "sector", w)
1561 if curwnd!=message_window:
1562 setwnd(message_window)
1564 game.quad[w.x][w.y]=IHDOT
1565 game.quad[jw.x][jw.y]=iquad
1566 prout(_(" displaced by blast to Sector %s ") % jw)
1567 for ll in range(game.nenhere):
1568 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector,game.enemies[ll].kloc)
1572 prout(_("Torpedo missed."))
1576 # critical-hit resolution
1577 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1579 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1580 proutn(_("***CRITICAL HIT--"))
1581 # Select devices and cause damage
1583 for loop1 in range(ncrit):
1586 # Cheat to prevent shuttle damage unless on ship
1587 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1590 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1591 game.damage[j] += extradm
1593 for (i, j) in enumerate(cdam):
1595 if skipcount % 3 == 2 and i < len(cdam)-1:
1600 prout(_(" damaged."))
1601 if damaged(DSHIELD) and game.shldup:
1602 prout(_("***Shields knocked down."))
1605 def attack(torps_ok):
1606 # bad guy attacks us
1607 # torps_ok == false forces use of phasers in an attack
1608 atackd = False; attempt = False; ihurt = False;
1609 hitmax=0.0; hittot=0.0; chgfac=1.0
1612 # game could be over at this point, check
1616 prout("=== ATTACK!")
1617 # Tholian gets to move before attacking
1620 # if you have just entered the RNZ, you'll get a warning
1621 if game.neutz: # The one chance not to be attacked
1624 # commanders get a chance to tac-move towards you
1625 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1627 # if no enemies remain after movement, we're done
1628 if game.nenhere==0 or (game.nenhere==1 and thing == game.quadrant and not iqengry):
1630 # set up partial hits if attack happens during shield status change
1631 pfac = 1.0/game.inshld
1633 chgfac = 0.25 + randreal(0.5)
1635 # message verbosity control
1636 if game.skill <= SKILL_FAIR:
1638 for loop in range(game.nenhere):
1639 if game.enemies[loop].kpower < 0:
1640 continue; # too weak to attack
1641 # compute hit strength and diminish shield power
1643 # Increase chance of photon torpedos if docked or enemy energy low
1644 if game.condition == "docked":
1646 if game.enemies[loop].kpower < 500:
1648 jay = game.enemies[loop].kloc
1649 iquad = game.quad[jay.x][jay.y]
1650 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1652 # different enemies have different probabilities of throwing a torp
1653 usephasers = not torps_ok or \
1654 (iquad == IHK and r > 0.0005) or \
1655 (iquad==IHC and r > 0.015) or \
1656 (iquad==IHR and r > 0.3) or \
1657 (iquad==IHS and r > 0.07) or \
1658 (iquad==IHQUEST and r > 0.05)
1659 if usephasers: # Enemy uses phasers
1660 if game.condition == "docked":
1661 continue; # Don't waste the effort!
1662 attempt = True; # Attempt to attack
1663 dustfac = 0.8 + randreal(0.5)
1664 hit = game.enemies[loop].kpower*math.pow(dustfac,game.enemies[loop].kavgd)
1665 game.enemies[loop].kpower *= 0.75
1666 else: # Enemy uses photon torpedo
1667 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1669 proutn(_("***TORPEDO INCOMING"))
1670 if not damaged(DSRSENS):
1672 crmena(False, iquad, where, jay)
1675 r = (randreal()+randreal())*0.5 - 0.5
1676 r += 0.002*game.enemies[loop].kpower*r
1677 hit = torpedo(course, r, jay, 1, 1)
1678 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1679 finish(FWON); # Klingons did themselves in!
1680 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1681 return; # Supernova or finished
1684 # incoming phaser or torpedo, shields may dissipate it
1685 if game.shldup or game.shldchg or game.condition=="docked":
1686 # shields will take hits
1687 propor = pfac * game.shield
1688 if game.condition =="docked":
1692 hitsh = propor*chgfac*hit+1.0
1694 if absorb > game.shield:
1695 absorb = game.shield
1696 game.shield -= absorb
1698 # taking a hit blasts us out of a starbase dock
1699 if game.condition == "docked":
1701 # but the shields may take care of it
1702 if propor > 0.1 and hit < 0.005*game.energy:
1704 # hit from this opponent got through shields, so take damage
1706 proutn(_("%d unit hit") % int(hit))
1707 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1708 proutn(_(" on the "))
1710 if not damaged(DSRSENS) and usephasers:
1712 crmena(False, iquad, where, jay)
1714 # Decide if hit is critical
1720 if game.energy <= 0:
1721 # Returning home upon your shield, not with it...
1724 if not attempt and game.condition == "docked":
1725 prout(_("***Enemies decide against attacking your ship."))
1728 percent = 100.0*pfac*game.shield+0.5
1730 # Shields fully protect ship
1731 proutn(_("Enemy attack reduces shield strength to "))
1733 # Print message if starship suffered hit(s)
1735 proutn(_("Energy left %2d shields ") % int(game.energy))
1738 elif not damaged(DSHIELD):
1741 proutn(_("damaged, "))
1742 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1743 # Check if anyone was hurt
1744 if hitmax >= 200 or hittot >= 500:
1745 icas = randrange(hittot * 0.015)
1748 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1749 prout(_(" in that last attack.\""))
1751 game.state.crew -= icas
1752 # After attack, reset average distance to enemies
1753 for loop in range(game.nenhere):
1754 game.enemies[loop].kavgd = game.enemies[loop].kdist
1758 def deadkl(w, type, mv):
1759 # kill a Klingon, Tholian, Romulan, or Thingy
1760 # Added mv to allow enemy to "move" before dying
1761 crmena(True, type, "sector", mv)
1762 # Decide what kind of enemy it is and update appropriately
1764 # chalk up a Romulan
1765 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1767 game.state.nromrem -= 1
1771 elif type == IHQUEST:
1777 # Some type of a Klingon
1778 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1781 game.comhere = False
1782 for i in range(game.state.remcom):
1783 if game.state.kcmdr[i] == game.quadrant:
1785 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1786 game.state.kcmdr[game.state.remcom].x = 0
1787 game.state.kcmdr[game.state.remcom].y = 0
1788 game.state.remcom -= 1
1790 if game.state.remcom != 0:
1791 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1793 game.state.remkl -= 1
1795 game.state.nscrem -= 1
1797 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1802 prout("*** Internal error, deadkl() called on %s\n" % type)
1803 # For each kind of enemy, finish message to player
1804 prout(_(" destroyed."))
1805 game.quad[w.x][w.y] = IHDOT
1806 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1809 # Remove enemy ship from arrays describing local conditions
1810 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1812 for i in range(game.nenhere):
1813 if game.enemies[i].kloc == w:
1814 for j in range(i, game.nenhere):
1815 game.enemies[j].kloc = game.enemies[j+1].kloc
1816 game.enemies[j].kpower = game.enemies[j+1].kpower
1817 game.enemies[j].kavgd = game.enemies[j].kdist = game.enemies[j+1].kdist
1818 game.enemies[game.nenhere].kloc.x = 0
1819 game.enemies[game.nenhere].kloc.y = 0
1820 game.enemies[game.nenhere].kdist = 0
1821 game.enemies[game.nenhere].kavgd = 0
1822 game.enemies[game.nenhere].kpower = 0
1828 def targetcheck(x, y):
1829 # Return None if target is invalid
1830 if not VALID_SECTOR(x, y):
1833 deltx = 0.1*(y - game.sector.y)
1834 delty = 0.1*(x - game.sector.x)
1835 if deltx==0 and delty== 0:
1837 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1838 prout(_(" I recommend an immediate review of"))
1839 prout(_(" the Captain's psychological profile.\""))
1842 return 1.90985932*math.atan2(deltx, delty)
1845 # launch photon torpedo
1847 if damaged(DPHOTON):
1848 prout(_("Photon tubes damaged."))
1852 prout(_("No torpedoes left."))
1861 prout(_("%d torpedoes left.") % game.torps)
1862 proutn(_("Number of torpedoes to fire- "))
1864 else: # key == IHREAL {
1866 if n <= 0: # abort command
1871 prout(_("Maximum of 3 torpedoes per burst."))
1878 for i in range(1, n+1):
1880 if i==1 and key == IHEOL:
1881 break; # we will try prompting
1882 if i==2 and key == IHEOL:
1883 # direct all torpedoes at one target
1885 targ[i][1] = targ[1][1]
1886 targ[i][2] = targ[1][2]
1887 course[i] = course[1]
1899 course[i] = targetcheck(targ[i][1], targ[i][2])
1900 if course[i] == None:
1903 if i == 1 and key == IHEOL:
1904 # prompt for each one
1905 for i in range(1, n+1):
1906 proutn(_("Target sector for torpedo number %d- ") % i)
1911 targ[i][1] = int(aaitem-0.5)
1916 targ[i][2] = int(aaitem-0.5)
1918 course[i] = targetcheck(targ[i][1], targ[i][2])
1919 if course[i] == None:
1922 # Loop for moving <n> torpedoes
1924 if game.condition != "docked":
1926 r = (randreal()+randreal())*0.5 -0.5
1927 if math.fabs(r) >= 0.47:
1929 r *= randreal(1.2, 2.2)
1931 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1933 prouts(_("***TORPEDO MISFIRES."))
1936 prout(_(" Remainder of burst aborted."))
1938 prout(_("***Photon tubes damaged by misfire."))
1939 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1941 if game.shldup or game.condition == "docked":
1942 r *= 1.0 + 0.0001*game.shield
1943 torpedo(course[i], r, game.sector, i, n)
1944 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1946 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1950 # check for phasers overheating
1952 checkburn = (rpow-1500.0)*0.00038
1953 if withprob(checkburn):
1954 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1955 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1957 def checkshctrl(rpow):
1958 # check shield control
1961 prout(_("Shields lowered."))
1963 # Something bad has happened
1964 prouts(_("***RED ALERT! RED ALERT!"))
1966 hit = rpow*game.shield/game.inshld
1967 game.energy -= rpow+hit*0.8
1968 game.shield -= hit*0.2
1969 if game.energy <= 0.0:
1970 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1975 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1977 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1978 icas = randrange(hit*0.012)
1983 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1984 prout(_(" %d casualties so far.\"") % icas)
1986 game.state.crew -= icas
1988 prout(_("Phaser energy dispersed by shields."))
1989 prout(_("Enemy unaffected."))
1994 # register a phaser hit on Klingons and Romulans
1995 nenhr2 = game.nenhere; kk=0
1998 for (k, wham) in enumerate(hits):
2001 dustfac = randreal(0.9, 1.0)
2002 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
2003 kpini = game.enemies[kk].kpower
2004 kp = math.fabs(kpini)
2005 if PHASEFAC*hit < kp:
2007 if game.enemies[kk].kpower < 0:
2008 game.enemies[kk].kpower -= -kp
2010 game.enemies[kk].kpower -= kp
2011 kpow = game.enemies[kk].kpower
2012 w = game.enemies[kk].kloc
2014 if not damaged(DSRSENS):
2016 proutn(_("%d unit hit on ") % int(hit))
2018 proutn(_("Very small hit on "))
2019 ienm = game.quad[w.x][w.y]
2023 crmena(False, ienm, "sector", w)
2027 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2031 kk -= 1 # don't do the increment
2033 else: # decide whether or not to emasculate klingon
2034 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
2035 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
2036 prout(_(" has just lost its firepower.\""))
2037 game.enemies[kk].kpower = -kpow
2044 kz = 0; k = 1; irec=0 # Cheating inhibitor
2045 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
2049 # SR sensors and Computer are needed fopr automode
2050 if damaged(DSRSENS) or damaged(DCOMPTR):
2052 if game.condition == "docked":
2053 prout(_("Phasers can't be fired through base shields."))
2056 if damaged(DPHASER):
2057 prout(_("Phaser control damaged."))
2061 if damaged(DSHCTRL):
2062 prout(_("High speed shield control damaged."))
2065 if game.energy <= 200.0:
2066 prout(_("Insufficient energy to activate high-speed shield control."))
2069 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2071 # Original code so convoluted, I re-did it all
2072 # (That was Tom Almy talking about the C code, I think -- ESR)
2073 while automode=="NOTSET":
2078 prout(_("There is no enemy present to select."))
2081 automode="AUTOMATIC"
2085 elif isit("automatic"):
2086 if (not itarg) and game.nenhere != 0:
2087 automode = "FORCEMAN"
2090 prout(_("Energy will be expended into space."))
2091 automode = "AUTOMATIC"
2100 prout(_("Energy will be expended into space."))
2101 automode = "AUTOMATIC"
2103 automode = "FORCEMAN"
2105 automode = "AUTOMATIC"
2109 prout(_("Energy will be expended into space."))
2110 automode = "AUTOMATIC"
2112 automode = "FORCEMAN"
2114 proutn(_("Manual or automatic? "))
2119 if automode == "AUTOMATIC":
2120 if key == IHALPHA and isit("no"):
2123 if key != IHREAL and game.nenhere != 0:
2124 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2129 for i in range(game.nenhere):
2130 irec += math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
2132 proutn(_("%d units required. ") % irec)
2134 proutn(_("Units to fire= "))
2140 proutn(_("Energy available= %.2f") % avail)
2143 if not rpow > avail:
2150 if key == IHALPHA and isit("no"):
2153 game.energy -= 200; # Go and do it!
2154 if checkshctrl(rpow):
2162 for i in range(game.nenhere):
2166 hits[i] = math.fabs(game.enemies[i].kpower)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
2167 over = randreal(1.01, 1.06) * hits[i]
2169 powrem -= hits[i] + over
2170 if powrem <= 0 and temp < hits[i]:
2179 if extra > 0 and not game.alldone:
2181 proutn(_("*** Tholian web absorbs "))
2183 proutn(_("excess "))
2184 prout(_("phaser energy."))
2186 prout(_("%d expended on empty space.") % int(extra))
2187 elif automode == "FORCEMAN":
2190 if damaged(DCOMPTR):
2191 prout(_("Battle computer damaged, manual fire only."))
2194 prouts(_("---WORKING---"))
2196 prout(_("Short-range-sensors-damaged"))
2197 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2198 prout(_("Manual-fire-must-be-used"))
2200 elif automode == "MANUAL":
2202 for k in range(game.nenhere):
2203 aim = game.enemies[k].kloc
2204 ienm = game.quad[aim.x][aim.y]
2206 proutn(_("Energy available= %.2f") % (avail-0.006))
2210 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2211 (ienm == IHC or ienm == IHS):
2213 prout(_(" can't be located without short range scan."))
2216 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2221 if itarg and k > kz:
2222 irec=(abs(game.enemies[k].kpower)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
2225 if not damaged(DCOMPTR):
2230 proutn(_("units to fire at "))
2231 crmena(False, ienm, "sector", aim)
2234 if key == IHALPHA and isit("no"):
2242 if k==1: # Let me say I'm baffled by this
2251 # If total requested is too much, inform and start over
2253 prout(_("Available energy exceeded -- try again."))
2256 key = scan(); # scan for next value
2259 # zero energy -- abort
2262 if key == IHALPHA and isit("no"):
2267 game.energy -= 200.0
2268 if checkshctrl(rpow):
2272 # Say shield raised or malfunction, if necessary
2279 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2280 prouts(_(" CLICK CLICK POP . . ."))
2281 prout(_(" No response, sir!"))
2284 prout(_("Shields raised."))
2289 # Code from events,c begins here.
2291 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2292 # event of each type active at any given time. Mostly these means we can
2293 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2294 # BSD Trek, from which we swiped the idea, can have up to 5.
2296 def unschedule(evtype):
2297 # remove an event from the schedule
2298 game.future[evtype].date = FOREVER
2299 return game.future[evtype]
2301 def is_scheduled(evtype):
2302 # is an event of specified type scheduled
2303 return game.future[evtype].date != FOREVER
2305 def scheduled(evtype):
2306 # when will this event happen?
2307 return game.future[evtype].date
2309 def schedule(evtype, offset):
2310 # schedule an event of specified type
2311 game.future[evtype].date = game.state.date + offset
2312 return game.future[evtype]
2314 def postpone(evtype, offset):
2315 # postpone a scheduled event
2316 game.future[evtype].date += offset
2319 # rest period is interrupted by event
2322 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2324 game.resting = False
2330 # run through the event queue looking for things to do
2332 fintim = game.state.date + game.optime; yank=0
2333 ictbeam = False; istract = False
2334 w = coord(); hold = coord()
2335 ev = event(); ev2 = event()
2337 def tractorbeam(yank):
2338 # tractor beaming cases merge here
2340 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2344 prout(_(" caught in long range tractor beam--"))
2345 # If Kirk & Co. screwing around on planet, handle
2346 atover(True) # atover(true) is Grab
2349 if game.icraft: # Caught in Galileo?
2352 # Check to see if shuttle is aboard
2353 if game.iscraft == "offship":
2356 prout(_("Galileo, left on the planet surface, is captured"))
2357 prout(_("by aliens and made into a flying McDonald's."))
2358 game.damage[DSHUTTL] = -10
2359 game.iscraft = "removed"
2361 prout(_("Galileo, left on the planet surface, is well hidden."))
2363 game.quadrant = game.state.kscmdr
2365 game.quadrant = game.state.kcmdr[i]
2366 game.sector = randplace(QUADSIZE)
2368 prout(_(" is pulled to Quadrant %s, Sector %s") \
2369 % (game.quadrant, game.sector))
2371 prout(_("(Remainder of rest/repair period cancelled.)"))
2372 game.resting = False
2374 if not damaged(DSHIELD) and game.shield > 0:
2375 doshield(shraise=True) # raise shields
2376 game.shldchg = False
2378 prout(_("(Shields not currently useable.)"))
2380 # Adjust finish time to time of tractor beaming
2381 fintim = game.state.date+game.optime
2383 if game.state.remcom <= 0:
2386 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2389 # Code merges here for any commander destroying base
2390 # Not perfect, but will have to do
2391 # Handle case where base is in same quadrant as starship
2392 if game.battle == game.quadrant:
2393 game.state.chart[game.battle.x][game.battle.y].starbase = False
2394 game.quad[game.base.x][game.base.y] = IHDOT
2395 game.base.x=game.base.y=0
2398 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2399 elif game.state.rembase != 1 and communicating():
2400 # Get word via subspace radio
2403 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2404 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2406 prout(_("the Klingon Super-Commander"))
2408 prout(_("a Klingon Commander"))
2409 game.state.chart[game.battle.x][game.battle.y].starbase = False
2410 # Remove Starbase from galaxy
2411 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2412 for i in range(1, game.state.rembase+1):
2413 if game.state.baseq[i] == game.battle:
2414 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2415 game.state.rembase -= 1
2417 # reinstate a commander's base attack
2421 invalidate(game.battle)
2424 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2425 for i in range(1, NEVENTS):
2426 if i == FSNOVA: proutn("=== Supernova ")
2427 elif i == FTBEAM: proutn("=== T Beam ")
2428 elif i == FSNAP: proutn("=== Snapshot ")
2429 elif i == FBATTAK: proutn("=== Base Attack ")
2430 elif i == FCDBAS: proutn("=== Base Destroy ")
2431 elif i == FSCMOVE: proutn("=== SC Move ")
2432 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2433 elif i == FDSPROB: proutn("=== Probe Move ")
2434 elif i == FDISTR: proutn("=== Distress Call ")
2435 elif i == FENSLV: proutn("=== Enslavement ")
2436 elif i == FREPRO: proutn("=== Klingon Build ")
2438 prout("%.2f" % (scheduled(i)))
2441 radio_was_broken = damaged(DRADIO)
2444 # Select earliest extraneous event, evcode==0 if no events
2449 for l in range(1, NEVENTS):
2450 if game.future[l].date < datemin:
2453 prout("== Event %d fires" % evcode)
2454 datemin = game.future[l].date
2455 xtime = datemin-game.state.date
2456 game.state.date = datemin
2457 # Decrement Federation resources and recompute remaining time
2458 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2460 if game.state.remtime <=0:
2463 # Any crew left alive?
2464 if game.state.crew <=0:
2467 # Is life support adequate?
2468 if damaged(DLIFSUP) and game.condition != "docked":
2469 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2472 game.lsupres -= xtime
2473 if game.damage[DLIFSUP] <= xtime:
2474 game.lsupres = game.inlsr
2477 if game.condition == "docked":
2478 repair /= game.docfac
2479 # Don't fix Deathray here
2480 for l in range(NDEVICES):
2481 if game.damage[l] > 0.0 and l != DDRAY:
2482 if game.damage[l]-repair > 0.0:
2483 game.damage[l] -= repair
2485 game.damage[l] = 0.0
2486 # If radio repaired, update star chart and attack reports
2487 if radio_was_broken and not damaged(DRADIO):
2488 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2489 prout(_(" surveillance reports are coming in."))
2491 if not game.iseenit:
2495 prout(_(" The star chart is now up to date.\""))
2497 # Cause extraneous event EVCODE to occur
2498 game.optime -= xtime
2499 if evcode == FSNOVA: # Supernova
2502 schedule(FSNOVA, expran(0.5*game.intime))
2503 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2505 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2506 if game.state.nscrem == 0 or \
2507 ictbeam or istract or \
2508 game.condition=="docked" or game.isatb==1 or game.iscate:
2510 if game.ientesc or \
2511 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2512 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2513 (damaged(DSHIELD) and \
2514 (game.energy < 2500 or damaged(DPHASER)) and \
2515 (game.torps < 5 or damaged(DPHOTON))):
2517 istract = ictbeam = True
2518 tractorbeam(distance(game.state.kscmdr, game.quadrant))
2521 elif evcode == FTBEAM: # Tractor beam
2522 if game.state.remcom == 0:
2525 i = randrange(game.state.remcom)
2526 yank = distance(game.state.kcmdr[i], game.quadrant)
2527 if istract or game.condition == "docked" or yank == 0:
2528 # Drats! Have to reschedule
2530 game.optime + expran(1.5*game.intime/game.state.remcom))
2534 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2535 game.snapsht = copy.deepcopy(game.state)
2536 game.state.snap = True
2537 schedule(FSNAP, expran(0.5 * game.intime))
2538 elif evcode == FBATTAK: # Commander attacks starbase
2539 if game.state.remcom==0 or game.state.rembase==0:
2545 for j in range(game.state.rembase):
2546 for k in range(game.state.remcom):
2547 if game.state.baseq[j] == game.state.kcmdr[k] and \
2548 not game.state.baseq[j] == game.quadrant and \
2549 not game.state.baseq[j] == game.state.kscmdr:
2553 if j>game.state.rembase:
2554 # no match found -- try later
2555 schedule(FBATTAK, expran(0.3*game.intime))
2558 # commander + starbase combination found -- launch attack
2559 game.battle = game.state.baseq[j]
2560 schedule(FCDBAS, randreal(1.0, 4.0))
2561 if game.isatb: # extra time if SC already attacking
2562 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2563 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2564 game.iseenit = False
2565 if not communicating():
2566 continue # No warning :-(
2570 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2571 prout(_(" reports that it is under attack and that it can"))
2572 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2575 elif evcode == FSCDBAS: # Supercommander destroys base
2578 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2579 continue # WAS RETURN!
2581 game.battle = game.state.kscmdr
2583 elif evcode == FCDBAS: # Commander succeeds in destroying base
2586 # find the lucky pair
2587 for i in range(game.state.remcom):
2588 if game.state.kcmdr[i] == game.battle:
2590 if i > game.state.remcom or game.state.rembase == 0 or \
2591 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2592 # No action to take after all
2593 invalidate(game.battle)
2596 elif evcode == FSCMOVE: # Supercommander moves
2597 schedule(FSCMOVE, 0.2777)
2598 if not game.ientesc and not istract and game.isatb != 1 and \
2599 (not game.iscate or not game.justin):
2601 elif evcode == FDSPROB: # Move deep space probe
2602 schedule(FDSPROB, 0.01)
2603 game.probex += game.probeinx
2604 game.probey += game.probeiny
2605 i = (int)(game.probex/QUADSIZE +0.05)
2606 j = (int)(game.probey/QUADSIZE + 0.05)
2607 if game.probec.x != i or game.probec.y != j:
2610 if not VALID_QUADRANT(i, j) or \
2611 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2612 # Left galaxy or ran into supernova
2616 proutn(_("Lt. Uhura- \"The deep space probe "))
2617 if not VALID_QUADRANT(j, i):
2618 proutn(_("has left the galaxy"))
2620 proutn(_("is no longer transmitting"))
2624 if not communicating():
2627 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2628 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2629 # Update star chart if Radio is working or have access to radio
2631 chp = game.state.chart[game.probec.x][game.probec.y]
2632 chp.klingons = pdest.klingons
2633 chp.starbase = pdest.starbase
2634 chp.stars = pdest.stars
2635 pdest.charted = True
2636 game.proben -= 1 # One less to travel
2637 if game.proben == 0 and game.isarmed and pdest.stars:
2638 # lets blow the sucker!
2639 supernova(True, game.probec)
2641 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2643 elif evcode == FDISTR: # inhabited system issues distress call
2645 # try a whole bunch of times to find something suitable
2646 for i in range(100):
2647 # need a quadrant which is not the current one,
2648 # which has some stars which are inhabited and
2649 # not already under attack, which is not
2650 # supernova'ed, and which has some Klingons in it
2651 w = randplace(GALSIZE)
2652 q = game.state.galaxy[w.x][w.y]
2653 if not (game.quadrant == w or q.planet == None or \
2654 not q.planet.inhabited or \
2655 q.supernova or q.status!="secure" or q.klingons<=0):
2658 # can't seem to find one; ignore this call
2660 prout("=== Couldn't find location for distress event.")
2662 # got one!! Schedule its enslavement
2663 ev = schedule(FENSLV, expran(game.intime))
2665 q.status = distressed
2667 # tell the captain about it if we can
2669 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2671 prout(_("by a Klingon invasion fleet."))
2674 elif evcode == FENSLV: # starsystem is enslaved
2675 ev = unschedule(FENSLV)
2676 # see if current distress call still active
2677 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2681 q.status = "enslaved"
2683 # play stork and schedule the first baby
2684 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2685 ev2.quadrant = ev.quadrant
2687 # report the disaster if we can
2689 prout(_("Uhura- We've lost contact with starsystem %s") % \
2691 prout(_("in Quadrant %s.\n") % ev.quadrant)
2692 elif evcode == FREPRO: # Klingon reproduces
2693 # If we ever switch to a real event queue, we'll need to
2694 # explicitly retrieve and restore the x and y.
2695 ev = schedule(FREPRO, expran(1.0 * game.intime))
2696 # see if current distress call still active
2697 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2701 if game.state.remkl >=MAXKLGAME:
2702 continue # full right now
2703 # reproduce one Klingon
2705 if game.klhere >= MAXKLQUAD:
2707 # this quadrant not ok, pick an adjacent one
2708 for i in range(w.x - 1, w.x + 2):
2709 for j in range(w.y - 1, w.y + 2):
2710 if not VALID_QUADRANT(i, j):
2712 q = game.state.galaxy[w.x][w.y]
2713 # check for this quad ok (not full & no snova)
2714 if q.klingons >= MAXKLQUAD or q.supernova:
2718 continue # search for eligible quadrant failed
2723 game.state.remkl += 1
2725 if game.quadrant == w:
2727 game.enemies.append(newkling())
2728 # recompute time left
2730 # report the disaster if we can
2732 if game.quadrant == w:
2733 prout(_("Spock- sensors indicate the Klingons have"))
2734 prout(_("launched a warship from %s.") % q.planet)
2736 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2737 if q.planet != None:
2738 proutn(_("near %s") % q.planet)
2739 prout(_("in Quadrant %s.") % w)
2748 proutn(_("How long? "))
2753 origTime = delay = aaitem
2756 if delay >= game.state.remtime or game.nenhere != 0:
2757 proutn(_("Are you sure? "))
2760 # Alternate resting periods (events) with attacks
2764 game.resting = False
2765 if not game.resting:
2766 prout(_("%d stardates left.") % int(game.state.remtime))
2768 temp = game.optime = delay
2770 rtime = randreal(1.0, 2.0)
2774 if game.optime < delay:
2783 # Repair Deathray if long rest at starbase
2784 if origTime-delay >= 9.99 and game.condition == "docked":
2785 game.damage[DDRAY] = 0.0
2786 # leave if quadrant supernovas
2787 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2789 game.resting = False
2792 # A nova occurs. It is the result of having a star hit with a
2793 # photon torpedo, or possibly of a probe warhead going off.
2794 # Stars that go nova cause stars which surround them to undergo
2795 # the same probabilistic process. Klingons next to them are
2796 # destroyed. And if the starship is next to it, it gets zapped.
2797 # If the zap is too much, it gets destroyed.
2801 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2802 newc = coord(); scratch = coord()
2804 # Wow! We've supernova'ed
2805 supernova(False, nov)
2807 # handle initial nova
2808 game.quad[nov.x][nov.y] = IHDOT
2809 crmena(False, IHSTAR, "sector", nov)
2811 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2812 game.state.starkl += 1
2814 # Set up stack to recursively trigger adjacent stars
2815 bot = top = top2 = 1
2821 for mm in range(bot, top+1):
2822 for nn in range(1, 3+1): # nn,j represents coordinates around current
2823 for j in range(1, 3+1):
2826 scratch.x = hits[mm][1]+nn-2
2827 scratch.y = hits[mm][2]+j-2
2828 if not VALID_SECTOR(scratch.y, scratch.x):
2830 iquad = game.quad[scratch.x][scratch.y]
2831 # Empty space ends reaction
2832 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2834 elif iquad == IHSTAR: # Affect another star
2836 # This star supernovas
2837 scratch = supernova(False)
2840 hits[top2][1]=scratch.x
2841 hits[top2][2]=scratch.y
2842 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2843 game.state.starkl += 1
2844 crmena(True, IHSTAR, "sector", scratch)
2846 game.quad[scratch.x][scratch.y] = IHDOT
2847 elif iquad == IHP: # Destroy planet
2848 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = None
2849 game.state.nplankl += 1
2850 crmena(True, IHP, "sector", scratch)
2851 prout(_(" destroyed."))
2852 game.iplnet.pclass = "destroyed"
2854 invalidate(game.plnet)
2858 game.quad[scratch.x][scratch.y] = IHDOT
2859 elif iquad == IHB: # Destroy base
2860 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2861 for i in range(game.state.rembase):
2862 if game.state.baseq[i] == game.quadrant:
2864 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2865 game.state.rembase -= 1
2866 invalidate(game.base)
2867 game.state.basekl += 1
2869 crmena(True, IHB, "sector", scratch)
2870 prout(_(" destroyed."))
2871 game.quad[scratch.x][scratch.y] = IHDOT
2872 elif iquad in (IHE, IHF): # Buffet ship
2873 prout(_("***Starship buffeted by nova."))
2875 if game.shield >= 2000.0:
2876 game.shield -= 2000.0
2878 diff = 2000.0 - game.shield
2882 prout(_("***Shields knocked out."))
2883 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2885 game.energy -= 2000.0
2886 if game.energy <= 0:
2889 # add in course nova contributes to kicking starship
2890 icx += game.sector.x-hits[mm][1]
2891 icy += game.sector.y-hits[mm][2]
2893 elif iquad == IHK: # kill klingon
2894 deadkl(scratch,iquad, scratch)
2895 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2896 for ll in range(game.nenhere):
2897 if game.enemies[ll].kloc == scratch:
2899 game.enemies[ll].kpower -= 800.0 # If firepower is lost, die
2900 if game.enemies[ll].kpower <= 0.0:
2901 deadkl(scratch, iquad, scratch)
2903 newc.x = scratch.x + scratch.x - hits[mm][1]
2904 newc.y = scratch.y + scratch.y - hits[mm][2]
2905 crmena(True, iquad, "sector", scratch)
2906 proutn(_(" damaged"))
2907 if not VALID_SECTOR(newc.x, newc.y):
2908 # can't leave quadrant
2911 iquad1 = game.quad[newc.x][newc.y]
2912 if iquad1 == IHBLANK:
2913 proutn(_(", blasted into "))
2914 crmena(False, IHBLANK, "sector", newc)
2916 deadkl(scratch, iquad, newc)
2919 # can't move into something else
2922 proutn(_(", buffeted to Sector %s") % newc)
2923 game.quad[scratch.x][scratch.y] = IHDOT
2924 game.quad[newc.x][newc.y] = iquad
2925 game.enemies[ll].kloc = newc
2926 game.enemies[ll].kdist = game.enemies[ll].kavgd = distance(game.sector, newc)
2935 # Starship affected by nova -- kick it away.
2936 game.dist = kount*0.1
2939 game.direc = course[3*(icx+1)+icy+2]
2940 if game.direc == 0.0:
2942 if game.dist == 0.0:
2944 game.optime = 10.0*game.dist/16.0
2946 prout(_("Force of nova displaces starship."))
2947 imove(novapush=True)
2948 game.optime = 10.0*game.dist/16.0
2951 def supernova(induced, w=None):
2952 # star goes supernova
2959 # Scheduled supernova -- select star
2960 # logic changed here so that we won't favor quadrants in top
2962 for nq.x in range(GALSIZE):
2963 for nq.y in range(GALSIZE):
2964 stars += game.state.galaxy[nq.x][nq.y].stars
2966 return # nothing to supernova exists
2967 num = randrange(stars) + 1
2968 for nq.x in range(GALSIZE):
2969 for nq.y in range(GALSIZE):
2970 num -= game.state.galaxy[nq.x][nq.y].stars
2976 proutn("=== Super nova here?")
2979 if not nq == game.quadrant or game.justin:
2980 # it isn't here, or we just entered (treat as enroute)
2983 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2984 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2987 # we are in the quadrant!
2988 num = randrange(game.state.galaxy[nq.x][nq.y].stars) + 1
2989 for ns.x in range(QUADSIZE):
2990 for ns.y in range(QUADSIZE):
2991 if game.quad[ns.x][ns.y]==IHSTAR:
2998 prouts(_("***RED ALERT! RED ALERT!"))
3000 prout(_("***Incipient supernova detected at Sector %s") % ns)
3001 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
3002 proutn(_("Emergency override attempts t"))
3003 prouts("***************")
3008 # destroy any Klingons in supernovaed quadrant
3009 kldead = game.state.galaxy[nq.x][nq.y].klingons
3010 game.state.galaxy[nq.x][nq.y].klingons = 0
3011 if nq == game.state.kscmdr:
3012 # did in the Supercommander!
3013 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
3017 if game.state.remcom:
3018 maxloop = game.state.remcom
3019 for l in range(maxloop):
3020 if game.state.kcmdr[l] == nq:
3021 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
3022 invalidate(game.state.kcmdr[game.state.remcom])
3023 game.state.remcom -= 1
3025 if game.state.remcom==0:
3028 game.state.remkl -= kldead
3029 # destroy Romulans and planets in supernovaed quadrant
3030 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
3031 game.state.galaxy[nq.x][nq.y].romulans = 0
3032 game.state.nromrem -= nrmdead
3034 for loop in range(game.inplan):
3035 if game.state.planets[loop].w == nq:
3036 game.state.planets[loop].pclass = "destroyed"
3038 # Destroy any base in supernovaed quadrant
3039 if game.state.rembase:
3040 maxloop = game.state.rembase
3041 for loop in range(maxloop):
3042 if game.state.baseq[loop] == nq:
3043 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3044 invalidate(game.state.baseq[game.state.rembase])
3045 game.state.rembase -= 1
3047 # If starship caused supernova, tally up destruction
3049 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3050 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3051 game.state.nplankl += npdead
3052 # mark supernova in galaxy and in star chart
3053 if game.quadrant == nq or communicating():
3054 game.state.galaxy[nq.x][nq.y].supernova = True
3055 # If supernova destroys last Klingons give special message
3056 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3059 prout(_("Lucky you!"))
3060 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3063 # if some Klingons remain, continue or die in supernova
3068 # Code from finish.c ends here.
3071 # self-destruct maneuver
3072 # Finish with a BANG!
3074 if damaged(DCOMPTR):
3075 prout(_("Computer damaged; cannot execute destruct sequence."))
3077 prouts(_("---WORKING---")); skip(1)
3078 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3079 prouts(" 10"); skip(1)
3080 prouts(" 9"); skip(1)
3081 prouts(" 8"); skip(1)
3082 prouts(" 7"); skip(1)
3083 prouts(" 6"); skip(1)
3085 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3087 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3089 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3093 if game.passwd != citem:
3094 prouts(_("PASSWORD-REJECTED;"))
3096 prouts(_("CONTINUITY-EFFECTED"))
3099 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3100 prouts(" 5"); skip(1)
3101 prouts(" 4"); skip(1)
3102 prouts(" 3"); skip(1)
3103 prouts(" 2"); skip(1)
3104 prouts(" 1"); skip(1)
3106 prouts(_("GOODBYE-CRUEL-WORLD"))
3114 prouts(_("********* Entropy of "))
3116 prouts(_(" maximized *********"))
3120 if game.nenhere != 0:
3121 whammo = 25.0 * game.energy
3123 while l <= game.nenhere:
3124 if game.enemies[l].kpower*game.enemies[l].kdist <= whammo:
3125 deadkl(game.enemies[l].kloc, game.quad[game.enemies[l].kloc.x][game.enemies[l].kloc.y], game.enemies[l].kloc)
3130 "Compute our rate of kils over time."
3131 elapsed = game.state.date - game.indate
3132 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
3135 starting = (game.inkling + game.incom + game.inscom)
3136 remaining = (game.state.remkl + game.state.remcom + game.state.nscrem)
3137 return (starting - remaining)/elapsed
3141 badpt = 5.0*game.state.starkl + \
3143 10.0*game.state.nplankl + \
3144 300*game.state.nworldkl + \
3146 100.0*game.state.basekl +\
3148 if game.ship == IHF:
3150 elif game.ship == None:
3155 # end the game, with appropriate notfications
3159 prout(_("It is stardate %.1f.") % game.state.date)
3161 if ifin == FWON: # Game has been won
3162 if game.state.nromrem != 0:
3163 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3166 prout(_("You have smashed the Klingon invasion fleet and saved"))
3167 prout(_("the Federation."))
3172 badpt = 0.0 # Close enough!
3173 # killsPerDate >= RateMax
3174 if game.state.date-game.indate < 5.0 or \
3175 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3177 prout(_("In fact, you have done so well that Starfleet Command"))
3178 if game.skill == SKILL_NOVICE:
3179 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3180 elif game.skill == SKILL_FAIR:
3181 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3182 elif game.skill == SKILL_GOOD:
3183 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3184 elif game.skill == SKILL_EXPERT:
3185 prout(_("promotes you to Commodore Emeritus."))
3187 prout(_("Now that you think you're really good, try playing"))
3188 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3189 elif game.skill == SKILL_EMERITUS:
3191 proutn(_("Computer- "))
3192 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3194 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3196 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3198 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3200 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3202 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3204 prout(_("Now you can retire and write your own Star Trek game!"))
3206 elif game.skill >= SKILL_EXPERT:
3207 if game.thawed and not idebug:
3208 prout(_("You cannot get a citation, so..."))
3210 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3214 # Only grant long life if alive (original didn't!)
3216 prout(_("LIVE LONG AND PROSPER."))
3221 elif ifin == FDEPLETE: # Federation Resources Depleted
3222 prout(_("Your time has run out and the Federation has been"))
3223 prout(_("conquered. Your starship is now Klingon property,"))
3224 prout(_("and you are put on trial as a war criminal. On the"))
3225 proutn(_("basis of your record, you are "))
3226 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3227 prout(_("acquitted."))
3229 prout(_("LIVE LONG AND PROSPER."))
3231 prout(_("found guilty and"))
3232 prout(_("sentenced to death by slow torture."))
3236 elif ifin == FLIFESUP:
3237 prout(_("Your life support reserves have run out, and"))
3238 prout(_("you die of thirst, starvation, and asphyxiation."))
3239 prout(_("Your starship is a derelict in space."))
3241 prout(_("Your energy supply is exhausted."))
3243 prout(_("Your starship is a derelict in space."))
3244 elif ifin == FBATTLE:
3247 prout(_("has been destroyed in battle."))
3249 prout(_("Dulce et decorum est pro patria mori."))
3251 prout(_("You have made three attempts to cross the negative energy"))
3252 prout(_("barrier which surrounds the galaxy."))
3254 prout(_("Your navigation is abominable."))
3257 prout(_("Your starship has been destroyed by a nova."))
3258 prout(_("That was a great shot."))
3260 elif ifin == FSNOVAED:
3263 prout(_(" has been fried by a supernova."))
3264 prout(_("...Not even cinders remain..."))
3265 elif ifin == FABANDN:
3266 prout(_("You have been captured by the Klingons. If you still"))
3267 prout(_("had a starbase to be returned to, you would have been"))
3268 prout(_("repatriated and given another chance. Since you have"))
3269 prout(_("no starbases, you will be mercilessly tortured to death."))
3270 elif ifin == FDILITHIUM:
3271 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3272 elif ifin == FMATERIALIZE:
3273 prout(_("Starbase was unable to re-materialize your starship."))
3274 prout(_("Sic transit gloria mundi"))
3275 elif ifin == FPHASER:
3278 prout(_(" has been cremated by its own phasers."))
3280 prout(_("You and your landing party have been"))
3281 prout(_("converted to energy, disipating through space."))
3282 elif ifin == FMINING:
3283 prout(_("You are left with your landing party on"))
3284 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3286 prout(_("They are very fond of \"Captain Kirk\" soup."))
3288 proutn(_("Without your leadership, the "))
3290 prout(_(" is destroyed."))
3291 elif ifin == FDPLANET:
3292 prout(_("You and your mining party perish."))
3294 prout(_("That was a great shot."))
3297 prout(_("The Galileo is instantly annihilated by the supernova."))
3298 prout(_("You and your mining party are atomized."))
3300 proutn(_("Mr. Spock takes command of the "))
3303 prout(_("joins the Romulans, reigning terror on the Federation."))
3304 elif ifin == FPNOVA:
3305 prout(_("You and your mining party are atomized."))
3307 proutn(_("Mr. Spock takes command of the "))
3310 prout(_("joins the Romulans, reigning terror on the Federation."))
3311 elif ifin == FSTRACTOR:
3312 prout(_("The shuttle craft Galileo is also caught,"))
3313 prout(_("and breaks up under the strain."))
3315 prout(_("Your debris is scattered for millions of miles."))
3316 proutn(_("Without your leadership, the "))
3318 prout(_(" is destroyed."))
3320 prout(_("The mutants attack and kill Spock."))
3321 prout(_("Your ship is captured by Klingons, and"))
3322 prout(_("your crew is put on display in a Klingon zoo."))
3323 elif ifin == FTRIBBLE:
3324 prout(_("Tribbles consume all remaining water,"))
3325 prout(_("food, and oxygen on your ship."))
3327 prout(_("You die of thirst, starvation, and asphyxiation."))
3328 prout(_("Your starship is a derelict in space."))
3330 prout(_("Your ship is drawn to the center of the black hole."))
3331 prout(_("You are crushed into extremely dense matter."))
3333 prout(_("Your last crew member has died."))
3334 if game.ship == IHF:
3336 elif game.ship == IHE:
3339 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3340 goodies = game.state.remres/game.inresor
3341 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3342 if goodies/baddies >= randreal(1.0, 1.5):
3343 prout(_("As a result of your actions, a treaty with the Klingon"))
3344 prout(_("Empire has been signed. The terms of the treaty are"))
3345 if goodies/baddies >= randreal(3.0):
3346 prout(_("favorable to the Federation."))
3348 prout(_("Congratulations!"))
3350 prout(_("highly unfavorable to the Federation."))
3352 prout(_("The Federation will be destroyed."))
3354 prout(_("Since you took the last Klingon with you, you are a"))
3355 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3356 prout(_("statue in your memory. Rest in peace, and try not"))
3357 prout(_("to think about pigeons."))
3362 # compute player's score
3363 timused = game.state.date - game.indate
3365 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3367 perdate = killrate()
3368 ithperd = 500*perdate + 0.5
3371 iwon = 100*game.skill
3372 if game.ship == IHE:
3374 elif game.ship == IHF:
3378 if not game.gamewon:
3379 game.state.nromrem = 0 # None captured if no win
3380 iscore = 10*(game.inkling - game.state.remkl) \
3381 + 50*(game.incom - game.state.remcom) \
3383 + 20*(game.inrom - game.state.nromrem) \
3384 + 200*(game.inscom - game.state.nscrem) \
3385 - game.state.nromrem \
3390 prout(_("Your score --"))
3391 if game.inrom - game.state.nromrem:
3392 prout(_("%6d Romulans destroyed %5d") %
3393 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3394 if game.state.nromrem:
3395 prout(_("%6d Romulans captured %5d") %
3396 (game.state.nromrem, game.state.nromrem))
3397 if game.inkling - game.state.remkl:
3398 prout(_("%6d ordinary Klingons destroyed %5d") %
3399 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3400 if game.incom - game.state.remcom:
3401 prout(_("%6d Klingon commanders destroyed %5d") %
3402 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3403 if game.inscom - game.state.nscrem:
3404 prout(_("%6d Super-Commander destroyed %5d") %
3405 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3407 prout(_("%6.2f Klingons per stardate %5d") %
3409 if game.state.starkl:
3410 prout(_("%6d stars destroyed by your action %5d") %
3411 (game.state.starkl, -5*game.state.starkl))
3412 if game.state.nplankl:
3413 prout(_("%6d planets destroyed by your action %5d") %
3414 (game.state.nplankl, -10*game.state.nplankl))
3415 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3416 prout(_("%6d inhabited planets destroyed by your action %5d") %
3417 (game.state.nplankl, -300*game.state.nworldkl))
3418 if game.state.basekl:
3419 prout(_("%6d bases destroyed by your action %5d") %
3420 (game.state.basekl, -100*game.state.basekl))
3422 prout(_("%6d calls for help from starbase %5d") %
3423 (game.nhelp, -45*game.nhelp))
3425 prout(_("%6d casualties incurred %5d") %
3426 (game.casual, -game.casual))
3428 prout(_("%6d crew abandoned in space %5d") %
3429 (game.abandoned, -3*game.abandoned))
3431 prout(_("%6d ship(s) lost or destroyed %5d") %
3432 (klship, -100*klship))
3434 prout(_("Penalty for getting yourself killed -200"))
3436 proutn(_("Bonus for winning "))
3437 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3438 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3439 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3440 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3441 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3442 prout(" %5d" % iwon)
3444 prout(_("TOTAL SCORE %5d") % iscore)
3447 # emit winner's commemmorative plaque
3450 proutn(_("File or device name for your plaque: "))
3453 fp = open(winner, "w")
3456 prout(_("Invalid name."))
3458 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3460 # The 38 below must be 64 for 132-column paper
3461 nskip = 38 - len(winner)/2
3462 fp.write("\n\n\n\n")
3463 # --------DRAW ENTERPRISE PICTURE.
3464 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3465 fp.write(" EEE E : : : E\n" )
3466 fp.write(" EE EEE E : : NCC-1701 : E\n")
3467 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3468 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3469 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3470 fp.write(" EEEEEEE EEEEE E E E E\n")
3471 fp.write(" EEE E E E E\n")
3472 fp.write(" E E E E\n")
3473 fp.write(" EEEEEEEEEEEEE E E\n")
3474 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3475 fp.write(" :E : EEEE E\n")
3476 fp.write(" .-E -:----- E\n")
3477 fp.write(" :E : E\n")
3478 fp.write(" EE : EEEEEEEE\n")
3479 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3481 fp.write(_(" U. S. S. ENTERPRISE\n"))
3482 fp.write("\n\n\n\n")
3483 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3485 fp.write(_(" Starfleet Command bestows to you\n"))
3487 fp.write("%*s%s\n\n" % (nskip, "", winner))
3488 fp.write(_(" the rank of\n\n"))
3489 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3491 if game.skill == SKILL_EXPERT:
3492 fp.write(_(" Expert level\n\n"))
3493 elif game.skill == SKILL_EMERITUS:
3494 fp.write(_("Emeritus level\n\n"))
3496 fp.write(_(" Cheat level\n\n"))
3497 timestring = ctime()
3498 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3499 (timestring+4, timestring+20, timestring+11))
3500 fp.write(_(" Your score: %d\n\n") % iscore)
3501 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3504 # Code from io.c begins here
3506 rows = linecount = 0 # for paging
3509 fullscreen_window = None
3510 srscan_window = None
3511 report_window = None
3512 status_window = None
3513 lrscan_window = None
3514 message_window = None
3515 prompt_window = None
3519 "wrap up, either normally or due to signal"
3520 if game.options & OPTION_CURSES:
3527 sys.stdout.write('\n')
3533 #setlocale(LC_ALL, "")
3534 #bindtextdomain(PACKAGE, LOCALEDIR)
3535 #textdomain(PACKAGE)
3536 if atexit.register(outro):
3537 sys.stderr.write("Unable to register outro(), exiting...\n")
3539 if not (game.options & OPTION_CURSES):
3540 ln_env = os.getenv("LINES")
3546 stdscr = curses.initscr()
3551 curses.start_color()
3552 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3553 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3554 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3555 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3556 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3557 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3558 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3559 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3561 global fullscreen_window, srscan_window, report_window, status_window
3562 global lrscan_window, message_window, prompt_window
3563 fullscreen_window = stdscr
3564 srscan_window = curses.newwin(12, 25, 0, 0)
3565 report_window = curses.newwin(11, 0, 1, 25)
3566 status_window = curses.newwin(10, 0, 1, 39)
3567 lrscan_window = curses.newwin(5, 0, 0, 64)
3568 message_window = curses.newwin(0, 0, 12, 0)
3569 prompt_window = curses.newwin(1, 0, rows-2, 0)
3570 message_window.scrollok(True)
3571 setwnd(fullscreen_window)
3575 "wait for user action -- OK to do nothing if on a TTY"
3576 if game.options & OPTION_CURSES:
3581 if game.skill > SKILL_FAIR:
3582 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3584 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3588 if game.skill > SKILL_FAIR:
3589 prompt = _("[CONTINUE?]")
3591 prompt = _("[PRESS ENTER TO CONTINUE]")
3593 if game.options & OPTION_CURSES:
3595 setwnd(prompt_window)
3596 prompt_window.wclear()
3597 prompt_window.addstr(prompt)
3598 prompt_window.getstr()
3599 prompt_window.clear()
3600 prompt_window.refresh()
3601 setwnd(message_window)
3604 sys.stdout.write('\n')
3607 for j in range(rows):
3608 sys.stdout.write('\n')
3612 "Skip i lines. Pause game if this would cause a scrolling event."
3613 for dummy in range(i):
3614 if game.options & OPTION_CURSES:
3615 (y, x) = curwnd.getyx()
3616 (my, mx) = curwnd.getmaxyx()
3617 if curwnd == message_window and y >= my - 3:
3625 if rows and linecount >= rows:
3628 sys.stdout.write('\n')
3631 "Utter a line with no following line feed."
3632 if game.options & OPTION_CURSES:
3636 sys.stdout.write(line)
3646 if not replayfp or replayfp.closed: # Don't slow down replays
3649 if game.options & OPTION_CURSES:
3653 if not replayfp or replayfp.closed:
3657 "Get a line of input."
3658 if game.options & OPTION_CURSES:
3659 line = curwnd.getstr() + "\n"
3662 if replayfp and not replayfp.closed:
3664 line = replayfp.readline()
3667 prout("*** Replay finished")
3670 elif line[0] != "#":
3675 logfp.write(line + "\n")
3679 "Change windows -- OK for this to be a no-op in tty mode."
3681 if game.options & OPTION_CURSES:
3683 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3686 "Clear to end of line -- can be a no-op in tty mode"
3687 if game.options & OPTION_CURSES:
3692 "Clear screen -- can be a no-op in tty mode."
3694 if game.options & OPTION_CURSES:
3700 def textcolor(color):
3701 "Set the current text color"
3702 if game.options & OPTION_CURSES:
3703 if color == DEFAULT:
3705 elif color == BLACK:
3706 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3708 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3709 elif color == GREEN:
3710 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3712 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3714 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3715 elif color == MAGENTA:
3716 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3717 elif color == BROWN:
3718 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3719 elif color == LIGHTGRAY:
3720 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3721 elif color == DARKGRAY:
3722 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3723 elif color == LIGHTBLUE:
3724 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3725 elif color == LIGHTGREEN:
3726 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3727 elif color == LIGHTCYAN:
3728 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3729 elif color == LIGHTRED:
3730 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3731 elif color == LIGHTMAGENTA:
3732 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3733 elif color == YELLOW:
3734 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3735 elif color == WHITE:
3736 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3739 "Set highlight video, if this is reasonable."
3740 if game.options & OPTION_CURSES:
3741 curwnd.attron(curses.A_REVERSE)
3744 # Things past this point have policy implications.
3748 "Hook to be called after moving to redraw maps."
3749 if game.options & OPTION_CURSES:
3752 setwnd(srscan_window)
3756 setwnd(status_window)
3757 status_window.clear()
3758 status_window.move(0, 0)
3759 setwnd(report_window)
3760 report_window.clear()
3761 report_window.move(0, 0)
3763 setwnd(lrscan_window)
3764 lrscan_window.clear()
3765 lrscan_window.move(0, 0)
3766 lrscan(silent=False)
3768 def put_srscan_sym(w, sym):
3769 "Emit symbol for short-range scan."
3770 srscan_window.move(w.x+1, w.y*2+2)
3771 srscan_window.addch(sym)
3772 srscan_window.refresh()
3775 "Enemy fall down, go boom."
3776 if game.options & OPTION_CURSES:
3778 setwnd(srscan_window)
3779 srscan_window.attron(curses.A_REVERSE)
3780 put_srscan_sym(w, game.quad[w.x][w.y])
3784 srscan_window.attroff(curses.A_REVERSE)
3785 put_srscan_sym(w, game.quad[w.x][w.y])
3786 curses.delay_output(500)
3787 setwnd(message_window)
3790 "Sound and visual effects for teleportation."
3791 if game.options & OPTION_CURSES:
3793 setwnd(message_window)
3795 prouts(" . . . . . ")
3796 if game.options & OPTION_CURSES:
3797 #curses.delay_output(1000)
3801 def tracktorpedo(w, l, i, n, iquad):
3802 "Torpedo-track animation."
3803 if not game.options & OPTION_CURSES:
3807 proutn(_("Track for torpedo number %d- ") % i)
3810 proutn(_("Torpedo track- "))
3813 proutn("%d - %d " % (w.x, w.y))
3815 if not damaged(DSRSENS) or game.condition=="docked":
3816 if i != 1 and l == 1:
3819 if (iquad==IHDOT) or (iquad==IHBLANK):
3820 put_srscan_sym(w, '+')
3824 put_srscan_sym(w, iquad)
3826 curwnd.attron(curses.A_REVERSE)
3827 put_srscan_sym(w, iquad)
3831 curwnd.attroff(curses.A_REVERSE)
3832 put_srscan_sym(w, iquad)
3834 proutn("%d - %d " % (w.x, w.y))
3837 "Display the current galaxy chart."
3838 if game.options & OPTION_CURSES:
3839 setwnd(message_window)
3840 message_window.clear()
3842 if game.options & OPTION_TTY:
3847 def prstat(txt, data):
3849 if game.options & OPTION_CURSES:
3851 setwnd(status_window)
3853 proutn(" " * (NSYM - len(txt)))
3856 if game.options & OPTION_CURSES:
3857 setwnd(report_window)
3859 # Code from moving.c begins here
3861 def imove(novapush):
3862 # movement execution for warp, impulse, supernova, and tractor-beam events
3863 w = coord(); final = coord()
3866 def no_quad_change():
3867 # No quadrant change -- compute new average enemy distances
3868 game.quad[game.sector.x][game.sector.y] = game.ship
3870 for m in range(game.nenhere):
3871 finald = distance(w, game.enemies[m].kloc)
3872 game.enemies[m].kavgd = 0.5 * (finald+game.enemies[m].kdist)
3873 game.enemies[m].kdist = finald
3875 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3877 for m in range(game.nenhere):
3878 game.enemies[m].kavgd = game.enemies[m].kdist
3881 setwnd(message_window)
3884 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3885 game.inorbit = False
3886 angle = ((15.0 - game.direc) * 0.5235988)
3887 deltax = -math.sin(angle)
3888 deltay = math.cos(angle)
3889 if math.fabs(deltax) > math.fabs(deltay):
3890 bigger = math.fabs(deltax)
3892 bigger = math.fabs(deltay)
3895 # If tractor beam is to occur, don't move full distance
3896 if game.state.date+game.optime >= scheduled(FTBEAM):
3898 game.condition = "red"
3899 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3900 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3901 # Move within the quadrant
3902 game.quad[game.sector.x][game.sector.y] = IHDOT
3905 n = int(10.0*game.dist*bigger+0.5)
3907 for m in range(1, n+1):
3912 if not VALID_SECTOR(w.x, w.y):
3913 # Leaving quadrant -- allow final enemy attack
3914 # Don't do it if being pushed by Nova
3915 if game.nenhere != 0 and not novapush:
3917 for m in range(game.nenhere):
3918 finald = distance(w, game.enemies[m].kloc)
3919 game.enemies[m].kavgd = 0.5 * (finald + game.enemies[m].kdist)
3921 # Stas Sergeev added the condition
3922 # that attacks only happen if Klingons
3923 # are present and your skill is good.
3925 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3929 # compute final position -- new quadrant and sector
3930 x = (QUADSIZE*game.quadrant.x)+game.sector.x
3931 y = (QUADSIZE*game.quadrant.y)+game.sector.y
3932 w.x = int(round(x+10.0*game.dist*bigger*deltax))
3933 w.y = int(round(y+10.0*game.dist*bigger*deltay))
3934 # check for edge of galaxy
3944 if w.x >= GALSIZE*QUADSIZE:
3945 w.x = (GALSIZE*QUADSIZE*2) - w.x
3947 if w.y >= GALSIZE*QUADSIZE:
3948 w.y = (GALSIZE*QUADSIZE*2) - w.y
3956 if game.nkinks == 3:
3957 # Three strikes -- you're out!
3961 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3962 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3963 prout(_("YOU WILL BE DESTROYED."))
3964 # Compute final position in new quadrant
3965 if trbeam: # Don't bother if we are to be beamed
3967 game.quadrant.x = w.x/QUADSIZE
3968 game.quadrant.y = w.y/QUADSIZE
3969 game.sector.x = w.x - (QUADSIZE*game.quadrant.x)
3970 game.sector.y = w.y - (QUADSIZE*game.quadrant.y)
3972 prout(_("Entering Quadrant %s.") % game.quadrant)
3973 game.quad[game.sector.x][game.sector.y] = game.ship
3975 if game.skill>SKILL_NOVICE:
3978 iquad = game.quad[w.x][w.y]
3980 # object encountered in flight path
3981 stopegy = 50.0*game.dist/game.optime
3982 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3983 if iquad in (IHT, IHK, IHC, IHS, IHR, IHQUEST):
3985 ram(False, iquad, game.sector)
3987 elif iquad == IHBLANK:
3989 prouts(_("***RED ALERT! RED ALERT!"))
3993 proutn(_(" pulled into black hole at Sector %s") % w)
3995 # Getting pulled into a black hole was certain
3996 # death in Almy's original. Stas Sergeev added a
3997 # possibility that you'll get timewarped instead.
4000 for m in range(NDEVICES):
4001 if game.damage[m]>0:
4003 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
4004 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
4014 proutn(_(" encounters Tholian web at %s;") % w)
4016 proutn(_(" blocked by object at %s;") % w)
4017 proutn(_("Emergency stop required "))
4018 prout(_("%2d units of energy.") % int(stopegy))
4019 game.energy -= stopegy
4020 final.x = x-deltax+0.5
4021 final.y = y-deltay+0.5
4023 if game.energy <= 0:
4029 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4036 # dock our ship at a starbase
4038 if game.condition == "docked" and verbose:
4039 prout(_("Already docked."))
4042 prout(_("You must first leave standard orbit."))
4044 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4046 prout(_(" not adjacent to base."))
4048 game.condition = "docked"
4052 if game.energy < game.inenrg:
4053 game.energy = game.inenrg
4054 game.shield = game.inshld
4055 game.torps = game.intorps
4056 game.lsupres = game.inlsr
4057 game.state.crew = FULLCREW
4058 if not damaged(DRADIO) and \
4059 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4060 # get attack report from base
4061 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4065 # This program originally required input in terms of a (clock)
4066 # direction and distance. Somewhere in history, it was changed to
4067 # cartesian coordinates. So we need to convert. Probably
4068 # "manual" input should still be done this way -- it's a real
4069 # pain if the computer isn't working! Manual mode is still confusing
4070 # because it involves giving x and y motions, yet the coordinates
4071 # are always displayed y - x, where +y is downward!
4073 def getcourse(isprobe, akey):
4074 # get course and distance
4076 dquad = copy.copy(game.quadrant)
4077 navmode = "unspecified"
4081 if game.landed and not isprobe:
4082 prout(_("Dummy! You can't leave standard orbit until you"))
4083 proutn(_("are back aboard the ship."))
4086 while navmode == "unspecified":
4087 if damaged(DNAVSYS):
4089 prout(_("Computer damaged; manual navigation only"))
4091 prout(_("Computer damaged; manual movement only"))
4096 if isprobe and akey != -1:
4097 # For probe launch, use pre-scanned value first time
4103 proutn(_("Manual or automatic- "))
4106 elif key == IHALPHA:
4111 elif isit("automatic"):
4112 navmode = "automatic"
4121 prout(_("(Manual navigation assumed.)"))
4123 prout(_("(Manual movement assumed.)"))
4126 if navmode == "automatic":
4129 proutn(_("Target quadrant or quadrant§or- "))
4131 proutn(_("Destination sector or quadrant§or- "))
4138 xi = int(round(aaitem))-1
4143 xj = int(round(aaitem))-1
4146 # both quadrant and sector specified
4147 xk = int(round(aaitem))-1
4152 xl = int(round(aaitem))-1
4158 # only one pair of numbers was specified
4160 # only quadrant specified -- go to center of dest quad
4163 dsect.y = dsect.x = 4 # preserves 1-origin behavior
4165 # only sector specified
4169 if not VALID_QUADRANT(dquad.y,dquad.x) or not VALID_SECTOR(dsect.x,dsect.y):
4176 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
4178 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4179 # the actual deltas get computed here
4180 deltax = dquad.y-game.quadrant.y + 0.1*(dsect.x-game.sector.y)
4181 deltay = game.quadrant.x-dquad.x + 0.1*(game.sector.x-dsect.y)
4184 proutn(_("X and Y displacements- "))
4198 # Check for zero movement
4199 if deltax == 0 and deltay == 0:
4202 if itemp == "verbose" and not isprobe:
4204 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4205 # Course actually laid in.
4206 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4207 game.direc = math.atan2(deltax, deltay)*1.90985932
4208 if game.direc < 0.0:
4214 # move under impulse power
4216 if damaged(DIMPULS):
4219 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4221 if game.energy > 30.0:
4222 if not getcourse(isprobe=False, akey=0):
4224 power = 20.0 + 100.0*game.dist
4227 if power >= game.energy:
4228 # Insufficient power for trip
4230 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4231 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4232 if game.energy > 30:
4233 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4234 int(0.01 * (game.energy-20.0)-0.05))
4235 prout(_(" quadrants.\""))
4237 prout(_("quadrant. They are, therefore, useless.\""))
4240 # Make sure enough time is left for the trip
4241 game.optime = game.dist/0.095
4242 if game.optime >= game.state.remtime:
4243 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4244 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4245 proutn(_("we dare spend the time?\" "))
4248 # Activate impulse engines and pay the cost
4249 imove(novapush=False)
4253 power = 20.0 + 100.0*game.dist
4254 game.energy -= power
4255 game.optime = game.dist/0.095
4256 if game.energy <= 0:
4261 # move under warp drive
4262 blooey = False; twarp = False
4263 if not timewarp: # Not WARPX entry
4265 if game.damage[DWARPEN] > 10.0:
4268 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4270 if damaged(DWARPEN) and game.warpfac > 4.0:
4273 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4274 prout(_(" is repaired, I can only give you warp 4.\""))
4276 # Read in course and distance
4277 if not getcourse(isprobe=False, akey=0):
4279 # Make sure starship has enough energy for the trip
4280 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4281 if power >= game.energy:
4282 # Insufficient power for trip
4285 prout(_("Engineering to bridge--"))
4286 if not game.shldup or 0.5*power > game.energy:
4287 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4289 prout(_("We can't do it, Captain. We don't have enough energy."))
4291 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4294 prout(_("if you'll lower the shields."))
4298 prout(_("We haven't the energy to go that far with the shields up."))
4301 # Make sure enough time is left for the trip
4302 game.optime = 10.0*game.dist/game.wfacsq
4303 if game.optime >= 0.8*game.state.remtime:
4305 prout(_("First Officer Spock- \"Captain, I compute that such"))
4306 proutn(_(" a trip would require approximately %2.0f") %
4307 (100.0*game.optime/game.state.remtime))
4308 prout(_(" percent of our"))
4309 proutn(_(" remaining time. Are you sure this is wise?\" "))
4315 if game.warpfac > 6.0:
4316 # Decide if engine damage will occur
4317 # ESR: Seems wrong. Probability of damage goes *down* with distance?
4318 prob = game.dist*square(6.0-game.warpfac)/66.666666666
4319 if prob > randreal():
4321 game.dist = randreal(game.dist)
4322 # Decide if time warp will occur
4323 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > randreal():
4325 if idebug and game.warpfac==10 and not twarp:
4327 proutn("=== Force time warp? ")
4331 # If time warp or engine damage, check path
4332 # If it is obstructed, don't do warp or damage
4333 angle = ((15.0-game.direc)*0.5235998)
4334 deltax = -math.sin(angle)
4335 deltay = math.cos(angle)
4336 if math.fabs(deltax) > math.fabs(deltay):
4337 bigger = math.fabs(deltax)
4339 bigger = math.fabs(deltay)
4343 n = 10.0 * game.dist * bigger +0.5
4346 for l in range(1, n+1):
4351 if not VALID_SECTOR(ix, iy):
4353 if game.quad[ix][iy] != IHDOT:
4356 # Activate Warp Engines and pay the cost
4357 imove(novapush=False)
4360 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4361 if game.energy <= 0:
4363 game.optime = 10.0*game.dist/game.wfacsq
4367 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
4369 prout(_("Engineering to bridge--"))
4370 prout(_(" Scott here. The warp engines are damaged."))
4371 prout(_(" We'll have to reduce speed to warp 4."))
4376 # change the warp factor
4382 proutn(_("Warp factor- "))
4387 if game.damage[DWARPEN] > 10.0:
4388 prout(_("Warp engines inoperative."))
4390 if damaged(DWARPEN) and aaitem > 4.0:
4391 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4392 prout(_(" but right now we can only go warp 4.\""))
4395 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4398 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4400 oldfac = game.warpfac
4401 game.warpfac = aaitem
4402 game.wfacsq=game.warpfac*game.warpfac
4403 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4404 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4407 if game.warpfac < 8.00:
4408 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4410 if game.warpfac == 10.0:
4411 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4413 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4417 # cope with being tossed out of quadrant by supernova or yanked by beam
4419 # is captain on planet?
4421 if damaged(DTRANSP):
4424 prout(_("Scotty rushes to the transporter controls."))
4426 prout(_("But with the shields up it's hopeless."))
4428 prouts(_("His desperate attempt to rescue you . . ."))
4433 prout(_("SUCCEEDS!"))
4436 proutn(_("The crystals mined were "))
4444 # Check to see if captain in shuttle craft
4449 # Inform captain of attempt to reach safety
4453 prouts(_("***RED ALERT! RED ALERT!"))
4457 prout(_(" has stopped in a quadrant containing"))
4458 prouts(_(" a supernova."))
4460 proutn(_("***Emergency automatic override attempts to hurl "))
4463 prout(_("safely out of quadrant."))
4464 if not damaged(DRADIO):
4465 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4466 # Try to use warp engines
4467 if damaged(DWARPEN):
4469 prout(_("Warp engines damaged."))
4472 game.warpfac = randreal(6.0, 8.0)
4473 game.wfacsq = game.warpfac * game.warpfac
4474 prout(_("Warp factor set to %d") % int(game.warpfac))
4475 power = 0.75*game.energy
4476 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4477 distreq = randreal(math.sqrt(2))
4478 if distreq < game.dist:
4480 game.optime = 10.0*game.dist/game.wfacsq
4481 game.direc = randreal(12) # How dumb!
4483 game.inorbit = False
4486 # This is bad news, we didn't leave quadrant.
4490 prout(_("Insufficient energy to leave quadrant."))
4493 # Repeat if another snova
4494 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4496 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4497 finish(FWON) # Snova killed remaining enemy.
4500 # let's do the time warp again
4501 prout(_("***TIME WARP ENTERED."))
4502 if game.state.snap and withprob(0.5):
4504 prout(_("You are traveling backwards in time %d stardates.") %
4505 int(game.state.date-game.snapsht.date))
4506 game.state = game.snapsht
4507 game.state.snap = False
4508 if game.state.remcom:
4509 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4510 schedule(FBATTAK, expran(0.3*game.intime))
4511 schedule(FSNOVA, expran(0.5*game.intime))
4512 # next snapshot will be sooner
4513 schedule(FSNAP, expran(0.25*game.state.remtime))
4515 if game.state.nscrem:
4516 schedule(FSCMOVE, 0.2777)
4520 invalidate(game.battle)
4522 # Make sure Galileo is consistant -- Snapshot may have been taken
4523 # when on planet, which would give us two Galileos!
4525 for l in range(game.inplan):
4526 if game.state.planets[l].known == "shuttle_down":
4528 if game.iscraft == "onship" and game.ship==IHE:
4529 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4530 game.iscraft = "offship"
4531 # Likewise, if in the original time the Galileo was abandoned, but
4532 # was on ship earlier, it would have vanished -- let's restore it.
4533 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4534 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4535 game.iscraft = "onship"
4537 # * There used to be code to do the actual reconstrction here,
4538 # * but the starchart is now part of the snapshotted galaxy state.
4540 prout(_("Spock has reconstructed a correct star chart from memory"))
4542 # Go forward in time
4543 game.optime = -0.5*game.intime*math.log(randreal())
4544 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4545 # cheat to make sure no tractor beams occur during time warp
4546 postpone(FTBEAM, game.optime)
4547 game.damage[DRADIO] += game.optime
4549 events() # Stas Sergeev added this -- do pending events
4552 # launch deep-space probe
4553 # New code to launch a deep space probe
4554 if game.nprobes == 0:
4557 if game.ship == IHE:
4558 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4560 prout(_("Ye Faerie Queene has no deep space probes."))
4565 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4567 if is_scheduled(FDSPROB):
4570 if damaged(DRADIO) and game.condition != "docked":
4571 prout(_("Spock- \"Records show the previous probe has not yet"))
4572 prout(_(" reached its destination.\""))
4574 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4578 # slow mode, so let Kirk know how many probes there are left
4579 if game.nprobes == 1:
4580 prout(_("1 probe left."))
4582 prout(_("%d probes left") % game.nprobes)
4583 proutn(_("Are you sure you want to fire a probe? "))
4586 game.isarmed = False
4587 if key == IHALPHA and citem == "armed":
4591 proutn(_("Arm NOVAMAX warhead? "))
4593 if not getcourse(isprobe=True, akey=key):
4596 angle = ((15.0 - game.direc) * 0.5235988)
4597 game.probeinx = -math.sin(angle)
4598 game.probeiny = math.cos(angle)
4599 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4600 bigger = math.fabs(game.probeinx)
4602 bigger = math.fabs(game.probeiny)
4603 game.probeiny /= bigger
4604 game.probeinx /= bigger
4605 game.proben = 10.0*game.dist*bigger +0.5
4606 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4607 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4608 game.probec = game.quadrant
4609 schedule(FDSPROB, 0.01) # Time to move one sector
4610 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4614 # Here's how the mayday code works:
4616 # First, the closest starbase is selected. If there is a a starbase
4617 # in your own quadrant, you are in good shape. This distance takes
4618 # quadrant distances into account only.
4620 # A magic number is computed based on the distance which acts as the
4621 # probability that you will be rematerialized. You get three tries.
4623 # When it is determined that you should be able to be rematerialized
4624 # (i.e., when the probability thing mentioned above comes up
4625 # positive), you are put into that quadrant (anywhere). Then, we try
4626 # to see if there is a spot adjacent to the star- base. If not, you
4627 # can't be rematerialized!!! Otherwise, it drops you there. It only
4628 # tries five times to find a spot to drop you. After that, it's your
4632 # yell for help from nearest starbase
4633 # There's more than one way to move in this game!
4636 # Test for conditions which prevent calling for help
4637 if game.condition == "docked":
4638 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4641 prout(_("Subspace radio damaged."))
4643 if game.state.rembase==0:
4644 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4647 proutn(_("You must be aboard the "))
4651 # OK -- call for help from nearest starbase
4654 # There's one in this quadrant
4655 ddist = distance(game.base, game.sector)
4658 for m in range(game.state.rembase):
4659 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4663 # Since starbase not in quadrant, set up new quadrant
4664 game.quadrant = game.state.baseq[line]
4666 # dematerialize starship
4667 game.quad[game.sector.x][game.sector.y]=IHDOT
4668 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4670 prout(_(" dematerializes."))
4672 for m in range(1, 5+1):
4673 w = game.base.scatter()
4674 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4675 # found one -- finish up
4678 if not is_valid(game.sector):
4679 prout(_("You have been lost in space..."))
4680 finish(FMATERIALIZE)
4682 # Give starbase three chances to rematerialize starship
4683 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4684 for m in range(1, 3+1):
4685 if m == 1: proutn(_("1st"))
4686 elif m == 2: proutn(_("2nd"))
4687 elif m == 3: proutn(_("3rd"))
4688 proutn(_(" attempt to re-materialize "))
4690 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4693 if randreal() > probf:
4696 curses.delay_output(500)
4699 game.quad[ix][iy]=IHQUEST
4702 setwnd(message_window)
4703 finish(FMATERIALIZE)
4705 game.quad[ix][iy]=game.ship
4707 prout(_("succeeds."))
4711 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4713 # Abandon Ship (the BSD-Trek description)
4715 # The ship is abandoned. If your current ship is the Faire
4716 # Queene, or if your shuttlecraft is dead, you're out of
4717 # luck. You need the shuttlecraft in order for the captain
4718 # (that's you!!) to escape.
4720 # Your crew can beam to an inhabited starsystem in the
4721 # quadrant, if there is one and if the transporter is working.
4722 # If there is no inhabited starsystem, or if the transporter
4723 # is out, they are left to die in outer space.
4725 # If there are no starbases left, you are captured by the
4726 # Klingons, who torture you mercilessly. However, if there
4727 # is at least one starbase, you are returned to the
4728 # Federation in a prisoner of war exchange. Of course, this
4729 # can't happen unless you have taken some prisoners.
4734 if game.condition=="docked":
4736 prout(_("You cannot abandon Ye Faerie Queene."))
4739 # Must take shuttle craft to exit
4740 if game.damage[DSHUTTL]==-1:
4741 prout(_("Ye Faerie Queene has no shuttle craft."))
4743 if game.damage[DSHUTTL]<0:
4744 prout(_("Shuttle craft now serving Big Macs."))
4746 if game.damage[DSHUTTL]>0:
4747 prout(_("Shuttle craft damaged."))
4750 prout(_("You must be aboard the ship."))
4752 if game.iscraft != "onship":
4753 prout(_("Shuttle craft not currently available."))
4755 # Print abandon ship messages
4757 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4759 prouts(_("***ALL HANDS ABANDON SHIP!"))
4761 prout(_("Captain and crew escape in shuttle craft."))
4762 if game.state.rembase==0:
4763 # Oops! no place to go...
4766 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4768 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4769 prout(_("Remainder of ship's complement beam down"))
4770 prout(_("to nearest habitable planet."))
4771 elif q.planet != None and not damaged(DTRANSP):
4772 prout(_("Remainder of ship's complement beam down to %s.") %
4775 prout(_("Entire crew of %d left to die in outer space.") %
4777 game.casual += game.state.crew
4778 game.abandoned += game.state.crew
4780 # If at least one base left, give 'em the Faerie Queene
4782 game.icrystl = False # crystals are lost
4783 game.nprobes = 0 # No probes
4784 prout(_("You are captured by Klingons and released to"))
4785 prout(_("the Federation in a prisoner-of-war exchange."))
4786 nb = randrange(game.state.rembase)
4787 # Set up quadrant and position FQ adjacient to base
4788 if not game.quadrant == game.state.baseq[nb]:
4789 game.quadrant = game.state.baseq[nb]
4790 game.sector.x = game.sector.y = 5
4793 # position next to base by trial and error
4794 game.quad[game.sector.x][game.sector.y] = IHDOT
4795 for l in range(QUADSIZE):
4796 game.sector = game.base.scatter()
4797 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4798 game.quad[game.sector.x][game.sector.y] == IHDOT:
4801 break # found a spot
4802 game.sector.x=QUADSIZE/2
4803 game.sector.y=QUADSIZE/2
4805 # Get new commission
4806 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4807 game.state.crew = FULLCREW
4808 prout(_("Starfleet puts you in command of another ship,"))
4809 prout(_("the Faerie Queene, which is antiquated but,"))
4810 prout(_("still useable."))
4812 prout(_("The dilithium crystals have been moved."))
4814 game.iscraft = "offship" # Galileo disappears
4816 game.condition="docked"
4817 for l in range(NDEVICES):
4818 game.damage[l] = 0.0
4819 game.damage[DSHUTTL] = -1
4820 game.energy = game.inenrg = 3000.0
4821 game.shield = game.inshld = 1250.0
4822 game.torps = game.intorps = 6
4823 game.lsupres=game.inlsr=3.0
4829 # Code from planets.c begins here.
4832 # abort a lengthy operation if an event interrupts it
4835 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4840 # report on (uninhabited) planets in the galaxy
4844 prout(_("Spock- \"Planet report follows, Captain.\""))
4846 for i in range(game.inplan):
4847 if game.state.planets[i].pclass == "destroyed":
4849 if (game.state.planets[i].known != "unknown" \
4850 and not game.state.planets[i].inhabited) \
4853 if idebug and game.state.planets[i].known=="unknown":
4854 proutn("(Unknown) ")
4855 proutn(_("Quadrant %s") % game.state.planets[i].w)
4856 proutn(_(" class "))
4857 proutn(game.state.planets[i].pclass)
4859 if game.state.planets[i].crystals != present:
4861 prout(_("dilithium crystals present."))
4862 if game.state.planets[i].known=="shuttle_down":
4863 prout(_(" Shuttle Craft Galileo on surface."))
4865 prout(_("No information available."))
4868 # enter standard orbit
4872 prout(_("Already in standard orbit."))
4874 if damaged(DWARPEN) and damaged(DIMPULS):
4875 prout(_("Both warp and impulse engines damaged."))
4877 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4879 prout(_(" not adjacent to planet."))
4882 game.optime = randreal(0.02, 0.05)
4883 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4887 game.height = randreal(1400, 8600)
4888 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4893 # examine planets in this quadrant
4894 if damaged(DSRSENS):
4895 if game.options & OPTION_TTY:
4896 prout(_("Short range sensors damaged."))
4898 if game.iplnet == None:
4899 if game.options & OPTION_TTY:
4900 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4902 if game.iplnet.known == "unknown":
4903 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4905 prout(_(" Planet at Sector %s is of class %s.") %
4906 (game.plnet, game.iplnet.pclass))
4907 if game.iplnet.known=="shuttle_down":
4908 prout(_(" Sensors show Galileo still on surface."))
4909 proutn(_(" Readings indicate"))
4910 if game.iplnet.crystals != "present":
4912 prout(_(" dilithium crystals present.\""))
4913 if game.iplnet.known == "unknown":
4914 game.iplnet.known = "known"
4915 elif game.iplnet.inhabited:
4916 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4917 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4920 # use the transporter
4924 if damaged(DTRANSP):
4925 prout(_("Transporter damaged."))
4926 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4928 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4932 if not game.inorbit:
4934 prout(_(" not in standard orbit."))
4937 prout(_("Impossible to transport through shields."))
4939 if game.iplnet.known=="unknown":
4940 prout(_("Spock- \"Captain, we have no information on this planet"))
4941 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4942 prout(_(" you may not go down.\""))
4944 if not game.landed and game.iplnet.crystals=="absent":
4945 prout(_("Spock- \"Captain, I fail to see the logic in"))
4946 prout(_(" exploring a planet with no dilithium crystals."))
4947 proutn(_(" Are you sure this is wise?\" "))
4951 if not (game.options & OPTION_PLAIN):
4952 nrgneed = 50 * game.skill + game.height / 100.0
4953 if nrgneed > game.energy:
4954 prout(_("Engineering to bridge--"))
4955 prout(_(" Captain, we don't have enough energy for transportation."))
4957 if not game.landed and nrgneed * 2 > game.energy:
4958 prout(_("Engineering to bridge--"))
4959 prout(_(" Captain, we have enough energy only to transport you down to"))
4960 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4961 if game.iplnet.known == "shuttle_down":
4962 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4963 proutn(_(" Are you sure this is wise?\" "))
4968 # Coming from planet
4969 if game.iplnet.known=="shuttle_down":
4970 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4974 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4975 prout(_("Landing party assembled, ready to beam up."))
4977 prout(_("Kirk whips out communicator..."))
4978 prouts(_("BEEP BEEP BEEP"))
4980 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4983 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4985 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4987 prout(_("Kirk- \"Energize.\""))
4990 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4993 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4995 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4998 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4999 game.landed = not game.landed
5000 game.energy -= nrgneed
5002 prout(_("Transport complete."))
5003 if game.landed and game.iplnet.known=="shuttle_down":
5004 prout(_("The shuttle craft Galileo is here!"))
5005 if not game.landed and game.imine:
5012 # strip-mine a world for dilithium
5016 prout(_("Mining party not on planet."))
5018 if game.iplnet.crystals == "mined":
5019 prout(_("This planet has already been strip-mined for dilithium."))
5021 elif game.iplnet.crystals == "absent":
5022 prout(_("No dilithium crystals on this planet."))
5025 prout(_("You've already mined enough crystals for this trip."))
5027 if game.icrystl and game.cryprob == 0.05:
5028 proutn(_("With all those fresh crystals aboard the "))
5031 prout(_("there's no reason to mine more at this time."))
5033 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
5036 prout(_("Mining operation complete."))
5037 game.iplnet.crystals = "mined"
5038 game.imine = game.ididit = True
5041 # use dilithium crystals
5045 if not game.icrystl:
5046 prout(_("No dilithium crystals available."))
5048 if game.energy >= 1000:
5049 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5050 prout(_(" except when Condition Yellow exists."))
5052 prout(_("Spock- \"Captain, I must warn you that loading"))
5053 prout(_(" raw dilithium crystals into the ship's power"))
5054 prout(_(" system may risk a severe explosion."))
5055 proutn(_(" Are you sure this is wise?\" "))
5060 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5061 prout(_(" Mr. Spock and I will try it.\""))
5063 prout(_("Spock- \"Crystals in place, Sir."))
5064 prout(_(" Ready to activate circuit.\""))
5066 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5068 if with(game.cryprob):
5069 prouts(_(" \"Activating now! - - No good! It's***"))
5071 prouts(_("***RED ALERT! RED A*L********************************"))
5074 prouts(_("****************** KA-BOOM!!!! *******************"))
5078 game.energy += randreal(5000.0, 5500.0)
5079 prouts(_(" \"Activating now! - - "))
5080 prout(_("The instruments"))
5081 prout(_(" are going crazy, but I think it's"))
5082 prout(_(" going to work!! Congratulations, Sir!\""))
5087 # use shuttlecraft for planetary jaunt
5090 if damaged(DSHUTTL):
5091 if game.damage[DSHUTTL] == -1.0:
5092 if game.inorbit and game.iplnet.known == "shuttle_down":
5093 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5095 prout(_("Ye Faerie Queene had no shuttle craft."))
5096 elif game.damage[DSHUTTL] > 0:
5097 prout(_("The Galileo is damaged."))
5098 else: # game.damage[DSHUTTL] < 0
5099 prout(_("Shuttle craft is now serving Big Macs."))
5101 if not game.inorbit:
5103 prout(_(" not in standard orbit."))
5105 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
5106 prout(_("Shuttle craft not currently available."))
5108 if not game.landed and game.iplnet.known=="shuttle_down":
5109 prout(_("You will have to beam down to retrieve the shuttle craft."))
5111 if game.shldup or game.condition == "docked":
5112 prout(_("Shuttle craft cannot pass through shields."))
5114 if game.iplnet.known=="unknown":
5115 prout(_("Spock- \"Captain, we have no information on this planet"))
5116 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5117 prout(_(" you may not fly down.\""))
5119 game.optime = 3.0e-5*game.height
5120 if game.optime >= 0.8*game.state.remtime:
5121 prout(_("First Officer Spock- \"Captain, I compute that such"))
5122 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5123 int(100*game.optime/game.state.remtime))
5124 prout(_("remaining time."))
5125 proutn(_("Are you sure this is wise?\" "))
5131 if game.iscraft == "onship":
5133 if not damaged(DTRANSP):
5134 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5138 proutn(_("Shuttle crew"))
5140 proutn(_("Rescue party"))
5141 prout(_(" boards Galileo and swoops toward planet surface."))
5142 game.iscraft = "offship"
5146 game.iplnet.known="shuttle_down"
5147 prout(_("Trip complete."))
5150 # Ready to go back to ship
5151 prout(_("You and your mining party board the"))
5152 prout(_("shuttle craft for the trip back to the Enterprise."))
5154 prouts(_("The short hop begins . . ."))
5156 game.iplnet.known="known"
5162 game.iscraft = "onship"
5168 prout(_("Trip complete."))
5173 prout(_("Mining party assembles in the hangar deck,"))
5174 prout(_("ready to board the shuttle craft \"Galileo\"."))
5176 prouts(_("The hangar doors open; the trip begins."))
5179 game.iscraft = "offship"
5182 game.iplnet.known = "shuttle_down"
5185 prout(_("Trip complete."))
5189 # use the big zapper
5193 if game.ship != IHE:
5194 prout(_("Ye Faerie Queene has no death ray."))
5197 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5200 prout(_("Death Ray is damaged."))
5202 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5203 prout(_(" is highly unpredictible. Considering the alternatives,"))
5204 proutn(_(" are you sure this is wise?\" "))
5207 prout(_("Spock- \"Acknowledged.\""))
5210 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5212 prout(_("Crew scrambles in emergency preparation."))
5213 prout(_("Spock and Scotty ready the death ray and"))
5214 prout(_("prepare to channel all ship's power to the device."))
5216 prout(_("Spock- \"Preparations complete, sir.\""))
5217 prout(_("Kirk- \"Engage!\""))
5219 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5222 if game.options & OPTION_PLAIN:
5226 prouts(_("Sulu- \"Captain! It's working!\""))
5228 while game.nenhere > 0:
5229 deadkl(game.enemies[1].kloc, game.quad[game.enemies[1].kloc.x][game.enemies[1].kloc.y],game.enemies[1].kloc)
5230 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5231 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5233 if (game.options & OPTION_PLAIN) == 0:
5234 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5236 prout(_(" is still operational.\""))
5238 prout(_(" has been rendered nonfunctional.\""))
5239 game.damage[DDRAY] = 39.95
5241 r = randreal() # Pick failure method
5243 prouts(_("Sulu- \"Captain! It's working!\""))
5245 prouts(_("***RED ALERT! RED ALERT!"))
5247 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5249 prouts(_("***RED ALERT! RED A*L********************************"))
5252 prouts(_("****************** KA-BOOM!!!! *******************"))
5257 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5259 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5261 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5262 prout(_(" have apparently been transformed into strange mutations."))
5263 prout(_(" Vulcans do not seem to be affected."))
5265 prout(_("Kirk- \"Raauch! Raauch!\""))
5270 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5272 proutn(_("Spock- \"I believe the word is"))
5273 prouts(_(" *ASTONISHING*"))
5274 prout(_(" Mr. Sulu."))
5275 for i in range(QUADSIZE):
5276 for j in range(QUADSIZE):
5277 if game.quad[i][j] == IHDOT:
5278 game.quad[i][j] = IHQUEST
5279 prout(_(" Captain, our quadrant is now infested with"))
5280 prouts(_(" - - - - - - *THINGS*."))
5282 prout(_(" I have no logical explanation.\""))
5284 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5286 prout(_("Scotty- \"There are so many tribbles down here"))
5287 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5291 # Code from reports.c begins here
5293 def attackreport(curt):
5294 # report status of bases under attack
5296 if is_scheduled(FCDBAS):
5297 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5298 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5299 elif game.isatb == 1:
5300 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5301 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5303 prout(_("No Starbase is currently under attack."))
5305 if is_scheduled(FCDBAS):
5306 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5308 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5312 # report on general game status
5314 s1 = "" and game.thawed and _("thawed ")
5315 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5316 s3 = (None, _("novice"). _("fair"),
5317 _("good"), _("expert"), _("emeritus"))[game.skill]
5318 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5319 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5320 prout(_("No plaque is allowed."))
5322 prout(_("This is tournament game %d.") % game.tourn)
5323 prout(_("Your secret password is \"%s\"") % game.passwd)
5324 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5325 (game.inkling + game.incom + game.inscom)))
5326 if game.incom - game.state.remcom:
5327 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5328 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5329 prout(_(", but no Commanders."))
5332 if game.skill > SKILL_FAIR:
5333 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5334 if game.state.rembase != game.inbase:
5336 if game.inbase-game.state.rembase==1:
5337 proutn(_("has been 1 base"))
5339 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5340 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5342 prout(_("There are %d bases.") % game.inbase)
5343 if communicating() or game.iseenit:
5344 # Don't report this if not seen and
5345 # either the radio is dead or not at base!
5349 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5351 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5352 if game.ship == IHE:
5353 proutn(_("You have "))
5355 proutn("%d" % (game.nprobes))
5358 proutn(_(" deep space probe"))
5362 if communicating() and is_scheduled(FDSPROB):
5364 proutn(_("An armed deep space probe is in "))
5366 proutn(_("A deep space probe is in "))
5367 prout("Quadrant %s." % game.probec)
5369 if game.cryprob <= .05:
5370 prout(_("Dilithium crystals aboard ship... not yet used."))
5374 while game.cryprob > ai:
5377 prout(_("Dilithium crystals have been used %d time%s.") % \
5378 (i, (_("s"), "")[i==1]))
5382 # long-range sensor scan
5383 if damaged(DLRSENS):
5384 # Now allow base's sensors if docked
5385 if game.condition != "docked":
5387 prout(_("LONG-RANGE SENSORS DAMAGED."))
5390 prout(_("Starbase's long-range scan"))
5392 prout(_("Long-range scan"))
5393 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5396 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5397 if not VALID_QUADRANT(x, y):
5401 if not damaged(DRADIO):
5402 game.state.galaxy[x][y].charted = True
5403 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5404 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5405 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5406 if not silent and game.state.galaxy[x][y].supernova:
5409 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5417 for i in range(NDEVICES):
5420 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5421 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5423 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5424 game.damage[i]+0.05,
5425 game.docfac*game.damage[i]+0.005))
5427 prout(_("All devices functional."))
5430 # update the chart in the Enterprise's computer from galaxy data
5431 game.lastchart = game.state.date
5432 for i in range(GALSIZE):
5433 for j in range(GALSIZE):
5434 if game.state.galaxy[i][j].charted:
5435 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5436 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5437 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5440 # display the star chart
5442 if (game.options & OPTION_AUTOSCAN):
5444 if not damaged(DRADIO):
5446 if game.lastchart < game.state.date and game.condition == "docked":
5447 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5450 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5451 if game.state.date > game.lastchart:
5452 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5453 prout(" 1 2 3 4 5 6 7 8")
5454 for i in range(GALSIZE):
5455 proutn("%d |" % (i+1))
5456 for j in range(GALSIZE):
5457 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5461 if game.state.galaxy[i][j].supernova:
5463 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5465 elif game.state.galaxy[i][j].charted:
5466 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5470 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5478 def sectscan(goodScan, i, j):
5479 # light up an individual dot in a sector
5480 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5481 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):
5482 if game.condition == "red": textcolor(RED)
5483 elif game.condition == "green": textcolor(GREEN)
5484 elif game.condition == "yellow": textcolor(YELLOW)
5485 elif game.condition == "docked": textcolor(CYAN)
5486 elif game.condition == "dead": textcolor(BROWN)
5487 if game.quad[i][j] != game.ship:
5489 proutn("%c " % game.quad[i][j])
5495 # print status report lines
5497 if not req or req == 1:
5498 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5499 % (game.state.date, game.state.remtime))
5500 if not req or req == 2:
5501 if game.condition != "docked":
5504 for t in range(NDEVICES):
5505 if game.damage[t]>0:
5507 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5508 if not req or req == 3:
5509 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5510 if not req or req == 4:
5511 if damaged(DLIFSUP):
5512 if game.condition == "docked":
5513 s = _("DAMAGED, Base provides")
5515 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5518 prstat(_("Life Support"), s)
5519 if not req or req == 5:
5520 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5521 if not req or req == 6:
5523 if game.icrystl and (game.options & OPTION_SHOWME):
5524 extra = _(" (have crystals)")
5525 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5526 if not req or req == 7:
5527 prstat(_("Torpedoes"), "%d" % (game.torps))
5528 if not req or req == 8:
5529 if damaged(DSHIELD):
5535 data = _(" %d%% %.1f units") \
5536 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5537 prstat(_("Shields"), s+data)
5538 if not req or req == 9:
5539 prstat(_("Klingons Left"), "%d" \
5540 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5541 if not req or req == 10:
5542 if game.options & OPTION_WORLDS:
5543 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5544 if plnet and plnet.inhabited:
5545 prstat(_("Major system"), plnet.name)
5547 prout(_("Sector is uninhabited"))
5548 elif not req or req == 11:
5549 attackreport(not req)
5552 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5553 while scan() == IHEOL:
5554 proutn(_("Information desired? "))
5556 if citem in requests:
5557 status(requests.index(citem))
5559 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5560 prout((" date, condition, position, lsupport, warpfactor,"))
5561 prout((" energy, torpedoes, shields, klingons, system, time."))
5566 if damaged(DSRSENS):
5567 # Allow base's sensors if docked
5568 if game.condition != "docked":
5569 prout(_(" S.R. SENSORS DAMAGED!"))
5572 prout(_(" [Using Base's sensors]"))
5574 prout(_(" Short-range scan"))
5575 if goodScan and not damaged(DRADIO):
5576 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5577 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5578 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5579 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5580 prout(" 1 2 3 4 5 6 7 8 9 10")
5581 if game.condition != "docked":
5583 for i in range(QUADSIZE):
5584 proutn("%2d " % (i+1))
5585 for j in range(QUADSIZE):
5586 sectscan(goodScan, i, j)
5591 # use computer to get estimated time of arrival for a warp jump
5592 w1 = coord(); w2 = coord()
5594 if damaged(DCOMPTR):
5595 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5598 if scan() != IHREAL:
5601 proutn(_("Destination quadrant and/or sector? "))
5605 w1.y = int(aaitem-0.5)
5606 if scan() != IHREAL:
5609 w1.x = int(aaitem-0.5)
5610 if scan() == IHREAL:
5611 w2.y = int(aaitem-0.5)
5612 if scan() != IHREAL:
5615 w2.x = int(aaitem-0.5)
5617 if game.quadrant.y>w1.x:
5621 if game.quadrant.x>w1.y:
5625 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5628 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5629 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5632 prout(_("Answer \"no\" if you don't know the value:"))
5635 proutn(_("Time or arrival date? "))
5638 if ttime > game.state.date:
5639 ttime -= game.state.date # Actually a star date
5640 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5641 if ttime <= 1e-10 or twarp > 10:
5642 prout(_("We'll never make it, sir."))
5649 proutn(_("Warp factor? "))
5653 if twarp<1.0 or twarp > 10.0:
5657 prout(_("Captain, certainly you can give me one of these."))
5660 ttime = (10.0*game.dist)/square(twarp)
5661 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5662 if tpower >= game.energy:
5663 prout(_("Insufficient energy, sir."))
5664 if not game.shldup or tpower > game.energy*2.0:
5667 proutn(_("New warp factor to try? "))
5668 if scan() == IHREAL:
5671 if twarp<1.0 or twarp > 10.0:
5679 prout(_("But if you lower your shields,"))
5680 proutn(_("remaining"))
5683 proutn(_("Remaining"))
5684 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5686 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5688 prout(_("Any warp speed is adequate."))
5690 prout(_("Minimum warp needed is %.2f,") % (twarp))
5691 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5692 if game.state.remtime < ttime:
5693 prout(_("Unfortunately, the Federation will be destroyed by then."))
5695 prout(_("You'll be taking risks at that speed, Captain"))
5696 if (game.isatb==1 and game.state.kscmdr == w1 and \
5697 scheduled(FSCDBAS)< ttime+game.state.date) or \
5698 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5699 prout(_("The starbase there will be destroyed by then."))
5700 proutn(_("New warp factor to try? "))
5701 if scan() == IHREAL:
5704 if twarp<1.0 or twarp > 10.0:
5713 # Code from setup.c begins here
5716 # issue a historically correct banner
5718 prout(_("-SUPER- STAR TREK"))
5720 # From the FORTRAN original
5721 # prout(_("Latest update-21 Sept 78"))
5727 citem = "emsave.trk"
5731 proutn(_("File name: "))
5737 if '.' not in citem:
5740 fp = open(citem, "wb")
5742 prout(_("Can't freeze game as file %s") % citem)
5744 cPickle.dump(game, fp)
5748 # retrieve saved game
5749 game.passwd[0] = '\0'
5752 proutn(_("File name: "))
5758 if '.' not in citem:
5761 fp = open(citem, "rb")
5763 prout(_("Can't thaw game in %s") % citem)
5765 game = cPickle.load(fp)
5769 # I used <http://www.memory-alpha.org> to find planets
5770 # with references in ST:TOS. Eath and the Alpha Centauri
5771 # Colony have been omitted.
5773 # Some planets marked Class G and P here will be displayed as class M
5774 # because of the way planets are generated. This is a known bug.
5777 _("Andoria (Fesoan)"), # several episodes
5778 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5779 _("Vulcan (T'Khasi)"), # many episodes
5780 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5781 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5782 _("Ardana"), # TOS: "The Cloud Minders"
5783 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5784 _("Gideon"), # TOS: "The Mark of Gideon"
5785 _("Aldebaran III"), # TOS: "The Deadly Years"
5786 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5787 _("Altair IV"), # TOS: "Amok Time
5788 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5789 _("Benecia"), # TOS: "The Conscience of the King"
5790 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5791 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5792 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5793 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5794 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5795 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5796 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5797 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5798 _("Ingraham B"), # TOS: "Operation: Annihilate"
5799 _("Janus IV"), # TOS: "The Devil in the Dark"
5800 _("Makus III"), # TOS: "The Galileo Seven"
5801 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5802 _("Omega IV"), # TOS: "The Omega Glory"
5803 _("Regulus V"), # TOS: "Amok Time
5804 _("Deneva"), # TOS: "Operation -- Annihilate!"
5805 # Worlds from BSD Trek
5806 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5807 _("Beta III"), # TOS: "The Return of the Archons"
5808 _("Triacus"), # TOS: "And the Children Shall Lead",
5809 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5811 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5812 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5813 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5814 # _("Izar"), # TOS: "Whom Gods Destroy"
5815 # _("Tiburon"), # TOS: "The Way to Eden"
5816 # _("Merak II"), # TOS: "The Cloud Minders"
5817 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5818 # _("Iotia"), # TOS: "A Piece of the Action"
5822 _("S. R. Sensors"), \
5823 _("L. R. Sensors"), \
5825 _("Photon Tubes"), \
5826 _("Life Support"), \
5827 _("Warp Engines"), \
5828 _("Impulse Engines"), \
5830 _("Subspace Radio"), \
5831 _("Shuttle Craft"), \
5833 _("Navigation System"), \
5835 _("Shield Control"), \
5840 def setup(needprompt):
5841 # prepare to play, set up cosmos
5843 # Decide how many of everything
5844 if choose(needprompt):
5845 return # frozen game
5846 # Prepare the Enterprise
5847 game.alldone = game.gamewon = False
5849 game.state.crew = FULLCREW
5850 game.energy = game.inenrg = 5000.0
5851 game.shield = game.inshld = 2500.0
5852 game.shldchg = False
5856 game.quadrant = randplace(GALSIZE)
5857 game.sector = randplace(QUADSIZE)
5858 game.torps = game.intorps = 10
5859 game.nprobes = randrange(2, 5)
5861 game.wfacsq = game.warpfac * game.warpfac
5862 for i in range(NDEVICES):
5863 game.damage[i] = 0.0
5864 # Set up assorted game parameters
5865 game.battle = coord()
5866 game.state.date = game.indate = 100.0 * randreal(20, 51)
5867 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5868 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5869 game.isatb = game.state.nplankl = 0
5870 game.state.starkl = game.state.basekl = 0
5871 game.iscraft = "onship"
5875 for i in range(GALSIZE):
5876 for j in range(GALSIZE):
5877 quad = game.state.galaxy[i][j]
5882 quad.starbase = False
5883 quad.supernova = False
5884 quad.status = "secure"
5885 # Initialize times for extraneous events
5886 schedule(FSNOVA, expran(0.5 * game.intime))
5887 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5888 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5889 schedule(FBATTAK, expran(0.3*game.intime))
5891 if game.state.nscrem:
5892 schedule(FSCMOVE, 0.2777)
5897 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5898 schedule(FDISTR, expran(1.0 + game.intime))
5903 # Starchart is functional but we've never seen it
5904 game.lastchart = FOREVER
5905 # Put stars in the galaxy
5907 for i in range(GALSIZE):
5908 for j in range(GALSIZE):
5909 k = randrange(1, QUADSIZE**2/10+1)
5911 game.state.galaxy[i][j].stars = k
5912 # Locate star bases in galaxy
5913 for i in range(game.inbase):
5916 w = randplace(GALSIZE)
5917 if not game.state.galaxy[w.x][w.y].starbase:
5920 # C version: for (j = i-1; j > 0; j--)
5921 # so it did them in the opposite order.
5922 for j in range(1, i):
5923 # Improved placement algorithm to spread out bases
5924 distq = w.distance(game.state.baseq[j])
5925 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5928 prout("=== Abandoning base #%d at %s" % (i, w))
5930 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5932 prout("=== Saving base #%d, close to #%d" % (i, j))
5935 game.state.baseq[i] = w
5936 game.state.galaxy[w.x][w.y].starbase = True
5937 game.state.chart[w.x][w.y].starbase = True
5938 # Position ordinary Klingon Battle Cruisers
5940 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5941 if klumper > MAXKLQUAD:
5945 klump = (1.0 - r*r)*klumper
5950 w = randplace(GALSIZE)
5951 if not game.state.galaxy[w.x][w.y].supernova and \
5952 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
5954 game.state.galaxy[w.x][w.y].klingons += int(klump)
5957 # Position Klingon Commander Ships
5958 for i in range(1, game.incom+1):
5960 w = randplace(GALSIZE)
5961 if (game.state.galaxy[w.x][w.y].klingons or withprob(0.25)) and \
5962 not game.state.galaxy[w.x][w.y].supernova and \
5963 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
5964 not w in game.state.kcmdr[:i]:
5966 game.state.galaxy[w.x][w.y].klingons += 1
5967 game.state.kcmdr[i] = w
5968 # Locate planets in galaxy
5969 for i in range(game.inplan):
5971 w = randplace(GALSIZE)
5972 if game.state.galaxy[w.x][w.y].planet == None:
5976 new.crystals = "absent"
5977 if (game.options & OPTION_WORLDS) and i < NINHAB:
5978 new.pclass = "M" # All inhabited planets are class M
5979 new.crystals = "absent"
5981 new.name = systnames[i]
5982 new.inhabited = True
5984 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5986 new.crystals = "present"
5987 new.known = "unknown"
5988 new.inhabited = False
5989 game.state.galaxy[w.x][w.y].planet = new
5990 game.state.planets.append(new)
5992 for i in range(game.state.nromrem):
5993 w = randplace(GALSIZE)
5994 game.state.galaxy[w.x][w.y].romulans += 1
5995 # Locate the Super Commander
5996 if game.state.nscrem > 0:
5998 w = randplace(GALSIZE)
5999 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
6001 game.state.kscmdr = w
6002 game.state.galaxy[w.x][w.y].klingons += 1
6003 # Place thing (in tournament game, we don't want one!)
6005 if game.tourn is None:
6006 thing = randplace(GALSIZE)
6008 game.state.snap = False
6009 if game.skill == SKILL_NOVICE:
6010 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6011 prout(_("a deadly Klingon invasion force. As captain of the United"))
6012 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6013 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6014 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6015 prout(_("your mission. As you proceed you may be given more time."))
6017 prout(_("You will have %d supporting starbases.") % (game.inbase))
6018 proutn(_("Starbase locations- "))
6020 prout(_("Stardate %d.") % int(game.state.date))
6022 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6023 prout(_("An unknown number of Romulans."))
6024 if game.state.nscrem:
6025 prout(_("And one (GULP) Super-Commander."))
6026 prout(_("%d stardates.") % int(game.intime))
6027 proutn(_("%d starbases in ") % game.inbase)
6028 for i in range(game.inbase):
6029 proutn(`game.state.baseq[i]`)
6032 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6033 proutn(_(" Sector %s") % game.sector)
6035 prout(_("Good Luck!"))
6036 if game.state.nscrem:
6037 prout(_(" YOU'LL NEED IT."))
6040 if game.nenhere - (thing == game.quadrant) - (game.tholian != None):
6042 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6045 def choose(needprompt):
6046 # choose your game type
6051 game.skill = SKILL_NONE
6053 if needprompt: # Can start with command line options
6054 proutn(_("Would you like a regular, tournament, or saved game? "))
6056 if len(citem)==0: # Try again
6058 if isit("tournament"):
6059 while scan() == IHEOL:
6060 proutn(_("Type in tournament number-"))
6063 continue # We don't want a blank entry
6064 game.tourn = int(round(aaitem))
6067 logfp.write("# random.seed(%d)\n" % aaitem)
6069 if isit("saved") or isit("frozen"):
6073 if game.passwd == None:
6075 if not game.alldone:
6076 game.thawed = True # No plaque if not finished
6082 proutn(_("What is \"%s\"?"), citem)
6084 while game.length==0 or game.skill==SKILL_NONE:
6085 if scan() == IHALPHA:
6088 elif isit("medium"):
6092 elif isit("novice"):
6093 game.skill = SKILL_NOVICE
6095 game.skill = SKILL_FAIR
6097 game.skill = SKILL_GOOD
6098 elif isit("expert"):
6099 game.skill = SKILL_EXPERT
6100 elif isit("emeritus"):
6101 game.skill = SKILL_EMERITUS
6103 proutn(_("What is \""))
6109 proutn(_("Would you like a Short, Medium, or Long game? "))
6110 elif game.skill == SKILL_NONE:
6111 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6112 # Choose game options -- added by ESR for SST2K
6113 if scan() != IHALPHA:
6115 proutn(_("Choose your game style (or just press enter): "))
6118 # Approximates the UT FORTRAN version.
6119 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6120 game.options |= OPTION_PLAIN
6122 # Approximates Tom Almy's version.
6123 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6124 game.options |= OPTION_ALMY
6128 proutn(_("What is \"%s\"?") % citem)
6130 if game.passwd == "debug":
6132 fputs("=== Debug mode enabled\n", sys.stdout)
6134 # Use parameters to generate initial values of things
6135 game.damfac = 0.5 * game.skill
6136 game.state.rembase = randrange(BASEMIN, BASEMAX+1)
6137 game.inbase = game.state.rembase
6139 if game.options & OPTION_PLANETS:
6140 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
6141 if game.options & OPTION_WORLDS:
6142 game.inplan += int(NINHAB)
6143 game.state.nromrem = game.inrom = randrange(2 *game.skill)
6144 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6145 game.state.remtime = 7.0 * game.length
6146 game.intime = game.state.remtime
6147 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
6148 game.incom = int(game.skill + 0.0625*game.inkling*randreal())
6149 game.state.remcom = min(10, game.incom)
6150 game.incom = game.state.remcom
6151 game.state.remres = (game.inkling+4*game.incom)*game.intime
6152 game.inresor = game.state.remres
6153 if game.inkling > 50:
6154 game.state.rembase += 1
6155 game.inbase = game.state.rembase
6159 # drop a feature on a random dot in the current quadrant
6162 w = randplace(QUADSIZE)
6163 if game.quad[w.x][w.y] == IHDOT:
6165 game.quad[w.x][w.y] = iquad
6169 # update our alert status
6170 game.condition = "green"
6171 if game.energy < 1000.0:
6172 game.condition = "yellow"
6173 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6174 game.condition = "red"
6176 game.condition="dead"
6179 # drop new Klingon into current quadrant
6180 return enemy(loc=dropin(IHK), power=randreal(300, 450) + 25.0*game.skill)
6183 # set up a new state of quadrant, for when we enter or re-enter it
6187 game.comhere = False
6193 game.inorbit = False
6195 game.ientesc = False
6198 game.iseenit = False
6200 # Attempt to escape Super-commander, so tbeam back!
6203 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6204 # cope with supernova
6207 game.klhere = q.klingons
6208 game.irhere = q.romulans
6209 game.nenhere = game.klhere + game.irhere
6211 game.quad[game.sector.x][game.sector.y] = game.ship
6214 # Position ordinary Klingons
6215 for i in range(game.klhere):
6216 game.enemies.append(newkling())
6217 # If we need a commander, promote a Klingon
6218 for i in range(game.state.remcom):
6219 if game.state.kcmdr[i] == game.quadrant:
6220 e = game.enemies[game.klhere-1]
6221 game.quad[e.kloc.x][e.kloc.y] = IHC
6222 e.kpower = randreal(950,1350) + 50.0*game.skill
6225 # If we need a super-commander, promote a Klingon
6226 if game.quadrant == game.state.kscmdr:
6228 game.quad[e.kloc.x][e.kloc.y] = IHS
6229 e.kpower = randreal(1175.0, 1575.0) + 125.0*game.skill
6230 game.iscate = (game.state.remkl > 1)
6232 # Put in Romulans if needed
6233 for i in range(game.klhere, game.nenhere):
6234 game.enemies.append(enemy(loc=dropin(IHR),
6235 power=randreal(400.0,850.0)+50.0*game.skill))
6236 # If quadrant needs a starbase, put it in
6238 game.base = dropin(IHB)
6239 # If quadrant needs a planet, put it in
6241 game.iplnet = q.planet
6242 if not q.planet.inhabited:
6243 game.plnet = dropin(IHP)
6245 game.plnet = dropin(IHW)
6246 # Check for condition
6248 # And finally the stars
6249 for i in range(q.stars):
6252 if game.irhere > 0 and game.klhere == 0:
6254 if not damaged(DRADIO):
6256 prout(_("LT. Uhura- \"Captain, an urgent message."))
6257 prout(_(" I'll put it on audio.\" CLICK"))
6259 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6260 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6262 # Put in THING if needed
6263 if thing == game.quadrant:
6264 e = enemy(dropin(IHQUEST))
6265 e.kdist = e.kavgd = distance(game.sector, e.kloc)
6266 e.kpower = randreal(6000,6500.0)+250.0*game.skill
6267 games.enemies.append(e)
6269 if not damaged(DSRSENS):
6271 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6272 prout(_(" Please examine your short-range scan.\""))
6273 # Decide if quadrant needs a Tholian; lighten up if skill is low
6274 if game.options & OPTION_THOLIAN:
6275 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
6276 (game.skill == SKILL_GOOD and withprob(0.05)) or \
6277 (game.skill > SKILL_GOOD and withprob(0.08)):
6278 game.tholian = coord()
6280 game.tholian.x = withprob(0.5) * (QUADSIZE-1)
6281 game.tholian.y = withprob(0.5) * (QUADSIZE-1)
6282 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6284 game.quad[game.tholian.x][game.tholian.y] = IHT
6285 game.enemies.append(loc=game.tholian,
6286 power=randrange(100, 500) + 25.0*game.skill)
6288 # Reserve unoccupied corners
6289 if game.quad[0][0]==IHDOT:
6290 game.quad[0][0] = 'X'
6291 if game.quad[0][QUADSIZE-1]==IHDOT:
6292 game.quad[0][QUADSIZE-1] = 'X'
6293 if game.quad[QUADSIZE-1][0]==IHDOT:
6294 game.quad[QUADSIZE-1][0] = 'X'
6295 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6296 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6298 # Put in a few black holes
6299 for i in range(1, 3+1):
6302 # Take out X's in corners if Tholian present
6304 if game.quad[0][0]=='X':
6305 game.quad[0][0] = IHDOT
6306 if game.quad[0][QUADSIZE-1]=='X':
6307 game.quad[0][QUADSIZE-1] = IHDOT
6308 if game.quad[QUADSIZE-1][0]=='X':
6309 game.quad[QUADSIZE-1][0] = IHDOT
6310 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6311 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6314 # sort Klingons by distance from us
6315 # The author liked bubble sort. So we will use it. :-(
6316 if game.nenhere-(thing==game.quadrant)-(game.tholian!=None) < 2:
6320 for j in range(game.nenhere-1):
6321 if game.enemies[j].kdist > game.enemies[j+1].kdist:
6323 t = game.enemies[j].kdist
6324 game.enemies[j].kdist = game.enemies[j+1].kdist
6325 game.enemies[j+1].kdist = t
6326 t = game.enemies[j].kavgd
6327 game.enemies[j].kavgd = game.enemies[j+1].kavgd
6328 game.enemies[j+1].kavgd = t
6329 k = game.enemies[j].kloc.x
6330 game.enemies[j].kloc.x = game.enemies[j+1].kloc.x
6331 game.enemies[j+1].kloc.x = k
6332 k = game.enemies[j].kloc.y
6333 game.enemies[j].kloc.y = game.enemies[j+1].kloc.y
6334 game.enemies[j+1].kloc.y = k
6335 t = game.enemies[j].kpower
6336 game.enemies[j].kpower = game.enemies[j+1].kpower
6337 game.enemies[j+1].kpower = t
6342 # set the self-destruct password
6343 if game.options & OPTION_PLAIN:
6346 proutn(_("Please type in a secret password- "))
6349 if game.passwd != None:
6354 game.passwd += chr(ord('a')+randrange(26))
6356 # Code from sst.c begins here
6359 "SRSCAN": OPTION_TTY,
6360 "STATUS": OPTION_TTY,
6361 "REQUEST": OPTION_TTY,
6362 "LRSCAN": OPTION_TTY,
6375 "SENSORS": OPTION_PLANETS,
6376 "ORBIT": OPTION_PLANETS,
6377 "TRANSPORT": OPTION_PLANETS,
6378 "MINE": OPTION_PLANETS,
6379 "CRYSTALS": OPTION_PLANETS,
6380 "SHUTTLE": OPTION_PLANETS,
6381 "PLANETS": OPTION_PLANETS,
6386 "PROBE": OPTION_PROBE,
6388 "FREEZE": 0, # Synonym for SAVE
6394 "SOS": 0, # Synonym for MAYDAY
6395 "CALL": 0, # Synonym for MAYDAY
6402 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6405 # generate a list of legal commands
6407 proutn(_("LEGAL COMMANDS ARE:"))
6408 for key in commands:
6412 proutn("%-12s " % key)
6417 # browse on-line help
6418 # Give help on commands
6422 setwnd(prompt_window)
6423 proutn(_("Help on what command? "))
6425 setwnd(message_window)
6428 if citem in commands or citem == "ABBREV":
6437 fp = open(SSTDOC, "r")
6440 fp = open(DOC_NAME, "r")
6442 prout(_("Spock- \"Captain, that information is missing from the"))
6443 proutn(_(" computer. You need to find "))
6445 prout(_(" and put it in the"))
6446 proutn(_(" current directory or to "))
6450 # This used to continue: "You need to find SST.DOC and put
6451 # it in the current directory."
6455 linebuf = fp.readline()
6457 prout(_("Spock- \"Captain, there is no information on that command.\""))
6460 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6461 linebuf = linebuf[3:].strip()
6465 prout(_("Spock- \"Captain, I've found the following information:\""))
6467 while linebuf in fp:
6468 if "******" in linebuf:
6474 # command-interpretation loop
6477 setwnd(message_window)
6478 while True: # command loop
6480 while True: # get a command
6485 setwnd(prompt_window)
6489 if game.options & OPTION_CURSES:
6494 setwnd(message_window)
6496 candidates = filter(lambda x: x.startswith(citem.upper()),
6498 if len(candidates) == 1:
6501 elif candidates and not (game.options & OPTION_PLAIN):
6502 prout("Commands with that prefix: " + " ".join(candidates))
6506 if cmd == "SRSCAN": # srscan
6508 elif cmd == "STATUS": # status
6510 elif cmd == "REQUEST": # status request
6512 elif cmd == "LRSCAN": # long range scan
6513 lrscan(silent=False)
6514 elif cmd == "PHASERS": # phasers
6518 elif cmd == "TORPEDO": # photon torpedos
6522 elif cmd == "MOVE": # move under warp
6524 elif cmd == "SHIELDS": # shields
6525 doshield(shraise=False)
6528 game.shldchg = False
6529 elif cmd == "DOCK": # dock at starbase
6533 elif cmd == "DAMAGES": # damage reports
6535 elif cmd == "CHART": # chart
6537 elif cmd == "IMPULSE": # impulse
6539 elif cmd == "REST": # rest
6543 elif cmd == "WARP": # warp
6545 elif cmd == "SCORE": # score
6547 elif cmd == "SENSORS": # sensors
6549 elif cmd == "ORBIT": # orbit
6553 elif cmd == "TRANSPORT": # transport "beam"
6555 elif cmd == "MINE": # mine
6559 elif cmd == "CRYSTALS": # crystals
6563 elif cmd == "SHUTTLE": # shuttle
6567 elif cmd == "PLANETS": # Planet list
6569 elif cmd == "REPORT": # Game Report
6571 elif cmd == "COMPUTER": # use COMPUTER!
6573 elif cmd == "COMMANDS":
6575 elif cmd == "EMEXIT": # Emergency exit
6576 clrscr() # Hide screen
6577 freeze(True) # forced save
6578 raise SysExit,1 # And quick exit
6579 elif cmd == "PROBE":
6580 probe() # Launch probe
6583 elif cmd == "ABANDON": # Abandon Ship
6585 elif cmd == "DESTRUCT": # Self Destruct
6587 elif cmd == "SAVE": # Save Game
6590 if game.skill > SKILL_GOOD:
6591 prout(_("WARNING--Saved games produce no plaques!"))
6592 elif cmd == "DEATHRAY": # Try a desparation measure
6596 elif cmd == "DEBUGCMD": # What do we want for debug???
6598 elif cmd == "MAYDAY": # Call for help
6603 game.alldone = True # quit the game
6608 break # Game has ended
6609 if game.optime != 0.0:
6612 break # Events did us in
6613 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6616 if hitme and not game.justin:
6620 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6632 if cmd == IHR: s = _("Romulan")
6633 elif cmd == IHK: s = _("Klingon")
6634 elif cmd == IHC: s = _("Commander")
6635 elif cmd == IHS: s = _("Super-commander")
6636 elif cmd == IHSTAR: s = _("Star")
6637 elif cmd == IHP: s = _("Planet")
6638 elif cmd == IHB: s = _("Starbase")
6639 elif cmd == IHBLANK: s = _("Black hole")
6640 elif cmd == IHT: s = _("Tholian")
6641 elif cmd == IHWEB: s = _("Tholian web")
6642 elif cmd == IHQUEST: s = _("Stranger")
6643 elif cmd == IHW: s = _("Inhabited World")
6644 else: s = "Unknown??"
6647 def crmena(stars, enemy, loctype, w):
6648 # print an enemy and his location
6654 if loctype == "quadrant":
6655 buf = _("Quadrant ")
6656 elif loctype == "sector":
6661 # print our ship name
6662 if game.ship == IHE:
6664 elif game.ship == IHF:
6665 s = _("Faerie Queene")
6671 # print a line of stars
6672 prouts("******************************************************")
6676 return -avrage*math.log(1e-7 + randreal())
6678 def randplace(size):
6679 # choose a random location
6681 w.x = randrange(size)
6682 w.y = randrange(size)
6686 # Demand input for next scan
6691 # return IHEOL next time
6696 # Get a token from the user
6697 global inqueue, line, citem, aaitem
6701 # Read a line if nothing here
6704 if curwnd==prompt_window:
6706 setwnd(message_window)
6708 # Skip leading white space
6709 line = line.lstrip()
6711 inqueue = line.split()
6717 # From here on in it's all looking at the queue
6718 citem = inqueue.pop(0)
6722 aaitem = float(citem)
6727 citem = citem.lower()
6731 # yes-or-no confirmation
6740 proutn(_("Please answer with \"y\" or \"n\": "))
6743 # complain about unparseable input
6746 prout(_("Beg your pardon, Captain?"))
6749 # compares s to citem and returns true if it matches to the length of s
6750 return s.startswith(citem)
6753 # access to the internals for debugging
6754 proutn("Reset levels? ")
6756 if game.energy < game.inenrg:
6757 game.energy = game.inenrg
6758 game.shield = game.inshld
6759 game.torps = game.intorps
6760 game.lsupres = game.inlsr
6761 proutn("Reset damage? ")
6763 for i in range(NDEVICES):
6764 if game.damage[i] > 0.0:
6765 game.damage[i] = 0.0
6766 proutn("Toggle debug flag? ")
6770 prout("Debug output ON")
6772 prout("Debug output OFF")
6773 proutn("Cause selective damage? ")
6775 for i in range(NDEVICES):
6781 if key == IHALPHA and isit("y"):
6782 game.damage[i] = 10.0
6783 proutn("Examine/change events? ")
6788 FSNOVA: "Supernova ",
6791 FBATTAK: "Base Attack ",
6792 FCDBAS: "Base Destroy ",
6793 FSCMOVE: "SC Move ",
6794 FSCDBAS: "SC Base Destroy ",
6795 FDSPROB: "Probe Move ",
6796 FDISTR: "Distress Call ",
6797 FENSLV: "Enslavement ",
6798 FREPRO: "Klingon Build ",
6800 for i in range(1, NEVENTS):
6803 proutn("%.2f" % (scheduled(i)-game.state.date))
6804 if i == FENSLV or i == FREPRO:
6806 proutn(" in %s" % ev.quadrant)
6816 ev = schedule(i, aaitem)
6817 if i == FENSLV or i == FREPRO:
6819 proutn("In quadrant- ")
6821 # IHEOL says to leave coordinates as they are
6824 prout("Event %d canceled, no x coordinate." % (i))
6827 w.x = int(round(aaitem))
6830 prout("Event %d canceled, no y coordinate." % (i))
6833 w.y = int(round(aaitem))
6836 proutn("Induce supernova here? ")
6838 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6841 if __name__ == '__main__':
6843 global line, thing, game, idebug, iqengry
6844 game = citem = aaitem = inqueue = None
6850 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6851 # Disable curses mode until the game logic is working.
6852 # if os.getenv("TERM"):
6853 # game.options |= OPTION_CURSES | OPTION_SHOWME
6855 game.options |= OPTION_TTY
6856 seed = int(time.time())
6857 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6858 for (switch, val) in options:
6861 replayfp = open(val, "r")
6863 sys.stderr.write("sst: can't open replay file %s\n" % val)
6866 line = replayfp.readline().strip()
6867 (leader, key, seed) = line.split()
6869 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6870 line = replayfp.readline().strip()
6871 arguments += line.split()[2:]
6873 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6875 game.options |= OPTION_TTY
6876 game.options &=~ OPTION_CURSES
6877 elif switch == '-t':
6878 game.options |= OPTION_TTY
6879 game.options &=~ OPTION_CURSES
6880 elif switch == '-x':
6883 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6885 # where to save the input in case of bugs
6887 logfp = open("/usr/tmp/sst-input.log", "w")
6889 sys.stderr.write("sst: warning, can't open logfile\n")
6891 logfp.write("# seed %s\n" % seed)
6892 logfp.write("# options %s\n" % " ".join(arguments))
6899 while True: # Play a game
6900 setwnd(fullscreen_window)
6903 setup(needprompt=not inqueue)
6906 game.alldone = False
6912 if game.tourn and game.alldone:
6913 proutn(_("Do you want your score recorded?"))
6918 proutn(_("Do you want to play again? "))
6922 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6924 except KeyboardInterrupt: