Classic bug: SYS GOTO desynchronizes warp state

Bug ID GE-BUG-036
Affected versions Classic 3.2e and published source
Status Verified in source; low-impact privileged-command defect
Fixed in ge-next 0.1
Primary source SYS GOTO handling in cmd_sysop()

Summary

Using classic GE's SYS GOTO command while a ship is traveling at warp speed can leave the ship moving at warp while its internal location state says that it is not in hyperspace.

This is a genuine state inconsistency, but not an important normal-play bug. SYS is a privileged collection of development and administration commands. It is used primarily for testing and is normally restricted to the sysop. Many SYS commands intentionally bypass ordinary gameplay rules; the defect here is specifically that SYS GOTO changes only one half of a paired movement state.

Separate speed and location state

A GE ship does not determine whether it is in hyperspace from speed alone. Its record stores both:

  • speed and speed2b, the current and requested speeds;
  • where, which identifies normal space, hyperspace, or planetary orbit.

For a freely moving ship, the important where values are:

where == 0    normal space
where == 1    hyperspace
where >= 10   orbit around a planet

Ordinary acceleration keeps these values synchronized. When a ship accelerates across the warp threshold, accel() calls hyperspace(..., 1), which performs the transition and assigns:

ptr->where = 1;

When it decelerates below that threshold, hyperspace(..., 0) returns it to normal space.

Classic SYS GOTO behavior

Classic's SYS GOTO x y directly relocates the invoking ship. Before changing its coordinates, it unconditionally does this:

warsptr->where = 0;
warsptr->hostile = 0;
warsptr->coord.xcoord = (double)i + .5;
warsptr->coord.ycoord = (double)j + .5;

It does not stop the ship, change speed2b, or perform the ordinary hyperspace transition. If the ship was already at warp, the resulting record can therefore resemble:

speed     = 10000    (warp 10)
speed2b   = 10000    (warp 10 requested)
where     = 0        (normal space)

Because current speed already equals requested speed, accel() has no threshold to cross and no reason to call hyperspace(). The mismatch can persist until another action causes an appropriate speed transition or the ship state is otherwise reset.

Consequences

The ship continues moving according to its numeric speed. Other routines, however, use where to decide which environment and rules apply. A warp-speed ship marked as being in normal space can therefore be treated as a normal-space ship for such behavior as:

  • gravity and proximity effects;
  • scanner visibility and scan-detail rules;
  • normal-space versus hyperspace weapon behavior;
  • commands that are accepted or rejected according to hyperspace state.

The exact visible result depends on what the administrator does after the teleport. This is not a practical player exploit under the normal configuration because ordinary navigation cannot create the state, and routine players do not normally have access to SYS GOTO.

Correction in ge-next

ge-next 0.1 made SYS GOTO preserve an existing hyperspace state:

if (warsptr->where != 1)
    warsptr->where = 0;

Thus, a ship already in hyperspace remains marked as being in hyperspace after the administrative relocation. A ship in orbit is still changed to ordinary space, which is appropriate because its coordinates have been moved away from the planet without using the normal departure procedure.

The same ge-next cleanup also validates both positive and negative destination coordinates against the galaxy boundary and reports the sector change. Those are useful improvements to the diagnostic command, but preserving where == 1 is the part that corrects this particular inconsistent state.