This takes care of a number of bugs / inconsistencies:
* Ships with zero firing range could return fire and fire support, but
not fire actively or interdict. Fix by testing for gun limit
instead in multifire() and mission(). No ships in the stock game
are affected.
* Required gun crew was inconsistent: multifire() let N military fire
max(1,floor(N/2)) guns for active fire. Ditto perform_mission() for
interdiction. quiet_bigdef() let them fire N guns for returning gun
fire. Ditto sd() for firing support and firing at boarding parties.
fire_dchrg() let them fire floor(N/2) for returning fire to
torpedoes. Unify to let N military fire floor((N+1)/2) guns.
* Shell use was inconsistent: sd() and perform_mission() used one
shell per gun, everything else one per two guns. Unify to one shell
per two guns.
* Shell resupply bugs: multifire() got two shells regardless of actual
ammo use. quiet_bigdef() got one shell (but use_ammo() uses only
one, which is a bug). sd() and perform_mission() resupplied before
checking all other requirements and could thus get more shells than
actually needed.
Before 4.0.6, depth charges required no guns, one military, did damage
like shell fire from two guns, and used two shells. Missions were not
quite consistent with that (bug). 4.0.6 changed depth charges to work
exactly like shell fire (but without updating documentation
accordingly): require guns and gun crew, non-zero firing range, scale
damage and ammunition use with guns.
Go back to the old model, but with damage like three guns, to avoid
changing the stock game's dd now (three gun damage for two shells).
Stock game's af changes from two gun damage for one shell, and nas
from four gun damage for two shells.
Factor out common depth-charging code into shp_dchrg().
This takes care of a number of bugs / inconsistencies:
* sb() fired support even when there were not enough mil.
* Shell resupply bugs: multifire() and quiet_bigdef() resupplied
shells before checking all other requirements and could thus get
more shells than actually needed.
Rename landgun() to fortgun() for consistency.
The macros defining unit stat development in tech are somewhat
inconvenient to use. Define more convenient functions, and hide away
the macros near the function definitions.
If gcc's preprocessor chokes, it leaves an empty dependency file
behind, and doesn't touch the object file. If an old object file
exists, and is newer than the .c file, make will then consider the
object file up-to-date. This can lead to nasty version errors.
delete_old_news() and init_nreport() tested for non-zero nws_when,
which is breaks for news at the epoch. Not likely to happen, but
still wrong.
ncache() tested nws_uid, which breaks for the first entry in the news
file. This made ncache() overlook that entry in the cache, and create
a new news item instead of incrementing nws_ntm. Was always broken
that way.
Fix by testing nws_vrb instead.
The call of ef_ensure_space() serves no purpose: the blank records it
adds are ignored on read, and overwritten (not updated) by new news.
Get rid of it.
Only treaty extension initialized ef_type and uid properly. None of
them zeroed unused members and holes in the struct. comm and trade
extension called ef_extend(), which had no effect, so remove that.
New struct emptypedstr to avoid depending on empobj.h there.
Remove now superfluous manual initializations elsewhere.
This doesn't fix any missing initializations.
Make sure all members of unit empobj_storage share uid in addition to
ef_type.
Add matching uid member to struct gamestr, struct natstr and struct
sctstr, and set them.
Swap struct empobj members uid and own to make that easier, and update
struct comstr, struct lndstr, struct lonstr, struct loststr, struct
nwsstr, struct nukstr, struct plnstr, struct realmstr, struct shpstr,
struct trdstr, struct trtstr accordingly.
Note that the uid isn't properly set for struct nwsstr, struct lonstr,
struct trdstr, struct comstr and struct loststr. To be fixed.
The get_FOOp() macros are generally avoided outside the update,
because direct access to the sector cache needs synchronization to be
safe. unit_map() didn't access the cache directly until it was
converted from get_ship() & friends to get_empobjp() in commit
fec9878c. Switching to get_empobj() reverts the change to direct
access while keeping the simplification.
There's no technical reason for rejecting sector access by id. It's
unusual, but not wrong.
Also remove the superfluous test for EF_BAD; ef_ptr() covers that.
put_empobj() used struct empobj member uid, which is valid only for
units. Existing users pass only units, fortunately. Fix by making it
take type and uid parameters.
This led to a bogus message when an interactive explore moved onto a
bridge and got prompted, the bridge was destroyed, and the player
stopped the explore "on the water".
get_empobj_chr() and emp_obj_chr_name() access struct sctstr member
sct_type through struct empobj member type. This is technically
non-portable, because the two differ in signedness. It was also
undocumented. Fix by making sct_type signed. sct_newtype as well,
for consistency.
map_char() uses unsigned char for a sector type argument. Change that
to int. Matches how this is done elsewhere.
Use ef_ensure_space() in getobj(). This also makes sure objects are
properly initialized before undumping writes to them.
Clean up how sentinels are appended: instead of keeping its slot
reserved while undumping, keep it in the table, and strip it off when
done.
ef_extend() extended the file bypassing the cache, which screws up the
cache if it's EFF_MEM. It fixed that by closing and reopening the
table. Cheesy, and worked only for file-backed tables.
Rewrite ef_extend() to remap the cache properly for EFF_MEM. While
there, simplify the !EFF_MEM case: steal a cache slot instead of
allocating a buffer.
Factor cache mapping out of ef_open() and ef_extend() into new
ef_realloc_cache().
Read-only was a bit of a misnomer: you could write to the table by
obtaining a pointer into it from ef_ptr(), you just couldn't write to
the backing file.
Semantic changes:
* ef_flush() is now allowed when the table is file-backed or privately
mapped. Before, it had to be file-backed. Flushing a privately
mapped table does nothing, just like flushing a read-only table did.
* ef_write() is now allowed when the table is file-backed or fully
cached. Before, it had to be file-backed and not read-only.
Writing to a privately mapped file-backed table doesn't write to the
file.
* ef_extend() is not implemented for privately mapped tables, just
like it wasn't implemented for read-only tables.