Jump to content

Classic bug: Fixed-width display column overflow: Difference between revisions

From Galactic Empire wiki
Link first command references to command pages
 
(No difference)

Latest revision as of 22:14, 11 October 2026

Bug ID GE-BUG-027
Affected versions Classic 3.2e and published classic source
Status Verified in source; recurring display defect
Fixed in Broadly corrected beginning in ge-next 0.1
Primary source Fixed-column formatters throughout the game

Summary

Many classic GE screens arrange values into fixed columns without enforcing a maximum display width for each value. A long ship-class name, large population, large inventory count, or other value can push every following column out of position and may wrap the remainder of the row onto another terminal line.

The roster, HELP CLASS, and planet administration accounting screen are prominent examples, but the pattern appears in numerous reports, lists, scans, and sysop displays. This is a family of related presentation defects rather than one bad message.

Why the fields expand

Classic frequently uses C formats such as:

%5ld
%-20s

The number is a minimum field width, not a maximum. %5ld right-justifies a short number in five positions, but a ten-digit number still prints all ten digits. Likewise, %-20s pads a short string to 20 characters but does not truncate a longer string.

That behavior is normally desirable because it preserves the complete value. It becomes a bug when the rest of a line was designed around the assumption that the field could never grow. Classic's 80-column layouts generally do not recalculate later column positions, continue on a second structured line, or otherwise recover from an expanded field.

Roster

The wide roster row is assembled with fixed minimum widths:

prf("%-30s%s%5d%3d%s\r",
    tmpusr.userid, gechrbuf, tmpusr.kills,
    tmpusr.planets, gechrbuf2);

The score is prepared in an 11-position field, and empire population is formatted separately as an eight-position floating-point value followed by m. Large populations can exceed that expected space. The expanded population text runs beyond the heading and divider, while large kill or planet counts shift every field to their right. On a narrow display, classic uses a second roster layout, but that does not solve values exceeding their individual column assumptions.

The database values remain intact; it is the rendered row that becomes jumbled. This can nevertheless make the roster difficult to interpret and can make one value appear to belong under the wrong heading.

HELP CLASS

Classic attempts to fit nearly every ship-class property on one line:

prf("%2d %-20s%-2d %-2d ... %s %2d %s %s %s %3d\r", ...);

The class name receives a minimum width of 20 even though configurable class names can be longer. Phaser, shield, warp, point, price, cargo, acceleration, and scan-range fields also have independently assumed widths. If one configured value exceeds its allotted space, all later capabilities cease to align with the multi-line heading. A sufficiently long row wraps, separating values from the headings intended to explain them.

This makes custom ship tables especially vulnerable. A table may be valid and load correctly while producing an unreadable HELP CLASS screen.

Planet administration

The planet accounting report uses one fixed row for seven item properties:

sprintf(gechrbuf,
        "%-11s %5u %5ld %5u %5u %1c %5ld",
        item_name[i],
        plptr->items[i].rate,
        plptr->items[i].qty,
        plptr->items[i].markup2a,
        plptr->items[i].reserve,
        plptr->items[i].sell,
        plptr->items[i].sold2a);

Item quantity and amount sold are long integers but are given only five display positions. Once either reaches six or more digits, later columns move to the right. Large enough values wrap the row and make the next terminal line look like a separate or corrupted item entry. Configurable item names can produce the same result if they exceed the assumed name width.

This is particularly noticeable in a mature game, where planet inventories and cumulative sales have had time to grow beyond the small values expected by the original display.

Other affected layouts

The same construction appears elsewhere in classic, including:

  • owned-planet lists with fixed name and coordinate columns;
  • fleet and ship-selection lists;
  • scan side tables containing distance, bearing, heading, and speed;
  • inventory, accounting, and production reports;
  • user, ship, and class listings available through sysop commands;
  • assorted debugging and maintenance tables.

Not every screen fails with the default configuration or normal early-game values. The defect becomes visible when a configurable string is longer than the author's expected example, a counter grows over time, or an administrator raises a configured limit without also rewriting the corresponding display.

This record concerns visual column overflow. It is separate from Classic bug: Ship-selection output overflow, where accumulated output can overflow a memory buffer.

Correction in ge-next

ge-next 0.1 began a broad cleanup of reports and fixed-column displays rather than applying one universal formatter change:

  • The roster was respaced and its population field enlarged so large empires did not immediately destroy the row layout.
  • HELP CLASS was redesigned around the actual class data and available terminal width.
  • Inventory, navigation, system, accounting, and administrative reports were realigned and given widths appropriate to their stored values.
  • Large values were formatted consistently, with abbreviated forms used where a complete decimal value could not reasonably share an 80-column table.

Later ge-next releases continued adjusting individual screens as numeric caps, new fields, and new game features exposed additional width assumptions. For that reason, "fixed in 0.1" identifies the first comprehensive correction, not a claim that one patch permanently solved every possible custom layout.

Guidance for ports

A port should treat every tabular formatter as a complete width budget:

  • Determine the actual maximum stored or configured value for each field.
  • Remember that a printf width does not truncate its argument.
  • Use precision for strings when truncation is acceptable, such as %-20.20s.
  • Abbreviate, split, paginate, or use multiple lines when full values cannot fit.
  • Test maximum-length names and maximum numeric values, not only defaults.
  • Keep ANSI escape sequences out of visible-width calculations.

Blindly truncating every value is not always the right correction. Financial, inventory, and score values may need to remain exact; in those cases the table itself must reserve enough room or use a different layout.