Jump to content

Classic bug: Extended BUY token executes PRICE

From Galactic Empire wiki
Bug ID GE-BUG-031
Affected versions Classic 3.2e and published classic source
Status Verified in source
Fixed in ge-next 0.1
Primary source Mismatch between three-character command dispatch and exact BUY test

Summary

Classic GE recognizes game commands by their first three characters, but the shared BUY/PRICE transaction routine later tests for the exact word buy. A command token that begins with buy but contains additional characters is dispatched as BUY, then handled as PRICE.

For example:

BUYTHIS 1 TOR

displays the price of one torpedo instead of buying it.

Command dispatch

The main command table contains separate three-character entries for BUY and PRICE:

{"buy", cmd_buy,   0},
{"pri", cmd_price, 0},

Classic's gesearch() compares only the first three characters of the player's command token:

c = strncmp(ptr, md->command, 3);

This is normal GE command behavior. buy, buying, and buythis all begin with the registered command prefix and therefore all dispatch to cmd_buy().

Shared BUY and PRICE logic

cmd_buy() and cmd_price() perform their command-specific checks, identify the requested item, and then call the same unfortunately named buy(item) worker. That worker calculates availability and price for both commands.

It decides whether to execute a purchase or merely display the price with this test:

if (sameas(margv[0], "buy"))
{
    /* transfer the item and charge the player */
}
else
{
    /* print PRICE1 */
}

Unlike gesearch(), sameas() requires the complete strings to match. A token such as buythis has already passed BUY dispatch, but it fails this exact comparison and falls into the PRICE branch.

Gameplay consequences

The command does not remove cash, transfer stock, or complete a purchase. It only reports what the transaction would cost. This is not normally destructive, but it is inconsistent with the parser rules used by every game command and can be confusing when a typo or habitual long form otherwise appears to have been accepted.

The bug is particularly unobvious because:

  • the command is not rejected as invalid;
  • BUY syntax and item validation have already succeeded;
  • the resulting price message is plausible; and
  • entering exactly buy immediately makes the transaction work.

PRICE itself behaves as intended. Tokens beginning with pri reach cmd_price() and correctly take the non-BUY branch in the shared worker.

Correction in ge-next

ge-next 0.1 changed the shared worker to use the same prefix rule as the command dispatcher:

if (strncmp(margv[0], "buy", 3) == 0)
{
    /* complete purchase */
}
else
{
    /* display price */
}

Any token that the command table accepts as BUY is therefore treated as BUY by the transaction routine. PRICE continues to use the same worker without being mistaken for a purchase.

An alternative structural correction would pass an explicit buy-or-price flag to the worker or use separate workers. The three-character comparison was the smallest change and preserves classic GE's established command-prefix behavior.