Ready to ship 2.8
[super-star-trek.git] / doc / HACKING
1 This is the hackers' guide to SST2K.  Read it before messing with the code.
2
3 It consists of an introduction, a history, suggestions for regression testing,
4 and some notes on the Python translation.  For a to-do list, see TODO in the
5 top-level directory.
6
7 INTRODUCTION:
8
9 SST2K is a Python translation of a C translation of a FORTRAN
10 original dating back to 1973.  Beautiful Python it is not, but it
11 works. 
12
13 The intention of SST2K is to be able to replicate precisely the 
14 experience of the original game, while allowing new features to be
15 added under option control.  Therefore, be very conservative about
16 what changes are visible under the 'plain' option.
17
18 HISTORY:
19
20 Dave Matuszek, one of the two original authors, says:
21
22 SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON,
23 LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE
24 were in the original non-"super" version of UT FORTRAN Star Trek.
25
26 Tholians were not in the original. Dave is dubious about their merits.
27 (They are now controlled by OPTION_THOLIAN and turned off if the game
28 type is "plain".)
29
30 Planets and dilithium crystals were not in the original.  Dave is OK
31 with this idea. (It's now controlled by OPTION_PLANETS and turned 
32 off if the game type is "plain".)
33
34 Dave says the bit about the Galileo getting turned into a
35 McDonald's is "consistant with our original vision".  (This has been
36 left permanently enabled, as it can only happen if OPTION_PLANETS
37 is on.)
38
39 Dave also says the Space Thingy should not be preserved across saved
40 games, so you can't prove to others that you've seen it.  He says it
41 shouldn't fire back, either.  It should do nothing except scream and
42 disappear when hit by photon torpedos.  It's OK that it may move
43 when attacked, but it didn't in the original. (The no-save behavior
44 has been restored.)
45
46 Dave says the Faerie Queen, black holes, and time warping were in the
47 original.  However, either he is misremembering about time warping or
48 the original implementation was lost during the FORTRAN-to-C
49 translation, as Stas Sergeev added a time-warping feature not
50 previiusly present in 2006.  Tom Almy also claims to have added
51 timewarping!
52
53 Here are Tom Almy's changes:
54
55 In early 1997, I got the bright idea to look for references to
56 "Super Star Trek" on the World Wide Web. There weren't many hits,
57 but there was one that came up with 1979 Fortran sources! This
58 version had a few additional features that mine didn't have,
59 however mine had some feature it didn't have. So I merged its
60 features that I liked. I also took a peek at the DECUS version (a
61 port, less sources, to the PDP-10), and some other variations.
62
63 1. Compared to the original UT version, I've changed the "help"
64 command to "call" and the "terminate" command to "quit" to better
65 match user expectations. The DECUS version apparently made those
66 changes as well as changing "freeze" to "save". However I like
67 "freeze".  (Both "freeze" and "save" work in SST2K.)
68
69 2. The experimental deathray originally had only a 5% chance of
70 success, but could be used repeatedly. I guess after a couple
71 years of use, it was less "experimental" because the 1979
72 version had a 70% success rate. However it was prone to breaking
73 after use. I upgraded the deathray, but kept the original set of
74 failure modes (great humor!).  (Now controlled by OPTION_DEATHRAY
75 and turned off if game type is "plain".)
76
77 3. The 1979 version also mentions srscan and lrscan working when
78 docked (using the starbase's scanners), so I made some changes here
79 to do this (and indicating that fact to the player), and then realized
80 the base would have a subspace radio as well -- doing a Chart when docked
81 updates the star chart, and all radio reports will be heard. The Dock
82 command will also give a report if a base is under attack.
83
84 4. Tholian Web from the 1979 version.  (Now controlled by
85 OPTION_THOLIAN and turned off if game type is "plain".)
86
87 5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING
88 and turned off if game type is "plain".)
89
90 6. Regular Klingons and Romulans can move in Expert and Emeritus games. 
91 This code could use improvement. (Now controlled by OPTION_MVBADDY
92 and turned off if game type is "plain".)
93
94 7. The deep-space probe feature from the DECUS version.  (Now controlled
95 by OPTION_PROBE and turned off if game type is "plain").
96
97 8. 'emexit' command from the 1979 version.
98
99 9. Bugfix: Klingon commander movements are no longer reported if long-range 
100 sensors are damaged.
101
102 10. Bugfix: Better base positioning at startup (more spread out).
103 That made sense to add because most people abort games with 
104 bad base placement.
105
106 In June 2002, I fixed two known bugs and a documentation typo.
107 In June 2004 I fixed a number of bugs involving: 1) parsing invalid
108 numbers, 2) manual phasers when SR scan is damaged and commander is
109 present, 3) time warping into the future, 4) hang when moving
110 klingons in crowded quadrants.  (These fixes are in SST2K.)
111
112 Here are Stas Sergeev's changes:
113
114 1. The Space Thingy can be shoved, if you ram it, and can fire back if 
115 fired upon. (Now controlled by OPTION_THINGY and turned off if game 
116 type is "plain" or "almy".)
117
118 2. When you are docked, base covers you with an almost invincible shield. 
119 (A commander can still ram you, or a Romulan can destroy the base,
120 or a SCom can even succeed with direct attack IIRC, but this rarely 
121 happens.)  (Now controlled by OPTION_BASE and turned off if game 
122 type is "plain" or "almy".)
123
124 3. Ramming a black hole is no longer instant death.  There is a
125 chance you might get timewarped instead. (Now controlled by 
126 OPTION_BLKHOLE and turned off if game type is "plain" or "almy".)
127
128 4. The Tholian can be hit with phasers.
129
130 5. SCom can't escape from you if no more enemies remain 
131 (without this, chasing SCom can take an eternity).
132
133 6. Probe target you enter is now the destination quadrant. Before I don't 
134 remember what it was, but it was something I had difficulty using.
135
136 7. Secret password is now autogenerated.
137
138 8. "Plaque" is adjusted for A4 paper :-)
139
140 9. Phasers now tells you how much energy needed, but only if the computer 
141 is alive.
142
143 10. Planets are auto-scanned when you enter the quadrant.
144
145 11. Mining or using crystals in presense of enemy now yields an attack.
146 There are other minor adjustments to what yields an attack
147 and what does not.
148
149 12. "freeze" command reverts to "save", most people will understand this
150 better anyway. (SST2K recognizes both.)
151
152 13. Screen-oriented interface, with sensor scans always up.  (SST2K
153 supports both screen-oriented and TTY modes.)
154
155 Eric Raymond's changes:
156
157 Mainly, I translated this C code out of FORTRAN into C -- created #defines
158 for a lot of magic numbers and refactored the heck out of it.
159
160 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good.
161
162 2. Status report now indicates when dilithium crystals are on board.
163
164 3. Per Dave Matuszek's remarks, Thingy state is never saved across games.
165
166 4. Added game option selection so you can play a close (but not bug-for-
167 bug identical) approximation of older versions.
168
169 5. Half the quadrants now have inhabited planets, from which one 
170 cannot mine dilithium (there will still be the same additional number
171 of dilithium-bearing planets).  Torpedoing an inhabited world is *bad*.
172 There is BSD-Trek-like logic for Klingons to attack and enslave 
173 inhabited worlds, producing more ships (only is skill is 'good' or 
174 better). (Controlled by OPTION_WORLDS and turned off if game 
175 type is "plain" or "almy".)
176
177 6. User input is now logged so we can do regression testing.
178
179 7. More BSD-Trek features: You can now lose if your entire crew
180 dies in battle.  When abandoning ship in a game with inhabited
181 worlds enabled, they must have one in the quadrant to beam down
182 to; otherwise they die in space and this counts heavily against
183 your score.  Docking at a starbase replenishes your crew.
184
185 8. Still more BSD-Trek: we now have a weighted damage table.  Quoth
186 Eric Allman in the code of BSD-Trek: "Under certain conditions you can
187 get a critical hit.  This sort of hit damages devices.  The
188 probability that a given device is damaged depends on the device.
189 Well protected devices (such as the computer, which is in the core of
190 the ship and has considerable redundancy) almost never get damaged,
191 whereas devices which are exposed (such as the warp engines) or which
192 are particularly delicate (such as the transporter) have a much higher
193 probability of being damaged."
194
195 This is one place where OPTION_PLAIN does not restore the original
196 behavior, which was equiprobable damage across all devices.  If we
197 wanted that, we'd return randrange(NDEVICES) and have done with it.
198 Also, in the original game, DNAVSYS and DCOMPTR were the same device.
199
200 Instead, we use a table of weights similar to the one from BSD Trek.
201 BSD doesn't have the shuttle, shield controller, death ray, or probes.
202 We don't have a cloaking device.  The shuttle got the allocation for
203 the cloaking device, then we shaved a half-percent off everything to
204 have some weight to give DSHCTRL/DDRAY/DDSP.
205
206 Also, the nav subsystem (enabling automatic course
207 setting) can be damaged separately from the main computer (which
208 handles weapons targeting, ETA calculation, and self-destruct).
209
210 After these features were added, I translated this program into Python
211 and added more:
212
213 9. A long-range scan is done silently whenever you call CHART; thus
214 the LRSCAN command is no longer needed.  (Controlled by OPTION_AUTOSCAN
215 and turned off if game type is "plain" or "almy".)
216
217 10. I imported Tom Almy's SCORE, CAPTURE, and CLOAK command from his
218 2013 version.
219
220 11. I added color.
221
222 TESTING:
223
224 This code has been designed to be tested.  A simple shellscript
225 included in the distribution, 'replay', automatically reruns the
226 last game you played.
227
228 See the "test" directory for regression-test logs and checkfiles.
229 Please run 'make check' every time you change this game to be sure
230 you haven't broken anything.  
231
232 When you fix a bug, add the log of the game that triggered it (and
233 a checkfile) to the regression tests. This is how we improve the code
234 coverage of the suite. 
235
236 Two things to do to the log before dropping it in the test directory:
237
238 (a) Strip out all lines beginning with "#curses:" - these are for debugging
239 the curses interface and are not needed for regression testing; removing
240 them makes it easier to see the game commands.
241
242 (b) Add a header comment line explaining what the log is a test for.
243 It should begin with "# Tests". This is what gets echoed before each
244 regression test is run.
245
246 Then drop it into the test directory and "make buildregress" to create
247 the check file. (Don't forget to commit and push the log and checkfile
248 to the repository.)
249
250 NOTES ON THE PYTHON TRANSLATION:
251
252 The Python translation was done with a regexp-based C-to-Python
253 translator I wrote for the purpose (I expect to release this as a
254 separate project).  I then hand-tuned and refactored the result.
255
256 The LOC count dropped by almost exactly 20% during this process, from
257 a bit over 8100 lines to a bit over 6500 lines.  If the code is still
258 shorter than that when you read this, it's because this file contains
259 most of what used to be a huge header comment.  
260
261 SST is not a data-structure- intensive program, so it compresses less
262 under translation to Python than the 50% drop in LOC I've found to be
263 more typical.  The gain in readability, though impossible to quantify,
264 is much greater than the drop in line count would suggest.
265
266 Some parts of the code, such as the finish() and score() functions, 
267 have barely been touched.  Code in the general category of report 
268 generators has tended to change little, especially since we've tried
269 to preserve the look and feel of the original.
270
271 On the other hand, the vector-arithmetic code around navigation and
272 torpedos, and deep-space-probe handling changed a lot.  All that 
273 stuff is now centralized in a 'course' object that hides the
274 trigonometric calculations.  
275
276 The course object builds on a 'coord' object, which I actually had
277 introduced while refactoring the C version.  Large parts of SST2K are,
278 perforce, an exercise in 2D vector arithmetic.  In the original
279 FORTRAN all the vector representation was done with parallel arrays;
280 in C, I introduced a struct; in Python, the class has a complete
281 repertoire of vector-algebra operations.
282
283 There's one weird archeological detail about the nav code that
284 deserves a remark.  This program originally required input in terms of
285 a (clock) direction and distance -- essentially, directions were real
286 numbers modulo 12 with zero being north.  Somewhere in history, it was
287 changed to Cartesian coordinates.  But the bearing method still computes
288 polar coordinates in clockface units -- that's the reason for the
289 wacky constant 1.90985, inherited straight from the ancestral FORTRAN.
290 Elsewhere, there were a bunch of computations, now centralized in the
291 course object, that looked like (15.0 - bearing)*0.5235988; this is a 
292 conversion from clockface units to radians with zero on the X axis.
293
294 As a previous maintainer, probably Tom Almy, observed: Probably
295 "manual" input should still be done this way -- it's a real pain if
296 the computer isn't working! Manual mode is still confusing because it
297 involves giving x and y motions, yet the coordinates are always
298 displayed y - x, where +y is downward!
299
300 Because I think he's arguably right, I haven't ripped out all the
301 clockface-to-radian conversions.  For this reason, and others, the 
302 trig code is still a bit wacky and obscure.  Modify with caution
303 and test thoroughly.
304
305 Adding or remobing random() calls is very likely to break lots of
306 regression tests. If you have to add new one, wrap them in a
307 save/restore of the LCG state; there's an example of this around
308 the setup for the Space Thingy.