Classic bug: Channel-zero NPC targeting: Difference between revisions
Remove source-only line breaks from bug article |
(No difference)
|
Latest revision as of 19:27, 8 October 2026
| Bug ID | GE-BUG-005 |
|---|---|
| Affected versions | Classic 3.2e and published classic source |
| Status | Verified in source |
| Fixed in | ge-next 0.2 |
| Primary source | GEFUNCS.C: initshp(); GECYBS.C: notclaimed(); GEDROIDS.C retaliation logic |
Summary
Classic uses numeric zero both as a valid player channel and as an uninitialized target value. This can prevent Cybertrons and some Droid logic from treating the player on channel 0 correctly.
Symptoms
When one person is logged into the BBS and playing Galactic Empire, that person normally occupies terminal channel 0. In a default classic game, Cybertrons do not select that player for pursuit. They remain in the galaxy, but none begins the normal long-range hunt toward the lone player.
The result can make classic GE seem unexpectedly empty or passive during single-player sessions. Cybertrons do not converge on the player's location, do not use their long-distance pursuit behavior to approach, and do not produce the encounters that normally result from being claimed as a target. A player may still happen to encounter a Cybertron and provoke or satisfy other local combat conditions; the defect is specifically in proactive target selection and pursuit, not removal of the Cybertrons themselves.
The behavior changes conspicuously when another player arrives. A user on channel 1 or above is not confused with the default value, so Cybertrons can claim and pursue that user. Channel 0 may continue to be ignored while the newer player receives the attention. This makes the defect appear related to the number of people online rather than to one particular numeric channel.
Strictly, “only player” and “channel 0” are not identical on every BBS. GE uses the system terminal number, so a lone GE player can occupy a higher channel when people are using other modules. The classic failure follows the channel number: it affects the player in channel 0, which is commonly the only player when testing an otherwise empty board.
Cause
Automated ships store a claimed player channel in cybmine, with 255 meaning no target. The generic ship initializer instead sets it to zero. Cybertron initialization replaces its own value with 255, but Droids created from the common template can retain zero.
Classic distinguishes these states only by the numeric value:
cybmine = 0..nterms-1 channel currently claimed or pursued cybmine = 255 no target
That representation makes channel 0 a valid target, not an empty value. Nevertheless, initshp() assigns zero to every generic new ship. The Cybertron initializer explicitly changes the field to 255, but droid_init() copies the generic ship and does not replace the zero. Those Droids therefore look as though they are targeting player 0 even though their simpler behavior does not use the field that way.
Before selecting a target, notclaimed() counts automatic ships whose cybmine matches the candidate channel. Classic counts Droids as well as Cybertrons, so uninitialized Droids look like Cybertrons that have already claimed channel 0. Once the class claim limit is reached, real Cybertrons reject that player. Separately, a Droid retaliation check uses lastfired > 0 rather than >= 0.
The default classic configuration creates two ships from each of three Droid classes: six Droids in total. All six have automatic-ship status and initially retain cybmine == 0. For a candidate player in channel 0, notclaimed() therefore counts six supposed claims before counting any actual pursuing Cybertron.
The user ship's NATK setting supplies the maximum number of Cybertrons that may claim it. The default Interceptor permits one; most combat-capable user classes permit two; the Heavy Freighter and Freight Barge intentionally permit none. For every normally eligible default class, the false count of six is already at or above the configured limit. The test nc < noclaim fails, so each Cybertron rejects channel 0.
Example: one player online
Assume the first and only caller enters GE on channel 0 in an Interceptor:
Interceptor NATK limit = 1 Droids whose default cybmine equals 0 = 6 notclaimed() result = (6 < 1), false
Each Cybertron eligible to hunt that class sees that the player is active and visible, but then fails the claim-limit test. With no second player to consider, the search leaves low_ship == -1. The Cybertron sets its target back to 255 and delays its next active check instead of plotting a course toward the player. Every otherwise eligible Cybertron repeats the same decision, so none pursues the lone player.
If a second player enters on channel 1, the same six Droids do not match cybmine == 1. The false claim count for that candidate is zero, allowing eligible Cybertrons to select the second player. This is why adding another player appears to “wake up” Cybertron pursuit.
Related Droid channel-zero error
Classic has a second zero-as-false error in the Vakory Survey Droid's retaliation path. It checks lastfired > 0; therefore an attacker on channel 1 or above qualifies, while an attacker on channel 0 does not. That defect affects the Droid's response to being attacked, but it is separate from the false-claim bug that prevents Cybertron pursuit.
Correction
ge-next limits the claim count to actual Cybertron classes. Droids no longer consume channel 0's pursuit allowance, so a lone eligible player can be claimed normally. Its rewritten Droid behavior also removes the separate lastfired > 0 assumption. These corrections were first released in ge-next 0.2. A new implementation should use explicit nullable identifiers rather than overloading zero.
Verification
Verified from the shared initializer, Cybertron claim logic, and Droid retaliation source paths.
Home · Play · Reference · Versions & history · Sysop · Development · Classic bugs