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 iqhere 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:
1740 global iqhere, iqengry
1741 iqhere = iqengry = False
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)
3715 def commandhook(cmd, before):
3719 # Things past this point have policy implications.
3723 "Hook to be called after moving to redraw maps."
3724 if game.options & OPTION_CURSES:
3727 setwnd(srscan_window)
3731 setwnd(status_window)
3732 status_window.clear()
3733 status_window.move(0, 0)
3734 setwnd(report_window)
3735 report_window.clear()
3736 report_window.move(0, 0)
3738 setwnd(lrscan_window)
3739 lrscan_window.clear()
3740 lrscan_window.move(0, 0)
3743 def put_srscan_sym(w, sym):
3744 "Emit symbol for short-range scan."
3745 srscan_window.move(w.x+1, w.y*2+2)
3746 srscan_window.addch(sym)
3747 srscan_window.refresh()
3750 "Enemy fall down, go boom."
3751 if game.options & OPTION_CURSES:
3753 setwnd(srscan_window)
3754 srscan_window.attron(curses.A_REVERSE)
3755 put_srscan_sym(w, game.quad[w.x][w.y])
3759 srscan_window.attroff(curses.A_REVERSE)
3760 put_srscan_sym(w, game.quad[w.x][w.y])
3761 curses.delay_output(500)
3762 setwnd(message_window)
3765 "Sound and visual effects for teleportation."
3766 if game.options & OPTION_CURSES:
3768 setwnd(message_window)
3770 prouts(" . . . . . ")
3771 if game.options & OPTION_CURSES:
3772 #curses.delay_output(1000)
3776 def tracktorpedo(w, l, i, n, iquad):
3777 "Torpedo-track animation."
3778 if not game.options & OPTION_CURSES:
3782 proutn(_("Track for torpedo number %d- ") % i)
3785 proutn(_("Torpedo track- "))
3788 proutn("%d - %d " % (w.x, w.y))
3790 if not damaged(DSRSENS) or game.condition=="docked":
3791 if i != 1 and l == 1:
3793 curses.delay_output(400)
3794 if (iquad==IHDOT) or (iquad==IHBLANK):
3795 put_srscan_sym(w, '+')
3797 #curses.delay_output(100)
3799 put_srscan_sym(w, iquad)
3801 curwnd.attron(curses.A_REVERSE)
3802 put_srscan_sym(w, iquad)
3804 #curses.delay_output(1000)
3806 curwnd.attroff(curses.A_REVERSE)
3807 put_srscan_sym(w, iquad)
3809 proutn("%d - %d " % (w.x, w.y))
3812 "Display the current galaxy chart."
3813 if game.options & OPTION_CURSES:
3814 setwnd(message_window)
3815 message_window.clear()
3817 if game.options & OPTION_TTY:
3822 def prstat(txt, data):
3824 if game.options & OPTION_CURSES:
3826 setwnd(status_window)
3828 proutn(" " * NSYM - len(tx))
3831 if game.options & OPTION_CURSES:
3832 setwnd(report_window)
3834 # Code from moving.c begins here
3836 def imove(novapush):
3837 # movement execution for warp, impulse, supernova, and tractor-beam events
3838 w = coord(); final = coord()
3841 def no_quad_change():
3842 # No quadrant change -- compute new avg enemy distances
3843 game.quad[game.sector.x][game.sector.y] = game.ship
3845 for m in range(game.nenhere):
3846 finald = distance(w, game.ks[m])
3847 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3848 game.kdist[m] = finald
3850 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3852 for m in range(game.nenhere):
3853 game.kavgd[m] = game.kdist[m]
3856 setwnd(message_window)
3860 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3861 game.inorbit = False
3863 angle = ((15.0 - game.direc) * 0.5235988)
3864 deltax = -math.sin(angle)
3865 deltay = math.cos(angle)
3866 if math.fabs(deltax) > math.fabs(deltay):
3867 bigger = math.fabs(deltax)
3869 bigger = math.fabs(deltay)
3874 # If tractor beam is to occur, don't move full distance
3875 if game.state.date+game.optime >= scheduled(FTBEAM):
3877 game.condition = "red"
3878 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3879 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3880 # Move within the quadrant
3881 game.quad[game.sector.x][game.sector.y] = IHDOT
3884 n = 10.0*game.dist*bigger+0.5
3887 for m in range(1, n+1):
3892 if not VALID_SECTOR(w.x, w.y):
3893 # Leaving quadrant -- allow final enemy attack
3894 # Don't do it if being pushed by Nova
3895 if game.nenhere != 0 and not novapush:
3897 for m in range(game.nenhere):
3898 finald = distance(w, game.ks[m])
3899 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
3901 # Stas Sergeev added the condition
3902 # that attacks only happen if Klingons
3903 # are present and your skill is good.
3905 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3909 # compute final position -- new quadrant and sector
3910 x = QUADSIZE*(game.quadrant.x-1)+game.sector.x
3911 y = QUADSIZE*(game.quadrant.y-1)+game.sector.y
3912 w.x = x+10.0*game.dist*bigger*deltax+0.5
3913 w.y = y+10.0*game.dist*bigger*deltay+0.5
3914 # check for edge of galaxy
3924 if w.x > GALSIZE*QUADSIZE:
3925 w.x = (GALSIZE*QUADSIZE*2)+1 - w.x
3927 if w.y > GALSIZE*QUADSIZE:
3928 w.y = (GALSIZE*QUADSIZE*2)+1 - w.y
3937 if game.nkinks == 3:
3938 # Three strikes -- you're out!
3942 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3943 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3944 prout(_("YOU WILL BE DESTROYED."))
3945 # Compute final position in new quadrant
3946 if trbeam: # Don't bother if we are to be beamed
3948 game.quadrant.x = (w.x+(QUADSIZE-1))/QUADSIZE
3949 game.quadrant.y = (w.y+(QUADSIZE-1))/QUADSIZE
3950 game.sector.x = w.x - QUADSIZE*(game.quadrant.x-1)
3951 game.sector.y = w.y - QUADSIZE*(game.quadrant.y-1)
3953 prout(_("Entering Quadrant %s.") % game.quadrant)
3954 game.quad[game.sector.x][game.sector.y] = game.ship
3956 if game.skill>SKILL_NOVICE:
3959 iquad = game.quad[w.x][w.y]
3961 # object encountered in flight path
3962 stopegy = 50.0*game.dist/game.optime
3963 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3964 if iquad in (IHT. IHK, OHC, IHS, IHR, IHQUEST):
3966 ram(False, iquad, game.sector)
3968 elif iquad == IHBLANK:
3970 prouts(_("***RED ALERT! RED ALERT!"))
3974 proutn(_(" pulled into black hole at Sector %s") % w)
3976 # Getting pulled into a black hole was certain
3977 # death in Almy's original. Stas Sergeev added a
3978 # possibility that you'll get timewarped instead.
3981 for m in range(NDEVICES):
3982 if game.damage[m]>0:
3984 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3985 if (game.options & OPTION_BLKHOLE) and random.random()>probf:
3995 proutn(_(" encounters Tholian web at %s;") % w)
3997 proutn(_(" blocked by object at %s;") % w)
3998 proutn(_("Emergency stop required "))
3999 prout(_("%2d units of energy.") % int(stopegy))
4000 game.energy -= stopegy
4001 final.x = x-deltax+0.5
4002 final.y = y-deltay+0.5
4004 if game.energy <= 0:
4010 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4017 # dock our ship at a starbase
4019 if game.condition == "docked" and verbose:
4020 prout(_("Already docked."))
4023 prout(_("You must first leave standard orbit."))
4025 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4027 prout(_(" not adjacent to base."))
4029 game.condition = "docked"
4033 if game.energy < game.inenrg:
4034 game.energy = game.inenrg
4035 game.shield = game.inshld
4036 game.torps = game.intorps
4037 game.lsupres = game.inlsr
4038 game.state.crew = FULLCREW
4039 if not damaged(DRADIO) and \
4040 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4041 # get attack report from base
4042 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4047 # This program originally required input in terms of a (clock)
4048 # direction and distance. Somewhere in history, it was changed to
4049 # cartesian coordinates. So we need to convert. Probably
4050 # "manual" input should still be done this way -- it's a real
4051 # pain if the computer isn't working! Manual mode is still confusing
4052 # because it involves giving x and y motions, yet the coordinates
4053 # are always displayed y - x, where +y is downward!
4056 def getcd(isprobe, akey):
4057 # get course and distance
4058 irowq=game.quadrant.x; icolq=game.quadrant.y; key=0
4059 navmode = "unspecified"
4064 # Get course direction and distance. If user types bad values, return
4065 # with DIREC = -1.0.
4068 if game.landed and not isprobe:
4069 prout(_("Dummy! You can't leave standard orbit until you"))
4070 proutn(_("are back aboard the ship."))
4073 while navmode == "unspecified":
4074 if damaged(DNAVSYS):
4076 prout(_("Computer damaged; manual navigation only"))
4078 prout(_("Computer damaged; manual movement only"))
4083 if isprobe and akey != -1:
4084 # For probe launch, use pre-scanned value first time
4091 proutn(_("Manual or automatic- "))
4094 elif key == IHALPHA:
4099 elif isit("automatic"):
4100 navmode = "automatic"
4109 prout(_("(Manual navigation assumed.)"))
4111 prout(_("(Manual movement assumed.)"))
4115 if navmode == "automatic":
4118 proutn(_("Target quadrant or quadrant§or- "))
4120 proutn(_("Destination sector or quadrant§or- "))
4128 xi = int(aaitem-0.05)
4133 xj = int(aaitem-0.5)
4136 # both quadrant and sector specified
4150 # only quadrant specified -- go to center of dest quad
4158 if not VALID_QUADRANT(icolq,irowq) or not VALID_SECTOR(incr.x,incr.y):
4165 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % incr)
4167 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4168 deltax = icolq - game.quadrant.y + 0.1*(incr.x-game.sector.y)
4169 deltay = game.quadrant.x - irowq + 0.1*(game.sector.x-incr.y)
4172 proutn(_("X and Y displacements- "))
4186 # Check for zero movement
4187 if deltax == 0 and deltay == 0:
4190 if itemp == "verbose" and not isprobe:
4192 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4193 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4194 game.direc = math.atan2(deltax, deltay)*1.90985932
4195 if game.direc < 0.0:
4201 # move under impulse power
4203 if damaged(DIMPULS):
4206 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4208 if game.energy > 30.0:
4210 if game.direc == -1.0:
4212 power = 20.0 + 100.0*game.dist
4216 if power >= game.energy:
4217 # Insufficient power for trip
4219 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4220 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4221 if game.energy > 30:
4222 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4223 int(0.01 * (game.energy-20.0)-0.05))
4224 prout(_(" quadrants.\""))
4226 prout(_("quadrant. They are, therefore, useless.\""))
4229 # Make sure enough time is left for the trip
4230 game.optime = game.dist/0.095
4231 if game.optime >= game.state.remtime:
4232 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4233 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4234 proutn(_("we dare spend the time?\" "))
4237 # Activate impulse engines and pay the cost
4242 power = 20.0 + 100.0*game.dist
4243 game.energy -= power
4244 game.optime = game.dist/0.095
4245 if game.energy <= 0:
4250 # move under warp drive
4251 blooey = False; twarp = False
4252 if not timewarp: # Not WARPX entry
4254 if game.damage[DWARPEN] > 10.0:
4257 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4259 if damaged(DWARPEN) and game.warpfac > 4.0:
4262 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4263 prout(_(" is repaired, I can only give you warp 4.\""))
4266 # Read in course and distance
4268 if game.direc == -1.0:
4271 # Make sure starship has enough energy for the trip
4272 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4273 if power >= game.energy:
4274 # Insufficient power for trip
4277 prout(_("Engineering to bridge--"))
4278 if not game.shldup or 0.5*power > game.energy:
4279 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4281 prout(_("We can't do it, Captain. We don't have enough energy."))
4283 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4286 prout(_("if you'll lower the shields."))
4290 prout(_("We haven't the energy to go that far with the shields up."))
4293 # Make sure enough time is left for the trip
4294 game.optime = 10.0*game.dist/game.wfacsq
4295 if game.optime >= 0.8*game.state.remtime:
4297 prout(_("First Officer Spock- \"Captain, I compute that such"))
4298 proutn(_(" a trip would require approximately %2.0f") %
4299 (100.0*game.optime/game.state.remtime))
4300 prout(_(" percent of our"))
4301 proutn(_(" remaining time. Are you sure this is wise?\" "))
4307 if game.warpfac > 6.0:
4308 # Decide if engine damage will occur
4309 prob = game.dist*(6.0-game.warpfac)*(6.0-game.warpfac)/66.666666666
4310 if prob > random.random():
4312 game.dist = random.random()*game.dist
4313 # Decide if time warp will occur
4314 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > random.random():
4316 if idebug and game.warpfac==10 and not twarp:
4318 proutn("=== Force time warp? ")
4322 # If time warp or engine damage, check path
4323 # If it is obstructed, don't do warp or damage
4324 angle = ((15.0-game.direc)*0.5235998)
4325 deltax = -math.sin(angle)
4326 deltay = math.cos(angle)
4327 if math.fabs(deltax) > math.fabs(deltay):
4328 bigger = math.fabs(deltax)
4330 bigger = math.fabs(deltay)
4334 n = 10.0 * game.dist * bigger +0.5
4337 for l in range(1, n+1):
4342 if not VALID_SECTOR(ix, iy):
4344 if game.quad[ix][iy] != IHDOT:
4349 # Activate Warp Engines and pay the cost
4353 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4354 if game.energy <= 0:
4356 game.optime = 10.0*game.dist/game.wfacsq
4360 game.damage[DWARPEN] = game.damfac*(3.0*random.random()+1.0)
4362 prout(_("Engineering to bridge--"))
4363 prout(_(" Scott here. The warp engines are damaged."))
4364 prout(_(" We'll have to reduce speed to warp 4."))
4369 # change the warp factor
4375 proutn(_("Warp factor- "))
4380 if game.damage[DWARPEN] > 10.0:
4381 prout(_("Warp engines inoperative."))
4383 if damaged(DWARPEN) and aaitem > 4.0:
4384 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4385 prout(_(" but right now we can only go warp 4.\""))
4388 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4391 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4393 oldfac = game.warpfac
4394 game.warpfac = aaitem
4395 game.wfacsq=game.warpfac*game.warpfac
4396 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4397 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4400 if game.warpfac < 8.00:
4401 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4403 if game.warpfac == 10.0:
4404 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4406 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4410 # cope with being tossed out of quadrant by supernova or yanked by beam
4413 # is captain on planet?
4415 if damaged(DTRANSP):
4418 prout(_("Scotty rushes to the transporter controls."))
4420 prout(_("But with the shields up it's hopeless."))
4422 prouts(_("His desperate attempt to rescue you . . ."))
4423 if random.random() <= 0.5:
4427 prout(_("SUCCEEDS!"))
4430 proutn(_("The crystals mined were "))
4431 if random.random() <= 0.25:
4439 # Check to see if captain in shuttle craft
4445 # Inform captain of attempt to reach safety
4449 prouts(_("***RED ALERT! RED ALERT!"))
4453 prout(_(" has stopped in a quadrant containing"))
4454 prouts(_(" a supernova."))
4456 proutn(_("***Emergency automatic override attempts to hurl "))
4459 prout(_("safely out of quadrant."))
4460 if not damaged(DRADIO):
4461 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4462 # Try to use warp engines
4463 if damaged(DWARPEN):
4465 prout(_("Warp engines damaged."))
4468 game.warpfac = 6.0+2.0*random.random()
4469 game.wfacsq = game.warpfac * game.warpfac
4470 prout(_("Warp factor set to %d") % int(game.warpfac))
4471 power = 0.75*game.energy
4472 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4473 distreq = 1.4142+random.random()
4474 if distreq < game.dist:
4476 game.optime = 10.0*game.dist/game.wfacsq
4477 game.direc = 12.0*random.random() # How dumb!
4479 game.inorbit = False
4482 # This is bad news, we didn't leave quadrant.
4486 prout(_("Insufficient energy to leave quadrant."))
4489 # Repeat if another snova
4490 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4492 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4493 finish(FWON) # Snova killed remaining enemy.
4496 # let's do the time warp again
4497 prout(_("***TIME WARP ENTERED."))
4498 if game.state.snap and random.random() < 0.5:
4500 prout(_("You are traveling backwards in time %d stardates.") %
4501 int(game.state.date-game.snapsht.date))
4502 game.state = game.snapsht
4503 game.state.snap = False
4504 if game.state.remcom:
4505 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4506 schedule(FBATTAK, expran(0.3*game.intime))
4507 schedule(FSNOVA, expran(0.5*game.intime))
4508 # next snapshot will be sooner
4509 schedule(FSNAP, expran(0.25*game.state.remtime))
4511 if game.state.nscrem:
4512 schedule(FSCMOVE, 0.2777)
4516 invalidate(game.battle)
4518 # Make sure Galileo is consistant -- Snapshot may have been taken
4519 # when on planet, which would give us two Galileos!
4521 for l in range(game.inplan):
4522 if game.state.planets[l].known == "shuttle_down":
4524 if game.iscraft == "onship" and game.ship==IHE:
4525 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4526 game.iscraft = "offship"
4527 # Likewise, if in the original time the Galileo was abandoned, but
4528 # was on ship earlier, it would have vanished -- let's restore it.
4529 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4530 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4531 game.iscraft = "onship"
4533 # * There used to be code to do the actual reconstrction here,
4534 # * but the starchart is now part of the snapshotted galaxy state.
4536 prout(_("Spock has reconstructed a correct star chart from memory"))
4538 # Go forward in time
4539 game.optime = -0.5*game.intime*math.log(random.random())
4540 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4541 # cheat to make sure no tractor beams occur during time warp
4542 postpone(FTBEAM, game.optime)
4543 game.damage[DRADIO] += game.optime
4545 events() # Stas Sergeev added this -- do pending events
4548 # launch deep-space probe
4549 # New code to launch a deep space probe
4550 if game.nprobes == 0:
4553 if game.ship == IHE:
4554 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4556 prout(_("Ye Faerie Queene has no deep space probes."))
4561 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4563 if is_scheduled(FDSPROB):
4566 if damaged(DRADIO) and game.condition != "docked":
4567 prout(_("Spock- \"Records show the previous probe has not yet"))
4568 prout(_(" reached its destination.\""))
4570 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4575 # slow mode, so let Kirk know how many probes there are left
4576 if game.nprobes == 1:
4577 prout(_("1 probe left."))
4579 prout(_("%d probes left") % game.nprobes)
4580 proutn(_("Are you sure you want to fire a probe? "))
4584 game.isarmed = False
4585 if key == IHALPHA and citem == "armed":
4589 proutn(_("Arm NOVAMAX warhead? "))
4592 if game.direc == -1.0:
4595 angle = ((15.0 - game.direc) * 0.5235988)
4596 game.probeinx = -math.sin(angle)
4597 game.probeiny = math.cos(angle)
4598 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4599 bigger = math.fabs(game.probeinx)
4601 bigger = math.fabs(game.probeiny)
4603 game.probeiny /= bigger
4604 game.probeinx /= bigger
4605 game.proben = 10.0*game.dist*bigger +0.5
4606 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4607 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4608 game.probec = game.quadrant
4609 schedule(FDSPROB, 0.01) # Time to move one sector
4610 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4614 # Here's how the mayday code works:
4616 # First, the closest starbase is selected. If there is a a starbase
4617 # in your own quadrant, you are in good shape. This distance takes
4618 # quadrant distances into account only.
4620 # A magic number is computed based on the distance which acts as the
4621 # probability that you will be rematerialized. You get three tries.
4623 # When it is determined that you should be able to be rematerialized
4624 # (i.e., when the probability thing mentioned above comes up
4625 # positive), you are put into that quadrant (anywhere). Then, we try
4626 # to see if there is a spot adjacent to the star- base. If not, you
4627 # can't be rematerialized!!! Otherwise, it drops you there. It only
4628 # tries five times to find a spot to drop you. After that, it's your
4632 # yell for help from nearest starbase
4633 # There's more than one way to move in this game!
4637 # Test for conditions which prevent calling for help
4638 if game.condition == "docked":
4639 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4642 prout(_("Subspace radio damaged."))
4644 if game.state.rembase==0:
4645 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4648 proutn(_("You must be aboard the "))
4652 # OK -- call for help from nearest starbase
4655 # There's one in this quadrant
4656 ddist = distance(game.base, game.sector)
4659 for m in range(game.state.rembase):
4660 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4664 # Since starbase not in quadrant, set up new quadrant
4665 game.quadrant = game.state.baseq[line]
4667 # dematerialize starship
4668 game.quad[game.sector.x][game.sector.y]=IHDOT
4669 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4671 prout(_(" dematerializes."))
4673 for m in range(1, 5+1):
4674 ix = game.base.x+3.0*random.random()-1
4675 iy = game.base.y+3.0*random.random()-1
4676 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4677 # found one -- finish up
4681 if not is_valid(game.sector):
4682 prout(_("You have been lost in space..."))
4683 finish(FMATERIALIZE)
4685 # Give starbase three chances to rematerialize starship
4686 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4687 for m in range(1, 3+1):
4688 if m == 1: proutn(_("1st"))
4689 elif m == 2: proutn(_("2nd"))
4690 elif m == 3: proutn(_("3rd"))
4691 proutn(_(" attempt to re-materialize "))
4693 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4696 if random.random() > probf:
4699 curses.delay_output(500)
4702 game.quad[ix][iy]=IHQUEST
4705 setwnd(message_window)
4706 finish(FMATERIALIZE)
4708 game.quad[ix][iy]=game.ship
4710 prout(_("succeeds."))
4714 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4716 # Abandon Ship (the BSD-Trek description)
4718 # The ship is abandoned. If your current ship is the Faire
4719 # Queene, or if your shuttlecraft is dead, you're out of
4720 # luck. You need the shuttlecraft in order for the captain
4721 # (that's you!!) to escape.
4723 # Your crew can beam to an inhabited starsystem in the
4724 # quadrant, if there is one and if the transporter is working.
4725 # If there is no inhabited starsystem, or if the transporter
4726 # is out, they are left to die in outer space.
4728 # If there are no starbases left, you are captured by the
4729 # Klingons, who torture you mercilessly. However, if there
4730 # is at least one starbase, you are returned to the
4731 # Federation in a prisoner of war exchange. Of course, this
4732 # can't happen unless you have taken some prisoners.
4737 if game.condition=="docked":
4739 prout(_("You cannot abandon Ye Faerie Queene."))
4742 # Must take shuttle craft to exit
4743 if game.damage[DSHUTTL]==-1:
4744 prout(_("Ye Faerie Queene has no shuttle craft."))
4746 if game.damage[DSHUTTL]<0:
4747 prout(_("Shuttle craft now serving Big Macs."))
4749 if game.damage[DSHUTTL]>0:
4750 prout(_("Shuttle craft damaged."))
4753 prout(_("You must be aboard the ship."))
4755 if game.iscraft != "onship":
4756 prout(_("Shuttle craft not currently available."))
4758 # Print abandon ship messages
4760 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4762 prouts(_("***ALL HANDS ABANDON SHIP!"))
4764 prout(_("Captain and crew escape in shuttle craft."))
4765 if game.state.rembase==0:
4766 # Oops! no place to go...
4769 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4771 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4772 prout(_("Remainder of ship's complement beam down"))
4773 prout(_("to nearest habitable planet."))
4774 elif q.planet != NOPLANET and not damaged(DTRANSP):
4775 prout(_("Remainder of ship's complement beam down to %s.") %
4778 prout(_("Entire crew of %d left to die in outer space.") %
4780 game.casual += game.state.crew
4781 game.abandoned += game.state.crew
4783 # If at least one base left, give 'em the Faerie Queene
4785 game.icrystl = False # crystals are lost
4786 game.nprobes = 0 # No probes
4787 prout(_("You are captured by Klingons and released to"))
4788 prout(_("the Federation in a prisoner-of-war exchange."))
4789 nb = random.random()*game.state.rembase+1
4790 # Set up quadrant and position FQ adjacient to base
4791 if not game.quadrant == game.state.baseq[nb]:
4792 game.quadrant = game.state.baseq[nb]
4793 game.sector.x = game.sector.y = 5
4796 # position next to base by trial and error
4797 game.quad[game.sector.x][game.sector.y] = IHDOT
4798 for l in range(QUADSIZE):
4799 game.sector.x = 3.0*random.random() - 1.0 + game.base.x
4800 game.sector.y = 3.0*random.random() - 1.0 + game.base.y
4801 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4802 game.quad[game.sector.x][game.sector.y] == IHDOT:
4805 break # found a spot
4806 game.sector.x=QUADSIZE/2
4807 game.sector.y=QUADSIZE/2
4809 # Get new commission
4810 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4811 game.state.crew = FULLCREW
4812 prout(_("Starfleet puts you in command of another ship,"))
4813 prout(_("the Faerie Queene, which is antiquated but,"))
4814 prout(_("still useable."))
4816 prout(_("The dilithium crystals have been moved."))
4818 game.iscraft = "offship" # Galileo disappears
4820 game.condition="docked"
4821 for l in range(NDEVICES):
4822 game.damage[l] = 0.0
4823 game.damage[DSHUTTL] = -1
4824 game.energy = game.inenrg = 3000.0
4825 game.shield = game.inshld = 1250.0
4826 game.torps = game.intorps = 6
4827 game.lsupres=game.inlsr=3.0
4833 # Code from planets.c begins here.
4836 # abort a lengthy operation if an event interrupts it
4839 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4844 # report on (uninhabited) planets in the galaxy
4848 prout(_("Spock- \"Planet report follows, Captain.\""))
4850 for i in range(game.inplan):
4851 if game.state.planets[i].pclass == destroyed:
4853 if (game.state.planets[i].known != "unknown" \
4854 and not game.state.planets[i].inhabited) \
4857 if idebug and game.state.planets[i].known=="unknown":
4858 proutn("(Unknown) ")
4859 proutn(_("Quadrant %s") % game.state.planets[i].w)
4860 proutn(_(" class "))
4861 proutn(game.state.planets[i].pclass)
4863 if game.state.planets[i].crystals != present:
4865 prout(_("dilithium crystals present."))
4866 if game.state.planets[i].known=="shuttle_down":
4867 prout(_(" Shuttle Craft Galileo on surface."))
4869 prout(_("No information available."))
4872 # enter standard orbit
4876 prout(_("Already in standard orbit."))
4878 if damaged(DWARPEN) and damaged(DIMPULS):
4879 prout(_("Both warp and impulse engines damaged."))
4881 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4883 prout(_(" not adjacent to planet."))
4886 game.optime = 0.02+0.03*random.random()
4887 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4891 game.height = (1400.0+7200.0*random.random())
4892 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4897 # examine planets in this quadrant
4898 if damaged(DSRSENS):
4899 if game.options & OPTION_TTY:
4900 prout(_("Short range sensors damaged."))
4902 if not is_valid(game.plnet):
4903 if game.options & OPTION_TTY:
4904 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4906 if game.state.planets[game.iplnet].known == "unknown":
4907 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4909 prout(_(" Planet at Sector %s is of class %s.") %
4910 (sector,game.plnet, game.state.planets[game.iplnet]))
4911 if game.state.planets[game.iplnet].known=="shuttle_down":
4912 prout(_(" Sensors show Galileo still on surface."))
4913 proutn(_(" Readings indicate"))
4914 if game.state.planets[game.iplnet].crystals != present:
4916 prout(_(" dilithium crystals present.\""))
4917 if game.state.planets[game.iplnet].known == "unknown":
4918 game.state.planets[game.iplnet].known = "known"
4921 # use the transporter
4925 if damaged(DTRANSP):
4926 prout(_("Transporter damaged."))
4927 if not damaged(DSHUTTL) and (game.state.planets[game.iplnet].known=="shuttle_down" or game.iscraft == "onship"):
4929 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4933 if not game.inorbit:
4935 prout(_(" not in standard orbit."))
4938 prout(_("Impossible to transport through shields."))
4940 if game.state.planets[game.iplnet].known=="unknown":
4941 prout(_("Spock- \"Captain, we have no information on this planet"))
4942 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4943 prout(_(" you may not go down.\""))
4945 if not game.landed and game.state.planets[game.iplnet].crystals==absent:
4946 prout(_("Spock- \"Captain, I fail to see the logic in"))
4947 prout(_(" exploring a planet with no dilithium crystals."))
4948 proutn(_(" Are you sure this is wise?\" "))
4952 if not (game.options & OPTION_PLAIN):
4953 nrgneed = 50 * game.skill + game.height / 100.0
4954 if nrgneed > game.energy:
4955 prout(_("Engineering to bridge--"))
4956 prout(_(" Captain, we don't have enough energy for transportation."))
4958 if not game.landed and nrgneed * 2 > game.energy:
4959 prout(_("Engineering to bridge--"))
4960 prout(_(" Captain, we have enough energy only to transport you down to"))
4961 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4962 if game.state.planets[game.iplnet].known == "shuttle_down":
4963 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4964 proutn(_(" Are you sure this is wise?\" "))
4969 # Coming from planet
4970 if game.state.planets[game.iplnet].known=="shuttle_down":
4971 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4975 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4976 prout(_("Landing party assembled, ready to beam up."))
4978 prout(_("Kirk whips out communicator..."))
4979 prouts(_("BEEP BEEP BEEP"))
4981 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4984 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4986 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4988 prout(_("Kirk- \"Energize.\""))
4991 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4993 if random.random() > 0.98:
4994 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4996 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4999 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
5000 game.landed = not game.landed
5001 game.energy -= nrgneed
5003 prout(_("Transport complete."))
5004 if game.landed and game.state.planets[game.iplnet].known=="shuttle_down":
5005 prout(_("The shuttle craft Galileo is here!"))
5006 if not game.landed and game.imine:
5013 # strip-mine a world for dilithium
5017 prout(_("Mining party not on planet."))
5019 if game.state.planets[game.iplnet].crystals == mined:
5020 prout(_("This planet has already been strip-mined for dilithium."))
5022 elif game.state.planets[game.iplnet].crystals == absent:
5023 prout(_("No dilithium crystals on this planet."))
5026 prout(_("You've already mined enough crystals for this trip."))
5028 if game.icrystl and game.cryprob == 0.05:
5029 proutn(_("With all those fresh crystals aboard the "))
5032 prout(_("there's no reason to mine more at this time."))
5034 game.optime = (0.1+0.2*random.random())*game.state.planets[game.iplnet].pclass
5037 prout(_("Mining operation complete."))
5038 game.state.planets[game.iplnet].crystals = mined
5039 game.imine = game.ididit = True
5042 # use dilithium crystals
5046 if not game.icrystl:
5047 prout(_("No dilithium crystals available."))
5049 if game.energy >= 1000:
5050 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5051 prout(_(" except when Condition Yellow exists."))
5053 prout(_("Spock- \"Captain, I must warn you that loading"))
5054 prout(_(" raw dilithium crystals into the ship's power"))
5055 prout(_(" system may risk a severe explosion."))
5056 proutn(_(" Are you sure this is wise?\" "))
5061 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5062 prout(_(" Mr. Spock and I will try it.\""))
5064 prout(_("Spock- \"Crystals in place, Sir."))
5065 prout(_(" Ready to activate circuit.\""))
5067 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5069 if random.random() <= game.cryprob:
5070 prouts(_(" \"Activating now! - - No good! It's***"))
5072 prouts(_("***RED ALERT! RED A*L********************************"))
5075 prouts(_("****************** KA-BOOM!!!! *******************"))
5079 game.energy += 5000.0*(1.0 + 0.9*random.random())
5080 prouts(_(" \"Activating now! - - "))
5081 prout(_("The instruments"))
5082 prout(_(" are going crazy, but I think it's"))
5083 prout(_(" going to work!! Congratulations, Sir!\""))
5088 # use shuttlecraft for planetary jaunt
5091 if damaged(DSHUTTL):
5092 if game.damage[DSHUTTL] == -1.0:
5093 if game.inorbit and game.state.planets[game.iplnet].known == "shuttle_down":
5094 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5096 prout(_("Ye Faerie Queene had no shuttle craft."))
5097 elif game.damage[DSHUTTL] > 0:
5098 prout(_("The Galileo is damaged."))
5099 else: # game.damage[DSHUTTL] < 0
5100 prout(_("Shuttle craft is now serving Big Macs."))
5102 if not game.inorbit:
5104 prout(_(" not in standard orbit."))
5106 if (game.state.planets[game.iplnet].known != "shuttle_down") and game.iscraft != "onship":
5107 prout(_("Shuttle craft not currently available."))
5109 if not game.landed and game.state.planets[game.iplnet].known=="shuttle_down":
5110 prout(_("You will have to beam down to retrieve the shuttle craft."))
5112 if game.shldup or game.condition == "docked":
5113 prout(_("Shuttle craft cannot pass through shields."))
5115 if game.state.planets[game.iplnet].known=="unknown":
5116 prout(_("Spock- \"Captain, we have no information on this planet"))
5117 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5118 prout(_(" you may not fly down.\""))
5120 game.optime = 3.0e-5*game.height
5121 if game.optime >= 0.8*game.state.remtime:
5122 prout(_("First Officer Spock- \"Captain, I compute that such"))
5123 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5124 int(100*game.optime/game.state.remtime))
5125 prout(_("remaining time."))
5126 proutn(_("Are you sure this is wise?\" "))
5132 if game.iscraft == "onship":
5134 if not damaged(DTRANSP):
5135 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5139 proutn(_("Shuttle crew"))
5141 proutn(_("Rescue party"))
5142 prout(_(" boards Galileo and swoops toward planet surface."))
5143 game.iscraft = "offship"
5147 game.state.planets[game.iplnet].known="shuttle_down"
5148 prout(_("Trip complete."))
5151 # Ready to go back to ship
5152 prout(_("You and your mining party board the"))
5153 prout(_("shuttle craft for the trip back to the Enterprise."))
5155 prouts(_("The short hop begins . . ."))
5157 game.state.planets[game.iplnet].known="known"
5163 game.iscraft = "onship"
5169 prout(_("Trip complete."))
5174 prout(_("Mining party assembles in the hangar deck,"))
5175 prout(_("ready to board the shuttle craft \"Galileo\"."))
5177 prouts(_("The hangar doors open; the trip begins."))
5180 game.iscraft = "offship"
5183 game.state.planets[game.iplnet].known = "shuttle_down"
5186 prout(_("Trip complete."))
5190 # use the big zapper
5196 if game.ship != IHE:
5197 prout(_("Ye Faerie Queene has no death ray."))
5200 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5203 prout(_("Death Ray is damaged."))
5205 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5206 prout(_(" is highly unpredictible. Considering the alternatives,"))
5207 proutn(_(" are you sure this is wise?\" "))
5210 prout(_("Spock- \"Acknowledged.\""))
5213 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5215 prout(_("Crew scrambles in emergency preparation."))
5216 prout(_("Spock and Scotty ready the death ray and"))
5217 prout(_("prepare to channel all ship's power to the device."))
5219 prout(_("Spock- \"Preparations complete, sir.\""))
5220 prout(_("Kirk- \"Engage!\""))
5222 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5225 if game.options & OPTION_PLAIN:
5228 prouts(_("Sulu- \"Captain! It's working!\""))
5230 while game.nenhere > 0:
5231 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5232 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5233 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5235 if (game.options & OPTION_PLAIN) == 0:
5236 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5237 if random.random() <= 0.05:
5238 prout(_(" is still operational.\""))
5240 prout(_(" has been rendered nonfunctional.\""))
5241 game.damage[DDRAY] = 39.95
5243 r = random.random() # Pick failure method
5245 prouts(_("Sulu- \"Captain! It's working!\""))
5247 prouts(_("***RED ALERT! RED ALERT!"))
5249 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5251 prouts(_("***RED ALERT! RED A*L********************************"))
5254 prouts(_("****************** KA-BOOM!!!! *******************"))
5259 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5261 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5263 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5264 prout(_(" have apparently been transformed into strange mutations."))
5265 prout(_(" Vulcans do not seem to be affected."))
5267 prout(_("Kirk- \"Raauch! Raauch!\""))
5272 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5274 proutn(_("Spock- \"I believe the word is"))
5275 prouts(_(" *ASTONISHING*"))
5276 prout(_(" Mr. Sulu."))
5277 for i in range(QUADSIZE):
5278 for j in range(QUADSIZE):
5279 if game.quad[i][j] == IHDOT:
5280 game.quad[i][j] = IHQUEST
5281 prout(_(" Captain, our quadrant is now infested with"))
5282 prouts(_(" - - - - - - *THINGS*."))
5284 prout(_(" I have no logical explanation.\""))
5286 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5288 prout(_("Scotty- \"There are so many tribbles down here"))
5289 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5293 # Code from reports.c begins here
5295 def attackreport(curt):
5296 # report status of bases under attack
5298 if is_scheduled(FCDBAS):
5299 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5300 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5301 elif game.isatb == 1:
5302 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5303 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5305 prout(_("No Starbase is currently under attack."))
5307 if is_scheduled(FCDBAS):
5308 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5310 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5314 # report on general game status
5316 s1 = "" and game.thawed and _("thawed ")
5317 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5318 s3 = (None, _("novice"). _("fair"),
5319 _("good"), _("expert"), _("emeritus"))[game.skill]
5320 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5321 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5322 prout(_("No plaque is allowed."))
5324 prout(_("This is tournament game %d.") % game.tourn)
5325 prout(_("Your secret password is \"%s\"") % game.passwd)
5326 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5327 (game.inkling + game.incom + game.inscom)))
5328 if game.incom - game.state.remcom:
5329 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5330 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5331 prout(_(", but no Commanders."))
5334 if game.skill > SKILL_FAIR:
5335 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5336 if game.state.rembase != game.inbase:
5338 if game.inbase-game.state.rembase==1:
5339 proutn(_("has been 1 base"))
5341 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5342 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5344 prout(_("There are %d bases.") % game.inbase)
5345 if communicating() or game.iseenit:
5346 # Don't report this if not seen and
5347 # either the radio is dead or not at base!
5351 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5353 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5354 if game.ship == IHE:
5355 proutn(_("You have "))
5357 proutn("%d" % (game.nprobes))
5360 proutn(_(" deep space probe"))
5364 if communicating() and is_scheduled(FDSPROB):
5366 proutn(_("An armed deep space probe is in "))
5368 proutn(_("A deep space probe is in "))
5369 prout("Quadrant %s." % game.probec)
5371 if game.cryprob <= .05:
5372 prout(_("Dilithium crystals aboard ship... not yet used."))
5376 while game.cryprob > ai:
5379 prout(_("Dilithium crystals have been used %d time%s.") % \
5380 (i, (_("s"), "")[i==1]))
5384 # long-range sensor scan
5385 if damaged(DLRSENS):
5386 # Now allow base's sensors if docked
5387 if game.condition != "docked":
5388 prout(_("LONG-RANGE SENSORS DAMAGED."))
5390 prout(_("Starbase's long-range scan"))
5392 prout(_("Long-range scan"))
5393 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5395 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5396 if not VALID_QUADRANT(x, y):
5399 if not damaged(DRADIO):
5400 game.state.galaxy[x][y].charted = True
5401 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5402 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5403 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5404 if game.state.galaxy[x][y].supernova:
5407 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5415 for i in range(NDEVICES):
5418 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5419 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5421 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5422 game.damage[i]+0.05,
5423 game.docfac*game.damage[i]+0.005))
5425 prout(_("All devices functional."))
5428 # update the chart in the Enterprise's computer from galaxy data
5429 game.lastchart = game.state.date
5430 for i in range(GALSIZE):
5431 for j in range(GALSIZE):
5432 if game.state.galaxy[i][j].charted:
5433 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5434 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5435 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5438 # display the star chart
5440 if not damaged(DRADIO):
5442 if game.lastchart < game.state.date and game.condition == "docked":
5443 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5446 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5447 if game.state.date > game.lastchart:
5448 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5449 prout(" 1 2 3 4 5 6 7 8")
5450 for i in range(GALSIZE):
5451 proutn("%d |" % (i))
5452 for j in range(GALSIZE):
5453 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5457 if game.state.galaxy[i][j].supernova:
5459 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5461 elif game.state.galaxy[i][j].charted:
5462 sprintf(buf, "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars))
5466 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5474 def sectscan(goodScan, i, j):
5475 # light up an individual dot in a sector
5476 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5477 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):
5478 if game.condition == "red": textcolor(RED)
5479 elif game.condition == "green": textcolor(GREEN)
5480 elif game.condition == "yellow": textcolor(YELLOW)
5481 elif game.condition == "docked": textcolor(CYAN)
5482 elif game.condition == "dead": textcolor(BROWN)
5483 if game.quad[i][j] != game.ship:
5485 proutn("%c " % game.quad[i][j])
5491 # print status report lines
5493 if not req or req == 1:
5494 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5495 % (game.state.date, game.state.remtime))
5496 elif not req or req == 2:
5497 if game.condition != "docked":
5500 for t in range(NDEVICES):
5501 if game.damage[t]>0:
5503 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5504 elif not req or req == 3:
5505 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5506 elif not req or req == 4:
5507 if damaged(DLIFSUP):
5508 if game.condition == "docked":
5509 sprintf(s, _("DAMAGED, Base provides"))
5511 sprintf(s, _("DAMAGED, reserves=%4.2f") % game.lsupres)
5513 sprintf(s, _("ACTIVE"))
5514 prstat(_("Life Support"), s)
5515 elif not req or req == 5:
5516 prstat(_("Warp Factor"), "%.1f" % (game.warpfac))
5517 elif not req or req == 6:
5519 if game.icrystl and (game.options & OPTION_SHOWME):
5520 extra = _(" (have crystals)")
5521 prstat(_("Energy"), "%.2f%s" % game.energy, extra)
5522 elif not req or req == 7:
5523 prstat(_("Torpedoes"), "%d" % (game.torps))
5524 elif not req or req == 8:
5525 if damaged(DSHIELD):
5526 strcpy(s, _("DAMAGED,"))
5530 strcpy(s, _("DOWN,"))
5531 data = _(" %d%% %.1f units") \
5532 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5533 prstat(_("Shields"), s)
5534 elif not req or req == 9:
5535 prstat(_("Klingons Left"), "%d" \
5536 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5537 elif not req or req == 10:
5538 if game.options & OPTION_WORLDS:
5539 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5540 if plnet != NOPLANET and game.state.planets[plnet].inhabited:
5541 prstat(_("Major system"), plnet.name)
5543 prout(_("Sector is uninhabited"))
5544 elif not req or req == 11:
5545 attackreport(not req)
5548 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5549 while scan() == IHEOL:
5550 proutn(_("Information desired? "))
5552 if citem in requests:
5553 status(requests.index(citem))
5555 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5556 prout((" date, condition, position, lsupport, warpfactor,"))
5557 prout((" energy, torpedoes, shields, klingons, system, time."))
5562 if damaged(DSRSENS):
5563 # Allow base's sensors if docked
5564 if game.condition != "docked":
5565 prout(_(" S.R. SENSORS DAMAGED!"))
5568 prout(_(" [Using Base's sensors]"))
5570 prout(_(" Short-range scan"))
5571 if goodScan and not damaged(DRADIO):
5572 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5573 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5574 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5575 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5576 prout(" 1 2 3 4 5 6 7 8 9 10")
5577 if game.condition != "docked":
5579 for i in range(QUADSIZE):
5580 proutn("%2d " % (i))
5581 for j in range(QUADSIZE):
5582 sectscan(goodScan, i, j)
5587 # use computer to get estimated time of arrival for a warp jump
5588 w1 = coord(); w2 = coord()
5590 if damaged(DCOMPTR):
5591 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5594 if scan() != IHREAL:
5597 proutn(_("Destination quadrant and/or sector? "))
5601 w1.y = int(aaitem-0.5)
5602 if scan() != IHREAL:
5605 w1.x = int(aaitem-0.5)
5606 if scan() == IHREAL:
5607 w2.y = int(aaitem-0.5)
5608 if scan() != IHREAL:
5611 w2.x = int(aaitem-0.5)
5613 if game.quadrant.y>w1.x:
5617 if game.quadrant.x>w1.y:
5622 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5625 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5626 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5630 prout(_("Answer \"no\" if you don't know the value:"))
5633 proutn(_("Time or arrival date? "))
5636 if ttime > game.state.date:
5637 ttime -= game.state.date # Actually a star date
5638 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5639 if ttime <= 1e-10 or twarp > 10:
5640 prout(_("We'll never make it, sir."))
5647 proutn(_("Warp factor? "))
5651 if twarp<1.0 or twarp > 10.0:
5655 prout(_("Captain, certainly you can give me one of these."))
5658 ttime = (10.0*game.dist)/square(twarp)
5659 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5660 if tpower >= game.energy:
5661 prout(_("Insufficient energy, sir."))
5662 if not game.shldup or tpower > game.energy*2.0:
5665 proutn(_("New warp factor to try? "))
5666 if scan() == IHREAL:
5669 if twarp<1.0 or twarp > 10.0:
5677 prout(_("But if you lower your shields,"))
5678 proutn(_("remaining"))
5681 proutn(_("Remaining"))
5682 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5684 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5686 prout(_("Any warp speed is adequate."))
5688 prout(_("Minimum warp needed is %.2f,") % (twarp))
5689 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5690 if game.state.remtime < ttime:
5691 prout(_("Unfortunately, the Federation will be destroyed by then."))
5693 prout(_("You'll be taking risks at that speed, Captain"))
5694 if (game.isatb==1 and game.state.kscmdr == w1 and \
5695 scheduled(FSCDBAS)< ttime+game.state.date) or \
5696 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5697 prout(_("The starbase there will be destroyed by then."))
5698 proutn(_("New warp factor to try? "))
5699 if scan() == IHREAL:
5702 if twarp<1.0 or twarp > 10.0:
5711 #ifdef BSD_BUG_FOR_BUG
5712 # A visual scan is made in a particular direction of three sectors
5713 # in the general direction specified. This takes time, and
5714 # Klingons can attack you, so it should be done only when sensors
5715 # are out. Code swiped from BSD-Trek. Not presently used, as we
5716 # automatically display all adjacent sectors on the short-range
5717 # scan even when short-range sensors are out.
5719 # This struct[] has the delta x, delta y for particular directions
5737 if scan() != IHREAL:
5739 proutn(_("Direction? "))
5743 if aaitem < 0.0 or aaitem > 360.0:
5745 co = (aaitem + 22) / 45
5747 ix = game.sector.x + v.x
5748 iy = game.sector.y + v.y
5749 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5752 co = game.quad[ix][iy]
5753 printf("%d,%d %c " % (ix+1, iy+1, co))
5755 ix = game.sector.x + v.x
5756 iy = game.sector.y + v.y
5757 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5760 co = game.quad[ix][iy]
5761 printf("%c " % (co))
5763 ix = game.sector.x + v.x
5764 iy = game.sector.y + v.y
5765 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5768 co = game.quad[ix][iy]
5769 prout("%c %d,%d\n" % (co, ix+1, iy+1))
5774 # Code from setup.c begins here
5777 return os.fstat(fd).st_size
5780 # issue a historically correct banner
5782 prout(_("-SUPER- STAR TREK"))
5784 #ifdef __HISTORICAL__
5785 # prout(_("Latest update-21 Sept 78"))
5787 #endif __HISTORICAL__
5792 citem = "emsave.trk"
5796 proutn(_("File name: "))
5802 if '.' not in citem:
5805 fp = open(citem, "wb")
5807 prout(_("Can't freeze game as file %s") % citem)
5809 cPickle.dump(game, fp)
5813 # retrieve saved game
5814 game.passwd[0] = '\0'
5817 proutn(_("File name: "))
5823 if '.' not in citem:
5826 fp = open(citem, "rb")
5828 prout(_("Can't thaw game in %s") % citem)
5830 game = cPickle.load(fp)
5834 # I used <http://www.memory-alpha.org> to find planets
5835 # with references in ST:TOS. Eath and the Alpha Centauri
5836 # Colony have been omitted.
5838 # Some planets marked Class G and P here will be displayed as class M
5839 # because of the way planets are generated. This is a known bug.
5842 _("Andoria (Fesoan)"), # several episodes
5843 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5844 _("Vulcan (T'Khasi)"), # many episodes
5845 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5846 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5847 _("Ardana"), # TOS: "The Cloud Minders"
5848 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5849 _("Gideon"), # TOS: "The Mark of Gideon"
5850 _("Aldebaran III"), # TOS: "The Deadly Years"
5851 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5852 _("Altair IV"), # TOS: "Amok Time
5853 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5854 _("Benecia"), # TOS: "The Conscience of the King"
5855 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5856 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5857 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5858 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5859 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5860 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5861 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5862 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5863 _("Ingraham B"), # TOS: "Operation: Annihilate"
5864 _("Janus IV"), # TOS: "The Devil in the Dark"
5865 _("Makus III"), # TOS: "The Galileo Seven"
5866 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5867 _("Omega IV"), # TOS: "The Omega Glory"
5868 _("Regulus V"), # TOS: "Amok Time
5869 _("Deneva"), # TOS: "Operation -- Annihilate!"
5870 # Worlds from BSD Trek
5871 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5872 _("Beta III"), # TOS: "The Return of the Archons"
5873 _("Triacus"), # TOS: "And the Children Shall Lead",
5874 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5876 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5877 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5878 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5879 # _("Izar"), # TOS: "Whom Gods Destroy"
5880 # _("Tiburon"), # TOS: "The Way to Eden"
5881 # _("Merak II"), # TOS: "The Cloud Minders"
5882 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5883 # _("Iotia"), # TOS: "A Piece of the Action"
5887 _("S. R. Sensors"), \
5888 _("L. R. Sensors"), \
5890 _("Photon Tubes"), \
5891 _("Life Support"), \
5892 _("Warp Engines"), \
5893 _("Impulse Engines"), \
5895 _("Subspace Radio"), \
5896 _("Shuttle Craft"), \
5898 _("Navigation System"), \
5900 _("Shield Control"), \
5905 def setup(needprompt):
5906 # prepare to play, set up cosmos
5909 # Decide how many of everything
5910 if choose(needprompt):
5911 return # frozen game
5912 # Prepare the Enterprise
5913 game.alldone = game.gamewon = False
5915 game.state.crew = FULLCREW
5916 game.energy = game.inenrg = 5000.0
5917 game.shield = game.inshld = 2500.0
5918 game.shldchg = False
5922 game.quadrant = randplace(GALSIZE)
5923 game.sector = randplace(QUADSIZE)
5924 game.torps = game.intorps = 10
5925 game.nprobes = int(3.0*random.random() + 2.0) # Give them 2-4 of these
5927 game.wfacsq = game.warpfac * game.warpfac
5928 for i in range(NDEVICES):
5929 game.damage[i] = 0.0
5930 # Set up assorted game parameters
5931 game.battle = coord()
5932 game.state.date = game.indate = 100.0*int(31.0*random.random()+20.0)
5933 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5934 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5935 game.isatb = game.state.nplankl = 0
5936 game.state.starkl = game.state.basekl = 0
5937 game.iscraft = "onship"
5941 for i in range(GALSIZE):
5942 for j in range(GALSIZE):
5943 quad = game.state.galaxy[i][j]
5945 quad.planet = NOPLANET
5948 quad.starbase = False
5949 quad.supernova = False
5950 quad.status = "secure"
5951 # Initialize times for extraneous events
5952 schedule(FSNOVA, expran(0.5 * game.intime))
5953 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5954 schedule(FSNAP, 1.0 + random.random()) # Force an early snapshot
5955 schedule(FBATTAK, expran(0.3*game.intime))
5957 if game.state.nscrem:
5958 schedule(FSCMOVE, 0.2777)
5963 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5964 schedule(FDISTR, expran(1.0 + game.intime))
5969 # Starchart is functional but we've never seen it
5970 game.lastchart = FOREVER
5971 # Put stars in the galaxy
5973 for i in range(GALSIZE):
5974 for j in range(GALSIZE):
5975 k = int(random.random()*9.0 + 1.0)
5977 game.state.galaxy[i][j].stars = k
5978 # Locate star bases in galaxy
5979 for i in range(game.inbase):
5982 w = randplace(GALSIZE)
5983 if not game.state.galaxy[w.x][w.y].starbase:
5986 # C version: for (j = i-1; j > 0; j--)
5987 # so it did them in the opposite order.
5988 for j in range(1, i):
5989 # Improved placement algorithm to spread out bases
5990 distq = w.distance(game.state.baseq[j])
5991 if distq < 6.0*(BASEMAX+1-game.inbase) and random.random() < 0.75:
5994 prout("=== Abandoning base #%d at %s" % (i, w))
5996 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5998 prout("=== Saving base #%d, close to #%d" % (i, j))
6001 game.state.baseq[i] = w
6002 game.state.galaxy[w.x][w.y].starbase = True
6003 game.state.chart[w.x][w.y].starbase = True
6004 # Position ordinary Klingon Battle Cruisers
6006 klumper = 0.25*game.skill*(9.0-game.length)+1.0
6007 if klumper > MAXKLQUAD:
6011 klump = (1.0 - r*r)*klumper
6016 w = randplace(GALSIZE)
6017 if not game.state.galaxy[w.x][w.y].supernova and \
6018 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
6020 game.state.galaxy[w.x][w.y].klingons += klump
6023 # Position Klingon Commander Ships
6024 for i in range(1, game.incom+1):
6026 w = randplace(GALSIZE)
6027 if (game.state.galaxy[w.x][w.y].klingons or random.random()>=0.75) and \
6028 not game.state.galaxy[w.x][w.y].supernova and \
6029 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
6030 not w in game.state.kcmdr[:i]:
6032 game.state.galaxy[w.x][w.y].klingons += 1
6033 game.state.kcmdr[i] = w
6034 # Locate planets in galaxy
6035 for i in range(game.inplan):
6037 w = randplace(GALSIZE)
6038 if game.state.galaxy[w.x][w.y].planet == NOPLANET:
6042 new.crystals = "absent"
6043 if (game.options & OPTION_WORLDS) and i < NINHAB:
6044 new.pclass = "M" # All inhabited planets are class M
6045 new.crystals = "absent"
6047 new.name = systnames[i]
6048 new.inhabited = True
6050 new.pclass = ("M", "N", "O")[random.randint(0, 2)]
6051 if random.random()*1.5: # 1 in 3 chance of crystals
6052 new.crystals = "present"
6053 new.known = "unknown"
6054 new.inhabited = False
6055 game.state.galaxy[w.x][w.y].planet = new
6056 game.state.planets.append(new)
6058 for i in range(game.state.nromrem):
6059 w = randplace(GALSIZE)
6060 game.state.galaxy[w.x][w.y].romulans += 1
6061 # Locate the Super Commander
6062 if game.state.nscrem > 0:
6064 w = randplace(GALSIZE)
6065 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD:
6067 game.state.kscmdr = w
6068 game.state.galaxy[w.x][w.y].klingons += 1
6069 # Place thing (in tournament game, thingx == -1, don't want one!)
6072 thing = randplace(GALSIZE)
6074 game.state.snap = False
6075 if game.skill == SKILL_NOVICE:
6076 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6077 prout(_("a deadly Klingon invasion force. As captain of the United"))
6078 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6079 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6080 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6081 prout(_("your mission. As you proceed you may be given more time."))
6083 prout(_("You will have %d supporting starbases.") % (game.inbase))
6084 proutn(_("Starbase locations- "))
6086 prout(_("Stardate %d.") % int(game.state.date))
6088 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6089 prout(_("An unknown number of Romulans."))
6090 if game.state.nscrem:
6091 prout(_("And one (GULP) Super-Commander."))
6092 prout(_("%d stardates.") % int(game.intime))
6093 proutn(_("%d starbases in ") % game.inbase)
6094 for i in range(game.inbase):
6095 proutn(`game.state.baseq[i]`)
6098 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6099 proutn(_(" Sector %s") % game.sector)
6101 prout(_("Good Luck!"))
6102 if game.state.nscrem:
6103 prout(_(" YOU'LL NEED IT."))
6106 if game.nenhere - iqhere-game.ithere:
6108 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6111 def choose(needprompt):
6112 # choose your game type
6117 game.skill = SKILL_NONE
6119 if needprompt: # Can start with command line options
6120 proutn(_("Would you like a regular, tournament, or saved game? "))
6122 if len(citem)==0: # Try again
6124 if isit("tournament"):
6125 while scan() == IHEOL:
6126 proutn(_("Type in tournament number-"))
6129 continue # We don't want a blank entry
6130 game.tourn = int(aaitem)
6133 if isit("saved") or isit("frozen"):
6137 if game.passwd == None:
6139 if not game.alldone:
6140 game.thawed = True # No plaque if not finished
6146 proutn(_("What is \"%s\"?"), citem)
6148 while game.length==0 or game.skill==SKILL_NONE:
6149 if scan() == IHALPHA:
6152 elif isit("medium"):
6156 elif isit("novice"):
6157 game.skill = SKILL_NOVICE
6159 game.skill = SKILL_FAIR
6161 game.skill = SKILL_GOOD
6162 elif isit("expert"):
6163 game.skill = SKILL_EXPERT
6164 elif isit("emeritus"):
6165 game.skill = SKILL_EMERITUS
6167 proutn(_("What is \""))
6173 proutn(_("Would you like a Short, Medium, or Long game? "))
6174 elif game.skill == SKILL_NONE:
6175 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6176 # Choose game options -- added by ESR for SST2K
6177 if scan() != IHALPHA:
6179 proutn(_("Choose your game style (or just press enter): "))
6182 # Approximates the UT FORTRAN version.
6183 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6184 game.options |= OPTION_PLAIN
6186 # Approximates Tom Almy's version.
6187 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6188 game.options |= OPTION_ALMY
6192 proutn(_("What is \"%s\"?") % citem)
6194 if game.passwd == "debug":
6196 fputs("=== Debug mode enabled\n", sys.stdout)
6198 # Use parameters to generate initial values of things
6199 game.damfac = 0.5 * game.skill
6200 game.state.rembase = random.randint(BASEMIN, BASEMAX)
6201 game.inbase = game.state.rembase
6203 if game.options & OPTION_PLANETS:
6204 game.inplan += int((MAXUNINHAB/2) + (MAXUNINHAB/2+1)*random.random())
6205 if game.options & OPTION_WORLDS:
6206 game.inplan += int(NINHAB)
6207 game.state.nromrem = game.inrom = int((2.0+random.random())*game.skill)
6208 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6209 game.state.remtime = 7.0 * game.length
6210 game.intime = game.state.remtime
6211 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*random.random())*game.skill*0.1+.15)
6212 game.incom = int(game.skill + 0.0625*game.inkling*random.random())
6213 game.state.remcom = min(10, game.incom)
6214 game.incom = game.state.remcom
6215 game.state.remres = (game.inkling+4*game.incom)*game.intime
6216 game.inresor = game.state.remres
6217 if game.inkling > 50:
6218 game.state.rembase += 1
6219 game.inbase = game.state.rembase
6223 # drop a feature on a random dot in the current quadrant
6226 w = randplace(QUADSIZE)
6227 if game.quad[w.x][w.y] == IHDOT:
6229 game.quad[w.x][w.y] = iquad
6233 # update our alert status
6234 game.condition = "green"
6235 if game.energy < 1000.0:
6236 game.condition = "yellow"
6237 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6238 game.condition = "red"
6240 game.condition="dead"
6243 # drop new Klingon into current quadrant
6246 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6247 game.kpower[i] = random.random()*150.0 +300.0 +25.0*game.skill
6251 # set up a new state of quadrant, for when we enter or re-enter it
6255 game.comhere = False
6261 game.inorbit = False
6263 game.ientesc = False
6265 global iqhere, iqengry
6268 game.iseenit = False
6270 # Attempt to escape Super-commander, so tbeam back!
6273 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6274 # cope with supernova
6277 game.klhere = q.klingons
6278 game.irhere = q.romulans
6279 game.nenhere = game.klhere + game.irhere
6282 game.quad[game.sector.x][game.sector.y] = game.ship
6285 w.x = w.y = 0 # quiet a gcc warning
6286 # Position ordinary Klingons
6287 for i in range(game.klhere):
6289 # If we need a commander, promote a Klingon
6290 for i in range(game.state.remcom):
6291 if game.state.kcmdr[i] == game.quadrant:
6294 if i <= game.state.remcom:
6295 game.quad[w.x][w.y] = IHC
6296 game.kpower[game.klhere] = 950.0+400.0*random.random()+50.0*game.skill
6299 # If we need a super-commander, promote a Klingon
6300 if same(game.quadrant, game.state.kscmdr):
6301 game.quad[game.ks[0].x][game.ks[0].y] = IHS
6302 game.kpower[1] = 1175.0 + 400.0*random.random() + 125.0*game.skill
6303 game.iscate = (game.state.remkl > 1)
6305 # Put in Romulans if needed
6306 for i in range(game.klhere, game.nenhere):
6309 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6310 game.kpower[i] = random.random()*400.0 + 450.0 + 50.0*game.skill
6311 # If quadrant needs a starbase, put it in
6313 game.base = dropin(IHB)
6315 # If quadrant needs a planet, put it in
6316 if q.planet != NOPLANET:
6317 game.iplnet = q.planet
6318 if not q.planet.inhabited:
6319 game.plnet = dropin(IHP)
6321 game.plnet = dropin(IHW)
6322 # Check for condition
6324 # And finally the stars
6325 for i in range(q.stars):
6329 if game.irhere > 0 and game.klhere == 0:
6331 if not damaged(DRADIO):
6333 prout(_("LT. Uhura- \"Captain, an urgent message."))
6334 prout(_(" I'll put it on audio.\" CLICK"))
6336 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6337 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6340 # Put in THING if needed
6342 if thing == game.quadrant:
6344 thing = randplace(GALSIZE)
6348 game.ks[game.nenhere] = w
6349 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6350 distance(game.sector, w)
6351 game.kpower[game.nenhere] = random.random()*6000.0 +500.0 +250.0*game.skill
6352 if not damaged(DSRSENS):
6354 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6355 prout(_(" Please examine your short-range scan.\""))
6357 # Decide if quadrant needs a Tholian; lighten up if skill is low
6358 if game.options & OPTION_THOLIAN:
6359 if (game.skill < SKILL_GOOD and random.random() <= 0.02) or \
6360 (game.skill == SKILL_GOOD and random.random() <= 0.05) or \
6361 (game.skill > SKILL_GOOD and random.random() <= 0.08):
6363 game.tholian.x = random.choice((0, QUADSIZE-1))
6364 game.tholian.y = random.choice((0, QUADSIZE-1))
6365 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6367 game.quad[game.tholian.x][game.tholian.y] = IHT
6370 game.ks[game.nenhere] = game.tholian
6371 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6372 distance(game.sector, game.tholian)
6373 game.kpower[game.nenhere] = random.random()*400.0 +100.0 +25.0*game.skill
6374 # Reserve unoccupied corners
6375 if game.quad[0][0]==IHDOT:
6376 game.quad[0][0] = 'X'
6377 if game.quad[0][QUADSIZE-1]==IHDOT:
6378 game.quad[0][QUADSIZE-1] = 'X'
6379 if game.quad[QUADSIZE-1][0]==IHDOT:
6380 game.quad[QUADSIZE-1][0] = 'X'
6381 if game.quad[QUADSIZE-1][QUADSIZE-1]==IHDOT:
6382 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
6385 # Put in a few black holes
6386 for i in range(1, 3+1):
6387 if random.random() > 0.5:
6390 # Take out X's in corners if Tholian present
6392 if game.quad[0][0]=='X':
6393 game.quad[0][0] = IHDOT
6394 if game.quad[0][QUADSIZE-1]=='X':
6395 game.quad[0][QUADSIZE-1] = IHDOT
6396 if game.quad[QUADSIZE-1][0]=='X':
6397 game.quad[QUADSIZE-1][0] = IHDOT
6398 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
6399 game.quad[QUADSIZE-1][QUADSIZE-1] = IHDOT
6402 # sort Klingons by distance from us
6403 # The author liked bubble sort. So we will use it. :-(
6404 if game.nenhere-iqhere-game.ithere < 2:
6408 for j in range(game.nenhere):
6409 if game.kdist[j] > game.kdist[j+1]:
6412 game.kdist[j] = game.kdist[j+1]
6415 game.kavgd[j] = game.kavgd[j+1]
6418 game.ks[j].x = game.ks[j+1].x
6421 game.ks[j].y = game.ks[j+1].y
6424 game.kpower[j] = game.kpower[j+1]
6425 game.kpower[j+1] = t
6430 # set the self-destruct password
6431 if game.options & OPTION_PLAIN:
6434 proutn(_("Please type in a secret password- "))
6437 if game.passwd != None:
6442 game.passwd += chr(97+int(random.random()*25))
6444 # Code from sst.c begins here
6447 "SRSCAN": OPTION_TTY,
6448 "STATUS": OPTION_TTY,
6449 "REQUEST": OPTION_TTY,
6450 "LRSCAN": OPTION_TTY,
6463 "SENSORS": OPTION_PLANETS,
6464 "ORBIT": OPTION_PLANETS,
6465 "TRANSPORT": OPTION_PLANETS,
6466 "MINE": OPTION_PLANETS,
6467 "CRYSTALS": OPTION_PLANETS,
6468 "SHUTTLE": OPTION_PLANETS,
6469 "PLANETS": OPTION_PLANETS,
6474 "PROBE": OPTION_PROBE,
6476 "FREEZE": 0, # Synonym for SAVE
6482 "SOS": 0, # Synonym for MAYDAY
6483 "CALL": 0, # Synonym for MAYDAY
6490 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6493 # generate a list of legal commands
6495 proutn(_("LEGAL COMMANDS ARE:"))
6496 for key in commands:
6500 proutn("%-12s " % key)
6505 # browse on-line help
6506 # Give help on commands
6510 setwnd(prompt_window)
6511 proutn(_("Help on what command? "))
6513 setwnd(message_window)
6516 if citem in commands or citem == "ABBREV":
6525 fp = open(SSTDOC, "r")
6528 fp = open(DOC_NAME, "r")
6530 prout(_("Spock- \"Captain, that information is missing from the"))
6531 proutn(_(" computer. You need to find "))
6533 prout(_(" and put it in the"))
6534 proutn(_(" current directory or to "))
6538 # This used to continue: "You need to find SST.DOC and put
6539 # it in the current directory."
6543 linebuf = fp.readline()
6545 prout(_("Spock- \"Captain, there is no information on that command.\""))
6548 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6549 linebuf = linebuf[3:].strip()
6553 prout(_("Spock- \"Captain, I've found the following information:\""))
6555 while linebuf in fp:
6556 if "******" in linebuf:
6562 # command-interpretation loop
6565 setwnd(message_window)
6566 while True: # command loop
6568 while True: # get a command
6574 setwnd(prompt_window)
6578 if game.options & OPTION_CURSES:
6583 setwnd(message_window)
6586 if cmd not in commands:
6589 commandhook(commands[i].name, True)
6590 if cmd == "SRSCAN": # srscan
6592 elif cmd == "STATUS": # status
6594 elif cmd == "REQUEST": # status request
6596 elif cmd == "LRSCAN": # long range scan
6598 elif cmd == "PHASERS": # phasers
6602 elif cmd == "TORPEDO": # photon torpedos
6606 elif cmd == "MOVE": # move under warp
6608 elif cmd == "SHIELDS": # shields
6612 game.shldchg = False
6613 elif cmd == "DOCK": # dock at starbase
6617 elif cmd == "DAMAGES": # damage reports
6619 elif cmd == "CHART": # chart
6621 elif cmd == "IMPULSE": # impulse
6623 elif cmd == "REST": # rest
6627 elif cmd == "WARP": # warp
6629 elif cmd == "SCORE": # score
6631 elif cmd == "SENSORS": # sensors
6633 elif cmd == "ORBIT": # orbit
6637 elif cmd == "TRANSPORT": # transport "beam"
6639 elif cmd == "MINE": # mine
6643 elif cmd == "CRYSTALS": # crystals
6647 elif cmd == "SHUTTLE": # shuttle
6651 elif cmd == "PLANETS": # Planet list
6653 elif cmd == "REPORT": # Game Report
6655 elif cmd == "COMPUTER": # use COMPUTER!
6657 elif cmd == "COMMANDS":
6659 elif cmd == "EMEXIT": # Emergency exit
6660 clrscr() # Hide screen
6661 freeze(True) # forced save
6662 os.exit(1) # And quick exit
6663 elif cmd == "PROBE":
6664 probe() # Launch probe
6667 elif cmd == "ABANDON": # Abandon Ship
6669 elif cmd == "DESTRUCT": # Self Destruct
6671 elif cmd == "SAVE": # Save Game
6674 if game.skill > SKILL_GOOD:
6675 prout(_("WARNING--Saved games produce no plaques!"))
6676 elif cmd == "DEATHRAY": # Try a desparation measure
6680 elif cmd == "DEBUGCMD": # What do we want for debug???
6682 elif cmd == "MAYDAY": # Call for help
6687 game.alldone = True # quit the game
6690 elif cmd == "SEED": # set random-number seed
6694 #ifdef BSD_BUG_FOR_BUG
6695 # elif cmd == "VISUAL":
6696 # visual() # perform visual scan
6698 commandhook(commands[i].name, False)
6701 break # Game has ended
6702 if game.optime != 0.0:
6705 break # Events did us in
6706 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6709 if hitme and not game.justin:
6713 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6725 if cmd == IHR: s = _("Romulan")
6726 elif cmd == IHK: s = _("Klingon")
6727 elif cmd == IHC: s = _("Commander")
6728 elif cmd == IHS: s = _("Super-commander")
6729 elif cmd == IHSTAR: s = _("Star")
6730 elif cmd == IHP: s = _("Planet")
6731 elif cmd == IHB: s = _("Starbase")
6732 elif cmd == IHBLANK: s = _("Black hole")
6733 elif cmd == IHT: s = _("Tholian")
6734 elif cmd == IHWEB: s = _("Tholian web")
6735 elif cmd == IHQUEST: s = _("Stranger")
6736 elif cmd == IHW: s = _("Inhabited World")
6737 else: s = "Unknown??"
6740 def cramlc(loctype, w):
6742 if loctype == "quadrant":
6743 buf = _("Quadrant ")
6744 elif loctype == "sector":
6746 buf += ("%d - %d" % (w.x, w.y))
6749 def crmena(stars, enemy, loctype, w):
6750 # print an enemy and his location
6755 proutn(cramlc(loctype, w))
6758 # print our ship name
6759 if game.ship == IHE:
6761 elif game.ship == IHF:
6762 s = _("Faerie Queene")
6768 # print a line of stars
6769 prouts("******************************************************")
6773 return -avrage*math.log(1e-7 + random.random())
6775 def randplace(size):
6776 # choose a random location
6778 w.x = random.randint(0, size-1)
6779 w.y = random.randint(0, size-1)
6783 # Demand input for next scan
6788 # return IHEOL next time
6793 # Get a token from the user
6794 global inqueue, line, citem
6798 # Read a line if nothing here
6801 if curwnd==prompt_window:
6803 setwnd(message_window)
6805 # Skip leading white space
6806 line = line.lstrip()
6808 inqueue = line.split()
6814 # From here on in it's all looking at the queue
6815 citem = inqueue.pop(0)
6819 aaitem = float(citem)
6824 citem = citem.lower()
6828 # yes-or-no confirmation
6837 proutn(_("Please answer with \"y\" or \"n\": "))
6840 # complain about unparseable input
6843 prout(_("Beg your pardon, Captain?"))
6846 # compares s to citem and returns true if it matches to the length of s
6847 return s.startswith(citem)
6850 # access to the internals for debugging
6851 proutn("Reset levels? ")
6853 if game.energy < game.inenrg:
6854 game.energy = game.inenrg
6855 game.shield = game.inshld
6856 game.torps = game.intorps
6857 game.lsupres = game.inlsr
6858 proutn("Reset damage? ")
6860 for i in range(NDEVICES):
6861 if game.damage[i] > 0.0:
6862 game.damage[i] = 0.0
6863 proutn("Toggle debug flag? ")
6867 prout("Debug output ON")
6869 prout("Debug output OFF")
6870 proutn("Cause selective damage? ")
6872 for i in range(NDEVICES):
6878 if key == IHALPHA and isit("y"):
6879 game.damage[i] = 10.0
6880 proutn("Examine/change events? ")
6885 FSNOVA: "Supernova ",
6888 FBATTAK: "Base Attack ",
6889 FCDBAS: "Base Destroy ",
6890 FSCMOVE: "SC Move ",
6891 FSCDBAS: "SC Base Destroy ",
6892 FDSPROB: "Probe Move ",
6893 FDISTR: "Distress Call ",
6894 FENSLV: "Enslavement ",
6895 FREPRO: "Klingon Build ",
6897 for i in range(1, NEVENTS):
6900 proutn("%.2f" % (scheduled(i)-game.state.date))
6901 if i == FENSLV or i == FREPRO:
6903 proutn(" in %s" % ev.quadrant)
6913 ev = schedule(i, aaitem)
6914 if i == FENSLV or i == FREPRO:
6916 proutn("In quadrant- ")
6918 # IHEOL says to leave coordinates as they are
6921 prout("Event %d canceled, no x coordinate." % (i))
6927 prout("Event %d canceled, no y coordinate." % (i))
6933 proutn("Induce supernova here? ")
6935 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6938 if __name__ == '__main__':
6939 global line, thing, game, idebug, iqhere, iqengry
6940 game = citem = aaitem = inqueue = None
6943 iqhere = iqengry = False
6947 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY)
6948 # Disable curses mode until the game logic is working.
6949 # if os.getenv("TERM"):
6950 # game.options |= OPTION_CURSES | OPTION_SHOWME
6952 game.options |= OPTION_TTY
6955 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6956 for (switch, val) in options:
6959 replayfp = open(optarg, "r")
6961 sys.stderr.write("sst: can't open replay file %s\n" % optarg)
6963 line = replayfp.readline().strip()
6965 (key, seed) = line.split()
6968 sys.stderr.write("sst: replay file %s is ill-formed\n"%optarg)
6970 game.options |= OPTION_TTY
6971 game.options &=~ OPTION_CURSES
6972 elif switch == '-t':
6973 game.options |= OPTION_TTY
6974 game.options &=~ OPTION_CURSES
6975 elif switch == '-x':
6978 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6980 # where to save the input in case of bugs
6982 logfp = open("/usr/tmp/sst-input.log", "w")
6984 sys.stderr.write("sst: warning, can't open logfile\n")
6987 logfp.write("seed %d\n" % (seed))
6996 while True: # Play a game
6997 setwnd(fullscreen_window)
7000 setup(needprompt=not line)
7003 game.alldone = False
7010 if game.tourn and game.alldone:
7011 proutn(_("Do you want your score recorded?"))
7015 proutn(_("Do you want to play again? "))
7019 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))