This is the hackers' guide to SST2K. Read it before messing with the code. It consists of an introduction, a history, suggestions for regression testing, and some notes on the Python translation. For a to-do list, see TODO in the top-level directory. INTRODUCTION: SST2K is a Python translation of a C translation of a FORTRAN original dating back to 1973. Beautiful Python it is not, but it works. The intention of SST2K is to be able to replicate precisely the experience of the original game, while allowing new features to be added under option control. Therefore, be very conservative about what changes are visible under the 'plain' option. HISTORY: Dave Matuszek, one of the two original authors, says: SRSCAN, MOVE, PHASERS, CALL, STATUS, IMPULSE, PHOTONS, ABANDON, LRSCAN, WARP, SHIELDS, DESTRUCT, CHART, REST, DOCK, QUIT, and DAMAGE were in the original non-"super" version of UT FORTRAN Star Trek. Tholians were not in the original. Dave is dubious about their merits. (They are now controlled by OPTION_THOLIAN and turned off if the game type is "plain".) Planets and dilithium crystals were not in the original. Dave is OK with this idea. (It's now controlled by OPTION_PLANETS and turned off if the game type is "plain".) Dave says the bit about the Galileo getting turned into a McDonald's is "consistant with our original vision". (This has been left permanently enabled, as it can only happen if OPTION_PLANETS is on.) Dave also says the Space Thingy should not be preserved across saved games, so you can't prove to others that you've seen it. He says it shouldn't fire back, either. It should do nothing except scream and disappear when hit by photon torpedos. It's OK that it may move when attacked, but it didn't in the original. (Whether the Thingy can fire back is now controlled by OPTION_THINGY and turned off if the game type is "plain" or "almy". The no-save behavior has been restored.) The Faerie Queen, black holes, and time warping were in the original. Here are Tom Almy's changes: In early 1997, I got the bright idea to look for references to "Super Star Trek" on the World Wide Web. There weren't many hits, but there was one that came up with 1979 Fortran sources! This version had a few additional features that mine didn't have, however mine had some feature it didn't have. So I merged its features that I liked. I also took a peek at the DECUS version (a port, less sources, to the PDP-10), and some other variations. 1, Compared to the original UT version, I've changed the "help" command to "call" and the "terminate" command to "quit" to better match user expectations. The DECUS version apparently made those changes as well as changing "freeze" to "save". However I like "freeze". (Both "freeze" and "save" work in SST2K.) 2. The experimental deathray originally had only a 5% chance of success, but could be used repeatedly. I guess after a couple years of use, it was less "experimental" because the 1979 version had a 70% success rate. However it was prone to breaking after use. I upgraded the deathray, but kept the original set of failure modes (great humor!). (Now controlled by OPTION_DEATHRAY and turned off if game type is "plain".) 3. The 1979 version also mentions srscan and lrscan working when docked (using the starbase's scanners), so I made some changes here to do this (and indicating that fact to the player), and then realized the base would have a subspace radio as well -- doing a Chart when docked updates the star chart, and all radio reports will be heard. The Dock command will also give a report if a base is under attack. 4. Tholian Web from the 1979 version. (Now controlled by OPTION_THOLIAN and turned off if game type is "plain".) 5. Enemies can ram the Enterprise. (Now controlled by OPTION_RAMMING and turned off if game type is "plain".) 6. Regular Klingons and Romulans can move in Expert and Emeritus games. This code could use improvement. (Now controlled by OPTION_MVBADDY and turned off if game type is "plain".) 7. The deep-space probe feature from the DECUS version. (Now controlled by OPTION_PROBE and turned off if game type is "plain"). 8. 'emexit' command from the 1979 version. 9. Bugfix: Klingon commander movements are no longer reported if long-range sensors are damaged. 10. Bugfix: Better base positioning at startup (more spread out). That made sense to add because most people abort games with bad base placement. In June 2002, I fixed two known bugs and a documentation typo. In June 2004 I fixed a number of bugs involving: 1) parsing invalid numbers, 2) manual phasers when SR scan is damaged and commander is present, 3) time warping into the future, 4) hang when moving klingons in crowded quadrants. (These fixes are in SST2K.) Here are Stas Sergeev's changes: 1. The Space Thingy can be shoved, if you ram it, and can fire back if fired upon. (Now controlled by OPTION_THINGY and turned off if game type is "plain" or "almy".) 2. When you are docked, base covers you with an almost invincible shield. (A commander can still ram you, or a Romulan can destroy the base, or a SCom can even succeed with direct attack IIRC, but this rarely happens.) (Now controlled by OPTION_BASE and turned off if game type is "plain" or "almy".) 3. Ramming a black hole is no longer instant death. There is a chance you might get timewarped instead. (Now controlled by OPTION_BLKHOLE and turned off if game type is "plain" or "almy".) 4. The Tholian can be hit with phasers. 5. SCom can't escape from you if no more enemies remain (without this, chasing SCom can take an eternity). 6. Probe target you enter is now the destination quadrant. Before I don't remember what it was, but it was something I had difficulty using. 7. Secret password is now autogenerated. 8. "Plaque" is adjusted for A4 paper :-) 9. Phasers now tells you how much energy needed, but only if the computer is alive. 10. Planets are auto-scanned when you enter the quadrant. 11. Mining or using crystals in presense of enemy now yields an attack. There are other minor adjustments to what yields an attack and what does not. 12. "freeze" command reverts to "save", most people will understand this better anyway. (SST2K recognizes both.) 13. Screen-oriented interface, with sensor scans always up. (SST2K supports both screen-oriented and TTY modes.) Eric Raymond's changes: Mainly, I translated this C code out of FORTRAN into C -- created #defines for a lot of magic numbers and refactored the heck out of it. 1. "sos" and "call" becomes "mayday", "freeze" and "save" are both good. 2. Status report now indicates when dilithium crystals are on board. 3. Per Dave Matuszek's remarks, Thingy state is never saved across games. 4. Added game option selection so you can play a close (but not bug-for- bug identical) approximation of older versions. 5. Half the quadrants now have inhabited planets, from which one cannot mine dilithium (there will still be the same additional number of dilithium-bearing planets). Torpedoing an inhabited world is *bad*. There is BSD-Trek-like logic for Klingons to attack and enslave inhabited worlds, producing more ships (only is skill is 'good' or better). (Controlled by OPTION_WORLDS and turned off if game type is "plain" or "almy".) 6. User input is now logged so we can do regression testing. 7. More BSD-Trek features: You can now lose if your entire crew dies in battle. When abandoning ship in a game with inhabited worlds enabled, they must have one in the quadrant to beam down to; otherwise they die in space and this counts heavily against your score. Docking at a starbase replenishes your crew. 8. Still more BSD-Trek: we now have a weighted damage table. Quoth Eric Allman in the code of BSD-Trek: "Under certain conditions you can get a critical hit. This sort of hit damages devices. The probability that a given device is damaged depends on the device. Well protected devices (such as the computer, which is in the core of the ship and has considerable redundancy) almost never get damaged, whereas devices which are exposed (such as the warp engines) or which are particularly delicate (such as the transporter) have a much higher probability of being damaged." This is one place where OPTION_PLAIN does not restore the original behavior, which was equiprobable damage across all devices. If we wanted that, we'd return randrange(NDEVICES) and have done with it. Also, in the original game, DNAVSYS and DCOMPTR were the same device. Instead, we use a table of weights similar to the one from BSD Trek. BSD doesn't have the shuttle, shield controller, death ray, or probes. We don't have a cloaking device. The shuttle got the allocation for the cloaking device, then we shaved a half-percent off everything to have some weight to give DSHCTRL/DDRAY/DDSP. Also, the nav subsystem (enabling automatic course setting) can be damaged separately from the main computer (which handles weapons targeting, ETA calculation, and self-destruct). After these features were added, I translated this program into Python and added more: 9. A long-range scan is done silently whenever you call CHART; thus the LRSCAN command is no longer needed. (Controlled by OPTION_AUTOSCAN and turned off if game type is "plain" or "almy".) TESTING: This code has been designed to be tested. A simple shellscript included in the distribution, 'replay', automatically reruns the last game you played. See the "test" directory for regression-test logs and checkfiles. Please run 'make check' every time you change this game to be sure you haven't broken anything. When you fix a bug, add the log of the game that triggered it (and a checkfile) to the regression tests. This is how we improve the code coverage of the suite. Two things to do to the log before dropping it in the test directory: (a) Strip out all lines beginning with "#curses:" - these are for debugging the curses interface and are not needed or regression testing; removing them makes it easier to see the game commands. (b) Add a header comment line explaining what the log is a test for. It should begin with "# Tests". This is what gets echoed before each regression test is run. Then drop it into the test directory and "make buildregress" to create the check file. (Don't forget to commit and push the log and checkfile to the repository.) NOTES ON THE PYTHON TRANSLATION: The Python translation was done with a regexp-based C-to-Python translator I wrote for the purpose (I expect to release this as a separate project). I then hand-tuned and refactored the result. The LOC count dropped by almost exactly 20% during this process, from a bit over 8100 lines to a bit over 6500 lines. If the code is still shorter than that when you read this, it's because this file contains most of what used to be a huge header comment. SST is not a data-structure- intensive program, so it compresses less under translation to Python than the 50% drop in LOC I've found to be more typical. The gain in readability, though impossible to quantify, is much greater than the drop in line count would suggest. Some parts of the code, such as the finish() and score() functions, have barely been touched. Code in the general category of report generators has tended to change little, especially since we've tried to preserve the look and feel of the original. On the other hand, the vector-arithmetic code around navigation and torpedos, and deep-space-probe handling changed a lot. All that stuff is now centralized in a 'course' object that hides the trigonometric calculations. The course object builds on a 'coord' object, which I actually had introduced while refactoring the C version. Large parts of SST2K are, perforce, an exercise in 2D vector arithmetic. In the original FORTRAN all the vector representation was done with parallel arrays; in C, I introduced a struct; in Python, the class has a complete repertoire of vector-algebra operations. There's one weird archeological detail about the nav code that deserves a remark. This program originally required input in terms of a (clock) direction and distance -- essentially, directions were real numbers modulo 12 with zero being north. Somewhere in history, it was changed to Cartesian coordinates. But the bearing method still computes polar coordinates in clockface units -- that's the reason for the wacky constant 1.90985, inherited straight from the ancestral FORTRAN. Elsewhere, there were a bunch of computations, now centralized in the course object, that looked like (15.0 - bearing)*0.5235988; this is a conversion from clockface units to radians with zero on the X axis. As a previous maintainer, probably Tom Almy, observed: Probably "manual" input should still be done this way -- it's a real pain if the computer isn't working! Manual mode is still confusing because it involves giving x and y motions, yet the coordinates are always displayed y - x, where +y is downward! Because I think he's arguably right, I haven't ripped out all the clockface-to-radian conversions. For this reason, and others, the trig code is still a bit wacky and obscure. Modify with caution and test thoroughly.