Automatic supply always leaves enough food to avoid starvation in
supply sources, except for one case: when drawing supplies from the
sector containing the sink.
This behavior contradicted info supply. However, do_feed() used to
rely on it (it would have wiped out food without it). Supply use
there was removed in commit 7da69c92, so we can now fix this.
Affected by this is the automatic food supply of land units in combat,
and the food supply in commands supply, load and lload. Except supply
is disabled due to bugs in the last two.
When a supply request got served completely from a remote sector after
some other source had already provided some of it, the sector was
charged mobility for the complete amount instead of just the part it
actually provided.
Its implementation in s_commod() increases lnd_seqno even when
!actually_doit, which can cause spurious seqno oopses in callers of
lnd_could_be_supplied(). I can't be bothered to clean up this mess
right now, because recursive resupply is too dumb to be really useful
anyway: each step uses the first source it finds, without
consideration of mobility cost.
Being in supply is relevant for defending and reacting units. The
code used has_supply() to check that.
Contrary to its name, has_supply() does not check whether the land
unit has enough supplies to be in supply, but whether it has or could
draw enough. So, defending and reacting units did not actually draw
any missing supplies.
Fix that in get_dlist() and att_reacting_units() by calling
resupply_all(), then checking with new lnd_in_supply() instead of
has_supply(). The fix of att_reacting_units() is complicated by the
fact that it is also used in the strength command, and should keep not
drawing supplies there.
Rename has_supply() to lnd_could_be_supplied(). Replace its uses
immediately after resupply_all() by lnd_in_supply().
Running supply recursively here is problematic, because it can draw
supplies from the outer supply's destination, which can then end up
with less than it asked for.
Serving as supply source never puts a unit that is in supply out of
supply. So, the recursive supply here denies the sink its supplies to
put a supply unit somewhere else back in supply. That's robbing Peter
to pay Paul. Drop it.
The common supply code does not supply a land unit from the ship
carrying it, only resupply_all() does that, since 4.3.14. It would be
nice to fix the inconsistency by always supplying land units that way,
but that's relatively costly now, because of the supply code's design.
Just drop it for now.
Affects load and lload (except resupply is disabled there because it's
buggy), supply, assault and board.
It claimed ships and land units don't need shells if they can draw
them from a supply source. That was never true for ships, I believe,
and became wrong for land units in commit f6c87d21.
Don't claim "now out of supply" when actually out of mobility.
Don't claim "out of supply" when actually out of shells. A land unit
is out of supply when out of shells, but not necessarily the other way
round.
Reading the sector again invalidates the sector type check. Bug can
currently bite only when the deity redesignates the sector. Call
check_sect_ok() instead.
Food supply during update adds complexity to the update. How much
good it does to players is highly doubtful; certainly nobody can rely
on it. It isn't covered by the starvation command. Starving ships or
land units can steal enough food from their sector to make it starve,
too. Finally, the supply code is notoriously hard to use correctly.
We don't know of issues with the update's use, but we haven't
convinced ourselves that there aren't any either.
4.0.9 changed flak not to use up shells, but they still had to be
present. Drop that, because it doesn't really provide any value.
Moreover, this gets rid of the buggy flak shell supply code (seqno
mismatch oopses, lost supplies).
may_play_now() tells deities about hours restriction and game down
status. It runs at login and before and after each command. Getting
notified that often is annoying.
Avoid repetition by remembering notification in new player flags
PF_HOURS and PF_DOWN. Add a notification when hours restriction has
been lifted. Ensure the notification is printed before the prompt,
not before the command, by calling may_play_now() from command() only
for mortals. Safe, because may_play_now() always returns true for
deities anyway.
New tel_read_header(), tel_read_body(). Use them in rea(),
show_first_tel(), copy_and_expire().
rea() now stops when it encounters a corrupt telegram, and logs the
problem. Before, error detection was incomplete, and errors were not
logged. Corrupt mailboxes could make it crash.
show_first_tel() and copy_and_expire() can now cope with telegrams of
arbitrary length, like rea(), and sanity-check the header fields they
don't actually use.
Move the gamedown() check from status to may_play_now() so it is
checked upon login, before a command is executed and after command
completion. This fixes the situation where a player to could execute
one more command after the game was down.
Report to the deities that the game is down.
Remove to duplicate gamedown message.
EMPTH_POSIX and EMPTH_W32 implementations rejected values other than a
single flag. Such values aren't used now, but it violates the
contract all the same.
Commit 08b94556 introduced the timeout parameter. The empthread
implementation could change it, at least on some systems, and its user
worked around a possible change. However, that behavior was not
documented, and it's inconvenient. Fix the pthread implementation,
and remove the workaround.
The ancients designed interception dead simple: when you overfly a
sector, you get intercepted by the sector owner. Fine print
interception rules govern which planes intercept.
Then complexity got piled on top of it.
Chainsaw 2 added an extra interception by surface ship owners, in the
target sector only.
Chainsaw 3 added an extra interception by land unit owners, in the
target sector only (Empire 4 later merged this extra land unit
interception with the extra surface ship interception).
Chainsaw 3 added an entirely separate kind of interception: air
defense missions. When you enter a sector in some air defense op
area, you get intercepted. Fine print air defense rules govern which
planes intercept. These rules differ significantly from the
interception fine print.
Additional complexity comes from these facts:
* Air defense mission interception happens in addition to non-mission
interception. You can boost your total interception by setting up
air defense. Which means you must set it up, or forgo an advantage.
* Air defense planes are not available for non-mission interception
duty. You need to decide on a split.
* In contrast to non-mission interception, interceptors flying air
defense get intercepted.
Moreover, the air defense code breaks one of the plane code's design
assumptions, namely that just one plane sortie is active at a time.
The air defense sortie runs while the sortie it intercepts is in
progress. This leads to two interceptions being active at the same
time: the one intercepting the original sortie, and the one
intercepting the air defense sortie. The same plane can fly in both
interceptions, and damage received in the interception of the air
defense sortie is wiped out, triggering a seqno mismatch oops.
The previous commit already simplified non-mission interception: you
get intercepted by anyone who owns the sector, or a surface ship or a
land unit there, whether it's the target sector or not.
Now simplify mission interception, by merging air defense back into
ordinary interception: when you overfly a sector, you get intercepted
by anyone who owns the sector, or a surface ship or land unit there,
or has an air defense mission covering the sector. That's all. No
multiple interceptions, no separate air defense rules.
Remove air_defense(). Simplify ac_encounter() and sam_intercept()
accordingly; both lose their last parameter.
Change sam_intercept() and ac_intercept() to intercept in mission op
areas. New parameter only_mission to suppress non-mission
interception. Pass zero when the intercepting country owns the sector
or a surface ship or land unit in the sector.
ac_encounter() can't efficiently predict whether a country intercepts,
so it needs to call ac_intercept() unconditionally. This kills the
optimization to collect interceptors only when needed; simplify
accordingly, replacing getilist() by getilists().
In each sector, any country owning the sector, a surface ship or a
land unit gets to intercept.
Before, only the sector owner got to intercept, except for the target
sector. There, any country owning surface ships or land units got to
intercept in addition to the sector owner. Thus, a sector owner with
surface ships or land units there got to intercept twice.
Info Intercept claimed you get to intercept once for ships and once
again for land units, which was wrong since 4.0.9.
Info bomb suggested that flak fires only in the target sector, which
was wrong since 4.2.8. Drop that.
Sectors already spotted overflying planes in every sector along the
flight path, but ships and land units did that only in the target
sector, once if you got any ships there, in ac_encounter(), once if
you got any land units there, in ac_encounter(), once for ships firing
flak, in ac_shipflak(), and once for land units firing flak, in
ac_landflak(). Remove all that, and generalize ac_encounter()'s code
for sectors to spot planes to include ships and land units. Unlike
before, ships and land units don't spot allied planes.
Planes now spot ships and land units only when flying recon or sweep,
and along all of their flight path instead of just the target sector.
It still takes a spy plane to identify ships and land units.
Before, non-spy planes spotted ships and land units only in the target
sector, regardless of type of sortie, once for all ships and land
units, in ac_encounter(), once for ships firing flak, in
ac_shipflak(), and once for land units firing flak, in ac_landflak().
Remove all that.
Change ac_encounter() to start intercepting and running air defense
missions at the assembly point instead of the first sector entered
from there.
This also fixes a coding bug: when the flight path was empty, evaded
was used uninitialized when checking whether to intercept over the
target. The compiler even warned about that. Since the uninitialized
evaded typically read non-zero, interception triggered by ships and
land units didn't work. Abusable: if you managed to make your target
sector an assembly point, e.g. by placing an own or allied ship there,
you could bomb it without getting intercepted or taking flak.