Ready to ship 2.8 master 2.8
authorEric S. Raymond <esr@thyrsus.com>
Sun, 11 Feb 2024 03:33:35 +0000 (22:33 -0500)
committerEric S. Raymond <esr@thyrsus.com>
Sun, 11 Feb 2024 03:33:35 +0000 (22:33 -0500)
79 files changed:
.gitignore
.gitlab-ci.yml [new file with mode: 0644]
Makefile
NEWS
control
doc/HACKING
doc/Makefile
doc/makehelp.py
doc/sst-doc.xml
doc/sst.xml
po/msgfmt.py
replay
sst [new file with mode: 0755]
sst.py [deleted file]
test/Makefile
test/tapdiffer [new file with mode: 0755]
test/tapview [new file with mode: 0755]
test/test01.chk
test/test01.log
test/test02.chk
test/test02.log
test/test03.chk
test/test03.log
test/test04.chk
test/test04.log
test/test05.chk
test/test05.log
test/test06.chk
test/test06.log
test/test07.chk
test/test07.log
test/test08.chk
test/test08.log
test/test09.chk
test/test09.log
test/test10.chk
test/test10.log
test/test11.chk
test/test11.log
test/test12.chk [new file with mode: 0644]
test/test12.log [new file with mode: 0644]
test/test13.chk [new file with mode: 0644]
test/test13.log [new file with mode: 0644]
test/test14.chk [new file with mode: 0644]
test/test14.log [new file with mode: 0644]
test/test15.chk [new file with mode: 0644]
test/test15.log [new file with mode: 0644]
test/test16.chk [new file with mode: 0644]
test/test16.log [new file with mode: 0644]
test/test17.chk [new file with mode: 0644]
test/test17.log [new file with mode: 0644]
test/test18.chk [new file with mode: 0644]
test/test18.log [new file with mode: 0644]
test/test19.chk [new file with mode: 0644]
test/test19.log [new file with mode: 0644]
test/test20.chk [new file with mode: 0644]
test/test20.log [new file with mode: 0644]
test/test21.chk [new file with mode: 0644]
test/test21.log [new file with mode: 0644]
test/test22.chk [new file with mode: 0644]
test/test22.log [new file with mode: 0644]
test/test23.chk [new file with mode: 0644]
test/test23.log [new file with mode: 0644]
test/test24.chk [new file with mode: 0644]
test/test24.log [new file with mode: 0644]
test/test25.chk [new file with mode: 0644]
test/test25.log [new file with mode: 0644]
test/test26.chk [new file with mode: 0644]
test/test26.log [new file with mode: 0644]
test/test27.chk [new file with mode: 0644]
test/test27.log [new file with mode: 0644]
test/test28.chk [new file with mode: 0644]
test/test28.log [new file with mode: 0644]
test/test29.chk [new file with mode: 0644]
test/test29.log [new file with mode: 0644]
test/test30.chk [new file with mode: 0644]
test/test30.log [new file with mode: 0644]
test/test31.chk [new file with mode: 0644]
test/test31.log [new file with mode: 0644]

index fabcf9ef41e10ab03c8b473e88a930abde6d3d34..8e3a213315e6ceaca4838356b19f31979df72002 100644 (file)
@@ -1,6 +1,7 @@
 index.html
 sst.pyc
 sst.html
+sst-doc.html
 sst.6
 doc/sst.doc
 doc/sst-doc.txt
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644 (file)
index 0000000..763985c
--- /dev/null
@@ -0,0 +1,11 @@
+image: ubuntu
+
+before_script:
+  - apt-get update
+  - apt-get -qy upgrade
+  - apt-get -y install make python2 python3 pylint
+
+test:
+  script:
+  - echo "Running as ${USER:-root}"
+  - make check
index 9e6b9cf5885bc2254498e2f506e9eb0aeb7b8a2b..6fb8a62199f46d8f12d174d588a109e75e9c613e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,20 @@
 # Makefile for the SST2K project
+#
+# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
+# SPDX-License-Identifier: BSD-2-Clause
 
-VERS=$(shell sed <sst.py -n -e '/version *= \"*\(.*\)\"/s//\1/p')
+VERS=$(shell sed <sst -n -e '/version *= \"*\(.*\)\"/s//\1/p')
 
 MANDIR=/usr/share/man/man1
 BINDIR=/usr/bin
 
 DOCS    = README COPYING NEWS doc/HACKING doc/sst-doc.xml doc/sst-layer.xsl doc/sst.xml
-SOURCES = sst.py Makefile replay doc/makehelp.py control $(DOCS)
+SOURCES = sst Makefile replay doc/makehelp.py control $(DOCS)
 
 all: super-star-trek-$(VERS).tar.gz
 
 install: sst.6
-       cp sst.py $(BINDIR)
+       cp sst $(BINDIR)
        gzip <sst.6 >$(MANDIR)/sst.6.gz
 
 sst.6: doc/sst.xml
@@ -28,24 +31,27 @@ super-star-trek-$(VERS).tar.gz: $(SOURCES) sst.6
 
 dist: sst-$(VERS).tar.gz
 
-check: #pylint
-       cd test; $(MAKE) --quiet
+check: pylint
+       @cd test >/dev/null; $(MAKE) --quiet
+
+reflow:
+       @black sst
 
-COMMON_PYLINT = --rcfile=/dev/null --reports=n \
-       --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" \
-       --dummy-variables-rgx='^_'
-PYLINTOPTS = $(COMMON_PYLINT) --disable=C0103,C0111,C0113,C1001,C0301,C0302,C0321,C0325,C0326,C0410,C1801,E1120,R0101,R0902,R0903,R0911,R0912,R0914,R0915,R0916,R1705,R1706,R1710,W0110,W0123,W0141,W0232,W0312,W0603,W0611
 pylint:
-       @pylint --output-format=parseable $(PYLINTOPTS) sst.py
+       @pylint --score=n sst
 
 clean:
-       rm -f sst.6 sst.html
+       rm -f sst.6 sst.html sst-doc.html
        rm -f *.6 MANIFEST index.html
 
+NEWSVERSION=$(shell sed -n <NEWS '/^[0-9]/s/:.*//p' | head -1)
+
 SHIPPER = version=$(VERS) bkgimage=lpt.jpg
 
 release: super-star-trek-$(VERS).tar.gz sst.html sst-doc.html
+       @[ $(VERS) = $(NEWSVERSION) ] || { echo "Version mismatch!"; exit 1; }
        shipper $(SHIPPER) | sh -e -x
 
 refresh: sst.html
+       @[ $(VERS) = $(NEWSVERSION) ] || { echo "Version mismatch!"; exit 1; }
        shipper -N -w $(SHIPPER)  | sh -e -x
diff --git a/NEWS b/NEWS
index 4d7c4d4030db2a06809334b9fb24a9121e9ce5e2..3959d92604f6e65fd93dcb6fb045c586fcbcabe1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,18 @@
                        SST2K project news.
 
-Repository head::
+2.8: 2024-02-10:
+    Fix for enemy dispersion on torpedo hits.
+    Re-conform to the documentation by removing the .py estension from sst.
+    Fancy-mode coordinates can have the Y as a letter, e,g. "c4" = "3 - 4".
+    Wayback option: you can revert the game to the behavior of past years.
+
+2.7: 2021-09-20::
+    Ubuntu has abolished /usr/bin/python, change shebang to python3.
+
+2.6: 2021-04-16::
     Fixed a longstanding bug in the chart display.
+    Minor port fixes for recent Python 23 versions.
+    Test suite is TAPified.
 
 2.5: 2019-04-24::
     Now runs identically under Python 2 and Python 3.
diff --git a/control b/control
index 3311e7fc82d9abfc5b0d864dd238102d780a567f..2af21bf753391cec4b9e9e34d4c0019d942c1648 100644 (file)
--- a/control
+++ b/control
@@ -1,5 +1,8 @@
 # This is not a real Debian control file, though the syntax is compatible.
 # It's project metadata for the shipper tool
+#
+# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
+# SPDX-License-Identifier: BSD-2-Clause
 
 Package: super-star-trek
 
@@ -47,4 +50,4 @@ XBS-Logo: trek.png
 
 XBS-VC-Tag-Template: %(version)s
 
-XBS-Validate: make pylint check
+XBS-Validate: make check
index abb692a03c587f1713645034d9ac8aa82058e7cb..e9404396b90eca07c6469aba67e9c6207687743a 100644 (file)
@@ -40,11 +40,15 @@ 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.)
+when attacked, but it didn't in the original. (The no-save behavior
+has been restored.)
 
-The Faerie Queen, black holes, and time warping were in the original.
+Dave says the Faerie Queen, black holes, and time warping were in the
+original.  However, either he is misremembering about time warping or
+the original implementation was lost during the FORTRAN-to-C
+translation, as Stas Sergeev added a time-warping feature not
+previiusly present in 2006.  Tom Almy also claims to have added
+timewarping!
 
 Here are Tom Almy's changes:
 
@@ -298,3 +302,7 @@ 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.
 
+Adding or remobing random() calls is very likely to break lots of
+regression tests. If you have to add new one, wrap them in a
+save/restore of the LCG state; there's an example of this around
+the setup for the Space Thingy.
index 6d5909dfdde44a5cf1a02e2f8ee61c106c719302..d115c60dd622ce4590ca2f30a3930322338e8acc 100644 (file)
@@ -1,5 +1,8 @@
 # From this directory, distribute the following files:
 # HACKING makehelp.py sst-doc.xml sst-layer.xsl sst.xml
+#
+# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
+# SPDX-License-Identifier: BSD-2-Clause
 
 sst.6: sst.xml
        xmlto man sst.xml
index 835b8731394524155444e446ef5229ce5b45106c..bbd317b37fc61874bcb79b19828178943bf6e5c4 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Generate an on-line help file for SST 2K from the text generated from
 # the XML documentation.
index 6f7051fd28304731c8ae4f2ec5b2d642a48aedf7..b07f3e6723b465f834809a9cb2a0e0a105a10a3b 100644 (file)
@@ -5,6 +5,10 @@
 <!ENTITY sst-site      "http://catb.org/~esr/super-star-trek/">
 <!ENTITY retro         "http://catb.org/~esr/retro/">
 ]>
+<!--
+Copyright by Eric S. Raymond
+SPDX-License-Identifier: BSD-2-clause
+-->
 <book>
 <bookinfo>
 <title>Super Star Trek</title>
@@ -251,16 +255,85 @@ game&mdash;but, of course, the level of game you play is up to you.  If
 you want to start at the Expert level, go ahead.  It's your funeral.
 The Emeritus game is strictly for masochists.</para>
 
-<para>The fourth question, new in SST2K, sets your game options.  A
-blank answer or 'fancy' enables all SST2K features.  The option
-'plain' approximated the original CDC 6600 FORTRAN game from UT Austin
-and disables a number of features: Tholians, planets &amp; dilithium,
-Thingies shooting back, deep-space-probes, Klingon ramming and
-movement, time-warping through black holes, death-ray
-upgrade. inhabited worlds.  The option 'almy' approximates Tom Almy's
-C translation from 1979, disabling Thingies shooting back, base
-shields, time-warping through black holes, and inhabited
-worlds.</para>
+<para>The fourth question, new in SST2K, sets the wayback machine.  A
+blank answer enables all SST2K features.  Given a year, it will disable
+features not implemented in that year or earlier. The year
+'1973' approximated the original CDC 6600 FORTRAN game from UT Austin.
+Here is a mapping of years to features:</para>
+
+<variablelist>
+<varlistentry>
+<term>1974</term>
+<listitem><para>Planets and dilithium mining</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>1979</term>
+<listitem><para>Tholians and their webs, supercommanders.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>1980</term>
+<listitem><para>Deep-space probes.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>1981</term>
+<listitem><para>Bad guys do tactical movement.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>1982</term>
+<listitem><para>Bad guys can ram you.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>1997</term>
+<listitem><para>Death ray gets an upgrade.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>1998</term>
+<listitem><para>Automatic generation of self-destruct password.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2004</term>
+<listitem><para>Upgraded shields for bases, and chance of time-waeping through a black hole.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2005</term>
+<listitem><para>Our ship is bracketed in the chart/</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2006</term>
+<listitem><para>Logic for inhabited worlds and Klingon captures.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2007</term>
+<listitem><para>Automatically update the long-range scan when displaying the chart.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2010</term>
+<listitem><para>Use color in interface.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2013</term>
+<listitem><para>Defeated Klingons can be captured.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2014</term>
+<listitem><para>The cloaking device.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2019</term>
+<listitem><para>Consistent dot-filling in the galaxy chart.</para></listitem>
+</varlistentry>
+<varlistentry>
+<term>2023</term>
+<listitem><para>Alphameric coordinates.</para></listitem>
+</varlistentry>
+</variablelist>
+
+<para>Some caveats apply.  The development history of this game is obscure; some
+years of introduction have had to be guessed, and we have chosen guesses to
+make support as many interesting wayback options as possible.  Some options
+are not affected by the wayback setting - notably, the TUI interface is always
+available even though it wasn't written until 2005.  Some early features,
+notably "clockface" course setting, couldn't be reconstructed.</para>
 
 </chapter>
 <chapter><title>How To Issue Commands</title>
@@ -383,12 +456,29 @@ described by an example.</para>
      10  . . . . . . . . . .  Time Left     3.72
 </screen>
 
+<para>In fancy mode, the display will use letters for Y coordinates.</para>
+
+<screen>
+         1 2 3 4 5 6 7 8 9 10
+      a  * . . . . R . . . .  Stardate      2516.3
+      b  . . . E . . . . . .  Condition     RED  
+      c  . . . . . * . B . .  Position      e1, b4
+      d  . . . S . . . . . .  Life Support  DAMAGED, Reserves=2.30
+      e  . . . . . . . K . .  Warp Factor   5.0
+      f  . K .   . . . . * .  Energy        2176.24
+      g  . . . . . P . . . .  Torpedoes     3
+      h  . . . . * . . . . .  Shields       UP, 42% 1050.0 units
+      i  . * . . * . . . C .  Klingons Left 12
+      j  . . . . . . . . . .  Time Left     3.72
+</screen>
+
+
 <para>The left part is a picture of the quadrant.  The E at sector 2 -
-4 represents the Enterprise; the B at sector 3 - 8 is a starbase.
-There are ordinary Klingons (K) at sectors 5 - 8 and 6 - 2, and a
-Klingon Commander (C) at 9 - 9.  The (GULP)
-<quote>Super-commander</quote> (S) is occupies sector 4 - 4, and a
-Romulan (R) is at 1 - 6.  An uninhabited planet (P) is at sector 7 - 6
+4 (or b4) represents the Enterprise; the B at sector 3 - 8 (or c8) is a starbase.
+There are ordinary Klingons (K) at sectors 5 - 8 (e8) and 6 - 2 (f2), and a
+Klingon Commander (C) at 9 - 9 (i9).  The (GULP)
+<quote>Super-commander</quote> (S) is occupies sector 4 - 4 (d4), and a
+Romulan (R) is at 1 - 6 (a6).  An uninhabited planet (P) is at sector 7 - 6 (g6)
 (if it were inhabited, it would display as a '@').  There are
 also a large number of stars (*). The periods (.) are just empty
 space&mdash;they are printed to help you get your bearings.  Sector 6
@@ -733,6 +823,23 @@ the current quadrant, the shortest command would be</para>
 <para>and it will be done.  In automatic mode, either two or four numbers
 must be supplied.</para>
 
+<para> If your game is in "fancy" mode, there ia a way to input
+coordinates that avoids any need to remember thet the Y coordinate
+comes first.  Y values may be given as lowercase letters starting with
+a = 1. So for example:</para>
+
+<screen>
+       a1 = 1 - 1
+       c5 = 3 - 5
+       f2 = 6 - 2
+</screen>
+
+<para>The previous move xommand could be expressed as</para>
+
+<screen>
+       m a c7 e8
+</screen>
+
 <para>Automatic mode utilizes the ship's <quote>battle
 computer.</quote> If the computer is damaged, manual movement must be
 used.</para>
@@ -942,7 +1049,7 @@ will hurt your final score.</para>
 
 <literallayout>
 Mnemonic:  CAPTURE
-Shortest abbreviation:  CA
+Shortest abbreviation:  CAPTURE
 Full commands:  CAPTURE
 </literallayout>
 
@@ -1060,6 +1167,14 @@ you can enter</para>
 <para>to aim between two sectors.  However, sector numbers must be 1 to 10
 inclusive.</para>
 
+<para>In fancy mode, you can write "PHO 3 2 6 1 10 4 7" as</para>
+
+<screen>
+     pho 3 b6 a10 d7
+</screen>
+
+<para>Fractional Y coordinates are not supported.</para>
+
 </sect1>
 <sect1><title>Dock at Starbase</title>
 
@@ -1501,6 +1616,20 @@ Full command:  CURSES
 <para>Switch from tty to curses interface. Mainly useful for
 debugging, when continuing a replayed game.</para>
 
+</sect1>
+<sect1><title>Option setting</title>
+
+<literallayout>
+Mnemonic:  OP
+Full command:  OPTIONS
+               OPTIONS SET
+              OPTIONS CLEAR
+</literallayout>
+
+<para>Set or clear feature flags. With no argument, list feature flags. The verbs SET and CLEAR
+are available to set or clear a list of feature flags following on the line.  Mainly useful
+for development and improving test coverage.</para>
+
 </sect1>
 </chapter>
 <chapter><title>Miscellaneous Notes</title>
@@ -1657,6 +1786,7 @@ orientation</quote>.</para>
  T         TRANSPORT                              transporter
  W         WARP &lt;FACTOR&gt;                          (none)
  CU        CURSES                                 (none)
+ OP        OPTIONS                                (none)
  
  L. R. Scan:   thousands digit:   supernova
                hundreds digit:    Klingons
@@ -2086,7 +2216,7 @@ child.</para></listitem>
 first FORTRAN version Tom Almy saw, on which he based his later C
 translation.</para></listitem>
 
-<listitem><para>1979 &mdash; Marc Newman adds Tholians, black holes,
+<listitem><para>1979 &mdash; Marc Newman adds Tholians,
 super-commanders, and Emeritus mode.</para></listitem>
 
 <listitem><para>1995-1996 &mdash; Tom Almy translates his FORTRAN
@@ -2122,6 +2252,10 @@ Cloaking device and capture command added from BSD (via Almy's
 uniformly dot-filled. (Suppressed in the plain and almy
 interface styles.)</para></listitem>
 
+<listitem><para>25 August 2023 &mdash; Coordinates optionally in
+alphameric mode, e.g "b3" rather than "2 - 3". (Suppressed in the
+plain and almy interface styles.)</para></listitem>
+
 
 </itemizedlist>
 
index 1fbe4a6dc0e99e183137f8d6b146d1924698ae30..c347168308c8f20f76b9b470819183629beb3bff 100644 (file)
@@ -3,6 +3,10 @@
 "docbook/docbookx.dtd" [
 <!ENTITY projecthome      'http://www.catb.org/~esr/super-star-trek'>
 ]>
+<!--
+Copyright by Eric S. Raymond
+SPDX-License-Identifier: BSD-2-clause
+-->
 <refentry id='sst.6'>
 <refmeta>
 <refentrytitle>sst</refentrytitle>
@@ -39,7 +43,7 @@ invasion fleet and make the galaxy safe for democracy.</para>
 
 <para>This is one of the great early classic computer games from the
 1970s and still has a remarkable amount of play value. Run
-<command>sst.py</command> in a terminal window to start it.  Typing
+<command>sst</command> in a terminal window to start it.  Typing
 'commands' at the prompt will list all commands; help is available for
 each one individually as well.  Full documentation is <ulink
 url='&projecthome;/sst-doc.html'>browseable</ulink>.  On
index 64331313cd6da95649018a8b037648650670bc81..c777437307bac4910bb7497c4103419a3a618af3 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 # -*- coding: iso-8859-1 -*-
 # Written by Martin v. Löwis <loewis@informatik.hu-berlin.de>
 
diff --git a/replay b/replay
index a5a93517f51bf66caa1666e0bea23841d728ef36..7fc0641555e615b4e145b4f90ef2a6abedff7b9e 100755 (executable)
--- a/replay
+++ b/replay
@@ -12,4 +12,4 @@ then
 else
     mv $TMP/sst-input.log replay.log
 fi
-python sst.py -t -r replay.log
+python3 sst -t -r replay.log
diff --git a/sst b/sst
new file mode 100755 (executable)
index 0000000..0c0ace9
--- /dev/null
+++ b/sst
@@ -0,0 +1,7651 @@
+#!/usr/bin/env python3
+"""
+sst.py -- Super Star Trek 2K
+
+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.  Translation by Eric S. Raymond; original game by David Matuszek
+and Paul Reynolds, with modifications by Don Smith, Tom Almy,
+Stas Sergeev, and Eric S. Raymond.
+
+See the doc/HACKING file in the distribution for designers notes and advice
+on how to modify (and how not to modify!) this code.
+"""
+# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
+# SPDX-License-Identifier: BSD-2-Clause
+
+# pylint: disable=line-too-long,superfluous-parens,too-many-lines,invalid-name,missing-function-docstring,missing-class-docstring,multiple-statements,too-many-branches,too-many-statements,too-many-locals,too-many-nested-blocks,too-many-return-statements,too-many-instance-attributes,global-statement,no-else-break,no-else-return,no-else-continue,too-few-public-methods,too-many-boolean-expressions,consider-using-f-string,consider-using-enumerate,consider-using-with,unspecified-encoding,consider-using-generator
+
+# pylint: disable=multiple-imports
+import os, sys, math, curses, time, pickle, copy, gettext, getpass
+import getopt, socket
+import codecs
+
+# This import only works on Unixes.  The intention is to enable
+# Ctrl-P, Ctrl-N, and friends in Cmd.
+try:
+    # pylint: disable=unused-import
+    import readline
+except ImportError:  # pragma: no cover
+    pass
+
+version = "2.8"
+
+docpath = (".", "doc/", "/usr/share/doc/sst/")
+
+
+def _(st):
+    return gettext.gettext(st)
+
+
+# Rolling our own LCG because Python changed its incompatibly in 3.2.
+# Thus, we needed to have our own to be 2/3 polyglot; it will be
+# helpful when and if we ever forward-port to another language.
+
+
+class randomizer:
+    # LCG PRNG parameters tested against
+    # Knuth vol. 2. by the authors of ADVENT
+    LCG_A = 1093
+    LCG_C = 221587
+    LCG_M = 1048576
+
+    @staticmethod
+    def random():
+        old_x = game.lcg_x
+        game.lcg_x = (
+            randomizer.LCG_A * game.lcg_x + randomizer.LCG_C
+        ) % randomizer.LCG_M
+        return old_x / randomizer.LCG_M
+
+    @staticmethod
+    def withprob(p):
+        v = randomizer.random()
+        # if logfp:
+        #    logfp.write("#withprob(%.2f) -> %s\n" % (p, v < p))
+        return v < p
+
+    @staticmethod
+    def integer(*args):
+        v = randomizer.random()
+        if len(args) == 1:
+            v = int(v * args[0])
+        else:
+            v = args[0] + int(v * (args[1] - args[0]))
+        # if logfp:
+        #    logfp.write("#integer%s -> %s\n" % (args, v))
+        return int(v)
+
+    @staticmethod
+    def real(*args):
+        v = randomizer.random()
+        if len(args) == 1:
+            v *= args[0]  # from [0, args[0])
+        elif len(args) == 2:
+            v = args[0] + v * (args[1] - args[0])  # from [args[0], args[1])
+        # if logfp:
+        #    logfp.write("#real%s -> %f\n" % (args, v))
+        return v
+
+    @staticmethod
+    def seed(n):
+        # if logfp:
+        #    logfp.write("#seed(%d)\n" % n)
+        game.lcg_x = n % randomizer.LCG_M
+
+    @staticmethod
+    def getrngstate():
+        return game.lcg_x
+
+    @staticmethod
+    def setrngstate(n):
+        game.lcg_x = n
+
+
+GALSIZE = 8  # Galaxy size in quadrants
+NINHAB = GALSIZE * GALSIZE // 2  # Number of inhabited worlds
+MAXUNINHAB = 10  # Maximum uninhabited worlds
+QUADSIZE = 10  # Quadrant size in sectors
+BASEMIN = 2  # Minimum starbases
+BASEMAX = GALSIZE * GALSIZE // 12  # Maximum starbases
+MAXKLGAME = 127  # Maximum Klingons per game
+MAXKLQUAD = 9  # Maximum Klingons per quadrant
+FULLCREW = 428  # Crew size. BSD Trek was 387, that's wrong
+FOREVER = 1e30  # Time for the indefinite future
+MAXBURST = 3  # Max # of torps you can launch in one turn
+MINCMDR = 10  # Minimum number of Klingon commanders
+DOCKFAC = 0.25  # Repair faster when docked
+PHASEFAC = 2.0  # Phaser attenuation factor
+
+ALGERON = 2311  # Date of the Treaty of Algeron
+
+
+DEFAULT = -1
+BLACK = 0
+BLUE = 1
+GREEN = 2
+CYAN = 3
+RED = 4
+MAGENTA = 5
+BROWN = 6
+LIGHTGRAY = 7
+DARKGRAY = 8
+LIGHTBLUE = 9
+LIGHTGREEN = 10
+LIGHTCYAN = 11
+LIGHTRED = 12
+LIGHTMAGENTA = 13
+YELLOW = 14
+WHITE = 15
+
+
+class TrekError(Exception):
+    pass
+
+
+class JumpOut(Exception):
+    pass
+
+
+def letterize(n):
+    return chr(ord("a") + n - 1)
+
+
+class Coord:
+    def __init__(self, x=None, y=None):
+        self.i = x  # Row
+        self.j = y  # Column
+
+    def valid_quadrant(self):
+        return (
+            (self.i is not None)
+            and (self.j is not None)
+            and (self.i >= 0)
+            and (self.i < GALSIZE)
+            and (self.j >= 0)
+            and (self.j < GALSIZE)
+        )
+
+    def valid_sector(self):
+        return (
+            (self.i is not None)
+            and (self.j is not None)
+            and (self.i >= 0)
+            and (self.i < QUADSIZE)
+            and (self.j >= 0)
+            and (self.j < QUADSIZE)
+        )
+
+    def invalidate(self):
+        self.i = self.j = None
+
+    def __eq__(self, other):
+        return other is not None and self.i == other.i and self.j == other.j
+
+    def __ne__(self, other):
+        return other is None or self.i != other.i or self.j != other.j
+
+    def __add__(self, other):
+        return Coord(self.i + other.i, self.j + other.j)
+
+    def __sub__(self, other):
+        return Coord(self.i - other.i, self.j - other.j)
+
+    def __mul__(self, other):
+        return Coord(self.i * other, self.j * other)
+
+    def __rmul__(self, other):
+        return Coord(self.i * other, self.j * other)
+
+    def __div__(self, other):  # pragma: no cover
+        return Coord(self.i / other, self.j / other)
+
+    def __truediv__(self, other):  # pragma: no cover
+        return Coord(self.i / other, self.j / other)
+
+    def __floordiv__(self, other):  # pragma: no cover
+        return Coord(self.i // other, self.j // other)
+
+    def __mod__(self, other):
+        return Coord(self.i % other, self.j % other)
+
+    def __rtruediv__(self, other):  # pragma: no cover
+        return Coord(self.i / other, self.j / other)
+
+    def __rfloordiv__(self, other):  # pragma: no cover
+        return Coord(self.i // other, self.j // other)
+
+    def roundtogrid(self):
+        return Coord(int(round(self.i)), int(round(self.j)))
+
+    def distance(self, other=None):
+        if not other:
+            other = Coord(0, 0)
+        return math.sqrt((self.i - other.i) ** 2 + (self.j - other.j) ** 2)
+
+    def bearing(self):
+        return 1.90985 * math.atan2(self.j, self.i)
+
+    def sgn(self):
+        s = Coord()
+        if self.i == 0:
+            s.i = 0
+        elif self.i < 0:
+            s.i = -1
+        else:
+            s.i = 1
+        if self.j == 0:
+            s.j = 0
+        elif self.j < 0:
+            s.j = -1
+        else:
+            s.j = 1
+        return s
+
+    def quadrant(self):
+        # print "Location %s -> %s" % (self, (self / QUADSIZE).roundtogrid())
+        return self.roundtogrid() // QUADSIZE
+
+    def sector(self):
+        return self.roundtogrid() % QUADSIZE
+
+    def __str__(self):
+        if self.i is None or self.j is None:
+            return "Nowhere"  # pragma: no cover
+        if game.options & OPTION_ALPHAMERIC:
+            return letterize(self.i + 1) + str(self.j + 1)
+        return "%s - %s" % (self.i + 1, self.j + 1)
+
+    __repr__ = __str__
+
+
+class Thingy:
+    "Do not anger the Space Thingy!"
+
+    def __init__(self):
+        self.location = Coord()
+
+    def at(self, q):
+        return (q.i, q.j) == (self.location.i, self.location.j)
+
+
+class Planet:
+    def __init__(self):
+        self.name = None  # string-valued if inhabited
+        self.quadrant = Coord()  # quadrant located
+        self.pclass = None  # could be ""M", "N", "O", or "destroyed"
+        self.crystals = "absent"  # could be "mined", "present", "absent"
+        self.known = "unknown"  # could be "unknown", "known", "shuttle_down"
+        self.inhabited = False  # is it inhabited?
+
+    def __str__(self):
+        return self.name
+
+
+class Quadrant:
+    def __init__(self):
+        self.stars = 0
+        self.planet = None
+        self.starbase = False
+        self.klingons = 0
+        self.romulans = 0
+        self.supernova = False
+        self.charted = False
+        self.status = "secure"  # Could be "secure", "distressed", "enslaved"
+
+    def __str__(self):
+        return "<Quadrant: %(klingons)d>" % self.__dict__  # pragma: no cover
+
+    __repr__ = __str__
+
+
+class Page:
+    def __init__(self):
+        self.stars = None
+        self.starbase = False
+        self.klingons = None
+
+    def __repr__(self):
+        return "<%s,%s,%s>" % (
+            self.klingons,
+            self.starbase,
+            self.stars,
+        )  # pragma: no cover
+
+
+def fill2d(size, fillfun):
+    "Fill an empty list in 2D."
+    lst = []
+    for i in range(size):
+        lst.append([])
+        for j in range(size):
+            lst[i].append(fillfun(i, j))
+    return lst
+
+
+class Snapshot:
+    def __init__(self):
+        self.snap = False  # snapshot taken
+        self.crew = 0  # crew complement
+        self.nscrem = 0  # remaining super commanders
+        self.starkl = 0  # destroyed stars
+        self.basekl = 0  # destroyed bases
+        self.nromrem = 0  # Romulans remaining
+        self.nplankl = 0  # destroyed uninhabited planets
+        self.nworldkl = 0  # destroyed inhabited planets
+        self.planets = []  # Planet information
+        self.date = 0.0  # stardate
+        self.remres = 0  # remaining resources
+        self.remtime = 0  # remaining time
+        self.baseq = []  # Base quadrant coordinates
+        self.kcmdr = []  # Commander quadrant coordinates
+        self.kscmdr = Coord()  # Supercommander quadrant coordinates
+        # the galaxy
+        self.galaxy = fill2d(GALSIZE, lambda i_unused, j_unused: Quadrant())
+        # the starchart
+        self.chart = fill2d(GALSIZE, lambda i_unused, j_unused: Page())
+
+    def traverse(self):
+        for i in range(GALSIZE):
+            for j in range(GALSIZE):
+                yield (i, j, self.galaxy[i][j])
+
+
+class Event:
+    def __init__(self):
+        self.date = None  # A real number
+        self.quadrant = None  # A coord structure
+
+
+# game options
+OPTION_ALL = 0xFFFFFFFF
+OPTION_TTY = 0x00000001  # old interface
+OPTION_CURSES = 0x00000002  # new interface
+OPTION_IOMODES = 0x00000003  # cover both interfaces
+OPTION_PLANETS = 0x00000004  # planets and mining (> 1974)
+OPTION_THOLIAN = 0x00000008  # Tholians and their webs (UT 1979 version)
+OPTION_SUPERCMDR = 0x00000010  # Supercommanders (UT 1979 version)
+OPTION_PROBE = 0x00000020  # deep-space probes (DECUS version, 1980)
+OPTION_MVBADDY = 0x00000040  # more enemies can move (Almy, 1979?)
+OPTION_RAMMING = 0x00000080  # enemies may ram Enterprise (Almy, 1979?)
+OPTION_ALMY = 0x00000100  # Almy's death ray upgrade (1997?)
+OPTION_AUTOPASS = 0x00000200  # Autogenerate password (Almy, 1997?)
+OPTION_BASE = 0x00000400  # bases have good shields (Stas, 2005)
+OPTION_BLKHOLE = 0x00000800  # black hole may timewarp you (Stas, 2005)
+OPTION_SHOWME = 0x00001000  # bracket Enterprise in chart (ESR, 2005)
+OPTION_WORLDS = 0x00002000  # logic for inhabited worlds (ESR, 2006)
+OPTION_AUTOSCAN = 0x00004000  # automatic LRSCAN before CHART (ESR, 2006)
+OPTION_COLOR = 0x00008000  # enable color display (ESR, 2010)
+OPTION_CAPTURE = 0x00010000  # Enable BSD-Trek capture (Almy, 2013).
+OPTION_CLOAK = 0x10020000  # Enable BSD-Trek capture (Almy, 2013).
+OPTION_DOTFILL = 0x01040000  # fix dotfill glitch in chart (ESR, 2019)
+OPTION_ALPHAMERIC = 0x00080000  # Alpha Y coordinates (ESR, 2023)
+
+option_names = {
+    "ALL": (OPTION_ALL, 0),
+    "TTY": (OPTION_TTY, 0),
+    "IOMODES": (OPTION_IOMODES, 0),
+    "PLANETS": (OPTION_PLANETS, 1974),
+    "THOLIAN": (OPTION_THOLIAN, 1979),
+    "SUPERCMDR": (OPTION_SUPERCMDR, 1979),
+    "PROBE": (OPTION_PROBE, 1980),
+    "MVBADDY": (OPTION_MVBADDY, 1981),  # year bumped to make it distinct
+    "RAMMING": (OPTION_RAMMING, 1982),  # year bumped to make it distinct
+    "ALMY": (OPTION_ALMY, 1997),
+    "AUTOPASS": (OPTION_AUTOPASS, 1998),  # year bumped to make it distinct
+    "BASE": (OPTION_BASE, 2004),  # year bumped to make it distinct
+    "BLKHOLE": (OPTION_BLKHOLE, 2004),  # year bumped to make it distinct
+    "SHOWME": (OPTION_SHOWME, 2005),
+    "WORLDS": (OPTION_WORLDS, 2006),
+    "AUTOSCAN": (OPTION_AUTOSCAN, 2007),  # year bumped to make it distinct
+    "COLOR": (OPTION_COLOR, 2010),
+    "CAPTURE": (OPTION_CAPTURE, 2013),
+    "CLOAK": (OPTION_CLOAK, 2014),  # year bumped to make it distinct
+    "DOTFILL": (OPTION_DOTFILL, 2019),
+    "ALPHAMERIC": (OPTION_ALPHAMERIC, 2023),
+}
+
+# Define devices
+DSRSENS = 0
+DLRSENS = 1
+DPHASER = 2
+DPHOTON = 3
+DLIFSUP = 4
+DWARPEN = 5
+DIMPULS = 6
+DSHIELD = 7
+DRADIO = 8
+DSHUTTL = 9
+DCOMPTR = 10
+DNAVSYS = 11
+DTRANSP = 12
+DSHCTRL = 13
+DDRAY = 14
+DDSP = 15
+DCLOAK = 16
+NDEVICES = 17  # Number of devices
+
+SKILL_NONE = 0
+SKILL_NOVICE = 1
+SKILL_FAIR = 2
+SKILL_GOOD = 3
+SKILL_EXPERT = 4
+SKILL_EMERITUS = 5
+
+
+def damaged(dev):
+    return game.damage[dev] != 0.0
+
+
+def communicating():
+    return not damaged(DRADIO) or game.condition == "docked"
+
+
+# Define future events
+FSPY = 0  # Spy event happens always (no future[] entry)
+# can cause SC to tractor beam Enterprise
+FSNOVA = 1  # Supernova
+FTBEAM = 2  # Commander tractor beams Enterprise
+FSNAP = 3  # Snapshot for time warp
+FBATTAK = 4  # Commander attacks base
+FCDBAS = 5  # Commander destroys base
+FSCMOVE = 6  # Supercommander moves (might attack base)
+FSCDBAS = 7  # Supercommander destroys base
+FDSPROB = 8  # Move deep space probe
+FDISTR = 9  # Emit distress call from an inhabited world
+FENSLV = 10  # Inhabited word is enslaved
+FREPRO = 11  # Klingons build a ship in an enslaved system
+NEVENTS = 12
+
+# Abstract out the event handling -- underlying data structures will change
+# when we implement stateful events
+def findevent(evtype):  # pragma: no cover
+    return game.future[evtype]
+
+
+class Enemy:
+    def __init__(self, etype=None, loc=None, power=None):
+        self.type = etype
+        self.location = Coord()
+        self.kdist = None
+        self.kavgd = None
+        if loc:
+            self.move(loc)
+        self.power = power  # enemy energy level
+        game.enemies.append(self)
+
+    def move(self, loc):
+        motion = loc != self.location
+        if self.location.i is not None and self.location.j is not None:
+            if motion:
+                if self.type == "T":
+                    game.quad[self.location.i][self.location.j] = "#"
+                else:
+                    game.quad[self.location.i][self.location.j] = "."
+        if loc:
+            self.location = copy.copy(loc)
+            game.quad[self.location.i][self.location.j] = self.type
+            self.kdist = self.kavgd = (game.sector - loc).distance()
+        else:
+            self.location = Coord()
+            self.kdist = self.kavgd = None
+            # Guard prevents failure on Tholian or thingy
+            if self in game.enemies:
+                game.enemies.remove(self)
+        return motion
+
+    def __repr__(self):
+        return "<%s,%s,%f>" % (self.type, self.location, self.power)  # pragma: no cover
+
+
+class Gamestate:
+    def __init__(self):
+        self.options = None  # Game options
+        self.state = Snapshot()  # A snapshot structure
+        self.snapsht = Snapshot()  # Last snapshot taken for time-travel purposes
+        self.quad = None  # contents of our quadrant
+        self.damage = [0.0] * NDEVICES  # damage encountered
+        self.future = []  # future events
+        i = NEVENTS
+        while i > 0:
+            i -= 1
+            self.future.append(Event())
+        self.passwd = None  # Self Destruct password
+        self.enemies = []
+        self.quadrant = None  # where we are in the large
+        self.sector = None  # where we are in the small
+        self.tholian = None  # Tholian enemy object
+        self.base = None  # position of base in current quadrant
+        self.battle = None  # base coordinates being attacked
+        self.plnet = None  # location of planet in quadrant
+        self.gamewon = False  # Finished!
+        self.ididit = False  # action taken -- allows enemy to attack
+        self.alive = False  # we are alive (not killed)
+        self.justin = False  # just entered quadrant
+        self.shldup = False  # shields are up
+        self.shldchg = False  # shield is changing (affects efficiency)
+        self.iscate = False  # super commander is here
+        self.ientesc = False  # attempted escape from supercommander
+        self.resting = False  # rest time
+        self.icraft = False  # Kirk in Galileo
+        self.landed = False  # party on planet (true), on ship (false)
+        self.alldone = False  # game is now finished
+        self.neutz = False  # Romulan Neutral Zone
+        self.isarmed = False  # probe is armed
+        self.inorbit = False  # orbiting a planet
+        self.imine = False  # mining
+        self.icrystl = False  # dilithium crystals aboard
+        self.iseenit = False  # seen base attack report
+        self.thawed = False  # thawed game
+        self.condition = None  # "green", "yellow", "red", "docked", "dead"
+        self.iscraft = None  # "onship", "offship", "removed"
+        self.skill = SKILL_NONE  # Player skill level
+        self.inkling = 0  # initial number of klingons
+        self.inbase = 0  # initial number of bases
+        self.incom = 0  # initial number of commanders
+        self.inscom = 0  # initial number of commanders
+        self.inrom = 0  # initial number of commanders
+        self.instar = 0  # initial stars
+        self.intorps = 0  # initial/max torpedoes
+        self.torps = 0  # number of torpedoes
+        self.ship = 0  # ship type -- 'E' is Enterprise
+        self.abandoned = 0  # count of crew abandoned in space
+        self.length = 0  # length of game
+        self.klhere = 0  # klingons here
+        self.casual = 0  # causalties
+        self.nhelp = 0  # calls for help
+        self.nkinks = 0  # count of energy-barrier crossings
+        self.iplnet = None  # planet # in quadrant
+        self.inplan = 0  # initial planets
+        self.irhere = 0  # Romulans in quadrant
+        self.isatb = 0  # =2 if super commander is attacking base
+        self.tourn = None  # tournament number
+        self.nprobes = 0  # number of probes available
+        self.inresor = 0.0  # initial resources
+        self.intime = 0.0  # initial time
+        self.inenrg = 0.0  # initial/max energy
+        self.inshld = 0.0  # initial/max shield
+        self.inlsr = 0.0  # initial life support resources
+        self.indate = 0.0  # initial date
+        self.energy = 0.0  # energy level
+        self.shield = 0.0  # shield level
+        self.warpfac = 0.0  # warp speed
+        self.lsupres = 0.0  # life support reserves
+        self.optime = 0.0  # time taken by current operation
+        self.damfac = 0.0  # damage factor
+        self.lastchart = 0.0  # time star chart was last updated
+        self.cryprob = 0.0  # probability that crystal will work
+        self.probe = None  # object holding probe course info
+        self.height = 0.0  # height of orbit around planet
+        self.score = 0.0  # overall score
+        self.perdate = 0.0  # rate of kills
+        self.idebug = False  # Debugging instrumentation enabled?
+        self.cdebug = False  # Debugging instrumentation for curses enabled?
+        self.statekscmdr = None  # No SuperCommander coordinates yet.
+        self.brigcapacity = 400  # Enterprise brig capacity
+        self.brigfree = 400  # How many klingons can we put in the brig?
+        self.kcaptured = 0  # Total Klingons captured, for scoring.
+        self.iscloaked = False  # Cloaking device on?
+        self.ncviol = 0  # Algreon treaty violations
+        self.isviolreported = False  # We have been warned
+        self.lcg_x = 0  # LCG generator value
+
+    def remkl(self):
+        return sum([q.klingons for (_i, _j, q) in list(self.state.traverse())])
+
+    def recompute(self):
+        # Stas thinks this should be (C expression):
+        # game.remkl() + len(game.state.kcmdr) > 0 ?
+        #        game.state.remres/(game.remkl() + 4*len(game.state.kcmdr)) : 99
+        # He says the existing expression is prone to divide-by-zero errors
+        # after killing the last klingon when score is shown -- perhaps also
+        # if the only remaining klingon is SCOM.
+        self.state.remtime = self.state.remres / (
+            self.remkl() + 4 * len(self.state.kcmdr)
+        )
+
+    def unwon(self):
+        "Are there Klingons remaining?"
+        return self.remkl()
+
+
+FWON = 0
+FDEPLETE = 1
+FLIFESUP = 2
+FNRG = 3
+FBATTLE = 4
+FNEG3 = 5
+FNOVA = 6
+FSNOVAED = 7
+FABANDN = 8
+FDILITHIUM = 9
+FMATERIALIZE = 10
+FPHASER = 11
+FLOST = 12
+FMINING = 13
+FDPLANET = 14
+FPNOVA = 15
+FSSC = 16
+FSTRACTOR = 17
+FDRAY = 18
+FTRIBBLE = 19
+FHOLE = 20
+FCREW = 21
+FCLOAK = 22
+
+# Code from ai.c begins here
+
+
+def welcoming(iq):
+    "Would this quadrant welcome another Klingon?"
+    return (
+        iq.valid_quadrant()
+        and not game.state.galaxy[iq.i][iq.j].supernova
+        and game.state.galaxy[iq.i][iq.j].klingons < MAXKLQUAD
+    )
+
+
+def tryexit(enemy, look, irun):
+    "A bad guy attempts to bug out."
+    iq = Coord()
+    iq.i = game.quadrant.i + (look.i + (QUADSIZE - 1)) // QUADSIZE - 1
+    iq.j = game.quadrant.j + (look.j + (QUADSIZE - 1)) // QUADSIZE - 1
+    if not welcoming(iq):
+        return []
+    if enemy.type == "R":
+        return []  # Romulans cannot escape!
+    if not irun:
+        # avoid intruding on another commander's territory
+        if enemy.type == "C":
+            if iq in game.state.kcmdr:
+                return []
+            # refuse to leave if currently attacking starbase
+            if game.battle == game.quadrant:
+                return []
+        # don't leave if over 1000 units of energy
+        if enemy.power > 1000.0:
+            return []
+    oldloc = copy.copy(enemy.location)
+    # handle local matters related to escape
+    enemy.move(None)
+    game.klhere -= 1
+    if game.condition != "docked":
+        newcnd()
+    # Handle global matters related to escape
+    game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
+    game.state.galaxy[iq.i][iq.j].klingons += 1
+    if enemy.type == "S":
+        game.iscate = False
+        game.ientesc = False
+        game.isatb = 0
+        schedule(FSCMOVE, 0.2777)
+        unschedule(FSCDBAS)
+        game.state.kscmdr = iq
+    else:
+        for cmdr in game.state.kcmdr:
+            if cmdr == game.quadrant:
+                game.state.kcmdr.append(iq)
+                break
+    # report move out of quadrant.
+    return [(True, enemy, oldloc, iq)]
+
+
+# The bad-guy movement algorithm:
+#
+# 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
+# If both are operating full strength, force is 1000. If both are damaged,
+# force is -1000. Having shields down subtracts an additional 1000.
+#
+# 2. Enemy has forces equal to the energy of the attacker plus
+# 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
+# 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
+#
+# Attacker Initial energy levels (nominal):
+# Klingon   Romulan   Commander   Super-Commander
+# Novice    400        700        1200
+# Fair      425        750        1250
+# Good      450        800        1300        1750
+# Expert    475        850        1350        1875
+# Emeritus  500        900        1400        2000
+# VARIANCE   75        200         200         200
+#
+# Enemy vessels only move prior to their attack. In Novice - Good games
+# only commanders move. In Expert games, all enemy vessels move if there
+# is a commander present. In Emeritus games all enemy vessels move.
+#
+# 3. If Enterprise is not docked, an aggressive action is taken if enemy
+# forces are 1000 greater than Enterprise.
+#
+# Agressive action on average cuts the distance between the ship and
+# the enemy to 1/4 the original.
+#
+# 4.  At lower energy advantage, movement units are proportional to the
+# advantage with a 650 advantage being to hold ground, 800 to move forward
+# 1, 950 for two, 150 for back 4, etc. Variance of 100.
+#
+# If docked, is reduced by roughly 1.75*game.skill, generally forcing a
+# retreat, especially at high skill levels.
+#
+# 5.  Motion is limited to skill level, except for SC hi-tailing it out.
+
+
+def movebaddy(enemy):
+    "Tactical movement for the bad guys."
+    goto = Coord()
+    look = Coord()
+    irun = False
+    # This should probably be just (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
+    if game.skill >= SKILL_EXPERT:
+        nbaddys = int(
+            (
+                (game.quadrant in game.state.kcmdr) * 2
+                + (game.state.kscmdr == game.quadrant) * 2
+                + game.klhere * 1.23
+                + game.irhere * 1.5
+            )
+            / 2.0
+        )
+    else:
+        nbaddys = (game.quadrant in game.state.kcmdr) + (
+            game.state.kscmdr == game.quadrant
+        )
+    old_dist = enemy.kdist
+    mdist = int(old_dist + 0.5)  # Nearest integer distance
+    # If SC, check with spy to see if should hi-tail it
+    if enemy.type == "S" and (
+        enemy.power <= 500.0 or (game.condition == "docked" and not damaged(DPHOTON))
+    ):
+        irun = True
+        motion = -QUADSIZE
+    else:
+        # decide whether to advance, retreat, or hold position
+        forces = enemy.power + 100.0 * len(game.enemies) + 400 * (nbaddys - 1)
+        if not game.shldup:
+            forces += 1000  # Good for enemy if shield is down!
+        if not damaged(DPHASER) or not damaged(DPHOTON):
+            if damaged(DPHASER):  # phasers damaged
+                forces += 300.0
+            else:
+                forces -= 0.2 * (game.energy - 2500.0)
+            if damaged(DPHOTON):  # photon torpedoes damaged
+                forces += 300.0
+            else:
+                forces -= 50.0 * game.torps
+        else:
+            # phasers and photon tubes both out!
+            forces += 1000.0
+        motion = 0
+        if forces <= 1000.0 and game.condition != "docked":  # Typical situation
+            motion = ((forces + rnd.real(200)) / 150.0) - 5.0
+        else:
+            if forces > 1000.0:  # Very strong -- move in for kill
+                motion = (1.0 - rnd.real()) ** 2 * old_dist + 1.0
+            if game.condition == "docked" and (
+                game.options & OPTION_BASE
+            ):  # protected by base -- back off !
+                motion -= game.skill * (2.0 - rnd.real() ** 2)
+        if game.idebug:
+            proutn(
+                "=== MOTION = %d, FORCES = %1.2f, " % (motion, forces)
+            )  # pragma: no cover
+        # don't move if no motion
+        if motion == 0:
+            return []
+        # Limit motion according to skill
+        if abs(motion) > game.skill:
+            if motion < 0:
+                motion = -game.skill
+            else:
+                motion = game.skill
+    # calculate preferred number of steps
+    nsteps = abs(int(motion))
+    if motion > 0 and nsteps > mdist:
+        nsteps = mdist  # don't overshoot
+    nsteps = min(nsteps, QUADSIZE)  # This shouldn't be necessary
+    nsteps = max(nsteps, 1)  # This shouldn't be necessary
+    if game.idebug:
+        proutn("NSTEPS = %d:" % nsteps)  # pragma: no cover
+    # Compute preferred values of delta X and Y
+    m = game.sector - enemy.location
+    if 2.0 * abs(m.i) < abs(m.j):
+        m.i = 0
+    if 2.0 * abs(m.j) < abs(game.sector.i - enemy.location.i):
+        m.j = 0
+    m = (motion * m).sgn()
+    goto = enemy.location
+    # main move loop
+    for ll in range(nsteps):
+        if game.idebug:
+            proutn(" %d" % (ll + 1))  # pragma: no cover
+        # Check if preferred position available
+        look = goto + m
+        if m.i < 0:
+            krawli = 1
+        else:
+            krawli = -1
+        if m.j < 0:
+            krawlj = 1
+        else:
+            krawlj = -1
+        success = False
+        attempts = 0  # Settle mysterious hang problem
+        while attempts < 20 and not success:
+            attempts += 1
+            if look.i < 0 or look.i >= QUADSIZE:
+                if motion < 0:
+                    return tryexit(enemy, look, irun)
+                if krawli == m.i or m.j == 0:
+                    break
+                look.i = goto.i + krawli
+                krawli = -krawli
+            elif look.j < 0 or look.j >= QUADSIZE:
+                if motion < 0:
+                    return tryexit(enemy, look, irun)
+                if krawlj == m.j or m.i == 0:
+                    break
+                look.j = goto.j + krawlj
+                krawlj = -krawlj
+            elif (game.options & OPTION_RAMMING) and game.quad[look.i][look.j] != ".":
+                # See if enemy should ram ship
+                if game.quad[look.i][look.j] == game.ship and enemy.type in ("C", "S"):
+                    collision(rammed=True, enemy=enemy)
+                    return []
+                if krawli != m.i and m.j != 0:
+                    look.i = goto.i + krawli
+                    krawli = -krawli
+                elif krawlj != m.j and m.i != 0:
+                    look.j = goto.j + krawlj
+                    krawlj = -krawlj
+                else:
+                    break  # we have failed
+            else:
+                success = True
+        if success:
+            goto = look
+            if game.idebug:
+                proutn(repr(goto))  # pragma: no cover
+        else:
+            break  # done early
+    if game.idebug:
+        skip(1)  # pragma: no cover
+    # Enemy moved, but is still in sector
+    return [(False, enemy, old_dist, goto)]
+
+
+def moveklings():
+    "Sequence Klingon tactical movement."
+    if game.idebug:
+        prout("== MOVCOM")  # pragma: no cover
+    # Figure out which Klingon is the commander (or Supercommander)
+    # and do move
+    tacmoves = []
+    if game.quadrant in game.state.kcmdr:
+        for enemy in game.enemies:
+            if enemy.type == "C":
+                tacmoves += movebaddy(enemy)
+    if game.state.kscmdr == game.quadrant:
+        for enemy in game.enemies:
+            if enemy.type == "S":
+                tacmoves += movebaddy(enemy)
+                break
+    # If skill level is high, move other Klingons and Romulans too!
+    # Move these last so they can base their actions on what the
+    # commander(s) do.
+    if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
+        for enemy in game.enemies:
+            if enemy.type in ("K", "R"):
+                tacmoves += movebaddy(enemy)
+    return tacmoves
+
+
+def movescom(iq, avoid):
+    "Supercommander movement helper."
+    # Avoid quadrants with bases if we want to avoid Enterprise
+    if not welcoming(iq) or (avoid and iq in game.state.baseq):
+        return False
+    if game.justin and not game.iscate:
+        return False
+    # do the move
+    game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons -= 1
+    game.state.kscmdr = iq
+    game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons += 1
+    if game.state.kscmdr == game.quadrant:
+        # SC has scooted, remove him from current quadrant
+        game.iscate = False
+        game.isatb = 0
+        game.ientesc = False
+        unschedule(FSCDBAS)
+        for enemy in game.enemies:
+            if enemy.type == "S":
+                enemy.move(None)
+        game.klhere -= 1
+        if game.condition != "docked":
+            newcnd()
+        sortenemies()
+    # check for a helpful planet
+    for i in range(game.inplan):
+        if (
+            game.state.planets[i].quadrant == game.state.kscmdr
+            and game.state.planets[i].crystals == "present"
+        ):
+            # destroy the planet
+            game.state.planets[i].pclass = "destroyed"
+            game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].planet = None
+            if communicating():
+                announce()
+                prout(_('Lt. Uhura-  "Captain, Starfleet Intelligence reports'))
+                prout(
+                    _("   a planet in Quadrant %s has been destroyed")
+                    % game.state.kscmdr
+                )
+                prout(_('   by the Super-commander."'))
+            break
+    return True  # looks good!
+
+
+def supercommander():
+    "Move the Super Commander."
+    iq = Coord()
+    sc = Coord()
+    ibq = Coord()
+    idelta = Coord()
+    basetbl = []
+    if game.idebug:
+        prout("== SUPERCOMMANDER")  # pragma: no cover
+    # Decide on being active or passive
+    avoid = (game.incom - len(game.state.kcmdr) + game.inkling - game.remkl()) / (
+        game.state.date + 0.01 - game.indate
+    ) < 0.1 * game.skill * (game.skill + 1.0) or (game.state.date - game.indate) < 3.0
+    if not game.iscate and avoid:
+        # compute move away from Enterprise
+        idelta = game.state.kscmdr - game.quadrant
+        if idelta.distance() > 2.0:
+            # circulate in space
+            idelta.i = game.state.kscmdr.j - game.quadrant.j
+            idelta.j = game.quadrant.i - game.state.kscmdr.i
+    else:
+        # compute distances to starbases
+        if not game.state.baseq:
+            # nothing left to do
+            unschedule(FSCMOVE)
+            return
+        sc = game.state.kscmdr
+        for (i, base) in enumerate(game.state.baseq):
+            basetbl.append((i, (base - sc).distance()))
+        if len(game.state.baseq) > 1:
+            basetbl.sort(key=lambda x: x[1])
+        # look for nearest base without a commander, no Enterprise, and
+        # without too many Klingons, and not already under attack.
+        ifindit = iwhichb = 0
+        for (i2, base) in enumerate(game.state.baseq):
+            i = basetbl[i2][0]  # bug in original had it not finding nearest
+            if base == game.quadrant or base == game.battle or not welcoming(base):
+                continue
+            # if there is a commander, and no other base is appropriate,
+            # we will take the one with the commander
+            for cmdr in game.state.kcmdr:
+                if base == cmdr and ifindit != 2:
+                    ifindit = 2
+                    iwhichb = i
+                    break
+            else:  # no commander -- use this one
+                ifindit = 1
+                iwhichb = i
+                break
+        if ifindit == 0:
+            return  # Nothing suitable -- wait until next time
+        ibq = game.state.baseq[iwhichb]
+        # decide how to move toward base
+        idelta = ibq - game.state.kscmdr
+    # Maximum movement is 1 quadrant in either or both axes
+    idelta = idelta.sgn()
+    # try moving in both x and y directions
+    # there was what looked like a bug in the Almy C code here,
+    # but it might be this translation is just wrong.
+    iq = game.state.kscmdr + idelta
+    if not movescom(iq, avoid):
+        # failed -- try some other maneuvers
+        if idelta.i == 0 or idelta.j == 0:
+            # attempt angle move
+            if idelta.i != 0:
+                iq.j = game.state.kscmdr.j + 1
+                if not movescom(iq, avoid):
+                    iq.j = game.state.kscmdr.j - 1
+                    movescom(iq, avoid)
+            elif idelta.j != 0:
+                iq.i = game.state.kscmdr.i + 1
+                if not movescom(iq, avoid):
+                    iq.i = game.state.kscmdr.i - 1
+                    movescom(iq, avoid)
+        else:
+            # try moving just in x or y
+            iq.j = game.state.kscmdr.j
+            if not movescom(iq, avoid):
+                iq.j = game.state.kscmdr.j + idelta.j
+                iq.i = game.state.kscmdr.i
+                movescom(iq, avoid)
+    # check for a base
+    if len(game.state.baseq) == 0:
+        unschedule(FSCMOVE)
+    else:
+        for ibq in game.state.baseq:
+            if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
+                # attack the base
+                if avoid:
+                    return  # no, don't attack base!
+                game.iseenit = False
+                game.isatb = 1
+                schedule(FSCDBAS, rnd.real(1.0, 3.0))
+                if is_scheduled(FCDBAS):
+                    postpone(FSCDBAS, scheduled(FCDBAS) - game.state.date)
+                if not communicating():
+                    return  # no warning
+                game.iseenit = True
+                announce()
+                prout(
+                    _('Lt. Uhura-  "Captain, the starbase in Quadrant %s')
+                    % game.state.kscmdr
+                )
+                prout(
+                    _(
+                        "   reports that it is under attack from the Klingon Super-commander."
+                    )
+                )
+                prout(
+                    _('   It can survive until stardate %d."') % int(scheduled(FSCDBAS))
+                )
+                if not game.resting:
+                    return
+                prout(_('Mr. Spock-  "Captain, shall we cancel the rest period?"'))
+                if not ja():
+                    return
+                game.resting = False
+                game.optime = 0.0  # actually finished
+                return
+    # Check for intelligence report
+    if not game.idebug and (
+        rnd.withprob(0.8)
+        or (not communicating())
+        or not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].charted
+    ):
+        return
+    announce()
+    prout(_('Lt. Uhura-  "Captain, Starfleet Intelligence reports'))
+    prout(_("   the Super-commander is in Quadrant %s.") % game.state.kscmdr)
+    return
+
+
+def movetholian():
+    "Move the Tholian."
+    if not game.tholian or game.justin:
+        return
+    tid = Coord()
+    if game.tholian.location.i == 0 and game.tholian.location.j == 0:
+        tid.i = 0
+        tid.j = QUADSIZE - 1
+    elif game.tholian.location.i == 0 and game.tholian.location.j == QUADSIZE - 1:
+        tid.i = QUADSIZE - 1
+        tid.j = QUADSIZE - 1
+    elif (
+        game.tholian.location.i == QUADSIZE - 1
+        and game.tholian.location.j == QUADSIZE - 1
+    ):
+        tid.i = QUADSIZE - 1
+        tid.j = 0
+    elif game.tholian.location.i == QUADSIZE - 1 and game.tholian.location.j == 0:
+        tid.i = 0
+        tid.j = 0
+    else:  # pragma: no cover
+        # something is wrong!
+        game.tholian.move(None)
+        prout("***Internal error: Tholian in a bad spot.")
+        return
+    # do nothing if we are blocked
+    if game.quad[tid.i][tid.j] not in (".", "#"):
+        return
+    here = copy.copy(game.tholian.location)
+    delta = (tid - game.tholian.location).sgn()
+    # move in x axis
+    while here.i != tid.i:
+        here.i += delta.i
+        if game.quad[here.i][here.j] == ".":
+            game.tholian.move(here)
+    # move in y axis
+    while here.j != tid.j:
+        here.j += delta.j
+        if game.quad[here.i][here.j] == ".":
+            game.tholian.move(here)
+    # check to see if all holes plugged
+    for i in range(QUADSIZE):
+        if game.quad[0][i] != "#" and game.quad[0][i] != "T":
+            return
+        if game.quad[QUADSIZE - 1][i] != "#" and game.quad[QUADSIZE - 1][i] != "T":
+            return
+        if game.quad[i][0] != "#" and game.quad[i][0] != "T":
+            return
+        if game.quad[i][QUADSIZE - 1] != "#" and game.quad[i][QUADSIZE - 1] != "T":
+            return
+    # All plugged up -- Tholian splits
+    game.quad[game.tholian.location.i][game.tholian.location.j] = "#"
+    dropin(" ")
+    prout(crmena(True, "T", "sector", game.tholian) + _(" completes web."))
+    game.tholian.move(None)
+    return
+
+
+# Code from battle.c begins here
+
+
+def cloak():
+    "Change cloaking-device status."
+    if game.ship == "F":
+        prout(_("Ye Faerie Queene hath no cloaking device."))
+        return
+
+    key = scanner.nexttok()
+
+    if key == "IHREAL":
+        huh()
+        return
+
+    action = None
+    if key == "IHALPHA":
+        if scanner.sees("on"):
+            if game.iscloaked:
+                prout(_("The cloaking device has already been switched on."))
+                return
+            action = "CLON"
+        elif scanner.sees("off"):
+            if not game.iscloaked:
+                prout(_("The cloaking device has already been switched off."))
+                return
+            action = "CLOFF"
+        else:
+            huh()
+            return
+    else:
+        if not game.iscloaked:
+            proutn(_("Switch cloaking device on? "))
+            if not ja():
+                return
+            action = "CLON"
+        else:
+            proutn(_("Switch cloaking device off? "))
+            if not ja():
+                return
+            action = "CLOFF"
+    if action is None:
+        return
+
+    if action == "CLOFF":
+        if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
+            prout(
+                _(
+                    'Spock- "Captain, the Treaty of Algeron is in effect.\n   Are you sure this is wise?"'
+                )
+            )
+            if not ja():
+                return
+        prout('Engineer Scott- "Aye, Sir."')
+        game.iscloaked = False
+        if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
+            prout(
+                _("The Romulan ship discovers you are breaking the Treaty of Algeron!")
+            )
+            game.ncviol += 1
+            game.isviolreported = True
+
+            # if (neutz and game.state.date >= ALGERON) finish(FCLOAK);
+            return
+
+    if action == "CLON":
+        if damaged(DCLOAK):
+            prout(_('Engineer Scott- "The cloaking device is damaged, Sir."'))
+            return
+
+        if game.condition == "docked":
+            prout(_("You cannot cloak while docked."))
+
+        if game.state.date >= ALGERON and not game.isviolreported:
+            prout(_('Spock- "Captain, using the cloaking device is a violation'))
+            prout(_("  of the Treaty of Algeron. Considering the alternatives,"))
+            proutn(_("  are you sure this is wise? "))
+            if not ja():
+                return
+        prout(_('Engineer Scott- "Cloaking device has engaging, Sir..."'))
+        attack(True)
+        prout(_('Engineer Scott- "Cloaking device has engaged, Sir."'))
+        game.iscloaked = True
+
+        if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
+            prout(
+                _("The Romulan ship discovers you are breaking the Treaty of Algeron!")
+            )
+            game.ncviol += 1
+            game.isviolreported = True
+
+
+def doshield(shraise):
+    "Change shield status."
+    action = "NONE"
+    game.ididit = False
+    if shraise:
+        action = "SHUP"
+    else:
+        key = scanner.nexttok()
+        if key == "IHALPHA":
+            if scanner.sees("transfer"):
+                action = "NRG"
+            else:
+                if damaged(DSHIELD):
+                    prout(_("Shields damaged and down."))
+                    return
+                if scanner.sees("up"):
+                    action = "SHUP"
+                elif scanner.sees("down"):
+                    action = "SHDN"
+        if action == "NONE":
+            proutn(_("Do you wish to change shield energy? "))
+            if ja():
+                action = "NRG"
+            elif damaged(DSHIELD):
+                prout(_("Shields damaged and down."))
+                return
+            elif game.shldup:
+                proutn(_("Shields are up. Do you want them down? "))
+                if ja():
+                    action = "SHDN"
+                else:
+                    scanner.chew()
+                    return
+            else:
+                proutn(_("Shields are down. Do you want them up? "))
+                if ja():
+                    action = "SHUP"
+                else:
+                    scanner.chew()
+                    return
+    if action == "SHUP":  # raise shields
+        if game.shldup:
+            prout(_("Shields already up."))
+            return
+        game.shldup = True
+        game.shldchg = True
+        if game.condition != "docked":
+            game.energy -= 50.0
+        prout(_("Shields raised."))
+        if game.energy <= 0:
+            skip(1)
+            prout(_("Shields raising uses up last of energy."))
+            finish(FNRG)
+            return
+        game.ididit = True
+        return
+    elif action == "SHDN":
+        if not game.shldup:
+            prout(_("Shields already down."))
+            return
+        game.shldup = False
+        game.shldchg = True
+        prout(_("Shields lowered."))
+        game.ididit = True
+        return
+    elif action == "NRG":
+        while scanner.nexttok() != "IHREAL":
+            scanner.chew()
+            proutn(_("Energy to transfer to shields- "))
+        nrg = scanner.real
+        scanner.chew()
+        if nrg == 0:
+            return
+        if nrg > game.energy:
+            prout(_("Insufficient ship energy."))
+            return
+        game.ididit = True
+        if game.shield + nrg >= game.inshld:
+            prout(_("Shield energy maximized."))
+            if game.shield + nrg > game.inshld:
+                prout(_("Excess energy requested returned to ship energy"))
+            game.energy -= game.inshld - game.shield
+            game.shield = game.inshld
+            return
+        if nrg < 0.0 and game.energy - nrg > game.inenrg:
+            # Prevent shield drain loophole
+            skip(1)
+            prout(_("Engineering to bridge--"))
+            prout(_("  Scott here. Power circuit problem, Captain."))
+            prout(_("  I can't drain the shields."))
+            game.ididit = False
+            return
+        if game.shield + nrg < 0:
+            prout(_("All shield energy transferred to ship."))
+            game.energy += game.shield
+            game.shield = 0.0
+            return
+        proutn(_('Scotty- "'))
+        if nrg > 0:
+            prout(_('Transferring energy to shields."'))
+        else:
+            prout(_('Draining energy from shields."'))
+        game.shield += nrg
+        game.energy -= nrg
+        return
+
+
+def randdevice():
+    "Choose a device to damage, at random."
+    weights = (
+        105,  # DSRSENS: short range scanners         10.5%
+        105,  # DLRSENS: long range scanners          10.5%
+        120,  # DPHASER: phasers                      12.0%
+        120,  # DPHOTON: photon torpedoes             12.0%
+        25,  # DLIFSUP: life support                  2.5%
+        65,  # DWARPEN: warp drive                    6.5%
+        70,  # DIMPULS: impulse engines               6.5%
+        135,  # DSHIELD: deflector shields            13.5%
+        30,  # DRADIO:  subspace radio                3.0%
+        45,  # DSHUTTL: shuttle                       4.5%
+        15,  # DCOMPTR: computer                      1.5%
+        20,  # NAVCOMP: navigation system             2.0%
+        75,  # DTRANSP: transporter                   7.5%
+        20,  # DSHCTRL: high-speed shield controller  2.0%
+        10,  # DDRAY: death ray                       1.0%
+        30,  # DDSP: deep-space probes                3.0%
+        10,  # DCLOAK: the cloaking device            1.0
+    )
+    assert sum(weights) == 1000
+    idx = rnd.integer(1000)
+    wsum = 0
+    for (i, w) in enumerate(weights):
+        wsum += w
+        if idx < wsum:
+            return i
+    return None  # pragma: no cover
+
+
+def collision(rammed, enemy):
+    "Collision handling for ramming events."
+    prouts(_("***RED ALERT!  RED ALERT!"))
+    skip(1)
+    prout(_("***COLLISION IMMINENT."))
+    skip(2)
+    proutn("***")
+    proutn(crmshp())
+    hardness = {"R": 1.5, "C": 2.0, "S": 2.5, "T": 0.5, "?": 4.0}.get(enemy.type, 1.0)
+    if rammed:
+        proutn(_(" rammed by "))
+    else:
+        proutn(_(" rams "))
+    proutn(crmena(False, enemy.type, "sector", enemy.location))
+    if rammed:
+        proutn(_(" (original position)"))
+    skip(1)
+    deadkl(enemy.location, enemy.type, game.sector)
+    prout("***" + crmshp() + " heavily damaged.")
+    icas = rnd.integer(10, 30)
+    prout(_("***Sickbay reports %d casualties") % icas)
+    game.casual += icas
+    game.state.crew -= icas
+    # In the pre-SST2K versions, all devices got equiprobably damaged,
+    # which was silly.  Instead, pick up to half the devices at
+    # random according to our weighting table,
+    ncrits = rnd.integer(NDEVICES // 2)
+    while ncrits > 0:
+        ncrits -= 1
+        dev = randdevice()
+        if game.damage[dev] < 0:
+            continue
+        extradm = (10.0 * hardness * rnd.real() + 1.0) * game.damfac
+        # Damage for at least time of travel!
+        game.damage[dev] += game.optime + extradm
+    game.shldup = False
+    prout(_("***Shields are down."))
+    if game.unwon():
+        announce()
+        damagereport()
+    else:
+        finish(FWON)
+
+
+def torpedo(origin, bearing, dispersion, number, nburst):
+    "Let a photon torpedo fly"
+    if not damaged(DSRSENS) or game.condition == "docked":
+        setwnd(srscan_window)
+    else:
+        setwnd(message_window)
+    ac = bearing + 0.25 * dispersion  # dispersion is a random variable
+    bullseye = (15.0 - bearing) * 0.5235988
+    track = course(bearing=ac, distance=QUADSIZE, origin=cartesian(origin))
+    bumpto = Coord(0, 0)
+    # Loop to move a single torpedo
+    setwnd(message_window)
+    for step in range(1, QUADSIZE * 2):
+        if not track.nextstep():
+            break
+        w = track.sector()
+        if not w.valid_sector():
+            break
+        iquad = game.quad[w.i][w.j]
+        tracktorpedo(w, step, number, nburst, iquad)
+        if iquad == ".":
+            continue
+        # hit something
+        setwnd(message_window)
+        if not damaged(DSRSENS) or game.condition == "docked":
+            skip(1)  # start new line after text track
+        if iquad in ("E", "F"):  # Hit our ship
+            skip(1)
+            prout(_("Torpedo hits %s.") % crmshp())
+            hit = (
+                700.0
+                + rnd.real(100)
+                - 1000.0
+                * (w - origin).distance()
+                * math.fabs(math.sin(bullseye - track.angle))
+            )
+            newcnd()  # we're blown out of dock
+            if game.landed or game.condition == "docked":
+                return hit  # Cheat if on a planet
+            # In the C/FORTRAN version, dispersion was 2.5 radians, which
+            # is 143 degrees, which is almost exactly 4.8 clockface units
+            displacement = course(
+                track.bearing + rnd.real(-2.4, 2.4), distance=2 ** 0.5
+            )
+            displacement.nextstep()
+            bumpto = displacement.sector()
+            if not bumpto.valid_sector():
+                return hit
+            if game.quad[bumpto.i][bumpto.j] == " ":
+                finish(FHOLE)
+                return hit
+            if game.quad[bumpto.i][bumpto.j] != ".":
+                # can't move into object
+                return hit
+            game.sector = bumpto
+            proutn(crmshp())
+            game.quad[w.i][w.j] = "."
+            game.quad[bumpto.i][bumpto.j] = iquad
+            prout(_(" displaced by blast to Sector %s ") % bumpto)
+            for enemy in game.enemies:
+                enemy.kdist = enemy.kavgd = (game.sector - enemy.location).distance()
+            sortenemies()
+            return None
+        elif iquad in ("C", "S", "R", "K"):  # Hit a regular enemy
+            # find the enemy
+            if iquad in ("C", "S") and rnd.withprob(0.05):
+                prout(crmena(True, iquad, "sector", w) + _(" uses anti-photon device;"))
+                prout(_("   torpedo neutralized."))
+                return None
+            for enemy in game.enemies:
+                if w == enemy.location:
+                    kp = math.fabs(enemy.power)
+                    h1 = (
+                        700.0
+                        + rnd.integer(100)
+                        - 1000.0
+                        * (w - origin).distance()
+                        * math.fabs(math.sin(bullseye - track.angle))
+                    )
+                    h1 = math.fabs(h1)
+                    if kp < h1:
+                        h1 = kp
+                    if enemy.power < 0:
+                        enemy.power -= -h1
+                    else:
+                        enemy.power -= h1
+                    if enemy.power == 0:
+                        deadkl(w, iquad, w)
+                        return None
+                    proutn(crmena(True, iquad, "sector", w))
+                    displacement = course(
+                        track.bearing + rnd.real(-2.4, 2.4), distance=2 ** 0.5, origin=w
+                    )
+                    displacement.nextstep()
+                    bumpto = displacement.sector()
+                    if game.quad[bumpto.i][bumpto.j] == " ":
+                        prout(_(" buffeted into black hole."))
+                        deadkl(w, iquad, bumpto)
+                        return None
+                    if not bumpto.valid_sector():
+                        prout(_(" damaged but not destroyed."))
+                        return None
+                    if game.quad[bumpto.i][bumpto.j] != ".":
+                        prout(_(" damaged but not destroyed."))
+                    else:
+                        prout(_(" damaged-- displaced by blast to Sector %s ") % bumpto)
+                        enemy.location = bumpto
+                        game.quad[w.i][w.j] = "."
+                        game.quad[bumpto.i][bumpto.j] = iquad
+                        for tenemy in game.enemies:
+                            tenemy.kdist = tenemy.kavgd = (
+                                game.sector - tenemy.location
+                            ).distance()
+                        sortenemies()
+                    break
+            else:  # pragma: no cover
+                prout("Internal error, no enemy where expected!")
+                raise SystemExit(1)
+            return None
+        elif iquad == "B":  # Hit a base
+            skip(1)
+            prout(_("***STARBASE DESTROYED.."))
+            game.state.baseq = [x for x in game.state.baseq if x != game.quadrant]
+            game.quad[w.i][w.j] = "."
+            game.base.invalidate()
+            game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase = False
+            game.state.chart[game.quadrant.i][game.quadrant.j].starbase = False
+            game.state.basekl += 1
+            newcnd()
+            return None
+        elif iquad == "P":  # Hit a planet
+            prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
+            game.state.nplankl += 1
+            game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
+            game.iplnet.pclass = "destroyed"
+            game.iplnet = None
+            game.plnet.invalidate()
+            game.quad[w.i][w.j] = "."
+            if game.landed:
+                # captain perishes on planet
+                finish(FDPLANET)
+            return None
+        elif iquad == "@":  # Hit an inhabited world -- very bad!
+            prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
+            game.state.nworldkl += 1
+            game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
+            game.iplnet.pclass = "destroyed"
+            game.iplnet = None
+            game.plnet.invalidate()
+            game.quad[w.i][w.j] = "."
+            if game.landed:
+                # captain perishes on planet
+                finish(FDPLANET)
+            prout(_("The torpedo destroyed an inhabited planet."))
+            return None
+        elif iquad == "*":  # Hit a star
+            if rnd.withprob(0.9):
+                nova(w)
+            else:
+                prout(
+                    crmena(True, "*", "sector", w) + _(" unaffected by photon blast.")
+                )
+            return None
+        elif iquad == "?":  # Hit a thingy
+            skip(1)
+            prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
+            skip(1)
+            prouts(_("    HACK!     HACK!    HACK!        *CHOKE!*  "))
+            skip(1)
+            proutn(_("Mr. Spock-"))
+            prouts(_('  "Fascinating!"'))
+            skip(1)
+            deadkl(w, iquad, w)
+            return None
+        elif iquad == " ":  # Black hole
+            skip(1)
+            prout(crmena(True, " ", "sector", w) + _(" swallows torpedo."))
+            return None
+        elif iquad == "#":  # hit the web
+            skip(1)
+            prout(_("***Torpedo absorbed by Tholian web."))
+            return None
+        elif iquad == "T":  # Hit a Tholian
+            h1 = (
+                700.0
+                + rnd.integer(100)
+                - 1000.0
+                * (w - origin).distance()
+                * math.fabs(math.sin(bullseye - track.angle))
+            )
+            h1 = math.fabs(h1)
+            if h1 >= 600:
+                game.quad[w.i][w.j] = "."
+                deadkl(w, iquad, w)
+                game.tholian = None
+                return None
+            skip(1)
+            proutn(crmena(True, "T", "sector", w))
+            if rnd.withprob(0.05):
+                prout(_(" survives photon blast."))
+                return None
+            prout(_(" disappears."))
+            game.tholian.move(None)
+            game.quad[w.i][w.j] = "#"
+            dropin(" ")
+            return None
+        else:  # Problem!
+            skip(1)
+            proutn("Don't know how to handle torpedo collision with ")
+            proutn(crmena(True, iquad, "sector", w))
+            skip(1)
+            return None
+        break
+    skip(1)
+    setwnd(message_window)
+    prout(_("Torpedo missed."))
+    return None
+
+
+def fry(hit):
+    "Critical-hit resolution."
+    if hit < (275.0 - 25.0 * game.skill) * rnd.real(1.0, 1.5):
+        return
+    ncrit = int(1.0 + hit / (500.0 + rnd.real(100)))
+    proutn(_("***CRITICAL HIT--"))
+    # Select devices and cause damage
+    cdam = []
+    while ncrit > 0:
+        while True:
+            j = randdevice()
+            # Cheat to prevent shuttle damage unless on ship
+            if not (
+                game.damage[j] < 0.0
+                or (j == DSHUTTL and game.iscraft != "onship")
+                or (j == DCLOAK and game.ship != "E" or j == DDRAY)
+            ):
+                break
+        cdam.append(j)
+        extradm = (hit * game.damfac) / (ncrit * rnd.real(75, 100))
+        game.damage[j] += extradm
+        ncrit -= 1
+    skipcount = 0
+    for (i, j) in enumerate(cdam):
+        proutn(device[j])
+        if skipcount % 3 == 2 and i < len(cdam) - 1:
+            skip(1)
+        skipcount += 1
+        if i < len(cdam) - 1:
+            proutn(_(" and "))
+    prout(_(" damaged."))
+    if damaged(DSHIELD) and game.shldup:
+        prout(_("***Shields knocked down."))
+        game.shldup = False
+    if damaged(DCLOAK) and game.iscloaked:
+        prout(_("***Cloaking device rendered inoperative."))
+        game.iscloaked = False
+
+
+def attack(torps_ok):
+    # bad guy attacks us
+    # torps_ok == False forces use of phasers in an attack
+    if game.iscloaked:
+        return
+    # game could be over at this point, check
+    if game.alldone:
+        return
+    attempt = False
+    ihurt = False
+    hitmax = 0.0
+    hittot = 0.0
+    chgfac = 1.0
+    where = "neither"
+    if game.idebug:
+        prout("=== ATTACK!")  # pragma: no cover
+    # Tholian gets to move before attacking
+    if game.tholian:
+        movetholian()
+    # if you have just entered the RNZ, you'll get a warning
+    if game.neutz:  # The one chance not to be attacked
+        game.neutz = False
+        return
+    # commanders get a chance to tac-move towards you
+    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:
+        for (bugout, enemy, old, goto) in moveklings():
+            if bugout:
+                # we know about this if either short or long range
+                # sensors are working
+                if damaged(DSRSENS) and damaged(DLRSENS) and game.condition != "docked":
+                    prout(
+                        crmena(True, enemy.type, "sector", old)
+                        + (_(" escapes to Quadrant %s (and regains strength).") % goto)
+                    )
+            else:  # Enemy still in-sector
+                if enemy.move(goto):
+                    if not damaged(DSRSENS) or game.condition == "docked":
+                        proutn(
+                            _("*** %s from Sector %s")
+                            % (cramen(enemy.type), enemy.location)
+                        )
+                        if enemy.kdist < old:
+                            proutn(_(" advances to "))
+                        else:
+                            proutn(_(" retreats to "))
+                        prout("Sector %s." % goto)
+        sortenemies()
+    # if no enemies remain after movement, we're done
+    if len(game.enemies) == 0 or (len(game.enemies) == 1 and thing.at(game.quadrant)):
+        return
+    # set up partial hits if attack happens during shield status change
+    pfac = 1.0 / game.inshld
+    if game.shldchg:
+        chgfac = 0.25 + rnd.real(0.5)
+    skip(1)
+    # message verbosity control
+    if game.skill <= SKILL_FAIR:
+        where = "sector"
+    for enemy in game.enemies:
+        if enemy.power < 0:
+            continue  # too weak to attack
+        # compute hit strength and diminish shield power
+        r = rnd.real()
+        # Increase chance of photon torpedos if docked or enemy energy is low
+        if game.condition == "docked":
+            r *= 0.25
+        if enemy.power < 500:
+            r *= 0.25
+        if enemy.type in ("T", "?"):
+            continue
+        # different enemies have different probabilities of throwing a torp
+        usephasers = (
+            not torps_ok
+            or (enemy.type == "K" and r > 0.0005)
+            or (enemy.type == "C" and r > 0.015)
+            or (enemy.type == "R" and r > 0.3)
+            or (enemy.type == "S" and r > 0.07)
+            or (enemy.type == "?" and r > 0.05)
+        )
+        if usephasers:  # Enemy uses phasers
+            if game.condition == "docked":
+                continue  # Don't waste the effort!
+            attempt = True  # Attempt to attack
+            dustfac = rnd.real(0.8, 0.85)
+            hit = enemy.power * math.pow(dustfac, enemy.kavgd)
+            enemy.power *= 0.75
+        else:  # Enemy uses photon torpedo
+            # We should be able to make the bearing() method work here
+            pcourse = 1.90985 * math.atan2(
+                game.sector.j - enemy.location.j, enemy.location.i - game.sector.i
+            )
+            hit = 0
+            proutn(_("***TORPEDO INCOMING"))
+            if not damaged(DSRSENS):
+                proutn(_(" From ") + crmena(False, enemy.type, where, enemy.location))
+            attempt = True
+            prout("  ")
+            dispersion = (rnd.real() + rnd.real()) * 0.5 - 0.5
+            dispersion += 0.002 * enemy.power * dispersion
+            hit = torpedo(enemy.location, pcourse, dispersion, number=1, nburst=1)
+            if game.unwon() == 0:
+                finish(FWON)  # Klingons did themselves in!
+            if (
+                game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova
+                or game.alldone
+            ):
+                return  # Supernova or finished
+            if hit is None:
+                continue
+        # incoming phaser or torpedo, shields may dissipate it
+        if game.shldup or game.shldchg or game.condition == "docked":
+            # shields will take hits
+            propor = pfac * game.shield
+            if game.condition == "docked":
+                propor *= 2.1
+            propor = max(propor, 0.1)
+            hitsh = propor * chgfac * hit + 1.0
+            absorb = 0.8 * hitsh
+            if absorb > game.shield:
+                absorb = game.shield
+            game.shield -= absorb
+            hit -= hitsh
+            # taking a hit blasts us out of a starbase dock
+            if game.condition == "docked":
+                dock(False)
+            # but the shields may take care of it
+            if propor > 0.1 and hit < 0.005 * game.energy:
+                continue
+        # hit from this opponent got through shields, so take damage
+        ihurt = True
+        proutn(_("%d unit hit") % int(hit))
+        if (damaged(DSRSENS) and usephasers) or game.skill <= SKILL_FAIR:
+            proutn(_(" on the ") + crmshp())
+        if not damaged(DSRSENS) and usephasers:
+            prout(_(" from ") + crmena(False, enemy.type, where, enemy.location))
+        skip(1)
+        # Decide if hit is critical
+        if hit > hitmax:
+            hitmax = hit
+        hittot += hit
+        fry(hit)
+        game.energy -= hit
+    if game.energy <= 0:
+        # Returning home upon your shield, not with it...
+        finish(FBATTLE)
+        return
+    if not attempt and game.condition == "docked":
+        prout(_("***Enemies decide against attacking your ship."))
+    percent = 100.0 * pfac * game.shield + 0.5
+    if not ihurt:
+        # Shields fully protect ship
+        proutn(_("Enemy attack reduces shield strength to "))
+    else:
+        # Emit message if starship suffered hit(s)
+        skip(1)
+        proutn(_("Energy left %2d    shields ") % int(game.energy))
+        if game.shldup:
+            proutn(_("up "))
+        elif not damaged(DSHIELD):
+            proutn(_("down "))
+        else:
+            proutn(_("damaged, "))
+    prout(_("%d%%,   torpedoes left %d") % (percent, game.torps))
+    # Check if anyone was hurt
+    if hitmax >= 200 or hittot >= 500:
+        icas = rnd.integer(int(hittot * 0.015))
+        if icas >= 2:
+            skip(1)
+            prout(_('Mc Coy-  "Sickbay to bridge.  We suffered %d casualties') % icas)
+            prout(_('   in that last attack."'))
+            game.casual += icas
+            game.state.crew -= icas
+    # After attack, reset average distance to enemies
+    for enemy in game.enemies:
+        enemy.kavgd = enemy.kdist
+    sortenemies()
+    return
+
+
+def deadkl(w, etype, mv):
+    "Kill a Klingon, Tholian, Romulan, or Thingy."
+    # Added mv to allow enemy to "move" before dying
+    proutn(crmena(True, etype, "sector", mv))
+    # Decide what kind of enemy it is and update appropriately
+    if etype == "R":
+        # Chalk up a Romulan
+        game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans -= 1
+        game.irhere -= 1
+        game.state.nromrem -= 1
+    elif etype == "T":
+        # Killed a Tholian
+        game.tholian = None
+    elif etype == "?":
+        # Killed a Thingy
+        global thing
+        thing = None
+    else:
+        # Killed some type of Klingon
+        game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
+        game.klhere -= 1
+        if etype == "C":
+            game.state.kcmdr.remove(game.quadrant)
+            unschedule(FTBEAM)
+            if game.state.kcmdr:
+                schedule(FTBEAM, expran(1.0 * game.incom / len(game.state.kcmdr)))
+            if is_scheduled(FCDBAS) and game.battle == game.quadrant:
+                unschedule(FCDBAS)
+        elif etype == "K":
+            pass
+        elif etype == "S":
+            game.state.nscrem -= 1
+            game.state.kscmdr.invalidate()
+            game.isatb = 0
+            game.iscate = False
+            unschedule(FSCMOVE)
+            unschedule(FSCDBAS)
+    # For each kind of enemy, finish message to player
+    prout(_(" destroyed."))
+    if game.unwon() == 0:
+        return
+    game.recompute()
+    # Remove enemy ship from arrays describing local conditions
+    for e in game.enemies:
+        if e.location == w:
+            e.move(None)
+            break
+    return
+
+
+def targetcheck(w):
+    "Return None if target is invalid, otherwise return a course angle."
+    if not w.valid_sector():
+        huh()
+        return None
+    delta = Coord()
+    # C code this was translated from is wacky -- why the sign reversal?
+    delta.j = w.j - game.sector.j
+    delta.i = game.sector.i - w.i
+    if delta == Coord(0, 0):
+        skip(1)
+        prout(_('Spock-  "Bridge to sickbay.  Dr. McCoy,'))
+        prout(_("  I recommend an immediate review of"))
+        prout(_("  the Captain's psychological profile.\""))
+        scanner.chew()
+        return None
+    return delta.bearing()
+
+
+def torps():
+    "Launch photon torpedo salvo."
+    tcourse = []
+    game.ididit = False
+    if damaged(DPHOTON):
+        prout(_("Photon tubes damaged."))
+        scanner.chew()
+        return
+    if game.torps == 0:
+        prout(_("No torpedoes left."))
+        scanner.chew()
+        return
+    # First, get torpedo count
+    while True:
+        scanner.nexttok()
+        if scanner.token == "IHALPHA":
+            huh()
+            return
+        elif scanner.token == "IHEOL" or not scanner.waiting():
+            prout(_("%d torpedoes left.") % game.torps)
+            scanner.chew()
+            proutn(_("Number of torpedoes to fire- "))
+            continue  # Go back around to get a number
+        else:  # key == "IHREAL"
+            try:
+                n = scanner.int()
+            except TypeError:
+                huh()
+                return
+            if n <= 0:  # abort command
+                scanner.chew()
+                return
+            if n > MAXBURST:
+                scanner.chew()
+                prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
+                return
+            if n > game.torps:
+                scanner.chew()  # User requested more torps than available
+                continue  # Go back around
+            break  # All is good, go to next stage
+    # Next, get targets
+    target = []
+    for i in range(n):
+        key = scanner.nexttok()
+        if i == 0 and key == "IHEOL":
+            break  # no coordinate waiting, we will try prompting
+        if i == 1 and key == "IHEOL":
+            # direct all torpedoes at one target
+            while i < n:
+                target.append(target[0])
+                tcourse.append(tcourse[0])
+                i += 1
+            break
+        scanner.push(scanner.token)
+        target.append(scanner.getcoord())
+        if target[-1] is None:
+            return
+        tcourse.append(targetcheck(target[-1]))
+        if tcourse[-1] is None:
+            return
+    scanner.chew()
+    if len(target) == 0:
+        # prompt for each one
+        for i in range(n):
+            proutn(_("Target sector for torpedo number %d- ") % (i + 1))
+            scanner.chew()
+            target.append(scanner.getcoord())
+            if target[-1] is None:
+                return
+            tcourse.append(targetcheck(target[-1]))
+            if tcourse[-1] is None:
+                return
+    game.ididit = True
+    # Loop for moving <n> torpedoes
+    for i in range(n):
+        if game.condition != "docked":
+            game.torps -= 1
+        dispersion = (rnd.real() + rnd.real()) * 0.5 - 0.5
+        if math.fabs(dispersion) >= 0.47:
+            # misfire!
+            dispersion *= rnd.real(1.2, 2.2)
+            if n > 0:
+                prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i + 1))
+            else:
+                prouts(_("***TORPEDO MISFIRES."))
+            skip(1)
+            if i < n:
+                prout(_("  Remainder of burst aborted."))
+            if rnd.withprob(0.2):
+                prout(_("***Photon tubes damaged by misfire."))
+                game.damage[DPHOTON] = game.damfac * rnd.real(1.0, 3.0)
+            break
+        if game.iscloaked:
+            dispersion *= 1.2
+        elif game.shldup or game.condition == "docked":
+            dispersion *= 1.0 + 0.0001 * game.shield
+        torpedo(game.sector, tcourse[i], dispersion, number=i, nburst=n)
+        if (
+            game.alldone
+            or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova
+        ):
+            return
+    if game.unwon() <= 0:
+        finish(FWON)
+
+
+def overheat(rpow):
+    "Check for phasers overheating."
+    if rpow > 1500:
+        checkburn = (rpow - 1500.0) * 0.00038
+        if rnd.withprob(checkburn):
+            prout(_('Weapons officer Sulu-  "Phasers overheated, sir."'))
+            game.damage[DPHASER] = game.damfac * rnd.real(1.0, 2.0) * (1.0 + checkburn)
+
+
+def checkshctrl(rpow):
+    "Check shield control."
+    skip(1)
+    if rnd.withprob(0.998):
+        prout(_("Shields lowered."))
+        return False
+    # Something bad has happened
+    prouts(_("***RED ALERT!  RED ALERT!"))
+    skip(2)
+    hit = rpow * game.shield / game.inshld
+    game.energy -= rpow + hit * 0.8
+    game.shield -= hit * 0.2
+    if game.energy <= 0.0:
+        prouts(_('Sulu-  "Captain! Shield malf***********************"'))
+        skip(1)
+        stars()
+        finish(FPHASER)
+        return True
+    prouts(_('Sulu-  "Captain! Shield malfunction! Phaser fire contained!"'))
+    skip(2)
+    prout(_('Lt. Uhura-  "Sir, all decks reporting damage."'))
+    icas = rnd.integer(int(hit * 0.012))
+    skip(1)
+    fry(0.8 * hit)
+    if icas:
+        skip(1)
+        prout(_('McCoy to bridge- "Severe radiation burns, Jim.'))
+        prout(_('  %d casualties so far."') % icas)
+        game.casual += icas
+        game.state.crew -= icas
+    skip(1)
+    prout(_("Phaser energy dispersed by shields."))
+    prout(_("Enemy unaffected."))
+    overheat(rpow)
+    return True
+
+
+def hittem(hits):
+    "Register a phaser hit on Klingons and Romulans."
+    w = Coord()
+    skip(1)
+    kk = 0
+    for wham in hits:
+        if wham == 0:
+            continue
+        dustfac = rnd.real(0.9, 1.0)
+        hit = wham * math.pow(dustfac, game.enemies[kk].kdist)
+        kpini = game.enemies[kk].power
+        kp = math.fabs(kpini)
+        if PHASEFAC * hit < kp:
+            kp = PHASEFAC * hit
+        if game.enemies[kk].power < 0:
+            game.enemies[kk].power -= -kp
+        else:
+            game.enemies[kk].power -= kp
+        kpow = game.enemies[kk].power
+        w = game.enemies[kk].location
+        if hit > 0.005:
+            if not damaged(DSRSENS):
+                boom(w)
+            proutn(_("%d unit hit on ") % int(hit))
+        else:
+            proutn(_("Very small hit on "))
+        ienm = game.quad[w.i][w.j]
+        proutn(crmena(False, ienm, "sector", w))
+        skip(1)
+        if kpow == 0:
+            deadkl(w, ienm, w)
+            if game.unwon() == 0:
+                finish(FWON)
+            if game.alldone:
+                return
+            continue
+        else:  # decide whether or not to emasculate klingon
+            # pylint: disable=chained-comparison
+            if kpow > 0 and rnd.withprob(0.9) and kpow <= rnd.real(0.4, 0.8) * kpini:
+                prout(_('***Mr. Spock-  "Captain, the vessel at Sector %s') % w)
+                prout(_('   has just lost its firepower."'))
+                game.enemies[kk].power = -kpow
+        kk += 1
+    return
+
+
+def phasers():
+    "Fire phasers at bad guys."
+    hits = []
+    kz = 0
+    k = 1
+    irec = 0  # Cheating inhibitor
+    ifast = False
+    no = False
+    itarg = True
+    msgflag = True
+    rpow = 0.0
+    automode = "NOTSET"
+    key = ""
+    skip(1)
+    # SR sensors and Computer are needed for automode
+    if damaged(DSRSENS) or damaged(DCOMPTR):
+        itarg = False
+    if game.condition == "docked":
+        prout(_("Phasers can't be fired through base shields."))
+        scanner.chew()
+        return
+    if damaged(DPHASER):
+        prout(_("Phaser control damaged."))
+        scanner.chew()
+        return
+    if game.shldup:
+        if damaged(DSHCTRL):
+            prout(_("High speed shield control damaged."))
+            scanner.chew()
+            return
+        if game.energy <= 200.0:
+            prout(_("Insufficient energy to activate high-speed shield control."))
+            scanner.chew()
+            return
+        prout(_('Weapons Officer Sulu-  "High-speed shield control enabled, sir."'))
+        ifast = True
+    # Original code so convoluted, I re-did it all
+    # (That was Tom Almy talking about the C code, I think -- ESR)
+    while automode == "NOTSET":
+        key = scanner.nexttok()
+        if key == "IHALPHA":
+            if scanner.sees("manual"):
+                if len(game.enemies) == 0:
+                    prout(_("There is no enemy present to select."))
+                    scanner.chew()
+                    key = "IHEOL"
+                    automode = "AUTOMATIC"
+                else:
+                    automode = "MANUAL"
+                    key = scanner.nexttok()
+            elif scanner.sees("automatic"):
+                if (not itarg) and len(game.enemies) != 0:
+                    automode = "FORCEMAN"
+                else:
+                    if len(game.enemies) == 0:
+                        prout(_("Energy will be expended into space."))
+                    automode = "AUTOMATIC"
+                    key = scanner.nexttok()
+            elif scanner.sees("no"):
+                no = True
+            else:
+                huh()
+                return
+        elif key == "IHREAL":
+            if len(game.enemies) == 0:
+                prout(_("Energy will be expended into space."))
+                automode = "AUTOMATIC"
+            elif not itarg:
+                automode = "FORCEMAN"
+            else:
+                automode = "AUTOMATIC"
+        else:
+            # "IHEOL"
+            if len(game.enemies) == 0:
+                prout(_("Energy will be expended into space."))
+                automode = "AUTOMATIC"
+            elif not itarg:
+                automode = "FORCEMAN"
+            else:
+                proutn(_("Manual or automatic? "))
+                scanner.chew()
+    avail = game.energy
+    if ifast:
+        avail -= 200.0
+    if automode == "AUTOMATIC":
+        if key == "IHALPHA" and scanner.sees("no"):
+            no = True
+            key = scanner.nexttok()
+        if key != "IHREAL" and len(game.enemies) != 0:
+            prout(_("Phasers locked on target. Energy available: %.2f") % avail)
+        irec = 0
+        while True:
+            scanner.chew()
+            if not kz:
+                for i in range(len(game.enemies)):
+                    irec += (
+                        math.fabs(game.enemies[i].power)
+                        / (PHASEFAC * math.pow(0.90, game.enemies[i].kdist))
+                        * rnd.real(1.01, 1.06)
+                        + 1.0
+                    )
+            kz = 1
+            proutn(_("%d units required. ") % irec)
+            scanner.chew()
+            proutn(_("Units to fire= "))
+            key = scanner.nexttok()
+            if key != "IHREAL":
+                return
+            rpow = scanner.real
+            if rpow > avail:
+                proutn(_("Energy available= %.2f") % avail)
+                skip(1)
+                key = "IHEOL"
+            if not rpow > avail:
+                break
+        if rpow <= 0:
+            # chicken out
+            scanner.chew()
+            return
+        key = scanner.nexttok()
+        if key == "IHALPHA" and scanner.sees("no"):
+            no = True
+        if ifast:
+            game.energy -= 200  # Go and do it!
+            if checkshctrl(rpow):
+                return
+        scanner.chew()
+        game.energy -= rpow
+        extra = rpow
+        if len(game.enemies):
+            extra = 0.0
+            powrem = rpow
+            for i in range(len(game.enemies)):
+                hits.append(0.0)
+                if powrem <= 0:
+                    continue
+                hits[i] = math.fabs(game.enemies[i].power) / (
+                    PHASEFAC * math.pow(0.90, game.enemies[i].kdist)
+                )
+                over = rnd.real(1.01, 1.06) * hits[i]
+                temp = powrem
+                powrem -= hits[i] + over
+                if powrem <= 0 and temp < hits[i]:
+                    hits[i] = temp
+                if powrem <= 0:
+                    over = 0.0
+                extra += over
+            if powrem > 0.0:
+                extra += powrem
+            hittem(hits)
+            game.ididit = True
+        if extra > 0 and not game.alldone:
+            if game.tholian:
+                proutn(_("*** Tholian web absorbs "))
+                if len(game.enemies) > 0:
+                    proutn(_("excess "))
+                prout(_("phaser energy."))
+            else:
+                prout(_("%d expended on empty space.") % int(extra))
+    elif automode == "FORCEMAN":
+        scanner.chew()
+        key = "IHEOL"
+        if damaged(DCOMPTR):
+            prout(_("Battle computer damaged, manual fire only."))
+        else:
+            skip(1)
+            prouts(_("---WORKING---"))
+            skip(1)
+            prout(_("Short-range-sensors-damaged"))
+            prout(_("Insufficient-data-for-automatic-phaser-fire"))
+            prout(_("Manual-fire-must-be-used"))
+            skip(1)
+    elif automode == "MANUAL":
+        rpow = 0.0
+        for k in range(len(game.enemies)):
+            aim = game.enemies[k].location
+            ienm = game.quad[aim.i][aim.j]
+            if msgflag:
+                proutn(_("Energy available= %.2f") % (avail - 0.006))
+                skip(1)
+                msgflag = False
+                rpow = 0.0
+            if (
+                damaged(DSRSENS)
+                and not game.sector.distance(aim) < 2 ** 0.5
+                and ienm in ("C", "S")
+            ):
+                prout(cramen(ienm) + _(" can't be located without short range scan."))
+                scanner.chew()
+                key = "IHEOL"
+                hits[k] = 0  # prevent overflow -- thanks to Alexei Voitenko
+                continue
+            if key == "IHEOL":
+                scanner.chew()
+                if itarg and k > kz:
+                    irec = (
+                        abs(game.enemies[k].power)
+                        / (PHASEFAC * math.pow(0.9, game.enemies[k].kdist))
+                    ) * rnd.real(1.01, 1.06) + 1.0
+                kz = k
+                proutn("(")
+                if not damaged(DCOMPTR):
+                    proutn("%d" % irec)
+                else:
+                    proutn("??")
+                proutn(")  ")
+                proutn(_("units to fire at %s-  ") % crmena(False, ienm, "sector", aim))
+                key = scanner.nexttok()
+            if key == "IHALPHA" and scanner.sees("no"):
+                no = True
+                key = scanner.nexttok()
+                continue
+            if key == "IHALPHA":
+                huh()
+                return
+            if key == "IHEOL":
+                if k == 1:  # Let me say I'm baffled by this
+                    msgflag = True
+                continue
+            if scanner.real < 0:
+                # abort out
+                scanner.chew()
+                return
+            hits.append(scanner.real)
+            rpow += scanner.real
+            # If total requested is too much, inform and start over
+            if rpow > avail:
+                prout(_("Available energy exceeded -- try again."))
+                scanner.chew()
+                return
+            key = scanner.nexttok()  # scan for next value
+        if rpow == 0.0:
+            # zero energy -- abort
+            scanner.chew()
+            return
+        if key == "IHALPHA" and scanner.sees("no"):
+            no = True
+        game.energy -= rpow
+        scanner.chew()
+        if ifast:
+            game.energy -= 200.0
+            if checkshctrl(rpow):
+                return
+        hittem(hits)
+        game.ididit = True
+    # Say shield raised or malfunction, if necessary
+    if game.alldone:
+        return
+    if ifast:
+        skip(1)
+        if no == 0:
+            if rnd.withprob(0.01):
+                prout(
+                    _(
+                        'Sulu-  "Sir, the high-speed shield control has malfunctioned . . .'
+                    )
+                )
+                prouts(_("         CLICK   CLICK   POP  . . ."))
+                prout(_(" No response, sir!"))
+                game.shldup = False
+            else:
+                prout(_("Shields raised."))
+        else:
+            game.shldup = False
+    overheat(rpow)
+
+
+def capture():
+    game.ididit = False  # Nothing if we fail
+    game.optime = 0.0
+
+    # Make sure there is room in the brig
+    if game.brigfree == 0:
+        prout(_("Security reports the brig is already full."))
+        return
+
+    if damaged(DRADIO):
+        prout(_('Uhura- "We have no subspace radio communication, sir."'))
+        return
+
+    if damaged(DTRANSP):
+        prout(_('Scotty- "Transporter damaged, sir."'))
+        return
+
+    # find out if there are any at all
+    if game.klhere < 1:
+        prout(_('Uhura- "Getting no response, sir."'))
+        return
+
+    # if there is more than one Klingon, find out which one
+    #  Cruddy, just takes one at random.  Should ask the captain.
+    #  Nah, just select the weakest one since it is most likely to
+    #  surrender (Tom Almy mod)
+    klingons = [e for e in game.enemies if e.type == "K"]
+    weakest = sorted(klingons, key=lambda e: e.power)[0]
+    game.optime = 0.05  # This action will take some time
+    game.ididit = True  #  So any others can strike back
+
+    # check out that Klingon
+    # The algorithm isn't that great and could use some more
+    # intelligent design
+    # x = 300 + 25*skill;
+    x = game.energy / (weakest.power * len(klingons))
+    # prout(_("Stats: energy = %s, kpower = %s, klingons = %s")
+    #      % (game.energy, weakest.power, len(klingons)))
+    x *= 2.5  # would originally have been equivalent of 1.4,
+    # but we want command to work more often, more humanely
+    # prout(_("Prob = %.4f" % x))
+    #  x = 100; // For testing, of course!
+    if x < rnd.real(100):
+        # guess what, he surrendered!!!
+        prout(_("Klingon captain at %s surrenders.") % weakest.location)
+        i = rnd.real(200)
+        if i > 0:
+            prout(
+                _("%d Klingons commit suicide rather than be taken captive.")
+                % (200 - i)
+            )
+        if i > game.brigfree:
+            prout(
+                _("%d Klingons die because there is no room for them in the brig.")
+                % (i - game.brigfree)
+            )
+            i = game.brigfree
+        game.brigfree -= i
+        prout(_("%d captives taken") % i)
+        deadkl(weakest.location, weakest.type, game.sector)
+        if game.unwon() <= 0:
+            finish(FWON)
+        return
+
+    # big surprise, he refuses to surrender
+    prout(_("Fat chance, captain!"))
+
+
+# Code from events.c begins here.
+
+# This isn't a real event queue a la BSD Trek yet -- you can only have one
+# event of each type active at any given time.  Mostly these means we can
+# only have one FDISTR/FENSLV/FREPRO sequence going at any given time
+# BSD Trek, from which we swiped the idea, can have up to 5.
+
+
+def unschedule(evtype):
+    "Remove an event from the schedule."
+    game.future[evtype].date = FOREVER
+    return game.future[evtype]
+
+
+def is_scheduled(evtype):
+    "Is an event of specified type scheduled."
+    return game.future[evtype].date != FOREVER
+
+
+def scheduled(evtype):
+    "When will this event happen?"
+    return game.future[evtype].date
+
+
+def schedule(evtype, offset):
+    "Schedule an event of specified type."
+    game.future[evtype].date = game.state.date + offset
+    return game.future[evtype]
+
+
+def postpone(evtype, offset):
+    "Postpone a scheduled event."
+    game.future[evtype].date += offset
+
+
+def cancelrest():
+    "Rest period is interrupted by event."
+    if game.resting:
+        skip(1)
+        proutn(_('Mr. Spock-  "Captain, shall we cancel the rest period?"'))
+        if ja():
+            game.resting = False
+            game.optime = 0.0
+            return True
+    return False
+
+
+def events():
+    "Run through the event queue looking for things to do."
+    i = 0
+    fintim = game.state.date + game.optime
+    yank = 0
+    ictbeam = False
+    istract = False
+    w = Coord()
+    hold = Coord()
+    ev = Event()
+    ev2 = Event()
+
+    def tractorbeam(yank):
+        "Tractor-beaming cases merge here."
+        announce()
+        game.optime = (10.0 / (7.5 * 7.5)) * yank  # 7.5 is yank rate (warp 7.5)
+        skip(1)
+        prout("***" + crmshp() + _(" caught in long range tractor beam--"))
+        # If Kirk & Co. screwing around on planet, handle
+        atover(True)  # atover(true) is Grab
+        if game.alldone:
+            return
+        if game.icraft:  # Caught in Galileo?
+            finish(FSTRACTOR)
+            return
+        # Check to see if shuttle is aboard
+        if game.iscraft == "offship":
+            skip(1)
+            if rnd.withprob(0.5):
+                prout(_("Galileo, left on the planet surface, is captured"))
+                prout(_("by aliens and made into a flying McDonald's."))
+                game.damage[DSHUTTL] = -10
+                game.iscraft = "removed"
+            else:
+                prout(_("Galileo, left on the planet surface, is well hidden."))
+        if evcode == FSPY:
+            game.quadrant = game.state.kscmdr
+        else:
+            game.quadrant = game.state.kcmdr[i]
+        game.sector = randplace(QUADSIZE)
+        prout(
+            crmshp()
+            + _(" is pulled to Quadrant %s, Sector %s") % (game.quadrant, game.sector)
+        )
+        if game.resting:
+            prout(_("(Remainder of rest/repair period cancelled.)"))
+            game.resting = False
+        if not game.shldup:
+            if not damaged(DSHIELD) and game.shield > 0:
+                doshield(shraise=True)  # raise shields
+                game.shldchg = False
+            else:
+                prout(_("(Shields not currently useable.)"))
+        newqad()
+        # Adjust finish time to time of tractor beaming?
+        # fintim = game.state.date+game.optime
+        attack(torps_ok=False)
+        if not game.state.kcmdr:
+            unschedule(FTBEAM)
+        else:
+            schedule(
+                FTBEAM, game.optime + expran(1.5 * game.intime / len(game.state.kcmdr))
+            )
+
+    def destroybase():
+        "Code merges here for any commander destroying a starbase."
+        # Not perfect, but will have to do
+        # Handle case where base is in same quadrant as starship
+        if game.battle == game.quadrant:
+            game.state.chart[game.battle.i][game.battle.j].starbase = False
+            game.quad[game.base.i][game.base.j] = "."
+            game.base.invalidate()
+            newcnd()
+            skip(1)
+            prout(_('Spock-  "Captain, I believe the starbase has been destroyed."'))
+        elif game.state.baseq and communicating():
+            # Get word via subspace radio
+            announce()
+            skip(1)
+            prout(_('Lt. Uhura-  "Captain, Starfleet Command reports that'))
+            proutn(
+                _("   the starbase in Quadrant %s has been destroyed by") % game.battle
+            )
+            if game.isatb == 2:
+                prout(_("the Klingon Super-Commander"))
+            else:
+                prout(_("a Klingon Commander"))
+            game.state.chart[game.battle.i][game.battle.j].starbase = False
+        # Remove Starbase from galaxy
+        game.state.galaxy[game.battle.i][game.battle.j].starbase = False
+        game.state.baseq = [x for x in game.state.baseq if x != game.battle]
+        if game.isatb == 2:
+            # reinstate a commander's base attack
+            game.battle = hold
+            game.isatb = 0
+        else:
+            game.battle.invalidate()
+
+    if game.idebug:  # pragma: no cover
+        prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
+        for i in range(1, NEVENTS):
+            if i == FSNOVA:
+                proutn("=== Supernova       ")
+            elif i == FTBEAM:
+                proutn("=== T Beam          ")
+            elif i == FSNAP:
+                proutn("=== Snapshot        ")
+            elif i == FBATTAK:
+                proutn("=== Base Attack     ")
+            elif i == FCDBAS:
+                proutn("=== Base Destroy    ")
+            elif i == FSCMOVE:
+                proutn("=== SC Move         ")
+            elif i == FSCDBAS:
+                proutn("=== SC Base Destroy ")
+            elif i == FDSPROB:
+                proutn("=== Probe Move      ")
+            elif i == FDISTR:
+                proutn("=== Distress Call   ")
+            elif i == FENSLV:
+                proutn("=== Enslavement     ")
+            elif i == FREPRO:
+                proutn("=== Klingon Build   ")
+            if is_scheduled(i):
+                prout("%.2f" % (scheduled(i)))
+            else:
+                prout("never")
+    radio_was_broken = damaged(DRADIO)
+    hold.i = hold.j = 0
+    while True:
+        # Select earliest extraneous event, evcode==0 if no events
+        evcode = FSPY
+        if game.alldone:
+            return
+        datemin = fintim
+        for l in range(1, NEVENTS):
+            if game.future[l].date < datemin:
+                evcode = l
+                if game.idebug:
+                    prout("== Event %d fires" % evcode)  # pragma: no cover
+                datemin = game.future[l].date
+        xtime = datemin - game.state.date
+        if game.iscloaked:
+            game.energy -= xtime * 500.0
+            if game.energy <= 0:
+                finish(FNRG)
+                return
+        game.state.date = datemin
+        # Decrement Federation resources and recompute remaining time
+        game.state.remres -= (game.remkl() + 4 * len(game.state.kcmdr)) * xtime
+        game.recompute()
+        if game.state.remtime <= 0:
+            finish(FDEPLETE)
+            return
+        # Any crew left alive?
+        if game.state.crew <= 0:
+            finish(FCREW)
+            return
+        # Is life support adequate?
+        if damaged(DLIFSUP) and game.condition != "docked":
+            if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
+                finish(FLIFESUP)
+                return
+            game.lsupres -= xtime
+            if game.damage[DLIFSUP] <= xtime:
+                game.lsupres = game.inlsr
+        # Fix devices
+        repair = xtime
+        if game.condition == "docked":
+            repair /= DOCKFAC
+        # Don't fix Deathray here
+        for l in range(NDEVICES):
+            if game.damage[l] > 0.0 and l != DDRAY:
+                if game.damage[l] - repair > 0.0:
+                    game.damage[l] -= repair
+                else:
+                    game.damage[l] = 0.0
+        # If radio repaired, update star chart and attack reports
+        if radio_was_broken and not damaged(DRADIO):
+            prout(_('Lt. Uhura- "Captain, the sub-space radio is working and'))
+            prout(_("   surveillance reports are coming in."))
+            skip(1)
+            if not game.iseenit:
+                attackreport(False)
+                game.iseenit = True
+            rechart()
+            prout(_('   The star chart is now up to date."'))
+            skip(1)
+        # Cause extraneous event EVCODE to occur
+        game.optime -= xtime
+        if evcode == FSNOVA:  # Supernova
+            announce()
+            supernova(None)
+            schedule(FSNOVA, expran(0.5 * game.intime))
+            if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
+                return
+        elif evcode == FSPY:  # Check with spy to see if SC should tractor beam
+            if (
+                game.state.nscrem == 0
+                or game.iscloaked
+                or ictbeam
+                or istract
+                or game.condition == "docked"
+                or game.isatb == 1
+                or game.iscate
+            ):
+                return
+            if (
+                game.ientesc
+                or (game.energy < 2000 and game.torps < 4 and game.shield < 1250)
+                or (damaged(DPHASER) and (damaged(DPHOTON) or game.torps < 4))
+                or (
+                    damaged(DSHIELD)
+                    and (game.energy < 2500 or damaged(DPHASER))
+                    and (game.torps < 5 or damaged(DPHOTON))
+                )
+            ):
+                # Tractor-beam her!
+                istract = ictbeam = True
+                tractorbeam((game.state.kscmdr - game.quadrant).distance())
+            else:
+                return
+        elif evcode == FTBEAM:  # Tractor beam
+            if not game.state.kcmdr:
+                unschedule(FTBEAM)
+                continue
+            i = rnd.integer(len(game.state.kcmdr))
+            yank = (game.state.kcmdr[i] - game.quadrant).distance()
+            if istract or game.condition == "docked" or game.iscloaked or yank == 0:
+                # Drats! Have to reschedule
+                schedule(
+                    FTBEAM,
+                    game.optime + expran(1.5 * game.intime / len(game.state.kcmdr)),
+                )
+                continue
+            ictbeam = True
+            tractorbeam(yank)
+        elif evcode == FSNAP:  # Snapshot of the universe (for time warp)
+            game.snapsht = copy.deepcopy(game.state)
+            game.state.snap = True
+            schedule(FSNAP, expran(0.5 * game.intime))
+        elif evcode == FBATTAK:  # Commander attacks starbase
+            if not game.state.kcmdr or not game.state.baseq:
+                # no can do
+                unschedule(FBATTAK)
+                unschedule(FCDBAS)
+                continue
+            ibq = None  # Force battle location to persist past loop
+            try:
+                for ibq in game.state.baseq:
+                    for cmdr in game.state.kcmdr:
+                        if (
+                            ibq == cmdr
+                            and ibq != game.quadrant
+                            and ibq != game.state.kscmdr
+                        ):
+                            raise JumpOut
+                # no match found -- try later
+                schedule(FBATTAK, expran(0.3 * game.intime))
+                unschedule(FCDBAS)
+                continue
+            except JumpOut:
+                pass
+            # commander + starbase combination found -- launch attack
+            game.battle = ibq
+            schedule(FCDBAS, rnd.real(1.0, 4.0))
+            if game.isatb:  # extra time if SC already attacking
+                postpone(FCDBAS, scheduled(FSCDBAS) - game.state.date)
+            game.future[FBATTAK].date = game.future[FCDBAS].date + expran(
+                0.3 * game.intime
+            )
+            game.iseenit = False
+            if not communicating():
+                continue  # No warning :-(
+            game.iseenit = True
+            announce()
+            skip(1)
+            prout(_('Lt. Uhura-  "Captain, the starbase in Quadrant %s') % game.battle)
+            prout(_("   reports that it is under attack and that it can"))
+            prout(_('   hold out only until stardate %d."') % (int(scheduled(FCDBAS))))
+            if cancelrest():
+                return
+        elif evcode == FSCDBAS:  # Supercommander destroys base
+            unschedule(FSCDBAS)
+            game.isatb = 2
+            if not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].starbase:
+                continue  # WAS RETURN!
+            hold = game.battle
+            game.battle = game.state.kscmdr
+            destroybase()
+        elif evcode == FCDBAS:  # Commander succeeds in destroying base
+            if evcode == FCDBAS:
+                unschedule(FCDBAS)
+                if (
+                    not game.state.baseq
+                    or not game.state.galaxy[game.battle.i][game.battle.j].starbase
+                ):
+                    game.battle.invalidate()
+                    continue
+                # find the lucky pair
+                for cmdr in game.state.kcmdr:
+                    if cmdr == game.battle:
+                        break
+                else:
+                    # No action to take after all
+                    continue
+            destroybase()
+        elif evcode == FSCMOVE:  # Supercommander moves
+            schedule(FSCMOVE, 0.2777)
+            if (
+                not game.ientesc
+                and not istract
+                and game.isatb != 1
+                and (not game.iscate or not game.justin)
+            ):
+                supercommander()
+        elif evcode == FDSPROB:  # Move deep space probe
+            schedule(FDSPROB, 0.01)
+            if not game.probe.nextstep():
+                if (
+                    not game.probe.quadrant().valid_quadrant()
+                    or game.state.galaxy[game.probe.quadrant().i][
+                        game.probe.quadrant().j
+                    ].supernova
+                ):
+                    # Left galaxy or ran into supernova
+                    if communicating():
+                        announce()
+                        skip(1)
+                        proutn(_('Lt. Uhura-  "The deep space probe '))
+                        if not game.probe.quadrant().valid_quadrant():
+                            prout(_('has left the galaxy."'))
+                        else:
+                            prout(_('is no longer transmitting."'))
+                    unschedule(FDSPROB)
+                    continue
+                if communicating():
+                    # announce()
+                    skip(1)
+                    prout(
+                        _('Lt. Uhura-  "The deep space probe is now in Quadrant %s."')
+                        % game.probe.quadrant()
+                    )
+            pquad = game.probe.quadrant()
+            pdest = game.state.galaxy[pquad.i][pquad.j]
+            if communicating():
+                game.state.chart[pquad.i][pquad.j].klingons = pdest.klingons
+                game.state.chart[pquad.i][pquad.j].starbase = pdest.starbase
+                game.state.chart[pquad.i][pquad.j].stars = pdest.stars
+                pdest.charted = True
+            game.probe.moves -= 1  # One less to travel
+            if game.probe.arrived() and game.isarmed and pdest.stars:
+                supernova(game.probe.quadrant())  # fire in the hole!
+                unschedule(FDSPROB)
+                if game.state.galaxy[pquad.i][pquad.j].supernova:
+                    return
+        elif evcode == FDISTR:  # inhabited system issues distress call
+            unschedule(FDISTR)
+            # try a whole bunch of times to find something suitable
+            for i in range(100):
+                # need a quadrant which is not the current one,
+                # which has some stars which are inhabited and
+                # not already under attack, which is not
+                # supernova'ed, and which has some Klingons in it
+                w = randplace(GALSIZE)
+                q = game.state.galaxy[w.i][w.j]
+                if not (
+                    game.quadrant == w
+                    or q.planet is None
+                    or not q.planet.inhabited
+                    or q.supernova
+                    or q.status != "secure"
+                    or q.klingons <= 0
+                ):
+                    break
+            else:
+                # can't seem to find one; ignore this call
+                if game.idebug:
+                    prout(
+                        "=== Couldn't find location for distress event."
+                    )  # pragma: no cover
+                continue
+            # got one!!  Schedule its enslavement
+            ev = schedule(FENSLV, expran(game.intime))
+            ev.quadrant = w
+            q.status = "distressed"
+            # tell the captain about it if we can
+            if communicating():
+                prout(
+                    _("Uhura- Captain, %s in Quadrant %s reports it is under attack")
+                    % (q.planet, repr(w))
+                )
+                prout(_("by a Klingon invasion fleet."))
+                if cancelrest():
+                    return
+        elif evcode == FENSLV:  # starsystem is enslaved
+            ev = unschedule(FENSLV)
+            # see if current distress call still active
+            q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
+            if q.klingons <= 0:
+                q.status = "secure"
+                continue
+            q.status = "enslaved"
+
+            # play stork and schedule the first baby
+            ev2 = schedule(FREPRO, expran(2.0 * game.intime))
+            ev2.quadrant = ev.quadrant
+
+            # report the disaster if we can
+            if communicating():
+                prout(_("Uhura- We've lost contact with starsystem %s") % q.planet)
+                prout(_("in Quadrant %s.\n") % ev.quadrant)
+        elif evcode == FREPRO:  # Klingon reproduces
+            # If we ever switch to a real event queue, we'll need to
+            # explicitly retrieve and restore the x and y.
+            ev = schedule(FREPRO, expran(1.0 * game.intime))
+            # see if current distress call still active
+            q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
+            if q.klingons <= 0:
+                q.status = "secure"
+                continue
+            if game.remkl() >= MAXKLGAME:
+                continue  # full right now
+            # reproduce one Klingon
+            w = ev.quadrant
+            m = Coord()
+            if game.klhere >= MAXKLQUAD:
+                try:
+                    # this quadrant not ok, pick an adjacent one
+                    for m.i in range(w.i - 1, w.i + 2):
+                        for m.j in range(w.j - 1, w.j + 2):
+                            if not m.valid_quadrant():
+                                continue
+                            q = game.state.galaxy[m.i][m.j]
+                            # check for this quad ok (not full & no snova)
+                            if q.klingons >= MAXKLQUAD or q.supernova:
+                                continue
+                            raise JumpOut
+                    # search for eligible quadrant failed
+                    continue
+                except JumpOut:
+                    w = m
+            # deliver the child
+            q.klingons += 1
+            if game.quadrant == w:
+                game.klhere += 1
+                newkling()  # also adds it to game.enemies
+            # recompute time left
+            game.recompute()
+            if communicating():
+                if game.quadrant == w:
+                    prout(_("Spock- sensors indicate the Klingons have"))
+                    prout(_("launched a warship from %s.") % q.planet)
+                else:
+                    prout(_("Uhura- Starfleet reports increased Klingon activity"))
+                    if q.planet is not None:
+                        proutn(_("near %s ") % q.planet)
+                    prout(_("in Quadrant %s.") % w)
+
+
+def wait():
+    "Wait on events."
+    game.ididit = False
+    while True:
+        key = scanner.nexttok()
+        if key != "IHEOL":
+            break
+        proutn(_("How long? "))
+        scanner.chew()
+    if key != "IHREAL":
+        huh()
+        return
+    origTime = delay = scanner.real
+    if delay <= 0.0:
+        return
+    if delay >= game.state.remtime or len(game.enemies) != 0:
+        proutn(_("Are you sure? "))
+        if not ja():
+            return
+    # Alternate resting periods (events) with attacks
+    game.resting = True
+    while True:
+        if delay <= 0:
+            game.resting = False
+        if not game.resting:
+            prout(_("%d stardates left.") % int(game.state.remtime))
+            return
+        temp = game.optime = delay
+        if len(game.enemies):
+            rtime = rnd.real(1.0, 2.0)
+            if rtime < temp:
+                temp = rtime
+            game.optime = temp
+        if game.optime < delay:
+            attack(torps_ok=False)
+        if game.alldone:
+            return
+        events()
+        game.ididit = True
+        if game.alldone:
+            return
+        delay -= temp
+        # Repair Deathray if long rest at starbase
+        if origTime - delay >= 9.99 and game.condition == "docked":
+            game.damage[DDRAY] = 0.0
+        # leave if quadrant supernovas
+        if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
+            break
+    game.resting = False
+    game.optime = 0.0
+
+
+def nova(nov):
+    "Star goes nova."
+    ncourse = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
+    newc = Coord()
+    neighbor = Coord()
+    bump = Coord(0, 0)
+    if rnd.withprob(0.05):
+        # Wow! We've supernova'ed
+        supernova(game.quadrant)
+        return
+    # handle initial nova
+    game.quad[nov.i][nov.j] = "."
+    prout(crmena(False, "*", "sector", nov) + _(" novas."))
+    game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
+    game.state.starkl += 1
+    # Set up queue to recursively trigger adjacent stars
+    hits = [nov]
+    kount = 0
+    while hits:
+        offset = Coord()
+        start = hits.pop()
+        for offset.i in range(-1, 1 + 1):
+            for offset.j in range(-1, 1 + 1):
+                if offset.j == 0 and offset.i == 0:
+                    continue
+                neighbor = start + offset
+                if not neighbor.valid_sector():
+                    continue
+                iquad = game.quad[neighbor.i][neighbor.j]
+                # Empty space ends reaction
+                if iquad in (".", "?", " ", "T", "#"):
+                    pass
+                elif iquad == "*":  # Affect another star
+                    if rnd.withprob(0.05):
+                        # This star supernovas
+                        supernova(game.quadrant)
+                        return
+                    else:
+                        hits.append(neighbor)
+                        game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
+                        game.state.starkl += 1
+                        proutn(crmena(True, "*", "sector", neighbor))
+                        prout(_(" novas."))
+                        game.quad[neighbor.i][neighbor.j] = "."
+                        kount += 1
+                elif iquad in ("P", "@"):  # Destroy planet
+                    game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
+                    if iquad == "P":
+                        game.state.nplankl += 1
+                    else:
+                        game.state.nworldkl += 1
+                    prout(crmena(True, "B", "sector", neighbor) + _(" destroyed."))
+                    game.iplnet.pclass = "destroyed"
+                    game.iplnet = None
+                    game.plnet.invalidate()
+                    if game.landed:
+                        finish(FPNOVA)
+                        return
+                    game.quad[neighbor.i][neighbor.j] = "."
+                elif iquad == "B":  # Destroy base
+                    game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase = False
+                    game.state.baseq = [
+                        x for x in game.state.baseq if x != game.quadrant
+                    ]
+                    game.base.invalidate()
+                    game.state.basekl += 1
+                    newcnd()
+                    prout(crmena(True, "B", "sector", neighbor) + _(" destroyed."))
+                    game.quad[neighbor.i][neighbor.j] = "."
+                elif iquad in ("E", "F"):  # Buffet ship
+                    prout(_("***Starship buffeted by nova."))
+                    if game.shldup:
+                        if game.shield >= 2000.0:
+                            game.shield -= 2000.0
+                        else:
+                            diff = 2000.0 - game.shield
+                            game.energy -= diff
+                            game.shield = 0.0
+                            game.shldup = False
+                            prout(_("***Shields knocked out."))
+                            game.damage[DSHIELD] += (
+                                0.005 * game.damfac * rnd.real() * diff
+                            )
+                    else:
+                        game.energy -= 2000.0
+                    if game.energy <= 0:
+                        finish(FNOVA)
+                        return
+                    # add in course nova contributes to kicking starship
+                    if hits:
+                        bump += (game.sector - hits[-1]).sgn()
+                elif iquad == "K":  # kill klingon
+                    deadkl(neighbor, iquad, neighbor)
+                elif iquad in ("C", "S", "R"):  # Damage/destroy big enemies
+                    target = None
+                    for ll in range(len(game.enemies)):
+                        if game.enemies[ll].location == neighbor:
+                            target = game.enemies[ll]
+                            break
+                    if target is not None:
+                        target.power -= 800.0  # If firepower is lost, die
+                        if target.power <= 0.0:
+                            deadkl(neighbor, iquad, neighbor)
+                            continue  # neighbor loop
+                        # Else enemy gets flung by the blast wave
+                        newc = neighbor + neighbor - start
+                        proutn(crmena(True, iquad, "sector", neighbor) + _(" damaged"))
+                        if not newc.valid_sector():
+                            # can't leave quadrant
+                            skip(1)
+                            continue
+                        iquad1 = game.quad[newc.i][newc.j]
+                        if iquad1 == " ":
+                            proutn(
+                                _(", blasted into ")
+                                + crmena(False, " ", "sector", newc)
+                            )
+                            skip(1)
+                            deadkl(neighbor, iquad, newc)
+                            continue
+                        if iquad1 != ".":
+                            # can't move into something else
+                            skip(1)
+                            continue
+                        proutn(_(", buffeted to Sector %s") % newc)
+                        game.quad[neighbor.i][neighbor.j] = "."
+                        game.quad[newc.i][newc.j] = iquad
+                        target.move(newc)
+    # Starship affected by nova -- kick it away.
+    dist = kount * 0.1
+    direc = ncourse[3 * (bump.i + 1) + bump.j + 2]
+    if direc == 0.0:
+        dist = 0.0
+    if dist == 0.0:
+        return
+    scourse = course(bearing=direc, distance=dist)
+    game.optime = scourse.time(w=4)
+    skip(1)
+    prout(_("Force of nova displaces starship."))
+    imove(scourse, noattack=True)
+    game.optime = scourse.time(w=4)
+    return
+
+
+def supernova(w):
+    "Star goes supernova."
+    num = 0
+    npdead = 0
+    if w is not None:
+        nq = copy.copy(w)
+    else:
+        # Scheduled supernova -- select star at random.
+        nstars = 0
+        nq = Coord()
+        for nq.i in range(GALSIZE):
+            for nq.j in range(GALSIZE):
+                nstars += game.state.galaxy[nq.i][nq.j].stars
+        if nstars == 0:
+            return  # nothing to supernova exists
+        num = rnd.integer(nstars) + 1
+        for nq.i in range(GALSIZE):
+            for nq.j in range(GALSIZE):
+                num -= game.state.galaxy[nq.i][nq.j].stars
+                if num <= 0:
+                    break
+            if num <= 0:
+                break
+        if game.idebug:  # pragma: no cover
+            proutn("=== Super nova here?")
+            if ja():
+                nq = game.quadrant
+    if nq != game.quadrant or game.justin:
+        # it isn't here, or we just entered (treat as enroute)
+        if communicating():
+            skip(1)
+            prout(
+                _("Message from Starfleet Command       Stardate %.2f")
+                % game.state.date
+            )
+            prout(_("     Supernova in Quadrant %s; caution advised.") % nq)
+    else:
+        ns = Coord()
+        # we are in the quadrant!
+        num = rnd.integer(game.state.galaxy[nq.i][nq.j].stars) + 1
+        for ns.i in range(QUADSIZE):
+            for ns.j in range(QUADSIZE):
+                if game.quad[ns.i][ns.j] == "*":
+                    num -= 1
+                    if num == 0:
+                        break
+            if num == 0:
+                break
+        skip(1)
+        prouts(_("***RED ALERT!  RED ALERT!"))
+        skip(1)
+        prout(_("***Incipient supernova detected at Sector %s") % ns)
+        if (ns.i - game.sector.i) ** 2 + (ns.j - game.sector.j) ** 2 <= 2.1:
+            proutn(_("Emergency override attempts t"))
+            prouts("***************")
+            skip(1)
+            stars()
+            game.alldone = True
+    # destroy any Klingons in supernovaed quadrant
+    game.state.galaxy[nq.i][nq.j].klingons = 0
+    if nq == game.state.kscmdr:
+        # did in the Supercommander!
+        game.state.nscrem = game.state.kscmdr.i = game.state.kscmdr.j = game.isatb = 0
+        game.iscate = False
+        unschedule(FSCMOVE)
+        unschedule(FSCDBAS)
+    # Changing this to [w for w in game.state.kcmdr if w != nq]
+    # causes regression-test failure
+    survivors = list(filter(lambda w: w != nq, game.state.kcmdr))
+    # comkills = len(game.state.kcmdr) - len(survivors)
+    game.state.kcmdr = survivors
+    if not game.state.kcmdr:
+        unschedule(FTBEAM)
+    # destroy Romulans and planets in supernovaed quadrant
+    nrmdead = game.state.galaxy[nq.i][nq.j].romulans
+    game.state.galaxy[nq.i][nq.j].romulans = 0
+    game.state.nromrem -= nrmdead
+    # Destroy planets
+    for loop in range(game.inplan):
+        if game.state.planets[loop].quadrant == nq:
+            game.state.planets[loop].pclass = "destroyed"
+            npdead += 1
+    # Destroy any base in supernovaed quadrant
+    game.state.baseq = [x for x in game.state.baseq if x != nq]
+    # If starship caused supernova, tally up destruction
+    if w is not None:
+        game.state.starkl += game.state.galaxy[nq.i][nq.j].stars
+        game.state.basekl += game.state.galaxy[nq.i][nq.j].starbase
+        game.state.nplankl += npdead
+    # mark supernova in galaxy and in star chart
+    if game.quadrant == nq or communicating():
+        game.state.galaxy[nq.i][nq.j].supernova = True
+    # If supernova destroys last Klingons give special message
+    if game.unwon() == 0 and nq != game.quadrant:
+        skip(2)
+        if w is None:
+            prout(_("Lucky you!"))
+        proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
+        finish(FWON)
+        return
+    # if some Klingons remain, continue or die in supernova
+    if game.alldone:
+        finish(FSNOVAED)
+    return
+
+
+# Code from finish.c ends here.
+
+
+def selfdestruct():
+    "Self-destruct maneuver. Finish with a BANG!"
+    scanner.chew()
+    if damaged(DCOMPTR):
+        prout(_("Computer damaged; cannot execute destruct sequence."))
+        return
+    prouts(_("---WORKING---"))
+    skip(1)
+    prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED"))
+    skip(1)
+    prouts("   10")
+    skip(1)
+    prouts("       9")
+    skip(1)
+    prouts("          8")
+    skip(1)
+    prouts("             7")
+    skip(1)
+    prouts("                6")
+    skip(1)
+    skip(1)
+    prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
+    skip(1)
+    prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
+    skip(1)
+    prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
+    skip(1)
+    scanner.nexttok()
+    if game.passwd != scanner.token:
+        prouts(_("PASSWORD-REJECTED;"))
+        skip(1)
+        prouts(_("CONTINUITY-EFFECTED"))
+        skip(2)
+        return
+    prouts(_("PASSWORD-ACCEPTED"))
+    skip(1)
+    prouts("                   5")
+    skip(1)
+    prouts("                      4")
+    skip(1)
+    prouts("                         3")
+    skip(1)
+    prouts("                            2")
+    skip(1)
+    prouts("                              1")
+    skip(1)
+    if rnd.withprob(0.15):
+        prouts(_("GOODBYE-CRUEL-WORLD"))
+        skip(1)
+    kaboom()
+
+
+def kaboom():
+    stars()
+    if game.ship == "E":
+        prouts("***")
+    prouts(_("********* Entropy of %s maximized *********") % crmshp())
+    skip(1)
+    stars()
+    skip(1)
+    if len(game.enemies) != 0:
+        whammo = 25.0 * game.energy
+        for e in game.enemies[::-1]:
+            if e.power * e.kdist <= whammo:
+                deadkl(e.location, game.quad[e.location.i][e.location.j], e.location)
+    finish(FDILITHIUM)
+
+
+def killrate():
+    "Compute our rate of kils over time."
+    elapsed = game.state.date - game.indate
+    if elapsed == 0:  # Avoid divide-by-zero error if calculated on turn 0
+        return 0
+    else:
+        starting = game.inkling + game.incom + game.inscom
+        remaining = game.unwon()
+        return (starting - remaining) / elapsed
+
+
+def badpoints():
+    "Compute demerits."
+    badpt = (
+        5.0 * game.state.starkl
+        + game.casual
+        + 10.0 * game.state.nplankl
+        + 300 * game.state.nworldkl
+        + 45.0 * game.nhelp
+        + 100.0 * game.state.basekl
+        + 3.0 * game.abandoned
+        + 100 * game.ncviol
+    )
+    if game.ship == "F":
+        badpt += 100.0
+    elif game.ship is None:
+        badpt += 200.0
+    return badpt
+
+
+def finish(ifin):
+    # end the game, with appropriate notifications
+    igotit = False
+    game.alldone = True
+    skip(3)
+    prout(_("It is stardate %.1f.") % game.state.date)
+    skip(1)
+    if ifin == FWON:  # Game has been won
+        if game.state.nromrem != 0:
+            prout(
+                _("The remaining %d Romulans surrender to Starfleet Command.")
+                % game.state.nromrem
+            )
+
+        prout(_("You have smashed the Klingon invasion fleet and saved"))
+        prout(_("the Federation."))
+        if game.alive and game.brigcapacity - game.brigfree > 0:
+            game.kcaptured += game.brigcapacity - game.brigfree
+            prout(
+                _("The %d captured Klingons are transferred to Star Fleet Command.")
+                % (game.brigcapacity - game.brigfree)
+            )
+        game.gamewon = True
+        if game.alive:
+            badpt = badpoints()
+            if badpt < 100.0:
+                badpt = 0.0  # Close enough!
+            # killsPerDate >= RateMax
+            if (
+                game.state.date - game.indate < 5.0
+                or killrate()
+                >= 0.1 * game.skill * (game.skill + 1.0) + 0.1 + 0.008 * badpt
+            ):
+                skip(1)
+                prout(_("In fact, you have done so well that Starfleet Command"))
+                if game.skill == SKILL_NOVICE:
+                    prout(_('promotes you one step in rank from "Novice" to "Fair".'))
+                elif game.skill == SKILL_FAIR:
+                    prout(_('promotes you one step in rank from "Fair" to "Good".'))
+                elif game.skill == SKILL_GOOD:
+                    prout(_('promotes you one step in rank from "Good" to "Expert".'))
+                elif game.skill == SKILL_EXPERT:
+                    prout(_("promotes you to Commodore Emeritus."))
+                    skip(1)
+                    prout(_("Now that you think you're really good, try playing"))
+                    prout(_('the "Emeritus" game. It will splatter your ego.'))
+                elif game.skill == SKILL_EMERITUS:
+                    skip(1)
+                    proutn(_("Computer-  "))
+                    prouts(_("ERROR-ERROR-ERROR-ERROR"))
+                    skip(2)
+                    prouts(_("  YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
+                    skip(1)
+                    prouts(_("  THIS-PROGRAM-MUST-SURVIVE"))
+                    skip(1)
+                    prouts(_("  THIS-PROGRAM-MUST-SURVIVE"))
+                    skip(1)
+                    prouts(_("  THIS-PROGRAM-MUST-SURVIVE"))
+                    skip(1)
+                    prouts(_("  THIS-PROGRAM-MUST?- MUST ? - SUR? ? -?  VI"))
+                    skip(2)
+                    prout(_("Now you can retire and write your own Star Trek game!"))
+                    skip(1)
+                elif game.skill >= SKILL_EXPERT:
+                    if game.thawed and not game.idebug:
+                        prout(_("You cannot get a citation, so..."))
+                    else:
+                        proutn(
+                            _("Do you want your Commodore Emeritus Citation printed? ")
+                        )
+                        scanner.chew()
+                        if ja():
+                            igotit = True
+            # Only grant long life if alive (original didn't!)
+            skip(1)
+            prout(_("LIVE LONG AND PROSPER."))
+        score()
+        if igotit:
+            plaque()
+        return
+    elif ifin == FDEPLETE:  # Federation Resources Depleted
+        prout(_("Your time has run out and the Federation has been"))
+        prout(_("conquered.  Your starship is now Klingon property,"))
+        prout(_("and you are put on trial as a war criminal.  On the"))
+        proutn(_("basis of your record, you are "))
+        if game.unwon() * 3.0 > (game.inkling + game.incom + game.inscom):
+            prout(_("acquitted."))
+            skip(1)
+            prout(_("LIVE LONG AND PROSPER."))
+        else:
+            prout(_("found guilty and"))
+            prout(_("sentenced to death by slow torture."))
+            game.alive = False
+        score()
+        return
+    elif ifin == FLIFESUP:
+        prout(_("Your life support reserves have run out, and"))
+        prout(_("you die of thirst, starvation, and asphyxiation."))
+        prout(_("Your starship is a derelict in space."))
+    elif ifin == FNRG:
+        prout(_("Your energy supply is exhausted."))
+        skip(1)
+        prout(_("Your starship is a derelict in space."))
+    elif ifin == FBATTLE:
+        prout(_("The %s has been destroyed in battle.") % crmshp())
+        skip(1)
+        prout(_("Dulce et decorum est pro patria mori."))
+    elif ifin == FNEG3:
+        prout(_("You have made three attempts to cross the negative energy"))
+        prout(_("barrier which surrounds the galaxy."))
+        skip(1)
+        prout(_("Your navigation is abominable."))
+        score()
+    elif ifin == FNOVA:
+        prout(_("Your starship has been destroyed by a nova."))
+        prout(_("That was a great shot."))
+        skip(1)
+    elif ifin == FSNOVAED:
+        prout(_("The %s has been fried by a supernova.") % crmshp())
+        prout(_("...Not even cinders remain..."))
+    elif ifin == FABANDN:
+        prout(_("You have been captured by the Klingons. If you still"))
+        prout(_("had a starbase to be returned to, you would have been"))
+        prout(_("repatriated and given another chance. Since you have"))
+        prout(_("no starbases, you will be mercilessly tortured to death."))
+    elif ifin == FDILITHIUM:
+        prout(_("Your starship is now an expanding cloud of subatomic particles"))
+    elif ifin == FMATERIALIZE:
+        prout(_("Starbase was unable to re-materialize your starship."))
+        prout(_("Sic transit gloria mundi."))
+    elif ifin == FPHASER:
+        prout(_("The %s has been cremated by its own phasers.") % crmshp())
+    elif ifin == FLOST:
+        prout(_("You and your landing party have been"))
+        prout(_("converted to energy, dissipating through space."))
+    elif ifin == FMINING:
+        # This does not seem to be reachable from any code path.
+        prout(_("You are left with your landing party on"))
+        prout(_("a wild jungle planet inhabited by primitive cannibals."))
+        skip(1)
+        prout(_('They are very fond of "Captain Kirk" soup.'))
+        skip(1)
+        prout(_("Without your leadership, the %s is destroyed.") % crmshp())
+    elif ifin == FDPLANET:
+        prout(_("You and your mining party perish."))
+        skip(1)
+        prout(_("That was a great shot."))
+        skip(1)
+    elif ifin == FSSC:
+        # This does not seem to be reachable from any code path.
+        prout(_("The Galileo is instantly annihilated by the supernova."))
+        prout(_("You and your mining party are atomized."))
+        skip(1)
+        prout(_("Mr. Spock takes command of the %s and") % crmshp())
+        prout(_("joins the Romulans, wreaking terror on the Federation."))
+    elif ifin == FPNOVA:
+        prout(_("You and your mining party are atomized."))
+        skip(1)
+        prout(_("Mr. Spock takes command of the %s and") % crmshp())
+        prout(_("joins the Romulans, wreaking terror on the Federation."))
+    elif ifin == FSTRACTOR:
+        prout(_("The shuttle craft Galileo is also caught,"))
+        prout(_("and breaks up under the strain."))
+        skip(1)
+        prout(_("Your debris is scattered for millions of miles."))
+        prout(_("Without your leadership, the %s is destroyed.") % crmshp())
+    elif ifin == FDRAY:
+        prout(_("The mutants attack and kill Spock."))
+        prout(_("Your ship is captured by Klingons, and"))
+        prout(_("your crew is put on display in a Klingon zoo."))
+    elif ifin == FTRIBBLE:
+        prout(_("Tribbles consume all remaining water,"))
+        prout(_("food, and oxygen on your ship."))
+        skip(1)
+        prout(_("You die of thirst, starvation, and asphyxiation."))
+        prout(_("Your starship is a derelict in space."))
+    elif ifin == FHOLE:
+        prout(_("Your ship is drawn to the center of the black hole."))
+        prout(_("You are crushed into extremely dense matter."))
+    elif ifin == FCLOAK:
+        game.ncviol += 1
+        prout(_("You have violated the Treaty of Algeron."))
+        prout(_("The Romulan Empire can never trust you again."))
+    elif ifin == FCREW:
+        prout(_("Your last crew member has died."))
+    if ifin != FWON and ifin != FCLOAK and game.iscloaked:
+        prout(
+            _("Your ship was cloaked so your subspace radio did not receive anything.")
+        )
+        prout(_("You may have missed some warning messages."))
+        skip(1)
+    if game.ship == "F":
+        game.ship = None
+    elif game.ship == "E":
+        game.ship = "F"
+    game.alive = False
+    if game.unwon() != 0:
+        goodies = game.state.remres / game.inresor
+        baddies = (game.remkl() + 2.0 * len(game.state.kcmdr)) / (
+            game.inkling + 2.0 * game.incom
+        )
+        if goodies / baddies >= rnd.real(1.0, 1.5):
+            prout(_("As a result of your actions, a treaty with the Klingon"))
+            prout(_("Empire has been signed. The terms of the treaty are"))
+            if goodies / baddies >= rnd.real(3.0):
+                prout(_("favorable to the Federation."))
+                skip(1)
+                prout(_("Congratulations!"))
+            else:
+                prout(_("highly unfavorable to the Federation."))
+        else:
+            prout(_("The Federation will be destroyed."))
+    else:
+        prout(_("Since you took the last Klingon with you, you are a"))
+        prout(_("martyr and a hero. Someday maybe they'll erect a"))
+        prout(_("statue in your memory. Rest in peace, and try not"))
+        prout(_("to think about pigeons."))
+        game.gamewon = True
+    score()
+    scanner.chew()  # Clean up leftovers
+
+
+def score():
+    "Compute player's score."
+    timused = game.state.date - game.indate
+    if (timused == 0 or game.unwon() != 0) and timused < 5.0:
+        timused = 5.0
+    game.perdate = killrate()
+    ithperd = 500 * game.perdate + 0.5
+    iwon = 0
+    if game.gamewon:
+        iwon = 100 * game.skill
+    if game.ship == "E":
+        klship = 0
+    elif game.ship == "F":
+        klship = 1
+    else:
+        klship = 2
+    dead_ordinaries = (
+        game.inkling - game.remkl() + len(game.state.kcmdr) + game.state.nscrem
+    )
+    game.score = (
+        10 * (dead_ordinaries)
+        + 50 * (game.incom - len(game.state.kcmdr))
+        + ithperd
+        + iwon
+        + 20 * (game.inrom - game.state.nromrem)
+        + 200 * (game.inscom - game.state.nscrem)
+        - game.state.nromrem
+        + 3 * game.kcaptured
+        - badpoints()
+    )
+    if not game.alive:
+        game.score -= 200
+    skip(2)
+    prout(_("Your score --"))
+    if game.inrom - game.state.nromrem:
+        prout(
+            _("%6d Romulans destroyed                 %5d")
+            % (game.inrom - game.state.nromrem, 20 * (game.inrom - game.state.nromrem))
+        )
+    if game.state.nromrem and game.gamewon:
+        prout(
+            _("%6d Romulans captured                  %5d")
+            % (game.state.nromrem, game.state.nromrem)
+        )
+    if dead_ordinaries:
+        prout(
+            _("%6d ordinary Klingons destroyed        %5d")
+            % (dead_ordinaries, 10 * dead_ordinaries)
+        )
+    if game.incom - len(game.state.kcmdr):
+        prout(
+            _("%6d Klingon commanders destroyed       %5d")
+            % (
+                game.incom - len(game.state.kcmdr),
+                50 * (game.incom - len(game.state.kcmdr)),
+            )
+        )
+    if game.kcaptured:
+        prout(
+            _("%d Klingons captured                   %5d")
+            % (game.kcaptured, 3 * game.kcaptured)
+        )
+    if game.inscom - game.state.nscrem:
+        prout(
+            _("%6d Super-Commander destroyed          %5d")
+            % (game.inscom - game.state.nscrem, 200 * (game.inscom - game.state.nscrem))
+        )
+    if ithperd:
+        prout(
+            _("%6.2f Klingons per stardate              %5d") % (game.perdate, ithperd)
+        )
+    if game.state.starkl:
+        prout(
+            _("%6d stars destroyed by your action     %5d")
+            % (game.state.starkl, -5 * game.state.starkl)
+        )
+    if game.state.nplankl:
+        prout(
+            _("%6d planets destroyed by your action   %5d")
+            % (game.state.nplankl, -10 * game.state.nplankl)
+        )
+    if (game.options & OPTION_WORLDS) and game.state.nworldkl:
+        prout(
+            _("%6d inhabited planets destroyed by your action   %5d")
+            % (game.state.nworldkl, -300 * game.state.nworldkl)
+        )
+    if game.state.basekl:
+        prout(
+            _("%6d bases destroyed by your action     %5d")
+            % (game.state.basekl, -100 * game.state.basekl)
+        )
+    if game.nhelp:
+        prout(
+            _("%6d calls for help from starbase       %5d")
+            % (game.nhelp, -45 * game.nhelp)
+        )
+    if game.casual:
+        prout(
+            _("%6d casualties incurred                %5d")
+            % (game.casual, -game.casual)
+        )
+    if game.abandoned:
+        prout(
+            _("%6d crew abandoned in space            %5d")
+            % (game.abandoned, -3 * game.abandoned)
+        )
+    if klship:
+        prout(_("%6d ship(s) lost or destroyed          %5d") % (klship, -100 * klship))
+    if game.ncviol > 0:
+        if game.ncviol == 1:
+            prout(_("1 Treaty of Algeron violation          -100"))
+        else:
+            prout(
+                _("%6d Treaty of Algeron violations       %5d\n")
+                % (game.ncviol, -100 * game.ncviol)
+            )
+    if not game.alive:
+        prout(_("Penalty for getting yourself killed        -200"))
+    if game.gamewon:
+        proutn(_("Bonus for winning "))
+        if game.skill == SKILL_NOVICE:
+            proutn(_("Novice game  "))
+        elif game.skill == SKILL_FAIR:
+            proutn(_("Fair game    "))
+        elif game.skill == SKILL_GOOD:
+            proutn(_("Good game    "))
+        elif game.skill == SKILL_EXPERT:
+            proutn(_("Expert game  "))
+        elif game.skill == SKILL_EMERITUS:
+            proutn(_("Emeritus game"))
+        prout("           %5d" % iwon)
+    skip(1)
+    prout(_("TOTAL SCORE                               %5d") % game.score)
+
+
+def plaque():
+    "Emit winner's commemmorative plaque."
+    skip(2)
+    while True:
+        proutn(_("File or device name for your plaque: "))
+        winner = cgetline()
+        try:
+            fp = open(winner, "w")
+            break
+        except IOError:
+            prout(_("Invalid name."))
+
+    proutn(_("Enter name to go on plaque (up to 30 characters): "))
+    winner = cgetline()
+    # The 38 below must be 64 for 132-column paper
+    nskip = 38 - len(winner) / 2
+    # This is where the ASCII art picture was emitted.
+    # It got garbled somewhere in the chain of transmission to the Almy version.
+    # We should restore it if we can find old enough FORTRAN sources.
+    fp.write("\n\n\n")
+    fp.write(
+        _(
+            "                                                       U. S. S. ENTERPRISE\n"
+        )
+    )
+    fp.write("\n\n\n\n")
+    fp.write(
+        _(
+            "                                  For demonstrating outstanding ability as a starship captain\n"
+        )
+    )
+    fp.write("\n")
+    fp.write(
+        _(
+            "                                                Starfleet Command bestows to you\n"
+        )
+    )
+    fp.write("\n")
+    fp.write("%*s%s\n\n" % (nskip, "", winner))
+    fp.write(
+        _("                                                           the rank of\n\n")
+    )
+    fp.write(
+        _(
+            '                                                       "Commodore Emeritus"\n\n'
+        )
+    )
+    fp.write("                                                          ")
+    if game.skill == SKILL_EXPERT:
+        fp.write(_(" Expert level\n\n"))
+    elif game.skill == SKILL_EMERITUS:
+        fp.write(_("Emeritus level\n\n"))
+    else:
+        fp.write(_(" Cheat level\n\n"))
+    timestring = time.ctime()
+    fp.write(
+        _(
+            "                                                 This day of %.6s %.4s, %.8s\n\n"
+        )
+        % (timestring + 4, timestring + 20, timestring + 11)
+    )
+    fp.write(
+        _("                                                        Your score:  %d\n\n")
+        % game.score
+    )
+    fp.write(
+        _(
+            "                                                    Klingons per stardate:  %.2f\n"
+        )
+        % game.perdate
+    )
+    fp.close()
+
+
+# Code from io.c begins here
+
+rows = linecount = 0  # for paging
+stdscr = None
+replayfp = None
+fullscreen_window = None
+srscan_window = None  # Short range scan
+report_window = None  # Report legends for status window
+status_window = None  # The status window itself
+lrscan_window = None  # Long range scan
+message_window = None  # Main window for scrolling text
+prompt_window = None  # Prompt window at bottom of display
+curwnd = None
+
+
+def iostart():
+    global stdscr, rows
+    gettext.bindtextdomain("sst", "/usr/local/share/locale")
+    gettext.textdomain("sst")
+    if not (game.options & OPTION_CURSES):
+        ln_env = os.getenv("LINES")
+        if ln_env:
+            rows = ln_env
+        else:
+            rows = 25
+    else:  # pragma: no cover
+        stdscr = curses.initscr()
+        stdscr.keypad(True)
+        curses.nonl()
+        curses.cbreak()
+        if game.options & OPTION_COLOR:
+            curses.start_color()
+            curses.use_default_colors()
+            curses.init_pair(curses.COLOR_BLACK, curses.COLOR_BLACK, -1)
+            curses.init_pair(curses.COLOR_GREEN, curses.COLOR_GREEN, -1)
+            curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, -1)
+            curses.init_pair(curses.COLOR_CYAN, curses.COLOR_CYAN, -1)
+            curses.init_pair(curses.COLOR_WHITE, curses.COLOR_WHITE, -1)
+            curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, -1)
+            curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, -1)
+            curses.init_pair(curses.COLOR_YELLOW, curses.COLOR_YELLOW, -1)
+        global fullscreen_window, srscan_window, report_window, status_window
+        global lrscan_window, message_window, prompt_window
+        (rows, _columns) = stdscr.getmaxyx()
+        fullscreen_window = stdscr
+        srscan_window = curses.newwin(12, 25, 0, 0)
+        report_window = curses.newwin(11, 0, 1, 25)
+        status_window = curses.newwin(10, 0, 1, 39)
+        lrscan_window = curses.newwin(5, 0, 0, 64)
+        message_window = curses.newwin(0, 0, 12, 0)
+        prompt_window = curses.newwin(1, 0, rows - 2, 0)
+        message_window.scrollok(True)
+        setwnd(fullscreen_window)
+
+
+def ioend():
+    "Wrap up I/O."
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        stdscr.keypad(False)
+        curses.echo()
+        curses.nocbreak()
+        curses.endwin()
+
+
+def waitfor():
+    "Wait for user action -- OK to do nothing if on a TTY"
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        stdscr.getch()
+
+
+def announce():
+    skip(1)
+    prouts(_("[ANNOUNCEMENT ARRIVING...]"))
+    skip(1)
+
+
+def pause_game():
+    if game.skill > SKILL_FAIR:
+        prompt = _("[CONTINUE?]")
+    else:
+        prompt = _("[PRESS ENTER TO CONTINUE]")
+
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        drawmaps(0)
+        setwnd(prompt_window)
+        prompt_window.clear()
+        prompt_window.addstr(prompt)
+        prompt_window.getstr()
+        prompt_window.clear()
+        prompt_window.refresh()
+        setwnd(message_window)
+    else:
+        global linecount
+        sys.stdout.write("\n")
+        proutn(prompt)
+        if not replayfp:
+            input()
+        sys.stdout.write("\n" * rows)
+        linecount = 0
+
+
+def skip(i):
+    "Skip i lines.  Pause game if this would cause a scrolling event."
+    for _dummy in range(i):
+        if game.options & OPTION_CURSES:  # pragma: no cover
+            (y, _x) = curwnd.getyx()
+            try:
+                curwnd.move(y + 1, 0)
+            except curses.error:
+                pass
+        else:
+            global linecount
+            linecount += 1
+            if rows and linecount >= rows:
+                pause_game()
+            else:
+                sys.stdout.write("\n")
+
+
+def proutn(proutntline):
+    "Utter a line with no following line feed."
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        (y, x) = curwnd.getyx()
+        (my, _mx) = curwnd.getmaxyx()
+        if curwnd == message_window and y >= my - 2:
+            pause_game()
+            clrscr()
+        if logfp and game.cdebug:
+            logfp.write("#curses: at %s proutn(%s)\n" % ((y, x), repr(proutntline)))
+        curwnd.addstr(proutntline)
+        curwnd.refresh()
+    else:
+        sys.stdout.write(proutntline)
+        sys.stdout.flush()
+
+
+def prout(proutline):
+    proutn(proutline)
+    skip(1)
+
+
+def prouts(proutsline):
+    "Emit slowly!"
+    for c in proutsline:
+        if not replayfp or replayfp.closed:  # Don't slow down replays
+            time.sleep(0.03)
+        proutn(c)
+        if game.options & OPTION_CURSES:  # pragma: no cover
+            curwnd.refresh()
+        else:
+            sys.stdout.flush()
+    if not replayfp or replayfp.closed:
+        time.sleep(0.03)
+
+
+def cgetline():
+    "Get a line of input."
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        linein = codecs.decode(curwnd.getstr()) + "\n"
+        curwnd.refresh()
+    else:
+        if replayfp and not replayfp.closed:
+            while True:
+                linein = replayfp.readline()
+                proutn(linein)
+                if linein == "":  # pragma: no cover
+                    prout("*** Replay finished")
+                    replayfp.close()
+                    break
+                elif linein[0] != "#":
+                    break
+        else:
+            try:
+                linein = input() + "\n"
+            except EOFError:
+                prout("")
+                sys.exit(0)
+    if logfp:
+        logfp.write(linein)
+    return linein
+
+
+def setwnd(wnd):
+    "Change windows -- OK for this to be a no-op in tty mode."
+    global curwnd
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        if game.cdebug and logfp:
+            if wnd == fullscreen_window:
+                legend = "fullscreen"
+            elif wnd == srscan_window:
+                legend = "srscan"
+            elif wnd == report_window:
+                legend = "report"
+            elif wnd == status_window:
+                legend = "status"
+            elif wnd == lrscan_window:
+                legend = "lrscan"
+            elif wnd == message_window:
+                legend = "message"
+            elif wnd == prompt_window:
+                legend = "prompt"
+            else:
+                legend = "unknown"
+            logfp.write("#curses: setwnd(%s)\n" % legend)
+        curwnd = wnd
+        # Some curses implementations get confused when you try this.
+        try:
+            curses.curs_set(wnd in (fullscreen_window, message_window, prompt_window))
+        except curses.error:
+            pass
+
+
+def clreol():
+    "Clear to end of line -- can be a no-op in tty mode"
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        curwnd.clrtoeol()
+        curwnd.refresh()
+
+
+def clrscr():
+    "Clear screen -- can be a no-op in tty mode."
+    global linecount
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        curwnd.clear()
+        curwnd.move(0, 0)
+        curwnd.refresh()
+    linecount = 0
+
+
+def textcolor(color=DEFAULT):
+    if (game.options & OPTION_COLOR) and (
+        game.options & OPTION_CURSES
+    ):  # pragma: no cover
+        if color == DEFAULT:
+            curwnd.attrset(0)
+        elif color == BLACK:
+            curwnd.attron(curses.color_pair(curses.COLOR_BLACK))
+        elif color == BLUE:
+            curwnd.attron(curses.color_pair(curses.COLOR_BLUE))
+        elif color == GREEN:
+            curwnd.attron(curses.color_pair(curses.COLOR_GREEN))
+        elif color == CYAN:
+            curwnd.attron(curses.color_pair(curses.COLOR_CYAN))
+        elif color == RED:
+            curwnd.attron(curses.color_pair(curses.COLOR_RED))
+        elif color == MAGENTA:
+            curwnd.attron(curses.color_pair(curses.COLOR_MAGENTA))
+        elif color == BROWN:
+            curwnd.attron(curses.color_pair(curses.COLOR_YELLOW))
+        elif color == LIGHTGRAY:
+            curwnd.attron(curses.color_pair(curses.COLOR_WHITE))
+        elif color == DARKGRAY:
+            curwnd.attron(curses.color_pair(curses.COLOR_BLACK) | curses.A_BOLD)
+        elif color == LIGHTBLUE:
+            curwnd.attron(curses.color_pair(curses.COLOR_BLUE) | curses.A_BOLD)
+        elif color == LIGHTGREEN:
+            curwnd.attron(curses.color_pair(curses.COLOR_GREEN) | curses.A_BOLD)
+        elif color == LIGHTCYAN:
+            curwnd.attron(curses.color_pair(curses.COLOR_CYAN) | curses.A_BOLD)
+        elif color == LIGHTRED:
+            curwnd.attron(curses.color_pair(curses.COLOR_RED) | curses.A_BOLD)
+        elif color == LIGHTMAGENTA:
+            curwnd.attron(curses.color_pair(curses.COLOR_MAGENTA) | curses.A_BOLD)
+        elif color == YELLOW:
+            curwnd.attron(curses.color_pair(curses.COLOR_YELLOW) | curses.A_BOLD)
+        elif color == WHITE:
+            curwnd.attron(curses.color_pair(curses.COLOR_WHITE) | curses.A_BOLD)
+
+
+def highvideo():
+    if (game.options & OPTION_COLOR) and (
+        game.options & OPTION_CURSES
+    ):  # pragma: no cover
+        curwnd.attron(curses.A_REVERSE)
+
+
+#
+# Things past this point have policy implications.
+#
+
+
+def drawmaps(mode):
+    "Hook to be called after moving to redraw maps."
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        if mode == 1:
+            sensor()
+        setwnd(srscan_window)
+        curwnd.move(0, 0)
+        srscan()
+        if mode != 2:
+            setwnd(status_window)
+            status_window.clear()
+            status_window.move(0, 0)
+            setwnd(report_window)
+            report_window.clear()
+            report_window.move(0, 0)
+            status()
+            setwnd(lrscan_window)
+            lrscan_window.clear()
+            lrscan_window.move(0, 0)
+            lrscan(silent=False)
+
+
+def put_srscan_sym(w, sym):  # pragma: no cover
+    "Emit symbol for short-range scan."
+    srscan_window.move(w.i + 1, w.j * 2 + 2)
+    srscan_window.addch(sym)
+    srscan_window.refresh()
+
+
+def boom(w):
+    "Enemy fall down, go boom."
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        drawmaps(0)
+        setwnd(srscan_window)
+        srscan_window.attron(curses.A_REVERSE)
+        put_srscan_sym(w, game.quad[w.i][w.j])
+        # sound(500)
+        # time.sleep(1.0)
+        # nosound()
+        srscan_window.attroff(curses.A_REVERSE)
+        put_srscan_sym(w, game.quad[w.i][w.j])
+        curses.delay_output(500)
+        setwnd(message_window)
+
+
+def warble():
+    "Sound and visual effects for teleportation."
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        drawmaps(2)
+        setwnd(message_window)
+        # sound(50)
+    prouts("     . . . . .     ")
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        # curses.delay_output(1000)
+        # nosound()
+        pass
+
+
+def tracktorpedo(w, step, i, n, iquad):
+    "Torpedo-track animation."
+    if not game.options & OPTION_CURSES:
+        if step == 1:
+            if n != 1:
+                skip(1)
+                proutn(_("Track for torpedo number %d-  ") % (i + 1))
+            else:
+                skip(1)
+                proutn(_("Torpedo track- "))
+        elif step in {4, 9}:
+            skip(1)
+        proutn("%s   " % w)
+    else:  # pragma: no cover
+        if not damaged(DSRSENS) or game.condition == "docked":
+            if i != 0 and step == 1:
+                drawmaps(2)
+                time.sleep(0.4)
+            if iquad in {".", " "}:
+                put_srscan_sym(w, "+")
+                # sound(step*10)
+                # time.sleep(0.1)
+                # nosound()
+                put_srscan_sym(w, iquad)
+            else:
+                curwnd.attron(curses.A_REVERSE)
+                put_srscan_sym(w, iquad)
+                # sound(500)
+                # time.sleep(1.0)
+                # nosound()
+                curwnd.attroff(curses.A_REVERSE)
+                put_srscan_sym(w, iquad)
+        else:
+            proutn("%s   " % w)
+
+
+def makechart():
+    "Display the current galaxy chart."
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        setwnd(message_window)
+        message_window.clear()
+    chart()
+    if game.options & OPTION_TTY:
+        skip(1)
+
+
+NSYM = 14
+
+
+def prstat(txt, data):
+    proutn(txt)
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        skip(1)
+        setwnd(status_window)
+    else:
+        proutn(" " * (NSYM - len(txt)))
+    proutn(data)
+    skip(1)
+    if game.options & OPTION_CURSES:  # pragma: no cover
+        setwnd(report_window)
+
+
+# Code from moving.c begins here
+
+
+def imove(icourse=None, noattack=False):
+    "Movement execution for warp, impulse, supernova, and tractor-beam events."
+    w = Coord()
+
+    def newquadrant(noattack):
+        # Leaving quadrant -- allow final enemy attack
+        # Don't set up attack if being pushed by nova or cloaked
+        if len(game.enemies) != 0 and not noattack and not game.iscloaked:
+            newcnd()
+            for enemy in game.enemies:
+                finald = (w - enemy.location).distance()
+                enemy.kavgd = 0.5 * (finald + enemy.kdist)
+            # Stas Sergeev added the condition
+            # that attacks only happen if Klingons
+            # are present and your skill is good.
+            if (
+                game.skill > SKILL_GOOD
+                and game.klhere > 0
+                and not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova
+            ):
+                attack(torps_ok=False)
+            if game.alldone:
+                return
+        # check for edge of galaxy
+        kinks = 0
+        while True:
+            kink = False
+            if icourse.final.i < 0:
+                icourse.final.i = -icourse.final.i
+                kink = True
+            if icourse.final.j < 0:
+                icourse.final.j = -icourse.final.j
+                kink = True
+            if icourse.final.i >= GALSIZE * QUADSIZE:
+                icourse.final.i = (GALSIZE * QUADSIZE * 2) - icourse.final.i
+                kink = True
+            if icourse.final.j >= GALSIZE * QUADSIZE:
+                icourse.final.j = (GALSIZE * QUADSIZE * 2) - icourse.final.j
+                kink = True
+            if kink:
+                kinks += 1
+            else:
+                break
+        if kinks:
+            game.nkinks += 1
+            if game.nkinks == 3:
+                # Three strikes -- you're out!
+                finish(FNEG3)
+                return
+            skip(1)
+            prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
+            prout(_("AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,"))
+            prout(_("YOU WILL BE DESTROYED."))
+        # Compute final position in new quadrant
+        if trbeam:  # Don't bother if we are to be beamed
+            return
+        game.quadrant = icourse.final.quadrant()
+        game.sector = icourse.final.sector()
+        skip(1)
+        prout(_("Entering Quadrant %s.") % game.quadrant)
+        game.quad[game.sector.i][game.sector.j] = game.ship
+        newqad()
+        if game.skill > SKILL_NOVICE:
+            attack(torps_ok=False)
+
+    def check_collision(h):
+        iquad = game.quad[h.i][h.j]
+        if iquad != ".":
+            # object encountered in flight path
+            stopegy = 50.0 * icourse.distance / game.optime
+            if iquad in ("T", "K", "C", "S", "R", "?"):
+                for enemy in game.enemies:
+                    if enemy.location == h:
+                        collision(rammed=False, enemy=enemy)
+                        return True
+                # This should not happen
+                prout(_("Which way did he go?"))  # pragma: no cover
+                return False  # pragma: no cover
+            elif iquad == " ":
+                skip(1)
+                prouts(_("***RED ALERT!  RED ALERT!"))
+                skip(1)
+                proutn("***" + crmshp())
+                proutn(_(" pulled into black hole at Sector %s") % h)
+                # Getting pulled into a black hole was certain
+                # death in Almy's original.  Stas Sergeev added a
+                # possibility that you'll get timewarped instead.
+                n = 0
+                for m in range(NDEVICES):
+                    if game.damage[m] > 0:
+                        n += 1
+                probf = math.pow(
+                    1.4, (game.energy + game.shield) / 5000.0 - 1.0
+                ) * math.pow(1.3, 1.0 / (n + 1) - 1.0)
+                if (game.options & OPTION_BLKHOLE) and rnd.withprob(1 - probf):
+                    timwrp()
+                else:
+                    finish(FHOLE)
+                return True
+            else:
+                # something else
+                skip(1)
+                proutn(crmshp())
+                if iquad == "#":
+                    prout(_(" encounters Tholian web at %s;") % h)
+                else:
+                    prout(_(" blocked by object at %s;") % h)
+                proutn(_("Emergency stop required "))
+                prout(_("%2d units of energy.") % int(stopegy))
+                game.energy -= stopegy
+                if game.energy <= 0:
+                    finish(FNRG)
+                return True
+        return False
+
+    trbeam = False
+    if game.inorbit:
+        prout(_('Helmsman Sulu- "Leaving standard orbit."'))
+        game.inorbit = False
+    # If tractor beam is to occur, don't move full distance
+    if game.state.date + game.optime >= scheduled(FTBEAM):
+        if game.iscloaked:
+            # We can't be tractor beamed if cloaked,
+            # so move the event into the future
+            postpone(
+                FTBEAM, game.optime + expran(1.5 * game.intime / len(game.state.kcmdr))
+            )
+        else:
+            trbeam = True
+            game.condition = "red"
+            icourse.distance = (
+                icourse.distance * (scheduled(FTBEAM) - game.state.date) / game.optime
+                + 0.1
+            )
+            game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
+    # Move out
+    game.quad[game.sector.i][game.sector.j] = "."
+    for _m in range(icourse.moves):
+        icourse.nextstep()
+        w = icourse.sector()
+        if icourse.origin.quadrant() != icourse.location.quadrant():
+            newquadrant(noattack)
+            break
+        elif check_collision(w):
+            prout(_("Collision detected"))
+            break
+        else:
+            game.sector = w
+    # We're in destination quadrant -- compute new average enemy distances
+    game.quad[game.sector.i][game.sector.j] = game.ship
+    if game.enemies:
+        for enemy in game.enemies:
+            finald = (w - enemy.location).distance()
+            enemy.kavgd = 0.5 * (finald + enemy.kdist)
+            enemy.kdist = finald
+        sortenemies()
+        if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
+            attack(torps_ok=False)
+        for enemy in game.enemies:
+            enemy.kavgd = enemy.kdist
+    newcnd()
+    drawmaps(0)
+    setwnd(message_window)
+
+
+def dock(verbose):
+    "Dock our ship at a starbase."
+    scanner.chew()
+    if game.condition == "docked" and verbose:
+        prout(_("Already docked."))
+        return
+    if game.inorbit:
+        prout(_("You must first leave standard orbit."))
+        return
+    if game.base is None or not game.base.valid_sector():
+        prout(_("No starbase available for docking in this quadrant."))
+        return
+    if (abs(game.sector.i - game.base.i) > 1) or (abs(game.sector.j - game.base.j) > 1):
+        prout(crmshp() + _(" not adjacent to base."))
+        return
+    if game.iscloaked:
+        prout(_("You cannot dock while cloaked."))
+        return
+    game.condition = "docked"
+    if verbose:
+        prout(_("Docked."))
+    game.ididit = True
+    if game.energy < game.inenrg:
+        game.energy = game.inenrg
+    game.shield = game.inshld
+    game.torps = game.intorps
+    game.lsupres = game.inlsr
+    game.state.crew = FULLCREW
+    if game.brigcapacity - game.brigfree > 0:
+        prout(
+            _("%d captured Klingons transferred to base")
+            % (game.brigcapacity - game.brigfree)
+        )
+        game.kcaptured += game.brigcapacity - game.brigfree
+        game.brigfree = game.brigcapacity
+    if communicating() and (
+        (is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit
+    ):
+        # get attack report from base
+        prout(_('Lt. Uhura- "Captain, an important message from the starbase:"'))
+        attackreport(False)
+        game.iseenit = True
+
+
+def cartesian(loc1=None, loc2=None):
+    if loc1 is None:
+        return game.quadrant * QUADSIZE + game.sector
+    elif loc2 is None:
+        return game.quadrant * QUADSIZE + loc1
+    else:
+        return loc1 * QUADSIZE + loc2
+
+
+def getcourse(isprobe):
+    "Get a course and distance from the user."
+    key = ""
+    dquad = copy.copy(game.quadrant)
+    navmode = "unspecified"
+    itemp = "curt"
+    dsect = Coord()
+    iprompt = False
+    if game.landed and not isprobe:
+        prout(_("Dummy! You can't leave standard orbit until you"))
+        proutn(_("are back aboard the ship."))
+        scanner.chew()
+        raise TrekError
+    while navmode == "unspecified":
+        if damaged(DNAVSYS):
+            if isprobe:
+                prout(_("Computer damaged; manual navigation only"))
+            else:
+                prout(_("Computer damaged; manual movement only"))
+            scanner.chew()
+            navmode = "manual"
+            key = "IHEOL"
+            break
+        key = scanner.nexttok()
+        if key == "IHEOL":
+            proutn(_("Manual or automatic- "))
+            iprompt = True
+            scanner.chew()
+        elif key == "IHALPHA":
+            if scanner.sees("manual"):
+                navmode = "manual"
+                key = scanner.nexttok()
+                break
+            elif scanner.sees("automatic"):
+                navmode = "automatic"
+                key = scanner.nexttok()
+                break
+            else:
+                huh()
+                scanner.chew()
+                raise TrekError
+        else:  # numeric
+            if isprobe:
+                prout(_("(Manual navigation assumed.)"))
+            else:
+                prout(_("(Manual movement assumed.)"))
+            navmode = "manual"
+            break
+    delta = Coord()
+    if navmode == "automatic":
+        while key == "IHEOL":
+            if isprobe:
+                proutn(_("Target quadrant or quadrant&sector- "))
+            else:
+                proutn(_("Destination sector or quadrant&sector- "))
+            scanner.chew()
+            iprompt = True
+            key = scanner.nexttok()
+        scanner.push(scanner.token)  # Something IHREAL or IHALPHA awaits us
+        first = scanner.getcoord()
+        if first is None:
+            raise TrekError
+        scanner.nexttok()
+        if scanner.type == "IHEOL":
+            second = None
+        else:
+            scanner.push(scanner.token)
+            second = scanner.getcoord()
+            if second is None:
+                raise TrekError
+        scanner.chew()
+        if second is not None:
+            dquad.i = first.i
+            dquad.j = first.j
+            dsect.i = second.i
+            dsect.j = second.j
+        else:
+            # only one pair of numbers was specified
+            if isprobe:
+                # only quadrant specified -- go to center of dest quad
+                dquad.i = first.i
+                dquad.j = first.j
+                dsect.j = dsect.i = (QUADSIZE / 2) - 1  # preserves 1-origin behavior
+            else:
+                # only sector specified
+                dsect.i = first.i
+                dsect.j = first.j
+            itemp = "normal"
+        if not dquad.valid_quadrant() or not dsect.valid_sector():
+            huh()
+            raise TrekError
+        skip(1)
+        if not isprobe:
+            if itemp > "curt":
+                if iprompt:
+                    prout(_('Helmsman Sulu- "Course locked in for Sector %s."') % dsect)
+            else:
+                prout(_('Ensign Chekov- "Course laid in, Captain."'))
+        # the actual deltas get computed here
+        delta.j = (
+            dquad.j - game.quadrant.j + (dsect.j - game.sector.j) / (QUADSIZE * 1.0)
+        )
+        delta.i = (
+            game.quadrant.i - dquad.i + (game.sector.i - dsect.i) / (QUADSIZE * 1.0)
+        )
+    else:  # manual
+        while key == "IHEOL":
+            proutn(_("X and Y displacements- "))
+            scanner.chew()
+            iprompt = True
+            key = scanner.nexttok()
+        itemp = "verbose"
+        if key == "IHREAL":
+            delta.j = scanner.real
+        else:
+            huh()
+            raise TrekError
+        key = scanner.nexttok()
+        if key == "IHREAL":
+            delta.i = scanner.real
+        elif key == "IHEOL":
+            delta.i = 0
+            scanner.push("\n")
+        else:
+            huh()
+            raise TrekError
+    # Check for zero movement
+    if delta.i == 0 and delta.j == 0:
+        scanner.chew()
+        raise TrekError
+    if itemp == "verbose" and not isprobe:
+        skip(1)
+        prout(_('Helmsman Sulu- "Aye, Sir."'))
+    scanner.chew()
+    return course(bearing=delta.bearing(), distance=delta.distance())
+
+
+class course:
+    def __init__(self, bearing, distance, origin=None):
+        self.distance = distance
+        self.bearing = bearing
+        if origin is None:
+            self.origin = cartesian(game.quadrant, game.sector)
+        else:
+            self.origin = origin
+        # The bearing() code we inherited from FORTRAN is actually computing
+        # clockface directions!
+        if self.bearing < 0.0:
+            self.bearing += 12.0
+        self.angle = (15.0 - self.bearing) * 0.5235988
+        self.increment = Coord(-math.sin(self.angle), math.cos(self.angle))
+        bigger = max(abs(self.increment.i), abs(self.increment.j))
+        self.increment /= bigger
+        self.moves = int(round(10 * self.distance * bigger))
+        self.reset()
+        self.final = (self.location + self.moves * self.increment).roundtogrid()
+        self.location = self.origin
+        self.nextlocation = None
+
+    def reset(self):
+        self.location = self.origin
+        self.step = 0
+
+    def arrived(self):
+        return self.location.roundtogrid() == self.final
+
+    def nextstep(self):
+        "Next step on course."
+        self.step += 1
+        self.nextlocation = self.location + self.increment
+        samequad = self.location.quadrant() == self.nextlocation.quadrant()
+        self.location = self.nextlocation
+        return samequad
+
+    def quadrant(self):
+        return self.location.quadrant()
+
+    def sector(self):
+        return self.location.sector()
+
+    def power(self, w):
+        return self.distance * (w ** 3) * (game.shldup + 1)
+
+    def time(self, w):
+        return 10.0 * self.distance / w ** 2
+
+
+def impulse():
+    "Move under impulse power."
+    game.ididit = False
+    if damaged(DIMPULS):
+        scanner.chew()
+        skip(1)
+        prout(_('Engineer Scott- "The impulse engines are damaged, Sir."'))
+        return
+    if game.energy > 30.0:
+        try:
+            icourse = getcourse(isprobe=False)
+        except TrekError:
+            return
+        power = 20.0 + 100.0 * icourse.distance
+    else:
+        power = 30.0
+    if power >= game.energy:
+        # Insufficient power for trip
+        skip(1)
+        prout(_('First Officer Spock- "Captain, the impulse engines'))
+        prout(_("require 20.0 units to engage, plus 100.0 units per"))
+        if game.energy > 30:
+            proutn(
+                _("quadrant.  We can go, therefore, a maximum of %d")
+                % int(0.01 * (game.energy - 20.0) - 0.05)
+            )
+            prout(_(' quadrants."'))
+        else:
+            prout(_('quadrant.  They are, therefore, useless."'))
+        scanner.chew()
+        return
+    # Make sure enough time is left for the trip
+    game.optime = icourse.distance / 0.095
+    if game.optime >= game.state.remtime:
+        prout(_('First Officer Spock- "Captain, our speed under impulse'))
+        prout(_("power is only 0.95 sectors per stardate. Are you sure"))
+        proutn(_('we dare spend the time?" '))
+        if not ja():
+            return
+    # Activate impulse engines and pay the cost
+    imove(icourse, noattack=False)
+    game.ididit = True
+    if game.alldone:
+        return
+    power = 20.0 + 100.0 * icourse.distance
+    game.energy -= power
+    game.optime = icourse.distance / 0.095
+    if game.energy <= 0:
+        finish(FNRG)
+    return
+
+
+def warp(wcourse, involuntary):
+    "Move under warp drive."
+    blooey = False
+    twarp = False
+    if not involuntary:  # Not WARPX entry
+        game.ididit = False
+        if game.iscloaked:
+            scanner.chew()
+            skip(1)
+            prout(
+                _(
+                    'Engineer Scott- "The warp engines can not be used while cloaked, Sir."'
+                )
+            )
+            return
+        if game.damage[DWARPEN] > 10.0:
+            scanner.chew()
+            skip(1)
+            prout(_('Engineer Scott- "The warp engines are damaged, Sir."'))
+            return
+        if damaged(DWARPEN) and game.warpfac > 4.0:
+            scanner.chew()
+            skip(1)
+            prout(_('Engineer Scott- "Sorry, Captain. Until this damage'))
+            prout(_('  is repaired, I can only give you warp 4."'))
+            return
+            # Read in course and distance
+        if wcourse is None:
+            try:
+                wcourse = getcourse(isprobe=False)
+            except TrekError:
+                return
+        # Make sure starship has enough energy for the trip
+        # Note: this formula is slightly different from the C version,
+        # and lets you skate a bit closer to the edge.
+        if wcourse.power(game.warpfac) >= game.energy:
+            # Insufficient power for trip
+            game.ididit = False
+            skip(1)
+            prout(_("Engineering to bridge--"))
+            if not game.shldup or 0.5 * wcourse.power(game.warpfac) > game.energy:
+                iwarp = (game.energy / (wcourse.distance + 0.05)) ** 0.333333333
+                if iwarp <= 0:
+                    prout(_("We can't do it, Captain. We don't have enough energy."))
+                else:
+                    proutn(
+                        _("We don't have enough energy, but we could do it at warp %d")
+                        % iwarp
+                    )
+                    if game.shldup:
+                        prout(",")
+                        prout(_("if you'll lower the shields."))
+                    else:
+                        prout(".")
+            else:
+                prout(_("We haven't the energy to go that far with the shields up."))
+            return
+        # Make sure enough time is left for the trip
+        game.optime = wcourse.time(game.warpfac)
+        if game.optime >= 0.8 * game.state.remtime:
+            skip(1)
+            prout(_('First Officer Spock- "Captain, I compute that such'))
+            proutn(
+                _("  a trip would require approximately %2.0f")
+                % (100.0 * game.optime / game.state.remtime)
+            )
+            prout(_(" percent of our"))
+            proutn(_('  remaining time.  Are you sure this is wise?" '))
+            if not ja():
+                game.ididit = False
+                game.optime = 0
+                return
+    # Entry WARPX
+    if game.warpfac > 6.0:
+        # Decide if engine damage will occur
+        # ESR: Seems wrong. Probability of damage goes *down* with distance?
+        prob = wcourse.distance * (6.0 - game.warpfac) ** 2 / 66.666666666
+        if prob > rnd.real():
+            blooey = True
+            wcourse.distance = rnd.real(wcourse.distance)
+        # Decide if time warp will occur
+        if 0.5 * wcourse.distance * math.pow(7.0, game.warpfac - 10.0) > rnd.real():
+            twarp = True
+        if game.idebug and game.warpfac == 10 and not twarp:  # pragma: no cover
+            blooey = False
+            proutn("=== Force time warp? ")
+            if ja():
+                twarp = True
+        if blooey or twarp:
+            # If time warp or engine damage, check path
+            # If it is obstructed, don't do warp or damage
+            look = wcourse.moves
+            while look > 0:
+                look -= 1
+                wcourse.nextstep()
+                w = wcourse.sector()
+                if not w.valid_sector():
+                    break
+                if game.quad[w.i][w.j] != ".":
+                    blooey = False
+                    twarp = False
+            wcourse.reset()
+    # Activate Warp Engines and pay the cost
+    imove(wcourse, noattack=False)
+    if game.alldone:
+        return
+    game.energy -= wcourse.power(game.warpfac)
+    if game.energy <= 0:
+        finish(FNRG)
+    game.optime = wcourse.time(game.warpfac)
+    if twarp:
+        timwrp()
+    if blooey:
+        game.damage[DWARPEN] = game.damfac * rnd.real(1.0, 4.0)
+        skip(1)
+        prout(_("Engineering to bridge--"))
+        prout(_("  Scott here.  The warp engines are damaged."))
+        prout(_("  We'll have to reduce speed to warp 4."))
+    game.ididit = True
+    return
+
+
+def setwarp():
+    "Change the warp factor."
+    while True:
+        key = scanner.nexttok()
+        if key != "IHEOL":
+            break
+        scanner.chew()
+        proutn(_("Warp factor- "))
+    if key != "IHREAL":
+        huh()
+        return
+    if game.damage[DWARPEN] > 10.0:
+        prout(_("Warp engines inoperative."))
+        return
+    if damaged(DWARPEN) and scanner.real > 4.0:
+        prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
+        prout(_('  but right now we can only go warp 4."'))
+        return
+    if scanner.real > 10.0:
+        prout(_('Helmsman Sulu- "Our top speed is warp 10, Captain."'))
+        return
+    if scanner.real < 1.0:
+        prout(_('Helmsman Sulu- "We can\'t go below warp 1, Captain."'))
+        return
+    oldfac = game.warpfac
+    game.warpfac = scanner.real
+    if game.warpfac <= oldfac or game.warpfac <= 6.0:
+        prout(_('Helmsman Sulu- "Warp factor %d, Captain."') % int(game.warpfac))
+        return
+    if game.warpfac < 8.00:
+        prout(_('Engineer Scott- "Aye, but our maximum safe speed is warp 6."'))
+        return
+    if game.warpfac == 10.0:
+        prout(_('Engineer Scott- "Aye, Captain, we\'ll try it."'))
+        return
+    prout(_('Engineer Scott- "Aye, Captain, but our engines may not take it."'))
+    return
+
+
+def atover(igrab):
+    "Cope with being tossed out of quadrant by supernova or yanked by beam."
+    scanner.chew()
+    # is captain on planet?
+    if game.landed:
+        if damaged(DTRANSP):
+            finish(FPNOVA)
+            return
+        prout(_("Scotty rushes to the transporter controls."))
+        if game.shldup:
+            prout(_("But with the shields up it's hopeless."))
+            finish(FPNOVA)
+        prouts(_("His desperate attempt to rescue you . . ."))
+        if rnd.withprob(0.5):
+            prout(_("fails."))
+            finish(FPNOVA)
+            return
+        prout(_("SUCCEEDS!"))
+        if game.imine:
+            game.imine = False
+            proutn(_("The crystals mined were "))
+            if rnd.withprob(0.25):
+                prout(_("lost."))
+            else:
+                prout(_("saved."))
+                game.icrystl = True
+    if igrab:
+        return
+    # Check to see if captain in shuttle craft
+    if game.icraft:
+        finish(FSTRACTOR)
+    if game.alldone:
+        return
+    # Inform captain of attempt to reach safety
+    skip(1)
+    while True:
+        if game.justin:
+            prouts(_("***RED ALERT!  RED ALERT!"))
+            skip(1)
+            proutn(_("The %s has stopped in a quadrant containing") % crmshp())
+            prouts(_("   a supernova."))
+            skip(2)
+        prout(_("***Emergency automatic override attempts to hurl ") + crmshp())
+        prout(_("safely out of quadrant."))
+        if not damaged(DRADIO):
+            game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
+        # Try to use warp engines
+        if damaged(DWARPEN):
+            skip(1)
+            prout(_("Warp engines damaged."))
+            finish(FSNOVAED)
+            return
+        game.warpfac = rnd.real(6.0, 8.0)
+        prout(_("Warp factor set to %d") % int(game.warpfac))
+        power = 0.75 * game.energy
+        dist = power / (game.warpfac * game.warpfac * game.warpfac * (game.shldup + 1))
+        dist = max(dist, rnd.real(math.sqrt(2)))
+        bugout = course(bearing=rnd.real(12), distance=dist)  # How dumb!
+        game.optime = bugout.time(game.warpfac)
+        game.justin = False
+        game.inorbit = False
+        warp(bugout, involuntary=True)
+        if not game.justin:
+            # This is bad news, we didn't leave quadrant.
+            if game.alldone:
+                return
+            skip(1)
+            prout(_("Insufficient energy to leave quadrant."))
+            finish(FSNOVAED)
+            return
+        # Repeat if another snova
+        if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
+            break
+    if game.unwon() == 0:
+        finish(FWON)  # Snova killed remaining enemy.
+
+
+def timwrp():
+    "Let's do the time warp again."
+    prout(_("***TIME WARP ENTERED."))
+    if game.state.snap and rnd.withprob(0.5):
+        # Go back in time
+        prout(
+            _("You are traveling backwards in time %d stardates.")
+            % int(game.state.date - game.snapsht.date)
+        )
+        game.state = game.snapsht
+        game.state.snap = False
+        if len(game.state.kcmdr):
+            schedule(FTBEAM, expran(game.intime / len(game.state.kcmdr)))
+            schedule(FBATTAK, expran(0.3 * game.intime))
+        schedule(FSNOVA, expran(0.5 * game.intime))
+        # next snapshot will be sooner
+        schedule(FSNAP, expran(0.25 * game.state.remtime))
+
+        if game.state.nscrem:
+            schedule(FSCMOVE, 0.2777)
+        game.isatb = 0
+        unschedule(FCDBAS)
+        unschedule(FSCDBAS)
+        game.battle.invalidate()
+        # Make sure Galileo is consistant -- Snapshot may have been taken
+        # when on planet, which would give us two Galileos!
+        gotit = False
+        for l in range(game.inplan):
+            if game.state.planets[l].known == "shuttle_down":
+                gotit = True
+                if game.iscraft == "onship" and game.ship == "E":
+                    prout(
+                        _(
+                            'Chekov-  "Security reports the Galileo has disappeared, Sir!'
+                        )
+                    )
+                    game.iscraft = "offship"
+        # Likewise, if in the original time the Galileo was abandoned, but
+        # was on ship earlier, it would have vanished -- let's restore it.
+        if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
+            prout(
+                _('Chekov-  "Security reports the Galileo has reappeared in the dock!"')
+            )
+            game.iscraft = "onship"
+        # There used to be code to do the actual reconstrction here,
+        # but the starchart is now part of the snapshotted galaxy state.
+        prout(_("Spock has reconstructed a correct star chart from memory"))
+    else:
+        # Go forward in time
+        game.optime = expran(0.5 * game.intime)
+        prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
+        # cheat to make sure no tractor beams occur during time warp
+        postpone(FTBEAM, game.optime)
+        game.damage[DRADIO] += game.optime
+    newqad()
+    events()  # Stas Sergeev added this -- do pending events
+
+
+def probe():
+    "Launch deep-space probe."
+    # New code to launch a deep space probe
+    if game.nprobes == 0:
+        scanner.chew()
+        skip(1)
+        if game.ship == "E":
+            prout(_('Engineer Scott- "We have no more deep space probes, Sir."'))
+        else:
+            prout(_("Ye Faerie Queene has no deep space probes."))
+        return
+    if damaged(DDSP):
+        scanner.chew()
+        skip(1)
+        prout(_('Engineer Scott- "The probe launcher is damaged, Sir."'))
+        return
+    if is_scheduled(FDSPROB):
+        scanner.chew()
+        skip(1)
+        if damaged(DRADIO) and game.condition != "docked":
+            prout(_('Spock-  "Records show the previous probe has not yet'))
+            prout(_('   reached its destination."'))
+        else:
+            prout(_('Uhura- "The previous probe is still reporting data, Sir."'))
+        return
+    key = scanner.nexttok()
+    if key == "IHEOL":
+        if game.nprobes == 1:
+            prout(_("1 probe left."))
+        else:
+            prout(_("%d probes left") % game.nprobes)
+        proutn(_("Are you sure you want to fire a probe? "))
+        if not ja():
+            return
+    game.isarmed = False
+    if key == "IHALPHA" and scanner.token == "armed":
+        game.isarmed = True
+        key = scanner.nexttok()
+    elif key == "IHEOL":
+        proutn(_("Arm NOVAMAX warhead? "))
+        game.isarmed = ja()
+    elif key == "IHREAL":  # first element of course
+        scanner.push(scanner.token)
+    try:
+        game.probe = getcourse(isprobe=True)
+    except TrekError:
+        return
+    game.nprobes -= 1
+    schedule(FDSPROB, 0.01)  # Time to move one sector
+    prout(_('Ensign Chekov-  "The deep space probe is launched, Captain."'))
+    game.ididit = True
+    return
+
+
+def mayday():
+    "Yell for help from nearest starbase."
+    # There's more than one way to move in this game!
+    scanner.chew()
+    # Test for conditions which prevent calling for help
+    if game.condition == "docked":
+        prout(_('Lt. Uhura-  "But Captain, we\'re already docked."'))
+        return
+    if damaged(DRADIO):
+        prout(_("Subspace radio damaged."))
+        return
+    if not game.state.baseq:
+        prout(_('Lt. Uhura-  "Captain, I\'m not getting any response from Starbase."'))
+        return
+    if game.landed:
+        prout(_("You must be aboard the %s.") % crmshp())
+        return
+    # OK -- call for help from nearest starbase
+    game.nhelp += 1
+    if game.base.i != 0:
+        # There's one in this quadrant
+        ddist = (game.base - game.sector).distance()
+    else:
+        ibq = None  # Force base-quadrant game to persist past loop
+        ddist = FOREVER
+        for ibq in game.state.baseq:
+            xdist = QUADSIZE * (ibq - game.quadrant).distance()
+            if xdist < ddist:
+                ddist = xdist
+        if ibq is None:
+            prout(_("No starbases remain. You are alone in a hostile galaxy."))
+            return
+        # Since starbase not in quadrant, set up new quadrant
+        game.quadrant = ibq
+        newqad()
+    # dematerialize starship
+    game.quad[game.sector.i][game.sector.j] = "."
+    proutn(
+        _("Starbase in Quadrant %s responds--%s dematerializes")
+        % (game.quadrant, crmshp())
+    )
+    game.sector.invalidate()
+    for m in range(1, 5 + 1):
+        w = game.base.scatter()
+        if w.valid_sector() and game.quad[w.i][w.j] == ".":
+            # found one -- finish up
+            game.sector = w
+            break
+    if game.sector is None:
+        prout(_("You have been lost in space..."))
+        finish(FMATERIALIZE)
+        return
+    # Give starbase three chances to rematerialize starship
+    probf = math.pow((1.0 - math.pow(0.98, ddist)), 0.33333333)
+    for m in range(1, 3 + 1):
+        if m == 1:
+            proutn(_("1st"))
+        elif m == 2:
+            proutn(_("2nd"))
+        elif m == 3:
+            proutn(_("3rd"))
+        proutn(_(" attempt to re-materialize ") + crmshp())
+        game.quad[game.sector.i][game.sector.j] = ("-", "o", "O")[m - 1]
+        textcolor(RED)
+        warble()
+        if rnd.real() > probf:
+            break
+        prout(_("fails."))
+        textcolor(DEFAULT)
+        if game.options & OPTION_CURSES:  # pragma: no cover
+            curses.delay_output(500)
+    if m > 3:
+        game.quad[game.sector.i][game.sector.j] = "?"
+        game.alive = False
+        drawmaps(1)
+        setwnd(message_window)
+        finish(FMATERIALIZE)
+        return
+    game.quad[game.sector.i][game.sector.j] = game.ship
+    textcolor(GREEN)
+    prout(_("succeeds."))
+    textcolor(DEFAULT)
+    dock(False)
+    skip(1)
+    prout(_('Lt. Uhura-  "Captain, we made it!"'))
+
+
+def abandon():
+    "Abandon ship."
+    scanner.chew()
+    if game.condition == "docked":
+        if game.ship != "E":
+            prout(_("You cannot abandon Ye Faerie Queene."))
+            return
+    else:
+        # Must take shuttle craft to exit
+        if game.damage[DSHUTTL] == -1:
+            prout(_("Ye Faerie Queene has no shuttle craft."))
+            return
+        if game.damage[DSHUTTL] < 0:
+            prout(_("Shuttle craft now serving Big Macs."))
+            return
+        if game.damage[DSHUTTL] > 0:
+            prout(_("Shuttle craft damaged."))
+            return
+        if game.landed:
+            prout(_("You must be aboard the ship."))
+            return
+        if game.iscraft != "onship":
+            prout(_("Shuttle craft not currently available."))
+            return
+        # Emit abandon ship messages
+        skip(1)
+        prouts(_("***ABANDON SHIP!  ABANDON SHIP!"))
+        skip(1)
+        prouts(_("***ALL HANDS ABANDON SHIP!"))
+        skip(2)
+        prout(_("Captain and crew escape in shuttle craft."))
+        if not game.state.baseq:
+            # Oops! no place to go...
+            finish(FABANDN)
+            return
+        q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
+        # Dispose of crew
+        if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
+            prout(_("Remainder of ship's complement beam down"))
+            prout(_("to nearest habitable planet."))
+        elif q.planet is not None and not damaged(DTRANSP):
+            prout(_("Remainder of ship's complement beam down to %s.") % q.planet)
+        else:
+            prout(_("Entire crew of %d left to die in outer space.") % game.state.crew)
+            game.casual += game.state.crew
+            game.abandoned += game.state.crew
+        # If at least one base left, give 'em the Faerie Queene
+        skip(1)
+        game.icrystl = False  # crystals are lost
+        game.nprobes = 0  # No probes
+        prout(_("You are captured by Klingons and released to"))
+        prout(_("the Federation in a prisoner-of-war exchange."))
+        nb = rnd.integer(len(game.state.baseq))
+        # Set up quadrant and position FQ adjacient to base
+        if not game.quadrant == game.state.baseq[nb]:
+            game.quadrant = game.state.baseq[nb]
+            game.sector.i = game.sector.j = 5
+            newqad()
+        while True:
+            # position next to base by trial and error
+            game.quad[game.sector.i][game.sector.j] = "."
+            l = QUADSIZE
+            for l in range(QUADSIZE):
+                game.sector = game.base.scatter()
+                if (
+                    game.sector.valid_sector()
+                    and game.quad[game.sector.i][game.sector.j] == "."
+                ):
+                    break
+            if l < QUADSIZE:
+                break  # found a spot
+            game.sector.i = QUADSIZE / 2
+            game.sector.j = QUADSIZE / 2
+            newqad()
+    # Get new commission
+    game.quad[game.sector.i][game.sector.j] = game.ship = "F"
+    game.state.crew = FULLCREW
+    prout(_("Starfleet puts you in command of another ship,"))
+    prout(_("the Faerie Queene, which is antiquated but,"))
+    prout(_("still useable."))
+    if game.icrystl:
+        prout(_("The dilithium crystals have been moved."))
+    game.imine = False
+    game.iscraft = "offship"  # Galileo disappears
+    # Resupply ship
+    game.condition = "docked"
+    for l in range(NDEVICES):
+        game.damage[l] = 0.0
+    game.damage[DSHUTTL] = -1
+    game.energy = game.inenrg = 3000.0
+    game.shield = game.inshld = 1250.0
+    game.torps = game.intorps = 6
+    game.lsupres = game.inlsr = 3.0
+    game.shldup = False
+    game.warpfac = 5.0
+    game.brigfree = game.brigcapacity = 300
+    return
+
+
+# Code from planets.c begins here.
+
+
+def consumeTime():
+    "Abort a lengthy operation if an event interrupts it."
+    game.ididit = True
+    events()
+    if (
+        game.alldone
+        or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova
+        or game.justin
+    ):
+        return True
+    return False
+
+
+def survey():
+    "Report on (uninhabited) planets in the galaxy."
+    iknow = False
+    skip(1)
+    scanner.chew()
+    prout(_('Spock-  "Planet report follows, Captain."'))
+    skip(1)
+    for i in range(game.inplan):
+        if game.state.planets[i].pclass == "destroyed":
+            continue
+        if (
+            game.state.planets[i].known != "unknown"
+            and not game.state.planets[i].inhabited
+        ) or game.idebug:
+            iknow = True
+            if game.idebug and game.state.planets[i].known == "unknown":
+                proutn("(Unknown) ")
+            proutn(_("Quadrant %s") % game.state.planets[i].quadrant)
+            proutn(_("   class "))
+            proutn(game.state.planets[i].pclass)
+            proutn("   ")
+            if game.state.planets[i].crystals != "present":
+                proutn(_("no "))
+            prout(_("dilithium crystals present."))
+            if game.state.planets[i].known == "shuttle_down":
+                prout(_("    Shuttle Craft Galileo on surface."))
+    if not iknow:
+        prout(_("No information available."))
+
+
+def orbit():
+    "Enter standard orbit."
+    skip(1)
+    scanner.chew()
+    if game.inorbit:
+        prout(_("Already in standard orbit."))
+        return
+    if damaged(DWARPEN) and damaged(DIMPULS):
+        prout(_("Both warp and impulse engines damaged."))
+        return
+    if game.plnet is None:
+        prout("There is no planet in this sector.")
+        return
+    if abs(game.sector.i - game.plnet.i) > 1 or abs(game.sector.j - game.plnet.j) > 1:
+        prout(crmshp() + _(" not adjacent to planet."))
+        skip(1)
+        return
+    game.optime = rnd.real(0.02, 0.05)
+    prout(_('Helmsman Sulu-  "Entering standard orbit, Sir."'))
+    newcnd()
+    if consumeTime():
+        return
+    game.height = rnd.real(1400, 8600)
+    prout(_('Sulu-  "Entered orbit at altitude %.2f kilometers."') % game.height)
+    game.inorbit = True
+    game.ididit = True
+
+
+def sensor():
+    "Examine planets in this quadrant."
+    if damaged(DSRSENS):
+        if game.options & OPTION_TTY:
+            prout(_("Short range sensors damaged."))
+        return
+    if game.iplnet is None:
+        if game.options & OPTION_TTY:
+            prout(_('Spock- "No planet in this quadrant, Captain."'))
+        return
+    if game.iplnet.known == "unknown":
+        prout(_('Spock-  "Sensor scan for Quadrant %s-') % game.quadrant)
+        skip(1)
+        prout(
+            _("         Planet at Sector %s is of class %s.")
+            % (game.plnet, game.iplnet.pclass)
+        )
+        if game.iplnet.known == "shuttle_down":
+            prout(_("         Sensors show Galileo still on surface."))
+        proutn(_("         Readings indicate"))
+        if game.iplnet.crystals != "present":
+            proutn(_(" no"))
+        prout(_(' dilithium crystals present."'))
+        if game.iplnet.known == "unknown":
+            game.iplnet.known = "known"
+    elif game.iplnet.inhabited:
+        prout(_('Spock-  "The inhabited planet %s ') % game.iplnet.name)
+        prout(_('        is located at Sector %s, Captain."') % game.plnet)
+
+
+def beam():
+    "Use the transporter."
+    nrgneed = 0
+    scanner.chew()
+    skip(1)
+    if damaged(DTRANSP):
+        prout(_("Transporter damaged."))
+        if not damaged(DSHUTTL) and (
+            game.iplnet.known == "shuttle_down" or game.iscraft == "onship"
+        ):
+            skip(1)
+            proutn(_('Spock-  "May I suggest the shuttle craft, Sir?" '))
+            if ja():
+                shuttle()
+        return
+    if not game.inorbit:
+        prout(crmshp() + _(" not in standard orbit."))
+        return
+    if game.shldup:
+        prout(_("Impossible to transport through shields."))
+        return
+    if game.iplnet.known == "unknown":
+        prout(_('Spock-  "Captain, we have no information on this planet'))
+        prout(_("  and Starfleet Regulations clearly state that in this situation"))
+        prout(_('  you may not go down."'))
+        return
+    if not game.landed and game.iplnet.crystals == "absent":
+        prout(_('Spock-  "Captain, I fail to see the logic in'))
+        prout(_("  exploring a planet with no dilithium crystals."))
+        proutn(_('  Are you sure this is wise?" '))
+        if not ja():
+            scanner.chew()
+            return
+    if game.options & OPTION_ALMY:
+        nrgneed = 50 * game.skill + game.height / 100.0
+        if nrgneed > game.energy:
+            prout(_("Engineering to bridge--"))
+            prout(_("  Captain, we don't have enough energy for transportation."))
+            return
+        if not game.landed and nrgneed * 2 > game.energy:
+            prout(_("Engineering to bridge--"))
+            prout(_("  Captain, we have enough energy only to transport you down to"))
+            prout(_("  the planet, but there wouldn't be an energy for the trip back."))
+            if game.iplnet.known == "shuttle_down":
+                prout(
+                    _("  Although the Galileo shuttle craft may still be on a surface.")
+                )
+            proutn(_('  Are you sure this is wise?" '))
+            if not ja():
+                scanner.chew()
+                return
+    if game.landed:
+        # Coming from planet
+        if game.iplnet.known == "shuttle_down":
+            proutn(_('Spock-  "Wouldn\'t you rather take the Galileo?" '))
+            if ja():
+                scanner.chew()
+                return
+            prout(_("Your crew hides the Galileo to prevent capture by aliens."))
+        prout(_("Landing party assembled, ready to beam up."))
+        skip(1)
+        prout(_("Kirk whips out communicator..."))
+        prouts(_("BEEP  BEEP  BEEP"))
+        skip(2)
+        prout(_('"Kirk to enterprise-  Lock on coordinates...energize."'))
+    else:
+        # Going to planet
+        prout(_('Scotty-  "Transporter room ready, Sir."'))
+        skip(1)
+        prout(_("Kirk and landing party prepare to beam down to planet surface."))
+        skip(1)
+        prout(_('Kirk-  "Energize."'))
+    game.ididit = True
+    skip(1)
+    prouts("WWHOOOIIIIIRRRRREEEE.E.E.  .  .  .  .   .    .")
+    skip(2)
+    if not rnd.withprob(0.98):
+        prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
+        skip(2)
+        prout(_('Scotty-  "Oh my God!  I\'ve lost them."'))
+        finish(FLOST)
+        return
+    prouts(".    .   .  .  .  .  .E.E.EEEERRRRRIIIIIOOOHWW")
+    game.landed = not game.landed
+    game.energy -= nrgneed
+    skip(2)
+    prout(_("Transport complete."))
+    if game.landed and game.iplnet.known == "shuttle_down":
+        prout(_("The shuttle craft Galileo is here!"))
+    if not game.landed and game.imine:
+        game.icrystl = True
+        game.cryprob = 0.05
+    game.imine = False
+    return
+
+
+def mine():
+    "Strip-mine a world for dilithium."
+    skip(1)
+    scanner.chew()
+    if not game.landed:
+        prout(_("Mining party not on planet."))
+        return
+    if game.iplnet.crystals == "mined":
+        prout(_("This planet has already been strip-mined for dilithium."))
+        return
+    elif game.iplnet.crystals == "absent":
+        prout(_("No dilithium crystals on this planet."))
+        return
+    if game.imine:
+        prout(_("You've already mined enough crystals for this trip."))
+        return
+    if game.icrystl and game.cryprob == 0.05:
+        prout(_("With all those fresh crystals aboard the ") + crmshp())
+        prout(_("there's no reason to mine more at this time."))
+        return
+    game.optime = rnd.real(0.1, 0.3) * (ord(game.iplnet.pclass) - ord("L"))
+    if consumeTime():
+        return
+    prout(_("Mining operation complete."))
+    game.iplnet.crystals = "mined"
+    game.imine = game.ididit = True
+
+
+def usecrystals():
+    "Use dilithium crystals."
+    game.ididit = False
+    skip(1)
+    scanner.chew()
+    if not game.icrystl:
+        prout(_("No dilithium crystals available."))
+        return
+    if game.energy >= 1000:
+        prout(_('Spock-  "Captain, Starfleet Regulations prohibit such an operation'))
+        prout(_("  except when Condition Yellow exists."))
+        return
+    prout(_('Spock- "Captain, I must warn you that loading'))
+    prout(_("  raw dilithium crystals into the ship's power"))
+    prout(_("  system may risk a severe explosion."))
+    proutn(_('  Are you sure this is wise?" '))
+    if not ja():
+        scanner.chew()
+        return
+    skip(1)
+    prout(_('Engineering Officer Scott-  "(GULP) Aye Sir.'))
+    prout(_('  Mr. Spock and I will try it."'))
+    skip(1)
+    prout(_('Spock-  "Crystals in place, Sir.'))
+    prout(_('  Ready to activate circuit."'))
+    skip(1)
+    prouts(_('Scotty-  "Keep your fingers crossed, Sir!"'))
+    skip(1)
+    if rnd.withprob(game.cryprob):
+        prouts(_("  \"Activating now! - - No good!  It's***"))
+        skip(2)
+        prouts(_("***RED ALERT!  RED A*L********************************"))
+        skip(1)
+        stars()
+        prouts(_("******************   KA-BOOM!!!!   *******************"))
+        skip(1)
+        kaboom()
+        return
+    game.energy += rnd.real(5000.0, 5500.0)
+    prouts(_('  "Activating now! - - '))
+    prout(_("The instruments"))
+    prout(_("   are going crazy, but I think it's"))
+    prout(_('   going to work!!  Congratulations, Sir!"'))
+    game.cryprob *= 2.0
+    game.ididit = True
+
+
+def shuttle():
+    "Use shuttlecraft for planetary jaunt."
+    scanner.chew()
+    skip(1)
+    if damaged(DSHUTTL):
+        if game.damage[DSHUTTL] == -1.0:
+            if game.inorbit and game.iplnet.known == "shuttle_down":
+                prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
+            else:
+                prout(_("Ye Faerie Queene had no shuttle craft."))
+        elif game.damage[DSHUTTL] > 0:
+            prout(_("The Galileo is damaged."))
+        else:  # game.damage[DSHUTTL] < 0
+            prout(_("Shuttle craft is now serving Big Macs."))
+        return
+    if not game.inorbit:
+        prout(crmshp() + _(" not in standard orbit."))
+        return
+    if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
+        prout(_("Shuttle craft not currently available."))
+        return
+    if not game.landed and game.iplnet.known == "shuttle_down":
+        prout(_("You will have to beam down to retrieve the shuttle craft."))
+        return
+    if game.shldup or game.condition == "docked":
+        prout(_("Shuttle craft cannot pass through shields."))
+        return
+    if game.iplnet.known == "unknown":
+        prout(_('Spock-  "Captain, we have no information on this planet'))
+        prout(_("  and Starfleet Regulations clearly state that in this situation"))
+        prout(_('  you may not fly down."'))
+        return
+    game.optime = 3.0e-5 * game.height
+    if game.optime >= 0.8 * game.state.remtime:
+        prout(_('First Officer Spock-  "Captain, I compute that such'))
+        proutn(
+            _("  a maneuver would require approximately %2d%% of our")
+            % int(100 * game.optime / game.state.remtime)
+        )
+        prout(_("remaining time."))
+        proutn(_('Are you sure this is wise?" '))
+        if not ja():
+            game.optime = 0.0
+            return
+    if game.landed:
+        # Kirk on planet
+        if game.iscraft == "onship":
+            # Galileo on ship!
+            if not damaged(DTRANSP):
+                proutn(_('Spock-  "Would you rather use the transporter?" '))
+                if ja():
+                    beam()
+                    return
+                proutn(_("Shuttle crew"))
+            else:
+                proutn(_("Rescue party"))
+            prout(_(" boards Galileo and swoops toward planet surface."))
+            game.iscraft = "offship"
+            skip(1)
+            if consumeTime():
+                return
+            game.iplnet.known = "shuttle_down"
+            prout(_("Trip complete."))
+            return
+        else:
+            # Ready to go back to ship
+            prout(_("You and your mining party board the"))
+            prout(_("shuttle craft for the trip back to the Enterprise."))
+            skip(1)
+            prouts(_("The short hop begins . . ."))
+            skip(1)
+            game.iplnet.known = "known"
+            game.icraft = True
+            skip(1)
+            game.landed = False
+            if consumeTime():
+                return
+            game.iscraft = "onship"
+            game.icraft = False
+            if game.imine:
+                game.icrystl = True
+                game.cryprob = 0.05
+            game.imine = False
+            prout(_("Trip complete."))
+            return
+    else:
+        # Kirk on ship and so is Galileo
+        prout(_("Mining party assembles in the hangar deck,"))
+        prout(_('ready to board the shuttle craft "Galileo".'))
+        skip(1)
+        prouts(_("The hangar doors open; the trip begins."))
+        skip(1)
+        game.icraft = True
+        game.iscraft = "offship"
+        if consumeTime():
+            return
+        game.iplnet.known = "shuttle_down"
+        game.landed = True
+        game.icraft = False
+        prout(_("Trip complete."))
+        return
+
+
+def deathray():
+    "Use the big zapper."
+    game.ididit = False
+    skip(1)
+    scanner.chew()
+    if game.ship != "E":
+        prout(_("Ye Faerie Queene has no death ray."))
+        return
+    if len(game.enemies) == 0:
+        prout(_('Sulu-  "But Sir, there are no enemies in this quadrant."'))
+        return
+    if damaged(DDRAY):
+        prout(_("Death Ray is damaged."))
+        return
+    prout(_("Spock-  \"Captain, the 'Experimental Death Ray'"))
+    prout(_("  is highly unpredictible.  Considering the alternatives,"))
+    proutn(_('  are you sure this is wise?" '))
+    if not ja():
+        return
+    prout(_('Spock-  "Acknowledged."'))
+    skip(1)
+    game.ididit = True
+    prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
+    skip(1)
+    prout(_("Crew scrambles in emergency preparation."))
+    prout(_("Spock and Scotty ready the death ray and"))
+    prout(_("prepare to channel all ship's power to the device."))
+    skip(1)
+    prout(_('Spock-  "Preparations complete, sir."'))
+    prout(_('Kirk-  "Engage!"'))
+    skip(1)
+    prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
+    skip(1)
+    dprob = 0.30
+    # Ugh. This test (For Tom Almy's death-ray upgrade) was inverted for a long time.
+    # Furthermore, somebody (ESR or Stas?) changed Tom Almy's 0.7 upgraded chance of
+    # working to 0.5.
+    if game.options & OPTION_ALMY:
+        dprob = 0.5
+    r = rnd.real()
+    if r > dprob:
+        prouts(_('Sulu- "Captain!  It\'s working!"'))
+        skip(2)
+        while len(game.enemies) > 0:
+            deadkl(
+                game.enemies[-1].location,
+                game.quad[game.enemies[-1].location.i][game.enemies[-1].location.j],
+                game.enemies[-1].location,
+            )
+        prout(_('Ensign Chekov-  "Congratulations, Captain!"'))
+        if game.unwon() == 0:
+            finish(FWON)
+        if game.options & OPTION_ALMY:
+            prout(_("Spock-  \"Captain, I believe the `Experimental Death Ray'"))
+            if rnd.withprob(0.05):
+                prout(_('   is still operational."'))
+            else:
+                prout(_('   has been rendered nonfunctional."'))
+                game.damage[DDRAY] = 39.95
+        return
+    r = rnd.real()  # Pick failure method
+    if r <= 0.30:
+        prouts(_('Sulu- "Captain!  It\'s working!"'))
+        skip(1)
+        prouts(_("***RED ALERT!  RED ALERT!"))
+        skip(1)
+        prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
+        skip(1)
+        prouts(_("***RED ALERT!  RED A*L********************************"))
+        skip(1)
+        stars()
+        prouts(_("******************   KA-BOOM!!!!   *******************"))
+        skip(1)
+        kaboom()
+        return
+    if r <= 0.55:
+        prouts(_('Sulu- "Captain!  Yagabandaghangrapl, brachriigringlanbla!"'))
+        skip(1)
+        prout(_('Lt. Uhura-  "Graaeek!  Graaeek!"'))
+        skip(1)
+        prout(_('Spock-  "Fascinating!  . . . All humans aboard'))
+        prout(_("  have apparently been transformed into strange mutations."))
+        prout(_("  Vulcans do not seem to be affected."))
+        skip(1)
+        prout(_('Kirk-  "Raauch!  Raauch!"'))
+        finish(FDRAY)
+        return
+    if r <= 0.75:
+        prouts(_('Sulu- "Captain!  It\'s   --WHAT?!?!"'))
+        skip(2)
+        proutn(_('Spock-  "I believe the word is'))
+        prouts(_(" *ASTONISHING*"))
+        prout(_(" Mr. Sulu."))
+        for i in range(QUADSIZE):
+            for j in range(QUADSIZE):
+                if game.quad[i][j] == ".":
+                    game.quad[i][j] = "?"
+        prout(_("  Captain, our quadrant is now infested with"))
+        prouts(_(" - - - - - -  *THINGS*."))
+        skip(1)
+        prout(_('  I have no logical explanation."'))
+        return
+    prouts(_('Sulu- "Captain!  The Death Ray is creating tribbles!"'))
+    skip(1)
+    prout(_('Scotty-  "There are so many tribbles down here'))
+    prout(_("  in Engineering, we can't move for 'em, Captain.\""))
+    finish(FTRIBBLE)
+    return
+
+
+# Code from reports.c begins here
+
+
+def attackreport(curt):
+    "eport status of bases under attack."
+    if not curt:
+        if is_scheduled(FCDBAS):
+            prout(
+                _("Starbase in Quadrant %s is currently under Commander attack.")
+                % game.battle
+            )
+            prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
+        elif game.isatb == 1:
+            prout(
+                _("Starbase in Quadrant %s is under Super-commander attack.")
+                % game.state.kscmdr
+            )
+            prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
+        else:
+            prout(_("No Starbase is currently under attack."))
+    else:
+        if is_scheduled(FCDBAS):
+            proutn(
+                _("Base in %s attacked by C. Alive until %.1f")
+                % (game.battle, scheduled(FCDBAS))
+            )
+        if game.isatb:
+            proutn(
+                _("Base in %s attacked by S. Alive until %.1f")
+                % (game.state.kscmdr, scheduled(FSCDBAS))
+            )
+        clreol()
+
+
+def report():
+    # report on general game status
+    scanner.chew()
+    # pylint: disable=consider-using-ternary
+    s1 = (game.thawed and _("thawed ")) or ""
+    s2 = {1: "short", 2: "medium", 4: "long"}[game.length]
+    s3 = (None, _("novice"), _("fair"), _("good"), _("expert"), _("emeritus"))[
+        game.skill
+    ]
+    prout(
+        _("You %s a %s%s %s game.")
+        % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3)
+    )
+    if game.skill > SKILL_GOOD and game.thawed and not game.alldone:
+        prout(_("No plaque is allowed."))
+    if game.tourn:
+        prout(_("This is tournament game %d.") % game.tourn)
+    prout(_('Your secret password is "%s"') % game.passwd)
+    proutn(
+        _("%d of %d Klingons have been killed")
+        % (
+            ((game.inkling + game.incom + game.inscom) - game.unwon()),
+            (game.inkling + game.incom + game.inscom),
+        )
+    )
+    if game.incom - len(game.state.kcmdr):
+        prout(
+            _(", including %d Commander%s.")
+            % (
+                game.incom - len(game.state.kcmdr),
+                (_("s"), "")[(game.incom - len(game.state.kcmdr)) == 1],
+            )
+        )
+    elif game.inkling - game.remkl() + (game.inscom - game.state.nscrem) > 0:
+        prout(_(", but no Commanders."))
+    else:
+        prout(".")
+    if game.skill > SKILL_FAIR:
+        prout(
+            _("The Super Commander has %sbeen destroyed.")
+            % ("", _("not "))[game.state.nscrem]
+        )
+    if len(game.state.baseq) != game.inbase:
+        proutn(_("There "))
+        if game.inbase - len(game.state.baseq) == 1:
+            proutn(_("has been 1 base"))
+        else:
+            proutn(_("have been %d bases") % (game.inbase - len(game.state.baseq)))
+        prout(_(" destroyed, %d remaining.") % len(game.state.baseq))
+    else:
+        prout(_("There are %d bases.") % game.inbase)
+    if communicating() or game.iseenit:
+        # Don't report this if not seen and
+        # either the radio is dead or not at base!
+        attackreport(False)
+        game.iseenit = True
+    if game.casual:
+        prout(
+            _("%d casualt%s suffered so far.")
+            % (game.casual, ("y", "ies")[game.casual != 1])
+        )
+    if game.brigcapacity != game.brigfree:
+        embriggened = game.brigcapacity - game.brigfree
+        if embriggened == 1:
+            prout(_("1 Klingon in brig"))
+        else:
+            prout(_("%d Klingons in brig.") % embriggened)
+        if game.kcaptured == 0:
+            pass
+        elif game.kcaptured == 1:
+            prout(_("1 captured Klingon turned in to Starfleet."))
+        else:
+            prout(_("%d captured Klingons turned in to Star Fleet.") % game.kcaptured)
+    if game.nhelp:
+        prout(
+            _("There were %d call%s for help.")
+            % (game.nhelp, ("", _("s"))[game.nhelp != 1])
+        )
+    if game.ship == "E":
+        proutn(_("You have "))
+        if game.nprobes:
+            proutn("%d" % (game.nprobes))
+        else:
+            proutn(_("no"))
+        proutn(_(" deep space probe"))
+        if game.nprobes != 1:
+            proutn(_("s"))
+        prout(".")
+    if communicating() and is_scheduled(FDSPROB):
+        if game.isarmed:
+            proutn(_("An armed deep space probe is in "))
+        else:
+            proutn(_("A deep space probe is in "))
+        prout("Quadrant %s." % game.probe.quadrant())
+    if game.icrystl:
+        if game.cryprob <= 0.05:
+            prout(_("Dilithium crystals aboard ship... not yet used."))
+        else:
+            i = 0
+            ai = 0.05
+            while game.cryprob > ai:
+                ai *= 2.0
+                i += 1
+            prout(
+                _("Dilithium crystals have been used %d time%s.")
+                % (i, (_("s"), "")[i == 1])
+            )
+    skip(1)
+
+
+def lrscan(silent):
+    "Long-range sensor scan."
+    if damaged(DLRSENS):
+        # Now allow base's sensors if docked
+        if game.condition != "docked":
+            if not silent:
+                prout(_("LONG-RANGE SENSORS DAMAGED."))
+            return
+        if not silent:
+            prout(_("Starbase's long-range scan"))
+    elif not silent:
+        prout(_("Long-range scan"))
+    for x in range(game.quadrant.i - 1, game.quadrant.i + 2):
+        if not silent:
+            proutn(" ")
+        for y in range(game.quadrant.j - 1, game.quadrant.j + 2):
+            if not Coord(x, y).valid_quadrant():
+                if not silent:
+                    proutn("  -1")
+            else:
+                if not damaged(DRADIO):
+                    game.state.galaxy[x][y].charted = True
+                game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
+                game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
+                game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
+                if not silent and game.state.galaxy[x][y].supernova:
+                    proutn(" ***")
+                elif not silent:
+                    cn = " %3d" % (
+                        game.state.chart[x][y].klingons * 100
+                        + game.state.chart[x][y].starbase * 10
+                        + game.state.chart[x][y].stars
+                    )
+                    proutn(((3 - len(cn)) * ".") + cn)
+        if not silent:
+            prout(" ")
+
+
+def damagereport():
+    "Damage report."
+    jdam = False
+    scanner.chew()
+    for i in range(NDEVICES):
+        if damaged(i):
+            if not jdam:
+                prout(_("DEVICE                             REPAIR TIMES"))
+                prout(
+                    _(
+                        "                                   IN FLIGHT                DOCKED"
+                    )
+                )
+                jdam = True
+            prout(
+                "  %-26s\t%8.2f\t\t%8.2f"
+                % (device[i], game.damage[i] + 0.05, DOCKFAC * game.damage[i] + 0.005)
+            )
+    if not jdam:
+        prout(_("All devices functional."))
+
+
+def rechart():
+    "Update the chart in the Enterprise's computer from galaxy data."
+    game.lastchart = game.state.date
+    for i in range(GALSIZE):
+        for j in range(GALSIZE):
+            if game.state.galaxy[i][j].charted:
+                game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
+                game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
+                game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
+
+
+def chart():
+    "Display the star chart."
+    scanner.chew()
+    if game.options & OPTION_AUTOSCAN:
+        lrscan(silent=True)
+    if communicating():
+        rechart()
+    if game.lastchart < game.state.date and game.condition == "docked":
+        prout(_('Spock-  "I revised the Star Chart from the starbase\'s records."'))
+        rechart()
+    prout(_("       STAR CHART FOR THE KNOWN GALAXY"))
+    if game.state.date > game.lastchart:
+        prout(
+            _("(Last surveillance update %d stardates ago).")
+            % ((int)(game.state.date - game.lastchart))
+        )
+    prout("      1    2    3    4    5    6    7    8")
+    for i in range(GALSIZE):
+        if game.options & OPTION_ALPHAMERIC:
+            proutn("%c |" % letterize(i + 1))
+        else:
+            proutn("%d |" % (i + 1))
+        for j in range(GALSIZE):
+            if (
+                (game.options & OPTION_SHOWME)
+                and i == game.quadrant.i
+                and j == game.quadrant.j
+            ):
+                proutn("<")
+            else:
+                proutn(" ")
+            if game.state.galaxy[i][j].supernova:
+                show = "***"
+            elif (
+                not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase
+            ):
+                show = ".1."
+            elif game.state.galaxy[i][j].charted:
+                show = "%3d" % (
+                    game.state.chart[i][j].klingons * 100
+                    + game.state.chart[i][j].starbase * 10
+                    + game.state.chart[i][j].stars
+                )
+                if game.options & OPTION_DOTFILL:
+                    show = show.replace(" ", ".")
+            else:
+                show = "..."
+            proutn(show)
+            if (
+                (game.options & OPTION_SHOWME)
+                and i == game.quadrant.i
+                and j == game.quadrant.j
+            ):
+                proutn(">")
+            else:
+                proutn(" ")
+        proutn("  |")
+        if i < GALSIZE:
+            skip(1)
+
+
+def sectscan(goodScan, i, j):
+    "Light up an individual dot in a sector."
+    if goodScan or (abs(i - game.sector.i) <= 1 and abs(j - game.sector.j) <= 1):
+        if game.quad[i][j] in ("E", "F"):
+            if game.iscloaked:
+                highvideo()  # pragma: no cover
+            textcolor(
+                {
+                    "green": GREEN,
+                    "yellow": YELLOW,
+                    "red": RED,
+                    "docked": CYAN,
+                    "dead": BROWN,
+                }[game.condition]
+            )
+        else:
+            textcolor(
+                {
+                    "?": LIGHTMAGENTA,
+                    "K": LIGHTRED,
+                    "S": LIGHTRED,
+                    "C": LIGHTRED,
+                    "R": LIGHTRED,
+                    "T": LIGHTRED,
+                    "@": LIGHTGREEN,
+                    "P": LIGHTGREEN,
+                }.get(game.quad[i][j], DEFAULT)
+            )
+        proutn("%c " % game.quad[i][j])
+        textcolor(DEFAULT)
+    else:
+        proutn("- ")
+
+
+def status(req=0):
+    "Emit status report lines"
+    if not req or req == 1:
+        prstat(
+            _("Stardate"),
+            _("%.1f, Time Left %.2f") % (game.state.date, game.state.remtime),
+        )
+    if not req or req == 2:
+        if game.condition != "docked":
+            newcnd()
+        prstat(
+            _("Condition"),
+            _("%s, %i DAMAGES")
+            % (game.condition.upper(), sum([x > 0 for x in game.damage])),
+        )
+        if game.iscloaked:
+            prout(_(", CLOAKED"))
+    if not req or req == 3:
+        prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
+    if not req or req == 4:
+        if damaged(DLIFSUP):
+            if game.condition == "docked":
+                s = _("DAMAGED, Base provides")
+            else:
+                s = _("DAMAGED, reserves=%4.2f") % game.lsupres
+        else:
+            s = _("ACTIVE")
+        prstat(_("Life Support"), s)
+    if not req or req == 5:
+        prstat(_("Warp Factor"), "%.1f" % game.warpfac)
+    if not req or req == 6:
+        extra = ""
+        if game.icrystl and (game.options & OPTION_SHOWME):
+            extra = _(" (have crystals)")
+        prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
+    if not req or req == 7:
+        prstat(_("Torpedoes"), "%d" % (game.torps))
+    if not req or req == 8:
+        if damaged(DSHIELD):
+            s = _("DAMAGED,")
+        elif game.shldup:
+            s = _("UP,")
+        else:
+            s = _("DOWN,")
+        data = _(" %d%% %.1f units") % (
+            int((100.0 * game.shield) / game.inshld + 0.5),
+            game.shield,
+        )
+        prstat(_("Shields"), s + data)
+    if not req or req == 9:
+        prstat(_("Klingons Left"), "%d" % game.unwon())
+    if not req or req == 10:
+        if game.options & OPTION_WORLDS:
+            plnet = game.state.galaxy[game.quadrant.i][game.quadrant.j].planet
+            if plnet and plnet.inhabited:
+                prstat(_("Major system"), plnet.name)
+            else:
+                prout(_("Sector is uninhabited"))
+    elif not req or req == 11:
+        attackreport(not req)
+
+
+def request():
+    "Request specified status data, a historical relic from slow TTYs."
+    requests = ("da", "co", "po", "ls", "wa", "en", "to", "sh", "kl", "sy", "ti")
+    while scanner.nexttok() == "IHEOL":
+        proutn(_("Information desired? "))
+    scanner.chew()
+    if scanner.token in requests:
+        status(requests.index(scanner.token))
+    else:
+        prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
+        prout(("  date, condition, position, lsupport, warpfactor,"))
+        prout(("  energy, torpedoes, shields, klingons, system, time."))
+
+
+def srscan():
+    "Short-range scan."
+    goodScan = True
+    if damaged(DSRSENS):
+        # Allow base's sensors if docked
+        if game.condition != "docked":
+            prout(_("   S.R. SENSORS DAMAGED!"))
+            goodScan = False
+        else:
+            prout(_("  [Using Base's sensors]"))
+    else:
+        prout(_("     Short-range scan"))
+    if goodScan and communicating():
+        game.state.chart[game.quadrant.i][game.quadrant.j].klingons = game.state.galaxy[
+            game.quadrant.i
+        ][game.quadrant.j].klingons
+        game.state.chart[game.quadrant.i][game.quadrant.j].starbase = game.state.galaxy[
+            game.quadrant.i
+        ][game.quadrant.j].starbase
+        game.state.chart[game.quadrant.i][game.quadrant.j].stars = game.state.galaxy[
+            game.quadrant.i
+        ][game.quadrant.j].stars
+        game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
+    prout("    1 2 3 4 5 6 7 8 9 10")
+    if game.condition != "docked":
+        newcnd()
+    for i in range(QUADSIZE):
+        if game.options & OPTION_ALPHAMERIC:
+            proutn("%c   " % letterize(i + 1))
+        else:
+            proutn("%2d  " % (i + 1))
+        for j in range(QUADSIZE):
+            sectscan(goodScan, i, j)
+        skip(1)
+
+
+def eta():
+    "Use computer to get estimated time of arrival for a warp jump."
+    w1 = Coord()
+    w2 = Coord()
+    prompt = False
+    if damaged(DCOMPTR):
+        prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
+        skip(1)
+        return
+    if scanner.nexttok() != "IHREAL":
+        prompt = True
+        scanner.chew()
+        proutn(_("Destination quadrant and/or sector? "))
+        if scanner.nexttok() != "IHREAL":
+            huh()
+            return
+    w1.j = int(scanner.real - 0.5)
+    if scanner.nexttok() != "IHREAL":
+        huh()
+        return
+    w1.i = int(scanner.real - 0.5)
+    if scanner.nexttok() == "IHREAL":
+        w2.j = int(scanner.real - 0.5)
+        if scanner.nexttok() != "IHREAL":
+            huh()
+            return
+        w2.i = int(scanner.real - 0.5)
+    else:
+        if game.quadrant.j > w1.i:
+            w2.i = 0
+        else:
+            w2.i = QUADSIZE - 1
+        if game.quadrant.i > w1.j:
+            w2.j = 0
+        else:
+            w2.j = QUADSIZE - 1
+    if not w1.valid_quadrant() or not w2.valid_sector():
+        huh()
+        return
+    dist = math.sqrt(
+        (w1.j - game.quadrant.j + (w2.j - game.sector.j) / (QUADSIZE * 1.0)) ** 2
+        + (w1.i - game.quadrant.i + (w2.i - game.sector.i) / (QUADSIZE * 1.0)) ** 2
+    )
+    wfl = False
+    if prompt:
+        prout(_('Answer "no" if you don\'t know the value:'))
+    while True:
+        scanner.chew()
+        proutn(_("Time or arrival date? "))
+        if scanner.nexttok() == "IHREAL":
+            ttime = scanner.real
+            if ttime > game.state.date:
+                ttime -= game.state.date  # Actually a star date
+            twarp = (math.floor(math.sqrt((10.0 * dist) / ttime) * 10.0) + 1.0) / 10.0
+            if ttime <= 1e-10 or twarp > 10:
+                prout(_("We'll never make it, sir."))
+                scanner.chew()
+                return
+            twarp = max(twarp, 1.0)
+            break
+        scanner.chew()
+        proutn(_("Warp factor? "))
+        if scanner.nexttok() == "IHREAL":
+            wfl = True
+            twarp = scanner.real
+            if twarp < 1.0 or twarp > 10.0:
+                huh()
+                return
+            break
+        prout(_("Captain, certainly you can give me one of these."))
+    while True:
+        scanner.chew()
+        ttime = (10.0 * dist) / twarp ** 2
+        tpower = dist * twarp * twarp * twarp * (game.shldup + 1)
+        if tpower >= game.energy:
+            prout(_("Insufficient energy, sir."))
+            if not game.shldup or tpower > game.energy * 2.0:
+                if not wfl:
+                    return
+                proutn(_("New warp factor to try? "))
+                if scanner.nexttok() == "IHREAL":
+                    wfl = True
+                    twarp = scanner.real
+                    if twarp < 1.0 or twarp > 10.0:
+                        huh()
+                        return
+                    continue
+                else:
+                    scanner.chew()
+                    skip(1)
+                    return
+            prout(_("But if you lower your shields,"))
+            proutn(_("remaining"))
+            tpower /= 2
+        else:
+            proutn(_("Remaining"))
+        prout(_(" energy will be %.2f.") % (game.energy - tpower))
+        if wfl:
+            prout(_("And we will arrive at stardate %.2f.") % (game.state.date + ttime))
+        elif twarp == 1.0:
+            prout(_("Any warp speed is adequate."))
+        else:
+            prout(_("Minimum warp needed is %.2f,") % (twarp))
+            prout(_("and we will arrive at stardate %.2f.") % (game.state.date + ttime))
+        if game.state.remtime < ttime:
+            prout(_("Unfortunately, the Federation will be destroyed by then."))
+        if twarp > 6.0:
+            prout(_("You'll be taking risks at that speed, Captain"))
+        if (
+            game.isatb == 1
+            and game.state.kscmdr == w1
+            and scheduled(FSCDBAS) < ttime + game.state.date
+        ) or (scheduled(FCDBAS) < ttime + game.state.date and game.battle == w1):
+            prout(_("The starbase there will be destroyed by then."))
+        proutn(_("New warp factor to try? "))
+        if scanner.nexttok() == "IHREAL":
+            wfl = True
+            twarp = scanner.real
+            if twarp < 1.0 or twarp > 10.0:
+                huh()
+                return
+        else:
+            scanner.chew()
+            skip(1)
+            return
+
+
+# This is new in SST2K.
+
+
+def goptions():
+    mode = scanner.nexttok()
+    if mode == "IHEOL":
+        active = []
+        for k, v in option_names.items():
+            if (v[0] & game.options) and k != "ALL":
+                active.append(k)
+        active.sort()
+        prout(str(" ".join(active)))
+    elif scanner.token in {"set", "clear"}:
+        mode = scanner.token
+        changemask = 0
+        while True:
+            scanner.nexttok()
+            if scanner.type == "IHEOL":
+                break
+            if scanner.token.upper() in option_names:
+                changemask |= option_names[scanner.token.upper()][0]
+            else:
+                prout(_("No such option as ") + scanner.token)
+        if mode == "set":
+            if (not (game.options & OPTION_CURSES)) and (
+                changemask & OPTION_CURSES
+            ):  # pragma: no cover
+                iostart()
+            game.options |= changemask
+        elif mode == "clear":
+            if (game.options & OPTION_CURSES) and (
+                not (changemask & OPTION_CURSES)
+            ):  # pragma: no cover
+                ioend()
+            game.options &= ~changemask
+        prout(_("Acknowledged, Captain."))
+    else:
+        huh()
+    scanner.chew()
+    skip(1)
+
+
+# Code from setup.c begins here
+
+
+def prelim():
+    "Issue a historically correct banner."
+    skip(2)
+    prout(_("-SUPER- STAR TREK"))
+    skip(1)
+
+
+# From the FORTRAN original
+#    prout(_("Latest update-21 Sept 78"))
+#    skip(1)
+
+
+def freeze(boss):
+    "Save game."
+    if boss:
+        scanner.push("emsave.trk")
+    key = scanner.nexttok()
+    if key == "IHEOL":
+        proutn(_("File name: "))
+        key = scanner.nexttok()
+    if key != "IHALPHA":
+        huh()
+        return
+    if "." not in scanner.token:
+        scanner.token += ".trk"
+    try:
+        fp = open(scanner.token, "wb")
+    except IOError:
+        prout(_("Can't freeze game as file %s") % scanner.token)
+        return
+    pickle.dump(game, fp)
+    fp.close()
+    scanner.chew()
+
+
+def thaw():
+    "Retrieve saved game."
+    global game
+    game.passwd = None
+    key = scanner.nexttok()
+    if key == "IHEOL":
+        proutn(_("File name: "))
+        key = scanner.nexttok()
+    if key != "IHALPHA":
+        huh()
+        return True
+    if "." not in scanner.token:
+        scanner.token += ".trk"
+    try:
+        fp = open(scanner.token, "rb")
+    except IOError:
+        prout(_("Can't thaw game in %s") % scanner.token)
+        return True
+    game = pickle.load(fp)
+    fp.close()
+    scanner.chew()
+    return False
+
+
+# I used <http://www.memory-alpha.org> to find planets
+# with references in ST:TOS.  Earth and the Alpha Centauri
+# Colony have been omitted.
+#
+# Some planets marked Class G and P here will be displayed as class M
+# because of the way planets are generated. This is a known bug.
+systnames = (
+    # Federation Worlds
+    _("Andoria (Fesoan)"),  # several episodes
+    _("Tellar Prime (Miracht)"),  # TOS: "Journey to Babel"
+    _("Vulcan (T'Khasi)"),  # many episodes
+    _("Medusa"),  # TOS: "Is There in Truth No Beauty?"
+    _("Argelius II (Nelphia)"),  # TOS: "Wolf in the Fold" ("IV" in BSD)
+    _("Ardana"),  # TOS: "The Cloud Minders"
+    _("Catulla (Cendo-Prae)"),  # TOS: "The Way to Eden"
+    _("Gideon"),  # TOS: "The Mark of Gideon"
+    _("Aldebaran III"),  # TOS: "The Deadly Years"
+    _("Alpha Majoris I"),  # TOS: "Wolf in the Fold"
+    _("Altair IV"),  # TOS: "Amok Time
+    _("Ariannus"),  # TOS: "Let That Be Your Last Battlefield"
+    _("Benecia"),  # TOS: "The Conscience of the King"
+    _("Beta Niobe I (Sarpeidon)"),  # TOS: "All Our Yesterdays"
+    _("Alpha Carinae II"),  # TOS: "The Ultimate Computer"
+    _("Capella IV (Kohath)"),  # TOS: "Friday's Child" (Class G)
+    _("Daran V"),  # TOS: "For the World is Hollow and I Have Touched the Sky"
+    _("Deneb II"),  # TOS: "Wolf in the Fold" ("IV" in BSD)
+    _("Eminiar VII"),  # TOS: "A Taste of Armageddon"
+    _("Gamma Canaris IV"),  # TOS: "Metamorphosis"
+    _("Gamma Tranguli VI (Vaalel)"),  # TOS: "The Apple"
+    _("Ingraham B"),  # TOS: "Operation: Annihilate"
+    _("Janus IV"),  # TOS: "The Devil in the Dark"
+    _("Makus III"),  # TOS: "The Galileo Seven"
+    _("Marcos XII"),  # TOS: "And the Children Shall Lead",
+    _("Omega IV"),  # TOS: "The Omega Glory"
+    _("Regulus V"),  # TOS: "Amok Time
+    _("Deneva"),  # TOS: "Operation -- Annihilate!"
+    # Worlds from BSD Trek
+    _("Rigel II"),  # TOS: "Shore Leave" ("III" in BSD)
+    _("Beta III"),  # TOS: "The Return of the Archons"
+    _("Triacus"),  # TOS: "And the Children Shall Lead",
+    _("Exo III"),  # TOS: "What Are Little Girls Made Of?" (Class P)
+    #        # Others
+    #    _("Hansen's Planet"),        # TOS: "The Galileo Seven"
+    #    _("Taurus IV"),                # TOS: "The Galileo Seven" (class G)
+    #    _("Antos IV (Doraphane)"),        # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
+    #    _("Izar"),                        # TOS: "Whom Gods Destroy"
+    #    _("Tiburon"),                # TOS: "The Way to Eden"
+    #    _("Merak II"),                # TOS: "The Cloud Minders"
+    #    _("Coridan (Desotriana)"),        # TOS: "Journey to Babel"
+    #    _("Iotia"),                # TOS: "A Piece of the Action"
+)
+
+device = (
+    _("S. R. Sensors"),
+    _("L. R. Sensors"),
+    _("Phasers"),
+    _("Photon Tubes"),
+    _("Life Support"),
+    _("Warp Engines"),
+    _("Impulse Engines"),
+    _("Shields"),
+    _("Subspace Radio"),
+    _("Shuttle Craft"),
+    _("Computer"),
+    _("Navigation System"),
+    _("Transporter"),
+    _("Shield Control"),
+    _("Death Ray"),
+    _("D. S. Probe"),
+    _("Cloaking Device"),
+)
+
+
+def setup():
+    "Prepare to play, set up cosmos."
+    w = Coord()
+    #  Decide how many of everything
+    if choose():
+        return  # frozen game
+    # Prepare the Enterprise
+    game.alldone = game.gamewon = game.shldchg = game.shldup = False
+    game.ship = "E"
+    game.state.crew = FULLCREW
+    game.energy = game.inenrg = 5000.0
+    game.shield = game.inshld = 2500.0
+    game.inlsr = 4.0
+    game.lsupres = 4.0
+    game.quadrant = randplace(GALSIZE)
+    game.sector = randplace(QUADSIZE)
+    game.torps = game.intorps = 10
+    game.nprobes = rnd.integer(2, 5)
+    game.warpfac = 5.0
+    for i in range(NDEVICES):
+        game.damage[i] = 0.0
+    # Set up assorted game parameters
+    game.battle = Coord()
+    game.state.date = game.indate = 100.0 * rnd.real(20, 51)
+    game.nkinks = game.nhelp = game.casual = game.abandoned = 0
+    game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
+    game.isatb = game.state.nplankl = 0
+    game.state.starkl = game.state.basekl = game.state.nworldkl = 0
+    game.iscraft = "onship"
+    game.landed = False
+    game.alive = True
+
+    # the galaxy
+    game.state.galaxy = fill2d(GALSIZE, lambda i_unused, j_unused: Quadrant())
+    # the starchart
+    game.state.chart = fill2d(GALSIZE, lambda i_unused, j_unused: Page())
+
+    game.state.planets = []  # Planet information
+    game.state.baseq = []  # Base quadrant coordinates
+    game.state.kcmdr = []  # Commander quadrant coordinates
+    game.statekscmdr = Coord()  # Supercommander quadrant coordinates
+
+    # Starchart is functional but we've never seen it
+    game.lastchart = FOREVER
+    # Put stars in the galaxy
+    game.instar = 0
+    for i in range(GALSIZE):
+        for j in range(GALSIZE):
+            # Can't have more stars per quadrant than fit in one decimal digit,
+            # if we do the chart representation will break.
+            k = rnd.integer(1, min(10, QUADSIZE ** 2 / 10))
+            game.instar += k
+            game.state.galaxy[i][j].stars = k
+    # Locate star bases in galaxy
+    if game.idebug:
+        prout("=== Allocating %d bases" % game.inbase)  # pragma: no cover
+    for i in range(game.inbase):
+        while True:
+            while True:
+                w = randplace(GALSIZE)
+                if not game.state.galaxy[w.i][w.j].starbase:
+                    break
+            contflag = False
+            # C version: for (j = i-1; j > 0; j--)
+            # so it did them in the opposite order.
+            for j in range(1, i):
+                # Improved placement algorithm to spread out bases
+                distq = (w - game.state.baseq[j]).distance()
+                if distq < 6.0 * (BASEMAX + 1 - game.inbase) and rnd.withprob(0.75):
+                    contflag = True
+                    if game.idebug:
+                        prout(
+                            "=== Abandoning base #%d at %s" % (i, w)
+                        )  # pragma: no cover
+                    break
+                elif distq < 6.0 * (BASEMAX + 1 - game.inbase):
+                    if game.idebug:
+                        prout(
+                            "=== Saving base #%d, close to #%d" % (i, j)
+                        )  # pragma: no cover
+            if not contflag:
+                break
+        if game.idebug:
+            prout("=== Placing base #%d in quadrant %s" % (i, w))  # pragma: no cover
+        game.state.baseq.append(w)
+        game.state.galaxy[w.i][w.j].starbase = game.state.chart[w.i][
+            w.j
+        ].starbase = True
+    # Position ordinary Klingon Battle Cruisers
+    krem = game.inkling
+    klumper = 0.25 * game.skill * (9.0 - game.length) + 1.0
+    klumper = min(klumper, MAXKLQUAD)
+    while True:
+        r = rnd.real()
+        klump = int((1.0 - r * r) * klumper)
+        klump = min(klump, krem)
+        krem -= klump
+        while True:
+            w = randplace(GALSIZE)
+            if (
+                not game.state.galaxy[w.i][w.j].supernova
+                and game.state.galaxy[w.i][w.j].klingons + klump <= MAXKLQUAD
+            ):
+                break
+        game.state.galaxy[w.i][w.j].klingons += klump
+        if krem <= 0:
+            break
+    # Position Klingon Commander Ships
+    for i in range(game.incom):
+        while True:
+            w = randplace(GALSIZE)
+            if not welcoming(w) or w in game.state.kcmdr:
+                continue
+            if game.state.galaxy[w.i][w.j].klingons or rnd.withprob(0.25):
+                break
+        game.state.galaxy[w.i][w.j].klingons += 1
+        game.state.kcmdr.append(w)
+    # Locate planets in galaxy
+    for i in range(game.inplan):
+        while True:
+            w = randplace(GALSIZE)
+            if game.state.galaxy[w.i][w.j].planet is None:
+                break
+        new = Planet()
+        new.quadrant = w
+        new.crystals = "absent"
+        if (game.options & OPTION_WORLDS) and i < NINHAB:
+            new.pclass = "M"  # All inhabited planets are class M
+            new.crystals = "absent"
+            new.known = "known"
+            new.name = systnames[i]
+            new.inhabited = True
+        else:
+            new.pclass = ("M", "N", "O")[rnd.integer(0, 3)]
+            if rnd.withprob(0.33):
+                new.crystals = "present"
+            new.known = "unknown"
+            new.inhabited = False
+        game.state.galaxy[w.i][w.j].planet = new
+        game.state.planets.append(new)
+    # Locate Romulans
+    for i in range(game.state.nromrem):
+        w = randplace(GALSIZE)
+        game.state.galaxy[w.i][w.j].romulans += 1
+    # Place the Super-Commander if needed
+    if game.state.nscrem > 0:
+        while True:
+            w = randplace(GALSIZE)
+            if welcoming(w):
+                break
+        game.state.kscmdr = w
+        game.state.galaxy[w.i][w.j].klingons += 1
+    # Initialize times for extraneous events
+    schedule(FSNOVA, expran(0.5 * game.intime))
+    schedule(FTBEAM, expran(1.5 * (game.intime / len(game.state.kcmdr))))
+    schedule(FSNAP, rnd.real(1.0, 2.0))  # Force an early snapshot
+    schedule(FBATTAK, expran(0.3 * game.intime))
+    unschedule(FCDBAS)
+    if game.state.nscrem:
+        schedule(FSCMOVE, 0.2777)
+    else:
+        unschedule(FSCMOVE)
+    unschedule(FSCDBAS)
+    unschedule(FDSPROB)
+    if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
+        schedule(FDISTR, expran(1.0 + game.intime))
+    else:
+        unschedule(FDISTR)
+    unschedule(FENSLV)
+    unschedule(FREPRO)
+    # Place thing (in tournament game, we don't want one!)
+    # New in SST2K: never place the Thing near a starbase.
+    # This makes sense and avoids a special case in the old code.
+    if game.tourn is None:
+        # Avoid distrubing the RNG chain.  This code
+        # was a late fix and we don't want to mess up
+        # all the regression tests.
+        state = randomizer.getrngstate()
+        while True:
+            thing.location = randplace(GALSIZE)
+            # Put it somewhere a starbase is not
+            if thing.location not in game.state.baseq:
+                break
+        randomizer.setrngstate(state)
+    skip(2)
+    game.state.snap = False
+    if game.skill == SKILL_NOVICE:
+        prout(
+            _("It is stardate %d. The Federation is being attacked by")
+            % int(game.state.date)
+        )
+        prout(_("a deadly Klingon invasion force. As captain of the United"))
+        prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
+        prout(
+            _("and destroy this invasion force of %d battle cruisers.")
+            % ((game.inkling + game.incom + game.inscom))
+        )
+        prout(
+            _("You have an initial allotment of %d stardates to complete")
+            % int(game.intime)
+        )
+        prout(_("your mission.  As you proceed you may be given more time."))
+        skip(1)
+        prout(_("You will have %d supporting starbases.") % (game.inbase))
+        proutn(_("Starbase locations-  "))
+    else:
+        prout(_("Stardate %d.") % int(game.state.date))
+        skip(1)
+        prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
+        prout(_("An unknown number of Romulans."))
+        if game.state.nscrem:
+            prout(_("And one (GULP) Super-Commander."))
+        prout(_("%d stardates.") % int(game.intime))
+        proutn(_("%d starbases in ") % game.inbase)
+    for i in range(game.inbase):
+        proutn(repr(game.state.baseq[i]))
+        proutn("  ")
+    skip(2)
+    proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
+    proutn(_(" Sector %s") % game.sector)
+    skip(2)
+    prout(_("Good Luck!"))
+    if game.state.nscrem:
+        prout(_("  YOU'LL NEED IT."))
+    waitfor()
+    clrscr()
+    setwnd(message_window)
+    newqad()
+    if (
+        len(game.enemies)
+        - (thing.location == game.quadrant)
+        - (game.tholian is not None)
+    ):
+        game.shldup = True
+    if game.neutz:  # bad luck to start in a Romulan Neutral Zone
+        attack(torps_ok=False)
+
+
+def choose():
+    "Choose your game type."
+    game.tourn = None
+    game.length = 0
+    game.thawed = False
+    game.skill = SKILL_NONE
+    gametype = None
+    wayback = 0
+    while (
+        gametype is None or game.length == 0 or game.skill == SKILL_NONE or wayback == 0
+    ):
+        eol_is_fancy = False
+        if (
+            not scanner.inqueue or scanner.token == "IHEOL"
+        ):  # Can start with command line options
+            if gametype is None:
+                proutn(_("Would you like a regular, tournament, or saved game? "))
+            elif game.length == 0:
+                proutn(_("Would you like a Short, Medium, or Long game? "))
+            elif game.skill == SKILL_NONE:
+                proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
+            elif wayback == 0:
+                proutn(_("Wayback setting (press enter for current year): "))
+                eol_is_fancy = True
+        scanner.nexttok()
+        if game.idebug:
+            prout("-- Token: %s=%s" % (scanner.type, repr(scanner.token)))
+        if scanner.token == "":
+            raise SystemExit(0)  # Early end of replay
+        if scanner.token.startswith("r"):  # regular
+            gametype = "regular"
+        elif scanner.token.startswith("t"):
+            gametype = "tournament"
+            proutn(_("Type in tournament number-"))
+            game.tourn = 0
+            while scanner.nexttok() == "IHEOL":
+                if scanner.real == 0:
+                    scanner.chew()
+                    continue  # We don't want a blank entry
+            game.tourn = int(round(scanner.real))
+            rnd.seed(scanner.real)
+            if logfp:
+                logfp.write("# rnd.seed(%d)\n" % scanner.real)
+        elif scanner.token.startswith("sa") or scanner.token.startswith(
+            "fr"
+        ):  # saved or frozen
+            gametype = "saved"
+            if thaw():
+                continue
+            scanner.chew()
+            if game.passwd is None:
+                continue
+            if not game.alldone:
+                game.thawed = True  # No plaque if not finished
+            report()
+            waitfor()
+            return True
+        elif scanner.token.startswith("s"):  # short
+            game.length = 1
+        elif scanner.token.startswith("m"):  # medium
+            game.length = 2
+        elif scanner.token.startswith("l"):  # long
+            game.length = 4
+        elif scanner.token.startswith("n"):  # novice
+            game.skill = SKILL_NOVICE
+        elif (game.skill is None) and scanner.token.startswith("f"):  # fair
+            game.skill = SKILL_FAIR
+        elif scanner.token.startswith("g"):  # good
+            game.skill = SKILL_GOOD
+        elif scanner.token.startswith("e"):  # expert
+            game.skill = SKILL_EXPERT
+        elif scanner.token.startswith("em"):  # emeritus
+            game.skill = SKILL_EMERITUS
+        elif scanner.type == "IHREAL":
+            wayback = scanner.int()
+        elif eol_is_fancy and scanner.token.startswith("\n"):
+            wayback = time.localtime().tm_year
+        elif scanner.token.startswith("\n"):
+            continue
+        elif scanner.token.startswith("idebug"):
+            game.idebug = True
+        else:
+            # Unrecognized token
+            prout(_("Can't interpret %s") % repr(scanner.token))
+    for (__, (option, year)) in option_names.items():
+        if wayback < year:
+            game.options &= ~option
+    setpassword()
+    if game.passwd == "debug":  # pragma: no cover
+        game.idebug = True
+        prout("=== Debug mode enabled.")
+    if game.idebug:
+        prout(
+            "--- Setup: type=%s length=%s skill=%s wayback=%s"
+            % (gametype, game.length, game.skill, wayback)
+        )
+    # Use parameters to generate initial values of things
+    game.damfac = 0.5 * game.skill
+    game.inbase = rnd.integer(BASEMIN, BASEMAX + 1)
+    game.inplan = 0
+    if game.options & OPTION_PLANETS:
+        game.inplan += rnd.integer(MAXUNINHAB / 2, MAXUNINHAB + 1)
+    if game.options & OPTION_WORLDS:
+        game.inplan += int(NINHAB)
+    game.state.nromrem = game.inrom = rnd.integer(2 * game.skill)
+    game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR) and (
+        (game.options & OPTION_SUPERCMDR) != 0
+    )
+    game.state.remtime = 7.0 * game.length
+    game.intime = game.state.remtime
+    game.inkling = int(
+        2.0
+        * game.intime
+        * ((game.skill + 1 - 2 * rnd.real()) * game.skill * 0.1 + 0.15)
+    )
+    game.incom = min(MINCMDR, int(game.skill + 0.0625 * game.inkling * rnd.real()))
+    game.state.remres = (game.inkling + 4 * game.incom) * game.intime
+    game.inresor = game.state.remres
+    if game.inkling > 50:
+        game.inbase += 1
+    return False
+
+
+def dropin(iquad=None):
+    "Drop a feature on a random dot in the current quadrant."
+    while True:
+        w = randplace(QUADSIZE)
+        if game.quad[w.i][w.j] == ".":
+            break
+    if iquad is not None:
+        game.quad[w.i][w.j] = iquad
+    return w
+
+
+def newcnd():
+    "Update our alert status."
+    game.condition = "green"
+    if game.energy < 1000.0:
+        game.condition = "yellow"
+    if (
+        game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons
+        or game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans
+    ):
+        game.condition = "red"
+    if not game.alive:
+        game.condition = "dead"
+
+
+def newkling():
+    "Drop new Klingon into current quadrant."
+    return Enemy("K", loc=dropin(), power=rnd.real(300, 450) + 25.0 * game.skill)
+
+
+def sortenemies():
+    "Sort enemies by distance so 'nearest' is meaningful."
+    game.enemies.sort(key=lambda x: x.kdist)
+
+
+def newqad():
+    "Set up a new state of quadrant, for when we enter or re-enter it."
+    game.justin = True
+    game.iplnet = None
+    game.neutz = game.inorbit = game.landed = False
+    game.ientesc = game.iseenit = game.isviolreported = False
+    game.tholian = None
+    # Create a blank quadrant
+    game.quad = fill2d(QUADSIZE, lambda i, j: ".")
+    if game.iscate:
+        # Attempt to escape Super-commander, so tbeam back!
+        game.iscate = False
+        game.ientesc = True
+    q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
+    # cope with supernova
+    if q.supernova:
+        return
+    game.klhere = q.klingons
+    game.irhere = q.romulans
+    # Position Starship
+    game.quad[game.sector.i][game.sector.j] = game.ship
+    game.enemies = []
+    if q.klingons:
+        # Position ordinary Klingons
+        for _i in range(game.klhere):
+            newkling()
+        # If we need a commander, promote a Klingon
+        for cmdr in game.state.kcmdr:
+            if cmdr == game.quadrant:
+                e = game.enemies[game.klhere - 1]
+                game.quad[e.location.i][e.location.j] = "C"
+                e.power = rnd.real(950, 1350) + 50.0 * game.skill
+                break
+        # If we need a super-commander, promote a Klingon
+        if game.quadrant == game.state.kscmdr:
+            e = game.enemies[0]
+            game.quad[e.location.i][e.location.j] = "S"
+            e.power = rnd.real(1175.0, 1575.0) + 125.0 * game.skill
+            game.iscate = game.remkl() > 1
+    # Put in Romulans if needed
+    for _i in range(q.romulans):
+        Enemy("R", loc=dropin(), power=rnd.real(400.0, 850.0) + 50.0 * game.skill)
+    # If quadrant needs a starbase, put it in
+    if q.starbase:
+        game.base = dropin("B")
+    # If quadrant needs a planet, put it in
+    if q.planet:
+        game.iplnet = q.planet
+        if not q.planet.inhabited:
+            game.plnet = dropin("P")
+        else:
+            game.plnet = dropin("@")
+    # Check for condition
+    newcnd()
+    # Check for RNZ
+    if game.irhere > 0 and game.klhere == 0:
+        game.neutz = True
+        if not damaged(DRADIO):
+            skip(1)
+            prout(_('LT. Uhura- "Captain, an urgent message.'))
+            prout(_("  I'll put it on audio.\"  CLICK"))
+            skip(1)
+            prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
+            prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
+    # Put in THING if needed
+    if thing.location == game.quadrant:
+        Enemy(
+            etype="?", loc=dropin(), power=rnd.real(6000, 6500.0) + 250.0 * game.skill
+        )
+        if not damaged(DSRSENS):
+            skip(1)
+            prout(_('Mr. Spock- "Captain, this is most unusual.'))
+            prout(_('    Please examine your short-range scan."'))
+    # Decide if quadrant needs a Tholian; lighten up if skill is low
+    if game.options & OPTION_THOLIAN:
+        if (
+            (game.skill < SKILL_GOOD and rnd.withprob(0.02))
+            or (game.skill == SKILL_GOOD and rnd.withprob(0.05))
+            or (game.skill > SKILL_GOOD and rnd.withprob(0.08))
+        ):
+            w = Coord()
+            while True:
+                w.i = rnd.withprob(0.5) * (QUADSIZE - 1)
+                w.j = rnd.withprob(0.5) * (QUADSIZE - 1)
+                if game.quad[w.i][w.j] == ".":
+                    break
+            game.tholian = Enemy(
+                etype="T", loc=w, power=rnd.integer(100, 500) + 25.0 * game.skill
+            )
+            # Reserve unoccupied corners
+            if game.quad[0][0] == ".":
+                game.quad[0][0] = "X"
+            if game.quad[0][QUADSIZE - 1] == ".":
+                game.quad[0][QUADSIZE - 1] = "X"
+            if game.quad[QUADSIZE - 1][0] == ".":
+                game.quad[QUADSIZE - 1][0] = "X"
+            if game.quad[QUADSIZE - 1][QUADSIZE - 1] == ".":
+                game.quad[QUADSIZE - 1][QUADSIZE - 1] = "X"
+    sortenemies()
+    # And finally the stars
+    for _i in range(q.stars):
+        dropin("*")
+    # Put in a few black holes
+    for _i in range(1, 3 + 1):
+        if rnd.withprob(0.5):
+            dropin(" ")
+    # Take out X's in corners if Tholian present
+    if game.tholian:
+        if game.quad[0][0] == "X":
+            game.quad[0][0] = "."
+        if game.quad[0][QUADSIZE - 1] == "X":
+            game.quad[0][QUADSIZE - 1] = "."
+        if game.quad[QUADSIZE - 1][0] == "X":
+            game.quad[QUADSIZE - 1][0] = "."
+        if game.quad[QUADSIZE - 1][QUADSIZE - 1] == "X":
+            game.quad[QUADSIZE - 1][QUADSIZE - 1] = "."
+    # This should guarantee that replay games don't lose info about the chart
+    if (game.options & OPTION_AUTOSCAN) or replayfp:
+        lrscan(silent=True)
+
+
+def setpassword():
+    "Set the self-destruct password."
+    if game.options & OPTION_AUTOPASS:
+        game.passwd = ""
+        game.passwd += chr(ord("a") + rnd.integer(26))
+        game.passwd += chr(ord("a") + rnd.integer(26))
+        game.passwd += chr(ord("a") + rnd.integer(26))
+    else:
+        while True:
+            scanner.chew()
+            proutn(_("Please type in a secret password- "))
+            scanner.nexttok()
+            game.passwd = scanner.token
+            # game.passwd = getpass.getpass("Please type in a secret password- ")
+            if game.passwd is not None:
+                break
+
+
+# Code from sst.c begins here
+
+commands = [
+    ("SRSCAN", OPTION_TTY),
+    ("STATUS", OPTION_TTY),
+    ("REQUEST", OPTION_TTY),
+    ("LRSCAN", OPTION_TTY),
+    ("PHASERS", 0),
+    ("TORPEDO", 0),
+    ("PHOTONS", 0),
+    ("MOVE", 0),
+    ("SHIELDS", 0),
+    ("DOCK", 0),
+    ("DAMAGES", 0),
+    ("CHART", 0),
+    ("IMPULSE", 0),
+    ("REST", 0),
+    ("WARP", 0),
+    ("SENSORS", OPTION_PLANETS),
+    ("ORBIT", OPTION_PLANETS),
+    ("TRANSPORT", OPTION_PLANETS),
+    ("MINE", OPTION_PLANETS),
+    ("CRYSTALS", OPTION_PLANETS),
+    ("SHUTTLE", OPTION_PLANETS),
+    ("PLANETS", OPTION_PLANETS),
+    ("REPORT", 0),
+    ("COMPUTER", 0),
+    ("COMMANDS", 0),
+    ("EMEXIT", 0),
+    ("PROBE", OPTION_PROBE),
+    ("SAVE", 0),
+    ("FREEZE", 0),  # Synonym for SAVE
+    ("OPTIONS", 0),
+    ("ABANDON", 0),
+    # No abbreviations accepted after this point
+    ("DESTRUCT", 0),
+    ("DEATHRAY", 0),
+    ("CAPTURE", OPTION_CAPTURE),
+    ("CLOAK", OPTION_CLOAK),
+    ("DEBUG", 0),
+    ("MAYDAY", 0),
+    ("SOS", 0),  # Synonym for MAYDAY
+    ("CALL", 0),  # Synonym for MAYDAY
+    ("QUIT", 0),
+    ("HELP", 0),
+    ("SCORE", 0),
+    ("CURSES", 0),
+    ("", 0),
+]
+
+
+def listCommands():  # pragma: no cover
+    "Generate a list of legal commands."
+    # Coverage-disabled because testing for this is fragile
+    # in the presence of changes in the command set.
+    prout(_("LEGAL COMMANDS ARE:"))
+    emitted = 0
+    for (key, opt) in commands:
+        if not opt or (opt & game.options):
+            proutn("%-12s " % key)
+            emitted += 1
+            if emitted % 5 == 4:
+                skip(1)
+    skip(1)
+
+
+def helpme():
+    "Browse on-line help."
+    key = scanner.nexttok()
+    while True:
+        if key == "IHEOL":
+            setwnd(prompt_window)
+            proutn(_("Help on what command? "))
+            key = scanner.nexttok()
+        setwnd(message_window)
+        if key == "IHEOL":
+            return
+        cmds = [x[0] for x in commands]
+        if scanner.token.upper() in cmds or scanner.token.upper() == "ABBREV":
+            break
+        skip(1)
+        listCommands()
+        key = "IHEOL"
+        scanner.chew()
+        skip(1)
+    cmd = scanner.token.upper()
+    for directory in docpath:
+        try:
+            fp = open(os.path.join(directory, "sst.doc"), "r")
+            break
+        except IOError:
+            pass
+    else:
+        prout(_('Spock-  "Captain, that information is missing from the'))
+        prout(_("   computer. You need to find sst.doc and put it somewhere"))
+        proutn(_("   in these directories: %s") % ":".join(docpath))
+        prout('."')
+        # This used to continue: "You need to find SST.DOC and put
+        # it in the current directory."
+        return
+    while True:
+        linebuf = fp.readline()
+        if linebuf == "":
+            prout(_('Spock- "Captain, there is no information on that command."'))
+            fp.close()
+            return
+        if linebuf[0] == "%" and linebuf[1] == "%" and linebuf[2] == " ":
+            linebuf = linebuf[3:].strip()
+            if cmd.upper() == linebuf:
+                break
+    skip(1)
+    prout(_('Spock- "Captain, I\'ve found the following information:"'))
+    skip(1)
+    while True:
+        linebuf = fp.readline()
+        if "******" in linebuf:
+            break
+        proutn(linebuf)
+    fp.close()
+
+
+def makemoves():
+    "Command-interpretation loop."
+
+    def checkviol():
+        if (
+            game.irhere
+            and game.state.date >= ALGERON
+            and not game.isviolreported
+            and game.iscloaked
+        ):
+            prout(
+                _("The Romulan ship discovers you are breaking the Treaty of Algeron!")
+            )
+            game.ncviol += 1
+            game.isviolreported = True
+
+    while True:  # command loop
+        drawmaps(1)
+        while True:  # get a command
+            hitme = False
+            game.optime = game.justin = False
+            scanner.chew()
+            setwnd(prompt_window)
+            clrscr()
+            proutn("COMMAND> ")
+            if scanner.nexttok() == "IHEOL":
+                if game.options & OPTION_CURSES:  # pragma: no cover
+                    makechart()
+                continue
+            elif scanner.token == "":
+                continue
+            game.ididit = False
+            clrscr()
+            setwnd(message_window)
+            clrscr()
+            abandon_passed = False
+            cmd = ""  # Force cmd to persist after loop
+            opt = 0  # Force opt to persist after loop
+            for (cmd, opt) in commands:
+                # commands after ABANDON cannot be abbreviated
+                if cmd == "ABANDON":
+                    abandon_passed = True
+                if cmd == scanner.token.upper() or (
+                    not abandon_passed and cmd.startswith(scanner.token.upper())
+                ):
+                    break
+            if cmd == "":  # pragma: no cover
+                listCommands()
+                continue
+            elif opt and not (opt & game.options):
+                huh()
+            else:
+                break
+        if game.options & OPTION_CURSES:  # pragma: no cover
+            prout("COMMAND> %s" % cmd)
+        if cmd == "SRSCAN":  # srscan
+            srscan()
+        elif cmd == "STATUS":  # status
+            status()
+        elif cmd == "REQUEST":  # status request
+            request()
+        elif cmd == "LRSCAN":  # long range scan
+            lrscan(silent=False)
+        elif cmd == "PHASERS":  # phasers
+            phasers()
+            if game.ididit:
+                checkviol()
+                hitme = True
+        elif cmd in ("TORPEDO", "PHOTONS"):  # photon torpedos
+            torps()
+            if game.ididit:
+                checkviol()
+                hitme = True
+        elif cmd == "MOVE":  # move under warp
+            warp(wcourse=None, involuntary=False)
+        elif cmd == "SHIELDS":  # shields
+            doshield(shraise=False)
+            if game.ididit:
+                hitme = True
+                game.shldchg = False
+        elif cmd == "DOCK":  # dock at starbase
+            dock(True)
+            if game.ididit:
+                attack(torps_ok=False)
+        elif cmd == "DAMAGES":  # damage reports
+            damagereport()
+        elif cmd == "CHART":  # chart
+            makechart()
+        elif cmd == "IMPULSE":  # impulse
+            impulse()
+        elif cmd == "REST":  # rest
+            wait()
+            if game.ididit:
+                hitme = True
+        elif cmd == "WARP":  # warp
+            setwarp()
+        elif cmd == "SENSORS":  # sensors
+            sensor()
+        elif cmd == "ORBIT":  # orbit
+            orbit()
+            if game.ididit:
+                hitme = True
+        elif cmd == "TRANSPORT":  # transport "beam"
+            beam()
+        elif cmd == "MINE":  # mine
+            mine()
+            if game.ididit:
+                hitme = True
+        elif cmd == "CRYSTALS":  # crystals
+            usecrystals()
+            if game.ididit:
+                hitme = True
+        elif cmd == "SHUTTLE":  # shuttle
+            shuttle()
+            if game.ididit:
+                hitme = True
+        elif cmd == "PLANETS":  # Planet list
+            survey()
+        elif cmd == "REPORT":  # Game Report
+            report()
+        elif cmd == "COMPUTER":  # use COMPUTER!
+            eta()
+        elif cmd == "COMMANDS":
+            listCommands()
+        elif cmd == "EMEXIT":  # Emergency exit
+            clrscr()  # Hide screen
+            freeze(True)  # forced save
+            raise SystemExit(1)  # And quick exit
+        elif cmd == "PROBE":
+            probe()  # Launch probe
+            if game.ididit:
+                hitme = True
+        elif cmd == "ABANDON":  # Abandon Ship
+            abandon()
+        elif cmd == "DESTRUCT":  # Self Destruct
+            selfdestruct()
+        elif cmd == "SAVE":  # Save Game
+            freeze(False)
+            clrscr()
+            if game.skill > SKILL_GOOD:
+                prout(_("WARNING--Saved games produce no plaques!"))
+        elif cmd == "DEATHRAY":  # Try a desparation measure
+            deathray()
+            if game.ididit:
+                hitme = True
+        elif cmd == "CAPTURE":
+            capture()
+        elif cmd == "CLOAK":
+            cloak()
+        elif cmd == "DEBUGCMD":  # What do we want for debug???
+            debugme()
+        elif cmd == "MAYDAY":  # Call for help
+            mayday()
+            if game.ididit:
+                hitme = True
+        elif cmd == "QUIT":
+            game.alldone = True  # quit the game
+        elif cmd == "HELP":
+            helpme()  # get help
+        elif cmd == "SCORE":
+            score()  # see current score
+        elif cmd == "CURSES":  # pragma: no cover
+            game.options |= OPTION_CURSES | OPTION_COLOR
+            iostart()
+        elif cmd == "OPTIONS":
+            goptions()
+        while True:
+            if game.alldone:
+                break  # Game has ended
+            if game.optime != 0.0:
+                events()
+                if game.alldone:
+                    break  # Events did us in
+            if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
+                atover(False)
+                continue
+            if hitme and not game.justin:
+                attack(torps_ok=True)
+                if game.alldone:
+                    break
+                if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
+                    atover(False)
+                    hitme = True
+                    continue
+            break
+        if game.alldone:
+            break
+    if game.idebug:
+        prout("=== Ending")  # pragma: no cover
+
+
+def cramen(ch):
+    "Emit the name of an enemy or feature."
+    if ch == "R":
+        s = _("Romulan")
+    elif ch == "K":
+        s = _("Klingon")
+    elif ch == "C":
+        s = _("Commander")
+    elif ch == "S":
+        s = _("Super-commander")
+    elif ch == "*":
+        s = _("Star")
+    elif ch == "P":
+        s = _("Planet")
+    elif ch == "B":
+        s = _("Starbase")
+    elif ch == " ":
+        s = _("Black hole")
+    elif ch == "T":
+        s = _("Tholian")
+    elif ch == "#":
+        s = _("Tholian web")
+    elif ch == "?":
+        s = _("Stranger")
+    elif ch == "@":
+        s = _("Inhabited World")
+    else:
+        s = "Unknown??"  # pragma: no cover
+    return s
+
+
+def crmena(loud, enemy, loctype, w):
+    "Emit the name of an enemy and his location."
+    buf = ""
+    if loud:
+        buf += "***"
+    buf += cramen(enemy) + _(" at ")
+    if loctype == "quadrant":
+        buf += _("Quadrant ")
+    elif loctype == "sector":
+        buf += _("Sector ")
+    return buf + repr(w)
+
+
+def crmshp():
+    "Emit our ship name."
+    return {"E": _("Enterprise"), "F": _("Faerie Queene")}.get(game.ship, "Ship???")
+
+
+def stars():
+    "Emit a line of stars"
+    prouts("******************************************************")
+    skip(1)
+
+
+def expran(avrage):
+    return -avrage * math.log(1e-7 + rnd.real())
+
+
+def randplace(size):
+    "Choose a random location."
+    w = Coord()
+    w.i = rnd.integer(size)
+    w.j = rnd.integer(size)
+    return w
+
+
+class sstscanner:
+    def __init__(self):
+        self.type = None
+        self.token = None
+        self.real = 0.0
+        self.inqueue = []
+
+    def nexttok(self):
+        # Get a token from the user
+        self.real = 0.0
+        self.token = ""
+        # Fill the token queue if nothing here
+        while not self.inqueue:
+            sline = cgetline()
+            if curwnd == prompt_window:
+                clrscr()
+                setwnd(message_window)
+                clrscr()
+            if sline == "":
+                return None
+            if not sline:
+                continue
+            else:
+                self.inqueue = sline.lstrip().split() + ["\n"]
+        # From here on in it's all looking at the queue
+        self.token = self.inqueue.pop(0)
+        if self.token == "\n":
+            self.type = "IHEOL"
+            return "IHEOL"
+        try:
+            self.real = float(self.token)
+            self.type = "IHREAL"
+            return "IHREAL"
+        except ValueError:
+            pass
+        # Treat as alpha
+        self.token = self.token.lower()
+        self.type = "IHALPHA"
+        self.real = None
+        return "IHALPHA"
+
+    def append(self, tok):
+        self.inqueue.append(tok)
+
+    def push(self, tok):
+        self.inqueue.insert(0, tok)
+
+    def waiting(self):
+        return self.inqueue
+
+    def chew(self):
+        # Demand input for next scan
+        self.inqueue = []
+        self.real = self.token = None
+
+    def sees(self, s):
+        # compares s to item and returns true if it matches to the length of s
+        return s.startswith(self.token)
+
+    def int(self):
+        # Round token value to nearest integer
+        return int(round(self.real))
+
+    def getcoord(self):
+        s = Coord()
+        self.nexttok()
+        if game.options & OPTION_ALPHAMERIC:
+            try:
+                if (
+                    (self.type == "IHALPHA")
+                    and (self.token[0] in "abcdefghij")
+                    and (self.token[1] in "0123456789")
+                ):
+                    s.i = ord(self.token[0]) - ord("a")
+                    s.j = int(self.token[1:]) - 1
+                    return s
+            except (TypeError, IndexError):
+                huh()
+                return None
+        if self.type != "IHREAL":
+            huh()
+            return None
+        s.i = self.int() - 1
+        self.nexttok()
+        if self.type != "IHREAL":
+            huh()
+            return None
+        s.j = self.int() - 1
+        return s
+
+    def __repr__(self):  # pragma: no cover
+        return "<sstcanner: token=%s, type=%s, queue=%s>" % (
+            self.token,
+            self.type,
+            self.inqueue,
+        )
+
+
+def ja():
+    "Yes-or-no confirmation."
+    scanner.chew()
+    while True:
+        scanner.nexttok()
+        if scanner.token == "y":
+            return True
+        if scanner.token == "n":
+            return False
+        scanner.chew()
+        proutn(_('Please answer with "y" or "n": '))
+
+
+def huh():
+    "Complain about unparseable input."
+    scanner.chew()
+    skip(1)
+    prout(_("Beg your pardon, Captain?"))
+
+
+def debugme():  # pragma: no cover
+    "Access to the internals for debugging."
+    proutn("Reset levels? ")
+    if ja():
+        if game.energy < game.inenrg:
+            game.energy = game.inenrg
+        game.shield = game.inshld
+        game.torps = game.intorps
+        game.lsupres = game.inlsr
+    proutn("Reset damage? ")
+    if ja():
+        for i in range(NDEVICES):
+            if game.damage[i] > 0.0:
+                game.damage[i] = 0.0
+    proutn("Toggle debug flag? ")
+    if ja():
+        game.idebug = not game.idebug
+        if game.idebug:  # pragma: no cover
+            prout("Debug output ON")
+        else:
+            prout("Debug output OFF")
+    proutn("Cause selective damage? ")
+    if ja():
+        for i in range(NDEVICES):
+            proutn("Kill %s?" % device[i])
+            scanner.chew()
+            key = scanner.nexttok()
+            if key == "IHALPHA" and scanner.sees("y"):
+                game.damage[i] = 10.0
+    proutn("Examine/change events? ")
+    if ja():
+        ev = Event()
+        w = Coord()
+        legends = {
+            FSNOVA: "Supernova       ",
+            FTBEAM: "T Beam          ",
+            FSNAP: "Snapshot        ",
+            FBATTAK: "Base Attack     ",
+            FCDBAS: "Base Destroy    ",
+            FSCMOVE: "SC Move         ",
+            FSCDBAS: "SC Base Destroy ",
+            FDSPROB: "Probe Move      ",
+            FDISTR: "Distress Call   ",
+            FENSLV: "Enslavement     ",
+            FREPRO: "Klingon Build   ",
+        }
+        for i in range(1, NEVENTS):
+            proutn(legends[i])
+            if is_scheduled(i):
+                proutn("%.2f" % (scheduled(i) - game.state.date))
+                if i in {FENSLV, FREPRO}:
+                    ev = findevent(i)
+                    proutn(" in %s" % ev.quadrant)
+            else:
+                proutn("never")
+            proutn("? ")
+            scanner.chew()
+            key = scanner.nexttok()
+            if key == "n":
+                unschedule(i)
+                scanner.chew()
+            elif key == "IHREAL":
+                ev = schedule(i, scanner.real)
+                if i in {FENSLV, FREPRO}:
+                    scanner.chew()
+                    proutn("In quadrant- ")
+                    key = scanner.nexttok()
+                    # "IHEOL" says to leave coordinates as they are
+                    if key != "IHEOL":
+                        if key != "IHREAL":
+                            prout("Event %d canceled, no x coordinate." % (i))
+                            unschedule(i)
+                            continue
+                        w.i = int(round(scanner.real))
+                        key = scanner.nexttok()
+                        if key != "IHREAL":
+                            prout("Event %d canceled, no y coordinate." % (i))
+                            unschedule(i)
+                            continue
+                        w.j = int(round(scanner.real))
+                        ev.quadrant = w
+        scanner.chew()
+    proutn("Induce supernova here? ")
+    if ja():
+        game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova = True
+        atover(True)
+
+
+if __name__ == "__main__":
+    try:
+        # global line, thing, game
+        game = None
+        thing = Thingy()
+        game = Gamestate()
+        rnd = randomizer()
+        logfp = None
+        game.options = OPTION_ALL & ~OPTION_IOMODES
+        if os.getenv("TERM"):
+            game.options |= OPTION_CURSES  # pragma: no cover
+        else:
+            game.options |= OPTION_TTY
+        seed = int(time.time())
+        try:
+            (options, arguments) = getopt.getopt(sys.argv[1:], "cr:s:txV")
+            for (switch, val) in options:
+                if switch == "-r":
+                    # pylint: disable=raise-missing-from
+                    try:
+                        replayfp = open(val, "r")
+                    except IOError:
+                        sys.stderr.write("sst: can't open replay file %s\n" % val)
+                        raise SystemExit(1)
+                    # pylint: disable=raise-missing-from
+                    try:
+                        while True:
+                            line = replayfp.readline().strip()
+                            print(line)
+                            if line == "#":
+                                break
+                            if line.startswith("# seed"):
+                                (__, __, seed) = line.split()
+                                # pylint: disable=eval-used
+                                seed = eval(seed)
+                            elif line.startswith("# arguments"):
+                                arguments += line.split()[2:]
+                    except ValueError:  # pragma: no cover
+                        sys.stderr.write("sst: replay file %s is ill-formed\n" % val)
+                        raise SystemExit(1)
+                    game.options |= OPTION_TTY
+                    game.options &= ~OPTION_CURSES
+                elif switch == "-s":  # pragma: no cover
+                    seed = int(val)
+                elif switch == "-t":  # pragma: no cover
+                    game.options |= OPTION_TTY
+                    game.options &= ~OPTION_CURSES
+                elif switch == "-x":  # pragma: no cover
+                    game.idebug = True
+                elif switch == "-c":  # Enable curses debugging - undocumented
+                    game.cdebug = True
+                elif switch == "-V":  # pragma: no cover
+                    print("SST2K", version)
+                    raise SystemExit(0)
+                else:  # pragma: no cover
+                    sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
+                    raise SystemExit(1)
+        except getopt.GetoptError as err:
+            print(err)
+            raise SystemExit(1) from err
+        # where to save the input in case of bugs
+        if "TMPDIR" in os.environ:  # pragma: no cover
+            tmpdir = os.environ["TMPDIR"]
+        else:
+            tmpdir = "/tmp"
+        try:
+            logfp = open(os.path.join(tmpdir, "sst-input.log"), "w")
+        except IOError:  # pragma: no cover
+            sys.stderr.write("sst: warning, can't open logfile\n")
+            sys.exit(1)
+        if logfp:
+            logfp.write("# seed %s\n" % seed)
+            logfp.write("# arguments %s\n" % " ".join(arguments))
+            logfp.write("# SST2K version %s\n" % version)
+            logfp.write(
+                "# recorded by %s@%s on %s\n"
+                % (getpass.getuser(), socket.getfqdn(), time.ctime())
+            )
+            logfp.write("#\n")
+        rnd.seed(seed)
+        scanner = sstscanner()
+        for arg in arguments:
+            scanner.append(arg)
+        try:
+            iostart()
+            while True:  # Play a game
+                setwnd(fullscreen_window)
+                clrscr()
+                prelim()
+                setup()
+                if game.alldone:
+                    score()
+                    game.alldone = False
+                else:
+                    makemoves()
+                if replayfp:
+                    break
+                skip(1)
+                if game.options & OPTION_TTY:
+                    stars()
+                skip(1)
+                if game.tourn and game.alldone:
+                    proutn(_("Do you want your score recorded?"))
+                    if ja():
+                        scanner.chew()
+                        scanner.push("\n")
+                        freeze(False)
+                scanner.chew()
+                if game.options & OPTION_TTY:
+                    proutn(_("Do you want to play again? "))
+                    if not ja():
+                        break
+                else:
+                    break
+            skip(1)
+            prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
+        finally:
+            ioend()
+        raise SystemExit(0)
+    except KeyboardInterrupt:  # pragma: no cover
+        if logfp:
+            logfp.close()
+        print("")
+
+# End.
diff --git a/sst.py b/sst.py
deleted file mode 100755 (executable)
index b2067e9..0000000
--- a/sst.py
+++ /dev/null
@@ -1,6812 +0,0 @@
-#!/usr/bin/env python
-"""
-sst.py -- Super Star Trek 2K
-
-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.  Translation by Eric S. Raymond; original game by David Matuszek
-and Paul Reynolds, with modifications by Don Smith, Tom Almy,
-Stas Sergeev, and Eric S. Raymond.
-
-See the doc/HACKING file in the distribution for designers notes and advice
-on how to modify (and how not to modify!) this code.
-"""
-from __future__ import print_function, division
-# Runs under Python 2 an Python 3. Preserve this property!
-# SPDX-License-Identifier: BSD-2-clause
-
-import os, sys, math, curses, time, pickle, copy, gettext, getpass
-import getopt, socket, locale
-
-# This import only works on Unixes.  The intention is to enable
-# Ctrl-P, Ctrl-N, and friends in Cmd.
-try:
-    import readline
-except ImportError:
-    pass
-
-# Prevent lossage under Python 3
-try:
-    my_input = raw_input
-except NameError:
-    my_input = input
-
-version = "2.5"
-
-docpath        = (".", "doc/", "/usr/share/doc/sst/")
-
-def _(st):
-    return gettext.gettext(st)
-
-# Rolling our own LCG because Python changed its incompatibly in 3.2.
-# Thus, we need to have our own to be 2/3 polyglot, which will also
-# be helpful when we forwrard-port.
-
-class randomizer:
-    # LCG PRNG parameters tested against
-    # Knuth vol. 2. by the authors of ADVENT
-    LCG_A = 1093
-    LCG_C = 221587
-    LCG_M = 1048576
-
-    @staticmethod
-    def random():
-        old_x = game.lcg_x
-        game.lcg_x = (randomizer.LCG_A * game.lcg_x + randomizer.LCG_C) % randomizer.LCG_M
-        return old_x / randomizer.LCG_M
-
-    @staticmethod
-    def withprob(p):
-        v = randomizer.random()
-        #if logfp:
-        #    logfp.write("#withprob(%.2f) -> %s\n" % (p, v < p))
-        return v < p
-
-    @staticmethod
-    def integer(*args):
-        v = randomizer.random()
-        if len(args) == 1:
-            v = int(v * args[0])
-        else:
-            v = args[0] + int(v * (args[1] - args[0]))
-        #if logfp:
-        #    logfp.write("#integer%s -> %s\n" % (args, v))
-        return int(v)
-
-    @staticmethod
-    def real(*args):
-        v = randomizer.random()
-        if len(args) == 1:
-            v *= args[0]                 # from [0, args[0])
-        elif len(args) == 2:
-            v = args[0] + v*(args[1]-args[0])        # from [args[0], args[1])
-        #if logfp:
-        #    logfp.write("#real%s -> %f\n" % (args, v))
-        return v
-
-    @staticmethod
-    def seed(n):
-        #if logfp:
-        #    logfp.write("#seed(%d)\n" % n)
-        game.lcg_x = n % randomizer.LCG_M
-
-GALSIZE        = 8             # Galaxy size in quadrants
-NINHAB         = (GALSIZE * GALSIZE // 2)      # Number of inhabited worlds
-MAXUNINHAB     = 10            # Maximum uninhabited worlds
-QUADSIZE       = 10            # Quadrant size in sectors
-BASEMIN                = 2                             # Minimum starbases
-BASEMAX        = (GALSIZE * GALSIZE // 12)     # Maximum starbases
-MAXKLGAME      = 127           # Maximum Klingons per game
-MAXKLQUAD      = 9             # Maximum Klingons per quadrant
-FULLCREW       = 428           # Crew size. BSD Trek was 387, that's wrong
-FOREVER        = 1e30          # Time for the indefinite future
-MAXBURST       = 3             # Max # of torps you can launch in one turn
-MINCMDR        = 10            # Minimum number of Klingon commanders
-DOCKFAC                = 0.25          # Repair faster when docked
-PHASEFAC       = 2.0           # Unclear what this is, it was in the C version
-
-ALGERON                = 2311          # Date of the Treaty of Algeron
-
-
-DEFAULT      = -1
-BLACK        = 0
-BLUE         = 1
-GREEN        = 2
-CYAN         = 3
-RED          = 4
-MAGENTA      = 5
-BROWN        = 6
-LIGHTGRAY    = 7
-DARKGRAY     = 8
-LIGHTBLUE    = 9
-LIGHTGREEN   = 10
-LIGHTCYAN    = 11
-LIGHTRED     = 12
-LIGHTMAGENTA = 13
-YELLOW       = 14
-WHITE        = 15
-
-class TrekError(Exception):
-    pass
-
-class JumpOut(Exception):
-    pass
-
-class Coord:
-    def __init__(self, x=None, y=None):
-        self.i = x     # Row
-        self.j = y     # Column
-    def valid_quadrant(self):
-        return self.i >= 0 and self.i < GALSIZE and self.j >= 0 and self.j < GALSIZE
-    def valid_sector(self):
-        return self.i >= 0 and self.i < QUADSIZE and self.j >= 0 and self.j < QUADSIZE
-    def invalidate(self):
-        self.i = self.j = None
-    def __eq__(self, other):
-        return other is not None and self.i == other.i and self.j == other.j
-    def __ne__(self, other):
-        return other is None or self.i != other.i or self.j != other.j
-    def __add__(self, other):
-        return Coord(self.i+other.i, self.j+other.j)
-    def __sub__(self, other):
-        return Coord(self.i-other.i, self.j-other.j)
-    def __mul__(self, other):
-        return Coord(self.i*other, self.j*other)
-    def __rmul__(self, other):
-        return Coord(self.i*other, self.j*other)
-    def __div__(self, other):
-        return Coord(self.i/other, self.j/other)
-    def __truediv__(self, other):
-        return Coord(self.i/other, self.j/other)
-    def __floordiv__(self, other):
-        return Coord(self.i//other, self.j//other)
-    def __mod__(self, other):
-        return Coord(self.i % other, self.j % other)
-    def __rtruediv__(self, other):
-        return Coord(self.i/other, self.j/other)
-    def __rfloordiv__(self, other):
-        return Coord(self.i//other, self.j//other)
-    def roundtogrid(self):
-        return Coord(int(round(self.i)), int(round(self.j)))
-    def distance(self, other=None):
-        if not other:
-            other = Coord(0, 0)
-        return math.sqrt((self.i - other.i)**2 + (self.j - other.j)**2)
-    def bearing(self):
-        return 1.90985*math.atan2(self.j, self.i)
-    def sgn(self):
-        s = Coord()
-        if self.i == 0:
-            s.i = 0
-        elif self.i < 0:
-            s.i = -1
-        else:
-            s.i = 1
-        if self.j == 0:
-            s.j = 0
-        elif self.j < 0:
-            s.j = -1
-        else:
-            s.j = 1
-        return s
-    def quadrant(self):
-        #print "Location %s -> %s" % (self, (self / QUADSIZE).roundtogrid())
-        return self.roundtogrid() // QUADSIZE
-    def sector(self):
-        return self.roundtogrid() % QUADSIZE
-    def scatter(self):
-        s = Coord()
-        s.i = self.i + rnd.integer(-1, 2)
-        s.j = self.j + rnd.integer(-1, 2)
-        return s
-    def __str__(self):
-        if self.i is None or self.j is None:
-            return "Nowhere"
-        return "%s - %s" % (self.i+1, self.j+1)
-    __repr__ = __str__
-
-class Thingy(Coord):
-    "Do not anger the Space Thingy!"
-    def __init__(self):
-        Coord.__init__(self)
-        self.angered = False
-    def angry(self):
-        self.angered = True
-    def at(self, q):
-        return (q.i, q.j) == (self.i, self.j)
-
-class Planet:
-    def __init__(self):
-        self.name = None        # string-valued if inhabited
-        self.quadrant = Coord()        # quadrant located
-        self.pclass = None        # could be ""M", "N", "O", or "destroyed"
-        self.crystals = "absent"# could be "mined", "present", "absent"
-        self.known = "unknown"        # could be "unknown", "known", "shuttle_down"
-        self.inhabited = False        # is it inhabited?
-    def __str__(self):
-        return self.name
-
-class Quadrant:
-    def __init__(self):
-        self.stars = 0
-        self.planet = None
-        self.starbase = False
-        self.klingons = 0
-        self.romulans = 0
-        self.supernova = False
-        self.charted = False
-        self.status = "secure"        # Could be "secure", "distressed", "enslaved"
-    def __str__(self):
-        return "<Quadrant: %(klingons)d>" % self.__dict__
-    __repr__ = __str__
-
-class Page:
-    def __init__(self):
-        self.stars = None
-        self.starbase = False
-        self.klingons = None
-    def __repr__(self):
-        return "<%s,%s,%s>" % (self.klingons, self.starbase, self.stars)
-
-def fill2d(size, fillfun):
-    "Fill an empty list in 2D."
-    lst = []
-    for i in range(size):
-        lst.append([])
-        for j in range(size):
-            lst[i].append(fillfun(i, j))
-    return lst
-
-class Snapshot:
-    def __init__(self):
-        self.snap = False       # snapshot taken
-        self.crew = 0           # crew complement
-        self.nscrem = 0         # remaining super commanders
-        self.starkl = 0         # destroyed stars
-        self.basekl = 0         # destroyed bases
-        self.nromrem = 0        # Romulans remaining
-        self.nplankl = 0        # destroyed uninhabited planets
-        self.nworldkl = 0        # destroyed inhabited planets
-        self.planets = []        # Planet information
-        self.date = 0.0           # stardate
-        self.remres = 0         # remaining resources
-        self.remtime = 0        # remaining time
-        self.baseq = []         # Base quadrant coordinates
-        self.kcmdr = []         # Commander quadrant coordinates
-        self.kscmdr = Coord()        # Supercommander quadrant coordinates
-        # the galaxy
-        self.galaxy = fill2d(GALSIZE, lambda i_unused, j_unused: Quadrant())
-        # the starchart
-        self.chart = fill2d(GALSIZE, lambda i_unused, j_unused: Page())
-    def traverse(self):
-        for i in range(GALSIZE):
-            for j in range(GALSIZE):
-                yield (i, j, self.galaxy[i][j])
-
-class Event:
-    def __init__(self):
-        self.date = None        # A real number
-        self.quadrant = None        # A coord structure
-
-# game options
-OPTION_ALL        = 0xffffffff
-OPTION_TTY        = 0x00000001        # old interface
-OPTION_CURSES     = 0x00000002        # new interface
-OPTION_IOMODES    = 0x00000003        # cover both interfaces
-OPTION_PLANETS    = 0x00000004        # planets and mining
-OPTION_THOLIAN    = 0x00000008        # Tholians and their webs (UT 1979 version)
-OPTION_THINGY     = 0x00000010        # Space Thingy can shoot back (Stas, 2005)
-OPTION_PROBE      = 0x00000020        # deep-space probes (DECUS version, 1980)
-OPTION_SHOWME     = 0x00000040        # bracket Enterprise in chart
-OPTION_RAMMING    = 0x00000080        # enemies may ram Enterprise (Almy)
-OPTION_MVBADDY    = 0x00000100        # more enemies can move (Almy)
-OPTION_BLKHOLE    = 0x00000200        # black hole may timewarp you (Stas, 2005)
-OPTION_BASE       = 0x00000400        # bases have good shields (Stas, 2005)
-OPTION_WORLDS     = 0x00000800        # logic for inhabited worlds (ESR, 2006)
-OPTION_AUTOSCAN   = 0x00001000        # automatic LRSCAN before CHART (ESR, 2006)
-OPTION_CAPTURE    = 0x00002000        # Enable BSD-Trek capture (Almy, 2013).
-OPTION_CLOAK      = 0x80004000        # Enable BSD-Trek capture (Almy, 2013).
-OPTION_PLAIN      = 0x01000000        # user chose plain game
-OPTION_ALMY       = 0x02000000        # user chose Almy variant
-OPTION_COLOR      = 0x04000000        # enable color display (ESR, 2010)
-OPTION_DOTFILL    = 0x08000000        # fix dotfill glitch in chart (ESR, 2019)
-
-# Define devices
-DSRSENS         = 0
-DLRSENS         = 1
-DPHASER         = 2
-DPHOTON         = 3
-DLIFSUP         = 4
-DWARPEN         = 5
-DIMPULS         = 6
-DSHIELD         = 7
-DRADIO          = 8
-DSHUTTL         = 9
-DCOMPTR         = 10
-DNAVSYS         = 11
-DTRANSP         = 12
-DSHCTRL         = 13
-DDRAY           = 14
-DDSP            = 15
-DCLOAK          = 16
-NDEVICES        = 17        # Number of devices
-
-SKILL_NONE      = 0
-SKILL_NOVICE    = 1
-SKILL_FAIR      = 2
-SKILL_GOOD      = 3
-SKILL_EXPERT    = 4
-SKILL_EMERITUS  = 5
-
-def damaged(dev):
-    return (game.damage[dev] != 0.0)
-def communicating():
-    return not damaged(DRADIO) or game.condition=="docked"
-
-# Define future events
-FSPY    = 0        # Spy event happens always (no future[] entry)
-                   # can cause SC to tractor beam Enterprise
-FSNOVA  = 1        # Supernova
-FTBEAM  = 2        # Commander tractor beams Enterprise
-FSNAP   = 3        # Snapshot for time warp
-FBATTAK = 4        # Commander attacks base
-FCDBAS  = 5        # Commander destroys base
-FSCMOVE = 6        # Supercommander moves (might attack base)
-FSCDBAS = 7        # Supercommander destroys base
-FDSPROB = 8        # Move deep space probe
-FDISTR  = 9        # Emit distress call from an inhabited world
-FENSLV  = 10       # Inhabited word is enslaved
-FREPRO  = 11       # Klingons build a ship in an enslaved system
-NEVENTS = 12
-
-# Abstract out the event handling -- underlying data structures will change
-# when we implement stateful events
-def findevent(evtype):
-    return game.future[evtype]
-
-class Enemy:
-    def __init__(self, etype=None, loc=None, power=None):
-        self.type = etype
-        self.location = Coord()
-        self.kdist = None
-        self.kavgd = None
-        if loc:
-            self.move(loc)
-        self.power = power        # enemy energy level
-        game.enemies.append(self)
-    def move(self, loc):
-        motion = (loc != self.location)
-        if self.location.i is not None and self.location.j is not None:
-            if motion:
-                if self.type == 'T':
-                    game.quad[self.location.i][self.location.j] = '#'
-                else:
-                    game.quad[self.location.i][self.location.j] = '.'
-        if loc:
-            self.location = copy.copy(loc)
-            game.quad[self.location.i][self.location.j] = self.type
-            self.kdist = self.kavgd = (game.sector - loc).distance()
-        else:
-            self.location = Coord()
-            self.kdist = self.kavgd = None
-            # Guard prevents failure on Tholian or thingy
-            if self in game.enemies:
-                game.enemies.remove(self)
-        return motion
-    def __repr__(self):
-        return "<%s,%s.%f>" % (self.type, self.location, self.power)        # For debugging
-
-class Gamestate:
-    def __init__(self):
-        self.options = None        # Game options
-        self.state = Snapshot()        # A snapshot structure
-        self.snapsht = Snapshot()        # Last snapshot taken for time-travel purposes
-        self.quad = None        # contents of our quadrant
-        self.damage = [0.0] * NDEVICES        # damage encountered
-        self.future = []        # future events
-        i = NEVENTS
-        while i > 0:
-            i -= 1
-            self.future.append(Event())
-        self.passwd  = None        # Self Destruct password
-        self.enemies = []
-        self.quadrant = None        # where we are in the large
-        self.sector = None        # where we are in the small
-        self.tholian = None        # Tholian enemy object
-        self.base = None        # position of base in current quadrant
-        self.battle = None        # base coordinates being attacked
-        self.plnet = None        # location of planet in quadrant
-        self.gamewon = False        # Finished!
-        self.ididit = False        # action taken -- allows enemy to attack
-        self.alive = False        # we are alive (not killed)
-        self.justin = False        # just entered quadrant
-        self.shldup = False        # shields are up
-        self.shldchg = False        # shield is changing (affects efficiency)
-        self.iscate = False        # super commander is here
-        self.ientesc = False        # attempted escape from supercommander
-        self.resting = False        # rest time
-        self.icraft = False        # Kirk in Galileo
-        self.landed = False        # party on planet (true), on ship (false)
-        self.alldone = False        # game is now finished
-        self.neutz = False        # Romulan Neutral Zone
-        self.isarmed = False        # probe is armed
-        self.inorbit = False        # orbiting a planet
-        self.imine = False        # mining
-        self.icrystl = False        # dilithium crystals aboard
-        self.iseenit = False        # seen base attack report
-        self.thawed = False        # thawed game
-        self.condition = None        # "green", "yellow", "red", "docked", "dead"
-        self.iscraft = None        # "onship", "offship", "removed"
-        self.skill = SKILL_NONE        # Player skill level
-        self.inkling = 0        # initial number of klingons
-        self.inbase = 0                # initial number of bases
-        self.incom = 0                # initial number of commanders
-        self.inscom = 0                # initial number of commanders
-        self.inrom = 0                # initial number of commanders
-        self.instar = 0                # initial stars
-        self.intorps = 0        # initial/max torpedoes
-        self.torps = 0                # number of torpedoes
-        self.ship = 0                # ship type -- 'E' is Enterprise
-        self.abandoned = 0        # count of crew abandoned in space
-        self.length = 0                # length of game
-        self.klhere = 0                # klingons here
-        self.casual = 0                # causalties
-        self.nhelp = 0                # calls for help
-        self.nkinks = 0                # count of energy-barrier crossings
-        self.iplnet = None        # planet # in quadrant
-        self.inplan = 0                # initial planets
-        self.irhere = 0                # Romulans in quadrant
-        self.isatb = 0                # =2 if super commander is attacking base
-        self.tourn = None        # tournament number
-        self.nprobes = 0        # number of probes available
-        self.inresor = 0.0        # initial resources
-        self.intime = 0.0        # initial time
-        self.inenrg = 0.0        # initial/max energy
-        self.inshld = 0.0        # initial/max shield
-        self.inlsr = 0.0        # initial life support resources
-        self.indate = 0.0        # initial date
-        self.energy = 0.0        # energy level
-        self.shield = 0.0        # shield level
-        self.warpfac = 0.0        # warp speed
-        self.lsupres = 0.0        # life support reserves
-        self.optime = 0.0        # time taken by current operation
-        self.damfac = 0.0        # damage factor
-        self.lastchart = 0.0        # time star chart was last updated
-        self.cryprob = 0.0        # probability that crystal will work
-        self.probe = None        # object holding probe course info
-        self.height = 0.0        # height of orbit around planet
-        self.score = 0.0        # overall score
-        self.perdate = 0.0        # rate of kills
-        self.idebug = False        # Debugging instrumentation enabled?
-        self.cdebug = False        # Debugging instrumentation for curses enabled?
-        self.statekscmdr = None # No SuperCommander coordinates yet.
-        self.brigcapacity = 400     # Enterprise brig capacity
-        self.brigfree = 400       # How many klingons can we put in the brig?
-        self.kcaptured = 0      # Total Klingons captured, for scoring.
-        self.iscloaked = False  # Cloaking device on?
-        self.ncviol = 0         # Algreon treaty violations
-        self.isviolreported = False # We have been warned
-        self.lcg_x = 0         # LCG generator value
-    def remkl(self):
-        return sum([q.klingons for (_i, _j, q) in list(self.state.traverse())])
-    def recompute(self):
-        # Stas thinks this should be (C expression):
-        # game.remkl() + len(game.state.kcmdr) > 0 ?
-        #        game.state.remres/(game.remkl() + 4*len(game.state.kcmdr)) : 99
-        # He says the existing expression is prone to divide-by-zero errors
-        # after killing the last klingon when score is shown -- perhaps also
-        # if the only remaining klingon is SCOM.
-        self.state.remtime = self.state.remres/(self.remkl() + 4*len(self.state.kcmdr))
-    def unwon(self):
-        "Are there Klingons remaining?"
-        return self.remkl()
-
-FWON = 0
-FDEPLETE = 1
-FLIFESUP = 2
-FNRG = 3
-FBATTLE = 4
-FNEG3 = 5
-FNOVA = 6
-FSNOVAED = 7
-FABANDN = 8
-FDILITHIUM = 9
-FMATERIALIZE = 10
-FPHASER = 11
-FLOST = 12
-FMINING = 13
-FDPLANET = 14
-FPNOVA = 15
-FSSC = 16
-FSTRACTOR = 17
-FDRAY = 18
-FTRIBBLE = 19
-FHOLE = 20
-FCREW = 21
-FCLOAK = 22
-
-# Code from ai.c begins here
-
-def welcoming(iq):
-    "Would this quadrant welcome another Klingon?"
-    return iq.valid_quadrant() and \
-        not game.state.galaxy[iq.i][iq.j].supernova and \
-        game.state.galaxy[iq.i][iq.j].klingons < MAXKLQUAD
-
-def tryexit(enemy, look, irun):
-    "A bad guy attempts to bug out."
-    iq = Coord()
-    iq.i = game.quadrant.i+(look.i+(QUADSIZE-1))//QUADSIZE - 1
-    iq.j = game.quadrant.j+(look.j+(QUADSIZE-1))//QUADSIZE - 1
-    if not welcoming(iq):
-        return False
-    if enemy.type == 'R':
-        return False # Romulans cannot escape!
-    if not irun:
-        # avoid intruding on another commander's territory
-        if enemy.type == 'C':
-            if iq in game.state.kcmdr:
-                return []
-            # refuse to leave if currently attacking starbase
-            if game.battle == game.quadrant:
-                return []
-        # don't leave if over 1000 units of energy
-        if enemy.power > 1000.0:
-            return []
-    oldloc = copy.copy(enemy.location)
-    # handle local matters related to escape
-    enemy.move(None)
-    game.klhere -= 1
-    if game.condition != "docked":
-        newcnd()
-    # Handle global matters related to escape
-    game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
-    game.state.galaxy[iq.i][iq.j].klingons += 1
-    if enemy.type == 'S':
-        game.iscate = False
-        game.ientesc = False
-        game.isatb = 0
-        schedule(FSCMOVE, 0.2777)
-        unschedule(FSCDBAS)
-        game.state.kscmdr = iq
-    else:
-        for cmdr in game.state.kcmdr:
-            if cmdr == game.quadrant:
-                game.state.kcmdr.append(iq)
-                break
-    # report move out of quadrant.
-    return [(True, enemy, oldloc, iq)]
-
-# The bad-guy movement algorithm:
-#
-# 1. Enterprise has "force" based on condition of phaser and photon torpedoes.
-# If both are operating full strength, force is 1000. If both are damaged,
-# force is -1000. Having shields down subtracts an additional 1000.
-#
-# 2. Enemy has forces equal to the energy of the attacker plus
-# 100*(K+R) + 500*(C+S) - 400 for novice through good levels OR
-# 346*K + 400*R + 500*(C+S) - 400 for expert and emeritus.
-#
-# Attacker Initial energy levels (nominal):
-# Klingon   Romulan   Commander   Super-Commander
-# Novice    400        700        1200
-# Fair      425        750        1250
-# Good      450        800        1300        1750
-# Expert    475        850        1350        1875
-# Emeritus  500        900        1400        2000
-# VARIANCE   75        200         200         200
-#
-# Enemy vessels only move prior to their attack. In Novice - Good games
-# only commanders move. In Expert games, all enemy vessels move if there
-# is a commander present. In Emeritus games all enemy vessels move.
-#
-# 3. If Enterprise is not docked, an aggressive action is taken if enemy
-# forces are 1000 greater than Enterprise.
-#
-# Agressive action on average cuts the distance between the ship and
-# the enemy to 1/4 the original.
-#
-# 4.  At lower energy advantage, movement units are proportional to the
-# advantage with a 650 advantage being to hold ground, 800 to move forward
-# 1, 950 for two, 150 for back 4, etc. Variance of 100.
-#
-# If docked, is reduced by roughly 1.75*game.skill, generally forcing a
-# retreat, especially at high skill levels.
-#
-# 5.  Motion is limited to skill level, except for SC hi-tailing it out.
-
-def movebaddy(enemy):
-    "Tactical movement for the bad guys."
-    goto = Coord()
-    look = Coord()
-    irun = False
-    # This should probably be just (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
-    if game.skill >= SKILL_EXPERT:
-        nbaddys = int(((game.quadrant in game.state.kcmdr)*2 + (game.state.kscmdr==game.quadrant)*2+game.klhere*1.23+game.irhere*1.5)/2.0)
-    else:
-        nbaddys = (game.quadrant in game.state.kcmdr) + (game.state.kscmdr==game.quadrant)
-    old_dist = enemy.kdist
-    mdist = int(old_dist + 0.5) # Nearest integer distance
-    # If SC, check with spy to see if should hi-tail it
-    if enemy.type == 'S' and \
-        (enemy.power <= 500.0 or (game.condition=="docked" and not damaged(DPHOTON))):
-        irun = True
-        motion = -QUADSIZE
-    else:
-        # decide whether to advance, retreat, or hold position
-        forces = enemy.power+100.0*len(game.enemies)+400*(nbaddys-1)
-        if not game.shldup:
-            forces += 1000 # Good for enemy if shield is down!
-        if not damaged(DPHASER) or not damaged(DPHOTON):
-            if damaged(DPHASER): # phasers damaged
-                forces += 300.0
-            else:
-                forces -= 0.2*(game.energy - 2500.0)
-            if damaged(DPHOTON): # photon torpedoes damaged
-                forces += 300.0
-            else:
-                forces -= 50.0*game.torps
-        else:
-            # phasers and photon tubes both out!
-            forces += 1000.0
-        motion = 0
-        if forces <= 1000.0 and game.condition != "docked": # Typical situation
-            motion = ((forces + rnd.real(200))/150.0) - 5.0
-        else:
-            if forces > 1000.0: # Very strong -- move in for kill
-                motion = (1.0 - rnd.real())**2 * old_dist + 1.0
-            if game.condition == "docked" and (game.options & OPTION_BASE): # protected by base -- back off !
-                motion -= game.skill*(2.0-rnd.real()**2)
-        if game.idebug:
-            proutn("=== MOTION = %d, FORCES = %1.2f, " % (motion, forces))
-        # don't move if no motion
-        if motion == 0:
-            return []
-        # Limit motion according to skill
-        if abs(motion) > game.skill:
-            if motion < 0:
-                motion = -game.skill
-            else:
-                motion = game.skill
-    # calculate preferred number of steps
-    nsteps = abs(int(motion))
-    if motion > 0 and nsteps > mdist:
-        nsteps = mdist # don't overshoot
-    if nsteps > QUADSIZE:
-        nsteps = QUADSIZE # This shouldn't be necessary
-    if nsteps < 1:
-        nsteps = 1 # This shouldn't be necessary
-    if game.idebug:
-        proutn("NSTEPS = %d:" % nsteps)
-    # Compute preferred values of delta X and Y
-    m = game.sector - enemy.location
-    if 2.0 * abs(m.i) < abs(m.j):
-        m.i = 0
-    if 2.0 * abs(m.j) < abs(game.sector.i-enemy.location.i):
-        m.j = 0
-    m = (motion * m).sgn()
-    goto = enemy.location
-    # main move loop
-    for ll in range(nsteps):
-        if game.idebug:
-            proutn(" %d" % (ll+1))
-        # Check if preferred position available
-        look = goto + m
-        if m.i < 0:
-            krawli = 1
-        else:
-            krawli = -1
-        if m.j < 0:
-            krawlj = 1
-        else:
-            krawlj = -1
-        success = False
-        attempts = 0 # Settle mysterious hang problem
-        while attempts < 20 and not success:
-            attempts += 1
-            if look.i < 0 or look.i >= QUADSIZE:
-                if motion < 0:
-                    return tryexit(enemy, look, irun)
-                if krawli == m.i or m.j == 0:
-                    break
-                look.i = goto.i + krawli
-                krawli = -krawli
-            elif look.j < 0 or look.j >= QUADSIZE:
-                if motion < 0:
-                    return tryexit(enemy, look, irun)
-                if krawlj == m.j or m.i == 0:
-                    break
-                look.j = goto.j + krawlj
-                krawlj = -krawlj
-            elif (game.options & OPTION_RAMMING) and game.quad[look.i][look.j] != '.':
-                # See if enemy should ram ship
-                if game.quad[look.i][look.j] == game.ship and \
-                    (enemy.type == 'C' or enemy.type == 'S'):
-                    collision(rammed=True, enemy=enemy)
-                    return []
-                if krawli != m.i and m.j != 0:
-                    look.i = goto.i + krawli
-                    krawli = -krawli
-                elif krawlj != m.j and m.i != 0:
-                    look.j = goto.j + krawlj
-                    krawlj = -krawlj
-                else:
-                    break # we have failed
-            else:
-                success = True
-        if success:
-            goto = look
-            if game.idebug:
-                proutn(repr(goto))
-        else:
-            break # done early
-    if game.idebug:
-        skip(1)
-    # Enemy moved, but is still in sector
-    return [(False, enemy, old_dist, goto)]
-
-def moveklings():
-    "Sequence Klingon tactical movement."
-    if game.idebug:
-        prout("== MOVCOM")
-    # Figure out which Klingon is the commander (or Supercommander)
-    # and do move
-    tacmoves = []
-    if game.quadrant in game.state.kcmdr:
-        for enemy in game.enemies:
-            if enemy.type == 'C':
-                tacmoves += movebaddy(enemy)
-    if game.state.kscmdr == game.quadrant:
-        for enemy in game.enemies:
-            if enemy.type == 'S':
-                tacmoves += movebaddy(enemy)
-                break
-    # If skill level is high, move other Klingons and Romulans too!
-    # Move these last so they can base their actions on what the
-    # commander(s) do.
-    if game.skill >= SKILL_EXPERT and (game.options & OPTION_MVBADDY):
-        for enemy in game.enemies:
-            if enemy.type in ('K', 'R'):
-                tacmoves += movebaddy(enemy)
-    return tacmoves
-
-def movescom(iq, avoid):
-    "Supercommander movement helper."
-    # Avoid quadrants with bases if we want to avoid Enterprise
-    if not welcoming(iq) or (avoid and iq in game.state.baseq):
-        return False
-    if game.justin and not game.iscate:
-        return False
-    # do the move
-    game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons -= 1
-    game.state.kscmdr = iq
-    game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].klingons += 1
-    if game.state.kscmdr == game.quadrant:
-        # SC has scooted, remove him from current quadrant
-        game.iscate = False
-        game.isatb = 0
-        game.ientesc = False
-        unschedule(FSCDBAS)
-        for enemy in game.enemies:
-            if enemy.type == 'S':
-                enemy.move(None)
-        game.klhere -= 1
-        if game.condition != "docked":
-            newcnd()
-        sortenemies()
-    # check for a helpful planet
-    for i in range(game.inplan):
-        if game.state.planets[i].quadrant == game.state.kscmdr and \
-            game.state.planets[i].crystals == "present":
-            # destroy the planet
-            game.state.planets[i].pclass = "destroyed"
-            game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].planet = None
-            if communicating():
-                announce()
-                prout(_("Lt. Uhura-  \"Captain, Starfleet Intelligence reports"))
-                prout(_("   a planet in Quadrant %s has been destroyed") % game.state.kscmdr)
-                prout(_("   by the Super-commander.\""))
-            break
-    return True # looks good!
-
-def supercommander():
-    "Move the Super Commander."
-    iq = Coord()
-    sc = Coord()
-    ibq = Coord()
-    idelta = Coord()
-    basetbl = []
-    if game.idebug:
-        prout("== SUPERCOMMANDER")
-    # Decide on being active or passive
-    avoid = ((game.incom - len(game.state.kcmdr) + game.inkling - game.remkl())/(game.state.date+0.01-game.indate) < 0.1*game.skill*(game.skill+1.0) or \
-            (game.state.date-game.indate) < 3.0)
-    if not game.iscate and avoid:
-        # compute move away from Enterprise
-        idelta = game.state.kscmdr-game.quadrant
-        if idelta.distance() > 2.0:
-            # circulate in space
-            idelta.i = game.state.kscmdr.j-game.quadrant.j
-            idelta.j = game.quadrant.i-game.state.kscmdr.i
-    else:
-        # compute distances to starbases
-        if not game.state.baseq:
-            # nothing left to do
-            unschedule(FSCMOVE)
-            return
-        sc = game.state.kscmdr
-        for (i, base) in enumerate(game.state.baseq):
-            basetbl.append((i, (base - sc).distance()))
-        if len(game.state.baseq) > 1:
-            basetbl.sort(key=lambda x: x[1])
-        # look for nearest base without a commander, no Enterprise, and
-        # without too many Klingons, and not already under attack.
-        ifindit = iwhichb = 0
-        for (i2, base) in enumerate(game.state.baseq):
-            i = basetbl[i2][0]        # bug in original had it not finding nearest
-            if base == game.quadrant or base == game.battle or not welcoming(base):
-                continue
-            # if there is a commander, and no other base is appropriate,
-            # we will take the one with the commander
-            for cmdr in game.state.kcmdr:
-                if base == cmdr and ifindit != 2:
-                    ifindit = 2
-                    iwhichb = i
-                    break
-            else:        # no commander -- use this one
-                ifindit = 1
-                iwhichb = i
-                break
-        if ifindit == 0:
-            return # Nothing suitable -- wait until next time
-        ibq = game.state.baseq[iwhichb]
-        # decide how to move toward base
-        idelta = ibq - game.state.kscmdr
-    # Maximum movement is 1 quadrant in either or both axes
-    idelta = idelta.sgn()
-    # try moving in both x and y directions
-    # there was what looked like a bug in the Almy C code here,
-    # but it might be this translation is just wrong.
-    iq = game.state.kscmdr + idelta
-    if not movescom(iq, avoid):
-        # failed -- try some other maneuvers
-        if idelta.i == 0 or idelta.j == 0:
-            # attempt angle move
-            if idelta.i != 0:
-                iq.j = game.state.kscmdr.j + 1
-                if not movescom(iq, avoid):
-                    iq.j = game.state.kscmdr.j - 1
-                    movescom(iq, avoid)
-            elif idelta.j != 0:
-                iq.i = game.state.kscmdr.i + 1
-                if not movescom(iq, avoid):
-                    iq.i = game.state.kscmdr.i - 1
-                    movescom(iq, avoid)
-        else:
-            # try moving just in x or y
-            iq.j = game.state.kscmdr.j
-            if not movescom(iq, avoid):
-                iq.j = game.state.kscmdr.j + idelta.j
-                iq.i = game.state.kscmdr.i
-                movescom(iq, avoid)
-    # check for a base
-    if len(game.state.baseq) == 0:
-        unschedule(FSCMOVE)
-    else:
-        for ibq in game.state.baseq:
-            if ibq == game.state.kscmdr and game.state.kscmdr == game.battle:
-                # attack the base
-                if avoid:
-                    return # no, don't attack base!
-                game.iseenit = False
-                game.isatb = 1
-                schedule(FSCDBAS, rnd.real(1.0, 3.0))
-                if is_scheduled(FCDBAS):
-                    postpone(FSCDBAS, scheduled(FCDBAS)-game.state.date)
-                if not communicating():
-                    return # no warning
-                game.iseenit = True
-                announce()
-                prout(_("Lt. Uhura-  \"Captain, the starbase in Quadrant %s") \
-                      % game.state.kscmdr)
-                prout(_("   reports that it is under attack from the Klingon Super-commander."))
-                prout(_("   It can survive until stardate %d.\"") \
-                       % int(scheduled(FSCDBAS)))
-                if not game.resting:
-                    return
-                prout(_("Mr. Spock-  \"Captain, shall we cancel the rest period?\""))
-                if not ja():
-                    return
-                game.resting = False
-                game.optime = 0.0 # actually finished
-                return
-    # Check for intelligence report
-    if not game.idebug and \
-        (rnd.withprob(0.8) or \
-         (not communicating()) or \
-         not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].charted):
-        return
-    announce()
-    prout(_("Lt. Uhura-  \"Captain, Starfleet Intelligence reports"))
-    prout(_("   the Super-commander is in Quadrant %s.") % game.state.kscmdr)
-    return
-
-def movetholian():
-    "Move the Tholian."
-    if not game.tholian or game.justin:
-        return
-    tid = Coord()
-    if game.tholian.location.i == 0 and game.tholian.location.j == 0:
-        tid.i = 0
-        tid.j = QUADSIZE-1
-    elif game.tholian.location.i == 0 and game.tholian.location.j == QUADSIZE-1:
-        tid.i = QUADSIZE-1
-        tid.j = QUADSIZE-1
-    elif game.tholian.location.i == QUADSIZE-1 and game.tholian.location.j == QUADSIZE-1:
-        tid.i = QUADSIZE-1
-        tid.j = 0
-    elif game.tholian.location.i == QUADSIZE-1 and game.tholian.location.j == 0:
-        tid.i = 0
-        tid.j = 0
-    else:
-        # something is wrong!
-        game.tholian.move(None)
-        prout("***Internal error: Tholian in a bad spot.")
-        return
-    # do nothing if we are blocked
-    if game.quad[tid.i][tid.j] not in ('.', '#'):
-        return
-    here = copy.copy(game.tholian.location)
-    delta = (tid - game.tholian.location).sgn()
-    # move in x axis
-    while here.i != tid.i:
-        here.i += delta.i
-        if game.quad[here.i][here.j] == '.':
-            game.tholian.move(here)
-    # move in y axis
-    while here.j != tid.j:
-        here.j += delta.j
-        if game.quad[here.i][here.j] == '.':
-            game.tholian.move(here)
-    # check to see if all holes plugged
-    for i in range(QUADSIZE):
-        if game.quad[0][i] != '#' and game.quad[0][i] != 'T':
-            return
-        if game.quad[QUADSIZE-1][i] != '#' and game.quad[QUADSIZE-1][i] != 'T':
-            return
-        if game.quad[i][0] != '#' and game.quad[i][0] != 'T':
-            return
-        if game.quad[i][QUADSIZE-1] != '#' and game.quad[i][QUADSIZE-1] != 'T':
-            return
-    # All plugged up -- Tholian splits
-    game.quad[game.tholian.location.i][game.tholian.location.j] = '#'
-    dropin(' ')
-    prout(crmena(True, 'T', "sector", game.tholian) + _(" completes web."))
-    game.tholian.move(None)
-    return
-
-# Code from battle.c begins here
-
-def cloak():
-    "Change cloaking-device status."
-    if game.ship == 'F':
-        prout(_("Ye Faerie Queene hath no cloaking device."))
-        return
-
-    key = scanner.nexttok()
-
-    if key == "IHREAL":
-        huh()
-        return
-
-    action = None
-    if key == "IHALPHA":
-        if scanner.sees("on"):
-            if game.iscloaked:
-                prout(_("The cloaking device has already been switched on."))
-                return
-            action = "CLON"
-        elif scanner.sees("off"):
-            if not game.iscloaked:
-                prout(_("The cloaking device has already been switched off."))
-                return
-            action = "CLOFF"
-        else:
-            huh()
-            return
-    else:
-        if not game.iscloaked:
-            proutn(_("Switch cloaking device on? "))
-            if not ja():
-                return
-            action = "CLON"
-        else:
-            proutn(_("Switch cloaking device off? "))
-            if not ja():
-                return
-            action = "CLOFF"
-    if action is None:
-        return
-
-    if action == "CLOFF":
-        if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
-            prout(_("Spock- \"Captain, the Treaty of Algeron is in effect.\n   Are you sure this is wise?\""))
-            if not ja():
-                return
-        prout("Engineer Scott- \"Aye, Sir.\"")
-        game.iscloaked = False
-        if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
-            prout(_("The Romulan ship discovers you are breaking the Treaty of Algeron!"))
-            game.ncviol += 1
-            game.isviolreported = True
-
-            #if (neutz and game.state.date >= ALGERON) finish(FCLOAK);
-            return
-
-    if action == "CLON":
-        if damaged(DCLOAK):
-            prout(_("Engineer Scott- \"The cloaking device is damaged, Sir.\""))
-            return
-
-        if game.condition == "docked":
-            prout(_("You cannot cloak while docked."))
-
-        if game.state.date >= ALGERON and not game.isviolreported:
-            prout(_("Spock- \"Captain, using the cloaking device is a violation"))
-            prout(_("  of the Treaty of Algeron. Considering the alternatives,"))
-            proutn(_("  are you sure this is wise? "))
-            if not ja():
-                return
-        prout(_("Engineer Scott- \"Cloaking device has engaging, Sir...\""))
-        attack(True)
-        prout(_("Engineer Scott- \"Cloaking device has engaged, Sir.\""))
-        game.iscloaked = True
-
-        if game.irhere and game.state.date >= ALGERON and not game.isviolreported:
-            prout(_("The Romulan ship discovers you are breaking the Treaty of Algeron!"))
-            game.ncviol += 1
-            game.isviolreported = True
-
-def doshield(shraise):
-    "Change shield status."
-    action = "NONE"
-    game.ididit = False
-    if shraise:
-        action = "SHUP"
-    else:
-        key = scanner.nexttok()
-        if key == "IHALPHA":
-            if scanner.sees("transfer"):
-                action = "NRG"
-            else:
-                if damaged(DSHIELD):
-                    prout(_("Shields damaged and down."))
-                    return
-                if scanner.sees("up"):
-                    action = "SHUP"
-                elif scanner.sees("down"):
-                    action = "SHDN"
-        if action == "NONE":
-            proutn(_("Do you wish to change shield energy? "))
-            if ja():
-                action = "NRG"
-            elif damaged(DSHIELD):
-                prout(_("Shields damaged and down."))
-                return
-            elif game.shldup:
-                proutn(_("Shields are up. Do you want them down? "))
-                if ja():
-                    action = "SHDN"
-                else:
-                    scanner.chew()
-                    return
-            else:
-                proutn(_("Shields are down. Do you want them up? "))
-                if ja():
-                    action = "SHUP"
-                else:
-                    scanner.chew()
-                    return
-    if action == "SHUP": # raise shields
-        if game.shldup:
-            prout(_("Shields already up."))
-            return
-        game.shldup = True
-        game.shldchg = True
-        if game.condition != "docked":
-            game.energy -= 50.0
-        prout(_("Shields raised."))
-        if game.energy <= 0:
-            skip(1)
-            prout(_("Shields raising uses up last of energy."))
-            finish(FNRG)
-            return
-        game.ididit = True
-        return
-    elif action == "SHDN":
-        if not game.shldup:
-            prout(_("Shields already down."))
-            return
-        game.shldup = False
-        game.shldchg = True
-        prout(_("Shields lowered."))
-        game.ididit = True
-        return
-    elif action == "NRG":
-        while scanner.nexttok() != "IHREAL":
-            scanner.chew()
-            proutn(_("Energy to transfer to shields- "))
-        nrg = scanner.real
-        scanner.chew()
-        if nrg == 0:
-            return
-        if nrg > game.energy:
-            prout(_("Insufficient ship energy."))
-            return
-        game.ididit = True
-        if game.shield+nrg >= game.inshld:
-            prout(_("Shield energy maximized."))
-            if game.shield+nrg > game.inshld:
-                prout(_("Excess energy requested returned to ship energy"))
-            game.energy -= game.inshld-game.shield
-            game.shield = game.inshld
-            return
-        if nrg < 0.0 and game.energy-nrg > game.inenrg:
-            # Prevent shield drain loophole
-            skip(1)
-            prout(_("Engineering to bridge--"))
-            prout(_("  Scott here. Power circuit problem, Captain."))
-            prout(_("  I can't drain the shields."))
-            game.ididit = False
-            return
-        if game.shield+nrg < 0:
-            prout(_("All shield energy transferred to ship."))
-            game.energy += game.shield
-            game.shield = 0.0
-            return
-        proutn(_("Scotty- \""))
-        if nrg > 0:
-            prout(_("Transferring energy to shields.\""))
-        else:
-            prout(_("Draining energy from shields.\""))
-        game.shield += nrg
-        game.energy -= nrg
-        return
-
-def randdevice():
-    "Choose a device to damage, at random."
-    weights = (
-        105,       # DSRSENS: short range scanners         10.5%
-        105,       # DLRSENS: long range scanners          10.5%
-        120,       # DPHASER: phasers                      12.0%
-        120,       # DPHOTON: photon torpedoes             12.0%
-        25,        # DLIFSUP: life support                  2.5%
-        65,        # DWARPEN: warp drive                    6.5%
-        70,        # DIMPULS: impulse engines               6.5%
-        135,       # DSHIELD: deflector shields            13.5%
-        30,        # DRADIO:  subspace radio                3.0%
-        45,        # DSHUTTL: shuttle                       4.5%
-        15,        # DCOMPTR: computer                      1.5%
-        20,        # NAVCOMP: navigation system             2.0%
-        75,        # DTRANSP: transporter                   7.5%
-        20,        # DSHCTRL: high-speed shield controller  2.0%
-        10,        # DDRAY: death ray                       1.0%
-        30,        # DDSP: deep-space probes                3.0%
-        10,        # DCLOAK: the cloaking device            1.0
-    )
-    assert(sum(weights) == 1000)
-    idx = rnd.integer(1000)
-    wsum = 0
-    for (i, w) in enumerate(weights):
-        wsum += w
-        if idx < wsum:
-            return i
-    return None        # we should never get here
-
-def collision(rammed, enemy):
-    "Collision handling for rammong events."
-    prouts(_("***RED ALERT!  RED ALERT!"))
-    skip(1)
-    prout(_("***COLLISION IMMINENT."))
-    skip(2)
-    proutn("***")
-    proutn(crmshp())
-    hardness = {'R':1.5, 'C':2.0, 'S':2.5, 'T':0.5, '?':4.0}.get(enemy.type, 1.0)
-    if rammed:
-        proutn(_(" rammed by "))
-    else:
-        proutn(_(" rams "))
-    proutn(crmena(False, enemy.type, "sector", enemy.location))
-    if rammed:
-        proutn(_(" (original position)"))
-    skip(1)
-    deadkl(enemy.location, enemy.type, game.sector)
-    proutn("***" + crmshp() + " heavily damaged.")
-    icas = rnd.integer(10, 30)
-    prout(_("***Sickbay reports %d casualties") % icas)
-    game.casual += icas
-    game.state.crew -= icas
-    # In the pre-SST2K version, all devices got equiprobably damaged,
-    # which was silly.  Instead, pick up to half the devices at
-    # random according to our weighting table,
-    ncrits = rnd.integer(NDEVICES//2)
-    while ncrits > 0:
-        ncrits -= 1
-        dev = randdevice()
-        if game.damage[dev] < 0:
-            continue
-        extradm = (10.0*hardness*rnd.real()+1.0)*game.damfac
-        # Damage for at least time of travel!
-        game.damage[dev] += game.optime + extradm
-    game.shldup = False
-    prout(_("***Shields are down."))
-    if game.unwon():
-        announce()
-        damagereport()
-    else:
-        finish(FWON)
-    return
-
-def torpedo(origin, bearing, dispersion, number, nburst):
-    "Let a photon torpedo fly"
-    if not damaged(DSRSENS) or game.condition == "docked":
-        setwnd(srscan_window)
-    else:
-        setwnd(message_window)
-    ac = bearing + 0.25*dispersion        # dispersion is a random variable
-    bullseye = (15.0 - bearing)*0.5235988
-    track = course(bearing=ac, distance=QUADSIZE, origin=cartesian(origin))
-    bumpto = Coord(0, 0)
-    # Loop to move a single torpedo
-    setwnd(message_window)
-    for step in range(1, QUADSIZE*2):
-        if not track.nexttok():
-            break
-        w = track.sector()
-        if not w.valid_sector():
-            break
-        iquad = game.quad[w.i][w.j]
-        tracktorpedo(w, step, number, nburst, iquad)
-        if iquad == '.':
-            continue
-        # hit something
-        setwnd(message_window)
-        if not damaged(DSRSENS) or game.condition == "docked":
-            skip(1)        # start new line after text track
-        if iquad in ('E', 'F'): # Hit our ship
-            skip(1)
-            prout(_("Torpedo hits %s.") % crmshp())
-            hit = 700.0 + rnd.real(100) - \
-                1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-track.angle))
-            newcnd() # we're blown out of dock
-            if game.landed or game.condition == "docked":
-                return hit # Cheat if on a planet
-            # In the C/FORTRAN version, dispersion was 2.5 radians, which
-            # is 143 degrees, which is almost exactly 4.8 clockface units
-            displacement = course(track.bearing+rnd.real(-2.4, 2.4), distance=2**0.5)
-            displacement.nexttok()
-            bumpto = displacement.sector()
-            if not bumpto.valid_sector():
-                return hit
-            if game.quad[bumpto.i][bumpto.j] == ' ':
-                finish(FHOLE)
-                return hit
-            if game.quad[bumpto.i][bumpto.j] != '.':
-                # can't move into object
-                return hit
-            game.sector = bumpto
-            proutn(crmshp())
-            game.quad[w.i][w.j] = '.'
-            game.quad[bumpto.i][bumpto.j] = iquad
-            prout(_(" displaced by blast to Sector %s ") % bumpto)
-            for enemy in game.enemies:
-                enemy.kdist = enemy.kavgd = (game.sector-enemy.location).distance()
-            sortenemies()
-            return None
-        elif iquad in ('C', 'S', 'R', 'K'): # Hit a regular enemy
-            # find the enemy
-            if iquad in ('C', 'S') and rnd.withprob(0.05):
-                prout(crmena(True, iquad, "sector", w) + _(" uses anti-photon device;"))
-                prout(_("   torpedo neutralized."))
-                return None
-            for enemy in game.enemies:
-                if w == enemy.location:
-                    kp = math.fabs(enemy.power)
-                    h1 = 700.0 + rnd.integer(100) - \
-                        1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-track.angle))
-                    h1 = math.fabs(h1)
-                    if kp < h1:
-                        h1 = kp
-                    if enemy.power < 0:
-                        enemy.power -= -h1
-                    else:
-                        enemy.power -= h1
-                    if enemy.power == 0:
-                        deadkl(w, iquad, w)
-                        return None
-                    proutn(crmena(True, iquad, "sector", w))
-                    displacement = course(track.bearing+rnd.real(-2.4, 2.4), distance=2**0.5)
-                    displacement.nexttok()
-                    bumpto = displacement.sector()
-                    if not bumpto.valid_sector():
-                        prout(_(" damaged but not destroyed."))
-                        return
-                    if game.quad[bumpto.i][bumpto.j] == ' ':
-                        prout(_(" buffeted into black hole."))
-                        deadkl(w, iquad, bumpto)
-                    if game.quad[bumpto.i][bumpto.j] != '.':
-                        prout(_(" damaged but not destroyed."))
-                    else:
-                        prout(_(" damaged-- displaced by blast to Sector %s ")%bumpto)
-                        enemy.location = bumpto
-                        game.quad[w.i][w.j] = '.'
-                        game.quad[bumpto.i][bumpto.j] = iquad
-                        for tenemy in game.enemies:
-                            tenemy.kdist = tenemy.kavgd = (game.sector-tenemy.location).distance()
-                        sortenemies()
-                    break
-            else:
-                prout("Internal error, no enemy where expected!")
-                raise SystemExit(1)
-            return None
-        elif iquad == 'B': # Hit a base
-            skip(1)
-            prout(_("***STARBASE DESTROYED.."))
-            game.state.baseq = [x for x in game.state.baseq if x != game.quadrant]
-            game.quad[w.i][w.j] = '.'
-            game.base.invalidate()
-            game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase = False
-            game.state.chart[game.quadrant.i][game.quadrant.j].starbase = False
-            game.state.basekl += 1
-            newcnd()
-            return None
-        elif iquad == 'P': # Hit a planet
-            prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
-            game.state.nplankl += 1
-            game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
-            game.iplnet.pclass = "destroyed"
-            game.iplnet = None
-            game.plnet.invalidate()
-            game.quad[w.i][w.j] = '.'
-            if game.landed:
-                # captain perishes on planet
-                finish(FDPLANET)
-            return None
-        elif iquad == '@': # Hit an inhabited world -- very bad!
-            prout(crmena(True, iquad, "sector", w) + _(" destroyed."))
-            game.state.nworldkl += 1
-            game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
-            game.iplnet.pclass = "destroyed"
-            game.iplnet = None
-            game.plnet.invalidate()
-            game.quad[w.i][w.j] = '.'
-            if game.landed:
-                # captain perishes on planet
-                finish(FDPLANET)
-            prout(_("The torpedo destroyed an inhabited planet."))
-            return None
-        elif iquad == '*': # Hit a star
-            if rnd.withprob(0.9):
-                nova(w)
-            else:
-                prout(crmena(True, '*', "sector", w) + _(" unaffected by photon blast."))
-            return None
-        elif iquad == '?': # Hit a thingy
-            if not (game.options & OPTION_THINGY) or rnd.withprob(0.3):
-                skip(1)
-                prouts(_("AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!"))
-                skip(1)
-                prouts(_("    HACK!     HACK!    HACK!        *CHOKE!*  "))
-                skip(1)
-                proutn(_("Mr. Spock-"))
-                prouts(_("  \"Fascinating!\""))
-                skip(1)
-                deadkl(w, iquad, w)
-            else:
-                # Stas Sergeev added the possibility that
-                # you can shove the Thingy and piss it off.
-                # It then becomes an enemy and may fire at you.
-                thing.angry()
-            return None
-        elif iquad == ' ': # Black hole
-            skip(1)
-            prout(crmena(True, ' ', "sector", w) + _(" swallows torpedo."))
-            return None
-        elif iquad == '#': # hit the web
-            skip(1)
-            prout(_("***Torpedo absorbed by Tholian web."))
-            return None
-        elif iquad == 'T':  # Hit a Tholian
-            h1 = 700.0 + rnd.integer(100) - \
-                1000.0 * (w-origin).distance() * math.fabs(math.sin(bullseye-track.angle))
-            h1 = math.fabs(h1)
-            if h1 >= 600:
-                game.quad[w.i][w.j] = '.'
-                deadkl(w, iquad, w)
-                game.tholian = None
-                return None
-            skip(1)
-            proutn(crmena(True, 'T', "sector", w))
-            if rnd.withprob(0.05):
-                prout(_(" survives photon blast."))
-                return None
-            prout(_(" disappears."))
-            game.tholian.move(None)
-            game.quad[w.i][w.j] = '#'
-            dropin(' ')
-            return None
-        else: # Problem!
-            skip(1)
-            proutn("Don't know how to handle torpedo collision with ")
-            proutn(crmena(True, iquad, "sector", w))
-            skip(1)
-            return None
-        break
-    skip(1)
-    setwnd(message_window)
-    prout(_("Torpedo missed."))
-    return None
-
-def fry(hit):
-    "Critical-hit resolution."
-    if hit < (275.0-25.0*game.skill)*rnd.real(1.0, 1.5):
-        return
-    ncrit = int(1.0 + hit/(500.0+rnd.real(100)))
-    proutn(_("***CRITICAL HIT--"))
-    # Select devices and cause damage
-    cdam = []
-    while ncrit > 0:
-        while True:
-            j = randdevice()
-            # Cheat to prevent shuttle damage unless on ship
-            if not (game.damage[j]<0.0 or (j == DSHUTTL and game.iscraft != "onship") or (j == DCLOAK and game.ship != 'E' or j == DDRAY)):
-                break
-        cdam.append(j)
-        extradm = (hit*game.damfac)/(ncrit*rnd.real(75, 100))
-        game.damage[j] += extradm
-        ncrit -= 1
-    skipcount = 0
-    for (i, j) in enumerate(cdam):
-        proutn(device[j])
-        if skipcount % 3 == 2 and i < len(cdam)-1:
-            skip(1)
-        skipcount += 1
-        if i < len(cdam)-1:
-            proutn(_(" and "))
-    prout(_(" damaged."))
-    if damaged(DSHIELD) and game.shldup:
-        prout(_("***Shields knocked down."))
-        game.shldup = False
-    if damaged(DCLOAK) and game.iscloaked:
-        prout(_("***Cloaking device rendered inoperative."))
-        game.iscloaked = False
-
-def attack(torps_ok):
-    # bad guy attacks us
-    # torps_ok == False forces use of phasers in an attack
-    if game.iscloaked:
-        return
-    # game could be over at this point, check
-    if game.alldone:
-        return
-    attempt = False
-    ihurt = False
-    hitmax = 0.0
-    hittot = 0.0
-    chgfac = 1.0
-    where = "neither"
-    if game.idebug:
-        prout("=== ATTACK!")
-    # Tholian gets to move before attacking
-    if game.tholian:
-        movetholian()
-    # if you have just entered the RNZ, you'll get a warning
-    if game.neutz: # The one chance not to be attacked
-        game.neutz = False
-        return
-    # commanders get a chance to tac-move towards you
-    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:
-        for (bugout, enemy, old, goto) in  moveklings():
-            if bugout:
-                # we know about this if either short or long range
-                # sensors are working
-                if damaged(DSRSENS) and damaged(DLRSENS) \
-                       and game.condition != "docked":
-                    prout(crmena(True, enemy.type, "sector", old) + \
-                          (_(" escapes to Quadrant %s (and regains strength).") % goto))
-            else: # Enemy still in-sector
-                if enemy.move(goto):
-                    if not damaged(DSRSENS) or game.condition == "docked":
-                        proutn(_("*** %s from Sector %s") % (cramen(enemy.type), enemy.location))
-                        if enemy.kdist < old:
-                            proutn(_(" advances to "))
-                        else:
-                            proutn(_(" retreats to "))
-                        prout("Sector %s." % goto)
-        sortenemies()
-    # if no enemies remain after movement, we're done
-    if len(game.enemies) == 0 or (len(game.enemies) == 1 and thing.at(game.quadrant) and not thing.angered):
-        return
-    # set up partial hits if attack happens during shield status change
-    pfac = 1.0/game.inshld
-    if game.shldchg:
-        chgfac = 0.25 + rnd.real(0.5)
-    skip(1)
-    # message verbosity control
-    if game.skill <= SKILL_FAIR:
-        where = "sector"
-    for enemy in game.enemies:
-        if enemy.power < 0:
-            continue        # too weak to attack
-        # compute hit strength and diminish shield power
-        r = rnd.real()
-        # Increase chance of photon torpedos if docked or enemy energy is low
-        if game.condition == "docked":
-            r *= 0.25
-        if enemy.power < 500:
-            r *= 0.25
-        if enemy.type == 'T' or (enemy.type == '?' and not thing.angered):
-            continue
-        # different enemies have different probabilities of throwing a torp
-        usephasers = not torps_ok or \
-            (enemy.type == 'K' and r > 0.0005) or \
-            (enemy.type == 'C' and r > 0.015) or \
-            (enemy.type == 'R' and r > 0.3) or \
-            (enemy.type == 'S' and r > 0.07) or \
-            (enemy.type == '?' and r > 0.05)
-        if usephasers:            # Enemy uses phasers
-            if game.condition == "docked":
-                continue # Don't waste the effort!
-            attempt = True # Attempt to attack
-            dustfac = rnd.real(0.8, 0.85)
-            hit = enemy.power*math.pow(dustfac, enemy.kavgd)
-            enemy.power *= 0.75
-        else: # Enemy uses photon torpedo
-            # We should be able to make the bearing() method work here
-            pcourse = 1.90985*math.atan2(game.sector.j-enemy.location.j, enemy.location.i-game.sector.i)
-            hit = 0
-            proutn(_("***TORPEDO INCOMING"))
-            if not damaged(DSRSENS):
-                proutn(_(" From ") + crmena(False, enemy.type, where, enemy.location))
-            attempt = True
-            prout("  ")
-            dispersion = (rnd.real()+rnd.real())*0.5 - 0.5
-            dispersion += 0.002*enemy.power*dispersion
-            hit = torpedo(enemy.location, pcourse, dispersion, number=1, nburst=1)
-            if game.unwon() == 0:
-                finish(FWON) # Klingons did themselves in!
-            if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.alldone:
-                return # Supernova or finished
-            if hit is None:
-                continue
-        # incoming phaser or torpedo, shields may dissipate it
-        if game.shldup or game.shldchg or game.condition == "docked":
-            # shields will take hits
-            propor = pfac * game.shield
-            if game.condition == "docked":
-                propor *= 2.1
-            if propor < 0.1:
-                propor = 0.1
-            hitsh = propor*chgfac*hit+1.0
-            absorb = 0.8*hitsh
-            if absorb > game.shield:
-                absorb = game.shield
-            game.shield -= absorb
-            hit -= hitsh
-            # taking a hit blasts us out of a starbase dock
-            if game.condition == "docked":
-                dock(False)
-            # but the shields may take care of it
-            if propor > 0.1 and hit < 0.005*game.energy:
-                continue
-        # hit from this opponent got through shields, so take damage
-        ihurt = True
-        proutn(_("%d unit hit") % int(hit))
-        if (damaged(DSRSENS) and usephasers) or game.skill<=SKILL_FAIR:
-            proutn(_(" on the ") + crmshp())
-        if not damaged(DSRSENS) and usephasers:
-            prout(_(" from ") + crmena(False, enemy.type, where, enemy.location))
-        skip(1)
-        # Decide if hit is critical
-        if hit > hitmax:
-            hitmax = hit
-        hittot += hit
-        fry(hit)
-        game.energy -= hit
-    if game.energy <= 0:
-        # Returning home upon your shield, not with it...
-        finish(FBATTLE)
-        return
-    if not attempt and game.condition == "docked":
-        prout(_("***Enemies decide against attacking your ship."))
-    percent = 100.0*pfac*game.shield+0.5
-    if not ihurt:
-        # Shields fully protect ship
-        proutn(_("Enemy attack reduces shield strength to "))
-    else:
-        # Emit message if starship suffered hit(s)
-        skip(1)
-        proutn(_("Energy left %2d    shields ") % int(game.energy))
-        if game.shldup:
-            proutn(_("up "))
-        elif not damaged(DSHIELD):
-            proutn(_("down "))
-        else:
-            proutn(_("damaged, "))
-    prout(_("%d%%,   torpedoes left %d") % (percent, game.torps))
-    # Check if anyone was hurt
-    if hitmax >= 200 or hittot >= 500:
-        icas = rnd.integer(int(hittot * 0.015))
-        if icas >= 2:
-            skip(1)
-            prout(_("Mc Coy-  \"Sickbay to bridge.  We suffered %d casualties") % icas)
-            prout(_("   in that last attack.\""))
-            game.casual += icas
-            game.state.crew -= icas
-    # After attack, reset average distance to enemies
-    for enemy in game.enemies:
-        enemy.kavgd = enemy.kdist
-    sortenemies()
-    return
-
-def deadkl(w, etype, mv):
-    "Kill a Klingon, Tholian, Romulan, or Thingy."
-    # Added mv to allow enemy to "move" before dying
-    proutn(crmena(True, etype, "sector", mv))
-    # Decide what kind of enemy it is and update appropriately
-    if etype == 'R':
-        # Chalk up a Romulan
-        game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans -= 1
-        game.irhere -= 1
-        game.state.nromrem -= 1
-    elif etype == 'T':
-        # Killed a Tholian
-        game.tholian = None
-    elif etype == '?':
-        # Killed a Thingy
-        global thing
-        thing = None
-    else:
-        # Killed some type of Klingon
-        game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons -= 1
-        game.klhere -= 1
-        if etype == 'C':
-            game.state.kcmdr.remove(game.quadrant)
-            unschedule(FTBEAM)
-            if game.state.kcmdr:
-                schedule(FTBEAM, expran(1.0*game.incom/len(game.state.kcmdr)))
-            if is_scheduled(FCDBAS) and game.battle == game.quadrant:
-                unschedule(FCDBAS)
-        elif etype ==  'K':
-            pass
-        elif etype ==  'S':
-            game.state.nscrem -= 1
-            game.state.kscmdr.invalidate()
-            game.isatb = 0
-            game.iscate = False
-            unschedule(FSCMOVE)
-            unschedule(FSCDBAS)
-    # For each kind of enemy, finish message to player
-    prout(_(" destroyed."))
-    if game.unwon() == 0:
-        return
-    game.recompute()
-    # Remove enemy ship from arrays describing local conditions
-    for e in game.enemies:
-        if e.location == w:
-            e.move(None)
-            break
-    return
-
-def targetcheck(w):
-    "Return None if target is invalid, otherwise return a course angle."
-    if not w.valid_sector():
-        huh()
-        return None
-    delta = Coord()
-    # C code this was translated from is wacky -- why the sign reversal?
-    delta.j = (w.j - game.sector.j)
-    delta.i = (game.sector.i - w.i)
-    if delta == Coord(0, 0):
-        skip(1)
-        prout(_("Spock-  \"Bridge to sickbay.  Dr. McCoy,"))
-        prout(_("  I recommend an immediate review of"))
-        prout(_("  the Captain's psychological profile.\""))
-        scanner.chew()
-        return None
-    return delta.bearing()
-
-def torps():
-    "Launch photon torpedo salvo."
-    tcourse = []
-    game.ididit = False
-    if damaged(DPHOTON):
-        prout(_("Photon tubes damaged."))
-        scanner.chew()
-        return
-    if game.torps == 0:
-        prout(_("No torpedoes left."))
-        scanner.chew()
-        return
-    # First, get torpedo count
-    while True:
-        scanner.nexttok()
-        if scanner.token == "IHALPHA":
-            huh()
-            return
-        elif scanner.token == "IHEOL" or not scanner.waiting():
-            prout(_("%d torpedoes left.") % game.torps)
-            scanner.chew()
-            proutn(_("Number of torpedoes to fire- "))
-            continue        # Go back around to get a number
-        else: # key == "IHREAL"
-            try:
-                n = scanner.int()
-            except TypeError:
-                huh()
-                return
-            if n <= 0: # abort command
-                scanner.chew()
-                return
-            if n > MAXBURST:
-                scanner.chew()
-                prout(_("Maximum of %d torpedoes per burst.") % MAXBURST)
-                return
-            if n > game.torps:
-                scanner.chew()        # User requested more torps than available
-                continue        # Go back around
-            break        # All is good, go to next stage
-    # Next, get targets
-    target = []
-    for i in range(n):
-        key = scanner.nexttok()
-        if i == 0 and key == "IHEOL":
-            break        # no coordinate waiting, we will try prompting
-        if i == 1 and key == "IHEOL":
-            # direct all torpedoes at one target
-            while i < n:
-                target.append(target[0])
-                tcourse.append(tcourse[0])
-                i += 1
-            break
-        scanner.push(scanner.token)
-        target.append(scanner.getcoord())
-        if target[-1] is None:
-            return
-        tcourse.append(targetcheck(target[-1]))
-        if tcourse[-1] is None:
-            return
-    scanner.chew()
-    if len(target) == 0:
-        # prompt for each one
-        for i in range(n):
-            proutn(_("Target sector for torpedo number %d- ") % (i+1))
-            scanner.chew()
-            target.append(scanner.getcoord())
-            if target[-1] is None:
-                return
-            tcourse.append(targetcheck(target[-1]))
-            if tcourse[-1] is None:
-                return
-    game.ididit = True
-    # Loop for moving <n> torpedoes
-    for i in range(n):
-        if game.condition != "docked":
-            game.torps -= 1
-        dispersion = (rnd.real()+rnd.real())*0.5 -0.5
-        if math.fabs(dispersion) >= 0.47:
-            # misfire!
-            dispersion *= rnd.real(1.2, 2.2)
-            if n > 0:
-                prouts(_("***TORPEDO NUMBER %d MISFIRES") % (i+1))
-            else:
-                prouts(_("***TORPEDO MISFIRES."))
-            skip(1)
-            if i < n:
-                prout(_("  Remainder of burst aborted."))
-            if rnd.withprob(0.2):
-                prout(_("***Photon tubes damaged by misfire."))
-                game.damage[DPHOTON] = game.damfac * rnd.real(1.0, 3.0)
-            break
-        if game.iscloaked:
-            dispersion *= 1.2
-        elif game.shldup or game.condition == "docked":
-            dispersion *= 1.0 + 0.0001*game.shield
-        torpedo(game.sector, tcourse[i], dispersion, number=i, nburst=n)
-        if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-            return
-    if game.unwon()<=0:
-        finish(FWON)
-
-def overheat(rpow):
-    "Check for phasers overheating."
-    if rpow > 1500:
-        checkburn = (rpow-1500.0)*0.00038
-        if rnd.withprob(checkburn):
-            prout(_("Weapons officer Sulu-  \"Phasers overheated, sir.\""))
-            game.damage[DPHASER] = game.damfac* rnd.real(1.0, 2.0) * (1.0+checkburn)
-
-def checkshctrl(rpow):
-    "Check shield control."
-    skip(1)
-    if rnd.withprob(0.998):
-        prout(_("Shields lowered."))
-        return False
-    # Something bad has happened
-    prouts(_("***RED ALERT!  RED ALERT!"))
-    skip(2)
-    hit = rpow*game.shield/game.inshld
-    game.energy -= rpow+hit*0.8
-    game.shield -= hit*0.2
-    if game.energy <= 0.0:
-        prouts(_("Sulu-  \"Captain! Shield malf***********************\""))
-        skip(1)
-        stars()
-        finish(FPHASER)
-        return True
-    prouts(_("Sulu-  \"Captain! Shield malfunction! Phaser fire contained!\""))
-    skip(2)
-    prout(_("Lt. Uhura-  \"Sir, all decks reporting damage.\""))
-    icas = rnd.integer(int(hit*0.012))
-    skip(1)
-    fry(0.8*hit)
-    if icas:
-        skip(1)
-        prout(_("McCoy to bridge- \"Severe radiation burns, Jim."))
-        prout(_("  %d casualties so far.\"") % icas)
-        game.casual += icas
-        game.state.crew -= icas
-    skip(1)
-    prout(_("Phaser energy dispersed by shields."))
-    prout(_("Enemy unaffected."))
-    overheat(rpow)
-    return True
-
-def hittem(hits):
-    "Register a phaser hit on Klingons and Romulans."
-    w = Coord()
-    skip(1)
-    kk = 0
-    for wham in hits:
-        if wham == 0:
-            continue
-        dustfac = rnd.real(0.9, 1.0)
-        hit = wham*math.pow(dustfac, game.enemies[kk].kdist)
-        kpini = game.enemies[kk].power
-        kp = math.fabs(kpini)
-        if PHASEFAC*hit < kp:
-            kp = PHASEFAC*hit
-        if game.enemies[kk].power < 0:
-            game.enemies[kk].power -= -kp
-        else:
-            game.enemies[kk].power -= kp
-        kpow = game.enemies[kk].power
-        w = game.enemies[kk].location
-        if hit > 0.005:
-            if not damaged(DSRSENS):
-                boom(w)
-            proutn(_("%d unit hit on ") % int(hit))
-        else:
-            proutn(_("Very small hit on "))
-        ienm = game.quad[w.i][w.j]
-        if ienm == '?':
-            thing.angry()
-        proutn(crmena(False, ienm, "sector", w))
-        skip(1)
-        if kpow == 0:
-            deadkl(w, ienm, w)
-            if game.unwon()==0:
-                finish(FWON)
-            if game.alldone:
-                return
-            continue
-        else: # decide whether or not to emasculate klingon
-            if kpow > 0 and rnd.withprob(0.9) and kpow <= rnd.real(0.4, 0.8)*kpini:
-                prout(_("***Mr. Spock-  \"Captain, the vessel at Sector %s")%w)
-                prout(_("   has just lost its firepower.\""))
-                game.enemies[kk].power = -kpow
-        kk += 1
-    return
-
-def phasers():
-    "Fire phasers at bad guys."
-    hits = []
-    kz = 0
-    k = 1
-    irec = 0 # Cheating inhibitor
-    ifast = False
-    no = False
-    itarg = True
-    msgflag = True
-    rpow = 0.0
-    automode = "NOTSET"
-    key = ""
-    skip(1)
-    # SR sensors and Computer are needed for automode
-    if damaged(DSRSENS) or damaged(DCOMPTR):
-        itarg = False
-    if game.condition == "docked":
-        prout(_("Phasers can't be fired through base shields."))
-        scanner.chew()
-        return
-    if damaged(DPHASER):
-        prout(_("Phaser control damaged."))
-        scanner.chew()
-        return
-    if game.shldup:
-        if damaged(DSHCTRL):
-            prout(_("High speed shield control damaged."))
-            scanner.chew()
-            return
-        if game.energy <= 200.0:
-            prout(_("Insufficient energy to activate high-speed shield control."))
-            scanner.chew()
-            return
-        prout(_("Weapons Officer Sulu-  \"High-speed shield control enabled, sir.\""))
-        ifast = True
-    # Original code so convoluted, I re-did it all
-    # (That was Tom Almy talking about the C code, I think -- ESR)
-    while automode == "NOTSET":
-        key = scanner.nexttok()
-        if key == "IHALPHA":
-            if scanner.sees("manual"):
-                if len(game.enemies)==0:
-                    prout(_("There is no enemy present to select."))
-                    scanner.chew()
-                    key = "IHEOL"
-                    automode = "AUTOMATIC"
-                else:
-                    automode = "MANUAL"
-                    key = scanner.nexttok()
-            elif scanner.sees("automatic"):
-                if (not itarg) and len(game.enemies) != 0:
-                    automode = "FORCEMAN"
-                else:
-                    if len(game.enemies)==0:
-                        prout(_("Energy will be expended into space."))
-                    automode = "AUTOMATIC"
-                    key = scanner.nexttok()
-            elif scanner.sees("no"):
-                no = True
-            else:
-                huh()
-                return
-        elif key == "IHREAL":
-            if len(game.enemies)==0:
-                prout(_("Energy will be expended into space."))
-                automode = "AUTOMATIC"
-            elif not itarg:
-                automode = "FORCEMAN"
-            else:
-                automode = "AUTOMATIC"
-        else:
-            # "IHEOL"
-            if len(game.enemies)==0:
-                prout(_("Energy will be expended into space."))
-                automode = "AUTOMATIC"
-            elif not itarg:
-                automode = "FORCEMAN"
-            else:
-                proutn(_("Manual or automatic? "))
-                scanner.chew()
-    avail = game.energy
-    if ifast:
-        avail -= 200.0
-    if automode == "AUTOMATIC":
-        if key == "IHALPHA" and scanner.sees("no"):
-            no = True
-            key = scanner.nexttok()
-        if key != "IHREAL" and len(game.enemies) != 0:
-            prout(_("Phasers locked on target. Energy available: %.2f")%avail)
-        irec = 0
-        while True:
-            scanner.chew()
-            if not kz:
-                for i in range(len(game.enemies)):
-                    irec += math.fabs(game.enemies[i].power)/(PHASEFAC*math.pow(0.90, game.enemies[i].kdist))*rnd.real(1.01, 1.06) + 1.0
-            kz = 1
-            proutn(_("%d units required. ") % irec)
-            scanner.chew()
-            proutn(_("Units to fire= "))
-            key = scanner.nexttok()
-            if key != "IHREAL":
-                return
-            rpow = scanner.real
-            if rpow > avail:
-                proutn(_("Energy available= %.2f") % avail)
-                skip(1)
-                key = "IHEOL"
-            if not rpow > avail:
-                break
-        if rpow <= 0:
-            # chicken out
-            scanner.chew()
-            return
-        key = scanner.nexttok()
-        if key == "IHALPHA" and scanner.sees("no"):
-            no = True
-        if ifast:
-            game.energy -= 200 # Go and do it!
-            if checkshctrl(rpow):
-                return
-        scanner.chew()
-        game.energy -= rpow
-        extra = rpow
-        if len(game.enemies):
-            extra = 0.0
-            powrem = rpow
-            for i in range(len(game.enemies)):
-                hits.append(0.0)
-                if powrem <= 0:
-                    continue
-                hits[i] = math.fabs(game.enemies[i].power)/(PHASEFAC*math.pow(0.90, game.enemies[i].kdist))
-                over = rnd.real(1.01, 1.06) * hits[i]
-                temp = powrem
-                powrem -= hits[i] + over
-                if powrem <= 0 and temp < hits[i]:
-                    hits[i] = temp
-                if powrem <= 0:
-                    over = 0.0
-                extra += over
-            if powrem > 0.0:
-                extra += powrem
-            hittem(hits)
-            game.ididit = True
-        if extra > 0 and not game.alldone:
-            if game.tholian:
-                proutn(_("*** Tholian web absorbs "))
-                if len(game.enemies)>0:
-                    proutn(_("excess "))
-                prout(_("phaser energy."))
-            else:
-                prout(_("%d expended on empty space.") % int(extra))
-    elif automode == "FORCEMAN":
-        scanner.chew()
-        key = "IHEOL"
-        if damaged(DCOMPTR):
-            prout(_("Battle computer damaged, manual fire only."))
-        else:
-            skip(1)
-            prouts(_("---WORKING---"))
-            skip(1)
-            prout(_("Short-range-sensors-damaged"))
-            prout(_("Insufficient-data-for-automatic-phaser-fire"))
-            prout(_("Manual-fire-must-be-used"))
-            skip(1)
-    elif automode == "MANUAL":
-        rpow = 0.0
-        for k in range(len(game.enemies)):
-            aim = game.enemies[k].location
-            ienm = game.quad[aim.i][aim.j]
-            if msgflag:
-                proutn(_("Energy available= %.2f") % (avail-0.006))
-                skip(1)
-                msgflag = False
-                rpow = 0.0
-            if damaged(DSRSENS) and \
-               not game.sector.distance(aim)<2**0.5 and ienm in ('C', 'S'):
-                prout(cramen(ienm) + _(" can't be located without short range scan."))
-                scanner.chew()
-                key = "IHEOL"
-                hits[k] = 0 # prevent overflow -- thanks to Alexei Voitenko
-                continue
-            if key == "IHEOL":
-                scanner.chew()
-                if itarg and k > kz:
-                    irec = (abs(game.enemies[k].power)/(PHASEFAC*math.pow(0.9, game.enemies[k].kdist))) *        rnd.real(1.01, 1.06) + 1.0
-                kz = k
-                proutn("(")
-                if not damaged(DCOMPTR):
-                    proutn("%d" % irec)
-                else:
-                    proutn("??")
-                proutn(")  ")
-                proutn(_("units to fire at %s-  ") % crmena(False, ienm, "sector", aim))
-                key = scanner.nexttok()
-            if key == "IHALPHA" and scanner.sees("no"):
-                no = True
-                key = scanner.nexttok()
-                continue
-            if key == "IHALPHA":
-                huh()
-                return
-            if key == "IHEOL":
-                if k == 1: # Let me say I'm baffled by this
-                    msgflag = True
-                continue
-            if scanner.real < 0:
-                # abort out
-                scanner.chew()
-                return
-            hits.append(scanner.real)
-            rpow += scanner.real
-            # If total requested is too much, inform and start over
-            if rpow > avail:
-                prout(_("Available energy exceeded -- try again."))
-                scanner.chew()
-                return
-            key = scanner.nexttok() # scan for next value
-        if rpow == 0.0:
-            # zero energy -- abort
-            scanner.chew()
-            return
-        if key == "IHALPHA" and scanner.sees("no"):
-            no = True
-        game.energy -= rpow
-        scanner.chew()
-        if ifast:
-            game.energy -= 200.0
-            if checkshctrl(rpow):
-                return
-        hittem(hits)
-        game.ididit = True
-     # Say shield raised or malfunction, if necessary
-    if game.alldone:
-        return
-    if ifast:
-        skip(1)
-        if no == 0:
-            if rnd.withprob(0.01):
-                prout(_("Sulu-  \"Sir, the high-speed shield control has malfunctioned . . ."))
-                prouts(_("         CLICK   CLICK   POP  . . ."))
-                prout(_(" No response, sir!"))
-                game.shldup = False
-            else:
-                prout(_("Shields raised."))
-        else:
-            game.shldup = False
-    overheat(rpow)
-
-
-def capture():
-    game.ididit = False # Nothing if we fail
-    game.optime = 0.0
-
-    # Make sure there is room in the brig
-    if game.brigfree == 0:
-        prout(_("Security reports the brig is already full."))
-        return
-
-    if damaged(DRADIO):
-        prout(_("Uhura- \"We have no subspace radio communication, sir.\""))
-        return
-
-    if damaged(DTRANSP):
-        prout(_("Scotty- \"Transporter damaged, sir.\""))
-        return
-
-    # find out if there are any at all
-    if game.klhere < 1:
-        prout(_("Uhura- \"Getting no response, sir.\""))
-        return
-
-    # if there is more than one Klingon, find out which one
-    #  Cruddy, just takes one at random.  Should ask the captain.
-    #  Nah, just select the weakest one since it is most likely to
-    #  surrender (Tom Almy mod)
-    klingons = [e for e in game.enemies if e.type == 'K']
-    weakest = sorted(klingons, key=lambda e: e.power)[0]
-    game.optime = 0.05         # This action will take some time
-    game.ididit = True #  So any others can strike back
-
-    # check out that Klingon
-    # The algorithm isn't that great and could use some more
-    # intelligent design
-    # x = 300 + 25*skill;
-    x = game.energy / (weakest.power * len(klingons))
-    #prout(_("Stats: energy = %s, kpower = %s, klingons = %s")
-    #      % (game.energy, weakest.power, len(klingons)))
-    x *= 2.5   # would originally have been equivalent of 1.4,
-               # but we want command to work more often, more humanely
-    #prout(_("Prob = %.4f" % x))
-    #  x = 100; // For testing, of course!
-    if x < rnd.real(100):
-        # guess what, he surrendered!!!
-        prout(_("Klingon captain at %s surrenders.") % weakest.location)
-        i = rnd.real(200)
-        if i > 0:
-            prout(_("%d Klingons commit suicide rather than be taken captive.") % (200 - i))
-        if i > game.brigfree:
-            prout(_("%d Klingons die because there is no room for them in the brig.") % (i-game.brigfree))
-            i = game.brigfree
-        game.brigfree -= i
-        prout(_("%d captives taken") % i)
-        deadkl(weakest.location, weakest.type, game.sector)
-        if game.unwon()<=0:
-            finish(FWON)
-        return
-
-       # big surprise, he refuses to surrender
-    prout(_("Fat chance, captain!"))
-
-# Code from events.c begins here.
-
-# This isn't a real event queue a la BSD Trek yet -- you can only have one
-# event of each type active at any given time.  Mostly these means we can
-# only have one FDISTR/FENSLV/FREPRO sequence going at any given time
-# BSD Trek, from which we swiped the idea, can have up to 5.
-
-def unschedule(evtype):
-    "Remove an event from the schedule."
-    game.future[evtype].date = FOREVER
-    return game.future[evtype]
-
-def is_scheduled(evtype):
-    "Is an event of specified type scheduled."
-    return game.future[evtype].date != FOREVER
-
-def scheduled(evtype):
-    "When will this event happen?"
-    return game.future[evtype].date
-
-def schedule(evtype, offset):
-    "Schedule an event of specified type."
-    game.future[evtype].date = game.state.date + offset
-    return game.future[evtype]
-
-def postpone(evtype, offset):
-    "Postpone a scheduled event."
-    game.future[evtype].date += offset
-
-def cancelrest():
-    "Rest period is interrupted by event."
-    if game.resting:
-        skip(1)
-        proutn(_("Mr. Spock-  \"Captain, shall we cancel the rest period?\""))
-        if ja():
-            game.resting = False
-            game.optime = 0.0
-            return True
-    return False
-
-def events():
-    "Run through the event queue looking for things to do."
-    i = 0
-    fintim = game.state.date + game.optime
-    yank = 0
-    ictbeam = False
-    istract = False
-    w = Coord()
-    hold = Coord()
-    ev = Event()
-    ev2 = Event()
-
-    def tractorbeam(yank):
-        "Tractor-beaming cases merge here."
-        announce()
-        game.optime = (10.0/(7.5*7.5))*yank # 7.5 is yank rate (warp 7.5)
-        skip(1)
-        prout("***" + crmshp() + _(" caught in long range tractor beam--"))
-        # If Kirk & Co. screwing around on planet, handle
-        atover(True) # atover(true) is Grab
-        if game.alldone:
-            return
-        if game.icraft: # Caught in Galileo?
-            finish(FSTRACTOR)
-            return
-        # Check to see if shuttle is aboard
-        if game.iscraft == "offship":
-            skip(1)
-            if rnd.withprob(0.5):
-                prout(_("Galileo, left on the planet surface, is captured"))
-                prout(_("by aliens and made into a flying McDonald's."))
-                game.damage[DSHUTTL] = -10
-                game.iscraft = "removed"
-            else:
-                prout(_("Galileo, left on the planet surface, is well hidden."))
-        if evcode == FSPY:
-            game.quadrant = game.state.kscmdr
-        else:
-            game.quadrant = game.state.kcmdr[i]
-        game.sector = randplace(QUADSIZE)
-        prout(crmshp() + _(" is pulled to Quadrant %s, Sector %s") \
-               % (game.quadrant, game.sector))
-        if game.resting:
-            prout(_("(Remainder of rest/repair period cancelled.)"))
-            game.resting = False
-        if not game.shldup:
-            if not damaged(DSHIELD) and game.shield > 0:
-                doshield(shraise=True) # raise shields
-                game.shldchg = False
-            else:
-                prout(_("(Shields not currently useable.)"))
-        newqad()
-        # Adjust finish time to time of tractor beaming?
-        # fintim = game.state.date+game.optime
-        attack(torps_ok=False)
-        if not game.state.kcmdr:
-            unschedule(FTBEAM)
-        else:
-            schedule(FTBEAM, game.optime+expran(1.5*game.intime/len(game.state.kcmdr)))
-
-    def destroybase():
-        "Code merges here for any commander destroying a starbase."
-        # Not perfect, but will have to do
-        # Handle case where base is in same quadrant as starship
-        if game.battle == game.quadrant:
-            game.state.chart[game.battle.i][game.battle.j].starbase = False
-            game.quad[game.base.i][game.base.j] = '.'
-            game.base.invalidate()
-            newcnd()
-            skip(1)
-            prout(_("Spock-  \"Captain, I believe the starbase has been destroyed.\""))
-        elif game.state.baseq and communicating():
-            # Get word via subspace radio
-            announce()
-            skip(1)
-            prout(_("Lt. Uhura-  \"Captain, Starfleet Command reports that"))
-            proutn(_("   the starbase in Quadrant %s has been destroyed by") % game.battle)
-            if game.isatb == 2:
-                prout(_("the Klingon Super-Commander"))
-            else:
-                prout(_("a Klingon Commander"))
-            game.state.chart[game.battle.i][game.battle.j].starbase = False
-        # Remove Starbase from galaxy
-        game.state.galaxy[game.battle.i][game.battle.j].starbase = False
-        game.state.baseq = [x for x in game.state.baseq if x != game.battle]
-        if game.isatb == 2:
-            # reinstate a commander's base attack
-            game.battle = hold
-            game.isatb = 0
-        else:
-            game.battle.invalidate()
-    if game.idebug:
-        prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
-        for i in range(1, NEVENTS):
-            if   i == FSNOVA:  proutn("=== Supernova       ")
-            elif i == FTBEAM:  proutn("=== T Beam          ")
-            elif i == FSNAP:   proutn("=== Snapshot        ")
-            elif i == FBATTAK: proutn("=== Base Attack     ")
-            elif i == FCDBAS:  proutn("=== Base Destroy    ")
-            elif i == FSCMOVE: proutn("=== SC Move         ")
-            elif i == FSCDBAS: proutn("=== SC Base Destroy ")
-            elif i == FDSPROB: proutn("=== Probe Move      ")
-            elif i == FDISTR:  proutn("=== Distress Call   ")
-            elif i == FENSLV:  proutn("=== Enslavement     ")
-            elif i == FREPRO:  proutn("=== Klingon Build   ")
-            if is_scheduled(i):
-                prout("%.2f" % (scheduled(i)))
-            else:
-                prout("never")
-    radio_was_broken = damaged(DRADIO)
-    hold.i = hold.j = 0
-    while True:
-        # Select earliest extraneous event, evcode==0 if no events
-        evcode = FSPY
-        if game.alldone:
-            return
-        datemin = fintim
-        for l in range(1, NEVENTS):
-            if game.future[l].date < datemin:
-                evcode = l
-                if game.idebug:
-                    prout("== Event %d fires" % evcode)
-                datemin = game.future[l].date
-        xtime = datemin-game.state.date
-        if game.iscloaked:
-            game.energy -= xtime*500.0
-            if game.energy <= 0:
-                finish(FNRG)
-                return
-        game.state.date = datemin
-        # Decrement Federation resources and recompute remaining time
-        game.state.remres -= (game.remkl()+4*len(game.state.kcmdr))*xtime
-        game.recompute()
-        if game.state.remtime <= 0:
-            finish(FDEPLETE)
-            return
-        # Any crew left alive?
-        if game.state.crew <= 0:
-            finish(FCREW)
-            return
-        # Is life support adequate?
-        if damaged(DLIFSUP) and game.condition != "docked":
-            if game.lsupres < xtime and game.damage[DLIFSUP] > game.lsupres:
-                finish(FLIFESUP)
-                return
-            game.lsupres -= xtime
-            if game.damage[DLIFSUP] <= xtime:
-                game.lsupres = game.inlsr
-        # Fix devices
-        repair = xtime
-        if game.condition == "docked":
-            repair /= DOCKFAC
-        # Don't fix Deathray here
-        for l in range(NDEVICES):
-            if game.damage[l] > 0.0 and l != DDRAY:
-                if game.damage[l]-repair > 0.0:
-                    game.damage[l] -= repair
-                else:
-                    game.damage[l] = 0.0
-        # If radio repaired, update star chart and attack reports
-        if radio_was_broken and not damaged(DRADIO):
-            prout(_("Lt. Uhura- \"Captain, the sub-space radio is working and"))
-            prout(_("   surveillance reports are coming in."))
-            skip(1)
-            if not game.iseenit:
-                attackreport(False)
-                game.iseenit = True
-            rechart()
-            prout(_("   The star chart is now up to date.\""))
-            skip(1)
-        # Cause extraneous event EVCODE to occur
-        game.optime -= xtime
-        if evcode == FSNOVA: # Supernova
-            announce()
-            supernova(None)
-            schedule(FSNOVA, expran(0.5*game.intime))
-            if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-                return
-        elif evcode == FSPY: # Check with spy to see if SC should tractor beam
-            if game.state.nscrem == 0 or game.iscloaked or \
-                ictbeam or istract or \
-                game.condition == "docked" or game.isatb == 1 or game.iscate:
-                return
-            if game.ientesc or \
-                (game.energy<2000 and game.torps<4 and game.shield < 1250) or \
-                (damaged(DPHASER) and (damaged(DPHOTON) or game.torps<4)) or \
-                (damaged(DSHIELD) and \
-                 (game.energy < 2500 or damaged(DPHASER)) and \
-                 (game.torps < 5 or damaged(DPHOTON))):
-                # Tractor-beam her!
-                istract = ictbeam = True
-                tractorbeam((game.state.kscmdr-game.quadrant).distance())
-            else:
-                return
-        elif evcode == FTBEAM: # Tractor beam
-            if not game.state.kcmdr:
-                unschedule(FTBEAM)
-                continue
-            i = rnd.integer(len(game.state.kcmdr))
-            yank = (game.state.kcmdr[i]-game.quadrant).distance()
-            if istract or game.condition == "docked" or game.iscloaked or yank == 0:
-                # Drats! Have to reschedule
-                schedule(FTBEAM,
-                         game.optime + expran(1.5*game.intime/len(game.state.kcmdr)))
-                continue
-            ictbeam = True
-            tractorbeam(yank)
-        elif evcode == FSNAP: # Snapshot of the universe (for time warp)
-            game.snapsht = copy.deepcopy(game.state)
-            game.state.snap = True
-            schedule(FSNAP, expran(0.5 * game.intime))
-        elif evcode == FBATTAK: # Commander attacks starbase
-            if not game.state.kcmdr or not game.state.baseq:
-                # no can do
-                unschedule(FBATTAK)
-                unschedule(FCDBAS)
-                continue
-            ibq = None # Force battle location to persist past loop
-            try:
-                for ibq in game.state.baseq:
-                    for cmdr in game.state.kcmdr:
-                        if ibq == cmdr and ibq != game.quadrant and ibq != game.state.kscmdr:
-                            raise JumpOut
-                # no match found -- try later
-                schedule(FBATTAK, expran(0.3*game.intime))
-                unschedule(FCDBAS)
-                continue
-            except JumpOut:
-                pass
-            # commander + starbase combination found -- launch attack
-            game.battle = ibq
-            schedule(FCDBAS, rnd.real(1.0, 4.0))
-            if game.isatb: # extra time if SC already attacking
-                postpone(FCDBAS, scheduled(FSCDBAS)-game.state.date)
-            game.future[FBATTAK].date = game.future[FCDBAS].date + expran(0.3*game.intime)
-            game.iseenit = False
-            if not communicating():
-                continue # No warning :-(
-            game.iseenit = True
-            announce()
-            skip(1)
-            prout(_("Lt. Uhura-  \"Captain, the starbase in Quadrant %s") % game.battle)
-            prout(_("   reports that it is under attack and that it can"))
-            prout(_("   hold out only until stardate %d.\"") % (int(scheduled(FCDBAS))))
-            if cancelrest():
-                return
-        elif evcode == FSCDBAS: # Supercommander destroys base
-            unschedule(FSCDBAS)
-            game.isatb = 2
-            if not game.state.galaxy[game.state.kscmdr.i][game.state.kscmdr.j].starbase:
-                continue # WAS RETURN!
-            hold = game.battle
-            game.battle = game.state.kscmdr
-            destroybase()
-        elif evcode == FCDBAS: # Commander succeeds in destroying base
-            if evcode == FCDBAS:
-                unschedule(FCDBAS)
-                if not game.state.baseq() \
-                       or not game.state.galaxy[game.battle.i][game.battle.j].starbase:
-                    game.battle.invalidate()
-                    continue
-                # find the lucky pair
-                for cmdr in game.state.kcmdr:
-                    if cmdr == game.battle:
-                        break
-                else:
-                    # No action to take after all
-                    continue
-            destroybase()
-        elif evcode == FSCMOVE: # Supercommander moves
-            schedule(FSCMOVE, 0.2777)
-            if not game.ientesc and not istract and game.isatb != 1 and \
-                   (not game.iscate or not game.justin):
-                supercommander()
-        elif evcode == FDSPROB: # Move deep space probe
-            schedule(FDSPROB, 0.01)
-            if not game.probe.nexttok():
-                if not game.probe.quadrant().valid_quadrant() or \
-                    game.state.galaxy[game.probe.quadrant().i][game.probe.quadrant().j].supernova:
-                    # Left galaxy or ran into supernova
-                    if communicating():
-                        announce()
-                        skip(1)
-                        proutn(_("Lt. Uhura-  \"The deep space probe "))
-                        if not game.probe.quadrant().valid_quadrant():
-                            prout(_("has left the galaxy.\""))
-                        else:
-                            prout(_("is no longer transmitting.\""))
-                    unschedule(FDSPROB)
-                    continue
-                if communicating():
-                    #announce()
-                    skip(1)
-                    prout(_("Lt. Uhura-  \"The deep space probe is now in Quadrant %s.\"") % game.probe.quadrant())
-            pquad = game.probe.quadrant()
-            pdest = game.state.galaxy[pquad.i][pquad.j]
-            if communicating():
-                game.state.chart[pquad.i][pquad.j].klingons = pdest.klingons
-                game.state.chart[pquad.i][pquad.j].starbase = pdest.starbase
-                game.state.chart[pquad.i][pquad.j].stars = pdest.stars
-                pdest.charted = True
-            game.probe.moves -= 1 # One less to travel
-            if game.probe.arrived() and game.isarmed and pdest.stars:
-                supernova(game.probe)                # fire in the hole!
-                unschedule(FDSPROB)
-                if game.state.galaxy[pquad.i][pquad.j].supernova:
-                    return
-        elif evcode == FDISTR: # inhabited system issues distress call
-            unschedule(FDISTR)
-            # try a whole bunch of times to find something suitable
-            for i in range(100):
-                # need a quadrant which is not the current one,
-                # which has some stars which are inhabited and
-                # not already under attack, which is not
-                # supernova'ed, and which has some Klingons in it
-                w = randplace(GALSIZE)
-                q = game.state.galaxy[w.i][w.j]
-                if not (game.quadrant == w or q.planet is None or \
-                      not q.planet.inhabited or \
-                      q.supernova or q.status!="secure" or q.klingons<=0):
-                    break
-            else:
-                # can't seem to find one; ignore this call
-                if game.idebug:
-                    prout("=== Couldn't find location for distress event.")
-                continue
-            # got one!!  Schedule its enslavement
-            ev = schedule(FENSLV, expran(game.intime))
-            ev.quadrant = w
-            q.status = "distressed"
-            # tell the captain about it if we can
-            if communicating():
-                prout(_("Uhura- Captain, %s in Quadrant %s reports it is under attack") \
-                        % (q.planet, repr(w)))
-                prout(_("by a Klingon invasion fleet."))
-                if cancelrest():
-                    return
-        elif evcode == FENSLV:                # starsystem is enslaved
-            ev = unschedule(FENSLV)
-            # see if current distress call still active
-            q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
-            if q.klingons <= 0:
-                q.status = "secure"
-                continue
-            q.status = "enslaved"
-
-            # play stork and schedule the first baby
-            ev2 = schedule(FREPRO, expran(2.0 * game.intime))
-            ev2.quadrant = ev.quadrant
-
-            # report the disaster if we can
-            if communicating():
-                prout(_("Uhura- We've lost contact with starsystem %s") % \
-                        q.planet)
-                prout(_("in Quadrant %s.\n") % ev.quadrant)
-        elif evcode == FREPRO:                # Klingon reproduces
-            # If we ever switch to a real event queue, we'll need to
-            # explicitly retrieve and restore the x and y.
-            ev = schedule(FREPRO, expran(1.0 * game.intime))
-            # see if current distress call still active
-            q = game.state.galaxy[ev.quadrant.i][ev.quadrant.j]
-            if q.klingons <= 0:
-                q.status = "secure"
-                continue
-            if game.remkl() >= MAXKLGAME:
-                continue                # full right now
-            # reproduce one Klingon
-            w = ev.quadrant
-            m = Coord()
-            if game.klhere >= MAXKLQUAD:
-                try:
-                    # this quadrant not ok, pick an adjacent one
-                    for m.i in range(w.i - 1, w.i + 2):
-                        for m.j in range(w.j - 1, w.j + 2):
-                            if not m.valid_quadrant():
-                                continue
-                            q = game.state.galaxy[m.i][m.j]
-                            # check for this quad ok (not full & no snova)
-                            if q.klingons >= MAXKLQUAD or q.supernova:
-                                continue
-                            raise JumpOut
-                    # search for eligible quadrant failed
-                    continue
-                except JumpOut:
-                    w = m
-            # deliver the child
-            q.klingons += 1
-            if game.quadrant == w:
-                game.klhere += 1
-                newkling() # also adds it to game.enemies
-            # recompute time left
-            game.recompute()
-            if communicating():
-                if game.quadrant == w:
-                    prout(_("Spock- sensors indicate the Klingons have"))
-                    prout(_("launched a warship from %s.") % q.planet)
-                else:
-                    prout(_("Uhura- Starfleet reports increased Klingon activity"))
-                    if q.planet is not None:
-                        proutn(_("near %s ") % q.planet)
-                    prout(_("in Quadrant %s.") % w)
-
-def wait():
-    "Wait on events."
-    game.ididit = False
-    while True:
-        key = scanner.nexttok()
-        if key  != "IHEOL":
-            break
-        proutn(_("How long? "))
-        scanner.chew()
-    if key != "IHREAL":
-        huh()
-        return
-    origTime = delay = scanner.real
-    if delay <= 0.0:
-        return
-    if delay >= game.state.remtime or len(game.enemies) != 0:
-        proutn(_("Are you sure? "))
-        if not ja():
-            return
-    # Alternate resting periods (events) with attacks
-    game.resting = True
-    while True:
-        if delay <= 0:
-            game.resting = False
-        if not game.resting:
-            prout(_("%d stardates left.") % int(game.state.remtime))
-            return
-        temp = game.optime = delay
-        if len(game.enemies):
-            rtime = rnd.real(1.0, 2.0)
-            if rtime < temp:
-                temp = rtime
-            game.optime = temp
-        if game.optime < delay:
-            attack(torps_ok=False)
-        if game.alldone:
-            return
-        events()
-        game.ididit = True
-        if game.alldone:
-            return
-        delay -= temp
-        # Repair Deathray if long rest at starbase
-        if origTime-delay >= 9.99 and game.condition == "docked":
-            game.damage[DDRAY] = 0.0
-        # leave if quadrant supernovas
-        if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-            break
-    game.resting = False
-    game.optime = 0.0
-
-def nova(nov):
-    "Star goes nova."
-    ncourse = (0.0, 10.5, 12.0, 1.5, 9.0, 0.0, 3.0, 7.5, 6.0, 4.5)
-    newc = Coord(); neighbor = Coord(); bump = Coord(0, 0)
-    if rnd.withprob(0.05):
-        # Wow! We've supernova'ed
-        supernova(game.quadrant)
-        return
-    # handle initial nova
-    game.quad[nov.i][nov.j] = '.'
-    prout(crmena(False, '*', "sector", nov) + _(" novas."))
-    game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
-    game.state.starkl += 1
-    # Set up queue to recursively trigger adjacent stars
-    hits = [nov]
-    kount = 0
-    while hits:
-        offset = Coord()
-        start = hits.pop()
-        for offset.i in range(-1, 1+1):
-            for offset.j in range(-1, 1+1):
-                if offset.j == 0 and offset.i == 0:
-                    continue
-                neighbor = start + offset
-                if not neighbor.valid_sector():
-                    continue
-                iquad = game.quad[neighbor.i][neighbor.j]
-                # Empty space ends reaction
-                if iquad in ('.', '?', ' ', 'T', '#'):
-                    pass
-                elif iquad == '*': # Affect another star
-                    if rnd.withprob(0.05):
-                        # This star supernovas
-                        supernova(game.quadrant)
-                        return
-                    else:
-                        hits.append(neighbor)
-                        game.state.galaxy[game.quadrant.i][game.quadrant.j].stars -= 1
-                        game.state.starkl += 1
-                        proutn(crmena(True, '*', "sector", neighbor))
-                        prout(_(" novas."))
-                        game.quad[neighbor.i][neighbor.j] = '.'
-                        kount += 1
-                elif iquad in ('P', '@'): # Destroy planet
-                    game.state.galaxy[game.quadrant.i][game.quadrant.j].planet = None
-                    if iquad == 'P':
-                        game.state.nplankl += 1
-                    else:
-                        game.state.nworldkl += 1
-                    prout(crmena(True, 'B', "sector", neighbor) + _(" destroyed."))
-                    game.iplnet.pclass = "destroyed"
-                    game.iplnet = None
-                    game.plnet.invalidate()
-                    if game.landed:
-                        finish(FPNOVA)
-                        return
-                    game.quad[neighbor.i][neighbor.j] = '.'
-                elif iquad == 'B': # Destroy base
-                    game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase = False
-                    game.state.baseq = [x for x in game.state.baseq if x!= game.quadrant]
-                    game.base.invalidate()
-                    game.state.basekl += 1
-                    newcnd()
-                    prout(crmena(True, 'B', "sector", neighbor) + _(" destroyed."))
-                    game.quad[neighbor.i][neighbor.j] = '.'
-                elif iquad in ('E', 'F'): # Buffet ship
-                    prout(_("***Starship buffeted by nova."))
-                    if game.shldup:
-                        if game.shield >= 2000.0:
-                            game.shield -= 2000.0
-                        else:
-                            diff = 2000.0 - game.shield
-                            game.energy -= diff
-                            game.shield = 0.0
-                            game.shldup = False
-                            prout(_("***Shields knocked out."))
-                            game.damage[DSHIELD] += 0.005*game.damfac*rnd.real()*diff
-                    else:
-                        game.energy -= 2000.0
-                    if game.energy <= 0:
-                        finish(FNOVA)
-                        return
-                    # add in course nova contributes to kicking starship
-                    if hits:
-                        bump += (game.sector-hits[-1]).sgn()
-                elif iquad == 'K': # kill klingon
-                    deadkl(neighbor, iquad, neighbor)
-                elif iquad in ('C','S','R'): # Damage/destroy big enemies
-                    target = None
-                    for ll in range(len(game.enemies)):
-                        if game.enemies[ll].location == neighbor:
-                            target = game.enemies[ll]
-                            break
-                    if target is not None:
-                        target.power -= 800.0 # If firepower is lost, die
-                        if target.power <= 0.0:
-                            deadkl(neighbor, iquad, neighbor)
-                            continue   # neighbor loop
-                        # Else enemy gets flung by the blast wave
-                        newc = neighbor + neighbor - start
-                        proutn(crmena(True, iquad, "sector", neighbor) + _(" damaged"))
-                        if not newc.valid_sector():
-                            # can't leave quadrant
-                            skip(1)
-                            continue
-                        iquad1 = game.quad[newc.i][newc.j]
-                        if iquad1 == ' ':
-                            proutn(_(", blasted into ") + crmena(False, ' ', "sector", newc))
-                            skip(1)
-                            deadkl(neighbor, iquad, newc)
-                            continue
-                        if iquad1 != '.':
-                            # can't move into something else
-                            skip(1)
-                            continue
-                        proutn(_(", buffeted to Sector %s") % newc)
-                        game.quad[neighbor.i][neighbor.j] = '.'
-                        game.quad[newc.i][newc.j] = iquad
-                        target.move(newc)
-    # Starship affected by nova -- kick it away.
-    dist = kount*0.1
-    direc = ncourse[3*(bump.i+1)+bump.j+2]
-    if direc == 0.0:
-        dist = 0.0
-    if dist == 0.0:
-        return
-    scourse = course(bearing=direc, distance=dist)
-    game.optime = scourse.time(w=4)
-    skip(1)
-    prout(_("Force of nova displaces starship."))
-    imove(scourse, noattack=True)
-    game.optime = scourse.time(w=4)
-    return
-
-def supernova(w):
-    "Star goes supernova."
-    num = 0; npdead = 0
-    if w is not None:
-        nq = copy.copy(w)
-    else:
-        # Scheduled supernova -- select star at random.
-        nstars = 0
-        nq = Coord()
-        for nq.i in range(GALSIZE):
-            for nq.j in range(GALSIZE):
-                nstars += game.state.galaxy[nq.i][nq.j].stars
-        if stars == 0:
-            return # nothing to supernova exists
-        num = rnd.integer(nstars) + 1
-        for nq.i in range(GALSIZE):
-            for nq.j in range(GALSIZE):
-                num -= game.state.galaxy[nq.i][nq.j].stars
-                if num <= 0:
-                    break
-            if num <=0:
-                break
-        if game.idebug:
-            proutn("=== Super nova here?")
-            if ja():
-                nq = game.quadrant
-    if not nq == game.quadrant or game.justin:
-        # it isn't here, or we just entered (treat as enroute)
-        if communicating():
-            skip(1)
-            prout(_("Message from Starfleet Command       Stardate %.2f") % game.state.date)
-            prout(_("     Supernova in Quadrant %s; caution advised.") % nq)
-    else:
-        ns = Coord()
-        # we are in the quadrant!
-        num = rnd.integer(game.state.galaxy[nq.i][nq.j].stars) + 1
-        for ns.i in range(QUADSIZE):
-            for ns.j in range(QUADSIZE):
-                if game.quad[ns.i][ns.j]=='*':
-                    num -= 1
-                    if num==0:
-                        break
-            if num==0:
-                break
-        skip(1)
-        prouts(_("***RED ALERT!  RED ALERT!"))
-        skip(1)
-        prout(_("***Incipient supernova detected at Sector %s") % ns)
-        if (ns.i-game.sector.i)**2 + (ns.j-game.sector.j)**2 <= 2.1:
-            proutn(_("Emergency override attempts t"))
-            prouts("***************")
-            skip(1)
-            stars()
-            game.alldone = True
-    # destroy any Klingons in supernovaed quadrant
-    game.state.galaxy[nq.i][nq.j].klingons = 0
-    if nq == game.state.kscmdr:
-        # did in the Supercommander!
-        game.state.nscrem = game.state.kscmdr.i = game.state.kscmdr.j = game.isatb =  0
-        game.iscate = False
-        unschedule(FSCMOVE)
-        unschedule(FSCDBAS)
-    # Changing this to [w for w in game.state.kcmdr if w != nq]
-    # causes regression-test failure
-    survivors = list(filter(lambda w: w != nq, game.state.kcmdr))
-    #comkills = len(game.state.kcmdr) - len(survivors)
-    game.state.kcmdr = survivors
-    if not game.state.kcmdr:
-        unschedule(FTBEAM)
-    # destroy Romulans and planets in supernovaed quadrant
-    nrmdead = game.state.galaxy[nq.i][nq.j].romulans
-    game.state.galaxy[nq.i][nq.j].romulans = 0
-    game.state.nromrem -= nrmdead
-    # Destroy planets
-    for loop in range(game.inplan):
-        if game.state.planets[loop].quadrant == nq:
-            game.state.planets[loop].pclass = "destroyed"
-            npdead += 1
-    # Destroy any base in supernovaed quadrant
-    game.state.baseq = [x for x in game.state.baseq if x != nq]
-    # If starship caused supernova, tally up destruction
-    if w is not None:
-        game.state.starkl += game.state.galaxy[nq.i][nq.j].stars
-        game.state.basekl += game.state.galaxy[nq.i][nq.j].starbase
-        game.state.nplankl += npdead
-    # mark supernova in galaxy and in star chart
-    if game.quadrant == nq or communicating():
-        game.state.galaxy[nq.i][nq.j].supernova = True
-    # If supernova destroys last Klingons give special message
-    if game.unwon()==0 and not nq == game.quadrant:
-        skip(2)
-        if w is None:
-            prout(_("Lucky you!"))
-        proutn(_("A supernova in %s has just destroyed the last Klingons.") % nq)
-        finish(FWON)
-        return
-    # if some Klingons remain, continue or die in supernova
-    if game.alldone:
-        finish(FSNOVAED)
-    return
-
-# Code from finish.c ends here.
-
-def selfdestruct():
-    "Self-destruct maneuver. Finish with a BANG!"
-    scanner.chew()
-    if damaged(DCOMPTR):
-        prout(_("Computer damaged; cannot execute destruct sequence."))
-        return
-    prouts(_("---WORKING---")); skip(1)
-    prouts(_("SELF-DESTRUCT-SEQUENCE-ACTIVATED")); skip(1)
-    prouts("   10"); skip(1)
-    prouts("       9"); skip(1)
-    prouts("          8"); skip(1)
-    prouts("             7"); skip(1)
-    prouts("                6"); skip(1)
-    skip(1)
-    prout(_("ENTER-CORRECT-PASSWORD-TO-CONTINUE-"))
-    skip(1)
-    prout(_("SELF-DESTRUCT-SEQUENCE-OTHERWISE-"))
-    skip(1)
-    prout(_("SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED"))
-    skip(1)
-    scanner.nexttok()
-    if game.passwd != scanner.token:
-        prouts(_("PASSWORD-REJECTED;"))
-        skip(1)
-        prouts(_("CONTINUITY-EFFECTED"))
-        skip(2)
-        return
-    prouts(_("PASSWORD-ACCEPTED")); skip(1)
-    prouts("                   5"); skip(1)
-    prouts("                      4"); skip(1)
-    prouts("                         3"); skip(1)
-    prouts("                            2"); skip(1)
-    prouts("                              1"); skip(1)
-    if rnd.withprob(0.15):
-        prouts(_("GOODBYE-CRUEL-WORLD"))
-        skip(1)
-    kaboom()
-
-def kaboom():
-    stars()
-    if game.ship=='E':
-        prouts("***")
-    prouts(_("********* Entropy of %s maximized *********") % crmshp())
-    skip(1)
-    stars()
-    skip(1)
-    if len(game.enemies) != 0:
-        whammo = 25.0 * game.energy
-        for e in game.enemies[::-1]:
-            if e.power*e.kdist <= whammo:
-                deadkl(e.location, game.quad[e.location.i][e.location.j], e.location)
-    finish(FDILITHIUM)
-
-def killrate():
-    "Compute our rate of kils over time."
-    elapsed = game.state.date - game.indate
-    if elapsed == 0:        # Avoid divide-by-zero error if calculated on turn 0
-        return 0
-    else:
-        starting = (game.inkling + game.incom + game.inscom)
-        remaining = game.unwon()
-        return (starting - remaining)/elapsed
-
-def badpoints():
-    "Compute demerits."
-    badpt = 5.0*game.state.starkl + \
-            game.casual + \
-            10.0*game.state.nplankl + \
-            300*game.state.nworldkl + \
-            45.0*game.nhelp +\
-            100.0*game.state.basekl +\
-            3.0*game.abandoned +\
-            100*game.ncviol
-    if game.ship == 'F':
-        badpt += 100.0
-    elif game.ship is None:
-        badpt += 200.0
-    return badpt
-
-def finish(ifin):
-    # end the game, with appropriate notifications
-    igotit = False
-    game.alldone = True
-    skip(3)
-    prout(_("It is stardate %.1f.") % game.state.date)
-    skip(1)
-    if ifin == FWON: # Game has been won
-        if game.state.nromrem != 0:
-            prout(_("The remaining %d Romulans surrender to Starfleet Command.") %
-                  game.state.nromrem)
-
-        prout(_("You have smashed the Klingon invasion fleet and saved"))
-        prout(_("the Federation."))
-        if game.alive and game.brigcapacity-game.brigfree > 0:
-            game.kcaptured += game.brigcapacity-game.brigfree
-            prout(_("The %d captured Klingons are transferred to Star Fleet Command.") % (game.brigcapacity-game.brigfree))
-        game.gamewon = True
-        if game.alive:
-            badpt = badpoints()
-            if badpt < 100.0:
-                badpt = 0.0        # Close enough!
-            # killsPerDate >= RateMax
-            if game.state.date-game.indate < 5.0 or \
-                killrate() >= 0.1*game.skill*(game.skill+1.0) + 0.1 + 0.008*badpt:
-                skip(1)
-                prout(_("In fact, you have done so well that Starfleet Command"))
-                if game.skill == SKILL_NOVICE:
-                    prout(_("promotes you one step in rank from \"Novice\" to \"Fair\"."))
-                elif game.skill == SKILL_FAIR:
-                    prout(_("promotes you one step in rank from \"Fair\" to \"Good\"."))
-                elif game.skill == SKILL_GOOD:
-                    prout(_("promotes you one step in rank from \"Good\" to \"Expert\"."))
-                elif game.skill == SKILL_EXPERT:
-                    prout(_("promotes you to Commodore Emeritus."))
-                    skip(1)
-                    prout(_("Now that you think you're really good, try playing"))
-                    prout(_("the \"Emeritus\" game. It will splatter your ego."))
-                elif game.skill == SKILL_EMERITUS:
-                    skip(1)
-                    proutn(_("Computer-  "))
-                    prouts(_("ERROR-ERROR-ERROR-ERROR"))
-                    skip(2)
-                    prouts(_("  YOUR-SKILL-HAS-EXCEEDED-THE-CAPACITY-OF-THIS-PROGRAM"))
-                    skip(1)
-                    prouts(_("  THIS-PROGRAM-MUST-SURVIVE"))
-                    skip(1)
-                    prouts(_("  THIS-PROGRAM-MUST-SURVIVE"))
-                    skip(1)
-                    prouts(_("  THIS-PROGRAM-MUST-SURVIVE"))
-                    skip(1)
-                    prouts(_("  THIS-PROGRAM-MUST?- MUST ? - SUR? ? -?  VI"))
-                    skip(2)
-                    prout(_("Now you can retire and write your own Star Trek game!"))
-                    skip(1)
-                elif game.skill >= SKILL_EXPERT:
-                    if game.thawed and not game.idebug:
-                        prout(_("You cannot get a citation, so..."))
-                    else:
-                        proutn(_("Do you want your Commodore Emeritus Citation printed? "))
-                        scanner.chew()
-                        if ja():
-                            igotit = True
-            # Only grant long life if alive (original didn't!)
-            skip(1)
-            prout(_("LIVE LONG AND PROSPER."))
-        score()
-        if igotit:
-            plaque()
-        return
-    elif ifin == FDEPLETE: # Federation Resources Depleted
-        prout(_("Your time has run out and the Federation has been"))
-        prout(_("conquered.  Your starship is now Klingon property,"))
-        prout(_("and you are put on trial as a war criminal.  On the"))
-        proutn(_("basis of your record, you are "))
-        if game.unwon()*3.0 > (game.inkling + game.incom + game.inscom):
-            prout(_("acquitted."))
-            skip(1)
-            prout(_("LIVE LONG AND PROSPER."))
-        else:
-            prout(_("found guilty and"))
-            prout(_("sentenced to death by slow torture."))
-            game.alive = False
-        score()
-        return
-    elif ifin == FLIFESUP:
-        prout(_("Your life support reserves have run out, and"))
-        prout(_("you die of thirst, starvation, and asphyxiation."))
-        prout(_("Your starship is a derelict in space."))
-    elif ifin == FNRG:
-        prout(_("Your energy supply is exhausted."))
-        skip(1)
-        prout(_("Your starship is a derelict in space."))
-    elif ifin == FBATTLE:
-        prout(_("The %s has been destroyed in battle.") % crmshp())
-        skip(1)
-        prout(_("Dulce et decorum est pro patria mori."))
-    elif ifin == FNEG3:
-        prout(_("You have made three attempts to cross the negative energy"))
-        prout(_("barrier which surrounds the galaxy."))
-        skip(1)
-        prout(_("Your navigation is abominable."))
-        score()
-    elif ifin == FNOVA:
-        prout(_("Your starship has been destroyed by a nova."))
-        prout(_("That was a great shot."))
-        skip(1)
-    elif ifin == FSNOVAED:
-        prout(_("The %s has been fried by a supernova.") % crmshp())
-        prout(_("...Not even cinders remain..."))
-    elif ifin == FABANDN:
-        prout(_("You have been captured by the Klingons. If you still"))
-        prout(_("had a starbase to be returned to, you would have been"))
-        prout(_("repatriated and given another chance. Since you have"))
-        prout(_("no starbases, you will be mercilessly tortured to death."))
-    elif ifin == FDILITHIUM:
-        prout(_("Your starship is now an expanding cloud of subatomic particles"))
-    elif ifin == FMATERIALIZE:
-        prout(_("Starbase was unable to re-materialize your starship."))
-        prout(_("Sic transit gloria mundi"))
-    elif ifin == FPHASER:
-        prout(_("The %s has been cremated by its own phasers.") % crmshp())
-    elif ifin == FLOST:
-        prout(_("You and your landing party have been"))
-        prout(_("converted to energy, dissipating through space."))
-    elif ifin == FMINING:
-        prout(_("You are left with your landing party on"))
-        prout(_("a wild jungle planet inhabited by primitive cannibals."))
-        skip(1)
-        prout(_("They are very fond of \"Captain Kirk\" soup."))
-        skip(1)
-        prout(_("Without your leadership, the %s is destroyed.") % crmshp())
-    elif ifin == FDPLANET:
-        prout(_("You and your mining party perish."))
-        skip(1)
-        prout(_("That was a great shot."))
-        skip(1)
-    elif ifin == FSSC:
-        prout(_("The Galileo is instantly annihilated by the supernova."))
-        prout(_("You and your mining party are atomized."))
-        skip(1)
-        prout(_("Mr. Spock takes command of the %s and") % crmshp())
-        prout(_("joins the Romulans, wreaking terror on the Federation."))
-    elif ifin == FPNOVA:
-        prout(_("You and your mining party are atomized."))
-        skip(1)
-        prout(_("Mr. Spock takes command of the %s and") % crmshp())
-        prout(_("joins the Romulans, wreaking terror on the Federation."))
-    elif ifin == FSTRACTOR:
-        prout(_("The shuttle craft Galileo is also caught,"))
-        prout(_("and breaks up under the strain."))
-        skip(1)
-        prout(_("Your debris is scattered for millions of miles."))
-        prout(_("Without your leadership, the %s is destroyed.") % crmshp())
-    elif ifin == FDRAY:
-        prout(_("The mutants attack and kill Spock."))
-        prout(_("Your ship is captured by Klingons, and"))
-        prout(_("your crew is put on display in a Klingon zoo."))
-    elif ifin == FTRIBBLE:
-        prout(_("Tribbles consume all remaining water,"))
-        prout(_("food, and oxygen on your ship."))
-        skip(1)
-        prout(_("You die of thirst, starvation, and asphyxiation."))
-        prout(_("Your starship is a derelict in space."))
-    elif ifin == FHOLE:
-        prout(_("Your ship is drawn to the center of the black hole."))
-        prout(_("You are crushed into extremely dense matter."))
-    elif ifin == FCLOAK:
-        game.ncviol += 1
-        prout(_("You have violated the Treaty of Algeron."))
-        prout(_("The Romulan Empire can never trust you again."))
-    elif ifin == FCREW:
-        prout(_("Your last crew member has died."))
-    if ifin != FWON and ifin != FCLOAK and game.iscloaked:
-        prout(_("Your ship was cloaked so your subspace radio did not receive anything."))
-        prout(_("You may have missed some warning messages."))
-        skip(1)
-    if game.ship == 'F':
-        game.ship = None
-    elif game.ship == 'E':
-        game.ship = 'F'
-    game.alive = False
-    if game.unwon() != 0:
-        goodies = game.state.remres/game.inresor
-        baddies = (game.remkl() + 2.0*len(game.state.kcmdr))/(game.inkling+2.0*game.incom)
-        if goodies/baddies >= rnd.real(1.0, 1.5):
-            prout(_("As a result of your actions, a treaty with the Klingon"))
-            prout(_("Empire has been signed. The terms of the treaty are"))
-            if goodies/baddies >= rnd.real(3.0):
-                prout(_("favorable to the Federation."))
-                skip(1)
-                prout(_("Congratulations!"))
-            else:
-                prout(_("highly unfavorable to the Federation."))
-        else:
-            prout(_("The Federation will be destroyed."))
-    else:
-        prout(_("Since you took the last Klingon with you, you are a"))
-        prout(_("martyr and a hero. Someday maybe they'll erect a"))
-        prout(_("statue in your memory. Rest in peace, and try not"))
-        prout(_("to think about pigeons."))
-        game.gamewon = True
-    score()
-    scanner.chew()     # Clean up leftovers
-
-def score():
-    "Compute player's score."
-    timused = game.state.date - game.indate
-    if (timused == 0 or game.unwon() != 0) and timused < 5.0:
-        timused = 5.0
-    game.perdate = killrate()
-    ithperd = 500*game.perdate + 0.5
-    iwon = 0
-    if game.gamewon:
-        iwon = 100*game.skill
-    if game.ship == 'E':
-        klship = 0
-    elif game.ship == 'F':
-        klship = 1
-    else:
-        klship = 2
-    dead_ordinaries= game.inkling - game.remkl() + len(game.state.kcmdr) + game.state.nscrem
-    game.score = 10*(dead_ordinaries)\
-             + 50*(game.incom - len(game.state.kcmdr)) \
-             + ithperd + iwon \
-             + 20*(game.inrom - game.state.nromrem) \
-             + 200*(game.inscom - game.state.nscrem) \
-                 - game.state.nromrem \
-             + 3 * game.kcaptured \
-             - badpoints()
-    if not game.alive:
-        game.score -= 200
-    skip(2)
-    prout(_("Your score --"))
-    if game.inrom - game.state.nromrem:
-        prout(_("%6d Romulans destroyed                 %5d") %
-              (game.inrom - game.state.nromrem, 20*(game.inrom - game.state.nromrem)))
-    if game.state.nromrem and game.gamewon:
-        prout(_("%6d Romulans captured                  %5d") %
-              (game.state.nromrem, game.state.nromrem))
-    if dead_ordinaries:
-        prout(_("%6d ordinary Klingons destroyed        %5d") %
-              (dead_ordinaries, 10*dead_ordinaries))
-    if game.incom - len(game.state.kcmdr):
-        prout(_("%6d Klingon commanders destroyed       %5d") %
-              (game.incom - len(game.state.kcmdr), 50*(game.incom - len(game.state.kcmdr))))
-    if game.kcaptured:
-        prout(_("%d Klingons captured                   %5d") %
-              (game.kcaptured, 3 * game.kcaptured))
-    if game.inscom - game.state.nscrem:
-        prout(_("%6d Super-Commander destroyed          %5d") %
-              (game.inscom - game.state.nscrem, 200*(game.inscom - game.state.nscrem)))
-    if ithperd:
-        prout(_("%6.2f Klingons per stardate              %5d") %
-              (game.perdate, ithperd))
-    if game.state.starkl:
-        prout(_("%6d stars destroyed by your action     %5d") %
-              (game.state.starkl, -5*game.state.starkl))
-    if game.state.nplankl:
-        prout(_("%6d planets destroyed by your action   %5d") %
-              (game.state.nplankl, -10*game.state.nplankl))
-    if (game.options & OPTION_WORLDS) and game.state.nworldkl:
-        prout(_("%6d inhabited planets destroyed by your action   %5d") %
-              (game.state.nworldkl, -300*game.state.nworldkl))
-    if game.state.basekl:
-        prout(_("%6d bases destroyed by your action     %5d") %
-              (game.state.basekl, -100*game.state.basekl))
-    if game.nhelp:
-        prout(_("%6d calls for help from starbase       %5d") %
-              (game.nhelp, -45*game.nhelp))
-    if game.casual:
-        prout(_("%6d casualties incurred                %5d") %
-              (game.casual, -game.casual))
-    if game.abandoned:
-        prout(_("%6d crew abandoned in space            %5d") %
-              (game.abandoned, -3*game.abandoned))
-    if klship:
-        prout(_("%6d ship(s) lost or destroyed          %5d") %
-              (klship, -100*klship))
-    if game.ncviol > 0:
-        if game.ncviol == 1:
-            prout(_("1 Treaty of Algeron violation          -100"))
-        else:
-            prout(_("%6d Treaty of Algeron violations       %5d\n") %
-                  (game.ncviol, -100*game.ncviol))
-    if not game.alive:
-        prout(_("Penalty for getting yourself killed        -200"))
-    if game.gamewon:
-        proutn(_("Bonus for winning "))
-        if game.skill   == SKILL_NOVICE:        proutn(_("Novice game  "))
-        elif game.skill == SKILL_FAIR:          proutn(_("Fair game    "))
-        elif game.skill ==  SKILL_GOOD:         proutn(_("Good game    "))
-        elif game.skill ==  SKILL_EXPERT:        proutn(_("Expert game  "))
-        elif game.skill ==  SKILL_EMERITUS:        proutn(_("Emeritus game"))
-        prout("           %5d" % iwon)
-    skip(1)
-    prout(_("TOTAL SCORE                               %5d") % game.score)
-
-def plaque():
-    "Emit winner's commemmorative plaque."
-    skip(2)
-    while True:
-        proutn(_("File or device name for your plaque: "))
-        winner = cgetline()
-        try:
-            fp = open(winner, "w")
-            break
-        except IOError:
-            prout(_("Invalid name."))
-
-    proutn(_("Enter name to go on plaque (up to 30 characters): "))
-    winner = cgetline()
-    # The 38 below must be 64 for 132-column paper
-    nskip = 38 - len(winner)/2
-    # This is where the ASCII art picture was emitted.
-    # It got garbled somewhere in the chain of transmission to the Almy version.
-    # We should restore it if we can find old enough FORTRAN sources.
-    fp.write("\n\n\n")
-    fp.write(_("                                                       U. S. S. ENTERPRISE\n"))
-    fp.write("\n\n\n\n")
-    fp.write(_("                                  For demonstrating outstanding ability as a starship captain\n"))
-    fp.write("\n")
-    fp.write(_("                                                Starfleet Command bestows to you\n"))
-    fp.write("\n")
-    fp.write("%*s%s\n\n" % (nskip, "", winner))
-    fp.write(_("                                                           the rank of\n\n"))
-    fp.write(_("                                                       \"Commodore Emeritus\"\n\n"))
-    fp.write("                                                          ")
-    if game.skill ==  SKILL_EXPERT:
-        fp.write(_(" Expert level\n\n"))
-    elif game.skill == SKILL_EMERITUS:
-        fp.write(_("Emeritus level\n\n"))
-    else:
-        fp.write(_(" Cheat level\n\n"))
-    timestring = time.ctime()
-    fp.write(_("                                                 This day of %.6s %.4s, %.8s\n\n") %
-             (timestring+4, timestring+20, timestring+11))
-    fp.write(_("                                                        Your score:  %d\n\n") % game.score)
-    fp.write(_("                                                    Klingons per stardate:  %.2f\n") % game.perdate)
-    fp.close()
-
-# Code from io.c begins here
-
-rows = linecount = 0        # for paging
-stdscr = None
-replayfp = None
-fullscreen_window = None
-srscan_window     = None   # Short range scan
-report_window     = None   # Report legends for status window
-status_window     = None   # The status window itself
-lrscan_window     = None   # Long range scan
-message_window    = None   # Main window for scrolling text
-prompt_window     = None   # Prompt window at bottom of display
-curwnd = None
-
-def iostart():
-    global stdscr, rows
-    # for some recent versions of python2, the following enables UTF8
-    # for the older ones we probably need to set C locale, and python3
-    # has no problems at all
-    if sys.version_info[0] < 3:
-        locale.setlocale(locale.LC_ALL, "")
-    gettext.bindtextdomain("sst", "/usr/local/share/locale")
-    gettext.textdomain("sst")
-    if not (game.options & OPTION_CURSES):
-        ln_env = os.getenv("LINES")
-        if ln_env:
-            rows = ln_env
-        else:
-            rows = 25
-    else:
-        stdscr = curses.initscr()
-        stdscr.keypad(True)
-        curses.nonl()
-        curses.cbreak()
-        if game.options & OPTION_COLOR:
-            curses.start_color()
-            curses.use_default_colors()
-            curses.init_pair(curses.COLOR_BLACK,   curses.COLOR_BLACK, -1)
-            curses.init_pair(curses.COLOR_GREEN,   curses.COLOR_GREEN, -1)
-            curses.init_pair(curses.COLOR_RED,     curses.COLOR_RED, -1)
-            curses.init_pair(curses.COLOR_CYAN,    curses.COLOR_CYAN, -1)
-            curses.init_pair(curses.COLOR_WHITE,   curses.COLOR_WHITE, -1)
-            curses.init_pair(curses.COLOR_MAGENTA, curses.COLOR_MAGENTA, -1)
-            curses.init_pair(curses.COLOR_BLUE,    curses.COLOR_BLUE, -1)
-            curses.init_pair(curses.COLOR_YELLOW,  curses.COLOR_YELLOW, -1)
-        global fullscreen_window, srscan_window, report_window, status_window
-        global lrscan_window, message_window, prompt_window
-        (rows, _columns)   = stdscr.getmaxyx()
-        fullscreen_window = stdscr
-        srscan_window     = curses.newwin(12, 25, 0,       0)
-        report_window     = curses.newwin(11, 0,  1,       25)
-        status_window     = curses.newwin(10, 0,  1,       39)
-        lrscan_window     = curses.newwin(5,  0,  0,       64)
-        message_window    = curses.newwin(0,  0,  12,      0)
-        prompt_window     = curses.newwin(1,  0,  rows-2,  0)
-        message_window.scrollok(True)
-        setwnd(fullscreen_window)
-
-def ioend():
-    "Wrap up I/O."
-    if game.options & OPTION_CURSES:
-        stdscr.keypad(False)
-        curses.echo()
-        curses.nocbreak()
-        curses.endwin()
-
-def waitfor():
-    "Wait for user action -- OK to do nothing if on a TTY"
-    if game.options & OPTION_CURSES:
-        stdscr.getch()
-
-def announce():
-    skip(1)
-    prouts(_("[ANNOUNCEMENT ARRIVING...]"))
-    skip(1)
-
-def pause_game():
-    if game.skill > SKILL_FAIR:
-        prompt = _("[CONTINUE?]")
-    else:
-        prompt = _("[PRESS ENTER TO CONTINUE]")
-
-    if game.options & OPTION_CURSES:
-        drawmaps(0)
-        setwnd(prompt_window)
-        prompt_window.clear()
-        prompt_window.addstr(prompt)
-        prompt_window.getstr()
-        prompt_window.clear()
-        prompt_window.refresh()
-        setwnd(message_window)
-    else:
-        global linecount
-        sys.stdout.write('\n')
-        proutn(prompt)
-        if not replayfp:
-            my_input()
-        sys.stdout.write('\n' * rows)
-        linecount = 0
-
-def skip(i):
-    "Skip i lines.  Pause game if this would cause a scrolling event."
-    for _dummy in range(i):
-        if game.options & OPTION_CURSES:
-            (y, _x) = curwnd.getyx()
-            try:
-                curwnd.move(y+1, 0)
-            except curses.error:
-                pass
-        else:
-            global linecount
-            linecount += 1
-            if rows and linecount >= rows:
-                pause_game()
-            else:
-                sys.stdout.write('\n')
-
-def proutn(proutntline):
-    "Utter a line with no following line feed."
-    if game.options & OPTION_CURSES:
-        (y, x) = curwnd.getyx()
-        (my, _mx) = curwnd.getmaxyx()
-        if curwnd == message_window and y >= my - 2:
-            pause_game()
-            clrscr()
-        if logfp and game.cdebug:
-            logfp.write("#curses: at %s proutn(%s)\n" % ((y, x), repr(proutntline)))
-        curwnd.addstr(proutntline)
-        curwnd.refresh()
-    else:
-        sys.stdout.write(proutntline)
-        sys.stdout.flush()
-
-def prout(proutline):
-    proutn(proutline)
-    skip(1)
-
-def prouts(proutsline):
-    "Emit slowly!"
-    for c in proutsline:
-        if not replayfp or replayfp.closed:        # Don't slow down replays
-            time.sleep(0.03)
-        proutn(c)
-        if game.options & OPTION_CURSES:
-            curwnd.refresh()
-        else:
-            sys.stdout.flush()
-    if not replayfp or replayfp.closed:
-        time.sleep(0.03)
-
-def cgetline():
-    "Get a line of input."
-    if game.options & OPTION_CURSES:
-        linein = curwnd.getstr() + "\n"
-        curwnd.refresh()
-    else:
-        if replayfp and not replayfp.closed:
-            while True:
-                linein = replayfp.readline()
-                proutn(linein)
-                if linein == '':
-                    prout("*** Replay finished")
-                    replayfp.close()
-                    break
-                elif linein[0] != "#":
-                    break
-        else:
-            try:
-                linein = my_input() + "\n"
-            except EOFError:
-                prout("")
-                sys.exit(0)
-    if logfp:
-        logfp.write(linein)
-    return linein
-
-def setwnd(wnd):
-    "Change windows -- OK for this to be a no-op in tty mode."
-    global curwnd
-    if game.options & OPTION_CURSES:
-        if game.cdebug and logfp:
-            if wnd == fullscreen_window:
-                legend = "fullscreen"
-            elif wnd == srscan_window:
-                legend = "srscan"
-            elif wnd == report_window:
-                legend = "report"
-            elif wnd == status_window:
-                legend = "status"
-            elif wnd == lrscan_window:
-                legend = "lrscan"
-            elif wnd == message_window:
-                legend = "message"
-            elif wnd == prompt_window:
-                legend = "prompt"
-            else:
-                legend = "unknown"
-            logfp.write("#curses: setwnd(%s)\n" % legend)
-        curwnd = wnd
-        # Some curses implementations get confused when you try this.
-        try:
-            curses.curs_set(wnd in (fullscreen_window, message_window, prompt_window))
-        except curses.error:
-            pass
-
-def clreol():
-    "Clear to end of line -- can be a no-op in tty mode"
-    if game.options & OPTION_CURSES:
-        curwnd.clrtoeol()
-        curwnd.refresh()
-
-def clrscr():
-    "Clear screen -- can be a no-op in tty mode."
-    global linecount
-    if game.options & OPTION_CURSES:
-        curwnd.clear()
-        curwnd.move(0, 0)
-        curwnd.refresh()
-    linecount = 0
-
-def textcolor(color=DEFAULT):
-    if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES):
-        if color == DEFAULT:
-            curwnd.attrset(0)
-        elif color ==  BLACK:
-            curwnd.attron(curses.color_pair(curses.COLOR_BLACK))
-        elif color ==  BLUE:
-            curwnd.attron(curses.color_pair(curses.COLOR_BLUE))
-        elif color ==  GREEN:
-            curwnd.attron(curses.color_pair(curses.COLOR_GREEN))
-        elif color ==  CYAN:
-            curwnd.attron(curses.color_pair(curses.COLOR_CYAN))
-        elif color ==  RED:
-            curwnd.attron(curses.color_pair(curses.COLOR_RED))
-        elif color ==  MAGENTA:
-            curwnd.attron(curses.color_pair(curses.COLOR_MAGENTA))
-        elif color ==  BROWN:
-            curwnd.attron(curses.color_pair(curses.COLOR_YELLOW))
-        elif color ==  LIGHTGRAY:
-            curwnd.attron(curses.color_pair(curses.COLOR_WHITE))
-        elif color ==  DARKGRAY:
-            curwnd.attron(curses.color_pair(curses.COLOR_BLACK) | curses.A_BOLD)
-        elif color ==  LIGHTBLUE:
-            curwnd.attron(curses.color_pair(curses.COLOR_BLUE) | curses.A_BOLD)
-        elif color ==  LIGHTGREEN:
-            curwnd.attron(curses.color_pair(curses.COLOR_GREEN) | curses.A_BOLD)
-        elif color ==  LIGHTCYAN:
-            curwnd.attron(curses.color_pair(curses.COLOR_CYAN) | curses.A_BOLD)
-        elif color ==  LIGHTRED:
-            curwnd.attron(curses.color_pair(curses.COLOR_RED) | curses.A_BOLD)
-        elif color ==  LIGHTMAGENTA:
-            curwnd.attron(curses.color_pair(curses.COLOR_MAGENTA) | curses.A_BOLD)
-        elif color ==  YELLOW:
-            curwnd.attron(curses.color_pair(curses.COLOR_YELLOW) | curses.A_BOLD)
-        elif color ==  WHITE:
-            curwnd.attron(curses.color_pair(curses.COLOR_WHITE) | curses.A_BOLD)
-
-def highvideo():
-    if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES):
-        curwnd.attron(curses.A_REVERSE)
-
-#
-# Things past this point have policy implications.
-#
-
-def drawmaps(mode):
-    "Hook to be called after moving to redraw maps."
-    if game.options & OPTION_CURSES:
-        if mode == 1:
-            sensor()
-        setwnd(srscan_window)
-        curwnd.move(0, 0)
-        srscan()
-        if mode != 2:
-            setwnd(status_window)
-            status_window.clear()
-            status_window.move(0, 0)
-            setwnd(report_window)
-            report_window.clear()
-            report_window.move(0, 0)
-            status()
-            setwnd(lrscan_window)
-            lrscan_window.clear()
-            lrscan_window.move(0, 0)
-            lrscan(silent=False)
-
-def put_srscan_sym(w, sym):
-    "Emit symbol for short-range scan."
-    srscan_window.move(w.i+1, w.j*2+2)
-    srscan_window.addch(sym)
-    srscan_window.refresh()
-
-def boom(w):
-    "Enemy fall down, go boom."
-    if game.options & OPTION_CURSES:
-        drawmaps(0)
-        setwnd(srscan_window)
-        srscan_window.attron(curses.A_REVERSE)
-        put_srscan_sym(w, game.quad[w.i][w.j])
-        #sound(500)
-        #time.sleep(1.0)
-        #nosound()
-        srscan_window.attroff(curses.A_REVERSE)
-        put_srscan_sym(w, game.quad[w.i][w.j])
-        curses.delay_output(500)
-        setwnd(message_window)
-
-def warble():
-    "Sound and visual effects for teleportation."
-    if game.options & OPTION_CURSES:
-        drawmaps(2)
-        setwnd(message_window)
-        #sound(50)
-    prouts("     . . . . .     ")
-    if game.options & OPTION_CURSES:
-        #curses.delay_output(1000)
-        #nosound()
-        pass
-
-def tracktorpedo(w, step, i, n, iquad):
-    "Torpedo-track animation."
-    if not game.options & OPTION_CURSES:
-        if step == 1:
-            if n != 1:
-                skip(1)
-                proutn(_("Track for torpedo number %d-  ") % (i+1))
-            else:
-                skip(1)
-                proutn(_("Torpedo track- "))
-        elif step==4 or step==9:
-            skip(1)
-        proutn("%s   " % w)
-    else:
-        if not damaged(DSRSENS) or game.condition=="docked":
-            if i != 0 and step == 1:
-                drawmaps(2)
-                time.sleep(0.4)
-            if (iquad=='.') or (iquad==' '):
-                put_srscan_sym(w, '+')
-                #sound(step*10)
-                #time.sleep(0.1)
-                #nosound()
-                put_srscan_sym(w, iquad)
-            else:
-                curwnd.attron(curses.A_REVERSE)
-                put_srscan_sym(w, iquad)
-                #sound(500)
-                #time.sleep(1.0)
-                #nosound()
-                curwnd.attroff(curses.A_REVERSE)
-                put_srscan_sym(w, iquad)
-        else:
-            proutn("%s   " % w)
-
-def makechart():
-    "Display the current galaxy chart."
-    if game.options & OPTION_CURSES:
-        setwnd(message_window)
-        message_window.clear()
-    chart()
-    if game.options & OPTION_TTY:
-        skip(1)
-
-NSYM        = 14
-
-def prstat(txt, data):
-    proutn(txt)
-    if game.options & OPTION_CURSES:
-        skip(1)
-        setwnd(status_window)
-    else:
-        proutn(" " * (NSYM - len(txt)))
-    proutn(data)
-    skip(1)
-    if game.options & OPTION_CURSES:
-        setwnd(report_window)
-
-# Code from moving.c begins here
-
-def imove(icourse=None, noattack=False):
-    "Movement execution for warp, impulse, supernova, and tractor-beam events."
-    w = Coord()
-
-    def newquadrant(noattack):
-        # Leaving quadrant -- allow final enemy attack
-        # Don't set up attack if being pushed by nova or cloaked
-        if len(game.enemies) != 0 and not noattack and not game.iscloaked:
-            newcnd()
-            for enemy in game.enemies:
-                finald = (w - enemy.location).distance()
-                enemy.kavgd = 0.5 * (finald + enemy.kdist)
-            # Stas Sergeev added the condition
-            # that attacks only happen if Klingons
-            # are present and your skill is good.
-            if game.skill > SKILL_GOOD and game.klhere > 0 and not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-                attack(torps_ok=False)
-            if game.alldone:
-                return
-        # check for edge of galaxy
-        kinks = 0
-        while True:
-            kink = False
-            if icourse.final.i < 0:
-                icourse.final.i = -icourse.final.i
-                kink = True
-            if icourse.final.j < 0:
-                icourse.final.j = -icourse.final.j
-                kink = True
-            if icourse.final.i >= GALSIZE*QUADSIZE:
-                icourse.final.i = (GALSIZE*QUADSIZE*2) - icourse.final.i
-                kink = True
-            if icourse.final.j >= GALSIZE*QUADSIZE:
-                icourse.final.j = (GALSIZE*QUADSIZE*2) - icourse.final.j
-                kink = True
-            if kink:
-                kinks += 1
-            else:
-                break
-        if kinks:
-            game.nkinks += 1
-            if game.nkinks == 3:
-                # Three strikes -- you're out!
-                finish(FNEG3)
-                return
-            skip(1)
-            prout(_("YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER"))
-            prout(_("AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,"))
-            prout(_("YOU WILL BE DESTROYED."))
-        # Compute final position in new quadrant
-        if trbeam: # Don't bother if we are to be beamed
-            return
-        game.quadrant = icourse.final.quadrant()
-        game.sector = icourse.final.sector()
-        skip(1)
-        prout(_("Entering Quadrant %s.") % game.quadrant)
-        game.quad[game.sector.i][game.sector.j] = game.ship
-        newqad()
-        if game.skill>SKILL_NOVICE:
-            attack(torps_ok=False)
-
-    def check_collision(h):
-        iquad = game.quad[h.i][h.j]
-        if iquad != '.':
-            # object encountered in flight path
-            stopegy = 50.0*icourse.distance/game.optime
-            if iquad in ('T', 'K', 'C', 'S', 'R', '?'):
-                for enemy in game.enemies:
-                    if enemy.location == game.sector:
-                        collision(rammed=False, enemy=enemy)
-                        return True
-                # This should not happen
-                prout(_("Which way did he go?"))
-                return False
-            elif iquad == ' ':
-                skip(1)
-                prouts(_("***RED ALERT!  RED ALERT!"))
-                skip(1)
-                proutn("***" + crmshp())
-                proutn(_(" pulled into black hole at Sector %s") % h)
-                # Getting pulled into a black hole was certain
-                # death in Almy's original.  Stas Sergeev added a
-                # possibility that you'll get timewarped instead.
-                n=0
-                for m in range(NDEVICES):
-                    if game.damage[m]>0:
-                        n += 1
-                probf=math.pow(1.4,(game.energy+game.shield)/5000.0-1.0)*math.pow(1.3,1.0/(n+1)-1.0)
-                if (game.options & OPTION_BLKHOLE) and rnd.withprob(1-probf):
-                    timwrp()
-                else:
-                    finish(FHOLE)
-                return True
-            else:
-                # something else
-                skip(1)
-                proutn(crmshp())
-                if iquad == '#':
-                    prout(_(" encounters Tholian web at %s;") % h)
-                else:
-                    prout(_(" blocked by object at %s;") % h)
-                proutn(_("Emergency stop required "))
-                prout(_("%2d units of energy.") % int(stopegy))
-                game.energy -= stopegy
-                if game.energy <= 0:
-                    finish(FNRG)
-                return True
-        return False
-
-    trbeam = False
-    if game.inorbit:
-        prout(_("Helmsman Sulu- \"Leaving standard orbit.\""))
-        game.inorbit = False
-    # If tractor beam is to occur, don't move full distance
-    if game.state.date+game.optime >= scheduled(FTBEAM):
-        if game.iscloaked:
-            # We can't be tractor beamed if cloaked,
-            # so move the event into the future
-            postpone(FTBEAM, game.optime + expran(1.5*game.intime/len(game.kcmdr)))
-        else:
-            trbeam = True
-            game.condition = "red"
-            icourse.distance = icourse.distance*(scheduled(FTBEAM)-game.state.date)/game.optime + 0.1
-            game.optime = scheduled(FTBEAM) - game.state.date + 1e-5
-    # Move out
-    game.quad[game.sector.i][game.sector.j] = '.'
-    for _m in range(icourse.moves):
-        icourse.nexttok()
-        w = icourse.sector()
-        if icourse.origin.quadrant() != icourse.location.quadrant():
-            newquadrant(noattack)
-            break
-        elif check_collision(w):
-            prout(_("Collision detected"))
-            break
-        else:
-            game.sector = w
-    # We're in destination quadrant -- compute new average enemy distances
-    game.quad[game.sector.i][game.sector.j] = game.ship
-    if game.enemies:
-        for enemy in game.enemies:
-            finald = (w-enemy.location).distance()
-            enemy.kavgd = 0.5 * (finald + enemy.kdist)
-            enemy.kdist = finald
-        sortenemies()
-        if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-            attack(torps_ok=False)
-        for enemy in game.enemies:
-            enemy.kavgd = enemy.kdist
-    newcnd()
-    drawmaps(0)
-    setwnd(message_window)
-    return
-
-def dock(verbose):
-    "Dock our ship at a starbase."
-    scanner.chew()
-    if game.condition == "docked" and verbose:
-        prout(_("Already docked."))
-        return
-    if game.inorbit:
-        prout(_("You must first leave standard orbit."))
-        return
-    if game.base is None or abs(game.sector.i-game.base.i) > 1 or abs(game.sector.j-game.base.j) > 1:
-        prout(crmshp() + _(" not adjacent to base."))
-        return
-    if game.iscloaked:
-        prout(_("You cannot dock while cloaked."))
-        return
-    game.condition = "docked"
-    if verbose:
-        prout(_("Docked."))
-    game.ididit = True
-    if game.energy < game.inenrg:
-        game.energy = game.inenrg
-    game.shield = game.inshld
-    game.torps = game.intorps
-    game.lsupres = game.inlsr
-    game.state.crew = FULLCREW
-    if game.brigcapacity-game.brigfree > 0:
-        prout(_("%d captured Klingons transferred to base") % (game.brigcapacity-game.brigfree))
-        game.kcaptured += game.brigcapacity-game.brigfree
-        game.brigfree = game.brigcapacity
-    if communicating() and \
-        ((is_scheduled(FCDBAS) or game.isatb == 1) and not game.iseenit):
-        # get attack report from base
-        prout(_("Lt. Uhura- \"Captain, an important message from the starbase:\""))
-        attackreport(False)
-        game.iseenit = True
-
-def cartesian(loc1=None, loc2=None):
-    if loc1 is None:
-        return game.quadrant * QUADSIZE + game.sector
-    elif loc2 is None:
-        return game.quadrant * QUADSIZE + loc1
-    else:
-        return loc1 * QUADSIZE + loc2
-
-def getcourse(isprobe):
-    "Get a course and distance from the user."
-    key = ""
-    dquad = copy.copy(game.quadrant)
-    navmode = "unspecified"
-    itemp = "curt"
-    dsect = Coord()
-    iprompt = False
-    if game.landed and not isprobe:
-        prout(_("Dummy! You can't leave standard orbit until you"))
-        proutn(_("are back aboard the ship."))
-        scanner.chew()
-        raise TrekError
-    while navmode == "unspecified":
-        if damaged(DNAVSYS):
-            if isprobe:
-                prout(_("Computer damaged; manual navigation only"))
-            else:
-                prout(_("Computer damaged; manual movement only"))
-            scanner.chew()
-            navmode = "manual"
-            key = "IHEOL"
-            break
-        key = scanner.nexttok()
-        if key == "IHEOL":
-            proutn(_("Manual or automatic- "))
-            iprompt = True
-            scanner.chew()
-        elif key == "IHALPHA":
-            if scanner.sees("manual"):
-                navmode = "manual"
-                key = scanner.nexttok()
-                break
-            elif scanner.sees("automatic"):
-                navmode = "automatic"
-                key = scanner.nexttok()
-                break
-            else:
-                huh()
-                scanner.chew()
-                raise TrekError
-        else: # numeric
-            if isprobe:
-                prout(_("(Manual navigation assumed.)"))
-            else:
-                prout(_("(Manual movement assumed.)"))
-            navmode = "manual"
-            break
-    delta = Coord()
-    if navmode == "automatic":
-        while key == "IHEOL":
-            if isprobe:
-                proutn(_("Target quadrant or quadrant&sector- "))
-            else:
-                proutn(_("Destination sector or quadrant&sector- "))
-            scanner.chew()
-            iprompt = True
-            key = scanner.nexttok()
-        if key != "IHREAL":
-            huh()
-            raise TrekError
-        xi = int(round(scanner.real))-1
-        key = scanner.nexttok()
-        if key != "IHREAL":
-            huh()
-            raise TrekError
-        xj = int(round(scanner.real))-1
-        key = scanner.nexttok()
-        if key == "IHREAL":
-            # both quadrant and sector specified
-            xk = int(round(scanner.real))-1
-            key = scanner.nexttok()
-            if key != "IHREAL":
-                huh()
-                raise TrekError
-            xl = int(round(scanner.real))-1
-            dquad.i = xi
-            dquad.j = xj
-            dsect.i = xk
-            dsect.j = xl
-        else:
-            # only one pair of numbers was specified
-            if isprobe:
-                # only quadrant specified -- go to center of dest quad
-                dquad.i = xi
-                dquad.j = xj
-                dsect.j = dsect.i = 4        # preserves 1-origin behavior
-            else:
-                # only sector specified
-                dsect.i = xi
-                dsect.j = xj
-            itemp = "normal"
-        if not dquad.valid_quadrant() or not dsect.valid_sector():
-            huh()
-            raise TrekError
-        skip(1)
-        if not isprobe:
-            if itemp > "curt":
-                if iprompt:
-                    prout(_("Helmsman Sulu- \"Course locked in for Sector %s.\"") % dsect)
-            else:
-                prout(_("Ensign Chekov- \"Course laid in, Captain.\""))
-        # the actual deltas get computed here
-        delta.j = dquad.j-game.quadrant.j + (dsect.j-game.sector.j)/(QUADSIZE*1.0)
-        delta.i = game.quadrant.i-dquad.i + (game.sector.i-dsect.i)/(QUADSIZE*1.0)
-    else: # manual
-        while key == "IHEOL":
-            proutn(_("X and Y displacements- "))
-            scanner.chew()
-            iprompt = True
-            key = scanner.nexttok()
-        itemp = "verbose"
-        if key == "IHREAL":
-            delta.j = scanner.real
-        else:
-            huh()
-            raise TrekError
-        key = scanner.nexttok()
-        if key == "IHREAL":
-            delta.i = scanner.real
-        elif key == "IHEOL":
-            delta.i = 0
-            scanner.push("\n")
-        else:
-            huh()
-            raise TrekError
-    # Check for zero movement
-    if delta.i == 0 and delta.j == 0:
-        scanner.chew()
-        raise TrekError
-    if itemp == "verbose" and not isprobe:
-        skip(1)
-        prout(_("Helmsman Sulu- \"Aye, Sir.\""))
-    scanner.chew()
-    return course(bearing=delta.bearing(), distance=delta.distance())
-
-class course:
-    def __init__(self, bearing, distance, origin=None):
-        self.distance = distance
-        self.bearing = bearing
-        if origin is None:
-            self.origin = cartesian(game.quadrant, game.sector)
-        else:
-            self.origin = origin
-        # The bearing() code we inherited from FORTRAN is actually computing
-        # clockface directions!
-        if self.bearing < 0.0:
-            self.bearing += 12.0
-        self.angle = ((15.0 - self.bearing) * 0.5235988)
-        self.increment = Coord(-math.sin(self.angle), math.cos(self.angle))
-        bigger = max(abs(self.increment.i), abs(self.increment.j))
-        self.increment /= bigger
-        self.moves = int(round(10*self.distance*bigger))
-        self.reset()
-        self.final = (self.location + self.moves*self.increment).roundtogrid()
-        self.location = self.origin
-        self.nextlocation = None
-    def reset(self):
-        self.location = self.origin
-        self.step = 0
-    def arrived(self):
-        return self.location.roundtogrid() == self.final
-    def nexttok(self):
-        "Next step on course."
-        self.step += 1
-        self.nextlocation = self.location + self.increment
-        samequad = (self.location.quadrant() == self.nextlocation.quadrant())
-        self.location = self.nextlocation
-        return samequad
-    def quadrant(self):
-        return self.location.quadrant()
-    def sector(self):
-        return self.location.sector()
-    def power(self, w):
-        return self.distance*(w**3)*(game.shldup+1)
-    def time(self, w):
-        return 10.0*self.distance/w**2
-
-def impulse():
-    "Move under impulse power."
-    game.ididit = False
-    if damaged(DIMPULS):
-        scanner.chew()
-        skip(1)
-        prout(_("Engineer Scott- \"The impulse engines are damaged, Sir.\""))
-        return
-    if game.energy > 30.0:
-        try:
-            icourse = getcourse(isprobe=False)
-        except TrekError:
-            return
-        power = 20.0 + 100.0*icourse.distance
-    else:
-        power = 30.0
-    if power >= game.energy:
-        # Insufficient power for trip
-        skip(1)
-        prout(_("First Officer Spock- \"Captain, the impulse engines"))
-        prout(_("require 20.0 units to engage, plus 100.0 units per"))
-        if game.energy > 30:
-            proutn(_("quadrant.  We can go, therefore, a maximum of %d") %
-                   int(0.01 * (game.energy-20.0)-0.05))
-            prout(_(" quadrants.\""))
-        else:
-            prout(_("quadrant.  They are, therefore, useless.\""))
-        scanner.chew()
-        return
-    # Make sure enough time is left for the trip
-    game.optime = icourse.distance/0.095
-    if game.optime >= game.state.remtime:
-        prout(_("First Officer Spock- \"Captain, our speed under impulse"))
-        prout(_("power is only 0.95 sectors per stardate. Are you sure"))
-        proutn(_("we dare spend the time?\" "))
-        if not ja():
-            return
-    # Activate impulse engines and pay the cost
-    imove(icourse, noattack=False)
-    game.ididit = True
-    if game.alldone:
-        return
-    power = 20.0 + 100.0*icourse.distance
-    game.energy -= power
-    game.optime = icourse.distance/0.095
-    if game.energy <= 0:
-        finish(FNRG)
-    return
-
-def warp(wcourse, involuntary):
-    "ove under warp drive."
-    blooey = False; twarp = False
-    if not involuntary: # Not WARPX entry
-        game.ididit = False
-        if game.iscloaked:
-            scanner.chew()
-            skip(1)
-            prout(_("Engineer Scott- \"The warp engines can not be used while cloaked, Sir.\""))
-            return
-        if game.damage[DWARPEN] > 10.0:
-            scanner.chew()
-            skip(1)
-            prout(_("Engineer Scott- \"The warp engines are damaged, Sir.\""))
-            return
-        if damaged(DWARPEN) and game.warpfac > 4.0:
-            scanner.chew()
-            skip(1)
-            prout(_("Engineer Scott- \"Sorry, Captain. Until this damage"))
-            prout(_("  is repaired, I can only give you warp 4.\""))
-            return
-               # Read in course and distance
-        if wcourse is None:
-            try:
-                wcourse = getcourse(isprobe=False)
-            except TrekError:
-                return
-        # Make sure starship has enough energy for the trip
-        # Note: this formula is slightly different from the C version,
-        # and lets you skate a bit closer to the edge.
-        if wcourse.power(game.warpfac) >= game.energy:
-            # Insufficient power for trip
-            game.ididit = False
-            skip(1)
-            prout(_("Engineering to bridge--"))
-            if not game.shldup or 0.5*wcourse.power(game.warpfac) > game.energy:
-                iwarp = (game.energy/(wcourse.distance+0.05)) ** 0.333333333
-                if iwarp <= 0:
-                    prout(_("We can't do it, Captain. We don't have enough energy."))
-                else:
-                    proutn(_("We don't have enough energy, but we could do it at warp %d") % iwarp)
-                    if game.shldup:
-                        prout(",")
-                        prout(_("if you'll lower the shields."))
-                    else:
-                        prout(".")
-            else:
-                prout(_("We haven't the energy to go that far with the shields up."))
-            return
-        # Make sure enough time is left for the trip
-        game.optime = wcourse.time(game.warpfac)
-        if game.optime >= 0.8*game.state.remtime:
-            skip(1)
-            prout(_("First Officer Spock- \"Captain, I compute that such"))
-            proutn(_("  a trip would require approximately %2.0f") %
-                   (100.0*game.optime/game.state.remtime))
-            prout(_(" percent of our"))
-            proutn(_("  remaining time.  Are you sure this is wise?\" "))
-            if not ja():
-                game.ididit = False
-                game.optime=0
-                return
-    # Entry WARPX
-    if game.warpfac > 6.0:
-        # Decide if engine damage will occur
-        # ESR: Seems wrong. Probability of damage goes *down* with distance?
-        prob = wcourse.distance*(6.0-game.warpfac)**2/66.666666666
-        if prob > rnd.real():
-            blooey = True
-            wcourse.distance = rnd.real(wcourse.distance)
-        # Decide if time warp will occur
-        if 0.5*wcourse.distance*math.pow(7.0,game.warpfac-10.0) > rnd.real():
-            twarp = True
-        if game.idebug and game.warpfac==10 and not twarp:
-            blooey = False
-            proutn("=== Force time warp? ")
-            if ja():
-                twarp = True
-        if blooey or twarp:
-            # If time warp or engine damage, check path
-            # If it is obstructed, don't do warp or damage
-            look = wcourse.moves
-            while look > 0:
-                look -= 1
-                wcourse.nexttok()
-                w = wcourse.sector()
-                if not w.valid_sector():
-                    break
-                if game.quad[w.i][w.j] != '.':
-                    blooey = False
-                    twarp = False
-            wcourse.reset()
-    # Activate Warp Engines and pay the cost
-    imove(wcourse, noattack=False)
-    if game.alldone:
-        return
-    game.energy -= wcourse.power(game.warpfac)
-    if game.energy <= 0:
-        finish(FNRG)
-    game.optime = wcourse.time(game.warpfac)
-    if twarp:
-        timwrp()
-    if blooey:
-        game.damage[DWARPEN] = game.damfac * rnd.real(1.0, 4.0)
-        skip(1)
-        prout(_("Engineering to bridge--"))
-        prout(_("  Scott here.  The warp engines are damaged."))
-        prout(_("  We'll have to reduce speed to warp 4."))
-    game.ididit = True
-    return
-
-def setwarp():
-    "Change the warp factor."
-    while True:
-        key=scanner.nexttok()
-        if key != "IHEOL":
-            break
-        scanner.chew()
-        proutn(_("Warp factor- "))
-    if key != "IHREAL":
-        huh()
-        return
-    if game.damage[DWARPEN] > 10.0:
-        prout(_("Warp engines inoperative."))
-        return
-    if damaged(DWARPEN) and scanner.real > 4.0:
-        prout(_("Engineer Scott- \"I'm doing my best, Captain,"))
-        prout(_("  but right now we can only go warp 4.\""))
-        return
-    if scanner.real > 10.0:
-        prout(_("Helmsman Sulu- \"Our top speed is warp 10, Captain.\""))
-        return
-    if scanner.real < 1.0:
-        prout(_("Helmsman Sulu- \"We can't go below warp 1, Captain.\""))
-        return
-    oldfac = game.warpfac
-    game.warpfac = scanner.real
-    if game.warpfac <= oldfac or game.warpfac <= 6.0:
-        prout(_("Helmsman Sulu- \"Warp factor %d, Captain.\"") %
-              int(game.warpfac))
-        return
-    if game.warpfac < 8.00:
-        prout(_("Engineer Scott- \"Aye, but our maximum safe speed is warp 6.\""))
-        return
-    if game.warpfac == 10.0:
-        prout(_("Engineer Scott- \"Aye, Captain, we'll try it.\""))
-        return
-    prout(_("Engineer Scott- \"Aye, Captain, but our engines may not take it.\""))
-    return
-
-def atover(igrab):
-    "Cope with being tossed out of quadrant by supernova or yanked by beam."
-    scanner.chew()
-    # is captain on planet?
-    if game.landed:
-        if damaged(DTRANSP):
-            finish(FPNOVA)
-            return
-        prout(_("Scotty rushes to the transporter controls."))
-        if game.shldup:
-            prout(_("But with the shields up it's hopeless."))
-            finish(FPNOVA)
-        prouts(_("His desperate attempt to rescue you . . ."))
-        if rnd.withprob(0.5):
-            prout(_("fails."))
-            finish(FPNOVA)
-            return
-        prout(_("SUCCEEDS!"))
-        if game.imine:
-            game.imine = False
-            proutn(_("The crystals mined were "))
-            if rnd.withprob(0.25):
-                prout(_("lost."))
-            else:
-                prout(_("saved."))
-                game.icrystl = True
-    if igrab:
-        return
-    # Check to see if captain in shuttle craft
-    if game.icraft:
-        finish(FSTRACTOR)
-    if game.alldone:
-        return
-    # Inform captain of attempt to reach safety
-    skip(1)
-    while True:
-        if game.justin:
-            prouts(_("***RED ALERT!  RED ALERT!"))
-            skip(1)
-            proutn(_("The %s has stopped in a quadrant containing") % crmshp())
-            prouts(_("   a supernova."))
-            skip(2)
-        prout(_("***Emergency automatic override attempts to hurl ")+crmshp())
-        prout(_("safely out of quadrant."))
-        if not damaged(DRADIO):
-            game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
-        # Try to use warp engines
-        if damaged(DWARPEN):
-            skip(1)
-            prout(_("Warp engines damaged."))
-            finish(FSNOVAED)
-            return
-        game.warpfac = rnd.real(6.0, 8.0)
-        prout(_("Warp factor set to %d") % int(game.warpfac))
-        power = 0.75*game.energy
-        dist = power/(game.warpfac*game.warpfac*game.warpfac*(game.shldup+1))
-        dist = max(dist, rnd.real(math.sqrt(2)))
-        bugout = course(bearing=rnd.real(12), distance=dist)        # How dumb!
-        game.optime = bugout.time(game.warpfac)
-        game.justin = False
-        game.inorbit = False
-        warp(bugout, involuntary=True)
-        if not game.justin:
-            # This is bad news, we didn't leave quadrant.
-            if game.alldone:
-                return
-            skip(1)
-            prout(_("Insufficient energy to leave quadrant."))
-            finish(FSNOVAED)
-            return
-        # Repeat if another snova
-        if not game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-            break
-    if game.unwon()==0:
-        finish(FWON) # Snova killed remaining enemy.
-
-def timwrp():
-    "Let's do the time warp again."
-    prout(_("***TIME WARP ENTERED."))
-    if game.state.snap and rnd.withprob(0.5):
-        # Go back in time
-        prout(_("You are traveling backwards in time %d stardates.") %
-              int(game.state.date-game.snapsht.date))
-        game.state = game.snapsht
-        game.state.snap = False
-        if len(game.state.kcmdr):
-            schedule(FTBEAM, expran(game.intime/len(game.state.kcmdr)))
-            schedule(FBATTAK, expran(0.3*game.intime))
-        schedule(FSNOVA, expran(0.5*game.intime))
-        # next snapshot will be sooner
-        schedule(FSNAP, expran(0.25*game.state.remtime))
-
-        if game.state.nscrem:
-            schedule(FSCMOVE, 0.2777)
-        game.isatb = 0
-        unschedule(FCDBAS)
-        unschedule(FSCDBAS)
-        game.battle.invalidate()
-        # Make sure Galileo is consistant -- Snapshot may have been taken
-        # when on planet, which would give us two Galileos!
-        gotit = False
-        for l in range(game.inplan):
-            if game.state.planets[l].known == "shuttle_down":
-                gotit = True
-                if game.iscraft == "onship" and game.ship=='E':
-                    prout(_("Chekov-  \"Security reports the Galileo has disappeared, Sir!"))
-                    game.iscraft = "offship"
-        # Likewise, if in the original time the Galileo was abandoned, but
-        # was on ship earlier, it would have vanished -- let's restore it.
-        if game.iscraft == "offship" and not gotit and game.damage[DSHUTTL] >= 0.0:
-            prout(_("Chekov-  \"Security reports the Galileo has reappeared in the dock!\""))
-            game.iscraft = "onship"
-        # There used to be code to do the actual reconstrction here,
-        # but the starchart is now part of the snapshotted galaxy state.
-        prout(_("Spock has reconstructed a correct star chart from memory"))
-    else:
-        # Go forward in time
-        game.optime = expran(0.5*game.intime)
-        prout(_("You are traveling forward in time %d stardates.") % int(game.optime))
-        # cheat to make sure no tractor beams occur during time warp
-        postpone(FTBEAM, game.optime)
-        game.damage[DRADIO] += game.optime
-    newqad()
-    events()        # Stas Sergeev added this -- do pending events
-
-def probe():
-    "Launch deep-space probe."
-    # New code to launch a deep space probe
-    if game.nprobes == 0:
-        scanner.chew()
-        skip(1)
-        if game.ship == 'E':
-            prout(_("Engineer Scott- \"We have no more deep space probes, Sir.\""))
-        else:
-            prout(_("Ye Faerie Queene has no deep space probes."))
-        return
-    if damaged(DDSP):
-        scanner.chew()
-        skip(1)
-        prout(_("Engineer Scott- \"The probe launcher is damaged, Sir.\""))
-        return
-    if is_scheduled(FDSPROB):
-        scanner.chew()
-        skip(1)
-        if damaged(DRADIO) and game.condition != "docked":
-            prout(_("Spock-  \"Records show the previous probe has not yet"))
-            prout(_("   reached its destination.\""))
-        else:
-            prout(_("Uhura- \"The previous probe is still reporting data, Sir.\""))
-        return
-    key = scanner.nexttok()
-    if key == "IHEOL":
-        if game.nprobes == 1:
-            prout(_("1 probe left."))
-        else:
-            prout(_("%d probes left") % game.nprobes)
-        proutn(_("Are you sure you want to fire a probe? "))
-        if not ja():
-            return
-    game.isarmed = False
-    if key == "IHALPHA" and scanner.token == "armed":
-        game.isarmed = True
-        key = scanner.nexttok()
-    elif key == "IHEOL":
-        proutn(_("Arm NOVAMAX warhead? "))
-        game.isarmed = ja()
-    elif key == "IHREAL":                # first element of course
-        scanner.push(scanner.token)
-    try:
-        game.probe = getcourse(isprobe=True)
-    except TrekError:
-        return
-    game.nprobes -= 1
-    schedule(FDSPROB, 0.01) # Time to move one sector
-    prout(_("Ensign Chekov-  \"The deep space probe is launched, Captain.\""))
-    game.ididit = True
-    return
-
-def mayday():
-    "Yell for help from nearest starbase."
-    # There's more than one way to move in this game!
-    scanner.chew()
-    # Test for conditions which prevent calling for help
-    if game.condition == "docked":
-        prout(_("Lt. Uhura-  \"But Captain, we're already docked.\""))
-        return
-    if damaged(DRADIO):
-        prout(_("Subspace radio damaged."))
-        return
-    if not game.state.baseq:
-        prout(_("Lt. Uhura-  \"Captain, I'm not getting any response from Starbase.\""))
-        return
-    if game.landed:
-        prout(_("You must be aboard the %s.") % crmshp())
-        return
-    # OK -- call for help from nearest starbase
-    game.nhelp += 1
-    if game.base.i!=0:
-        # There's one in this quadrant
-        ddist = (game.base - game.sector).distance()
-    else:
-        ibq = None     # Force base-quadrant game to persist past loop
-        ddist = FOREVER
-        for ibq in game.state.baseq:
-            xdist = QUADSIZE * (ibq - game.quadrant).distance()
-            if xdist < ddist:
-                ddist = xdist
-        if ibq is None:
-            prout(_("No starbases remain. You are alone in a hostile galaxy."))
-            return
-        # Since starbase not in quadrant, set up new quadrant
-        game.quadrant = ibq
-        newqad()
-    # dematerialize starship
-    game.quad[game.sector.i][game.sector.j]='.'
-    proutn(_("Starbase in Quadrant %s responds--%s dematerializes") \
-           % (game.quadrant, crmshp()))
-    game.sector.invalidate()
-    for m in range(1, 5+1):
-        w = game.base.scatter()
-        if w.valid_sector() and game.quad[w.i][w.j]=='.':
-            # found one -- finish up
-            game.sector = w
-            break
-    if game.sector is None:
-        prout(_("You have been lost in space..."))
-        finish(FMATERIALIZE)
-        return
-    # Give starbase three chances to rematerialize starship
-    probf = math.pow((1.0 - math.pow(0.98,ddist)), 0.33333333)
-    for m in range(1, 3+1):
-        if m == 1: proutn(_("1st"))
-        elif m == 2: proutn(_("2nd"))
-        elif m == 3: proutn(_("3rd"))
-        proutn(_(" attempt to re-materialize ") + crmshp())
-        game.quad[game.sector.i][game.sector.j]=('-','o','O')[m-1]
-        textcolor(RED)
-        warble()
-        if rnd.real() > probf:
-            break
-        prout(_("fails."))
-        textcolor(DEFAULT)
-        curses.delay_output(500)
-    if m > 3:
-        game.quad[game.sector.i][game.sector.j]='?'
-        game.alive = False
-        drawmaps(1)
-        setwnd(message_window)
-        finish(FMATERIALIZE)
-        return
-    game.quad[game.sector.i][game.sector.j]=game.ship
-    textcolor(GREEN)
-    prout(_("succeeds."))
-    textcolor(DEFAULT)
-    dock(False)
-    skip(1)
-    prout(_("Lt. Uhura-  \"Captain, we made it!\""))
-
-def abandon():
-    "Abandon ship."
-    scanner.chew()
-    if game.condition=="docked":
-        if game.ship!='E':
-            prout(_("You cannot abandon Ye Faerie Queene."))
-            return
-    else:
-        # Must take shuttle craft to exit
-        if game.damage[DSHUTTL]==-1:
-            prout(_("Ye Faerie Queene has no shuttle craft."))
-            return
-        if game.damage[DSHUTTL]<0:
-            prout(_("Shuttle craft now serving Big Macs."))
-            return
-        if game.damage[DSHUTTL]>0:
-            prout(_("Shuttle craft damaged."))
-            return
-        if game.landed:
-            prout(_("You must be aboard the ship."))
-            return
-        if game.iscraft != "onship":
-            prout(_("Shuttle craft not currently available."))
-            return
-        # Emit abandon ship messages
-        skip(1)
-        prouts(_("***ABANDON SHIP!  ABANDON SHIP!"))
-        skip(1)
-        prouts(_("***ALL HANDS ABANDON SHIP!"))
-        skip(2)
-        prout(_("Captain and crew escape in shuttle craft."))
-        if not game.state.baseq:
-            # Oops! no place to go...
-            finish(FABANDN)
-            return
-        q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
-        # Dispose of crew
-        if not (game.options & OPTION_WORLDS) and not damaged(DTRANSP):
-            prout(_("Remainder of ship's complement beam down"))
-            prout(_("to nearest habitable planet."))
-        elif q.planet is not None and not damaged(DTRANSP):
-            prout(_("Remainder of ship's complement beam down to %s.") %
-                  q.planet)
-        else:
-            prout(_("Entire crew of %d left to die in outer space.") %
-                  game.state.crew)
-            game.casual += game.state.crew
-            game.abandoned += game.state.crew
-        # If at least one base left, give 'em the Faerie Queene
-        skip(1)
-        game.icrystl = False # crystals are lost
-        game.nprobes = 0 # No probes
-        prout(_("You are captured by Klingons and released to"))
-        prout(_("the Federation in a prisoner-of-war exchange."))
-        nb = rnd.integer(len(game.state.baseq))
-        # Set up quadrant and position FQ adjacient to base
-        if not game.quadrant == game.state.baseq[nb]:
-            game.quadrant = game.state.baseq[nb]
-            game.sector.i = game.sector.j = 5
-            newqad()
-        while True:
-            # position next to base by trial and error
-            game.quad[game.sector.i][game.sector.j] = '.'
-            l = QUADSIZE
-            for l in range(QUADSIZE):
-                game.sector = game.base.scatter()
-                if game.sector.valid_sector() and \
-                       game.quad[game.sector.i][game.sector.j] == '.':
-                    break
-            if l < QUADSIZE:
-                break # found a spot
-            game.sector.i=QUADSIZE/2
-            game.sector.j=QUADSIZE/2
-            newqad()
-    # Get new commission
-    game.quad[game.sector.i][game.sector.j] = game.ship = 'F'
-    game.state.crew = FULLCREW
-    prout(_("Starfleet puts you in command of another ship,"))
-    prout(_("the Faerie Queene, which is antiquated but,"))
-    prout(_("still useable."))
-    if game.icrystl:
-        prout(_("The dilithium crystals have been moved."))
-    game.imine = False
-    game.iscraft = "offship" # Galileo disappears
-    # Resupply ship
-    game.condition="docked"
-    for l in range(NDEVICES):
-        game.damage[l] = 0.0
-    game.damage[DSHUTTL] = -1
-    game.energy = game.inenrg = 3000.0
-    game.shield = game.inshld = 1250.0
-    game.torps = game.intorps = 6
-    game.lsupres=game.inlsr=3.0
-    game.shldup=False
-    game.warpfac=5.0
-    game.brigfree = game.brigcapacity = 300
-    return
-
-# Code from planets.c begins here.
-
-def consumeTime():
-    "Abort a lengthy operation if an event interrupts it."
-    game.ididit = True
-    events()
-    if game.alldone or game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova or game.justin:
-        return True
-    return False
-
-def survey():
-    "Report on (uninhabited) planets in the galaxy."
-    iknow = False
-    skip(1)
-    scanner.chew()
-    prout(_("Spock-  \"Planet report follows, Captain.\""))
-    skip(1)
-    for i in range(game.inplan):
-        if game.state.planets[i].pclass == "destroyed":
-            continue
-        if (game.state.planets[i].known != "unknown" \
-            and not game.state.planets[i].inhabited) \
-            or game.idebug:
-            iknow = True
-            if game.idebug and game.state.planets[i].known=="unknown":
-                proutn("(Unknown) ")
-            proutn(_("Quadrant %s") % game.state.planets[i].quadrant)
-            proutn(_("   class "))
-            proutn(game.state.planets[i].pclass)
-            proutn("   ")
-            if game.state.planets[i].crystals != "present":
-                proutn(_("no "))
-            prout(_("dilithium crystals present."))
-            if game.state.planets[i].known=="shuttle_down":
-                prout(_("    Shuttle Craft Galileo on surface."))
-    if not iknow:
-        prout(_("No information available."))
-
-def orbit():
-    "Enter standard orbit."
-    skip(1)
-    scanner.chew()
-    if game.inorbit:
-        prout(_("Already in standard orbit."))
-        return
-    if damaged(DWARPEN) and damaged(DIMPULS):
-        prout(_("Both warp and impulse engines damaged."))
-        return
-    if game.plnet is None:
-        prout("There is no planet in this sector.")
-        return
-    if abs(game.sector.i-game.plnet.i)>1 or abs(game.sector.j-game.plnet.j)>1:
-        prout(crmshp() + _(" not adjacent to planet."))
-        skip(1)
-        return
-    game.optime = rnd.real(0.02, 0.05)
-    prout(_("Helmsman Sulu-  \"Entering standard orbit, Sir.\""))
-    newcnd()
-    if consumeTime():
-        return
-    game.height = rnd.real(1400, 8600)
-    prout(_("Sulu-  \"Entered orbit at altitude %.2f kilometers.\"") % game.height)
-    game.inorbit = True
-    game.ididit = True
-
-def sensor():
-    "Examine planets in this quadrant."
-    if damaged(DSRSENS):
-        if game.options & OPTION_TTY:
-            prout(_("Short range sensors damaged."))
-        return
-    if game.iplnet is None:
-        if game.options & OPTION_TTY:
-            prout(_("Spock- \"No planet in this quadrant, Captain.\""))
-        return
-    if game.iplnet.known == "unknown":
-        prout(_("Spock-  \"Sensor scan for Quadrant %s-") % game.quadrant)
-        skip(1)
-        prout(_("         Planet at Sector %s is of class %s.") %
-              (game.plnet, game.iplnet.pclass))
-        if game.iplnet.known=="shuttle_down":
-            prout(_("         Sensors show Galileo still on surface."))
-        proutn(_("         Readings indicate"))
-        if game.iplnet.crystals != "present":
-            proutn(_(" no"))
-        prout(_(" dilithium crystals present.\""))
-        if game.iplnet.known == "unknown":
-            game.iplnet.known = "known"
-    elif game.iplnet.inhabited:
-        prout(_("Spock-  \"The inhabited planet %s ") % game.iplnet.name)
-        prout(_("        is located at Sector %s, Captain.\"") % game.plnet)
-
-def beam():
-    "Use the transporter."
-    nrgneed = 0
-    scanner.chew()
-    skip(1)
-    if damaged(DTRANSP):
-        prout(_("Transporter damaged."))
-        if not damaged(DSHUTTL) and (game.iplnet.known=="shuttle_down" or game.iscraft == "onship"):
-            skip(1)
-            proutn(_("Spock-  \"May I suggest the shuttle craft, Sir?\" "))
-            if ja():
-                shuttle()
-        return
-    if not game.inorbit:
-        prout(crmshp() + _(" not in standard orbit."))
-        return
-    if game.shldup:
-        prout(_("Impossible to transport through shields."))
-        return
-    if game.iplnet.known=="unknown":
-        prout(_("Spock-  \"Captain, we have no information on this planet"))
-        prout(_("  and Starfleet Regulations clearly state that in this situation"))
-        prout(_("  you may not go down.\""))
-        return
-    if not game.landed and game.iplnet.crystals=="absent":
-        prout(_("Spock-  \"Captain, I fail to see the logic in"))
-        prout(_("  exploring a planet with no dilithium crystals."))
-        proutn(_("  Are you sure this is wise?\" "))
-        if not ja():
-            scanner.chew()
-            return
-    if not (game.options & OPTION_PLAIN):
-        nrgneed = 50 * game.skill + game.height / 100.0
-        if nrgneed > game.energy:
-            prout(_("Engineering to bridge--"))
-            prout(_("  Captain, we don't have enough energy for transportation."))
-            return
-        if not game.landed and nrgneed * 2 > game.energy:
-            prout(_("Engineering to bridge--"))
-            prout(_("  Captain, we have enough energy only to transport you down to"))
-            prout(_("  the planet, but there wouldn't be an energy for the trip back."))
-            if game.iplnet.known == "shuttle_down":
-                prout(_("  Although the Galileo shuttle craft may still be on a surface."))
-            proutn(_("  Are you sure this is wise?\" "))
-            if not ja():
-                scanner.chew()
-                return
-    if game.landed:
-        # Coming from planet
-        if game.iplnet.known=="shuttle_down":
-            proutn(_("Spock-  \"Wouldn't you rather take the Galileo?\" "))
-            if ja():
-                scanner.chew()
-                return
-            prout(_("Your crew hides the Galileo to prevent capture by aliens."))
-        prout(_("Landing party assembled, ready to beam up."))
-        skip(1)
-        prout(_("Kirk whips out communicator..."))
-        prouts(_("BEEP  BEEP  BEEP"))
-        skip(2)
-        prout(_("\"Kirk to enterprise-  Lock on coordinates...energize.\""))
-    else:
-        # Going to planet
-        prout(_("Scotty-  \"Transporter room ready, Sir.\""))
-        skip(1)
-        prout(_("Kirk and landing party prepare to beam down to planet surface."))
-        skip(1)
-        prout(_("Kirk-  \"Energize.\""))
-    game.ididit = True
-    skip(1)
-    prouts("WWHOOOIIIIIRRRRREEEE.E.E.  .  .  .  .   .    .")
-    skip(2)
-    if not rnd.withprob(0.98):
-        prouts("BOOOIIIOOOIIOOOOIIIOIING . . .")
-        skip(2)
-        prout(_("Scotty-  \"Oh my God!  I've lost them.\""))
-        finish(FLOST)
-        return
-    prouts(".    .   .  .  .  .  .E.E.EEEERRRRRIIIIIOOOHWW")
-    game.landed = not game.landed
-    game.energy -= nrgneed
-    skip(2)
-    prout(_("Transport complete."))
-    if game.landed and game.iplnet.known=="shuttle_down":
-        prout(_("The shuttle craft Galileo is here!"))
-    if not game.landed and game.imine:
-        game.icrystl = True
-        game.cryprob = 0.05
-    game.imine = False
-    return
-
-def mine():
-    "Strip-mine a world for dilithium."
-    skip(1)
-    scanner.chew()
-    if not game.landed:
-        prout(_("Mining party not on planet."))
-        return
-    if game.iplnet.crystals == "mined":
-        prout(_("This planet has already been strip-mined for dilithium."))
-        return
-    elif game.iplnet.crystals == "absent":
-        prout(_("No dilithium crystals on this planet."))
-        return
-    if game.imine:
-        prout(_("You've already mined enough crystals for this trip."))
-        return
-    if game.icrystl and game.cryprob == 0.05:
-        prout(_("With all those fresh crystals aboard the ") + crmshp())
-        prout(_("there's no reason to mine more at this time."))
-        return
-    game.optime = rnd.real(0.1, 0.3)*(ord(game.iplnet.pclass)-ord("L"))
-    if consumeTime():
-        return
-    prout(_("Mining operation complete."))
-    game.iplnet.crystals = "mined"
-    game.imine = game.ididit = True
-
-def usecrystals():
-    "Use dilithium crystals."
-    game.ididit = False
-    skip(1)
-    scanner.chew()
-    if not game.icrystl:
-        prout(_("No dilithium crystals available."))
-        return
-    if game.energy >= 1000:
-        prout(_("Spock-  \"Captain, Starfleet Regulations prohibit such an operation"))
-        prout(_("  except when Condition Yellow exists."))
-        return
-    prout(_("Spock- \"Captain, I must warn you that loading"))
-    prout(_("  raw dilithium crystals into the ship's power"))
-    prout(_("  system may risk a severe explosion."))
-    proutn(_("  Are you sure this is wise?\" "))
-    if not ja():
-        scanner.chew()
-        return
-    skip(1)
-    prout(_("Engineering Officer Scott-  \"(GULP) Aye Sir."))
-    prout(_("  Mr. Spock and I will try it.\""))
-    skip(1)
-    prout(_("Spock-  \"Crystals in place, Sir."))
-    prout(_("  Ready to activate circuit.\""))
-    skip(1)
-    prouts(_("Scotty-  \"Keep your fingers crossed, Sir!\""))
-    skip(1)
-    if rnd.withprob(game.cryprob):
-        prouts(_("  \"Activating now! - - No good!  It's***"))
-        skip(2)
-        prouts(_("***RED ALERT!  RED A*L********************************"))
-        skip(1)
-        stars()
-        prouts(_("******************   KA-BOOM!!!!   *******************"))
-        skip(1)
-        kaboom()
-        return
-    game.energy += rnd.real(5000.0, 5500.0)
-    prouts(_("  \"Activating now! - - "))
-    prout(_("The instruments"))
-    prout(_("   are going crazy, but I think it's"))
-    prout(_("   going to work!!  Congratulations, Sir!\""))
-    game.cryprob *= 2.0
-    game.ididit = True
-
-def shuttle():
-    "Use shuttlecraft for planetary jaunt."
-    scanner.chew()
-    skip(1)
-    if damaged(DSHUTTL):
-        if game.damage[DSHUTTL] == -1.0:
-            if game.inorbit and game.iplnet.known == "shuttle_down":
-                prout(_("Ye Faerie Queene has no shuttle craft bay to dock it at."))
-            else:
-                prout(_("Ye Faerie Queene had no shuttle craft."))
-        elif game.damage[DSHUTTL] > 0:
-            prout(_("The Galileo is damaged."))
-        else: # game.damage[DSHUTTL] < 0
-            prout(_("Shuttle craft is now serving Big Macs."))
-        return
-    if not game.inorbit:
-        prout(crmshp() + _(" not in standard orbit."))
-        return
-    if (game.iplnet.known != "shuttle_down") and game.iscraft != "onship":
-        prout(_("Shuttle craft not currently available."))
-        return
-    if not game.landed and game.iplnet.known=="shuttle_down":
-        prout(_("You will have to beam down to retrieve the shuttle craft."))
-        return
-    if game.shldup or game.condition == "docked":
-        prout(_("Shuttle craft cannot pass through shields."))
-        return
-    if game.iplnet.known=="unknown":
-        prout(_("Spock-  \"Captain, we have no information on this planet"))
-        prout(_("  and Starfleet Regulations clearly state that in this situation"))
-        prout(_("  you may not fly down.\""))
-        return
-    game.optime = 3.0e-5*game.height
-    if game.optime >= 0.8*game.state.remtime:
-        prout(_("First Officer Spock-  \"Captain, I compute that such"))
-        proutn(_("  a maneuver would require approximately %2d%% of our") % \
-               int(100*game.optime/game.state.remtime))
-        prout(_("remaining time."))
-        proutn(_("Are you sure this is wise?\" "))
-        if not ja():
-            game.optime = 0.0
-            return
-    if game.landed:
-        # Kirk on planet
-        if game.iscraft == "onship":
-            # Galileo on ship!
-            if not damaged(DTRANSP):
-                proutn(_("Spock-  \"Would you rather use the transporter?\" "))
-                if ja():
-                    beam()
-                    return
-                proutn(_("Shuttle crew"))
-            else:
-                proutn(_("Rescue party"))
-            prout(_(" boards Galileo and swoops toward planet surface."))
-            game.iscraft = "offship"
-            skip(1)
-            if consumeTime():
-                return
-            game.iplnet.known="shuttle_down"
-            prout(_("Trip complete."))
-            return
-        else:
-            # Ready to go back to ship
-            prout(_("You and your mining party board the"))
-            prout(_("shuttle craft for the trip back to the Enterprise."))
-            skip(1)
-            prouts(_("The short hop begins . . ."))
-            skip(1)
-            game.iplnet.known="known"
-            game.icraft = True
-            skip(1)
-            game.landed = False
-            if consumeTime():
-                return
-            game.iscraft = "onship"
-            game.icraft = False
-            if game.imine:
-                game.icrystl = True
-                game.cryprob = 0.05
-            game.imine = False
-            prout(_("Trip complete."))
-            return
-    else:
-        # Kirk on ship and so is Galileo
-        prout(_("Mining party assembles in the hangar deck,"))
-        prout(_("ready to board the shuttle craft \"Galileo\"."))
-        skip(1)
-        prouts(_("The hangar doors open; the trip begins."))
-        skip(1)
-        game.icraft = True
-        game.iscraft = "offship"
-        if consumeTime():
-            return
-        game.iplnet.known = "shuttle_down"
-        game.landed = True
-        game.icraft = False
-        prout(_("Trip complete."))
-        return
-
-def deathray():
-    "Use the big zapper."
-    game.ididit = False
-    skip(1)
-    scanner.chew()
-    if game.ship != 'E':
-        prout(_("Ye Faerie Queene has no death ray."))
-        return
-    if len(game.enemies)==0:
-        prout(_("Sulu-  \"But Sir, there are no enemies in this quadrant.\""))
-        return
-    if damaged(DDRAY):
-        prout(_("Death Ray is damaged."))
-        return
-    prout(_("Spock-  \"Captain, the 'Experimental Death Ray'"))
-    prout(_("  is highly unpredictible.  Considering the alternatives,"))
-    proutn(_("  are you sure this is wise?\" "))
-    if not ja():
-        return
-    prout(_("Spock-  \"Acknowledged.\""))
-    skip(1)
-    game.ididit = True
-    prouts(_("WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE"))
-    skip(1)
-    prout(_("Crew scrambles in emergency preparation."))
-    prout(_("Spock and Scotty ready the death ray and"))
-    prout(_("prepare to channel all ship's power to the device."))
-    skip(1)
-    prout(_("Spock-  \"Preparations complete, sir.\""))
-    prout(_("Kirk-  \"Engage!\""))
-    skip(1)
-    prouts(_("WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"))
-    skip(1)
-    dprob = 0.30
-    if game.options & OPTION_PLAIN:
-        dprob = 0.5
-    r = rnd.real()
-    if r > dprob:
-        prouts(_("Sulu- \"Captain!  It's working!\""))
-        skip(2)
-        while len(game.enemies) > 0:
-            deadkl(game.enemies[-1].location, game.quad[game.enemies[-1].location.i][game.enemies[-1].location.j],game.enemies[-1].location)
-        prout(_("Ensign Chekov-  \"Congratulations, Captain!\""))
-        if game.unwon() == 0:
-            finish(FWON)
-        if (game.options & OPTION_PLAIN) == 0:
-            prout(_("Spock-  \"Captain, I believe the `Experimental Death Ray'"))
-            if rnd.withprob(0.05):
-                prout(_("   is still operational.\""))
-            else:
-                prout(_("   has been rendered nonfunctional.\""))
-                game.damage[DDRAY] = 39.95
-        return
-    r = rnd.real()        # Pick failure method
-    if r <= 0.30:
-        prouts(_("Sulu- \"Captain!  It's working!\""))
-        skip(1)
-        prouts(_("***RED ALERT!  RED ALERT!"))
-        skip(1)
-        prout(_("***MATTER-ANTIMATTER IMPLOSION IMMINENT!"))
-        skip(1)
-        prouts(_("***RED ALERT!  RED A*L********************************"))
-        skip(1)
-        stars()
-        prouts(_("******************   KA-BOOM!!!!   *******************"))
-        skip(1)
-        kaboom()
-        return
-    if r <= 0.55:
-        prouts(_("Sulu- \"Captain!  Yagabandaghangrapl, brachriigringlanbla!\""))
-        skip(1)
-        prout(_("Lt. Uhura-  \"Graaeek!  Graaeek!\""))
-        skip(1)
-        prout(_("Spock-  \"Fascinating!  . . . All humans aboard"))
-        prout(_("  have apparently been transformed into strange mutations."))
-        prout(_("  Vulcans do not seem to be affected."))
-        skip(1)
-        prout(_("Kirk-  \"Raauch!  Raauch!\""))
-        finish(FDRAY)
-        return
-    if r <= 0.75:
-        prouts(_("Sulu- \"Captain!  It's   --WHAT?!?!\""))
-        skip(2)
-        proutn(_("Spock-  \"I believe the word is"))
-        prouts(_(" *ASTONISHING*"))
-        prout(_(" Mr. Sulu."))
-        for i in range(QUADSIZE):
-            for j in range(QUADSIZE):
-                if game.quad[i][j] == '.':
-                    game.quad[i][j] = '?'
-        prout(_("  Captain, our quadrant is now infested with"))
-        prouts(_(" - - - - - -  *THINGS*."))
-        skip(1)
-        prout(_("  I have no logical explanation.\""))
-        return
-    prouts(_("Sulu- \"Captain!  The Death Ray is creating tribbles!\""))
-    skip(1)
-    prout(_("Scotty-  \"There are so many tribbles down here"))
-    prout(_("  in Engineering, we can't move for 'em, Captain.\""))
-    finish(FTRIBBLE)
-    return
-
-# Code from reports.c begins here
-
-def attackreport(curt):
-    "eport status of bases under attack."
-    if not curt:
-        if is_scheduled(FCDBAS):
-            prout(_("Starbase in Quadrant %s is currently under Commander attack.") % game.battle)
-            prout(_("It can hold out until Stardate %d.") % int(scheduled(FCDBAS)))
-        elif game.isatb == 1:
-            prout(_("Starbase in Quadrant %s is under Super-commander attack.") % game.state.kscmdr)
-            prout(_("It can hold out until Stardate %d.") % int(scheduled(FSCDBAS)))
-        else:
-            prout(_("No Starbase is currently under attack."))
-    else:
-        if is_scheduled(FCDBAS):
-            proutn(_("Base in %s attacked by C. Alive until %.1f") % (game.battle, scheduled(FCDBAS)))
-        if game.isatb:
-            proutn(_("Base in %s attacked by S. Alive until %.1f") % (game.state.kscmdr, scheduled(FSCDBAS)))
-        clreol()
-
-def report():
-    # report on general game status
-    scanner.chew()
-    s1 = (game.thawed and _("thawed ")) or ""
-    s2 = {1:"short", 2:"medium", 4:"long"}[game.length]
-    s3 = (None, _("novice"), _("fair"),
-          _("good"), _("expert"), _("emeritus"))[game.skill]
-    prout(_("You %s a %s%s %s game.") % ((_("were playing"), _("are playing"))[game.alldone], s1, s2, s3))
-    if game.skill>SKILL_GOOD and game.thawed and not game.alldone:
-        prout(_("No plaque is allowed."))
-    if game.tourn:
-        prout(_("This is tournament game %d.") % game.tourn)
-    prout(_("Your secret password is \"%s\"") % game.passwd)
-    proutn(_("%d of %d Klingons have been killed") % (((game.inkling + game.incom + game.inscom) - game.unwon()),
-                                                      (game.inkling + game.incom + game.inscom)))
-    if game.incom - len(game.state.kcmdr):
-        prout(_(", including %d Commander%s.") % (game.incom - len(game.state.kcmdr), (_("s"), "")[(game.incom - len(game.state.kcmdr))==1]))
-    elif game.inkling - game.remkl() + (game.inscom - game.state.nscrem) > 0:
-        prout(_(", but no Commanders."))
-    else:
-        prout(".")
-    if game.skill > SKILL_FAIR:
-        prout(_("The Super Commander has %sbeen destroyed.") % ("", _("not "))[game.state.nscrem])
-    if len(game.state.baseq) != game.inbase:
-        proutn(_("There "))
-        if game.inbase-len(game.state.baseq)==1:
-            proutn(_("has been 1 base"))
-        else:
-            proutn(_("have been %d bases") % (game.inbase-len(game.state.baseq)))
-        prout(_(" destroyed, %d remaining.") % len(game.state.baseq))
-    else:
-        prout(_("There are %d bases.") % game.inbase)
-    if communicating() or game.iseenit:
-        # Don't report this if not seen and
-        # either the radio is dead or not at base!
-        attackreport(False)
-        game.iseenit = True
-    if game.casual:
-        prout(_("%d casualt%s suffered so far.") % (game.casual, ("y", "ies")[game.casual!=1]))
-    if game.brigcapacity != game.brigfree:
-        embriggened = game.brigcapacity-game.brigfree
-        if embriggened == 1:
-            prout(_("1 Klingon in brig"))
-        else:
-            prout(_("%d Klingons in brig.") %  embriggened)
-        if game.kcaptured == 0:
-            pass
-        elif game.kcaptured == 1:
-            prout(_("1 captured Klingon turned in to Starfleet."))
-        else:
-            prout(_("%d captured Klingons turned in to Star Fleet.") % game.kcaptured)
-    if game.nhelp:
-        prout(_("There were %d call%s for help.") % (game.nhelp,  ("" , _("s"))[game.nhelp!=1]))
-    if game.ship == 'E':
-        proutn(_("You have "))
-        if game.nprobes:
-            proutn("%d" % (game.nprobes))
-        else:
-            proutn(_("no"))
-        proutn(_(" deep space probe"))
-        if game.nprobes!=1:
-            proutn(_("s"))
-        prout(".")
-    if communicating() and is_scheduled(FDSPROB):
-        if game.isarmed:
-            proutn(_("An armed deep space probe is in "))
-        else:
-            proutn(_("A deep space probe is in "))
-        prout("Quadrant %s." % game.probe.quadrant())
-    if game.icrystl:
-        if game.cryprob <= .05:
-            prout(_("Dilithium crystals aboard ship... not yet used."))
-        else:
-            i=0
-            ai = 0.05
-            while game.cryprob > ai:
-                ai *= 2.0
-                i += 1
-            prout(_("Dilithium crystals have been used %d time%s.") % \
-                  (i, (_("s"), "")[i==1]))
-    skip(1)
-
-def lrscan(silent):
-    "Long-range sensor scan."
-    if damaged(DLRSENS):
-        # Now allow base's sensors if docked
-        if game.condition != "docked":
-            if not silent:
-                prout(_("LONG-RANGE SENSORS DAMAGED."))
-            return
-        if not silent:
-            prout(_("Starbase's long-range scan"))
-    elif not silent:
-        prout(_("Long-range scan"))
-    for x in range(game.quadrant.i-1, game.quadrant.i+2):
-        if not silent:
-            proutn(" ")
-        for y in range(game.quadrant.j-1, game.quadrant.j+2):
-            if not Coord(x, y).valid_quadrant():
-                if not silent:
-                    proutn("  -1")
-            else:
-                if not damaged(DRADIO):
-                    game.state.galaxy[x][y].charted = True
-                game.state.chart[x][y].klingons = game.state.galaxy[x][y].klingons
-                game.state.chart[x][y].starbase = game.state.galaxy[x][y].starbase
-                game.state.chart[x][y].stars = game.state.galaxy[x][y].stars
-                if not silent and game.state.galaxy[x][y].supernova:
-                    proutn(" ***")
-                elif not silent:
-                    cn = " %3d" % (game.state.chart[x][y].klingons*100 + game.state.chart[x][y].starbase * 10 + game.state.chart[x][y].stars)
-                    proutn(((3 - len(cn)) * '.') + cn)
-        if not silent:
-            prout(" ")
-
-def damagereport():
-    "Damage report."
-    jdam = False
-    scanner.chew()
-    for i in range(NDEVICES):
-        if damaged(i):
-            if not jdam:
-                prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
-                prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
-                jdam = True
-            prout("  %-26s\t%8.2f\t\t%8.2f" % (device[i],
-                                               game.damage[i]+0.05,
-                                               DOCKFAC*game.damage[i]+0.005))
-    if not jdam:
-        prout(_("All devices functional."))
-
-def rechart():
-    "Update the chart in the Enterprise's computer from galaxy data."
-    game.lastchart = game.state.date
-    for i in range(GALSIZE):
-        for j in range(GALSIZE):
-            if game.state.galaxy[i][j].charted:
-                game.state.chart[i][j].klingons = game.state.galaxy[i][j].klingons
-                game.state.chart[i][j].starbase = game.state.galaxy[i][j].starbase
-                game.state.chart[i][j].stars = game.state.galaxy[i][j].stars
-
-def chart():
-    "Display the star chart."
-    scanner.chew()
-    if (game.options & OPTION_AUTOSCAN):
-        lrscan(silent=True)
-    if communicating():
-        rechart()
-    if game.lastchart < game.state.date and game.condition == "docked":
-        prout(_("Spock-  \"I revised the Star Chart from the starbase's records.\""))
-        rechart()
-    prout(_("       STAR CHART FOR THE KNOWN GALAXY"))
-    if game.state.date > game.lastchart:
-        prout(_("(Last surveillance update %d stardates ago).") % ((int)(game.state.date-game.lastchart)))
-    prout("      1    2    3    4    5    6    7    8")
-    for i in range(GALSIZE):
-        proutn("%d |" % (i+1))
-        for j in range(GALSIZE):
-            if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
-                proutn("<")
-            else:
-                proutn(" ")
-            if game.state.galaxy[i][j].supernova:
-                show = "***"
-            elif not game.state.galaxy[i][j].charted and game.state.galaxy[i][j].starbase:
-                show = ".1."
-            elif game.state.galaxy[i][j].charted:
-                show = "%3d" % (game.state.chart[i][j].klingons*100 + game.state.chart[i][j].starbase * 10 + game.state.chart[i][j].stars)
-                if (game.options & OPTION_DOTFILL):
-                    show = show.replace(" ", ".")
-            else:
-                show = "..."
-            proutn(show)
-            if (game.options & OPTION_SHOWME) and i == game.quadrant.i and j == game.quadrant.j:
-                proutn(">")
-            else:
-                proutn(" ")
-        proutn("  |")
-        if i<GALSIZE:
-            skip(1)
-
-def sectscan(goodScan, i, j):
-    "Light up an individual dot in a sector."
-    if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1):
-        if game.quad[i][j] in ('E', 'F'):
-            if game.iscloaked:
-                highvideo()
-            textcolor({"green":GREEN,
-                       "yellow":YELLOW,
-                       "red":RED,
-                       "docked":CYAN,
-                       "dead":BROWN}[game.condition])
-        else:
-            textcolor({'?':LIGHTMAGENTA,
-                       'K':LIGHTRED,
-                       'S':LIGHTRED,
-                       'C':LIGHTRED,
-                       'R':LIGHTRED,
-                       'T':LIGHTRED,
-                       '@':LIGHTGREEN,
-                       'P':LIGHTGREEN,
-                       '?':MAGENTA,
-                      }.get(game.quad[i][j], DEFAULT))
-        proutn("%c " % game.quad[i][j])
-        textcolor(DEFAULT)
-    else:
-        proutn("- ")
-
-def status(req=0):
-    "Emit status report lines"
-    if not req or req == 1:
-        prstat(_("Stardate"), _("%.1f, Time Left %.2f") \
-               % (game.state.date, game.state.remtime))
-    if not req or req == 2:
-        if game.condition != "docked":
-            newcnd()
-        prstat(_("Condition"), _("%s, %i DAMAGES") % \
-               (game.condition.upper(), sum([x > 0 for x in game.damage])))
-        if game.iscloaked:
-            prout(_(", CLOAKED"))
-    if not req or req == 3:
-        prstat(_("Position"), "%s , %s" % (game.quadrant, game.sector))
-    if not req or req == 4:
-        if damaged(DLIFSUP):
-            if game.condition == "docked":
-                s = _("DAMAGED, Base provides")
-            else:
-                s = _("DAMAGED, reserves=%4.2f") % game.lsupres
-        else:
-            s = _("ACTIVE")
-        prstat(_("Life Support"), s)
-    if not req or req == 5:
-        prstat(_("Warp Factor"), "%.1f" % game.warpfac)
-    if not req or req == 6:
-        extra = ""
-        if game.icrystl and (game.options & OPTION_SHOWME):
-            extra = _(" (have crystals)")
-        prstat(_("Energy"), "%.2f%s" % (game.energy, extra))
-    if not req or req == 7:
-        prstat(_("Torpedoes"), "%d" % (game.torps))
-    if not req or req == 8:
-        if damaged(DSHIELD):
-            s = _("DAMAGED,")
-        elif game.shldup:
-            s = _("UP,")
-        else:
-            s = _("DOWN,")
-        data = _(" %d%% %.1f units") \
-               % (int((100.0*game.shield)/game.inshld + 0.5), game.shield)
-        prstat(_("Shields"), s+data)
-    if not req or req == 9:
-        prstat(_("Klingons Left"), "%d" % game.unwon())
-    if not req or req == 10:
-        if game.options & OPTION_WORLDS:
-            plnet = game.state.galaxy[game.quadrant.i][game.quadrant.j].planet
-            if plnet and plnet.inhabited:
-                prstat(_("Major system"), plnet.name)
-            else:
-                prout(_("Sector is uninhabited"))
-    elif not req or req == 11:
-        attackreport(not req)
-
-def request():
-    "Request specified status data, a historical relic from slow TTYs."
-    requests = ("da","co","po","ls","wa","en","to","sh","kl","sy", "ti")
-    while scanner.nexttok() == "IHEOL":
-        proutn(_("Information desired? "))
-    scanner.chew()
-    if scanner.token in requests:
-        status(requests.index(scanner.token))
-    else:
-        prout(_("UNRECOGNIZED REQUEST. Legal requests are:"))
-        prout(("  date, condition, position, lsupport, warpfactor,"))
-        prout(("  energy, torpedoes, shields, klingons, system, time."))
-
-def srscan():
-    "Short-range scan."
-    goodScan=True
-    if damaged(DSRSENS):
-        # Allow base's sensors if docked
-        if game.condition != "docked":
-            prout(_("   S.R. SENSORS DAMAGED!"))
-            goodScan=False
-        else:
-            prout(_("  [Using Base's sensors]"))
-    else:
-        prout(_("     Short-range scan"))
-    if goodScan and communicating():
-        game.state.chart[game.quadrant.i][game.quadrant.j].klingons = game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons
-        game.state.chart[game.quadrant.i][game.quadrant.j].starbase = game.state.galaxy[game.quadrant.i][game.quadrant.j].starbase
-        game.state.chart[game.quadrant.i][game.quadrant.j].stars = game.state.galaxy[game.quadrant.i][game.quadrant.j].stars
-        game.state.galaxy[game.quadrant.i][game.quadrant.j].charted = True
-    prout("    1 2 3 4 5 6 7 8 9 10")
-    if game.condition != "docked":
-        newcnd()
-    for i in range(QUADSIZE):
-        proutn("%2d  " % (i+1))
-        for j in range(QUADSIZE):
-            sectscan(goodScan, i, j)
-        skip(1)
-
-def eta():
-    "Use computer to get estimated time of arrival for a warp jump."
-    w1 = Coord(); w2 = Coord()
-    prompt = False
-    if damaged(DCOMPTR):
-        prout(_("COMPUTER DAMAGED, USE A POCKET CALCULATOR."))
-        skip(1)
-        return
-    if scanner.nexttok() != "IHREAL":
-        prompt = True
-        scanner.chew()
-        proutn(_("Destination quadrant and/or sector? "))
-        if scanner.nexttok()!="IHREAL":
-            huh()
-            return
-    w1.j = int(scanner.real-0.5)
-    if scanner.nexttok() != "IHREAL":
-        huh()
-        return
-    w1.i = int(scanner.real-0.5)
-    if scanner.nexttok() == "IHREAL":
-        w2.j = int(scanner.real-0.5)
-        if scanner.nexttok() != "IHREAL":
-            huh()
-            return
-        w2.i = int(scanner.real-0.5)
-    else:
-        if game.quadrant.j>w1.i:
-            w2.i = 0
-        else:
-            w2.i=QUADSIZE-1
-        if game.quadrant.i>w1.j:
-            w2.j = 0
-        else:
-            w2.j=QUADSIZE-1
-    if not w1.valid_quadrant() or not w2.valid_sector():
-        huh()
-        return
-    dist = math.sqrt((w1.j-game.quadrant.j+(w2.j-game.sector.j)/(QUADSIZE*1.0))**2+
-                     (w1.i-game.quadrant.i+(w2.i-game.sector.i)/(QUADSIZE*1.0))**2)
-    wfl = False
-    if prompt:
-        prout(_("Answer \"no\" if you don't know the value:"))
-    while True:
-        scanner.chew()
-        proutn(_("Time or arrival date? "))
-        if scanner.nexttok()=="IHREAL":
-            ttime = scanner.real
-            if ttime > game.state.date:
-                ttime -= game.state.date # Actually a star date
-            twarp=(math.floor(math.sqrt((10.0*dist)/ttime)*10.0)+1.0)/10.0
-            if ttime <= 1e-10 or twarp > 10:
-                prout(_("We'll never make it, sir."))
-                scanner.chew()
-                return
-            if twarp < 1.0:
-                twarp = 1.0
-            break
-        scanner.chew()
-        proutn(_("Warp factor? "))
-        if scanner.nexttok()== "IHREAL":
-            wfl = True
-            twarp = scanner.real
-            if twarp<1.0 or twarp > 10.0:
-                huh()
-                return
-            break
-        prout(_("Captain, certainly you can give me one of these."))
-    while True:
-        scanner.chew()
-        ttime = (10.0*dist)/twarp**2
-        tpower = dist*twarp*twarp*twarp*(game.shldup+1)
-        if tpower >= game.energy:
-            prout(_("Insufficient energy, sir."))
-            if not game.shldup or tpower > game.energy*2.0:
-                if not wfl:
-                    return
-                proutn(_("New warp factor to try? "))
-                if scanner.nexttok() == "IHREAL":
-                    wfl = True
-                    twarp = scanner.real
-                    if twarp<1.0 or twarp > 10.0:
-                        huh()
-                        return
-                    continue
-                else:
-                    scanner.chew()
-                    skip(1)
-                    return
-            prout(_("But if you lower your shields,"))
-            proutn(_("remaining"))
-            tpower /= 2
-        else:
-            proutn(_("Remaining"))
-        prout(_(" energy will be %.2f.") % (game.energy-tpower))
-        if wfl:
-            prout(_("And we will arrive at stardate %.2f.") % (game.state.date+ttime))
-        elif twarp==1.0:
-            prout(_("Any warp speed is adequate."))
-        else:
-            prout(_("Minimum warp needed is %.2f,") % (twarp))
-            prout(_("and we will arrive at stardate %.2f.") % (game.state.date+ttime))
-        if game.state.remtime < ttime:
-            prout(_("Unfortunately, the Federation will be destroyed by then."))
-        if twarp > 6.0:
-            prout(_("You'll be taking risks at that speed, Captain"))
-        if (game.isatb==1 and game.state.kscmdr == w1 and \
-             scheduled(FSCDBAS)< ttime+game.state.date) or \
-            (scheduled(FCDBAS)<ttime+game.state.date and game.battle == w1):
-            prout(_("The starbase there will be destroyed by then."))
-        proutn(_("New warp factor to try? "))
-        if scanner.nexttok() == "IHREAL":
-            wfl = True
-            twarp = scanner.real
-            if twarp<1.0 or twarp > 10.0:
-                huh()
-                return
-        else:
-            scanner.chew()
-            skip(1)
-            return
-
-# Code from setup.c begins here
-
-def prelim():
-    "Issue a historically correct banner."
-    skip(2)
-    prout(_("-SUPER- STAR TREK"))
-    skip(1)
-# From the FORTRAN original
-#    prout(_("Latest update-21 Sept 78"))
-#    skip(1)
-
-def freeze(boss):
-    "Save game."
-    if boss:
-        scanner.push("emsave.trk")
-    key = scanner.nexttok()
-    if key == "IHEOL":
-        proutn(_("File name: "))
-        key = scanner.nexttok()
-    if key != "IHALPHA":
-        huh()
-        return
-    if '.' not in scanner.token:
-        scanner.token += ".trk"
-    try:
-        fp = open(scanner.token, "wb")
-    except IOError:
-        prout(_("Can't freeze game as file %s") % scanner.token)
-        return
-    pickle.dump(game, fp)
-    fp.close()
-    scanner.chew()
-
-def thaw():
-    "Retrieve saved game."
-    global game
-    game.passwd = None
-    key = scanner.nexttok()
-    if key == "IHEOL":
-        proutn(_("File name: "))
-        key = scanner.nexttok()
-    if key != "IHALPHA":
-        huh()
-        return True
-    if '.' not in scanner.token:
-        scanner.token += ".trk"
-    try:
-        fp = open(scanner.token, "rb")
-    except IOError:
-        prout(_("Can't thaw game in %s") % scanner.token)
-        return True
-    game = pickle.load(fp)
-    fp.close()
-    scanner.chew()
-    return False
-
-# I used <http://www.memory-alpha.org> to find planets
-# with references in ST:TOS.  Earth and the Alpha Centauri
-# Colony have been omitted.
-#
-# Some planets marked Class G and P here will be displayed as class M
-# because of the way planets are generated. This is a known bug.
-systnames = (
-    # Federation Worlds
-    _("Andoria (Fesoan)"),        # several episodes
-    _("Tellar Prime (Miracht)"),        # TOS: "Journey to Babel"
-    _("Vulcan (T'Khasi)"),        # many episodes
-    _("Medusa"),                # TOS: "Is There in Truth No Beauty?"
-    _("Argelius II (Nelphia)"),        # TOS: "Wolf in the Fold" ("IV" in BSD)
-    _("Ardana"),                # TOS: "The Cloud Minders"
-    _("Catulla (Cendo-Prae)"),        # TOS: "The Way to Eden"
-    _("Gideon"),                # TOS: "The Mark of Gideon"
-    _("Aldebaran III"),                # TOS: "The Deadly Years"
-    _("Alpha Majoris I"),        # TOS: "Wolf in the Fold"
-    _("Altair IV"),                # TOS: "Amok Time
-    _("Ariannus"),                # TOS: "Let That Be Your Last Battlefield"
-    _("Benecia"),                # TOS: "The Conscience of the King"
-    _("Beta Niobe I (Sarpeidon)"),        # TOS: "All Our Yesterdays"
-    _("Alpha Carinae II"),        # TOS: "The Ultimate Computer"
-    _("Capella IV (Kohath)"),        # TOS: "Friday's Child" (Class G)
-    _("Daran V"),                # TOS: "For the World is Hollow and I Have Touched the Sky"
-    _("Deneb II"),                # TOS: "Wolf in the Fold" ("IV" in BSD)
-    _("Eminiar VII"),                # TOS: "A Taste of Armageddon"
-    _("Gamma Canaris IV"),        # TOS: "Metamorphosis"
-    _("Gamma Tranguli VI (Vaalel)"),        # TOS: "The Apple"
-    _("Ingraham B"),                # TOS: "Operation: Annihilate"
-    _("Janus IV"),                # TOS: "The Devil in the Dark"
-    _("Makus III"),                # TOS: "The Galileo Seven"
-    _("Marcos XII"),                # TOS: "And the Children Shall Lead",
-    _("Omega IV"),                # TOS: "The Omega Glory"
-    _("Regulus V"),                # TOS: "Amok Time
-    _("Deneva"),                # TOS: "Operation -- Annihilate!"
-    # Worlds from BSD Trek
-    _("Rigel II"),                # TOS: "Shore Leave" ("III" in BSD)
-    _("Beta III"),                # TOS: "The Return of the Archons"
-    _("Triacus"),                # TOS: "And the Children Shall Lead",
-    _("Exo III"),                # TOS: "What Are Little Girls Made Of?" (Class P)
-    #        # Others
-    #    _("Hansen's Planet"),        # TOS: "The Galileo Seven"
-    #    _("Taurus IV"),                # TOS: "The Galileo Seven" (class G)
-    #    _("Antos IV (Doraphane)"),        # TOS: "Whom Gods Destroy", "Who Mourns for Adonais?"
-    #    _("Izar"),                        # TOS: "Whom Gods Destroy"
-    #    _("Tiburon"),                # TOS: "The Way to Eden"
-    #    _("Merak II"),                # TOS: "The Cloud Minders"
-    #    _("Coridan (Desotriana)"),        # TOS: "Journey to Babel"
-    #    _("Iotia"),                # TOS: "A Piece of the Action"
-)
-
-device = (
-    _("S. R. Sensors"), \
-    _("L. R. Sensors"), \
-    _("Phasers"), \
-    _("Photon Tubes"), \
-    _("Life Support"), \
-    _("Warp Engines"), \
-    _("Impulse Engines"), \
-    _("Shields"), \
-    _("Subspace Radio"), \
-    _("Shuttle Craft"), \
-    _("Computer"), \
-    _("Navigation System"), \
-    _("Transporter"), \
-    _("Shield Control"), \
-    _("Death Ray"), \
-    _("D. S. Probe"), \
-    _("Cloaking Device"), \
-)
-
-def setup():
-    "Prepare to play, set up cosmos."
-    w = Coord()
-    #  Decide how many of everything
-    if choose():
-        return # frozen game
-    # Prepare the Enterprise
-    game.alldone = game.gamewon = game.shldchg = game.shldup = False
-    game.ship = 'E'
-    game.state.crew = FULLCREW
-    game.energy = game.inenrg = 5000.0
-    game.shield = game.inshld = 2500.0
-    game.inlsr = 4.0
-    game.lsupres = 4.0
-    game.quadrant = randplace(GALSIZE)
-    game.sector = randplace(QUADSIZE)
-    game.torps = game.intorps = 10
-    game.nprobes = rnd.integer(2, 5)
-    game.warpfac = 5.0
-    for i in range(NDEVICES):
-        game.damage[i] = 0.0
-    # Set up assorted game parameters
-    game.battle = Coord()
-    game.state.date = game.indate = 100.0 * rnd.real(20, 51)
-    game.nkinks = game.nhelp = game.casual = game.abandoned = 0
-    game.iscate = game.resting = game.imine = game.icrystl = game.icraft = False
-    game.isatb = game.state.nplankl = 0
-    game.state.starkl = game.state.basekl = game.state.nworldkl = 0
-    game.iscraft = "onship"
-    game.landed = False
-    game.alive = True
-
-    # the galaxy
-    game.state.galaxy = fill2d(GALSIZE, lambda i_unused, j_unused: Quadrant())
-    # the starchart
-    game.state.chart = fill2d(GALSIZE, lambda i_unused, j_unused: Page())
-
-    game.state.planets = []      # Planet information
-    game.state.baseq = []      # Base quadrant coordinates
-    game.state.kcmdr = []      # Commander quadrant coordinates
-    game.statekscmdr = Coord() # Supercommander quadrant coordinates
-
-    # Starchart is functional but we've never seen it
-    game.lastchart = FOREVER
-    # Put stars in the galaxy
-    game.instar = 0
-    for i in range(GALSIZE):
-        for j in range(GALSIZE):
-            # Can't have more stars per quadrant than fit in one decimal digit,
-            # if we do the chart representation will break.
-            k = rnd.integer(1, min(10, QUADSIZE**2/10))
-            game.instar += k
-            game.state.galaxy[i][j].stars = k
-    # Locate star bases in galaxy
-    if game.idebug:
-        prout("=== Allocating %d bases" % game.inbase)
-    for i in range(game.inbase):
-        while True:
-            while True:
-                w = randplace(GALSIZE)
-                if not game.state.galaxy[w.i][w.j].starbase:
-                    break
-            contflag = False
-            # C version: for (j = i-1; j > 0; j--)
-            # so it did them in the opposite order.
-            for j in range(1, i):
-                # Improved placement algorithm to spread out bases
-                distq = (w - game.state.baseq[j]).distance()
-                if distq < 6.0*(BASEMAX+1-game.inbase) and rnd.withprob(0.75):
-                    contflag = True
-                    if game.idebug:
-                        prout("=== Abandoning base #%d at %s" % (i, w))
-                    break
-                elif distq < 6.0 * (BASEMAX+1-game.inbase):
-                    if game.idebug:
-                        prout("=== Saving base #%d, close to #%d" % (i, j))
-            if not contflag:
-                break
-        if game.idebug:
-            prout("=== Placing base #%d in quadrant %s" % (i, w))
-        game.state.baseq.append(w)
-        game.state.galaxy[w.i][w.j].starbase = game.state.chart[w.i][w.j].starbase = True
-    # Position ordinary Klingon Battle Cruisers
-    krem = game.inkling
-    klumper = 0.25*game.skill*(9.0-game.length)+1.0
-    if klumper > MAXKLQUAD:
-        klumper = MAXKLQUAD
-    while True:
-        r = rnd.real()
-        klump = int((1.0 - r*r)*klumper)
-        if klump > krem:
-            klump = krem
-        krem -= klump
-        while True:
-            w = randplace(GALSIZE)
-            if not game.state.galaxy[w.i][w.j].supernova and \
-               game.state.galaxy[w.i][w.j].klingons + klump <= MAXKLQUAD:
-                break
-        game.state.galaxy[w.i][w.j].klingons += klump
-        if krem <= 0:
-            break
-    # Position Klingon Commander Ships
-    for i in range(game.incom):
-        while True:
-            w = randplace(GALSIZE)
-            if not welcoming(w) or w in game.state.kcmdr:
-                continue
-            if (game.state.galaxy[w.i][w.j].klingons or rnd.withprob(0.25)):
-                break
-        game.state.galaxy[w.i][w.j].klingons += 1
-        game.state.kcmdr.append(w)
-    # Locate planets in galaxy
-    for i in range(game.inplan):
-        while True:
-            w = randplace(GALSIZE)
-            if game.state.galaxy[w.i][w.j].planet is None:
-                break
-        new = Planet()
-        new.quadrant = w
-        new.crystals = "absent"
-        if (game.options & OPTION_WORLDS) and i < NINHAB:
-            new.pclass = "M"        # All inhabited planets are class M
-            new.crystals = "absent"
-            new.known = "known"
-            new.name = systnames[i]
-            new.inhabited = True
-        else:
-            new.pclass = ("M", "N", "O")[rnd.integer(0, 3)]
-            if rnd.withprob(0.33):
-                new.crystals = "present"
-            new.known = "unknown"
-            new.inhabited = False
-        game.state.galaxy[w.i][w.j].planet = new
-        game.state.planets.append(new)
-    # Locate Romulans
-    for i in range(game.state.nromrem):
-        w = randplace(GALSIZE)
-        game.state.galaxy[w.i][w.j].romulans += 1
-    # Place the Super-Commander if needed
-    if game.state.nscrem > 0:
-        while True:
-            w = randplace(GALSIZE)
-            if welcoming(w):
-                break
-        game.state.kscmdr = w
-        game.state.galaxy[w.i][w.j].klingons += 1
-    # Initialize times for extraneous events
-    schedule(FSNOVA, expran(0.5 * game.intime))
-    schedule(FTBEAM, expran(1.5 * (game.intime / len(game.state.kcmdr))))
-    schedule(FSNAP, rnd.real(1.0, 2.0)) # Force an early snapshot
-    schedule(FBATTAK, expran(0.3*game.intime))
-    unschedule(FCDBAS)
-    if game.state.nscrem:
-        schedule(FSCMOVE, 0.2777)
-    else:
-        unschedule(FSCMOVE)
-    unschedule(FSCDBAS)
-    unschedule(FDSPROB)
-    if (game.options & OPTION_WORLDS) and game.skill >= SKILL_GOOD:
-        schedule(FDISTR, expran(1.0 + game.intime))
-    else:
-        unschedule(FDISTR)
-    unschedule(FENSLV)
-    unschedule(FREPRO)
-    # Place thing (in tournament game, we don't want one!)
-    # New in SST2K: never place the Thing near a starbase.
-    # This makes sense and avoids a special case in the old code.
-    global thing
-    if game.tourn is None:
-        while True:
-            thing = randplace(GALSIZE)
-            if thing not in game.state.baseq:
-                break
-    skip(2)
-    game.state.snap = False
-    if game.skill == SKILL_NOVICE:
-        prout(_("It is stardate %d. The Federation is being attacked by") % int(game.state.date))
-        prout(_("a deadly Klingon invasion force. As captain of the United"))
-        prout(_("Starship U.S.S. Enterprise, it is your mission to seek out"))
-        prout(_("and destroy this invasion force of %d battle cruisers.") % ((game.inkling + game.incom + game.inscom)))
-        prout(_("You have an initial allotment of %d stardates to complete") % int(game.intime))
-        prout(_("your mission.  As you proceed you may be given more time."))
-        skip(1)
-        prout(_("You will have %d supporting starbases.") % (game.inbase))
-        proutn(_("Starbase locations-  "))
-    else:
-        prout(_("Stardate %d.") % int(game.state.date))
-        skip(1)
-        prout(_("%d Klingons.") % (game.inkling + game.incom + game.inscom))
-        prout(_("An unknown number of Romulans."))
-        if game.state.nscrem:
-            prout(_("And one (GULP) Super-Commander."))
-        prout(_("%d stardates.") % int(game.intime))
-        proutn(_("%d starbases in ") % game.inbase)
-    for i in range(game.inbase):
-        proutn(repr(game.state.baseq[i]))
-        proutn("  ")
-    skip(2)
-    proutn(_("The Enterprise is currently in Quadrant %s") % game.quadrant)
-    proutn(_(" Sector %s") % game.sector)
-    skip(2)
-    prout(_("Good Luck!"))
-    if game.state.nscrem:
-        prout(_("  YOU'LL NEED IT."))
-    waitfor()
-    clrscr()
-    setwnd(message_window)
-    newqad()
-    if len(game.enemies) - (thing == game.quadrant) - (game.tholian is not None):
-        game.shldup = True
-    if game.neutz:        # bad luck to start in a Romulan Neutral Zone
-        attack(torps_ok=False)
-
-def choose():
-    "Choose your game type."
-    while True:
-        game.tourn = game.length = 0
-        game.thawed = False
-        game.skill = SKILL_NONE
-        # Do not chew here, we want to use command-line tokens
-        if not scanner.inqueue: # Can start with command line options
-            proutn(_("Would you like a regular, tournament, or saved game? "))
-        scanner.nexttok()
-        if scanner.sees("tournament"):
-            while scanner.nexttok() == "IHEOL":
-                proutn(_("Type in tournament number-"))
-            if scanner.real == 0:
-                scanner.chew()
-                continue # We don't want a blank entry
-            game.tourn = int(round(scanner.real))
-            rnd.seed(scanner.real)
-            if logfp:
-                logfp.write("# rnd.seed(%d)\n" % scanner.real)
-            break
-        if scanner.sees("saved") or scanner.sees("frozen"):
-            if thaw():
-                continue
-            scanner.chew()
-            if game.passwd is None:
-                continue
-            if not game.alldone:
-                game.thawed = True # No plaque if not finished
-            report()
-            waitfor()
-            return True
-        if scanner.sees("regular"):
-            break
-        proutn(_("What is \"%s\"? ") % scanner.token)
-        scanner.chew()
-    while game.length==0 or game.skill==SKILL_NONE:
-        if scanner.nexttok() == "IHALPHA":
-            if scanner.sees("short"):
-                game.length = 1
-            elif scanner.sees("medium"):
-                game.length = 2
-            elif scanner.sees("long"):
-                game.length = 4
-            elif scanner.sees("novice"):
-                game.skill = SKILL_NOVICE
-            elif scanner.sees("fair"):
-                game.skill = SKILL_FAIR
-            elif scanner.sees("good"):
-                game.skill = SKILL_GOOD
-            elif scanner.sees("expert"):
-                game.skill = SKILL_EXPERT
-            elif scanner.sees("emeritus"):
-                game.skill = SKILL_EMERITUS
-            else:
-                proutn(_("What is \""))
-                proutn(scanner.token)
-                prout("\"?")
-        else:
-            scanner.chew()
-            if game.length==0:
-                proutn(_("Would you like a Short, Medium, or Long game? "))
-            elif game.skill == SKILL_NONE:
-                proutn(_("Are you a Novice, Fair, Good, Expert, or Emeritus player? "))
-    # Choose game options -- added by ESR for SST2K
-    if scanner.nexttok() != "IHALPHA":
-        scanner.chew()
-        proutn(_("Choose your game style (plain, almy, fancy or just press enter): "))
-        scanner.nexttok()
-    if scanner.sees("plain"):
-        # Approximates the UT FORTRAN version.
-        game.options &=~ (OPTION_THOLIAN | OPTION_PLANETS | OPTION_THINGY | OPTION_PROBE | OPTION_RAMMING | OPTION_MVBADDY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS | OPTION_COLOR | OPTION_CAPTURE | OPTION_CLOAK | OPTION_DOTFILL)
-        game.options |= OPTION_PLAIN
-    elif scanner.sees("almy"):
-        # Approximates Tom Almy's version.
-        game.options &=~ (OPTION_THINGY | OPTION_BLKHOLE | OPTION_BASE | OPTION_WORLDS | OPTION_COLOR | OPTION_DOTFILL)
-        game.options |= OPTION_ALMY
-    elif scanner.sees("fancy") or scanner.sees("\n"):
-        pass
-    elif len(scanner.token):
-        proutn(_("What is \"%s\"?") % scanner.token)
-    setpassword()
-    if game.passwd == "debug":
-        game.idebug = True
-        prout("=== Debug mode enabled.")
-    # Use parameters to generate initial values of things
-    game.damfac = 0.5 * game.skill
-    game.inbase = rnd.integer(BASEMIN, BASEMAX+1)
-    game.inplan = 0
-    if game.options & OPTION_PLANETS:
-        game.inplan += rnd.integer(MAXUNINHAB/2, MAXUNINHAB+1)
-    if game.options & OPTION_WORLDS:
-        game.inplan += int(NINHAB)
-    game.state.nromrem = game.inrom = rnd.integer(2 * game.skill)
-    game.state.nscrem = game.inscom = (game.skill > SKILL_FAIR)
-    game.state.remtime = 7.0 * game.length
-    game.intime = game.state.remtime
-    game.inkling = int(2.0*game.intime*((game.skill+1 - 2*rnd.real())*game.skill*0.1+.15))
-    game.incom = min(MINCMDR, int(game.skill + 0.0625*game.inkling*rnd.real()))
-    game.state.remres = (game.inkling+4*game.incom)*game.intime
-    game.inresor = game.state.remres
-    if game.inkling > 50:
-        game.inbase += 1
-    return False
-
-def dropin(iquad=None):
-    "Drop a feature on a random dot in the current quadrant."
-    while True:
-        w = randplace(QUADSIZE)
-        if game.quad[w.i][w.j] == '.':
-            break
-    if iquad is not None:
-        game.quad[w.i][w.j] = iquad
-    return w
-
-def newcnd():
-    "Update our alert status."
-    game.condition = "green"
-    if game.energy < 1000.0:
-        game.condition = "yellow"
-    if game.state.galaxy[game.quadrant.i][game.quadrant.j].klingons or game.state.galaxy[game.quadrant.i][game.quadrant.j].romulans:
-        game.condition = "red"
-    if not game.alive:
-        game.condition="dead"
-
-def newkling():
-    "Drop new Klingon into current quadrant."
-    return Enemy('K', loc=dropin(), power=rnd.real(300,450)+25.0*game.skill)
-
-def sortenemies():
-    "Sort enemies by distance so 'nearest' is meaningful."
-    game.enemies.sort(key=lambda x: x.kdist)
-
-def newqad():
-    "Set up a new state of quadrant, for when we enter or re-enter it."
-    game.justin = True
-    game.iplnet = None
-    game.neutz = game.inorbit = game.landed = False
-    game.ientesc = game.iseenit = game.isviolreported = False
-    game.tholian = None
-    # Create a blank quadrant
-    game.quad = fill2d(QUADSIZE, lambda i, j: '.')
-    if game.iscate:
-        # Attempt to escape Super-commander, so tbeam back!
-        game.iscate = False
-        game.ientesc = True
-    q = game.state.galaxy[game.quadrant.i][game.quadrant.j]
-    # cope with supernova
-    if q.supernova:
-        return
-    game.klhere = q.klingons
-    game.irhere = q.romulans
-    # Position Starship
-    game.quad[game.sector.i][game.sector.j] = game.ship
-    game.enemies = []
-    if q.klingons:
-        # Position ordinary Klingons
-        for _i in range(game.klhere):
-            newkling()
-        # If we need a commander, promote a Klingon
-        for cmdr in game.state.kcmdr:
-            if cmdr == game.quadrant:
-                e = game.enemies[game.klhere-1]
-                game.quad[e.location.i][e.location.j] = 'C'
-                e.power = rnd.real(950,1350) + 50.0*game.skill
-                break
-        # If we need a super-commander, promote a Klingon
-        if game.quadrant == game.state.kscmdr:
-            e = game.enemies[0]
-            game.quad[e.location.i][e.location.j] = 'S'
-            e.power = rnd.real(1175.0,  1575.0) + 125.0*game.skill
-            game.iscate = (game.remkl() > 1)
-    # Put in Romulans if needed
-    for _i in range(q.romulans):
-        Enemy('R', loc=dropin(), power=rnd.real(400.0,850.0)+50.0*game.skill)
-    # If quadrant needs a starbase, put it in
-    if q.starbase:
-        game.base = dropin('B')
-    # If quadrant needs a planet, put it in
-    if q.planet:
-        game.iplnet = q.planet
-        if not q.planet.inhabited:
-            game.plnet = dropin('P')
-        else:
-            game.plnet = dropin('@')
-    # Check for condition
-    newcnd()
-    # Check for RNZ
-    if game.irhere > 0 and game.klhere == 0:
-        game.neutz = True
-        if not damaged(DRADIO):
-            skip(1)
-            prout(_("LT. Uhura- \"Captain, an urgent message."))
-            prout(_("  I'll put it on audio.\"  CLICK"))
-            skip(1)
-            prout(_("INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE."))
-            prout(_("LEAVE AT ONCE, OR YOU WILL BE DESTROYED!"))
-    # Put in THING if needed
-    if thing == game.quadrant:
-        Enemy(etype='?', loc=dropin(),
-              power=rnd.real(6000,6500.0)+250.0*game.skill)
-        if not damaged(DSRSENS):
-            skip(1)
-            prout(_("Mr. Spock- \"Captain, this is most unusual."))
-            prout(_("    Please examine your short-range scan.\""))
-    # Decide if quadrant needs a Tholian; lighten up if skill is low
-    if game.options & OPTION_THOLIAN:
-        if (game.skill < SKILL_GOOD and rnd.withprob(0.02)) or \
-            (game.skill == SKILL_GOOD and rnd.withprob(0.05)) or \
-            (game.skill > SKILL_GOOD and rnd.withprob(0.08)):
-            w = Coord()
-            while True:
-                w.i = rnd.withprob(0.5) * (QUADSIZE-1)
-                w.j = rnd.withprob(0.5) * (QUADSIZE-1)
-                if game.quad[w.i][w.j] == '.':
-                    break
-            game.tholian = Enemy(etype='T', loc=w,
-                                 power=rnd.integer(100, 500) + 25.0*game.skill)
-            # Reserve unoccupied corners
-            if game.quad[0][0]=='.':
-                game.quad[0][0] = 'X'
-            if game.quad[0][QUADSIZE-1]=='.':
-                game.quad[0][QUADSIZE-1] = 'X'
-            if game.quad[QUADSIZE-1][0]=='.':
-                game.quad[QUADSIZE-1][0] = 'X'
-            if game.quad[QUADSIZE-1][QUADSIZE-1]=='.':
-                game.quad[QUADSIZE-1][QUADSIZE-1] = 'X'
-    sortenemies()
-    # And finally the stars
-    for _i in range(q.stars):
-        dropin('*')
-    # Put in a few black holes
-    for _i in range(1, 3+1):
-        if rnd.withprob(0.5):
-            dropin(' ')
-    # Take out X's in corners if Tholian present
-    if game.tholian:
-        if game.quad[0][0]=='X':
-            game.quad[0][0] = '.'
-        if game.quad[0][QUADSIZE-1]=='X':
-            game.quad[0][QUADSIZE-1] = '.'
-        if game.quad[QUADSIZE-1][0]=='X':
-            game.quad[QUADSIZE-1][0] = '.'
-        if game.quad[QUADSIZE-1][QUADSIZE-1]=='X':
-            game.quad[QUADSIZE-1][QUADSIZE-1] = '.'
-    # This should guarantee that replay games don't lose info about the chart
-    if (game.options & OPTION_AUTOSCAN) or replayfp:
-        lrscan(silent=True)
-
-def setpassword():
-    "Set the self-destruct password."
-    if game.options & OPTION_PLAIN:
-        while True:
-            scanner.chew()
-            proutn(_("Please type in a secret password- "))
-            scanner.nexttok()
-            game.passwd = scanner.token
-            if game.passwd is not None:
-                break
-    else:
-        game.passwd = ""
-        game.passwd += chr(ord('a')+rnd.integer(26))
-        game.passwd += chr(ord('a')+rnd.integer(26))
-        game.passwd += chr(ord('a')+rnd.integer(26))
-
-# Code from sst.c begins here
-
-commands = [
-    ("SRSCAN",           OPTION_TTY),
-    ("STATUS",           OPTION_TTY),
-    ("REQUEST",          OPTION_TTY),
-    ("LRSCAN",           OPTION_TTY),
-    ("PHASERS",          0),
-    ("TORPEDO",          0),
-    ("PHOTONS",          0),
-    ("MOVE",             0),
-    ("SHIELDS",          0),
-    ("DOCK",             0),
-    ("DAMAGES",          0),
-    ("CHART",            0),
-    ("IMPULSE",          0),
-    ("REST",             0),
-    ("WARP",             0),
-    ("SENSORS",          OPTION_PLANETS),
-    ("ORBIT",            OPTION_PLANETS),
-    ("TRANSPORT",        OPTION_PLANETS),
-    ("MINE",             OPTION_PLANETS),
-    ("CRYSTALS",         OPTION_PLANETS),
-    ("SHUTTLE",          OPTION_PLANETS),
-    ("PLANETS",          OPTION_PLANETS),
-    ("REPORT",           0),
-    ("COMPUTER",         0),
-    ("COMMANDS",         0),
-    ("EMEXIT",           0),
-    ("PROBE",            OPTION_PROBE),
-    ("SAVE",             0),
-    ("FREEZE",           0),        # Synonym for SAVE
-    ("ABANDON",          0),
-    ("DESTRUCT",         0),
-    ("DEATHRAY",         0),
-    ("CAPTURE",          OPTION_CAPTURE),
-    ("CLOAK",            OPTION_CLOAK),
-    ("DEBUG",            0),
-    ("MAYDAY",           0),
-    ("SOS",              0),        # Synonym for MAYDAY
-    ("CALL",             0),        # Synonym for MAYDAY
-    ("QUIT",             0),
-    ("HELP",             0),
-    ("SCORE",            0),
-    ("CURSES",            0),
-    ("",                 0),
-]
-
-def listCommands():
-    "Generate a list of legal commands."
-    prout(_("LEGAL COMMANDS ARE:"))
-    emitted = 0
-    for (key, opt) in commands:
-        if not opt or (opt & game.options):
-            proutn("%-12s " % key)
-            emitted += 1
-            if emitted % 5 == 4:
-                skip(1)
-    skip(1)
-
-def helpme():
-    "Browse on-line help."
-    key = scanner.nexttok()
-    while True:
-        if key == "IHEOL":
-            setwnd(prompt_window)
-            proutn(_("Help on what command? "))
-            key = scanner.nexttok()
-        setwnd(message_window)
-        if key == "IHEOL":
-            return
-        cmds = [x[0] for x in commands]
-        if scanner.token.upper() in cmds or scanner.token.upper() == "ABBREV":
-            break
-        skip(1)
-        listCommands()
-        key = "IHEOL"
-        scanner.chew()
-        skip(1)
-    cmd = scanner.token.upper()
-    for directory in docpath:
-        try:
-            fp = open(os.path.join(directory, "sst.doc"), "r")
-            break
-        except IOError:
-            pass
-    else:
-        prout(_("Spock-  \"Captain, that information is missing from the"))
-        prout(_("   computer. You need to find sst.doc and put it somewhere"))
-        proutn(_("   in these directories: %s") % ":".join(docpath))
-        prout(".\"")
-        # This used to continue: "You need to find SST.DOC and put
-        # it in the current directory."
-        return
-    while True:
-        linebuf = fp.readline()
-        if linebuf == '':
-            prout(_("Spock- \"Captain, there is no information on that command.\""))
-            fp.close()
-            return
-        if linebuf[0] == '%' and linebuf[1] == '%' and linebuf[2] == ' ':
-            linebuf = linebuf[3:].strip()
-            if cmd.upper() == linebuf:
-                break
-    skip(1)
-    prout(_("Spock- \"Captain, I've found the following information:\""))
-    skip(1)
-    while True:
-        linebuf = fp.readline()
-        if "******" in linebuf:
-            break
-        proutn(linebuf)
-    fp.close()
-
-def makemoves():
-    "Command-interpretation loop."
-    def checkviol():
-        if game.irhere and game.state.date >= ALGERON and not game.isviolreported and game.iscloaked:
-            prout(_("The Romulan ship discovers you are breaking the Treaty of Algeron!"))
-            game.ncviol += 1
-            game.isviolreported = True
-    while True:         # command loop
-        drawmaps(1)
-        while True:        # get a command
-            hitme = False
-            game.optime = game.justin = False
-            scanner.chew()
-            setwnd(prompt_window)
-            clrscr()
-            proutn("COMMAND> ")
-            if scanner.nexttok() == "IHEOL":
-                if game.options & OPTION_CURSES:
-                    makechart()
-                continue
-            elif scanner.token == "":
-                continue
-            game.ididit = False
-            clrscr()
-            setwnd(message_window)
-            clrscr()
-            abandon_passed = False
-            cmd = ""   # Force cmd to persist after loop
-            opt = 0    # Force opt to persist after loop
-            for (cmd, opt) in commands:
-                # commands after ABANDON cannot be abbreviated
-                if cmd == "ABANDON":
-                    abandon_passed = True
-                if cmd == scanner.token.upper() or (not abandon_passed \
-                        and cmd.startswith(scanner.token.upper())):
-                    break
-            if cmd == "":
-                listCommands()
-                continue
-            elif opt and not (opt & game.options):
-                huh()
-            else:
-                break
-        if game.options & OPTION_CURSES:
-            prout("COMMAND> %s" % cmd)
-        if cmd == "SRSCAN":                # srscan
-            srscan()
-        elif cmd == "STATUS":                # status
-            status()
-        elif cmd == "REQUEST":                # status request
-            request()
-        elif cmd == "LRSCAN":                # long range scan
-            lrscan(silent=False)
-        elif cmd == "PHASERS":                # phasers
-            phasers()
-            if game.ididit:
-                checkviol()
-                hitme = True
-        elif cmd in ("TORPEDO", "PHOTONS"):        # photon torpedos
-            torps()
-            if game.ididit:
-                checkviol()
-                hitme = True
-        elif cmd == "MOVE":                # move under warp
-            warp(wcourse=None, involuntary=False)
-        elif cmd == "SHIELDS":                # shields
-            doshield(shraise=False)
-            if game.ididit:
-                hitme = True
-                game.shldchg = False
-        elif cmd == "DOCK":                # dock at starbase
-            dock(True)
-            if game.ididit:
-                attack(torps_ok=False)
-        elif cmd == "DAMAGES":                # damage reports
-            damagereport()
-        elif cmd == "CHART":                # chart
-            makechart()
-        elif cmd == "IMPULSE":                # impulse
-            impulse()
-        elif cmd == "REST":                # rest
-            wait()
-            if game.ididit:
-                hitme = True
-        elif cmd == "WARP":                # warp
-            setwarp()
-        elif cmd == "SENSORS":                # sensors
-            sensor()
-        elif cmd == "ORBIT":                # orbit
-            orbit()
-            if game.ididit:
-                hitme = True
-        elif cmd == "TRANSPORT":                # transport "beam"
-            beam()
-        elif cmd == "MINE":                # mine
-            mine()
-            if game.ididit:
-                hitme = True
-        elif cmd == "CRYSTALS":                # crystals
-            usecrystals()
-            if game.ididit:
-                hitme = True
-        elif cmd == "SHUTTLE":                # shuttle
-            shuttle()
-            if game.ididit:
-                hitme = True
-        elif cmd == "PLANETS":                # Planet list
-            survey()
-        elif cmd == "REPORT":                # Game Report
-            report()
-        elif cmd == "COMPUTER":                # use COMPUTER!
-            eta()
-        elif cmd == "COMMANDS":
-            listCommands()
-        elif cmd == "EMEXIT":                # Emergency exit
-            clrscr()                        # Hide screen
-            freeze(True)                # forced save
-            raise SystemExit(1)                # And quick exit
-        elif cmd == "PROBE":
-            probe()                        # Launch probe
-            if game.ididit:
-                hitme = True
-        elif cmd == "ABANDON":                # Abandon Ship
-            abandon()
-        elif cmd == "DESTRUCT":                # Self Destruct
-            selfdestruct()
-        elif cmd == "SAVE":                # Save Game
-            freeze(False)
-            clrscr()
-            if game.skill > SKILL_GOOD:
-                prout(_("WARNING--Saved games produce no plaques!"))
-        elif cmd == "DEATHRAY":                # Try a desparation measure
-            deathray()
-            if game.ididit:
-                hitme = True
-        elif cmd == "CAPTURE":
-            capture()
-        elif cmd == "CLOAK":
-            cloak()
-        elif cmd == "DEBUGCMD":                # What do we want for debug???
-            debugme()
-        elif cmd == "MAYDAY":                # Call for help
-            mayday()
-            if game.ididit:
-                hitme = True
-        elif cmd == "QUIT":
-            game.alldone = True                # quit the game
-        elif cmd == "HELP":
-            helpme()                        # get help
-        elif cmd == "SCORE":
-            score()                         # see current score
-        elif cmd == "CURSES":
-            game.options |= (OPTION_CURSES | OPTION_COLOR)
-            iostart()
-        while True:
-            if game.alldone:
-                break                # Game has ended
-            if game.optime != 0.0:
-                events()
-                if game.alldone:
-                    break        # Events did us in
-            if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-                atover(False)
-                continue
-            if hitme and not game.justin:
-                attack(torps_ok=True)
-                if game.alldone:
-                    break
-                if game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova:
-                    atover(False)
-                    hitme = True
-                    continue
-            break
-        if game.alldone:
-            break
-    if game.idebug:
-        prout("=== Ending")
-
-def cramen(ch):
-    "Emit the name of an enemy or feature."
-    if   ch == 'R': s = _("Romulan")
-    elif ch == 'K': s = _("Klingon")
-    elif ch == 'C': s = _("Commander")
-    elif ch == 'S': s = _("Super-commander")
-    elif ch == '*': s = _("Star")
-    elif ch == 'P': s = _("Planet")
-    elif ch == 'B': s = _("Starbase")
-    elif ch == ' ': s = _("Black hole")
-    elif ch == 'T': s = _("Tholian")
-    elif ch == '#': s = _("Tholian web")
-    elif ch == '?': s = _("Stranger")
-    elif ch == '@': s = _("Inhabited World")
-    else: s = "Unknown??"
-    return s
-
-def crmena(loud, enemy, loctype, w):
-    "Emit the name of an enemy and his location."
-    buf = ""
-    if loud:
-        buf += "***"
-    buf += cramen(enemy) + _(" at ")
-    if loctype == "quadrant":
-        buf += _("Quadrant ")
-    elif loctype == "sector":
-        buf += _("Sector ")
-    return buf + repr(w)
-
-def crmshp():
-    "Emit our ship name."
-    return{'E':_("Enterprise"),'F':_("Faerie Queene")}.get(game.ship,"Ship???")
-
-def stars():
-    "Emit a line of stars"
-    prouts("******************************************************")
-    skip(1)
-
-def expran(avrage):
-    return -avrage*math.log(1e-7 + rnd.real())
-
-def randplace(size):
-    "Choose a random location."
-    w = Coord()
-    w.i = rnd.integer(size)
-    w.j = rnd.integer(size)
-    return w
-
-class sstscanner:
-    def __init__(self):
-        self.type = None
-        self.token = None
-        self.real = 0.0
-        self.inqueue = []
-    def nexttok(self):
-        # Get a token from the user
-        self.real = 0.0
-        self.token = ''
-        # Fill the token quue if nothing here
-        while not self.inqueue:
-            sline = cgetline()
-            if curwnd==prompt_window:
-                clrscr()
-                setwnd(message_window)
-                clrscr()
-            if sline == '':
-                return None
-            if not sline:
-                continue
-            else:
-                self.inqueue = sline.lstrip().split() + ["\n"]
-        # From here on in it's all looking at the queue
-        self.token = self.inqueue.pop(0)
-        if self.token == "\n":
-            self.type = "IHEOL"
-            return "IHEOL"
-        try:
-            self.real = float(self.token)
-            self.type = "IHREAL"
-            return "IHREAL"
-        except ValueError:
-            pass
-        # Treat as alpha
-        self.token = self.token.lower()
-        self.type = "IHALPHA"
-        self.real = None
-        return "IHALPHA"
-    def append(self, tok):
-        self.inqueue.append(tok)
-    def push(self, tok):
-        self.inqueue.insert(0, tok)
-    def waiting(self):
-        return self.inqueue
-    def chew(self):
-        # Demand input for next scan
-        self.inqueue = []
-        self.real = self.token = None
-    def sees(self, s):
-        # compares s to item and returns true if it matches to the length of s
-        return s.startswith(self.token)
-    def int(self):
-        # Round token value to nearest integer
-        return int(round(self.real))
-    def getcoord(self):
-        s = Coord()
-        self.nexttok()
-        if self.type != "IHREAL":
-            huh()
-            return None
-        s.i = self.int()-1
-        self.nexttok()
-        if self.type != "IHREAL":
-            huh()
-            return None
-        s.j = self.int()-1
-        return s
-    def __repr__(self):
-        return "<sstcanner: token=%s, type=%s, queue=%s>" % (self.token, self.type, self.inqueue)
-
-def ja():
-    "Yes-or-no confirmation."
-    scanner.chew()
-    while True:
-        scanner.nexttok()
-        if scanner.token == 'y':
-            return True
-        if scanner.token == 'n':
-            return False
-        scanner.chew()
-        proutn(_("Please answer with \"y\" or \"n\": "))
-
-def huh():
-    "Complain about unparseable input."
-    scanner.chew()
-    skip(1)
-    prout(_("Beg your pardon, Captain?"))
-
-def debugme():
-    "Access to the internals for debugging."
-    proutn("Reset levels? ")
-    if ja():
-        if game.energy < game.inenrg:
-            game.energy = game.inenrg
-        game.shield = game.inshld
-        game.torps = game.intorps
-        game.lsupres = game.inlsr
-    proutn("Reset damage? ")
-    if ja():
-        for i in range(NDEVICES):
-            if game.damage[i] > 0.0:
-                game.damage[i] = 0.0
-    proutn("Toggle debug flag? ")
-    if ja():
-        game.idebug = not game.idebug
-        if game.idebug:
-            prout("Debug output ON")
-        else:
-            prout("Debug output OFF")
-    proutn("Cause selective damage? ")
-    if ja():
-        for i in range(NDEVICES):
-            proutn("Kill %s?" % device[i])
-            scanner.chew()
-            key = scanner.nexttok()
-            if key == "IHALPHA" and scanner.sees("y"):
-                game.damage[i] = 10.0
-    proutn("Examine/change events? ")
-    if ja():
-        ev = Event()
-        w = Coord()
-        legends = {
-            FSNOVA:  "Supernova       ",
-            FTBEAM:  "T Beam          ",
-            FSNAP:   "Snapshot        ",
-            FBATTAK: "Base Attack     ",
-            FCDBAS:  "Base Destroy    ",
-            FSCMOVE: "SC Move         ",
-            FSCDBAS: "SC Base Destroy ",
-            FDSPROB: "Probe Move      ",
-            FDISTR:  "Distress Call   ",
-            FENSLV:  "Enslavement     ",
-            FREPRO:  "Klingon Build   ",
-        }
-        for i in range(1, NEVENTS):
-            proutn(legends[i])
-            if is_scheduled(i):
-                proutn("%.2f" % (scheduled(i)-game.state.date))
-                if i == FENSLV or i == FREPRO:
-                    ev = findevent(i)
-                    proutn(" in %s" % ev.quadrant)
-            else:
-                proutn("never")
-            proutn("? ")
-            scanner.chew()
-            key = scanner.nexttok()
-            if key == 'n':
-                unschedule(i)
-                scanner.chew()
-            elif key == "IHREAL":
-                ev = schedule(i, scanner.real)
-                if i == FENSLV or i == FREPRO:
-                    scanner.chew()
-                    proutn("In quadrant- ")
-                    key = scanner.nexttok()
-                    # "IHEOL" says to leave coordinates as they are
-                    if key != "IHEOL":
-                        if key != "IHREAL":
-                            prout("Event %d canceled, no x coordinate." % (i))
-                            unschedule(i)
-                            continue
-                        w.i = int(round(scanner.real))
-                        key = scanner.nexttok()
-                        if key != "IHREAL":
-                            prout("Event %d canceled, no y coordinate." % (i))
-                            unschedule(i)
-                            continue
-                        w.j = int(round(scanner.real))
-                        ev.quadrant = w
-        scanner.chew()
-    proutn("Induce supernova here? ")
-    if ja():
-        game.state.galaxy[game.quadrant.i][game.quadrant.j].supernova = True
-        atover(True)
-
-if __name__ == '__main__':
-    try:
-        #global line, thing, game
-        game = None
-        thing = Thingy()
-        game = Gamestate()
-        rnd = randomizer()
-        logfp = None
-        game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
-        if os.getenv("TERM"):
-            game.options |= OPTION_CURSES
-        else:
-            game.options |= OPTION_TTY
-        seed = int(time.time())
-        (options, arguments) = getopt.getopt(sys.argv[1:], "cr:s:txV")
-        replay = False
-        for (switch, val) in options:
-            if switch == '-r':
-                try:
-                    replayfp = open(val, "r")
-                except IOError:
-                    sys.stderr.write("sst: can't open replay file %s\n" % val)
-                    raise SystemExit(1)
-                try:
-                    line = replayfp.readline().strip()
-                    (leader, __, seed) = line.split()
-                    seed = eval(seed)
-                    line = replayfp.readline().strip()
-                    arguments += line.split()[2:]
-                    replay = True
-                except ValueError:
-                    sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
-                    raise SystemExit(1)
-                game.options |= OPTION_TTY
-                game.options &=~ OPTION_CURSES
-            elif switch == '-s':
-                seed = int(val)
-            elif switch == '-t':
-                game.options |= OPTION_TTY
-                game.options &=~ OPTION_CURSES
-            elif switch == '-x':
-                game.idebug = True
-            elif switch == '-c':       # Enable curses debugging - undocumented
-                game.cdebug = True
-            elif switch == '-V':
-                print("SST2K", version)
-                raise SystemExit(0)
-            else:
-                sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
-                raise SystemExit(1)
-        # where to save the input in case of bugs
-        if "TMPDIR" in os.environ:
-            tmpdir = os.environ['TMPDIR']
-        else:
-            tmpdir = "/tmp"
-        try:
-            logfp = open(os.path.join(tmpdir, "sst-input.log"), "w")
-        except IOError:
-            sys.stderr.write("sst: warning, can't open logfile\n")
-            sys.exit(1)
-        if logfp:
-            logfp.write("# seed %s\n" % seed)
-            logfp.write("# options %s\n" % " ".join(arguments))
-            logfp.write("# SST2K version %s\n" % version)
-            logfp.write("# recorded by %s@%s on %s\n" % \
-                    (getpass.getuser(),socket.gethostname(),time.ctime()))
-        rnd.seed(seed)
-        scanner = sstscanner()
-        for arg in arguments:
-            scanner.append(arg)
-        try:
-            iostart()
-            while True: # Play a game
-                setwnd(fullscreen_window)
-                clrscr()
-                prelim()
-                setup()
-                if game.alldone:
-                    score()
-                    game.alldone = False
-                else:
-                    makemoves()
-                if replay:
-                    break
-                skip(1)
-                stars()
-                skip(1)
-                if game.tourn and game.alldone:
-                    proutn(_("Do you want your score recorded?"))
-                    if ja():
-                        scanner.chew()
-                        scanner.push("\n")
-                        freeze(False)
-                scanner.chew()
-                proutn(_("Do you want to play again? "))
-                if not ja():
-                    break
-            skip(1)
-            prout(_("May the Great Bird of the Galaxy roost upon your home planet."))
-        finally:
-            ioend()
-        raise SystemExit(0)
-    except KeyboardInterrupt:
-        if logfp:
-            logfp.close()
-        print("")
-
-# End.
index cf908beb7c607e34a9bcfcc210beb519567a103f..de8df77745187ef9bf1b3ea4d58f1733e667e25a 100644 (file)
@@ -1,37 +1,44 @@
 # Test-suite makefile for sst
 
-PYTHON=python
-
 all:
-       @echo "With Python 2:"
-       @$(MAKE) -e PYTHON=python2 regress
-       @echo "With Python 3:"
-       @$(MAKE) -e PYTHON=python3 regress
-       @echo "No diff output is good news."
+       @$(MAKE) regress | ./tapview
 
 .SUFFIXES: .log .chk
 
 .log.chk:
-       ../sst.py -r $< >$@ 2>&1
+       ../sst -r $< >$@ 2>&1
 
 TESTLOADS := $(shell ls *.log | sed '/.log/s///')
-buildregress:
+rebuild:
        @for test in $(TESTLOADS); do \
            if [ ! -f $${test}.tst ] ; \
-           then \
+    then \
                    echo "Remaking $${test}.chk"; \
-                   rm -f $${test}.chk && ../sst.py -r $${test}.log >$${test}.chk 2>&1; \
+                   rm -f $${test}.chk && ../sst -r $${test}.log >$${test}.chk 2>&1; \
            fi \
        done
 regress:
+       @echo "1..$$(ls *.log | wc -l)"
        @for test in $(TESTLOADS); \
        do \
            if [ ! -f $${test}.tst ] ; \
            then \
-               (if echo -n "$${test}: " >&2; grep 'Test' $${test}.log >&2;\
-               $(PYTHON) ../sst.py -r $${test}.log >/tmp/regress 2>&1; \
-               then diff -u $${test}.chk /tmp/regress; \
-               else echo "*** Nonzero return status on $${test}!"; exit 1; fi;) \
+               legend=$$(sed -n -e '/# Test/s//Test/p' <$${test}.log); \
+               ../sst -r "$${test}.log" | ./tapdiffer "$${legend}" "$${test}.chk"; \
            fi \
        done
        @rm -f /tmp/regress
+
+coverage:
+       @coverage erase
+       @for test in $(TESTLOADS); \
+       do \
+           if [ ! -f $${test}.tst ] ; \
+           then \
+               coverage run -a ../sst -r "$${test}.log" >/dev/null; \
+           fi \
+       done
+       @coverage html
+
+clean:
+       rm -f .coverage htmlcov/index.html
diff --git a/test/tapdiffer b/test/tapdiffer
new file mode 100755 (executable)
index 0000000..efb7b9c
--- /dev/null
@@ -0,0 +1,52 @@
+#! /bin/sh
+# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
+# SPDX-License-Identifier: MIT-0
+#
+# tapdiffer - Render diff between input and checkfile as a TAP report
+#
+# Usage: tapdiffer LEGEND CHECKFILE
+#
+# Output is a TAP report, ok if the diff is empty and not ok otherwise.
+# A nonempty diff is shipped as a TAP YAML block following "not ok" 
+# unless QUIET=1 in the environment.
+#
+# This code is intended to be embedded in your project. The author
+# grants permission for it to be distributed under the prevailing
+# license of your project if you choose, provided that license is
+# OSD-compliant; otherwise the following SPDX tag incorporates the
+# MIT No Attribution license by reference.
+#
+# A newer version may be available at https://gitlab.com/esr/tapview
+# Check your last commit dqte for this file against the commit list
+# there to see if it might be a good idea to update.
+#
+diffopts=-u
+while getopts bn opt
+do
+    case $opt in
+       b) diffopts=-ub;;
+       *) echo "tapdiffer: unknown option ${opt}."; exit 1;;
+    esac
+done
+# shellcheck disable=SC2004
+shift $(($OPTIND - 1))
+
+legend=$1
+checkfile=$2
+
+trap 'rm /tmp/tapdiff$$' EXIT HUP INT QUIT TERM
+
+if diff --text "${diffopts}" "${checkfile}" - >/tmp/tapdiff$$
+then
+       echo "ok - ${legend}"
+else
+       echo "not ok - ${legend}"
+       if [ ! "${QUIET}" = 1 ]
+       then
+               echo "  --- |"
+               sed </tmp/tapdiff$$ -e 's/^/  /'
+               echo "  ..."
+       fi
+fi
+
+# end
diff --git a/test/tapview b/test/tapview
new file mode 100755 (executable)
index 0000000..df63bbc
--- /dev/null
@@ -0,0 +1,287 @@
+#! /bin/sh
+# tapview - a TAP (Test Anything Protocol) viewer in pure POSIX shell
+#
+# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
+# SPDX-License-Identifier: MIT-0
+#
+# This code is intended to be embedded in your project. The author
+# grants permission for it to be distributed under the prevailing
+# license of your project if you choose, provided that license is
+# OSD-compliant; otherwise the following SPDX tag incorporates the
+# MIT No Attribution license by reference.
+#
+# A newer version may be available at https://gitlab.com/esr/tapview
+# Check your last commit dqte for this file against the commit list
+# there to see if it might be a good idea to update.
+#
+OK="."
+FAIL="F"
+SKIP="s"
+TODO_NOT_OK="x"
+TODO_OK="u"
+
+LF='
+'
+
+ship_char() {
+    # shellcheck disable=SC2039
+    printf '%s' "$1"   # https://www.etalabs.net/sh_tricks.html
+}
+
+ship_line() {
+    report="${report}${1}$LF"
+}
+
+ship_error() {
+    # Terminate dot display and bail out with error
+    if [ "${testcount}" -gt 0 ]
+    then
+       echo ""
+    fi
+    report="${report}${1}$LF"
+    echo "${report}"
+    exit 1
+}
+
+testcount=0
+failcount=0
+skipcount=0
+todocount=0
+status=0
+report=""
+IFS=""
+ln=0
+state=plaintext
+
+# shellcheck disable=SC2086
+context_get () { printenv "ctx_${1}${depth}"; }
+context_set () { export "ctx_${1}${depth}=${2}"; }
+
+context_push () {
+    context_set plan ""
+    context_set count 0
+    context_set test_before_plan no
+    context_set test_after_plan no
+    context_set expect ""
+    context_set bail no
+    context_set strict no
+}
+
+context_pop () {
+    if [ "$(context_get count)" -gt 0 ] && [ -z "$(context_get plan)" ]
+    then
+       ship_line "Missing a plan at line ${ln}."
+       status=1
+    elif [ "$(context_get test_before_plan)" = "yes" ] && [ "$(context_get test_after_plan)" = "yes" ] 
+    then
+       ship_line "A plan line may only be placed before or after all tests."
+       status=1
+    elif [ "$(context_get plan)" != "" ] && [ "$(context_get expect)" -gt "$(context_get count)" ]
+    then
+       ship_line "Expected $(context_get expect) tests but only ${testcount} ran."
+       status=1
+     elif [ "$(context_get plan)" != "" ] && [ "$(context_get expect)" -lt "$(context_get count)" ]
+    then
+       ship_line "${testcount} ran but $(context_get expect) expected."
+       status=1
+    fi
+}
+
+depth=0
+context_push
+
+while read -r line
+do
+    ln=$((ln + 1))
+    # Process bailout
+    if expr "$line" : "Bail out!" >/dev/null
+    then
+       ship_line "$line"
+       status=2
+       break
+    fi
+    # Use the current indent to choose a scope level
+    indent=$(expr "$line" : '[         ]*')
+    if [ "${indent}" -lt "${depth}" ]
+    then
+       context_pop
+        depth="${indent}"
+    elif [ "${indent}" -gt "${depth}" ]
+    then
+       depth="${indent}"
+       context_push
+    fi
+    # Process a plan line
+    if expr "$line" : '[       ]*1\.\.[0-9][0-9]*' >/dev/null
+    then
+       if [ "$(context_get plan)" != "" ]
+       then
+           ship_error "tapview: cannot have more than one plan line."
+       fi
+       if expr "$line" : ".* *SKIP" >/dev/null || expr "$line" : ".* *skip" >/dev/null
+       then
+           ship_line "$line"
+           echo "${report}"
+           exit 1      # Not specified in the standard whether this should exit 1 or 0
+       fi
+       context_set plan "${line}"
+       context_set expect "$(expr "$line" : '[         ]*1\.\.\([0-9][0-9]*\)')"
+       continue
+    elif expr "$line" : '[     ]*[0-9][0-9]*\.\.[0-9][0-9]*' >/dev/null
+    then
+        echo "Ill-formed plan line at ${ln}"
+        exit 1
+    fi
+    # Check for out-of-order test point numbers with the sequence (TAP 14)
+    testpoint=$(expr "$line" : '.*ok  *\([0-9][0-9]*\)')
+    if [ "${testpoint}" != "" ] && [ "$(context_get expect)" != "" ] && [ "${testpoint}" -gt "$(context_get expect)" ]
+    then
+       ship_error "tapview: testpoint number ${testpoint} is out of range for plan $(context_get plan)."
+    fi
+    # Process an ok line
+    if expr "$line" : "[       ]*ok" >/dev/null
+    then
+       context_set count $(($(context_get count) + 1)) 
+       testcount=$((testcount + 1))
+       if [ "$(context_get plan)" = "" ]
+       then
+           context_set test_before_plan yes
+       else
+           context_set test_after_plan yes
+       fi
+       if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null
+       then
+           ship_char ${TODO_OK}
+           ship_line "$line"
+           todocount=$((todocount + 1))
+           if expr "$line" : "[^#]*#[^ ]" >/dev/null
+           then
+               ship_line "Suspicious comment leader at ${ln}"
+           fi
+       elif expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null
+       then
+           ship_char ${SKIP}
+           ship_line "$line"
+           skipcount=$((skipcount + 1))
+           if expr "$line" : "[^#]*#[^ ]" >/dev/null
+           then
+               ship_line "Suspicious comment leader at ${ln}"
+           fi
+       else
+           ship_char ${OK}
+       fi
+       state=plaintext
+       continue
+    fi
+    # Process a not-ok line
+    if expr "$line" : "[       ]*not ok" >/dev/null
+    then
+       context_set count $(($(context_get count) + 1)) 
+       testcount=$((testcount + 1))
+       if [ "$(context_get plan)" = "" ]
+       then
+           context_set test_before_plan yes
+       else
+           context_set test_after_plan yes
+       fi
+       if expr "$line" : "[^#]* # *SKIP" >/dev/null || expr "$line" : "[^#]* # *skip" >/dev/null
+       then
+           ship_char "${SKIP}"
+           state=plaintext
+           skipcount=$((skipcount + 1))
+           if expr "$line" : "[^#]* #[^ ]" >/dev/null
+           then
+               ship_line "Suspicious comment leader at lime ${ln}"
+           fi
+           continue
+       fi
+       if expr "$line" : "[^#]* # *TODO" >/dev/null || expr "$line" : "[^#]* # *todo" >/dev/null
+       then
+           ship_char ${TODO_NOT_OK}
+           state=plaintext
+           todocount=$((todocount + 1))
+           if expr "$line" : "[^#]* #[^ ]" >/dev/null
+           then
+               ship_line "Suspicious comment leader at line ${ln}"
+           fi
+           continue
+       fi
+       ship_char "${FAIL}"
+       ship_line "$line"
+       state=plaintext
+       failcount=$((failcount + 1))
+       status=1
+       if [ "$(context_get bail)" = yes ]
+       then
+           ship_line "Bailing out on line ${ln} due to +bail pragma."
+           break
+       fi
+       continue
+    fi
+    # Process a TAP 14 pragma
+    if expr "$line" : "pragma" >/dev/null
+    then
+       unset IFS
+       # shellcheck disable=SC2086
+       set -- $line
+       case "$2" in
+           +bail) context_set bail yes;;
+           -bail) context_set bail yes;;
+           +strict) context_set strict yes;;
+           -strict) context_set strict yes;;
+           *) ship_line "Pragma '$line' ignored";;
+       esac
+       IFS=""
+       continue
+    fi
+    # shellcheck disable=SC2166
+    if [ "${state}" = "yaml" ]
+    then
+       ship_line "$line"
+       if expr "$line" : '[    ]*\.\.\.' >/dev/null
+       then
+           state=plaintext
+       else
+           continue
+       fi
+    elif expr "$line" : "[     ]*---" >/dev/null
+    then
+       ship_line "$line"
+       state=yaml
+       continue
+    fi
+    # Ignore blank lines and comments
+    if [ -z "$line" ] || expr "$line" : '[     ]+$' >/dev/null || expr "$line" : "#" >/dev/null
+    then
+       continue
+    fi
+    # Any line that is not a valid plan, test result, pragma,
+    # or comment lands here.
+    if [ "$(context_get strict)" = yes ]
+    then
+       ship_line "Bailing out on line ${ln} due to +strict pragma"
+       status=1
+       break
+    fi
+done
+
+/bin/echo ""
+
+depth=0
+context_pop
+
+report="${report}${testcount} tests, ${failcount} failures"
+if [ "$todocount" != 0 ]
+then
+    report="${report}, ${todocount} TODOs"
+fi
+if [ "$skipcount" != 0 ]
+then
+    report="${report}, ${skipcount} SKIPs"
+fi
+
+echo "${report}."
+
+exit "${status}"
+
+# end
index b811a073a44c5849b7725f481beac91a03ed1b25..a2c4e5c472671fcb09ac1fed5a4be88c910cabfa 100644 (file)
@@ -1,15 +1,17 @@
+# seed 1556084761
+# arguments
+# SST2K version 2.4
+# Test bringing game up, viewing galaxy, quitting
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 01:46:01 2019
+#
 
 
 -SUPER- STAR TREK
 
-Would you like a regular, tournament, or saved game? # SST2K version 2.4
-# Test bringng game up, viewng galaxy, quitting
-# recorded by esr@snark on Wed Apr 24 01:46:01 2019
-#seed(1556084761)
-r
+Would you like a regular, tournament, or saved game? r
 Would you like a Short, Medium, or Long game? s
 Are you a Novice, Fair, Good, Expert, or Emeritus player? g
-Choose your game style (plain, almy, fancy or just press enter): f
+Wayback setting (press enter for current year): 2023
 
 
 Stardate 3188.
@@ -18,23 +20,23 @@ Stardate 3188.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
 7 stardates.
-4 starbases in 2 - 7  6 - 6  3 - 1  7 - 4  
+4 starbases in b7  f6  c1  g4  
 
-The Enterprise is currently in Quadrant 3 - 5 Sector 3 - 10
+The Enterprise is currently in Quadrant c5 Sector c10
 
 Good Luck!
   YOU'LL NEED IT.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  ...  ...  ..8  ..3  ..3  .1.  ...   |
-3 | .1.  ...  ...  ..8 <..3> ..4  ...  ...   |
-4 | ...  ...  ...  ..8  ..9  ..6  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  .1.  ...  ...   |
-7 | ...  ...  ...  .1.  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  ...  ...  ..8  ..3  ..3  .1.  ...   |
+c | .1.  ...  ...  ..8 <..3> ..4  ...  ...   |
+d | ...  ...  ...  ..8  ..9  ..6  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  .1.  ...  ...   |
+g | ...  ...  ...  .1.  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> quit
 
index c38f57cbf7f469e3622fe0ac9d093e85348856a3..76f47f470587e58b8616816c19c40d8a7fbed7bd 100644 (file)
@@ -1,13 +1,12 @@
 # seed 1556084761
-# option
+# argument
 # SST2K version 2.4
-# Test bringng game up, viewng galaxy, quitting
-# recorded by esr@snark on Wed Apr 24 01:46:01 2019
-#seed(1556084761)
+# Test bringing game up, viewing galaxy, quitting
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 01:46:01 2019
+#
 r
 s
 g
-f
+2023
 chart
 quit
-n
index 972cb2e1137b62271d1f8b3af2c6d4a1a909e97a..dd2ac3faf4e720e764dd12c5d0a81f031e16c930 100644 (file)
@@ -1,3 +1,9 @@
+# seed 1556101787
+# arguments regular short good 2023
+# SST2K version 2.4
+# Test critical hit on sensors
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 06:29:47 2019
+#
 
 
 -SUPER- STAR TREK
@@ -10,26 +16,23 @@ Stardate 4340.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
 7 stardates.
-3 starbases in 4 - 8  7 - 5  2 - 2  
+3 starbases in d8  g5  b2  
 
-The Enterprise is currently in Quadrant 8 - 8 Sector 10 - 3
+The Enterprise is currently in Quadrant h8 Sector j3
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # SST2K version 2.4
-# Test critical hit on sensors
-# recorded by esr@snark on Wed Apr 24 06:29:47 2019
-chart
+COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ...  ...  ...  ...  ...  ...  ...  .1.   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  .1.  ...  ..8  ..1   |
-8 | ...  ...  ...  ...  ...  ...  ..8 <..9>  |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  ...   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  .1.   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  .1.  ...  ..8  ..1   |
+h | ...  ...  ...  ...  ...  ...  ..8 <..9>  |
 
 COMMAND> m a 3 6
 
@@ -40,23 +43,23 @@ COMMAND> m a 7 8 10 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 7 - 8.
+Entering Quadrant g8.
 
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 4340.41
-     Supernova in Quadrant 3 - 8; caution advised.
+     Supernova in Quadrant c8; caution advised.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ***   |
-4 | ...  ...  ...  ...  ...  ...  ...  .1.   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ..9  107   |
-7 | ...  ...  ...  ...  .1.  ...  ..8 <..1>  |
-8 | ...  ...  ...  ...  ...  ...  ..8  ..9   |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  ...   |
+c | ...  ...  ...  ...  ...  ...  ...  ***   |
+d | ...  ...  ...  ...  ...  ...  ...  .1.   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ..9  107   |
+g | ...  ...  ...  ...  .1.  ...  ..8 <..1>  |
+h | ...  ...  ...  ...  ...  ...  ..8  ..9   |
 
 COMMAND> m a 1 10
 
@@ -64,9 +67,9 @@ COMMAND> m a 6 8 10 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 6 - 8.
+Entering Quadrant f8.
 
-606 unit hit from Klingon at 7 - 7
+606 unit hit from Klingon at g7
 
 ***CRITICAL HIT--L. R. Sensors and S. R. Sensors damaged.
 
index b5ace151f2b5349c75ca080053f8ac21292c1926..6d0bb84505e83394d0cfeeef5dbc7d9344cf7803 100644 (file)
@@ -1,8 +1,9 @@
 # seed 1556101787
-# options regular short good fancy
+# arguments regular short good 2023
 # SST2K version 2.4
 # Test critical hit on sensors
-# recorded by esr@snark on Wed Apr 24 06:29:47 2019
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 06:29:47 2019
+#
 chart
 m a 3 6
 m a 7 8 10 20
index b8bd98e31f4f82ee40cf46ed5acf6bd166dc5404..86eed5ea17534748f6dc702bab0548ea7a1ae199 100644 (file)
@@ -1,3 +1,9 @@
+# seed 1556102474
+# arguments regular short good 2023
+# SST2K version 2.4
+# Test Tholian boxing us in followed by death by tractor beam
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 09:48:31 2019
+#
 
 
 -SUPER- STAR TREK
@@ -10,26 +16,23 @@ Stardate 2412.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
 7 stardates.
-2 starbases in 6 - 3  3 - 6  
+2 starbases in f3  c6  
 
-The Enterprise is currently in Quadrant 2 - 1 Sector 9 - 10
+The Enterprise is currently in Quadrant b1 Sector i10
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # SST2K version 2.4
-# Test Tholian boxing us in followed by death by tractor beam
-# recorded by esr@snark on Wed Apr 24 09:48:31 2019
-chart
+COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ..8  ..4  ...  ...  ...  ...  ...  ...   |
-2 |<..4> ..7  ...  ...  ...  ...  ...  ...   |
-3 | ..9  ..3  ...  ...  ...  .1.  ...  ...   |
-4 | ...  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  .1.  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ..8  ..4  ...  ...  ...  ...  ...  ...   |
+b |<..4> ..7  ...  ...  ...  ...  ...  ...   |
+c | ..9  ..3  ...  ...  ...  .1.  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  .1.  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> sh down
 Shields already down.
@@ -37,7 +40,7 @@ COMMAND> m a 3 1 1 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 3 - 1.
+Entering Quadrant c1.
 COMMAND> m a 10 10
 
 COMMAND> sh up
@@ -46,22 +49,11 @@ COMMAND> m a 4 1 1 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 4 - 1.
+Entering Quadrant d1.
 
 Enemy attack reduces shield strength to 87%,   torpedoes left 10
 
 Enemy attack reduces shield strength to 78%,   torpedoes left 10
-COMMAND> laser auto
-LEGAL COMMANDS ARE:
-SRSCAN       STATUS       REQUEST      LRSCAN       
-PHASERS      TORPEDO      PHOTONS      MOVE         SHIELDS      
-DOCK         DAMAGES      CHART        IMPULSE      REST         
-WARP         SENSORS      ORBIT        TRANSPORT    MINE         
-CRYSTALS     SHUTTLE      PLANETS      REPORT       COMPUTER     
-COMMANDS     EMEXIT       PROBE        SAVE         FREEZE       
-ABANDON      DESTRUCT     DEATHRAY     CAPTURE      CLOAK        
-DEBUG        MAYDAY       SOS          CALL         QUIT         
-HELP         SCORE        CURSES                    
 COMMAND> p a
 
 Weapons Officer Sulu-  "High-speed shield control enabled, sir."
@@ -70,13 +62,13 @@ Phasers locked on target. Energy available: 4587.50
 
 Shields lowered.
 
-221 unit hit on Klingon at Sector 2 - 5
-***Klingon at Sector 2 - 5 destroyed.
-180 unit hit on Klingon at Sector 5 - 3
-***Klingon at Sector 5 - 3 destroyed.
-242 unit hit on Klingon at Sector 10 - 6
-***Klingon at Sector 10 - 6 destroyed.
-44 unit hit on Klingon at Sector 10 - 4
+221 unit hit on Klingon at Sector b5
+***Klingon at Sector b5 destroyed.
+180 unit hit on Klingon at Sector e3
+***Klingon at Sector e3 destroyed.
+242 unit hit on Klingon at Sector j6
+***Klingon at Sector j6 destroyed.
+44 unit hit on Klingon at Sector j4
 926 expended on empty space.
 
 Shields raised.
@@ -90,9 +82,9 @@ Phasers locked on target. Energy available: 2504.50
 
 Shields lowered.
 
-101 unit hit on Klingon at Sector 10 - 4
-***Klingon at Sector 10 - 4 destroyed.
-60 unit hit on Klingon at Sector 9 - 1
+101 unit hit on Klingon at Sector j4
+***Klingon at Sector j4 destroyed.
+60 unit hit on Klingon at Sector i1
 204 expended on empty space.
 
 Shields raised.
@@ -104,21 +96,21 @@ COMMAND> m a 9 10
 Enemy attack reduces shield strength to 76%,   torpedoes left 10
 COMMAND> torp 1 9 1
 
-Torpedo track- 9 - 9   9 - 8   9 - 7   
-9 - 6   9 - 5   9 - 4   9 - 3   9 - 2   
-9 - 1   
-***Klingon at Sector 9 - 1 destroyed.
+Torpedo track- i9   i8   i7   
+i6   i5   i4   i3   i2   
+i1   
+***Klingon at Sector i1 destroyed.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ..8  ..4  ...  ...  ...  ...  ...  ...   |
-2 | ..4  ..7  ...  ...  ...  ...  ...  ...   |
-3 | ..9  ..3  ...  ...  ...  .1.  ...  ...   |
-4 |<..3> ..4  ...  ...  ...  ...  ...  ...   |
-5 | ..3  ..3  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  .1.  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ..8  ..4  ...  ...  ...  ...  ...  ...   |
+b | ..4  ..7  ...  ...  ...  ...  ...  ...   |
+c | ..9  ..3  ...  ...  ...  .1.  ...  ...   |
+d |<..3> ..4  ...  ...  ...  ...  ...  ...   |
+e | ..3  ..3  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  .1.  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> sh down
 Shields lowered.
@@ -127,18 +119,18 @@ COMMAND> m 4 2 1 10
 
 Helmsman Sulu- "Aye, Sir."
 
-Entering Quadrant 2 - 5.
+Entering Quadrant b5.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ..8  ..4  ...  ..8  ..2  ..6  ...  ...   |
-2 | ..4  ..7  ...  ..1 <..6> ..5  ...  ...   |
-3 | ..9  ..3  ...  ..5  ..8  .14  ...  ...   |
-4 | ..3  ..4  ...  ...  ...  ...  ...  ...   |
-5 | ..3  ..3  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  .1.  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ..8  ..4  ...  ..8  ..2  ..6  ...  ...   |
+b | ..4  ..7  ...  ..1 <..6> ..5  ...  ...   |
+c | ..9  ..3  ...  ..5  ..8  .14  ...  ...   |
+d | ..3  ..4  ...  ...  ...  ...  ...  ...   |
+e | ..3  ..3  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  .1.  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> rep
 You were playing a short good game.
@@ -172,16 +164,16 @@ YOU WILL BE DESTROYED.
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 2416.51
-     Supernova in Quadrant 3 - 6; caution advised.
+     Supernova in Quadrant c6; caution advised.
 
 [ANNOUNCEMENT ARRIVING...]
 Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 3 - 1.
+   the Super-commander is in Quadrant c1.
 
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 2416.77
-     Supernova in Quadrant 8 - 2; caution advised.
+     Supernova in Quadrant h2; caution advised.
 
 [ANNOUNCEMENT ARRIVING...]
 
@@ -211,10 +203,10 @@ Message from Starfleet Command       Stardate 2416.77
 
 
 
-Enterprise is pulled to Quadrant 4 - 7, Sector 4 - 9
+Enterprise is pulled to Quadrant d7, Sector d9
 Shields raised.
 
-61 unit hit from Klingon at 8 - 2
+61 unit hit from Klingon at h2
 
 
 Energy left 360    shields up 70%,   torpedoes left 9
@@ -245,21 +237,21 @@ Helmsman Sulu- "Warp factor 2, Captain."
 COMMAND> m a 8 8
 
 
-83 unit hit from Klingon at 8 - 2
+83 unit hit from Klingon at h2
 
 
 Energy left 277    shields up 63%,   torpedoes left 9
 COMMAND> torp 2 10 1
 
-Track for torpedo number 1-  8 - 7   9 - 6   
-Star at Sector 9 - 6 novas.
+Track for torpedo number 1-  h7   i6   
+Star at Sector i6 novas.
 
-Track for torpedo number 2-  8 - 7   9 - 6   9 - 5   
-9 - 4   9 - 3   10 - 2   
+Track for torpedo number 2-  h7   i6   i5   
+i4   i3   j2   
 
 ***Torpedo absorbed by Tholian web.
 
-100 unit hit from Klingon at 8 - 2
+100 unit hit from Klingon at h2
 
 
 Energy left 171    shields up 58%,   torpedoes left 7
@@ -280,12 +272,12 @@ First Officer Spock- "Captain, I compute that such
 Please answer with "y" or "n": n
 COMMAND> torp 2 8 3
 
-Track for torpedo number 1-  8 - 7   8 - 6   8 - 5   
-8 - 4   8 - 3   8 - 2   
-***Commander at Sector 8 - 2 destroyed.
+Track for torpedo number 1-  h7   h6   h5   
+h4   h3   h2   
+***Commander at Sector h2 destroyed.
 
-Track for torpedo number 2-  8 - 7   8 - 6   8 - 5   
-8 - 4   8 - 3   8 - 2   8 - 1   
+Track for torpedo number 2-  h7   h6   h5   
+h4   h3   h2   h1   
 
 ***Torpedo absorbed by Tholian web.
 
@@ -298,27 +290,27 @@ Long-range scan
 COMMAND> srscan
      Short-range scan
     1 2 3 4 5 6 7 8 9 10
- 1  # #   # # # # # # T 
- 2  # . . . . . . . . . 
- 3  # . . . . . . . . . 
- 4  # . . . . . . . . . 
- 5  # . . . . . . . . . 
- 6  # . . . . . . . . . 
- 7  # . . . . . . . . . 
- 8  # . . . . . . E . * 
- 9  # . . . . . . . . . 
-10  # # # # # # # # # # 
+  # #   # # # # # # T 
+  # . . . . . . . . . 
+  # . . . . . . . . . 
+  # . . . . . . . . . 
+  # . . . . . . . . . 
+  # . . . . . . . . . 
+  # . . . . . . . . . 
+  # . . . . . . E . * 
+  # . . . . . . . . . 
+  # # # # # # # # # # 
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ..8  ..4  ...  ..8  ..2  106  ...  ...   |
-2 | ..4  ..7  ...  ..1  ..6  ..5  ...  ...   |
-3 | ..9  ..3  ...  ..5  ..8  ***  109  ..9   |
-4 | ..3  ..4  ...  ...  ...  ..4 <..1> ..6   |
-5 | ..3  ..3  ...  ...  ...  ..6  ..4  108   |
-6 | ...  ...  .1.  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  ***  ...  ...  ...  ...  ...  ...   |
+a | ..8  ..4  ...  ..8  ..2  106  ...  ...   |
+b | ..4  ..7  ...  ..1  ..6  ..5  ...  ...   |
+c | ..9  ..3  ...  ..5  ..8  ***  109  ..9   |
+d | ..3  ..4  ...  ...  ...  ..4 <..1> ..6   |
+e | ..3  ..3  ...  ...  ...  ..6  ..4  108   |
+f | ...  ...  .1.  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ***  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> m a 4 8 1 6
 
@@ -333,9 +325,9 @@ Enemy attack reduces shield strength to 58%,   torpedoes left 5
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 5 - 8, Sector 5 - 4
+Enterprise is pulled to Quadrant e8, Sector e4
 
-213 unit hit from Klingon at 6 - 8
+213 unit hit from Klingon at f8
 
 
 
index 38275b9a8b14010b88c4f1288ee9ffb033589ad7..47db40727d799a224502fd9bbfb9eaf2fdfc062c 100644 (file)
@@ -1,15 +1,15 @@
 # seed 1556102474
-# options regular short good fancy
+# arguments regular short good 2023
 # SST2K version 2.4
 # Test Tholian boxing us in followed by death by tractor beam
-# recorded by esr@snark on Wed Apr 24 09:48:31 2019
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 09:48:31 2019
+#
 chart
 sh down
 m a 3 1 1 10
 m a 10 10
 sh up
 m a 4 1 1 10
-laser auto
 p a
 1883
 p a
index c14ba11751c63e312a9e1d94291fab86ea55959b..72960791fff24c8010ebec63b4efdc1b38a0a0bd 100644 (file)
@@ -1,3 +1,9 @@
+# seed 1556116333
+# arguments regular short good 2023
+# SST2K version 2.4
+# Test starbase destruction, planet destruction, docking after destruction.
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 08:59:1 3 2023
+#
 
 
 -SUPER- STAR TREK
@@ -10,43 +16,40 @@ Stardate 4778.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
 7 stardates.
-4 starbases in 7 - 4  1 - 1  1 - 2  1 - 4  
+4 starbases in g4  a1  a2  a4  
 
-The Enterprise is currently in Quadrant 2 - 6 Sector 5 - 9
+The Enterprise is currently in Quadrant b6 Sector e9
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # SST2K version 2.4
-# Test ill-formed torpedo command
-# recorded by esr@snark on Wed Apr 24 11:16:25 2019
-chart
+COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  .1.  ...  .1.  107  ..3  ..2  ...   |
-2 | ...  ...  ...  ...  ..7 <..9> ..5  ...   |
-3 | ...  ...  ...  ...  ..8  ..7  207  ...   |
-4 | ...  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  .1.  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | .1.  .1.  ...  .1.  107  ..3  ..2  ...   |
+b | ...  ...  ...  ...  ..7 <..9> ..5  ...   |
+c | ...  ...  ...  ...  ..8  ..7  207  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  .1.  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> m a 3 7 1 2
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 3 - 7.
+Entering Quadrant c7.
 
-144 unit hit from Klingon at 5 - 7
+144 unit hit from Klingon at e7
 
-94 unit hit from Klingon at 8 - 9
+94 unit hit from Klingon at h9
 
 
 Energy left 4761    shields down 100%,   torpedoes left 10
 
-99 unit hit from Klingon at 5 - 7
+99 unit hit from Klingon at e7
 
-69 unit hit from Klingon at 8 - 9
+69 unit hit from Klingon at h9
 
 
 Energy left 4592    shields down 100%,   torpedoes left 10
@@ -56,9 +59,9 @@ Shields raised.
 Enemy attack reduces shield strength to 96%,   torpedoes left 10
 COMMAND> torp 1 7 9
 
-Torpedo track- 2 - 3   3 - 4   4 - 5   
-5 - 6   5 - 7   
-***Klingon at Sector 5 - 7 destroyed.
+Torpedo track- b3   c4   d5   
+e6   e7   
+***Klingon at Sector e7 destroyed.
 
 Enemy attack reduces shield strength to 94%,   torpedoes left 9
 COMMAND> p a
@@ -69,8 +72,8 @@ Phasers locked on target. Energy available: 4258.58
 
 Shields lowered.
 
-143 unit hit on Klingon at Sector 8 - 9
-***Klingon at Sector 8 - 9 destroyed.
+143 unit hit on Klingon at Sector h9
+***Klingon at Sector h9 destroyed.
 
 Shields raised.
 COMMAND> sh down
@@ -78,29 +81,29 @@ Shields lowered.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  .1.  ...  .1.  107  ..3  ..2  ...   |
-2 | ...  ...  ...  ...  ..7  ..9  ..5  ..4   |
-3 | ...  ...  ...  ...  ..8  ..7 <..7> 106   |
-4 | ...  ...  ...  ...  ...  ..1  ..1  ..2   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  .1.  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | .1.  .1.  ...  .1.  107  ..3  ..2  ...   |
+b | ...  ...  ...  ...  ..7  ..9  ..5  ..4   |
+c | ...  ...  ...  ...  ..8  ..7 <..7> 106   |
+d | ...  ...  ...  ...  ...  ..1  ..1  ..2   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  .1.  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> m a 2 10
 
 
-Enterprise blocked by object at 1 - 5;
+Enterprise blocked by object at a5;
 Emergency stop required 124 units of energy.
 Collision detected
 
 [ANNOUNCEMENT ARRIVING...]
 Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 1 - 5.
+   the Super-commander is in Quadrant a5.
 
 [ANNOUNCEMENT ARRIVING...]
 
-Lt. Uhura-  "Captain, the starbase in Quadrant 7 - 4
+Lt. Uhura-  "Captain, the starbase in Quadrant g4
    reports that it is under attack and that it can
    hold out only until stardate 4782."
 COMMAND> 
@@ -116,584 +119,42 @@ YOU WILL BE DESTROYED.
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 7 - 4, Sector 9 - 10
+Enterprise is pulled to Quadrant g4, Sector i10
 Shields raised.
 
 Enemy attack reduces shield strength to 91%,   torpedoes left 9
 COMMAND> torp 3 2 1 2 1 2 1
 
-Track for torpedo number 1-  8 - 9   7 - 8   7 - 7   
-6 - 6   5 - 5   4 - 4   4 - 3   3 - 2   
-2 - 1   
-***Commander at Sector 2 - 1 damaged-- displaced by blast to Sector 8 - 10 
+Track for torpedo number 1-  h9   g8   g7   
+f6   e5   d4   d3   c2   
+b1   
+***Commander at Sector b1 damaged-- displaced by blast to Sector a1 
 
-Track for torpedo number 2-  8 - 9   8 - 8   7 - 7   
-6 - 6   5 - 5   5 - 4   4 - 3   3 - 2   
-3 - 1   
+Track for torpedo number 2-  h9   h8   g7   
+f6   e5   e4   d3   c2   
+c1   
 Torpedo missed.
 
-Track for torpedo number 3-  8 - 9   7 - 8   7 - 7   
-6 - 6   5 - 5   4 - 4   3 - 3   2 - 2   
-***Inhabited World at Sector 2 - 2 destroyed.
+Track for torpedo number 3-  h9   g8   g7   
+f6   e5   d4   c3   b2   
+***Inhabited World at Sector b2 destroyed.
 The torpedo destroyed an inhabited planet.
 
-20 unit hit from Klingon at 8 - 10
-
-
-Energy left 3369    shields up 84%,   torpedoes left 6
+Enemy attack reduces shield strength to 90%,   torpedoes left 6
 COMMAND> torp 1 8 10
 
-Torpedo track- 8 - 10   
-***Commander at Sector 8 - 10 destroyed.
-COMMAND> m a 6 10
-
-COMMAND> dock
-Docked.
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "aao"
-3 of 15 Klingons have been killed, including 1 Commander.
-The Super Commander has not been destroyed.
-There are 4 bases.
-No Starbase is currently under attack.
-You have 2 deep space probes.
-
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  .1.  ...  .1.  107  ..3  ..2  ...   |
-2 | ...  ...  ...  ...  ..7  ..9  ..5  104   |
-3 | ...  ...  ...  ...  ..8  ..7  ..7  106   |
-4 | ...  ...  ...  ...  ...  ..1  ..1  ..2   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ..1  ..8  ..3  ...  ...  ...   |
-7 | ...  ...  ..6 <.11> ..2  ...  ...  ...   |
-8 | ...  ...  ..3  ..2  ..7  ...  ...  ...   |
-
-COMMAND> m a 6 7 1 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 6 - 7.
-
-[ANNOUNCEMENT ARRIVING...]
-
-Message from Starfleet Command       Stardate 4780.51
-     Supernova in Quadrant 3 - 7; caution advised.
-COMMAND> chaer
-LEGAL COMMANDS ARE:
-SRSCAN       STATUS       REQUEST      LRSCAN       
-PHASERS      TORPEDO      PHOTONS      MOVE         SHIELDS      
-DOCK         DAMAGES      CHART        IMPULSE      REST         
-WARP         SENSORS      ORBIT        TRANSPORT    MINE         
-CRYSTALS     SHUTTLE      PLANETS      REPORT       COMPUTER     
-COMMANDS     EMEXIT       PROBE        SAVE         FREEZE       
-ABANDON      DESTRUCT     DEATHRAY     CAPTURE      CLOAK        
-DEBUG        MAYDAY       SOS          CALL         QUIT         
-HELP         SCORE        CURSES                    
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  .1.  ...  .1.  107  ..3  ..2  ...   |
-2 | ...  ...  ...  ...  ..7  ..9  ..5  104   |
-3 | ...  ...  ...  ...  ..8  ..7  ***  106   |
-4 | ...  ...  ...  ...  ...  ..1  ..1  ..2   |
-5 | ...  ...  ...  ...  ...  ..3  ..4  ..3   |
-6 | ...  ...  ..1  ..8  ..3  ..4 <..6> ..8   |
-7 | ...  ...  ..6  .11  ..2  ..2  ..8  607   |
-8 | ...  ...  ..3  ..2  ..7  ...  ...  ...   |
-
-COMMAND> sh down
-Shields lowered.
-COMMAND> m a 8 9
-
-COMMAND> sh up
-Shields raised.
-COMMAND> m a 8 10 8 1
-
-Beg your pardon, Captain?
-COMMAND> m a 8 10 8 1
-
-Beg your pardon, Captain?
-COMMAND> m a 8 10 8 1
-
-Beg your pardon, Captain?
-COMMAND> move auto
-Destination sector or quadrant&sector- 6 8 8 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 6 - 8.
-COMMAND> m 7 8 1 1
-(Manual movement assumed.)
-
-Helmsman Sulu- "Aye, Sir."
-
-First Officer Spock- "Captain, I compute that such
-  a trip would require approximately 105 percent of our
-  remaining time.  Are you sure this is wise?" n
-COMMAND> m a 7 8 1 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 7 - 8.
-
-Enemy attack reduces shield strength to 77%,   torpedoes left 10
-
-24 unit hit from Klingon at 5 - 5
-
-24 unit hit from Klingon at 7 - 2
-
-31 unit hit from Klingon at 5 - 6
-
-28 unit hit from Klingon at 6 - 6
-
-
-Energy left 4013    shields up 65%,   torpedoes left 10
-COMMAND> torp 3 5 5 5 6 6 6
-
-Track for torpedo number 1-  2 - 2   3 - 3   4 - 4   
-5 - 5   
-***Klingon at Sector 5 - 5 destroyed.
-
-Track for torpedo number 2-  2 - 2   3 - 3   3 - 4   
-4 - 5   
-
-***Black hole at Sector 4 - 5 swallows torpedo.
-
-Track for torpedo number 3-  2 - 2   3 - 3   4 - 4   
-5 - 5   6 - 6   
-***Klingon at Sector 6 - 6 destroyed.
-
-28 unit hit from Klingon at 7 - 2
-
-31 unit hit from Klingon at 5 - 6
-
-
-Energy left 3878    shields up 60%,   torpedoes left 7
-COMMAND> torp torp 2 7 2 10 3
-
-Beg your pardon, Captain?
-COMMAND> 2 
-LEGAL COMMANDS ARE:
-SRSCAN       STATUS       REQUEST      LRSCAN       
-PHASERS      TORPEDO      PHOTONS      MOVE         SHIELDS      
-DOCK         DAMAGES      CHART        IMPULSE      REST         
-WARP         SENSORS      ORBIT        TRANSPORT    MINE         
-CRYSTALS     SHUTTLE      PLANETS      REPORT       COMPUTER     
-COMMANDS     EMEXIT       PROBE        SAVE         FREEZE       
-ABANDON      DESTRUCT     DEATHRAY     CAPTURE      CLOAK        
-DEBUG        MAYDAY       SOS          CALL         QUIT         
-HELP         SCORE        CURSES                    
-COMMAND> 7 2
-LEGAL COMMANDS ARE:
-SRSCAN       STATUS       REQUEST      LRSCAN       
-PHASERS      TORPEDO      PHOTONS      MOVE         SHIELDS      
-DOCK         DAMAGES      CHART        IMPULSE      REST         
-WARP         SENSORS      ORBIT        TRANSPORT    MINE         
-CRYSTALS     SHUTTLE      PLANETS      REPORT       COMPUTER     
-COMMANDS     EMEXIT       PROBE        SAVE         FREEZE       
-ABANDON      DESTRUCT     DEATHRAY     CAPTURE      CLOAK        
-DEBUG        MAYDAY       SOS          CALL         QUIT         
-HELP         SCORE        CURSES                    
-COMMAND> 10 3
-LEGAL COMMANDS ARE:
-SRSCAN       STATUS       REQUEST      LRSCAN       
-PHASERS      TORPEDO      PHOTONS      MOVE         SHIELDS      
-DOCK         DAMAGES      CHART        IMPULSE      REST         
-WARP         SENSORS      ORBIT        TRANSPORT    MINE         
-CRYSTALS     SHUTTLE      PLANETS      REPORT       COMPUTER     
-COMMANDS     EMEXIT       PROBE        SAVE         FREEZE       
-ABANDON      DESTRUCT     DEATHRAY     CAPTURE      CLOAK        
-DEBUG        MAYDAY       SOS          CALL         QUIT         
-HELP         SCORE        CURSES                    
-COMMAND> lrscan
-Long-range scan
-    6   8  -1 
-    8 407  -1 
-    5   4  -1 
-COMMAND> srscan
-     Short-range scan
-    1 2 3 4 5 6 7 8 9 10
- 1  E . . . . . . . . . 
- 2  . . . . . . * . . . 
- 3  * . . . . . . . . . 
- 4  . . . .   . . . . . 
- 5  . . . . . K . . . . 
- 6  . . . . * . . . . . 
- 7  . K . . . . . . . . 
- 8  . . . . * . . *   . 
- 9  . . . . * . . . K . 
-10  . . K . . . . . * . 
-COMMAND> m a 1 10
-
-
-25 unit hit from Klingon at 5 - 6
-
-
-Energy left 3853    shields up 57%,   torpedoes left 7
-COMMAND> p a
-
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 3428.47
-812 units required. Units to fire= 432
-
-Shields lowered.
-
-111 unit hit on Klingon at Sector 5 - 6
-***Klingon at Sector 5 - 6 destroyed.
-106 unit hit on Klingon at Sector 9 - 9
-***Klingon at Sector 9 - 9 destroyed.
-149 expended on empty space.
-
-Shields raised.
-
-Enemy attack reduces shield strength to 56%,   torpedoes left 7
-COMMAND> srscan
-     Short-range scan
-    1 2 3 4 5 6 7 8 9 10
- 1  . . . . . . . . . E 
- 2  . . . . . . * . . . 
- 3  * . . . . . . . . . 
- 4  . . . .   . . . . . 
- 5  . . . . . . . . . . 
- 6  . . . . * . . . . . 
- 7  . K . . . . . . . . 
- 8  . . . . * . . *   . 
- 9  . . . . * . . . . . 
-10  . . K . . . . . * . 
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "aao"
-7 of 15 Klingons have been killed, including 1 Commander.
-The Super Commander has not been destroyed.
-There are 4 bases.
-No Starbase is currently under attack.
-You have 2 deep space probes.
-
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  .1.  ...  .1.  107  ..3  ..2  ...   |
-2 | ...  ...  ...  ...  ..7  ..9  ..5  ..4   |
-3 | ...  ...  ...  ...  ..8  ..7  ***  106   |
-4 | ...  ...  ...  ...  ...  ..1  ..1  102   |
-5 | ...  ...  ...  ...  ...  ..3  ..4  ..3   |
-6 | ...  ...  ..1  ..8  ..3  ..4  ..6  ..8   |
-7 | ...  ...  ..6  .11  ..2  ..2  ..8 <207>  |
-8 | ...  ...  ..3  ..2  ..7  ...  ..5  ..4   |
-
-COMMAND> m a 1 1
-
-
-Enemy attack reduces shield strength to 55%,   torpedoes left 7
-
-[ANNOUNCEMENT ARRIVING...]
-
-***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 1 - 5, Sector 2 - 5
-
-116 unit hit from Klingon at 9 - 1
-
-
-Energy left 2642    shields up 51%,   torpedoes left 7
-COMMAND> lrscan
-Long-range scan
-   -1  -1  -1 
-   13 107   3 
-    4   7   9 
-COMMAND> srscan
-     Short-range scan
-    1 2 3 4 5 6 7 8 9 10
- 1  . .   . . . . . . . 
- 2  . . . . E . . . . * 
- 3  . . . . . . . . . . 
- 4  . . . . . . . . . . 
- 5  . . . . . . . . . . 
- 6  . . . * . . . . . . 
- 7  . .   . * . . . . * 
- 8  . . . . . . . * . . 
- 9  C . @ . . * . . . . 
-10  . . . . . . . . . * 
-COMMAND> torp 2 2 1 2
-
-Beg your pardon, Captain?
-COMMAND> torp 2 2 1 2 1
-
-Track for torpedo number 1-  2 - 4   2 - 3   2 - 2   
-2 - 1   
-Torpedo missed.
-
-Track for torpedo number 2-  2 - 4   2 - 3   2 - 2   
-2 - 1   
-Torpedo missed.
-
-126 unit hit from Klingon at 9 - 1
-
-
-Energy left 2516    shields up 46%,   torpedoes left 5
-COMMAND> torp 2 1 2 1 2
-
-Track for torpedo number 1-  2 - 4   1 - 3   
-
-***Black hole at Sector 1 - 3 swallows torpedo.
-
-Track for torpedo number 2-  2 - 4   1 - 3   
-
-***Black hole at Sector 1 - 3 swallows torpedo.
-
-66 unit hit from Klingon at 9 - 1
-
-
-Energy left 2450    shields up 45%,   torpedoes left 3
-COMMAND> srscan
-     Short-range scan
-    1 2 3 4 5 6 7 8 9 10
- 1  . .   . . . . . . . 
- 2  . . . . E . . . . * 
- 3  . . . . . . . . . . 
- 4  . . . . . . . . . . 
- 5  . . . . . . . . . . 
- 6  . . . * . . . . . . 
- 7  . .   . * . . . . * 
- 8  . . . . . . . * . . 
- 9  C . @ . . * . . . . 
-10  . . . . . . . . . * 
-COMMAND> p a
-
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 2250.27
-642 units required. Units to fire= 51
-
-Shields lowered.
-
-35 unit hit on Commander at Sector 9 - 1
-
-Shields raised.
-
-56 unit hit from Klingon at 9 - 1
+Torpedo track- h10   g10   f10   
+e10   
 
+***STARBASE DESTROYED..
 
-Energy left 2142    shields up 43%,   torpedoes left 3
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  .1.  ...  .13 <107> ..3  ..2  ...   |
-2 | ...  ...  ...  ..4  ..7  ..9  ..5  ..4   |
-3 | ...  ...  ...  ...  ..8  ..7  ***  106   |
-4 | ...  ...  ...  ...  ...  ..1  ..1  102   |
-5 | ...  ...  ...  ...  ...  ..3  ..4  ..3   |
-6 | ...  ...  ..1  ..8  ..3  ..4  ..6  ..8   |
-7 | ...  ...  ..6  .11  ..2  ..2  ..8  207   |
-8 | ...  ...  ..3  ..2  ..7  ...  ..5  ..4   |
-
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "aao"
-7 of 15 Klingons have been killed, including 1 Commander.
-The Super Commander has not been destroyed.
-There are 4 bases.
-No Starbase is currently under attack.
-You have 2 deep space probes.
-
-COMMAND> st
-Stardate      4782.5, Time Left 4.13
-Condition     RED, 0 DAMAGES
-Position      1 - 5 , 2 - 5
-Life Support  ACTIVE
-Warp Factor   5.0
-Energy        2142.31
-Torpedoes     3
-Shields       UP, 43% 1075.0 units
-Klingons Left 8
-Major system  Altair IV
-COMMAND> move a 4 8 1 3
-
-Ensign Chekov- "Course laid in, Captain."
-
-Enterprise blocked by object at 7 - 10;
-Emergency stop required 128 units of energy.
-Collision detected
-
-28 unit hit from Klingon at 9 - 1
-
-
-Energy left 1985    shields up 42%,   torpedoes left 3
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 5 - 7.
-
-[ANNOUNCEMENT ARRIVING...]
-
-Message from Starfleet Command       Stardate 4782.57
-     Supernova in Quadrant 4 - 1; caution advised.
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 6 - 6.
-
-[CONTINUE?]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 7 - 5.
-
-[ANNOUNCEMENT ARRIVING...]
-
-***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 3 - 8, Sector 2 - 2
-
-149 unit hit from Klingon at 7 - 9
-
-
-Energy left 811    shields up 39%,   torpedoes left 3
-COMMAND> srscan
-     Short-range scan
-    1 2 3 4 5 6 7 8 9 10
- 1  . . . . . * . . *   
- 2  . E . . . . . . . . 
- 3  . . . . . . . . * . 
- 4  * . . . . . . . . . 
- 5  . . . . . . . . . . 
- 6  . . . . . . . . . . 
- 7  . . * . . . . . C . 
- 8  . @ . . . . .   . * 
- 9  . . . . . . . . . . 
-10  . . . . . . . . . . 
-COMMAND> torp 3
-Target sector for torpedo number 1- 7 9
-Target sector for torpedo number 2- 7 9
-Target sector for torpedo number 3- 7 9
-
-Track for torpedo number 1-  3 - 3   3 - 4   4 - 5   
-5 - 6   5 - 7   6 - 8   7 - 9   
-***Commander at Sector 7 - 9 damaged-- displaced by blast to Sector 2 - 3 
-
-Track for torpedo number 2-  3 - 3   3 - 4   4 - 5   
-5 - 6   5 - 7   6 - 8   7 - 9   7 - 10   
-Torpedo missed.
-
-Track for torpedo number 3-  3 - 3   3 - 4   4 - 5   
-5 - 6   6 - 7   6 - 8   7 - 9   8 - 10   
-Star at Sector 8 - 10 novas.
-
-261 unit hit from Klingon at 2 - 3
-
-***CRITICAL HIT--S. R. Sensors damaged.
-
-Energy left 549    shields up 33%,   torpedoes left 0
-
-Mc Coy-  "Sickbay to bridge.  We suffered 2 casualties
-   in that last attack."
-COMMAND> lrscan
-Long-range scan
-    5   4  -1 
-  *** 105  -1 
-    1   2  -1 
-COMMAND> srscan
-   S.R. SENSORS DAMAGED!
-    1 2 3 4 5 6 7 8 9 10
- 1  . . . - - - - - - - 
- 2  . E C - - - - - - - 
- 3  . . . - - - - - - - 
- 4  - - - - - - - - - - 
- 5  - - - - - - - - - - 
- 6  - - - - - - - - - - 
- 7  - - - - - - - - - - 
- 8  - - - - - - - - - - 
- 9  - - - - - - - - - - 
-10  - - - - - - - - - - 
-COMMAND> p a
-
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-
----WORKING---
-Short-range-sensors-damaged
-Insufficient-data-for-automatic-phaser-fire
-Manual-fire-must-be-used
-
-
-Shields raised.
-COMMAND> p
-
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-
----WORKING---
-Short-range-sensors-damaged
-Insufficient-data-for-automatic-phaser-fire
-Manual-fire-must-be-used
-
-
-Shields raised.
-COMMAND> p m
-
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Energy available= 349.34
-(0)  units to fire at Commander at Sector 2 - 3-  349
-
-Shields lowered.
-
-344 unit hit on Commander at Sector 2 - 3
-***Commander at Sector 2 - 3 destroyed.
-
-Shields raised.
-COMMAND> srscan
-   S.R. SENSORS DAMAGED!
-    1 2 3 4 5 6 7 8 9 10
- 1  . . . - - - - - - - 
- 2  . E . - - - - - - - 
- 3  . . . - - - - - - - 
- 4  - - - - - - - - - - 
- 5  - - - - - - - - - - 
- 6  - - - - - - - - - - 
- 7  - - - - - - - - - - 
- 8  - - - - - - - - - - 
- 9  - - - - - - - - - - 
-10  - - - - - - - - - - 
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  .1.  ...  .13  107  ..3  ..2  ...   |
-2 | ...  ...  ...  ..4  ..7  ..9  ..5  ..4   |
-3 | ...  ...  ...  ...  ..8  ..7  *** <..5>  |
-4 | ***  ...  ...  ...  ...  ..1  ..1  ..2   |
-5 | ...  ...  ...  ...  ...  ..3  ..4  ..3   |
-6 | ...  ...  ..1  ..8  ..3  ..4  ..6  ..8   |
-7 | ...  ...  ..6  .11  ..2  ..2  ..8  207   |
-8 | ...  ...  ..3  ..2  ..7  ...  ..5  ..4   |
-
-COMMAND> sh down
-Shields lowered.
-COMMAND> m a 7 4 1 10
+Enemy attack reduces shield strength to 89%,   torpedoes left 5
+COMMAND> m a 6 10
 
-Ensign Chekov- "Course laid in, Captain."
 
-Engineering to bridge--
-We don't have enough energy, but we could do it at warp 0.
+Enemy attack reduces shield strength to 89%,   torpedoes left 5
+COMMAND> dock
+No starbase available for docking in this quadrant.
 COMMAND> quit
 
 May the Great Bird of the Galaxy roost upon your home planet.
index 69c2fdb1f0132abc72af26b7ad405c16f041db24..cdededd0091173cba82ce8f214f12dc7a1534320 100644 (file)
@@ -1,8 +1,9 @@
 # seed 1556116333
-# options regular short good fancy
+# arguments regular short good 2023
 # SST2K version 2.4
-# Test ill-formed torpedo command
-# recorded by esr@snark on Wed Apr 24 11:16:25 2019
+# Test starbase destruction, planet destruction, docking after destruction.
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 08:59:1 3 2023
+#
 chart
 m a 3 7 1 2
 sh up
@@ -18,61 +19,4 @@ torp 3 2 1 2 1 2 1
 torp 1 8 10
 m a 6 10
 dock
-rep
-chart
-m a 6 7 1 1
-chaer
-chart
-sh down
-m a 8 9
-sh up
-m a 8 10 8 1
-m a 8 10 8 1
-m a 8 10 8 1
-move auto
-6 8 8 1
-m 7 8 1 1
-n
-m a 7 8 1 1
-torp 3 5 5 5 6 6 6
-torp torp 2 7 2 10 3
-2 
-7 2
-10 3
-lrscan
-srscan
-m a 1 10
-p a
-432
-srscan
-rep
-chart
-m a 1 1
-lrscan
-srscan
-torp 2 2 1 2
-torp 2 2 1 2 1
-torp 2 1 2 1 2
-srscan
-p a
-51
-chart
-rep
-st
-move a 4 8 1 3
-srscan
-torp 3
-7 9
-7 9
-7 9
-lrscan
-srscan
-p a
-p
-p m
-349
-srscan
-chart
-sh down
-m a 7 4 1 10
 quit
index 28344d09b682b6ed61640e527bfacd2e84011d8f..779f4b4cddb3d63550fd5b77ccde74f0bafc95ee 100644 (file)
@@ -1,3 +1,8 @@
+# seed 1556120044
+# arguments regular short good 2023
+# Test deep-space probes
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 11:34:04 2019
+#
 
 
 -SUPER- STAR TREK
@@ -10,57 +15,55 @@ Stardate 5021.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
 7 stardates.
-2 starbases in 4 - 2  8 - 7  
+2 starbases in d2  h7  
 
-The Enterprise is currently in Quadrant 2 - 6 Sector 7 - 7
+The Enterprise is currently in Quadrant b6 Sector g7
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # Test deep-space probes and battle death
-# recorded by esr@snark on Wed Apr 24 11:34:04 2019
-chart
+COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ...   |
-2 | ...  ...  ...  ...  ..4 <..5> ..4  ...   |
-3 | ...  ...  ...  ...  ..2  ..4  ..7  ...   |
-4 | ...  .1.  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  .1.  ...   |
+a | ...  ...  ...  ...  ..8  ..5  106  ...   |
+b | ...  ...  ...  ...  ..4 <..5> ..4  ...   |
+c | ...  ...  ...  ...  ..2  ..4  ..7  ...   |
+d | ...  .1.  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  .1.  ...   |
 
 COMMAND> m a 1 10
 
 COMMAND> s hup
      Short-range scan
     1 2 3 4 5 6 7 8 9 10
- 1  . * . . . . . @ . E 
- 2  . . . . . . .   . . 
- 3  . . . .   . . . . . 
- 4  . . . . . . . . . . 
- 5  . . . . * . . . . . 
- 6  . . . . . . . . . . 
- 7  . . . . . . . . * . 
- 8  . . . . *   . . . . 
- 9  . * . . . . . . . . 
-10  . . . . . . . . . . 
+  . * . . . . . @ . E 
+  . . . . . . .   . . 
+  . . . .   . . . . . 
+  . . . . . . . . . . 
+  . . . . * . . . . . 
+  . . . . . . . . . . 
+  . . . . . . . . * . 
+  . . . . *   . . . . 
+  . * . . . . . . . . 
+  . . . . . . . . . . 
 COMMAND> m a 2 7 1 1
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 2 - 7.
+Entering Quadrant b7.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ..5   |
-2 | ...  ...  ...  ...  ..4  ..5 <..4> ..2   |
-3 | ...  ...  ...  ...  ..2  ..4  ..7  ..7   |
-4 | ...  .1.  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  .1.  ...   |
+a | ...  ...  ...  ...  ..8  ..5  106  ..5   |
+b | ...  ...  ...  ...  ..4  ..5 <..4> ..2   |
+c | ...  ...  ...  ...  ..2  ..4  ..7  ..7   |
+d | ...  .1.  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  .1.  ...   |
 
 COMMAND> probe
 2 probes left
@@ -81,17 +84,17 @@ YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER
 AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,
 YOU WILL BE DESTROYED.
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 2 - 6."
+Lt. Uhura-  "The deep space probe is now in Quadrant b6."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 2 - 5."
+Lt. Uhura-  "The deep space probe is now in Quadrant b5."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 2 - 4."
+Lt. Uhura-  "The deep space probe is now in Quadrant b4."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 2 - 3."
+Lt. Uhura-  "The deep space probe is now in Quadrant b3."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 2 - 2."
+Lt. Uhura-  "The deep space probe is now in Quadrant b2."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 2 - 1."
+Lt. Uhura-  "The deep space probe is now in Quadrant b1."
 
 [ANNOUNCEMENT ARRIVING...]
 
@@ -124,19 +127,19 @@ Lt. Uhura-  "The deep space probe has left the galaxy."
 
 
 Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   a planet in Quadrant 1 - 3 has been destroyed
+   a planet in Quadrant a3 has been destroyed
    by the Super-commander."
 
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 3 - 3, Sector 6 - 8
+Enterprise is pulled to Quadrant c3, Sector f8
 
 Enemy attack reduces shield strength to 85%,   torpedoes left 10
 COMMAND> m a 6 10
 
 
-52 unit hit from Klingon at 1 - 8
+52 unit hit from Klingon at a8
 
 
 Energy left 3399    shields up 75%,   torpedoes left 10
@@ -144,36 +147,37 @@ Energy left 3399    shields up 75%,   torpedoes left 10
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 5024.18
-     Supernova in Quadrant 2 - 6; caution advised.
+     Supernova in Quadrant b6; caution advised.
 COMMAND> torp 2 1 8 1 8
 
-Track for torpedo number 1-  5 - 10   4 - 9   3 - 9   
-2 - 9   1 - 8   
-***Commander at Sector 1 - 8 damaged-- displaced by blast to Sector 5 - 9 
+Track for torpedo number 1-  e10   d9   c9   
+b9   a8   
+***Commander at Sector a8 damaged-- displaced by blast to Sector j7 
 
-Track for torpedo number 2-  5 - 10   4 - 9   3 - 9   
-2 - 8   1 - 8   
+Track for torpedo number 2-  e10   d9   c9   
+b8   a8   
 Torpedo missed.
 
-38 unit hit from Klingon at 5 - 9
+21 unit hit from Klingon at j7
 
 
-Energy left 3310    shields up 71%,   torpedoes left 8
-COMMAND> torp 1 5 9
+Energy left 3328    shields up 73%,   torpedoes left 8
+COMMAND> torp 1 10 7
 
-Torpedo track- 5 - 9   
-***Commander at Sector 5 - 9 destroyed.
+Torpedo track- g9   h9   i8   
+j7   
+***Commander at Sector j7 destroyed.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ..5   |
-2 | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
-3 | ...  ..3 <..6> ..6  ..2  ..4  ..7  ..7   |
-4 | ...  .15  ..6  ..1  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  ...  ...  ...  ...  ...  .1.  ...   |
+a | ...  ...  ...  ...  ..8  ..5  106  ..5   |
+b | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
+c | ...  ..3 <..6> ..6  ..2  ..4  ..7  ..7   |
+d | ...  .15  ..6  ..1  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  .1.  ...   |
 
 COMMAND> m a 10 6
 
@@ -181,41 +185,43 @@ COMMAND> m a 10 6
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 7 - 3, Sector 3 - 2
+Enterprise is pulled to Quadrant g3, Sector c2
 
-67 unit hit from Klingon at 10 - 6
+63 unit hit from Klingon at j6
 
 
-Energy left 3126    shields up 66%,   torpedoes left 7
+Energy left 3148    shields up 67%,   torpedoes left 7
 COMMAND> torp 2 10 6
 
-Track for torpedo number 1-  4 - 3   5 - 3   6 - 4   
-7 - 4   8 - 5   9 - 5   10 - 6   
-***Commander at Sector 10 - 6 damaged-- displaced by blast to Sector 3 - 3 
+Track for torpedo number 1-  d3   e3   f4   
+g4   h5   i5   j6   
+***Commander at Sector j6 damaged-- displaced by blast to Sector j7 
 
-Track for torpedo number 2-  4 - 3   5 - 3   6 - 4   
-7 - 4   8 - 5   9 - 5   10 - 6   
+Track for torpedo number 2-  d3   e3   f4   
+g4   h5   i5   j6   
 Torpedo missed.
 
-73 unit hit from Klingon at 3 - 3
-
+Enemy attack reduces shield strength to 66%,   torpedoes left 5
+COMMAND> torp 2 10 7 10 7
 
-Energy left 3052    shields up 61%,   torpedoes left 5
-COMMAND> torp 1 3 3
+Track for torpedo number 1-  d3   e4   f4   
+g5   h6   i7   j8   
+Torpedo missed.
 
-Torpedo track- 3 - 3   
-***Commander at Sector 3 - 3 destroyed.
+Track for torpedo number 2-  d3   e3   f4   
+g5   h5   i6   j7   
+***Commander at Sector j7 destroyed.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ..5   |
-2 | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
-3 | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
-4 | ...  .15  ..6  ..1  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
-7 | ...  ..8 <..1> ..8  ...  ...  ...  ...   |
-8 | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
+a | ...  ...  ...  ...  ..8  ..5  106  ..5   |
+b | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
+c | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
+d | ...  .15  ..6  ..1  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
+g | ...  ..8 <..1> ..8  ...  ...  ...  ...   |
+h | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
 
 COMMAND> probe
 1 probe left.
@@ -228,14 +234,14 @@ Beg your pardon, Captain?
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ..5   |
-2 | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
-3 | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
-4 | ...  .15  ..6  ..1  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
-7 | ...  ..8 <..1> ..8  ...  ...  ...  ...   |
-8 | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
+a | ...  ...  ...  ...  ..8  ..5  106  ..5   |
+b | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
+c | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
+d | ...  .15  ..6  ..1  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
+g | ...  ..8 <..1> ..8  ...  ...  ...  ...   |
+h | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
 
 COMMAND> probe
 1 probe left.
@@ -248,167 +254,51 @@ Ensign Chekov-  "The deep space probe is launched, Captain."
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ..5   |
-2 | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
-3 | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
-4 | ...  .15  ..6  ..1  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
-7 | ...  ..8 <..1> ..8  ...  ...  ...  ...   |
-8 | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
+a | ...  ...  ...  ...  ..8  ..5  106  ..5   |
+b | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
+c | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
+d | ...  .15  ..6  ..1  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
+g | ...  ..8 <..1> ..8  ...  ...  ...  ...   |
+h | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
 
 COMMAND> m a 5 3 5 5
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 5 - 3.
+Entering Quadrant e3.
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 4."
+Lt. Uhura-  "The deep space probe is now in Quadrant g4."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 5."
+Lt. Uhura-  "The deep space probe is now in Quadrant g5."
 
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 5024.61
-     Supernova in Quadrant 7 - 7; caution advised.
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 6."
-
-[ANNOUNCEMENT ARRIVING...]
-
-Lt. Uhura-  "The deep space probe is no longer transmitting."
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ..5   |
-2 | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
-3 | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
-4 | ...  .15  ..6  ..1  ...  ...  ...  ...   |
-5 | ...  ..1 <..6> ..7  ...  ...  ...  ...   |
-6 | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
-7 | ...  ..8  ..1  ..8  602  ..5  ***  ...   |
-8 | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
-
-COMMAND> sh down
-Shields lowered.
-COMMAND> m a 1 1
-
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 2 - 5.
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5  106  ..5   |
-2 | ..4  ..9  ..3  ..5  104  ***  ..4  ..2   |
-3 | ...  ..3  ..6  ..6  ..2  ..4  ..7  ..7   |
-4 | ...  .15  ..6  ..1  ...  ...  ...  ...   |
-5 | ...  ..1 <..6> ..7  ...  ...  ...  ...   |
-6 | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
-7 | ...  ..8  ..1  ..8  602  ..5  ***  ...   |
-8 | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
+     Supernova in Quadrant c8; caution advised.
 
-COMMAND> m a 4 2 10 10
+Lt. Uhura-  "The deep space probe is now in Quadrant g6."
 
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 4 - 2.
-COMMAND> m a 10 4
-
-COMMAND> m a 6 4
+Lt. Uhura-  "The deep space probe is now in Quadrant g7."
 
+Lt. Uhura-  "The deep space probe is now in Quadrant g8."
 
 [ANNOUNCEMENT ARRIVING...]
 
-***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 1 - 7, Sector 8 - 5
-Shields raised.
-
-335 unit hit from Klingon at 9 - 3
-
-***CRITICAL HIT--Shields damaged.
-***Shields knocked down.
-
-Energy left 2027    shields damaged, 44%,   torpedoes left 4
-COMMAND> p a
-
-Phasers locked on target. Energy available: 2027.62
-646 units required. Units to fire= 646
-
-523 unit hit on Commander at Sector 9 - 3
-***Commander at Sector 9 - 3 destroyed.
-COMMAND> sh down
-Shields damaged and down.
+Lt. Uhura-  "The deep space probe has left the galaxy."
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ..8  ..5 <..6> ..5   |
-2 | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
-3 | ..7  ..3  ..6  ..6  ..2  104  ..7  ..7   |
-4 | ..8  .15  ..6  ..1  ...  ...  ...  ...   |
-5 | ..2  ..1  ..6  ..7  ...  ...  ...  ...   |
-6 | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
-7 | ...  ..8  ..1  ..8  602  ..5  ***  ...   |
-8 | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
-
-COMMAND> m a 4 2 1 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 4 - 2.
-
-[ANNOUNCEMENT ARRIVING...]
-
-***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 3 - 6, Sector 3 - 10
-(Shields not currently useable.)
-
-1302 unit hit from Klingon at 1 - 10
-
-***CRITICAL HIT--Transporter and Impulse Engines and Impulse Engines damaged.
-
-
-
-It is stardate 5027.7.
-
-The Enterprise has been destroyed in battle.
-
-Dulce et decorum est pro patria mori.
-The Federation will be destroyed.
-
-
-[CONTINUE?]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Your score --
-     3 Klingon commanders destroyed         150
-  0.49 Klingons per stardate                244
-     1 ship(s) lost or destroyed           -100
-Penalty for getting yourself killed        -200
-
-TOTAL SCORE                                  93
+a | ...  ...  ...  ...  ..8  ..5  106  ..5   |
+b | ..4  ..9  ..3  ..5  ..4  ***  ..4  ..2   |
+c | ...  ..3  ..6  ..6  ..2  ..4  ..7  ***   |
+d | ...  .15  ..6  ..1  ...  ...  ...  ...   |
+e | ...  ..1 <..6> ..7  ...  ...  ...  ...   |
+f | ...  ..8  ..2  ..5  ...  ...  ...  ...   |
+g | ...  ..8  ..1  ..8  602  ..5  ..4  ..3   |
+h | ...  ..5  ..7  ..9  ...  ...  .1.  ...   |
+
+COMMAND> quit
 
 May the Great Bird of the Galaxy roost upon your home planet.
index c2762c1e9694867ff91a801df248b579a9213ef5..34972455f6aabcded2a3b347ac00bd7a5963a46f 100644 (file)
@@ -1,7 +1,8 @@
 # seed 1556120044
-# options regular short good fancy
-# Test deep-space probes and battle death
-# recorded by esr@snark on Wed Apr 24 11:34:04 2019
+# arguments regular short good 2023
+# Test deep-space probes
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 11:34:04 2019
+#
 chart
 m a 1 10
 s hup
@@ -16,11 +17,11 @@ sh up
 m 1 7 10 1
 m a 6 10
 torp 2 1 8 1 8
-torp 1 5 9
+torp 1 10 7
 chart
 m a 10 6
 torp 2 10 6
-torp 1 3 3
+torp 2 10 7 10 7
 chart
 probe
 y
@@ -36,15 +37,4 @@ a
 chart
 m a 5 3 5 5
 chart
-sh down
-m a 1 1
-chart
-m a 4 2 10 10
-m a 10 4
-m a 6 4
-p a
-646
-sh down
-chart
-m a 4 2 1 10
-n
+quit
index cc00a2f3059267b3332b1b1dad84ba0d782b3e67..1dd3d307abfa02e4399174e83e57d87a5ab8b1de 100644 (file)
@@ -1,3 +1,9 @@
+# seed 1556121767
+# arguments regular short good 2023
+# SST2K version 2.4
+# Test shuttle landing with no crystals
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 12:02:47 2019
+#
 
 
 -SUPER- STAR TREK
@@ -10,45 +16,42 @@ Stardate 3292.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
 7 stardates.
-5 starbases in 3 - 6  4 - 1  6 - 8  2 - 8  2 - 2  
+5 starbases in c6  d1  f8  b8  b2  
 
-The Enterprise is currently in Quadrant 6 - 6 Sector 3 - 3
+The Enterprise is currently in Quadrant f6 Sector c3
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # SST2K version 2.4
-# Test shuttle landing with no crystals
-# recorded by esr@snark on Wed Apr 24 12:02:47 2019
-chart
+COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  .1.   |
-3 | ...  ...  ...  ...  ...  .1.  ...  ...   |
-4 | .1.  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
-6 | ...  ...  ...  ...  ..5 <..3> ..6  .1.   |
-7 | ...  ...  ...  ...  ..5  ..5  ..1  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  .1.   |
+c | ...  ...  ...  ...  ...  .1.  ...  ...   |
+d | .1.  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
+f | ...  ...  ...  ...  ..5 <..3> ..6  .1.   |
+g | ...  ...  ...  ...  ..5  ..5  ..1  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> p a
 
 Phasers locked on target. Energy available: 5000.00
 148 units required. Units to fire= 148
 
-130 unit hit on Tholian at Sector 1 - 1
-***Tholian at Sector 1 - 1 destroyed.
+130 unit hit on Tholian at Sector a1
+***Tholian at Sector a1 destroyed.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  .1.   |
-3 | ...  ...  ...  ...  ...  .1.  ...  ...   |
-4 | .1.  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
-6 | ...  ...  ...  ...  ..5 <..3> ..6  .1.   |
-7 | ...  ...  ...  ...  ..5  ..5  ..1  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  .1.   |
+c | ...  ...  ...  ...  ...  .1.  ...  ...   |
+d | .1.  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
+f | ...  ...  ...  ...  ..5 <..3> ..6  .1.   |
+g | ...  ...  ...  ...  ..5  ..5  ..1  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> sh up
 Shields raised.
@@ -59,36 +62,36 @@ COMMAND> m a 7 10
 
 [ANNOUNCEMENT ARRIVING...]
 Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   a planet in Quadrant 6 - 3 has been destroyed
+   a planet in Quadrant f3 has been destroyed
    by the Super-commander."
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  .1.   |
-3 | ...  ...  ...  ...  ...  .1.  ...  ...   |
-4 | .1.  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
-6 | ...  ...  ...  ...  ..5 <..3> ..6  .1.   |
-7 | ...  ...  ...  ...  ..5  ..5  ..1  ...   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  .1.   |
+c | ...  ...  ...  ...  ...  .1.  ...  ...   |
+d | .1.  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
+f | ...  ...  ...  ...  ..5 <..3> ..6  .1.   |
+g | ...  ...  ...  ...  ..5  ..5  ..1  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
 
 COMMAND> m a 7 7 1 1
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 7 - 7.
+Entering Quadrant g7.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  .1.   |
-3 | ...  ...  ...  ...  ...  .1.  ...  ...   |
-4 | .1.  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
-6 | ...  ...  ...  ...  ..5  ..3  ..6  .12   |
-7 | ...  ...  ...  ...  ..5  ..5 <..1> ..7   |
-8 | ...  ...  ...  ...  ...  ..6  ..9  ..6   |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  .1.   |
+c | ...  ...  ...  ...  ...  .1.  ...  ...   |
+d | .1.  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
+f | ...  ...  ...  ...  ..5  ..3  ..6  .12   |
+g | ...  ...  ...  ...  ..5  ..5 <..1> ..7   |
+h | ...  ...  ...  ...  ...  ..6  ..9  ..6   |
 
 COMMAND> probe
 4 probes left
@@ -101,48 +104,48 @@ Ensign Chekov-  "The deep space probe is launched, Captain."
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ...  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  .1.   |
-3 | ...  ...  ...  ...  ...  .1.  ...  ...   |
-4 | .1.  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
-6 | ...  ...  ...  ...  ..5  ..3  ..6  .12   |
-7 | ...  ...  ...  ...  ..5  ..5 <..1> ..7   |
-8 | ...  ...  ...  ...  ...  ..6  ..9  ..6   |
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  .1.   |
+c | ...  ...  ...  ...  ...  .1.  ...  ...   |
+d | .1.  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
+f | ...  ...  ...  ...  ..5  ..3  ..6  .12   |
+g | ...  ...  ...  ...  ..5  ..5 <..1> ..7   |
+h | ...  ...  ...  ...  ...  ..6  ..9  ..6   |
 
 COMMAND> m a 8 6 1 1
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 8 - 6.
+Entering Quadrant h6.
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 6."
+Lt. Uhura-  "The deep space probe is now in Quadrant g6."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 5."
+Lt. Uhura-  "The deep space probe is now in Quadrant g5."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 4."
+Lt. Uhura-  "The deep space probe is now in Quadrant g4."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 3."
+Lt. Uhura-  "The deep space probe is now in Quadrant g3."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 2."
+Lt. Uhura-  "The deep space probe is now in Quadrant g2."
 
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 3293.58
-     Supernova in Quadrant 1 - 1; caution advised.
+     Supernova in Quadrant a1; caution advised.
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 7 - 1."
+Lt. Uhura-  "The deep space probe is now in Quadrant g1."
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | ***  ...  ...  ...  ...  ...  ...  ...   |
-2 | ...  .1.  ...  ...  ...  ...  ...  .1.   |
-3 | ...  ...  ...  ...  ...  .1.  ...  ...   |
-4 | .1.  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
-6 | ...  ...  ...  ...  ..5  ..3  ..6  .12   |
-7 | ..1  ..8  ..3  ..3  ..5  ..5  ..1  ..7   |
-8 | ...  ...  ...  ...  ..4 <..6> ..9  ..6   |
+a | ***  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  .1.  ...  ...  ...  ...  ...  .1.   |
+c | ...  ...  ...  ...  ...  .1.  ...  ...   |
+d | .1.  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ..6  ..2  ..1  ...   |
+f | ...  ...  ...  ...  ..5  ..3  ..6  .12   |
+g | ..1  ..8  ..3  ..3  ..5  ..5  ..1  ..7   |
+h | ...  ...  ...  ...  ..4 <..6> ..9  ..6   |
 
 COMMAND> m a 2 5
 
@@ -158,17 +161,6 @@ COMMAND> orbit
 
 Helmsman Sulu-  "Entering standard orbit, Sir."
 Sulu-  "Entered orbit at altitude 7779.00 kilometers."
-COMMAND> beam
-LEGAL COMMANDS ARE:
-SRSCAN       STATUS       REQUEST      LRSCAN       
-PHASERS      TORPEDO      PHOTONS      MOVE         SHIELDS      
-DOCK         DAMAGES      CHART        IMPULSE      REST         
-WARP         SENSORS      ORBIT        TRANSPORT    MINE         
-CRYSTALS     SHUTTLE      PLANETS      REPORT       COMPUTER     
-COMMANDS     EMEXIT       PROBE        SAVE         FREEZE       
-ABANDON      DESTRUCT     DEATHRAY     CAPTURE      CLOAK        
-DEBUG        MAYDAY       SOS          CALL         QUIT         
-HELP         SCORE        CURSES                    
 COMMAND> shuttle
 
 Spock-  "Captain, we have no information on this planet
index 4df8e8dddbb458193c541ede6949f21cd142f313..0576598a8e1780c159352810ff9bb147c29456d7 100644 (file)
@@ -1,8 +1,9 @@
 # seed 1556121767
-# options regular short good fancy
+# arguments regular short good 2023
 # SST2K version 2.4
 # Test shuttle landing with no crystals
-# recorded by esr@snark on Wed Apr 24 12:02:47 2019
+# recorded by esr@snark.thyrsus.com on Wed Apr 24 12:02:47 2019
+#
 chart
 p a
 148
@@ -25,7 +26,6 @@ m a 2 5
 m a 2 9
 m a 4 9
 orbit
-beam
 shuttle
 crystals
 shuttle
index 0206de6e0c5be8643e35c58ea3db9d726fc27c39..e0ab438193c59e673e0e5f3a877e10f003996473 100644 (file)
+# seed 1691789031
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test supercommander destruction.
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 17:23:51 2023
+#
 
 
 -SUPER- STAR TREK
 
 
 
-Stardate 2869.
+Stardate 3034.
 
-17 Klingons.
+31 Klingons.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
-7 stardates.
-2 starbases in 8 - 8  8 - 2  
+14 stardates.
+5 starbases in e8  c1  f8  b1  c2  
 
-The Enterprise is currently in Quadrant 1 - 6 Sector 1 - 6
+The Enterprise is currently in Quadrant e1 Sector j3
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # SST2K version 2.4
-# Test supercommander destruction
-# recorded by esr@snark on Wed Apr 24 12:34:44 2019
+COMMAND> sh up
+Shields already up.
+COMMAND> phasers
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Manual or automatic? a
+Phasers locked on target. Energy available: 4800.00
+2695 units required. Units to fire= 2695
+
+Shields lowered.
+
+277 unit hit on Klingon at Sector e3
+***Klingon at Sector e3 destroyed.
+440 unit hit on Klingon at Sector c5
+***Klingon at Sector c5 destroyed.
+474 unit hit on Klingon at Sector b1
+***Klingon at Sector b1 destroyed.
+882 expended on empty space.
 
-COMMAND> m a 7 10
+Shields raised.
+Weapons officer Sulu-  "Phasers overheated, sir."
 
-COMMAND> s hup
+Enemy attack reduces shield strength to 95%,   torpedoes left 10
+COMMAND> srscan
      Short-range scan
     1 2 3 4 5 6 7 8 9 10
- 1  . . . . . . . . . . 
- 2  . . . . . . . . . . 
- 3  . . . . . . . . . . 
- 4  . . . . . . . . . . 
- 5  . . . . . .   . . . 
- 6  . . . . . . . . . . 
- 7  .   . . . * . . . E 
- 8  . . . . . . . . . * 
- 9  . . . . . . . . . . 
-10  . . . . . . . . . . 
-COMMAND> sh up
-Shields raised.
-COMMAND> m a 2 7 1 1
+a   . . . . . . . . . K 
+b   . * . . * . . . . . 
+c   . . . . . . . K . * 
+d   . . . . . . . . . . 
+e   * * . . @ . . . . . 
+f   . . * . . . . . . . 
+g   . . . . . . . . . . 
+h   . . . . . . . . * . 
+i   . . . . . . . . * . 
+j   . . E . . . . . . . 
+COMMAND> m a 5 8
+
+
+Enemy attack reduces shield strength to 89%,   torpedoes left 10
+COMMAND> torp 2 3 8 1 10
+
+Track for torpedo number 1-  d8   c8   
+***Klingon at Sector c8 destroyed.
+
+Track for torpedo number 2-  d9   c9   b10   
+a10   
+***Klingon at Sector a10 destroyed.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | .1.  ...  ...  ...  ...  ...  ...  ...   |
+c | .1.  .1.  ...  ...  ...  ...  ...  ...   |
+d | ..4  ..6  ...  ...  ...  ...  ...  ...   |
+e |<..8> ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ...  ...  ...  ...  ...  .1.   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
+
+COMMAND> m a 3 2 10 8
 
 Ensign Chekov- "Course laid in, Captain."
 
-Enterprise blocked by object at 8 - 10;
-Emergency stop required 125 units of energy.
-Collision detected
-Uhura- Captain, Ingraham B in Quadrant 7 - 5 reports it is under attack
-by a Klingon invasion fleet.
-COMMAND> sh down
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant c5, Sector h2
+
+102 unit hit from Klingon at h3
+
+
+Energy left 1758    shields up 62%,   torpedoes left 8
+COMMAND> torp 2 8 3 8 3
+
+Track for torpedo number 1-  h3   
+***Commander at Sector h3 uses anti-photon device;
+   torpedo neutralized.
+
+Track for torpedo number 2-  h3   
+***Commander at Sector h3 damaged-- displaced by blast to Sector g4 
+
+52 unit hit from Klingon at g4
+
+
+Energy left 1706    shields up 59%,   torpedoes left 6
+COMMAND> phasers
+
+Phaser control damaged.
+COMMAND> torp 1 7 4
+
+Torpedo track- g3   g4   
+***Commander at Sector g4 destroyed.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | .1.  ...  ...  ..7  ..1  101  ...  ...   |
+c | .1.  .1.  ...  ..8 <..1> ..2  ...  ...   |
+d | ..4  ..6  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ...  ...  ...  ...  ...  .1.   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  ...  ...  ...  ...   |
+
+COMMAND> m a 7 3 8 1
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant g3.
+
+[ANNOUNCEMENT ARRIVING...]
+
+Message from Starfleet Command       Stardate 3036.12
+     Supernova in Quadrant f3; caution advised.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | .1.  ...  ...  ..7  ..1  101  ...  ...   |
+c | .1.  .1.  ...  ..8  ..1  ..2  ...  ...   |
+d | ..4  ..6  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ...  ..8 <..6> ..5  ...  ...  ...  ...   |
+h | ...  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> m a 7 1 1 10
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant g1.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | .1.  ...  ...  ..7  ..1  101  ...  ...   |
+c | .1.  .1.  ...  ..8  ..1  ..2  ...  ...   |
+d | ..4  ..6  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g |<..7> ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> sh d
 Shields lowered.
-COMMAND> m a 7 4 1 1
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | .1.  ...  ...  ..7  ..1  101  ...  ...   |
+c | .1.  .1.  ...  ..8  ..1  ..2  ...  ...   |
+d | ..4  ..6  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g |<..7> ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> m a 3 1 10 10
 
 Ensign Chekov- "Course laid in, Captain."
-Uhura- We've lost contact with starsystem Ingraham B
-in Quadrant 7 - 5.
 
+Engineering to bridge--
+We don't have enough energy, but we could do it at warp 4.
+COMMAND> warp 4
+Helmsman Sulu- "Warp factor 4, Captain."
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | .1.  ...  ...  ..7  ..1  101  ...  ...   |
+c | .1.  .1.  ...  ..8  ..1  ..2  ...  ...   |
+d | ..4  ..6  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g |<..7> ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> m a 3 1 10 10
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant c1.
 
 [ANNOUNCEMENT ARRIVING...]
+Lt. Uhura-  "Captain, Starfleet Intelligence reports
+   the Super-commander is in Quadrant b2.
 
-Message from Starfleet Command       Stardate 2871.92
-     Supernova in Quadrant 8 - 3; caution advised.
+[ANNOUNCEMENT ARRIVING...]
+Lt. Uhura-  "Captain, Starfleet Intelligence reports
+   the Super-commander is in Quadrant b2.
+COMMAND> m a 6 6
+
+COMMAND> dock
+Docked.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ...  ...  ...  ...   |
+b | .16  ..2  ...  107  ..1  101  ...  ...   |
+c |<.15> .19  ...  ..8  ..1  ..2  ...  ...   |
+d | ..4  ..6  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> m a 2 1 1 6
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant b1.
+
+[ANNOUNCEMENT ARRIVING...]
+
+Message from Starfleet Command       Stardate 3039.83
+     Supernova in Quadrant d2; caution advised.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ...  ...  ...  ...   |
+b |<.16> ..2  ...  107  ..1  101  ...  ...   |
+c | .15  .19  ...  ..8  ..1  ..2  ...  ...   |
+d | ..4  ***  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> m a 2 10
+
+
+Enterprise blocked by object at a8;
+Emergency stop required 106 units of energy.
+Collision detected
 
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 1 - 2, Sector 8 - 1
+Enterprise is pulled to Quadrant b6, Sector e8
 Shields raised.
 
-Enemy attack reduces shield strength to 90%,   torpedoes left 10
-COMMAND> torp 2 4 6
+Enemy attack reduces shield strength to 94%,   torpedoes left 10
+COMMAND> torpedo 2 1 1 1 1
+
+Track for torpedo number 1-  d7   d6   c5   
+c4   b3   a2   a1   
+***Commander at Sector a1 damaged-- displaced by blast to Sector j1 
 
-Track for torpedo number 1-  7 - 2   6 - 3   6 - 4   
-5 - 5   4 - 6   
-***Commander at Sector 4 - 6 damaged-- displaced by blast to Sector 7 - 2 
+Track for torpedo number 2-  d7   d6   c5   
+c4   b3   a2   a1   
+Torpedo missed.
 
-Track for torpedo number 2-  7 - 2   
-***Commander at Sector 7 - 2 destroyed.
+Enemy attack reduces shield strength to 92%,   torpedoes left 8
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | 108 <..4> ..5  ...  ..4  ..2  ..3  ...   |
-2 | ..8  ..1  ..6  ...  ..2  ..1  109  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ...  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  .1.  ***  ...  ...  ...  ...  .1.   |
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  ...   |
+b | .16  ..2  ...  ..7  ..1 <101> ..9  ...   |
+c | .15  .19  ...  108  ..1  ..2  ..7  ...   |
+d | ..4  ***  ...  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
 
-COMMAND> m a 1 1 10 10
+COMMAND> m a 3 4 5 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 1 - 1.
+Entering Quadrant c4.
 
-77 unit hit from Klingon at 8 - 6
+106 unit hit from Klingon at f8
 
 
-Energy left 3781    shields up 67%,   torpedoes left 8
+Energy left 4615    shields up 54%,   torpedoes left 8
 
-169 unit hit from Klingon at 8 - 6
+370 unit hit from Klingon at f8
 
+***CRITICAL HIT--Computer damaged.
 
-Energy left 3611    shields up 56%,   torpedoes left 8
-COMMAND> m a 5 10
+Energy left 4244    shields up 40%,   torpedoes left 8
 
+Mc Coy-  "Sickbay to bridge.  We suffered 3 casualties
+   in that last attack."
+COMMAND> phasers
 
-170 unit hit from Klingon at 8 - 6
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Battle computer damaged, manual fire only.
 
+Shields raised.
+COMMAND> torpedo 3 6 8 5 8 6 8
 
-Energy left 3385    shields up 49%,   torpedoes left 8
-COMMAND> torp 3 8 7
+Track for torpedo number 1-  f9   f8   
+***Super-commander at Sector f8 damaged-- displaced by blast to Sector f7 
 
-Track for torpedo number 1-  6 - 9   7 - 8   8 - 7   
-9 - 6   10 - 5   
-***Star at Sector 10 - 5 unaffected by photon blast.
+Track for torpedo number 2-  e9   e8   e7   
+e6   
+Star at Sector e6 novas.
+***Super-commander at Sector f7 destroyed.
 
-Track for torpedo number 2-  6 - 9   7 - 8   8 - 7   
-9 - 6   10 - 5   
-Star at Sector 10 - 5 novas.
+Track for torpedo number 3-  f9   f8   g7   
+g6   h5   h4   i3   i2   
+Star at Sector i2 novas.
+***Star at Sector j3 novas.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  ...   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9  ...   |
+c | .15  .19  ..3 <..5> ..1  ..2  ..7  ...   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> m a 6 1
+
+COMMAND> chart 
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  ...   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9  ...   |
+c | .15  .19  ..3 <..5> ..1  ..2  ..7  ...   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  104  ..4  ...  ...  ...  ...   |
+
+COMMAND> m 3 2 5 10
+(Manual movement assumed.)
+
+Helmsman Sulu- "Aye, Sir."
+Uhura- Captain, Vulcan (T'Khasi) in Quadrant b6 reports it is under attack
+by a Klingon invasion fleet.
 
-Track for torpedo number 3-  6 - 9   7 - 8   8 - 7   
-9 - 6   10 - 5   
-Torpedo missed.
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant h3, Sector a4
+
+179 unit hit from Klingon at e10
 
-132 unit hit from Klingon at 8 - 6
 
+Energy left 3480    shields up 36%,   torpedoes left 5
+COMMAND> torpedo 2 5 10 5 10
 
-Energy left 3127    shields up 45%,   torpedoes left 5
-COMMAND> torp 1 8 7
+Track for torpedo number 1-  b5   b6   c7   
+d8   d9   e10   
+***Commander at Sector e10 damaged-- displaced by blast to Sector d1 
 
-Torpedo track- 6 - 9   7 - 8   8 - 7   
-9 - 6   10 - 5   10 - 4   
+Track for torpedo number 2-  b5   b6   c7   
+d8   d9   e10   
 Torpedo missed.
 
-103 unit hit from Klingon at 8 - 6
+167 unit hit from Klingon at d1
 
 
-Energy left 3024    shields up 42%,   torpedoes left 4
-COMMAND> p a
+Energy left 3313    shields up 33%,   torpedoes left 3
+COMMAND> torpedo 2 4 1 4 1
 
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 2824.69
-353 units required. Units to fire= 353
+Track for torpedo number 1-  b3   c2   d1   
+***Commander at Sector d1 destroyed.
 
+Track for torpedo number 2-  b3   c2   d1   
+Torpedo missed.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  ...   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9  ...   |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ...   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8 <..4> ..4  ...  ...  ...  ...   |
+
+COMMAND> sh d
 Shields lowered.
+COMMAND> m a 8 1 9 10
 
-239 unit hit on Super-commander at Sector 8 - 6
-***Super-commander at Sector 8 - 6 destroyed.
+Ensign Chekov- "Course laid in, Captain."
+
+Enterprise blocked by object at c1;
+Emergency stop required 80 units of energy.
+Collision detected
+COMMAND> m a 2 1
 
-Shields raised.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 |<-93> ..4  ..5  ...  ..4  ..2  ..3  ...   |
-2 | ..8  101  ..6  ...  ..2  ..1  109  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ...  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ...  ...  ...   |
-7 | ...  ...  ...  ...  ...  ...  ...  ...   |
-8 | ...  .1.  ***  ...  ...  ...  ...  .1.   |
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  ...   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9  ...   |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ...   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8 <..4> ..4  ...  ...  ...  ...   |
 
-COMMAND> m a 2 2 1 1
+COMMAND> m a 3 1 10 10
 
 Ensign Chekov- "Course laid in, Captain."
 
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 7 - 7, Sector 1 - 7
-
-488 unit hit from Klingon at 1 - 10
-
-***CRITICAL HIT--Impulse Engines damaged.
-74 unit hit from Klingon at 8 - 7
-
-82 unit hit from Klingon at 7 - 3
+Enterprise is pulled to Quadrant b6, Sector f8
+Shields raised.
 
-50 unit hit from Klingon at 9 - 6
+359 unit hit from Klingon at e2
 
+***CRITICAL HIT--Shields damaged.
+***Shields knocked down.
 
-Energy left 1610    shields up 28%,   torpedoes left 4
+Energy left 2651    shields damaged, 27%,   torpedoes left 1
 
 Mc Coy-  "Sickbay to bridge.  We suffered 4 casualties
    in that last attack."
-COMMAND> p a
+COMMAND> torpedo 2 5 2 5 2
 
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 1410.29
-1908 units required. Units to fire= 1908
-Energy available= 1410.29
-1908 units required. Units to fire= 1000
+1 torpedoes left.
+Number of torpedoes to fire- 1
+Target sector for torpedo number 1- 5 2
 
-Shields lowered.
+Torpedo track- f7   f6   e5   
+e4   e3   e2   
+***Commander at Sector e2 damaged-- displaced by blast to Sector d1 
 
-587 unit hit on Commander at Sector 1 - 10
-***Commander at Sector 1 - 10 destroyed.
+116 unit hit from Klingon at d1
 
-Shields raised.
 
-67 unit hit from Klingon at 8 - 7
+Energy left 2535    shields damaged, 27%,   torpedoes left 0
+COMMAND> phasers
 
-84 unit hit from Klingon at 7 - 3
-
-50 unit hit from Klingon at 9 - 6
+Battle computer damaged, manual fire only.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  ...   |
+b | .16  ..2  ..6  ..7  ..1 <101> ..9  ...   |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ...   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  ..4  ..4  ...  ...  ...  ...   |
 
+COMMAND> m a 2 8 1 6
 
-Energy left 207    shields up 25%,   torpedoes left 4
-COMMAND> torp 2 7 3 9 6
+Ensign Chekov- "Course laid in, Captain."
 
-Track for torpedo number 1-  2 - 6   3 - 6   4 - 5   
-5 - 5   6 - 4   7 - 3   
-***Klingon at Sector 7 - 3 destroyed.
+Entering Quadrant b8.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  107   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9 <..9>  |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ..5   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  ..4  ..4  ...  ...  ...  ...   |
 
-Track for torpedo number 2-  2 - 7   3 - 7   4 - 7   
-5 - 7   
-Star at Sector 5 - 7 novas.
+COMMAND> m a 3 8
 
-59 unit hit from Klingon at 8 - 7
+COMMAND> m a 10 7
 
-37 unit hit from Klingon at 9 - 6
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  107   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9 <..9>  |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ..5   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ...  ...   |
+e | ..8  ..5  ...  ...  ...  ...  ...  .1.   |
+f | ..3  ..6  ***  ..6  ...  ...  ...  .1.   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  ..4  ..4  ...  ...  ...  ...   |
 
+COMMAND> m a 5 8 1 7
 
-Energy left 110    shields up 24%,   torpedoes left 2
-COMMAND> torp 2 9 6 8 7
+Ensign Chekov- "Course laid in, Captain."
 
-Track for torpedo number 1-  2 - 7   3 - 7   4 - 7   
-5 - 6   6 - 6   7 - 6   8 - 6   9 - 6   
-***Klingon at Sector 9 - 6 destroyed.
+Entering Quadrant e8.
+COMMAND> m a 7 3
 
-Track for torpedo number 2-  2 - 7   3 - 7   4 - 7   
-5 - 7   6 - 7   7 - 7   8 - 7   
-***Klingon at Sector 8 - 7 destroyed.
+COMMAND> dock
+Docked.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  107   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9  ..9   |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ..5   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ..3  ..9   |
+e | ..8  ..5  ...  ...  ...  ...  ..8 <.14>  |
+f | ..3  ..6  ***  ..6  ...  ...  603  517   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  ..4  ..4  ...  ...  ...  ...   |
+
+COMMAND> rest
+How long? 3
+0 stardates left.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | -93  ..4  ..5  ...  ..4  ..2  ..3  ...   |
-2 | ..8  101  ..6  ...  ..2  ..1  109  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ...  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ...  ...  ...   |
-6 | ...  ...  ...  ...  ...  ..8  ..9  ..2   |
-7 | ...  ...  ...  ...  ...  ..4 <..1> ..2   |
-8 | ...  .1.  ***  ...  ...  ..3  ..5  .15   |
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  107   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9  ..9   |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ..5   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ..3  ..9   |
+e | ..8  ..5  ...  ...  ...  ...  ..8 <.14>  |
+f | ..3  ..6  ***  ..6  ...  ...  603  517   |
+g | ..7  ..8  ..6  ..5  ...  ...  ...  ...   |
+h | ..9  ..8  ..4  ..4  ...  ...  ...  ...   |
 
-COMMAND> m a 8 8 1 1
+COMMAND> m a 6 8 1 3
 
 Ensign Chekov- "Course laid in, Captain."
 
-Engineering to bridge--
-We don't have enough energy, but we could do it at warp 4,
-if you'll lower the shields.
-COMMAND> s hdown
-     Short-range scan
-    1 2 3 4 5 6 7 8 9 10
- 1  . . . . P . E . . . 
- 2    . . . . . . . . . 
- 3  . . . . . . . * . . 
- 4  . . . . . . . . . . 
- 5  . . . . . . . .   . 
- 6  . . . . . . . . . . 
- 7  . . . . . . . . . . 
- 8  . . . . . . . . . . 
- 9  . . . . . . . . . . 
-10  . . . . . . . . . . 
-COMMAND> m a 8 8 1 1
+Entering Quadrant f8.
 
-Ensign Chekov- "Course laid in, Captain."
+312 unit hit from Klingon at b2
 
-Engineering to bridge--
-We don't have enough energy, but we could do it at warp 4,
-if you'll lower the shields.
-COMMAND> warp 4
-Helmsman Sulu- "Warp factor 4, Captain."
-COMMAND> m a 8 8 1 1
+***CRITICAL HIT--Transporter damaged.
+302 unit hit from Klingon at c2
 
-Ensign Chekov- "Course laid in, Captain."
+***CRITICAL HIT--D. S. Probe damaged.
+71 unit hit from Klingon at i7
 
-Engineering to bridge--
-We haven't the energy to go that far with the shields up.
-COMMAND> sh down
-Shields lowered.
-COMMAND> m a 8 8 1 1
+75 unit hit from Klingon at h9
 
-Ensign Chekov- "Course laid in, Captain."
+71 unit hit from Klingon at h10
 
-Enterprise blocked by object at 3 - 8;
-Emergency stop required 80 units of energy.
-Collision detected
 
+Energy left 4166    shields down 100%,   torpedoes left 10
+
+Mc Coy-  "Sickbay to bridge.  We suffered 5 casualties
+   in that last attack."
+
+221 unit hit from Klingon at b2
+
+[CONTINUE?]
 
 
-It is stardate 2872.9.
 
-Your energy supply is exhausted.
 
-Your starship is a derelict in space.
-The Federation will be destroyed.
 
 
-Your score --
-     3 ordinary Klingons destroyed           30
-     2 Klingon commanders destroyed         100
-     1 Super-Commander destroyed            200
-  1.81 Klingons per stardate                903
-     2 stars destroyed by your action       -10
-     4 casualties incurred                   -4
-     1 ship(s) lost or destroyed           -100
-[CONTINUE?]
 
 
 
@@ -326,14 +593,117 @@ Your score --
 
 
 
+220 unit hit from Klingon at c2
 
+63 unit hit from Klingon at i7
 
+79 unit hit from Klingon at h9
 
+43 unit hit from Klingon at h10
 
 
+Energy left 3538    shields down 100%,   torpedoes left 10
 
-Penalty for getting yourself killed        -200
+Mc Coy-  "Sickbay to bridge.  We suffered 5 casualties
+   in that last attack."
+COMMAND> sh up
+Shields raised.
+
+Enemy attack reduces shield strength to 84%,   torpedoes left 10
+COMMAND> phasers
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Manual or automatic? a
+Phasers locked on target. Energy available: 3262.69
+1085 units required. Units to fire= 1085
+
+Shields lowered.
+
+86 unit hit on Klingon at Sector b2
+***Klingon at Sector b2 destroyed.
+104 unit hit on Klingon at Sector c2
+***Klingon at Sector c2 destroyed.
+150 unit hit on Klingon at Sector i7
+***Klingon at Sector i7 destroyed.
+36 unit hit on Klingon at Sector h9
+***Mr. Spock-  "Captain, the vessel at Sector h9
+   has just lost its firepower."
+518 expended on empty space.
+
+Shields raised.
 
-TOTAL SCORE                                 919
+Enemy attack reduces shield strength to 84%,   torpedoes left 10
+COMMAND> m a 5 7
+
+
+Enemy attack reduces shield strength to 83%,   torpedoes left 10
+COMMAND> phasers
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Manual or automatic? a
+Phasers locked on target. Energy available: 1905.28
+196 units required. Units to fire= 196
+
+Shields lowered.
+
+89 unit hit on Klingon at Sector h9
+***Klingon at Sector h9 destroyed.
+
+Shields raised.
+
+Enemy attack reduces shield strength to 82%,   torpedoes left 10
+COMMAND> torpedo 1 8 10
+
+Torpedo track- f8   g9   h10   
+***Klingon at Sector h10 destroyed.
+COMMAND> m a 10 7
+
+
+First Officer Spock- "Captain, I compute that such
+  a trip would require approximately 80 percent of our
+  remaining time.  Are you sure this is wise?" n
+COMMAND> warp 2
+Helmsman Sulu- "Warp factor 2, Captain."
+COMMAND> m a 10 7
+
+
+First Officer Spock- "Captain, I compute that such
+  a trip would require approximately 321 percent of our
+  remaining time.  Are you sure this is wise?" n
+COMMAND> warp 3
+Helmsman Sulu- "Warp factor 3, Captain."
+COMMAND> m a 10 7
+
+
+First Officer Spock- "Captain, I compute that such
+  a trip would require approximately 143 percent of our
+  remaining time.  Are you sure this is wise?" n
+COMMAND> warp 5
+Helmsman Sulu- "Warp factor 5, Captain."
+COMMAND> m a 10 7
+
+COMMAND> m a 10 4
+
+COMMAND> dock
+Docked.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..1  ..6  ...  ...  ..1  ..8  ..7  107   |
+b | .16  ..2  ..6  ..7  ..1  101  ..9  ..9   |
+c | .15  .19  ..3  ..5  ..1  ..2  ..7  ..5   |
+d | ..4  ***  ..3  ..2  ..6  ..3  ..3  ..9   |
+e | ..8  ..5  ...  ...  ...  ...  ..8  .14   |
+f | ..3  ..6  ***  ..6  ...  ...  603 <.17>  |
+g | ..7  ..8  ..6  ..5  ...  ...  ..3  ..6   |
+h | ..9  ..8  ..4  ..4  ...  ...  ...  ...   |
+
+COMMAND> m a 9 3
+
+
+First Officer Spock- "Captain, I compute that such
+  a trip would require approximately 81 percent of our
+  remaining time.  Are you sure this is wise?" n
+COMMAND> quit
 
 May the Great Bird of the Galaxy roost upon your home planet.
index 468155af8ee90ff349802e980e6f6e2e41c3bfc5..eee5561ecdca2e9e52d7cd7c48621d082165c885 100644 (file)
@@ -1,36 +1,97 @@
-# seed 1556123684
-# options regular short good fancy
-# SST2K version 2.4
-# Test supercommander destruction
-# recorded by esr@snark on Wed Apr 24 12:34:44 2019
-
-m a 7 10
-s hup
+# seed 1691789031
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test supercommander destruction.
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 17:23:51 2023
+#
 sh up
-m a 2 7 1 1
-sh down
-m a 7 4 1 1
-torp 2 4 6
-chart
-m a 1 1 10 10
-m a 5 10
-torp 3 8 7
-torp 1 8 7
-p a
-353
-chart
-m a 2 2 1 1
-p a
-1908
-1000
-torp 2 7 3 9 6
-torp 2 9 6 8 7
-chart
-m a 8 8 1 1
-s hdown
-m a 8 8 1 1
+phasers
+a
+2695
+srscan
+m a 5 8
+torp 2 3 8 1 10
+chart
+m a 3 2 10 8
+torp 2 8 3 8 3
+phasers
+torp 1 7 4
+chart
+m a 7 3 8 1
+chart
+m a 7 1 1 10
+chart
+sh d
+chart
+m a 3 1 10 10
 warp 4
-m a 8 8 1 1
-sh down
-m a 8 8 1 1
+chart
+m a 3 1 10 10
+m a 6 6
+dock
+chart
+m a 2 1 1 6
+chart
+m a 2 10
+torpedo 2 1 1 1 1
+chart
+m a 3 4 5 10
+phasers
+torpedo 3 6 8 5 8 6 8
+chart
+m a 6 1
+chart 
+m 3 2 5 10
+torpedo 2 5 10 5 10
+torpedo 2 4 1 4 1
+chart
+sh d
+m a 8 1 9 10
+m a 2 1
+chart
+m a 3 1 10 10
+torpedo 2 5 2 5 2
+
+1
+5 2
+phasers
+chart
+m a 2 8 1 6
+chart
+m a 3 8
+m a 10 7
+chart
+m a 5 8 1 7
+m a 7 3
+dock
+chart
+rest
+3
+chart
+m a 6 8 1 3
+sh up
+phasers
+a
+1085
+m a 5 7
+phasers
+a
+196
+torpedo 1 8 10
+m a 10 7
+n
+warp 2
+m a 10 7
+n
+warp 3
+m a 10 7
+n
+warp 5
+m a 10 7
+m a 10 4
+dock
+chart
+m a 9 3
+n
+quit
 n
index 8b18174efc3ce606ef70bac113482ced505d4ffa..e9f3f4d8e977cb913403934017057f6ef20cb5cb 100644 (file)
+# seed 1691831923
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test game-win condition
+# recorded by esr@snark.thyrsus.com on Sat Aug 12 05:18:43 2023
+#
 
 
 -SUPER- STAR TREK
 
 
 
-Stardate 2964.
+It is stardate 4983. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 9 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
 
-15 Klingons.
-An unknown number of Romulans.
-And one (GULP) Super-Commander.
-7 stardates.
-5 starbases in 7 - 8  7 - 3  1 - 1  1 - 8  7 - 4  
+You will have 4 supporting starbases.
+Starbase locations-  b5  g3  h3  b4  
 
-The Enterprise is currently in Quadrant 6 - 7 Sector 7 - 10
+The Enterprise is currently in Quadrant a8 Sector f4
 
 Good Luck!
-  YOU'LL NEED IT.
-COMMAND> # SST2K version 2.4
-# Test winning end of game
-# recorded by esr@snark on Wed Apr 24 12:57:36 2019
-chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ...  ...  ...  ...  .1.   |
-2 | ...  ...  ...  ...  ...  ...  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ...  ...  ...  ...  ...  ...  ...  ...   |
-5 | ...  ...  ...  ...  ...  ..3  104  ..5   |
-6 | ...  ...  ...  ...  ...  ..7 <..8> ..3   |
-7 | ...  ...  .1.  .1.  ...  ..2  ..5  .16   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
-
-COMMAND> m a 7 8
-
-COMMAND> m a 7 7
-
-COMMAND> m a 1 1
-
-
-[ANNOUNCEMENT ARRIVING...]
-
-Message from Starfleet Command       Stardate 2964.92
-     Supernova in Quadrant 4 - 5; caution advised.
-COMMAND> sh up
-Shields raised.
-COMMAND> m a 5 7 10 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 5 - 7.
-
-Enemy attack reduces shield strength to 84%,   torpedoes left 10
-
-51 unit hit from Klingon at 5 - 3
-
-
-Energy left 4755    shields up 75%,   torpedoes left 10
-COMMAND> torp 1 5 3
-
-Torpedo track- 9 - 1   8 - 2   7 - 2   
-6 - 2   5 - 3   
-***Commander at Sector 5 - 3 damaged but not destroyed.
-
-Enemy attack reduces shield strength to 74%,   torpedoes left 9
-COMMAND> torp 1 5 3
-
-Torpedo track- 9 - 1   8 - 2   7 - 2   
-6 - 3   5 - 3   
-***Commander at Sector 5 - 3 destroyed.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ...  ...  ...  ...  .1.   |
-2 | ...  ...  ...  ...  ...  ...  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ...  ...  ...  ...  ***  ..4  ..8  ..1   |
-5 | ...  ...  ...  ...  ...  ..3 <..4> ..5   |
-6 | ...  ...  ...  ...  ...  ..7  ..8  ..3   |
-7 | ...  ...  .1.  .1.  ...  ..2  ..5  .16   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
-
-COMMAND> sh down
-Shields lowered.
-COMMAND> m a 1 1
-
-
-[ANNOUNCEMENT ARRIVING...]
-
-***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 1 - 5, Sector 10 - 8
-Shields raised.
-
-98 unit hit from Klingon at 3 - 7
-
-
-Energy left 4492    shields up 65%,   torpedoes left 8
-COMMAND> m a 10 6
-
+a | ...  ...  ...  ...  ...  ...  ..3 <..3>  |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  .1.  ...  ...  ...  ...  ...   |
+h | ...  ...  .1.  ...  ...  ...  ...  ...   |
 
-101 unit hit from Klingon at 3 - 7
-
-
-Energy left 4391    shields up 59%,   torpedoes left 8
-COMMAND> torp 1 3 7
-
-Torpedo track- 9 - 6   8 - 6   7 - 7   
-6 - 7   5 - 7   4 - 7   3 - 7   
-***Commander at Sector 3 - 7 damaged-- displaced by blast to Sector 9 - 7 
-
-90 unit hit from Klingon at 9 - 7
-
-
-Energy left 4250    shields up 54%,   torpedoes left 7
-COMMAND> torp 1 9 7
+COMMAND> probe
+3 probes left
+Are you sure you want to fire a probe? y
+Arm NOVAMAX warhead? n
+Manual or automatic- a
+Target quadrant or quadrant&sector- 1 1
 
-Torpedo track- 9 - 7   
-***Commander at Sector 9 - 7 destroyed.
+Ensign Chekov-  "The deep space probe is launched, Captain."
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1 <..5> ..8  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ...  ...  ...  ...  ***  ..4  ..8  ..1   |
-5 | ...  ...  ...  ...  ...  ..3  ..4  ..5   |
-6 | ...  ...  ...  ...  ...  ..7  ..8  ..3   |
-7 | ...  ...  .1.  .1.  ...  ..2  ..5  .16   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
+a | ...  ...  ...  ...  ...  ...  ..3 <..3>  |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  .1.  ...  ...  ...  ...  ...   |
+h | ...  ...  .1.  ...  ...  ...  ...  ...   |
 
-COMMAND> m a 1 8 1 1
+COMMAND> m a 7 4 1 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-[ANNOUNCEMENT ARRIVING...]
-
-***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 5 - 2, Sector 10 - 4
-
-177 unit hit from Klingon at 4 - 3
-
-
-Energy left 3920    shields up 48%,   torpedoes left 6
-COMMAND> m a 10 1
+Entering Quadrant g4.
 
+Lt. Uhura-  "The deep space probe is now in Quadrant a7."
 
-198 unit hit from Klingon at 4 - 3
+Lt. Uhura-  "The deep space probe is now in Quadrant a6."
 
+Lt. Uhura-  "The deep space probe is now in Quadrant a5."
 
-Energy left 3722    shields up 42%,   torpedoes left 6
-COMMAND> torp a 4 3
+Lt. Uhura-  "The deep space probe is now in Quadrant a4."
 
-Beg your pardon, Captain?
-COMMAND> torp 1 4 3
+Lt. Uhura-  "The deep space probe is now in Quadrant a3."
 
-Torpedo track- 9 - 1   8 - 2   7 - 2   
-6 - 2   5 - 3   4 - 3   
-***Commander at Sector 4 - 3 damaged-- displaced by blast to Sector 9 - 1 
+Lt. Uhura-  "The deep space probe is now in Quadrant a2."
 
-29 unit hit from Klingon at 9 - 1
+Lt. Uhura-  "The deep space probe is now in Quadrant a1."
 
+[ANNOUNCEMENT ARRIVING...]
 
-Energy left 3617    shields up 41%,   torpedoes left 5
-COMMAND> torp 1 9 1
-
-Torpedo track- 9 - 1   
-***Commander at Sector 9 - 1 destroyed.
+Lt. Uhura-  "The deep space probe has left the galaxy."
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ..8  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  101   |
-5 | 208 <..7> ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ...  ...  ..7  ..8  ..3   |
-7 | ...  ...  .1.  .1.  ...  ..2  ..5  .16   |
-8 | ...  ...  ...  ...  ...  ...  ...  ...   |
-
-COMMAND> m a 7 3 5 5
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 7 - 3.
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 4 - 8.
-COMMAND> m a 1 3
-
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ..2  ..5  ..2  ...  ...  ...   |
+g | ...  ...  111 <..5> ..4  ...  ...  ...   |
+h | ...  ...  .19  ..5  ..7  ...  ...  ...   |
 
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 5 - 8.
-COMMAND> m a 1 4
+COMMAND> m a 3 1
 
-COMMAND> dock
-Docked.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ..8  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 | 208  ..7  ..3  ...  ...  ..3  ..4  105   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1 <.18> .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  ...  ..2  ..5  ..2  ...  ...  ...   |
+g | ...  ...  111 <..5> ..4  ...  ...  ...   |
+h | ...  ...  .19  ..5  ..7  ...  ...  ...   |
 
-COMMAND> m a 5 1 10 10
+COMMAND> m a 7 3 3 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 5 - 1.
-
-Enemy attack reduces shield strength to 90%,   torpedoes left 10
-
-Enemy attack reduces shield strength to 85%,   torpedoes left 10
-
-[ANNOUNCEMENT ARRIVING...]
+Entering Quadrant g3.
 
-Message from Starfleet Command       Stardate 2967.40
-     Supernova in Quadrant 1 - 6; caution advised.
-COMMAND> p a 
+83 unit hit on the Enterprise from Klingon at Sector j5
 
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 4354.89
-641 units required. Units to fire= 641
 
-Shields lowered.
+Energy left 3992    shields down 100%,   torpedoes left 10
+COMMAND> phasers
 
-160 unit hit on Klingon at Sector 4 - 6
-***Klingon at Sector 4 - 6 destroyed.
-52 unit hit on Klingon at Sector 4 - 8
-***Mr. Spock-  "Captain, the vessel at Sector 4 - 8
-   has just lost its firepower."
-293 expended on empty space.
+Manual or automatic? a
+Phasers locked on target. Energy available: 3980.41
+326 units required. Units to fire= 326
 
-Shields raised.
+218 unit hit on Klingon at Sector j5
+***Klingon at Sector j5 destroyed.
+COMMAND> m a 6 10
 
-Enemy attack reduces shield strength to 85%,   torpedoes left 10
-COMMAND> capture
-Klingon captain at 4 - 8 surrenders.
-192 Klingons commit suicide rather than be taken captive.
-7 captives taken
-***Klingon at Sector 10 - 10 destroyed.
+COMMAND> dock
+Docked.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 |<..8> ..7  ..3  ...  ...  ..3  ..4  105   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
-
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "acs"
-5 of 15 Klingons have been killed, including 3 Commanders.
-The Super Commander has not been destroyed.
-There are 5 bases.
-No Starbase is currently under attack.
-7 Klingons in brig.
-You have 3 deep space probes.
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  207  ..2  ..5  ..2  ...  ...  ...   |
+g | ...  ..8 <.11> ..5  ..4  ...  ...  ...   |
+h | ...  ..7  .19  ..5  ..7  ...  ...  ...   |
 
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 |<..8> ..7  ..3  ...  ...  ..3  ..4  105   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
-
-COMMAND> sh down
-Shields lowered.
 COMMAND> m a 1 10
 
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 7 - 7.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 |<..8> ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  105  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
-
-COMMAND> m s 4 1 1 1
-
-Beg your pardon, Captain?
-COMMAND> chart
-       STAR CHART FOR THE KNOWN GALAXY
-      1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ...  ...  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 |<..8> ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  105  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  207  ..2  ..5  ..2  ...  ...  ...   |
+g | ...  ..8 <.11> ..5  ..4  ...  ...  ...   |
+h | ...  ..7  .19  ..5  ..7  ...  ...  ...   |
 
-COMMAND> m a 4 1 10 10
+COMMAND> m a 7 4 1 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 4 - 1.
+Entering Quadrant g4.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ..3  ..5  ...  ...  ...  ...  ...  ...   |
-4 |<..6> ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 | ..8  ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  105  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  207  ..2  ..5  ..2  ...  ...  ...   |
+g | ...  ..8  .11 <..5> ..4  ...  ...  ...   |
+h | ...  ..7  .19  ..5  ..7  ...  ...  ...   |
 
-COMMAND> m a 1 10
+COMMAND> m a 2 9
 
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ...  ...  ...  ..3  ..8  ..3  ...  ...   |
-3 | ..3  ..5  ...  ...  ...  ...  ...  ...   |
-4 |<..6> ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 | ..8  ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ...  207  ..2  ..5  ..2  ...  ...  ...   |
+g | ...  ..8  .11 <..5> ..4  ...  ...  ...   |
+h | ...  ..7  .19  ..5  ..7  ...  ...  ...   |
 
-COMMAND> m a 3 1 1 10
+COMMAND> m a 7 2 2 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 3 - 1.
-
-[ANNOUNCEMENT ARRIVING...]
-
-Message from Starfleet Command       Stardate 2968.64
-     Supernova in Quadrant 2 - 8; caution advised.
+Entering Quadrant g2.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ..1  ..9  ...  ..3  ..8  ..3  ...  ***   |
-3 |<..3> ..5  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 | ..8  ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ..7  207  ..2  ..5  ..2  ...  ...  ...   |
+g | ..1 <..8> .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
 
+COMMAND> sh up
+Shields raised.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ..1  ..9  ...  ..3  ..8  ..3  ...  ***   |
-3 |<..3> ..5  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 | ..8  ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  ...  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  ...  ...  ...  ...   |
+f | ..7  207  ..2  ..5  ..2  ...  ...  ...   |
+g | ..1 <..8> .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
 
-COMMAND> probe
-3 probes left
-Are you sure you want to fire a probe? y
-Arm NOVAMAX warhead? n
-Manual or automatic- a
-Target quadrant or quadrant&sector- 3 8
+COMMAND> m a 5 2 10 10
 
-Ensign Chekov-  "The deep space probe is launched, Captain."
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant e2.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 | .1.  ...  ...  ..1  ..5  ***  ...  .1.   |
-2 | ..1  ..9  ...  ..3  ..8  ..3  ...  ***   |
-3 |<..3> ..5  ...  ...  ...  ...  ...  ...   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 | ..8  ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ..1  ..2  ..7  ...  ...  ...  ...  ...   |
+e | 209 <..5> ..2  ...  ...  ...  ...  ...   |
+f | ..7  207  ..2  ..5  ..2  ...  ...  ...   |
+g | ..1  ..8  .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
 
-COMMAND> m a 1 1 10 10
+COMMAND> m a 6 2 1 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 1 - 1.
+Entering Quadrant f2.
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 2."
+Enemy attack reduces shield strength to 82%,   torpedoes left 10
+COMMAND> m a 1 9
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 3."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 4."
+88 unit hit on the Enterprise from Klingon at Sector e9
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 5."
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 6."
-COMMAND> m a 6 9
+Energy left 4094    shields up 68%,   torpedoes left 10
+COMMAND> torp 2 5 9 5 9
 
+Track for torpedo number 1-  b9   c9   d9   
+e9   
+***Commander at Sector e9 damaged-- displaced by blast to Sector f8 
 
-Enterprise blocked by object at 8 - 10;
-Emergency stop required 125 units of energy.
-Collision detected
+Track for torpedo number 2-  b9   c9   d9   
+e9   f9   g9   h9   i9   
+j9   
+Torpedo missed.
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 7."
-COMMAND> m a 9 5
+Enemy attack reduces shield strength to 66%,   torpedoes left 8
+COMMAND> phasers
 
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Manual or automatic? a
+Phasers locked on target. Energy available: 3869.31
+386 units required. Units to fire= 386
 
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 8."
+Shields lowered.
 
-[ANNOUNCEMENT ARRIVING...]
+101 unit hit on Commander at Sector f8
+***Commander at Sector f8 destroyed.
+94 unit hit on Klingon at Sector h1
+***Klingon at Sector h1 destroyed.
+110 expended on empty space.
 
-Lt. Uhura-  "The deep space probe has left the galaxy."
-COMMAND> d
-Docked.
-7 captured Klingons transferred to base
+Shields raised.
 COMMAND> chart
        STAR CHART FOR THE KNOWN GALAXY
       1    2    3    4    5    6    7    8
-1 |<.13> ..7  ...  ..1  ..5  ***  ...  .1.   |
-2 | ..1  ..9  ...  ..3  ..8  ..3  ...  ***   |
-3 | ..3  ..5  ..3  ..2  ..2  ..1  ..5  ..6   |
-4 | ..6  ..7  ..6  ...  ***  ..4  ..8  ..1   |
-5 | ..8  ..7  ..3  ...  ...  ..3  ..4  ..5   |
-6 | ..9  ..6  ..3  ..6  ...  ..7  ..8  ..3   |
-7 | ...  ..1  .18  .12  ...  ..2  ..5  .16   |
-8 | ...  ..5  ..5  ..5  ...  ...  ...  ...   |
-
-COMMAND> 
-COMMAND> sh down
-Shields already down.
-COMMAND> 
-COMMAND> m a 2 2 10 10
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ..1  ..2  ..7  ...  ...  ...  ...  ...   |
+e | 209  ..5  ..2  ...  ...  ...  ...  ...   |
+f | ..7 <..7> ..2  ..5  ..2  ...  ...  ...   |
+g | ..1  ..8  .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
 
-Ensign Chekov- "Course laid in, Captain."
+COMMAND> probe
+2 probes left
+Are you sure you want to fire a probe? y
+Arm NOVAMAX warhead? n
+Manual or automatic- a
+Target quadrant or quadrant&sector- 6 8
 
-Entering Quadrant 2 - 2.
-COMMAND> 
-COMMAND> m a 4 3 10 10
+Ensign Chekov-  "The deep space probe is launched, Captain."
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ...  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ..1  ..2  ..7  ...  ...  ...  ...  ...   |
+e | 209  ..5  ..2  ...  ...  ...  ...  ...   |
+f | ..7 <..7> ..2  ..5  ..2  ...  ...  ...   |
+g | ..1  ..8  .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
+
+COMMAND> sh s
+Do you wish to change shield energy? n
+Shields are up. Do you want them down? y
+Shields lowered.
+COMMAND> m a 1 5
 
-Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 4 - 3.
-COMMAND> 
-COMMAND> m a 7 2 10 1
+Lt. Uhura-  "The deep space probe is now in Quadrant f3."
 
-Ensign Chekov- "Course laid in, Captain."
+Lt. Uhura-  "The deep space probe is now in Quadrant f4."
+COMMAND> m 5 3
+(Manual movement assumed.)
 
-Entering Quadrant 7 - 2.
+Helmsman Sulu- "Aye, Sir."
 
-[ANNOUNCEMENT ARRIVING...]
+Entering Quadrant c7.
 
-Message from Starfleet Command       Stardate 2972.03
-     Supernova in Quadrant 5 - 2; caution advised.
-COMMAND> 
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "acs"
-5 of 15 Klingons have been killed, including 3 Commanders.
-The Super Commander has not been destroyed.
-There are 5 bases.
-No Starbase is currently under attack.
-You have 2 deep space probes.
-
-COMMAND> 
-COMMAND> m a 7 4 10 10
+Lt. Uhura-  "The deep space probe is now in Quadrant f5."
 
-Ensign Chekov- "Course laid in, Captain."
+Lt. Uhura-  "The deep space probe is now in Quadrant f6."
 
-Entering Quadrant 7 - 4.
+Lt. Uhura-  "The deep space probe is now in Quadrant f7."
 
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 8 - 5.
+Lt. Uhura-  "The deep space probe is now in Quadrant f8."
 
 [ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 8 - 5.
-COMMAND> 
-COMMAND> sh up
-Shields raised.
-COMMAND> 
-COMMAND> m a 8 5 1 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 8 - 5.
-
-37 unit hit from Klingon at 4 - 6
-
-43 unit hit from Klingon at 8 - 4
-
-29 unit hit from Klingon at 9 - 1
-
-34 unit hit from Klingon at 9 - 2
-
-27 unit hit from Klingon at 6 - 8
-
-
-Energy left 3459    shields up 60%,   torpedoes left 10
-
-219 unit hit from Klingon at 3 - 4
-
-60 unit hit from Klingon at 4 - 6
-
-37 unit hit from Klingon at 8 - 4
-
-38 unit hit from Klingon at 9 - 1
-[CONTINUE?]
-
-
-
-
-
-
-
-
-
-
-
 
+Lt. Uhura-  "The deep space probe has left the galaxy."
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7 <..1> ..7   |
+d | ..1  ..2  ..7  ...  ...  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ...  ...  ...  ...  ...   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
 
+COMMAND> m a 10 10
 
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7 <..1> ..7   |
+d | ..1  ..2  ..7  ...  ...  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ...  ...  ...  ...  ...   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
 
+COMMAND> m a 5 7 1 10
 
+Ensign Chekov- "Course laid in, Captain."
 
+Entering Quadrant e7.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ...  ...  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ...  ...  ..3 <..4> ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ...  ...  ...   |
+h | ..5  ..7  .19  ..5  ..7  ...  ...  ...   |
 
+COMMAND> m a 7 7 1 10
 
+Ensign Chekov- "Course laid in, Captain."
 
+Entering Quadrant g7.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ...  ...  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ...  ...  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8 <..4> ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
+
+COMMAND> chart 5 4 10 10
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ...  ...  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ...  ...  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8 <..4> ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ...  ...  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ...  ...  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8 <..4> ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
+COMMAND> m a 5 4 10 10
 
+Ensign Chekov- "Course laid in, Captain."
 
+Entering Quadrant e4.
 
-40 unit hit from Klingon at 9 - 2
+257 unit hit on the Enterprise from Klingon at Sector i8
 
-26 unit hit from Klingon at 6 - 8
+90 unit hit on the Enterprise from Klingon at Sector c8
 
 
-Energy left 3034    shields up 43%,   torpedoes left 10
+Energy left 1840    shields down 66%,   torpedoes left 8
 
 Mc Coy-  "Sickbay to bridge.  We suffered 3 casualties
    in that last attack."
-COMMAND> torp 3 4 3 4 4 6
-
-Beg your pardon, Captain?
-COMMAND> to 3 34 34 4 6
-
-Beg your pardon, Captain?
-COMMAND> torp 3
-Target sector for torpedo number 1- 3 4
-Target sector for torpedo number 2- 3 4
-Target sector for torpedo number 3- 4 6
-
-Track for torpedo number 1-  2 - 2   2 - 3   3 - 4   
-***Super-commander at Sector 3 - 4 damaged-- displaced by blast to Sector 2 - 1 
-
-Track for torpedo number 2-  2 - 2   2 - 3   3 - 4   
-4 - 5   4 - 6   
-***Klingon at Sector 4 - 6 destroyed.
-
-Track for torpedo number 3-  2 - 2   2 - 3   3 - 4   
-4 - 5   4 - 6   5 - 7   5 - 8   6 - 9   
-7 - 10   
-Torpedo missed.
-
-113 unit hit from Klingon at 2 - 1
-
-30 unit hit from Klingon at 8 - 4
-
-30 unit hit from Klingon at 9 - 1
-
-32 unit hit from Klingon at 9 - 2
-
-26 unit hit from Klingon at 6 - 8
-
-
-Energy left 2765    shields up 38%,   torpedoes left 7
-[CONTINUE?]
-
-
-
-
-
-
-
-
-
-
-
-
+COMMAND> phasers
 
+Manual or automatic? a
+Phasers locked on target. Energy available: 1441.14
+490 units required. Units to fire= 490
 
+129 unit hit on Klingon at Sector i8
+***Klingon at Sector i8 destroyed.
+101 unit hit on Klingon at Sector c8
+***Mr. Spock-  "Captain, the vessel at Sector c8
+   has just lost its firepower."
+148 expended on empty space.
 
+Enemy attack reduces shield strength to 66%,   torpedoes left 8
+COMMAND> torp 1 3 8
 
+Torpedo track- i10   h9   g9   
+f9   e9   d8   c8   
+***Klingon at Sector c8 destroyed.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ..6  ..8  ..4  ..4  ..1   |
+e | 209  ..5  ..2 <..3> ..5  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8  ..4  ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
+COMMAND> m a 1 5
 
+COMMAND> sh up
+Shields raised.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ...  .1.  .1.  ..4  ..7  ..3   |
+c | ...  ...  ...  ...  ...  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ..6  ..8  ..4  ..4  ..1   |
+e | 209  ..5  ..2 <..3> ..5  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8  ..4  ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
+COMMAND> m a 3 4 10 5
 
+Ensign Chekov- "Course laid in, Captain."
 
+Entering Quadrant c4.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ..3  215  .12  ..4  ..7  ..3   |
+c | ...  ...  ..9 <..6> ..4  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ..6  ..8  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ..3  ..5  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8  ..4  ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
+COMMAND> m a 1 1
 
+COMMAND> sh up
+Shields already up.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ..3  215  .12  ..4  ..7  ..3   |
+c | ...  ...  ..9 <..6> ..4  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ..6  ..8  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ..3  ..5  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8  ..4  ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
-COMMAND> p a
+COMMAND> m a 2 4 10 1
 
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 2565.27
-1085 units required. Units to fire= 1085
+Ensign Chekov- "Course laid in, Captain."
 
-Shields lowered.
+Entering Quadrant b4.
 
-97 unit hit on Super-commander at Sector 2 - 1
-***Super-commander at Sector 2 - 1 destroyed.
-161 unit hit on Klingon at Sector 8 - 4
-***Klingon at Sector 8 - 4 destroyed.
-114 unit hit on Klingon at Sector 9 - 1
-***Klingon at Sector 9 - 1 destroyed.
-353 expended on empty space.
+75 unit hit on the Enterprise from Klingon at Sector h4
 
-Shields raised.
+19 unit hit on the Enterprise from Klingon at Sector d9
 
-24 unit hit from Klingon at 9 - 2
 
-23 unit hit from Klingon at 6 - 8
+Energy left 155    shields up 60%,   torpedoes left 7
+COMMAND> phasers
 
+Insufficient energy to activate high-speed shield control.
+COMMAND> torpedo 2
+Target sector for torpedo number 1- 8 5 4 9
+Target sector for torpedo number 2- 4 9
 
-Energy left 1431    shields up 37%,   torpedoes left 7
-COMMAND> torp 2 8 6 9 2
+Track for torpedo number 1-  i2   i3   h4   
+***Klingon at Sector h4 destroyed.
 
-Track for torpedo number 1-  2 - 2   3 - 2   4 - 3   
-5 - 4   
-Star at Sector 5 - 4 novas.
+Track for torpedo number 2-  i2   i3   h4   
+g5   g6   f7   e8   e9   
+d10   
+Torpedo missed.
 
-Track for torpedo number 2-  2 - 1   3 - 1   4 - 1   
-5 - 2   6 - 2   7 - 2   8 - 2   9 - 2   
-***Klingon at Sector 9 - 2 destroyed.
+16 unit hit on the Enterprise from Klingon at Sector d9
 
-17 unit hit from Klingon at 6 - 8
 
+Energy left 113    shields up 59%,   torpedoes left 5
+COMMAND> torp 1
+Target sector for torpedo number 1- 4 9
 
-Energy left 1414    shields up 36%,   torpedoes left 5
-COMMAND> p a
+Torpedo track- i2   h3   h4   
+g5   f6   e7   e8   d9   
+***Klingon at Sector d9 destroyed.
+COMMAND> m a 2 10
 
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 1214.40
-134 units required. Units to fire= 134
 
+Engineering to bridge--
+We don't have enough energy, but we could do it at warp 4,
+if you'll lower the shields.
+COMMAND> sh d
 Shields lowered.
+COMMAND> warp 4
+Helmsman Sulu- "Warp factor 4, Captain."
+COMMAND> m a 2 10
 
-56 unit hit on Klingon at Sector 6 - 8
-***Klingon at Sector 6 - 8 destroyed.
-
-Shields raised.
-COMMAND> 
-COMMAND> m a 7 4 10 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 7 - 4.
-COMMAND> m a 3 7
-
-
-[ANNOUNCEMENT ARRIVING...]
-
-Message from Starfleet Command       Stardate 2973.97
-     Supernova in Quadrant 3 - 4; caution advised.
-COMMAND> d
+COMMAND> dock
 Docked.
-COMMAND> 
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "acs"
-11 of 15 Klingons have been killed, including 3 Commanders.
-The Super Commander has been destroyed.
-There are 5 bases.
-No Starbase is currently under attack.
-3 casualties suffered so far.
-You have 2 deep space probes.
-
-COMMAND> 
-COMMAND> sh down
-Shields lowered.
-COMMAND> 
-COMMAND> m a 8 6 10 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 8 - 6.
-COMMAND> 
-COMMAND> sh up
-Shields raised.
-COMMAND> m a 8 8 10 1
-
-Ensign Chekov- "Course laid in, Captain."
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ..3 <.15> .12  ..4  ..7  ..3   |
+c | ...  ...  ..9  ..6  ..4  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ..6  ..8  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ..3  ..5  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8  ..4  ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
-Entering Quadrant 8 - 8.
-COMMAND> 
-COMMAND> sh down
-Shields lowered.
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "acs"
-11 of 15 Klingons have been killed, including 3 Commanders.
-The Super Commander has been destroyed.
-There are 5 bases.
-No Starbase is currently under attack.
-3 casualties suffered so far.
-You have 2 deep space probes.
-
-COMMAND> 
-COMMAND> m a 6 5 1 1
+COMMAND> m a 1 1
 
-Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 6 - 5.
-COMMAND> sh up
-Shields raised.
-COMMAND> 
-COMMAND> sh down
-Shields lowered.
-COMMAND> 
-COMMAND> m a 3 6 1 10
+Enterprise blocked by object at b9;
+Emergency stop required 80 units of energy.
+Collision detected
+COMMAND> m a 10 2
 
-Ensign Chekov- "Course laid in, Captain."
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..3  ..4  ..4  ..1  ..7  ..5  ..3  ..3   |
+b | ...  ...  ..3 <.15> .12  ..4  ..7  ..3   |
+c | ...  ...  ..9  ..6  ..4  ..7  ..1  ..7   |
+d | ..1  ..2  ..7  ..6  ..8  ..4  ..4  ..1   |
+e | 209  ..5  ..2  ..3  ..5  ..3  ..4  ..7   |
+f | ..7  ..7  ..2  ..5  ..2  ..9  ..6  ..6   |
+g | ..1  ..8  .11  ..5  ..4  ..8  ..4  ..6   |
+h | ..5  ..7  .19  ..5  ..7  ..1  ..5  ..3   |
 
-Entering Quadrant 3 - 6.
-COMMAND> 
-COMMAND> sh up
-Shields raised.
-COMMAND> 
-COMMAND> m a 1 7 10 1
+COMMAND> m a 5 1 1 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 1 - 7.
-COMMAND> 
-COMMAND> m a 1 8 1 1
-
-Ensign Chekov- "Course laid in, Captain."
+Entering Quadrant e1.
 
-Entering Quadrant 1 - 8.
+150 unit hit on the Enterprise from Klingon at Sector b4
 
-Enemy attack reduces shield strength to 84%,   torpedoes left 10
+161 unit hit on the Enterprise from Klingon at Sector b7
 
-18 unit hit from Klingon at 4 - 5
 
-15 unit hit from Klingon at 4 - 6
+Energy left 4477    shields down 100%,   torpedoes left 10
 
-22 unit hit from Klingon at 1 - 7
+[ANNOUNCEMENT ARRIVING...]
 
+Message from Starfleet Command       Stardate 4999.03
+     Supernova in Quadrant b4; caution advised.
 
-Energy left 2919    shields up 74%,   torpedoes left 10
-COMMAND> p a
+[ANNOUNCEMENT ARRIVING...]
 
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 2382.96
-1051 units required. Units to fire= 1051
+Message from Starfleet Command       Stardate 4999.40
+     Supernova in Quadrant f4; caution advised.
+COMMAND> phasers
 
-Shields lowered.
+Manual or automatic? a
+Phasers locked on target. Energy available: 4282.64
+532 units required. Units to fire= 532
 
-158 unit hit on Klingon at Sector 4 - 5
-***Klingon at Sector 4 - 5 destroyed.
-189 unit hit on Klingon at Sector 4 - 6
-***Klingon at Sector 4 - 6 destroyed.
-105 unit hit on Klingon at Sector 1 - 7
-***Mr. Spock-  "Captain, the vessel at Sector 1 - 7
+158 unit hit on Klingon at Sector b4
+***Klingon at Sector b4 destroyed.
+119 unit hit on Klingon at Sector b7
+***Mr. Spock-  "Captain, the vessel at Sector b7
    has just lost its firepower."
-459 expended on empty space.
-
-Shields raised.
+195 expended on empty space.
 
-11 unit hit from Klingon at 9 - 5
+Enemy attack reduces shield strength to 100%,   torpedoes left 10
+COMMAND> torp 1 2 7
 
+Torpedo track- a9   b8   
 
-Energy left 1320    shields up 73%,   torpedoes left 10
-COMMAND> p a
+***Black hole at Sector b8 swallows torpedo.
 
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 1120.24
-299 units required. Units to fire= 299
+Enemy attack reduces shield strength to 100%,   torpedoes left 9
+COMMAND> phasers
 
-Shields lowered.
+Manual or automatic? a
+Phasers locked on target. Energy available: 3750.64
+101 units required. Units to fire= 101
 
-20 unit hit on Klingon at Sector 1 - 7
-***Klingon at Sector 1 - 7 destroyed.
-180 unit hit on Klingon at Sector 9 - 5
-***Klingon at Sector 9 - 5 destroyed.
+64 unit hit on Klingon at Sector b7
+***Klingon at Sector b7 destroyed.
 
 
 
-It is stardate 2979.9.
+It is stardate 4999.7.
 
 You have smashed the Klingon invasion fleet and saved
 the Federation.
 
+In fact, you have done so well that Starfleet Command
+promotes you one step in rank from "Novice" to "Fair".
+
 LIVE LONG AND PROSPER.
 
 
 Your score --
-    11 ordinary Klingons destroyed          110
-     3 Klingon commanders destroyed         150
-7 Klingons captured                      23
-     1 Super-Commander destroyed            200
-  0.98 Klingons per stardate                491
-     1 stars destroyed by your action        -5
-[CONTINUE?]
+     8 ordinary Klingons destroyed           80
+     1 Klingon commanders destroyed          50
+  0.57 Klingons per stardate                286
+     3 casualties incurred                   -3
+Bonus for winning Novice game               100
 
+TOTAL SCORE                                 513
+[PRESS ENTER TO CONTINUE]
 
 
 
@@ -847,9 +692,6 @@ Your score --
 
 
 
-     3 casualties incurred                   -3
-Bonus for winning Good game                 300
 
-TOTAL SCORE                                1266
 
 May the Great Bird of the Galaxy roost upon your home planet.
index cc36e81ff84ad6d28800120cf7ebbba446fc68a9..6ff36f98d97ca6a919cc7b50ad116f651784e1bb 100644 (file)
-# seed 1556125056
-# options regular short good fancy
-# SST2K version 2.4
-# Test winning end of game
-# recorded by esr@snark on Wed Apr 24 12:57:36 2019
-chart
-m a 7 8
-m a 7 7
-m a 1 1
-sh up
-m a 5 7 10 1
-torp 1 5 3
-torp 1 5 3
+# seed 1691831923
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test game-win condition
+# recorded by esr@snark.thyrsus.com on Sat Aug 12 05:18:43 2023
+#
 chart
-sh down
-m a 1 1
-m a 10 6
-torp 1 3 7
-torp 1 9 7
-chart
-m a 1 8 1 1
-m a 10 1
-torp a 4 3
-torp 1 4 3
-torp 1 9 1
-chart
-m a 7 3 5 5
-m a 1 3
-m a 1 4
-dock
+probe
+y
+n
+a
+1 1
 chart
-m a 5 1 10 10
-p a 
-641
-capture
+m a 7 4 1 10
 chart
-rep
+m a 3 1
+chart
+m a 7 3 3 10
+phasers
+a
+326
+m a 6 10
+dock
 chart
-sh down
 m a 1 10
 chart
-m s 4 1 1 1
+m a 7 4 1 10
 chart
-m a 4 1 10 10
+m a 2 9
 chart
-m a 1 10
+m a 7 2 2 10
 chart
-m a 3 1 1 10
+sh up
 chart
+m a 5 2 10 10
+chart
+m a 6 2 1 10
+m a 1 9
+torp 2 5 9 5 9
+phasers
+a
+386
 chart
 probe
 y
 n
 a
-3 8
-chart
-m a 1 1 10 10
-m a 6 9
-m a 9 5
-d
-chart
-
-sh down
-
-m a 2 2 10 10
-
-m a 4 3 10 10
-
-m a 7 2 10 1
-
-rep
-
-m a 7 4 10 10
-
-sh up
-
-m a 8 5 1 1
-torp 3 4 3 4 4 6
-to 3 34 34 4 6
-torp 3
-3 4
-3 4
-4 6
-p a
-1085
-torp 2 8 6 9 2
-p a
-134
-
-m a 7 4 10 10
-m a 3 7
-d
-
-rep
-
-sh down
-
-m a 8 6 10 10
-
-sh up
-m a 8 8 10 1
-
-sh down
-rep
-
-m a 6 5 1 1
+6 8
+chart
+sh s
+n
+y
+m a 1 5
+m 5 3
+chart
+m a 10 10
+chart
+m a 5 7 1 10
+chart
+m a 7 7 1 10
+chart
+chart 5 4 10 10
+chart
+m a 5 4 10 10
+phasers
+a
+490
+torp 1 3 8
+chart
+m a 1 5
 sh up
-
-sh down
-
-m a 3 6 1 10
-
+chart
+m a 3 4 10 5
+chart
+m a 1 1
 sh up
-
-m a 1 7 10 1
-
-m a 1 8 1 1
-p a
-1051
-p a
-299
+chart
+m a 2 4 10 1
+phasers
+torpedo 2
+8 5 4 9
+4 9
+torp 1
+4 9
+m a 2 10
+sh d
+warp 4
+m a 2 10
+dock
+chart
+m a 1 1
+m a 10 2
+chart
+m a 5 1 1 10
+phasers
+a
+532
+torp 1 2 7
+phasers
+a
+101
 n
index 099fb007d2677287cf5d723a24cfc125172e230e..66349ea63234dad5290862e3d4ce91ad987c6391 100644 (file)
+# seed 1691779887
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test behavior of Tholian
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 14:51:27 2023
+#
 
 
 -SUPER- STAR TREK
 
 
 
-Stardate 3632.
+Stardate 2302.
 
-16 Klingons.
+27 Klingons.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
-7 stardates.
-2 starbases in 6 - 2  5 - 6  
+14 stardates.
+4 starbases in f2  b5  c6  b6  
 
-The Enterprise is currently in Quadrant 3 - 6 Sector 8 - 6
+The Enterprise is currently in Quadrant d4 Sector a7
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # SST2K version 2.5
-# Test that escaping a quadrant with a Tholian in it removes him.
-# recorded by esr@snark on Thu Apr 25 09:27:17 2019
-
-COMMAND> m a 8 10
-
-Uhura- Captain, Gamma Tranguli VI (Vaalel) in Quadrant 7 - 2 reports it is under attack
-by a Klingon invasion fleet.
-COMMAND> 
-COMMAND> sh up
-Shields raised.
-COMMAND> m a 7 2 7 1
+COMMAND> srscan
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   T . . . . . E . . . 
+b   . . . . . . * .   . 
+c   * . . . . . . . . . 
+d   . . . . . . . . . . 
+e   . . . . . . . . . . 
+f   . . . . . . . . . . 
+g   . . . . . . . . . . 
+h   . . . . . * . . . . 
+i   . . . . . * . . . . 
+j   . . . . . . . * . . 
+COMMAND> m a 1 10
+
+
+Enemy attack reduces shield strength to 100%,   torpedoes left 10
+COMMAND> # Observe that the Tolian doesn't spin a web..
+srscan
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   T . . . . . . . . E 
+b   . . . . . . * .   . 
+c   * . . . . . . . . . 
+d   . . . . . . . . . . 
+e   . . . . . . . . . . 
+f   . . . . . . . . . . 
+g   . . . . . . . . . . 
+h   . . . . . * . . . . 
+i   . . . . . * . . . . 
+j   . . . . . . . * . . 
+COMMAND> m a 6 10
+
+
+Enemy attack reduces shield strength to 100%,   torpedoes left 10
+COMMAND> # ... until it can be done without hitting the E
+srscan
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   # # # # # # # # # T 
+b   . . . . . . * .   . 
+c   * . . . . . . . . . 
+d   . . . . . . . . . . 
+e   . . . . . . . . . . 
+f   . . . . . . . . . E 
+g   . . . . . . . . . . 
+h   . . . . . * . . . . 
+i   . . . . . * . . . . 
+j   . . . . . . . * . . 
+COMMAND> # Move out of quadrant and then back
+m a 4 5 1 6
 
 Ensign Chekov- "Course laid in, Captain."
 
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   a planet in Quadrant 3 - 3 has been destroyed
-   by the Super-commander."
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   a planet in Quadrant 2 - 3 has been destroyed
-   by the Super-commander."
-Uhura- We've lost contact with starsystem Gamma Tranguli VI (Vaalel)
-in Quadrant 7 - 2.
-
-
-[ANNOUNCEMENT ARRIVING...]
-
-***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 4 - 7, Sector 1 - 8
-
-Enemy attack reduces shield strength to 93%,   torpedoes left 10
-COMMAND> 
-COMMAND> torp 1 9 8
-
-Torpedo track- 2 - 8   3 - 8   4 - 8   
-5 - 8   6 - 8   7 - 8   8 - 8   9 - 8   
-***Commander at Sector 9 - 8 damaged-- displaced by blast to Sector 2 - 7 
-
-26 unit hit from Klingon at 2 - 7
-
-
-Energy left 3938    shields up 81%,   torpedoes left 9
-COMMAND> torp 1 2 7
-
-Torpedo track- 2 - 7   
-***Commander at Sector 2 - 7 destroyed.
-COMMAND> 
-COMMAND> sh down
-Shields lowered.
-COMMAND> 
-COMMAND> m a 2 7 1 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 2 - 7.
-COMMAND> 
-COMMAND> sh up
-Shields raised.
-COMMAND> 
-COMMAND> m a 1 6 10 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 1 - 6.
-
-111 unit hit from Klingon at 9 - 4
-
-
-Energy left 3525    shields up 66%,   torpedoes left 8
-
-264 unit hit from Klingon at 9 - 4
-
-
-Energy left 3260    shields up 49%,   torpedoes left 8
-COMMAND> m a 0 10
-
-Beg your pardon, Captain?
-COMMAND> m a 9 10
-
-
-257 unit hit from Klingon at 9 - 4
-
-***CRITICAL HIT--D. S. Probe damaged.
-
-Energy left 2752    shields up 41%,   torpedoes left 8
-
-Mc Coy-  "Sickbay to bridge.  We suffered 2 casualties
-   in that last attack."
-COMMAND> torp 2 9 5
-
-Track for torpedo number 1-  9 - 9   9 - 8   9 - 7   
-9 - 6   9 - 5   9 - 4   
-***Super-commander at Sector 9 - 4 uses anti-photon device;
-   torpedo neutralized.
-
-Track for torpedo number 2-  9 - 9   9 - 8   9 - 7   
-9 - 6   9 - 5   9 - 4   
-***Super-commander at Sector 9 - 4 damaged-- displaced by blast to Sector 8 - 9 
-
-63 unit hit from Klingon at 8 - 9
-
-
-Energy left 2663    shields up 40%,   torpedoes left 6
-COMMAND> torp 1 8 9
-
-Torpedo track- 8 - 9   
-***Super-commander at Sector 8 - 9 uses anti-photon device;
-   torpedo neutralized.
-
-50 unit hit from Klingon at 8 - 9
-
-
-Energy left 2613    shields up 39%,   torpedoes left 5
-COMMAND> torp 2 8 9
-
-Track for torpedo number 1-  8 - 9   
-***Super-commander at Sector 8 - 9 destroyed.
-
-Track for torpedo number 2-  8 - 9   7 - 8   6 - 7   
-5 - 6   4 - 5   
-Star at Sector 4 - 5 novas.
+Entering Quadrant d5.
+COMMAND> m a 1 1
 
-Enemy attack reduces shield strength to 39%,   torpedoes left 3
-COMMAND> 
-COMMAND> m a 1 7 9 1
+COMMAND> m a 4 4 1 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 1 - 7.
-COMMAND> 
-COMMAND> sh down
-Shields lowered.
+Entering Quadrant d4.
+
+Enemy attack reduces shield strength to 100%,   torpedoes left 10
+
+Enemy attack reduces shield strength to 100%,   torpedoes left 10
+COMMAND> # Look for the Tholian; the web should be gone.
+srscan
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   T . . . * . . . . E 
+b   . . . .   . . . . . 
+c   . . . . . . . . .   
+d   . . . . * . . . . . 
+e   . . . . . . . . . . 
+f   . . . . . . . . . . 
+g   . . . . . . . . . . 
+h   . . . . . * . . . . 
+i   . . . * . . . . . . 
+j   . . . . . . * . . . 
 COMMAND> quit
 
 May the Great Bird of the Galaxy roost upon your home planet.
index 67a083356aac0bbbe21a83c47658725816e2ef2a..8438ace67f64f6269a53f164686bf44bf7147722 100644 (file)
@@ -1,31 +1,21 @@
-# seed 1556198837
-# options regular short good fancy
-# SST2K version 2.5
-# Test that escaping a quadrant with a Tholian in it removes him.
-# recorded by esr@snark on Thu Apr 25 09:27:17 2019
-
-m a 8 10
-
-sh up
-m a 7 2 7 1
-
-torp 1 9 8
-torp 1 2 7
-
-sh down
-
-m a 2 7 1 10
-
-sh up
-
-m a 1 6 10 10
-m a 0 10
-m a 9 10
-torp 2 9 5
-torp 1 8 9
-torp 2 8 9
-
-m a 1 7 9 1
-
-sh down
+# seed 1691779887
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test behavior of Tholian
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 14:51:27 2023
+#
+srscan
+m a 1 10
+# Observe that the Tolian doesn't spin a web..
+srscan
+m a 6 10
+# ... until it can be done without hitting the E
+srscan
+# Move out of quadrant and then back
+m a 4 5 1 6
+m a 1 1
+m a 4 4 1 10
+# Look for the Tholian; the web should be gone.
+srscan
 quit
+n
index 392050be3bab24c90ea305fd56a5333513910835..70d002763c05e70c7c5fbe621e683cb2087c9950 100644 (file)
+# seed 1691834337
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test game timeout condition
+# recorded by esr@snark.thyrsus.com on Sat Aug 12 05:58:57 2023
+#
 
 
 -SUPER- STAR TREK
 
 
 
-Stardate 3250.
+It is stardate 2728. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 5 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
 
-20 Klingons.
-An unknown number of Romulans.
-And one (GULP) Super-Commander.
-7 stardates.
-3 starbases in 3 - 8  1 - 4  1 - 5  
+You will have 5 supporting starbases.
+Starbase locations-  b5  c4  h2  d7  g1  
 
-The Enterprise is currently in Quadrant 1 - 5 Sector 4 - 9
+The Enterprise is currently in Quadrant a8 Sector c1
 
 Good Luck!
-  YOU'LL NEED IT.
-COMMAND> # SST2K version 2.5
-# Test game end due to running out of time
-# recorded by esr@snark on Thu Apr 25 10:58:03 2019
-
-COMMAND> sh up
-Shields raised.
-COMMAND> m a 1 6 4 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 1 - 6.
-
-Enemy attack reduces shield strength to 88%,   torpedoes left 10
-
-Enemy attack reduces shield strength to 81%,   torpedoes left 10
-COMMAND> torp 2 1 6 6 4
-
-Track for torpedo number 1-  3 - 2   3 - 3   2 - 4   
-1 - 5   1 - 6   
-***Klingon at Sector 1 - 6 destroyed.
-
-Track for torpedo number 2-  5 - 2   5 - 3   6 - 4   
-***Klingon at Sector 6 - 4 destroyed.
-COMMAND> 
-COMMAND> m a 1 7 4 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 1 - 7.
-
-[ANNOUNCEMENT ARRIVING...]
-Lt. Uhura-  "Captain, Starfleet Intelligence reports
-   the Super-commander is in Quadrant 2 - 8.
-COMMAND> 
-COMMAND> m a 9 8
-
-COMMAND> 
-COMMAND> m a 2 8 1 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 2 - 8.
-
-196 unit hit from Klingon at 1 - 4
-
-
-Energy left 4093    shields up 54%,   torpedoes left 8
-
-350 unit hit from Klingon at 1 - 4
-
-***CRITICAL HIT--Phasers damaged.
-
-Energy left 3743    shields up 41%,   torpedoes left 8
-COMMAND> 
-COMMAND> torp 2 1 4
-
-Track for torpedo number 1-  1 - 2   1 - 3   1 - 4   
-***Super-commander at Sector 1 - 4 damaged-- displaced by blast to Sector 10 - 2 
-
-Track for torpedo number 2-  1 - 2   1 - 3   1 - 4   
-1 - 5   1 - 6   1 - 7   1 - 8   
-Star at Sector 1 - 8 novas.
-
-33 unit hit from Klingon at 10 - 2
-
-
-Energy left 3620    shields up 40%,   torpedoes left 6
-COMMAND> torp 2 10 2
-
-Track for torpedo number 1-  2 - 1   3 - 1   4 - 1   
-5 - 1   6 - 1   7 - 2   8 - 2   9 - 2   
-10 - 2   
-***Super-commander at Sector 10 - 2 destroyed.
-
-Track for torpedo number 2-  2 - 1   3 - 1   4 - 1   
-5 - 2   6 - 2   7 - 2   8 - 2   9 - 2   
-10 - 2   
-Torpedo missed.
-COMMAND> 
-COMMAND> 
-COMMAND> m a 3 8 1 1
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 3 - 8.
-COMMAND> m a 3 1
-
-COMMAND> d
-Docked.
-COMMAND> 
 COMMAND> rest
-How long? 1
-4 stardates left.
-COMMAND> 
-COMMAND> probe
-2 probes left
-Are you sure you want to fire a probe? y
-Arm NOVAMAX warhead? n
-Manual or automatic- a
-Target quadrant or quadrant&sector- 3 1
-
-Ensign Chekov-  "The deep space probe is launched, Captain."
-COMMAND> rest 0.5
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 7."
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 6."
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 5."
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 4."
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 3."
-3 stardates left.
-COMMAND> 
-COMMAND> sh down
-Shields lowered.
-COMMAND> m a 4 2
-
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 2."
-COMMAND> 
-COMMAND> m a 4 7 1 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 4 - 7.
-
-Lt. Uhura-  "The deep space probe is now in Quadrant 3 - 1."
+How long? 16
+Are you sure? y
 
 [ANNOUNCEMENT ARRIVING...]
 
-Lt. Uhura-  "The deep space probe has left the galaxy."
-COMMAND> 
-COMMAND> m a 1 7
-
-COMMAND> m a 7 1
-
-COMMAND> 
-COMMAND> sh up
-Shields raised.
-COMMAND> m a 5 6 1 10
-
-Ensign Chekov- "Course laid in, Captain."
-
-Entering Quadrant 5 - 6.
-
-Enemy attack reduces shield strength to 96%,   torpedoes left 10
-
-Enemy attack reduces shield strength to 90%,   torpedoes left 10
-COMMAND> p a
-
-Weapons Officer Sulu-  "High-speed shield control enabled, sir."
-Phasers locked on target. Energy available: 4394.68
-945 units required. Units to fire= 945
-
-Shields lowered.
-
-530 unit hit on Commander at Sector 10 - 2
-***Commander at Sector 10 - 2 destroyed.
-
-Shields raised.
-COMMAND> 
-COMMAND> m a 1 4 10 10
-
-Ensign Chekov- "Course laid in, Captain."
+Message from Starfleet Command       Stardate 2729.61
+     Supernova in Quadrant d8; caution advised.
 
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 1 - 4, Sector 2 - 8
-
-36 unit hit from Klingon at 8 - 8
-
+Enterprise is pulled to Quadrant b1, Sector j9
+(Remainder of rest/repair period cancelled.)
+Shields raised.
 
-Energy left 2684    shields up 79%,   torpedoes left 10
-COMMAND> torp 2 8 8
+Enemy attack reduces shield strength to 90%,   torpedoes left 10
 
-Track for torpedo number 1-  3 - 8   4 - 8   5 - 8   
-6 - 8   7 - 8   8 - 8   
-***Commander at Sector 8 - 8 damaged-- displaced by blast to Sector 3 - 7 
 
-Track for torpedo number 2-  3 - 8   4 - 8   5 - 8   
-6 - 8   7 - 8   8 - 8   9 - 8   10 - 8   
-Torpedo missed.
 
-59 unit hit from Klingon at 3 - 7
+It is stardate 2745.0.
 
+Your time has run out and the Federation has been
+conquered.  Your starship is now Klingon property,
+and you are put on trial as a war criminal.  On the
+basis of your record, you are acquitted.
 
-Energy left 2624    shields up 72%,   torpedoes left 8
-COMMAND> torp 1 3 7
+LIVE LONG AND PROSPER.
+[PRESS ENTER TO CONTINUE]
 
-Torpedo track- 3 - 7   
-***Commander at Sector 3 - 7 destroyed.
-COMMAND> 
-COMMAND> m a 3 6
 
-COMMAND> d
-Docked.
-COMMAND> 
-COMMAND> rep
-You were playing a short good game.
-Your secret password is "crn"
-5 of 20 Klingons have been killed, including 2 Commanders.
-The Super Commander has been destroyed.
-There are 3 bases.
-No Starbase is currently under attack.
-You have 1 deep space probe.
 
-COMMAND> 
-COMMAND> 
-COMMAND> sh down
-Shields lowered.
-COMMAND> m a 1 3 1 1
 
-Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 1 - 3.
-COMMAND> 
-COMMAND> m a 1 2 1 1
 
-Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 1 - 2.
-COMMAND> 
-COMMAND> m a 10 1
 
-COMMAND> 
-COMMAND> m a 3 2 1 1
 
-Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 3 - 2.
 
-[ANNOUNCEMENT ARRIVING...]
 
-Message from Starfleet Command       Stardate 3256.95
-     Supernova in Quadrant 5 - 1; caution advised.
-COMMAND> 
-COMMAND> 
-COMMAND> m a 10 1
 
 
-Enterprise blocked by object at 3 - 1;
-Emergency stop required 125 units of energy.
-Collision detected
-COMMAND> 
-COMMAND> m a 3 2
 
-COMMAND> m a 10 1
 
 
-First Officer Spock- "Captain, I compute that such
-  a trip would require approximately 230 percent of our
-  remaining time.  Are you sure this is wise?" n
-COMMAND> m a 10 1
 
 
-First Officer Spock- "Captain, I compute that such
-  a trip would require approximately 230 percent of our
-  remaining time.  Are you sure this is wise?" 
-Please answer with "y" or "n": y
 
 
 
-It is stardate 3258.1.
 
-Your time has run out and the Federation has been
-conquered.  Your starship is now Klingon property,
-and you are put on trial as a war criminal.  On the
-basis of your record, you are acquitted.
 
-LIVE LONG AND PROSPER.
 
 
 Your score --
-     2 ordinary Klingons destroyed           20
-     2 Klingon commanders destroyed         100
-     1 Super-Commander destroyed            200
-  0.63 Klingons per stardate                316
-     1 stars destroyed by your action        -5
+  0.00 Klingons per stardate                  0
 
-TOTAL SCORE                                 631
+TOTAL SCORE                                   0
 
 May the Great Bird of the Galaxy roost upon your home planet.
index 3e4efd7935ea2cc31dfa0079ea0f4a56b050ba7b..7eef4551c1d0d7c71c06d6d0480ef9c71a1060cf 100644 (file)
@@ -1,76 +1,10 @@
-# seed 1556204283
-# options regular short good fancy
-# SST2K version 2.5
-# Test game end due to running out of time
-# recorded by esr@snark on Thu Apr 25 10:58:03 2019
-
-sh up
-m a 1 6 4 1
-torp 2 1 6 6 4
-
-m a 1 7 4 10
-
-m a 9 8
-
-m a 2 8 1 1
-
-torp 2 1 4
-torp 2 10 2
-
-
-m a 3 8 1 1
-m a 3 1
-d
-
+# seed 1691834337
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test game timeout condition
+# recorded by esr@snark.thyrsus.com on Sat Aug 12 05:58:57 2023
+#
 rest
-1
-
-probe
-y
-n
-a
-3 1
-rest 0.5
-
-sh down
-m a 4 2
-
-m a 4 7 1 10
-
-m a 1 7
-m a 7 1
-
-sh up
-m a 5 6 1 10
-p a
-945
-
-m a 1 4 10 10
-torp 2 8 8
-torp 1 3 7
-
-m a 3 6
-d
-
-rep
-
-
-sh down
-m a 1 3 1 1
-
-m a 1 2 1 1
-
-m a 10 1
-
-m a 3 2 1 1
-
-
-m a 10 1
-
-m a 3 2
-m a 10 1
-n
-m a 10 1
-
+16
 y
 n
index 2f03037f70a25206935dc6aa8663d8c939db41a7..85b1949e9d3c8664dd4f0d7d289e75b431887aff 100644 (file)
@@ -1,3 +1,9 @@
+# seed 1556212919
+# arguments regular short good 2023
+# SST2K version 2.5
+# Test loss by energy exhaustion.
+# recorded by esr@snark.thyrsus.com on Thu Apr 25 13:21:59 2019
+#
 
 
 -SUPER- STAR TREK
@@ -10,35 +16,30 @@ Stardate 2736.
 An unknown number of Romulans.
 And one (GULP) Super-Commander.
 7 stardates.
-2 starbases in 1 - 6  3 - 5  
+2 starbases in a6  c5  
 
-The Enterprise is currently in Quadrant 6 - 6 Sector 6 - 9
+The Enterprise is currently in Quadrant f6 Sector f9
 
 Good Luck!
   YOU'LL NEED IT.
-COMMAND> # SST2K version 2.5
-# Test loss by energy exhaustion.
-# recorded by esr@snark on Thu Apr 25 13:21:59 2019
-
 COMMAND> m a 1 4
 
-COMMAND> 
 COMMAND> sh up
 Shields raised.
 COMMAND> m a 5 6 10 5
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 5 - 6.
+Entering Quadrant e6.
 
-35 unit hit from Klingon at 3 - 4
+35 unit hit from Klingon at c4
 
 
 Energy left 4826    shields up 79%,   torpedoes left 10
 
-30 unit hit from Romulan at 5 - 9
+30 unit hit from Romulan at e9
 
-59 unit hit from Klingon at 3 - 4
+59 unit hit from Klingon at c4
 
 
 Energy left 4735    shields up 69%,   torpedoes left 10
@@ -50,10 +51,10 @@ Phasers locked on target. Energy available: 4500.37
 
 Shields lowered.
 
-336 unit hit on Romulan at Sector 5 - 9
-***Romulan at Sector 5 - 9 destroyed.
-319 unit hit on Commander at Sector 3 - 4
-***Mr. Spock-  "Captain, the vessel at Sector 3 - 4
+336 unit hit on Romulan at Sector e9
+***Romulan at Sector e9 destroyed.
+319 unit hit on Commander at Sector c4
+***Mr. Spock-  "Captain, the vessel at Sector c4
    has just lost its firepower."
 477 expended on empty space.
 
@@ -61,12 +62,10 @@ Shields raised.
 
 Enemy attack reduces shield strength to 69%,   torpedoes left 10
 COMMAND> capture
-Klingon captain at 3 - 4 surrenders.
+Klingon captain at c4 surrenders.
 47 Klingons commit suicide rather than be taken captive.
 152 captives taken
-***Klingon at Sector 10 - 5 destroyed.
-COMMAND> 
-COMMAND> 
+***Klingon at Sector j5 destroyed.
 COMMAND> sh down
 Shields lowered.
 COMMAND> m a 10 8
@@ -77,36 +76,35 @@ COMMAND> m a 1 8
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 2737.23
-     Supernova in Quadrant 5 - 4; caution advised.
+     Supernova in Quadrant e4; caution advised.
 COMMAND> sh up
 Shields raised.
-COMMAND> 
 COMMAND> m a 4 6 10 8
 
 Ensign Chekov- "Course laid in, Captain."
 
-Entering Quadrant 4 - 6.
+Entering Quadrant d6.
 
-108 unit hit from Klingon at 9 - 10
+108 unit hit from Klingon at i10
 
-31 unit hit from Klingon at 1 - 8
+31 unit hit from Klingon at a8
 
-25 unit hit from Klingon at 1 - 7
+25 unit hit from Klingon at a7
 
-24 unit hit from Klingon at 1 - 5
+24 unit hit from Klingon at a5
 
-32 unit hit from Klingon at 2 - 2
+32 unit hit from Klingon at b2
 
 
 Energy left 2767    shields up 56%,   torpedoes left 10
 
-104 unit hit from Klingon at 9 - 10
+104 unit hit from Klingon at i10
 
-22 unit hit from Klingon at 1 - 8
+22 unit hit from Klingon at a8
 
-21 unit hit from Klingon at 1 - 7
+21 unit hit from Klingon at a7
 
-32 unit hit from Klingon at 1 - 5
+32 unit hit from Klingon at a5
 [CONTINUE?]
 
 
@@ -133,32 +131,32 @@ Energy left 2767    shields up 56%,   torpedoes left 10
 
 
 
-18 unit hit from Klingon at 2 - 2
+18 unit hit from Klingon at b2
 
 
 Energy left 2568    shields up 48%,   torpedoes left 10
 COMMAND> torp 3 9 10 1 8 1 7
 
-Track for torpedo number 1-  9 - 9   9 - 10   
-***Klingon at Sector 9 - 10 destroyed.
+Track for torpedo number 1-  i9   i10   
+***Klingon at Sector i10 destroyed.
 
-Track for torpedo number 2-  9 - 8   8 - 8   7 - 8   
-6 - 8   
+Track for torpedo number 2-  i8   h8   g8   
+f8   
 
-***Black hole at Sector 6 - 8 swallows torpedo.
+***Black hole at Sector f8 swallows torpedo.
 
-Track for torpedo number 3-  9 - 8   8 - 8   7 - 8   
-6 - 8   
+Track for torpedo number 3-  i8   h8   g8   
+f8   
 
-***Black hole at Sector 6 - 8 swallows torpedo.
+***Black hole at Sector f8 swallows torpedo.
 
-17 unit hit from Klingon at 1 - 8
+17 unit hit from Klingon at a8
 
-19 unit hit from Klingon at 1 - 7
+19 unit hit from Klingon at a7
 
-25 unit hit from Klingon at 1 - 5
+25 unit hit from Klingon at a5
 
-20 unit hit from Klingon at 2 - 2
+20 unit hit from Klingon at b2
 
 
 Energy left 2460    shields up 46%,   torpedoes left 7
@@ -170,18 +168,18 @@ Phasers locked on target. Energy available: 2260.19
 
 Shields lowered.
 
-103 unit hit on Klingon at Sector 1 - 8
-***Klingon at Sector 1 - 8 destroyed.
-94 unit hit on Klingon at Sector 1 - 7
-***Klingon at Sector 1 - 7 destroyed.
-46 unit hit on Klingon at Sector 1 - 5
+103 unit hit on Klingon at Sector a8
+***Klingon at Sector a8 destroyed.
+94 unit hit on Klingon at Sector a7
+***Klingon at Sector a7 destroyed.
+46 unit hit on Klingon at Sector a5
 425 expended on empty space.
 
 Shields raised.
 
-9 unit hit from Klingon at 1 - 5
+9 unit hit from Klingon at a5
 
-13 unit hit from Klingon at 2 - 2
+13 unit hit from Klingon at b2
 
 
 Energy left 1279    shields up 45%,   torpedoes left 7
@@ -193,14 +191,14 @@ Phasers locked on target. Energy available: 1079.13
 
 Shields lowered.
 
-87 unit hit on Klingon at Sector 1 - 5
-***Klingon at Sector 1 - 5 destroyed.
-30 unit hit on Klingon at Sector 2 - 2
+87 unit hit on Klingon at Sector a5
+***Klingon at Sector a5 destroyed.
+30 unit hit on Klingon at Sector b2
 110 expended on empty space.
 
 Shields raised.
 
-5 unit hit from Klingon at 2 - 2
+5 unit hit from Klingon at b2
 
 
 Energy left 777    shields up 45%,   torpedoes left 7
@@ -212,19 +210,17 @@ Phasers locked on target. Energy available: 577.72
 
 Shields lowered.
 
-25 unit hit on Klingon at Sector 2 - 2
-***Klingon at Sector 2 - 2 destroyed.
+25 unit hit on Klingon at Sector b2
+***Klingon at Sector b2 destroyed.
 
 Shields raised.
-COMMAND> 
 COMMAND> m a 8 1
 
 
 [ANNOUNCEMENT ARRIVING...]
 
 Message from Starfleet Command       Stardate 2737.64
-     Supernova in Quadrant 3 - 6; caution advised.
-COMMAND> 
+     Supernova in Quadrant c6; caution advised.
 COMMAND> m a 3 5 10 10
 
 Ensign Chekov- "Course laid in, Captain."
@@ -232,9 +228,7 @@ Ensign Chekov- "Course laid in, Captain."
 [ANNOUNCEMENT ARRIVING...]
 
 ***Enterprise caught in long range tractor beam--
-Enterprise is pulled to Quadrant 5 - 6, Sector 5 - 1
-COMMAND> 
-COMMAND> 
+Enterprise is pulled to Quadrant e6, Sector e1
 COMMAND> m a 3 5 10 10
 
 Ensign Chekov- "Course laid in, Captain."
@@ -247,7 +241,7 @@ COMMAND> m a 3 5 10 10
 
 Ensign Chekov- "Course laid in, Captain."
 
-Enterprise blocked by object at 2 - 1;
+Enterprise blocked by object at b1;
 Emergency stop required 125 units of energy.
 Collision detected
 
index 4b5935ba5597782728b397e02d1510b73df5a295..fef6d6291c37a873854a15b75bcdb220d19b8260 100644 (file)
@@ -1,23 +1,19 @@
 # seed 1556212919
-# options regular short good fancy
+# arguments regular short good 2023
 # SST2K version 2.5
 # Test loss by energy exhaustion.
-# recorded by esr@snark on Thu Apr 25 13:21:59 2019
-
+# recorded by esr@snark.thyrsus.com on Thu Apr 25 13:21:59 2019
+#
 m a 1 4
-
 sh up
 m a 5 6 10 5
 p a
 1310
 capture
-
-
 sh down
 m a 10 8
 m a 1 8
 sh up
-
 m a 4 6 10 8
 torp 3 9 10 1 8 1 7
 p a
@@ -26,14 +22,9 @@ p a
 296
 p a
 73
-
 m a 8 1
-
 m a 3 5 10 10
-
-
 m a 3 5 10 10
 sh down
 m a 3 5 10 10
-
 n
diff --git a/test/test12.chk b/test/test12.chk
new file mode 100644 (file)
index 0000000..48d6620
--- /dev/null
@@ -0,0 +1,92 @@
+# seed 1691778615
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test dilithium mining
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 14:30:15 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 3135.
+
+37 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+5 starbases in d7  a6  c2  h7  d2  
+
+The Enterprise is currently in Quadrant c7 Sector c9
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> status
+Stardate      3135.8, Time Left 14.00
+Condition     GREEN, 0 DAMAGES
+Position      c7 , c9
+Life Support  ACTIVE
+Warp Factor   5.0
+Energy        5000.00
+Torpedoes     10
+Shields       DOWN, 100% 2500.0 units
+Klingons Left 37
+Sector is uninhabited
+COMMAND> sensors
+Spock-  "Sensor scan for Quadrant c7-
+
+         Planet at Sector f1 is of class O.
+         Readings indicate dilithium crystals present."
+COMMAND> m a 3 10
+
+
+[ANNOUNCEMENT ARRIVING...]
+
+Message from Starfleet Command       Stardate 3135.83
+     Supernova in Quadrant e1; caution advised.
+COMMAND> m a 6 10
+
+COMMAND> m a 6 2
+
+COMMAND> orbit
+
+Helmsman Sulu-  "Entering standard orbit, Sir."
+Sulu-  "Entered orbit at altitude 7351.64 kilometers."
+COMMAND> sh down
+Shields already down.
+COMMAND> crystals
+
+No dilithium crystals available.
+COMMAND> shu down
+
+Mining party assembles in the hangar deck,
+ready to board the shuttle craft "Galileo".
+
+The hangar doors open; the trip begins.
+Trip complete.
+COMMAND> mine
+
+Mining operation complete.
+COMMAND> shu up
+
+You and your mining party board the
+shuttle craft for the trip back to the Enterprise.
+
+The short hop begins . . .
+
+Trip complete.
+COMMAND> status
+Stardate      3137.4, Time Left 11.28
+Condition     GREEN, 0 DAMAGES
+Position      c7 , f2
+Life Support  ACTIVE
+Warp Factor   5.0
+Energy        4850.00 (have crystals)
+Torpedoes     10
+Shields       DOWN, 100% 2500.0 units
+Klingons Left 37
+Sector is uninhabited
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test12.log b/test/test12.log
new file mode 100644 (file)
index 0000000..e811ce5
--- /dev/null
@@ -0,0 +1,20 @@
+# seed 1691778615
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test dilithium mining
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 14:30:15 2023
+#
+status
+sensors
+m a 3 10
+m a 6 10
+m a 6 2
+orbit
+sh down
+crystals
+shu down
+mine
+shu up
+status
+quit
+n
diff --git a/test/test13.chk b/test/test13.chk
new file mode 100644 (file)
index 0000000..98d5ca6
--- /dev/null
@@ -0,0 +1,295 @@
+# seed 1556292107
+# arguments regular short good 2023
+# SST2K version 2.5
+# Test multiple critical hits ending in defeat by Supercommander
+# recorded by esr@snark.thyrsus.com on Fri Apr 26 11:21:47 2019
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 2535.
+
+14 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+7 stardates.
+3 starbases in e1  f3  c5  
+
+The Enterprise is currently in Quadrant b2 Sector g3
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> torp 3 7 4 8 4 9 2
+
+Track for torpedo number 1-  g4   
+***Klingon at Sector g4 destroyed.
+
+Track for torpedo number 2-  h4   
+***Klingon at Sector h4 destroyed.
+
+Track for torpedo number 3-  h3   i2   
+***Klingon at Sector i2 destroyed.
+
+38 unit hit from Klingon at d9
+
+
+Energy left 4961    shields up 76%,   torpedoes left 7
+COMMAND> torp 3 6 6 8 10 10 8
+
+Track for torpedo number 1-  g4   f5   f6   
+***Klingon at Sector f6 destroyed.
+
+Track for torpedo number 2-  g4   g5   h6   
+h7   h8   h9   h10   
+***Klingon at Sector h10 destroyed.
+
+Track for torpedo number 3-  h4   h5   i6   
+i7   j8   
+***Klingon at Sector j8 destroyed.
+
+70 unit hit from Klingon at d9
+
+
+Energy left 4890    shields up 69%,   torpedoes left 4
+COMMAND> p a
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Phasers locked on target. Energy available: 4690.82
+764 units required. Units to fire= 754
+
+Shields lowered.
+
+442 unit hit on Commander at Sector d9
+***Commander at Sector d9 destroyed.
+
+Shields raised.
+COMMAND> sh down
+Shields lowered.
+COMMAND> m a 7 7
+
+COMMAND> m a 1 7
+
+COMMAND> sh up
+Shields raised.
+COMMAND> m a 1 2 10 7
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant a2.
+
+157 unit hit from Klingon at g4
+
+
+Energy left 3604    shields up 58%,   torpedoes left 4
+
+185 unit hit from Klingon at g4
+
+
+Energy left 3419    shields up 49%,   torpedoes left 4
+COMMAND> torp 1 7 4
+
+Torpedo track- i6   h5   g4   
+***Commander at Sector g4 destroyed.
+COMMAND> rep
+You were playing a short good game.
+Your secret password is "fgy"
+8 of 14 Klingons have been killed, including 2 Commanders.
+The Super Commander has not been destroyed.
+There are 3 bases.
+No Starbase is currently under attack.
+You have 4 deep space probes.
+
+COMMAND> m a 5 2 1 1
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant e2.
+Uhura- Captain, Medusa in Quadrant f2 reports it is under attack
+by a Klingon invasion fleet.
+COMMAND> sh down 
+Shields lowered.
+COMMAND> m a 10 5
+
+
+[ANNOUNCEMENT ARRIVING...]
+
+Message from Starfleet Command       Stardate 2537.73
+     Supernova in Quadrant d3; caution advised.
+
+[ANNOUNCEMENT ARRIVING...]
+Lt. Uhura-  "Captain, Starfleet Intelligence reports
+   a planet in Quadrant g6 has been destroyed
+   by the Super-commander."
+COMMAND> sh up
+Shields raised.
+COMMAND> m a 6 2 1 5
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant f2.
+
+333 unit hit from Klingon at c3
+
+***CRITICAL HIT--Cloaking Device damaged.
+
+Energy left 2098    shields up 39%,   torpedoes left 3
+
+321 unit hit from Klingon at c3
+
+***CRITICAL HIT--Phasers damaged.
+
+Energy left 1776    shields up 32%,   torpedoes left 3
+
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant g6, Sector c10
+
+670 unit hit from Klingon at c7
+
+***CRITICAL HIT--Warp Engines and Photon Tubes damaged.
+[CONTINUE?]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Energy left 1081    shields up 22%,   torpedoes left 3
+
+Mc Coy-  "Sickbay to bridge.  We suffered 8 casualties
+   in that last attack."
+COMMAND> torp 1 3 7
+Photon tubes damaged.
+COMMAND> p a
+
+Phaser control damaged.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ..2  ..4  ..8  ...  ...  ...  ...  ...   |
+b | ..1  ..6  ..2  ...  ...  ...  ...  ...   |
+c | ..7  ..4  ..6  ...  .1.  ...  ...  ...   |
+d | ..6  ..9  ***  ...  ...  ...  ...  ...   |
+e | .14  ..8  ..7  ...  ...  ...  ...  ...   |
+f | ..2  106  312  ...  ..6  ..1  ..2  ...   |
+g | ..8  ..4  ..1  ...  ..4 <101> ..7  ...   |
+h | ...  ...  ...  ...  ..3  ..9  ..9  ...   |
+
+COMMAND> m a 1 1
+
+Engineer Scott- "Sorry, Captain. Until this damage
+  is repaired, I can only give you warp 4."
+COMMAND> warp 4
+Helmsman Sulu- "Warp factor 4, Captain."
+COMMAND> m a 6 6 10 10
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant f6.
+
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant g6, Sector j5
+
+252 unit hit from Klingon at b5
+
+***CRITICAL HIT--Shields damaged.
+***Shields knocked down.
+
+Energy left 790    shields damaged, 20%,   torpedoes left 3
+
+Mc Coy-  "Sickbay to bridge.  We suffered 2 casualties
+   in that last attack."
+COMMAND> p a
+
+Phaser control damaged.
+COMMAND> torp
+Photon tubes damaged.
+COMMAND> m a 8 6 1 1
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant h6.
+
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant g6, Sector e7
+(Shields not currently useable.)
+
+805 unit hit from Klingon at j7
+
+***CRITICAL HIT--Shuttle Craft and L. R. Sensors damaged.
+
+
+
+It is stardate 2538.5.
+
+The Enterprise has been destroyed in battle.
+
+Dulce et decorum est pro patria mori.
+As a result of your actions, a treaty with the Klingon
+Empire has been signed. The terms of the treaty are
+highly unfavorable to the Federation.
+[CONTINUE?]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Your score --
+     6 ordinary Klingons destroyed           60
+     2 Klingon commanders destroyed         100
+  3.10 Klingons per stardate               1549
+    10 casualties incurred                  -10
+     1 ship(s) lost or destroyed           -100
+Penalty for getting yourself killed        -200
+
+TOTAL SCORE                                1396
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test13.log b/test/test13.log
new file mode 100644 (file)
index 0000000..256d511
--- /dev/null
@@ -0,0 +1,32 @@
+# seed 1556292107
+# arguments regular short good 2023
+# SST2K version 2.5
+# Test multiple critical hits ending in defeat by Supercommander
+# recorded by esr@snark.thyrsus.com on Fri Apr 26 11:21:47 2019
+#
+torp 3 7 4 8 4 9 2
+torp 3 6 6 8 10 10 8
+p a
+754
+sh down
+m a 7 7
+m a 1 7
+sh up
+m a 1 2 10 7
+torp 1 7 4
+rep
+m a 5 2 1 1
+sh down 
+m a 10 5
+sh up
+m a 6 2 1 5
+torp 1 3 7
+p a
+chart
+m a 1 1
+warp 4
+m a 6 6 10 10
+p a
+torp
+m a 8 6 1 1
+n
diff --git a/test/test14.chk b/test/test14.chk
new file mode 100644 (file)
index 0000000..50544e3
--- /dev/null
@@ -0,0 +1,80 @@
+# seed 1691765367
+# arguments
+# SST2K version 2.7
+# Test death by black hole
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 10:49:27 2023
+#
+
+
+-SUPER- STAR TREK
+
+Would you like a regular, tournament, or saved game? r
+Would you like a Short, Medium, or Long game? s
+Are you a Novice, Fair, Good, Expert, or Emeritus player? n
+Wayback setting (press enter for current year): 2023
+
+
+It is stardate 3221. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 4 battle cruisers.
+You have an initial allotment of 7 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 2 supporting starbases.
+Starbase locations-  a4  d4  
+
+The Enterprise is currently in Quadrant d6 Sector d10
+
+Good Luck!
+COMMAND> lrscan
+Long-range scan
+    8   7   6 
+    4   7   7 
+    3 107   4 
+COMMAND> srscan
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   . . . . . * . . . . 
+b   . . .   . . . . . * 
+c   . . . * . . . * . * 
+d   . . .   . . . . . E 
+e   . . . . . . . . . . 
+f   . . . . . . . . . . 
+g   . @ . * . . . . . . 
+h   . . . . . . . . . . 
+i   . . . . . . . . . . 
+j   . . . * . . . . . . 
+COMMAND> move
+Manual or automatic- a
+Destination sector or quadrant&sector- 4 5 1 1
+
+Ensign Chekov- "Course laid in, Captain."
+
+Enterprise blocked by object at c4;
+Emergency stop required 125 units of energy.
+Collision detected
+COMMAND> m a 1 1 4 5
+
+Ensign Chekov- "Course laid in, Captain."
+
+***RED ALERT!  RED ALERT!
+***Enterprise pulled into black hole at Sector b4
+
+
+It is stardate 3222.3.
+
+Your ship is drawn to the center of the black hole.
+You are crushed into extremely dense matter.
+The Federation will be destroyed.
+
+
+Your score --
+  0.00 Klingons per stardate                  0
+     1 ship(s) lost or destroyed           -100
+Penalty for getting yourself killed        -200
+
+TOTAL SCORE                                -299
+Collision detected
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test14.log b/test/test14.log
new file mode 100644 (file)
index 0000000..e2cdd71
--- /dev/null
@@ -0,0 +1,17 @@
+# seed 1691765367
+# arguments 
+# SST2K version 2.7
+# Test death by black hole
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 10:49:27 2023
+#
+r
+s
+n
+2023
+lrscan
+srscan
+move
+a
+4 5 1 1
+m a 1 1 4 5
+n
diff --git a/test/test15.chk b/test/test15.chk
new file mode 100644 (file)
index 0000000..d12b3b6
--- /dev/null
@@ -0,0 +1,56 @@
+# seed 1691766356
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test encounter with Romulan and multiline torpedo firing
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 11:05:56 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 3231.
+
+31 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+4 starbases in f5  f4  f2  c8  
+
+The Enterprise is currently in Quadrant h2 Sector i8
+
+Good Luck!
+  YOU'LL NEED IT.
+
+LT. Uhura- "Captain, an urgent message.
+  I'll put it on audio."  CLICK
+
+INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE.
+LEAVE AT ONCE, OR YOU WILL BE DESTROYED!
+COMMAND> m a 5 9
+
+
+Enemy attack reduces shield strength to 94%,   torpedoes left 10
+COMMAND> m a 4 3
+
+
+Enemy attack reduces shield strength to 88%,   torpedoes left 10
+COMMAND> torp
+10 torpedoes left.
+Number of torpedoes to fire- 3
+Target sector for torpedo number 1- 1 6
+Target sector for torpedo number 2- 1 6
+Target sector for torpedo number 3- 1 6
+
+Track for torpedo number 1-  c4   b5   a6   
+***Romulan at Sector a6 destroyed.
+
+Track for torpedo number 2-  c4   b5   a6   
+Torpedo missed.
+
+Track for torpedo number 3-  c4   b5   a6   
+Torpedo missed.
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test15.log b/test/test15.log
new file mode 100644 (file)
index 0000000..d533253
--- /dev/null
@@ -0,0 +1,15 @@
+# seed 1691766356
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test encounter with Romulan and multiline torpedo firing
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 11:05:56 2023
+#
+m a 5 9
+m a 4 3
+torp
+3
+1 6
+1 6
+1 6
+quit
+n
diff --git a/test/test16.chk b/test/test16.chk
new file mode 100644 (file)
index 0000000..1880db7
--- /dev/null
@@ -0,0 +1,30 @@
+# seed 1691769251
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test malformed torpedo command
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 11:54:11 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 2839.
+
+41 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+5 starbases in a6  c2  a8  g8  d4  
+
+The Enterprise is currently in Quadrant h3 Sector d5
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> torp 1 3
+
+Beg your pardon, Captain?
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test16.log b/test/test16.log
new file mode 100644 (file)
index 0000000..4333957
--- /dev/null
@@ -0,0 +1,9 @@
+# seed 1691769251
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test malformed torpedo command
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 11:54:11 2023
+#
+torp 1 3
+quit
+n
diff --git a/test/test17.chk b/test/test17.chk
new file mode 100644 (file)
index 0000000..63d0d54
--- /dev/null
@@ -0,0 +1,87 @@
+# seed 1691774489
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test commander destruction and supernova alert
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 13:31:26 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 3997.
+
+29 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+5 starbases in c5  c2  f6  b1  g8  
+
+The Enterprise is currently in Quadrant f3 Sector h10
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> m 6 4
+(Manual movement assumed.)
+
+Helmsman Sulu- "Aye, Sir."
+
+YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER
+AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,
+YOU WILL BE DESTROYED.
+
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant f2, Sector a5
+Shields raised.
+
+Enemy attack reduces shield strength to 89%,   torpedoes left 10
+COMMAND> m a 1 9
+
+
+28 unit hit from Klingon at g9
+
+
+Energy left 4755    shields up 81%,   torpedoes left 10
+COMMAND> srscan
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a     * . . . . . . E . 
+b   . . . . . . . . . . 
+c   . . . . . . . . . . 
+d   * . . . . * . . . . 
+e   . . . . . . . . . . 
+f   . . . . . . . . . . 
+g   . . . . . . . . C . 
+h   . . . . . . . . . . 
+i   . . . . P . . . * . 
+j   .   . . . . . * * . 
+COMMAND> 
+COMMAND> torp 3 7 9 7 9 7 9
+
+Track for torpedo number 1-  b9   c9   d9   
+e9   f9   g9   
+***Commander at Sector g9 damaged-- displaced by blast to Sector h8 
+
+Track for torpedo number 2-  b9   c9   d9   
+e9   f9   g9   h9   i9   
+Star at Sector i9 novas.
+***Commander at Sector h8 destroyed.
+
+***RED ALERT!  RED ALERT!
+***Incipient supernova detected at Sector d1
+
+***Emergency automatic override attempts to hurl Enterprise
+safely out of quadrant.
+Warp factor set to 7
+
+YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER
+AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,
+YOU WILL BE DESTROYED.
+
+Entering Quadrant h3.
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test17.log b/test/test17.log
new file mode 100644 (file)
index 0000000..cab0e91
--- /dev/null
@@ -0,0 +1,12 @@
+# seed 1691774489
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test commander destruction and supernova alert
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 13:31:26 2023
+#
+m 6 4
+m a 1 9
+srscan
+
+torp 3 7 9 7 9 7 9
+quit
diff --git a/test/test18.chk b/test/test18.chk
new file mode 100644 (file)
index 0000000..cec7498
--- /dev/null
@@ -0,0 +1,91 @@
+# seed 1691786582
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test behavior when emy is buffered into black hole
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 16:43:02 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 3104.
+
+25 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+3 starbases in e5  d3  h5  
+
+The Enterprise is currently in Quadrant a6 Sector i5
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ...  ..4 <..7> ..5  ...   |
+b | ...  ...  ...  ...  ..4  ..3  ..5  ...   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  .1.  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  .1.  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  .1.  ...  ...  ...   |
+
+COMMAND> probe
+2 probes left
+Are you sure you want to fire a probe? y
+Arm NOVAMAX warhead? n
+Manual or automatic- a
+Target quadrant or quadrant&sector- 1 1
+
+Ensign Chekov-  "The deep space probe is launched, Captain."
+COMMAND> 
+COMMAND> m a 2 8 5 1
+
+Ensign Chekov- "Course laid in, Captain."
+
+Enterprise blocked by object at j9;
+Emergency stop required 153 units of energy.
+Collision detected
+
+Lt. Uhura-  "The deep space probe is now in Quadrant a5."
+
+Lt. Uhura-  "The deep space probe is now in Quadrant a4."
+
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant a8, Sector f2
+Shields raised.
+
+Enemy attack reduces shield strength to 91%,   torpedoes left 10
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | ...  ...  ...  ..5  ..4  ..7  ..5 <104>  |
+b | ...  ...  ...  ...  ..4  ..3  ..5  101   |
+c | ...  ...  ...  ...  ...  ...  ...  ...   |
+d | ...  ...  .1.  ...  ...  ...  ...  ...   |
+e | ...  ...  ...  ...  .1.  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  ...  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  .1.  ...  ...  ...   |
+
+COMMAND> sh up
+Shields already up.
+COMMAND> torp 2 5 10 5 10
+
+Track for torpedo number 1-  f3   f4   f5   
+f6   e7   e8   e9   e10   
+***Commander at Sector e10 buffeted into black hole.
+***Commander at Sector d1 destroyed.
+
+Track for torpedo number 2-  f3   f4   f5   
+e6   e7   e8   e9   e10   
+Torpedo missed.
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test18.log b/test/test18.log
new file mode 100644 (file)
index 0000000..67c2925
--- /dev/null
@@ -0,0 +1,19 @@
+# seed 1691786582
+# arguments regular medium good 2023
+# SST2K version 2.7
+# Test behavior when emy is buffered into black hole
+# recorded by esr@snark.thyrsus.com on Fri Aug 11 16:43:02 2023
+#
+chart
+probe
+y
+n
+a
+1 1
+
+m a 2 8 5 1
+chart
+sh up
+torp 2 5 10 5 10
+quit
+n
diff --git a/test/test19.chk b/test/test19.chk
new file mode 100644 (file)
index 0000000..ca64487
--- /dev/null
@@ -0,0 +1,132 @@
+# seed 1692088612
+# arguments regular medium novice 1973
+# SST2K version 2.7
+# Test 1973 interface and old-fashioned coordinates
+# recorded by esr@snark.thyrsus.com on Tue Aug 15 04:36:52 2023
+#
+
+
+-SUPER- STAR TREK
+
+Please type in a secret password- foo
+
+
+It is stardate 4349. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 10 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 4 supporting starbases.
+Starbase locations-  8 - 5  4 - 4  5 - 1  2 - 2  
+
+The Enterprise is currently in Quadrant 3 - 4 Sector 2 - 5
+
+Good Luck!
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+1 | ...  ...  ...  ...  ...  ...  ...  ...   |
+2 | ...  .1.    8    6    8  ...  ...  ...   |
+3 | ...  ...    8    7    2  ...  ...  ...   |
+4 | ...  ...    7   13    2  ...  ...  ...   |
+5 | .1.  ...  ...  ...  ...  ...  ...  ...   |
+6 | ...  ...  ...  ...  ...  ...  ...  ...   |
+7 | ...  ...  ...  ...  ...  ...  ...  ...   |
+8 | ...  ...  ...  ...  .1.  ...  ...  ...   |
+
+COMMAND> m 3 7 1 5
+(Manual movement assumed.)
+
+Helmsman Sulu- "Aye, Sir."
+
+Enterprise blocked by object at 1 - 5;
+Emergency stop required 125 units of energy.
+Collision detected
+COMMAND> m a 2 10
+
+COMMAND> m 3 7 2 1
+(Manual movement assumed.)
+
+Helmsman Sulu- "Aye, Sir."
+
+YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER
+AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,
+YOU WILL BE DESTROYED.
+
+Entering Quadrant 5 - 7.
+COMMAND> 
+COMMAND> m 2 7 5 5
+(Manual movement assumed.)
+
+Helmsman Sulu- "Aye, Sir."
+
+YOU HAVE ATTEMPTED TO CROSS THE NEGATIVE ENERGY BARRIER
+AT THE EDGE OF THE GALAXY.  THE THIRD TIME YOU TRY THIS,
+YOU WILL BE DESTROYED.
+
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant 2 - 7, Sector 2 - 5
+Shields raised.
+
+30 unit hit on the Enterprise from Klingon at Sector 5 - 1
+
+
+Energy left 2538    shields up 80%,   torpedoes left 10
+COMMAND> phasers
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Manual or automatic? a
+Phasers locked on target. Energy available: 2338.09
+887 units required. Units to fire= 887
+
+Shields lowered.
+
+136 unit hit on Klingon at Sector 3 - 4
+***Klingon at Sector 3 - 4 destroyed.
+364 unit hit on Commander at Sector 5 - 1
+***Mr. Spock-  "Captain, the vessel at Sector 5 - 1
+   has just lost its firepower."
+149 expended on empty space.
+
+Shields raised.
+
+Enemy attack reduces shield strength to 80%,   torpedoes left 10
+COMMAND> capture
+
+Beg your pardon, Captain?
+COMMAND> m a 4 2
+
+
+Enemy attack reduces shield strength to 80%,   torpedoes left 10
+COMMAND> phasers
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Manual or automatic? a
+Phasers locked on target. Energy available: 1160.95
+53 units required. Units to fire= 53
+
+Shields lowered.
+
+48 unit hit on Commander at Sector 5 - 1
+***Commander at Sector 5 - 1 destroyed.
+
+Shields raised.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+1 | ...  ...  ...  ...  ...    2    7    9   |
+2 | ...  .1.    8    6    8    2    1    3   |
+3 | ...  ...    8    7    2    4  109    8   |
+4 | ...  ...    7   13    2    8    3    8   |
+5 | .1.  ...  ...  ...  ...    1    2    7   |
+6 | ...  ...  ...  ...  ...    2    8    4   |
+7 | ...  ...  ...  ...  ...  ...  ...  ...   |
+8 | ...  ...  ...  ...  .1.  ...  ...  ...   |
+
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test19.log b/test/test19.log
new file mode 100644 (file)
index 0000000..272e39d
--- /dev/null
@@ -0,0 +1,23 @@
+# seed 1692088612
+# arguments regular medium novice 1973
+# SST2K version 2.7
+# Test 1973 interface and old-fashioned coordinates
+# recorded by esr@snark.thyrsus.com on Tue Aug 15 04:36:52 2023
+#
+foo
+chart
+m 3 7 1 5
+m a 2 10
+m 3 7 2 1
+
+m 2 7 5 5
+phasers
+a
+887
+capture
+m a 4 2
+phasers
+a
+53
+chart
+quit
diff --git a/test/test20.chk b/test/test20.chk
new file mode 100644 (file)
index 0000000..257f656
--- /dev/null
@@ -0,0 +1,122 @@
+# seed 1692093194
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test self-destruct
+# recorded by esr@snark.thyrsus.com on Tue Aug 15 05:53:14 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 2982. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 10 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 4 supporting starbases.
+Starbase locations-  e2  b5  g3  b3  
+
+The Enterprise is currently in Quadrant h8 Sector c8
+
+Good Luck!
+COMMAND> destruct
+---WORKING---
+SELF-DESTRUCT-SEQUENCE-ACTIVATED
+   10
+       9
+          8
+             7
+                6
+
+ENTER-CORRECT-PASSWORD-TO-CONTINUE-
+
+SELF-DESTRUCT-SEQUENCE-OTHERWISE-
+
+SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED
+
+
+PASSWORD-REJECTED;
+CONTINUITY-EFFECTED
+
+COMMAND> rep
+You were playing a medium novice game.
+Your secret password is "srl"
+0 of 10 Klingons have been killed.
+There are 4 bases.
+No Starbase is currently under attack.
+You have 4 deep space probes.
+
+COMMAND> destruct
+---WORKING---
+SELF-DESTRUCT-SEQUENCE-ACTIVATED
+   10
+       9
+          8
+             7
+                6
+
+ENTER-CORRECT-PASSWORD-TO-CONTINUE-
+
+SELF-DESTRUCT-SEQUENCE-OTHERWISE-
+
+SELF-DESTRUCT-SEQUENCE-WILL-BE-ABORTED
+
+srl
+PASSWORD-ACCEPTED
+                   5
+                      4
+                         3
+                            2
+                              1
+******************************************************
+************ Entropy of Enterprise maximized *********
+******************************************************
+
+***Commander at Sector f8 destroyed.
+
+
+
+It is stardate 2982.6.
+
+Your starship is now an expanding cloud of subatomic particles
+The Federation will be destroyed.
+
+
+Your score --
+     1 Klingon commanders destroyed          50
+  0.00 Klingons per stardate                  0
+     1 ship(s) lost or destroyed           -100
+Penalty for getting yourself killed        -200
+[PRESS ENTER TO CONTINUE]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+TOTAL SCORE                                -250
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test20.log b/test/test20.log
new file mode 100644 (file)
index 0000000..2764a2b
--- /dev/null
@@ -0,0 +1,11 @@
+# seed 1692093194
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test self-destruct
+# recorded by esr@snark.thyrsus.com on Tue Aug 15 05:53:14 2023
+#
+destruct
+
+rep
+destruct
+srl
diff --git a/test/test21.chk b/test/test21.chk
new file mode 100644 (file)
index 0000000..7035a56
--- /dev/null
@@ -0,0 +1,61 @@
+# seed 1692093957
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test edge and failure cases in coordinate parsing
+# recorded by esr@snark.thyrsus.com on Tue Aug 15 06:05:57 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 2877. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 9 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 2 supporting starbases.
+Starbase locations-  b1  b5  
+
+The Enterprise is currently in Quadrant b6 Sector c3
+
+Good Luck!
+COMMAND> sr
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   . . . . . . . . . . 
+b   . . . * . . . . . . 
+c   . . E . .   . . . . 
+d   . . . . . . . . . . 
+e   . . . . . . . . . . 
+f   . . . . .   . . . . 
+g   . . . . . . . . . . 
+h   . . . . . . . . . . 
+i   . @ . . . . . . . . 
+j   . . . . . . . . * . 
+COMMAND> m a a 3
+
+Beg your pardon, Captain?
+COMMAND> m a a3
+
+COMMAND> sr
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   . . E . . . . . . . 
+b   . . . * . . . . . . 
+c   . . . . .   . . . . 
+d   . . . . . . . . . . 
+e   . . . . . . . . . . 
+f   . . . . .   . . . . 
+g   . . . . . . . . . . 
+h   . . . . . . . . . . 
+i   . @ . . . . . . . . 
+j   . . . . . . . . * . 
+COMMAND> m a a10
+
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test21.log b/test/test21.log
new file mode 100644 (file)
index 0000000..d19621e
--- /dev/null
@@ -0,0 +1,13 @@
+# seed 1692093957
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test edge and failure cases in coordinate parsing
+# recorded by esr@snark.thyrsus.com on Tue Aug 15 06:05:57 2023
+#
+sr
+m a a 3
+m a a3
+sr
+m a a10
+quit
+n
diff --git a/test/test22.chk b/test/test22.chk
new file mode 100644 (file)
index 0000000..7861ca3
--- /dev/null
@@ -0,0 +1,35 @@
+# seed 1692177511
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test torpedoing uninhabited planet
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:18:31 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 2183. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 9 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 2 supporting starbases.
+Starbase locations-  d2  h1  
+
+The Enterprise is currently in Quadrant e4 Sector c9
+
+Good Luck!
+COMMAND> m a i9
+
+COMMAND> torpedo 1 i5
+
+Torpedo track- i8   i7   i6   
+i5   
+***Planet at Sector i5 destroyed.
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test22.log b/test/test22.log
new file mode 100644 (file)
index 0000000..54d6534
--- /dev/null
@@ -0,0 +1,9 @@
+# seed 1692177511
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test torpedoing uninhabited planet
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:18:31 2023
+#
+m a i9
+torpedo 1 i5
+quit
diff --git a/test/test23.chk b/test/test23.chk
new file mode 100644 (file)
index 0000000..1212f1e
--- /dev/null
@@ -0,0 +1,41 @@
+# seed 1692177676
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test torpedoing inhabited planet and starbase
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:21:16 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 4956. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 7 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 3 supporting starbases.
+Starbase locations-  g2  b2  b3  
+
+The Enterprise is currently in Quadrant b2 Sector e9
+
+Good Luck!
+COMMAND> m a c0
+
+Beg your pardon, Captain?
+COMMAND> m a c9
+
+COMMAND> torpedo 1 c 2
+
+Beg your pardon, Captain?
+COMMAND> torpedo 1 f10
+
+Torpedo track- d9   e10   f10   
+
+***STARBASE DESTROYED..
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test23.log b/test/test23.log
new file mode 100644 (file)
index 0000000..0a5a56a
--- /dev/null
@@ -0,0 +1,11 @@
+# seed 1692177676
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test torpedoing inhabited planet and starbase
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:21:16 2023
+#
+m a c0
+m a c9
+torpedo 1 c 2
+torpedo 1 f10
+quit
diff --git a/test/test24.chk b/test/test24.chk
new file mode 100644 (file)
index 0000000..5a46a38
--- /dev/null
@@ -0,0 +1,35 @@
+# seed 1692177875
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test cloaking device with no enemies present
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:24:35 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 2588. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 6 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 3 supporting starbases.
+Starbase locations-  g4  f3  d7  
+
+The Enterprise is currently in Quadrant h6 Sector a6
+
+Good Luck!
+COMMAND> cloak
+Switch cloaking device on? y
+Spock- "Captain, using the cloaking device is a violation
+  of the Treaty of Algeron. Considering the alternatives,
+  are you sure this is wise? y
+Engineer Scott- "Cloaking device has engaging, Sir..."
+Engineer Scott- "Cloaking device has engaged, Sir."
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test24.log b/test/test24.log
new file mode 100644 (file)
index 0000000..d1a0fb7
--- /dev/null
@@ -0,0 +1,10 @@
+# seed 1692177875
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test cloaking device with no enemies present
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:24:35 2023
+#
+cloak
+y
+y
+quit
diff --git a/test/test25.chk b/test/test25.chk
new file mode 100644 (file)
index 0000000..b3f01c9
--- /dev/null
@@ -0,0 +1,53 @@
+# seed 1692263971
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test death ray (successful)
+# recorded by esr@snark.thyrsus.com on Thu Aug 17 05:19:31 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 4176.
+
+57 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+4 starbases in h5  d5  h8  b7  
+
+The Enterprise is currently in Quadrant g7 Sector e6
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> deathray
+
+Spock-  "Captain, the 'Experimental Death Ray'
+  is highly unpredictible.  Considering the alternatives,
+  are you sure this is wise?" y
+Spock-  "Acknowledged."
+
+WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE
+Crew scrambles in emergency preparation.
+Spock and Scotty ready the death ray and
+prepare to channel all ship's power to the device.
+
+Spock-  "Preparations complete, sir."
+Kirk-  "Engage!"
+
+WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+Sulu- "Captain!  It's working!"
+
+***Klingon at Sector j8 destroyed.
+***Klingon at Sector h2 destroyed.
+***Klingon at Sector b4 destroyed.
+***Klingon at Sector b8 destroyed.
+***Klingon at Sector e9 destroyed.
+Ensign Chekov-  "Congratulations, Captain!"
+Spock-  "Captain, I believe the `Experimental Death Ray'
+   has been rendered nonfunctional."
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test25.log b/test/test25.log
new file mode 100644 (file)
index 0000000..a529d9d
--- /dev/null
@@ -0,0 +1,9 @@
+# seed 1692263971
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test death ray (successful)
+# recorded by esr@snark.thyrsus.com on Thu Aug 17 05:19:31 2023
+#
+deathray
+y
+quit
diff --git a/test/test26.chk b/test/test26.chk
new file mode 100644 (file)
index 0000000..3049136
--- /dev/null
@@ -0,0 +1,30 @@
+# seed 1692178191
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test damage-report command (no damage)
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:29:51 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 4779. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 10 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 2 supporting starbases.
+Starbase locations-  g4  g7  
+
+The Enterprise is currently in Quadrant c1 Sector g6
+
+Good Luck!
+COMMAND> damage
+All devices functional.
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test26.log b/test/test26.log
new file mode 100644 (file)
index 0000000..a6e4435
--- /dev/null
@@ -0,0 +1,8 @@
+# seed 1692178191
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test damage-report command (no damage)
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:29:51 2023
+#
+damage
+quit
diff --git a/test/test27.chk b/test/test27.chk
new file mode 100644 (file)
index 0000000..3db0c83
--- /dev/null
@@ -0,0 +1,51 @@
+# seed 1692178540
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test simple collision and damage treport.
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:35:40 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 3804. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 9 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 3 supporting starbases.
+Starbase locations-  c2  a8  c6  
+
+The Enterprise is currently in Quadrant c7 Sector e7
+
+Good Luck!
+
+LT. Uhura- "Captain, an urgent message.
+  I'll put it on audio."  CLICK
+
+INTRUDER! YOU HAVE VIOLATED THE ROMULAN NEUTRAL ZONE.
+LEAVE AT ONCE, OR YOU WILL BE DESTROYED!
+COMMAND> m a j7
+
+***RED ALERT!  RED ALERT!
+***COLLISION IMMINENT.
+
+
+***Enterprise rams Romulan at Sector j7
+***Romulan at Sector i7 destroyed.
+***Enterprise heavily damaged.
+***Sickbay reports 20 casualties
+***Shields are down.
+
+[ANNOUNCEMENT ARRIVING...]
+DEVICE                             REPAIR TIMES
+                                   IN FLIGHT                DOCKED
+  Transporter                     11.63                    2.90
+Collision detected
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test27.log b/test/test27.log
new file mode 100644 (file)
index 0000000..59526dd
--- /dev/null
@@ -0,0 +1,8 @@
+# seed 1692178540
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test simple collision and damage treport.
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 05:35:40 2023
+#
+m a j7
+quit
diff --git a/test/test28.chk b/test/test28.chk
new file mode 100644 (file)
index 0000000..cff5792
--- /dev/null
@@ -0,0 +1,63 @@
+# seed 1692187822
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test encounter with Space Thingy and torperdoing it
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 08:28:50 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+It is stardate 4827. The Federation is being attacked by
+a deadly Klingon invasion force. As captain of the United
+Starship U.S.S. Enterprise, it is your mission to seek out
+and destroy this invasion force of 10 battle cruisers.
+You have an initial allotment of 14 stardates to complete
+your mission.  As you proceed you may be given more time.
+
+You will have 5 supporting starbases.
+Starbase locations-  f1  g6  e2  a1  a8  
+
+The Enterprise is currently in Quadrant d6 Sector h8
+
+Good Luck!
+COMMAND> m a e8
+
+COMMAND> m a a1
+
+COMMAND> m a c2 j10
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant c2.
+
+Mr. Spock- "Captain, this is most unusual.
+    Please examine your short-range scan."
+COMMAND> sr
+     Short-range scan
+    1 2 3 4 5 6 7 8 9 10
+a   . . . . . . . . . . 
+b   . . . . . . . . . . 
+c   . . . . . . . . . . 
+d   ? . . . . . . . . * 
+e   . . . . . . . .   . 
+f   . . . . . . . . . . 
+g   . . .   . . . . . . 
+h   . . . * . . . . . . 
+i   . . P . . . . . . . 
+j   . . . * . . . . . E 
+COMMAND> torp 1 d1
+
+Torpedo track- i9   i8   h7   
+g6   g5   f4   e3   d2   
+d1   
+
+AAAAIIIIEEEEEEEEAAAAAAAAUUUUUGGGGGHHHHHHHHHHHH!!!
+    HACK!     HACK!    HACK!        *CHOKE!*  
+Mr. Spock-  "Fascinating!"
+***Stranger at Sector d1 destroyed.
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test28.log b/test/test28.log
new file mode 100644 (file)
index 0000000..246ff28
--- /dev/null
@@ -0,0 +1,12 @@
+# seed 1692187822
+# arguments regular medium novice 2023
+# SST2K version 2.7
+# Test encounter with Space Thingy and torperdoing it
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 08:28:50 2023
+#
+m a e8
+m a a1
+m a c2 j10
+sr
+torp 1 d1
+quit
diff --git a/test/test29.chk b/test/test29.chk
new file mode 100644 (file)
index 0000000..a7b9a76
--- /dev/null
@@ -0,0 +1,67 @@
+# seed 1692210781
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test capture - trdsuccessful
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 14:33:01 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 4912.
+
+57 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+4 starbases in d7  c7  a4  d8  
+
+The Enterprise is currently in Quadrant a2 Sector c10
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> phasers
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Manual or automatic? a
+Phasers locked on target. Energy available: 4800.00
+1657 units required. Units to fire= 1657
+
+Shields lowered.
+
+299 unit hit on Klingon at Sector a8
+***Klingon at Sector a8 destroyed.
+330 unit hit on Klingon at Sector a7
+***Klingon at Sector a7 destroyed.
+210 unit hit on Klingon at Sector b5
+***Mr. Spock-  "Captain, the vessel at Sector b5
+   has just lost its firepower."
+661 expended on empty space.
+
+Shields raised.
+
+Enemy attack reduces shield strength to 96%,   torpedoes left 10
+COMMAND> torpedo 1 i8
+
+Torpedo track- d10   e9   f9   
+Star at Sector f9 novas.
+***Star at Sector g10 novas.
+
+Enemy attack reduces shield strength to 92%,   torpedoes left 9
+COMMAND> torpedo 1 i7
+
+Torpedo track- d9   e9   f8   
+g8   h7   i7   
+***Klingon at Sector i7 destroyed.
+
+Enemy attack reduces shield strength to 92%,   torpedoes left 8
+COMMAND> capture
+Klingon captain at b5 surrenders.
+149 Klingons commit suicide rather than be taken captive.
+50 captives taken
+***Klingon at Sector c10 destroyed.
+COMMAND> quit
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test29.log b/test/test29.log
new file mode 100644 (file)
index 0000000..14aabd3
--- /dev/null
@@ -0,0 +1,13 @@
+# seed 1692210781
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test capture - trdsuccessful
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 14:33:01 2023
+#
+phasers
+a
+1657
+torpedo 1 i8
+torpedo 1 i7
+capture
+quit
diff --git a/test/test30.chk b/test/test30.chk
new file mode 100644 (file)
index 0000000..cfebdb7
--- /dev/null
@@ -0,0 +1,345 @@
+# seed 1692212577
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test death ray - failure (kaboom)
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 15:02:57 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 4729.
+
+59 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+3 starbases in a1  h5  g4  
+
+The Enterprise is currently in Quadrant d2 Sector h6
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | .1.  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  ...  ...  ...  ...  ...  ...  ...   |
+c | ..6  ..7  ..9  ...  ...  ...  ...  ...   |
+d | ..4 <..6> 109  ...  ...  ...  ...  ...   |
+e | ..3  ..2  402  ...  ...  ...  ...  ...   |
+f | ...  ...  ...  ...  ...  ...  ...  ...   |
+g | ...  ...  ...  .1.  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  .1.  ...  ...  ...   |
+
+COMMAND> m a d10
+
+COMMAND> sh up
+Shields raised.
+COMMAND> m a d3 d1
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant d3.
+
+Enemy attack reduces shield strength to 89%,   torpedoes left 10
+
+28 unit hit from Klingon at j4
+
+
+Energy left 4850    shields up 81%,   torpedoes left 10
+COMMAND> torp 2 j4
+
+Track for torpedo number 1-  e1   f2   g2   
+h3   i3   j4   
+***Commander at Sector j4 destroyed.
+
+Track for torpedo number 2-  e2   f2   g3   
+h3   i4   j5   
+Torpedo missed.
+
+Enemy attack reduces shield strength to 81%,   torpedoes left 8
+COMMAND> m a j 4
+
+Beg your pardon, Captain?
+COMMAND> m a j4
+
+
+Enemy attack reduces shield strength to 81%,   torpedoes left 8
+COMMAND> m a e3 a4
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant e3.
+
+59 unit hit from Klingon at b3
+
+72 unit hit from Klingon at a7
+
+52 unit hit from Klingon at f2
+
+
+Energy left 4472    shields up 62%,   torpedoes left 8
+
+92 unit hit from Klingon at b3
+
+87 unit hit from Klingon at a7
+
+49 unit hit from Klingon at f2
+
+22 unit hit from Klingon at j4
+
+
+Energy left 4220    shields up 50%,   torpedoes left 8
+COMMAND> phasers a
+
+Weapons Officer Sulu-  "High-speed shield control enabled, sir."
+Phasers locked on target. Energy available: 3995.16
+873 units required. Units to fire= 873
+
+Shields lowered.
+
+132 unit hit on Klingon at Sector b3
+***Klingon at Sector b3 destroyed.
+170 unit hit on Klingon at Sector a7
+***Klingon at Sector a7 destroyed.
+182 unit hit on Klingon at Sector f2
+***Klingon at Sector f2 destroyed.
+331 expended on empty space.
+
+Shields raised.
+
+19 unit hit from Klingon at j4
+
+
+Energy left 3102    shields up 50%,   torpedoes left 8
+COMMAND> torp 1 j4
+
+Torpedo track- b4   c4   d4   
+e4   f4   g4   h4   i4   
+j4   
+***Klingon at Sector j4 destroyed.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | .1.  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  ...  ...  ...  ...  ...  ...  ...   |
+c | ..6  ..7  ..9  ..9  ...  ...  ...  ...   |
+d | ..4  ..6  ..9  ..5  ...  ...  ...  ...   |
+e | ..3  ..2 <..2> ..1  ...  ...  ...  ...   |
+f | ...  ..1  ..1  102  ...  ...  ...  ...   |
+g | ...  ...  ...  .1.  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  .1.  ...  ...  ...   |
+
+COMMAND> sh down
+Shields lowered.
+COMMAND> m a j6
+
+COMMAND> m a f3 a6
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant f3.
+COMMAND> chart
+       STAR CHART FOR THE KNOWN GALAXY
+      1    2    3    4    5    6    7    8
+a | .1.  ...  ...  ...  ...  ...  ...  ...   |
+b | ...  ...  ...  ...  ...  ...  ...  ...   |
+c | ..6  ..7  ..9  ..9  ...  ...  ...  ...   |
+d | ..4  ..6  ..9  ..5  ...  ...  ...  ...   |
+e | ..3  ..2  ..2  ..1  ...  ...  ...  ...   |
+f | ...  ..1 <..1> 102  ...  ...  ...  ...   |
+g | ...  ..6  ..4  .19  ...  ...  ...  ...   |
+h | ...  ...  ...  ...  .1.  ...  ...  ...   |
+
+COMMAND> m a f5
+
+COMMAND> m a f10
+
+COMMAND> sh up
+Shields raised.
+COMMAND> m a f4 f1
+
+Ensign Chekov- "Course laid in, Captain."
+
+Entering Quadrant f4.
+
+251 unit hit from Klingon at a3
+
+***CRITICAL HIT--Computer damaged.
+
+Energy left 2547    shields up 42%,   torpedoes left 7
+
+226 unit hit from Klingon at a3
+
+
+Energy left 2320    shields up 36%,   torpedoes left 7
+COMMAND> m a g 7
+
+Beg your pardon, Captain?
+COMMAND> m a g7
+
+
+113 unit hit from Klingon at a3
+
+
+Energy left 2182    shields up 34%,   torpedoes left 7
+
+[ANNOUNCEMENT ARRIVING...]
+
+***Enterprise caught in long range tractor beam--
+Enterprise is pulled to Quadrant e8, Sector i8
+
+117 unit hit from Klingon at d9
+
+91 unit hit from Klingon at c8
+
+116 unit hit from Klingon at d4
+
+73 unit hit from Klingon at h1
+
+72 unit hit from Klingon at a8
+
+51 unit hit from Klingon at e1
+
+199 unit hit from Klingon at b4
+[CONTINUE?]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+89 unit hit from Klingon at c2
+
+
+Energy left 1239    shields up 23%,   torpedoes left 7
+
+Mc Coy-  "Sickbay to bridge.  We suffered 9 casualties
+   in that last attack."
+COMMAND> deathray
+
+Spock-  "Captain, the 'Experimental Death Ray'
+  is highly unpredictible.  Considering the alternatives,
+  are you sure this is wise?" y
+Spock-  "Acknowledged."
+
+WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE
+Crew scrambles in emergency preparation.
+Spock and Scotty ready the death ray and
+prepare to channel all ship's power to the device.
+
+Spock-  "Preparations complete, sir."
+Kirk-  "Engage!"
+
+WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+Sulu- "Captain!  It's working!"
+***RED ALERT!  RED ALERT!
+***MATTER-ANTIMATTER IMPLOSION IMMINENT!
+
+***RED ALERT!  RED A*L********************************
+******************************************************
+******************   KA-BOOM!!!!   *******************
+******************************************************
+************ Entropy of Enterprise maximized *********
+******************************************************
+
+***Klingon at Sector c2 destroyed.
+***Commander at Sector b4 destroyed.
+***Klingon at Sector e1 destroyed.
+[CONTINUE?]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+***Klingon at Sector a8 destroyed.
+***Klingon at Sector h1 destroyed.
+***Klingon at Sector d4 destroyed.
+***Klingon at Sector c8 destroyed.
+***Klingon at Sector d9 destroyed.
+
+
+
+It is stardate 4731.3.
+
+Your starship is now an expanding cloud of subatomic particles
+The Federation will be destroyed.
+
+
+Your score --
+    11 ordinary Klingons destroyed          110
+     2 Klingon commanders destroyed         100
+  7.96 Klingons per stardate               3979
+     9 casualties incurred                   -9
+     1 ship(s) lost or destroyed           -100
+Penalty for getting yourself killed        -200
+
+TOTAL SCORE                                3880
+
+May the Great Bird of the Galaxy roost upon your home planet.
+[CONTINUE?]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/test30.log b/test/test30.log
new file mode 100644 (file)
index 0000000..7e0dbe0
--- /dev/null
@@ -0,0 +1,30 @@
+# seed 1692212577
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test death ray - failure (kaboom)
+# recorded by esr@snark.thyrsus.com on Wed Aug 16 15:02:57 2023
+#
+chart
+m a d10
+sh up
+m a d3 d1
+torp 2 j4
+m a j 4
+m a j4
+m a e3 a4
+phasers a
+873
+torp 1 j4
+chart
+sh down
+m a j6
+m a f3 a6
+chart
+m a f5
+m a f10
+sh up
+m a f4 f1
+m a g 7
+m a g7
+deathray
+y
diff --git a/test/test31.chk b/test/test31.chk
new file mode 100644 (file)
index 0000000..7c14efe
--- /dev/null
@@ -0,0 +1,92 @@
+# seed 1692263709
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test death ray - fail (mutation)
+# recorded by esr@snark.thyrsus.com on Thu Aug 17 05:15:09 2023
+#
+
+
+-SUPER- STAR TREK
+
+
+
+Stardate 3851.
+
+60 Klingons.
+An unknown number of Romulans.
+And one (GULP) Super-Commander.
+14 stardates.
+6 starbases in f5  a2  h1  e6  g4  b6  
+
+The Enterprise is currently in Quadrant f1 Sector f6
+
+Good Luck!
+  YOU'LL NEED IT.
+COMMAND> deathray
+
+Spock-  "Captain, the 'Experimental Death Ray'
+  is highly unpredictible.  Considering the alternatives,
+  are you sure this is wise?" y
+Spock-  "Acknowledged."
+
+WHOOEE ... WHOOEE ... WHOOEE ... WHOOEE
+Crew scrambles in emergency preparation.
+Spock and Scotty ready the death ray and
+prepare to channel all ship's power to the device.
+
+Spock-  "Preparations complete, sir."
+Kirk-  "Engage!"
+
+WHIRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+Sulu- "Captain!  Yagabandaghangrapl, brachriigringlanbla!"
+Lt. Uhura-  "Graaeek!  Graaeek!"
+
+Spock-  "Fascinating!  . . . All humans aboard
+  have apparently been transformed into strange mutations.
+  Vulcans do not seem to be affected.
+
+Kirk-  "Raauch!  Raauch!"
+
+
+
+It is stardate 3851.3.
+
+The mutants attack and kill Spock.
+[CONTINUE?]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Your ship is captured by Klingons, and
+your crew is put on display in a Klingon zoo.
+The Federation will be destroyed.
+
+
+Your score --
+  0.00 Klingons per stardate                  0
+     1 ship(s) lost or destroyed           -100
+Penalty for getting yourself killed        -200
+
+TOTAL SCORE                                -303
+
+May the Great Bird of the Galaxy roost upon your home planet.
diff --git a/test/test31.log b/test/test31.log
new file mode 100644 (file)
index 0000000..f035a46
--- /dev/null
@@ -0,0 +1,8 @@
+# seed 1692263709
+# arguments regular medium expert 2023
+# SST2K version 2.7
+# Test death ray - fail (mutation)
+# recorded by esr@snark.thyrsus.com on Thu Aug 17 05:15:09 2023
+#
+deathray
+y