Jump to content

Classic bug: Invalid WARP heading reports helm damage

From Galactic Empire wiki
Bug ID GE-BUG-028
Affected versions Classic 3.2e and published classic source
Status Verified in source
Fixed in ge-next 0.1
Primary source cmd_warp() condition combining helm state and valdegree()

Summary

Entering an invalid relative heading with the classic WARP command produces two error messages. The game correctly reports that the heading must be between -180 and 180, then incorrectly reports that the ship's helm is damaged.

The helm does not have to be damaged. The second message is caused by control flow that treats two unrelated failures as the same condition.

Example

With a fully functional helm, a command such as:

WARP 10 181

causes classic to print the equivalent of:

Please enter a number in the range from -180 to 180.
Sorry Sir, The Helm is still not functional, Damage Control is working on it.

The warp order is rejected, which is correct. Only the helm-damage message is false.

Cause

valdegree() validates a relative heading. When the value is outside -180 through 180, the helper prints the range error itself and returns false.

Classic cmd_warp() combines that return value with the helm state:

if (warsptr->helm == 0 && valdegree(gechrbuf))
{
    /* carry out the warp order */
}
else
{
    prfmsg(HLBROKE);
    outprfge(ALWAYS, usrnum);
}

The combined condition can be false for either of two reasons:

  • warsptr->helm != 0: the helm really is damaged.
  • valdegree() returned false: the player entered an invalid heading.

The single else cannot distinguish those cases and prints HLBROKE for both. Since valdegree() has already printed the proper range message, an invalid heading receives both messages.

The short-circuit behavior of && also means that valdegree() is not called when the helm is actually damaged. That part is harmless; the defect is assigning the same error branch to both tests.

Why IMPULSE behaves differently

Classic's impulse command performs heading validation outside its helm test:

if (valpcnt(margv[1], 0, 99) && valdegree(gechrbuf))
{
    if (warsptr->helm == 0)
    {
        /* carry out the impulse order */
    }
    else
    {
        prfmsg(HLBROKE);
    }
}

An invalid impulse heading prevents entry into the outer block, so it does not fall into the helm-damage branch. GE-BUG-028 specifically affects the classic WARP command's arrangement of the same checks.

Correction in ge-next

ge-next separated the helm-state test from heading validation. The helm error is now reached only when the helm is damaged, while a failed valdegree() simply ends command processing after the helper prints the range error.

A simplified form of the corrected structure is:

if (warsptr->helm == 0)
{
    if (!valdegree(gechrbuf))
        return;

    /* carry out the warp order */
}
else
{
    prfmsg(HLBROKE);
}

The behavioral fix first shipped in ge-next 0.1. Later command cleanup made the early return more explicit, but did not change the already-correct outcome.