It reported the ship's location in the ship's coordinate system
instead of the player's. Fortunately, they're the same in normal
usage. They can differ only when a deity uses a foreign ship.
It reported the engineer's location in the engineer's coordinate
system instead of the player's. Fortunately, they're the same in
normal usage. They can differ only when a deity uses a foreign
engineer.
The buggy code is also reachable from and march sub-command 'd', but
can't bite there, because even deities can't march foreign land units.
It reported capital location in the nation's coordinate system instead
of the player's. Fortunately, they're the same in normal usage. They
can differ only when a deity requests a nation report for another
country.
When reporting sweeps, it reported the location in the plane owner's
coordinate system instead of the player's. Fortunately, they're the
same in normal usage. They can differ only when a deity flies foreign
planes.
If it does happen, assertion failure isn't very nice, but it beats
asking the user to report the bug to an inappropriate e-mail address
that most probably ceased to work years ago.
When take_casualties() kills a land unit, it neglects to take it off
its carrier. This triggers an oops in unit_cargo_init(). Instead of
fixing this, just don't let them fight. They can't defend against
other attacks, either.
guerrilla() lets only the sector owner's land units fight. But
take_casualties() spread the casualties among all land units in the
sector. Thus, defending land units could survive a defeat if foreign
land units were present. The sector takeover then had che capture
them, or their crews blow them up. The foreign land units were
damaged silently.
These ships could only use their x-light slots for x-light planes, not
their plane slots. For instance, agc (30 x-light slots, 32 plane
slots) could load only 30 sams, and mb (0 x-light slots, 10 plane
slots) could not load any sams.
Culprit is could_be_on_ship(). Broken in commit 3e370da5, v4.3.17.
It assumed option SUPER_BARS enabled. It's disabled by default since
4.0.9.
It assumed people_damage = 0.4. It's 1.0 since 4.0.0.
It still claimed damaging a sector doesn't damage its planes. It does
since 4.0.9.
When an inefficient missile exploded on launch, it could damage
itself. The damage had no effect, because the missile gets used up
right after. But it triggers a seqno mismatch oops, in laun(). Fix
by making msl_launch() set PLN_LAUNCHED before the explosion.
This case was missed in commit 7bc63871, v4.3.14. It didn't oops
until sequence numbers were added in v4.3.15.
When d of n cargo items are discarded for want of space, pln_dropoff()
reported -d items discarded and -d items unloaded. Already broken in
BSD Empire 1.1.
Old version recognizes the first ':', which prevents use of ':' in
host names. They are used in numerical IPv6 addresses. New version
recognizes the last ':', which prevents use of ':' in service names.
Old version treats empty host or port specially (use default).
Documentation suggests ':' is required, but the code doesn't do that.
Instead, the argument is interpreted as host, even when it's empty.
New version makes the HOST: part optional. You can't specify host and
default the port. Tough. Keeps documentation and code as simple as
possible.
Compare:
old version new version
argument host port host port
"" "" default default ""
"A" "A" default default "A"
":" default default "" ""
"A:" "A" default "A" ""
":B" default "B" "" "B"
"A:B" "A" "B" "A" "B"
Both coas() and skyw() want to iterate over a circular area with
radius vrange. They did that by iterating over a rectangle that
encloses the circle, skipping coordinates out of range. To "save
time", they used a rather odd predicate for "out of range", namely
"vrange * vrange < (j * j + 3 * k * k) / 4)".
The predicate is wrong. coastwatch and skywatch could see one sector
too far in certain directions for practical radar ranges, and up to
two sectors for not so practical tech 1900+ radar stations.
For instance, with j = 13 and k = 3, vrange = 7, the predicate
evaluates to false (49 < 48), i.e. in range. However, the true
distance is 8, i.e. out of range. Likewise, j = 22, k = 8, vrange =
13: 169 < 169, true distance 15.
Fix by iterating over the circle directly, without comparing
distances.
Before commit a269cdd7, pln_damage() returned zero when the damage was
nuclear, and callers used that to bypass conventional damage code.
Zero value can't happen anymore.
The server aborts the current command when it receives a special line
of input for a prompt. To make the client send it, you type the INTR
character (normally ^C). This sends the client the SIGINT signal.
Unfortunately, it never quite worked.
Because we use a special line of input to signal interrupt, the client
can do that only after a complete line of input.
What if SIGINT arrives in the middle of a line? We split the line in
two then and there, by inserting a newline. Nasty, but it's simple,
and happens rarely.
However, we inserted the newline always, even after a complete line.
In that case, we inserted an empty line of input before the interrupt.
If you hit INTR at a server prompt, the server received an empty line
of input for that prompt, and the interrupt only for the *next*
prompt. Which may well be too late to abort the command you wanted to
abort.
Fix by inserting the newline only when needed.
Ships can expend shells to defend against missiles, in
shp_missile_defense(). Any shell use by the target ship got wiped out
when shp_missile_interdiction() wrote back the target ship, triggering
a seqno mismatch oops.
Ships get updated when they launch planes to intercept interdicting
planes, in mission_pln_equip(). Any petrol use by the target ship got
wiped out when shp_mission_interdiction() wrote back the target ship,
triggering a seqno mismatch oops.
Fix by re-reading the target ship in shp_damage_one(). This also
affects shp_fort_interdiction(), where it is not necessary. A bit
inefficient, but let's keep this fix simple.
do_unit_move() reads the ships into a list. It re-reads them when it
prompts for sub-commands. shp_nav_one_sector() writes them back when
it moves ships.
Mine-laying (sub-command 'd') updates the minelayer, invalidating the
copy in the list. Any movement sub-command before the next prompt for
sub-commands wiped out this update, triggering a seno mismatch oops.
Happens only if 'd' is used without arguments, because remaining
sub-commands are discarded when there are arguments.
Broken when mine-laying was added in commits 2438fe7c, v4.3.7.
Same for march, commit 274c8e42, v4.3.7.
Fix by stopping after 'd' regardless of arguments.
When sub-command 'd' was used without arguments, do_unit_move() failed
to supply the second argument to mine(), which duly prompted for it.
This contracticted info, and could trigger a generation oops.
do_unit_move() reads the ships into a list. It re-reads them when it
prompts for sub-commands. shp_nav_one_sector() writes them back when
it moves ships.
The mine prompt made the list stale. Movement sub-commands before the
next prompt for sub-commands wrote back stale ships, triggering a
generation oops. Example: "nav 15 dg".
Broken when mine-laying was added in commits 2438fe7c, v4.3.7.
Same for march, commit 274c8e42, v4.3.7.
Commit a269cdd7 (v4.3.23) removed the nuclear damage. But it left the
nuke on the missile, which made pln_damage() oops and return zero
damage.
Fix by destroying the nuke separately.