Before, satellites could be disarmed and armed even in orbit. Nukes
on satellites went along into orbit, where they did nothing in
particular.
Nukes on ABMs and SAMs were lost without effect when their missile
intercepted.
The stock game is not affected, because its satellites, ABMs and SAMs
all have zero load.
The various bombing functions silently skipped planes not carrying
bombs. This sanity check was wrong: it checked capabilities "tactical
or not cargo" instead of "tactical or bomber", and failed for
non-tactical cargo bombers. No such planes exist in the stock game.
The broken check comes from Chainsaw; it replaced an equally wrong
"not cargo" check.
Because pln_sel() lets only suitable planes go on a bombing run, the
broken sanity check is unnecessary. Drop it.
Plane flying commands first select the planes to fly the mission and
their escorts, then equip them. They all fail when no planes to fly
the mission can be equipped.
Unlike bomb and paradrop, commands drop, fly, recon and sweep had an
additional check that made them fail when no planes to fly the mission
could be selected. Because "none selected" implies "none equipped",
the additional check is redundant. Remove it.
While there, break lines in calls of pln_sel() more tastefully.
Before, bomb selected any plane, but planes with zero load could not
be equipped. Cargo planes could be equipped fine, and they flew bombs
to the target, where they silently vanished.
Closes#1388263.
Initially, paradrop capability was implied both by capability cargo
and by capability VTOL. Chainsaw changed para() to require cargo, and
added compile-time option PARAFLAG to additionally require new
capability para. The optional PARAFLAG rule became mandatory in
Empire 2.
Chainsaw left the old tests for "cargo or VTOL" in place. Because
para() checked "cargo and para" first, the old tests for "cargo or
VTOL" always passed, so they had no effect.
Clean them up anyway.
These missions imply the cargo type, just like bombing missions. Use
the implied type instead of cargo type parameter ip there. Parameter
ip is now optional except for missions 't' (transport) and 'd' (drop).
Simplify para() not to pass the optional cargo type. Leave drop()
alone, because always passing the type is simpler there.
pln_arm(), pln_equip(), mission_pln_arm() mission_pln_equip() took a
mission parameter encoding the kind of sortie (strategic bomb,
pinpoint bomb, transport, ...), a flag parameter to further specify
the plane's role, and a parameter ip to specify the load.
The flags argument was always either P_F (intercept), P_F | P_ESC
(escort), or zero (any other role).
With non-zero flags, mission and ip argument were not used in any way.
Use mission 'e' and null load for escorts, and remove flags.
Intercept can still be identified by mission zero.
Also change pln_mobcost() to take a mission parameter instead of
flags, so that pln_arm() and mission_pln_arm() can simply pass on
their mission.
Before, it took a sector argument, and targeted the lowest-numbered
satellite there. Rather inconvenient when your own satellite masks
one of the enemy's.
Moreover, the command could be abused to find all sectors with
satellites. Now it can "only" be abused to find satellite ids, and
whether they're in range. Still not ideal, but tolerable.
This could make production command mispredict resource-depleting level
production. Stock game is not affected. In fact, such a product
would be highly unusual.
prod() and produce() dereferenced resource uninitialized for products
depleting resource "none" (p_nrdep != 0 && p_nrndx == 0). The latter
even wrote to it.
Depleting "none" makes no sense, and the depletion is now ignored.
Before, it could conceivably crash the server or corrupt the game.
Commit 1bca66c0 added show news and commit 71bbd642 show product
without updating the help text. Fix that. The prompt is now too
long, so add option '?' to show it, and change the prompt to refer to
that.
Unlike POSIX sockets, Windows sockets are not file descriptors, but
"OS handles", with a completely separate set of functions.
However, Windows can create a file descriptor for a socket, and return
a file descriptor's underlying handle. Use that instead of wrapping
our own file descriptors around Windows file descriptors and sockets.
Remove the wrapping machinery: MAX_FDS, enum fdmap_io_type, struct
fdmap, fdmap[], nfd, get_fd(), free_fd(), set_fd(), lookup_handle(),
lookup_fd().
Rewrite SOCKET_FUNCTION(), posix_accept(), posix_socket(),
posix_close(), ftruncate(), posix_open(), posix_read(), posix_write(),
fcntl().
Remove FILE_FUNCTION(), posix_fstat(), posix_lseek(),
SHARED_FUNCTION(), and fileno(), because the system's functions now
work fine.
posix_fsync() is used only #ifdef _WIN32, remove it, and call
_commit() directly.
The old code stuffed WSA error codes into errno, which doesn't work.
Use new w32_set_winsock_errno() to retrieve, convert & stuff into
errno. Adapt inet_ntop() to set the WSA error code instead of errno,
so it can use w32_set_winsock_errno().
Move EWOULDBLOCK from sys/socket.h to w32misc.h, and drop unused
ENOTSOCK, EAFNOSUPPORT.
Use SOCKET rather than int in Windows-specific code.
Replace the fixed $1 per ETU maintenance for capital/city sectors that
are at least 60% efficient by a configurable maintenance cost, payable
regardless of efficiency. The only change in the default
configuration is that inefficient capitals now pay maintenance.
Charging sector maintenance regardless of efficiency is consistent
with unit maintenance.
New struct dchrstr member d_maint and sector-chr selector maint. Make
show_sect_build() show it. Change produce_sect() to record
maintenance in new slot p_sect[SCT_MAINT] instead of abusing
p_sect[SCT_CAPIT]. Replace the "Capital maintenance" line in budget
by "Sector maintenance".
This is for consistency with aerial mining. Seamines don't work under
bridges anyway (they did a long time ago, until Empire 2).
Making seamines work under bridges again wouldn't be hard, but it
would make the 'X' in bmaps ambiguous.
Seamines and landmines share storage. Sea and bridge span sectors can
hold only sea mines, other sector types only landmines. Sector type
checks were missing or incorrect in several places:
* Seamines under bridge spans were mistaken for landmines in several
places:
- ground combat mine defense bonus, in get_mine_dsupport() and
stre(),
- land units retreating from bombs, in retreat_land1(),
- non-land unit ground movement (commands explore, move, transport,
and INTERDICT_ATT of military), in check_lmines(),
Fix them to check the sector type with new SCT_MINES_ARE_SEAMINES(),
SCT_LANDMINES().
* plane_sweep() mistook landmines for seamines in harbors. Bug could
not bite, because it's only called for sea sectors. Drop the bogus
check for harbor.
* Collapsing a bridge tower magically converted landmines into
seamines. Make knockdown() clear landmines.
Also use SCT_MINES_ARE_SEAMINES() and SCT_LANDMINES() in mine(),
landmine(), lnd_sweep() and lnd_check_mines(). No functional change
there.
Keep checking only for sea in pln_mine(), plane_sweep(),
retreat_ship1(), shp_sweep() and shp_check_one_mines(). This means
seamines continue not to work under bridges. Making them work there
is tempting, but as long as finding seamines clobbers the sector
designation in the bmap, it's better to have them in sea sectors only.
Historical notes:
Mines started out simple enough: you could mine sea and bridge spans,
and ships hit and swept mines in foreign sectors.
Chainsaw 2 introduced aerial mining and sweeping. Unlike ships,
planes could not mine bridge spans. plane_sweep() could sweep
harbors, which was wrong, but it was never called there, so the bug
could not bite.
Chainsaw 3 introduced landmines. The idea was to permit only seamines
in some sector types, and only landmines in the others, so they can
share storage. To figure out whether a sector has a particular kind
of mines, you need to check the sector type. Such checks already
existed in mine, drop and sweep, and they were kept unchanged. The
new lmine command also got the check. Everything else did not.
Ground movement and combat could hit and sweep seamines in bridge
spans. Ships could hit and sweep landmines in harbors.
Empire 2 fixed land unit movement (march, INTERDICT_ATT) not to
mistake seamines for landmines on bridge spans. It fixed ships not to
mistake landmines for seamines. The fix also neutered seamines under
bridge spans: ships could neither hit nor sweep them anymore. Both
fixes missed retreat.
Commit 5663713b (v4.3.1) made ship retreat consistent with other ship
movement.
Pinpointed assignments within if conditionals with spatch -sp_file
tests/bad_assign.cocci (from coccinelle-0.1.4). Cherry-picked diff
hunks affecting conditionals split over multiple lines, and cleaned
them up.
The commands to fly planes read the planes into a plane list, and
write them back when they land. If a plane changes in the file while
it is in that plane list, the changes get wiped out when the plane
lands, triggering a seqno oops.
This is not an issue as long as the complete sortie runs
uninterrupted, because that code takes care to update flying planes
only through the appropriate plane list.
However, the bomb command suspends the planes on a pinpoint bombing
run mid-air over the target sector to let the player choose targets.
This lets code run that *can* update flying planes, for instance the
edit command.
Fix by aborting changed planes, taking care not to clobber the
changes.
When bombing ships with a force containing both planes with and
without capability ASW, pin_bomb() could fail to report presence of
submarines, and could refuse to bomb ships when there were only
submarines. The culprit is pin_bomb()'s check for capability ASW: it
checked whether the first plane in the plane list was capable instead
of checking whether any plane in the list was capable.
The automatic supply interface has design flaws that make it hard to
use correctly. Its current uses are in fact all wrong (until commit
0179fd86, the update had a few uses that might have been correct).
Some of the bugs can only bite with land unit capability combinations
that don't exist in the stock game, though.
Automatic supply draws supplies from supply sources in range. Since
that can update any supply source in range, all copies of potential
supply sources a caller may keep can get invalidated. Writing back
such an invalid copy wipes out the deduction of supplies and mobility
from a source, triggering a seqno mismatch oops.
This commit redesigns the interface so that callers can safely keep a
copy of the object drawing the supplies (the "supply sink"). The idea
is to pass the sink to the supply code, so it can avoid using it as
source. The actual avoiding will be implemented in a later commit.
Copies other than the supply sink still need to be eliminated. See
commit 65410d16 for an example.
Other improvements to help avoid common errors:
* Supply functions are commonly used to ensure the sink has a certain
amount of supplies. A common error is to fetch that amount
regardless of how many the sink already has. It's more convenient
for such users to pass how many they need to have instead of how
many to get.
* A common use of supply functions is to get supplies for immediate
use. If that use turns out not to be possible after all, the
supplies need to be added somewhere, which is all too easy to
forget. Many bugs of this kind have been fixed over time, and there
are still some left. This class of bugs can be avoided by adding
the supplies to the sink automatically.
In fact, this commit fixes precisely such bugs in mission_pln_equip()
and shp_missile_defense(): plane interception and support missions,
missile interception (abms), launch of ballistic missiles and
anti-sats could all lose shells, or supply more than needed.
Replace supply_commod() by new sct_supply(), shp_supply(),
lnd_supply(), and resupply_all() by new lnd_supply_all(). Simplify
users accordingly.
There's just one use of resupply_commod() left, in landmine(). Use
lnd_supply_all() there, and remove resupply_commod().
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().
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.