3 sst.py -- Super Star Trek 2K
5 SST2K is a Python translation of a C translation of a FORTRAN
6 original dating back to 1973. Beautiful Python it is not, but it
7 works. Translation by Eric S. Raymond; original game by David Matuszek
8 and Paul Reynolds, with modifications by Don Smith, Tom Almy,
9 Stas Sergeev, and Eric S. Raymond.
11 See the doc/HACKING file in the distribution for designers notes and advice
12 ion how to modify (and how not to modify!) this code.
14 import os, sys, math, curses, time, readline, cPickle, random, copy, gettext
16 SSTDOC = "/usr/share/doc/sst/sst.doc"
19 def _(str): return gettext.gettext(str)
23 NINHAB = (GALSIZE * GALSIZE / 2)
25 PLNETMAX = (NINHAB + MAXUNINHAB)
28 BASEMAX = (GALSIZE * GALSIZE / 12)
31 FULLCREW = 428 # BSD Trek was 387, that's wrong
40 def __init__(self, x=None, y=None):
43 def valid_quadrant(self):
44 return self.i>=0 and self.i<GALSIZE and self.j>=0 and self.j<GALSIZE
45 def valid_sector(self):
46 return self.i>=0 and self.i<QUADSIZE and self.j>=0 and self.j<QUADSIZE
48 self.i = self.j = None
50 return self.i != None and self.j != None
51 def __eq__(self, other):
52 return other != None and self.i == other.i and self.j == other.j
53 def __ne__(self, other):
54 return other == None or self.i != other.i or self.j != other.j
55 def __add__(self, other):
56 return coord(self.i+other.i, self.j+other.j)
57 def __sub__(self, other):
58 return coord(self.i-other.i, self.j-other.j)
59 def __mul__(self, other):
60 return coord(self.i*other, self.j*other)
61 def __rmul__(self, other):
62 return coord(self.i*other, self.j*other)
63 def __div__(self, other):
64 return coord(self.i/other, self.j/other)
65 def __mod__(self, other):
66 return coord(self.i % other, self.j % other)
67 def __rdiv__(self, other):
68 return coord(self.i/other, self.j/other)
69 def roundtogrid(self):
70 return coord(int(round(self.i)), int(round(self.j)))
71 def distance(self, other=None):
72 if not other: other = coord(0, 0)
73 return math.sqrt((self.i - other.i)**2 + (self.j - other.j)**2)
75 return 1.90985*math.atan2(self.j, self.i)
81 s.i = self.i / abs(self.i)
85 s.j = self.j / abs(self.j)
88 #print "Location %s -> %s" % (self, (self / QUADSIZE).roundtogrid())
89 return self.roundtogrid() / QUADSIZE
91 return self.roundtogrid() % QUADSIZE
94 s.i = self.i + randrange(-1, 2)
95 s.j = self.j + randrange(-1, 2)
98 if self.i == None or self.j == None:
100 return "%s - %s" % (self.i+1, self.j+1)
105 self.name = None # string-valued if inhabited
106 self.quadrant = coord() # quadrant located
107 self.pclass = None # could be ""M", "N", "O", or "destroyed"
108 self.crystals = "absent"# could be "mined", "present", "absent"
109 self.known = "unknown" # could be "unknown", "known", "shuttle_down"
110 self.inhabited = False # is it inhabites?
118 self.starbase = False
121 self.supernova = False
123 self.status = "secure" # Could be "secure", "distressed", "enslaved"
131 def fill2d(size, fillfun):
132 "Fill an empty list in 2D."
134 for i in range(size):
136 for j in range(size):
137 lst[i].append(fillfun(i, j))
142 self.snap = False # snapshot taken
143 self.crew = 0 # crew complement
144 self.remkl = 0 # remaining klingons
145 self.nscrem = 0 # remaining super commanders
146 self.starkl = 0 # destroyed stars
147 self.basekl = 0 # destroyed bases
148 self.nromrem = 0 # Romulans remaining
149 self.nplankl = 0 # destroyed uninhabited planets
150 self.nworldkl = 0 # destroyed inhabited planets
151 self.planets = [] # Planet information
152 self.date = 0.0 # stardate
153 self.remres = 0 # remaining resources
154 self.remtime = 0 # remaining time
155 self.baseq = [] # Base quadrant coordinates
156 self.kcmdr = [] # Commander quadrant coordinates
157 self.kscmdr = coord() # Supercommander quadrant coordinates
159 self.galaxy = fill2d(GALSIZE, lambda i, j: quadrant())
161 self.chart = fill2d(GALSIZE, lambda i, j: page())
165 self.date = None # A real number
166 self.quadrant = None # A coord structure
169 OPTION_ALL = 0xffffffff
170 OPTION_TTY = 0x00000001 # old interface
171 OPTION_CURSES = 0x00000002 # new interface
172 OPTION_IOMODES = 0x00000003 # cover both interfaces
173 OPTION_PLANETS = 0x00000004 # planets and mining
174 OPTION_THOLIAN = 0x00000008 # Tholians and their webs (UT 1979 version)
175 OPTION_THINGY = 0x00000010 # Space Thingy can shoot back (Stas, 2005)
176 OPTION_PROBE = 0x00000020 # deep-space probes (DECUS version, 1980)
177 OPTION_SHOWME = 0x00000040 # bracket Enterprise in chart
178 OPTION_RAMMING = 0x00000080 # enemies may ram Enterprise (Almy)
179 OPTION_MVBADDY = 0x00000100 # more enemies can move (Almy)
180 OPTION_BLKHOLE = 0x00000200 # black hole may timewarp you (Stas, 2005)
181 OPTION_BASE = 0x00000400 # bases have good shields (Stas, 2005)
182 OPTION_WORLDS = 0x00000800 # logic for inhabited worlds (ESR, 2006)
183 OPTION_AUTOSCAN = 0x00001000 # automatic LRSCAN before CHART (ESR, 2006)
184 OPTION_PLAIN = 0x01000000 # user chose plain game
185 OPTION_ALMY = 0x02000000 # user chose Almy variant
204 NDEVICES= 16 # Number of devices
213 def damaged(dev): return (game.damage[dev] != 0.0)
214 def communicating(): return not damaged(DRADIO) or game.condition=="docked"
216 # Define future events
217 FSPY = 0 # Spy event happens always (no future[] entry)
218 # can cause SC to tractor beam Enterprise
219 FSNOVA = 1 # Supernova
220 FTBEAM = 2 # Commander tractor beams Enterprise
221 FSNAP = 3 # Snapshot for time warp
222 FBATTAK = 4 # Commander attacks base
223 FCDBAS = 5 # Commander destroys base
224 FSCMOVE = 6 # Supercommander moves (might attack base)
225 FSCDBAS = 7 # Supercommander destroys base
226 FDSPROB = 8 # Move deep space probe
227 FDISTR = 9 # Emit distress call from an inhabited world
228 FENSLV = 10 # Inhabited word is enslaved */
229 FREPRO = 11 # Klingons build a ship in an enslaved system
232 # Abstract out the event handling -- underlying data structures will change
233 # when we implement stateful events
234 def findevent(evtype): return game.future[evtype]
237 def __init__(self, type=None, loc=None, power=None):
239 self.location = coord()
242 self.power = power # enemy energy level
243 game.enemies.append(self)
245 motion = (loc != self.location)
246 if self.location.i is not None and self.location.j is not None:
249 game.quad[self.location.i][self.location.j] = '#'
251 game.quad[self.location.i][self.location.j] = '.'
253 self.location = copy.copy(loc)
254 game.quad[self.location.i][self.location.j] = self.type
255 self.kdist = self.kavgd = (game.sector - loc).distance()
257 self.location = coord()
258 self.kdist = self.kavgd = None
259 game.enemies.remove(self)
262 return "<%s,%s.%f>" % (self.type, self.location, self.power) # For debugging
266 self.options = None # Game options
267 self.state = snapshot() # A snapshot structure
268 self.snapsht = snapshot() # Last snapshot taken for time-travel purposes
269 self.quad = None # contents of our quadrant
270 self.damage = [0.0] * NDEVICES # damage encountered
271 self.future = [] # future events
272 for i in range(NEVENTS):
273 self.future.append(event())
274 self.passwd = None; # Self Destruct password
276 self.quadrant = None # where we are in the large
277 self.sector = None # where we are in the small
278 self.tholian = None # Tholian enemy object
279 self.base = None # position of base in current quadrant
280 self.battle = None # base coordinates being attacked
281 self.plnet = None # location of planet in quadrant
282 self.gamewon = False # Finished!
283 self.ididit = False # action taken -- allows enemy to attack
284 self.alive = False # we are alive (not killed)
285 self.justin = False # just entered quadrant
286 self.shldup = False # shields are up
287 self.shldchg = False # shield is changing (affects efficiency)
288 self.iscate = False # super commander is here
289 self.ientesc = False # attempted escape from supercommander
290 self.resting = False # rest time
291 self.icraft = False # Kirk in Galileo
292 self.landed = False # party on planet (true), on ship (false)
293 self.alldone = False # game is now finished
294 self.neutz = False # Romulan Neutral Zone
295 self.isarmed = False # probe is armed
296 self.inorbit = False # orbiting a planet
297 self.imine = False # mining
298 self.icrystl = False # dilithium crystals aboard
299 self.iseenit = False # seen base attack report
300 self.thawed = False # thawed game
301 self.condition = None # "green", "yellow", "red", "docked", "dead"
302 self.iscraft = None # "onship", "offship", "removed"
303 self.skill = None # Player skill level
304 self.inkling = 0 # initial number of klingons
305 self.inbase = 0 # initial number of bases
306 self.incom = 0 # initial number of commanders
307 self.inscom = 0 # initial number of commanders
308 self.inrom = 0 # initial number of commanders
309 self.instar = 0 # initial stars
310 self.intorps = 0 # initial/max torpedoes
311 self.torps = 0 # number of torpedoes
312 self.ship = 0 # ship type -- 'E' is Enterprise
313 self.abandoned = 0 # count of crew abandoned in space
314 self.length = 0 # length of game
315 self.klhere = 0 # klingons here
316 self.casual = 0 # causalties
317 self.nhelp = 0 # calls for help
318 self.nkinks = 0 # count of energy-barrier crossings
319 self.iplnet = None # planet # in quadrant
320 self.inplan = 0 # initial planets
321 self.irhere = 0 # Romulans in quadrant
322 self.isatb = 0 # =1 if super commander is attacking base
323 self.tourn = None # tournament number
324 self.nprobes = 0 # number of probes available
325 self.inresor = 0.0 # initial resources
326 self.intime = 0.0 # initial time
327 self.inenrg = 0.0 # initial/max energy
328 self.inshld = 0.0 # initial/max shield
329 self.inlsr = 0.0 # initial life support resources
330 self.indate = 0.0 # initial date
331 self.energy = 0.0 # energy level
332 self.shield = 0.0 # shield level
333 self.warpfac = 0.0 # warp speed
334 self.wfacsq = 0.0 # squared warp factor
335 self.lsupres = 0.0 # life support reserves
336 self.optime = 0.0 # time taken by current operation
337 self.docfac = 0.0 # repair factor when docking (constant?)
338 self.damfac = 0.0 # damage factor
339 self.lastchart = 0.0 # time star chart was last updated
340 self.cryprob = 0.0 # probability that crystal will work
341 self.probe = None # object holding probe course info
342 self.height = 0.0 # height of orbit around planet
344 # Stas thinks this should be (C expression):
345 # game.state.remkl + len(game.state.kcmdr) > 0 ?
346 # game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr)) : 99
347 # He says the existing expression is prone to divide-by-zero errors
348 # after killing the last klingon when score is shown -- perhaps also
349 # if the only remaining klingon is SCOM.
350 game.state.remtime = game.state.remres/(game.state.remkl + 4*len(game.state.kcmdr))
377 #logfp.write("# withprob(%s) -> %f (%s) at %s\n" % (p, v, v<p, traceback.extract_stack()[-2][1:]))
380 def randrange(*args):
381 v = random.randrange(*args)
382 #logfp.write("# randrange%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
388 v *= args[0] # returns from [0, args[0])
390 v = args[0] + v*(args[1]-args[0]) # returns from [args[0], args[1])
391 #logfp.write("# randreal%s -> %s at %s\n" % (args, v, traceback.extract_stack()[-2][1:]))
394 # Code from ai.c begins here
397 "Would this quadrant welcome another Klingon?"
398 return iq.valid_quadrant() and \
399 not game.state.galaxy[iq.i][iq.j].supernova and \
400 game.state.galaxy[iq.i][iq.j].klingons < MAXKLQUAD
402 def tryexit(enemy, look, irun):
403 "A bad guy attempts to bug out."
405 iq.i = game.quadrant.i+(look.i+(QUADSIZE-1))/QUADSIZE - 1
406 iq.j = game.quadrant.j+(look.j+(QUADSIZE-1))/QUADSIZE - 1
407 if not welcoming(iq):
409 if enemy.type == 'R':
410 return False; # Romulans cannot escape!
412 # avoid intruding on another commander's territory
413 if enemy.type == 'C':
414 if iq in game.state.kcmdr:
416 # refuse to leave if currently attacking starbase
417 if game.battle == game.quadrant:
419 # don't leave if over 1000 units of energy
420 if enemy.power > 1000.0:
422 # emit escape message and move out of quadrant.
423 # we know this if either short or long range sensors are working
424 if not damaged(DSRSENS) or not damaged(DLRSENS) or \
425 game.condition == "docked":
426 prout(crmena(True, enemy.type, "sector", enemy.location) + \
427 (_(" escapes to Quadrant %s (and regains strength).") % q))
428 # handle local matters related to escape
431 if game.condition != "docked":
433 # Handle global matters related to escape
434 game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
435 game.state.galaxy[iq.i][iq.j].klingons += 1
440 schedule(FSCMOVE, 0.2777)
444 for cmdr in game.state.kcmdr:
445 if cmdr == game.quadrant:
446 game.state.kcmdr[n] = iq
448 return True; # success
450 # The bad-guy movement algorithm:
452 # 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
453 # If both are operating full strength, force is 1000. If both are damaged,
454 # force is -1000. Having shields down subtracts an additional 1000.
456 # 2. Enemy has forces equal to the energy of the attacker plus
457 # 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
458 # 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
460 # Attacker Initial energy levels (nominal):
461 # Klingon Romulan Commander Super-Commander
462 # Novice 400 700 1200
464 # Good 450 800 1300 1750
465 # Expert 475 850 1350 1875
466 # Emeritus 500 900 1400 2000
467 # VARIANCE 75 200 200 200
469 # Enemy vessels only move prior to their attack. In Novice - Good games
470 # only commanders move. In Expert games, all enemy vessels move if there
471 # is a commander present. In Emeritus games all enemy vessels move.
473 # 3. If Enterprise is not docked, an aggressive action is taken if enemy
474 # forces are 1000 greater than Enterprise.
476 # Agressive action on average cuts the distance between the ship and
477 # the enemy to 1/4 the original.
479 # 4. At lower energy advantage, movement units are proportional to the
480 # advantage with a 650 advantage being to hold ground, 800 to move forward
481 # 1, 950 for two, 150 for back 4, etc. Variance of 100.
483 # If docked, is reduced by roughly 1.75*game.skill, generally forcing a
484 # retreat, especially at high skill levels.
486 # 5. Motion is limited to skill level, except for SC hi-tailing it out.
488 def movebaddy(enemy):
489 "Tactical movement for the bad guys."
490 next = coord(); look = coord()
492 # This should probably be just (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
493 if game.skill >= SKILL_EXPERT:
494 nbaddys = (((game.quadrant in game.state.kcmdr)*2 + (game.state.kscmdr==game.quadrant)*2+game.klhere*1.23+game.irhere*1.5)/2.0)
496 nbaddys = (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
498 mdist = int(dist1 + 0.5); # Nearest integer distance
499 # If SC, check with spy to see if should hi-tail it
500 if enemy.type=='S' and \
501 (enemy.power <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
505 # decide whether to advance, retreat, or hold position
506 forces = enemy.power+100.0*len(game.enemies)+400*(nbaddys-1)
508 forces += 1000; # Good for enemy if shield is down!
509 if not damaged(DPHASER) or not damaged(DPHOTON):
510 if damaged(DPHASER): # phasers damaged
513 forces -= 0.2*(game.energy - 2500.0)
514 if damaged(DPHOTON): # photon torpedoes damaged
517 forces -= 50.0*game.torps
519 # phasers and photon tubes both out!
522 if forces <= 1000.0 and game.condition != "docked": # Typical situation
523 motion = ((forces + randreal(200))/150.0) - 5.0
525 if forces > 1000.0: # Very strong -- move in for kill
526 motion = (1.0 - randreal())**2 * dist1 + 1.0
527 if game.condition=="docked" and (game.options & OPTION_BASE): # protected by base -- back off !
528 motion -= game.skill*(2.0-randreal()**2)
530 proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
531 # don't move if no motion
534 # Limit motion according to skill
535 if abs(motion) > game.skill:
540 # calculate preferred number of steps
541 nsteps = abs(int(motion))
542 if motion > 0 and nsteps > mdist:
543 nsteps = mdist; # don't overshoot
544 if nsteps > QUADSIZE:
545 nsteps = QUADSIZE; # This shouldn't be necessary
547 nsteps = 1; # This shouldn't be necessary
549 proutn("NSTEPS = %d:" % nsteps)
550 # Compute preferred values of delta X and Y
551 m = game.sector - enemy.location
552 if 2.0 * abs(m.i) < abs(m.j):
554 if 2.0 * abs(m.j) < abs(game.sector.i-enemy.location.i):
556 m = (motion * m).sgn()
557 next = enemy.location
559 for ll in range(nsteps):
561 proutn(" %d" % (ll+1))
562 # Check if preferred position available
573 attempts = 0; # Settle mysterious hang problem
574 while attempts < 20 and not success:
576 if look.i < 0 or look.i >= QUADSIZE:
577 if motion < 0 and tryexit(enemy, look, irun):
579 if krawli == m.i or m.j == 0:
581 look.i = next.i + krawli
583 elif look.j < 0 or look.j >= QUADSIZE:
584 if motion < 0 and tryexit(enemy, look, irun):
586 if krawlj == m.j or m.i == 0:
588 look.j = next.j + krawlj
590 elif (game.options & OPTION_RAMMING) and game.quad[look.i][look.j] != '.':
591 # See if enemy should ram ship
592 if game.quad[look.i][look.j] == game.ship and \
593 (enemy.type == 'C' or enemy.type == 'S'):
594 collision(rammed=True, enemy=enemy)
596 if krawli != m.i and m.j != 0:
597 look.i = next.i + krawli
599 elif krawlj != m.j and m.i != 0:
600 look.j = next.j + krawlj
603 break; # we have failed
615 if not damaged(DSRSENS) or game.condition == "docked":
616 proutn(_("*** %s from Sector %s") % (cramen(enemy.type), enemy.location))
617 if enemy.kdist < dist1:
618 proutn(_(" advances to "))
620 proutn(_(" retreats to "))
621 prout("Sector %s." % next)
624 "Sequence Klingon tactical movement."
627 # Figure out which Klingon is the commander (or Supercommander)
629 if game.quadrant in game.state.kcmdr:
630 for enemy in game.enemies:
631 if enemy.type == 'C':
633 if game.state.kscmdr==game.quadrant:
634 for enemy in game.enemies:
635 if enemy.type == 'S':
638 # If skill level is high, move other Klingons and Romulans too!
639 # Move these last so they can base their actions on what the
641 if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
642 for enemy in game.enemies:
643 if enemy.type in ('K', 'R'):
645 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
647 def movescom(iq, avoid):
648 "Commander movement helper."
649 # Avoid quadrants with bases if we want to avoid Enterprise
650 if not welcoming(iq) or (avoid and iq in game.state.baseq):
652 if game.justin and not game.iscate:
655 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons -= 1
656 game.state.kscmdr = iq
657 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons += 1
658 if game.state.kscmdr==game.quadrant:
659 # SC has scooted, Remove him from current quadrant
664 for enemy in game.enemies:
665 if enemy.type == 'S':
669 if game.condition != "docked":
671 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
672 # check for a helpful planet
673 for i in range(game.inplan):
674 if game.state.planets[i].quadrant == game.state.kscmdr and \
675 game.state.planets[i].crystals == "present":
677 game.state.planets[i].pclass = "destroyed"
678 game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].planet = None
681 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
682 proutn(_(" a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
683 prout(_(" by the Super-commander.\""))
685 return True; # looks good!
687 def supercommander():
688 "Move the Super Commander."
689 iq = coord(); sc = coord(); ibq = coord(); idelta = coord()
692 prout("== SUPERCOMMANDER")
693 # Decide on being active or passive
694 avoid = ((game.incom - len(game.state.kcmdr) + game.inkling - game.state.remkl)/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) or \
695 (game.state.date-game.indate) < 3.0)
696 if not game.iscate and avoid:
697 # compute move away from Enterprise
698 idelta = game.state.kscmdr-game.quadrant
699 if idelta.distance() > 2.0:
701 idelta.i = game.state.kscmdr.j-game.quadrant.j
702 idelta.j = game.quadrant.i-game.state.kscmdr.i
704 # compute distances to starbases
705 if not game.state.baseq:
709 sc = game.state.kscmdr
710 for base in game.state.baseq:
711 basetbl.append((i, (base - sc).distance()))
712 if game.state.baseq > 1:
713 basetbl.sort(lambda x, y: cmp(x[1]. y[1]))
714 # look for nearest base without a commander, no Enterprise, and
715 # without too many Klingons, and not already under attack.
716 ifindit = iwhichb = 0
717 for (i2, base) in enumerate(game.state.baseq):
718 i = basetbl[i2][0]; # bug in original had it not finding nearest
719 if base==game.quadrant or base==game.battle or not welcoming(base):
721 # if there is a commander, and no other base is appropriate,
722 # we will take the one with the commander
723 for cmdr in game.state.kcmdr:
724 if base == cmdr and ifindit != 2:
728 else: # no commander -- use this one
733 return # Nothing suitable -- wait until next time
734 ibq = game.state.baseq[iwhichb]
735 # decide how to move toward base
736 idelta = ibq - game.state.kscmdr
737 # Maximum movement is 1 quadrant in either or both axes
738 idelta = idelta.sgn()
739 # try moving in both x and y directions
740 # there was what looked like a bug in the Almy C code here,
741 # but it might be this translation is just wrong.
742 iq = game.state.kscmdr + idelta
743 if not movescom(iq, avoid):
744 # failed -- try some other maneuvers
745 if idelta.i==0 or idelta.j==0:
748 iq.j = game.state.kscmdr.j + 1
749 if not movescom(iq, avoid):
750 iq.j = game.state.kscmdr.j - 1
753 iq.i = game.state.kscmdr.i + 1
754 if not movescom(iq, avoid):
755 iq.i = game.state.kscmdr.i - 1
758 # try moving just in x or y
759 iq.j = game.state.kscmdr.j
760 if not movescom(iq, avoid):
761 iq.j = game.state.kscmdr.j + idelta.j
762 iq.i = game.state.kscmdr.i
765 if len(game.state.baseq) == 0:
768 for ibq in game.state.baseq:
769 if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
772 return # no, don't attack base!
775 schedule(FSCDBAS, randreal(1.0, 3.0))
776 if is_scheduled(FCDBAS):
777 postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
778 if not communicating():
782 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") \
784 prout(_(" reports that it is under attack from the Klingon Super-commander."))
785 proutn(_(" It can survive until stardate %d.\"") \
786 % int(scheduled(FSCDBAS)))
789 prout(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
793 game.optime = 0.0; # actually finished
795 # Check for intelligence report
798 (not communicating()) or \
799 not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].charted):
802 prout(_("Lt. Uhura- \"Captain, Starfleet Intelligence reports"))
803 proutn(_(" the Super-commander is in Quadrant %s,") % game.state.kscmdr)
808 if not game.tholian or game.justin:
811 if game.tholian.location.i == 0 and game.tholian.location.j == 0:
812 id.i = 0; id.j = QUADSIZE-1
813 elif game.tholian.location.i == 0 and game.tholian.location.j == QUADSIZE-1:
814 id.i = QUADSIZE-1; id.j = QUADSIZE-1
815 elif game.tholian.location.i == QUADSIZE-1 and game.tholian.location.j == QUADSIZE-1:
816 id.i = QUADSIZE-1; id.j = 0
817 elif game.tholian.location.i == QUADSIZE-1 and game.tholian.location.j == 0:
820 # something is wrong!
821 game.tholian.move(None)
822 prout("***Internal error: Tholian in a bad spot.")
824 # do nothing if we are blocked
825 if game.quad[id.i][id.j] not in ('.', '#'):
827 here = copy.copy(game.tholian.location)
828 delta = (id - game.tholian.location).sgn()
830 while here.i != id.i:
832 if game.quad[here.i][here.j]=='.':
833 game.tholian.move(here)
835 while here.j != id.j:
837 if game.quad[here.i][here.j]=='.':
838 game.tholian.move(here)
839 # check to see if all holes plugged
840 for i in range(QUADSIZE):
841 if game.quad[0][i]!='#' and game.quad[0][i]!='T':
843 if game.quad[QUADSIZE-1][i]!='#' and game.quad[QUADSIZE-1][i]!='T':
845 if game.quad[i][0]!='#' and game.quad[i][0]!='T':
847 if game.quad[i][QUADSIZE-1]!='#' and game.quad[i][QUADSIZE-1]!='T':
849 # All plugged up -- Tholian splits
850 game.quad[game.tholian.location.i][game.tholian.location.j]='#'
852 prout(crmena(True, 'T', "sector", game.tholian) + _(" completes web."))
853 game.tholian.move(None)
856 # Code from battle.c begins here
858 def doshield(shraise):
859 "Change shield status."
867 if scanner.sees("transfer"):
871 prout(_("Shields damaged and down."))
873 if scanner.sees("up"):
875 elif scanner.sees("down"):
878 proutn(_("Do you wish to change shield energy? "))
880 proutn(_("Energy to transfer to shields- "))
882 elif damaged(DSHIELD):
883 prout(_("Shields damaged and down."))
886 proutn(_("Shields are up. Do you want them down? "))
893 proutn(_("Shields are down. Do you want them up? "))
899 if action == "SHUP": # raise shields
901 prout(_("Shields already up."))
905 if game.condition != "docked":
907 prout(_("Shields raised."))
910 prout(_("Shields raising uses up last of energy."))
915 elif action == "SHDN":
917 prout(_("Shields already down."))
921 prout(_("Shields lowered."))
924 elif action == "NRG":
925 while scanner.next() != "IHREAL":
927 proutn(_("Energy to transfer to shields- "))
929 if scanner.real == 0:
931 if scanner.real > game.energy:
932 prout(_("Insufficient ship energy."))
935 if game.shield+scanner.real >= game.inshld:
936 prout(_("Shield energy maximized."))
937 if game.shield+scanner.real > game.inshld:
938 prout(_("Excess energy requested returned to ship energy"))
939 game.energy -= game.inshld-game.shield
940 game.shield = game.inshld
942 if scanner.real < 0.0 and game.energy-scanner.real > game.inenrg:
943 # Prevent shield drain loophole
945 prout(_("Engineering to bridge--"))
946 prout(_(" Scott here. Power circuit problem, Captain."))
947 prout(_(" I can't drain the shields."))
950 if game.shield+scanner.real < 0:
951 prout(_("All shield energy transferred to ship."))
952 game.energy += game.shield
955 proutn(_("Scotty- \""))
957 prout(_("Transferring energy to shields.\""))
959 prout(_("Draining energy from shields.\""))
960 game.shield += scanner.real
961 game.energy -= scanner.real
965 "Choose a device to damage, at random."
966 # Quoth Eric Allman in the code of BSD-Trek:
967 # "Under certain conditions you can get a critical hit. This
968 # sort of hit damages devices. The probability that a given
969 # device is damaged depends on the device. Well protected
970 # devices (such as the computer, which is in the core of the
971 # ship and has considerable redundancy) almost never get
972 # damaged, whereas devices which are exposed (such as the
973 # warp engines) or which are particularly delicate (such as
974 # the transporter) have a much higher probability of being
977 # This is one place where OPTION_PLAIN does not restore the
978 # original behavior, which was equiprobable damage across
979 # all devices. If we wanted that, we'd return randrange(NDEVICES)
980 # and have done with it. Also, in the original game, DNAVYS
981 # and DCOMPTR were the same device.
983 # Instead, we use a table of weights similar to the one from BSD Trek.
984 # BSD doesn't have the shuttle, shield controller, death ray, or probes.
985 # We don't have a cloaking device. The shuttle got the allocation
986 # for the cloaking device, then we shaved a half-percent off
987 # everything to have some weight to give DSHCTRL/DDRAY/DDSP.
989 105, # DSRSENS: short range scanners 10.5%
990 105, # DLRSENS: long range scanners 10.5%
991 120, # DPHASER: phasers 12.0%
992 120, # DPHOTON: photon torpedoes 12.0%
993 25, # DLIFSUP: life support 2.5%
994 65, # DWARPEN: warp drive 6.5%
995 70, # DIMPULS: impulse engines 6.5%
996 145, # DSHIELD: deflector shields 14.5%
997 30, # DRADIO: subspace radio 3.0%
998 45, # DSHUTTL: shuttle 4.5%
999 15, # DCOMPTR: computer 1.5%
1000 20, # NAVCOMP: navigation system 2.0%
1001 75, # DTRANSP: transporter 7.5%
1002 20, # DSHCTRL: high-speed shield controller 2.0%
1003 10, # DDRAY: death ray 1.0%
1004 30, # DDSP: deep-space probes 3.0%
1006 idx = randrange(1000) # weights must sum to 1000
1008 for (i, w) in enumerate(weights):
1012 return None; # we should never get here
1014 def collision(rammed, enemy):
1015 "Collision handling fot rammong events."
1016 prouts(_("***RED ALERT! RED ALERT!"))
1018 prout(_("***COLLISION IMMINENT."))
1022 hardness = {'R':1.5, 'C':2.0, 'S':2.5, 'T':0.5, '?':4.0}.get(enemy.type, 1.0)
1024 proutn(_(" rammed by "))
1027 proutn(crmena(False, enemy.type, "sector", enemy.location))
1029 proutn(_(" (original position)"))
1031 deadkl(enemy.location, enemy.type, game.sector)
1032 proutn("***" + crmship() + " heavily damaged.")
1033 icas = randrange(10, 30)
1034 prout(_("***Sickbay reports %d casualties"), icas)
1036 game.state.crew -= icas
1037 # In the pre-SST2K version, all devices got equiprobably damaged,
1038 # which was silly. Instead, pick up to half the devices at
1039 # random according to our weighting table,
1040 ncrits = randrange(NDEVICES/2)
1041 for m in range(ncrits):
1043 if game.damage[dev] < 0:
1045 extradm = (10.0*hardness*randreal()+1.0)*game.damfac
1046 # Damage for at least time of travel!
1047 game.damage[dev] += game.optime + extradm
1049 prout(_("***Shields are down."))
1050 if game.state.remkl + len(game.state.kcmdr) + game.state.nscrem:
1057 def torpedo(origin, bearing, dispersion, number, nburst):
1058 "Let a photon torpedo fly"
1059 if not damaged(DSRSENS) or game.condition=="docked":
1060 setwnd(srscan_window)
1062 setwnd(message_window)
1063 ac = bearing + 0.25*dispersion # dispersion is a random variable
1064 bullseye = (15.0 - bearing)*0.5235988
1065 track = course(bearing=ac, distance=QUADSIZE, origin=cartesian(origin))
1066 bumpto = coord(0, 0)
1067 # Loop to move a single torpedo
1068 setwnd(message_window)
1069 for step in range(1, QUADSIZE*2):
1070 if not track.next(): break
1072 if not w.valid_sector():
1074 iquad=game.quad[w.i][w.j]
1075 tracktorpedo(origin, w, step, number, nburst, iquad)
1079 if not damaged(DSRSENS) or game.condition == "docked":
1080 skip(1); # start new line after text track
1081 if iquad in ('E', 'F'): # Hit our ship
1083 prout(_("Torpedo hits %s.") % crmshp())
1084 hit = 700.0 + randreal(100) - \
1085 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-track.angle))
1086 newcnd(); # we're blown out of dock
1087 if game.landed or game.condition=="docked":
1088 return hit # Cheat if on a planet
1089 # In the C/FORTRAN version, dispersion was 2.5 radians, which
1090 # is 143 degrees, which is almost exactly 4.8 clockface units
1091 displacement = course(track.bearing+randreal(-2.4,2.4), distance=2**0.5)
1093 bumpto = displacement.sector()
1094 if not bumpto.valid_sector():
1096 if game.quad[bumpto.i][bumpto.j]==' ':
1099 if game.quad[bumpto.i][bumpto.j]!='.':
1100 # can't move into object
1102 game.sector = bumpto
1104 game.quad[w.i][w.j]='.'
1105 game.quad[bumpto.i][bumpto.j]=iquad
1106 prout(_(" displaced by blast to Sector %s ") % bumpto)
1107 for enemy in game.enemies:
1108 enemy.kdist = enemy.kavgd = (game.sector-enemy.location).distance()
1109 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1111 elif iquad in ('C', 'S', 'R', 'K'): # Hit a regular enemy
1113 if iquad in ('C', 'S') and withprob(0.05):
1114 prout(crmena(True, iquad, "sector", w) + _(" uses anti-photon device;"))
1115 prout(_(" torpedo neutralized."))
1117 for enemy in game.enemies:
1118 if w == enemy.location:
1120 kp = math.fabs(enemy.power)
1121 h1 = 700.0 + randrange(100) - \
1122 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-track.angle))
1130 if enemy.power == 0:
1133 proutn(crmena(True, iquad, "sector", w))
1134 displacement = course(track.bearing+randreal(-2.4,2.4), distance=2**0.5)
1136 bumpto = displacement.sector()
1137 if not bumpto.valid_sector():
1138 prout(_(" damaged but not destroyed."))
1140 if game.quad[bumpto.i][bumpto.j] == ' ':
1141 prout(_(" buffeted into black hole."))
1142 deadkl(w, iquad, bumpto)
1143 if game.quad[bumpto.i][bumpto.j] != '.':
1144 prout(_(" damaged but not destroyed."))
1146 prout(_(" damaged-- displaced by blast to Sector %s ")%bumpto)
1147 enemy.location = bumpto
1148 game.quad[w.i][w.j]='.'
1149 game.quad[bumpto.i][bumpto.j]=iquad
1150 for enemy in game.enemies:
1151 enemy.kdist = enemy.kavgd = (game.sector-enemy.location).distance()
1152 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1154 elif iquad == 'B': # Hit a base
1156 prout(_("***STARBASE DESTROYED.."))
1157 game.state.baseq = filter(lambda x: x != game.quadrant, game.state.baseq)
1158 game.quad[w.i][w.j]='.'
1159 game.base.invalidate()
1160 game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase -= 1
1161 game.state.chart[game.quadrant.i][game.quadrant.j].starbase -= 1
1162 game.state.basekl += 1
1165 elif iquad == 'P': # Hit a planet
1166 prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
1167 game.state.nplankl += 1
1168 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
1169 game.iplnet.pclass = "destroyed"
1171 game.plnet.invalidate()
1172 game.quad[w.i][w.j] = '.'
1174 # captain perishes on planet
1177 elif iquad == '@': # Hit an inhabited world -- very bad!
1178 prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
1179 game.state.nworldkl += 1
1180 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
1181 game.iplnet.pclass = "destroyed"
1183 game.plnet.invalidate()
1184 game.quad[w.i][w.j] = '.'
1186 # captain perishes on planet
1188 prout(_("The torpedo destroyed an inhabited planet."))
1190 elif iquad == '*': # Hit a star
1194 prout(crmena(True, '*', "sector", w) + _(" unaffected by photon blast."))
1196 elif iquad == '?': # Hit a thingy
1197 if not (game.options & OPTION_THINGY) or withprob(0.3):
1199 prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
1201 prouts(_(" HACK! HACK! HACK! *CHOKE!* "))
1203 proutn(_("Mr. Spock-"))
1204 prouts(_(" \"Fascinating!\""))
1208 # Stas Sergeev added the possibility that
1209 # you can shove the Thingy and piss it off.
1210 # It then becomes an enemy and may fire at you.
1214 elif iquad == ' ': # Black hole
1216 prout(crmena(True, ' ', "sector", w) + _(" swallows torpedo."))
1218 elif iquad == '#': # hit the web
1220 prout(_("***Torpedo absorbed by Tholian web."))
1222 elif iquad == 'T': # Hit a Tholian
1223 h1 = 700.0 + randrange(100) - \
1224 1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-angle))
1227 game.quad[w.i][w.j] = '.'
1232 proutn(crmena(True, 'T', "sector", w))
1234 prout(_(" survives photon blast."))
1236 prout(_(" disappears."))
1237 game.tholian.move(None)
1238 game.quad[w.i][w.j] = '#'
1243 proutn("Don't know how to handle torpedo collision with ")
1244 proutn(crmena(True, iquad, "sector", w))
1249 prout(_("Torpedo missed."))
1253 "Critical-hit resolution."
1254 if hit < (275.0-25.0*game.skill)*randreal(1.0, 1.5):
1256 ncrit = int(1.0 + hit/(500.0+randreal(100)))
1257 proutn(_("***CRITICAL HIT--"))
1258 # Select devices and cause damage
1260 for loop1 in range(ncrit):
1263 # Cheat to prevent shuttle damage unless on ship
1264 if not (game.damage[j]<0.0 or (j==DSHUTTL and game.iscraft != "onship")):
1267 extradm = (hit*game.damfac)/(ncrit*randreal(75, 100))
1268 game.damage[j] += extradm
1270 for (i, j) in enumerate(cdam):
1272 if skipcount % 3 == 2 and i < len(cdam)-1:
1277 prout(_(" damaged."))
1278 if damaged(DSHIELD) and game.shldup:
1279 prout(_("***Shields knocked down."))
1282 def attack(torps_ok):
1283 # bad guy attacks us
1284 # torps_ok == False forces use of phasers in an attack
1285 # game could be over at this point, check
1288 attempt = False; ihurt = False;
1289 hitmax=0.0; hittot=0.0; chgfac=1.0
1292 prout("=== ATTACK!")
1293 # Tholian gets to move before attacking
1296 # if you have just entered the RNZ, you'll get a warning
1297 if game.neutz: # The one chance not to be attacked
1300 # commanders get a chance to tac-move towards you
1301 if (((game.quadrant in game.state.kcmdr or game.state.kscmdr==game.quadrant) and not game.justin) or game.skill == SKILL_EMERITUS) and torps_ok:
1303 # if no enemies remain after movement, we're done
1304 if len(game.enemies)==0 or (len(game.enemies)==1 and thing == game.quadrant and not thing.angry):
1306 # set up partial hits if attack happens during shield status change
1307 pfac = 1.0/game.inshld
1309 chgfac = 0.25 + randreal(0.5)
1311 # message verbosity control
1312 if game.skill <= SKILL_FAIR:
1314 for enemy in game.enemies:
1316 continue; # too weak to attack
1317 # compute hit strength and diminish shield power
1319 # Increase chance of photon torpedos if docked or enemy energy is low
1320 if game.condition == "docked":
1322 if enemy.power < 500:
1324 if enemy.type=='T' or (enemy.type=='?' and not thing.angry):
1326 # different enemies have different probabilities of throwing a torp
1327 usephasers = not torps_ok or \
1328 (enemy.type == 'K' and r > 0.0005) or \
1329 (enemy.type=='C' and r > 0.015) or \
1330 (enemy.type=='R' and r > 0.3) or \
1331 (enemy.type=='S' and r > 0.07) or \
1332 (enemy.type=='?' and r > 0.05)
1333 if usephasers: # Enemy uses phasers
1334 if game.condition == "docked":
1335 continue; # Don't waste the effort!
1336 attempt = True; # Attempt to attack
1337 dustfac = randreal(0.8, 0.85)
1338 hit = enemy.power*math.pow(dustfac,enemy.kavgd)
1340 else: # Enemy uses photon torpedo
1341 # We should be able to make the bearing() method work here
1342 course = 1.90985*math.atan2(game.sector.j-enemy.location.j, enemy.location.i-game.sector.i)
1344 proutn(_("***TORPEDO INCOMING"))
1345 if not damaged(DSRSENS):
1346 proutn(_(" From ") + crmena(False, enemy.type, where, enemy.location))
1349 dispersion = (randreal()+randreal())*0.5 - 0.5
1350 dispersion += 0.002*enemy.power*dispersion
1351 hit = torpedo(enemy.location, course, dispersion, number=1, nburst=1)
1352 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1353 finish(FWON); # Klingons did themselves in!
1354 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.alldone:
1355 return # Supernova or finished
1358 # incoming phaser or torpedo, shields may dissipate it
1359 if game.shldup or game.shldchg or game.condition=="docked":
1360 # shields will take hits
1361 propor = pfac * game.shield
1362 if game.condition =="docked":
1366 hitsh = propor*chgfac*hit+1.0
1368 if absorb > game.shield:
1369 absorb = game.shield
1370 game.shield -= absorb
1372 # taking a hit blasts us out of a starbase dock
1373 if game.condition == "docked":
1375 # but the shields may take care of it
1376 if propor > 0.1 and hit < 0.005*game.energy:
1378 # hit from this opponent got through shields, so take damage
1380 proutn(_("%d unit hit") % int(hit))
1381 if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
1382 proutn(_(" on the ") + crmshp())
1383 if not damaged(DSRSENS) and usephasers:
1384 prout(_(" from ") + crmena(False, enemy.type, where, enemy.location))
1386 # Decide if hit is critical
1392 if game.energy <= 0:
1393 # Returning home upon your shield, not with it...
1396 if not attempt and game.condition == "docked":
1397 prout(_("***Enemies decide against attacking your ship."))
1398 percent = 100.0*pfac*game.shield+0.5
1400 # Shields fully protect ship
1401 proutn(_("Enemy attack reduces shield strength to "))
1403 # Emit message if starship suffered hit(s)
1405 proutn(_("Energy left %2d shields ") % int(game.energy))
1408 elif not damaged(DSHIELD):
1411 proutn(_("damaged, "))
1412 prout(_("%d%%, torpedoes left %d") % (percent, game.torps))
1413 # Check if anyone was hurt
1414 if hitmax >= 200 or hittot >= 500:
1415 icas = randrange(int(hittot * 0.015))
1418 prout(_("Mc Coy- \"Sickbay to bridge. We suffered %d casualties") % icas)
1419 prout(_(" in that last attack.\""))
1421 game.state.crew -= icas
1422 # After attack, reset average distance to enemies
1423 for enemy in game.enemies:
1424 enemy.kavgd = enemy.kdist
1425 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
1428 def deadkl(w, type, mv):
1429 "Kill a Klingon, Tholian, Romulan, or Thingy."
1430 # Added mv to allow enemy to "move" before dying
1431 proutn(crmena(True, type, "sector", mv))
1432 # Decide what kind of enemy it is and update appropriately
1434 # Chalk up a Romulan
1435 game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans -= 1
1437 game.state.nromrem -= 1
1446 # Killed some type of Klingon
1447 game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
1450 game.state.kcmdr.remove(game.quadrant)
1452 if game.state.kcmdr:
1453 schedule(FTBEAM, expran(1.0*game.incom/len(game.state.kcmdr)))
1454 if is_scheduled(FCDBAS) and game.battle == game.quadrant:
1457 game.state.remkl -= 1
1459 game.state.nscrem -= 1
1460 game.state.kscmdr.invalidate()
1465 # For each kind of enemy, finish message to player
1466 prout(_(" destroyed."))
1467 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1470 # Remove enemy ship from arrays describing local conditions
1471 for e in game.enemies:
1478 "Return None if target is invalid, otherwise return a course angle."
1479 if not w.valid_sector():
1483 # FIXME: C code this was translated from is wacky -- why the sign reversal?
1484 delta.j = (w.j - game.sector.j);
1485 delta.i = (game.sector.i - w.i);
1486 if delta == coord(0, 0):
1488 prout(_("Spock- \"Bridge to sickbay. Dr. McCoy,"))
1489 prout(_(" I recommend an immediate review of"))
1490 prout(_(" the Captain's psychological profile.\""))
1493 return delta.bearing()
1496 "Launch photon torpedo."
1499 if damaged(DPHOTON):
1500 prout(_("Photon tubes damaged."))
1504 prout(_("No torpedoes left."))
1507 # First, get torpedo count
1510 if scanner.token == "IHALPHA":
1513 elif scanner.token == "IHEOL" or not scanner.waiting():
1514 prout(_("%d torpedoes left.") % game.torps)
1516 proutn(_("Number of torpedoes to fire- "))
1517 continue # Go back around to get a number
1518 else: # key == "IHREAL"
1520 if n <= 0: # abort command
1525 prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
1528 scanner.chew() # User requested more torps than available
1529 continue # Go back around
1530 break # All is good, go to next stage
1534 key = scanner.next()
1535 if i==0 and key == "IHEOL":
1536 break; # no coordinate waiting, we will try prompting
1537 if i==1 and key == "IHEOL":
1538 # direct all torpedoes at one target
1540 target.append(target[0])
1541 course.append(course[0])
1544 scanner.push(scanner.token)
1545 target.append(scanner.getcoord())
1546 if target[-1] == None:
1548 course.append(targetcheck(target[-1]))
1549 if course[-1] == None:
1552 if len(target) == 0:
1553 # prompt for each one
1555 proutn(_("Target sector for torpedo number %d- ") % (i+1))
1557 target.append(scanner.getcoord())
1558 if target[-1] == None:
1560 course.append(targetcheck(target[-1]))
1561 if course[-1] == None:
1564 # Loop for moving <n> torpedoes
1566 if game.condition != "docked":
1568 dispersion = (randreal()+randreal())*0.5 -0.5
1569 if math.fabs(dispersion) >= 0.47:
1571 dispersion *= randreal(1.2, 2.2)
1573 prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
1575 prouts(_("***TORPEDO MISFIRES."))
1578 prout(_(" Remainder of burst aborted."))
1580 prout(_("***Photon tubes damaged by misfire."))
1581 game.damage[DPHOTON] = game.damfac * randreal(1.0, 3.0)
1583 if game.shldup or game.condition == "docked":
1584 dispersion *= 1.0 + 0.0001*game.shield
1585 torpedo(game.sector, course[i], dispersion, number=i, nburst=n)
1586 if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
1588 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1592 "Check for phasers overheating."
1594 checkburn = (rpow-1500.0)*0.00038
1595 if withprob(checkburn):
1596 prout(_("Weapons officer Sulu- \"Phasers overheated, sir.\""))
1597 game.damage[DPHASER] = game.damfac* randreal(1.0, 2.0) * (1.0+checkburn)
1599 def checkshctrl(rpow):
1600 "Check shield control."
1603 prout(_("Shields lowered."))
1605 # Something bad has happened
1606 prouts(_("***RED ALERT! RED ALERT!"))
1608 hit = rpow*game.shield/game.inshld
1609 game.energy -= rpow+hit*0.8
1610 game.shield -= hit*0.2
1611 if game.energy <= 0.0:
1612 prouts(_("Sulu- \"Captain! Shield malf***********************\""))
1617 prouts(_("Sulu- \"Captain! Shield malfunction! Phaser fire contained!\""))
1619 prout(_("Lt. Uhura- \"Sir, all decks reporting damage.\""))
1620 icas = randrange(int(hit*0.012))
1625 prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
1626 prout(_(" %d casualties so far.\"") % icas)
1628 game.state.crew -= icas
1630 prout(_("Phaser energy dispersed by shields."))
1631 prout(_("Enemy unaffected."))
1636 "Register a phaser hit on Klingons and Romulans."
1637 nenhr2 = len(game.enemies); kk=0
1640 for (k, wham) in enumerate(hits):
1643 dustfac = randreal(0.9, 1.0)
1644 hit = wham*math.pow(dustfac,game.enemies[kk].kdist)
1645 kpini = game.enemies[kk].power
1646 kp = math.fabs(kpini)
1647 if PHASEFAC*hit < kp:
1649 if game.enemies[kk].power < 0:
1650 game.enemies[kk].power -= -kp
1652 game.enemies[kk].power -= kp
1653 kpow = game.enemies[kk].power
1654 w = game.enemies[kk].location
1656 if not damaged(DSRSENS):
1658 proutn(_("%d unit hit on ") % int(hit))
1660 proutn(_("Very small hit on "))
1661 ienm = game.quad[w.i][w.j]
1664 proutn(crmena(False, ienm, "sector", w))
1668 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
1672 kk -= 1 # don't do the increment
1674 else: # decide whether or not to emasculate klingon
1675 if kpow>0 and withprob(0.9) and kpow <= randreal(0.4, 0.8)*kpini:
1676 prout(_("***Mr. Spock- \"Captain, the vessel at Sector %s")%w)
1677 prout(_(" has just lost its firepower.\""))
1678 game.enemies[kk].power = -kpow
1683 "Fire phasers at bad guys."
1685 kz = 0; k = 1; irec=0 # Cheating inhibitor
1686 ifast = False; no = False; itarg = True; msgflag = True; rpow=0
1690 # SR sensors and Computer are needed for automode
1691 if damaged(DSRSENS) or damaged(DCOMPTR):
1693 if game.condition == "docked":
1694 prout(_("Phasers can't be fired through base shields."))
1697 if damaged(DPHASER):
1698 prout(_("Phaser control damaged."))
1702 if damaged(DSHCTRL):
1703 prout(_("High speed shield control damaged."))
1706 if game.energy <= 200.0:
1707 prout(_("Insufficient energy to activate high-speed shield control."))
1710 prout(_("Weapons Officer Sulu- \"High-speed shield control enabled, sir.\""))
1712 # Original code so convoluted, I re-did it all
1713 # (That was Tom Almy talking about the C code, I think -- ESR)
1714 while automode=="NOTSET":
1716 if key == "IHALPHA":
1717 if scanner.sees("manual"):
1718 if len(game.enemies)==0:
1719 prout(_("There is no enemy present to select."))
1722 automode="AUTOMATIC"
1725 key = scanner.next()
1726 elif scanner.sees("automatic"):
1727 if (not itarg) and len(game.enemies) != 0:
1728 automode = "FORCEMAN"
1730 if len(game.enemies)==0:
1731 prout(_("Energy will be expended into space."))
1732 automode = "AUTOMATIC"
1733 key = scanner.next()
1734 elif scanner.sees("no"):
1739 elif key == "IHREAL":
1740 if len(game.enemies)==0:
1741 prout(_("Energy will be expended into space."))
1742 automode = "AUTOMATIC"
1744 automode = "FORCEMAN"
1746 automode = "AUTOMATIC"
1749 if len(game.enemies)==0:
1750 prout(_("Energy will be expended into space."))
1751 automode = "AUTOMATIC"
1753 automode = "FORCEMAN"
1755 proutn(_("Manual or automatic? "))
1760 if automode == "AUTOMATIC":
1761 if key == "IHALPHA" and scanner.sees("no"):
1763 key = scanner.next()
1764 if key != "IHREAL" and len(game.enemies) != 0:
1765 prout(_("Phasers locked on target. Energy available: %.2f")%avail)
1770 for i in range(len(game.enemies)):
1771 irec += math.fabs(game.enemies[i].power)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))*randreal(1.01, 1.06) + 1.0
1773 proutn(_("%d units required. ") % irec)
1775 proutn(_("Units to fire= "))
1776 key = scanner.next()
1781 proutn(_("Energy available= %.2f") % avail)
1784 if not rpow > avail:
1791 if key == "IHALPHA" and scanner.sees("no"):
1794 game.energy -= 200; # Go and do it!
1795 if checkshctrl(rpow):
1800 if len(game.enemies):
1803 for i in range(len(game.enemies)):
1807 hits[i] = math.fabs(game.enemies[i].power)/(PHASEFAC*math.pow(0.90,game.enemies[i].kdist))
1808 over = randreal(1.01, 1.06) * hits[i]
1810 powrem -= hits[i] + over
1811 if powrem <= 0 and temp < hits[i]:
1820 if extra > 0 and not game.alldone:
1822 proutn(_("*** Tholian web absorbs "))
1823 if len(game.enemies)>0:
1824 proutn(_("excess "))
1825 prout(_("phaser energy."))
1827 prout(_("%d expended on empty space.") % int(extra))
1828 elif automode == "FORCEMAN":
1831 if damaged(DCOMPTR):
1832 prout(_("Battle computer damaged, manual fire only."))
1835 prouts(_("---WORKING---"))
1837 prout(_("Short-range-sensors-damaged"))
1838 prout(_("Insufficient-data-for-automatic-phaser-fire"))
1839 prout(_("Manual-fire-must-be-used"))
1841 elif automode == "MANUAL":
1843 for k in range(len(game.enemies)):
1844 aim = game.enemies[k].location
1845 ienm = game.quad[aim.i][aim.j]
1847 proutn(_("Energy available= %.2f") % (avail-0.006))
1851 if damaged(DSRSENS) and \
1852 not game.sector.distance(aim)<2**0.5 and ienm in ('C', 'S'):
1853 prout(cramen(ienm) + _(" can't be located without short range scan."))
1856 hits[k] = 0; # prevent overflow -- thanks to Alexei Voitenko
1861 if itarg and k > kz:
1862 irec=(abs(game.enemies[k].power)/(PHASEFAC*math.pow(0.9,game.enemies[k].kdist))) * randreal(1.01, 1.06) + 1.0
1865 if not damaged(DCOMPTR):
1870 proutn(_("units to fire at %s- ") % crmena(False, ienm, "sector", aim))
1871 key = scanner.next()
1872 if key == "IHALPHA" and scanner.sees("no"):
1874 key = scanner.next()
1876 if key == "IHALPHA":
1880 if k==1: # Let me say I'm baffled by this
1883 if scanner.real < 0:
1887 hits[k] = scanner.real
1888 rpow += scanner.real
1889 # If total requested is too much, inform and start over
1891 prout(_("Available energy exceeded -- try again."))
1894 key = scanner.next(); # scan for next value
1897 # zero energy -- abort
1900 if key == "IHALPHA" and scanner.sees("no"):
1905 game.energy -= 200.0
1906 if checkshctrl(rpow):
1910 # Say shield raised or malfunction, if necessary
1917 prout(_("Sulu- \"Sir, the high-speed shield control has malfunctioned . . ."))
1918 prouts(_(" CLICK CLICK POP . . ."))
1919 prout(_(" No response, sir!"))
1922 prout(_("Shields raised."))
1927 # Code from events,c begins here.
1929 # This isn't a real event queue a la BSD Trek yet -- you can only have one
1930 # event of each type active at any given time. Mostly these means we can
1931 # only have one FDISTR/FENSLV/FREPRO sequence going at any given time
1932 # BSD Trek, from which we swiped the idea, can have up to 5.
1934 def unschedule(evtype):
1935 "Remove an event from the schedule."
1936 game.future[evtype].date = FOREVER
1937 return game.future[evtype]
1939 def is_scheduled(evtype):
1940 "Is an event of specified type scheduled."
1941 return game.future[evtype].date != FOREVER
1943 def scheduled(evtype):
1944 "When will this event happen?"
1945 return game.future[evtype].date
1947 def schedule(evtype, offset):
1948 "Schedule an event of specified type."
1949 game.future[evtype].date = game.state.date + offset
1950 return game.future[evtype]
1952 def postpone(evtype, offset):
1953 "Postpone a scheduled event."
1954 game.future[evtype].date += offset
1957 "Rest period is interrupted by event."
1960 proutn(_("Mr. Spock- \"Captain, shall we cancel the rest period?\""))
1962 game.resting = False
1968 "Run through the event queue looking for things to do."
1970 fintim = game.state.date + game.optime; yank=0
1971 ictbeam = False; istract = False
1972 w = coord(); hold = coord()
1973 ev = event(); ev2 = event()
1975 def tractorbeam(yank):
1976 "Tractor-beaming cases merge here."
1978 game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
1980 prout("***" + crmshp() + _(" caught in long range tractor beam--"))
1981 # If Kirk & Co. screwing around on planet, handle
1982 atover(True) # atover(true) is Grab
1985 if game.icraft: # Caught in Galileo?
1988 # Check to see if shuttle is aboard
1989 if game.iscraft == "offship":
1992 prout(_("Galileo, left on the planet surface, is captured"))
1993 prout(_("by aliens and made into a flying McDonald's."))
1994 game.damage[DSHUTTL] = -10
1995 game.iscraft = "removed"
1997 prout(_("Galileo, left on the planet surface, is well hidden."))
1999 game.quadrant = game.state.kscmdr
2001 game.quadrant = game.state.kcmdr[i]
2002 game.sector = randplace(QUADSIZE)
2003 prout(crmshp() + _(" is pulled to Quadrant %s, Sector %s") \
2004 % (game.quadrant, game.sector))
2006 prout(_("(Remainder of rest/repair period cancelled.)"))
2007 game.resting = False
2009 if not damaged(DSHIELD) and game.shield > 0:
2010 doshield(shraise=True) # raise shields
2011 game.shldchg = False
2013 prout(_("(Shields not currently useable.)"))
2015 # Adjust finish time to time of tractor beaming
2016 fintim = game.state.date+game.optime
2017 attack(torps_ok=False)
2018 if not game.state.kcmdr:
2021 schedule(FTBEAM, game.optime+expran(1.5*game.intime/len(game.state.kcmdr)))
2024 "Code merges here for any commander destroying a starbase."
2025 # Not perfect, but will have to do
2026 # Handle case where base is in same quadrant as starship
2027 if game.battle == game.quadrant:
2028 game.state.chart[game.battle.i][game.battle.j].starbase = False
2029 game.quad[game.base.i][game.base.j] = '.'
2030 game.base.invalidate()
2033 prout(_("Spock- \"Captain, I believe the starbase has been destroyed.\""))
2034 elif game.state.baseq and communicating():
2035 # Get word via subspace radio
2038 prout(_("Lt. Uhura- \"Captain, Starfleet Command reports that"))
2039 proutn(_(" the starbase in Quadrant %s has been destroyed by") % game.battle)
2041 prout(_("the Klingon Super-Commander"))
2043 prout(_("a Klingon Commander"))
2044 game.state.chart[game.battle.i][game.battle.j].starbase = False
2045 # Remove Starbase from galaxy
2046 game.state.galaxy[game.battle.i][game.battle.j].starbase = False
2047 game.state.baseq = filter(lambda x: x != game.battle, game.state.baseq)
2049 # reinstate a commander's base attack
2053 game.battle.invalidate()
2055 prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
2056 for i in range(1, NEVENTS):
2057 if i == FSNOVA: proutn("=== Supernova ")
2058 elif i == FTBEAM: proutn("=== T Beam ")
2059 elif i == FSNAP: proutn("=== Snapshot ")
2060 elif i == FBATTAK: proutn("=== Base Attack ")
2061 elif i == FCDBAS: proutn("=== Base Destroy ")
2062 elif i == FSCMOVE: proutn("=== SC Move ")
2063 elif i == FSCDBAS: proutn("=== SC Base Destroy ")
2064 elif i == FDSPROB: proutn("=== Probe Move ")
2065 elif i == FDISTR: proutn("=== Distress Call ")
2066 elif i == FENSLV: proutn("=== Enslavement ")
2067 elif i == FREPRO: proutn("=== Klingon Build ")
2069 prout("%.2f" % (scheduled(i)))
2072 radio_was_broken = damaged(DRADIO)
2075 # Select earliest extraneous event, evcode==0 if no events
2080 for l in range(1, NEVENTS):
2081 if game.future[l].date < datemin:
2084 prout("== Event %d fires" % evcode)
2085 datemin = game.future[l].date
2086 xtime = datemin-game.state.date
2087 game.state.date = datemin
2088 # Decrement Federation resources and recompute remaining time
2089 game.state.remres -= (game.state.remkl+4*len(game.state.kcmdr))*xtime
2091 if game.state.remtime <=0:
2094 # Any crew left alive?
2095 if game.state.crew <=0:
2098 # Is life support adequate?
2099 if damaged(DLIFSUP) and game.condition != "docked":
2100 if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
2103 game.lsupres -= xtime
2104 if game.damage[DLIFSUP] <= xtime:
2105 game.lsupres = game.inlsr
2108 if game.condition == "docked":
2109 repair /= game.docfac
2110 # Don't fix Deathray here
2111 for l in range(NDEVICES):
2112 if game.damage[l] > 0.0 and l != DDRAY:
2113 if game.damage[l]-repair > 0.0:
2114 game.damage[l] -= repair
2116 game.damage[l] = 0.0
2117 # If radio repaired, update star chart and attack reports
2118 if radio_was_broken and not damaged(DRADIO):
2119 prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
2120 prout(_(" surveillance reports are coming in."))
2122 if not game.iseenit:
2126 prout(_(" The star chart is now up to date.\""))
2128 # Cause extraneous event EVCODE to occur
2129 game.optime -= xtime
2130 if evcode == FSNOVA: # Supernova
2133 schedule(FSNOVA, expran(0.5*game.intime))
2134 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2136 elif evcode == FSPY: # Check with spy to see if SC should tractor beam
2137 if game.state.nscrem == 0 or \
2138 ictbeam or istract or \
2139 game.condition=="docked" or game.isatb==1 or game.iscate:
2141 if game.ientesc or \
2142 (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
2143 (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
2144 (damaged(DSHIELD) and \
2145 (game.energy < 2500 or damaged(DPHASER)) and \
2146 (game.torps < 5 or damaged(DPHOTON))):
2148 istract = ictbeam = True
2149 tractorbeam((game.state.kscmdr-game.quadrant).distance())
2152 elif evcode == FTBEAM: # Tractor beam
2153 if not game.state.kcmdr:
2156 i = randrange(len(game.state.kcmdr))
2157 yank = (game.state.kcmdr[i]-game.quadrant).distance()
2158 if istract or game.condition == "docked" or yank == 0:
2159 # Drats! Have to reschedule
2161 game.optime + expran(1.5*game.intime/len(game.state.kcmdr)))
2165 elif evcode == FSNAP: # Snapshot of the universe (for time warp)
2166 game.snapsht = copy.deepcopy(game.state)
2167 game.state.snap = True
2168 schedule(FSNAP, expran(0.5 * game.intime))
2169 elif evcode == FBATTAK: # Commander attacks starbase
2170 if not game.state.kcmdr or not game.state.baseq:
2176 for ibq in game.state.baseq:
2177 for cmdr in game.state.kcmdr:
2178 if ibq == cmdr and ibq != game.quadrant and ibq != game.state.kscmdr:
2181 # no match found -- try later
2182 schedule(FBATTAK, expran(0.3*game.intime))
2187 # commander + starbase combination found -- launch attack
2189 schedule(FCDBAS, randreal(1.0, 4.0))
2190 if game.isatb: # extra time if SC already attacking
2191 postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
2192 game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
2193 game.iseenit = False
2194 if not communicating():
2195 continue # No warning :-(
2199 prout(_("Lt. Uhura- \"Captain, the starbase in Quadrant %s") % game.battle)
2200 prout(_(" reports that it is under attack and that it can"))
2201 prout(_(" hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
2204 elif evcode == FSCDBAS: # Supercommander destroys base
2207 if not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].starbase:
2208 continue # WAS RETURN!
2210 game.battle = game.state.kscmdr
2212 elif evcode == FCDBAS: # Commander succeeds in destroying base
2215 if not game.state.baseq() \
2216 or not game.state.galaxy[game.battle.i][game.battle.j].starbase:
2217 game.battle.invalidate()
2219 # find the lucky pair
2220 for cmdr in game.state.kcmdr:
2221 if cmdr == game.battle:
2224 # No action to take after all
2227 elif evcode == FSCMOVE: # Supercommander moves
2228 schedule(FSCMOVE, 0.2777)
2229 if not game.ientesc and not istract and game.isatb != 1 and \
2230 (not game.iscate or not game.justin):
2232 elif evcode == FDSPROB: # Move deep space probe
2233 schedule(FDSPROB, 0.01)
2234 if not game.probe.next():
2235 if not game.probe.quadrant().valid_quadrant() or \
2236 game.state.galaxy[game.probe.quadrant().i][game.probe.quadrant().j].supernova:
2237 # Left galaxy or ran into supernova
2241 proutn(_("Lt. Uhura- \"The deep space probe "))
2242 if not game.probe.quadrant().valid_quadrant():
2243 prout(_("has left the galaxy.\""))
2245 prout(_("is no longer transmitting.\""))
2251 prout(_("Lt. Uhura- \"The deep space probe is now in Quadrant %s.\"") % game.probe.quadrant())
2252 pdest = game.state.galaxy[game.probe.quadrant().i][game.probe.quadrant().j]
2254 chp = game.state.chart[game.probe.quadrant().i][game.probe.quadrant().j]
2255 chp.klingons = pdest.klingons
2256 chp.starbase = pdest.starbase
2257 chp.stars = pdest.stars
2258 pdest.charted = True
2259 game.probe.moves -= 1 # One less to travel
2260 if game.probe.arrived() and game.isarmed and pdest.stars:
2261 supernova(game.probe) # fire in the hole!
2263 if game.state.galaxy[game.quadrant().i][game.quadrant().j].supernova:
2265 elif evcode == FDISTR: # inhabited system issues distress call
2267 # try a whole bunch of times to find something suitable
2268 for i in range(100):
2269 # need a quadrant which is not the current one,
2270 # which has some stars which are inhabited and
2271 # not already under attack, which is not
2272 # supernova'ed, and which has some Klingons in it
2273 w = randplace(GALSIZE)
2274 q = game.state.galaxy[w.i][w.j]
2275 if not (game.quadrant == w or q.planet == None or \
2276 not q.planet.inhabited or \
2277 q.supernova or q.status!="secure" or q.klingons<=0):
2280 # can't seem to find one; ignore this call
2282 prout("=== Couldn't find location for distress event.")
2284 # got one!! Schedule its enslavement
2285 ev = schedule(FENSLV, expran(game.intime))
2287 q.status = "distressed"
2288 # tell the captain about it if we can
2290 prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
2292 prout(_("by a Klingon invasion fleet."))
2295 elif evcode == FENSLV: # starsystem is enslaved
2296 ev = unschedule(FENSLV)
2297 # see if current distress call still active
2298 q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
2302 q.status = "enslaved"
2304 # play stork and schedule the first baby
2305 ev2 = schedule(FREPRO, expran(2.0 * game.intime))
2306 ev2.quadrant = ev.quadrant
2308 # report the disaster if we can
2310 prout(_("Uhura- We've lost contact with starsystem %s") % \
2312 prout(_("in Quadrant %s.\n") % ev.quadrant)
2313 elif evcode == FREPRO: # Klingon reproduces
2314 # If we ever switch to a real event queue, we'll need to
2315 # explicitly retrieve and restore the x and y.
2316 ev = schedule(FREPRO, expran(1.0 * game.intime))
2317 # see if current distress call still active
2318 q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
2322 if game.state.remkl >=MAXKLGAME:
2323 continue # full right now
2324 # reproduce one Klingon
2327 if game.klhere >= MAXKLQUAD:
2329 # this quadrant not ok, pick an adjacent one
2330 for m.i in range(w.i - 1, w.i + 2):
2331 for m.j in range(w.j - 1, w.j + 2):
2332 if not m.valid_quadrant():
2334 q = game.state.galaxy[m.i][m.j]
2335 # check for this quad ok (not full & no snova)
2336 if q.klingons >= MAXKLQUAD or q.supernova:
2340 continue # search for eligible quadrant failed
2344 game.state.remkl += 1
2346 if game.quadrant == w:
2348 game.enemies.append(newkling())
2349 # recompute time left
2352 if game.quadrant == w:
2353 prout(_("Spock- sensors indicate the Klingons have"))
2354 prout(_("launched a warship from %s.") % q.planet)
2356 prout(_("Uhura- Starfleet reports increased Klingon activity"))
2357 if q.planet != None:
2358 proutn(_("near %s") % q.planet)
2359 prout(_("in Quadrant %s.") % w)
2365 key = scanner.next()
2368 proutn(_("How long? "))
2373 origTime = delay = scanner.real
2376 if delay >= game.state.remtime or len(game.enemies) != 0:
2377 proutn(_("Are you sure? "))
2380 # Alternate resting periods (events) with attacks
2384 game.resting = False
2385 if not game.resting:
2386 prout(_("%d stardates left.") % int(game.state.remtime))
2388 temp = game.optime = delay
2389 if len(game.enemies):
2390 rtime = randreal(1.0, 2.0)
2394 if game.optime < delay:
2395 attack(torps_ok=False)
2403 # Repair Deathray if long rest at starbase
2404 if origTime-delay >= 9.99 and game.condition == "docked":
2405 game.damage[DDRAY] = 0.0
2406 # leave if quadrant supernovas
2407 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
2409 game.resting = False
2414 course = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
2415 newc = coord(); neighbor = coord(); bump = coord(0, 0)
2417 # Wow! We've supernova'ed
2418 supernova(game.quadrant)
2420 # handle initial nova
2421 game.quad[nov.i][nov.j] = '.'
2422 prout(crmena(False, '*', "sector", nov) + _(" novas."))
2423 game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
2424 game.state.starkl += 1
2425 # Set up queue to recursively trigger adjacent stars
2431 for offset.i in range(-1, 1+1):
2432 for offset.j in range(-1, 1+1):
2433 if offset.j==0 and offset.i==0:
2435 neighbor = start + offset
2436 if not neighbor.valid_sector():
2438 iquad = game.quad[neighbor.i][neighbor.j]
2439 # Empty space ends reaction
2440 if iquad in ('.', '?', ' ', 'T', '#'):
2442 elif iquad == '*': # Affect another star
2444 # This star supernovas
2445 supernova(game.quadrant)
2448 hits.append(neighbor)
2449 game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
2450 game.state.starkl += 1
2451 proutn(crmena(True, '*', "sector", neighbor))
2453 game.quad[neighbor.i][neighbor.j] = '.'
2455 elif iquad in ('P', '@'): # Destroy planet
2456 game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
2458 game.state.nplankl += 1
2460 game.state.worldkl += 1
2461 prout(crmena(True, 'B', "sector", neighbor) + _(" destroyed."))
2462 game.iplnet.pclass = "destroyed"
2464 game.plnet.invalidate()
2468 game.quad[neighbor.i][neighbor.j] = '.'
2469 elif iquad == 'B': # Destroy base
2470 game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase = False
2471 game.state.baseq = filter(lambda x: x!= game.quadrant, game.state.baseq)
2472 game.base.invalidate()
2473 game.state.basekl += 1
2475 prout(crmena(True, 'B', "sector", neighbor) + _(" destroyed."))
2476 game.quad[neighbor.i][neighbor.j] = '.'
2477 elif iquad in ('E', 'F'): # Buffet ship
2478 prout(_("***Starship buffeted by nova."))
2480 if game.shield >= 2000.0:
2481 game.shield -= 2000.0
2483 diff = 2000.0 - game.shield
2487 prout(_("***Shields knocked out."))
2488 game.damage[DSHIELD] += 0.005*game.damfac*randreal()*diff
2490 game.energy -= 2000.0
2491 if game.energy <= 0:
2494 # add in course nova contributes to kicking starship
2495 bump += (game.sector-hits[mm]).sgn()
2496 elif iquad == 'K': # kill klingon
2497 deadkl(neighbor, iquad, neighbor)
2498 elif iquad in ('C','S','R'): # Damage/destroy big enemies
2499 for ll in range(len(game.enemies)):
2500 if game.enemies[ll].location == neighbor:
2502 game.enemies[ll].power -= 800.0 # If firepower is lost, die
2503 if game.enemies[ll].power <= 0.0:
2504 deadkl(neighbor, iquad, neighbor)
2506 newc = neighbor + neighbor - hits[mm]
2507 proutn(crmena(True, iquad, "sector", neighbor) + _(" damaged"))
2508 if not newc.valid_sector():
2509 # can't leave quadrant
2512 iquad1 = game.quad[newc.i][newc.j]
2514 proutn(_(", blasted into ") + crmena(False, ' ', "sector", newc))
2516 deadkl(neighbor, iquad, newc)
2519 # can't move into something else
2522 proutn(_(", buffeted to Sector %s") % newc)
2523 game.quad[neighbor.i][neighbor.j] = '.'
2524 game.quad[newc.i][newc.j] = iquad
2525 game.enemies[ll].move(newc)
2526 # Starship affected by nova -- kick it away.
2528 direc = course[3*(bump.i+1)+bump.j+2]
2533 course = course(bearing=direc, distance=dist)
2534 game.optime = course.time(warp=4)
2536 prout(_("Force of nova displaces starship."))
2537 imove(course, noattack=True)
2538 game.optime = course.time(warp=4)
2542 "Star goes supernova."
2547 # Scheduled supernova -- select star at random.
2550 for nq.i in range(GALSIZE):
2551 for nq.j in range(GALSIZE):
2552 stars += game.state.galaxy[nq.i][nq.j].stars
2554 return # nothing to supernova exists
2555 num = randrange(stars) + 1
2556 for nq.i in range(GALSIZE):
2557 for nq.j in range(GALSIZE):
2558 num -= game.state.galaxy[nq.i][nq.j].stars
2564 proutn("=== Super nova here?")
2567 if not nq == game.quadrant or game.justin:
2568 # it isn't here, or we just entered (treat as enroute)
2571 prout(_("Message from Starfleet Command Stardate %.2f") % game.state.date)
2572 prout(_(" Supernova in Quadrant %s; caution advised.") % nq)
2575 # we are in the quadrant!
2576 num = randrange(game.state.galaxy[nq.i][nq.j].stars) + 1
2577 for ns.i in range(QUADSIZE):
2578 for ns.j in range(QUADSIZE):
2579 if game.quad[ns.i][ns.j]=='*':
2586 prouts(_("***RED ALERT! RED ALERT!"))
2588 prout(_("***Incipient supernova detected at Sector %s") % ns)
2589 if (ns.i-game.sector.i)**2 + (ns.j-game.sector.j)**2 <= 2.1:
2590 proutn(_("Emergency override attempts t"))
2591 prouts("***************")
2595 # destroy any Klingons in supernovaed quadrant
2596 kldead = game.state.galaxy[nq.i][nq.j].klingons
2597 game.state.galaxy[nq.i][nq.j].klingons = 0
2598 if nq == game.state.kscmdr:
2599 # did in the Supercommander!
2600 game.state.nscrem = game.state.kscmdr.i = game.state.kscmdr.j = game.isatb = 0
2604 survivors = filter(lambda w: w != nq, game.state.kcmdr)
2605 comkills = len(game.state.kcmdr) - len(survivors)
2606 game.state.kcmdr = survivors
2608 if not game.state.kcmdr:
2610 game.state.remkl -= kldead
2611 # destroy Romulans and planets in supernovaed quadrant
2612 nrmdead = game.state.galaxy[nq.i][nq.j].romulans
2613 game.state.galaxy[nq.i][nq.j].romulans = 0
2614 game.state.nromrem -= nrmdead
2616 for loop in range(game.inplan):
2617 if game.state.planets[loop].quadrant == nq:
2618 game.state.planets[loop].pclass = "destroyed"
2620 # Destroy any base in supernovaed quadrant
2621 game.state.baseq = filter(lambda x: x != nq, game.state.baseq)
2622 # If starship caused supernova, tally up destruction
2624 game.state.starkl += game.state.galaxy[nq.i][nq.j].stars
2625 game.state.basekl += game.state.galaxy[nq.i][nq.j].starbase
2626 game.state.nplankl += npdead
2627 # mark supernova in galaxy and in star chart
2628 if game.quadrant == nq or communicating():
2629 game.state.galaxy[nq.i][nq.j].supernova = True
2630 # If supernova destroys last Klingons give special message
2631 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0 and not nq == game.quadrant:
2634 prout(_("Lucky you!"))
2635 proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
2638 # if some Klingons remain, continue or die in supernova
2643 # Code from finish.c ends here.
2646 "Self-destruct maneuver. Finish with a BANG!"
2648 if damaged(DCOMPTR):
2649 prout(_("Computer damaged; cannot execute destruct sequence."))
2651 prouts(_("---WORKING---")); skip(1)
2652 prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
2653 prouts(" 10"); skip(1)
2654 prouts(" 9"); skip(1)
2655 prouts(" 8"); skip(1)
2656 prouts(" 7"); skip(1)
2657 prouts(" 6"); skip(1)
2659 prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
2661 prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
2663 prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
2667 if game.passwd != scanner.token:
2668 prouts(_("PASSWORD-REJECTED;"))
2670 prouts(_("CONTINUITY-EFFECTED"))
2673 prouts(_("PASSWORD-ACCEPTED")); skip(1)
2674 prouts(" 5"); skip(1)
2675 prouts(" 4"); skip(1)
2676 prouts(" 3"); skip(1)
2677 prouts(" 2"); skip(1)
2678 prouts(" 1"); skip(1)
2680 prouts(_("GOODBYE-CRUEL-WORLD"))
2688 prouts(_("********* Entropy of %s maximized *********") % crmshp())
2692 if len(game.enemies) != 0:
2693 whammo = 25.0 * game.energy
2695 while l <= len(game.enemies):
2696 if game.enemies[l].power*game.enemies[l].kdist <= whammo:
2697 deadkl(game.enemies[l].location, game.quad[game.enemies[l].location.i][game.enemies[l].location.j], game.enemies[l].location)
2702 "Compute our rate of kils over time."
2703 elapsed = game.state.date - game.indate
2704 if elapsed == 0: # Avoid divide-by-zero error if calculated on turn 0
2707 starting = (game.inkling + game.incom + game.inscom)
2708 remaining = (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)
2709 return (starting - remaining)/elapsed
2713 badpt = 5.0*game.state.starkl + \
2715 10.0*game.state.nplankl + \
2716 300*game.state.nworldkl + \
2718 100.0*game.state.basekl +\
2720 if game.ship == 'F':
2722 elif game.ship == None:
2727 # end the game, with appropriate notfications
2731 prout(_("It is stardate %.1f.") % game.state.date)
2733 if ifin == FWON: # Game has been won
2734 if game.state.nromrem != 0:
2735 prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
2738 prout(_("You have smashed the Klingon invasion fleet and saved"))
2739 prout(_("the Federation."))
2744 badpt = 0.0 # Close enough!
2745 # killsPerDate >= RateMax
2746 if game.state.date-game.indate < 5.0 or \
2747 killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
2749 prout(_("In fact, you have done so well that Starfleet Command"))
2750 if game.skill == SKILL_NOVICE:
2751 prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
2752 elif game.skill == SKILL_FAIR:
2753 prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
2754 elif game.skill == SKILL_GOOD:
2755 prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
2756 elif game.skill == SKILL_EXPERT:
2757 prout(_("promotes you to Commodore Emeritus."))
2759 prout(_("Now that you think you're really good, try playing"))
2760 prout(_("the \"Emeritus\" game. It will splatter your ego."))
2761 elif game.skill == SKILL_EMERITUS:
2763 proutn(_("Computer- "))
2764 prouts(_("ERROR-ERROR-ERROR-ERROR"))
2766 prouts(_(" YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
2768 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
2770 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
2772 prouts(_(" THIS-PROGRAM-MUST-SURVIVE"))
2774 prouts(_(" THIS-PROGRAM-MUST?- MUST ? - SUR? ? -? VI"))
2776 prout(_("Now you can retire and write your own Star Trek game!"))
2778 elif game.skill >= SKILL_EXPERT:
2779 if game.thawed and not idebug:
2780 prout(_("You cannot get a citation, so..."))
2782 proutn(_("Do you want your Commodore Emeritus Citation printed? "))
2786 # Only grant long life if alive (original didn't!)
2788 prout(_("LIVE LONG AND PROSPER."))
2793 elif ifin == FDEPLETE: # Federation Resources Depleted
2794 prout(_("Your time has run out and the Federation has been"))
2795 prout(_("conquered. Your starship is now Klingon property,"))
2796 prout(_("and you are put on trial as a war criminal. On the"))
2797 proutn(_("basis of your record, you are "))
2798 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)*3.0 > (game.inkling + game.incom + game.inscom):
2799 prout(_("acquitted."))
2801 prout(_("LIVE LONG AND PROSPER."))
2803 prout(_("found guilty and"))
2804 prout(_("sentenced to death by slow torture."))
2808 elif ifin == FLIFESUP:
2809 prout(_("Your life support reserves have run out, and"))
2810 prout(_("you die of thirst, starvation, and asphyxiation."))
2811 prout(_("Your starship is a derelict in space."))
2813 prout(_("Your energy supply is exhausted."))
2815 prout(_("Your starship is a derelict in space."))
2816 elif ifin == FBATTLE:
2817 prout(_("The %s has been destroyed in battle.") % crmshp())
2819 prout(_("Dulce et decorum est pro patria mori."))
2821 prout(_("You have made three attempts to cross the negative energy"))
2822 prout(_("barrier which surrounds the galaxy."))
2824 prout(_("Your navigation is abominable."))
2827 prout(_("Your starship has been destroyed by a nova."))
2828 prout(_("That was a great shot."))
2830 elif ifin == FSNOVAED:
2831 prout(_("The %s has been fried by a supernova.") % crmshp())
2832 prout(_("...Not even cinders remain..."))
2833 elif ifin == FABANDN:
2834 prout(_("You have been captured by the Klingons. If you still"))
2835 prout(_("had a starbase to be returned to, you would have been"))
2836 prout(_("repatriated and given another chance. Since you have"))
2837 prout(_("no starbases, you will be mercilessly tortured to death."))
2838 elif ifin == FDILITHIUM:
2839 prout(_("Your starship is now an expanding cloud of subatomic particles"))
2840 elif ifin == FMATERIALIZE:
2841 prout(_("Starbase was unable to re-materialize your starship."))
2842 prout(_("Sic transit gloria mundi"))
2843 elif ifin == FPHASER:
2844 prout(_("The %s has been cremated by its own phasers.") % crmshp())
2846 prout(_("You and your landing party have been"))
2847 prout(_("converted to energy, disipating through space."))
2848 elif ifin == FMINING:
2849 prout(_("You are left with your landing party on"))
2850 prout(_("a wild jungle planet inhabited by primitive cannibals."))
2852 prout(_("They are very fond of \"Captain Kirk\" soup."))
2854 prout(_("Without your leadership, the %s is destroyed.") % crmshp())
2855 elif ifin == FDPLANET:
2856 prout(_("You and your mining party perish."))
2858 prout(_("That was a great shot."))
2861 prout(_("The Galileo is instantly annihilated by the supernova."))
2862 prout(_("You and your mining party are atomized."))
2864 prout(_("Mr. Spock takes command of the %s and") % crmshp())
2865 prout(_("joins the Romulans, wreaking terror on the Federation."))
2866 elif ifin == FPNOVA:
2867 prout(_("You and your mining party are atomized."))
2869 prout(_("Mr. Spock takes command of the %s and") % crmshp())
2870 prout(_("joins the Romulans, wreaking terror on the Federation."))
2871 elif ifin == FSTRACTOR:
2872 prout(_("The shuttle craft Galileo is also caught,"))
2873 prout(_("and breaks up under the strain."))
2875 prout(_("Your debris is scattered for millions of miles."))
2876 prout(_("Without your leadership, the %s is destroyed.") % crmshp())
2878 prout(_("The mutants attack and kill Spock."))
2879 prout(_("Your ship is captured by Klingons, and"))
2880 prout(_("your crew is put on display in a Klingon zoo."))
2881 elif ifin == FTRIBBLE:
2882 prout(_("Tribbles consume all remaining water,"))
2883 prout(_("food, and oxygen on your ship."))
2885 prout(_("You die of thirst, starvation, and asphyxiation."))
2886 prout(_("Your starship is a derelict in space."))
2888 prout(_("Your ship is drawn to the center of the black hole."))
2889 prout(_("You are crushed into extremely dense matter."))
2891 prout(_("Your last crew member has died."))
2892 if game.ship == 'F':
2894 elif game.ship == 'E':
2897 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0:
2898 goodies = game.state.remres/game.inresor
2899 baddies = (game.state.remkl + 2.0*len(game.state.kcmdr))/(game.inkling+2.0*game.incom)
2900 if goodies/baddies >= randreal(1.0, 1.5):
2901 prout(_("As a result of your actions, a treaty with the Klingon"))
2902 prout(_("Empire has been signed. The terms of the treaty are"))
2903 if goodies/baddies >= randreal(3.0):
2904 prout(_("favorable to the Federation."))
2906 prout(_("Congratulations!"))
2908 prout(_("highly unfavorable to the Federation."))
2910 prout(_("The Federation will be destroyed."))
2912 prout(_("Since you took the last Klingon with you, you are a"))
2913 prout(_("martyr and a hero. Someday maybe they'll erect a"))
2914 prout(_("statue in your memory. Rest in peace, and try not"))
2915 prout(_("to think about pigeons."))
2920 "Compute player's score."
2921 timused = game.state.date - game.indate
2923 if (timused == 0 or (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) != 0) and timused < 5.0:
2925 perdate = killrate()
2926 ithperd = 500*perdate + 0.5
2929 iwon = 100*game.skill
2930 if game.ship == 'E':
2932 elif game.ship == 'F':
2936 if not game.gamewon:
2937 game.state.nromrem = 0 # None captured if no win
2938 iscore = 10*(game.inkling - game.state.remkl) \
2939 + 50*(game.incom - len(game.state.kcmdr)) \
2941 + 20*(game.inrom - game.state.nromrem) \
2942 + 200*(game.inscom - game.state.nscrem) \
2943 - game.state.nromrem \
2948 prout(_("Your score --"))
2949 if game.inrom - game.state.nromrem:
2950 prout(_("%6d Romulans destroyed %5d") %
2951 (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
2952 if game.state.nromrem:
2953 prout(_("%6d Romulans captured %5d") %
2954 (game.state.nromrem, game.state.nromrem))
2955 if game.inkling - game.state.remkl:
2956 prout(_("%6d ordinary Klingons destroyed %5d") %
2957 (game.inkling - game.state.remkl, 10*(game.inkling - game.state.remkl)))
2958 if game.incom - len(game.state.kcmdr):
2959 prout(_("%6d Klingon commanders destroyed %5d") %
2960 (game.incom - len(game.state.kcmdr), 50*(game.incom - len(game.state.kcmdr))))
2961 if game.inscom - game.state.nscrem:
2962 prout(_("%6d Super-Commander destroyed %5d") %
2963 (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
2965 prout(_("%6.2f Klingons per stardate %5d") %
2967 if game.state.starkl:
2968 prout(_("%6d stars destroyed by your action %5d") %
2969 (game.state.starkl, -5*game.state.starkl))
2970 if game.state.nplankl:
2971 prout(_("%6d planets destroyed by your action %5d") %
2972 (game.state.nplankl, -10*game.state.nplankl))
2973 if (game.options & OPTION_WORLDS) and game.state.nworldkl:
2974 prout(_("%6d inhabited planets destroyed by your action %5d") %
2975 (game.state.nplankl, -300*game.state.nworldkl))
2976 if game.state.basekl:
2977 prout(_("%6d bases destroyed by your action %5d") %
2978 (game.state.basekl, -100*game.state.basekl))
2980 prout(_("%6d calls for help from starbase %5d") %
2981 (game.nhelp, -45*game.nhelp))
2983 prout(_("%6d casualties incurred %5d") %
2984 (game.casual, -game.casual))
2986 prout(_("%6d crew abandoned in space %5d") %
2987 (game.abandoned, -3*game.abandoned))
2989 prout(_("%6d ship(s) lost or destroyed %5d") %
2990 (klship, -100*klship))
2992 prout(_("Penalty for getting yourself killed -200"))
2994 proutn(_("Bonus for winning "))
2995 if game.skill == SKILL_NOVICE: proutn(_("Novice game "))
2996 elif game.skill == SKILL_FAIR: proutn(_("Fair game "))
2997 elif game.skill == SKILL_GOOD: proutn(_("Good game "))
2998 elif game.skill == SKILL_EXPERT: proutn(_("Expert game "))
2999 elif game.skill == SKILL_EMERITUS: proutn(_("Emeritus game"))
3000 prout(" %5d" % iwon)
3002 prout(_("TOTAL SCORE %5d") % iscore)
3005 "Emit winner's commemmorative plaque."
3008 proutn(_("File or device name for your plaque: "))
3011 fp = open(winner, "w")
3014 prout(_("Invalid name."))
3016 proutn(_("Enter name to go on plaque (up to 30 characters): "))
3018 # The 38 below must be 64 for 132-column paper
3019 nskip = 38 - len(winner)/2
3020 fp.write("\n\n\n\n")
3021 # --------DRAW ENTERPRISE PICTURE.
3022 fp.write(" EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n" )
3023 fp.write(" EEE E : : : E\n" )
3024 fp.write(" EE EEE E : : NCC-1701 : E\n")
3025 fp.write("EEEEEEEEEEEEEEEE EEEEEEEEEEEEEEE : : : E\n")
3026 fp.write(" E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n")
3027 fp.write(" EEEEEEEEE EEEEEEEEEEEEE E E\n")
3028 fp.write(" EEEEEEE EEEEE E E E E\n")
3029 fp.write(" EEE E E E E\n")
3030 fp.write(" E E E E\n")
3031 fp.write(" EEEEEEEEEEEEE E E\n")
3032 fp.write(" EEE : EEEEEEE EEEEEEEE\n")
3033 fp.write(" :E : EEEE E\n")
3034 fp.write(" .-E -:----- E\n")
3035 fp.write(" :E : E\n")
3036 fp.write(" EE : EEEEEEEE\n")
3037 fp.write(" EEEEEEEEEEEEEEEEEEEEEEE\n")
3039 fp.write(_(" U. S. S. ENTERPRISE\n"))
3040 fp.write("\n\n\n\n")
3041 fp.write(_(" For demonstrating outstanding ability as a starship captain\n"))
3043 fp.write(_(" Starfleet Command bestows to you\n"))
3045 fp.write("%*s%s\n\n" % (nskip, "", winner))
3046 fp.write(_(" the rank of\n\n"))
3047 fp.write(_(" \"Commodore Emeritus\"\n\n"))
3049 if game.skill == SKILL_EXPERT:
3050 fp.write(_(" Expert level\n\n"))
3051 elif game.skill == SKILL_EMERITUS:
3052 fp.write(_("Emeritus level\n\n"))
3054 fp.write(_(" Cheat level\n\n"))
3055 timestring = time.ctime()
3056 fp.write(_(" This day of %.6s %.4s, %.8s\n\n") %
3057 (timestring+4, timestring+20, timestring+11))
3058 fp.write(_(" Your score: %d\n\n") % iscore)
3059 fp.write(_(" Klingons per stardate: %.2f\n") % perdate)
3062 # Code from io.c begins here
3064 rows = linecount = 0 # for paging
3067 fullscreen_window = None
3068 srscan_window = None
3069 report_window = None
3070 status_window = None
3071 lrscan_window = None
3072 message_window = None
3073 prompt_window = None
3078 gettext.bindtextdomain("sst", "/usr/local/share/locale")
3079 gettext.textdomain("sst")
3080 if not (game.options & OPTION_CURSES):
3081 ln_env = os.getenv("LINES")
3087 stdscr = curses.initscr()
3091 global fullscreen_window, srscan_window, report_window, status_window
3092 global lrscan_window, message_window, prompt_window
3093 (rows, columns) = stdscr.getmaxyx()
3094 fullscreen_window = stdscr
3095 srscan_window = curses.newwin(12, 25, 0, 0)
3096 report_window = curses.newwin(11, 0, 1, 25)
3097 status_window = curses.newwin(10, 0, 1, 39)
3098 lrscan_window = curses.newwin(5, 0, 0, 64)
3099 message_window = curses.newwin(0, 0, 12, 0)
3100 prompt_window = curses.newwin(1, 0, rows-2, 0)
3101 message_window.scrollok(True)
3102 setwnd(fullscreen_window)
3106 if game.options & OPTION_CURSES:
3107 stdscr.keypad(False)
3113 "Wait for user action -- OK to do nothing if on a TTY"
3114 if game.options & OPTION_CURSES:
3119 prouts(_("[ANNOUNCEMENT ARRIVING...]"))
3123 if game.skill > SKILL_FAIR:
3124 prompt = _("[CONTINUE?]")
3126 prompt = _("[PRESS ENTER TO CONTINUE]")
3128 if game.options & OPTION_CURSES:
3130 setwnd(prompt_window)
3131 prompt_window.clear()
3132 prompt_window.addstr(prompt)
3133 prompt_window.getstr()
3134 prompt_window.clear()
3135 prompt_window.refresh()
3136 setwnd(message_window)
3139 sys.stdout.write('\n')
3142 for j in range(rows):
3143 sys.stdout.write('\n')
3147 "Skip i lines. Pause game if this would cause a scrolling event."
3148 for dummy in range(i):
3149 if game.options & OPTION_CURSES:
3150 (y, x) = curwnd.getyx()
3151 (my, mx) = curwnd.getmaxyx()
3152 if curwnd == message_window and y >= my - 3:
3158 except curses.error:
3163 if rows and linecount >= rows:
3166 sys.stdout.write('\n')
3169 "Utter a line with no following line feed."
3170 if game.options & OPTION_CURSES:
3174 sys.stdout.write(line)
3184 if not replayfp or replayfp.closed: # Don't slow down replays
3187 if game.options & OPTION_CURSES:
3191 if not replayfp or replayfp.closed:
3195 "Get a line of input."
3196 if game.options & OPTION_CURSES:
3197 line = curwnd.getstr() + "\n"
3200 if replayfp and not replayfp.closed:
3202 line = replayfp.readline()
3205 prout("*** Replay finished")
3208 elif line[0] != "#":
3211 line = raw_input() + "\n"
3217 "Change windows -- OK for this to be a no-op in tty mode."
3219 if game.options & OPTION_CURSES:
3221 curses.curs_set(wnd == fullscreen_window or wnd == message_window or wnd == prompt_window)
3224 "Clear to end of line -- can be a no-op in tty mode"
3225 if game.options & OPTION_CURSES:
3230 "Clear screen -- can be a no-op in tty mode."
3232 if game.options & OPTION_CURSES:
3239 # Things past this point have policy implications.
3243 "Hook to be called after moving to redraw maps."
3244 if game.options & OPTION_CURSES:
3247 setwnd(srscan_window)
3251 setwnd(status_window)
3252 status_window.clear()
3253 status_window.move(0, 0)
3254 setwnd(report_window)
3255 report_window.clear()
3256 report_window.move(0, 0)
3258 setwnd(lrscan_window)
3259 lrscan_window.clear()
3260 lrscan_window.move(0, 0)
3261 lrscan(silent=False)
3263 def put_srscan_sym(w, sym):
3264 "Emit symbol for short-range scan."
3265 srscan_window.move(w.i+1, w.j*2+2)
3266 srscan_window.addch(sym)
3267 srscan_window.refresh()
3270 "Enemy fall down, go boom."
3271 if game.options & OPTION_CURSES:
3273 setwnd(srscan_window)
3274 srscan_window.attron(curses.A_REVERSE)
3275 put_srscan_sym(w, game.quad[w.i][w.j])
3279 srscan_window.attroff(curses.A_REVERSE)
3280 put_srscan_sym(w, game.quad[w.i][w.j])
3281 curses.delay_output(500)
3282 setwnd(message_window)
3285 "Sound and visual effects for teleportation."
3286 if game.options & OPTION_CURSES:
3288 setwnd(message_window)
3290 prouts(" . . . . . ")
3291 if game.options & OPTION_CURSES:
3292 #curses.delay_output(1000)
3296 def tracktorpedo(origin, w, step, i, n, iquad):
3297 "Torpedo-track animation."
3298 if not game.options & OPTION_CURSES:
3302 proutn(_("Track for torpedo number %d- ") % (i+1))
3305 proutn(_("Torpedo track- "))
3306 elif step==4 or step==9:
3310 if not damaged(DSRSENS) or game.condition=="docked":
3311 if i != 0 and step == 1:
3314 if (iquad=='.') or (iquad==' '):
3315 put_srscan_sym(w, '+')
3319 put_srscan_sym(w, iquad)
3321 curwnd.attron(curses.A_REVERSE)
3322 put_srscan_sym(w, iquad)
3326 curwnd.attroff(curses.A_REVERSE)
3327 put_srscan_sym(w, iquad)
3332 "Display the current galaxy chart."
3333 if game.options & OPTION_CURSES:
3334 setwnd(message_window)
3335 message_window.clear()
3337 if game.options & OPTION_TTY:
3342 def prstat(txt, data):
3344 if game.options & OPTION_CURSES:
3346 setwnd(status_window)
3348 proutn(" " * (NSYM - len(txt)))
3351 if game.options & OPTION_CURSES:
3352 setwnd(report_window)
3354 # Code from moving.c begins here
3356 def imove(course=None, noattack=False):
3357 "Movement execution for warp, impulse, supernova, and tractor-beam events."
3360 def newquadrant(noattack):
3361 # Leaving quadrant -- allow final enemy attack
3362 # Don't do it if being pushed by Nova
3363 if len(game.enemies) != 0 and not noattack:
3365 for enemy in game.enemies:
3366 finald = (w - enemy.location).distance()
3367 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3368 # Stas Sergeev added the condition
3369 # that attacks only happen if Klingons
3370 # are present and your skill is good.
3371 if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3372 attack(torps_ok=False)
3375 # check for edge of galaxy
3379 if course.final.i < 0:
3380 course.final.i = -course.final.i
3382 if course.final.j < 0:
3383 course.final.j = -course.final.j
3385 if course.final.i >= GALSIZE*QUADSIZE:
3386 course.final.i = (GALSIZE*QUADSIZE*2) - course.final.i
3388 if course.final.j >= GALSIZE*QUADSIZE:
3389 course.final.j = (GALSIZE*QUADSIZE*2) - course.final.j
3397 if game.nkinks == 3:
3398 # Three strikes -- you're out!
3402 prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
3403 prout(_("AT THE EDGE OF THE GALAXY. THE THIRD TIME YOU TRY THIS,"))
3404 prout(_("YOU WILL BE DESTROYED."))
3405 # Compute final position in new quadrant
3406 if trbeam: # Don't bother if we are to be beamed
3408 game.quadrant = course.final.quadrant()
3409 game.sector = course.final.sector()
3411 prout(_("Entering Quadrant %s.") % game.quadrant)
3412 game.quad[game.sector.i][game.sector.j] = game.ship
3414 if game.skill>SKILL_NOVICE:
3415 attack(torps_ok=False)
3417 def check_collision(h):
3418 iquad = game.quad[h.i][h.j]
3420 # object encountered in flight path
3421 stopegy = 50.0*course.distance/game.optime
3422 if iquad in ('T', 'K', 'C', 'S', 'R', '?'):
3423 for enemy in game.enemies:
3424 if enemy.location == game.sector:
3426 collision(rammed=False, enemy=enemy)
3430 prouts(_("***RED ALERT! RED ALERT!"))
3432 proutn("***" + crmshp())
3433 proutn(_(" pulled into black hole at Sector %s") % h)
3434 # Getting pulled into a black hole was certain
3435 # death in Almy's original. Stas Sergeev added a
3436 # possibility that you'll get timewarped instead.
3438 for m in range(NDEVICES):
3439 if game.damage[m]>0:
3441 probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
3442 if (game.options & OPTION_BLKHOLE) and withprob(1-probf):
3452 prout(_(" encounters Tholian web at %s;") % h)
3454 prout(_(" blocked by object at %s;") % h)
3455 proutn(_("Emergency stop required "))
3456 prout(_("%2d units of energy.") % int(stopegy))
3457 game.energy -= stopegy
3458 if game.energy <= 0:
3465 prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
3466 game.inorbit = False
3467 # If tractor beam is to occur, don't move full distance
3468 if game.state.date+game.optime >= scheduled(FTBEAM):
3470 game.condition = "red"
3471 course.distance = course.distance*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
3472 game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
3474 game.quad[game.sector.i][game.sector.j] = '.'
3475 for m in range(course.moves):
3478 if course.origin.quadrant() != course.location.quadrant():
3479 newquadrant(noattack)
3481 elif check_collision(w):
3482 print "Collision detected"
3486 # We're in destination quadrant -- compute new average enemy distances
3487 game.quad[game.sector.i][game.sector.j] = game.ship
3489 for enemy in game.enemies:
3490 finald = (w-enemy.location).distance()
3491 enemy.kavgd = 0.5 * (finald + enemy.kdist)
3492 enemy.kdist = finald
3493 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
3494 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3495 attack(torps_ok=False)
3496 for enemy in game.enemies:
3497 enemy.kavgd = enemy.kdist
3500 setwnd(message_window)
3504 "Dock our ship at a starbase."
3506 if game.condition == "docked" and verbose:
3507 prout(_("Already docked."))
3510 prout(_("You must first leave standard orbit."))
3512 if not game.base.is_valid() or abs(game.sector.i-game.base.i) > 1 or abs(game.sector.j-game.base.j) > 1:
3513 prout(crmshp() + _(" not adjacent to base."))
3515 game.condition = "docked"
3519 if game.energy < game.inenrg:
3520 game.energy = game.inenrg
3521 game.shield = game.inshld
3522 game.torps = game.intorps
3523 game.lsupres = game.inlsr
3524 game.state.crew = FULLCREW
3525 if not damaged(DRADIO) and \
3526 ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
3527 # get attack report from base
3528 prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
3532 def cartesian(loc1=None, loc2=None):
3534 return game.quadrant * QUADSIZE + game.sector
3536 return game.quadrant * QUADSIZE + loc1
3538 return loc1 * QUADSIZE + loc2
3540 def getcourse(isprobe):
3541 "Get a course and distance from the user."
3543 dquad = copy.copy(game.quadrant)
3544 navmode = "unspecified"
3548 if game.landed and not isprobe:
3549 prout(_("Dummy! You can't leave standard orbit until you"))
3550 proutn(_("are back aboard the ship."))
3553 while navmode == "unspecified":
3554 if damaged(DNAVSYS):
3556 prout(_("Computer damaged; manual navigation only"))
3558 prout(_("Computer damaged; manual movement only"))
3563 key = scanner.next()
3565 proutn(_("Manual or automatic- "))
3568 elif key == "IHALPHA":
3569 if scanner.sees("manual"):
3571 key = scanner.next()
3573 elif scanner.sees("automatic"):
3574 navmode = "automatic"
3575 key = scanner.next()
3583 prout(_("(Manual navigation assumed.)"))
3585 prout(_("(Manual movement assumed.)"))
3589 if navmode == "automatic":
3590 while key == "IHEOL":
3592 proutn(_("Target quadrant or quadrant§or- "))
3594 proutn(_("Destination sector or quadrant§or- "))
3597 key = scanner.next()
3601 xi = int(round(scanner.real))-1
3602 key = scanner.next()
3606 xj = int(round(scanner.real))-1
3607 key = scanner.next()
3609 # both quadrant and sector specified
3610 xk = int(round(scanner.real))-1
3611 key = scanner.next()
3615 xl = int(round(scanner.real))-1
3621 # only one pair of numbers was specified
3623 # only quadrant specified -- go to center of dest quad
3626 dsect.j = dsect.i = 4 # preserves 1-origin behavior
3628 # only sector specified
3632 if not dquad.valid_quadrant() or not dsect.valid_sector():
3639 prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
3641 prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
3642 # the actual deltas get computed here
3643 delta.j = dquad.j-game.quadrant.j + (dsect.j-game.sector.j)/(QUADSIZE*1.0)
3644 delta.i = game.quadrant.i-dquad.i + (game.sector.i-dsect.i)/(QUADSIZE*1.0)
3646 while key == "IHEOL":
3647 proutn(_("X and Y displacements- "))
3650 key = scanner.next()
3655 delta.j = scanner.real
3656 key = scanner.next()
3660 delta.i = scanner.real
3661 # Check for zero movement
3662 if delta.i == 0 and delta.j == 0:
3665 if itemp == "verbose" and not isprobe:
3667 prout(_("Helmsman Sulu- \"Aye, Sir.\""))
3669 return course(bearing=delta.bearing(), distance=delta.distance())
3672 def __init__(self, bearing, distance, origin=None):
3673 self.distance = distance
3674 self.bearing = bearing
3676 self.origin = cartesian(game.quadrant, game.sector)
3678 self.origin = origin
3679 # The bearing() code we inherited from FORTRAN is actually computing
3680 # clockface directions!
3681 if self.bearing < 0.0:
3682 self.bearing += 12.0
3683 self.angle = ((15.0 - self.bearing) * 0.5235988)
3685 self.origin = cartesian(game.quadrant, game.sector)
3687 self.origin = cartesian(game.quadrant, origin)
3688 self.increment = coord(-math.sin(self.angle), math.cos(self.angle))
3689 bigger = max(abs(self.increment.i), abs(self.increment.j))
3690 self.increment /= bigger
3691 self.moves = int(round(10*self.distance*bigger))
3693 self.final = (self.location + self.moves*self.increment).roundtogrid()
3695 self.location = self.origin
3698 return self.location.roundtogrid() == self.final
3700 "Next step on course."
3702 self.nextlocation = self.location + self.increment
3703 samequad = (self.location.quadrant() == self.nextlocation.quadrant())
3704 self.location = self.nextlocation
3707 return self.location.quadrant()
3709 return self.location.sector()
3710 def power(self, warp):
3711 return self.distance*(warp**3)*(game.shldup+1)
3712 def time(self, warp):
3713 return 10.0*self.distance/warp**2
3716 "Move under impulse power."
3718 if damaged(DIMPULS):
3721 prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
3723 if game.energy > 30.0:
3725 course = getcourse(isprobe=False)
3728 power = 20.0 + 100.0*course.distance
3731 if power >= game.energy:
3732 # Insufficient power for trip
3734 prout(_("First Officer Spock- \"Captain, the impulse engines"))
3735 prout(_("require 20.0 units to engage, plus 100.0 units per"))
3736 if game.energy > 30:
3737 proutn(_("quadrant. We can go, therefore, a maximum of %d") %
3738 int(0.01 * (game.energy-20.0)-0.05))
3739 prout(_(" quadrants.\""))
3741 prout(_("quadrant. They are, therefore, useless.\""))
3744 # Make sure enough time is left for the trip
3745 game.optime = course.dist/0.095
3746 if game.optime >= game.state.remtime:
3747 prout(_("First Officer Spock- \"Captain, our speed under impulse"))
3748 prout(_("power is only 0.95 sectors per stardate. Are you sure"))
3749 proutn(_("we dare spend the time?\" "))
3752 # Activate impulse engines and pay the cost
3753 imove(course, noattack=False)
3757 power = 20.0 + 100.0*course.dist
3758 game.energy -= power
3759 game.optime = course.dist/0.095
3760 if game.energy <= 0:
3764 def warp(course, involuntary):
3765 "ove under warp drive."
3766 blooey = False; twarp = False
3767 if not involuntary: # Not WARPX entry
3769 if game.damage[DWARPEN] > 10.0:
3772 prout(_("Engineer Scott- \"The warp engines are damaged, Sir.\""))
3774 if damaged(DWARPEN) and game.warpfac > 4.0:
3777 prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
3778 prout(_(" is repaired, I can only give you warp 4.\""))
3780 # Read in course and distance
3783 course = getcourse(isprobe=False)
3786 # Make sure starship has enough energy for the trip
3787 # Note: this formula is slightly different from the C version,
3788 # and lets you skate a bit closer to the edge.
3789 if course.power(game.warpfac) >= game.energy:
3790 # Insufficient power for trip
3793 prout(_("Engineering to bridge--"))
3794 if not game.shldup or 0.5*power > game.energy:
3795 iwarp = (game.energy/(course.dist+0.05)) ** 0.333333333
3797 prout(_("We can't do it, Captain. We don't have enough energy."))
3799 proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
3802 prout(_("if you'll lower the shields."))
3806 prout(_("We haven't the energy to go that far with the shields up."))
3808 # Make sure enough time is left for the trip
3809 game.optime = course.time(game.warpfac)
3810 if game.optime >= 0.8*game.state.remtime:
3812 prout(_("First Officer Spock- \"Captain, I compute that such"))
3813 proutn(_(" a trip would require approximately %2.0f") %
3814 (100.0*game.optime/game.state.remtime))
3815 prout(_(" percent of our"))
3816 proutn(_(" remaining time. Are you sure this is wise?\" "))
3822 if game.warpfac > 6.0:
3823 # Decide if engine damage will occur
3824 # ESR: Seems wrong. Probability of damage goes *down* with distance?
3825 prob = course.distance*(6.0-game.warpfac)**2/66.666666666
3826 if prob > randreal():
3828 course.distance = randreal(course.distance)
3829 # Decide if time warp will occur
3830 if 0.5*course.distance*math.pow(7.0,game.warpfac-10.0) > randreal():
3832 if idebug and game.warpfac==10 and not twarp:
3834 proutn("=== Force time warp? ")
3838 # If time warp or engine damage, check path
3839 # If it is obstructed, don't do warp or damage
3840 for m in range(course.moves):
3843 if not w.valid_sector():
3845 if game.quad[w.i][w.j] != '.':
3849 # Activate Warp Engines and pay the cost
3850 imove(course, noattack=False)
3853 game.energy -= course.power(game.warpfac)
3854 if game.energy <= 0:
3856 game.optime = course.time(game.warpfac)
3860 game.damage[DWARPEN] = game.damfac * randreal(1.0, 4.0)
3862 prout(_("Engineering to bridge--"))
3863 prout(_(" Scott here. The warp engines are damaged."))
3864 prout(_(" We'll have to reduce speed to warp 4."))
3869 "Change the warp factor."
3875 proutn(_("Warp factor- "))
3880 if game.damage[DWARPEN] > 10.0:
3881 prout(_("Warp engines inoperative."))
3883 if damaged(DWARPEN) and scanner.real > 4.0:
3884 prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
3885 prout(_(" but right now we can only go warp 4.\""))
3887 if scanner.real > 10.0:
3888 prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
3890 if scanner.real < 1.0:
3891 prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
3893 oldfac = game.warpfac
3894 game.warpfac = scanner.real
3895 if game.warpfac <= oldfac or game.warpfac <= 6.0:
3896 prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
3899 if game.warpfac < 8.00:
3900 prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
3902 if game.warpfac == 10.0:
3903 prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
3905 prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
3909 "Cope with being tossed out of quadrant by supernova or yanked by beam."
3911 # is captain on planet?
3913 if damaged(DTRANSP):
3916 prout(_("Scotty rushes to the transporter controls."))
3918 prout(_("But with the shields up it's hopeless."))
3920 prouts(_("His desperate attempt to rescue you . . ."))
3925 prout(_("SUCCEEDS!"))
3928 proutn(_("The crystals mined were "))
3936 # Check to see if captain in shuttle craft
3941 # Inform captain of attempt to reach safety
3945 prouts(_("***RED ALERT! RED ALERT!"))
3947 proutn(_("The %s has stopped in a quadrant containing") % crmshp())
3948 prouts(_(" a supernova."))
3950 prout(_("***Emergency automatic override attempts to hurl ")+crmshp())
3951 prout(_("safely out of quadrant."))
3952 if not damaged(DRADIO):
3953 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
3954 # Try to use warp engines
3955 if damaged(DWARPEN):
3957 prout(_("Warp engines damaged."))
3960 game.warpfac = randreal(6.0, 8.0)
3961 prout(_("Warp factor set to %d") % int(game.warpfac))
3962 power = 0.75*game.energy
3963 dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
3964 dist = max(dist, randreal(math.sqrt(2)))
3965 bugout = course(bearing=randreal(12), distance=dist) # How dumb!
3966 game.optime = bugout.time(game.warpfac)
3968 game.inorbit = False
3969 warp(bugout, involuntary=True)
3971 # This is bad news, we didn't leave quadrant.
3975 prout(_("Insufficient energy to leave quadrant."))
3978 # Repeat if another snova
3979 if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
3981 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)==0:
3982 finish(FWON) # Snova killed remaining enemy.
3985 "Let's do the time warp again."
3986 prout(_("***TIME WARP ENTERED."))
3987 if game.state.snap and withprob(0.5):
3989 prout(_("You are traveling backwards in time %d stardates.") %
3990 int(game.state.date-game.snapsht.date))
3991 game.state = game.snapsht
3992 game.state.snap = False
3993 if len(game.state.kcmdr):
3994 schedule(FTBEAM, expran(game.intime/len(game.state.kcmdr)))
3995 schedule(FBATTAK, expran(0.3*game.intime))
3996 schedule(FSNOVA, expran(0.5*game.intime))
3997 # next snapshot will be sooner
3998 schedule(FSNAP, expran(0.25*game.state.remtime))
4000 if game.state.nscrem:
4001 schedule(FSCMOVE, 0.2777)
4005 game.battle.invalidate()
4006 # Make sure Galileo is consistant -- Snapshot may have been taken
4007 # when on planet, which would give us two Galileos!
4009 for l in range(game.inplan):
4010 if game.state.planets[l].known == "shuttle_down":
4012 if game.iscraft == "onship" and game.ship=='E':
4013 prout(_("Chekov- \"Security reports the Galileo has disappeared, Sir!"))
4014 game.iscraft = "offship"
4015 # Likewise, if in the original time the Galileo was abandoned, but
4016 # was on ship earlier, it would have vanished -- let's restore it.
4017 if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
4018 prout(_("Checkov- \"Security reports the Galileo has reappeared in the dock!\""))
4019 game.iscraft = "onship"
4020 # There used to be code to do the actual reconstrction here,
4021 # but the starchart is now part of the snapshotted galaxy state.
4022 prout(_("Spock has reconstructed a correct star chart from memory"))
4024 # Go forward in time
4025 game.optime = -0.5*game.intime*math.log(randreal())
4026 prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
4027 # cheat to make sure no tractor beams occur during time warp
4028 postpone(FTBEAM, game.optime)
4029 game.damage[DRADIO] += game.optime
4031 events() # Stas Sergeev added this -- do pending events
4034 "Launch deep-space probe."
4035 # New code to launch a deep space probe
4036 if game.nprobes == 0:
4039 if game.ship == 'E':
4040 prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
4042 prout(_("Ye Faerie Queene has no deep space probes."))
4047 prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
4049 if is_scheduled(FDSPROB):
4052 if damaged(DRADIO) and game.condition != "docked":
4053 prout(_("Spock- \"Records show the previous probe has not yet"))
4054 prout(_(" reached its destination.\""))
4056 prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
4058 key = scanner.next()
4060 if game.nprobes == 1:
4061 prout(_("1 probe left."))
4063 prout(_("%d probes left") % game.nprobes)
4064 proutn(_("Are you sure you want to fire a probe? "))
4067 game.isarmed = False
4068 if key == "IHALPHA" and scanner.token == "armed":
4070 key = scanner.next()
4071 elif key == "IHEOL":
4072 proutn(_("Arm NOVAMAX warhead? "))
4074 elif key == "IHREAL": # first element of course
4075 scanner.push(scanner.token)
4077 game.probe = getcourse(isprobe=True)
4081 schedule(FDSPROB, 0.01) # Time to move one sector
4082 prout(_("Ensign Chekov- \"The deep space probe is launched, Captain.\""))
4087 "Yell for help from nearest starbase."
4088 # There's more than one way to move in this game!
4090 # Test for conditions which prevent calling for help
4091 if game.condition == "docked":
4092 prout(_("Lt. Uhura- \"But Captain, we're already docked.\""))
4095 prout(_("Subspace radio damaged."))
4097 if not game.state.baseq:
4098 prout(_("Lt. Uhura- \"Captain, I'm not getting any response from Starbase.\""))
4101 prout(_("You must be aboard the %s.") % crmshp())
4103 # OK -- call for help from nearest starbase
4106 # There's one in this quadrant
4107 ddist = (game.base - game.sector).distance()
4110 for ibq in game.state.baseq:
4111 xdist = QUADSIZE * (ibq - game.quadrant).distance()
4114 # Since starbase not in quadrant, set up new quadrant
4117 # dematerialize starship
4118 game.quad[game.sector.i][game.sector.j]='.'
4119 proutn(_("Starbase in Quadrant %s responds--%s dematerializes") \
4120 % (game.quadrant, crmshp()))
4121 game.sector.invalidate()
4122 for m in range(1, 5+1):
4123 w = game.base.scatter()
4124 if w.valid_sector() and game.quad[w.i][w.j]=='.':
4125 # found one -- finish up
4128 if not game.sector.is_valid():
4129 prout(_("You have been lost in space..."))
4130 finish(FMATERIALIZE)
4132 # Give starbase three chances to rematerialize starship
4133 probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
4134 for m in range(1, 3+1):
4135 if m == 1: proutn(_("1st"))
4136 elif m == 2: proutn(_("2nd"))
4137 elif m == 3: proutn(_("3rd"))
4138 proutn(_(" attempt to re-materialize ") + crmshp())
4139 game.quad[ix][iy]=('-','o','O')[m-1]
4141 if randreal() > probf:
4144 curses.delay_output(500)
4146 game.quad[ix][iy]='?'
4149 setwnd(message_window)
4150 finish(FMATERIALIZE)
4152 game.quad[ix][iy]=game.ship
4153 prout(_("succeeds."))
4156 prout(_("Lt. Uhura- \"Captain, we made it!\""))
4161 if game.condition=="docked":
4163 prout(_("You cannot abandon Ye Faerie Queene."))
4166 # Must take shuttle craft to exit
4167 if game.damage[DSHUTTL]==-1:
4168 prout(_("Ye Faerie Queene has no shuttle craft."))
4170 if game.damage[DSHUTTL]<0:
4171 prout(_("Shuttle craft now serving Big Macs."))
4173 if game.damage[DSHUTTL]>0:
4174 prout(_("Shuttle craft damaged."))
4177 prout(_("You must be aboard the ship."))
4179 if game.iscraft != "onship":
4180 prout(_("Shuttle craft not currently available."))
4182 # Emit abandon ship messages
4184 prouts(_("***ABANDON SHIP! ABANDON SHIP!"))
4186 prouts(_("***ALL HANDS ABANDON SHIP!"))
4188 prout(_("Captain and crew escape in shuttle craft."))
4189 if not game.state.baseq:
4190 # Oops! no place to go...
4193 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
4195 if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
4196 prout(_("Remainder of ship's complement beam down"))
4197 prout(_("to nearest habitable planet."))
4198 elif q.planet != None and not damaged(DTRANSP):
4199 prout(_("Remainder of ship's complement beam down to %s.") %
4202 prout(_("Entire crew of %d left to die in outer space.") %
4204 game.casual += game.state.crew
4205 game.abandoned += game.state.crew
4206 # If at least one base left, give 'em the Faerie Queene
4208 game.icrystl = False # crystals are lost
4209 game.nprobes = 0 # No probes
4210 prout(_("You are captured by Klingons and released to"))
4211 prout(_("the Federation in a prisoner-of-war exchange."))
4212 nb = randrange(len(game.state.baseq))
4213 # Set up quadrant and position FQ adjacient to base
4214 if not game.quadrant == game.state.baseq[nb]:
4215 game.quadrant = game.state.baseq[nb]
4216 game.sector.i = game.sector.j = 5
4219 # position next to base by trial and error
4220 game.quad[game.sector.i][game.sector.j] = '.'
4221 for l in range(QUADSIZE):
4222 game.sector = game.base.scatter()
4223 if game.sector.valid_sector() and \
4224 game.quad[game.sector.i][game.sector.j] == '.':
4227 break # found a spot
4228 game.sector.i=QUADSIZE/2
4229 game.sector.j=QUADSIZE/2
4231 # Get new commission
4232 game.quad[game.sector.i][game.sector.j] = game.ship = 'F'
4233 game.state.crew = FULLCREW
4234 prout(_("Starfleet puts you in command of another ship,"))
4235 prout(_("the Faerie Queene, which is antiquated but,"))
4236 prout(_("still useable."))
4238 prout(_("The dilithium crystals have been moved."))
4240 game.iscraft = "offship" # Galileo disappears
4242 game.condition="docked"
4243 for l in range(NDEVICES):
4244 game.damage[l] = 0.0
4245 game.damage[DSHUTTL] = -1
4246 game.energy = game.inenrg = 3000.0
4247 game.shield = game.inshld = 1250.0
4248 game.torps = game.intorps = 6
4249 game.lsupres=game.inlsr=3.0
4254 # Code from planets.c begins here.
4257 "Abort a lengthy operation if an event interrupts it."
4260 if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.justin:
4265 "Report on (uninhabited) planets in the galaxy."
4269 prout(_("Spock- \"Planet report follows, Captain.\""))
4271 for i in range(game.inplan):
4272 if game.state.planets[i].pclass == "destroyed":
4274 if (game.state.planets[i].known != "unknown" \
4275 and not game.state.planets[i].inhabited) \
4278 if idebug and game.state.planets[i].known=="unknown":
4279 proutn("(Unknown) ")
4280 proutn(_("Quadrant %s") % game.state.planets[i].quadrant)
4281 proutn(_(" class "))
4282 proutn(game.state.planets[i].pclass)
4284 if game.state.planets[i].crystals != present:
4286 prout(_("dilithium crystals present."))
4287 if game.state.planets[i].known=="shuttle_down":
4288 prout(_(" Shuttle Craft Galileo on surface."))
4290 prout(_("No information available."))
4293 "Enter standard orbit."
4297 prout(_("Already in standard orbit."))
4299 if damaged(DWARPEN) and damaged(DIMPULS):
4300 prout(_("Both warp and impulse engines damaged."))
4302 if not game.plnet.is_valid():
4303 prout("There is no planet in this sector.")
4305 if abs(game.sector.i-game.plnet.i)>1 or abs(game.sector.j-game.plnet.j)>1:
4306 prout(crmshp() + _(" not adjacent to planet."))
4309 game.optime = randreal(0.02, 0.05)
4310 prout(_("Helmsman Sulu- \"Entering standard orbit, Sir.\""))
4314 game.height = randreal(1400, 8600)
4315 prout(_("Sulu- \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
4320 "Examine planets in this quadrant."
4321 if damaged(DSRSENS):
4322 if game.options & OPTION_TTY:
4323 prout(_("Short range sensors damaged."))
4325 if game.iplnet == None:
4326 if game.options & OPTION_TTY:
4327 prout(_("Spock- \"No planet in this quadrant, Captain.\""))
4329 if game.iplnet.known == "unknown":
4330 prout(_("Spock- \"Sensor scan for Quadrant %s-") % game.quadrant)
4332 prout(_(" Planet at Sector %s is of class %s.") %
4333 (game.plnet, game.iplnet.pclass))
4334 if game.iplnet.known=="shuttle_down":
4335 prout(_(" Sensors show Galileo still on surface."))
4336 proutn(_(" Readings indicate"))
4337 if game.iplnet.crystals != "present":
4339 prout(_(" dilithium crystals present.\""))
4340 if game.iplnet.known == "unknown":
4341 game.iplnet.known = "known"
4342 elif game.iplnet.inhabited:
4343 prout(_("Spock- \"The inhabited planet %s ") % game.iplnet.name)
4344 prout(_(" is located at Sector %s, Captain.\"") % game.plnet)
4347 "Use the transporter."
4351 if damaged(DTRANSP):
4352 prout(_("Transporter damaged."))
4353 if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
4355 proutn(_("Spock- \"May I suggest the shuttle craft, Sir?\" "))
4359 if not game.inorbit:
4360 prout(crmshp() + _(" not in standard orbit."))
4363 prout(_("Impossible to transport through shields."))
4365 if game.iplnet.known=="unknown":
4366 prout(_("Spock- \"Captain, we have no information on this planet"))
4367 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4368 prout(_(" you may not go down.\""))
4370 if not game.landed and game.iplnet.crystals=="absent":
4371 prout(_("Spock- \"Captain, I fail to see the logic in"))
4372 prout(_(" exploring a planet with no dilithium crystals."))
4373 proutn(_(" Are you sure this is wise?\" "))
4377 if not (game.options & OPTION_PLAIN):
4378 nrgneed = 50 * game.skill + game.height / 100.0
4379 if nrgneed > game.energy:
4380 prout(_("Engineering to bridge--"))
4381 prout(_(" Captain, we don't have enough energy for transportation."))
4383 if not game.landed and nrgneed * 2 > game.energy:
4384 prout(_("Engineering to bridge--"))
4385 prout(_(" Captain, we have enough energy only to transport you down to"))
4386 prout(_(" the planet, but there wouldn't be an energy for the trip back."))
4387 if game.iplnet.known == "shuttle_down":
4388 prout(_(" Although the Galileo shuttle craft may still be on a surface."))
4389 proutn(_(" Are you sure this is wise?\" "))
4394 # Coming from planet
4395 if game.iplnet.known=="shuttle_down":
4396 proutn(_("Spock- \"Wouldn't you rather take the Galileo?\" "))
4400 prout(_("Your crew hides the Galileo to prevent capture by aliens."))
4401 prout(_("Landing party assembled, ready to beam up."))
4403 prout(_("Kirk whips out communicator..."))
4404 prouts(_("BEEP BEEP BEEP"))
4406 prout(_("\"Kirk to enterprise- Lock on coordinates...energize.\""))
4409 prout(_("Scotty- \"Transporter room ready, Sir.\""))
4411 prout(_("Kirk and landing party prepare to beam down to planet surface."))
4413 prout(_("Kirk- \"Energize.\""))
4416 prouts("WWHOOOIIIIIRRRRREEEE.E.E. . . . . . .")
4419 prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
4421 prout(_("Scotty- \"Oh my God! I've lost them.\""))
4424 prouts(". . . . . . .E.E.EEEERRRRRIIIIIOOOHWW")
4425 game.landed = not game.landed
4426 game.energy -= nrgneed
4428 prout(_("Transport complete."))
4429 if game.landed and game.iplnet.known=="shuttle_down":
4430 prout(_("The shuttle craft Galileo is here!"))
4431 if not game.landed and game.imine:
4438 "Strip-mine a world for dilithium."
4442 prout(_("Mining party not on planet."))
4444 if game.iplnet.crystals == "mined":
4445 prout(_("This planet has already been strip-mined for dilithium."))
4447 elif game.iplnet.crystals == "absent":
4448 prout(_("No dilithium crystals on this planet."))
4451 prout(_("You've already mined enough crystals for this trip."))
4453 if game.icrystl and game.cryprob == 0.05:
4454 prout(_("With all those fresh crystals aboard the ") + crmshp())
4455 prout(_("there's no reason to mine more at this time."))
4457 game.optime = randreal(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
4460 prout(_("Mining operation complete."))
4461 game.iplnet.crystals = "mined"
4462 game.imine = game.ididit = True
4465 "Use dilithium crystals."
4469 if not game.icrystl:
4470 prout(_("No dilithium crystals available."))
4472 if game.energy >= 1000:
4473 prout(_("Spock- \"Captain, Starfleet Regulations prohibit such an operation"))
4474 prout(_(" except when Condition Yellow exists."))
4476 prout(_("Spock- \"Captain, I must warn you that loading"))
4477 prout(_(" raw dilithium crystals into the ship's power"))
4478 prout(_(" system may risk a severe explosion."))
4479 proutn(_(" Are you sure this is wise?\" "))
4484 prout(_("Engineering Officer Scott- \"(GULP) Aye Sir."))
4485 prout(_(" Mr. Spock and I will try it.\""))
4487 prout(_("Spock- \"Crystals in place, Sir."))
4488 prout(_(" Ready to activate circuit.\""))
4490 prouts(_("Scotty- \"Keep your fingers crossed, Sir!\""))
4492 if with(game.cryprob):
4493 prouts(_(" \"Activating now! - - No good! It's***"))
4495 prouts(_("***RED ALERT! RED A*L********************************"))
4498 prouts(_("****************** KA-BOOM!!!! *******************"))
4502 game.energy += randreal(5000.0, 5500.0)
4503 prouts(_(" \"Activating now! - - "))
4504 prout(_("The instruments"))
4505 prout(_(" are going crazy, but I think it's"))
4506 prout(_(" going to work!! Congratulations, Sir!\""))
4511 "Use shuttlecraft for planetary jaunt."
4514 if damaged(DSHUTTL):
4515 if game.damage[DSHUTTL] == -1.0:
4516 if game.inorbit and game.iplnet.known == "shuttle_down":
4517 prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
4519 prout(_("Ye Faerie Queene had no shuttle craft."))
4520 elif game.damage[DSHUTTL] > 0:
4521 prout(_("The Galileo is damaged."))
4522 else: # game.damage[DSHUTTL] < 0
4523 prout(_("Shuttle craft is now serving Big Macs."))
4525 if not game.inorbit:
4526 prout(crmshp() + _(" not in standard orbit."))
4528 if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
4529 prout(_("Shuttle craft not currently available."))
4531 if not game.landed and game.iplnet.known=="shuttle_down":
4532 prout(_("You will have to beam down to retrieve the shuttle craft."))
4534 if game.shldup or game.condition == "docked":
4535 prout(_("Shuttle craft cannot pass through shields."))
4537 if game.iplnet.known=="unknown":
4538 prout(_("Spock- \"Captain, we have no information on this planet"))
4539 prout(_(" and Starfleet Regulations clearly state that in this situation"))
4540 prout(_(" you may not fly down.\""))
4542 game.optime = 3.0e-5*game.height
4543 if game.optime >= 0.8*game.state.remtime:
4544 prout(_("First Officer Spock- \"Captain, I compute that such"))
4545 proutn(_(" a maneuver would require approximately %2d%% of our") % \
4546 int(100*game.optime/game.state.remtime))
4547 prout(_("remaining time."))
4548 proutn(_("Are you sure this is wise?\" "))
4554 if game.iscraft == "onship":
4556 if not damaged(DTRANSP):
4557 proutn(_("Spock- \"Would you rather use the transporter?\" "))
4561 proutn(_("Shuttle crew"))
4563 proutn(_("Rescue party"))
4564 prout(_(" boards Galileo and swoops toward planet surface."))
4565 game.iscraft = "offship"
4569 game.iplnet.known="shuttle_down"
4570 prout(_("Trip complete."))
4573 # Ready to go back to ship
4574 prout(_("You and your mining party board the"))
4575 prout(_("shuttle craft for the trip back to the Enterprise."))
4577 prouts(_("The short hop begins . . ."))
4579 game.iplnet.known="known"
4585 game.iscraft = "onship"
4591 prout(_("Trip complete."))
4594 # Kirk on ship and so is Galileo
4595 prout(_("Mining party assembles in the hangar deck,"))
4596 prout(_("ready to board the shuttle craft \"Galileo\"."))
4598 prouts(_("The hangar doors open; the trip begins."))
4601 game.iscraft = "offship"
4604 game.iplnet.known = "shuttle_down"
4607 prout(_("Trip complete."))
4611 "Use the big zapper."
4615 if game.ship != 'E':
4616 prout(_("Ye Faerie Queene has no death ray."))
4618 if len(game.enemies)==0:
4619 prout(_("Sulu- \"But Sir, there are no enemies in this quadrant.\""))
4622 prout(_("Death Ray is damaged."))
4624 prout(_("Spock- \"Captain, the 'Experimental Death Ray'"))
4625 prout(_(" is highly unpredictible. Considering the alternatives,"))
4626 proutn(_(" are you sure this is wise?\" "))
4629 prout(_("Spock- \"Acknowledged.\""))
4632 prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
4634 prout(_("Crew scrambles in emergency preparation."))
4635 prout(_("Spock and Scotty ready the death ray and"))
4636 prout(_("prepare to channel all ship's power to the device."))
4638 prout(_("Spock- \"Preparations complete, sir.\""))
4639 prout(_("Kirk- \"Engage!\""))
4641 prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
4644 if game.options & OPTION_PLAIN:
4648 prouts(_("Sulu- \"Captain! It's working!\""))
4650 while len(game.enemies) > 0:
4651 deadkl(game.enemies[1].location, game.quad[game.enemies[1].location.i][game.enemies[1].location.j],game.enemies[1].location)
4652 prout(_("Ensign Chekov- \"Congratulations, Captain!\""))
4653 if (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem) == 0:
4655 if (game.options & OPTION_PLAIN) == 0:
4656 prout(_("Spock- \"Captain, I believe the `Experimental Death Ray'"))
4658 prout(_(" is still operational.\""))
4660 prout(_(" has been rendered nonfunctional.\""))
4661 game.damage[DDRAY] = 39.95
4663 r = randreal() # Pick failure method
4665 prouts(_("Sulu- \"Captain! It's working!\""))
4667 prouts(_("***RED ALERT! RED ALERT!"))
4669 prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
4671 prouts(_("***RED ALERT! RED A*L********************************"))
4674 prouts(_("****************** KA-BOOM!!!! *******************"))
4679 prouts(_("Sulu- \"Captain! Yagabandaghangrapl, brachriigringlanbla!\""))
4681 prout(_("Lt. Uhura- \"Graaeek! Graaeek!\""))
4683 prout(_("Spock- \"Fascinating! . . . All humans aboard"))
4684 prout(_(" have apparently been transformed into strange mutations."))
4685 prout(_(" Vulcans do not seem to be affected."))
4687 prout(_("Kirk- \"Raauch! Raauch!\""))
4692 prouts(_("Sulu- \"Captain! It's --WHAT?!?!\""))
4694 proutn(_("Spock- \"I believe the word is"))
4695 prouts(_(" *ASTONISHING*"))
4696 prout(_(" Mr. Sulu."))
4697 for i in range(QUADSIZE):
4698 for j in range(QUADSIZE):
4699 if game.quad[i][j] == '.':
4700 game.quad[i][j] = '?'
4701 prout(_(" Captain, our quadrant is now infested with"))
4702 prouts(_(" - - - - - - *THINGS*."))
4704 prout(_(" I have no logical explanation.\""))
4706 prouts(_("Sulu- \"Captain! The Death Ray is creating tribbles!\""))
4708 prout(_("Scotty- \"There are so many tribbles down here"))
4709 prout(_(" in Engineering, we can't move for 'em, Captain.\""))
4713 # Code from reports.c begins here
4715 def attackreport(curt):
4716 "eport status of bases under attack."
4718 if is_scheduled(FCDBAS):
4719 prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
4720 prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
4721 elif game.isatb == 1:
4722 prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
4723 prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
4725 prout(_("No Starbase is currently under attack."))
4727 if is_scheduled(FCDBAS):
4728 proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
4730 proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
4734 # report on general game status
4736 s1 = "" and game.thawed and _("thawed ")
4737 s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
4738 s3 = (None, _("novice"). _("fair"),
4739 _("good"), _("expert"), _("emeritus"))[game.skill]
4740 prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
4741 if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
4742 prout(_("No plaque is allowed."))
4744 prout(_("This is tournament game %d.") % game.tourn)
4745 prout(_("Your secret password is \"%s\"") % game.passwd)
4746 proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - (game.state.remkl + len(game.state.kcmdr) + game.state.nscrem)),
4747 (game.inkling + game.incom + game.inscom)))
4748 if game.incom - len(game.state.kcmdr):
4749 prout(_(", including %d Commander%s.") % (game.incom - len(game.state.kcmdr), (_("s"), "")[(game.incom - len(game.state.kcmdr))==1]))
4750 elif game.inkling - game.state.remkl + (game.inscom - game.state.nscrem) > 0:
4751 prout(_(", but no Commanders."))
4754 if game.skill > SKILL_FAIR:
4755 prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
4756 if len(game.state.baseq) != game.inbase:
4758 if game.inbase-len(game.state.baseq)==1:
4759 proutn(_("has been 1 base"))
4761 proutn(_("have been %d bases") % (game.inbase-len(game.state.baseq)))
4762 prout(_(" destroyed, %d remaining.") % len(game.state.baseq))
4764 prout(_("There are %d bases.") % game.inbase)
4765 if communicating() or game.iseenit:
4766 # Don't report this if not seen and
4767 # either the radio is dead or not at base!
4771 prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
4773 prout(_("There were %d call%s for help.") % (game.nhelp, ("" , _("s"))[game.nhelp!=1]))
4774 if game.ship == 'E':
4775 proutn(_("You have "))
4777 proutn("%d" % (game.nprobes))
4780 proutn(_(" deep space probe"))
4784 if communicating() and is_scheduled(FDSPROB):
4786 proutn(_("An armed deep space probe is in "))
4788 proutn(_("A deep space probe is in "))
4789 prout("Quadrant %s." % game.probec)
4791 if game.cryprob <= .05:
4792 prout(_("Dilithium crystals aboard ship... not yet used."))
4796 while game.cryprob > ai:
4799 prout(_("Dilithium crystals have been used %d time%s.") % \
4800 (i, (_("s"), "")[i==1]))
4804 "Long-range sensor scan."
4805 if damaged(DLRSENS):
4806 # Now allow base's sensors if docked
4807 if game.condition != "docked":
4809 prout(_("LONG-RANGE SENSORS DAMAGED."))
4812 prout(_("Starbase's long-range scan"))
4814 prout(_("Long-range scan"))
4815 for x in range(game.quadrant.i-1, game.quadrant.i+2):
4818 for y in range(game.quadrant.j-1, game.quadrant.j+2):
4819 if not coord(x, y).valid_quadrant():
4823 if not damaged(DRADIO):
4824 game.state.galaxy[x][y].charted = True
4825 game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
4826 game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
4827 game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
4828 if not silent and game.state.galaxy[x][y].supernova:
4831 proutn(" %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars))
4838 for i in range(NDEVICES):
4841 prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
4842 prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
4844 prout(" %-26s\t%8.2f\t\t%8.2f" % (device[i],
4845 game.damage[i]+0.05,
4846 game.docfac*game.damage[i]+0.005))
4848 prout(_("All devices functional."))
4851 "Update the chart in the Enterprise's computer from galaxy data."
4852 game.lastchart = game.state.date
4853 for i in range(GALSIZE):
4854 for j in range(GALSIZE):
4855 if game.state.galaxy[i][j].charted:
4856 game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
4857 game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
4858 game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
4861 "Display the star chart."
4863 if (game.options & OPTION_AUTOSCAN):
4865 if not damaged(DRADIO):
4867 if game.lastchart < game.state.date and game.condition == "docked":
4868 prout(_("Spock- \"I revised the Star Chart from the starbase's records.\""))
4870 prout(_(" STAR CHART FOR THE KNOWN GALAXY"))
4871 if game.state.date > game.lastchart:
4872 prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
4873 prout(" 1 2 3 4 5 6 7 8")
4874 for i in range(GALSIZE):
4875 proutn("%d |" % (i+1))
4876 for j in range(GALSIZE):
4877 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
4881 if game.state.galaxy[i][j].supernova:
4883 elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
4885 elif game.state.galaxy[i][j].charted:
4886 show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
4890 if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
4898 def sectscan(goodScan, i, j):
4899 "Light up an individual dot in a sector."
4900 if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1):
4901 proutn("%c " % game.quad[i][j])
4906 "Emit status report lines"
4907 if not req or req == 1:
4908 prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
4909 % (game.state.date, game.state.remtime))
4910 if not req or req == 2:
4911 if game.condition != "docked":
4913 prstat(_("Condition"), _("%s, %i DAMAGES") % \
4914 (game.condition.upper(), sum(map(lambda x: x > 0, game.damage))))
4915 if not req or req == 3:
4916 prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
4917 if not req or req == 4:
4918 if damaged(DLIFSUP):
4919 if game.condition == "docked":
4920 s = _("DAMAGED, Base provides")
4922 s = _("DAMAGED, reserves=%4.2f") % game.lsupres
4925 prstat(_("Life Support"), s)
4926 if not req or req == 5:
4927 prstat(_("Warp Factor"), "%.1f" % game.warpfac)
4928 if not req or req == 6:
4930 if game.icrystl and (game.options & OPTION_SHOWME):
4931 extra = _(" (have crystals)")
4932 prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
4933 if not req or req == 7:
4934 prstat(_("Torpedoes"), "%d" % (game.torps))
4935 if not req or req == 8:
4936 if damaged(DSHIELD):
4942 data = _(" %d%% %.1f units") \
4943 % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
4944 prstat(_("Shields"), s+data)
4945 if not req or req == 9:
4946 prstat(_("Klingons Left"), "%d" \
4947 % (game.state.remkl+len(game.state.kcmdr)+game.state.nscrem))
4948 if not req or req == 10:
4949 if game.options & OPTION_WORLDS:
4950 plnet = game.state.galaxy[game.quadrant.i][game.quadrant.j].planet
4951 if plnet and plnet.inhabited:
4952 prstat(_("Major system"), plnet.name)
4954 prout(_("Sector is uninhabited"))
4955 elif not req or req == 11:
4956 attackreport(not req)
4959 "Request specified status data, a historical relic from slow TTYs."
4960 requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
4961 while scanner.next() == "IHEOL":
4962 proutn(_("Information desired? "))
4964 if scanner.token in requests:
4965 status(requests.index(scanner.token))
4967 prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
4968 prout((" date, condition, position, lsupport, warpfactor,"))
4969 prout((" energy, torpedoes, shields, klingons, system, time."))
4974 if damaged(DSRSENS):
4975 # Allow base's sensors if docked
4976 if game.condition != "docked":
4977 prout(_(" S.R. SENSORS DAMAGED!"))
4980 prout(_(" [Using Base's sensors]"))
4982 prout(_(" Short-range scan"))
4983 if goodScan and not damaged(DRADIO):
4984 game.state.chart[game.quadrant.i][game.quadrant.j].klingons = game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons
4985 game.state.chart[game.quadrant.i][game.quadrant.j].starbase = game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase
4986 game.state.chart[game.quadrant.i][game.quadrant.j].stars = game.state.galaxy[game.quadrant.i][game.quadrant.j].stars
4987 game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
4988 prout(" 1 2 3 4 5 6 7 8 9 10")
4989 if game.condition != "docked":
4991 for i in range(QUADSIZE):
4992 proutn("%2d " % (i+1))
4993 for j in range(QUADSIZE):
4994 sectscan(goodScan, i, j)
4998 "Use computer to get estimated time of arrival for a warp jump."
4999 w1 = coord(); w2 = coord()
5001 if damaged(DCOMPTR):
5002 prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
5005 if scanner.next() != "IHREAL":
5008 proutn(_("Destination quadrant and/or sector? "))
5009 if scanner.next()!="IHREAL":
5012 w1.j = int(scanner.real-0.5)
5013 if scanner.next() != "IHREAL":
5016 w1.i = int(scanner.real-0.5)
5017 if scanner.next() == "IHREAL":
5018 w2.j = int(scanner.real-0.5)
5019 if scanner.next() != "IHREAL":
5022 w2.i = int(scanner.real-0.5)
5024 if game.quadrant.j>w1.i:
5028 if game.quadrant.i>w1.j:
5032 if not w1.valid_quadrant() or not w2.valid_sector():
5035 dist = math.sqrt((w1.j-game.quadrant.j+(w2.j-game.sector.j)/(QUADSIZE*1.0))**2+
5036 (w1.i-game.quadrant.i+(w2.i-game.sector.i)/(QUADSIZE*1.0))**2)
5039 prout(_("Answer \"no\" if you don't know the value:"))
5042 proutn(_("Time or arrival date? "))
5043 if scanner.next()=="IHREAL":
5044 ttime = scanner.real
5045 if ttime > game.state.date:
5046 ttime -= game.state.date # Actually a star date
5047 twarp=(math.floor(math.sqrt((10.0*dist)/ttime)*10.0)+1.0)/10.0
5048 if ttime <= 1e-10 or twarp > 10:
5049 prout(_("We'll never make it, sir."))
5056 proutn(_("Warp factor? "))
5057 if scanner.next()== "IHREAL":
5059 twarp = scanner.real
5060 if twarp<1.0 or twarp > 10.0:
5064 prout(_("Captain, certainly you can give me one of these."))
5067 ttime = (10.0*dist)/twarp**2
5068 tpower = dist*twarp*twarp*twarp*(game.shldup+1)
5069 if tpower >= game.energy:
5070 prout(_("Insufficient energy, sir."))
5071 if not game.shldup or tpower > game.energy*2.0:
5074 proutn(_("New warp factor to try? "))
5075 if scanner.next() == "IHREAL":
5077 twarp = scanner.real
5078 if twarp<1.0 or twarp > 10.0:
5086 prout(_("But if you lower your shields,"))
5087 proutn(_("remaining"))
5090 proutn(_("Remaining"))
5091 prout(_(" energy will be %.2f.") % (game.energy-tpower))
5093 prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
5095 prout(_("Any warp speed is adequate."))
5097 prout(_("Minimum warp needed is %.2f,") % (twarp))
5098 prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
5099 if game.state.remtime < ttime:
5100 prout(_("Unfortunately, the Federation will be destroyed by then."))
5102 prout(_("You'll be taking risks at that speed, Captain"))
5103 if (game.isatb==1 and game.state.kscmdr == w1 and \
5104 scheduled(FSCDBAS)< ttime+game.state.date) or \
5105 (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
5106 prout(_("The starbase there will be destroyed by then."))
5107 proutn(_("New warp factor to try? "))
5108 if scanner.next() == "IHREAL":
5110 twarp = scanner.real
5111 if twarp<1.0 or twarp > 10.0:
5119 # Code from setup.c begins here
5122 "Issue a historically correct banner."
5124 prout(_("-SUPER- STAR TREK"))
5126 # From the FORTRAN original
5127 # prout(_("Latest update-21 Sept 78"))
5133 scanner.push("emsave.trk")
5134 key = scanner.next()
5136 proutn(_("File name: "))
5137 key = scanner.next()
5138 if key != "IHALPHA":
5142 if '.' not in scanner.token:
5143 scanner.token += ".trk"
5145 fp = open(scanner.token, "wb")
5147 prout(_("Can't freeze game as file %s") % scanner.token)
5149 cPickle.dump(game, fp)
5153 "Retrieve saved game."
5154 game.passwd[0] = '\0'
5155 key = scanner.next()
5157 proutn(_("File name: "))
5158 key = scanner.next()
5159 if key != "IHALPHA":
5163 if '.' not in scanner.token:
5164 scanner.token += ".trk"
5166 fp = open(scanner.token, "rb")
5168 prout(_("Can't thaw game in %s") % scanner.token)
5170 game = cPickle.load(fp)
5174 # I used <http://www.memory-alpha.org> to find planets
5175 # with references in ST:TOS. Eath and the Alpha Centauri
5176 # Colony have been omitted.
5178 # Some planets marked Class G and P here will be displayed as class M
5179 # because of the way planets are generated. This is a known bug.
5182 _("Andoria (Fesoan)"), # several episodes
5183 _("Tellar Prime (Miracht)"), # TOS: "Journey to Babel"
5184 _("Vulcan (T'Khasi)"), # many episodes
5185 _("Medusa"), # TOS: "Is There in Truth No Beauty?"
5186 _("Argelius II (Nelphia)"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5187 _("Ardana"), # TOS: "The Cloud Minders"
5188 _("Catulla (Cendo-Prae)"), # TOS: "The Way to Eden"
5189 _("Gideon"), # TOS: "The Mark of Gideon"
5190 _("Aldebaran III"), # TOS: "The Deadly Years"
5191 _("Alpha Majoris I"), # TOS: "Wolf in the Fold"
5192 _("Altair IV"), # TOS: "Amok Time
5193 _("Ariannus"), # TOS: "Let That Be Your Last Battlefield"
5194 _("Benecia"), # TOS: "The Conscience of the King"
5195 _("Beta Niobe I (Sarpeidon)"), # TOS: "All Our Yesterdays"
5196 _("Alpha Carinae II"), # TOS: "The Ultimate Computer"
5197 _("Capella IV (Kohath)"), # TOS: "Friday's Child" (Class G)
5198 _("Daran V"), # TOS: "For the World is Hollow and I Have Touched the Sky"
5199 _("Deneb II"), # TOS: "Wolf in the Fold" ("IV" in BSD)
5200 _("Eminiar VII"), # TOS: "A Taste of Armageddon"
5201 _("Gamma Canaris IV"), # TOS: "Metamorphosis"
5202 _("Gamma Tranguli VI (Vaalel)"), # TOS: "The Apple"
5203 _("Ingraham B"), # TOS: "Operation: Annihilate"
5204 _("Janus IV"), # TOS: "The Devil in the Dark"
5205 _("Makus III"), # TOS: "The Galileo Seven"
5206 _("Marcos XII"), # TOS: "And the Children Shall Lead",
5207 _("Omega IV"), # TOS: "The Omega Glory"
5208 _("Regulus V"), # TOS: "Amok Time
5209 _("Deneva"), # TOS: "Operation -- Annihilate!"
5210 # Worlds from BSD Trek
5211 _("Rigel II"), # TOS: "Shore Leave" ("III" in BSD)
5212 _("Beta III"), # TOS: "The Return of the Archons"
5213 _("Triacus"), # TOS: "And the Children Shall Lead",
5214 _("Exo III"), # TOS: "What Are Little Girls Made Of?" (Class P)
5216 # _("Hansen's Planet"), # TOS: "The Galileo Seven"
5217 # _("Taurus IV"), # TOS: "The Galileo Seven" (class G)
5218 # _("Antos IV (Doraphane)"), # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
5219 # _("Izar"), # TOS: "Whom Gods Destroy"
5220 # _("Tiburon"), # TOS: "The Way to Eden"
5221 # _("Merak II"), # TOS: "The Cloud Minders"
5222 # _("Coridan (Desotriana)"), # TOS: "Journey to Babel"
5223 # _("Iotia"), # TOS: "A Piece of the Action"
5227 _("S. R. Sensors"), \
5228 _("L. R. Sensors"), \
5230 _("Photon Tubes"), \
5231 _("Life Support"), \
5232 _("Warp Engines"), \
5233 _("Impulse Engines"), \
5235 _("Subspace Radio"), \
5236 _("Shuttle Craft"), \
5238 _("Navigation System"), \
5240 _("Shield Control"), \
5246 "Prepare to play, set up cosmos."
5248 # Decide how many of everything
5250 return # frozen game
5251 # Prepare the Enterprise
5252 game.alldone = game.gamewon = game.shldchg = game.shldup = False
5254 game.state.crew = FULLCREW
5255 game.energy = game.inenrg = 5000.0
5256 game.shield = game.inshld = 2500.0
5259 game.quadrant = randplace(GALSIZE)
5260 game.sector = randplace(QUADSIZE)
5261 game.torps = game.intorps = 10
5262 game.nprobes = randrange(2, 5)
5264 for i in range(NDEVICES):
5265 game.damage[i] = 0.0
5266 # Set up assorted game parameters
5267 game.battle = coord()
5268 game.state.date = game.indate = 100.0 * randreal(20, 51)
5269 game.nkinks = game.nhelp = game.casual = game.abandoned = 0
5270 game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
5271 game.isatb = game.state.nplankl = 0
5272 game.state.starkl = game.state.basekl = 0
5273 game.iscraft = "onship"
5277 # Starchart is functional but we've never seen it
5278 game.lastchart = FOREVER
5279 # Put stars in the galaxy
5281 for i in range(GALSIZE):
5282 for j in range(GALSIZE):
5283 k = randrange(1, QUADSIZE**2/10+1)
5285 game.state.galaxy[i][j].stars = k
5286 # Locate star bases in galaxy
5287 for i in range(game.inbase):
5290 w = randplace(GALSIZE)
5291 if not game.state.galaxy[w.i][w.j].starbase:
5294 # C version: for (j = i-1; j > 0; j--)
5295 # so it did them in the opposite order.
5296 for j in range(1, i):
5297 # Improved placement algorithm to spread out bases
5298 distq = (w - game.state.baseq[j]).distance()
5299 if distq < 6.0*(BASEMAX+1-game.inbase) and withprob(0.75):
5302 prout("=== Abandoning base #%d at %s" % (i, w))
5304 elif distq < 6.0 * (BASEMAX+1-game.inbase):
5306 prout("=== Saving base #%d, close to #%d" % (i, j))
5309 game.state.baseq.append(w)
5310 game.state.galaxy[w.i][w.j].starbase = game.state.chart[w.i][w.j].starbase = True
5311 # Position ordinary Klingon Battle Cruisers
5313 klumper = 0.25*game.skill*(9.0-game.length)+1.0
5314 if klumper > MAXKLQUAD:
5318 klump = (1.0 - r*r)*klumper
5323 w = randplace(GALSIZE)
5324 if not game.state.galaxy[w.i][w.j].supernova and \
5325 game.state.galaxy[w.i][w.j].klingons + klump <= MAXKLQUAD:
5327 game.state.galaxy[w.i][w.j].klingons += int(klump)
5330 # Position Klingon Commander Ships
5331 for i in range(game.incom):
5333 w = randplace(GALSIZE)
5334 if not welcoming(w) or w in game.state.kcmdr:
5336 if (game.state.galaxy[w.i][w.j].klingons or withprob(0.25)):
5338 game.state.galaxy[w.i][w.j].klingons += 1
5339 game.state.kcmdr.append(w)
5340 # Locate planets in galaxy
5341 for i in range(game.inplan):
5343 w = randplace(GALSIZE)
5344 if game.state.galaxy[w.i][w.j].planet == None:
5348 new.crystals = "absent"
5349 if (game.options & OPTION_WORLDS) and i < NINHAB:
5350 new.pclass = "M" # All inhabited planets are class M
5351 new.crystals = "absent"
5353 new.name = systnames[i]
5354 new.inhabited = True
5356 new.pclass = ("M", "N", "O")[randrange(0, 3)]
5358 new.crystals = "present"
5359 new.known = "unknown"
5360 new.inhabited = False
5361 game.state.galaxy[w.i][w.j].planet = new
5362 game.state.planets.append(new)
5364 for i in range(game.state.nromrem):
5365 w = randplace(GALSIZE)
5366 game.state.galaxy[w.i][w.j].romulans += 1
5367 # Place the Super-Commander if needed
5368 if game.state.nscrem > 0:
5370 w = randplace(GALSIZE)
5373 game.state.kscmdr = w
5374 game.state.galaxy[w.i][w.j].klingons += 1
5375 # Initialize times for extraneous events
5376 schedule(FSNOVA, expran(0.5 * game.intime))
5377 schedule(FTBEAM, expran(1.5 * (game.intime / len(game.state.kcmdr))))
5378 schedule(FSNAP, randreal(1.0, 2.0)) # Force an early snapshot
5379 schedule(FBATTAK, expran(0.3*game.intime))
5381 if game.state.nscrem:
5382 schedule(FSCMOVE, 0.2777)
5387 if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
5388 schedule(FDISTR, expran(1.0 + game.intime))
5393 # Place thing (in tournament game, we don't want one!)
5394 # New in SST2K: never place the Thing near a starbase.
5395 # This makes sense and avoids a special case in the old code.
5397 if game.tourn is None:
5399 thing = randplace(GALSIZE)
5400 if thing not in game.state.baseq:
5403 game.state.snap = False
5404 if game.skill == SKILL_NOVICE:
5405 prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
5406 prout(_("a deadly Klingon invasion force. As captain of the United"))
5407 prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
5408 prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
5409 prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
5410 prout(_("your mission. As you proceed you may be given more time."))
5412 prout(_("You will have %d supporting starbases.") % (game.inbase))
5413 proutn(_("Starbase locations- "))
5415 prout(_("Stardate %d.") % int(game.state.date))
5417 prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
5418 prout(_("An unknown number of Romulans."))
5419 if game.state.nscrem:
5420 prout(_("And one (GULP) Super-Commander."))
5421 prout(_("%d stardates.") % int(game.intime))
5422 proutn(_("%d starbases in ") % game.inbase)
5423 for i in range(game.inbase):
5424 proutn(`game.state.baseq[i]`)
5427 proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
5428 proutn(_(" Sector %s") % game.sector)
5430 prout(_("Good Luck!"))
5431 if game.state.nscrem:
5432 prout(_(" YOU'LL NEED IT."))
5435 if len(game.enemies) - (thing == game.quadrant) - (game.tholian != None):
5437 if game.neutz: # bad luck to start in a Romulan Neutral Zone
5438 attack(torps_ok=False)
5441 "Choose your game type."
5446 game.skill = SKILL_NONE
5448 if not scanner.inqueue: # Can start with command line options
5449 proutn(_("Would you like a regular, tournament, or saved game? "))
5451 if scanner.sees("tournament"):
5452 while scanner.next() == "IHEOL":
5453 proutn(_("Type in tournament number-"))
5454 if scanner.real == 0:
5456 continue # We don't want a blank entry
5457 game.tourn = int(round(scanner.real))
5458 random.seed(scanner.real)
5460 logfp.write("# random.seed(%d)\n" % scanner.real)
5462 if scanner.sees("saved") or scanner.sees("frozen"):
5466 if game.passwd == None:
5468 if not game.alldone:
5469 game.thawed = True # No plaque if not finished
5473 if scanner.sees("regular"):
5475 proutn(_("What is \"%s\"?") % scanner.token)
5477 while game.length==0 or game.skill==SKILL_NONE:
5478 if scanner.next() == "IHALPHA":
5479 if scanner.sees("short"):
5481 elif scanner.sees("medium"):
5483 elif scanner.sees("long"):
5485 elif scanner.sees("novice"):
5486 game.skill = SKILL_NOVICE
5487 elif scanner.sees("fair"):
5488 game.skill = SKILL_FAIR
5489 elif scanner.sees("good"):
5490 game.skill = SKILL_GOOD
5491 elif scanner.sees("expert"):
5492 game.skill = SKILL_EXPERT
5493 elif scanner.sees("emeritus"):
5494 game.skill = SKILL_EMERITUS
5496 proutn(_("What is \""))
5497 proutn(scanner.token)
5502 proutn(_("Would you like a Short, Medium, or Long game? "))
5503 elif game.skill == SKILL_NONE:
5504 proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
5505 # Choose game options -- added by ESR for SST2K
5506 if scanner.next() != "IHALPHA":
5508 proutn(_("Choose your game style (or just press enter): "))
5510 if scanner.sees("plain"):
5511 # Approximates the UT FORTRAN version.
5512 game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5513 game.options |= OPTION_PLAIN
5514 elif scanner.sees("almy"):
5515 # Approximates Tom Almy's version.
5516 game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS)
5517 game.options |= OPTION_ALMY
5518 elif scanner.sees("fancy") or scanner.sees("\n"):
5520 elif len(scanner.token):
5521 proutn(_("What is \"%s\"?") % scanner.token)
5523 if game.passwd == "debug":
5525 prout("=== Debug mode enabled.")
5526 # Use parameters to generate initial values of things
5527 game.damfac = 0.5 * game.skill
5528 game.inbase = randrange(BASEMIN, BASEMAX+1)
5530 if game.options & OPTION_PLANETS:
5531 game.inplan += randrange(MAXUNINHAB/2, MAXUNINHAB+1)
5532 if game.options & OPTION_WORLDS:
5533 game.inplan += int(NINHAB)
5534 game.state.nromrem = game.inrom = randrange(2 *game.skill)
5535 game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
5536 game.state.remtime = 7.0 * game.length
5537 game.intime = game.state.remtime
5538 game.state.remkl = game.inkling = 2.0*game.intime*((game.skill+1 - 2*randreal())*game.skill*0.1+.15)
5539 game.incom = min(MINCMDR, int(game.skill + 0.0625*game.inkling*randreal()))
5540 game.state.remres = (game.inkling+4*game.incom)*game.intime
5541 game.inresor = game.state.remres
5542 if game.inkling > 50:
5543 game.state.inbase += 1
5546 def dropin(iquad=None):
5547 "Drop a feature on a random dot in the current quadrant."
5549 w = randplace(QUADSIZE)
5550 if game.quad[w.i][w.j] == '.':
5552 if iquad is not None:
5553 game.quad[w.i][w.j] = iquad
5557 "Update our alert status."
5558 game.condition = "green"
5559 if game.energy < 1000.0:
5560 game.condition = "yellow"
5561 if game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons or game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans:
5562 game.condition = "red"
5564 game.condition="dead"
5567 "Drop new Klingon into current quadrant."
5568 return enemy('K', loc=dropin(), power=randreal(300,450)+25.0*game.skill)
5571 "Set up a new state of quadrant, for when we enter or re-enter it."
5574 game.neutz = game.inorbit = game.landed = False
5575 game.ientesc = game.iseenit = False
5576 # Create a blank quadrant
5577 game.quad = fill2d(QUADSIZE, lambda i, j: '.')
5579 # Attempt to escape Super-commander, so tbeam back!
5582 q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
5583 # cope with supernova
5586 game.klhere = q.klingons
5587 game.irhere = q.romulans
5589 game.quad[game.sector.i][game.sector.j] = game.ship
5592 # Position ordinary Klingons
5593 for i in range(game.klhere):
5595 # If we need a commander, promote a Klingon
5596 for cmdr in game.state.kcmdr:
5597 if cmdr == game.quadrant:
5598 e = game.enemies[game.klhere-1]
5599 game.quad[e.location.i][e.location.j] = 'C'
5600 e.power = randreal(950,1350) + 50.0*game.skill
5602 # If we need a super-commander, promote a Klingon
5603 if game.quadrant == game.state.kscmdr:
5605 game.quad[e.location.i][e.location.j] = 'S'
5606 e.power = randreal(1175.0, 1575.0) + 125.0*game.skill
5607 game.iscate = (game.state.remkl > 1)
5608 # Put in Romulans if needed
5609 for i in range(q.romulans):
5610 enemy('R', loc=dropin(), power=randreal(400.0,850.0)+50.0*game.skill)
5611 # If quadrant needs a starbase, put it in
5613 game.base = dropin('B')
5614 # If quadrant needs a planet, put it in
5616 game.iplnet = q.planet
5617 if not q.planet.inhabited:
5618 game.plnet = dropin('P')
5620 game.plnet = dropin('@')
5621 # Check for condition
5624 if game.irhere > 0 and game.klhere == 0:
5626 if not damaged(DRADIO):
5628 prout(_("LT. Uhura- \"Captain, an urgent message."))
5629 prout(_(" I'll put it on audio.\" CLICK"))
5631 prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
5632 prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
5633 # Put in THING if needed
5634 if thing == game.quadrant:
5635 enemy(type='?', loc=dropin(),
5636 power=randreal(6000,6500.0)+250.0*game.skill)
5637 if not damaged(DSRSENS):
5639 prout(_("Mr. Spock- \"Captain, this is most unusual."))
5640 prout(_(" Please examine your short-range scan.\""))
5641 # Decide if quadrant needs a Tholian; lighten up if skill is low
5642 if game.options & OPTION_THOLIAN:
5643 if (game.skill < SKILL_GOOD and withprob(0.02)) or \
5644 (game.skill == SKILL_GOOD and withprob(0.05)) or \
5645 (game.skill > SKILL_GOOD and withprob(0.08)):
5648 w.i = withprob(0.5) * (QUADSIZE-1)
5649 w.j = withprob(0.5) * (QUADSIZE-1)
5650 if game.quad[w.i][w.j] == '.':
5652 game.tholian = enemy(type='T', loc=w,
5653 power=randrange(100, 500) + 25.0*game.skill)
5654 # Reserve unoccupied corners
5655 if game.quad[0][0]=='.':
5656 game.quad[0][0] = 'X'
5657 if game.quad[0][QUADSIZE-1]=='.':
5658 game.quad[0][QUADSIZE-1] = 'X'
5659 if game.quad[QUADSIZE-1][0]=='.':
5660 game.quad[QUADSIZE-1][0] = 'X'
5661 if game.quad[QUADSIZE-1][QUADSIZE-1]=='.':
5662 game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
5663 game.enemies.sort(lambda x, y: cmp(x.kdist, y.kdist))
5664 # And finally the stars
5665 for i in range(q.stars):
5667 # Put in a few black holes
5668 for i in range(1, 3+1):
5671 # Take out X's in corners if Tholian present
5673 if game.quad[0][0]=='X':
5674 game.quad[0][0] = '.'
5675 if game.quad[0][QUADSIZE-1]=='X':
5676 game.quad[0][QUADSIZE-1] = '.'
5677 if game.quad[QUADSIZE-1][0]=='X':
5678 game.quad[QUADSIZE-1][0] = '.'
5679 if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
5680 game.quad[QUADSIZE-1][QUADSIZE-1] = '.'
5683 "Set the self-destruct password."
5684 if game.options & OPTION_PLAIN:
5687 proutn(_("Please type in a secret password- "))
5689 game.passwd = scanner.token
5690 if game.passwd != None:
5695 game.passwd += chr(ord('a')+randrange(26))
5697 # Code from sst.c begins here
5700 "SRSCAN": OPTION_TTY,
5701 "STATUS": OPTION_TTY,
5702 "REQUEST": OPTION_TTY,
5703 "LRSCAN": OPTION_TTY,
5716 "SENSORS": OPTION_PLANETS,
5717 "ORBIT": OPTION_PLANETS,
5718 "TRANSPORT": OPTION_PLANETS,
5719 "MINE": OPTION_PLANETS,
5720 "CRYSTALS": OPTION_PLANETS,
5721 "SHUTTLE": OPTION_PLANETS,
5722 "PLANETS": OPTION_PLANETS,
5727 "PROBE": OPTION_PROBE,
5729 "FREEZE": 0, # Synonym for SAVE
5735 "SOS": 0, # Synonym for MAYDAY
5736 "CALL": 0, # Synonym for MAYDAY
5742 "Generate a list of legal commands."
5743 prout(_("LEGAL COMMANDS ARE:"))
5745 for key in commands:
5746 if not commands[key] or (commands[key] & game.options):
5747 proutn("%-12s " % key)
5749 if emitted % 5 == 4:
5754 "Browse on-line help."
5755 key = scanner.next()
5758 setwnd(prompt_window)
5759 proutn(_("Help on what command? "))
5760 key = scanner.next()
5761 setwnd(message_window)
5764 if scanner.token in commands or scanner.token == "ABBREV":
5771 cmd = scanner.token.upper()
5773 fp = open(SSTDOC, "r")
5776 fp = open(DOC_NAME, "r")
5778 prout(_("Spock- \"Captain, that information is missing from the"))
5779 proutn(_(" computer. You need to find "))
5781 prout(_(" and put it in the"))
5782 proutn(_(" current directory or to "))
5785 # This used to continue: "You need to find SST.DOC and put
5786 # it in the current directory."
5789 linebuf = fp.readline()
5791 prout(_("Spock- \"Captain, there is no information on that command.\""))
5794 if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
5795 linebuf = linebuf[3:].strip()
5799 prout(_("Spock- \"Captain, I've found the following information:\""))
5801 while linebuf in fp:
5802 if "******" in linebuf:
5808 "Command-interpretation loop."
5810 setwnd(message_window)
5811 while True: # command loop
5813 while True: # get a command
5818 setwnd(prompt_window)
5821 if scanner.next() == "IHEOL":
5822 if game.options & OPTION_CURSES:
5825 elif scanner.token == "":
5829 setwnd(message_window)
5831 candidates = filter(lambda x: x.startswith(scanner.token.upper()),
5833 if len(candidates) == 1:
5836 elif candidates and not (game.options & OPTION_PLAIN):
5837 prout("Commands with prefix '%s': %s" % (scanner.token, " ".join(candidates)))
5841 if cmd == "SRSCAN": # srscan
5843 elif cmd == "STATUS": # status
5845 elif cmd == "REQUEST": # status request
5847 elif cmd == "LRSCAN": # long range scan
5848 lrscan(silent=False)
5849 elif cmd == "PHASERS": # phasers
5853 elif cmd == "TORPEDO": # photon torpedos
5857 elif cmd == "MOVE": # move under warp
5858 warp(course=None, involuntary=False)
5859 elif cmd == "SHIELDS": # shields
5860 doshield(shraise=False)
5863 game.shldchg = False
5864 elif cmd == "DOCK": # dock at starbase
5867 attack(torps_ok=False)
5868 elif cmd == "DAMAGES": # damage reports
5870 elif cmd == "CHART": # chart
5872 elif cmd == "IMPULSE": # impulse
5874 elif cmd == "REST": # rest
5878 elif cmd == "WARP": # warp
5880 elif cmd == "SCORE": # score
5882 elif cmd == "SENSORS": # sensors
5884 elif cmd == "ORBIT": # orbit
5888 elif cmd == "TRANSPORT": # transport "beam"
5890 elif cmd == "MINE": # mine
5894 elif cmd == "CRYSTALS": # crystals
5898 elif cmd == "SHUTTLE": # shuttle
5902 elif cmd == "PLANETS": # Planet list
5904 elif cmd == "REPORT": # Game Report
5906 elif cmd == "COMPUTER": # use COMPUTER!
5908 elif cmd == "COMMANDS":
5910 elif cmd == "EMEXIT": # Emergency exit
5911 clrscr() # Hide screen
5912 freeze(True) # forced save
5913 raise SysExit,1 # And quick exit
5914 elif cmd == "PROBE":
5915 probe() # Launch probe
5918 elif cmd == "ABANDON": # Abandon Ship
5920 elif cmd == "DESTRUCT": # Self Destruct
5922 elif cmd == "SAVE": # Save Game
5925 if game.skill > SKILL_GOOD:
5926 prout(_("WARNING--Saved games produce no plaques!"))
5927 elif cmd == "DEATHRAY": # Try a desparation measure
5931 elif cmd == "DEBUGCMD": # What do we want for debug???
5933 elif cmd == "MAYDAY": # Call for help
5938 game.alldone = True # quit the game
5943 break # Game has ended
5944 if game.optime != 0.0:
5947 break # Events did us in
5948 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
5951 if hitme and not game.justin:
5952 attack(torps_ok=True)
5955 if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
5966 "Emit the name of an enemy or feature."
5967 if type == 'R': s = _("Romulan")
5968 elif type == 'K': s = _("Klingon")
5969 elif type == 'C': s = _("Commander")
5970 elif type == 'S': s = _("Super-commander")
5971 elif type == '*': s = _("Star")
5972 elif type == 'P': s = _("Planet")
5973 elif type == 'B': s = _("Starbase")
5974 elif type == ' ': s = _("Black hole")
5975 elif type == 'T': s = _("Tholian")
5976 elif type == '#': s = _("Tholian web")
5977 elif type == '?': s = _("Stranger")
5978 elif type == '@': s = _("Inhabited World")
5979 else: s = "Unknown??"
5982 def crmena(stars, enemy, loctype, w):
5983 "Emit the name of an enemy and his location."
5987 buf += cramen(enemy) + _(" at ")
5988 if loctype == "quadrant":
5989 buf += _("Quadrant ")
5990 elif loctype == "sector":
5995 "Emit our ship name."
5996 return{'E':_("Enterprise"),'F':_("Faerie Queene")}.get(game.ship,"Ship???")
5999 "Emit a line of stars"
6000 prouts("******************************************************")
6004 return -avrage*math.log(1e-7 + randreal())
6006 def randplace(size):
6007 "Choose a random location."
6009 w.i = randrange(size)
6010 w.j = randrange(size)
6020 # Get a token from the user
6023 # Fill the token quue if nothing here
6024 while not self.inqueue:
6026 if curwnd==prompt_window:
6028 setwnd(message_window)
6035 self.inqueue = line.lstrip().split() + ["\n"]
6036 # From here on in it's all looking at the queue
6037 self.token = self.inqueue.pop(0)
6038 if self.token == "\n":
6042 self.real = float(self.token)
6043 self.type = "IHREAL"
6048 self.token = self.token.lower()
6049 self.type = "IHALPHA"
6052 def append(self, tok):
6053 self.inqueue.append(tok)
6054 def push(self, tok):
6055 self.inqueue.insert(0, tok)
6059 # Demand input for next scan
6061 self.real = self.token = None
6063 # compares s to item and returns true if it matches to the length of s
6064 return s.startswith(self.token)
6066 # Round token value to nearest integer
6067 return int(round(scanner.real))
6071 if scanner.type != "IHREAL":
6074 s.i = scanner.int()-1
6076 if scanner.type != "IHREAL":
6079 s.j = scanner.int()-1
6082 return "<sstcanner: token=%s, type=%s, queue=%s>" % (scanner.token, scanner.type, scanner.inqueue)
6085 "Yes-or-no confirmation."
6089 if scanner.token == 'y':
6091 if scanner.token == 'n':
6094 proutn(_("Please answer with \"y\" or \"n\": "))
6097 "Complain about unparseable input."
6100 prout(_("Beg your pardon, Captain?"))
6103 "Access to the internals for debugging."
6104 proutn("Reset levels? ")
6106 if game.energy < game.inenrg:
6107 game.energy = game.inenrg
6108 game.shield = game.inshld
6109 game.torps = game.intorps
6110 game.lsupres = game.inlsr
6111 proutn("Reset damage? ")
6113 for i in range(NDEVICES):
6114 if game.damage[i] > 0.0:
6115 game.damage[i] = 0.0
6116 proutn("Toggle debug flag? ")
6120 prout("Debug output ON")
6122 prout("Debug output OFF")
6123 proutn("Cause selective damage? ")
6125 for i in range(NDEVICES):
6126 proutn("Kill %s?" % device[i])
6128 key = scanner.next()
6129 if key == "IHALPHA" and scanner.sees("y"):
6130 game.damage[i] = 10.0
6131 proutn("Examine/change events? ")
6136 FSNOVA: "Supernova ",
6139 FBATTAK: "Base Attack ",
6140 FCDBAS: "Base Destroy ",
6141 FSCMOVE: "SC Move ",
6142 FSCDBAS: "SC Base Destroy ",
6143 FDSPROB: "Probe Move ",
6144 FDISTR: "Distress Call ",
6145 FENSLV: "Enslavement ",
6146 FREPRO: "Klingon Build ",
6148 for i in range(1, NEVENTS):
6151 proutn("%.2f" % (scheduled(i)-game.state.date))
6152 if i == FENSLV or i == FREPRO:
6154 proutn(" in %s" % ev.quadrant)
6159 key = scanner.next()
6163 elif key == "IHREAL":
6164 ev = schedule(i, scanner.real)
6165 if i == FENSLV or i == FREPRO:
6167 proutn("In quadrant- ")
6168 key = scanner.next()
6169 # "IHEOL" says to leave coordinates as they are
6172 prout("Event %d canceled, no x coordinate." % (i))
6175 w.i = int(round(scanner.real))
6176 key = scanner.next()
6178 prout("Event %d canceled, no y coordinate." % (i))
6181 w.j = int(round(scanner.real))
6184 proutn("Induce supernova here? ")
6186 game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova = True
6189 if __name__ == '__main__':
6190 import getopt, socket
6192 global line, thing, game, idebug
6198 game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
6199 if os.getenv("TERM"):
6200 game.options |= OPTION_CURSES
6202 game.options |= OPTION_TTY
6203 seed = int(time.time())
6204 (options, arguments) = getopt.getopt(sys.argv[1:], "r:s:tx")
6205 for (switch, val) in options:
6208 replayfp = open(val, "r")
6210 sys.stderr.write("sst: can't open replay file %s\n" % val)
6213 line = replayfp.readline().strip()
6214 (leader, key, seed) = line.split()
6216 sys.stderr.write("sst2k: seed set to %s\n" % seed)
6217 line = replayfp.readline().strip()
6218 arguments += line.split()[2:]
6220 sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
6222 game.options |= OPTION_TTY
6223 game.options &=~ OPTION_CURSES
6224 elif switch == '-s':
6226 elif switch == '-t':
6227 game.options |= OPTION_TTY
6228 game.options &=~ OPTION_CURSES
6229 elif switch == '-x':
6232 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
6234 # where to save the input in case of bugs
6236 logfp = open("/usr/tmp/sst-input.log", "w")
6238 sys.stderr.write("sst: warning, can't open logfile\n")
6240 logfp.write("# seed %s\n" % seed)
6241 logfp.write("# options %s\n" % " ".join(arguments))
6242 logfp.write("# recorded by %s@%s on %s\n" % \
6243 (os.getenv("LOGNAME"),socket.gethostname(),time.ctime()))
6245 scanner = sstscanner()
6246 map(scanner.append, arguments)
6249 while True: # Play a game
6250 setwnd(fullscreen_window)
6256 game.alldone = False
6262 if game.tourn and game.alldone:
6263 proutn(_("Do you want your score recorded?"))
6269 proutn(_("Do you want to play again? "))
6273 prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
6277 except KeyboardInterrupt: