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 1-origin index
7 an a lot of parallel arrays where a more modern language would use structures
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)
190 BASEMAX = (GALSIZE * GALSIZE / 12)
193 FULLCREW = 428 # BSD Trek was 387, that's wrong
196 # These functions hide the difference between 0-origin and 1-origin addressing.
197 def VALID_QUADRANT(x, y): return ((x)>=1 and (x)<=GALSIZE and (y)>=1 and (y)<=GALSIZE)
198 def VALID_SECTOR(x, y): return ((x)>=1 and (x)<=QUADSIZE and (y)>=1 and (y)<=QUADSIZE)
200 def square(i): return ((i)*(i))
201 def distance(c1, c2): return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
202 def invalidate(w): w.x = w.y = 0
203 def is_valid(w): return (w.x != 0 and w.y != 0)
205 # How to represent features
230 def __init(self, x=None, y=None):
233 def invalidate(self):
234 self.x = self.y = None
236 return self.x != None and self.y != None
237 def __eq__(self, other):
238 return self.x == other.y and self.x == other.y
239 def __add__(self, other):
240 return coord(self.x+self.x, self.y+self.y)
241 def __sub__(self, other):
242 return coord(self.x-self.x, self.y-self.y)
243 def distance(self, other):
244 return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
246 return coord(self.x / abs(x), self.y / abs(y));
250 return "%d - %d" % (self.x, self.y)
254 self.name = None # string-valued if inhabited
255 self.w = coord() # quadrant located
256 self.pclass = None # could be ""M", "N", "O", or "destroyed"
257 self.crystals = None # could be "mined", "present", "absent"
258 self.known = None # could be "unknown", "known", "shuttle_down"
259 self.inhabited # is it inhabites?
271 self.supernova = None
273 self.status = None # Could be "secure", "distressed", "enslaved"
283 self.snap = False # snapshot taken
284 self.crew = None # crew complement
285 self.remkl = None # remaining klingons
286 self.remcom = None # remaining commanders
287 self.nscrem = None # remaining super commanders
288 self.rembase = None # remaining bases
289 self.starkl = None # destroyed stars
290 self.basekl = None # destroyed bases
291 self.nromrem = None # Romulans remaining
292 self.nplankl = None # destroyed uninhabited planets
293 self.nworldkl = None # destroyed inhabited planets
294 self.planets = [] # Planet information
295 self.date = None # stardate
296 self.remres = None # remaining resources
297 self.remtime = None # remaining time
298 self.baseq = [] # Base quadrant coordinates
299 for i in range(BASEMAX+1):
300 self.baseq.append(coord())
301 self.kcmdr = [] # Commander quadrant coordinates
302 for i in range(QUADSIZE+1):
303 self.kcmdr.append(coord())
304 self.kscmdr = coord() # Supercommander quadrant coordinates
305 self.galaxy = [] # The Galaxy (subscript 0 not used)
306 for i in range(GALSIZE+1):
307 self.chart.append([])
308 for j in range(GALSIZE+1):
309 self.galaxy[i].append(quadrant())
310 self.chart = [] # the starchart (subscript 0 not used)
311 for i in range(GALSIZE+1):
312 self.chart.append([])
313 for j in range(GALSIZE+1):
314 self.chart[i].append(page())
318 self.date = None # A real number
319 self.quadrant = None # A coord structure
322 OPTION_ALL = 0xffffffff
323 OPTION_TTY = 0x00000001 # old interface
324 OPTION_CURSES = 0x00000002 # new interface
325 OPTION_IOMODES = 0x00000003 # cover both interfaces
326 OPTION_PLANETS = 0x00000004 # planets and mining
327 OPTION_THOLIAN = 0x00000008 # Tholians and their webs
328 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back
329 OPTION_PROBE = 0x00000020 # deep-space probes
330 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
331 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise
332 OPTION_MVBADDY = 0x00000100 # more enemies can move
333 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you
334 OPTION_BASE = 0x00000400 # bases have good shields
335 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds
336 OPTION_PLAIN = 0x01000000 # user chose plain game
337 OPTION_ALMY = 0x02000000 # user chose Almy variant
356 NDEVICES= 16 # Number of devices
365 def damaged(dev): return (game.damage[dev] != 0.0)
366 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
368 # Define future events
369 FSPY = 0 # Spy event happens always (no future[] entry)
370 # can cause SC to tractor beam Enterprise
371 FSNOVA = 1 # Supernova
372 FTBEAM = 2 # Commander tractor beams Enterprise
373 FSNAP = 3 # Snapshot for time warp
374 FBATTAK = 4 # Commander attacks base
375 FCDBAS = 5 # Commander destroys base
376 FSCMOVE = 6 # Supercommander moves (might attack base)
377 FSCDBAS = 7 # Supercommander destroys base
378 FDSPROB = 8 # Move deep space probe
379 FDISTR = 9 # Emit distress call from an inhabited world
380 FENSLV = 10 # Inhabited word is enslaved */
381 FREPRO = 11 # Klingons build a ship in an enslaved system
385 # abstract out the event handling -- underlying data structures will change
386 # when we implement stateful events
388 def findevent(evtype): return game.future[evtype]
392 self.options = None # Game options
393 self.state = None # A snapshot structure
394 self.snapsht = None # Last snapshot taken for time-travel purposes
395 self.quad = [[IHDOT * (QUADSIZE+1)] * (QUADSIZE+1)] # contents of our quadrant
396 self.kpower = [[0 * (QUADSIZE+1)] * (QUADSIZE+1)] # enemy energy levels
397 self.kdist = [[0 * (QUADSIZE+1)] * (QUADSIZE+1)] # enemy distances
398 self.kavgd = [[0 * (QUADSIZE+1)] * (QUADSIZE+1)] # average distances
399 self.damage = [0.0] * NDEVICES # damage encountered
400 self.future = [0.0] * NEVENTS # future events
401 for i in range(NEVENTS):
402 self.future.append(event())
403 self.passwd = None; # Self Destruct password
404 self.ks = [[0 * (QUADSIZE+1)] * (QUADSIZE+1)] # enemy sector locations
405 self.quadrant = None # where we are in the large
406 self.sector = None # where we are in the small
407 self.tholian = None # coordinates of Tholian
408 self.base = None # position of base in current quadrant
409 self.battle = None # base coordinates being attacked
410 self.plnet = None # location of planet in quadrant
411 self.probec = None # current probe quadrant
412 self.gamewon = False # Finished!
413 self.ididit = False # action taken -- allows enemy to attack
414 self.alive = False # we are alive (not killed)
415 self.justin = False # just entered quadrant
416 self.shldup = False # shields are up
417 self.shldchg = False # shield is changing (affects efficiency)
418 self.comhere = False # commander here
419 self.ishere = False # super-commander in quadrant
420 self.iscate = False # super commander is here
421 self.ientesc = False # attempted escape from supercommander
422 self.ithere = False # Tholian is here
423 self.resting = False # rest time
424 self.icraft = False # Kirk in Galileo
425 self.landed = False # party on planet (true), on ship (false)
426 self.alldone = False # game is now finished
427 self.neutz = False # Romulan Neutral Zone
428 self.isarmed = False # probe is armed
429 self.inorbit = False # orbiting a planet
430 self.imine = False # mining
431 self.icrystl = False # dilithium crystals aboard
432 self.iseenit = False # seen base attack report
433 self.thawed = False # thawed game
434 self.condition = None # "green", "yellow", "red", "docked", "dead"
435 self.iscraft = None # "onship", "offship", "removed"
436 self.skill = None # Player skill level
437 self.inkling = 0 # initial number of klingons
438 self.inbase = 0 # initial number of bases
439 self.incom = 0 # initial number of commanders
440 self.inscom = 0 # initial number of commanders
441 self.inrom = 0 # initial number of commanders
442 self.instar = 0 # initial stars
443 self.intorps = 0 # initial/max torpedoes
444 self.torps = 0 # number of torpedoes
445 self.ship = 0 # ship type -- 'E' is Enterprise
446 self.abandoned = 0 # count of crew abandoned in space
447 self.length = 0 # length of game
448 self.klhere = 0 # klingons here
449 self.casual = 0 # causalties
450 self.nhelp = 0 # calls for help
451 self.nkinks = 0 # count of energy-barrier crossings
452 self.iplnet = 0 # planet # in quadrant
453 self.inplan = 0 # initial planets
454 self.nenhere = 0 # number of enemies in quadrant
455 self.irhere = 0 # Romulans in quadrant
456 self.isatb = 0 # =1 if super commander is attacking base
457 self.tourn = 0 # tournament number
458 self.proben = 0 # number of moves for probe
459 self.nprobes = 0 # number of probes available
460 self.inresor = 0.0 # initial resources
461 self.intime = 0.0 # initial time
462 self.inenrg = 0.0 # initial/max energy
463 self.inshld = 0.0 # initial/max shield
464 self.inlsr = 0.0 # initial life support resources
465 self.indate = 0.0 # initial date
466 self.energy = 0.0 # energy level
467 self.shield = 0.0 # shield level
468 self.warpfac = 0.0 # warp speed
469 self.wfacsq = 0.0 # squared warp factor
470 self.lsupres = 0.0 # life support reserves
471 self.dist = 0.0 # movement distance
472 self.direc = 0.0 # movement direction
473 self.optime = 0.0 # time taken by current operation
474 self.docfac = 0.0 # repair factor when docking (constant?)
475 self.damfac = 0.0 # damage factor
476 self.lastchart = 0.0 # time star chart was last updated
477 self.cryprob = 0.0 # probability that crystal will work
478 self.probex = 0.0 # location of probe
480 self.probeinx = 0.0 # probe x,y increment
481 self.probeiny = 0.0 #
482 self.height = 0.0 # height of orbit around planet
484 # Stas thinks this should be (C expression):
485 # game.state.remkl + game.state.remcom > 0 ?
486 # game.state.remres/(game.state.remkl + 4*game.state.remcom) : 99
487 # He says the existing expression is prone to divide-by-zero errors
488 # after killing the last klingon when score is shown -- perhaps also
489 # if the only remaining klingon is SCOM.
490 game.state.remtime = game.state.remres/(game.state.remkl + 4*game.state.remcom)
491 # From enumerated type 'feature'
512 # From enumerated type 'FINTYPE'
536 # From enumerated type 'COLORS'
555 # Code from ai.c begins here
557 def tryexit(look, ienm, loccom, irun):
558 # a bad guy attempts to bug out
560 iq.x = game.quadrant.x+(look.x+(QUADSIZE-1))/QUADSIZE - 1
561 iq.y = game.quadrant.y+(look.y+(QUADSIZE-1))/QUADSIZE - 1
562 if not VALID_QUADRANT(iq.x,iq.y) or \
563 game.state.galaxy[iq.x][iq.y].supernova or \
564 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
565 return False; # no can do -- neg energy, supernovae, or >MAXKLQUAD-1 Klingons
567 return False; # Romulans cannot escape!
569 # avoid intruding on another commander's territory
571 for n in range(1, game.state.remcom+1):
572 if game.state.kcmdr[n] == iq:
574 # refuse to leave if currently attacking starbase
575 if game.battle == game.quadrant:
577 # don't leave if over 1000 units of energy
578 if game.kpower[loccom] > 1000.0:
580 # print escape message and move out of quadrant.
581 # we know this if either short or long range sensors are working
582 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
583 game.condition == docked:
584 crmena(True, ienm, "sector", game.ks[loccom])
585 prout(_(" escapes to Quadrant %s (and regains strength).") % q)
586 # handle local matters related to escape
587 game.quad[game.ks[loccom].x][game.ks[loccom].y] = IHDOT
588 game.ks[loccom] = game.ks[game.nenhere]
589 game.kavgd[loccom] = game.kavgd[game.nenhere]
590 game.kpower[loccom] = game.kpower[game.nenhere]
591 game.kdist[loccom] = game.kdist[game.nenhere]
594 if game.condition != docked:
596 # Handle global matters related to escape
597 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
598 game.state.galaxy[iq.x][iq.y].klingons += 1
604 schedule(FSCMOVE, 0.2777)
608 for n in range(1, game.state.remcom+1):
609 if game.state.kcmdr[n] == game.quadrant:
610 game.state.kcmdr[n]=iq
613 return True; # success
616 # The bad-guy movement algorithm:
618 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
619 # If both are operating full strength, force is 1000. If both are damaged,
620 # force is -1000. Having shields down subtracts an additional 1000.
622 # 2. Enemy has forces equal to the energy of the attacker plus
623 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
624 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
626 # Attacker Initial energy levels (nominal):
627 # Klingon Romulan Commander Super-Commander
628 # Novice 400 700 1200
630 # Good 450 800 1300 1750
631 # Expert 475 850 1350 1875
632 # Emeritus 500 900 1400 2000
633 # VARIANCE 75 200 200 200
635 # Enemy vessels only move prior to their attack. In Novice - Good games
636 # only commanders move. In Expert games, all enemy vessels move if there
637 # is a commander present. In Emeritus games all enemy vessels move.
639 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
640 # forces are 1000 greater than Enterprise.
642 # Agressive action on average cuts the distance between the ship and
643 # the enemy to 1/4 the original.
645 # 4. At lower energy advantage, movement units are proportional to the
646 # advantage with a 650 advantage being to hold ground, 800 to move forward
647 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
649 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
650 # retreat, especially at high skill levels.
652 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
655 def movebaddy(com, loccom, ienm):
656 # tactical movement for the bad guys
657 next = coord(); look = coord()
659 # This should probably be just game.comhere + game.ishere
660 if game.skill >= SKILL_EXPERT:
661 nbaddys = ((game.comhere*2 + game.ishere*2+game.klhere*1.23+game.irhere*1.5)/2.0)
663 nbaddys = game.comhere + game.ishere
665 dist1 = game.kdist[loccom]
666 mdist = int(dist1 + 0.5); # Nearest integer distance
668 # If SC, check with spy to see if should hi-tail it
670 (game.kpower[loccom] <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
674 # decide whether to advance, retreat, or hold position
675 forces = game.kpower[loccom]+100.0*game.nenhere+400*(nbaddys-1)
677 forces += 1000; # Good for enemy if shield is down!
678 if not damaged(DPHASER) or not damaged(DPHOTON):
679 if damaged(DPHASER): # phasers damaged
682 forces -= 0.2*(game.energy - 2500.0)
683 if damaged(DPHOTON): # photon torpedoes damaged
686 forces -= 50.0*game.torps
688 # phasers and photon tubes both out!
691 if forces <= 1000.0 and game.condition != "docked": # Typical situation
692 motion = ((forces+200.0*random.random())/150.0) - 5.0
694 if forces > 1000.0: # Very strong -- move in for kill
695 motion = (1.0-square(random.random()))*dist1 + 1.0
696 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
697 motion -= game.skill*(2.0-square(random.random()))
699 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
700 # don't move if no motion
703 # Limit motion according to skill
704 if abs(motion) > game.skill:
709 # calculate preferred number of steps
714 if motion > 0 and nsteps > mdist:
715 nsteps = mdist; # don't overshoot
716 if nsteps > QUADSIZE:
717 nsteps = QUADSIZE; # This shouldn't be necessary
719 nsteps = 1; # This shouldn't be necessary
721 proutn("NSTEPS = %d:" % nsteps)
722 # Compute preferred values of delta X and Y
723 mx = game.sector.x - com.x
724 my = game.sector.y - com.y
725 if 2.0 * abs(mx) < abs(my):
727 if 2.0 * abs(my) < abs(game.sector.x-com.x):
741 for ll in range(nsteps):
743 proutn(" %d" % (ll+1))
744 # Check if preferred position available
756 attempts = 0; # Settle mysterious hang problem
757 while attempts < 20 and not success:
759 if look.x < 1 or look.x > QUADSIZE:
760 if motion < 0 and tryexit(look, ienm, loccom, irun):
762 if krawlx == mx or my == 0:
764 look.x = next.x + krawlx
766 elif look.y < 1 or look.y > QUADSIZE:
767 if motion < 0 and tryexit(look, ienm, loccom, irun):
769 if krawly == my or mx == 0:
771 look.y = next.y + krawly
773 elif (game.options & OPTION_RAMMING) and game.quad[look.x][look.y] != IHDOT:
774 # See if we should ram ship
775 if game.quad[look.x][look.y] == game.ship and \
776 (ienm == IHC or ienm == IHS):
779 if krawlx != mx and my != 0:
780 look.x = next.x + krawlx
782 elif krawly != my and mx != 0:
783 look.y = next.y + krawly
786 break; # we have failed
798 # Put commander in place within same quadrant
799 game.quad[com.x][com.y] = IHDOT
800 game.quad[next.x][next.y] = ienm
803 game.ks[loccom] = next
804 game.kdist[loccom] = game.kavgd[loccom] = distance(game.sector, next)
805 if not damaged(DSRSENS) or game.condition == docked:
808 proutn(_(" from Sector %s") % com)
809 if game.kdist[loccom] < dist1:
810 proutn(_(" advances to "))
812 proutn(_(" retreats to "))
813 prout("Sector %s." % next)
816 # Klingon tactical movement
819 # Figure out which Klingon is the commander (or Supercommander)
822 for i in range(1, game.nenhere+1):
824 if game.quad[w.x][w.y] == IHC:
828 for i in range(1, game.nenhere+1):
830 if game.quad[w.x][w.y] == IHS:
833 # If skill level is high, move other Klingons and Romulans too!
834 # Move these last so they can base their actions on what the
836 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
837 for i in range(1, game.nenhere+1):
839 if game.quad[w.x][w.y] == IHK or game.quad[w.x][w.y] == IHR:
840 movebaddy(w, i, game.quad[w.x][w.y])
843 def movescom(iq, avoid):
844 # commander movement helper
845 if iq == game.quadrant or not VALID_QUADRANT(iq.x, iq.y) or \
846 game.state.galaxy[iq.x][iq.y].supernova or \
847 game.state.galaxy[iq.x][iq.y].klingons > MAXKLQUAD-1:
850 # Avoid quadrants with bases if we want to avoid Enterprise
851 for i in range(1, game.state.rembase+1):
852 if game.state.baseq[i] == iq:
854 if game.justin and not game.iscate:
857 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons -= 1
858 game.state.kscmdr = iq
859 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].klingons += 1
861 # SC has scooted, Remove him from current quadrant
867 for i in range(1, game.nenhere+1):
868 if game.quad[game.ks[i].x][game.ks[i].y] == IHS:
870 game.quad[game.ks[i].x][game.ks[i].y] = IHDOT
871 game.ks[i] = game.ks[game.nenhere]
872 game.kdist[i] = game.kdist[game.nenhere]
873 game.kavgd[i] = game.kavgd[game.nenhere]
874 game.kpower[i] = game.kpower[game.nenhere]
877 if game.condition!=docked:
880 # check for a helpful planet
881 for i in range(game.inplan):
882 if game.state.planets[i].w == game.state.kscmdr and \
883 game.state.planets[i].crystals == "present":
885 game.state.planets[i].pclass = "destroyed"
886 game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].planet = NOPLANET
889 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
890 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
891 prout(_(" by the Super-commander.\""))
893 return False; # looks good!
895 def supercommander():
896 # move the Super Commander
897 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
900 prout("== SUPERCOMMANDER")
901 # Decide on being active or passive
902 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 \
903 (game.state.date-game.indate) < 3.0)
904 if not game.iscate and avoid:
905 # compute move away from Enterprise
906 idelta = game.state.kscmdr-game.quadrant
907 if math.sqrt(idelta.x*idelta.x+idelta.y*idelta.y) > 2.0:
909 idelta.x = game.state.kscmdr.y-game.quadrant.y
910 idelta.y = game.quadrant.x-game.state.kscmdr.x
912 # compute distances to starbases
913 if game.state.rembase <= 0:
917 sc = game.state.kscmdr
918 for i in range(1, game.state.rembase+1):
919 basetbl.append((i, distance(game.state.baseq[i], sc)))
920 if game.state.rembase > 1:
921 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
922 # look for nearest base without a commander, no Enterprise, and
923 # without too many Klingons, and not already under attack.
924 ifindit = iwhichb = 0
925 for i2 in range(1, game.state.rembase+1):
926 i = basetbl[i2][0]; # bug in original had it not finding nearest
927 ibq = game.state.baseq[i]
928 if ibq == game.quadrant or ibq == game.battle or \
929 game.state.galaxy[ibq.x][ibq.y].supernova or \
930 game.state.galaxy[ibq.x][ibq.y].klingons > MAXKLQUAD-1:
932 # if there is a commander, and no other base is appropriate,
933 # we will take the one with the commander
934 for j in range(1, game.state.remcom+1):
935 if ibq == game.state.kcmdr[j] and ifindit!= 2:
939 if j > game.state.remcom: # no commander -- use this one
944 return; # Nothing suitable -- wait until next time
945 ibq = game.state.baseq[iwhichb]
946 # decide how to move toward base
947 idelta = ibq - game.state.kscmdr
948 # Maximum movement is 1 quadrant in either or both axes
949 idelta = idelta.sgn()
950 # try moving in both x and y directions
951 # there was what looked like a bug in the Almy C code here,
952 # but it might be this translation is just wrong.
953 iq = game.state.kscmdr + idelta
954 if movescom(iq, avoid):
955 # failed -- try some other maneuvers
956 if idelta.x==0 or idelta.y==0:
959 iq.y = game.state.kscmdr.y + 1
960 if movescom(iq, avoid):
961 iq.y = game.state.kscmdr.y - 1
964 iq.x = game.state.kscmdr.x + 1
965 if movescom(iq, avoid):
966 iq.x = game.state.kscmdr.x - 1
969 # try moving just in x or y
970 iq.y = game.state.kscmdr.y
971 if movescom(iq, avoid):
972 iq.y = game.state.kscmdr.y + idelta.y
973 iq.x = game.state.kscmdr.x
976 if game.state.rembase == 0:
979 for i in range(1, game.state.rembase+1):
980 ibq = game.state.baseq[i]
981 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
984 return; # no, don't attack base!
987 schedule(FSCDBAS, 1.0 +2.0*random.random())
988 if is_scheduled(FCDBAS):
989 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
990 if not communicating():
994 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
996 prout(_(" reports that it is under attack from the Klingon Super-commander."))
997 proutn(_(" It can survive until stardate %d.\"") \
998 % int(scheduled(FSCDBAS)))
1001 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1004 game.resting = False
1005 game.optime = 0.0; # actually finished
1007 # Check for intelligence report
1009 (random.random() > 0.2 or \
1010 (not communicating()) or \
1011 not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].charted):
1014 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
1015 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
1020 if not game.ithere or game.justin:
1023 if game.tholian.x == 1 and game.tholian.y == 1:
1024 idx = 1; idy = QUADSIZE
1025 elif game.tholian.x == 1 and game.tholian.y == QUADSIZE:
1026 idx = QUADSIZE; idy = QUADSIZE
1027 elif game.tholian.x == QUADSIZE and game.tholian.y == QUADSIZE:
1028 idx = QUADSIZE; idy = 1
1029 elif game.tholian.x == QUADSIZE and game.tholian.y == 1:
1032 # something is wrong!
1036 # do nothing if we are blocked
1037 if game.quad[idx][idy]!= IHDOT and game.quad[idx][idy]!= IHWEB:
1039 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1041 if game.tholian.x != idx:
1043 im = math.fabs(idx - game.tholian.x)*1.0/(idx - game.tholian.x)
1044 while game.tholian.x != idx:
1045 game.tholian.x += im
1046 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1047 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1048 elif game.tholian.y != idy:
1050 im = math.fabs(idy - game.tholian.y)*1.0/(idy - game.tholian.y)
1051 while game.tholian.y != idy:
1052 game.tholian.y += im
1053 if game.quad[game.tholian.x][game.tholian.y]==IHDOT:
1054 game.quad[game.tholian.x][game.tholian.y] = IHWEB
1055 game.quad[game.tholian.x][game.tholian.y] = IHT
1056 game.ks[game.nenhere] = game.tholian
1058 # check to see if all holes plugged
1059 for i in range(1, QUADSIZE+1):
1060 if game.quad[1][i]!=IHWEB and game.quad[1][i]!=IHT:
1062 if game.quad[QUADSIZE][i]!=IHWEB and game.quad[QUADSIZE][i]!=IHT:
1064 if game.quad[i][1]!=IHWEB and game.quad[i][1]!=IHT:
1066 if game.quad[i][QUADSIZE]!=IHWEB and game.quad[i][QUADSIZE]!=IHT:
1068 # All plugged up -- Tholian splits
1069 game.quad[game.tholian.x][game.tholian.y]=IHWEB
1071 crmena(True, IHT, "sector", game.tholian)
1072 prout(_(" completes web."))
1077 # Code from battle.c begins here
1079 def doshield(shraise):
1080 # change shield status
1088 if isit("transfer"):
1092 if damaged(DSHIELD):
1093 prout(_("Shields damaged and down."))
1100 proutn(_("Do you wish to change shield energy? "))
1102 proutn(_("Energy to transfer to shields- "))
1104 elif damaged(DSHIELD):
1105 prout(_("Shields damaged and down."))
1108 proutn(_("Shields are up. Do you want them down? "))
1115 proutn(_("Shields are down. Do you want them up? "))
1121 if action == "SHUP": # raise shields
1123 prout(_("Shields already up."))
1127 if game.condition != "docked":
1129 prout(_("Shields raised."))
1130 if game.energy <= 0:
1132 prout(_("Shields raising uses up last of energy."))
1137 elif action == "SHDN":
1139 prout(_("Shields already down."))
1143 prout(_("Shields lowered."))
1146 elif action == "NRG":
1147 while scan() != IHREAL:
1149 proutn(_("Energy to transfer to shields- "))
1153 if aaitem > game.energy:
1154 prout(_("Insufficient ship energy."))
1157 if game.shield+aaitem >= game.inshld:
1158 prout(_("Shield energy maximized."))
1159 if game.shield+aaitem > game.inshld:
1160 prout(_("Excess energy requested returned to ship energy"))
1161 game.energy -= game.inshld-game.shield
1162 game.shield = game.inshld
1164 if aaitem < 0.0 and game.energy-aaitem > game.inenrg:
1165 # Prevent shield drain loophole
1167 prout(_("Engineering to bridge--"))
1168 prout(_(" Scott here. Power circuit problem, Captain."))
1169 prout(_(" I can't drain the shields."))
1172 if game.shield+aaitem < 0:
1173 prout(_("All shield energy transferred to ship."))
1174 game.energy += game.shield
1177 proutn(_("Scotty- \""))
1179 prout(_("Transferring energy to shields.\""))
1181 prout(_("Draining energy from shields.\""))
1182 game.shield += aaitem
1183 game.energy -= aaitem
1187 # choose a device to damage, at random.
1189 # Quoth Eric Allman in the code of BSD-Trek:
1190 # "Under certain conditions you can get a critical hit. This
1191 # sort of hit damages devices. The probability that a given
1192 # device is damaged depends on the device. Well protected
1193 # devices (such as the computer, which is in the core of the
1194 # ship and has considerable redundancy) almost never get
1195 # damaged, whereas devices which are exposed (such as the
1196 # warp engines) or which are particularly delicate (such as
1197 # the transporter) have a much higher probability of being
1200 # This is one place where OPTION_PLAIN does not restore the
1201 # original behavior, which was equiprobable damage across
1202 # all devices. If we wanted that, we'd return NDEVICES*random.random()
1203 # and have done with it. Also, in the original game, DNAVYS
1204 # and DCOMPTR were the same device.
1206 # Instead, we use a table of weights similar to the one from BSD Trek.
1207 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
1208 # We don't have a cloaking device. The shuttle got the allocation
1209 # for the cloaking device, then we shaved a half-percent off
1210 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
1213 105, # DSRSENS: short range scanners 10.5%
1214 105, # DLRSENS: long range scanners 10.5%
1215 120, # DPHASER: phasers 12.0%
1216 120, # DPHOTON: photon torpedoes 12.0%
1217 25, # DLIFSUP: life support 2.5%
1218 65, # DWARPEN: warp drive 6.5%
1219 70, # DIMPULS: impulse engines 6.5%
1220 145, # DSHIELD: deflector shields 14.5%
1221 30, # DRADIO: subspace radio 3.0%
1222 45, # DSHUTTL: shuttle 4.5%
1223 15, # DCOMPTR: computer 1.5%
1224 20, # NAVCOMP: navigation system 2.0%
1225 75, # DTRANSP: transporter 7.5%
1226 20, # DSHCTRL: high-speed shield controller 2.0%
1227 10, # DDRAY: death ray 1.0%
1228 30, # DDSP: deep-space probes 3.0%
1230 idx = random.random() * 1000.0 # weights must sum to 1000
1232 for (i, w) in enumerate(weights):
1236 return None; # we should never get here
1238 def ram(ibumpd, ienm, w):
1239 # make our ship ram something
1240 prouts(_("***RED ALERT! RED ALERT!"))
1242 prout(_("***COLLISION IMMINENT."))
1246 hardness = {IHR:1.5, IHC:2.0, IHS:2.5, IHT:0.5, IHQUEST:4.0}.get(ienm, 1.0)
1248 proutn(_(" rammed by "))
1251 crmena(False, ienm, sector, w)
1253 proutn(_(" (original position)"))
1255 deadkl(w, ienm, game.sector)
1258 prout(_(" heavily damaged."))
1259 icas = 10.0+20.0*random.random()
1260 prout(_("***Sickbay reports %d casualties"), icas)
1262 game.state.crew -= icas
1264 # In the pre-SST2K version, all devices got equiprobably damaged,
1265 # which was silly. Instead, pick up to half the devices at
1266 # random according to our weighting table,
1268 ncrits = random.randrange(NDEVICES/2)
1269 for m in range(ncrits):
1271 if game.damage[dev] < 0:
1273 extradm = (10.0*hardness*random.random()+1.0)*game.damfac
1274 # Damage for at least time of travel!
1275 game.damage[dev] += game.optime + extradm
1277 prout(_("***Shields are down."))
1278 if game.state.remkl + game.state.remcom + game.state.nscrem:
1285 def torpedo(course, r, incoming, i, n):
1286 # let a photon torpedo fly
1289 ac = course + 0.25*r
1290 angle = (15.0-ac)*0.5235988
1291 bullseye = (15.0 - course)*0.5235988
1292 deltax = -math.sin(angle);
1293 deltay = math.cos(angle);
1294 x = incoming.x; y = incoming.y
1295 w = coord(); jw = coord()
1296 w.x = w.y = jw.x = jw.y = 0
1297 bigger = max(math.fabs(deltax), math.fabs(deltay))
1300 if not damaged(DSRSENS) or game.condition=="docked":
1301 setwnd(srscan_window)
1303 setwnd(message_window)
1304 # Loop to move a single torpedo
1305 for l in range(1, 15+1):
1310 if not VALID_SECTOR(w.x, w.y):
1312 iquad=game.quad[w.x][w.y]
1313 tracktorpedo(w, l, i, n, iquad)
1317 setwnd(message_window)
1318 if damaged(DSRSENS) and not game.condition=="docked":
1319 skip(1); # start new line after text track
1320 if iquad in (IHE, IHF): # Hit our ship
1322 proutn(_("Torpedo hits "))
1325 hit = 700.0 + 100.0*random.random() - \
1326 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1327 newcnd(); # we're blown out of dock
1328 # We may be displaced.
1329 if game.landed or game.condition=="docked":
1330 return hit # Cheat if on a planet
1331 ang = angle + 2.5*(random.random()-0.5)
1332 temp = math.fabs(math.sin(ang))
1333 if math.fabs(math.cos(ang)) > temp:
1334 temp = math.fabs(math.cos(ang))
1335 xx = -math.sin(ang)/temp
1336 yy = math.cos(ang)/temp
1339 if not VALID_SECTOR(jw.x, jw.y):
1341 if game.quad[jw.x][jw.y]==IHBLANK:
1344 if game.quad[jw.x][jw.y]!=IHDOT:
1345 # can't move into object
1350 elif iquad in (IHC, IHS): # Hit a commander
1351 if random.random() <= 0.05:
1352 crmena(True, iquad, sector, w)
1353 prout(_(" uses anti-photon device;"))
1354 prout(_(" torpedo neutralized."))
1356 elif iquad in (IHR, IHK): # Hit a regular enemy
1358 for ll in range(1, game.nenhere+1):
1359 if w == game.ks[ll]:
1361 kp = math.fabs(game.kpower[ll])
1362 h1 = 700.0 + 100.0*random.random() - \
1363 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1367 if game.kpower[ll] < 0:
1368 game.kpower[ll] -= -h1
1370 game.kpower[ll] -= h1
1371 if game.kpower[ll] == 0:
1374 crmena(True, iquad, "sector", w)
1375 # If enemy damaged but not destroyed, try to displace
1376 ang = angle + 2.5*(random.random()-0.5)
1377 temp = math.fabs(math.sin(ang))
1378 if math.fabs(math.cos(ang)) > temp:
1379 temp = math.fabs(math.cos(ang))
1380 xx = -math.sin(ang)/temp
1381 yy = math.cos(ang)/temp
1384 if not VALID_SECTOR(jw.x, jw.y):
1385 prout(_(" damaged but not destroyed."))
1387 if game.quad[jw.x][jw.y]==IHBLANK:
1388 prout(_(" buffeted into black hole."))
1389 deadkl(w, iquad, jw)
1391 if game.quad[jw.x][jw.y]!=IHDOT:
1392 # can't move into object
1393 prout(_(" damaged but not destroyed."))
1395 proutn(_(" damaged--"))
1399 elif iquad == IHB: # Hit a base
1401 prout(_("***STARBASE DESTROYED.."))
1402 for ll in range(1, game.state.rembase+1):
1403 if game.state.baseq[ll] == game.quadrant:
1404 game.state.baseq[ll]=game.state.baseq[game.state.rembase]
1406 game.quad[w.x][w.y]=IHDOT
1407 game.state.rembase -= 1
1408 game.base.x=game.base.y=0
1409 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase -= 1
1410 game.state.chart[game.quadrant.x][game.quadrant.y].starbase -= 1
1411 game.state.basekl += 1
1414 elif iquad == IHP: # Hit a planet
1415 crmena(True, iquad, sector, w)
1416 prout(_(" destroyed."))
1417 game.state.nplankl += 1
1418 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET
1419 game.state.planets[game.iplnet].pclass = destroyed
1421 invalidate(game.plnet)
1422 game.quad[w.x][w.y] = IHDOT
1424 # captain perishes on planet
1427 elif iquad == IHW: # Hit an inhabited world -- very bad!
1428 crmena(True, iquad, sector, w)
1429 prout(_(" destroyed."))
1430 game.state.nworldkl += 1
1431 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET
1432 game.state.planets[game.iplnet].pclass = destroyed
1434 invalidate(game.plnet)
1435 game.quad[w.x][w.y] = IHDOT
1437 # captain perishes on planet
1439 prout(_("You have just destroyed an inhabited planet."))
1440 prout(_("Celebratory rallies are being held on the Klingon homeworld."))
1442 elif iquad == IHSTAR: # Hit a star
1443 if random.random() > 0.10:
1446 crmena(True, IHSTAR, sector, w)
1447 prout(_(" unaffected by photon blast."))
1449 elif iquad == IHQUEST: # Hit a thingy
1450 if not (game.options & OPTION_THINGY) or random.random()>0.7:
1452 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1454 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1456 proutn(_("Mr. Spock-"))
1457 prouts(_(" \"Fascinating!\""))
1462 # Stas Sergeev added the possibility that
1463 # you can shove the Thingy and piss it off.
1464 # It then becomes an enemy and may fire at you.
1469 elif iquad == IHBLANK: # Black hole
1471 crmena(True, IHBLANK, sector, w)
1472 prout(_(" swallows torpedo."))
1474 elif iquad == IHWEB: # hit the web
1476 prout(_("***Torpedo absorbed by Tholian web."))
1478 elif iquad == IHT: # Hit a Tholian
1479 h1 = 700.0 + 100.0*random.random() - \
1480 1000.0 * distance(w, incoming) * math.fabs(math.sin(bullseye-angle))
1483 game.quad[w.x][w.y] = IHDOT
1488 crmena(True, IHT, sector, w)
1489 if random.random() > 0.05:
1490 prout(_(" survives photon blast."))
1492 prout(_(" disappears."))
1493 game.quad[w.x][w.y] = IHWEB
1500 proutn("Don't know how to handle torpedo collision with ")
1501 crmena(True, iquad, sector, w)
1505 if curwnd!=message_window:
1506 setwnd(message_window)
1508 game.quad[w.x][w.y]=IHDOT
1509 game.quad[jw.x][jw.y]=iquad
1510 prout(_(" displaced by blast to Sector %s ") % jw)
1511 for ll in range(1, game.nenhere+1):
1512 game.kdist[ll] = game.kavgd[ll] = distance(game.sector,game.ks[ll])
1516 prout(_("Torpedo missed."))
1520 # critical-hit resolution
1522 # a critical hit occured
1523 if hit < (275.0-25.0*game.skill)*(1.0+0.5*random.random()):
1526 ncrit = 1.0 + hit/(500.0+100.0*random.random())
1527 proutn(_("***CRITICAL HIT--"))
1528 # Select devices and cause damage
1530 for loop1 in range(ncrit):
1533 # Cheat to prevent shuttle damage unless on ship
1534 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1537 extradm = (hit*game.damfac)/(ncrit*(75.0+25.0*random.random()))
1538 game.damage[j] += extradm
1540 for loop2 in range(loop1):
1541 if j == cdam[loop2]:
1550 prout(_(" damaged."))
1551 if damaged(DSHIELD) and game.shldup:
1552 prout(_("***Shields knocked down."))
1555 def attack(torps_ok):
1556 # bad guy attacks us
1557 # torps_ok == false forces use of phasers in an attack
1558 atackd = False; attempt = False; ihurt = False;
1559 hitmax=0.0; hittot=0.0; chgfac=1.0
1563 # game could be over at this point, check
1568 prout("=== ATTACK!")
1570 # Tholian gewts to move before attacking
1574 # if you have just entered the RNZ, you'll get a warning
1575 if game.neutz: # The one chance not to be attacked
1579 # commanders get a chance to tac-move towards you
1580 if (((game.comhere or game.ishere) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1583 # if no enemies remain after movement, we're done
1584 if game.nenhere==0 or (game.nenhere==1 and iqhere and not iqengry):
1587 # set up partial hits if attack happens during shield status change
1588 pfac = 1.0/game.inshld
1590 chgfac = 0.25+0.5*random.random()
1594 # message verbosity control
1595 if game.skill <= SKILL_FAIR:
1598 for loop in range(1, game.nenhere+1):
1599 if game.kpower[loop] < 0:
1600 continue; # too weak to attack
1601 # compute hit strength and diminish shield power
1603 # Increase chance of photon torpedos if docked or enemy energy low
1604 if game.condition == "docked":
1606 if game.kpower[loop] < 500:
1609 iquad = game.quad[jay.x][jay.y]
1610 if iquad==IHT or (iquad==IHQUEST and not iqengry):
1612 # different enemies have different probabilities of throwing a torp
1613 usephasers = not torps_ok or \
1614 (iquad == IHK and r > 0.0005) or \
1615 (iquad==IHC and r > 0.015) or \
1616 (iquad==IHR and r > 0.3) or \
1617 (iquad==IHS and r > 0.07) or \
1618 (iquad==IHQUEST and r > 0.05)
1619 if usephasers: # Enemy uses phasers
1620 if game.condition == "docked":
1621 continue; # Don't waste the effort!
1622 attempt = True; # Attempt to attack
1623 dustfac = 0.8+0.05*random.random()
1624 hit = game.kpower[loop]*math.pow(dustfac,game.kavgd[loop])
1625 game.kpower[loop] *= 0.75
1626 else: # Enemy uses photon torpedo
1627 course = 1.90985*math.atan2(game.sector.y-jay.y, jay.x-game.sector.x)
1629 proutn(_("***TORPEDO INCOMING"))
1630 if not damaged(DSRSENS):
1632 crmena(False, iquad, where, jay)
1635 r = (random.random()+random.random())*0.5 -0.5
1636 r += 0.002*game.kpower[loop]*r
1637 hit = torpedo(course, r, jay, 1, 1)
1638 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1639 finish(FWON); # Klingons did themselves in!
1640 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.alldone:
1641 return; # Supernova or finished
1644 # incoming phaser or torpedo, shields may dissipate it
1645 if game.shldup or game.shldchg or game.condition=="docked":
1646 # shields will take hits
1647 propor = pfac * game.shield
1648 if game.condition =="docked":
1652 hitsh = propor*chgfac*hit+1.0
1654 if absorb > game.shield:
1655 absorb = game.shield
1656 game.shield -= absorb
1658 # taking a hit blasts us out of a starbase dock
1659 if game.condition == "docked":
1661 # but the shields may take care of it
1662 if propor > 0.1 and hit < 0.005*game.energy:
1664 # hit from this opponent got through shields, so take damage
1666 proutn(_("%d unit hit") % int(hit))
1667 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1668 proutn(_(" on the "))
1670 if not damaged(DSRSENS) and usephasers:
1672 crmena(False, iquad, where, jay)
1674 # Decide if hit is critical
1680 if game.energy <= 0:
1681 # Returning home upon your shield, not with it...
1684 if not attempt and game.condition == "docked":
1685 prout(_("***Enemies decide against attacking your ship."))
1688 percent = 100.0*pfac*game.shield+0.5
1690 # Shields fully protect ship
1691 proutn(_("Enemy attack reduces shield strength to "))
1693 # Print message if starship suffered hit(s)
1695 proutn(_("Energy left %2d shields ") % int(game.energy))
1698 elif not damaged(DSHIELD):
1701 proutn(_("damaged, "))
1702 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1703 # Check if anyone was hurt
1704 if hitmax >= 200 or hittot >= 500:
1705 icas= hittot*random.random()*0.015
1708 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1709 prout(_(" in that last attack.\""))
1711 game.state.crew -= icas
1712 # After attack, reset average distance to enemies
1713 for loop in range(1, game.nenhere+1):
1714 game.kavgd[loop] = game.kdist[loop]
1718 def deadkl(w, type, mv):
1719 # kill a Klingon, Tholian, Romulan, or Thingy
1720 # Added mv to allow enemy to "move" before dying
1722 crmena(True, type, sector, mv)
1723 # Decide what kind of enemy it is and update appropriately
1725 # chalk up a Romulan
1726 game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans -= 1
1728 game.state.nromrem -= 1
1732 elif type == IHQUEST:
1734 iqhere = iqengry = False
1737 # Some type of a Klingon
1738 game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons -= 1
1741 game.comhere = False
1742 for i in range(1, game.state.remcom+1):
1743 if game.state.kcmdr[i] == game.quadrant:
1745 game.state.kcmdr[i] = game.state.kcmdr[game.state.remcom]
1746 game.state.kcmdr[game.state.remcom].x = 0
1747 game.state.kcmdr[game.state.remcom].y = 0
1748 game.state.remcom -= 1
1750 if game.state.remcom != 0:
1751 schedule(FTBEAM, expran(1.0*game.incom/game.state.remcom))
1753 game.state.remkl -= 1
1755 game.state.nscrem -= 1
1757 game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
1762 prout("*** Internal error, deadkl() called on %s\n" % type)
1764 # For each kind of enemy, finish message to player
1765 prout(_(" destroyed."))
1766 game.quad[w.x][w.y] = IHDOT
1767 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1770 # Remove enemy ship from arrays describing local conditions
1771 if is_scheduled(FCDBAS) and game.battle == game.quadrant and type==IHC:
1773 for i in range(1, game.nenhere+1):
1777 if i <= game.nenhere:
1778 for j in range(i, game.nenhere+1):
1779 game.ks[j] = game.ks[j+1]
1780 game.kpower[j] = game.kpower[j+1]
1781 game.kavgd[j] = game.kdist[j] = game.kdist[j+1]
1782 game.ks[game.nenhere+1].x = 0
1783 game.ks[game.nenhere+1].x = 0
1784 game.kdist[game.nenhere+1] = 0
1785 game.kavgd[game.nenhere+1] = 0
1786 game.kpower[game.nenhere+1] = 0
1789 def targetcheck(x, y):
1790 # Return None if target is invalid
1791 if not VALID_SECTOR(x, y):
1794 deltx = 0.1*(y - game.sector.y)
1795 delty = 0.1*(x - game.sector.x)
1796 if deltx==0 and delty== 0:
1798 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1799 prout(_(" I recommend an immediate review of"))
1800 prout(_(" the Captain's psychological profile.\""))
1803 return 1.90985932*math.atan2(deltx, delty)
1806 # launch photon torpedo
1808 if damaged(DPHOTON):
1809 prout(_("Photon tubes damaged."))
1813 prout(_("No torpedoes left."))
1822 prout(_("%d torpedoes left.") % game.torps)
1823 proutn(_("Number of torpedoes to fire- "))
1825 else: # key == IHREAL {
1827 if n <= 0: # abort command
1832 prout(_("Maximum of 3 torpedoes per burst."))
1839 for i in range(1, n+1):
1841 if i==1 and key == IHEOL:
1842 break; # we will try prompting
1843 if i==2 and key == IHEOL:
1844 # direct all torpedoes at one target
1846 targ[i][1] = targ[1][1]
1847 targ[i][2] = targ[1][2]
1848 course[i] = course[1]
1860 course[i] = targetcheck(targ[i][1], targ[i][2])
1861 if course[i] == None:
1864 if i == 1 and key == IHEOL:
1865 # prompt for each one
1866 for i in range(1, n+1):
1867 proutn(_("Target sector for torpedo number %d- ") % i)
1879 course[i] = targetcheck(targ[i][1], targ[i][2])
1880 if course[i] == None:
1883 # Loop for moving <n> torpedoes
1884 for i in range(1, n+1):
1885 if game.condition != "docked":
1887 r = (random.random()+random.random())*0.5 -0.5
1888 if math.fabs(r) >= 0.47:
1890 r = (random.random()+1.2) * r
1892 prouts(_("***TORPEDO NUMBER %d MISFIRES") % i)
1894 prouts(_("***TORPEDO MISFIRES."))
1897 prout(_(" Remainder of burst aborted."))
1898 if random.random() <= 0.2:
1899 prout(_("***Photon tubes damaged by misfire."))
1900 game.damage[DPHOTON] = game.damfac*(1.0+2.0*random.random())
1902 if game.shldup or game.condition == "docked":
1903 r *= 1.0 + 0.0001*game.shield
1904 torpedo(course[i], r, game.sector, i, n)
1905 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
1907 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1911 # check for phasers overheating
1913 chekbrn = (rpow-1500.)*0.00038
1914 if random.random() <= chekbrn:
1915 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1916 game.damage[DPHASER] = game.damfac*(1.0 + random.random()) * (1.0+chekbrn)
1918 def checkshctrl(rpow):
1919 # check shield control
1922 if random.random() < 0.998:
1923 prout(_("Shields lowered."))
1925 # Something bad has happened
1926 prouts(_("***RED ALERT! RED ALERT!"))
1928 hit = rpow*game.shield/game.inshld
1929 game.energy -= rpow+hit*0.8
1930 game.shield -= hit*0.2
1931 if game.energy <= 0.0:
1932 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1937 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1939 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1940 icas = hit*random.random()*0.012
1945 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1946 prout(_(" %d casualties so far.\"") % icas)
1948 game.state.crew -= icas
1950 prout(_("Phaser energy dispersed by shields."))
1951 prout(_("Enemy unaffected."))
1955 def hittem(doublehits):
1956 # register a phaser hit on Klingons and Romulans
1957 nenhr2=game.nenhere; kk=1
1960 for k in range(1, nenhr2+1):
1964 dustfac = 0.9 + 0.01*random.random()
1965 hit = wham*math.pow(dustfac,game.kdist[kk])
1966 kpini = game.kpower[kk]
1967 kp = math.fabs(kpini)
1968 if PHASEFAC*hit < kp:
1970 if game.kpower[kk] < 0:
1971 game.kpower[kk] -= -kp
1973 game.kpower[kk] -= kp
1974 kpow = game.kpower[kk]
1977 if not damaged(DSRSENS):
1979 proutn(_("%d unit hit on ") % int(hit))
1981 proutn(_("Very small hit on "))
1982 ienm = game.quad[w.x][w.y]
1985 crmena(False, ienm, "sector", w)
1989 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
1993 kk -= 1; # don't do the increment
1994 else: # decide whether or not to emasculate klingon
1995 if kpow > 0 and random.random() >= 0.9 and \
1996 kpow <= ((0.4 + 0.4*random.random())*kpini):
1997 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s"), w)
1998 prout(_(" has just lost its firepower.\""))
1999 game.kpower[kk] = -kpow
2006 kz = 0; k = 1; irec=0 # Cheating inhibitor
2007 ifast = False; no = False; itarg = True; msgflag = True
2012 # SR sensors and Computer are needed fopr automode
2013 if damaged(DSRSENS) or damaged(DCOMPTR):
2015 if game.condition == "docked":
2016 prout(_("Phasers can't be fired through base shields."))
2019 if damaged(DPHASER):
2020 prout(_("Phaser control damaged."))
2024 if damaged(DSHCTRL):
2025 prout(_("High speed shield control damaged."))
2028 if game.energy <= 200.0:
2029 prout(_("Insufficient energy to activate high-speed shield control."))
2032 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
2035 # Original code so convoluted, I re-did it all
2036 while automode=="NOTSET":
2041 prout(_("There is no enemy present to select."))
2044 automode="AUTOMATIC"
2048 elif isit("automatic"):
2049 if (not itarg) and game.nenhere != 0:
2050 automode = "FORCEMAN"
2053 prout(_("Energy will be expended into space."))
2054 automode = "AUTOMATIC"
2063 prout(_("Energy will be expended into space."))
2064 automode = "AUTOMATIC"
2066 automode = "FORCEMAN"
2068 automode = "AUTOMATIC"
2072 prout(_("Energy will be expended into space."))
2073 automode = "AUTOMATIC"
2075 automode = "FORCEMAN"
2077 proutn(_("Manual or automatic? "))
2081 if automode == "AUTOMATIC":
2082 if key == IHALPHA and isit("no"):
2085 if key != IHREAL and game.nenhere != 0:
2086 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
2091 for i in range(1, game.nenhere+1):
2092 irec += math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))*(1.01+0.05*random.random()) + 1.0
2094 proutn(_("%d units required. ") % irec)
2096 proutn(_("Units to fire= "))
2102 proutn(_("Energy available= %.2f") % avail)
2105 if not rpow > avail:
2112 if key == IHALPHA and isit("no"):
2115 game.energy -= 200; # Go and do it!
2116 if checkshctrl(rpow):
2124 for i in range(1, game.nenhere+1):
2128 hits[i] = math.fabs(game.kpower[i])/(PHASEFAC*math.pow(0.90,game.kdist[i]))
2129 over = (0.01 + 0.05*random.random())*hits[i]
2131 powrem -= hits[i] + over
2132 if powrem <= 0 and temp < hits[i]:
2141 if extra > 0 and not game.alldone:
2143 proutn(_("*** Tholian web absorbs "))
2145 proutn(_("excess "))
2146 prout(_("phaser energy."))
2148 prout(_("%d expended on empty space.") % int(extra))
2149 elif automode == "FORCEMAN":
2152 if damaged(DCOMPTR):
2153 prout(_("Battle computer damaged, manual fire only."))
2156 prouts(_("---WORKING---"))
2158 prout(_("Short-range-sensors-damaged"))
2159 prout(_("Insufficient-data-for-automatic-phaser-fire"))
2160 prout(_("Manual-fire-must-be-used"))
2162 elif automode == "MANUAL":
2164 for k in range(1, game.nenhere+1):
2166 ienm = game.quad[aim.x][aim.y]
2168 proutn(_("Energy available= %.2f") % (avail-0.006))
2172 if damaged(DSRSENS) and not (abs(game.sector.x-aim.x) < 2 and abs(game.sector.y-aim.y) < 2) and \
2173 (ienm == IHC or ienm == IHS):
2175 prout(_(" can't be located without short range scan."))
2178 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
2183 if itarg and k > kz:
2184 irec=(abs(game.kpower[k])/(PHASEFAC*math.pow(0.9,game.kdist[k]))) * (1.01+0.05*random.random()) + 1.0
2187 if not damaged(DCOMPTR):
2192 proutn(_("units to fire at "))
2193 crmena(False, ienm, sector, aim)
2196 if key == IHALPHA and isit("no"):
2204 if k==1: # Let me say I'm baffled by this
2213 # If total requested is too much, inform and start over
2215 prout(_("Available energy exceeded -- try again."))
2218 key = scan(); # scan for next value
2221 # zero energy -- abort
2224 if key == IHALPHA and isit("no"):
2229 game.energy -= 200.0
2230 if checkshctrl(rpow):
2234 # Say shield raised or malfunction, if necessary
2240 if random.random() >= 0.99:
2241 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
2242 prouts(_(" CLICK CLICK POP . . ."))
2243 prout(_(" No response, sir!"))
2246 prout(_("Shields raised."))
2251 # Code from events,c begins here.
2253 # This isn't a real event queue a la BSD Trek yet -- you can only have one
2254 # event of each type active at any given time. Mostly these means we can
2255 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
2256 # BSD Trek, from which we swiped the idea, can have up to 5.
2260 def unschedule(evtype):
2261 # remove an event from the schedule
2262 game.future[evtype].date = FOREVER
2263 return game.future[evtype]
2265 def is_scheduled(evtype):
2266 # is an event of specified type scheduled
2267 return game.future[evtype].date != FOREVER
2269 def scheduled(evtype):
2270 # when will this event happen?
2271 return game.future[evtype].date
2273 def schedule(evtype, offset):
2274 # schedule an event of specified type
2275 game.future[evtype].date = game.state.date + offset
2276 return game.future[evtype]
2278 def postpone(evtype, offset):
2279 # postpone a scheduled event
2280 game.future[evtype].date += offset
2283 # rest period is interrupted by event
2286 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
2288 game.resting = False
2295 # run through the event queue looking for things to do
2297 fintim = game.state.date + game.optime; yank=0
2298 ictbeam = False; istract = False
2299 w = coord(); hold = coord()
2300 ev = event(); ev2 = event()
2303 # tractor beaming cases merge here
2304 yank = math.sqrt(yank)
2306 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
2310 prout(_(" caught in long range tractor beam--"))
2311 # If Kirk & Co. screwing around on planet, handle
2312 atover(True) # atover(true) is Grab
2315 if game.icraft: # Caught in Galileo?
2318 # Check to see if shuttle is aboard
2319 if game.iscraft == "offship":
2321 if random.random() > 0.5:
2322 prout(_("Galileo, left on the planet surface, is captured"))
2323 prout(_("by aliens and made into a flying McDonald's."))
2324 game.damage[DSHUTTL] = -10
2325 game.iscraft = "removed"
2327 prout(_("Galileo, left on the planet surface, is well hidden."))
2329 game.quadrant = game.state.kscmdr
2331 game.quadrant = game.state.kcmdr[i]
2332 game.sector = randplace(QUADSIZE)
2334 prout(_(" is pulled to Quadrant %s, Sector %s") \
2335 % (game.quadrant, game.sector))
2337 prout(_("(Remainder of rest/repair period cancelled.)"))
2338 game.resting = False
2340 if not damaged(DSHIELD) and game.shield > 0:
2341 doshield(True) # raise shields
2344 prout(_("(Shields not currently useable.)"))
2346 # Adjust finish time to time of tractor beaming
2347 fintim = game.state.date+game.optime
2349 if game.state.remcom <= 0:
2352 schedule(FTBEAM, game.optime+expran(1.5*game.intime/game.state.remcom))
2355 # Code merges here for any commander destroying base
2356 # Not perfect, but will have to do
2357 # Handle case where base is in same quadrant as starship
2358 if game.battle == game.quadrant:
2359 game.state.chart[game.battle.x][game.battle.y].starbase = False
2360 game.quad[game.base.x][game.base.y] = IHDOT
2361 game.base.x=game.base.y=0
2364 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2365 elif game.state.rembase != 1 and communicating():
2366 # Get word via subspace radio
2369 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2370 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2372 prout(_("the Klingon Super-Commander"))
2374 prout(_("a Klingon Commander"))
2375 game.state.chart[game.battle.x][game.battle.y].starbase = False
2376 # Remove Starbase from galaxy
2377 game.state.galaxy[game.battle.x][game.battle.y].starbase = False
2378 for i in range(1, game.state.rembase+1):
2379 if game.state.baseq[i] == game.battle:
2380 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2381 game.state.rembase -= 1
2383 # reinstate a commander's base attack
2387 invalidate(game.battle)
2390 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2391 for i in range(1, NEVENTS):
2392 if i == FSNOVA: proutn("=== Supernova ")
2393 elif i == FTBEAM: proutn("=== T Beam ")
2394 elif i == FSNAP: proutn("=== Snapshot ")
2395 elif i == FBATTAK: proutn("=== Base Attack ")
2396 elif i == FCDBAS: proutn("=== Base Destroy ")
2397 elif i == FSCMOVE: proutn("=== SC Move ")
2398 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2399 elif i == FDSPROB: proutn("=== Probe Move ")
2400 elif i == FDISTR: proutn("=== Distress Call ")
2401 elif i == FENSLV: proutn("=== Enslavement ")
2402 elif i == FREPRO: proutn("=== Klingon Build ")
2404 prout("%.2f" % (scheduled(i)))
2407 radio_was_broken = damaged(DRADIO)
2410 # Select earliest extraneous event, evcode==0 if no events
2415 for l in range(1, NEVENTS):
2416 if game.future[l].date < datemin:
2419 prout("== Event %d fires" % evcode)
2420 datemin = game.future[l].date
2421 xtime = datemin-game.state.date
2422 game.state.date = datemin
2423 # Decrement Federation resources and recompute remaining time
2424 game.state.remres -= (game.state.remkl+4*game.state.remcom)*xtime
2426 if game.state.remtime <=0:
2429 # Any crew left alive?
2430 if game.state.crew <=0:
2433 # Is life support adequate?
2434 if damaged(DLIFSUP) and game.condition != "docked":
2435 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2438 game.lsupres -= xtime
2439 if game.damage[DLIFSUP] <= xtime:
2440 game.lsupres = game.inlsr
2443 if game.condition == "docked":
2444 repair /= game.docfac
2445 # Don't fix Deathray here
2446 for l in range(0, NDEVICES):
2447 if game.damage[l] > 0.0 and l != DDRAY:
2448 if game.damage[l]-repair > 0.0:
2449 game.damage[l] -= repair
2451 game.damage[l] = 0.0
2452 # If radio repaired, update star chart and attack reports
2453 if radio_was_broken and not damaged(DRADIO):
2454 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2455 prout(_(" surveillance reports are coming in."))
2457 if not game.iseenit:
2461 prout(_(" The star chart is now up to date.\""))
2463 # Cause extraneous event EVCODE to occur
2464 game.optime -= xtime
2465 if evcode == FSNOVA: # Supernova
2468 schedule(FSNOVA, expran(0.5*game.intime))
2469 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2471 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2472 if game.state.nscrem == 0 or \
2473 ictbeam or istract or \
2474 game.condition=="docked" or game.isatb==1 or game.iscate:
2476 if game.ientesc or \
2477 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2478 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2479 (damaged(DSHIELD) and \
2480 (game.energy < 2500 or damaged(DPHASER)) and \
2481 (game.torps < 5 or damaged(DPHOTON))):
2484 yank = distance(game.state.kscmdr, game.quadrant)
2489 elif evcode == FTBEAM: # Tractor beam
2490 if game.state.remcom == 0:
2493 i = random.random()*game.state.remcom+1.0
2494 yank = square(game.state.kcmdr[i].x-game.quadrant.x) + square(game.state.kcmdr[i].y-game.quadrant.y)
2495 if istract or game.condition == "docked" or yank == 0:
2496 # Drats! Have to reschedule
2498 game.optime + expran(1.5*game.intime/game.state.remcom))
2502 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2503 game.snapsht = game.state
2504 game.state.snap = True
2505 schedule(FSNAP, expran(0.5 * game.intime))
2506 elif evcode == FBATTAK: # Commander attacks starbase
2507 if game.state.remcom==0 or game.state.rembase==0:
2513 for j in range(1, game.state.rembase+1):
2514 for k in range(1, game.state.remcom+1):
2515 if game.state.baseq[j] == game.state.kcmdr[k] and \
2516 not game.state.baseq[j] == game.quadrant and \
2517 not game.state.baseq[j] == game.state.kscmdr:
2521 if j>game.state.rembase:
2522 # no match found -- try later
2523 schedule(FBATTAK, expran(0.3*game.intime))
2526 # commander + starbase combination found -- launch attack
2527 game.battle = game.state.baseq[j]
2528 schedule(FCDBAS, 1.0+3.0*random.random())
2529 if game.isatb: # extra time if SC already attacking
2530 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2531 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2532 game.iseenit = False
2533 if not communicating():
2534 continue # No warning :-(
2538 proutn(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2539 prout(_(" reports that it is under attack and that it can"))
2540 proutn(_(" hold out only until stardate %d") % (int(scheduled(FCDBAS))))
2544 elif evcode == FSCDBAS: # Supercommander destroys base
2547 if not game.state.galaxy[game.state.kscmdr.x][game.state.kscmdr.y].starbase:
2548 continue # WAS RETURN!
2550 game.battle = game.state.kscmdr
2552 elif evcode == FCDBAS: # Commander succeeds in destroying base
2555 # find the lucky pair
2556 for i in range(1, game.state.remcom+1):
2557 if game.state.kcmdr[i] == game.battle:
2559 if i > game.state.remcom or game.state.rembase == 0 or \
2560 not game.state.galaxy[game.battle.x][game.battle.y].starbase:
2561 # No action to take after all
2562 invalidate(game.battle)
2565 elif evcode == FSCMOVE: # Supercommander moves
2566 schedule(FSCMOVE, 0.2777)
2567 if not game.ientesc and not istract and game.isatb != 1 and \
2568 (not game.iscate or not game.justin):
2570 elif evcode == FDSPROB: # Move deep space probe
2571 schedule(FDSPROB, 0.01)
2572 game.probex += game.probeinx
2573 game.probey += game.probeiny
2574 i = (int)(game.probex/QUADSIZE +0.05)
2575 j = (int)(game.probey/QUADSIZE + 0.05)
2576 if game.probec.x != i or game.probec.y != j:
2579 if not VALID_QUADRANT(i, j) or \
2580 game.state.galaxy[game.probec.x][game.probec.y].supernova:
2581 # Left galaxy or ran into supernova
2585 proutn(_("Lt. Uhura- \"The deep space probe "))
2586 if not VALID_QUADRANT(j, i):
2587 proutn(_("has left the galaxy"))
2589 proutn(_("is no longer transmitting"))
2593 if not communicating():
2596 proutn(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probec)
2597 pdest = game.state.galaxy[game.probec.x][game.probec.y]
2598 # Update star chart if Radio is working or have access to radio
2600 chp = game.state.chart[game.probec.x][game.probec.y]
2601 chp.klingons = pdest.klingons
2602 chp.starbase = pdest.starbase
2603 chp.stars = pdest.stars
2604 pdest.charted = True
2605 game.proben -= 1 # One less to travel
2606 if game.proben == 0 and game.isarmed and pdest.stars:
2607 # lets blow the sucker!
2608 supernova(True, game.probec)
2610 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2612 elif evcode == FDISTR: # inhabited system issues distress call
2614 # try a whole bunch of times to find something suitable
2615 for i in range(100):
2616 # need a quadrant which is not the current one,
2617 # which has some stars which are inhabited and
2618 # not already under attack, which is not
2619 # supernova'ed, and which has some Klingons in it
2620 w = randplace(GALSIZE)
2621 q = game.state.galaxy[w.x][w.y]
2622 if not (game.quadrant == w or q.planet == NOPLANET or \
2623 not game.state.planets[q.planet].inhabited or \
2624 q.supernova or q.status!=secure or q.klingons<=0):
2627 # can't seem to find one; ignore this call
2629 prout("=== Couldn't find location for distress event.")
2631 # got one!! Schedule its enslavement
2632 ev = schedule(FENSLV, expran(game.intime))
2634 q.status = distressed
2636 # tell the captain about it if we can
2638 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2640 prout(_("by a Klingon invasion fleet."))
2643 elif evcode == FENSLV: # starsystem is enslaved
2644 ev = unschedule(FENSLV)
2645 # see if current distress call still active
2646 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2650 q.status = "enslaved"
2652 # play stork and schedule the first baby
2653 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2654 ev2.quadrant = ev.quadrant
2656 # report the disaster if we can
2658 prout(_("Uhura- We've lost contact with starsystem %s") % \
2660 prout(_("in Quadrant %s.\n") % ev.quadrant)
2661 elif evcode == FREPRO: # Klingon reproduces
2662 # If we ever switch to a real event queue, we'll need to
2663 # explicitly retrieve and restore the x and y.
2664 ev = schedule(FREPRO, expran(1.0 * game.intime))
2665 # see if current distress call still active
2666 q = game.state.galaxy[ev.quadrant.x][ev.quadrant.y]
2670 if game.state.remkl >=MAXKLGAME:
2671 continue # full right now
2672 # reproduce one Klingon
2674 if game.klhere >= MAXKLQUAD:
2676 # this quadrant not ok, pick an adjacent one
2677 for i in range(w.x - 1, w.x + 2):
2678 for j in range(w.y - 1, w.y + 2):
2679 if not VALID_QUADRANT(i, j):
2681 q = game.state.galaxy[w.x][w.y]
2682 # check for this quad ok (not full & no snova)
2683 if q.klingons >= MAXKLQUAD or q.supernova:
2687 continue # search for eligible quadrant failed
2692 game.state.remkl += 1
2694 if game.quadrant == w:
2696 newkling(game.klhere)
2697 # recompute time left
2699 # report the disaster if we can
2701 if game.quadrant == w:
2702 prout(_("Spock- sensors indicate the Klingons have"))
2703 prout(_("launched a warship from %s.") % q.planet)
2705 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2706 if q.planet != NOPLANET:
2707 proutn(_("near %s") % q.planet)
2708 prout(_("in Quadrant %s.") % w)
2717 proutn(_("How long? "))
2722 origTime = delay = aaitem
2725 if delay >= game.state.remtime or game.nenhere != 0:
2726 proutn(_("Are you sure? "))
2730 # Alternate resting periods (events) with attacks
2735 game.resting = False
2736 if not game.resting:
2737 prout(_("%d stardates left.") % int(game.state.remtime))
2739 temp = game.optime = delay
2741 rtime = 1.0 + random.random()
2745 if game.optime < delay:
2754 # Repair Deathray if long rest at starbase
2755 if origTime-delay >= 9.99 and game.condition == "docked":
2756 game.damage[DDRAY] = 0.0
2757 # leave if quadrant supernovas
2758 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
2760 game.resting = False
2763 # A nova occurs. It is the result of having a star hit with a
2764 # photon torpedo, or possibly of a probe warhead going off.
2765 # Stars that go nova cause stars which surround them to undergo
2766 # the same probabilistic process. Klingons next to them are
2767 # destroyed. And if the starship is next to it, it gets zapped.
2768 # If the zap is too much, it gets destroyed.
2772 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2773 newc = coord(); scratch = coord()
2775 if random.random() < 0.05:
2776 # Wow! We've supernova'ed
2777 supernova(False, nov)
2780 # handle initial nova
2781 game.quad[nov.x][nov.y] = IHDOT
2782 crmena(False, IHSTAR, sector, nov)
2784 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2785 game.state.starkl += 1
2787 # Set up stack to recursively trigger adjacent stars
2788 bot = top = top2 = 1
2794 for mm in range(bot, top+1):
2795 for nn in range(1, 3+1): # nn,j represents coordinates around current
2796 for j in range(1, 3+1):
2799 scratch.x = hits[mm][1]+nn-2
2800 scratch.y = hits[mm][2]+j-2
2801 if not VALID_SECTOR(scratch.y, scratch.x):
2803 iquad = game.quad[scratch.x][scratch.y]
2804 # Empty space ends reaction
2805 if iquad in (IHDOT, IHQUEST, IHBLANK, IHT, IHWEB):
2807 elif iquad == IHSTAR: # Affect another star
2808 if random.random() < 0.05:
2809 # This star supernovas
2810 scratch = supernova(False)
2813 hits[top2][1]=scratch.x
2814 hits[top2][2]=scratch.y
2815 game.state.galaxy[game.quadrant.x][game.quadrant.y].stars -= 1
2816 game.state.starkl += 1
2817 crmena(True, IHSTAR, sector, scratch)
2819 game.quad[scratch.x][scratch.y] = IHDOT
2820 elif iquad == IHP: # Destroy planet
2821 game.state.galaxy[game.quadrant.x][game.quadrant.y].planet = NOPLANET
2822 game.state.nplankl += 1
2823 crmena(True, IHP, sector, scratch)
2824 prout(_(" destroyed."))
2825 game.state.planets[game.iplnet].pclass = destroyed
2827 invalidate(game.plnet)
2831 game.quad[scratch.x][scratch.y] = IHDOT
2832 elif iquad == IHB: # Destroy base
2833 game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase = False
2834 for i in range(1, game.state.rembase+1):
2835 if game.state.baseq[i] == game.quadrant:
2837 game.state.baseq[i] = game.state.baseq[game.state.rembase]
2838 game.state.rembase -= 1
2839 invalidate(game.base)
2840 game.state.basekl += 1
2842 crmena(True, IHB, sector, scratch)
2843 prout(_(" destroyed."))
2844 game.quad[scratch.x][scratch.y] = IHDOT
2845 elif iquad in (IHE, IHF): # Buffet ship
2846 prout(_("***Starship buffeted by nova."))
2848 if game.shield >= 2000.0:
2849 game.shield -= 2000.0
2851 diff = 2000.0 - game.shield
2855 prout(_("***Shields knocked out."))
2856 game.damage[DSHIELD] += 0.005*game.damfac*random.random()*diff
2858 game.energy -= 2000.0
2859 if game.energy <= 0:
2862 # add in course nova contributes to kicking starship
2863 icx += game.sector.x-hits[mm][1]
2864 icy += game.sector.y-hits[mm][2]
2866 elif iquad == IHK: # kill klingon
2867 deadkl(scratch,iquad, scratch)
2868 elif iquad in (IHC,IHS,IHR): # Damage/destroy big enemies
2869 for ll in range(1, game.nenhere+1):
2870 if game.ks[ll] == scratch:
2872 game.kpower[ll] -= 800.0 # If firepower is lost, die
2873 if game.kpower[ll] <= 0.0:
2874 deadkl(scratch, iquad, scratch)
2876 newc.x = scratch.x + scratch.x - hits[mm][1]
2877 newc.y = scratch.y + scratch.y - hits[mm][2]
2878 crmena(True, iquad, sector, scratch)
2879 proutn(_(" damaged"))
2880 if not VALID_SECTOR(newc.x, newc.y):
2881 # can't leave quadrant
2884 iquad1 = game.quad[newc.x][newc.y]
2885 if iquad1 == IHBLANK:
2886 proutn(_(", blasted into "))
2887 crmena(False, IHBLANK, sector, newc)
2889 deadkl(scratch, iquad, newc)
2892 # can't move into something else
2895 proutn(_(", buffeted to Sector %s") % newc)
2896 game.quad[scratch.x][scratch.y] = IHDOT
2897 game.quad[newc.x][newc.y] = iquad
2899 game.kdist[ll] = game.kavgd[ll] = distance(game.sector, newc)
2908 # Starship affected by nova -- kick it away.
2909 game.dist = kount*0.1
2912 game.direc = course[3*(icx+1)+icy+2]
2913 if game.direc == 0.0:
2915 if game.dist == 0.0:
2917 game.optime = 10.0*game.dist/16.0
2919 prout(_("Force of nova displaces starship."))
2921 game.optime = 10.0*game.dist/16.0
2924 def supernova(induced, w=None):
2925 # star goes supernova
2933 # Scheduled supernova -- select star
2934 # logic changed here so that we won't favor quadrants in top
2936 for nq.x in range(1, GALSIZE+1):
2937 for nq.y in range(1, GALSIZE+1):
2938 stars += game.state.galaxy[nq.x][nq.y].stars
2940 return # nothing to supernova exists
2941 num = random.random()*stars + 1
2942 for nq.x in range(1, GALSIZE+1):
2943 for nq.y in range(1, GALSIZE+1):
2944 num -= game.state.galaxy[nq.x][nq.y].stars
2950 proutn("=== Super nova here?")
2954 if not nq == game.quadrant or game.justin:
2955 # it isn't here, or we just entered (treat as enroute)
2958 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2959 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2962 # we are in the quadrant!
2963 num = random.random()* game.state.galaxy[nq.x][nq.y].stars + 1
2964 for ns.x in range(1, QUADSIZE+1):
2965 for ns.y in range(1, QUADSIZE+1):
2966 if game.quad[ns.x][ns.y]==IHSTAR:
2974 prouts(_("***RED ALERT! RED ALERT!"))
2976 prout(_("***Incipient supernova detected at Sector %s") % ns)
2977 if square(ns.x-game.sector.x) + square(ns.y-game.sector.y) <= 2.1:
2978 proutn(_("Emergency override attempts t"))
2979 prouts("***************")
2984 # destroy any Klingons in supernovaed quadrant
2985 kldead = game.state.galaxy[nq.x][nq.y].klingons
2986 game.state.galaxy[nq.x][nq.y].klingons = 0
2987 if nq == game.state.kscmdr:
2988 # did in the Supercommander!
2989 game.state.nscrem = game.state.kscmdr.x = game.state.kscmdr.y = game.isatb = 0
2993 if game.state.remcom:
2994 maxloop = game.state.remcom
2995 for l in range(1, maxloop+1):
2996 if game.state.kcmdr[l] == nq:
2997 game.state.kcmdr[l] = game.state.kcmdr[game.state.remcom]
2998 invalidate(game.state.kcmdr[game.state.remcom])
2999 game.state.remcom -= 1
3001 if game.state.remcom==0:
3004 game.state.remkl -= kldead
3005 # destroy Romulans and planets in supernovaed quadrant
3006 nrmdead = game.state.galaxy[nq.x][nq.y].romulans
3007 game.state.galaxy[nq.x][nq.y].romulans = 0
3008 game.state.nromrem -= nrmdead
3010 for loop in range(game.inplan):
3011 if game.state.planets[loop].w == nq:
3012 game.state.planets[loop].pclass = destroyed
3014 # Destroy any base in supernovaed quadrant
3015 if game.state.rembase:
3016 maxloop = game.state.rembase
3017 for loop in range(1, maxloop+1):
3018 if game.state.baseq[loop] == nq:
3019 game.state.baseq[loop] = game.state.baseq[game.state.rembase]
3020 invalidate(game.state.baseq[game.state.rembase])
3021 game.state.rembase -= 1
3023 # If starship caused supernova, tally up destruction
3025 game.state.starkl += game.state.galaxy[nq.x][nq.y].stars
3026 game.state.basekl += game.state.galaxy[nq.x][nq.y].starbase
3027 game.state.nplankl += npdead
3028 # mark supernova in galaxy and in star chart
3029 if game.quadrant == nq or communicating():
3030 game.state.galaxy[nq.x][nq.y].supernova = True
3031 # If supernova destroys last Klingons give special message
3032 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0 and not nq == game.quadrant:
3035 prout(_("Lucky you!"))
3036 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
3039 # if some Klingons remain, continue or die in supernova
3044 # Code from finish.c ends here.
3047 # self-destruct maneuver
3048 # Finish with a BANG!
3050 if damaged(DCOMPTR):
3051 prout(_("Computer damaged; cannot execute destruct sequence."))
3053 prouts(_("---WORKING---")); skip(1)
3054 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
3055 prouts(" 10"); skip(1)
3056 prouts(" 9"); skip(1)
3057 prouts(" 8"); skip(1)
3058 prouts(" 7"); skip(1)
3059 prouts(" 6"); skip(1)
3061 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
3063 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
3065 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
3069 if game.passwd != citem:
3070 prouts(_("PASSWORD-REJECTED;"))
3072 prouts(_("CONTINUITY-EFFECTED"))
3075 prouts(_("PASSWORD-ACCEPTED")); skip(1)
3076 prouts(" 5"); skip(1)
3077 prouts(" 4"); skip(1)
3078 prouts(" 3"); skip(1)
3079 prouts(" 2"); skip(1)
3080 prouts(" 1"); skip(1)
3081 if random.random() < 0.15:
3082 prouts(_("GOODBYE-CRUEL-WORLD"))
3090 prouts(_("********* Entropy of "))
3092 prouts(_(" maximized *********"))
3096 if game.nenhere != 0:
3097 whammo = 25.0 * game.energy
3099 while l <= game.nenhere:
3100 if game.kpower[l]*game.kdist[l] <= whammo:
3101 deadkl(game.ks[l], game.quad[game.ks[l].x][game.ks[l].y], game.ks[l])
3106 "Compute our rate of kils over time."
3107 return ((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem))/(game.state.date-game.indate)
3111 badpt = 5.0*game.state.starkl + \
3113 10.0*game.state.nplankl + \
3114 300*game.state.nworldkl + \
3116 100.0*game.state.basekl +\
3118 if game.ship == IHF:
3120 elif game.ship == None:
3126 # end the game, with appropriate notfications
3130 prout(_("It is stardate %.1f.") % game.state.date)
3132 if ifin == FWON: # Game has been won
3133 if game.state.nromrem != 0:
3134 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
3137 prout(_("You have smashed the Klingon invasion fleet and saved"))
3138 prout(_("the Federation."))
3143 badpt = 0.0 # Close enough!
3144 # killsPerDate >= RateMax
3145 if game.state.date-game.indate < 5.0 or \
3146 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
3148 prout(_("In fact, you have done so well that Starfleet Command"))
3149 if game.skill == SKILL_NOVICE:
3150 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
3151 elif game.skill == SKILL_FAIR:
3152 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
3153 elif game.skill == SKILL_GOOD:
3154 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
3155 elif game.skill == SKILL_EXPERT:
3156 prout(_("promotes you to Commodore Emeritus."))
3158 prout(_("Now that you think you're really good, try playing"))
3159 prout(_("the \"Emeritus\" game. It will splatter your ego."))
3160 elif game.skill == SKILL_EMERITUS:
3162 proutn(_("Computer- "))
3163 prouts(_("ERROR-ERROR-ERROR-ERROR"))
3165 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
3167 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3169 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3171 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
3173 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
3175 prout(_("Now you can retire and write your own Star Trek game!"))
3177 elif game.skill >= SKILL_EXPERT:
3178 if game.thawed and not idebug:
3179 prout(_("You cannot get a citation, so..."))
3181 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
3185 # Only grant long life if alive (original didn't!)
3187 prout(_("LIVE LONG AND PROSPER."))
3192 elif ifin == FDEPLETE: # Federation Resources Depleted
3193 prout(_("Your time has run out and the Federation has been"))
3194 prout(_("conquered. Your starship is now Klingon property,"))
3195 prout(_("and you are put on trial as a war criminal. On the"))
3196 proutn(_("basis of your record, you are "))
3197 if (game.state.remkl + game.state.remcom + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
3198 prout(_("acquitted."))
3200 prout(_("LIVE LONG AND PROSPER."))
3202 prout(_("found guilty and"))
3203 prout(_("sentenced to death by slow torture."))
3207 elif ifin == FLIFESUP:
3208 prout(_("Your life support reserves have run out, and"))
3209 prout(_("you die of thirst, starvation, and asphyxiation."))
3210 prout(_("Your starship is a derelict in space."))
3212 prout(_("Your energy supply is exhausted."))
3214 prout(_("Your starship is a derelict in space."))
3215 elif ifin == FBATTLE:
3218 prout(_("has been destroyed in battle."))
3220 prout(_("Dulce et decorum est pro patria mori."))
3222 prout(_("You have made three attempts to cross the negative energy"))
3223 prout(_("barrier which surrounds the galaxy."))
3225 prout(_("Your navigation is abominable."))
3228 prout(_("Your starship has been destroyed by a nova."))
3229 prout(_("That was a great shot."))
3231 elif ifin == FSNOVAED:
3234 prout(_(" has been fried by a supernova."))
3235 prout(_("...Not even cinders remain..."))
3236 elif ifin == FABANDN:
3237 prout(_("You have been captured by the Klingons. If you still"))
3238 prout(_("had a starbase to be returned to, you would have been"))
3239 prout(_("repatriated and given another chance. Since you have"))
3240 prout(_("no starbases, you will be mercilessly tortured to death."))
3241 elif ifin == FDILITHIUM:
3242 prout(_("Your starship is now an expanding cloud of subatomic particles"))
3243 elif ifin == FMATERIALIZE:
3244 prout(_("Starbase was unable to re-materialize your starship."))
3245 prout(_("Sic transit gloria mundi"))
3246 elif ifin == FPHASER:
3249 prout(_(" has been cremated by its own phasers."))
3251 prout(_("You and your landing party have been"))
3252 prout(_("converted to energy, disipating through space."))
3253 elif ifin == FMINING:
3254 prout(_("You are left with your landing party on"))
3255 prout(_("a wild jungle planet inhabited by primitive cannibals."))
3257 prout(_("They are very fond of \"Captain Kirk\" soup."))
3259 proutn(_("Without your leadership, the "))
3261 prout(_(" is destroyed."))
3262 elif ifin == FDPLANET:
3263 prout(_("You and your mining party perish."))
3265 prout(_("That was a great shot."))
3268 prout(_("The Galileo is instantly annihilated by the supernova."))
3269 prout(_("You and your mining party are atomized."))
3271 proutn(_("Mr. Spock takes command of the "))
3274 prout(_("joins the Romulans, reigning terror on the Federation."))
3275 elif ifin == FPNOVA:
3276 prout(_("You and your mining party are atomized."))
3278 proutn(_("Mr. Spock takes command of the "))
3281 prout(_("joins the Romulans, reigning terror on the Federation."))
3282 elif ifin == FSTRACTOR:
3283 prout(_("The shuttle craft Galileo is also caught,"))
3284 prout(_("and breaks up under the strain."))
3286 prout(_("Your debris is scattered for millions of miles."))
3287 proutn(_("Without your leadership, the "))
3289 prout(_(" is destroyed."))
3291 prout(_("The mutants attack and kill Spock."))
3292 prout(_("Your ship is captured by Klingons, and"))
3293 prout(_("your crew is put on display in a Klingon zoo."))
3294 elif ifin == FTRIBBLE:
3295 prout(_("Tribbles consume all remaining water,"))
3296 prout(_("food, and oxygen on your ship."))
3298 prout(_("You die of thirst, starvation, and asphyxiation."))
3299 prout(_("Your starship is a derelict in space."))
3301 prout(_("Your ship is drawn to the center of the black hole."))
3302 prout(_("You are crushed into extremely dense matter."))
3304 prout(_("Your last crew member has died."))
3305 if game.ship == IHF:
3307 elif game.ship == IHE:
3310 if (game.state.remkl + game.state.remcom + game.state.nscrem) != 0:
3311 goodies = game.state.remres/game.inresor
3312 baddies = (game.state.remkl + 2.0*game.state.remcom)/(game.inkling+2.0*game.incom)
3313 if goodies/baddies >= 1.0+0.5*random.random():
3314 prout(_("As a result of your actions, a treaty with the Klingon"))
3315 prout(_("Empire has been signed. The terms of the treaty are"))
3316 if goodies/baddies >= 3.0+random.random():
3317 prout(_("favorable to the Federation."))
3319 prout(_("Congratulations!"))
3321 prout(_("highly unfavorable to the Federation."))
3323 prout(_("The Federation will be destroyed."))
3325 prout(_("Since you took the last Klingon with you, you are a"))
3326 prout(_("martyr and a hero. Someday maybe they'll erect a"))
3327 prout(_("statue in your memory. Rest in peace, and try not"))
3328 prout(_("to think about pigeons."))
3333 # compute player's score
3334 timused = game.state.date - game.indate
3337 if (timused == 0 or (game.state.remkl + game.state.remcom + game.state.nscrem) != 0) and timused < 5.0:
3339 perdate = killrate()
3340 ithperd = 500*perdate + 0.5
3343 iwon = 100*game.skill
3344 if game.ship == IHE:
3346 elif game.ship == IHF:
3350 if not game.gamewon:
3351 game.state.nromrem = 0 # None captured if no win
3352 iscore = 10*(game.inkling - game.state.remkl) \
3353 + 50*(game.incom - game.state.remcom) \
3355 + 20*(game.inrom - game.state.nromrem) \
3356 + 200*(game.inscom - game.state.nscrem) \
3357 - game.state.nromrem \
3362 prout(_("Your score --"))
3363 if game.inrom - game.state.nromrem:
3364 prout(_("%6d Romulans destroyed %5d") %
3365 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
3366 if game.state.nromrem:
3367 prout(_("%6d Romulans captured %5d") %
3368 (game.state.nromrem, game.state.nromrem))
3369 if game.inkling - game.state.remkl:
3370 prout(_("%6d ordinary Klingons destroyed %5d") %
3371 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
3372 if game.incom - game.state.remcom:
3373 prout(_("%6d Klingon commanders destroyed %5d") %
3374 (game.incom - game.state.remcom, 50*(game.incom - game.state.remcom)))
3375 if game.inscom - game.state.nscrem:
3376 prout(_("%6d Super-Commander destroyed %5d") %
3377 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
3379 prout(_("%6.2f Klingons per stardate %5d") %
3381 if game.state.starkl:
3382 prout(_("%6d stars destroyed by your action %5d") %
3383 (game.state.starkl, -5*game.state.starkl))
3384 if game.state.nplankl:
3385 prout(_("%6d planets destroyed by your action %5d") %
3386 (game.state.nplankl, -10*game.state.nplankl))
3387 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
3388 prout(_("%6d inhabited planets destroyed by your action %5d") %
3389 (game.state.nplankl, -300*game.state.nworldkl))
3390 if game.state.basekl:
3391 prout(_("%6d bases destroyed by your action %5d") %
3392 (game.state.basekl, -100*game.state.basekl))
3394 prout(_("%6d calls for help from starbase %5d") %
3395 (game.nhelp, -45*game.nhelp))
3397 prout(_("%6d casualties incurred %5d") %
3398 (game.casual, -game.casual))
3400 prout(_("%6d crew abandoned in space %5d") %
3401 (game.abandoned, -3*game.abandoned))
3403 prout(_("%6d ship(s) lost or destroyed %5d") %
3404 (klship, -100*klship))
3406 prout(_("Penalty for getting yourself killed -200"))
3408 proutn(_("Bonus for winning "))
3409 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
3410 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
3411 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
3412 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
3413 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3414 prout(" %5d" % iwon)
3416 prout(_("TOTAL SCORE %5d") % iscore)
3419 # emit winner's commemmorative plaque
3422 proutn(_("File or device name for your plaque: "))
3425 fp = open(winner, "w")
3428 prout(_("Invalid name."))
3430 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3432 # The 38 below must be 64 for 132-column paper
3433 nskip = 38 - len(winner)/2
3435 fp.write("\n\n\n\n")
3436 # --------DRAW ENTERPRISE PICTURE.
3437 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3438 fp.write(" EEE E : : : E\n" )
3439 fp.write(" EE EEE E : : NCC-1701 : E\n")
3440 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3441 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3442 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3443 fp.write(" EEEEEEE EEEEE E E E E\n")
3444 fp.write(" EEE E E E E\n")
3445 fp.write(" E E E E\n")
3446 fp.write(" EEEEEEEEEEEEE E E\n")
3447 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3448 fp.write(" :E : EEEE E\n")
3449 fp.write(" .-E -:----- E\n")
3450 fp.write(" :E : E\n")
3451 fp.write(" EE : EEEEEEEE\n")
3452 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3454 fp.write(_(" U. S. S. ENTERPRISE\n"))
3455 fp.write("\n\n\n\n")
3456 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3458 fp.write(_(" Starfleet Command bestows to you\n"))
3460 fp.write("%*s%s\n\n" % (nskip, "", winner))
3461 fp.write(_(" the rank of\n\n"))
3462 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3464 if game.skill == SKILL_EXPERT:
3465 fp.write(_(" Expert level\n\n"))
3466 elif game.skill == SKILL_EMERITUS:
3467 fp.write(_("Emeritus level\n\n"))
3469 fp.write(_(" Cheat level\n\n"))
3470 timestring = ctime()
3471 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3472 (timestring+4, timestring+20, timestring+11))
3473 fp.write(_(" Your score: %d\n\n") % iscore)
3474 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3477 # Code from io.c begins here
3479 rows = linecount = 0 # for paging
3482 fullscreen_window = None
3483 srscan_window = None
3484 report_window = None
3485 status_window = None
3486 lrscan_window = None
3487 message_window = None
3488 prompt_window = None
3492 "wrap up, either normally or due to signal"
3493 if game.options & OPTION_CURSES:
3500 sys.stdout.write('\n')
3506 #setlocale(LC_ALL, "")
3507 #bindtextdomain(PACKAGE, LOCALEDIR)
3508 #textdomain(PACKAGE)
3509 if atexit.register(outro):
3510 sys.stderr.write("Unable to register outro(), exiting...\n")
3512 if not (game.options & OPTION_CURSES):
3513 ln_env = os.getenv("LINES")
3519 stdscr = curses.initscr()
3524 curses.start_color()
3525 curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, curses.COLOR_BLACK)
3526 curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, curses.COLOR_BLACK)
3527 curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_BLACK)
3528 curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, curses.COLOR_BLACK)
3529 curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, curses.COLOR_BLACK)
3530 curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
3531 curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_BLACK)
3532 curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, curses.COLOR_BLACK)
3534 global fullscreen_window, srscan_window, report_window, status_window
3535 global lrscan_window, message_window, prompt_window
3536 fullscreen_window = stdscr
3537 srscan_window = curses.newwin(12, 25, 0, 0)
3538 report_window = curses.newwin(11, 0, 1, 25)
3539 status_window = curses.newwin(10, 0, 1, 39)
3540 lrscan_window = curses.newwin(5, 0, 0, 64)
3541 message_window = curses.newwin(0, 0, 12, 0)
3542 prompt_window = curses.newwin(1, 0, rows-2, 0)
3543 message_window.scrollok(True)
3544 setwnd(fullscreen_window)
3549 "wait for user action -- OK to do nothing if on a TTY"
3550 if game.options & OPTION_CURSES:
3555 if game.skill > SKILL_FAIR:
3556 prouts(_("[ANOUNCEMENT ARRIVING...]"))
3558 prouts(_("[IMPORTANT ANNOUNCEMENT ARRIVING -- PRESS ENTER TO CONTINUE]"))
3562 if game.skill > SKILL_FAIR:
3563 prompt = _("[CONTINUE?]")
3565 prompt = _("[PRESS ENTER TO CONTINUE]")
3567 if game.options & OPTION_CURSES:
3569 setwnd(prompt_window)
3570 prompt_window.wclear()
3571 prompt_window.addstr(prompt)
3572 prompt_window.getstr()
3573 prompt_window.clear()
3574 prompt_window.refresh()
3575 setwnd(message_window)
3578 sys.stdout.write('\n')
3581 for j in range(0, rows):
3582 sys.stdout.write('\n')
3586 "Skip i lines. Pause game if this would cause a scrolling event."
3587 for dummy in range(i):
3588 if game.options & OPTION_CURSES:
3589 (y, x) = curwnd.getyx()
3590 (my, mx) = curwnd.getmaxyx()
3591 if curwnd == message_window and y >= my - 3:
3599 if rows and linecount >= rows:
3602 sys.stdout.write('\n')
3605 "Utter a line with no following line feed."
3606 if game.options & OPTION_CURSES:
3610 sys.stdout.write(line)
3620 curses.delay_output(30)
3622 if game.options & OPTION_CURSES:
3626 curses.delay_output(300)
3629 "Get a line of input."
3630 if game.options & OPTION_CURSES:
3631 line = curwnd.getstr() + "\n"
3634 if replayfp and not replayfp.closed:
3635 line = replayfp.readline()
3643 "Change windows -- OK for this to be a no-op in tty mode."
3645 if game.options & OPTION_CURSES:
3647 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3650 "Clear to end of line -- can be a no-op in tty mode"
3651 if game.options & OPTION_CURSES:
3656 "Clear screen -- can be a no-op in tty mode."
3658 if game.options & OPTION_CURSES:
3664 def textcolor(color):
3665 "Set the current text color"
3666 if game.options & OPTION_CURSES:
3667 if color == DEFAULT:
3669 elif color == BLACK:
3670 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK))
3672 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE))
3673 elif color == GREEN:
3674 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN))
3676 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN))
3678 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED))
3679 elif color == MAGENTA:
3680 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA))
3681 elif color == BROWN:
3682 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW))
3683 elif color == LIGHTGRAY:
3684 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE))
3685 elif color == DARKGRAY:
3686 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLACK) | curses.A_BOLD)
3687 elif color == LIGHTBLUE:
3688 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_BLUE) | curses.A_BOLD)
3689 elif color == LIGHTGREEN:
3690 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_GREEN) | curses.A_BOLD)
3691 elif color == LIGHTCYAN:
3692 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_CYAN) | curses.A_BOLD)
3693 elif color == LIGHTRED:
3694 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_RED) | curses.A_BOLD)
3695 elif color == LIGHTMAGENTA:
3696 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_MAGENTA) | curses.A_BOLD)
3697 elif color == YELLOW:
3698 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_YELLOW) | curses.A_BOLD)
3699 elif color == WHITE:
3700 curwnd.attron(curses.COLOR_PAIR(curses.COLOR_WHITE) | curses.A_BOLD)
3703 "Set highlight video, if this is reasonable."
3704 if game.options & OPTION_CURSES:
3705 curwnd.attron(curses.A_REVERSE)
3707 def commandhook(cmd, before):
3711 # Things past this point have policy implications.
3715 "Hook to be called after moving to redraw maps."
3716 if game.options & OPTION_CURSES:
3719 setwnd(srscan_window)
3723 setwnd(status_window)
3724 status_window.clear()
3725 status_window.move(0, 0)
3726 setwnd(report_window)
3727 report_window.clear()
3728 report_window.move(0, 0)
3730 setwnd(lrscan_window)
3731 lrscan_window.clear()
3732 lrscan_window.move(0, 0)
3735 def put_srscan_sym(w, sym):
3736 "Emit symbol for short-range scan."
3737 srscan_window.move(w.x+1, w.y*2+2)
3738 srscan_window.addch(sym)
3739 srscan_window.refresh()
3742 "Enemy fall down, go boom."
3743 if game.options & OPTION_CURSES:
3745 setwnd(srscan_window)
3746 srscan_window.attron(curses.A_REVERSE)
3747 put_srscan_sym(w, game.quad[w.x][w.y])
3751 srscan_window.attroff(curses.A_REVERSE)
3752 put_srscan_sym(w, game.quad[w.x][w.y])
3753 curses.delay_output(500)
3754 setwnd(message_window)
3757 "Sound and visual effects for teleportation."
3758 if game.options & OPTION_CURSES:
3760 setwnd(message_window)
3762 prouts(" . . . . . ")
3763 if game.options & OPTION_CURSES:
3764 #curses.delay_output(1000)
3768 def tracktorpedo(w, l, i, n, iquad):
3769 "Torpedo-track animation."
3770 if not game.options & OPTION_CURSES:
3774 proutn(_("Track for torpedo number %d- ") % i)
3777 proutn(_("Torpedo track- "))
3780 proutn("%d - %d " % (w.x, w.y))
3782 if not damaged(DSRSENS) or game.condition=="docked":
3783 if i != 1 and l == 1:
3785 curses.delay_output(400)
3786 if (iquad==IHDOT) or (iquad==IHBLANK):
3787 put_srscan_sym(w, '+')
3789 #curses.delay_output(100)
3791 put_srscan_sym(w, iquad)
3793 curwnd.attron(curses.A_REVERSE)
3794 put_srscan_sym(w, iquad)
3796 #curses.delay_output(1000)
3798 curwnd.attroff(curses.A_REVERSE)
3799 put_srscan_sym(w, iquad)
3801 proutn("%d - %d " % (w.x, w.y))
3804 "Display the current galaxy chart."
3805 if game.options & OPTION_CURSES:
3806 setwnd(message_window)
3807 message_window.clear()
3809 if game.options & OPTION_TTY:
3814 def prstat(txt, data):
3816 if game.options & OPTION_CURSES:
3818 setwnd(status_window)
3820 proutn(" " * NSYM - len(tx))
3823 if game.options & OPTION_CURSES:
3824 setwnd(report_window)
3826 # Code from moving.c begins here
3828 def imove(novapush):
3829 # movement execution for warp, impulse, supernova, and tractor-beam events
3830 w = coord(); final = coord()
3833 def no_quad_change():
3834 # No quadrant change -- compute new avg enemy distances
3835 game.quad[game.sector.x][game.sector.y] = game.ship
3837 for m in range(1, game.nenhere+1):
3838 finald = distance(w, game.ks[m])
3839 game.kavgd[m] = 0.5 * (finald+game.kdist[m])
3840 game.kdist[m] = finald
3842 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3844 for m in range(1, game.nenhere+1):
3845 game.kavgd[m] = game.kdist[m]
3848 setwnd(message_window)
3852 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3853 game.inorbit = False
3855 angle = ((15.0 - game.direc) * 0.5235988)
3856 deltax = -math.sin(angle)
3857 deltay = math.cos(angle)
3858 if math.fabs(deltax) > math.fabs(deltay):
3859 bigger = math.fabs(deltax)
3861 bigger = math.fabs(deltay)
3866 # If tractor beam is to occur, don't move full distance
3867 if game.state.date+game.optime >= scheduled(FTBEAM):
3869 game.condition = "red"
3870 game.dist = game.dist*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3871 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3872 # Move within the quadrant
3873 game.quad[game.sector.x][game.sector.y] = IHDOT
3876 n = 10.0*game.dist*bigger+0.5
3879 for m in range(1, n+1):
3884 if not VALID_SECTOR(w.x, w.y):
3885 # Leaving quadrant -- allow final enemy attack
3886 # Don't do it if being pushed by Nova
3887 if game.nenhere != 0 and not novapush:
3889 for m in range(1, game.nenhere+1):
3890 finald = distance(w, game.ks[m])
3891 game.kavgd[m] = 0.5 * (finald + game.kdist[m])
3893 # Stas Sergeev added the condition
3894 # that attacks only happen if Klingons
3895 # are present and your skill is good.
3897 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
3901 # compute final position -- new quadrant and sector
3902 x = QUADSIZE*(game.quadrant.x-1)+game.sector.x
3903 y = QUADSIZE*(game.quadrant.y-1)+game.sector.y
3904 w.x = x+10.0*game.dist*bigger*deltax+0.5
3905 w.y = y+10.0*game.dist*bigger*deltay+0.5
3906 # check for edge of galaxy
3916 if w.x > GALSIZE*QUADSIZE:
3917 w.x = (GALSIZE*QUADSIZE*2)+1 - w.x
3919 if w.y > GALSIZE*QUADSIZE:
3920 w.y = (GALSIZE*QUADSIZE*2)+1 - w.y
3929 if game.nkinks == 3:
3930 # Three strikes -- you're out!
3934 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3935 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3936 prout(_("YOU WILL BE DESTROYED."))
3937 # Compute final position in new quadrant
3938 if trbeam: # Don't bother if we are to be beamed
3940 game.quadrant.x = (w.x+(QUADSIZE-1))/QUADSIZE
3941 game.quadrant.y = (w.y+(QUADSIZE-1))/QUADSIZE
3942 game.sector.x = w.x - QUADSIZE*(game.quadrant.x-1)
3943 game.sector.y = w.y - QUADSIZE*(game.quadrant.y-1)
3945 prout(_("Entering Quadrant %s.") % game.quadrant)
3946 game.quad[game.sector.x][game.sector.y] = game.ship
3948 if game.skill>SKILL_NOVICE:
3951 iquad = game.quad[w.x][w.y]
3953 # object encountered in flight path
3954 stopegy = 50.0*game.dist/game.optime
3955 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
3956 if iquad in (IHT. IHK, OHC, IHS, IHR, IHQUEST):
3958 ram(False, iquad, game.sector)
3960 elif iquad == IHBLANK:
3962 prouts(_("***RED ALERT! RED ALERT!"))
3966 proutn(_(" pulled into black hole at Sector %s") % w)
3968 # Getting pulled into a black hole was certain
3969 # death in Almy's original. Stas Sergeev added a
3970 # possibility that you'll get timewarped instead.
3973 for m in range(0, NDEVICES):
3974 if game.damage[m]>0:
3976 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3977 if (game.options & OPTION_BLKHOLE) and random.random()>probf:
3987 proutn(_(" encounters Tholian web at %s;") % w)
3989 proutn(_(" blocked by object at %s;") % w)
3990 proutn(_("Emergency stop required "))
3991 prout(_("%2d units of energy.") % int(stopegy))
3992 game.energy -= stopegy
3993 final.x = x-deltax+0.5
3994 final.y = y-deltay+0.5
3996 if game.energy <= 0:
4002 game.dist = distance(game.sector, w) / (QUADSIZE * 1.0)
4009 # dock our ship at a starbase
4011 if game.condition == "docked" and verbose:
4012 prout(_("Already docked."))
4015 prout(_("You must first leave standard orbit."))
4017 if not is_valid(game.base) or abs(game.sector.x-game.base.x) > 1 or abs(game.sector.y-game.base.y) > 1:
4019 prout(_(" not adjacent to base."))
4021 game.condition = "docked"
4025 if game.energy < game.inenrg:
4026 game.energy = game.inenrg
4027 game.shield = game.inshld
4028 game.torps = game.intorps
4029 game.lsupres = game.inlsr
4030 game.state.crew = FULLCREW
4031 if not damaged(DRADIO) and \
4032 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
4033 # get attack report from base
4034 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
4039 # This program originally required input in terms of a (clock)
4040 # direction and distance. Somewhere in history, it was changed to
4041 # cartesian coordinates. So we need to convert. Probably
4042 # "manual" input should still be done this way -- it's a real
4043 # pain if the computer isn't working! Manual mode is still confusing
4044 # because it involves giving x and y motions, yet the coordinates
4045 # are always displayed y - x, where +y is downward!
4048 def getcd(isprobe, akey):
4049 # get course and distance
4050 irowq=game.quadrant.x; icolq=game.quadrant.y; key=0
4051 navmode = "unspecified"
4056 # Get course direction and distance. If user types bad values, return
4057 # with DIREC = -1.0.
4060 if game.landed and not isprobe:
4061 prout(_("Dummy! You can't leave standard orbit until you"))
4062 proutn(_("are back aboard the ship."))
4065 while navmode == "unspecified":
4066 if damaged(DNAVSYS):
4068 prout(_("Computer damaged; manual navigation only"))
4070 prout(_("Computer damaged; manual movement only"))
4075 if isprobe and akey != -1:
4076 # For probe launch, use pre-scanned value first time
4083 proutn(_("Manual or automatic- "))
4086 elif key == IHALPHA:
4091 elif isit("automatic"):
4092 navmode = "automatic"
4101 prout(_("(Manual navigation assumed.)"))
4103 prout(_("(Manual movement assumed.)"))
4107 if navmode == "automatic":
4110 proutn(_("Target quadrant or quadrant§or- "))
4112 proutn(_("Destination sector or quadrant§or- "))
4128 # both quadrant and sector specified
4142 # only quadrant specified -- go to center of dest quad
4150 if not VALID_QUADRANT(icolq,irowq) or not VALID_SECTOR(incr.x,incr.y):
4157 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % incr)
4159 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
4160 deltax = icolq - game.quadrant.y + 0.1*(incr.x-game.sector.y)
4161 deltay = game.quadrant.x - irowq + 0.1*(game.sector.x-incr.y)
4164 proutn(_("X and Y displacements- "))
4178 # Check for zero movement
4179 if deltax == 0 and deltay == 0:
4182 if itemp == "verbose" and not isprobe:
4184 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
4185 game.dist = math.sqrt(deltax*deltax + deltay*deltay)
4186 game.direc = math.atan2(deltax, deltay)*1.90985932
4187 if game.direc < 0.0:
4193 # move under impulse power
4195 if damaged(DIMPULS):
4198 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4200 if game.energy > 30.0:
4202 if game.direc == -1.0:
4204 power = 20.0 + 100.0*game.dist
4208 if power >= game.energy:
4209 # Insufficient power for trip
4211 prout(_("First Officer Spock- \"Captain, the impulse engines"))
4212 prout(_("require 20.0 units to engage, plus 100.0 units per"))
4213 if game.energy > 30:
4214 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
4215 int(0.01 * (game.energy-20.0)-0.05))
4216 prout(_(" quadrants.\""))
4218 prout(_("quadrant. They are, therefore, useless.\""))
4221 # Make sure enough time is left for the trip
4222 game.optime = game.dist/0.095
4223 if game.optime >= game.state.remtime:
4224 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
4225 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
4226 proutn(_("we dare spend the time?\" "))
4229 # Activate impulse engines and pay the cost
4234 power = 20.0 + 100.0*game.dist
4235 game.energy -= power
4236 game.optime = game.dist/0.095
4237 if game.energy <= 0:
4242 # move under warp drive
4243 blooey = False; twarp = False
4244 if not timewarp: # Not WARPX entry
4246 if game.damage[DWARPEN] > 10.0:
4249 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
4251 if damaged(DWARPEN) and game.warpfac > 4.0:
4254 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
4255 prout(_(" is repaired, I can only give you warp 4.\""))
4258 # Read in course and distance
4260 if game.direc == -1.0:
4263 # Make sure starship has enough energy for the trip
4264 power = (game.dist+0.05)*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4265 if power >= game.energy:
4266 # Insufficient power for trip
4269 prout(_("Engineering to bridge--"))
4270 if not game.shldup or 0.5*power > game.energy:
4271 iwarp = math.pow((game.energy/(game.dist+0.05)), 0.333333333)
4273 prout(_("We can't do it, Captain. We don't have enough energy."))
4275 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
4278 prout(_("if you'll lower the shields."))
4282 prout(_("We haven't the energy to go that far with the shields up."))
4285 # Make sure enough time is left for the trip
4286 game.optime = 10.0*game.dist/game.wfacsq
4287 if game.optime >= 0.8*game.state.remtime:
4289 prout(_("First Officer Spock- \"Captain, I compute that such"))
4290 proutn(_(" a trip would require approximately %2.0f") %
4291 (100.0*game.optime/game.state.remtime))
4292 prout(_(" percent of our"))
4293 proutn(_(" remaining time. Are you sure this is wise?\" "))
4299 if game.warpfac > 6.0:
4300 # Decide if engine damage will occur
4301 prob = game.dist*(6.0-game.warpfac)*(6.0-game.warpfac)/66.666666666
4302 if prob > random.random():
4304 game.dist = random.random()*game.dist
4305 # Decide if time warp will occur
4306 if 0.5*game.dist*math.pow(7.0,game.warpfac-10.0) > random.random():
4308 if idebug and game.warpfac==10 and not twarp:
4310 proutn("=== Force time warp? ")
4314 # If time warp or engine damage, check path
4315 # If it is obstructed, don't do warp or damage
4316 angle = ((15.0-game.direc)*0.5235998)
4317 deltax = -math.sin(angle)
4318 deltay = math.cos(angle)
4319 if math.fabs(deltax) > math.fabs(deltay):
4320 bigger = math.fabs(deltax)
4322 bigger = math.fabs(deltay)
4326 n = 10.0 * game.dist * bigger +0.5
4329 for l in range(1, n+1):
4334 if not VALID_SECTOR(ix, iy):
4336 if game.quad[ix][iy] != IHDOT:
4341 # Activate Warp Engines and pay the cost
4345 game.energy -= game.dist*game.warpfac*game.warpfac*game.warpfac*(game.shldup+1)
4346 if game.energy <= 0:
4348 game.optime = 10.0*game.dist/game.wfacsq
4352 game.damage[DWARPEN] = game.damfac*(3.0*random.random()+1.0)
4354 prout(_("Engineering to bridge--"))
4355 prout(_(" Scott here. The warp engines are damaged."))
4356 prout(_(" We'll have to reduce speed to warp 4."))
4361 # change the warp factor
4367 proutn(_("Warp factor- "))
4372 if game.damage[DWARPEN] > 10.0:
4373 prout(_("Warp engines inoperative."))
4375 if damaged(DWARPEN) and aaitem > 4.0:
4376 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
4377 prout(_(" but right now we can only go warp 4.\""))
4380 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
4383 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
4385 oldfac = game.warpfac
4386 game.warpfac = aaitem
4387 game.wfacsq=game.warpfac*game.warpfac
4388 if game.warpfac <= oldfac or game.warpfac <= 6.0:
4389 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
4392 if game.warpfac < 8.00:
4393 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
4395 if game.warpfac == 10.0:
4396 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
4398 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
4402 # cope with being tossed out of quadrant by supernova or yanked by beam
4405 # is captain on planet?
4407 if damaged(DTRANSP):
4410 prout(_("Scotty rushes to the transporter controls."))
4412 prout(_("But with the shields up it's hopeless."))
4414 prouts(_("His desperate attempt to rescue you . . ."))
4415 if random.random() <= 0.5:
4419 prout(_("SUCCEEDS!"))
4422 proutn(_("The crystals mined were "))
4423 if random.random() <= 0.25:
4431 # Check to see if captain in shuttle craft
4437 # Inform captain of attempt to reach safety
4441 prouts(_("***RED ALERT! RED ALERT!"))
4445 prout(_(" has stopped in a quadrant containing"))
4446 prouts(_(" a supernova."))
4448 proutn(_("***Emergency automatic override attempts to hurl "))
4451 prout(_("safely out of quadrant."))
4452 if not damaged(DRADIO):
4453 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
4454 # Try to use warp engines
4455 if damaged(DWARPEN):
4457 prout(_("Warp engines damaged."))
4460 game.warpfac = 6.0+2.0*random.random()
4461 game.wfacsq = game.warpfac * game.warpfac
4462 prout(_("Warp factor set to %d") % int(game.warpfac))
4463 power = 0.75*game.energy
4464 game.dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
4465 distreq = 1.4142+random.random()
4466 if distreq < game.dist:
4468 game.optime = 10.0*game.dist/game.wfacsq
4469 game.direc = 12.0*random.random() # How dumb!
4471 game.inorbit = False
4474 # This is bad news, we didn't leave quadrant.
4478 prout(_("Insufficient energy to leave quadrant."))
4481 # Repeat if another snova
4482 if not game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
4484 if (game.state.remkl + game.state.remcom + game.state.nscrem)==0:
4485 finish(FWON) # Snova killed remaining enemy.
4488 # let's do the time warp again
4489 prout(_("***TIME WARP ENTERED."))
4490 if game.state.snap and random.random() < 0.5:
4492 prout(_("You are traveling backwards in time %d stardates.") %
4493 int(game.state.date-game.snapsht.date))
4494 game.state = game.snapsht
4495 game.state.snap = False
4496 if game.state.remcom:
4497 schedule(FTBEAM, expran(game.intime/game.state.remcom))
4498 schedule(FBATTAK, expran(0.3*game.intime))
4499 schedule(FSNOVA, expran(0.5*game.intime))
4500 # next snapshot will be sooner
4501 schedule(FSNAP, expran(0.25*game.state.remtime))
4503 if game.state.nscrem:
4504 schedule(FSCMOVE, 0.2777)
4508 invalidate(game.battle)
4510 # Make sure Galileo is consistant -- Snapshot may have been taken
4511 # when on planet, which would give us two Galileos!
4513 for l in range(game.inplan):
4514 if game.state.planets[l].known == "shuttle_down":
4516 if game.iscraft == "onship" and game.ship==IHE:
4517 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4518 game.iscraft = "offship"
4519 # Likewise, if in the original time the Galileo was abandoned, but
4520 # was on ship earlier, it would have vanished -- let's restore it.
4521 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4522 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4523 game.iscraft = "onship"
4525 # * There used to be code to do the actual reconstrction here,
4526 # * but the starchart is now part of the snapshotted galaxy state.
4528 prout(_("Spock has reconstructed a correct star chart from memory"))
4530 # Go forward in time
4531 game.optime = -0.5*game.intime*math.log(random.random())
4532 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4533 # cheat to make sure no tractor beams occur during time warp
4534 postpone(FTBEAM, game.optime)
4535 game.damage[DRADIO] += game.optime
4537 events() # Stas Sergeev added this -- do pending events
4540 # launch deep-space probe
4541 # New code to launch a deep space probe
4542 if game.nprobes == 0:
4545 if game.ship == IHE:
4546 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4548 prout(_("Ye Faerie Queene has no deep space probes."))
4553 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4555 if is_scheduled(FDSPROB):
4558 if damaged(DRADIO) and game.condition != "docked":
4559 prout(_("Spock- \"Records show the previous probe has not yet"))
4560 prout(_(" reached its destination.\""))
4562 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4567 # slow mode, so let Kirk know how many probes there are left
4568 if game.nprobes == 1:
4569 prout(_("1 probe left."))
4571 prout(_("%d probes left") % game.nprobes)
4572 proutn(_("Are you sure you want to fire a probe? "))
4576 game.isarmed = False
4577 if key == IHALPHA and citem == "armed":
4581 proutn(_("Arm NOVAMAX warhead? "))
4584 if game.direc == -1.0:
4587 angle = ((15.0 - game.direc) * 0.5235988)
4588 game.probeinx = -math.sin(angle)
4589 game.probeiny = math.cos(angle)
4590 if math.fabs(game.probeinx) > math.fabs(game.probeiny):
4591 bigger = math.fabs(game.probeinx)
4593 bigger = math.fabs(game.probeiny)
4595 game.probeiny /= bigger
4596 game.probeinx /= bigger
4597 game.proben = 10.0*game.dist*bigger +0.5
4598 game.probex = game.quadrant.x*QUADSIZE + game.sector.x - 1 # We will use better packing than original
4599 game.probey = game.quadrant.y*QUADSIZE + game.sector.y - 1
4600 game.probec = game.quadrant
4601 schedule(FDSPROB, 0.01) # Time to move one sector
4602 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4606 # Here's how the mayday code works:
4608 # First, the closest starbase is selected. If there is a a starbase
4609 # in your own quadrant, you are in good shape. This distance takes
4610 # quadrant distances into account only.
4612 # A magic number is computed based on the distance which acts as the
4613 # probability that you will be rematerialized. You get three tries.
4615 # When it is determined that you should be able to be rematerialized
4616 # (i.e., when the probability thing mentioned above comes up
4617 # positive), you are put into that quadrant (anywhere). Then, we try
4618 # to see if there is a spot adjacent to the star- base. If not, you
4619 # can't be rematerialized!!! Otherwise, it drops you there. It only
4620 # tries five times to find a spot to drop you. After that, it's your
4624 # yell for help from nearest starbase
4625 # There's more than one way to move in this game!
4629 # Test for conditions which prevent calling for help
4630 if game.condition == "docked":
4631 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4634 prout(_("Subspace radio damaged."))
4636 if game.state.rembase==0:
4637 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4640 proutn(_("You must be aboard the "))
4644 # OK -- call for help from nearest starbase
4647 # There's one in this quadrant
4648 ddist = distance(game.base, game.sector)
4651 for m in range(1, game.state.rembase+1):
4652 xdist = QUADSIZE * distance(game.state.baseq[m], game.quadrant)
4656 # Since starbase not in quadrant, set up new quadrant
4657 game.quadrant = game.state.baseq[line]
4659 # dematerialize starship
4660 game.quad[game.sector.x][game.sector.y]=IHDOT
4661 proutn(_("Starbase in Quadrant %s responds--") % game.quadrant)
4663 prout(_(" dematerializes."))
4665 for m in range(1, 5+1):
4666 ix = game.base.x+3.0*random.random()-1
4667 iy = game.base.y+3.0*random.random()-1
4668 if VALID_SECTOR(ix,iy) and game.quad[ix][iy]==IHDOT:
4669 # found one -- finish up
4673 if not is_valid(game.sector):
4674 prout(_("You have been lost in space..."))
4675 finish(FMATERIALIZE)
4677 # Give starbase three chances to rematerialize starship
4678 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4679 for m in range(1, 3+1):
4680 if m == 1: proutn(_("1st"))
4681 elif m == 2: proutn(_("2nd"))
4682 elif m == 3: proutn(_("3rd"))
4683 proutn(_(" attempt to re-materialize "))
4685 game.quad[ix][iy]=(IHMATER0,IHMATER1,IHMATER2)[m-1]
4688 if random.random() > probf:
4691 curses.delay_output(500)
4694 game.quad[ix][iy]=IHQUEST
4697 setwnd(message_window)
4698 finish(FMATERIALIZE)
4700 game.quad[ix][iy]=game.ship
4702 prout(_("succeeds."))
4706 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4708 # Abandon Ship (the BSD-Trek description)
4710 # The ship is abandoned. If your current ship is the Faire
4711 # Queene, or if your shuttlecraft is dead, you're out of
4712 # luck. You need the shuttlecraft in order for the captain
4713 # (that's you!!) to escape.
4715 # Your crew can beam to an inhabited starsystem in the
4716 # quadrant, if there is one and if the transporter is working.
4717 # If there is no inhabited starsystem, or if the transporter
4718 # is out, they are left to die in outer space.
4720 # If there are no starbases left, you are captured by the
4721 # Klingons, who torture you mercilessly. However, if there
4722 # is at least one starbase, you are returned to the
4723 # Federation in a prisoner of war exchange. Of course, this
4724 # can't happen unless you have taken some prisoners.
4729 if game.condition=="docked":
4731 prout(_("You cannot abandon Ye Faerie Queene."))
4734 # Must take shuttle craft to exit
4735 if game.damage[DSHUTTL]==-1:
4736 prout(_("Ye Faerie Queene has no shuttle craft."))
4738 if game.damage[DSHUTTL]<0:
4739 prout(_("Shuttle craft now serving Big Macs."))
4741 if game.damage[DSHUTTL]>0:
4742 prout(_("Shuttle craft damaged."))
4745 prout(_("You must be aboard the ship."))
4747 if game.iscraft != "onship":
4748 prout(_("Shuttle craft not currently available."))
4750 # Print abandon ship messages
4752 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4754 prouts(_("***ALL HANDS ABANDON SHIP!"))
4756 prout(_("Captain and crew escape in shuttle craft."))
4757 if game.state.rembase==0:
4758 # Oops! no place to go...
4761 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
4763 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4764 prout(_("Remainder of ship's complement beam down"))
4765 prout(_("to nearest habitable planet."))
4766 elif q.planet != NOPLANET and not damaged(DTRANSP):
4767 prout(_("Remainder of ship's complement beam down to %s.") %
4770 prout(_("Entire crew of %d left to die in outer space.") %
4772 game.casual += game.state.crew
4773 game.abandoned += game.state.crew
4775 # If at least one base left, give 'em the Faerie Queene
4777 game.icrystl = False # crystals are lost
4778 game.nprobes = 0 # No probes
4779 prout(_("You are captured by Klingons and released to"))
4780 prout(_("the Federation in a prisoner-of-war exchange."))
4781 nb = random.random()*game.state.rembase+1
4782 # Set up quadrant and position FQ adjacient to base
4783 if not game.quadrant == game.state.baseq[nb]:
4784 game.quadrant = game.state.baseq[nb]
4785 game.sector.x = game.sector.y = 5
4788 # position next to base by trial and error
4789 game.quad[game.sector.x][game.sector.y] = IHDOT
4790 for l in range(1, QUADSIZE+1):
4791 game.sector.x = 3.0*random.random() - 1.0 + game.base.x
4792 game.sector.y = 3.0*random.random() - 1.0 + game.base.y
4793 if VALID_SECTOR(game.sector.x, game.sector.y) and \
4794 game.quad[game.sector.x][game.sector.y] == IHDOT:
4797 break # found a spot
4798 game.sector.x=QUADSIZE/2
4799 game.sector.y=QUADSIZE/2
4801 # Get new commission
4802 game.quad[game.sector.x][game.sector.y] = game.ship = IHF
4803 game.state.crew = FULLCREW
4804 prout(_("Starfleet puts you in command of another ship,"))
4805 prout(_("the Faerie Queene, which is antiquated but,"))
4806 prout(_("still useable."))
4808 prout(_("The dilithium crystals have been moved."))
4810 game.iscraft = "offship" # Galileo disappears
4812 game.condition="docked"
4813 for l in range(0, NDEVICES):
4814 game.damage[l] = 0.0
4815 game.damage[DSHUTTL] = -1
4816 game.energy = game.inenrg = 3000.0
4817 game.shield = game.inshld = 1250.0
4818 game.torps = game.intorps = 6
4819 game.lsupres=game.inlsr=3.0
4825 # Code from planets.c begins here.
4828 # abort a lengthy operation if an event interrupts it
4831 if game.alldone or game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova or game.justin:
4836 # report on (uninhabited) planets in the galaxy
4840 prout(_("Spock- \"Planet report follows, Captain.\""))
4842 for i in range(game.inplan):
4843 if game.state.planets[i].pclass == destroyed:
4845 if (game.state.planets[i].known != "unknown" \
4846 and not game.state.planets[i].inhabited) \
4849 if idebug and game.state.planets[i].known=="unknown":
4850 proutn("(Unknown) ")
4851 proutn(_("Quadrant %s") % game.state.planets[i].w)
4852 proutn(_(" class "))
4853 proutn(game.state.planets[i].pclass)
4855 if game.state.planets[i].crystals != present:
4857 prout(_("dilithium crystals present."))
4858 if game.state.planets[i].known=="shuttle_down":
4859 prout(_(" Shuttle Craft Galileo on surface."))
4861 prout(_("No information available."))
4864 # enter standard orbit
4868 prout(_("Already in standard orbit."))
4870 if damaged(DWARPEN) and damaged(DIMPULS):
4871 prout(_("Both warp and impulse engines damaged."))
4873 if not is_valid(game.plnet) or abs(game.sector.x-game.plnet.x) > 1 or abs(game.sector.y-game.plnet.y) > 1:
4875 prout(_(" not adjacent to planet."))
4878 game.optime = 0.02+0.03*random.random()
4879 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4883 game.height = (1400.0+7200.0*random.random())
4884 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4889 # examine planets in this quadrant
4890 if damaged(DSRSENS):
4891 if game.options & OPTION_TTY:
4892 prout(_("Short range sensors damaged."))
4894 if not is_valid(game.plnet):
4895 if game.options & OPTION_TTY:
4896 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4898 if game.state.planets[game.iplnet].known == "unknown":
4899 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4901 prout(_(" Planet at Sector %s is of class %s.") %
4902 (sector,game.plnet, game.state.planets[game.iplnet]))
4903 if game.state.planets[game.iplnet].known=="shuttle_down":
4904 prout(_(" Sensors show Galileo still on surface."))
4905 proutn(_(" Readings indicate"))
4906 if game.state.planets[game.iplnet].crystals != present:
4908 prout(_(" dilithium crystals present.\""))
4909 if game.state.planets[game.iplnet].known == "unknown":
4910 game.state.planets[game.iplnet].known = "known"
4913 # use the transporter
4917 if damaged(DTRANSP):
4918 prout(_("Transporter damaged."))
4919 if not damaged(DSHUTTL) and (game.state.planets[game.iplnet].known=="shuttle_down" or game.iscraft == "onship"):
4921 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4925 if not game.inorbit:
4927 prout(_(" not in standard orbit."))
4930 prout(_("Impossible to transport through shields."))
4932 if game.state.planets[game.iplnet].known=="unknown":
4933 prout(_("Spock- \"Captain, we have no information on this planet"))
4934 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4935 prout(_(" you may not go down.\""))
4937 if not game.landed and game.state.planets[game.iplnet].crystals==absent:
4938 prout(_("Spock- \"Captain, I fail to see the logic in"))
4939 prout(_(" exploring a planet with no dilithium crystals."))
4940 proutn(_(" Are you sure this is wise?\" "))
4944 if not (game.options & OPTION_PLAIN):
4945 nrgneed = 50 * game.skill + game.height / 100.0
4946 if nrgneed > game.energy:
4947 prout(_("Engineering to bridge--"))
4948 prout(_(" Captain, we don't have enough energy for transportation."))
4950 if not game.landed and nrgneed * 2 > game.energy:
4951 prout(_("Engineering to bridge--"))
4952 prout(_(" Captain, we have enough energy only to transport you down to"))
4953 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4954 if game.state.planets[game.iplnet].known == "shuttle_down":
4955 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4956 proutn(_(" Are you sure this is wise?\" "))
4961 # Coming from planet
4962 if game.state.planets[game.iplnet].known=="shuttle_down":
4963 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4967 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4968 prout(_("Landing party assembled, ready to beam up."))
4970 prout(_("Kirk whips out communicator..."))
4971 prouts(_("BEEP BEEP BEEP"))
4973 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4976 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4978 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4980 prout(_("Kirk- \"Energize.\""))
4983 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4985 if random.random() > 0.98:
4986 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4988 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4991 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4992 game.landed = not game.landed
4993 game.energy -= nrgneed
4995 prout(_("Transport complete."))
4996 if game.landed and game.state.planets[game.iplnet].known=="shuttle_down":
4997 prout(_("The shuttle craft Galileo is here!"))
4998 if not game.landed and game.imine:
5005 # strip-mine a world for dilithium
5009 prout(_("Mining party not on planet."))
5011 if game.state.planets[game.iplnet].crystals == mined:
5012 prout(_("This planet has already been strip-mined for dilithium."))
5014 elif game.state.planets[game.iplnet].crystals == absent:
5015 prout(_("No dilithium crystals on this planet."))
5018 prout(_("You've already mined enough crystals for this trip."))
5020 if game.icrystl and game.cryprob == 0.05:
5021 proutn(_("With all those fresh crystals aboard the "))
5024 prout(_("there's no reason to mine more at this time."))
5026 game.optime = (0.1+0.2*random.random())*game.state.planets[game.iplnet].pclass
5029 prout(_("Mining operation complete."))
5030 game.state.planets[game.iplnet].crystals = mined
5031 game.imine = game.ididit = True
5034 # use dilithium crystals
5038 if not game.icrystl:
5039 prout(_("No dilithium crystals available."))
5041 if game.energy >= 1000:
5042 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
5043 prout(_(" except when Condition Yellow exists."))
5045 prout(_("Spock- \"Captain, I must warn you that loading"))
5046 prout(_(" raw dilithium crystals into the ship's power"))
5047 prout(_(" system may risk a severe explosion."))
5048 proutn(_(" Are you sure this is wise?\" "))
5053 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
5054 prout(_(" Mr. Spock and I will try it.\""))
5056 prout(_("Spock- \"Crystals in place, Sir."))
5057 prout(_(" Ready to activate circuit.\""))
5059 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
5061 if random.random() <= game.cryprob:
5062 prouts(_(" \"Activating now! - - No good! It's***"))
5064 prouts(_("***RED ALERT! RED A*L********************************"))
5067 prouts(_("****************** KA-BOOM!!!! *******************"))
5071 game.energy += 5000.0*(1.0 + 0.9*random.random())
5072 prouts(_(" \"Activating now! - - "))
5073 prout(_("The instruments"))
5074 prout(_(" are going crazy, but I think it's"))
5075 prout(_(" going to work!! Congratulations, Sir!\""))
5080 # use shuttlecraft for planetary jaunt
5083 if damaged(DSHUTTL):
5084 if game.damage[DSHUTTL] == -1.0:
5085 if game.inorbit and game.state.planets[game.iplnet].known == "shuttle_down":
5086 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
5088 prout(_("Ye Faerie Queene had no shuttle craft."))
5089 elif game.damage[DSHUTTL] > 0:
5090 prout(_("The Galileo is damaged."))
5091 else: # game.damage[DSHUTTL] < 0
5092 prout(_("Shuttle craft is now serving Big Macs."))
5094 if not game.inorbit:
5096 prout(_(" not in standard orbit."))
5098 if (game.state.planets[game.iplnet].known != "shuttle_down") and game.iscraft != "onship":
5099 prout(_("Shuttle craft not currently available."))
5101 if not game.landed and game.state.planets[game.iplnet].known=="shuttle_down":
5102 prout(_("You will have to beam down to retrieve the shuttle craft."))
5104 if game.shldup or game.condition == "docked":
5105 prout(_("Shuttle craft cannot pass through shields."))
5107 if game.state.planets[game.iplnet].known=="unknown":
5108 prout(_("Spock- \"Captain, we have no information on this planet"))
5109 prout(_(" and Starfleet Regulations clearly state that in this situation"))
5110 prout(_(" you may not fly down.\""))
5112 game.optime = 3.0e-5*game.height
5113 if game.optime >= 0.8*game.state.remtime:
5114 prout(_("First Officer Spock- \"Captain, I compute that such"))
5115 proutn(_(" a maneuver would require approximately %2d%% of our") % \
5116 int(100*game.optime/game.state.remtime))
5117 prout(_("remaining time."))
5118 proutn(_("Are you sure this is wise?\" "))
5124 if game.iscraft == "onship":
5126 if not damaged(DTRANSP):
5127 proutn(_("Spock- \"Would you rather use the transporter?\" "))
5131 proutn(_("Shuttle crew"))
5133 proutn(_("Rescue party"))
5134 prout(_(" boards Galileo and swoops toward planet surface."))
5135 game.iscraft = "offship"
5139 game.state.planets[game.iplnet].known="shuttle_down"
5140 prout(_("Trip complete."))
5143 # Ready to go back to ship
5144 prout(_("You and your mining party board the"))
5145 prout(_("shuttle craft for the trip back to the Enterprise."))
5147 prouts(_("The short hop begins . . ."))
5149 game.state.planets[game.iplnet].known="known"
5155 game.iscraft = "onship"
5161 prout(_("Trip complete."))
5166 prout(_("Mining party assembles in the hangar deck,"))
5167 prout(_("ready to board the shuttle craft \"Galileo\"."))
5169 prouts(_("The hangar doors open; the trip begins."))
5172 game.iscraft = "offship"
5175 game.state.planets[game.iplnet].known = "shuttle_down"
5178 prout(_("Trip complete."))
5182 # use the big zapper
5188 if game.ship != IHE:
5189 prout(_("Ye Faerie Queene has no death ray."))
5192 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
5195 prout(_("Death Ray is damaged."))
5197 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
5198 prout(_(" is highly unpredictible. Considering the alternatives,"))
5199 proutn(_(" are you sure this is wise?\" "))
5202 prout(_("Spock- \"Acknowledged.\""))
5205 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
5207 prout(_("Crew scrambles in emergency preparation."))
5208 prout(_("Spock and Scotty ready the death ray and"))
5209 prout(_("prepare to channel all ship's power to the device."))
5211 prout(_("Spock- \"Preparations complete, sir.\""))
5212 prout(_("Kirk- \"Engage!\""))
5214 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
5217 if game.options & OPTION_PLAIN:
5220 prouts(_("Sulu- \"Captain! It's working!\""))
5222 while game.nenhere > 0:
5223 deadkl(game.ks[1], game.quad[game.ks[1].x][game.ks[1].y],game.ks[1])
5224 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
5225 if (game.state.remkl + game.state.remcom + game.state.nscrem) == 0:
5227 if (game.options & OPTION_PLAIN) == 0:
5228 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
5229 if random.random() <= 0.05:
5230 prout(_(" is still operational.\""))
5232 prout(_(" has been rendered nonfunctional.\""))
5233 game.damage[DDRAY] = 39.95
5235 r = random.random() # Pick failure method
5237 prouts(_("Sulu- \"Captain! It's working!\""))
5239 prouts(_("***RED ALERT! RED ALERT!"))
5241 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
5243 prouts(_("***RED ALERT! RED A*L********************************"))
5246 prouts(_("****************** KA-BOOM!!!! *******************"))
5251 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
5253 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
5255 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
5256 prout(_(" have apparently been transformed into strange mutations."))
5257 prout(_(" Vulcans do not seem to be affected."))
5259 prout(_("Kirk- \"Raauch! Raauch!\""))
5264 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
5266 proutn(_("Spock- \"I believe the word is"))
5267 prouts(_(" *ASTONISHING*"))
5268 prout(_(" Mr. Sulu."))
5269 for i in range(1, QUADSIZE+1):
5270 for j in range(1, QUADSIZE+1):
5271 if game.quad[i][j] == IHDOT:
5272 game.quad[i][j] = IHQUEST
5273 prout(_(" Captain, our quadrant is now infested with"))
5274 prouts(_(" - - - - - - *THINGS*."))
5276 prout(_(" I have no logical explanation.\""))
5278 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
5280 prout(_("Scotty- \"There are so many tribbles down here"))
5281 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
5285 # Code from reports.c begins here
5287 def attackreport(curt):
5288 # report status of bases under attack
5290 if is_scheduled(FCDBAS):
5291 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
5292 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
5293 elif game.isatb == 1:
5294 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
5295 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
5297 prout(_("No Starbase is currently under attack."))
5299 if is_scheduled(FCDBAS):
5300 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
5302 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
5306 # report on general game status
5308 s1 = "" and game.thawed and _("thawed ")
5309 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
5310 s3 = (None, _("novice"). _("fair"),
5311 _("good"), _("expert"), _("emeritus"))[game.skill]
5312 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
5313 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
5314 prout(_("No plaque is allowed."))
5316 prout(_("This is tournament game %d.") % game.tourn)
5317 prout(_("Your secret password is \"%s\"") % game.passwd)
5318 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + game.state.remcom + game.state.nscrem)),
5319 (game.inkling + game.incom + game.inscom)))
5320 if game.incom - game.state.remcom:
5321 prout(_(", including %d Commander%s.") % (game.incom - game.state.remcom, (_("s"), "")[(game.incom - game.state.remcom)==1]))
5322 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
5323 prout(_(", but no Commanders."))
5326 if game.skill > SKILL_FAIR:
5327 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
5328 if game.state.rembase != game.inbase:
5330 if game.inbase-game.state.rembase==1:
5331 proutn(_("has been 1 base"))
5333 proutn(_("have been %d bases") % (game.inbase-game.state.rembase))
5334 prout(_(" destroyed, %d remaining.") % game.state.rembase)
5336 prout(_("There are %d bases.") % game.inbase)
5337 if communicating() or game.iseenit:
5338 # Don't report this if not seen and
5339 # either the radio is dead or not at base!
5343 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
5345 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
5346 if game.ship == IHE:
5347 proutn(_("You have "))
5349 proutn("%d" % (game.nprobes))
5352 proutn(_(" deep space probe"))
5356 if communicating() and is_scheduled(FDSPROB):
5358 proutn(_("An armed deep space probe is in "))
5360 proutn(_("A deep space probe is in "))
5361 prout("Quadrant %s." % game.probec)
5363 if game.cryprob <= .05:
5364 prout(_("Dilithium crystals aboard ship... not yet used."))
5368 while game.cryprob > ai:
5371 prout(_("Dilithium crystals have been used %d time%s.") % \
5372 (i, (_("s"), "")[i==1]))
5376 # long-range sensor scan
5377 if damaged(DLRSENS):
5378 # Now allow base's sensors if docked
5379 if game.condition != "docked":
5380 prout(_("LONG-RANGE SENSORS DAMAGED."))
5382 prout(_("Starbase's long-range scan"))
5384 prout(_("Long-range scan"))
5385 for x in range(game.quadrant.x-1, game.quadrant.x+2):
5387 for y in range(game.quadrant.y-1, game.quadrant.y+2):
5388 if not VALID_QUADRANT(x, y):
5391 if not damaged(DRADIO):
5392 game.state.galaxy[x][y].charted = True
5393 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
5394 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
5395 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
5396 if game.state.galaxy[x][y].supernova:
5399 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
5407 for i in range(NDEVICES):
5410 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
5411 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
5413 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
5414 game.damage[i]+0.05,
5415 game.docfac*game.damage[i]+0.005))
5417 prout(_("All devices functional."))
5420 # update the chart in the Enterprise's computer from galaxy data
5421 game.lastchart = game.state.date
5422 for i in range(1, GALSIZE+1):
5423 for j in range(1, GALSIZE+1):
5424 if game.state.galaxy[i][j].charted:
5425 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
5426 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
5427 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
5430 # display the star chart
5432 if not damaged(DRADIO):
5434 if game.lastchart < game.state.date and game.condition == "docked":
5435 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
5438 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
5439 if game.state.date > game.lastchart:
5440 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
5441 prout(" 1 2 3 4 5 6 7 8")
5442 for i in range(1, GALSIZE+1):
5443 proutn("%d |" % (i))
5444 for j in range(1, GALSIZE+1):
5445 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5449 if game.state.galaxy[i][j].supernova:
5451 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
5453 elif game.state.galaxy[i][j].charted:
5454 sprintf(buf, "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars))
5458 if (game.options & OPTION_SHOWME) and i == game.quadrant.x and j == game.quadrant.y:
5466 def sectscan(goodScan, i, j):
5467 # light up an individual dot in a sector
5468 if goodScan or (abs(i-game.sector.x)<= 1 and abs(j-game.sector.y) <= 1):
5469 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):
5470 if game.condition == "red": textcolor(RED)
5471 elif game.condition == "green": textcolor(GREEN)
5472 elif game.condition == "yellow": textcolor(YELLOW)
5473 elif game.condition == "docked": textcolor(CYAN)
5474 elif game.condition == "dead": textcolor(BROWN)
5475 if game.quad[i][j] != game.ship:
5477 proutn("%c " % game.quad[i][j])
5483 # print status report lines
5485 if not req or req == 1:
5486 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
5487 % (game.state.date, game.state.remtime))
5488 elif not req or req == 2:
5489 if game.condition != "docked":
5492 for t in range(0, NDEVICES):
5493 if game.damage[t]>0:
5495 prstat(_("Condition"), _("%s, %i DAMAGES") % (game.condition.upper(), dam))
5496 elif not req or req == 3:
5497 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
5498 elif not req or req == 4:
5499 if damaged(DLIFSUP):
5500 if game.condition == "docked":
5501 sprintf(s, _("DAMAGED, Base provides"))
5503 sprintf(s, _("DAMAGED, reserves=%4.2f") % game.lsupres)
5505 sprintf(s, _("ACTIVE"))
5506 prstat(_("Life Support"), s)
5507 elif not req or req == 5:
5508 prstat(_("Warp Factor"), "%.1f" % (game.warpfac))
5509 elif not req or req == 6:
5511 if game.icrystl and (game.options & OPTION_SHOWME):
5512 extra = _(" (have crystals)")
5513 prstat(_("Energy"), "%.2f%s" % game.energy, extra)
5514 elif not req or req == 7:
5515 prstat(_("Torpedoes"), "%d" % (game.torps))
5516 elif not req or req == 8:
5517 if damaged(DSHIELD):
5518 strcpy(s, _("DAMAGED,"))
5522 strcpy(s, _("DOWN,"))
5523 data = _(" %d%% %.1f units") \
5524 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
5525 prstat(_("Shields"), s)
5526 elif not req or req == 9:
5527 prstat(_("Klingons Left"), "%d" \
5528 % (game.state.remkl + game.state.remcom + game.state.nscrem))
5529 elif not req or req == 10:
5530 if game.options & OPTION_WORLDS:
5531 plnet = game.state.galaxy[game.quadrant.x][game.quadrant.y].planet
5532 if plnet != NOPLANET and game.state.planets[plnet].inhabited:
5533 prstat(_("Major system"), plnet.name)
5535 prout(_("Sector is uninhabited"))
5536 elif not req or req == 11:
5537 attackreport(not req)
5540 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
5541 while scan() == IHEOL:
5542 proutn(_("Information desired? "))
5544 if citem in requests:
5545 status(requests.index(citem))
5547 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
5548 prout((" date, condition, position, lsupport, warpfactor,"))
5549 prout((" energy, torpedoes, shields, klingons, system, time."))
5554 if damaged(DSRSENS):
5555 # Allow base's sensors if docked
5556 if game.condition != "docked":
5557 prout(_(" S.R. SENSORS DAMAGED!"))
5560 prout(_(" [Using Base's sensors]"))
5562 prout(_(" Short-range scan"))
5563 if goodScan and not damaged(DRADIO):
5564 game.state.chart[game.quadrant.x][game.quadrant.y].klingons = game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons
5565 game.state.chart[game.quadrant.x][game.quadrant.y].starbase = game.state.galaxy[game.quadrant.x][game.quadrant.y].starbase
5566 game.state.chart[game.quadrant.x][game.quadrant.y].stars = game.state.galaxy[game.quadrant.x][game.quadrant.y].stars
5567 game.state.galaxy[game.quadrant.x][game.quadrant.y].charted = True
5568 prout(" 1 2 3 4 5 6 7 8 9 10")
5569 if game.condition != "docked":
5571 for i in range(1, QUADSIZE+1):
5572 proutn("%2d " % (i))
5573 for j in range(1, QUADSIZE+1):
5574 sectscan(goodScan, i, j)
5579 # use computer to get estimated time of arrival for a warp jump
5580 w1 = coord(); w2 = coord()
5582 if damaged(DCOMPTR):
5583 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5586 if scan() != IHREAL:
5589 proutn(_("Destination quadrant and/or sector? "))
5594 if scan() != IHREAL:
5598 if scan() == IHREAL:
5600 if scan() != IHREAL:
5605 if game.quadrant.y>w1.x:
5609 if game.quadrant.x>w1.y:
5614 if not VALID_QUADRANT(w1.x, w1.y) or not VALID_SECTOR(w2.x, w2.y):
5617 game.dist = math.sqrt(square(w1.y-game.quadrant.y+0.1*(w2.y-game.sector.y))+
5618 square(w1.x-game.quadrant.x+0.1*(w2.x-game.sector.x)))
5622 prout(_("Answer \"no\" if you don't know the value:"))
5625 proutn(_("Time or arrival date? "))
5628 if ttime > game.state.date:
5629 ttime -= game.state.date # Actually a star date
5630 twarp=(math.floor(math.sqrt((10.0*game.dist)/ttime)*10.0)+1.0)/10.0
5631 if ttime <= 1e-10 or twarp > 10:
5632 prout(_("We'll never make it, sir."))
5639 proutn(_("Warp factor? "))
5643 if twarp<1.0 or twarp > 10.0:
5647 prout(_("Captain, certainly you can give me one of these."))
5650 ttime = (10.0*game.dist)/square(twarp)
5651 tpower = game.dist*twarp*twarp*twarp*(game.shldup+1)
5652 if tpower >= game.energy:
5653 prout(_("Insufficient energy, sir."))
5654 if not game.shldup or tpower > game.energy*2.0:
5657 proutn(_("New warp factor to try? "))
5658 if scan() == IHREAL:
5661 if twarp<1.0 or twarp > 10.0:
5669 prout(_("But if you lower your shields,"))
5670 proutn(_("remaining"))
5673 proutn(_("Remaining"))
5674 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5676 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5678 prout(_("Any warp speed is adequate."))
5680 prout(_("Minimum warp needed is %.2f,") % (twarp))
5681 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5682 if game.state.remtime < ttime:
5683 prout(_("Unfortunately, the Federation will be destroyed by then."))
5685 prout(_("You'll be taking risks at that speed, Captain"))
5686 if (game.isatb==1 and game.state.kscmdr == w1 and \
5687 scheduled(FSCDBAS)< ttime+game.state.date) or \
5688 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5689 prout(_("The starbase there will be destroyed by then."))
5690 proutn(_("New warp factor to try? "))
5691 if scan() == IHREAL:
5694 if twarp<1.0 or twarp > 10.0:
5703 #ifdef BSD_BUG_FOR_BUG
5704 # A visual scan is made in a particular direction of three sectors
5705 # in the general direction specified. This takes time, and
5706 # Klingons can attack you, so it should be done only when sensors
5707 # are out. Code swiped from BSD-Trek. Not presently used, as we
5708 # automatically display all adjacent sectors on the short-range
5709 # scan even when short-range sensors are out.
5711 # This struct[] has the delta x, delta y for particular directions
5729 if scan() != IHREAL:
5731 proutn(_("Direction? "))
5735 if aaitem < 0.0 or aaitem > 360.0:
5737 co = (aaitem + 22) / 45
5739 ix = game.sector.x + v.x
5740 iy = game.sector.y + v.y
5741 if ix < 0 or ix >= QUADSIZE or iy < 0 or iy >= QUADSIZE:
5744 co = game.quad[ix][iy]
5745 printf("%d,%d %c " % (ix, iy, co))
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("%c " % (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 prout("%c %d,%d\n" % (co, ix, iy))
5766 # Code from setup.c begins here
5769 return os.fstat(fd).st_size
5772 # issue a historically correct banner
5774 prout(_("-SUPER- STAR TREK"))
5776 #ifdef __HISTORICAL__
5777 # prout(_("Latest update-21 Sept 78"))
5779 #endif __HISTORICAL__
5784 citem = "emsave.trk"
5788 proutn(_("File name: "))
5794 if '.' not in citem:
5797 fp = open(citem, "wb")
5799 prout(_("Can't freeze game as file %s") % citem)
5801 cPickle.dump(game, fp)
5805 # retrieve saved game
5806 game.passwd[0] = '\0'
5809 proutn(_("File name: "))
5815 if '.' not in citem:
5818 fp = open(citem, "rb")
5820 prout(_("Can't thaw game in %s") % citem)
5822 game = cPickle.load(fp)
5826 # I used <http://www.memory-alpha.org> to find planets
5827 # with references in ST:TOS. Eath and the Alpha Centauri
5828 # Colony have been omitted.
5830 # Some planets marked Class G and P here will be displayed as class M
5831 # because of the way planets are generated. This is a known bug.
5834 _("Andoria (Fesoan)"), # several episodes
5835 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5836 _("Vulcan (T'Khasi)"), # many episodes
5837 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5838 _("Argelius II (Nelphia)"),# TOS: "Wolf in the Fold" ("IV" in BSD)
5839 _("Ardana"), # TOS: "The Cloud Minders"
5840 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5841 _("Gideon"), # TOS: "The Mark of Gideon"
5842 _("Aldebaran III"), # TOS: "The Deadly Years"
5843 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5844 _("Altair IV"), # TOS: "Amok Time
5845 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5846 _("Benecia"), # TOS: "The Conscience of the King"
5847 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5848 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5849 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5850 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5851 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5852 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5853 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5854 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5855 _("Ingraham B"), # TOS: "Operation: Annihilate"
5856 _("Janus IV"), # TOS: "The Devil in the Dark"
5857 _("Makus III"), # TOS: "The Galileo Seven"
5858 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5859 _("Omega IV"), # TOS: "The Omega Glory"
5860 _("Regulus V"), # TOS: "Amok Time
5861 _("Deneva"), # TOS: "Operation -- Annihilate!"
5862 # Worlds from BSD Trek
5863 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5864 _("Beta III"), # TOS: "The Return of the Archons"
5865 _("Triacus"), # TOS: "And the Children Shall Lead",
5866 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5868 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5869 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5870 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5871 # _("Izar"), # TOS: "Whom Gods Destroy"
5872 # _("Tiburon"), # TOS: "The Way to Eden"
5873 # _("Merak II"), # TOS: "The Cloud Minders"
5874 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5875 # _("Iotia"), # TOS: "A Piece of the Action"
5879 _("S. R. Sensors"), \
5880 _("L. R. Sensors"), \
5882 _("Photon Tubes"), \
5883 _("Life Support"), \
5884 _("Warp Engines"), \
5885 _("Impulse Engines"), \
5887 _("Subspace Radio"), \
5888 _("Shuttle Craft"), \
5890 _("Navigation System"), \
5892 _("Shield Control"), \
5897 def setup(needprompt):
5898 # prepare to play, set up cosmos
5901 # Decide how many of everything
5902 if choose(needprompt):
5903 return # frozen game
5904 # Prepare the Enterprise
5905 game.alldone = game.gamewon = False
5907 game.state.crew = FULLCREW
5908 game.energy = game.inenrg = 5000.0
5909 game.shield = game.inshld = 2500.0
5910 game.shldchg = False
5914 game.quadrant = randplace(GALSIZE)
5915 game.sector = randplace(QUADSIZE)
5916 game.torps = game.intorps = 10
5917 game.nprobes = int(3.0*random.random() + 2.0) # Give them 2-4 of these
5919 game.wfacsq = game.warpfac * game.warpfac
5920 for i in range(0, NDEVICES):
5921 game.damage[i] = 0.0
5922 # Set up assorted game parameters
5923 invalidate(game.battle)
5924 game.state.date = game.indate = 100.0*int(31.0*random.random()+20.0)
5925 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5926 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5927 game.isatb = game.state.nplankl = 0
5928 game.state.starkl = game.state.basekl = 0
5929 game.iscraft = "onship"
5933 for i in range(1, GALSIZE+1):
5934 for j in range(1, GALSIZE+1):
5935 quad = game.state.galaxy[i][j]
5937 quad.planet = NOPLANET
5940 quad.starbase = False
5941 quad.supernova = False
5942 quad.status = "secure"
5943 # Initialize times for extraneous events
5944 schedule(FSNOVA, expran(0.5 * game.intime))
5945 schedule(FTBEAM, expran(1.5 * (game.intime / game.state.remcom)))
5946 schedule(FSNAP, 1.0 + random.random()) # Force an early snapshot
5947 schedule(FBATTAK, expran(0.3*game.intime))
5949 if game.state.nscrem:
5950 schedule(FSCMOVE, 0.2777)
5955 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5956 schedule(FDISTR, expran(1.0 + game.intime))
5961 # Starchart is functional but we've never seen it
5962 game.lastchart = FOREVER
5963 # Put stars in the galaxy
5965 for i in range(1, GALSIZE+1):
5966 for j in range(1, GALSIZE+1):
5967 k = random.random()*9.0 + 1.0
5969 game.state.galaxy[i][j].stars = k
5970 # Locate star bases in galaxy
5971 for i in range(1, game.inbase+1):
5974 w = randplace(GALSIZE)
5975 if not game.state.galaxy[w.x][w.y].starbase:
5978 # C version: for (j = i-1; j > 0; j--)
5979 # so it did them in the opposite order.
5981 # Improved placement algorithm to spread out bases
5982 distq = w.distance(baseq[j])
5983 if distq < 6.0*(BASEMAX+1-game.inbase) and random.random() < 0.75:
5986 prout("=== Abandoning base #%d at %s" % (i, w))
5988 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5990 prout("=== Saving base #%d, close to #%d" % (i, j))
5993 game.state.baseq[i] = w
5994 game.state.galaxy[w.x][w.y].starbase = True
5995 game.state.chart[w.x][w.y].starbase = True
5996 # Position ordinary Klingon Battle Cruisers
5998 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5999 if klumper > MAXKLQUAD:
6003 klump = (1.0 - r*r)*klumper
6008 w = randplace(GALSIZE)
6009 if not game.state.galaxy[w.x][w.y].supernova and \
6010 game.state.galaxy[w.x][w.y].klingons + klump <= MAXKLQUAD:
6012 game.state.galaxy[w.x][w.y].klingons += klump
6015 # Position Klingon Commander Ships
6016 for i in range(1, game.incom+1):
6018 w = randplace(GALSIZE)
6019 if (game.state.galaxy[w.x][w.y].klingons or random.random()>=0.75) and \
6020 not game.state.galaxy[w.x][w.y].supernova and \
6021 game.state.galaxy[w.x][w.y].klingons <= MAXKLQUAD-1 and \
6022 not w in game.state.kcmdr[:i]:
6024 game.state.galaxy[w.x][w.y].klingons += 1
6025 game.state.kcmdr[i] = w
6026 # Locate planets in galaxy
6027 for i in range(game.inplan):
6029 w = randplace(GALSIZE)
6030 if game.state.galaxy[w.x][w.y].planet == NOPLANET:
6034 new.crystals = "absent"
6035 if (game.options & OPTION_WORLDS) and i < NINHAB:
6036 new.pclass = "M" # All inhabited planets are class M
6037 new.crystals = "absent"
6039 new.name = systnames[i]
6040 new.inhabited = True
6042 new.pclass = ("M", "N", "O")[random.random()*3.0]
6043 if random.random()*1.5: # 1 in 3 chance of crystals
6044 new.crystals = "present"
6045 new.known = "unknown"
6046 new.inhabited = False
6047 game.state.galaxy[w.x][w.y].planet = new
6048 game.state.plnets.append(new)
6050 for i in range(1, game.state.nromrem+1):
6051 w = randplace(GALSIZE)
6052 game.state.galaxy[w.x][w.y].romulans += 1
6053 # Locate the Super Commander
6054 if game.state.nscrem > 0:
6056 w = randplace(GALSIZE)
6057 if not game.state.galaxy[w.x][w.y].supernova and game.state.galaxy[w.x][w.y].klingons <= MXKLQUAD:
6059 game.state.kscmdr = w
6060 game.state.galaxy[w.x][w.y].klingons += 1
6061 # Place thing (in tournament game, thingx == -1, don't want one!)
6063 thing = randplace(GALSIZE)
6067 game.state.snap = False
6068 if game.skill == SKILL_NOVICE:
6069 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
6070 prout(_("a deadly Klingon invasion force. As captain of the United"))
6071 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
6072 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
6073 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
6074 prout(_("your mission. As you proceed you may be given more time."))
6076 prout(_("You will have %d supporting starbases.") % (game.inbase))
6077 proutn(_("Starbase locations- "))
6079 prout(_("Stardate %d.") % int(game.state.date))
6081 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
6082 prout(_("An unknown number of Romulans."))
6083 if game.state.nscrem:
6084 prout(_("And one (GULP) Super-Commander."))
6085 prout(_("%d stardates.") % int(game.intime))
6086 proutn(_("%d starbases in ") % game.inbase)
6087 for i in range(1, game.inbase+1):
6088 proutn(`game.state.baseq[i]`)
6091 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
6092 proutn(_(" Sector %s") % game.sector)
6094 prout(_("Good Luck!"))
6095 if game.state.nscrem:
6096 prout(_(" YOU'LL NEED IT."))
6099 if game.nenhere - iqhere-game.ithere:
6101 if game.neutz: # bad luck to start in a Romulan Neutral Zone
6104 def choose(needprompt):
6105 # choose your game type
6109 game.skill = SKILL_NONE
6111 if needprompt: # Can start with command line options
6112 proutn(_("Would you like a regular, tournament, or saved game? "))
6114 if len(citem)==0: # Try again
6116 if isit("tournament"):
6117 while scan() == IHEOL:
6118 proutn(_("Type in tournament number-"))
6121 continue # We don't want a blank entry
6122 game.tourn = int(aaitem)
6126 if isit("saved") or isit("frozen"):
6130 if game.passwd == None:
6132 if not game.alldone:
6133 game.thawed = True # No plaque if not finished
6139 proutn(_("What is \"%s\"?"), citem)
6141 while game.length==0 or game.skill==SKILL_NONE:
6142 if scan() == IHALPHA:
6145 elif isit("medium"):
6149 elif isit("novice"):
6150 game.skill = SKILL_NOVICE
6152 game.skill = SKILL_FAIR
6154 game.skill = SKILL_GOOD
6155 elif isit("expert"):
6156 game.skill = SKILL_EXPERT
6157 elif isit("emeritus"):
6158 game.skill = SKILL_EMERITUS
6160 proutn(_("What is \""))
6166 proutn(_("Would you like a Short, Medium, or Long game? "))
6167 elif game.skill == SKILL_NONE:
6168 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
6169 # Choose game options -- added by ESR for SST2K
6170 if scan() != IHALPHA:
6172 proutn(_("Choose your game style (or just press enter): "))
6175 # Approximates the UT FORTRAN version.
6176 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6177 game.options |= OPTION_PLAIN
6179 # Approximates Tom Almy's version.
6180 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
6181 game.options |= OPTION_ALMY
6185 proutn(_("What is \"%s\"?") % citem)
6187 if game.passwd == "debug":
6189 fputs("=== Debug mode enabled\n", sys.stdout)
6191 # Use parameters to generate initial values of things
6192 game.damfac = 0.5 * game.skill
6193 game.state.rembase = 2.0 + random.random()*(BASEMAX-2.0)
6194 game.inbase = game.state.rembase
6196 if game.options & OPTION_PLANETS:
6197 game.inplan += (MAXUNINHAB/2) + (MAXUNINHAB/2+1)*random.random()
6198 if game.options & OPTION_WORLDS:
6199 game.inplan += NINHAB
6200 game.state.nromrem = game.inrom = (2.0+random.random())*game.skill
6201 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
6202 game.state.remtime = 7.0 * game.length
6203 game.intime = game.state.remtime
6204 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*random.random())*game.skill*0.1+.15)
6205 game.incom = game.skill + 0.0625*game.inkling*random.random()
6206 game.state.remcom = min(10, game.incom)
6207 game.incom = game.state.remcom
6208 game.state.remres = (game.inkling+4*game.incom)*game.intime
6209 game.inresor = game.state.remres
6210 if game.inkling > 50:
6211 game.state.rembase += 1
6212 game.inbase = game.state.rembase
6216 # drop a feature on a random dot in the current quadrant
6219 w = randplace(QUADSIZE)
6220 if game.quad[w.x][w.y] == IHDOT:
6222 game.quad[w.x][w.y] = iquad
6226 # update our alert status
6227 game.condition = "green"
6228 if game.energy < 1000.0:
6229 game.condition = "yellow"
6230 if game.state.galaxy[game.quadrant.x][game.quadrant.y].klingons or game.state.galaxy[game.quadrant.x][game.quadrant.y].romulans:
6231 game.condition = "red"
6233 game.condition="dead"
6236 # drop new Klingon into current quadrant
6239 game.kdist[i] = game.kavgd[i] = distance(game.sector, pi)
6240 game.kpower[i] = random.random()*150.0 +300.0 +25.0*game.skill
6244 # set up a new state of quadrant, for when we enter or re-enter it
6247 invalidate(game.base)
6249 game.comhere = False
6250 invalidate(game.plnet)
6256 game.inorbit = False
6258 game.ientesc = False
6262 game.iseenit = False
6264 # Attempt to escape Super-commander, so tbeam back!
6268 for i in range(1, QUADSIZE+1):
6269 for j in range(1, QUADSIZE+1):
6270 game.quad[i][j] = IHDOT
6271 q = game.state.galaxy[game.quadrant.x][game.quadrant.y]
6272 # cope with supernova
6275 game.klhere = q.klingons
6276 game.irhere = q.romulans
6277 game.nenhere = game.klhere + game.irhere
6280 game.quad[game.sector.x][game.sector.y] = game.ship
6283 w.x = w.y = 0 # quiet a gcc warning
6284 # Position ordinary Klingons
6285 for i in range(1, game.klhere+1):
6287 # If we need a commander, promote a Klingon
6288 for i in range(1, game.state.remcom+1):
6289 if same(game.state.kcmdr[i], game.quadrant):
6292 if i <= game.state.remcom:
6293 game.quad[w.x][w.y] = IHC
6294 game.kpower[game.klhere] = 950.0+400.0*random.random()+50.0*game.skill
6297 # If we need a super-commander, promote a Klingon
6298 if same(game.quadrant, game.state.kscmdr):
6299 game.quad[game.ks[1].x][game.ks[1].y] = IHS
6300 game.kpower[1] = 1175.0 + 400.0*random.random() + 125.0*game.skill
6301 game.iscate = (game.state.remkl > 1)
6303 # Put in Romulans if needed
6304 for i in range(game.klhere+1, game.nenhere+1):
6307 game.kdist[i] = game.kavgd[i] = distance(game.sector, w)
6308 game.kpower[i] = random.random()*400.0 + 450.0 + 50.0*game.skill
6309 # If quadrant needs a starbase, put it in
6311 game.base = dropin(IHB)
6313 # If quadrant needs a planet, put it in
6314 if q.planet != NOPLANET:
6315 game.iplnet = q.planet
6316 if game.state.planets[q.planet].inhabited == UNINHABITED:
6317 game.plnet = dropin(IHP)
6319 game.plnet = dropin(IHW)
6320 # Check for condition
6322 # And finally the stars
6323 for i in range(1, q.stars+1):
6327 if game.irhere > 0 and game.klhere == 0:
6329 if not damaged(DRADIO):
6331 prout(_("LT. Uhura- \"Captain, an urgent message."))
6332 prout(_(" I'll put it on audio.\" CLICK"))
6334 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
6335 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
6338 # Put in THING if needed
6339 if same(thing, game.quadrant):
6341 thing = randplace(GALSIZE)
6344 game.ks[game.nenhere] = w
6345 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6346 distance(game.sector, w)
6347 game.kpower[game.nenhere] = random.random()*6000.0 +500.0 +250.0*game.skill
6348 if not damaged(DSRSENS):
6350 prout(_("Mr. Spock- \"Captain, this is most unusual."))
6351 prout(_(" Please examine your short-range scan.\""))
6353 # Decide if quadrant needs a Tholian; lighten up if skill is low
6354 if game.options & OPTION_THOLIAN:
6355 if (game.skill < SKILL_GOOD and random.random() <= 0.02) or \
6356 (game.skill == SKILL_GOOD and random.random() <= 0.05) or \
6357 (game.skill > SKILL_GOOD and random.random() <= 0.08):
6359 game.tholian.x = random.choice((1, QUADSIZE))
6360 game.tholian.y = random.choice((1, QUADSIZE))
6361 if game.quad[game.tholian.x][game.tholian.y] == IHDOT:
6363 game.quad[game.tholian.x][game.tholian.y] = IHT
6366 game.ks[game.nenhere] = game.tholian
6367 game.kdist[game.nenhere] = game.kavgd[game.nenhere] = \
6368 distance(game.sector, game.tholian)
6369 game.kpower[game.nenhere] = random.random()*400.0 +100.0 +25.0*game.skill
6370 # Reserve unoccupied corners
6371 if game.quad[1][1]==IHDOT:
6372 game.quad[1][1] = 'X'
6373 if game.quad[1][QUADSIZE]==IHDOT:
6374 game.quad[1][QUADSIZE] = 'X'
6375 if game.quad[QUADSIZE][1]==IHDOT:
6376 game.quad[QUADSIZE][1] = 'X'
6377 if game.quad[QUADSIZE][QUADSIZE]==IHDOT:
6378 game.quad[QUADSIZE][QUADSIZE] = 'X'
6381 # Put in a few black holes
6382 for i in range(1, 3+1):
6383 if random.random() > 0.5:
6386 # Take out X's in corners if Tholian present
6388 if game.quad[1][1]=='X':
6389 game.quad[1][1] = IHDOT
6390 if game.quad[1][QUADSIZE]=='X':
6391 game.quad[1][QUADSIZE] = IHDOT
6392 if game.quad[QUADSIZE][1]=='X':
6393 game.quad[QUADSIZE][1] = IHDOT
6394 if game.quad[QUADSIZE][QUADSIZE]=='X':
6395 game.quad[QUADSIZE][QUADSIZE] = IHDOT
6398 # sort Klingons by distance from us
6399 # The author liked bubble sort. So we will use it. :-(
6400 if game.nenhere-iqhere-game.ithere < 2:
6404 for j in range(1, game.nenhere):
6405 if game.kdist[j] > game.kdist[j+1]:
6408 game.kdist[j] = game.kdist[j+1]
6411 game.kavgd[j] = game.kavgd[j+1]
6414 game.ks[j].x = game.ks[j+1].x
6417 game.ks[j].y = game.ks[j+1].y
6420 game.kpower[j] = game.kpower[j+1]
6421 game.kpower[j+1] = t
6426 # set the self-destruct password
6427 if game.options & OPTION_PLAIN:
6430 proutn(_("Please type in a secret password- "))
6433 if game.passwd != None:
6438 game.passwd[i] += chr(97+int(random.random()*25))
6440 # Code from sst.c begins here
6443 "SRSCAN": OPTION_TTY,
6444 "STATUS": OPTION_TTY,
6445 "REQUEST": OPTION_TTY,
6446 "LRSCAN": OPTION_TTY,
6459 "SENSORS": OPTION_PLANETS,
6460 "ORBIT": OPTION_PLANETS,
6461 "TRANSPORT": OPTION_PLANETS,
6462 "MINE": OPTION_PLANETS,
6463 "CRYSTALS": OPTION_PLANETS,
6464 "SHUTTLE": OPTION_PLANETS,
6465 "PLANETS": OPTION_PLANETS,
6470 "PROBE": OPTION_PROBE,
6472 "FREEZE": 0, # Synonym for SAVE
6478 "SOS": 0, # Synonym for MAYDAY
6479 "CALL": 0, # Synonym for MAYDAY
6486 def ACCEPT(cmd): return (not commands[cmd] or (commands[cmd] & game.options))
6489 # generate a list of legal commands
6491 proutn(_("LEGAL COMMANDS ARE:"))
6492 for key in commands:
6496 proutn("%-12s " % key)
6501 # browse on-line help
6502 # Give help on commands
6506 setwnd(prompt_window)
6507 proutn(_("Help on what command? "))
6509 setwnd(message_window)
6512 if citem in commands or citem == "ABBREV":
6521 fp = open(SSTDOC, "r")
6524 fp = open(DOC_NAME, "r")
6526 prout(_("Spock- \"Captain, that information is missing from the"))
6527 proutn(_(" computer. You need to find "))
6529 prout(_(" and put it in the"))
6530 proutn(_(" current directory or to "))
6534 # This used to continue: "You need to find SST.DOC and put
6535 # it in the current directory."
6539 linebuf = fp.readline()
6541 prout(_("Spock- \"Captain, there is no information on that command.\""))
6544 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
6545 linebuf = linebuf[3:].strip()
6549 prout(_("Spock- \"Captain, I've found the following information:\""))
6551 while linebuf in fp:
6552 if "******" in linebuf:
6558 # command-interpretation loop
6561 setwnd(message_window)
6562 while True: # command loop
6564 while True: # get a command
6570 setwnd(prompt_window)
6574 if game.options & OPTION_CURSES:
6579 setwnd(message_window)
6582 if cmd not in commands:
6585 commandhook(commands[i].name, True)
6586 if cmd == "SRSCAN": # srscan
6588 elif cmd == "STATUS": # status
6590 elif cmd == "REQUEST": # status request
6592 elif cmd == "LRSCAN": # long range scan
6594 elif cmd == "PHASERS": # phasers
6598 elif cmd == "TORPEDO": # photon torpedos
6602 elif cmd == "MOVE": # move under warp
6604 elif cmd == "SHIELDS": # shields
6608 game.shldchg = False
6609 elif cmd == "DOCK": # dock at starbase
6613 elif cmd == "DAMAGES": # damage reports
6615 elif cmd == "CHART": # chart
6617 elif cmd == "IMPULSE": # impulse
6619 elif cmd == "REST": # rest
6623 elif cmd == "WARP": # warp
6625 elif cmd == "SCORE": # score
6627 elif cmd == "SENSORS": # sensors
6629 elif cmd == "ORBIT": # orbit
6633 elif cmd == "TRANSPORT": # transport "beam"
6635 elif cmd == "MINE": # mine
6639 elif cmd == "CRYSTALS": # crystals
6643 elif cmd == "SHUTTLE": # shuttle
6647 elif cmd == "PLANETS": # Planet list
6649 elif cmd == "REPORT": # Game Report
6651 elif cmd == "COMPUTER": # use COMPUTER!
6653 elif cmd == "COMMANDS":
6655 elif cmd == "EMEXIT": # Emergency exit
6656 clrscr() # Hide screen
6657 freeze(True) # forced save
6658 os.exit(1) # And quick exit
6659 elif cmd == "PROBE":
6660 probe() # Launch probe
6663 elif cmd == "ABANDON": # Abandon Ship
6665 elif cmd == "DESTRUCT": # Self Destruct
6667 elif cmd == "SAVE": # Save Game
6670 if game.skill > SKILL_GOOD:
6671 prout(_("WARNING--Saved games produce no plaques!"))
6672 elif cmd == "DEATHRAY": # Try a desparation measure
6676 elif cmd == "DEBUGCMD": # What do we want for debug???
6678 elif cmd == "MAYDAY": # Call for help
6683 game.alldone = True # quit the game
6686 elif cmd == "SEED": # set random-number seed
6690 #ifdef BSD_BUG_FOR_BUG
6691 # elif cmd == "VISUAL":
6692 # visual() # perform visual scan
6694 commandhook(commands[i].name, False)
6697 break # Game has ended
6698 if game.optime != 0.0:
6701 break # Events did us in
6702 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6705 if hitme and not game.justin:
6709 if game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova:
6721 if cmd == IHR: s = _("Romulan")
6722 elif cmd == IHK: s = _("Klingon")
6723 elif cmd == IHC: s = _("Commander")
6724 elif cmd == IHS: s = _("Super-commander")
6725 elif cmd == IHSTAR: s = _("Star")
6726 elif cmd == IHP: s = _("Planet")
6727 elif cmd == IHB: s = _("Starbase")
6728 elif cmd == IHBLANK: s = _("Black hole")
6729 elif cmd == IHT: s = _("Tholian")
6730 elif cmd == IHWEB: s = _("Tholian web")
6731 elif cmd == IHQUEST: s = _("Stranger")
6732 elif cmd == IHW: s = _("Inhabited World")
6733 else: s = "Unknown??"
6736 def cramlc(loctype, w):
6738 if loctype == "quadrant":
6739 buf = _("Quadrant ")
6740 elif loctype == "sector":
6742 buf += ("%d - %d" % (w.x, w.y))
6745 def crmena(stars, enemy, loctype, w):
6746 # print an enemy and his location
6751 proutn(cramlc(loctype, w))
6754 # print our ship name
6755 if game.ship == IHE:
6757 elif game.ship == IHF:
6758 s = _("Faerie Queene")
6764 # print a line of stars
6765 prouts("******************************************************")
6769 return -avrage*math.log(1e-7 + random.random())
6771 def randplace(size):
6772 # choose a random location
6774 w.x = random.randint(1, size)
6775 w.y = random.randint(1, size)
6779 # Demand input for next scan
6784 # return IHEOL next time
6789 # Get a token from the user
6790 global inqueue, line, citem
6794 # Read a line if nothing here
6797 if curwnd==prompt_window:
6799 setwnd(message_window)
6801 # Skip leading white space
6802 line = line.lstrip()
6804 inqueue = line.split()
6807 # From here on in it's all looking at the queue
6808 citem = inqueue.pop(0)
6812 aaitem = float(citem)
6817 citem = citem.lower()
6821 # yes-or-no confirmation
6830 proutn(_("Please answer with \"y\" or \"n\": "))
6833 # complain about unparseable input
6836 prout(_("Beg your pardon, Captain?"))
6839 # compares s to citem and returns true if it matches to the length of s
6840 return s.startswith(citem)
6843 # access to the internals for debugging
6844 proutn("Reset levels? ")
6846 if game.energy < game.inenrg:
6847 game.energy = game.inenrg
6848 game.shield = game.inshld
6849 game.torps = game.intorps
6850 game.lsupres = game.inlsr
6851 proutn("Reset damage? ")
6853 for i in range(0, NDEVICES):
6854 if game.damage[i] > 0.0:
6855 game.damage[i] = 0.0
6856 proutn("Toggle debug flag? ")
6860 prout("Debug output ON")
6862 prout("Debug output OFF")
6863 proutn("Cause selective damage? ")
6865 for i in range(NDEVICES):
6871 if key == IHALPHA and isit("y"):
6872 game.damage[i] = 10.0
6873 proutn("Examine/change events? ")
6878 FSNOVA: "Supernova ",
6881 FBATTAK: "Base Attack ",
6882 FCDBAS: "Base Destroy ",
6883 FSCMOVE: "SC Move ",
6884 FSCDBAS: "SC Base Destroy ",
6885 FDSPROB: "Probe Move ",
6886 FDISTR: "Distress Call ",
6887 FENSLV: "Enslavement ",
6888 FREPRO: "Klingon Build ",
6890 for i in range(1, NEVENTS):
6893 proutn("%.2f" % (scheduled(i)-game.state.date))
6894 if i == FENSLV or i == FREPRO:
6896 proutn(" in %s" % ev.quadrant)
6906 ev = schedule(i, aaitem)
6907 if i == FENSLV or i == FREPRO:
6909 proutn("In quadrant- ")
6911 # IHEOL says to leave coordinates as they are
6914 prout("Event %d canceled, no x coordinate." % (i))
6920 prout("Event %d canceled, no y coordinate." % (i))
6926 proutn("Induce supernova here? ")
6928 game.state.galaxy[game.quadrant.x][game.quadrant.y].supernova = True
6931 if __name__ == '__main__':
6932 global line, thing, game
6933 game = citem = aaitem = inqueue = None
6938 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_SHOWME | OPTION_PLAIN | OPTION_ALMY)
6939 # Disable curses mode until the game logic is working.
6940 # if os.getenv("TERM"):
6941 # game.options |= OPTION_CURSES | OPTION_SHOWME
6943 game.options |= OPTION_TTY
6946 (options, arguments) = getopt.getopt(sys.argv[1:], "r:tx")
6947 for (switch, val) in options:
6950 replayfp = open(optarg, "r")
6952 sys.stderr.write("sst: can't open replay file %s\n" % optarg)
6954 line = replayfp.readline().strip()
6956 (key, seed) = line.split()
6959 sys.stderr.write("sst: replay file %s is ill-formed\n"%optarg)
6961 game.options |= OPTION_TTY
6962 game.options &=~ OPTION_CURSES
6964 game.options |= OPTION_TTY
6965 game.options &=~ OPTION_CURSES
6969 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6971 # where to save the input in case of bugs
6973 logfp = open("/usr/tmp/sst-input.log", "w")
6975 sys.stderr.write("sst: warning, can't open logfile\n")
6978 logfp.write("seed %d\n" % (seed))
6983 for tok in arguments:
6987 while True: # Play a game
6988 setwnd(fullscreen_window)
6991 setup(needprompt=not line)
6994 game.alldone = False
7001 if game.tourn and game.alldone:
7002 proutn(_("Do you want your score recorded?"))
7006 proutn(_("Do you want to play again? "))
7010 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))