Classic bug: Damaged warp overrides requested speed

Bug ID GE-BUG-026
Affected versions Classic 3.2e and published classic source
Status Verified in source
Fixed in ge-next 0.1
Primary source Overspeed penalty in moveship()

Summary

When classic GE applies engine damage after an overspeed warning sequence, it unconditionally changes the ship's requested speed to the newly reduced maximum. This can override a lower speed the player just requested, including a request to stop.

The bug was fixed in ge-next 0.1. It predates and is separate from the smooth overspeed system introduced in ge-next 0.3.

Overspeed state in classic

Each user ship has a current safe top speed in topspeed, a current speed in speed, and a requested destination speed in speed2b. Traveling above topspeed can increment warncntr as progressively stronger engine warnings are issued.

The accumulated penalty is not applied immediately. Once the ship is no longer continuing to accelerate at excessive speed, moveship() divides topspeed by warncntr. This represents the reduction in the engines' safe maximum after the overspeed incident.

That general process is intentional. The error is what classic does to speed2b at the same time:

ptr->topspeed = ptr->topspeed / ptr->warncntr;
ptr->speed2b = ptr->topspeed * 1000.0;

The second assignment does not check what speed the player requested. It always replaces that request with the damaged engine maximum.

Gameplay consequences

Suppose a ship has a safe top speed of warp 10, is still traveling at warp 12, and has accumulated an overspeed warning count of 2. The player recognizes the danger and enters:

WARP 0

The command correctly sets the requested speed to zero. On the next movement update, however, classic applies the pending engine penalty:

new top speed = 10 / 2 = warp 5
requested speed = warp 5

The ship decelerates only to warp 5 instead of stopping. A request for warp 3 would likewise be changed to warp 5. The player is warned that the recommended maximum has fallen, but the more immediate problem is that the helm no longer obeys the lower speed that was ordered.

This is especially hazardous when the player is trying to stop near a planet, another ship, a wormhole, or the galactic perimeter. The corrective command can leave the ship moving at substantial warp speed and require another command after the penalty has been applied.

Clamping a request above the new maximum is reasonable. Raising a request that is already at or below the new maximum is not.

Cause

Classic uses the same assignment both to enforce the damaged maximum and to set the target speed. It therefore treats all requested speeds as though they were above the new limit. The code never compares speed2b with the reduced topspeed before overwriting it.

The behavior occurs in the movement update rather than directly in cmd_warp(). The WARP command accepts the lower speed correctly; moveship() replaces it when resolving the outstanding overspeed warnings.

Correction in ge-next

ge-next 0.1 made the assignment conditional:

ptr->topspeed = ptr->topspeed / ptr->warncntr;
if (ptr->speed2b > ptr->topspeed * 1000.0)
    ptr->speed2b = ptr->topspeed * 1000.0;

The damaged maximum is still calculated exactly as before. A requested speed above that maximum is reduced to it, while a lower requested speed remains unchanged. In particular, WARP 0 continues toward a dead stop.

ge-next 0.3 later replaced the broader overspeed mechanics with a smoother system. That later feature should not be confused with this fix: the incorrect target-speed overwrite had already been corrected in the first public ge-next release.