Deleting a country in state STAT_SANCT, STAT_ACTIVE or STAT_GOD is
risky, because any references to this country become dangling, which
makes ef_verify() unhappy. For a reason: we may well have code that
isn't prepared for dangling references, and breaks.
Replacing a country that is being used is risky, because it can get us
into weird states. For instance, replacing a player by a visitor can
result in a visitor that owns stuff.
Just create sanctuaries, put country into STAT_SANCT, grant BTUs and
money, set origin and initial realms.
This reverts commit e1a68c72 (v4.3.12) as far as newcap is concerned.
Except we still set nat_access, because that needs to be set along
with nat_btu.
Additionally, leave levels and telegrams alone.
Should have no effect in practice, because newcap works only in
STAT_NEW, and we get there with the add command, which wipes the
country.
Before, add reset the country only when adding a player or a visitor.
When adding a deity or deleting a country, it set just nat_cnam,
nat_pnam and nat_state. Has always been that way.
Because of that, a newly minted deity country could inherit all kinds
of crap from a previous user of its country number: origin, realms,
relations, telegrams, ... Harmless if the country number has never
been used before, which is how add is generally used.
When adding a deity country, initial levels (start_education, ...) now
apply, relations start NEUTRAL instead of AT_WAR, and the usual
initial nation flags are set.
Reset on delete as well, just to get rid of the special case.
Argument "active" is obscure. It creates a country in STAT_ACTIVE
that doesn't have a capital, and has its origin at the true origin.
If you really want such a country, create it in STAT_NEW normally,
then use edit to go to STAT_ACTIVE.
sell used to search multiple sectors for sellable commodities, keeping
tally in totalcom. It failed with message "No eligible" when none
could be found.
sell's second argument got changed to a single sector in Empire 3. If
the sector can't sell, we return early. Else, totalcom is positive.
Thus, the "No eligible" code is unreachable. Remove it.
boar() lets a sector board if it has mobility or usable land units.
Embarked land units are not usable. But it tests only "on ship", not
"on land unit". Broken in 4.0.17.
The transported plane remains on its carrier. When the land unit
moves, the plane is teleported right back to it. Broken since
Chainsaw 3 added land units.
While there, improve the message for planes on ships.
Commit e3cf1e32 (v4.3.27) created make_stale_if_command_arg() to
permit catching more potential yields on input. Unfortunately, the
implementation of navigate and march sub-commands 'r', 'l' and 's'
breaks it.
do_unit_move() reads units into a unit list at the beginning and at
each stop. It writes them back when they move or sweep. If a unit
changed in the file in between, the changes would get wiped out.
Therefore, do_unit_move() must not yield between stops.
do_unit_move() parses sub-commands into player->argp[], then supplies
defaults for missing arguments, so that code using them (radar(),
do_look(), sona(), mine(), landmine()) won't prompt for missing
arguments. Unclean and brittle. See also commit 28cc236e and commit
45106ab9.
Unfortunately, make_stale_if_command_arg() doesn't recognize the
difference between these defaulted arguments and parsed arguments, so
it makes objects stale, even though the defaulted arguments can't be
missing. If a move or sweep follows, it triggers a false positive
generation oops.
To fix, test "points into argument buffer" (only true for parsed
arguments) instead of "is in player->argp[]". Requires making the
argument buffer accessible: new struct player member argbuf[]. Use it
for parsing commands, in command(), execute(), do_unit_move(). Don't
use it in emp_config(), player_login(), move_ground(), because these
parse something else.
verify_row() refrains from rejecting zero uids, because some tables
may contain blank entries, with zero uid.
Change it to check only header sanity for entries that are not in use.
This filters out all legitimately blank entries. Tighten up the uid
check.
For computing "in use", factor empobj_in_use() out of xdvisible().
Note that xdvisible()'s case EF_COUNTRY doesn't bother to check
nat_stat, because that's implied by what it does check. It's not
implied in empobj_in_use(), so add it there.
Spy units are now enabled when a land unit type with capability spy
exists. To disable them, deities have to customize table land-chr.
Before, spy units types were ignored when option LANDSPIES was
disabled. Except for xdump land-chr, which happily dumped unusable
spy unit types.
Trade ships are now enabled when a ship type with capability trade
exists. No such type exists by default; to enable trade ships,
deities have to customize table ship-chr.
Before, trade ship types were ignored when option TRADESHIPS was
disabled. Except for xdump ship-chr, which happily dumped unusable
trade ship types.
Configuration table entries not defined by builtin and custom
configuration files remain blank. They get misinterpreted as sentinel
in tables that use one. Affected are tables product, ship-chr,
plane-chr, land-chr and nuke-chr. Tables item, sect-chr and
infrastructure are immune despite using a sentinel, because omitting
entries is not permitted there.
Code relying on the sentinel fails to pick up entries after the first
blank one. They don't get set up correctly, they're invisible to
build and show, and not recognized as symbolic selector values (the
frg in ship ?type=frg). xdump is fine, because it doesn't rely on
sentinels. It dumps blank entries normally.
The bugs don't bite in the stock game, because the builtin
configuration files are all dense.
The sentinels are all null strings. Set them to "" in the affected
tables' oninit callback. Fix up code iterating over the tables to
ignore such entries. This is precisely the code relying on sentinels,
plus xdump's xdvisible().
To enable that, make build_ship() & friends all take the same int type
argument instead of each one its own pointer. Passing pointers
triggered "may be used uninitialized" compiler warnings (the code was
safe despite the warnings).
For drnuke_const 0.33, research level 92.4 now suffices for a tech 280
nuke. Before, you needed 93, which was inconsistent with what
version's promise "need 0.33 times the tech level in research".
buy() reads the lot, prompts for input, then writes back the lot,
triggering a generation oops. Any updates made by other threads while
buy() waits for input are wiped out, triggering a seqno mismatch oops.
Since commodities are taken from the seller when he puts them on the
market, and given to the buyer when the trade executes, the wiped out
lot's seller loses his goods without compensation, the other seller
gets to keep his goods, and the buyer receives their duplicates.
This can be abused by two conspiring countries to duplicate
commodities. The seller puts them on the market (say 100 gold bars).
The buyer starts a buy command, and waits at its last prompt for the
lot to be replaced. The seller takes them off the market (possible,
since there's no bid, yet), and sells something else (say one food)
quickly enough to get the same lot number assigned. The buyer then
completes the buy command. The seller loses one food, the buyer gains
100 gold bars.
Replaces a partial fix from v4.0.1, which only caught lots gone away,
not lots replaced by new ones.
setsector() reads the sector, prompts for input, then writes back the
sector, triggering a generation oops. Any updates made by other
threads while setsector() waits for input are wiped out, triggering a
seqno mismatch oops.
Same for setres().