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 import os, sys, math, curses, time, atexit, readline, cPickle, random, getopt
178 SSTDOC = "/usr/share/doc/sst/sst.doc"
181 # Stub to be replaced
182 def _(str): return str
186 NINHAB = (GALSIZE * GALSIZE / 2)
188 PLNETMAX = (NINHAB + MAXUNINHAB)
191 BASEMAX = (GALSIZE * GALSIZE / 12)
194 FULLCREW = 428 # BSD Trek was 387, that's wrong
197 # These functions hide the difference between 0-origin and 1-origin addressing.
198 def VALID_QUADRANT(x, y): return ((x)>=0 and (x)<GALSIZE and (y)>=0 and (y)<GALSIZE)
199 def VALID_SECTOR(x, y): return ((x)>=0 and (x)<QUADSIZE and (y)>=0 and (y)<QUADSIZE)
201 def square(i): return ((i)*(i))
202 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
203 def invalidate(w): w.x = w.y = 0
204 def is_valid(w): return (w.x != 0 and w.y != 0)
206 # How to represent features
231 def __init__(self, x=None, y=None):
234 def invalidate(self):
235 self.x = self.y = None
237 return self.x != None and self.y != None
238 def __eq__(self, other):
239 return other != None and self.x == other.y and self.x == other.y
240 def __add__(self, other):
241 return coord(self.x+self.x, self.y+self.y)
242 def __sub__(self, other):
243 return coord(self.x-self.x, self.y-self.y)
244 def distance(self, other):
245 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
247 return coord(self.x / abs(x), self.y / abs(y));
251 return "%s - %s" % (self.x+1, self.y+1)
256 self.name = None # string-valued if inhabited
257 self.w = coord() # quadrant located
258 self.pclass = None # could be ""M", "N", "O", or "destroyed"
259 self.crystals = "absent"# could be "mined", "present", "absent"
260 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
261 self.inhabited = False # is it inhabites?
273 self.supernova = None
275 self.status = None # Could be "secure", "distressed", "enslaved"
283 def fill2d(size, fillfun):
284 "Fill an empty list in 2D."
286 for i in range(size):
288 for j in range(size):
289 lst[i].append(fillfun(i, j))
294 self.snap = False # snapshot taken
295 self.crew = 0 # crew complement
296 self.remkl = 0 # remaining klingons
297 self.remcom = 0 # remaining commanders
298 self.nscrem = 0 # remaining super commanders
299 self.rembase = 0 # remaining bases
300 self.starkl = 0 # destroyed stars
301 self.basekl = 0 # destroyed bases
302 self.nromrem = 0 # Romulans remaining
303 self.nplankl = 0 # destroyed uninhabited planets
304 self.nworldkl = 0 # destroyed inhabited planets
305 self.planets = [] # Planet information
306 self.date = 0.0 # stardate
307 self.remres = 0 # remaining resources
308 self.remtime = 0 # remaining time
309 self.baseq = [] # Base quadrant coordinates
310 for i in range(BASEMAX):
311 self.baseq.append(coord())
312 self.kcmdr = [] # Commander quadrant coordinates
313 for i in range(QUADSIZE):
314 self.kcmdr.append(coord())
315 self.kscmdr = coord() # Supercommander quadrant coordinates
316 # the galaxy (subscript 0 not used)
317 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
318 # the starchart (subscript 0 not used)
319 self.chart = fill2d(GALSIZE, lambda i, j: page())
323 self.date = None # A real number
324 self.quadrant = None # A coord structure
327 OPTION_ALL = 0xffffffff
328 OPTION_TTY = 0x00000001 # old interface
329 OPTION_CURSES = 0x00000002 # new interface
330 OPTION_IOMODES = 0x00000003 # cover both interfaces
331 OPTION_PLANETS = 0x00000004 # planets and mining
332 OPTION_THOLIAN = 0x00000008 # Tholians and their webs
333 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back
334 OPTION_PROBE = 0x00000020 # deep-space probes
335 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
336 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise
337 OPTION_MVBADDY = 0x00000100 # more enemies can move
338 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you
339 OPTION_BASE = 0x00000400 # bases have good shields
340 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds
341 OPTION_PLAIN = 0x01000000 # user chose plain game
342 OPTION_ALMY = 0x02000000 # user chose Almy variant
361 NDEVICES= 16 # Number of devices
370 def damaged(dev): return (game.damage[dev] != 0.0)
371 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
373 # Define future events
374 FSPY = 0 # Spy event happens always (no future[] entry)
375 # can cause SC to tractor beam Enterprise
376 FSNOVA = 1 # Supernova
377 FTBEAM = 2 # Commander tractor beams Enterprise
378 FSNAP = 3 # Snapshot for time warp
379 FBATTAK = 4 # Commander attacks base
380 FCDBAS = 5 # Commander destroys base
381 FSCMOVE = 6 # Supercommander moves (might attack base)
382 FSCDBAS = 7 # Supercommander destroys base
383 FDSPROB = 8 # Move deep space probe
384 FDISTR = 9 # Emit distress call from an inhabited world
385 FENSLV = 10 # Inhabited word is enslaved */
386 FREPRO = 11 # Klingons build a ship in an enslaved system
390 # abstract out the event handling -- underlying data structures will change
391 # when we implement stateful events
393 def findevent(evtype): return game.future[evtype]
397 self.options = None # Game options
398 self.state = snapshot() # A snapshot structure
399 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
400 self.quad = fill2d(QUADSIZE, lambda i, j: IHDOT) # contents of our quadrant
401 self.kpower = fill2d(QUADSIZE, lambda i, j: 0.0) # enemy energy levels
402 self.kdist = fill2d(QUADSIZE, lambda i, j: 0.0) # enemy distances
403 self.kavgd = fill2d(QUADSIZE, lambda i, j: 0.0) # average distances
404 self.damage = [0.0] * NDEVICES # damage encountered
405 self.future = [] # future events
406 for i in range(NEVENTS):
407 self.future.append(event())
408 self.passwd = None; # Self Destruct password
409 self.ks = fill2d(QUADSIZE, lambda i, j: coord()) # enemy sector locations
410 self.quadrant = None # where we are in the large
411 self.sector = None # where we are in the small
412 self.tholian = None # coordinates of Tholian
413 self.base = None # position of base in current quadrant
414 self.battle = None # base coordinates being attacked
415 self.plnet = None # location of planet in quadrant
416 self.probec = None # current probe quadrant
417 self.gamewon = False # Finished!
418 self.ididit = False # action taken -- allows enemy to attack
419 self.alive = False # we are alive (not killed)
420 self.justin = False # just entered quadrant
421 self.shldup = False # shields are up
422 self.shldchg = False # shield is changing (affects efficiency)
423 self.comhere = False # commander here
424 self.ishere = False # super-commander in quadrant
425 self.iscate = False # super commander is here
426 self.ientesc = False # attempted escape from supercommander
427 self.ithere = False # Tholian is here
428 self.resting = False # rest time
429 self.icraft = False # Kirk in Galileo
430 self.landed = False # party on planet (true), on ship (false)
431 self.alldone = False # game is now finished
432 self.neutz = False # Romulan Neutral Zone
433 self.isarmed = False # probe is armed
434 self.inorbit = False # orbiting a planet
435 self.imine = False # mining
436 self.icrystl = False # dilithium crystals aboard
437 self.iseenit = False # seen base attack report
438 self.thawed = False # thawed game
439 self.condition = None # "green", "yellow", "red", "docked", "dead"
440 self.iscraft = None # "onship", "offship", "removed"
441 self.skill = None # Player skill level
442 self.inkling = 0 # initial number of klingons
443 self.inbase = 0 # initial number of bases
444 self.incom = 0 # initial number of commanders
445 self.inscom = 0 # initial number of commanders
446 self.inrom = 0 # initial number of commanders
447 self.instar = 0 # initial stars
448 self.intorps = 0 # initial/max torpedoes
449 self.torps = 0 # number of torpedoes
450 self.ship = 0 # ship type -- 'E' is Enterprise
451 self.abandoned = 0 # count of crew abandoned in space
452 self.length = 0 # length of game
453 self.klhere = 0 # klingons here
454 self.casual = 0 # causalties
455 self.nhelp = 0 # calls for help
456 self.nkinks = 0 # count of energy-barrier crossings
457 self.iplnet = 0 # planet # in quadrant
458 self.inplan = 0 # initial planets
459 self.nenhere = 0 # number of enemies in quadrant
460 self.irhere = 0 # Romulans in quadrant
461 self.isatb = 0 # =1 if super commander is attacking base
462 self.tourn = 0 # tournament number
463 self.proben = 0 # number of moves for probe
464 self.nprobes = 0 # number of probes available
465 self.inresor = 0.0 # initial resources
466 self.intime = 0.0 # initial time
467 self.inenrg = 0.0 # initial/max energy
468 self.inshld = 0.0 # initial/max shield
469 self.inlsr = 0.0 # initial life support resources
470 self.indate = 0.0 # initial date
471 self.energy = 0.0 # energy level
472 self.shield = 0.0 # shield level
473 self.warpfac = 0.0 # warp speed
474 self.wfacsq = 0.0 # squared warp factor
475 self.lsupres = 0.0 # life support reserves
476 self.dist = 0.0 # movement distance
477 self.direc = 0.0 # movement direction
478 self.optime = 0.0 # time taken by current operation
479 self.docfac = 0.0 # repair factor when docking (constant?)
480 self.damfac = 0.0 # damage factor
481 self.lastchart = 0.0 # time star chart was last updated
482 self.cryprob = 0.0 # probability that crystal will work
483 self.probex = 0.0 # location of probe
485 self.probeinx = 0.0 # probe x,y increment
486 self.probeiny = 0.0 #
487 self.height = 0.0 # height of orbit around planet
489 # Stas thinks this should be (C expression):
490 # game.state.remkl + game.state.remcom > 0 ?
491 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
492 # He says the existing expression is prone to divide-by-zero errors
493 # after killing the last klingon when score is shown -- perhaps also
494 # if the only remaining klingon is SCOM.
495 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
496 # From enumerated type 'feature'
517 # From enumerated type 'FINTYPE'
541 # From enumerated type 'COLORS'
560 # Code from ai.c begins here
562 def tryexit(look, ienm, loccom, irun):
563 # a bad guy attempts to bug out
565 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
566 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
567 if not VALID_QUADRANT(iq.x,iq.y) or \
568 game.state.galaxy[iq.x][iq.y].supernova or \
569 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
570 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
572 return False; # Romulans cannot escape!
574 # avoid intruding on another commander's territory
576 for n in range(game.state.remcom):
577 if game.state.kcmdr[n] == iq:
579 # refuse to leave if currently attacking starbase
580 if game.battle == game.quadrant:
582 # don't leave if over 1000 units of energy
583 if game.kpower[loccom] > 1000.0:
585 # print escape message and move out of quadrant.
586 # we know this if either short or long range sensors are working
587 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
588 game.condition == docked:
589 crmena(True, ienm, "sector", game.ks[loccom])
590 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
591 # handle local matters related to escape
592 game.quad[game.ks[loccom].x][game.ks[loccom].y] = IHDOT
593 game.ks[loccom] = game.ks[game.nenhere]
594 game.kavgd[loccom] = game.kavgd[game.nenhere]
595 game.kpower[loccom] = game.kpower[game.nenhere]
596 game.kdist[loccom] = game.kdist[game.nenhere]
599 if game.condition != docked:
601 # Handle global matters related to escape
602 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
603 game.state.galaxy[iq.x][iq.y].klingons += 1
609 schedule(FSCMOVE, 0.2777)
613 for n in range(game.state.remcom):
614 if game.state.kcmdr[n] == game.quadrant:
615 game.state.kcmdr[n]=iq
618 return True; # success
621 # The bad-guy movement algorithm:
623 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
624 # If both are operating full strength, force is 1000. If both are damaged,
625 # force is -1000. Having shields down subtracts an additional 1000.
627 # 2. Enemy has forces equal to the energy of the attacker plus
628 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
629 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
631 # Attacker Initial energy levels (nominal):
632 # Klingon Romulan Commander Super-Commander
633 # Novice 400 700 1200
635 # Good 450 800 1300 1750
636 # Expert 475 850 1350 1875
637 # Emeritus 500 900 1400 2000
638 # VARIANCE 75 200 200 200
640 # Enemy vessels only move prior to their attack. In Novice - Good games
641 # only commanders move. In Expert games, all enemy vessels move if there
642 # is a commander present. In Emeritus games all enemy vessels move.
644 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
645 # forces are 1000 greater than Enterprise.
647 # Agressive action on average cuts the distance between the ship and
648 # the enemy to 1/4 the original.
650 # 4. At lower energy advantage, movement units are proportional to the
651 # advantage with a 650 advantage being to hold ground, 800 to move forward
652 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
654 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
655 # retreat, especially at high skill levels.
657 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
660 def movebaddy(com, loccom, ienm):
661 # tactical movement for the bad guys
662 next = coord(); look = coord()
664 # This should probably be just game.comhere + game.ishere
665 if game.skill >= SKILL_EXPERT:
666 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
668 nbaddys = game.comhere + game.ishere
670 dist1 = game.kdist[loccom]
671 mdist = int(dist1 + 0.5); # Nearest integer distance
673 # If SC, check with spy to see if should hi-tail it
675 (game.kpower[loccom] <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
679 # decide whether to advance, retreat, or hold position
680 forces = game.kpower[loccom]+100.0*game.nenhere+400*(nbaddys-1)
682 forces += 1000; # Good for enemy if shield is down!
683 if not damaged(DPHASER) or not damaged(DPHOTON):
684 if damaged(DPHASER): # phasers damaged
687 forces -= 0.2*(game.energy - 2500.0)
688 if damaged(DPHOTON): # photon torpedoes damaged
691 forces -= 50.0*game.torps
693 # phasers and photon tubes both out!
696 if forces <= 1000.0 and game.condition != "docked": # Typical situation
697 motion = ((forces+200.0*random.random())/150.0) - 5.0
699 if forces > 1000.0: # Very strong -- move in for kill
700 motion = (1.0-square(random.random()))*dist1 + 1.0
701 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
702 motion -= game.skill*(2.0-square(random.random()))
704 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
705 # don't move if no motion
708 # Limit motion according to skill
709 if abs(motion) > game.skill:
714 # calculate preferred number of steps
719 if motion > 0 and nsteps > mdist:
720 nsteps = mdist; # don't overshoot
721 if nsteps > QUADSIZE:
722 nsteps = QUADSIZE; # This shouldn't be necessary
724 nsteps = 1; # This shouldn't be necessary
726 proutn("NSTEPS = %d:" % nsteps)
727 # Compute preferred values of delta X and Y
728 mx = game.sector.x - com.x
729 my = game.sector.y - com.y
730 if 2.0 * abs(mx) < abs(my):
732 if 2.0 * abs(my) < abs(game.sector.x-com.x):
746 for ll in range(nsteps):
748 proutn(" %d" % (ll+1))
749 # Check if preferred position available
761 attempts = 0; # Settle mysterious hang problem
762 while attempts < 20 and not success:
764 if look.x < 0 or look.x >= QUADSIZE:
765 if motion < 0 and tryexit(look, ienm, loccom, irun):
767 if krawlx == mx or my == 0:
769 look.x = next.x + krawlx
771 elif look.y < 0 or look.y >= QUADSIZE:
772 if motion < 0 and tryexit(look, ienm, loccom, irun):
774 if krawly == my or mx == 0:
776 look.y = next.y + krawly
778 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
779 # See if we should ram ship
780 if game.quad[look.x][look.y] == game.ship and \
781 (ienm == IHC or ienm == IHS):
784 if krawlx != mx and my != 0:
785 look.x = next.x + krawlx
787 elif krawly != my and mx != 0:
788 look.y = next.y + krawly
791 break; # we have failed
803 # Put commander in place within same quadrant
804 game.quad[com.x][com.y] = IHDOT
805 game.quad[next.x][next.y] = ienm
808 game.ks[loccom] = next
809 game.kdist[loccom] = game.kavgd[loccom] = distance(game.sector, next)
810 if not damaged(DSRSENS) or game.condition == docked:
813 proutn(_(" from Sector %s") % com)
814 if game.kdist[loccom] < dist1:
815 proutn(_(" advances to "))
817 proutn(_(" retreats to "))
818 prout("Sector %s." % next)
821 # Klingon tactical movement
824 # Figure out which Klingon is the commander (or Supercommander)
827 for i in range(game.nenhere):
829 if game.quad[w.x][w.y] == IHC:
833 for i in range(game.nenhere):
835 if game.quad[w.x][w.y] == IHS:
838 # If skill level is high, move other Klingons and Romulans too!
839 # Move these last so they can base their actions on what the
841 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
842 for i in range(game.nenhere):
844 if game.quad[w.x][w.y] == IHK or game.quad[w.x][w.y] == IHR:
845 movebaddy(w, i, game.quad[w.x][w.y])
848 def movescom(iq, avoid):
849 # commander movement helper
850 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
851 game.state.galaxy[iq.x][iq.y].supernova or \
852 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
855 # Avoid quadrants with bases if we want to avoid Enterprise
856 for i in range(game.state.rembase):
857 if game.state.baseq[i] == iq:
859 if game.justin and not game.iscate:
862 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
863 game.state.kscmdr = iq
864 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
866 # SC has scooted, Remove him from current quadrant
872 for i in range(game.nenhere):
873 if game.quad[game.ks[i].x][game.ks[i].y] == IHS:
875 game.quad[game.ks[i].x][game.ks[i].y] = IHDOT
876 game.ks[i] = game.ks[game.nenhere]
877 game.kdist[i] = game.kdist[game.nenhere]
878 game.kavgd[i] = game.kavgd[game.nenhere]
879 game.kpower[i] = game.kpower[game.nenhere]
882 if game.condition!=docked:
885 # check for a helpful planet
886 for i in range(game.inplan):
887 if game.state.planets[i].w == game.state.kscmdr and \
888 game.state.planets[i].crystals == "present":
890 game.state.planets[i].pclass = "destroyed"
891 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = NOPLANET
894 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
895 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
896 prout(_(" by the Super-commander.\""))
898 return False; # looks good!
900 def supercommander():
901 # move the Super Commander
902 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
905 prout("== SUPERCOMMANDER")
906 # Decide on being active or passive
907 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 \
908 (game.state.date-game.indate) < 3.0)
909 if not game.iscate and avoid:
910 # compute move away from Enterprise
911 idelta = game.state.kscmdr-game.quadrant
912 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
914 idelta.x = game.state.kscmdr.y-game.quadrant.y
915 idelta.y = game.quadrant.x-game.state.kscmdr.x
917 # compute distances to starbases
918 if game.state.rembase <= 0:
922 sc = game.state.kscmdr
923 for i in range(game.state.rembase):
924 basetbl.append((i, distance(game.state.baseq[i], sc)))
925 if game.state.rembase > 1:
926 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
927 # look for nearest base without a commander, no Enterprise, and
928 # without too many Klingons, and not already under attack.
929 ifindit = iwhichb = 0
930 for i2 in range(game.state.rembase):
931 i = basetbl[i2][0]; # bug in original had it not finding nearest
932 ibq = game.state.baseq[i]
933 if ibq == game.quadrant or ibq == game.battle or \
934 game.state.galaxy[ibq.x][ibq.y].supernova or \
935 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
937 # if there is a commander, and no other base is appropriate,
938 # we will take the one with the commander
939 for j in range(game.state.remcom):
940 if ibq == game.state.kcmdr[j] and ifindit!= 2:
944 if j > game.state.remcom: # no commander -- use this one
949 return; # Nothing suitable -- wait until next time
950 ibq = game.state.baseq[iwhichb]
951 # decide how to move toward base
952 idelta = ibq - game.state.kscmdr
953 # Maximum movement is 1 quadrant in either or both axes
954 idelta = idelta.sgn()
955 # try moving in both x and y directions
956 # there was what looked like a bug in the Almy C code here,
957 # but it might be this translation is just wrong.
958 iq = game.state.kscmdr + idelta
959 if movescom(iq, avoid):
960 # failed -- try some other maneuvers
961 if idelta.x==0 or idelta.y==0:
964 iq.y = game.state.kscmdr.y + 1
965 if movescom(iq, avoid):
966 iq.y = game.state.kscmdr.y - 1
969 iq.x = game.state.kscmdr.x + 1
970 if movescom(iq, avoid):
971 iq.x = game.state.kscmdr.x - 1
974 # try moving just in x or y
975 iq.y = game.state.kscmdr.y
976 if movescom(iq, avoid):
977 iq.y = game.state.kscmdr.y + idelta.y
978 iq.x = game.state.kscmdr.x
981 if game.state.rembase == 0:
984 for i in range(game.state.rembase):
985 ibq = game.state.baseq[i]
986 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
989 return; # no, don't attack base!
992 schedule(FSCDBAS, 1.0 +2.0*random.random())
993 if is_scheduled(FCDBAS):
994 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
995 if not communicating():
999 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
1000 % game.state.kscmdr)
1001 prout(_(" reports that it is under attack from the Klingon Super-commander."))
1002 proutn(_(" It can survive until stardate %d.\"") \
1003 % int(scheduled(FSCDBAS)))
1004 if not game.resting:
1006 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1009 game.resting = False
1010 game.optime = 0.0; # actually finished
1012 # Check for intelligence report
1014 (random.random() > 0.2 or \
1015 (not communicating()) or \
1016 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1019 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1020 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1025 if not game.ithere or game.justin:
1028 if game.tholian.x == 0 and game.tholian.y == 0:
1029 idx = 0; idy = QUADSIZE-1
1030 elif game.tholian.x == 0 and game.tholian.y == QUADSIZE-1:
1031 idx = QUADSIZE-1; idy = QUADSIZE-1
1032 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == QUADSIZE-1:
1033 idx = QUADSIZE-1; idy = 0
1034 elif game.tholian.x == QUADSIZE-1 and game.tholian.y == 0:
1037 # something is wrong!
1041 # do nothing if we are blocked
1042 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1044 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1046 if game.tholian.x != idx:
1048 im = math.fabs(idx - game.tholian.x)*1.0/(idx - game.tholian.x)
1049 while game.tholian.x != idx:
1050 game.tholian.x += im
1051 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1052 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1053 elif game.tholian.y != idy:
1055 im = math.fabs(idy - game.tholian.y)*1.0/(idy - game.tholian.y)
1056 while game.tholian.y != idy:
1057 game.tholian.y += im
1058 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1059 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1060 game.quad[game.tholian.x][game.tholian.y] = IHT
1061 game.ks[game.nenhere] = game.tholian
1063 # check to see if all holes plugged
1064 for i in range(QUADSIZE):
1065 if game.quad[0][i]!=IHWEB and game.quad[0][i]!=IHT:
1067 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1069 if game.quad[i][0]!=IHWEB and game.quad[i][0]!=IHT:
1071 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1073 # All plugged up -- Tholian splits
1074 game.quad[game.tholian.x][game.tholian.y]=IHWEB
1076 crmena(True, IHT, "sector", game.tholian)
1077 prout(_(" completes web."))
1082 # Code from battle.c begins here
1084 def doshield(shraise):
1085 # change shield status
1093 if isit("transfer"):
1097 if damaged(DSHIELD):
1098 prout(_("Shields damaged and down."))
1105 proutn(_("Do you wish to change shield energy? "))
1107 proutn(_("Energy to transfer to shields- "))
1109 elif damaged(DSHIELD):
1110 prout(_("Shields damaged and down."))
1113 proutn(_("Shields are up. Do you want them down? "))
1120 proutn(_("Shields are down. Do you want them up? "))
1126 if action == "SHUP": # raise shields
1128 prout(_("Shields already up."))
1132 if game.condition != "docked":
1134 prout(_("Shields raised."))
1135 if game.energy <= 0:
1137 prout(_("Shields raising uses up last of energy."))
1142 elif action == "SHDN":
1144 prout(_("Shields already down."))
1148 prout(_("Shields lowered."))
1151 elif action == "NRG":
1152 while scan() != IHREAL:
1154 proutn(_("Energy to transfer to shields- "))
1158 if aaitem > game.energy:
1159 prout(_("Insufficient ship energy."))
1162 if game.shield+aaitem >= game.inshld:
1163 prout(_("Shield energy maximized."))
1164 if game.shield+aaitem > game.inshld:
1165 prout(_("Excess energy requested returned to ship energy"))
1166 game.energy -= game.inshld-game.shield
1167 game.shield = game.inshld
1169 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1170 # Prevent shield drain loophole
1172 prout(_("Engineering to bridge--"))
1173 prout(_(" Scott here. Power circuit problem, Captain."))
1174 prout(_(" I can't drain the shields."))
1177 if game.shield+aaitem < 0:
1178 prout(_("All shield energy transferred to ship."))
1179 game.energy += game.shield
1182 proutn(_("Scotty- \""))
1184 prout(_("Transferring energy to shields.\""))
1186 prout(_("Draining energy from shields.\""))
1187 game.shield += aaitem
1188 game.energy -= aaitem
1192 # choose a device to damage, at random.
1194 # Quoth Eric Allman in the code of BSD-Trek:
1195 # "Under certain conditions you can get a critical hit. This
1196 # sort of hit damages devices. The probability that a given
1197 # device is damaged depends on the device. Well protected
1198 # devices (such as the computer, which is in the core of the
1199 # ship and has considerable redundancy) almost never get
1200 # damaged, whereas devices which are exposed (such as the
1201 # warp engines) or which are particularly delicate (such as
1202 # the transporter) have a much higher probability of being
1205 # This is one place where OPTION_PLAIN does not restore the
1206 # original behavior, which was equiprobable damage across
1207 # all devices. If we wanted that, we'd return NDEVICES*random.random()
1208 # and have done with it. Also, in the original game, DNAVYS
1209 # and DCOMPTR were the same device.
1211 # Instead, we use a table of weights similar to the one from BSD Trek.
1212 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1213 # We don't have a cloaking device. The shuttle got the allocation
1214 # for the cloaking device, then we shaved a half-percent off
1215 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1218 105, # DSRSENS: short range scanners 10.5%
1219 105, # DLRSENS: long range scanners 10.5%
1220 120, # DPHASER: phasers 12.0%
1221 120, # DPHOTON: photon torpedoes 12.0%
1222 25, # DLIFSUP: life support 2.5%
1223 65, # DWARPEN: warp drive 6.5%
1224 70, # DIMPULS: impulse engines 6.5%
1225 145, # DSHIELD: deflector shields 14.5%
1226 30, # DRADIO: subspace radio 3.0%
1227 45, # DSHUTTL: shuttle 4.5%
1228 15, # DCOMPTR: computer 1.5%
1229 20, # NAVCOMP: navigation system 2.0%
1230 75, # DTRANSP: transporter 7.5%
1231 20, # DSHCTRL: high-speed shield controller 2.0%
1232 10, # DDRAY: death ray 1.0%
1233 30, # DDSP: deep-space probes 3.0%
1235 idx = random.random() * 1000.0 # weights must sum to 1000
1237 for (i, w) in enumerate(weights):
1241 return None; # we should never get here
1243 def ram(ibumpd, ienm, w):
1244 # make our ship ram something
1245 prouts(_("***RED ALERT! RED ALERT!"))
1247 prout(_("***COLLISION IMMINENT."))
1251 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1253 proutn(_(" rammed by "))
1256 crmena(False, ienm, sector, w)
1258 proutn(_(" (original position)"))
1260 deadkl(w, ienm, game.sector)
1263 prout(_(" heavily damaged."))
1264 icas = 10.0+20.0*random.random()
1265 prout(_("***Sickbay reports %d casualties"), icas)
1267 game.state.crew -= icas
1269 # In the pre-SST2K version, all devices got equiprobably damaged,
1270 # which was silly. Instead, pick up to half the devices at
1271 # random according to our weighting table,
1273 ncrits = random.randrange(NDEVICES/2)
1274 for m in range(ncrits):
1276 if game.damage[dev] < 0:
1278 extradm = (10.0*hardness*random.random()+1.0)*game.damfac
1279 # Damage for at least time of travel!
1280 game.damage[dev] += game.optime + extradm
1282 prout(_("***Shields are down."))
1283 if game.state.remkl + game.state.remcom + game.state.nscrem:
1290 def torpedo(course, r, incoming, i, n):
1291 # let a photon torpedo fly
1294 ac = course + 0.25*r
1295 angle = (15.0-ac)*0.5235988
1296 bullseye = (15.0 - course)*0.5235988
1297 deltax = -math.sin(angle);
1298 deltay = math.cos(angle);
1299 x = incoming.x; y = incoming.y
1300 w = coord(); jw = coord()
1301 w.x = w.y = jw.x = jw.y = 0
1302 bigger = max(math.fabs(deltax), math.fabs(deltay))
1305 if not damaged(DSRSENS) or game.condition=="docked":
1306 setwnd(srscan_window)
1308 setwnd(message_window)
1309 # Loop to move a single torpedo
1310 for l in range(1, 15+1):
1315 if not VALID_SECTOR(w.x, w.y):
1317 iquad=game.quad[w.x][w.y]
1318 tracktorpedo(w, l, i, n, iquad)
1322 setwnd(message_window)
1323 if damaged(DSRSENS) and not game.condition=="docked":
1324 skip(1); # start new line after text track
1325 if iquad in (IHE, IHF): # Hit our ship
1327 proutn(_("Torpedo hits "))
1330 hit = 700.0 + 100.0*random.random() - \
1331 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1332 newcnd(); # we're blown out of dock
1333 # We may be displaced.
1334 if game.landed or game.condition=="docked":
1335 return hit # Cheat if on a planet
1336 ang = angle + 2.5*(random.random()-0.5)
1337 temp = math.fabs(math.sin(ang))
1338 if math.fabs(math.cos(ang)) > temp:
1339 temp = math.fabs(math.cos(ang))
1340 xx = -math.sin(ang)/temp
1341 yy = math.cos(ang)/temp
1344 if not VALID_SECTOR(jw.x, jw.y):
1346 if game.quad[jw.x][jw.y]==IHBLANK:
1349 if game.quad[jw.x][jw.y]!=IHDOT:
1350 # can't move into object
1355 elif iquad in (IHC, IHS): # Hit a commander
1356 if random.random() <= 0.05:
1357 crmena(True, iquad, sector, w)
1358 prout(_(" uses anti-photon device;"))
1359 prout(_(" torpedo neutralized."))
1361 elif iquad in (IHR, IHK): # Hit a regular enemy
1363 for ll in range(game.nenhere):
1364 if w == game.ks[ll]:
1366 kp = math.fabs(game.kpower[ll])
1367 h1 = 700.0 + 100.0*random.random() - \
1368 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1372 if game.kpower[ll] < 0:
1373 game.kpower[ll] -= -h1
1375 game.kpower[ll] -= h1
1376 if game.kpower[ll] == 0:
1379 crmena(True, iquad, "sector", w)
1380 # If enemy damaged but not destroyed, try to displace
1381 ang = angle + 2.5*(random.random()-0.5)
1382 temp = math.fabs(math.sin(ang))
1383 if math.fabs(math.cos(ang)) > temp:
1384 temp = math.fabs(math.cos(ang))
1385 xx = -math.sin(ang)/temp
1386 yy = math.cos(ang)/temp
1389 if not VALID_SECTOR(jw.x, jw.y):
1390 prout(_(" damaged but not destroyed."))
1392 if game.quad[jw.x][jw.y]==IHBLANK:
1393 prout(_(" buffeted into black hole."))
1394 deadkl(w, iquad, jw)
1396 if game.quad[jw.x][jw.y]!=IHDOT:
1397 # can't move into object
1398 prout(_(" damaged but not destroyed."))
1400 proutn(_(" damaged--"))
1404 elif iquad == IHB: # Hit a base
1406 prout(_("***STARBASE DESTROYED.."))
1407 for ll in range(game.state.rembase):
1408 if game.state.baseq[ll] == game.quadrant:
1409 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1411 game.quad[w.x][w.y]=IHDOT
1412 game.state.rembase -= 1
1413 game.base.x=game.base.y=0
1414 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1415 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1416 game.state.basekl += 1
1419 elif iquad == IHP: # Hit a planet
1420 crmena(True, iquad, sector, w)
1421 prout(_(" destroyed."))
1422 game.state.nplankl += 1
1423 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET
1424 game.state.planets[game.iplnet].pclass = destroyed
1426 invalidate(game.plnet)
1427 game.quad[w.x][w.y] = IHDOT
1429 # captain perishes on planet
1432 elif iquad == IHW: # Hit an inhabited world -- very bad!
1433 crmena(True, iquad, sector, w)
1434 prout(_(" destroyed."))
1435 game.state.nworldkl += 1
1436 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET
1437 game.state.planets[game.iplnet].pclass = destroyed
1439 invalidate(game.plnet)
1440 game.quad[w.x][w.y] = IHDOT
1442 # captain perishes on planet
1444 prout(_("You have just destroyed an inhabited planet."))
1445 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1447 elif iquad == IHSTAR: # Hit a star
1448 if random.random() > 0.10:
1451 crmena(True, IHSTAR, sector, w)
1452 prout(_(" unaffected by photon blast."))
1454 elif iquad == IHQUEST: # Hit a thingy
1455 if not (game.options & OPTION_THINGY) or random.random()>0.7:
1457 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1459 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1461 proutn(_("Mr. Spock-"))
1462 prouts(_(" \"Fascinating!\""))
1467 # Stas Sergeev added the possibility that
1468 # you can shove the Thingy and piss it off.
1469 # It then becomes an enemy and may fire at you.
1475 elif iquad == IHBLANK: # Black hole
1477 crmena(True, IHBLANK, sector, w)
1478 prout(_(" swallows torpedo."))
1480 elif iquad == IHWEB: # hit the web
1482 prout(_("***Torpedo absorbed by Tholian web."))
1484 elif iquad == IHT: # Hit a Tholian
1485 h1 = 700.0 + 100.0*random.random() - \
1486 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1489 game.quad[w.x][w.y] = IHDOT
1494 crmena(True, IHT, sector, w)
1495 if random.random() > 0.05:
1496 prout(_(" survives photon blast."))
1498 prout(_(" disappears."))
1499 game.quad[w.x][w.y] = IHWEB
1506 proutn("Don't know how to handle torpedo collision with ")
1507 crmena(True, iquad, sector, w)
1511 if curwnd!=message_window:
1512 setwnd(message_window)
1514 game.quad[w.x][w.y]=IHDOT
1515 game.quad[jw.x][jw.y]=iquad
1516 prout(_(" displaced by blast to Sector %s ") % jw)
1517 for ll in range(game.nenhere):
1518 game.kdist[ll] = game.kavgd[ll] = distance(game.sector,game.ks[ll])
1522 prout(_("Torpedo missed."))
1526 # critical-hit resolution
1528 # a critical hit occured
1529 if hit < (275.0-25.0*game.skill)*(1.0+0.5*random.random()):
1532 ncrit = 1.0 + hit/(500.0+100.0*random.random())
1533 proutn(_("***CRITICAL HIT--"))
1534 # Select devices and cause damage
1536 for loop1 in range(ncrit):
1539 # Cheat to prevent shuttle damage unless on ship
1540 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1543 extradm = (hit*game.damfac)/(ncrit*(75.0+25.0*random.random()))
1544 game.damage[j] += extradm
1546 for loop2 in range(loop1):
1547 if j == cdam[loop2]:
1556 prout(_(" damaged."))
1557 if damaged(DSHIELD) and game.shldup:
1558 prout(_("***Shields knocked down."))
1561 def attack(torps_ok):
1562 # bad guy attacks us
1563 # torps_ok == false forces use of phasers in an attack
1564 atackd = False; attempt = False; ihurt = False;
1565 hitmax=0.0; hittot=0.0; chgfac=1.0
1569 # game could be over at this point, check
1574 prout("=== ATTACK!")
1576 # Tholian gewts to move before attacking
1580 # if you have just entered the RNZ, you'll get a warning
1581 if game.neutz: # The one chance not to be attacked
1585 # commanders get a chance to tac-move towards you
1586 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1589 # if no enemies remain after movement, we're done
1590 if game.nenhere==0 or (game.nenhere==1 and thing == game.quadrant and not iqengry):
1593 # set up partial hits if attack happens during shield status change
1594 pfac = 1.0/game.inshld
1596 chgfac = 0.25+0.5*random.random()
1600 # message verbosity control
1601 if game.skill <= SKILL_FAIR:
1604 for loop in range(game.nenhere):
1605 if game.kpower[loop] < 0:
1606 continue; # too weak to attack
1607 # compute hit strength and diminish shield power
1609 # Increase chance of photon torpedos if docked or enemy energy low
1610 if game.condition == "docked":
1612 if game.kpower[loop] < 500:
1615 iquad = game.quad[jay.x][jay.y]
1616 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1618 # different enemies have different probabilities of throwing a torp
1619 usephasers = not torps_ok or \
1620 (iquad == IHK and r > 0.0005) or \
1621 (iquad==IHC and r > 0.015) or \
1622 (iquad==IHR and r > 0.3) or \
1623 (iquad==IHS and r > 0.07) or \
1624 (iquad==IHQUEST and r > 0.05)
1625 if usephasers: # Enemy uses phasers
1626 if game.condition == "docked":
1627 continue; # Don't waste the effort!
1628 attempt = True; # Attempt to attack
1629 dustfac = 0.8+0.05*random.random()
1630 hit = game.kpower[loop]*math.pow(dustfac,game.kavgd[loop])
1631 game.kpower[loop] *= 0.75
1632 else: # Enemy uses photon torpedo
1633 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1635 proutn(_("***TORPEDO INCOMING"))
1636 if not damaged(DSRSENS):
1638 crmena(False, iquad, where, jay)
1641 r = (random.random()+random.random())*0.5 -0.5
1642 r += 0.002*game.kpower[loop]*r
1643 hit = torpedo(course, r, jay, 1, 1)
1644 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1645 finish(FWON); # Klingons did themselves in!
1646 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1647 return; # Supernova or finished
1650 # incoming phaser or torpedo, shields may dissipate it
1651 if game.shldup or game.shldchg or game.condition=="docked":
1652 # shields will take hits
1653 propor = pfac * game.shield
1654 if game.condition =="docked":
1658 hitsh = propor*chgfac*hit+1.0
1660 if absorb > game.shield:
1661 absorb = game.shield
1662 game.shield -= absorb
1664 # taking a hit blasts us out of a starbase dock
1665 if game.condition == "docked":
1667 # but the shields may take care of it
1668 if propor > 0.1 and hit < 0.005*game.energy:
1670 # hit from this opponent got through shields, so take damage
1672 proutn(_("%d unit hit") % int(hit))
1673 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1674 proutn(_(" on the "))
1676 if not damaged(DSRSENS) and usephasers:
1678 crmena(False, iquad, where, jay)
1680 # Decide if hit is critical
1686 if game.energy <= 0:
1687 # Returning home upon your shield, not with it...
1690 if not attempt and game.condition == "docked":
1691 prout(_("***Enemies decide against attacking your ship."))
1694 percent = 100.0*pfac*game.shield+0.5
1696 # Shields fully protect ship
1697 proutn(_("Enemy attack reduces shield strength to "))
1699 # Print message if starship suffered hit(s)
1701 proutn(_("Energy left %2d shields ") % int(game.energy))
1704 elif not damaged(DSHIELD):
1707 proutn(_("damaged, "))
1708 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1709 # Check if anyone was hurt
1710 if hitmax >= 200 or hittot >= 500:
1711 icas= hittot*random.random()*0.015
1714 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1715 prout(_(" in that last attack.\""))
1717 game.state.crew -= icas
1718 # After attack, reset average distance to enemies
1719 for loop in range(game.nenhere):
1720 game.kavgd[loop] = game.kdist[loop]
1724 def deadkl(w, type, mv):
1725 # kill a Klingon, Tholian, Romulan, or Thingy
1726 # Added mv to allow enemy to "move" before dying
1728 crmena(True, type, sector, mv)
1729 # Decide what kind of enemy it is and update appropriately
1731 # chalk up a Romulan
1732 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1734 game.state.nromrem -= 1
1738 elif type == IHQUEST:
1744 # Some type of a Klingon
1745 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1748 game.comhere = False
1749 for i in range(game.state.remcom):
1750 if game.state.kcmdr[i] == game.quadrant:
1752 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1753 game.state.kcmdr[game.state.remcom].x = 0
1754 game.state.kcmdr[game.state.remcom].y = 0
1755 game.state.remcom -= 1
1757 if game.state.remcom != 0:
1758 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1760 game.state.remkl -= 1
1762 game.state.nscrem -= 1
1764 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1769 prout("*** Internal error, deadkl() called on %s\n" % type)
1771 # For each kind of enemy, finish message to player
1772 prout(_(" destroyed."))
1773 game.quad[w.x][w.y] = IHDOT
1774 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1777 # Remove enemy ship from arrays describing local conditions
1778 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1780 for i in range(game.nenhere):
1782 for j in range(i, game.nenhere):
1783 game.ks[j] = game.ks[j+1]
1784 game.kpower[j] = game.kpower[j+1]
1785 game.kavgd[j] = game.kdist[j] = game.kdist[j+1]
1786 game.ks[game.nenhere].x = 0
1787 game.ks[game.nenhere].y = 0
1788 game.kdist[game.nenhere] = 0
1789 game.kavgd[game.nenhere] = 0
1790 game.kpower[game.nenhere] = 0
1796 def targetcheck(x, y):
1797 # Return None if target is invalid
1798 if not VALID_SECTOR(x, y):
1801 deltx = 0.1*(y - game.sector.y)
1802 delty = 0.1*(x - game.sector.x)
1803 if deltx==0 and delty== 0:
1805 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1806 prout(_(" I recommend an immediate review of"))
1807 prout(_(" the Captain's psychological profile.\""))
1810 return 1.90985932*math.atan2(deltx, delty)
1813 # launch photon torpedo
1815 if damaged(DPHOTON):
1816 prout(_("Photon tubes damaged."))
1820 prout(_("No torpedoes left."))
1829 prout(_("%d torpedoes left.") % game.torps)
1830 proutn(_("Number of torpedoes to fire- "))
1832 else: # key == IHREAL {
1834 if n <= 0: # abort command
1839 prout(_("Maximum of 3 torpedoes per burst."))
1846 for i in range(1, n+1):
1848 if i==1 and key == IHEOL:
1849 break; # we will try prompting
1850 if i==2 and key == IHEOL:
1851 # direct all torpedoes at one target
1853 targ[i][1] = targ[1][1]
1854 targ[i][2] = targ[1][2]
1855 course[i] = course[1]
1867 course[i] = targetcheck(targ[i][1], targ[i][2])
1868 if course[i] == None:
1871 if i == 1 and key == IHEOL:
1872 # prompt for each one
1873 for i in range(1, n+1):
1874 proutn(_("Target sector for torpedo number %d- ") % i)
1879 targ[i][1] = int(aaitem-0.5)
1884 targ[i][2] = int(aaitem-0.5)
1886 course[i] = targetcheck(targ[i][1], targ[i][2])
1887 if course[i] == None:
1890 # Loop for moving <n> torpedoes
1891 for i in range(1, n+1):
1892 if game.condition != "docked":
1894 r = (random.random()+random.random())*0.5 -0.5
1895 if math.fabs(r) >= 0.47:
1897 r = (random.random()+1.2) * r
1899 prouts(_("***TORPEDO NUMBER %d MISFIRES") % i)
1901 prouts(_("***TORPEDO MISFIRES."))
1904 prout(_(" Remainder of burst aborted."))
1905 if random.random() <= 0.2:
1906 prout(_("***Photon tubes damaged by misfire."))
1907 game.damage[DPHOTON] = game.damfac*(1.0+2.0*random.random())
1909 if game.shldup or game.condition == "docked":
1910 r *= 1.0 + 0.0001*game.shield
1911 torpedo(course[i], r, game.sector, i, n)
1912 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1914 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1918 # check for phasers overheating
1920 chekbrn = (rpow-1500.)*0.00038
1921 if random.random() <= chekbrn:
1922 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1923 game.damage[DPHASER] = game.damfac*(1.0 + random.random()) * (1.0+chekbrn)
1925 def checkshctrl(rpow):
1926 # check shield control
1929 if random.random() < 0.998:
1930 prout(_("Shields lowered."))
1932 # Something bad has happened
1933 prouts(_("***RED ALERT! RED ALERT!"))
1935 hit = rpow*game.shield/game.inshld
1936 game.energy -= rpow+hit*0.8
1937 game.shield -= hit*0.2
1938 if game.energy <= 0.0:
1939 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1944 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1946 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1947 icas = hit*random.random()*0.012
1952 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1953 prout(_(" %d casualties so far.\"") % icas)
1955 game.state.crew -= icas
1957 prout(_("Phaser energy dispersed by shields."))
1958 prout(_("Enemy unaffected."))
1963 # register a phaser hit on Klingons and Romulans
1964 nenhr2=game.nenhere; kk=1
1967 for k in range(nenhr2):
1971 dustfac = 0.9 + 0.01*random.random()
1972 hit = wham*math.pow(dustfac,game.kdist[kk])
1973 kpini = game.kpower[kk]
1974 kp = math.fabs(kpini)
1975 if PHASEFAC*hit < kp:
1977 if game.kpower[kk] < 0:
1978 game.kpower[kk] -= -kp
1980 game.kpower[kk] -= kp
1981 kpow = game.kpower[kk]
1984 if not damaged(DSRSENS):
1986 proutn(_("%d unit hit on ") % int(hit))
1988 proutn(_("Very small hit on "))
1989 ienm = game.quad[w.x][w.y]
1993 crmena(False, ienm, "sector", w)
1997 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
2001 kk -= 1; # don't do the increment
2002 else: # decide whether or not to emasculate klingon
2003 if kpow > 0 and random.random() >= 0.9 and \
2004 kpow <= ((0.4 + 0.4*random.random())*kpini):
2005 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s"), w)
2006 prout(_(" has just lost its firepower.\""))
2007 game.kpower[kk] = -kpow
2014 kz = 0; k = 1; irec=0 # Cheating inhibitor
2015 ifast = False; no = False; itarg = True; msgflag = True
2020 # SR sensors and Computer are needed fopr automode
2021 if damaged(DSRSENS) or damaged(DCOMPTR):
2023 if game.condition == "docked":
2024 prout(_("Phasers can't be fired through base shields."))
2027 if damaged(DPHASER):
2028 prout(_("Phaser control damaged."))
2032 if damaged(DSHCTRL):
2033 prout(_("High speed shield control damaged."))
2036 if game.energy <= 200.0:
2037 prout(_("Insufficient energy to activate high-speed shield control."))
2040 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2043 # Original code so convoluted, I re-did it all
2044 while automode=="NOTSET":
2049 prout(_("There is no enemy present to select."))
2052 automode="AUTOMATIC"
2056 elif isit("automatic"):
2057 if (not itarg) and game.nenhere != 0:
2058 automode = "FORCEMAN"
2061 prout(_("Energy will be expended into space."))
2062 automode = "AUTOMATIC"
2071 prout(_("Energy will be expended into space."))
2072 automode = "AUTOMATIC"
2074 automode = "FORCEMAN"
2076 automode = "AUTOMATIC"
2080 prout(_("Energy will be expended into space."))
2081 automode = "AUTOMATIC"
2083 automode = "FORCEMAN"
2085 proutn(_("Manual or automatic? "))
2089 if automode == "AUTOMATIC":
2090 if key == IHALPHA and isit("no"):
2093 if key != IHREAL and game.nenhere != 0:
2094 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2099 for i in range(game.nenhere):
2100 irec += math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))*(1.01+0.05*random.random()) + 1.0
2102 proutn(_("%d units required. ") % irec)
2104 proutn(_("Units to fire= "))
2110 proutn(_("Energy available= %.2f") % avail)
2113 if not rpow > avail:
2120 if key == IHALPHA and isit("no"):
2123 game.energy -= 200; # Go and do it!
2124 if checkshctrl(rpow):
2132 for i in range(game.nenhere):
2136 hits[i] = math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))
2137 over = (0.01 + 0.05*random.random())*hits[i]
2139 powrem -= hits[i] + over
2140 if powrem <= 0 and temp < hits[i]:
2149 if extra > 0 and not game.alldone:
2151 proutn(_("*** Tholian web absorbs "))
2153 proutn(_("excess "))
2154 prout(_("phaser energy."))
2156 prout(_("%d expended on empty space.") % int(extra))
2157 elif automode == "FORCEMAN":
2160 if damaged(DCOMPTR):
2161 prout(_("Battle computer damaged, manual fire only."))
2164 prouts(_("---WORKING---"))
2166 prout(_("Short-range-sensors-damaged"))
2167 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2168 prout(_("Manual-fire-must-be-used"))
2170 elif automode == "MANUAL":
2172 for k in range(game.nenhere):
2174 ienm = game.quad[aim.x][aim.y]
2176 proutn(_("Energy available= %.2f") % (avail-0.006))
2180 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2181 (ienm == IHC or ienm == IHS):
2183 prout(_(" can't be located without short range scan."))
2186 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2191 if itarg and k > kz:
2192 irec=(abs(game.kpower[k])/(PHASEFAC*math.pow(0.9,game.kdist[k]))) * (1.01+0.05*random.random()) + 1.0
2195 if not damaged(DCOMPTR):
2200 proutn(_("units to fire at "))
2201 crmena(False, ienm, sector, aim)
2204 if key == IHALPHA and isit("no"):
2212 if k==1: # Let me say I'm baffled by this
2221 # If total requested is too much, inform and start over
2223 prout(_("Available energy exceeded -- try again."))
2226 key = scan(); # scan for next value
2229 # zero energy -- abort
2232 if key == IHALPHA and isit("no"):
2237 game.energy -= 200.0
2238 if checkshctrl(rpow):
2242 # Say shield raised or malfunction, if necessary
2248 if random.random() >= 0.99:
2249 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2250 prouts(_(" CLICK CLICK POP . . ."))
2251 prout(_(" No response, sir!"))
2254 prout(_("Shields raised."))
2259 # Code from events,c begins here.
2261 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2262 # event of each type active at any given time. Mostly these means we can
2263 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2264 # BSD Trek, from which we swiped the idea, can have up to 5.
2268 def unschedule(evtype):
2269 # remove an event from the schedule
2270 game.future[evtype].date = FOREVER
2271 return game.future[evtype]
2273 def is_scheduled(evtype):
2274 # is an event of specified type scheduled
2275 return game.future[evtype].date != FOREVER
2277 def scheduled(evtype):
2278 # when will this event happen?
2279 return game.future[evtype].date
2281 def schedule(evtype, offset):
2282 # schedule an event of specified type
2283 game.future[evtype].date = game.state.date + offset
2284 return game.future[evtype]
2286 def postpone(evtype, offset):
2287 # postpone a scheduled event
2288 game.future[evtype].date += offset
2291 # rest period is interrupted by event
2294 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2296 game.resting = False
2303 # run through the event queue looking for things to do
2305 fintim = game.state.date + game.optime; yank=0
2306 ictbeam = False; istract = False
2307 w = coord(); hold = coord()
2308 ev = event(); ev2 = event()
2311 # tractor beaming cases merge here
2312 yank = math.sqrt(yank)
2314 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2318 prout(_(" caught in long range tractor beam--"))
2319 # If Kirk & Co. screwing around on planet, handle
2320 atover(True) # atover(true) is Grab
2323 if game.icraft: # Caught in Galileo?
2326 # Check to see if shuttle is aboard
2327 if game.iscraft == "offship":
2329 if random.random() > 0.5:
2330 prout(_("Galileo, left on the planet surface, is captured"))
2331 prout(_("by aliens and made into a flying McDonald's."))
2332 game.damage[DSHUTTL] = -10
2333 game.iscraft = "removed"
2335 prout(_("Galileo, left on the planet surface, is well hidden."))
2337 game.quadrant = game.state.kscmdr
2339 game.quadrant = game.state.kcmdr[i]
2340 game.sector = randplace(QUADSIZE)
2342 prout(_(" is pulled to Quadrant %s, Sector %s") \
2343 % (game.quadrant, game.sector))
2345 prout(_("(Remainder of rest/repair period cancelled.)"))
2346 game.resting = False
2348 if not damaged(DSHIELD) and game.shield > 0:
2349 doshield(True) # raise shields
2352 prout(_("(Shields not currently useable.)"))
2354 # Adjust finish time to time of tractor beaming
2355 fintim = game.state.date+game.optime
2357 if game.state.remcom <= 0:
2360 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2363 # Code merges here for any commander destroying base
2364 # Not perfect, but will have to do
2365 # Handle case where base is in same quadrant as starship
2366 if game.battle == game.quadrant:
2367 game.state.chart[game.battle.x][game.battle.y].starbase = False
2368 game.quad[game.base.x][game.base.y] = IHDOT
2369 game.base.x=game.base.y=0
2372 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2373 elif game.state.rembase != 1 and communicating():
2374 # Get word via subspace radio
2377 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2378 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2380 prout(_("the Klingon Super-Commander"))
2382 prout(_("a Klingon Commander"))
2383 game.state.chart[game.battle.x][game.battle.y].starbase = False
2384 # Remove Starbase from galaxy
2385 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2386 for i in range(1, game.state.rembase+1):
2387 if game.state.baseq[i] == game.battle:
2388 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2389 game.state.rembase -= 1
2391 # reinstate a commander's base attack
2395 invalidate(game.battle)
2398 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2399 for i in range(1, NEVENTS):
2400 if i == FSNOVA: proutn("=== Supernova ")
2401 elif i == FTBEAM: proutn("=== T Beam ")
2402 elif i == FSNAP: proutn("=== Snapshot ")
2403 elif i == FBATTAK: proutn("=== Base Attack ")
2404 elif i == FCDBAS: proutn("=== Base Destroy ")
2405 elif i == FSCMOVE: proutn("=== SC Move ")
2406 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2407 elif i == FDSPROB: proutn("=== Probe Move ")
2408 elif i == FDISTR: proutn("=== Distress Call ")
2409 elif i == FENSLV: proutn("=== Enslavement ")
2410 elif i == FREPRO: proutn("=== Klingon Build ")
2412 prout("%.2f" % (scheduled(i)))
2415 radio_was_broken = damaged(DRADIO)
2418 # Select earliest extraneous event, evcode==0 if no events
2423 for l in range(1, NEVENTS):
2424 if game.future[l].date < datemin:
2427 prout("== Event %d fires" % evcode)
2428 datemin = game.future[l].date
2429 xtime = datemin-game.state.date
2430 game.state.date = datemin
2431 # Decrement Federation resources and recompute remaining time
2432 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2434 if game.state.remtime <=0:
2437 # Any crew left alive?
2438 if game.state.crew <=0:
2441 # Is life support adequate?
2442 if damaged(DLIFSUP) and game.condition != "docked":
2443 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2446 game.lsupres -= xtime
2447 if game.damage[DLIFSUP] <= xtime:
2448 game.lsupres = game.inlsr
2451 if game.condition == "docked":
2452 repair /= game.docfac
2453 # Don't fix Deathray here
2454 for l in range(NDEVICES):
2455 if game.damage[l] > 0.0 and l != DDRAY:
2456 if game.damage[l]-repair > 0.0:
2457 game.damage[l] -= repair
2459 game.damage[l] = 0.0
2460 # If radio repaired, update star chart and attack reports
2461 if radio_was_broken and not damaged(DRADIO):
2462 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2463 prout(_(" surveillance reports are coming in."))
2465 if not game.iseenit:
2469 prout(_(" The star chart is now up to date.\""))
2471 # Cause extraneous event EVCODE to occur
2472 game.optime -= xtime
2473 if evcode == FSNOVA: # Supernova
2476 schedule(FSNOVA, expran(0.5*game.intime))
2477 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2479 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2480 if game.state.nscrem == 0 or \
2481 ictbeam or istract or \
2482 game.condition=="docked" or game.isatb==1 or game.iscate:
2484 if game.ientesc or \
2485 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2486 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2487 (damaged(DSHIELD) and \
2488 (game.energy < 2500 or damaged(DPHASER)) and \
2489 (game.torps < 5 or damaged(DPHOTON))):
2492 yank = distance(game.state.kscmdr, game.quadrant)
2497 elif evcode == FTBEAM: # Tractor beam
2498 if game.state.remcom == 0:
2501 i = random.random()*game.state.remcom+1.0
2502 yank = square(game.state.kcmdr[i].x-game.quadrant.x) + square(game.state.kcmdr[i].y-game.quadrant.y)
2503 if istract or game.condition == "docked" or yank == 0:
2504 # Drats! Have to reschedule
2506 game.optime + expran(1.5*game.intime/game.state.remcom))
2510 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2511 game.snapsht = game.state
2512 game.state.snap = True
2513 schedule(FSNAP, expran(0.5 * game.intime))
2514 elif evcode == FBATTAK: # Commander attacks starbase
2515 if game.state.remcom==0 or game.state.rembase==0:
2521 for j in range(game.state.rembase):
2522 for k in range(game.state.remcom):
2523 if game.state.baseq[j] == game.state.kcmdr[k] and \
2524 not game.state.baseq[j] == game.quadrant and \
2525 not game.state.baseq[j] == game.state.kscmdr:
2529 if j>game.state.rembase:
2530 # no match found -- try later
2531 schedule(FBATTAK, expran(0.3*game.intime))
2534 # commander + starbase combination found -- launch attack
2535 game.battle = game.state.baseq[j]
2536 schedule(FCDBAS, 1.0+3.0*random.random())
2537 if game.isatb: # extra time if SC already attacking
2538 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2539 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2540 game.iseenit = False
2541 if not communicating():
2542 continue # No warning :-(
2546 proutn(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2547 prout(_(" reports that it is under attack and that it can"))
2548 proutn(_(" hold out only until stardate %d") % (int(scheduled(FCDBAS))))
2552 elif evcode == FSCDBAS: # Supercommander destroys base
2555 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2556 continue # WAS RETURN!
2558 game.battle = game.state.kscmdr
2560 elif evcode == FCDBAS: # Commander succeeds in destroying base
2563 # find the lucky pair
2564 for i in range(game.state.remcom):
2565 if game.state.kcmdr[i] == game.battle:
2567 if i > game.state.remcom or game.state.rembase == 0 or \
2568 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2569 # No action to take after all
2570 invalidate(game.battle)
2573 elif evcode == FSCMOVE: # Supercommander moves
2574 schedule(FSCMOVE, 0.2777)
2575 if not game.ientesc and not istract and game.isatb != 1 and \
2576 (not game.iscate or not game.justin):
2578 elif evcode == FDSPROB: # Move deep space probe
2579 schedule(FDSPROB, 0.01)
2580 game.probex += game.probeinx
2581 game.probey += game.probeiny
2582 i = (int)(game.probex/QUADSIZE +0.05)
2583 j = (int)(game.probey/QUADSIZE + 0.05)
2584 if game.probec.x != i or game.probec.y != j:
2587 if not VALID_QUADRANT(i, j) or \
2588 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2589 # Left galaxy or ran into supernova
2593 proutn(_("Lt. Uhura- \"The deep space probe "))
2594 if not VALID_QUADRANT(j, i):
2595 proutn(_("has left the galaxy"))
2597 proutn(_("is no longer transmitting"))
2601 if not communicating():
2604 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2605 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2606 # Update star chart if Radio is working or have access to radio
2608 chp = game.state.chart[game.probec.x][game.probec.y]
2609 chp.klingons = pdest.klingons
2610 chp.starbase = pdest.starbase
2611 chp.stars = pdest.stars
2612 pdest.charted = True
2613 game.proben -= 1 # One less to travel
2614 if game.proben == 0 and game.isarmed and pdest.stars:
2615 # lets blow the sucker!
2616 supernova(True, game.probec)
2618 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2620 elif evcode == FDISTR: # inhabited system issues distress call
2622 # try a whole bunch of times to find something suitable
2623 for i in range(100):
2624 # need a quadrant which is not the current one,
2625 # which has some stars which are inhabited and
2626 # not already under attack, which is not
2627 # supernova'ed, and which has some Klingons in it
2628 w = randplace(GALSIZE)
2629 q = game.state.galaxy[w.x][w.y]
2630 if not (game.quadrant == w or q.planet == NOPLANET or \
2631 not game.state.planets[q.planet].inhabited or \
2632 q.supernova or q.status!=secure or q.klingons<=0):
2635 # can't seem to find one; ignore this call
2637 prout("=== Couldn't find location for distress event.")
2639 # got one!! Schedule its enslavement
2640 ev = schedule(FENSLV, expran(game.intime))
2642 q.status = distressed
2644 # tell the captain about it if we can
2646 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2648 prout(_("by a Klingon invasion fleet."))
2651 elif evcode == FENSLV: # starsystem is enslaved
2652 ev = unschedule(FENSLV)
2653 # see if current distress call still active
2654 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2658 q.status = "enslaved"
2660 # play stork and schedule the first baby
2661 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2662 ev2.quadrant = ev.quadrant
2664 # report the disaster if we can
2666 prout(_("Uhura- We've lost contact with starsystem %s") % \
2668 prout(_("in Quadrant %s.\n") % ev.quadrant)
2669 elif evcode == FREPRO: # Klingon reproduces
2670 # If we ever switch to a real event queue, we'll need to
2671 # explicitly retrieve and restore the x and y.
2672 ev = schedule(FREPRO, expran(1.0 * game.intime))
2673 # see if current distress call still active
2674 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2678 if game.state.remkl >=MAXKLGAME:
2679 continue # full right now
2680 # reproduce one Klingon
2682 if game.klhere >= MAXKLQUAD:
2684 # this quadrant not ok, pick an adjacent one
2685 for i in range(w.x - 1, w.x + 2):
2686 for j in range(w.y - 1, w.y + 2):
2687 if not VALID_QUADRANT(i, j):
2689 q = game.state.galaxy[w.x][w.y]
2690 # check for this quad ok (not full & no snova)
2691 if q.klingons >= MAXKLQUAD or q.supernova:
2695 continue # search for eligible quadrant failed
2700 game.state.remkl += 1
2702 if game.quadrant == w:
2704 newkling(game.klhere)
2705 # recompute time left
2707 # report the disaster if we can
2709 if game.quadrant == w:
2710 prout(_("Spock- sensors indicate the Klingons have"))
2711 prout(_("launched a warship from %s.") % q.planet)
2713 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2714 if q.planet != NOPLANET:
2715 proutn(_("near %s") % q.planet)
2716 prout(_("in Quadrant %s.") % w)
2725 proutn(_("How long? "))
2730 origTime = delay = aaitem
2733 if delay >= game.state.remtime or game.nenhere != 0:
2734 proutn(_("Are you sure? "))
2738 # Alternate resting periods (events) with attacks
2743 game.resting = False
2744 if not game.resting:
2745 prout(_("%d stardates left.") % int(game.state.remtime))
2747 temp = game.optime = delay
2749 rtime = 1.0 + random.random()
2753 if game.optime < delay:
2762 # Repair Deathray if long rest at starbase
2763 if origTime-delay >= 9.99 and game.condition == "docked":
2764 game.damage[DDRAY] = 0.0
2765 # leave if quadrant supernovas
2766 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2768 game.resting = False
2771 # A nova occurs. It is the result of having a star hit with a
2772 # photon torpedo, or possibly of a probe warhead going off.
2773 # Stars that go nova cause stars which surround them to undergo
2774 # the same probabilistic process. Klingons next to them are
2775 # destroyed. And if the starship is next to it, it gets zapped.
2776 # If the zap is too much, it gets destroyed.
2780 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2781 newc = coord(); scratch = coord()
2783 if random.random() < 0.05:
2784 # Wow! We've supernova'ed
2785 supernova(False, nov)
2788 # handle initial nova
2789 game.quad[nov.x][nov.y] = IHDOT
2790 crmena(False, IHSTAR, sector, nov)
2792 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2793 game.state.starkl += 1
2795 # Set up stack to recursively trigger adjacent stars
2796 bot = top = top2 = 1
2802 for mm in range(bot, top+1):
2803 for nn in range(1, 3+1): # nn,j represents coordinates around current
2804 for j in range(1, 3+1):
2807 scratch.x = hits[mm][1]+nn-2
2808 scratch.y = hits[mm][2]+j-2
2809 if not VALID_SECTOR(scratch.y, scratch.x):
2811 iquad = game.quad[scratch.x][scratch.y]
2812 # Empty space ends reaction
2813 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2815 elif iquad == IHSTAR: # Affect another star
2816 if random.random() < 0.05:
2817 # This star supernovas
2818 scratch = supernova(False)
2821 hits[top2][1]=scratch.x
2822 hits[top2][2]=scratch.y
2823 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2824 game.state.starkl += 1
2825 crmena(True, IHSTAR, sector, scratch)
2827 game.quad[scratch.x][scratch.y] = IHDOT
2828 elif iquad == IHP: # Destroy planet
2829 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET
2830 game.state.nplankl += 1
2831 crmena(True, IHP, sector, scratch)
2832 prout(_(" destroyed."))
2833 game.state.planets[game.iplnet].pclass = destroyed
2835 invalidate(game.plnet)
2839 game.quad[scratch.x][scratch.y] = IHDOT
2840 elif iquad == IHB: # Destroy base
2841 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2842 for i in range(game.state.rembase):
2843 if game.state.baseq[i] == game.quadrant:
2845 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2846 game.state.rembase -= 1
2847 invalidate(game.base)
2848 game.state.basekl += 1
2850 crmena(True, IHB, sector, scratch)
2851 prout(_(" destroyed."))
2852 game.quad[scratch.x][scratch.y] = IHDOT
2853 elif iquad in (IHE, IHF): # Buffet ship
2854 prout(_("***Starship buffeted by nova."))
2856 if game.shield >= 2000.0:
2857 game.shield -= 2000.0
2859 diff = 2000.0 - game.shield
2863 prout(_("***Shields knocked out."))
2864 game.damage[DSHIELD] += 0.005*game.damfac*random.random()*diff
2866 game.energy -= 2000.0
2867 if game.energy <= 0:
2870 # add in course nova contributes to kicking starship
2871 icx += game.sector.x-hits[mm][1]
2872 icy += game.sector.y-hits[mm][2]
2874 elif iquad == IHK: # kill klingon
2875 deadkl(scratch,iquad, scratch)
2876 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2877 for ll in range(game.nenhere):
2878 if game.ks[ll] == scratch:
2880 game.kpower[ll] -= 800.0 # If firepower is lost, die
2881 if game.kpower[ll] <= 0.0:
2882 deadkl(scratch, iquad, scratch)
2884 newc.x = scratch.x + scratch.x - hits[mm][1]
2885 newc.y = scratch.y + scratch.y - hits[mm][2]
2886 crmena(True, iquad, sector, scratch)
2887 proutn(_(" damaged"))
2888 if not VALID_SECTOR(newc.x, newc.y):
2889 # can't leave quadrant
2892 iquad1 = game.quad[newc.x][newc.y]
2893 if iquad1 == IHBLANK:
2894 proutn(_(", blasted into "))
2895 crmena(False, IHBLANK, sector, newc)
2897 deadkl(scratch, iquad, newc)
2900 # can't move into something else
2903 proutn(_(", buffeted to Sector %s") % newc)
2904 game.quad[scratch.x][scratch.y] = IHDOT
2905 game.quad[newc.x][newc.y] = iquad
2907 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc)
2916 # Starship affected by nova -- kick it away.
2917 game.dist = kount*0.1
2920 game.direc = course[3*(icx+1)+icy+2]
2921 if game.direc == 0.0:
2923 if game.dist == 0.0:
2925 game.optime = 10.0*game.dist/16.0
2927 prout(_("Force of nova displaces starship."))
2929 game.optime = 10.0*game.dist/16.0
2932 def supernova(induced, w=None):
2933 # star goes supernova
2941 # Scheduled supernova -- select star
2942 # logic changed here so that we won't favor quadrants in top
2944 for nq.x in range(GALSIZE):
2945 for nq.y in range(GALSIZE):
2946 stars += game.state.galaxy[nq.x][nq.y].stars
2948 return # nothing to supernova exists
2949 num = random.random()*stars + 1
2950 for nq.x in range(GALSIZE):
2951 for nq.y in range(GALSIZE):
2952 num -= game.state.galaxy[nq.x][nq.y].stars
2958 proutn("=== Super nova here?")
2962 if not nq == game.quadrant or game.justin:
2963 # it isn't here, or we just entered (treat as enroute)
2966 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2967 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2970 # we are in the quadrant!
2971 num = random.random()* game.state.galaxy[nq.x][nq.y].stars + 1
2972 for ns.x in range(QUADSIZE):
2973 for ns.y in range(QUADSIZE):
2974 if game.quad[ns.x][ns.y]==IHSTAR:
2982 prouts(_("***RED ALERT! RED ALERT!"))
2984 prout(_("***Incipient supernova detected at Sector %s") % ns)
2985 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2986 proutn(_("Emergency override attempts t"))
2987 prouts("***************")
2992 # destroy any Klingons in supernovaed quadrant
2993 kldead = game.state.galaxy[nq.x][nq.y].klingons
2994 game.state.galaxy[nq.x][nq.y].klingons = 0
2995 if nq == game.state.kscmdr:
2996 # did in the Supercommander!
2997 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
3001 if game.state.remcom:
3002 maxloop = game.state.remcom
3003 for l in range(maxloop):
3004 if game.state.kcmdr[l] == nq:
3005 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
3006 invalidate(game.state.kcmdr[game.state.remcom])
3007 game.state.remcom -= 1
3009 if game.state.remcom==0:
3012 game.state.remkl -= kldead
3013 # destroy Romulans and planets in supernovaed quadrant
3014 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
3015 game.state.galaxy[nq.x][nq.y].romulans = 0
3016 game.state.nromrem -= nrmdead
3018 for loop in range(game.inplan):
3019 if game.state.planets[loop].w == nq:
3020 game.state.planets[loop].pclass = destroyed
3022 # Destroy any base in supernovaed quadrant
3023 if game.state.rembase:
3024 maxloop = game.state.rembase
3025 for loop in range(maxloop):
3026 if game.state.baseq[loop] == nq:
3027 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3028 invalidate(game.state.baseq[game.state.rembase])
3029 game.state.rembase -= 1
3031 # If starship caused supernova, tally up destruction
3033 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3034 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3035 game.state.nplankl += npdead
3036 # mark supernova in galaxy and in star chart
3037 if game.quadrant == nq or communicating():
3038 game.state.galaxy[nq.x][nq.y].supernova = True
3039 # If supernova destroys last Klingons give special message
3040 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3043 prout(_("Lucky you!"))
3044 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3047 # if some Klingons remain, continue or die in supernova
3052 # Code from finish.c ends here.
3055 # self-destruct maneuver
3056 # Finish with a BANG!
3058 if damaged(DCOMPTR):
3059 prout(_("Computer damaged; cannot execute destruct sequence."))
3061 prouts(_("---WORKING---")); skip(1)
3062 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3063 prouts(" 10"); skip(1)
3064 prouts(" 9"); skip(1)
3065 prouts(" 8"); skip(1)
3066 prouts(" 7"); skip(1)
3067 prouts(" 6"); skip(1)
3069 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3071 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3073 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3077 if game.passwd != citem:
3078 prouts(_("PASSWORD-REJECTED;"))
3080 prouts(_("CONTINUITY-EFFECTED"))
3083 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3084 prouts(" 5"); skip(1)
3085 prouts(" 4"); skip(1)
3086 prouts(" 3"); skip(1)
3087 prouts(" 2"); skip(1)
3088 prouts(" 1"); skip(1)
3089 if random.random() < 0.15:
3090 prouts(_("GOODBYE-CRUEL-WORLD"))
3098 prouts(_("********* Entropy of "))
3100 prouts(_(" maximized *********"))
3104 if game.nenhere != 0:
3105 whammo = 25.0 * game.energy
3107 while l <= game.nenhere:
3108 if game.kpower[l]*game.kdist[l] <= whammo:
3109 deadkl(game.ks[l], game.quad[game.ks[l].x][game.ks[l].y], game.ks[l])
3114 "Compute our rate of kils over time."
3115 return ((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem))/(game.state.date-game.indate)
3119 badpt = 5.0*game.state.starkl + \
3121 10.0*game.state.nplankl + \
3122 300*game.state.nworldkl + \
3124 100.0*game.state.basekl +\
3126 if game.ship == IHF:
3128 elif game.ship == None:
3134 # end the game, with appropriate notfications
3138 prout(_("It is stardate %.1f.") % game.state.date)
3140 if ifin == FWON: # Game has been won
3141 if game.state.nromrem != 0:
3142 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3145 prout(_("You have smashed the Klingon invasion fleet and saved"))
3146 prout(_("the Federation."))
3151 badpt = 0.0 # Close enough!
3152 # killsPerDate >= RateMax
3153 if game.state.date-game.indate < 5.0 or \
3154 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3156 prout(_("In fact, you have done so well that Starfleet Command"))
3157 if game.skill == SKILL_NOVICE:
3158 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3159 elif game.skill == SKILL_FAIR:
3160 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3161 elif game.skill == SKILL_GOOD:
3162 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3163 elif game.skill == SKILL_EXPERT:
3164 prout(_("promotes you to Commodore Emeritus."))
3166 prout(_("Now that you think you're really good, try playing"))
3167 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3168 elif game.skill == SKILL_EMERITUS:
3170 proutn(_("Computer- "))
3171 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3173 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3175 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3177 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3179 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3181 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3183 prout(_("Now you can retire and write your own Star Trek game!"))
3185 elif game.skill >= SKILL_EXPERT:
3186 if game.thawed and not idebug:
3187 prout(_("You cannot get a citation, so..."))
3189 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3193 # Only grant long life if alive (original didn't!)
3195 prout(_("LIVE LONG AND PROSPER."))
3200 elif ifin == FDEPLETE: # Federation Resources Depleted
3201 prout(_("Your time has run out and the Federation has been"))
3202 prout(_("conquered. Your starship is now Klingon property,"))
3203 prout(_("and you are put on trial as a war criminal. On the"))
3204 proutn(_("basis of your record, you are "))
3205 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3206 prout(_("acquitted."))
3208 prout(_("LIVE LONG AND PROSPER."))
3210 prout(_("found guilty and"))
3211 prout(_("sentenced to death by slow torture."))
3215 elif ifin == FLIFESUP:
3216 prout(_("Your life support reserves have run out, and"))
3217 prout(_("you die of thirst, starvation, and asphyxiation."))
3218 prout(_("Your starship is a derelict in space."))
3220 prout(_("Your energy supply is exhausted."))
3222 prout(_("Your starship is a derelict in space."))
3223 elif ifin == FBATTLE:
3226 prout(_("has been destroyed in battle."))
3228 prout(_("Dulce et decorum est pro patria mori."))
3230 prout(_("You have made three attempts to cross the negative energy"))
3231 prout(_("barrier which surrounds the galaxy."))
3233 prout(_("Your navigation is abominable."))
3236 prout(_("Your starship has been destroyed by a nova."))
3237 prout(_("That was a great shot."))
3239 elif ifin == FSNOVAED:
3242 prout(_(" has been fried by a supernova."))
3243 prout(_("...Not even cinders remain..."))
3244 elif ifin == FABANDN:
3245 prout(_("You have been captured by the Klingons. If you still"))
3246 prout(_("had a starbase to be returned to, you would have been"))
3247 prout(_("repatriated and given another chance. Since you have"))
3248 prout(_("no starbases, you will be mercilessly tortured to death."))
3249 elif ifin == FDILITHIUM:
3250 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3251 elif ifin == FMATERIALIZE:
3252 prout(_("Starbase was unable to re-materialize your starship."))
3253 prout(_("Sic transit gloria mundi"))
3254 elif ifin == FPHASER:
3257 prout(_(" has been cremated by its own phasers."))
3259 prout(_("You and your landing party have been"))
3260 prout(_("converted to energy, disipating through space."))
3261 elif ifin == FMINING:
3262 prout(_("You are left with your landing party on"))
3263 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3265 prout(_("They are very fond of \"Captain Kirk\" soup."))
3267 proutn(_("Without your leadership, the "))
3269 prout(_(" is destroyed."))
3270 elif ifin == FDPLANET:
3271 prout(_("You and your mining party perish."))
3273 prout(_("That was a great shot."))
3276 prout(_("The Galileo is instantly annihilated by the supernova."))
3277 prout(_("You and your mining party are atomized."))
3279 proutn(_("Mr. Spock takes command of the "))
3282 prout(_("joins the Romulans, reigning terror on the Federation."))
3283 elif ifin == FPNOVA:
3284 prout(_("You and your mining party are atomized."))
3286 proutn(_("Mr. Spock takes command of the "))
3289 prout(_("joins the Romulans, reigning terror on the Federation."))
3290 elif ifin == FSTRACTOR:
3291 prout(_("The shuttle craft Galileo is also caught,"))
3292 prout(_("and breaks up under the strain."))
3294 prout(_("Your debris is scattered for millions of miles."))
3295 proutn(_("Without your leadership, the "))
3297 prout(_(" is destroyed."))
3299 prout(_("The mutants attack and kill Spock."))
3300 prout(_("Your ship is captured by Klingons, and"))
3301 prout(_("your crew is put on display in a Klingon zoo."))
3302 elif ifin == FTRIBBLE:
3303 prout(_("Tribbles consume all remaining water,"))
3304 prout(_("food, and oxygen on your ship."))
3306 prout(_("You die of thirst, starvation, and asphyxiation."))
3307 prout(_("Your starship is a derelict in space."))
3309 prout(_("Your ship is drawn to the center of the black hole."))
3310 prout(_("You are crushed into extremely dense matter."))
3312 prout(_("Your last crew member has died."))
3313 if game.ship == IHF:
3315 elif game.ship == IHE:
3318 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3319 goodies = game.state.remres/game.inresor
3320 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3321 if goodies/baddies >= 1.0+0.5*random.random():
3322 prout(_("As a result of your actions, a treaty with the Klingon"))
3323 prout(_("Empire has been signed. The terms of the treaty are"))
3324 if goodies/baddies >= 3.0+random.random():
3325 prout(_("favorable to the Federation."))
3327 prout(_("Congratulations!"))
3329 prout(_("highly unfavorable to the Federation."))
3331 prout(_("The Federation will be destroyed."))
3333 prout(_("Since you took the last Klingon with you, you are a"))
3334 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3335 prout(_("statue in your memory. Rest in peace, and try not"))
3336 prout(_("to think about pigeons."))
3341 # compute player's score
3342 timused = game.state.date - game.indate
3345 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3347 perdate = killrate()
3348 ithperd = 500*perdate + 0.5
3351 iwon = 100*game.skill
3352 if game.ship == IHE:
3354 elif game.ship == IHF:
3358 if not game.gamewon:
3359 game.state.nromrem = 0 # None captured if no win
3360 iscore = 10*(game.inkling - game.state.remkl) \
3361 + 50*(game.incom - game.state.remcom) \
3363 + 20*(game.inrom - game.state.nromrem) \
3364 + 200*(game.inscom - game.state.nscrem) \
3365 - game.state.nromrem \
3370 prout(_("Your score --"))
3371 if game.inrom - game.state.nromrem:
3372 prout(_("%6d Romulans destroyed %5d") %
3373 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3374 if game.state.nromrem:
3375 prout(_("%6d Romulans captured %5d") %
3376 (game.state.nromrem, game.state.nromrem))
3377 if game.inkling - game.state.remkl:
3378 prout(_("%6d ordinary Klingons destroyed %5d") %
3379 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3380 if game.incom - game.state.remcom:
3381 prout(_("%6d Klingon commanders destroyed %5d") %
3382 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3383 if game.inscom - game.state.nscrem:
3384 prout(_("%6d Super-Commander destroyed %5d") %
3385 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3387 prout(_("%6.2f Klingons per stardate %5d") %
3389 if game.state.starkl:
3390 prout(_("%6d stars destroyed by your action %5d") %
3391 (game.state.starkl, -5*game.state.starkl))
3392 if game.state.nplankl:
3393 prout(_("%6d planets destroyed by your action %5d") %
3394 (game.state.nplankl, -10*game.state.nplankl))
3395 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3396 prout(_("%6d inhabited planets destroyed by your action %5d") %
3397 (game.state.nplankl, -300*game.state.nworldkl))
3398 if game.state.basekl:
3399 prout(_("%6d bases destroyed by your action %5d") %
3400 (game.state.basekl, -100*game.state.basekl))
3402 prout(_("%6d calls for help from starbase %5d") %
3403 (game.nhelp, -45*game.nhelp))
3405 prout(_("%6d casualties incurred %5d") %
3406 (game.casual, -game.casual))
3408 prout(_("%6d crew abandoned in space %5d") %
3409 (game.abandoned, -3*game.abandoned))
3411 prout(_("%6d ship(s) lost or destroyed %5d") %
3412 (klship, -100*klship))
3414 prout(_("Penalty for getting yourself killed -200"))
3416 proutn(_("Bonus for winning "))
3417 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3418 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3419 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3420 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3421 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3422 prout(" %5d" % iwon)
3424 prout(_("TOTAL SCORE %5d") % iscore)
3427 # emit winner's commemmorative plaque
3430 proutn(_("File or device name for your plaque: "))
3433 fp = open(winner, "w")
3436 prout(_("Invalid name."))
3438 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3440 # The 38 below must be 64 for 132-column paper
3441 nskip = 38 - len(winner)/2
3443 fp.write("\n\n\n\n")
3444 # --------DRAW ENTERPRISE PICTURE.
3445 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3446 fp.write(" EEE E : : : E\n" )
3447 fp.write(" EE EEE E : : NCC-1701 : E\n")
3448 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3449 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3450 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3451 fp.write(" EEEEEEE EEEEE E E E E\n")
3452 fp.write(" EEE E E E E\n")
3453 fp.write(" E E E E\n")
3454 fp.write(" EEEEEEEEEEEEE E E\n")
3455 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3456 fp.write(" :E : EEEE E\n")
3457 fp.write(" .-E -:----- E\n")
3458 fp.write(" :E : E\n")
3459 fp.write(" EE : EEEEEEEE\n")
3460 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3462 fp.write(_(" U. S. S. ENTERPRISE\n"))
3463 fp.write("\n\n\n\n")
3464 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3466 fp.write(_(" Starfleet Command bestows to you\n"))
3468 fp.write("%*s%s\n\n" % (nskip, "", winner))
3469 fp.write(_(" the rank of\n\n"))
3470 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3472 if game.skill == SKILL_EXPERT:
3473 fp.write(_(" Expert level\n\n"))
3474 elif game.skill == SKILL_EMERITUS:
3475 fp.write(_("Emeritus level\n\n"))
3477 fp.write(_(" Cheat level\n\n"))
3478 timestring = ctime()
3479 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3480 (timestring+4, timestring+20, timestring+11))
3481 fp.write(_(" Your score: %d\n\n") % iscore)
3482 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3485 # Code from io.c begins here
3487 rows = linecount = 0 # for paging
3490 fullscreen_window = None
3491 srscan_window = None
3492 report_window = None
3493 status_window = None
3494 lrscan_window = None
3495 message_window = None
3496 prompt_window = None
3500 "wrap up, either normally or due to signal"
3501 if game.options & OPTION_CURSES:
3508 sys.stdout.write('\n')
3514 #setlocale(LC_ALL, "")
3515 #bindtextdomain(PACKAGE, LOCALEDIR)
3516 #textdomain(PACKAGE)
3517 if atexit.register(outro):
3518 sys.stderr.write("Unable to register outro(), exiting...\n")
3520 if not (game.options & OPTION_CURSES):
3521 ln_env = os.getenv("LINES")
3527 stdscr = curses.initscr()
3532 curses.start_color()
3533 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3534 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3535 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3536 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3537 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3538 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3539 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3540 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3542 global fullscreen_window, srscan_window, report_window, status_window
3543 global lrscan_window, message_window, prompt_window
3544 fullscreen_window = stdscr
3545 srscan_window = curses.newwin(12, 25, 0, 0)
3546 report_window = curses.newwin(11, 0, 1, 25)
3547 status_window = curses.newwin(10, 0, 1, 39)
3548 lrscan_window = curses.newwin(5, 0, 0, 64)
3549 message_window = curses.newwin(0, 0, 12, 0)
3550 prompt_window = curses.newwin(1, 0, rows-2, 0)
3551 message_window.scrollok(True)
3552 setwnd(fullscreen_window)
3557 "wait for user action -- OK to do nothing if on a TTY"
3558 if game.options & OPTION_CURSES:
3563 if game.skill > SKILL_FAIR:
3564 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3566 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3570 if game.skill > SKILL_FAIR:
3571 prompt = _("[CONTINUE?]")
3573 prompt = _("[PRESS ENTER TO CONTINUE]")
3575 if game.options & OPTION_CURSES:
3577 setwnd(prompt_window)
3578 prompt_window.wclear()
3579 prompt_window.addstr(prompt)
3580 prompt_window.getstr()
3581 prompt_window.clear()
3582 prompt_window.refresh()
3583 setwnd(message_window)
3586 sys.stdout.write('\n')
3589 for j in range(rows):
3590 sys.stdout.write('\n')
3594 "Skip i lines. Pause game if this would cause a scrolling event."
3595 for dummy in range(i):
3596 if game.options & OPTION_CURSES:
3597 (y, x) = curwnd.getyx()
3598 (my, mx) = curwnd.getmaxyx()
3599 if curwnd == message_window and y >= my - 3:
3607 if rows and linecount >= rows:
3610 sys.stdout.write('\n')
3613 "Utter a line with no following line feed."
3614 if game.options & OPTION_CURSES:
3618 sys.stdout.write(line)
3628 curses.delay_output(30)
3630 if game.options & OPTION_CURSES:
3634 curses.delay_output(300)
3637 "Get a line of input."
3638 if game.options & OPTION_CURSES:
3639 line = curwnd.getstr() + "\n"
3642 if replayfp and not replayfp.closed:
3643 line = replayfp.readline()
3651 "Change windows -- OK for this to be a no-op in tty mode."
3653 if game.options & OPTION_CURSES:
3655 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3658 "Clear to end of line -- can be a no-op in tty mode"
3659 if game.options & OPTION_CURSES:
3664 "Clear screen -- can be a no-op in tty mode."
3666 if game.options & OPTION_CURSES:
3672 def textcolor(color):
3673 "Set the current text color"
3674 if game.options & OPTION_CURSES:
3675 if color == DEFAULT:
3677 elif color == BLACK:
3678 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3680 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3681 elif color == GREEN:
3682 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3684 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3686 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3687 elif color == MAGENTA:
3688 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3689 elif color == BROWN:
3690 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3691 elif color == LIGHTGRAY:
3692 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3693 elif color == DARKGRAY:
3694 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3695 elif color == LIGHTBLUE:
3696 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3697 elif color == LIGHTGREEN:
3698 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3699 elif color == LIGHTCYAN:
3700 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3701 elif color == LIGHTRED:
3702 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3703 elif color == LIGHTMAGENTA:
3704 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3705 elif color == YELLOW:
3706 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3707 elif color == WHITE:
3708 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3711 "Set highlight video, if this is reasonable."
3712 if game.options & OPTION_CURSES:
3713 curwnd.attron(curses.A_REVERSE)
3716 # Things past this point have policy implications.
3720 "Hook to be called after moving to redraw maps."
3721 if game.options & OPTION_CURSES:
3724 setwnd(srscan_window)
3728 setwnd(status_window)
3729 status_window.clear()
3730 status_window.move(0, 0)
3731 setwnd(report_window)
3732 report_window.clear()
3733 report_window.move(0, 0)
3735 setwnd(lrscan_window)
3736 lrscan_window.clear()
3737 lrscan_window.move(0, 0)
3740 def put_srscan_sym(w, sym):
3741 "Emit symbol for short-range scan."
3742 srscan_window.move(w.x+1, w.y*2+2)
3743 srscan_window.addch(sym)
3744 srscan_window.refresh()
3747 "Enemy fall down, go boom."
3748 if game.options & OPTION_CURSES:
3750 setwnd(srscan_window)
3751 srscan_window.attron(curses.A_REVERSE)
3752 put_srscan_sym(w, game.quad[w.x][w.y])
3756 srscan_window.attroff(curses.A_REVERSE)
3757 put_srscan_sym(w, game.quad[w.x][w.y])
3758 curses.delay_output(500)
3759 setwnd(message_window)
3762 "Sound and visual effects for teleportation."
3763 if game.options & OPTION_CURSES:
3765 setwnd(message_window)
3767 prouts(" . . . . . ")
3768 if game.options & OPTION_CURSES:
3769 #curses.delay_output(1000)
3773 def tracktorpedo(w, l, i, n, iquad):
3774 "Torpedo-track animation."
3775 if not game.options & OPTION_CURSES:
3779 proutn(_("Track for torpedo number %d- ") % i)
3782 proutn(_("Torpedo track- "))
3785 proutn("%d - %d " % (w.x, w.y))
3787 if not damaged(DSRSENS) or game.condition=="docked":
3788 if i != 1 and l == 1:
3790 curses.delay_output(400)
3791 if (iquad==IHDOT) or (iquad==IHBLANK):
3792 put_srscan_sym(w, '+')
3794 #curses.delay_output(100)
3796 put_srscan_sym(w, iquad)
3798 curwnd.attron(curses.A_REVERSE)
3799 put_srscan_sym(w, iquad)
3801 #curses.delay_output(1000)
3803 curwnd.attroff(curses.A_REVERSE)
3804 put_srscan_sym(w, iquad)
3806 proutn("%d - %d " % (w.x, w.y))
3809 "Display the current galaxy chart."
3810 if game.options & OPTION_CURSES:
3811 setwnd(message_window)
3812 message_window.clear()
3814 if game.options & OPTION_TTY:
3819 def prstat(txt, data):
3821 if game.options & OPTION_CURSES:
3823 setwnd(status_window)
3825 proutn(" " * (NSYM - len(txt)))
3828 if game.options & OPTION_CURSES:
3829 setwnd(report_window)
3831 # Code from moving.c begins here
3833 def imove(novapush):
3834 # movement execution for warp, impulse, supernova, and tractor-beam events
3835 w = coord(); final = coord()
3838 def no_quad_change():
3839 # No quadrant change -- compute new avg enemy distances
3840 game.quad[game.sector.x][game.sector.y] = game.ship
3842 for m in range(game.nenhere):
3843 finald = distance(w, game.ks[m])
3844 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3845 game.kdist[m] = finald
3847 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3849 for m in range(game.nenhere):
3850 game.kavgd[m] = game.kdist[m]
3853 setwnd(message_window)
3857 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3858 game.inorbit = False
3860 angle = ((15.0 - game.direc) * 0.5235988)
3861 deltax = -math.sin(angle)
3862 deltay = math.cos(angle)
3863 if math.fabs(deltax) > math.fabs(deltay):
3864 bigger = math.fabs(deltax)
3866 bigger = math.fabs(deltay)
3871 # If tractor beam is to occur, don't move full distance
3872 if game.state.date+game.optime >= scheduled(FTBEAM):
3874 game.condition = "red"
3875 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3876 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3877 # Move within the quadrant
3878 game.quad[game.sector.x][game.sector.y] = IHDOT
3881 n = 10.0*game.dist*bigger+0.5
3884 for m in range(1, n+1):
3889 if not VALID_SECTOR(w.x, w.y):
3890 # Leaving quadrant -- allow final enemy attack
3891 # Don't do it if being pushed by Nova
3892 if game.nenhere != 0 and not novapush:
3894 for m in range(game.nenhere):
3895 finald = distance(w, game.ks[m])
3896 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
3898 # Stas Sergeev added the condition
3899 # that attacks only happen if Klingons
3900 # are present and your skill is good.
3902 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3906 # compute final position -- new quadrant and sector
3907 x = QUADSIZE*(game.quadrant.x-1)+game.sector.x
3908 y = QUADSIZE*(game.quadrant.y-1)+game.sector.y
3909 w.x = x+10.0*game.dist*bigger*deltax+0.5
3910 w.y = y+10.0*game.dist*bigger*deltay+0.5
3911 # check for edge of galaxy
3921 if w.x > GALSIZE*QUADSIZE:
3922 w.x = (GALSIZE*QUADSIZE*2)+1 - w.x
3924 if w.y > GALSIZE*QUADSIZE:
3925 w.y = (GALSIZE*QUADSIZE*2)+1 - w.y
3934 if game.nkinks == 3:
3935 # Three strikes -- you're out!
3939 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3940 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3941 prout(_("YOU WILL BE DESTROYED."))
3942 # Compute final position in new quadrant
3943 if trbeam: # Don't bother if we are to be beamed
3945 game.quadrant.x = (w.x+(QUADSIZE-1))/QUADSIZE
3946 game.quadrant.y = (w.y+(QUADSIZE-1))/QUADSIZE
3947 game.sector.x = w.x - QUADSIZE*(game.quadrant.x-1)
3948 game.sector.y = w.y - QUADSIZE*(game.quadrant.y-1)
3950 prout(_("Entering Quadrant %s.") % game.quadrant)
3951 game.quad[game.sector.x][game.sector.y] = game.ship
3953 if game.skill>SKILL_NOVICE:
3956 iquad = game.quad[w.x][w.y]
3958 # object encountered in flight path
3959 stopegy = 50.0*game.dist/game.optime
3960 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3961 if iquad in (IHT. IHK, OHC, IHS, IHR, IHQUEST):
3963 ram(False, iquad, game.sector)
3965 elif iquad == IHBLANK:
3967 prouts(_("***RED ALERT! RED ALERT!"))
3971 proutn(_(" pulled into black hole at Sector %s") % w)
3973 # Getting pulled into a black hole was certain
3974 # death in Almy's original. Stas Sergeev added a
3975 # possibility that you'll get timewarped instead.
3978 for m in range(NDEVICES):
3979 if game.damage[m]>0:
3981 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3982 if (game.options & OPTION_BLKHOLE) and random.random()>probf:
3992 proutn(_(" encounters Tholian web at %s;") % w)
3994 proutn(_(" blocked by object at %s;") % w)
3995 proutn(_("Emergency stop required "))
3996 prout(_("%2d units of energy.") % int(stopegy))
3997 game.energy -= stopegy
3998 final.x = x-deltax+0.5
3999 final.y = y-deltay+0.5
4001 if game.energy <= 0:
4007 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4014 # dock our ship at a starbase
4016 if game.condition == "docked" and verbose:
4017 prout(_("Already docked."))
4020 prout(_("You must first leave standard orbit."))
4022 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4024 prout(_(" not adjacent to base."))
4026 game.condition = "docked"
4030 if game.energy < game.inenrg:
4031 game.energy = game.inenrg
4032 game.shield = game.inshld
4033 game.torps = game.intorps
4034 game.lsupres = game.inlsr
4035 game.state.crew = FULLCREW
4036 if not damaged(DRADIO) and \
4037 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4038 # get attack report from base
4039 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4044 # This program originally required input in terms of a (clock)
4045 # direction and distance. Somewhere in history, it was changed to
4046 # cartesian coordinates. So we need to convert. Probably
4047 # "manual" input should still be done this way -- it's a real
4048 # pain if the computer isn't working! Manual mode is still confusing
4049 # because it involves giving x and y motions, yet the coordinates
4050 # are always displayed y - x, where +y is downward!
4053 def getcd(isprobe, akey):
4054 # get course and distance
4055 irowq=game.quadrant.x; icolq=game.quadrant.y; key=0
4056 navmode = "unspecified"
4061 # Get course direction and distance. If user types bad values, return
4062 # with DIREC = -1.0.
4065 if game.landed and not isprobe:
4066 prout(_("Dummy! You can't leave standard orbit until you"))
4067 proutn(_("are back aboard the ship."))
4070 while navmode == "unspecified":
4071 if damaged(DNAVSYS):
4073 prout(_("Computer damaged; manual navigation only"))
4075 prout(_("Computer damaged; manual movement only"))
4080 if isprobe and akey != -1:
4081 # For probe launch, use pre-scanned value first time
4088 proutn(_("Manual or automatic- "))
4091 elif key == IHALPHA:
4096 elif isit("automatic"):
4097 navmode = "automatic"
4106 prout(_("(Manual navigation assumed.)"))
4108 prout(_("(Manual movement assumed.)"))
4112 if navmode == "automatic":
4115 proutn(_("Target quadrant or quadrant§or- "))
4117 proutn(_("Destination sector or quadrant§or- "))
4125 xi = int(aaitem-0.05)
4130 xj = int(aaitem-0.5)
4133 # both quadrant and sector specified
4147 # only quadrant specified -- go to center of dest quad
4155 if not VALID_QUADRANT(icolq,irowq) or not VALID_SECTOR(incr.x,incr.y):
4162 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % incr)
4164 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4165 deltax = icolq - game.quadrant.y + 0.1*(incr.x-game.sector.y)
4166 deltay = game.quadrant.x - irowq + 0.1*(game.sector.x-incr.y)
4169 proutn(_("X and Y displacements- "))
4183 # Check for zero movement
4184 if deltax == 0 and deltay == 0:
4187 if itemp == "verbose" and not isprobe:
4189 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4190 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4191 game.direc = math.atan2(deltax, deltay)*1.90985932
4192 if game.direc < 0.0:
4198 # move under impulse power
4200 if damaged(DIMPULS):
4203 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4205 if game.energy > 30.0:
4207 if game.direc == -1.0:
4209 power = 20.0 + 100.0*game.dist
4213 if power >= game.energy:
4214 # Insufficient power for trip
4216 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4217 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4218 if game.energy > 30:
4219 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4220 int(0.01 * (game.energy-20.0)-0.05))
4221 prout(_(" quadrants.\""))
4223 prout(_("quadrant. They are, therefore, useless.\""))
4226 # Make sure enough time is left for the trip
4227 game.optime = game.dist/0.095
4228 if game.optime >= game.state.remtime:
4229 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4230 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4231 proutn(_("we dare spend the time?\" "))
4234 # Activate impulse engines and pay the cost
4239 power = 20.0 + 100.0*game.dist
4240 game.energy -= power
4241 game.optime = game.dist/0.095
4242 if game.energy <= 0:
4247 # move under warp drive
4248 blooey = False; twarp = False
4249 if not timewarp: # Not WARPX entry
4251 if game.damage[DWARPEN] > 10.0:
4254 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4256 if damaged(DWARPEN) and game.warpfac > 4.0:
4259 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4260 prout(_(" is repaired, I can only give you warp 4.\""))
4263 # Read in course and distance
4265 if game.direc == -1.0:
4268 # Make sure starship has enough energy for the trip
4269 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4270 if power >= game.energy:
4271 # Insufficient power for trip
4274 prout(_("Engineering to bridge--"))
4275 if not game.shldup or 0.5*power > game.energy:
4276 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4278 prout(_("We can't do it, Captain. We don't have enough energy."))
4280 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4283 prout(_("if you'll lower the shields."))
4287 prout(_("We haven't the energy to go that far with the shields up."))
4290 # Make sure enough time is left for the trip
4291 game.optime = 10.0*game.dist/game.wfacsq
4292 if game.optime >= 0.8*game.state.remtime:
4294 prout(_("First Officer Spock- \"Captain, I compute that such"))
4295 proutn(_(" a trip would require approximately %2.0f") %
4296 (100.0*game.optime/game.state.remtime))
4297 prout(_(" percent of our"))
4298 proutn(_(" remaining time. Are you sure this is wise?\" "))
4304 if game.warpfac > 6.0:
4305 # Decide if engine damage will occur
4306 prob = game.dist*(6.0-game.warpfac)*(6.0-game.warpfac)/66.666666666
4307 if prob > random.random():
4309 game.dist = random.random()*game.dist
4310 # Decide if time warp will occur
4311 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > random.random():
4313 if idebug and game.warpfac==10 and not twarp:
4315 proutn("=== Force time warp? ")
4319 # If time warp or engine damage, check path
4320 # If it is obstructed, don't do warp or damage
4321 angle = ((15.0-game.direc)*0.5235998)
4322 deltax = -math.sin(angle)
4323 deltay = math.cos(angle)
4324 if math.fabs(deltax) > math.fabs(deltay):
4325 bigger = math.fabs(deltax)
4327 bigger = math.fabs(deltay)
4331 n = 10.0 * game.dist * bigger +0.5
4334 for l in range(1, n+1):
4339 if not VALID_SECTOR(ix, iy):
4341 if game.quad[ix][iy] != IHDOT:
4346 # Activate Warp Engines and pay the cost
4350 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4351 if game.energy <= 0:
4353 game.optime = 10.0*game.dist/game.wfacsq
4357 game.damage[DWARPEN] = game.damfac*(3.0*random.random()+1.0)
4359 prout(_("Engineering to bridge--"))
4360 prout(_(" Scott here. The warp engines are damaged."))
4361 prout(_(" We'll have to reduce speed to warp 4."))
4366 # change the warp factor
4372 proutn(_("Warp factor- "))
4377 if game.damage[DWARPEN] > 10.0:
4378 prout(_("Warp engines inoperative."))
4380 if damaged(DWARPEN) and aaitem > 4.0:
4381 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4382 prout(_(" but right now we can only go warp 4.\""))
4385 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4388 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4390 oldfac = game.warpfac
4391 game.warpfac = aaitem
4392 game.wfacsq=game.warpfac*game.warpfac
4393 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4394 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4397 if game.warpfac < 8.00:
4398 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4400 if game.warpfac == 10.0:
4401 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4403 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4407 # cope with being tossed out of quadrant by supernova or yanked by beam
4410 # is captain on planet?
4412 if damaged(DTRANSP):
4415 prout(_("Scotty rushes to the transporter controls."))
4417 prout(_("But with the shields up it's hopeless."))
4419 prouts(_("His desperate attempt to rescue you . . ."))
4420 if random.random() <= 0.5:
4424 prout(_("SUCCEEDS!"))
4427 proutn(_("The crystals mined were "))
4428 if random.random() <= 0.25:
4436 # Check to see if captain in shuttle craft
4442 # Inform captain of attempt to reach safety
4446 prouts(_("***RED ALERT! RED ALERT!"))
4450 prout(_(" has stopped in a quadrant containing"))
4451 prouts(_(" a supernova."))
4453 proutn(_("***Emergency automatic override attempts to hurl "))
4456 prout(_("safely out of quadrant."))
4457 if not damaged(DRADIO):
4458 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4459 # Try to use warp engines
4460 if damaged(DWARPEN):
4462 prout(_("Warp engines damaged."))
4465 game.warpfac = 6.0+2.0*random.random()
4466 game.wfacsq = game.warpfac * game.warpfac
4467 prout(_("Warp factor set to %d") % int(game.warpfac))
4468 power = 0.75*game.energy
4469 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4470 distreq = 1.4142+random.random()
4471 if distreq < game.dist:
4473 game.optime = 10.0*game.dist/game.wfacsq
4474 game.direc = 12.0*random.random() # How dumb!
4476 game.inorbit = False
4479 # This is bad news, we didn't leave quadrant.
4483 prout(_("Insufficient energy to leave quadrant."))
4486 # Repeat if another snova
4487 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4489 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4490 finish(FWON) # Snova killed remaining enemy.
4493 # let's do the time warp again
4494 prout(_("***TIME WARP ENTERED."))
4495 if game.state.snap and random.random() < 0.5:
4497 prout(_("You are traveling backwards in time %d stardates.") %
4498 int(game.state.date-game.snapsht.date))
4499 game.state = game.snapsht
4500 game.state.snap = False
4501 if game.state.remcom:
4502 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4503 schedule(FBATTAK, expran(0.3*game.intime))
4504 schedule(FSNOVA, expran(0.5*game.intime))
4505 # next snapshot will be sooner
4506 schedule(FSNAP, expran(0.25*game.state.remtime))
4508 if game.state.nscrem:
4509 schedule(FSCMOVE, 0.2777)
4513 invalidate(game.battle)
4515 # Make sure Galileo is consistant -- Snapshot may have been taken
4516 # when on planet, which would give us two Galileos!
4518 for l in range(game.inplan):
4519 if game.state.planets[l].known == "shuttle_down":
4521 if game.iscraft == "onship" and game.ship==IHE:
4522 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4523 game.iscraft = "offship"
4524 # Likewise, if in the original time the Galileo was abandoned, but
4525 # was on ship earlier, it would have vanished -- let's restore it.
4526 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4527 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4528 game.iscraft = "onship"
4530 # * There used to be code to do the actual reconstrction here,
4531 # * but the starchart is now part of the snapshotted galaxy state.
4533 prout(_("Spock has reconstructed a correct star chart from memory"))
4535 # Go forward in time
4536 game.optime = -0.5*game.intime*math.log(random.random())
4537 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4538 # cheat to make sure no tractor beams occur during time warp
4539 postpone(FTBEAM, game.optime)
4540 game.damage[DRADIO] += game.optime
4542 events() # Stas Sergeev added this -- do pending events
4545 # launch deep-space probe
4546 # New code to launch a deep space probe
4547 if game.nprobes == 0:
4550 if game.ship == IHE:
4551 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4553 prout(_("Ye Faerie Queene has no deep space probes."))
4558 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4560 if is_scheduled(FDSPROB):
4563 if damaged(DRADIO) and game.condition != "docked":
4564 prout(_("Spock- \"Records show the previous probe has not yet"))
4565 prout(_(" reached its destination.\""))
4567 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4572 # slow mode, so let Kirk know how many probes there are left
4573 if game.nprobes == 1:
4574 prout(_("1 probe left."))
4576 prout(_("%d probes left") % game.nprobes)
4577 proutn(_("Are you sure you want to fire a probe? "))
4581 game.isarmed = False
4582 if key == IHALPHA and citem == "armed":
4586 proutn(_("Arm NOVAMAX warhead? "))
4589 if game.direc == -1.0:
4592 angle = ((15.0 - game.direc) * 0.5235988)
4593 game.probeinx = -math.sin(angle)
4594 game.probeiny = math.cos(angle)
4595 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4596 bigger = math.fabs(game.probeinx)
4598 bigger = math.fabs(game.probeiny)
4600 game.probeiny /= bigger
4601 game.probeinx /= bigger
4602 game.proben = 10.0*game.dist*bigger +0.5
4603 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4604 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4605 game.probec = game.quadrant
4606 schedule(FDSPROB, 0.01) # Time to move one sector
4607 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4611 # Here's how the mayday code works:
4613 # First, the closest starbase is selected. If there is a a starbase
4614 # in your own quadrant, you are in good shape. This distance takes
4615 # quadrant distances into account only.
4617 # A magic number is computed based on the distance which acts as the
4618 # probability that you will be rematerialized. You get three tries.
4620 # When it is determined that you should be able to be rematerialized
4621 # (i.e., when the probability thing mentioned above comes up
4622 # positive), you are put into that quadrant (anywhere). Then, we try
4623 # to see if there is a spot adjacent to the star- base. If not, you
4624 # can't be rematerialized!!! Otherwise, it drops you there. It only
4625 # tries five times to find a spot to drop you. After that, it's your
4629 # yell for help from nearest starbase
4630 # There's more than one way to move in this game!
4634 # Test for conditions which prevent calling for help
4635 if game.condition == "docked":
4636 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4639 prout(_("Subspace radio damaged."))
4641 if game.state.rembase==0:
4642 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4645 proutn(_("You must be aboard the "))
4649 # OK -- call for help from nearest starbase
4652 # There's one in this quadrant
4653 ddist = distance(game.base, game.sector)
4656 for m in range(game.state.rembase):
4657 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4661 # Since starbase not in quadrant, set up new quadrant
4662 game.quadrant = game.state.baseq[line]
4664 # dematerialize starship
4665 game.quad[game.sector.x][game.sector.y]=IHDOT
4666 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4668 prout(_(" dematerializes."))
4670 for m in range(1, 5+1):
4671 ix = game.base.x+3.0*random.random()-1
4672 iy = game.base.y+3.0*random.random()-1
4673 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4674 # 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 random.random() > 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 != NOPLANET 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 = random.random()*game.state.rembase+1
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.x = 3.0*random.random() - 1.0 + game.base.x
4797 game.sector.y = 3.0*random.random() - 1.0 + game.base.y
4798 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4799 game.quad[game.sector.x][game.sector.y] == IHDOT:
4802 break # found a spot
4803 game.sector.x=QUADSIZE/2
4804 game.sector.y=QUADSIZE/2
4806 # Get new commission
4807 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4808 game.state.crew = FULLCREW
4809 prout(_("Starfleet puts you in command of another ship,"))
4810 prout(_("the Faerie Queene, which is antiquated but,"))
4811 prout(_("still useable."))
4813 prout(_("The dilithium crystals have been moved."))
4815 game.iscraft = "offship" # Galileo disappears
4817 game.condition="docked"
4818 for l in range(NDEVICES):
4819 game.damage[l] = 0.0
4820 game.damage[DSHUTTL] = -1
4821 game.energy = game.inenrg = 3000.0
4822 game.shield = game.inshld = 1250.0
4823 game.torps = game.intorps = 6
4824 game.lsupres=game.inlsr=3.0
4830 # Code from planets.c begins here.
4833 # abort a lengthy operation if an event interrupts it
4836 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4841 # report on (uninhabited) planets in the galaxy
4845 prout(_("Spock- \"Planet report follows, Captain.\""))
4847 for i in range(game.inplan):
4848 if game.state.planets[i].pclass == destroyed:
4850 if (game.state.planets[i].known != "unknown" \
4851 and not game.state.planets[i].inhabited) \
4854 if idebug and game.state.planets[i].known=="unknown":
4855 proutn("(Unknown) ")
4856 proutn(_("Quadrant %s") % game.state.planets[i].w)
4857 proutn(_(" class "))
4858 proutn(game.state.planets[i].pclass)
4860 if game.state.planets[i].crystals != present:
4862 prout(_("dilithium crystals present."))
4863 if game.state.planets[i].known=="shuttle_down":
4864 prout(_(" Shuttle Craft Galileo on surface."))
4866 prout(_("No information available."))
4869 # enter standard orbit
4873 prout(_("Already in standard orbit."))
4875 if damaged(DWARPEN) and damaged(DIMPULS):
4876 prout(_("Both warp and impulse engines damaged."))
4878 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4880 prout(_(" not adjacent to planet."))
4883 game.optime = 0.02+0.03*random.random()
4884 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4888 game.height = (1400.0+7200.0*random.random())
4889 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4894 # examine planets in this quadrant
4895 if damaged(DSRSENS):
4896 if game.options & OPTION_TTY:
4897 prout(_("Short range sensors damaged."))
4899 if not is_valid(game.plnet):
4900 if game.options & OPTION_TTY:
4901 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4903 if game.state.planets[game.iplnet].known == "unknown":
4904 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4906 prout(_(" Planet at Sector %s is of class %s.") %
4907 (sector,game.plnet, game.state.planets[game.iplnet]))
4908 if game.state.planets[game.iplnet].known=="shuttle_down":
4909 prout(_(" Sensors show Galileo still on surface."))
4910 proutn(_(" Readings indicate"))
4911 if game.state.planets[game.iplnet].crystals != present:
4913 prout(_(" dilithium crystals present.\""))
4914 if game.state.planets[game.iplnet].known == "unknown":
4915 game.state.planets[game.iplnet].known = "known"
4918 # use the transporter
4922 if damaged(DTRANSP):
4923 prout(_("Transporter damaged."))
4924 if not damaged(DSHUTTL) and (game.state.planets[game.iplnet].known=="shuttle_down" or game.iscraft == "onship"):
4926 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4930 if not game.inorbit:
4932 prout(_(" not in standard orbit."))
4935 prout(_("Impossible to transport through shields."))
4937 if game.state.planets[game.iplnet].known=="unknown":
4938 prout(_("Spock- \"Captain, we have no information on this planet"))
4939 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4940 prout(_(" you may not go down.\""))
4942 if not game.landed and game.state.planets[game.iplnet].crystals==absent:
4943 prout(_("Spock- \"Captain, I fail to see the logic in"))
4944 prout(_(" exploring a planet with no dilithium crystals."))
4945 proutn(_(" Are you sure this is wise?\" "))
4949 if not (game.options & OPTION_PLAIN):
4950 nrgneed = 50 * game.skill + game.height / 100.0
4951 if nrgneed > game.energy:
4952 prout(_("Engineering to bridge--"))
4953 prout(_(" Captain, we don't have enough energy for transportation."))
4955 if not game.landed and nrgneed * 2 > game.energy:
4956 prout(_("Engineering to bridge--"))
4957 prout(_(" Captain, we have enough energy only to transport you down to"))
4958 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4959 if game.state.planets[game.iplnet].known == "shuttle_down":
4960 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4961 proutn(_(" Are you sure this is wise?\" "))
4966 # Coming from planet
4967 if game.state.planets[game.iplnet].known=="shuttle_down":
4968 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4972 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4973 prout(_("Landing party assembled, ready to beam up."))
4975 prout(_("Kirk whips out communicator..."))
4976 prouts(_("BEEP BEEP BEEP"))
4978 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4981 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4983 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4985 prout(_("Kirk- \"Energize.\""))
4988 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4990 if random.random() > 0.98:
4991 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4993 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4996 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4997 game.landed = not game.landed
4998 game.energy -= nrgneed
5000 prout(_("Transport complete."))
5001 if game.landed and game.state.planets[game.iplnet].known=="shuttle_down":
5002 prout(_("The shuttle craft Galileo is here!"))
5003 if not game.landed and game.imine:
5010 # strip-mine a world for dilithium
5014 prout(_("Mining party not on planet."))
5016 if game.state.planets[game.iplnet].crystals == mined:
5017 prout(_("This planet has already been strip-mined for dilithium."))
5019 elif game.state.planets[game.iplnet].crystals == absent:
5020 prout(_("No dilithium crystals on this planet."))
5023 prout(_("You've already mined enough crystals for this trip."))
5025 if game.icrystl and game.cryprob == 0.05:
5026 proutn(_("With all those fresh crystals aboard the "))
5029 prout(_("there's no reason to mine more at this time."))
5031 game.optime = (0.1+0.2*random.random())*game.state.planets[game.iplnet].pclass
5034 prout(_("Mining operation complete."))
5035 game.state.planets[game.iplnet].crystals = mined
5036 game.imine = game.ididit = True
5039 # use dilithium crystals
5043 if not game.icrystl:
5044 prout(_("No dilithium crystals available."))
5046 if game.energy >= 1000:
5047 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5048 prout(_(" except when Condition Yellow exists."))
5050 prout(_("Spock- \"Captain, I must warn you that loading"))
5051 prout(_(" raw dilithium crystals into the ship's power"))
5052 prout(_(" system may risk a severe explosion."))
5053 proutn(_(" Are you sure this is wise?\" "))
5058 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5059 prout(_(" Mr. Spock and I will try it.\""))
5061 prout(_("Spock- \"Crystals in place, Sir."))
5062 prout(_(" Ready to activate circuit.\""))
5064 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5066 if random.random() <= game.cryprob:
5067 prouts(_(" \"Activating now! - - No good! It's***"))
5069 prouts(_("***RED ALERT! RED A*L********************************"))
5072 prouts(_("****************** KA-BOOM!!!! *******************"))
5076 game.energy += 5000.0*(1.0 + 0.9*random.random())
5077 prouts(_(" \"Activating now! - - "))
5078 prout(_("The instruments"))
5079 prout(_(" are going crazy, but I think it's"))
5080 prout(_(" going to work!! Congratulations, Sir!\""))
5085 # use shuttlecraft for planetary jaunt
5088 if damaged(DSHUTTL):
5089 if game.damage[DSHUTTL] == -1.0:
5090 if game.inorbit and game.state.planets[game.iplnet].known == "shuttle_down":
5091 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5093 prout(_("Ye Faerie Queene had no shuttle craft."))
5094 elif game.damage[DSHUTTL] > 0:
5095 prout(_("The Galileo is damaged."))
5096 else: # game.damage[DSHUTTL] < 0
5097 prout(_("Shuttle craft is now serving Big Macs."))
5099 if not game.inorbit:
5101 prout(_(" not in standard orbit."))
5103 if (game.state.planets[game.iplnet].known != "shuttle_down") and game.iscraft != "onship":
5104 prout(_("Shuttle craft not currently available."))
5106 if not game.landed and game.state.planets[game.iplnet].known=="shuttle_down":
5107 prout(_("You will have to beam down to retrieve the shuttle craft."))
5109 if game.shldup or game.condition == "docked":
5110 prout(_("Shuttle craft cannot pass through shields."))
5112 if game.state.planets[game.iplnet].known=="unknown":
5113 prout(_("Spock- \"Captain, we have no information on this planet"))
5114 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5115 prout(_(" you may not fly down.\""))
5117 game.optime = 3.0e-5*game.height
5118 if game.optime >= 0.8*game.state.remtime:
5119 prout(_("First Officer Spock- \"Captain, I compute that such"))
5120 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5121 int(100*game.optime/game.state.remtime))
5122 prout(_("remaining time."))
5123 proutn(_("Are you sure this is wise?\" "))
5129 if game.iscraft == "onship":
5131 if not damaged(DTRANSP):
5132 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5136 proutn(_("Shuttle crew"))
5138 proutn(_("Rescue party"))
5139 prout(_(" boards Galileo and swoops toward planet surface."))
5140 game.iscraft = "offship"
5144 game.state.planets[game.iplnet].known="shuttle_down"
5145 prout(_("Trip complete."))
5148 # Ready to go back to ship
5149 prout(_("You and your mining party board the"))
5150 prout(_("shuttle craft for the trip back to the Enterprise."))
5152 prouts(_("The short hop begins . . ."))
5154 game.state.planets[game.iplnet].known="known"
5160 game.iscraft = "onship"
5166 prout(_("Trip complete."))
5171 prout(_("Mining party assembles in the hangar deck,"))
5172 prout(_("ready to board the shuttle craft \"Galileo\"."))
5174 prouts(_("The hangar doors open; the trip begins."))
5177 game.iscraft = "offship"
5180 game.state.planets[game.iplnet].known = "shuttle_down"
5183 prout(_("Trip complete."))
5187 # 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:
5225 prouts(_("Sulu- \"Captain! It's working!\""))
5227 while game.nenhere > 0:
5228 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5229 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5230 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5232 if (game.options & OPTION_PLAIN) == 0:
5233 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5234 if random.random() <= 0.05:
5235 prout(_(" is still operational.\""))
5237 prout(_(" has been rendered nonfunctional.\""))
5238 game.damage[DDRAY] = 39.95
5240 r = random.random() # Pick failure method
5242 prouts(_("Sulu- \"Captain! It's working!\""))
5244 prouts(_("***RED ALERT! RED ALERT!"))
5246 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5248 prouts(_("***RED ALERT! RED A*L********************************"))
5251 prouts(_("****************** KA-BOOM!!!! *******************"))
5256 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5258 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5260 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5261 prout(_(" have apparently been transformed into strange mutations."))
5262 prout(_(" Vulcans do not seem to be affected."))
5264 prout(_("Kirk- \"Raauch! Raauch!\""))
5269 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5271 proutn(_("Spock- \"I believe the word is"))
5272 prouts(_(" *ASTONISHING*"))
5273 prout(_(" Mr. Sulu."))
5274 for i in range(QUADSIZE):
5275 for j in range(QUADSIZE):
5276 if game.quad[i][j] == IHDOT:
5277 game.quad[i][j] = IHQUEST
5278 prout(_(" Captain, our quadrant is now infested with"))
5279 prouts(_(" - - - - - - *THINGS*."))
5281 prout(_(" I have no logical explanation.\""))
5283 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5285 prout(_("Scotty- \"There are so many tribbles down here"))
5286 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5290 # Code from reports.c begins here
5292 def attackreport(curt):
5293 # report status of bases under attack
5295 if is_scheduled(FCDBAS):
5296 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5297 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5298 elif game.isatb == 1:
5299 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5300 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5302 prout(_("No Starbase is currently under attack."))
5304 if is_scheduled(FCDBAS):
5305 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5307 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5311 # report on general game status
5313 s1 = "" and game.thawed and _("thawed ")
5314 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5315 s3 = (None, _("novice"). _("fair"),
5316 _("good"), _("expert"), _("emeritus"))[game.skill]
5317 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5318 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5319 prout(_("No plaque is allowed."))
5321 prout(_("This is tournament game %d.") % game.tourn)
5322 prout(_("Your secret password is \"%s\"") % game.passwd)
5323 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5324 (game.inkling + game.incom + game.inscom)))
5325 if game.incom - game.state.remcom:
5326 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5327 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5328 prout(_(", but no Commanders."))
5331 if game.skill > SKILL_FAIR:
5332 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5333 if game.state.rembase != game.inbase:
5335 if game.inbase-game.state.rembase==1:
5336 proutn(_("has been 1 base"))
5338 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5339 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5341 prout(_("There are %d bases.") % game.inbase)
5342 if communicating() or game.iseenit:
5343 # Don't report this if not seen and
5344 # either the radio is dead or not at base!
5348 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5350 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5351 if game.ship == IHE:
5352 proutn(_("You have "))
5354 proutn("%d" % (game.nprobes))
5357 proutn(_(" deep space probe"))
5361 if communicating() and is_scheduled(FDSPROB):
5363 proutn(_("An armed deep space probe is in "))
5365 proutn(_("A deep space probe is in "))
5366 prout("Quadrant %s." % game.probec)
5368 if game.cryprob <= .05:
5369 prout(_("Dilithium crystals aboard ship... not yet used."))
5373 while game.cryprob > ai:
5376 prout(_("Dilithium crystals have been used %d time%s.") % \
5377 (i, (_("s"), "")[i==1]))
5381 # long-range sensor scan
5382 if damaged(DLRSENS):
5383 # Now allow base's sensors if docked
5384 if game.condition != "docked":
5385 prout(_("LONG-RANGE SENSORS DAMAGED."))
5387 prout(_("Starbase's long-range scan"))
5389 prout(_("Long-range scan"))
5390 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5392 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5393 if not VALID_QUADRANT(x, y):
5396 if not damaged(DRADIO):
5397 game.state.galaxy[x][y].charted = True
5398 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5399 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5400 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5401 if game.state.galaxy[x][y].supernova:
5404 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5412 for i in range(NDEVICES):
5415 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5416 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5418 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5419 game.damage[i]+0.05,
5420 game.docfac*game.damage[i]+0.005))
5422 prout(_("All devices functional."))
5425 # update the chart in the Enterprise's computer from galaxy data
5426 game.lastchart = game.state.date
5427 for i in range(GALSIZE):
5428 for j in range(GALSIZE):
5429 if game.state.galaxy[i][j].charted:
5430 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5431 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5432 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5435 # display the star chart
5437 if not damaged(DRADIO):
5439 if game.lastchart < game.state.date and game.condition == "docked":
5440 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5443 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5444 if game.state.date > game.lastchart:
5445 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5446 prout(" 1 2 3 4 5 6 7 8")
5447 for i in range(GALSIZE):
5448 proutn("%d |" % (i))
5449 for j in range(GALSIZE):
5450 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5454 if game.state.galaxy[i][j].supernova:
5456 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5458 elif game.state.galaxy[i][j].charted:
5459 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
5463 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5471 def sectscan(goodScan, i, j):
5472 # light up an individual dot in a sector
5473 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5474 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):
5475 if game.condition == "red": textcolor(RED)
5476 elif game.condition == "green": textcolor(GREEN)
5477 elif game.condition == "yellow": textcolor(YELLOW)
5478 elif game.condition == "docked": textcolor(CYAN)
5479 elif game.condition == "dead": textcolor(BROWN)
5480 if game.quad[i][j] != game.ship:
5482 proutn("%c " % game.quad[i][j])
5488 # print status report lines
5490 if not req or req == 1:
5491 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5492 % (game.state.date, game.state.remtime))
5493 if not req or req == 2:
5494 if game.condition != "docked":
5497 for t in range(NDEVICES):
5498 if game.damage[t]>0:
5500 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5501 if not req or req == 3:
5502 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5503 if not req or req == 4:
5504 if damaged(DLIFSUP):
5505 if game.condition == "docked":
5506 s = _("DAMAGED, Base provides")
5508 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
5511 prstat(_("Life Support"), s)
5512 if not req or req == 5:
5513 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
5514 if not req or req == 6:
5516 if game.icrystl and (game.options & OPTION_SHOWME):
5517 extra = _(" (have crystals)")
5518 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
5519 if not req or req == 7:
5520 prstat(_("Torpedoes"), "%d" % (game.torps))
5521 if not req or req == 8:
5522 if damaged(DSHIELD):
5528 data = _(" %d%% %.1f units") \
5529 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5530 prstat(_("Shields"), s+data)
5531 if not req or req == 9:
5532 prstat(_("Klingons Left"), "%d" \
5533 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5534 if not req or req == 10:
5535 if game.options & OPTION_WORLDS:
5536 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5537 if plnet != NOPLANET and game.state.planets[plnet].inhabited:
5538 prstat(_("Major system"), plnet.name)
5540 prout(_("Sector is uninhabited"))
5541 elif not req or req == 11:
5542 attackreport(not req)
5545 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5546 while scan() == IHEOL:
5547 proutn(_("Information desired? "))
5549 if citem in requests:
5550 status(requests.index(citem))
5552 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5553 prout((" date, condition, position, lsupport, warpfactor,"))
5554 prout((" energy, torpedoes, shields, klingons, system, time."))
5559 if damaged(DSRSENS):
5560 # Allow base's sensors if docked
5561 if game.condition != "docked":
5562 prout(_(" S.R. SENSORS DAMAGED!"))
5565 prout(_(" [Using Base's sensors]"))
5567 prout(_(" Short-range scan"))
5568 if goodScan and not damaged(DRADIO):
5569 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5570 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5571 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5572 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5573 prout(" 1 2 3 4 5 6 7 8 9 10")
5574 if game.condition != "docked":
5576 for i in range(QUADSIZE):
5577 proutn("%2d " % (i))
5578 for j in range(QUADSIZE):
5579 sectscan(goodScan, i, j)
5584 # use computer to get estimated time of arrival for a warp jump
5585 w1 = coord(); w2 = coord()
5587 if damaged(DCOMPTR):
5588 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5591 if scan() != IHREAL:
5594 proutn(_("Destination quadrant and/or sector? "))
5598 w1.y = int(aaitem-0.5)
5599 if scan() != IHREAL:
5602 w1.x = int(aaitem-0.5)
5603 if scan() == IHREAL:
5604 w2.y = int(aaitem-0.5)
5605 if scan() != IHREAL:
5608 w2.x = int(aaitem-0.5)
5610 if game.quadrant.y>w1.x:
5614 if game.quadrant.x>w1.y:
5619 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5622 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5623 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5627 prout(_("Answer \"no\" if you don't know the value:"))
5630 proutn(_("Time or arrival date? "))
5633 if ttime > game.state.date:
5634 ttime -= game.state.date # Actually a star date
5635 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5636 if ttime <= 1e-10 or twarp > 10:
5637 prout(_("We'll never make it, sir."))
5644 proutn(_("Warp factor? "))
5648 if twarp<1.0 or twarp > 10.0:
5652 prout(_("Captain, certainly you can give me one of these."))
5655 ttime = (10.0*game.dist)/square(twarp)
5656 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5657 if tpower >= game.energy:
5658 prout(_("Insufficient energy, sir."))
5659 if not game.shldup or tpower > game.energy*2.0:
5662 proutn(_("New warp factor to try? "))
5663 if scan() == IHREAL:
5666 if twarp<1.0 or twarp > 10.0:
5674 prout(_("But if you lower your shields,"))
5675 proutn(_("remaining"))
5678 proutn(_("Remaining"))
5679 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5681 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5683 prout(_("Any warp speed is adequate."))
5685 prout(_("Minimum warp needed is %.2f,") % (twarp))
5686 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5687 if game.state.remtime < ttime:
5688 prout(_("Unfortunately, the Federation will be destroyed by then."))
5690 prout(_("You'll be taking risks at that speed, Captain"))
5691 if (game.isatb==1 and game.state.kscmdr == w1 and \
5692 scheduled(FSCDBAS)< ttime+game.state.date) or \
5693 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5694 prout(_("The starbase there will be destroyed by then."))
5695 proutn(_("New warp factor to try? "))
5696 if scan() == IHREAL:
5699 if twarp<1.0 or twarp > 10.0:
5708 #ifdef BSD_BUG_FOR_BUG
5709 # A visual scan is made in a particular direction of three sectors
5710 # in the general direction specified. This takes time, and
5711 # Klingons can attack you, so it should be done only when sensors
5712 # are out. Code swiped from BSD-Trek. Not presently used, as we
5713 # automatically display all adjacent sectors on the short-range
5714 # scan even when short-range sensors are out.
5716 # This struct[] has the delta x, delta y for particular directions
5734 if scan() != IHREAL:
5736 proutn(_("Direction? "))
5740 if aaitem < 0.0 or aaitem > 360.0:
5742 co = (aaitem + 22) / 45
5744 ix = game.sector.x + v.x
5745 iy = game.sector.y + v.y
5746 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5749 co = game.quad[ix][iy]
5750 printf("%d,%d %c " % (ix+1, iy+1, co))
5752 ix = game.sector.x + v.x
5753 iy = game.sector.y + v.y
5754 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5757 co = game.quad[ix][iy]
5758 printf("%c " % (co))
5760 ix = game.sector.x + v.x
5761 iy = game.sector.y + v.y
5762 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5765 co = game.quad[ix][iy]
5766 prout("%c %d,%d\n" % (co, ix+1, iy+1))
5771 # Code from setup.c begins here
5774 return os.fstat(fd).st_size
5777 # issue a historically correct banner
5779 prout(_("-SUPER- STAR TREK"))
5781 #ifdef __HISTORICAL__
5782 # prout(_("Latest update-21 Sept 78"))
5784 #endif __HISTORICAL__
5789 citem = "emsave.trk"
5793 proutn(_("File name: "))
5799 if '.' not in citem:
5802 fp = open(citem, "wb")
5804 prout(_("Can't freeze game as file %s") % citem)
5806 cPickle.dump(game, fp)
5810 # retrieve saved game
5811 game.passwd[0] = '\0'
5814 proutn(_("File name: "))
5820 if '.' not in citem:
5823 fp = open(citem, "rb")
5825 prout(_("Can't thaw game in %s") % citem)
5827 game = cPickle.load(fp)
5831 # I used <http://www.memory-alpha.org> to find planets
5832 # with references in ST:TOS. Eath and the Alpha Centauri
5833 # Colony have been omitted.
5835 # Some planets marked Class G and P here will be displayed as class M
5836 # because of the way planets are generated. This is a known bug.
5839 _("Andoria (Fesoan)"), # several episodes
5840 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5841 _("Vulcan (T'Khasi)"), # many episodes
5842 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5843 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5844 _("Ardana"), # TOS: "The Cloud Minders"
5845 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5846 _("Gideon"), # TOS: "The Mark of Gideon"
5847 _("Aldebaran III"), # TOS: "The Deadly Years"
5848 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5849 _("Altair IV"), # TOS: "Amok Time
5850 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5851 _("Benecia"), # TOS: "The Conscience of the King"
5852 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5853 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5854 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5855 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5856 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5857 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5858 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5859 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5860 _("Ingraham B"), # TOS: "Operation: Annihilate"
5861 _("Janus IV"), # TOS: "The Devil in the Dark"
5862 _("Makus III"), # TOS: "The Galileo Seven"
5863 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5864 _("Omega IV"), # TOS: "The Omega Glory"
5865 _("Regulus V"), # TOS: "Amok Time
5866 _("Deneva"), # TOS: "Operation -- Annihilate!"
5867 # Worlds from BSD Trek
5868 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5869 _("Beta III"), # TOS: "The Return of the Archons"
5870 _("Triacus"), # TOS: "And the Children Shall Lead",
5871 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5873 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5874 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5875 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5876 # _("Izar"), # TOS: "Whom Gods Destroy"
5877 # _("Tiburon"), # TOS: "The Way to Eden"
5878 # _("Merak II"), # TOS: "The Cloud Minders"
5879 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5880 # _("Iotia"), # TOS: "A Piece of the Action"
5884 _("S. R. Sensors"), \
5885 _("L. R. Sensors"), \
5887 _("Photon Tubes"), \
5888 _("Life Support"), \
5889 _("Warp Engines"), \
5890 _("Impulse Engines"), \
5892 _("Subspace Radio"), \
5893 _("Shuttle Craft"), \
5895 _("Navigation System"), \
5897 _("Shield Control"), \
5902 def setup(needprompt):
5903 # prepare to play, set up cosmos
5906 # Decide how many of everything
5907 if choose(needprompt):
5908 return # frozen game
5909 # Prepare the Enterprise
5910 game.alldone = game.gamewon = False
5912 game.state.crew = FULLCREW
5913 game.energy = game.inenrg = 5000.0
5914 game.shield = game.inshld = 2500.0
5915 game.shldchg = False
5919 game.quadrant = randplace(GALSIZE)
5920 game.sector = randplace(QUADSIZE)
5921 game.torps = game.intorps = 10
5922 game.nprobes = int(3.0*random.random() + 2.0) # Give them 2-4 of these
5924 game.wfacsq = game.warpfac * game.warpfac
5925 for i in range(NDEVICES):
5926 game.damage[i] = 0.0
5927 # Set up assorted game parameters
5928 game.battle = coord()
5929 game.state.date = game.indate = 100.0*int(31.0*random.random()+20.0)
5930 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5931 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5932 game.isatb = game.state.nplankl = 0
5933 game.state.starkl = game.state.basekl = 0
5934 game.iscraft = "onship"
5938 for i in range(GALSIZE):
5939 for j in range(GALSIZE):
5940 quad = game.state.galaxy[i][j]
5942 quad.planet = NOPLANET
5945 quad.starbase = False
5946 quad.supernova = False
5947 quad.status = "secure"
5948 # Initialize times for extraneous events
5949 schedule(FSNOVA, expran(0.5 * game.intime))
5950 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5951 schedule(FSNAP, 1.0 + random.random()) # Force an early snapshot
5952 schedule(FBATTAK, expran(0.3*game.intime))
5954 if game.state.nscrem:
5955 schedule(FSCMOVE, 0.2777)
5960 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5961 schedule(FDISTR, expran(1.0 + game.intime))
5966 # Starchart is functional but we've never seen it
5967 game.lastchart = FOREVER
5968 # Put stars in the galaxy
5970 for i in range(GALSIZE):
5971 for j in range(GALSIZE):
5972 k = int(random.random()*9.0 + 1.0)
5974 game.state.galaxy[i][j].stars = k
5975 # Locate star bases in galaxy
5976 for i in range(game.inbase):
5979 w = randplace(GALSIZE)
5980 if not game.state.galaxy[w.x][w.y].starbase:
5983 # C version: for (j = i-1; j > 0; j--)
5984 # so it did them in the opposite order.
5985 for j in range(1, i):
5986 # Improved placement algorithm to spread out bases
5987 distq = w.distance(game.state.baseq[j])
5988 if distq < 6.0*(BASEMAX+1-game.inbase) and random.random() < 0.75:
5991 prout("=== Abandoning base #%d at %s" % (i, w))
5993 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5995 prout("=== Saving base #%d, close to #%d" % (i, j))
5998 game.state.baseq[i] = w
5999 game.state.galaxy[w.x][w.y].starbase = True
6000 game.state.chart[w.x][w.y].starbase = True
6001 # Position ordinary Klingon Battle Cruisers
6003 klumper = 0.25*game.skill*(9.0-game.length)+1.0
6004 if klumper > MAXKLQUAD:
6008 klump = (1.0 - r*r)*klumper
6013 w = randplace(GALSIZE)
6014 if not game.state.galaxy[w.x][w.y].supernova and \
6015 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
6017 game.state.galaxy[w.x][w.y].klingons += int(klump)
6020 # Position Klingon Commander Ships
6021 for i in range(1, game.incom+1):
6023 w = randplace(GALSIZE)
6024 if (game.state.galaxy[w.x][w.y].klingons or random.random()>=0.75) and \
6025 not game.state.galaxy[w.x][w.y].supernova and \
6026 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
6027 not w in game.state.kcmdr[:i]:
6029 game.state.galaxy[w.x][w.y].klingons += 1
6030 game.state.kcmdr[i] = w
6031 # Locate planets in galaxy
6032 for i in range(game.inplan):
6034 w = randplace(GALSIZE)
6035 if game.state.galaxy[w.x][w.y].planet == NOPLANET:
6039 new.crystals = "absent"
6040 if (game.options & OPTION_WORLDS) and i < NINHAB:
6041 new.pclass = "M" # All inhabited planets are class M
6042 new.crystals = "absent"
6044 new.name = systnames[i]
6045 new.inhabited = True
6047 new.pclass = ("M", "N", "O")[random.randint(0, 2)]
6048 if random.random()*1.5: # 1 in 3 chance of crystals
6049 new.crystals = "present"
6050 new.known = "unknown"
6051 new.inhabited = False
6052 game.state.galaxy[w.x][w.y].planet = new
6053 game.state.planets.append(new)
6055 for i in range(game.state.nromrem):
6056 w = randplace(GALSIZE)
6057 game.state.galaxy[w.x][w.y].romulans += 1
6058 # Locate the Super Commander
6059 if game.state.nscrem > 0:
6061 w = randplace(GALSIZE)
6062 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
6064 game.state.kscmdr = w
6065 game.state.galaxy[w.x][w.y].klingons += 1
6066 # Place thing (in tournament game, thingx == -1, don't want one!)
6069 thing = randplace(GALSIZE)
6071 game.state.snap = False
6072 if game.skill == SKILL_NOVICE:
6073 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6074 prout(_("a deadly Klingon invasion force. As captain of the United"))
6075 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6076 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6077 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6078 prout(_("your mission. As you proceed you may be given more time."))
6080 prout(_("You will have %d supporting starbases.") % (game.inbase))
6081 proutn(_("Starbase locations- "))
6083 prout(_("Stardate %d.") % int(game.state.date))
6085 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6086 prout(_("An unknown number of Romulans."))
6087 if game.state.nscrem:
6088 prout(_("And one (GULP) Super-Commander."))
6089 prout(_("%d stardates.") % int(game.intime))
6090 proutn(_("%d starbases in ") % game.inbase)
6091 for i in range(game.inbase):
6092 proutn(`game.state.baseq[i]`)
6095 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6096 proutn(_(" Sector %s") % game.sector)
6098 prout(_("Good Luck!"))
6099 if game.state.nscrem:
6100 prout(_(" YOU'LL NEED IT."))
6103 if game.nenhere - (thing == game.quadrant) - game.ithere:
6105 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6108 def choose(needprompt):
6109 # choose your game type
6114 game.skill = SKILL_NONE
6116 if needprompt: # Can start with command line options
6117 proutn(_("Would you like a regular, tournament, or saved game? "))
6119 if len(citem)==0: # Try again
6121 if isit("tournament"):
6122 while scan() == IHEOL:
6123 proutn(_("Type in tournament number-"))
6126 continue # We don't want a blank entry
6127 game.tourn = int(aaitem)
6130 if isit("saved") or isit("frozen"):
6134 if game.passwd == None:
6136 if not game.alldone:
6137 game.thawed = True # No plaque if not finished
6143 proutn(_("What is \"%s\"?"), citem)
6145 while game.length==0 or game.skill==SKILL_NONE:
6146 if scan() == IHALPHA:
6149 elif isit("medium"):
6153 elif isit("novice"):
6154 game.skill = SKILL_NOVICE
6156 game.skill = SKILL_FAIR
6158 game.skill = SKILL_GOOD
6159 elif isit("expert"):
6160 game.skill = SKILL_EXPERT
6161 elif isit("emeritus"):
6162 game.skill = SKILL_EMERITUS
6164 proutn(_("What is \""))
6170 proutn(_("Would you like a Short, Medium, or Long game? "))
6171 elif game.skill == SKILL_NONE:
6172 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6173 # Choose game options -- added by ESR for SST2K
6174 if scan() != IHALPHA:
6176 proutn(_("Choose your game style (or just press enter): "))
6179 # Approximates the UT FORTRAN version.
6180 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6181 game.options |= OPTION_PLAIN
6183 # Approximates Tom Almy's version.
6184 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6185 game.options |= OPTION_ALMY
6189 proutn(_("What is \"%s\"?") % citem)
6191 if game.passwd == "debug":
6193 fputs("=== Debug mode enabled\n", sys.stdout)
6195 # Use parameters to generate initial values of things
6196 game.damfac = 0.5 * game.skill
6197 game.state.rembase = random.randint(BASEMIN, BASEMAX)
6198 game.inbase = game.state.rembase
6200 if game.options & OPTION_PLANETS:
6201 game.inplan += int((MAXUNINHAB/2) + (MAXUNINHAB/2+1)*random.random())
6202 if game.options & OPTION_WORLDS:
6203 game.inplan += int(NINHAB)
6204 game.state.nromrem = game.inrom = int((2.0+random.random())*game.skill)
6205 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6206 game.state.remtime = 7.0 * game.length
6207 game.intime = game.state.remtime
6208 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*random.random())*game.skill*0.1+.15)
6209 game.incom = int(game.skill + 0.0625*game.inkling*random.random())
6210 game.state.remcom = min(10, game.incom)
6211 game.incom = game.state.remcom
6212 game.state.remres = (game.inkling+4*game.incom)*game.intime
6213 game.inresor = game.state.remres
6214 if game.inkling > 50:
6215 game.state.rembase += 1
6216 game.inbase = game.state.rembase
6220 # drop a feature on a random dot in the current quadrant
6223 w = randplace(QUADSIZE)
6224 if game.quad[w.x][w.y] == IHDOT:
6226 game.quad[w.x][w.y] = iquad
6230 # update our alert status
6231 game.condition = "green"
6232 if game.energy < 1000.0:
6233 game.condition = "yellow"
6234 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6235 game.condition = "red"
6237 game.condition="dead"
6240 # drop new Klingon into current quadrant
6243 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6244 game.kpower[i] = random.random()*150.0 +300.0 +25.0*game.skill
6248 # set up a new state of quadrant, for when we enter or re-enter it
6252 game.comhere = False
6258 game.inorbit = False
6260 game.ientesc = False
6264 game.iseenit = False
6266 # Attempt to escape Super-commander, so tbeam back!
6269 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6270 # cope with supernova
6273 game.klhere = q.klingons
6274 game.irhere = q.romulans
6275 game.nenhere = game.klhere + game.irhere
6278 game.quad[game.sector.x][game.sector.y] = game.ship
6281 w.x = w.y = 0 # quiet a gcc warning
6282 # Position ordinary Klingons
6283 for i in range(game.klhere):
6285 # If we need a commander, promote a Klingon
6286 for i in range(game.state.remcom):
6287 if game.state.kcmdr[i] == game.quadrant:
6290 if i <= game.state.remcom:
6291 game.quad[w.x][w.y] = IHC
6292 game.kpower[game.klhere] = 950.0+400.0*random.random()+50.0*game.skill
6295 # If we need a super-commander, promote a Klingon
6296 if same(game.quadrant, game.state.kscmdr):
6297 game.quad[game.ks[0].x][game.ks[0].y] = IHS
6298 game.kpower[1] = 1175.0 + 400.0*random.random() + 125.0*game.skill
6299 game.iscate = (game.state.remkl > 1)
6301 # Put in Romulans if needed
6302 for i in range(game.klhere, game.nenhere):
6305 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6306 game.kpower[i] = random.random()*400.0 + 450.0 + 50.0*game.skill
6307 # If quadrant needs a starbase, put it in
6309 game.base = dropin(IHB)
6311 # If quadrant needs a planet, put it in
6312 if q.planet != NOPLANET:
6313 game.iplnet = q.planet
6314 if not q.planet.inhabited:
6315 game.plnet = dropin(IHP)
6317 game.plnet = dropin(IHW)
6318 # Check for condition
6320 # And finally the stars
6321 for i in range(q.stars):
6325 if game.irhere > 0 and game.klhere == 0:
6327 if not damaged(DRADIO):
6329 prout(_("LT. Uhura- \"Captain, an urgent message."))
6330 prout(_(" I'll put it on audio.\" CLICK"))
6332 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6333 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6336 # Put in THING if needed
6338 if thing == game.quadrant:
6340 thing = randplace(GALSIZE)
6342 game.ks[game.nenhere] = w
6343 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6344 distance(game.sector, w)
6345 game.kpower[game.nenhere] = random.random()*6000.0 +500.0 +250.0*game.skill
6346 if not damaged(DSRSENS):
6348 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6349 prout(_(" Please examine your short-range scan.\""))
6351 # Decide if quadrant needs a Tholian; lighten up if skill is low
6352 if game.options & OPTION_THOLIAN:
6353 if (game.skill < SKILL_GOOD and random.random() <= 0.02) or \
6354 (game.skill == SKILL_GOOD and random.random() <= 0.05) or \
6355 (game.skill > SKILL_GOOD and random.random() <= 0.08):
6357 game.tholian.x = random.choice((0, QUADSIZE-1))
6358 game.tholian.y = random.choice((0, QUADSIZE-1))
6359 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6361 game.quad[game.tholian.x][game.tholian.y] = IHT
6364 game.ks[game.nenhere] = game.tholian
6365 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6366 distance(game.sector, game.tholian)
6367 game.kpower[game.nenhere] = random.random()*400.0 +100.0 +25.0*game.skill
6368 # Reserve unoccupied corners
6369 if game.quad[0][0]==IHDOT:
6370 game.quad[0][0] = 'X'
6371 if game.quad[0][QUADSIZE-1]==IHDOT:
6372 game.quad[0][QUADSIZE-1] = 'X'
6373 if game.quad[QUADSIZE-1][0]==IHDOT:
6374 game.quad[QUADSIZE-1][0] = 'X'
6375 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6376 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6379 # Put in a few black holes
6380 for i in range(1, 3+1):
6381 if random.random() > 0.5:
6384 # Take out X's in corners if Tholian present
6386 if game.quad[0][0]=='X':
6387 game.quad[0][0] = IHDOT
6388 if game.quad[0][QUADSIZE-1]=='X':
6389 game.quad[0][QUADSIZE-1] = IHDOT
6390 if game.quad[QUADSIZE-1][0]=='X':
6391 game.quad[QUADSIZE-1][0] = IHDOT
6392 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6393 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6396 # sort Klingons by distance from us
6397 # The author liked bubble sort. So we will use it. :-(
6398 if game.nenhere-(thing==game.quadrant)-game.ithere < 2:
6402 for j in range(game.nenhere):
6403 if game.kdist[j] > game.kdist[j+1]:
6406 game.kdist[j] = game.kdist[j+1]
6409 game.kavgd[j] = game.kavgd[j+1]
6412 game.ks[j].x = game.ks[j+1].x
6415 game.ks[j].y = game.ks[j+1].y
6418 game.kpower[j] = game.kpower[j+1]
6419 game.kpower[j+1] = t
6424 # set the self-destruct password
6425 if game.options & OPTION_PLAIN:
6428 proutn(_("Please type in a secret password- "))
6431 if game.passwd != None:
6436 game.passwd += chr(97+int(random.random()*25))
6438 # Code from sst.c begins here
6441 "SRSCAN": OPTION_TTY,
6442 "STATUS": OPTION_TTY,
6443 "REQUEST": OPTION_TTY,
6444 "LRSCAN": OPTION_TTY,
6457 "SENSORS": OPTION_PLANETS,
6458 "ORBIT": OPTION_PLANETS,
6459 "TRANSPORT": OPTION_PLANETS,
6460 "MINE": OPTION_PLANETS,
6461 "CRYSTALS": OPTION_PLANETS,
6462 "SHUTTLE": OPTION_PLANETS,
6463 "PLANETS": OPTION_PLANETS,
6468 "PROBE": OPTION_PROBE,
6470 "FREEZE": 0, # Synonym for SAVE
6476 "SOS": 0, # Synonym for MAYDAY
6477 "CALL": 0, # Synonym for MAYDAY
6484 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6487 # generate a list of legal commands
6489 proutn(_("LEGAL COMMANDS ARE:"))
6490 for key in commands:
6494 proutn("%-12s " % key)
6499 # browse on-line help
6500 # Give help on commands
6504 setwnd(prompt_window)
6505 proutn(_("Help on what command? "))
6507 setwnd(message_window)
6510 if citem in commands or citem == "ABBREV":
6519 fp = open(SSTDOC, "r")
6522 fp = open(DOC_NAME, "r")
6524 prout(_("Spock- \"Captain, that information is missing from the"))
6525 proutn(_(" computer. You need to find "))
6527 prout(_(" and put it in the"))
6528 proutn(_(" current directory or to "))
6532 # This used to continue: "You need to find SST.DOC and put
6533 # it in the current directory."
6537 linebuf = fp.readline()
6539 prout(_("Spock- \"Captain, there is no information on that command.\""))
6542 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6543 linebuf = linebuf[3:].strip()
6547 prout(_("Spock- \"Captain, I've found the following information:\""))
6549 while linebuf in fp:
6550 if "******" in linebuf:
6556 # command-interpretation loop
6559 setwnd(message_window)
6560 while True: # command loop
6562 while True: # get a command
6568 setwnd(prompt_window)
6572 if game.options & OPTION_CURSES:
6577 setwnd(message_window)
6579 candidates = filter(lambda x: x.startswith(citem.upper()),
6581 if len(candidates) == 1:
6587 if cmd == "SRSCAN": # srscan
6589 elif cmd == "STATUS": # status
6591 elif cmd == "REQUEST": # status request
6593 elif cmd == "LRSCAN": # long range scan
6595 elif cmd == "PHASERS": # phasers
6599 elif cmd == "TORPEDO": # photon torpedos
6603 elif cmd == "MOVE": # move under warp
6605 elif cmd == "SHIELDS": # shields
6609 game.shldchg = False
6610 elif cmd == "DOCK": # dock at starbase
6614 elif cmd == "DAMAGES": # damage reports
6616 elif cmd == "CHART": # chart
6618 elif cmd == "IMPULSE": # impulse
6620 elif cmd == "REST": # rest
6624 elif cmd == "WARP": # warp
6626 elif cmd == "SCORE": # score
6628 elif cmd == "SENSORS": # sensors
6630 elif cmd == "ORBIT": # orbit
6634 elif cmd == "TRANSPORT": # transport "beam"
6636 elif cmd == "MINE": # mine
6640 elif cmd == "CRYSTALS": # crystals
6644 elif cmd == "SHUTTLE": # shuttle
6648 elif cmd == "PLANETS": # Planet list
6650 elif cmd == "REPORT": # Game Report
6652 elif cmd == "COMPUTER": # use COMPUTER!
6654 elif cmd == "COMMANDS":
6656 elif cmd == "EMEXIT": # Emergency exit
6657 clrscr() # Hide screen
6658 freeze(True) # forced save
6659 os.exit(1) # And quick exit
6660 elif cmd == "PROBE":
6661 probe() # Launch probe
6664 elif cmd == "ABANDON": # Abandon Ship
6666 elif cmd == "DESTRUCT": # Self Destruct
6668 elif cmd == "SAVE": # Save Game
6671 if game.skill > SKILL_GOOD:
6672 prout(_("WARNING--Saved games produce no plaques!"))
6673 elif cmd == "DEATHRAY": # Try a desparation measure
6677 elif cmd == "DEBUGCMD": # What do we want for debug???
6679 elif cmd == "MAYDAY": # Call for help
6684 game.alldone = True # quit the game
6687 elif cmd == "SEED": # set random-number seed
6691 #ifdef BSD_BUG_FOR_BUG
6692 # elif cmd == "VISUAL":
6693 # visual() # perform visual scan
6697 break # Game has ended
6698 if game.optime != 0.0:
6701 break # Events did us in
6702 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6705 if hitme and not game.justin:
6709 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6721 if cmd == IHR: s = _("Romulan")
6722 elif cmd == IHK: s = _("Klingon")
6723 elif cmd == IHC: s = _("Commander")
6724 elif cmd == IHS: s = _("Super-commander")
6725 elif cmd == IHSTAR: s = _("Star")
6726 elif cmd == IHP: s = _("Planet")
6727 elif cmd == IHB: s = _("Starbase")
6728 elif cmd == IHBLANK: s = _("Black hole")
6729 elif cmd == IHT: s = _("Tholian")
6730 elif cmd == IHWEB: s = _("Tholian web")
6731 elif cmd == IHQUEST: s = _("Stranger")
6732 elif cmd == IHW: s = _("Inhabited World")
6733 else: s = "Unknown??"
6736 def cramlc(loctype, w):
6738 if loctype == "quadrant":
6739 buf = _("Quadrant ")
6740 elif loctype == "sector":
6742 buf += ("%d - %d" % (w.x, w.y))
6745 def crmena(stars, enemy, loctype, w):
6746 # print an enemy and his location
6751 proutn(cramlc(loctype, w))
6754 # print our ship name
6755 if game.ship == IHE:
6757 elif game.ship == IHF:
6758 s = _("Faerie Queene")
6764 # print a line of stars
6765 prouts("******************************************************")
6769 return -avrage*math.log(1e-7 + random.random())
6771 def randplace(size):
6772 # choose a random location
6774 w.x = random.randint(0, size-1)
6775 w.y = random.randint(0, size-1)
6779 # Demand input for next scan
6784 # return IHEOL next time
6789 # Get a token from the user
6790 global inqueue, line, citem
6794 # Read a line if nothing here
6797 if curwnd==prompt_window:
6799 setwnd(message_window)
6801 # Skip leading white space
6802 line = line.lstrip()
6804 inqueue = line.split()
6810 # From here on in it's all looking at the queue
6811 citem = inqueue.pop(0)
6815 aaitem = float(citem)
6820 citem = citem.lower()
6824 # yes-or-no confirmation
6833 proutn(_("Please answer with \"y\" or \"n\": "))
6836 # complain about unparseable input
6839 prout(_("Beg your pardon, Captain?"))
6842 # compares s to citem and returns true if it matches to the length of s
6843 return s.startswith(citem)
6846 # access to the internals for debugging
6847 proutn("Reset levels? ")
6849 if game.energy < game.inenrg:
6850 game.energy = game.inenrg
6851 game.shield = game.inshld
6852 game.torps = game.intorps
6853 game.lsupres = game.inlsr
6854 proutn("Reset damage? ")
6856 for i in range(NDEVICES):
6857 if game.damage[i] > 0.0:
6858 game.damage[i] = 0.0
6859 proutn("Toggle debug flag? ")
6863 prout("Debug output ON")
6865 prout("Debug output OFF")
6866 proutn("Cause selective damage? ")
6868 for i in range(NDEVICES):
6874 if key == IHALPHA and isit("y"):
6875 game.damage[i] = 10.0
6876 proutn("Examine/change events? ")
6881 FSNOVA: "Supernova ",
6884 FBATTAK: "Base Attack ",
6885 FCDBAS: "Base Destroy ",
6886 FSCMOVE: "SC Move ",
6887 FSCDBAS: "SC Base Destroy ",
6888 FDSPROB: "Probe Move ",
6889 FDISTR: "Distress Call ",
6890 FENSLV: "Enslavement ",
6891 FREPRO: "Klingon Build ",
6893 for i in range(1, NEVENTS):
6896 proutn("%.2f" % (scheduled(i)-game.state.date))
6897 if i == FENSLV or i == FREPRO:
6899 proutn(" in %s" % ev.quadrant)
6909 ev = schedule(i, aaitem)
6910 if i == FENSLV or i == FREPRO:
6912 proutn("In quadrant- ")
6914 # IHEOL says to leave coordinates as they are
6917 prout("Event %d canceled, no x coordinate." % (i))
6923 prout("Event %d canceled, no y coordinate." % (i))
6929 proutn("Induce supernova here? ")
6931 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6934 if __name__ == '__main__':
6935 global line, thing, game, idebug, iqengry
6936 game = citem = aaitem = inqueue = None
6943 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY)
6944 # Disable curses mode until the game logic is working.
6945 # if os.getenv("TERM"):
6946 # game.options |= OPTION_CURSES | OPTION_SHOWME
6948 game.options |= OPTION_TTY
6951 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6952 for (switch, val) in options:
6955 replayfp = open(optarg, "r")
6957 sys.stderr.write("sst: can't open replay file %s\n" % optarg)
6959 line = replayfp.readline().strip()
6961 (key, seed) = line.split()
6964 sys.stderr.write("sst: replay file %s is ill-formed\n"%optarg)
6966 game.options |= OPTION_TTY
6967 game.options &=~ OPTION_CURSES
6968 elif switch == '-t':
6969 game.options |= OPTION_TTY
6970 game.options &=~ OPTION_CURSES
6971 elif switch == '-x':
6974 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6976 # where to save the input in case of bugs
6978 logfp = open("/usr/tmp/sst-input.log", "w")
6980 sys.stderr.write("sst: warning, can't open logfile\n")
6983 logfp.write("seed %d\n" % (seed))
6992 while True: # Play a game
6993 setwnd(fullscreen_window)
6996 setup(needprompt=not inqueue)
6999 game.alldone = False
7006 if game.tourn and game.alldone:
7007 proutn(_("Do you want your score recorded?"))
7011 proutn(_("Do you want to play again? "))
7015 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))