RET_SYS was used for commands failing due to internal or environmental
errors, but not really systematically. The difference to RET_FAIL is
how dispatch() treats them: RET_SYS got logged, and cost no BTUs.
More specific logging is possible at the point of failure than in
dispatch(). Make sure that's done for all failures that used to
return RET_SYS.
The change in BTU charging affects commands consider, offer, repay,
trade failing due to internal errors. It also affects deity commands
reload and turn (irrelevant because deities get unlimited BTUs), and
commands apropos, info and motd (irrelevant because they cost no
BTUs).
The initial parts of struct loststr and struct empobj must match.
Commit 49780e2c screwed that up for members lost_uid/uid, which also
broke the equivalence of lost_owner/own. Since lost_uid is not used,
the former had no effect. But the latter broke xdvisible(). Could
make xdump lost leak information.
Commit a680c811 reorderd struct loststr members to make lost_timestamp
equivalent to new struct empobj member timestamp, but failed due to
the bug in commit 49780e2c. Commit f33b96b1 then set the timestamp
through empobj, which screwed up timestamps in lostitems, i.e. it
broke incremental xdump lost.
All of the above is in v4.3.12.
Commit 536ef0b0 (v4.3.15) added lost_seqno / seqno. No effect,
because only seqno is used.
This is the human-readable buddy of xdump product, which dumps pchr[].
It duplicates much of the information in show sect c, but in more
accessible form. It's in show_product().
Remove product information from info Quick-ref. show reflects the
actual game, is more complete, and should be just as readable.
The old code used getstarg() to get an argument with a different
prompt than snxtitem() uses, then passed the value to snxtitem()
unchecked. If the player aborts, getstarg() returns a null pointer,
and snxtitem() prompts again. Affected:
* load/lload plane/land third argument; load_plane_ship(),
load_land_ship(), load_plane_land(), load_land_land()
* bomb, drop, fly, paradrop, recon and sweep second argument;
get_planes()
* tend and ltend second and fourth argument; ltend(), tend(),
tend_land()
* mission second argument; mission()
Fix by making snxtitem() taking a prompt argument, null pointer
requests the old prompt.
Use that to simplify multifire() and torp(). Change the other callers
to pass NULL.
Commit 79407e68 (v4.3.11) changed recvclient() to keep failing after
receiving EOF from player. This was bad, because some places getting
input check player->aborted instead of recvclient() failure, and
player->aborted wasn't set on EOF. Bugs caused by this:
* comm_bomb(), ship_bomb(), plane_bomb(), land_bomb() went into an
infinite loop that eventually ate all memory.
* deli(), desi(), dist(), fly(), morale(), zdon(), att_prompt(),
ask_move_in() interpreted EOF as empty input instead of no more
input.
* cmd_sail_ship() dereferenced a null pointer.
Fix by setting player->aborted on EOF, too.
Reading input fails after EOF and while the current command is
aborted. Commands should detect that and fail. If a command neglects
to do that in a loop, the loop can become infinite. This is
especially bad after EOF, because then the client might not read
output anymore. Output gets buffered until memory runs out.
Mitigate such bugs by counting how many calls have failed in a row,
oopsing on the 256th, and sleeping one minute from the 256th on.
The values in these columns were computed by count_sect_units() and
count_sect_planes(), which included land units and planes in the count
that aren't shown by prunits() and prplanes(), namely own and embarked
units. Confusing. Moreover, count_sect_planes() and prunits() rolled
dice separately for spy units. This could leak the presence of spies
even when prunits() didn't show them.
All fixable, but not worth the trouble; just remove the counts.
This oopses on output dependency violations, e.g. two threads doing a
read-modify-write without synchronization, or the one thread nesting
several read-modify-writes. Such bugs are difficult to spot, and tend
to be abusable. I figure we have quite a few of them.
New struct emptypedstr member seqno. Make sure all members of unit
empobj_storage share it. Initialize it in files: main() and
file_sct_init(). Set it in ef_blank() and new ef_set_uid() by calling
new get_seqno(). Use ef_set_uid() when copying objects: swaps(),
doland(), doship(), doplane(), dounit(), delete_old_news(). Step it
in ef_write() by calling new new_seqno().
Factor do_read() out of fillcache() to make it available for
get_seqno().
Commit f33b96b1 (v4.3.12) made files again set timestamps. That was
intentionally suppressed in commit 990eb46b (v4.3.10), because it
facilitates attacks against the PRNG. Commit 8f98e53a (v4.3.0) had
added it as a feature.
Fix by making files's main() pass new flag EFF_NOTIME to ef_open().
Implement the flag in do_write().
Certain tables have a fixed size depending on configuration: EF_SECTOR
has WORLD_SZ() elements, EF_NATION, EF_MAP and EF_BMAP have MAXNOC
elements, and EF_REALM has MAXNOC * MAXNOR elements. Bad things
happen if the files backing them are shorter.
Pass expected size to ef_open(), and make it fail when the actual size
differs.
The value of diffx() had the wrong sign when the arguments differed by
WORLD_X / 2. Same for diffy() and WORLD_Y / 2. satmap() used them to
find the vector from map center to ship or land unit to put on the
map, and got incorrect values for ships and land units directly
opposite to the center in x or y. The bug made satmap() read a
pointer out bounds of its malloced radbuf[], and then write through
that with unpredictable consequences.
Broken in 4.2.12. The original bug was in Empire 1.1: it
miscalculated where to put ships on the map (no crash). An incomplete
fix for radmap() and satmap() appeared in Chainsaw 2 (still no crash).
radmap() got fixed correctly in Chainsaw 3, but satmap() was
forgotten. That one got "fixed" in 4.2.7, and again in 4.2.12, but
both "fixes" were flawed and could crash.
Fix by backing out the flawed fixes and adopting the fix from radmap()
instead.
Broken in commit 5f764285 (v4.3.12) for negative multiples of WORLD_X
and WORLD_Y, respectively.
This could theoretically lead to buffer overruns and other
unpleasantness. None have been reproduced, though.
Commit da8a1dae (v4.3.12) introduced virtual selectors, but neglected
to update xundump. Xundump can't work for them, because they don't
provide a setter method.
This didn't actually break anything, because all virtual selectors
have flag NSC_EXTRA set, or are in table EF_VERSION, which xundump
refuses to touch.
Make deffld() oops on virtual selector, just to be safe.
The abstract idea of tying ships and land units to a logistical tether
is sound, the concrete implementation as option FUEL is flawed. It
adds too much busy-work to the game to be enjoyable. It hasn't been
enabled in a public game for years. The code implementing it is ugly,
repetitive, and a burden to maintain.
Remove selector fuel from ship_ca[] and land_ca[], and selectors
fuelc, fuelu from mchr_ca[] and lchr_ca[]. Remove fields fuelc, fuelu
from ship.config and land.config.
Remove command fuel from player_coms[].
Deprecate edit key 'B' in doship(), dounit(), and don't show it in
pr_ship(), pr_land().
Drop opt_FUEL code from build_ship(), shi(), sdump(), ship_damage(),
show_ship_stats(), do_mob_ship(), nav_ship(), build_land(), land(),
ldump(), land_damage(), show_land_stats(), do_mob_land(),
resupply_all(), resupply_commod(), get_minimum(), has_supply(),
unit_list(), vers().
Remove opt_FUEL, fuel_mult, struct shpstr member shp_fuel, struct
mchrstr members m_fuelc and m_fuelu, M_OILER, struct lndstr member
lnd_fuel, struct lchrstr members l_fuelc and l_fuelu, fuel(), and
auto_fuel_ship().
pin_bomb() computed the number of foreign subs as number of ships less
number of foreign surface ships. This counted own surface ships as
subs.
Change it to count foreign subs directly. Closes#906040.
However, shipsatxy(), the function for counting foreign ships, also
lists them. Add a parameter to suppress that, and change its callers.
Change oops() to call the new oops_handler function pointer instead of
offering a fixed set of actions. Change server's main() to install a
handler for the action requested by -E.
Three options: abort, crash-dump, nothing. crash-dump works by
aborting a fork. It isn't implemented for Windows.
The oops action is no longer tied to daemon mode, but -d still implies
-E abort for convenience.
This is because we want to define them in src/lib/global/, and code
there can't use getnatp(), because that requires
src/lib/common/file.c. Which renders a cnum parameter pretty useless.
Virtual selectors requiring code from common/ could well come up again
in the future, but let's not worry about that now.
launch_sat() failed to call msl_equip(). Change msl_equip() to take
the mission character as argument, because the old hardcoded 'p' isn't
appropriate for satellites. Best fit for satellites is 'r' for
reconnaissance, but mission_pln_equip() doesn't accept that
(pln_equip() does). Fix that as well.
Planes normally sit in their base (sector or carrier), where they can
be spied, damaged, captured, loaded, unloaded, upgraded and so forth.
All this must not be possible while they fly. There are two kinds of
flying planes: satellites in orbit, and planes flying a sortie.
Satellites in orbit have always been marked with flag PLN_LAUNCHED.
Works. What didn't work was tracking planes flying a sortie.
If you look at one sortie in isolation, up to three groups of planes
can be flying at any point of time: the primary group, which carries
out the sortie's mission (bomb, transport, ...), their escorts, and a
group of hostile planes flying interception or air defense.
The old code attempted to track these planes by passing those groups
to the places that need to know whether a plane is flying. This was
complex and incomplete, and broke down completely for the pin-bombing
command.
It was complex, because the plane code needs to keep track of all the
call chains that can lead to a place that needs to know whether a
plane flies, and pass the groups down the call chains. This leads to
a rather ugly passing of plane groups all over the place.
It was incomplete, because it generally failed to pass the escorts.
And the whole scheme broke down for the pin-bombing command. That's
because pin-bombing asks the player for targets while his planes are
loitering above the target sector. This yields the processor and lets
other code run. Which does not get the flying planes passed.
The new code marks planes and SAMs (but not other missiles) flying a
sortie with flag PLN_LAUNCHED (the previous commit laid the groundwork
for that), and does away with passing around groups of flying planes.
This fixes the following bugs:
* Many commands could interact with foreign planes flying for a
pin-bombing command as if they were sitting in their base. This
includes spying, damaging, capturing, loading, or upgrading them,
and even getting intercepted by them. Any changes to those planes
were wiped out when they landed. Abusable.
* The bomb command could bomb its own escorts, directly (pin-bomb
planes) or through collateral damage, strategic sector damage,
collapsing bridges or nuke damage. The damage to the escorts was
wiped out when they landed.
* If you asked for a plane to fly both in the primary group and the
escort group, you got charged fuel for two sorties instead of one.
* pln_put1() and pln_put() now recognize planes that didn't take off,
and refrain from making them land. Intercept (since commit
c64e2149) and air defense can do that. Making them land had no
ill-effects, but it was still wrong.
There's one new problem: if PLN_LAUNCHED doesn't get reset properly,
due to game crash during flight or some other bug, the plane gets
stuck in the air. Catch and fix that on game start in ef_verify().
Use new pln_is_in_orbit() when we want to test for orbit specifically,
and test PLN_LAUNCHED when we want to test whether the plane not
sitting in the sector (because it is flying). This distinction is
pointless at this time, because the only way PLN_LAUNCHED gets set is
when a satellite goes into orbit. It will become useful in a later
commit, which will use PLN_LAUNCHED to mark flying planes.
Use it in pln_put() and ac_planedamage().
This changes ac_planedamage() to deal with a destroyed airbase.
Before, aborted planes happily landed there. This bug could not
actually bite, because the code neither yields nor does damage to
potential airbases between checking the landing airbase before takeoff
and aborting planes in ac_planedamage().
It changes pln_put() to cope with dead planes. Before, it made them
land as if they lived, fortunately without ill effects (complaints
about not being able to land were suppressed for dead planes).
ac_planedamage() removes dead planes, but pinflak_planedamage()
doesn't, and these end up in pln_put(). pinflak_planedamage() no
longer has to take shot down planes off their carriers, because
pln_put() now takes care of that.
Make sure all members of unit empobj_storage share it.
Add matching timestamp member to struct comstr, struct empobj, struct
gamestr, struct lonstr, struct natstr, struct nwsstr, struct trdstr,
struct trtstr. The timestamp isn't yet set for these. To be fixed.
Move the timestamp member to the right place in struct lndstr, struct
loststr, struct realmstr, struct nukstr, struct plnstr, struct sctstr,
struct shpstr.
The common nation wipe code is not quite identical, and it doesn't
wipe the nation thoroughly enough. The new code does.
Changes to both commands:
* Wipe nat_update, nat_ann, nat_access, and nat_contact. Bug: should
set nat_ann to the number of announcements.
Changes to add command:
* Don't wipe for status active and god. Before, nat_relate and
nat_flags where wiped then.
Changes to newcap command:
* Wipe nat_hostaddr, nat_hostname, nat_userid, nat_dayno, nat_minused,
nat_reserve, nat_last_login, nat_last_logout, nat_newstim,
nat_annotim, nat_relate, nat_rejects, nat_flags.
This is for the forthcoming empdump utility program. The xdump
command still does not support the human-readable dialect.
xundump has supported the human-readable dialect for a long time
(commit 4871a10a).
struct lndstr members lnd_spy, lnd_rad, lnd_ammo, lnd_fuelc,
lnd_fuelu, lnd_maxlight, lnd_maxlight are mere copies of struct
lchrstr members l_spy, l_rad, l_ammo, l_fuelc, l_fuelu, l_nxlight,
l_nland. Remove them.
Make land unit selectors spy, rmax, ammo, fuelc, fuelu, maxlight
virtual.
New lnd_att(), lnd_def(), lnd_vul(), lnd_spd(), lnd_vis(), lnd_frg(),
lnd_acc(), lnd_dam(), lnd_aaf() replace the struct lndstr members with
the same names.
Make land unit selectors att, def, vul, spd, vis, frg, acc, dam, aaf
virtual.
New pln_att(), pln_def(), pln_acc(), pln_range_max(), pln_load()
replace the struct plnstr members with the same names.
Make plane selectors att and def virtual.
Where ordinary selectors specify a value stored in some object,
virtual selectors specify a function to call to compute a value
associated with some object.
Use them to replace the special case xdump ver by new table
EF_VERSION.
Move configkeys[] to lib/common because nsc_init() needs it to
initialize empfile[EF_VERSION].cadef.