GCC std::array uses std::size_t for its size_type. On Linux/amd64,
`std::size_t` is `unsigned long`. On Win32, `std::size_t` is
`unsigned int`. This provokes format string warnings because an
unsigned int is passed where the format string declares an unsigned
long. On Win32, `unsigned int` and `unsigned long` are the same size,
so `unsigned long` could have been used to avoid this problem by
maintaining consistency with Linux, but it was not. This may have been
an attempt to achieve bug compatibility with Microsoft's types.
Add a workaround by defining a macro DXX_PRI_size_type in the style of
inttypes.h PRI* macros. Use an SConf test to determine the correct
value by inspecting which compilation runs succeed. Currently, Linux
needs "l", Win32 needs "", and Win64 needs "I64".
Some tests may benefit from the results of earlier tests. Other tests
may give different results if the macros from earlier tests are defined.
SCons dependency checking rejects including dxxsconf.h during testing,
so save the results of self._check_macro and insert them into later
tests. Some tests define their macros in other ways. The macros from
those tests and are not yet inserted.
Boost enable_if works differently from std::enable_if, so the build is
broken when using Boost.TypeTraits. The broken code has been present
for a long time and no one reported it. Remove the fallback to Boost.
Previously, if the player was invulnerable, it was impossible to grab an
invulnerability powerup. Relax this by allowing a spawn-induced fake
invulnerability not to count as invulnerable for this test. Players
still cannot grab an invulnerability powerup if they are still under the
influence of a prior invulnerability powerup.
An optimizing compiler should inline these tests. Moving them out makes
the code easier to read, since the statements can focus on what is
updated, rather than how it is done.
Change the clearing of MultiLevelInv during initialization to reduce
wasted stores. MultiLevelInv has three fields.
Field ::Initial is not accessed by MultiLevelInv_CountLevelPowerups, and
is overwritten immediately afterward, so it does not need to be cleared
first.
Field ::Current is unconditionally cleared by
MultiLevelInv_CountLevelPowerups, so it does not need to be cleared
first.
Field ::RespawnTimer is not accessed by
MultiLevelInv_CountLevelPowerups, but needs to be cleared. Add a clear
of field .RespawnTimer and remove the clear of the entire structure.
All callers of MultiLevelInv_Count passed a constant value. Factor
out the top level blocks of MultiLevelInv_Count into helper functions,
then create two new functions corresponding to MultiLevelInv_Count(0)
and MultiLevelInv_Count(1), implemented by calling the appropriate new
helper functions.