#!/usr/bin/env python3 # Extracted from HP tape image 16-Nov-2003 by Pete Turnbull # # **** HP BASIC PROGRAM LIBRARY ****************************** # # STTR1: STAR TREK # # 36243 REV B -- 10/73 # # **** CONTRIBUTED PROGRAM *********************************** # ***************************************************************** # *** *** # *** STAR TREK: BY MIKE MAYFIELD, CENTERLINE ENGINEERING *** # *** *** # *** TOTAL INTERACTION GAME - ORIG. 20 OCT 1972 # *** *** # ***************************************************************** # # Python conversion of the HP 2000 Time-Shared BASIC original. # Line numbers in the comments refer to the BASIC listing. # # BASIC name -> Python name # A command C$ condition K9 klingonsLeft # B3 quadBases C[] courseTable[] K7 klingonsAtStart # B9 basesLeft D[] damage[] P torpedoes # E energy G[] galaxy[][] Q1,Q2 quadRow, quadCol # E0 maxEnergy Z[] galaxyMemory[][] S shields # K3 quadKlingons K[] klingon[][] S1,S2 sectRow, sectCol # S3 quadStars S9 klingonShield T stardate # T0 startDate T9 daysAllowed T7 startClock # Q$,R$,S$ (72+72+48 characters) -> sector[row][col], one 3-char cell each # # Arrays are 1-based like the BASIC; element 0 is unused. import math import random import time from decimal import Context, Decimal, ROUND_HALF_UP blank = " " # an empty sector: three blanks maxNumber = 1.70141E+38 # largest number HP BASIC can hold sixDigits = Context(prec=6, rounding=ROUND_HALF_UP) class GameOver(Exception): """Raised where the BASIC jumped to its end-of-game code (GOTO 230).""" # ------------------------------------------------------------ game state galaxy = galaxyMemory = klingon = sector = None damage = [0]*9 stardate = startDate = daysAllowed = startClock = 0 energy = maxEnergy = torpedoes = shields = klingonShield = 0 quadRow = quadCol = sectRow = sectCol = 0 quadKlingons = quadBases = quadStars = 0 klingonsLeft = klingonsAtStart = basesLeft = 0 condition = "" # course 1 is due "right" (column +1); each entry is (row step, column step) courseTable = [None, (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (0, 1)] # lines 460-480: D$ and E$ held these as 12-character slices deviceNames = [None, "WARP ENGINES", "S.R. SENSORS", "L.R. SENSORS", "PHASER CNTRL", "PHOTON TUBES", "DAMAGE CNTRL", "SHIELD CNTRL", "COMPUTER"] # ------------------------------------------------ BASIC output and input def num(x): """PRINT of a number: sign or space, digits, trailing space. Integers to 32767 print plain; larger whole numbers end in a period; other reals get 6 significant digits, trailing zeros dropped and no leading zero; beyond 1E6 or below 1E-6 it is d.dddddE+dd.""" a = abs(x) if a == 0: body = "0" elif a >= 999999.5 or a < .000001: body = "%.5E" % a elif a == math.floor(a): body = str(int(a)) + ("." if a > 32767 else "") else: body = format(sixDigits.plus(Decimal(a)), "f") body = body.rstrip("0") if "." in body else body + "." if body.startswith("0."): body = body[1:] return ("-" if x < 0 else " ") + body + " " def d(x, width=1): """PRINT USING field nD: rounded to a whole number, blank filled, a minus sign takes one digit position, overflow shows as asterisks.""" n = math.floor(abs(x) + .5) text = str(-n if x < 0 and n else n) return text.rjust(width) if len(text) <= width else "*"*width def divide(p, q): """HP BASIC gives the closest representable number on divide by zero.""" if q == 0: return maxNumber if p >= 0 else -maxNumber return p/q def getNumbers(count, text=""): """INPUT of count numbers; 'text' is what the BASIC had just PRINTed. HP prompts with "? " ("?? " for more input, "??? " if unreadable). The ??, ???, and EXTRA INPUT are prompts that the HP 2000C would have printed for the original STTR1. They do not show up in the original code because they are an HP BASIC effect is reproduced here for authenticity. """ values = [] prompt = text + "? " while len(values) < count: line = input(prompt) try: fields = [float(f) for f in line.split(",")] if line.strip() else [] if not all(math.isfinite(f) for f in fields): raise ValueError except ValueError: values, prompt = [], "??? " continue values += fields prompt = "?? " if len(values) > count: print("EXTRA INPUT-WARNING ONLY") return values[:count] def getChoice(text=""): """INPUT of one number where empty or unreadable input is not re-asked: returns the rounded number, or None.""" try: return math.floor(float(input(text + "? ")) + .5) except (ValueError, OverflowError): return None def getString(text=""): """INPUT A$ -- A$ is DIM A$[3], so only 3 characters are kept. (Upper case, as the original teleprinter terminals were.)""" return input(text + "? ").strip().upper()[:3] def rnd(): return random.random() # RND(1) def rnd8(): return math.floor(rnd()*8 + 1) # INT(RND(1)*8+1) def clockMinutes(): now = time.localtime() return now.tm_min + 60*now.tm_hour # TIM(0)+60*TIM(1) def blankLines(): # lines 5460-5500 print("\n"*11) # ------------------------------------------------ the quadrant map # ****** INSERTION IN STRING ARRAY FOR QUADRANT ****** def putCell(row, col, text): # lines 5510-5600 sector[row][col] = text # ******* STRING COMPARISON IN QUADRANT ARRAY ********** def cellIs(row, col, text): # lines 5680-5810 return sector[math.floor(row + .5)][math.floor(col + .5)] == text # **** PRINTS DEVICE NAME FROM ARRAY ***** def deviceName(n): # lines 5610-5670 return deviceNames[n] def randomEmpty(): # lines 5380-5450 while True: row, col = rnd8(), rnd8() if cellIs(row, col, blank): return row, col def updateGalaxy(): # lines 3400 and 3770 galaxy[quadRow][quadCol] = quadKlingons*100 + quadBases*10 + quadStars def klingonDistance(i): # line 360, DEF FND return math.sqrt( (klingon[i][1] - sectRow)**2 + (klingon[i][2] - sectCol)**2) def courseSteps(course): # lines 1885-1900, 2895-2910 c = math.floor(course) frac = course - c here, there = courseTable[c], courseTable[c + 1] rowStep = here[0] + (there[0] - here[0])*frac colStep = here[1] + (there[1] - here[1])*frac return rowStep, colStep # ------------------------------------------------ setting up a game def makeGalaxy(): # lines 490-775 global galaxy, galaxyMemory global klingonsLeft, klingonsAtStart, basesLeft galaxy = [[0]*9 for _ in range(9)] galaxyMemory = [[0]*9 for _ in range(9)] while True: basesLeft = klingonsLeft = 0 for i in range(1, 9): for j in range(1, 9): r = rnd() k3 = 3 if r > .98 else 2 if r > .95 else 1 if r > .8 else 0 klingonsLeft += k3 b3 = 1 if rnd() > .96 else 0 basesLeft += b3 galaxy[i][j] = k3*100 + b3*10 + rnd8() galaxyMemory[i][j] = 0 klingonsAtStart = klingonsLeft if basesLeft > 0 and klingonsLeft > 0: # else make another galaxy return def newGame(): # lines 240-780 global stardate, startDate, daysAllowed, energy, maxEnergy, torpedoes global klingonShield, shields, quadRow, quadCol, sectRow, sectCol global startClock, damage blankLines() startDate = stardate = math.floor(rnd()*20 + 20)*100 daysAllowed = 30 energy = maxEnergy = 3000 torpedoes = 10 klingonShield = 200 shields = 0 quadRow, quadCol = rnd8(), rnd8() sectRow, sectCol = rnd8(), rnd8() startClock = clockMinutes() damage = [0]*9 makeGalaxy() print("YOU MUST DESTROY" + num(klingonsLeft) + " KLINGONS IN" + num(daysAllowed) + " STARDATES WITH" + num(basesLeft) + " STARBASES") def enterQuadrant(): # lines 810-1250 global quadKlingons, quadBases, quadStars, klingon, sector quadKlingons = quadBases = quadStars = 0 if 1 <= quadRow <= 8 and 1 <= quadCol <= 8: g = galaxy[quadRow][quadCol] # digits are K, B, S quadKlingons, quadBases, quadStars = g // 100, g // 10 % 10, g % 10 if quadKlingons != 0 and shields <= 200: print("COMBAT AREA CONDITION RED") print(" SHIELDS DANGEROUSLY LOW") klingon = [[0, 0, 0, 0] for _ in range(4)] # K[I,1..3]: row, col, shield sector = [[blank]*9 for _ in range(9)] putCell(sectRow, sectCol, "<*>") for i in range(1, quadKlingons + 1): row, col = randomEmpty() putCell(row, col, "+++") klingon[i] = [0, row, col, klingonShield] for _ in range(quadBases): row, col = randomEmpty() putCell(row, col, ">!<") for _ in range(quadStars): row, col = randomEmpty() putCell(row, col, " * ") # ------------------------------------------------ command loop def playGame(): # ***** PROGRAM STARTS HERE ***** newGame() step = "quadrant" while True: if step == "quadrant": enterQuadrant() if step != "prompt": # line 1260 shortRange() step = command() # line 1270 def command(): # lines 1270-1400 c = getChoice("COMMAND:") # GOTO A+1 OF ... if c == 0: return setCourse() if c == 1: return "scan" if c == 2: return longRange() if c == 3: return phasers() if c == 4: return fireTorpedo() if c == 5: return shieldControl() if c == 6: return damageReport() if c == 7: return computer() print() print(" 0 = SET COURSE") print(" 1 = SHORT RANGE SENSOR SCAN") print(" 2 = LONG RANGE SENSOR SCAN") print(" 3 = FIRE PHASERS") print(" 4 = FIRE PHOTON TORPEDOES") print(" 5 = SHIELD CONTROL") print(" 6 = DAMAGE CONTROL REPORT") print(" 7 = CALL ON LIBRARY COMPUTER") print() return "prompt" # ------------------------------------------------ 0: set course def setCourse(): # lines 1410-2320 global energy, stardate, sectRow, sectCol, quadRow, quadCol while True: course = getNumbers(1, "COURSE (1-9):")[0] if course == 0: return "prompt" if course < 1 or course >= 9: continue warp = getNumbers(1, "WARP FACTOR (0-8):")[0] if warp < 0 or warp > 8: continue if damage[1] >= 0 or warp <= .2: break print("WARP ENGINES ARE DAMAGED, MAXIMUM SPEED = WARP .2") if quadKlingons > 0: # lines 1510-1550 klingonsFire() if shields < 0: destroyed() elif energy <= 0: # lines 1560-1600 if shields < 1: deadInSpace() print("YOU HAVE" + num(energy) + " UNITS OF ENERGY") print("SUGGEST YOU GET SOME FROM YOUR SHIELDS WHICH HAVE" + num(shields) + " UNITS LEFT") return "prompt" repairDevices() randomDamage() steps = math.floor(warp*8) # line 1810 putCell(sectRow, sectCol, blank) startRow, startCol = sectRow, sectCol rowStep, colStep = courseSteps(course) for _ in range(steps): sectRow += rowStep sectCol += colStep if sectRow < .5 or sectRow >= 8.5 or sectCol < .5 or sectCol >= 8.5: # lines 2170-2320: left the quadrant x = quadRow*8 + startRow + rowStep*steps y = quadCol*8 + startCol + colStep*steps quadRow = math.floor(x/8) quadCol = math.floor(y/8) sectRow = math.floor(x - quadRow*8 + .5) sectCol = math.floor(y - quadCol*8 + .5) if sectRow == 0: quadRow -= 1 sectRow = 8 if sectCol == 0: quadCol -= 1 sectCol = 8 stardate += 1 energy = energy - steps + 5 if stardate > startDate + daysAllowed: timeUp() return "quadrant" if not cellIs(sectRow, sectCol, blank): # lines 1950-2060 print(" WARP ENGINES SHUTDOWN AT SECTOR " + d(sectRow) + "," + d(sectCol) + " DUE TO BAD NAVIGATION") sectRow -= rowStep sectCol -= colStep break sectRow = math.floor(sectRow + .5) # lines 2080-2160 sectCol = math.floor(sectCol + .5) putCell(sectRow, sectCol, "<*>") energy = energy - steps + 5 if warp >= 1: stardate += 1 if stardate > startDate + daysAllowed: timeUp() return "scan" def repairDevices(): # lines 1610-1640 for i in range(1, 9): if damage[i] < 0: damage[i] += 1 def randomDamage(): # lines 1650-1800 if rnd() > .2: return n = rnd8() if rnd() < .5: damage[n] -= rnd()*5 + 1 print() print("DAMAGE CONTROL REPORT:" + deviceName(n) + " DAMAGED") else: damage[n] += rnd()*5 + 1 print() print("DAMAGE CONTROL REPORT:" + deviceName(n) + " STATE OF REPAIR IMPROVED") print() # ------------------------------------------------ 1: short range scan def shortRange(): # lines 4120-4530 global condition, energy, torpedoes, shields docked = False for i in range(sectRow - 1, sectRow + 2): for j in range(sectCol - 1, sectCol + 2): if 1 <= i <= 8 and 1 <= j <= 8 and cellIs(i, j, ">!<"): docked = True if docked: condition = "DOCKED" energy = 3000 torpedoes = 10 print("SHIELDS DROPPED FOR DOCKING PURPOSES") shields = 0 elif quadKlingons > 0: condition = "RED" elif energy < maxEnergy*.1: condition = "YELLOW" else: condition = "GREEN" if damage[2] < 0: print() print("*** SHORT RANGE SENSORS ARE OUT ***") print() return rule = "-"*33 # IMAGE 4540 gap = " "*8 # 8X tails = [ # IMAGES 4550-4620 "", gap + "STARDATE" + gap + d(stardate, 5), gap + "CONDITION" + gap + condition.ljust(6)[:6], gap + "QUADRANT" + " "*9 + d(quadRow) + "," + d(quadCol), gap + "SECTOR" + " "*11 + d(sectRow) + "," + d(sectCol), gap + "ENERGY" + " "*9 + d(energy, 6), gap + "PHOTON TORPEDOES" + d(torpedoes, 3), gap + "SHIELDS" + gap + d(shields, 6), ] print(rule) for row in range(1, 9): cells = "".join(" " + sector[row][col] # 8(X,3A) for col in range(1, 9)) print(cells + tails[row - 1]) print(rule) # ------------------------------------------------ 2: long range scan def longRange(): # lines 2330-2500 if damage[3] < 0: print("LONG RANGE SENSORS ARE INOPERABLE") return "prompt" print("LONG RANGE SENSOR SCAN FOR QUADRANT" + d(quadRow) + "," + d(quadCol)) rule = "-"*17 # IMAGE 2520 print(rule) for i in range(quadRow - 1, quadRow + 2): row = [0, 0, 0] for j in range(quadCol - 1, quadCol + 2): if 1 <= i <= 8 and 1 <= j <= 8: row[j - quadCol + 1] = galaxy[i][j] if damage[7] >= 0: galaxyMemory[i][j] = galaxy[i][j] print(": " + "".join(d(v, 3) + " :" for v in row)) # IMAGE 2510 print(rule) return "prompt" # ------------------------------------------------ 3: phasers def phasers(): # lines 2530-2790 global energy if quadKlingons <= 0: print("SHORT RANGE SENSORS REPORT NO KLINGONS IN THIS QUADRANT") return "prompt" if damage[4] < 0: print("PHASER CONTROL IS DISABLED") return "prompt" while True: if damage[7] < 0: print(" COMPUTER FAILURE HAMPERS ACCURACY") print("PHASERS LOCKED ON TARGET. ENERGY AVAILABLE=" + num(energy)) x = getNumbers(1, "NUMBER OF UNITS TO FIRE:")[0] if x <= 0: return "prompt" if energy - x >= 0: break energy -= x klingonsFire() if damage[7] < 0: x *= rnd() for i in range(1, 4): if klingon[i][3] <= 0: continue hit = (x/quadKlingons/klingonDistance(i))*(2*rnd()) klingon[i][3] -= hit print(d(hit, 4) + " UNIT HIT ON KLINGON AT SECTOR " # IMAGE 2730 + d(klingon[i][1]) + "," + d(klingon[i][2]) + " (" + d(klingon[i][3], 3) + " LEFT)") if klingon[i][3] > 0: continue klingonDestroyed(i) if klingonsLeft <= 0: win() if energy < 0: destroyed() return "prompt" def klingonDestroyed(i): # lines 3690-3780 global quadKlingons, klingonsLeft print("KLINGON AT SECTOR " + d(klingon[i][1]) + "," + d(klingon[i][2]) + " DESTROYED ****") # IMAGE 3700 quadKlingons -= 1 klingonsLeft -= 1 putCell(klingon[i][1], klingon[i][2], blank) updateGalaxy() # ------------------------------------------------ 4: photon torpedoes def fireTorpedo(): # lines 2800-3450 global torpedoes, quadKlingons, quadBases, klingonsLeft if damage[5] < 0: print("PHOTON TUBES ARE NOT OPERATIONAL") return "prompt" if torpedoes <= 0: print("ALL PHOTON TORPEDOES EXPENDED") return "prompt" while True: course = getNumbers(1, "TORPEDO COURSE (1-9):")[0] if course == 0: return "prompt" if 1 <= course < 9: break rowStep, colStep = courseSteps(course) x, y = sectRow, sectCol torpedoes -= 1 print("TORPEDO TRACK:") while True: x += rowStep y += colStep if x < .5 or x >= 8.5 or y < .5 or y >= 8.5: print("TORPEDO MISSED") break print(" "*15 + d(x) + "," + d(y)) # IMAGE 3000 if cellIs(x, y, blank): continue if cellIs(x, y, "+++"): print("*** KLINGON DESTROYED ***") quadKlingons -= 1 klingonsLeft -= 1 if klingonsLeft <= 0: win() for i in range(1, 4): # which klingon was it? if (math.floor(x + .5) == klingon[i][1] and math.floor(y + .5) == klingon[i][2]): break klingon[i][3] = 0 putCell(math.floor(x + .5), math.floor(y + .5), blank) updateGalaxy() break if cellIs(x, y, " * "): print("YOU CAN'T DESTROY STARS SILLY") print("TORPEDO MISSED") break if cellIs(x, y, ">!<"): print("*** STAR BASE DESTROYED *** .......CONGRATULATIONS") quadBases -= 1 putCell(math.floor(x + .5), math.floor(y + .5), blank) updateGalaxy() break klingonsFire() if energy < 0: destroyed() return "prompt" # ------------------------------------------------ 5: shield control def shieldControl(): # lines 3460-3550 global energy, shields if damage[7] < 0: print("SHIELD CONTROL IS NON-OPERATIONAL") return "prompt" while True: x = getNumbers(1, "ENERGY AVAILABLE =" + num(energy + shields) + " NUMBER OF UNITS TO SHIELDS:")[0] if x <= 0: return "prompt" if energy + shields - x >= 0: break energy = energy + shields - x shields = x return "prompt" # ------------------------------------------------ 6: damage control report def damageReport(): # lines 3560-3660 if damage[6] < 0: print("DAMAGE CONTROL REPORT IS NOT AVAILABLE") return "prompt" print() print("DEVICE STATE OF REPAIR") for n in range(1, 9): name = deviceName(n) print(name + " "*(15 - len(name)) + num(damage[n])) # PRINT "",D[R1] print() return "prompt" # ------------------------------------------------ 7: library computer def computer(): # lines 4630-4730 if damage[8] < 0: print("COMPUTER DISABLED") return "prompt" while True: c = getChoice("COMPUTER ACTIVE AND AWAITING COMMAND") if c == 0: return galaxyRecord() if c == 1: return statusReport() if c == 2: return torpedoData() print("FUNCTIONS AVAILABLE FROM COMPUTER") print(" 0 = CUMULATIVE GALACTIC RECORD") print(" 1 = STATUS REPORT") print(" 2 = PHOTON TORPEDO DATA") def galaxyRecord(): # lines 4740-4820 print("COMPUTER RECORD OF GALAXY FOR QUADRANT " + d(quadRow) + "," + d(quadCol)) rule = " ----- ----- ----- ----- ----- ----- ----- -----" # IMAGE 5360 print(" 1 2 3 4 5 6 7 8") # IMAGE 5330 print(rule) for i in range(1, 9): print(d(i) + "".join(" " + d(galaxyMemory[i][j], 3) for j in range(1, 9))) print(rule) return "prompt" def statusReport(): # lines 4830-4870 print("\n STATUS REPORT\n") print("NUMBER OF KLINGONS LEFT =" + num(klingonsLeft)) print("NUMBER OF STARDATES LEFT =" + num((startDate + daysAllowed) - stardate)) print("NUMBER OF STARBASES LEFT =" + num(basesLeft)) return damageReport() # the BASIC continues at 3560 def torpedoData(): # lines 4880-5320 print() for i in range(1, 4): if klingon[i][3] > 0: direction(sectRow, sectCol, klingon[i][1], klingon[i][2]) while True: answer = getString("DO YOU WANT TO USE THE CALCULATOR") if answer == "YES": print("YOU ARE AT QUADRANT ( " + d(quadRow) + "," + d(quadCol) + " ) SECTOR ( " + d(sectRow) + "," + d(sectCol) + " )") row, col, targetRow, targetCol = getNumbers( 4, "SHIP'S & TARGET'S COORDINATES ARE") direction(row, col, targetRow, targetCol) elif answer == "NO": return "prompt" def direction(shipRow, shipCol, targetRow, targetCol): # lines 5010-5240 x = targetCol - shipCol # east of the ship a = shipRow - targetRow # north of the ship if x < 0: base, wide = (3, False) if a > 0 else (5, True) elif a < 0: base, wide = 7, False elif x > 0 or a > 0: base, wide = 1, True else: base, wide = 5, True ax, aa = abs(x), abs(a) if wide: # lines 5080-5110 if aa <= ax: course = base + divide(aa, ax) else: course = base + divide((aa - ax) + aa, aa) else: # lines 5200-5230 if aa >= ax: course = base + divide(ax, aa) else: course = base + divide((ax - aa) + ax, ax) print("DIRECTION =" + num(course)) print("DISTANCE =" + num(math.sqrt(x**2 + a**2))) # ------------------------------------------------ klingon attacks def klingonsFire(): # lines 3790-3910 global shields if condition == "DOCKED": print("STAR BASE SHIELDS PROTECT THE ENTERPRISE") return if quadKlingons <= 0: return for i in range(1, 4): if klingon[i][3] <= 0: continue hit = (klingon[i][3]/klingonDistance(i))*(2*rnd()) shields -= hit print(d(hit, 4) + " UNIT HIT ON ENTERPRISE AT SECTOR " # IMAGE 3880 + d(klingon[i][1]) + "," + d(klingon[i][2]) + " (" + d(shields, 4) + " LEFT)") if shields < 0: destroyed() # ------------------------------------------------ ways the game ends def deadInSpace(): # lines 3920-3960 print("THE ENTERPRISE IS DEAD IN SPACE. IF YOU SURVIVE ALL IMPENDING") print("ATTACK YOU WILL BE DEMOTED TO THE RANK OF PRIVATE") while quadKlingons > 0: klingonsFire() stillKlingons() def timeUp(): # lines 3970-3990 print() print("IT IS STARDATE" + num(stardate)) stillKlingons() def destroyed(): # lines 4000-4010 print() print("THE ENTERPRISE HAS BEEN DESTROYED. " "THE FEDERATION WILL BE CONQUERED") stillKlingons() def stillKlingons(): # lines 4020-4030 print("THERE ARE STILL" + num(klingonsLeft) + " KLINGON BATTLE CRUISERS") raise GameOver def win(): # lines 4040-4110 print() print("THE LAST KLINGON BATTLE CRUISER IN THE GALAXY HAS BEEN DESTROYED") print("THE FEDERATION HAS BEEN SAVED !!!") print() print("YOUR EFFICIENCY RATING =" + num(divide(klingonsAtStart*1000, stardate - startDate))) elapsed = clockMinutes() - startClock # formula exactly as in line 4100 print("YOUR ACTUAL TIME OF MISSION =" + num(math.floor(((elapsed*.4) - startClock)*100)) + " MINUTES") raise GameOver # ------------------------------------------------ instructions instructionText = ( " INSTRUCTIONS:", "<*> = ENTERPRISE", "+++ = KLINGON", ">!< = STARBASE", " * = STAR", "COMMAND 0 = WARP ENGINE CONTROL", " 'COURSE' IS IN A CIRCULAR NUMERICAL 4 3 2", " VECTOR ARRANGEMENT AS SHOWN. \\ ^ /", " INTERGER AND REAL VALUES MAY BE \\^/", " USED. THEREFORE COURSE 1.5 IS 5 ----- 1", " HALF WAY BETWEEN 1 AND 2. /^\\", " / ^ \\", " A VECTOR OF 9 IS UNDEFINED, BUT 6 7 8", " VALUES MAY APPROACH 9.", " COURSE", " ONE 'WARP FACTOR' IS THE SIZE OF", " ONE QUADRANT. THEREFORE TO GET", " FROM QUADRANT 6,5 TO 5,5 YOU WOULD", " USE COURSE 3, WARP FACTOR 1", "COMMAND 1 = SHORT RANGE SENSOR SCAN", " PRINTS THE QUADRANT YOU ARE CURRENTLY IN, INCLUDING", " STARS, KLINGONS, STARBASES, AND THE ENTERPRISE; ALONG", " WITH OTHER PERTINATE INFORMATION.", "COMMAND 2 = LONG RANGE SENSOR SCAN", " SHOWS CONDITIONS IN SPACE FOR ONE QUADRANT ON EACH SIDE", " OF THE ENTERPRISE IN THE MIDDLE OF THE SCAN. THE SCAN", " IS CODED IN THE FORM XXX, WHERE THE UNITS DIGIT IS THE", " NUMBER OF STARS, THE TENS DIGIT IS THE NUMBER OF STAR-", " BASES, THE HUNDREDS DIGIT IS THE NUMBER OF KLINGONS.", "COMMAND 3 = PHASER CONTROL", " ALLOWS YOU TO DESTROY THE KLINGONS BY HITTING HIM WITH", " SUITABLY LARGE NUMBERS OF ENERGY UNITS TO DEPLETE HIS ", " SHIELD POWER. KEEP IN MIND THAT WHEN YOU SHOOT AT", " HIM, HE GONNA DO IT TO YOU TOO.", "COMMAND 4 = PHOTON TORPEDO CONTROL", " COURSE IS THE SAME AS USED IN WARP ENGINE CONTROL", " IF YOU HIT THE KLINGON, HE IS DESTROYED AND CANNOT FIRE", " BACK AT YOU. IF YOU MISS, HE WILL SHOOT HIS PHASERS AT", " YOU.", " NOTE: THE LIBRARY COMPUTER (COMMAND 7) HAS AN OPTION", " TO COMPUTE TORPEDO TRAJECTORY FOR YOU (OPTION 2).", "COMMAND 5 = SHIELD CONTROL", " DEFINES NUMBER OF ENERGY UNITS TO BE ASSIGNED TO SHIELDS", " ENERGY IS TAKEN FROM TOTAL SHIP'S ENERGY.", "COMMAND 6 = DAMAGE CONTROL REPORT", " GIVES STATE OF REPAIRS OF ALL DEVICES. A STATE OF REPAIR", " LESS THAN ZERO SHOWS THAT THAT DEVICE IS TEMPORARALY", " DAMAGED.", "COMMAND 7 = LIBRARY COMPUTER", " THE LIBRARY COMPUTER CONTAINS THREE OPTIONS:", " OPTION 0 = CUMULATIVE GALACTIC RECORD", " SHOWS COMPUTER MEMORY OF THE RESULTS OF ALL PREVIOUS", " LONG RANGE SENSOR SCANS", " OPTION 1 = STATUS REPORT", " SHOWS NUMBER OF KLINGONS, STARDATES AND STARBASES", " LEFT.", " OPTION 2 = PHOTON TORPEDO DATA", " GIVES TRAJECTORY AND DISTANCE BETWEEN THE ENTERPRISE", " AND ALL KLINGONS IN YOUR QUADRANT", ) def instructions(): # lines 5820-6410 for line in instructionText: print(line) def main(): # lines 170-220 blankLines() print(" STAR TREK ") if getString("DO YOU WANT INSTRUCTIONS (THEY'RE LONG!)") == "YES": instructions() while True: # every ending restarts at 230 try: playGame() except GameOver: pass if __name__ == "__main__": try: main() except (EOFError, KeyboardInterrupt): print()