2615673668caf9e21860e750d74224370dd6c357
[super-star-trek.git] / src / sst.py
1 """
2 sst.py =-- Super Star Trek in Python
3
4 """
5 import os, sys, math, curses
6
7 SSTDOC = "/usr/share/doc/sst/sst.doc"
8
9 # Stub to be replaced
10 def _(str): return str
11
12 PHASEFAC        = 2.0
13 GALSIZE         = 8
14 NINHAB          = (GALSIZE * GALSIZE / 2)
15 MAXUNINHAB      = 10
16 PLNETMAX        = (NINHAB + MAXUNINHAB)
17 QUADSIZE        = 10
18 BASEMAX         = (GALSIZE * GALSIZE / 12)
19 MAXKLGAME       = 127
20 MAXKLQUAD       = 9
21 FULLCREW        = 428   # BSD Trek was 387, that's wrong 
22 FOREVER         = 1e30
23
24 # These functions hide the difference between 0-origin and 1-origin addressing.
25 def VALID_QUADRANT(x, y):       return ((x)>=1 and (x)<=GALSIZE and (y)>=1 and (y)<=GALSIZE)
26 def VALID_SECTOR(x, y): return ((x)>=1 and (x)<=QUADSIZE and (y)>=1 and (y)<=QUADSIZE)
27
28 def square(i):          return ((i)*(i))
29 def distance(c1, c2):   return math.sqrt(square(c1.x - c2.x) + square(c1.y - c2.y))
30 def invalidate(w):      w.x = w.y = 0
31 def is_valid(w):        return (w.x != 0 and w.y != 0)
32
33 class coord:
34     def __init(self, x=None, y=None):
35         self.x = x
36         self.y = y
37     def invalidate(self):
38         self.x = self.y = None
39     def is_valid(self):
40         return self.x != None and self.y != None
41     def __eq__(self, other):
42         return self.x == other.y and self.x == other.y
43     def __add__(self, other):
44         return coord(self.x+self.x, self.y+self.y)
45     def __sub__(self, other):
46         return coord(self.x-self.x, self.y-self.y)
47     def distance(self, other):
48         return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
49     def sgn(self):
50         return coord(self.x / abs(x), self.y / abs(y));
51     def __hash__(self):
52         return hash((x, y))
53     def __str__(self):
54         return "%d - %d" % (self.x, self.y)
55
56 class planet:
57     def __init(self):
58         self.name = None        # String-valued if inhabited
59         self.w = None
60         self.pclass = None      # could be ""M", "N", "O", or "destroyed"
61         self.crystals = None    # could be "mined", "present", "absent"
62         self.known = None       # could be "unknown", "known", "shuttle_down"
63
64 # How to represent features
65 IHR = 'R',
66 IHK = 'K',
67 IHC = 'C',
68 IHS = 'S',
69 IHSTAR = '*',
70 IHP = 'P',
71 IHW = '@',
72 IHB = 'B',
73 IHBLANK = ' ',
74 IHDOT = '.',
75 IHQUEST = '?',
76 IHE = 'E',
77 IHF = 'F',
78 IHT = 'T',
79 IHWEB = '#',
80 IHMATER0 = '-',
81 IHMATER1 = 'o',
82 IHMATER2 = '0'
83
84 NOPLANET = None
85 class quadrant:
86     def __init(self):
87         self.stars = None
88         self.planet = None
89         self.starbase = None
90         self.klingons = None
91         self.romulans = None
92         self.supernova = None
93         self.charted = None
94         self.status = None      # Could be "secure", "distressed", "enslaved"
95
96 class snapshot:
97     def __init(self):
98         self.snap = False       # snapshot taken
99         self.crew = None        # crew complement
100         self.remkl = None       # remaining klingons
101         self.remcom = None      # remaining commanders
102         self.nscrem = None      # remaining super commanders
103         self.rembase = None     # remaining bases
104         self.starkl = None      # destroyed stars
105         self.basekl = None      # destroyed bases
106         self.nromrem = None     # Romulans remaining
107         self.nplankl = None     # destroyed uninhabited planets
108         self.nworldkl = None    # destroyed inhabited planets
109         self.planets = []       # Planet information
110         self.date = None        # stardate
111         self.remres = None      # remaining resources
112         self.remtime = None     # remaining time
113         self.baseq = []         # Base quadrant coordinates
114         self.kcmdr = []         # Commander quadrant coordinates
115         self.kscmdr = None      # Supercommander quadrant coordinates
116         self.galaxy = None      # The Galaxy (subscript 0 not used)
117         self.chart = None       # the starchart (subscript 0 not used)
118
119 class event:
120     def __init__(self):
121         self.date = None        # A real number
122         self.quadrant = None    # A coord structure
123
124 # game options 
125 OPTION_ALL      = 0xffffffff
126 OPTION_TTY      = 0x00000001    # old interface 
127 OPTION_CURSES   = 0x00000002    # new interface 
128 OPTION_IOMODES  = 0x00000003    # cover both interfaces 
129 OPTION_PLANETS  = 0x00000004    # planets and mining 
130 OPTION_THOLIAN  = 0x00000008    # Tholians and their webs 
131 OPTION_THINGY   = 0x00000010    # Space Thingy can shoot back 
132 OPTION_PROBE    = 0x00000020    # deep-space probes 
133 OPTION_SHOWME   = 0x00000040    # bracket Enterprise in chart 
134 OPTION_RAMMING  = 0x00000080    # enemies may ram Enterprise 
135 OPTION_MVBADDY  = 0x00000100    # more enemies can move 
136 OPTION_BLKHOLE  = 0x00000200    # black hole may timewarp you 
137 OPTION_BASE     = 0x00000400    # bases have good shields 
138 OPTION_WORLDS   = 0x00000800    # logic for inhabited worlds 
139 OPTION_PLAIN    = 0x01000000    # user chose plain game 
140 OPTION_ALMY     = 0x02000000    # user chose Almy variant 
141
142 # Define devices 
143 DSRSENS = 0
144 DLRSENS = 1
145 DPHASER = 2
146 DPHOTON = 3
147 DLIFSUP = 4
148 DWARPEN = 5
149 DIMPULS = 6
150 DSHIELD = 7
151 DRADIO  = 0
152 DSHUTTL = 9
153 DCOMPTR = 10
154 DNAVSYS = 11
155 DTRANSP = 12
156 DSHCTRL = 13
157 DDRAY   = 14
158 DDSP    = 15
159 NDEVICES= 16    # Number of devices
160
161 def damaged(dev):       return (game.damage[dev] != 0.0)
162
163 # Define future events 
164 FSPY    = 0     # Spy event happens always (no future[] entry)
165                 # can cause SC to tractor beam Enterprise
166 FSNOVA  = 1     # Supernova
167 FTBEAM  = 2     # Commander tractor beams Enterprise
168 FSNAP   = 3     # Snapshot for time warp
169 FBATTAK = 4     # Commander attacks base
170 FCDBAS  = 5     # Commander destroys base
171 FSCMOVE = 6     # Supercommander moves (might attack base)
172 FSCDBAS = 7     # Supercommander destroys base
173 FDSPROB = 8     # Move deep space probe
174 FDISTR  = 9     # Emit distress call from an inhabited world 
175 FENSLV  = 10    # Inhabited word is enslaved */
176 FREPRO  = 11    # Klingons build a ship in an enslaved system
177 NEVENTS = 12
178
179 #
180 # abstract out the event handling -- underlying data structures will change
181 # when we implement stateful events
182
183 def findevent(evtype):  return game.future[evtype]
184
185 class gamestate:
186     def __init__(self):
187         self.options = None     # Game options
188         self.state = None       # A snapshot structure
189         self.snapsht = None     # Last snapshot taken for time-travel purposes
190         self.quad = [[IHDOT * (QUADSIZE+1)] * (QUADSIZE+1)]     # contents of our quadrant
191         self.kpower = [[0 * (QUADSIZE+1)] * (QUADSIZE+1)]       # enemy energy levels
192         self.kdist = [[0 * (QUADSIZE+1)] * (QUADSIZE+1)]        # enemy distances
193         self.kavgd = [[0 * (QUADSIZE+1)] * (QUADSIZE+1)]        # average distances
194         self.damage = [0] * NDEVICES    # damage encountered
195         self.future = [None] * NEVENTS  # future events
196         self.passwd  = None;            # Self Destruct password
197         self.ks = [[None * (QUADSIZE+1)] * (QUADSIZE+1)]        # enemy sector locations
198         self.quadrant = None    # where we are in the large
199         self.sector = None      # where we are in the small
200         self.tholian = None     # coordinates of Tholian
201         self.base = None        # position of base in current quadrant
202         self.battle = None      # base coordinates being attacked
203         self.plnet = None       # location of planet in quadrant
204         self.probec = None      # current probe quadrant
205         self.gamewon = False    # Finished!
206         self.ididit = False     # action taken -- allows enemy to attack
207         self.alive = False      # we are alive (not killed)
208         self.justin = False     # just entered quadrant
209         self.shldup = False     # shields are up
210         self.shldchg = False    # shield is changing (affects efficiency)
211         self.comhere = False    # commander here
212         self.ishere = False     # super-commander in quadrant
213         self.iscate = False     # super commander is here
214         self.ientesc = False    # attempted escape from supercommander
215         self.ithere = False     # Tholian is here 
216         self.resting = False    # rest time
217         self.icraft = False     # Kirk in Galileo
218         self.landed = False     # party on planet (true), on ship (false)
219         self.alldone = False    # game is now finished
220         self.neutz = False      # Romulan Neutral Zone
221         self.isarmed = False    # probe is armed
222         self.inorbit = False    # orbiting a planet
223         self.imine = False      # mining
224         self.icrystl = False    # dilithium crystals aboard
225         self.iseenit = False    # seen base attack report
226         self.thawed = False     # thawed game
227         self.condition = None   # "green", "yellow", "red", "docked", "dead"
228         self.iscraft = None     # "onship", "offship", "removed"
229         self.skill = None       # Player skill level
230         self.inkling = 0        # initial number of klingons
231         self.inbase = 0         # initial number of bases
232         self.incom = 0          # initial number of commanders
233         self.inscom = 0         # initial number of commanders
234         self.inrom = 0          # initial number of commanders
235         self.instar = 0         # initial stars
236         self.intorps = 0        # initial/max torpedoes
237         self.torps = 0          # number of torpedoes
238         self.ship = 0           # ship type -- 'E' is Enterprise
239         self.abandoned = 0      # count of crew abandoned in space
240         self.length = 0         # length of game
241         self.klhere = 0         # klingons here
242         self.casual = 0         # causalties
243         self.nhelp = 0          # calls for help
244         self.nkinks = 0         # count of energy-barrier crossings
245         self.iplnet = 0         # planet # in quadrant
246         self.inplan = 0         # initial planets
247         self.nenhere = 0        # number of enemies in quadrant
248         self.irhere = 0         # Romulans in quadrant
249         self.isatb = 0          # =1 if super commander is attacking base
250         self.tourn = 0          # tournament number
251         self.proben = 0         # number of moves for probe
252         self.nprobes = 0        # number of probes available
253         self.inresor = 0.0      # initial resources
254         self.intime = 0.0       # initial time
255         self.inenrg = 0.0       # initial/max energy
256         self.inshld = 0.0       # initial/max shield
257         self.inlsr = 0.0        # initial life support resources
258         self.indate = 0.0       # initial date
259         self.energy = 0.0       # energy level
260         self.shield = 0.0       # shield level
261         self.warpfac = 0.0      # warp speed
262         self.wfacsq = 0.0       # squared warp factor
263         self.lsupres = 0.0      # life support reserves
264         self.dist = 0.0         # movement distance
265         self.direc = 0.0        # movement direction
266         self.optime = 0.0       # time taken by current operation
267         self.docfac = 0.0       # repair factor when docking (constant?)
268         self.damfac = 0.0       # damage factor
269         self.lastchart = 0.0    # time star chart was last updated
270         self.cryprob = 0.0      # probability that crystal will work
271         self.probex = 0.0       # location of probe
272         self.probey = 0.0       #
273         self.probeinx = 0.0     # probe x,y increment
274         self.probeiny = 0.0     #
275         self.height = 0.0       # height of orbit around planet
276
277