https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109249
--- Comment #2 from Andre Schackier <andre.schackier at gmail dot com> ---
I'm soryy will keep that in mind for the future :)
Example #1:
#include <array>
#include <cstdint>
enum class Type {
None,
Bug,
Dark,
Dragon,
Electric,
Fighting,
Fire,
Flying,
Ghost,
Grass,
Ground,
Ice,
Normal,
Poison,
Psychic,
Rock,
Steel,
Water,
Count,
};
static constexpr const std::size_t NumberOfTypes =
static_cast<std::size_t>(Type::Count);
namespace detail {
constexpr float GetTypeDamageMultiplierImpl(Type defending_type,
Type attacking_type) noexcept {
switch (defending_type) {
case Type::None:
return 1.0f;
case Type::Bug:
switch (attacking_type) {
case Type::Fighting:
case Type::Grass:
case Type::Ground:
return 0.5f;
case Type::Fire:
case Type::Flying:
case Type::Rock:
return 2.0f;
default:
return 1.0f;
}
case Type::Dark:
switch (attacking_type) {
case Type::Psychic:
return 0.0f;
case Type::Dark:
case Type::Ghost:
return 0.5f;
case Type::Bug:
case Type::Fighting:
return 2.0f;
default:
return 1.0f;
}
case Type::Dragon:
switch (attacking_type) {
case Type::Electric:
case Type::Fire:
case Type::Grass:
case Type::Water:
return 0.5f;
case Type::Dragon:
case Type::Ice:
return 2.0f;
default:
return 1.0f;
}
case Type::Electric:
switch (attacking_type) {
case Type::Electric:
case Type::Flying:
case Type::Steel:
return 0.5f;
case Type::Ground:
return 2.0f;
default:
return 1.0f;
}
case Type::Fighting:
switch (attacking_type) {
case Type::Bug:
case Type::Dark:
case Type::Rock:
return 0.5f;
case Type::Flying:
case Type::Psychic:
return 2.0f;
default:
return 1.0f;
}
case Type::Fire:
switch (attacking_type) {
case Type::Bug:
case Type::Fire:
case Type::Grass:
case Type::Ice:
case Type::Steel:
return 0.5f;
case Type::Ground:
case Type::Rock:
case Type::Water:
return 2.0f;
default:
return 1.0f;
}
case Type::Flying:
switch (attacking_type) {
case Type::Ground:
return 0.0f;
case Type::Bug:
case Type::Fighting:
case Type::Grass:
return 0.5f;
case Type::Electric:
case Type::Ice:
case Type::Rock:
return 2.0f;
default:
return 1.0f;
}
case Type::Ghost:
switch (attacking_type) {
case Type::Normal:
case Type::Fighting:
return 0.0f;
case Type::Bug:
case Type::Poison:
return 0.5f;
case Type::Dark:
case Type::Ghost:
return 2.0f;
default:
return 1.0f;
}
case Type::Grass:
switch (attacking_type) {
case Type::Electric:
case Type::Grass:
case Type::Ground:
case Type::Water:
return 0.5f;
case Type::Bug:
case Type::Fire:
case Type::Flying:
case Type::Ice:
case Type::Poison:
return 2.0f;
default:
return 1.0f;
}
case Type::Ground:
switch (attacking_type) {
case Type::Electric:
return 0.0f;
case Type::Poison:
case Type::Rock:
return 0.5f;
case Type::Grass:
case Type::Ice:
case Type::Water:
return 2.0f;
default:
return 1.0f;
}
case Type::Ice:
switch (attacking_type) {
case Type::Ice:
return 0.5f;
case Type::Fighting:
case Type::Fire:
case Type::Rock:
case Type::Steel:
return 2.0f;
default:
return 1.0f;
}
case Type::Normal:
switch (attacking_type) {
case Type::Ghost:
return 0.0f;
case Type::Fighting:
return 2.0f;
default:
return 1.0f;
}
case Type::Poison:
switch (attacking_type) {
case Type::Fighting:
case Type::Poison:
case Type::Bug:
case Type::Grass:
return 0.5f;
case Type::Ground:
case Type::Psychic:
return 2.0f;
default:
return 1.0f;
}
case Type::Psychic:
switch (attacking_type) {
case Type::Fighting:
case Type::Psychic:
return 0.5f;
case Type::Bug:
case Type::Dark:
case Type::Ghost:
return 2.0f;
default:
return 1.0f;
}
case Type::Rock:
switch (attacking_type) {
case Type::Fire:
case Type::Flying:
case Type::Normal:
case Type::Poison:
return 0.5f;
case Type::Fighting:
case Type::Grass:
case Type::Ground:
case Type::Steel:
case Type::Water:
return 2.0f;
default:
return 1.0f;
}
case Type::Steel:
switch (attacking_type) {
case Type::Poison:
return 0.0f;
case Type::Bug:
case Type::Dark:
case Type::Dragon:
case Type::Flying:
case Type::Ghost:
case Type::Grass:
case Type::Ice:
case Type::Normal:
case Type::Psychic:
case Type::Rock:
case Type::Steel:
return 0.5f;
case Type::Fighting:
case Type::Fire:
case Type::Ground:
return 2.0f;
default:
return 1.0f;
}
case Type::Water:
switch (attacking_type) {
case Type::Fire:
case Type::Ice:
case Type::Steel:
case Type::Water:
return 0.5f;
case Type::Electric:
case Type::Grass:
return 2.0f;
default:
return 1.0f;
}
default:
__builtin_unreachable();
}
}
constexpr std::array<float, NumberOfTypes * NumberOfTypes>
GenerateTypeDamageTable() noexcept {
std::array<float, NumberOfTypes * NumberOfTypes> table{};
for (std::uint32_t defending_type{0u}; defending_type < NumberOfTypes;
++defending_type) {
for (std::uint32_t attacking_type{0u}; attacking_type < NumberOfTypes;
++attacking_type) {
table[defending_type * NumberOfTypes + attacking_type] =
GetTypeDamageMultiplierImpl(static_cast<Type>(defending_type),
static_cast<Type>(attacking_type));
}
}
return std::move(table);
}
} // namespace detail
float GetTypeDamageMultiplier(Type defending_type,
Type attacking_type) noexcept {
constexpr const auto table = detail::GenerateTypeDamageTable();
return table[static_cast<std::size_t>(defending_type) * NumberOfTypes +
static_cast<std::size_t>(attacking_type)];
}
Example #2:
#include <array>
#include <cstdint>
enum class Type {
None,
Bug,
Dark,
Dragon,
Electric,
Fighting,
Fire,
Flying,
Count,
};
static constexpr const std::size_t NumberOfTypes =
static_cast<std::size_t>(Type::Count);
namespace detail {
constexpr float GetTypeDamageMultiplierImpl(
const Type defending_type, const Type attacking_type) noexcept {
switch (defending_type) {
case Type::None:
return 1.0f;
case Type::Bug:
switch (attacking_type) {
case Type::Fighting:
return 0.5f;
case Type::Fire:
case Type::Flying:
return 2.0f;
default:
return 1.0f;
}
case Type::Dark:
switch (attacking_type) {
case Type::Dark:
return 0.5f;
case Type::Bug:
case Type::Fighting:
return 2.0f;
default:
return 1.0f;
}
case Type::Dragon:
switch (attacking_type) {
case Type::Electric:
case Type::Fire:
return 0.5f;
case Type::Dragon:
return 2.0f;
default:
return 1.0f;
}
case Type::Electric:
switch (attacking_type) {
case Type::Electric:
case Type::Flying:
return 0.5f;
default:
return 1.0f;
}
case Type::Fighting:
switch (attacking_type) {
case Type::Bug:
case Type::Dark:
return 0.5f;
case Type::Flying:
return 2.0f;
default:
return 1.0f;
}
case Type::Fire:
switch (attacking_type) {
case Type::Bug:
case Type::Fire:
return 0.5f;
default:
return 1.0f;
}
case Type::Flying:
switch (attacking_type) {
case Type::Bug:
case Type::Fighting:
return 0.5f;
case Type::Electric:
return 2.0f;
default:
return 1.0f;
}
default:
__builtin_unreachable();
}
}
constexpr std::array<float, NumberOfTypes * NumberOfTypes>
GenerateTypeDamageTable() noexcept {
std::array<float, NumberOfTypes * NumberOfTypes> table{};
for (std::uint32_t defending_type{0u}; defending_type < NumberOfTypes;
++defending_type) {
for (std::uint32_t attacking_type{0u}; attacking_type < NumberOfTypes;
++attacking_type) {
table[defending_type * NumberOfTypes + attacking_type] =
GetTypeDamageMultiplierImpl(static_cast<Type>(defending_type),
static_cast<Type>(attacking_type));
}
}
return std::move(table);
}
} // namespace detail
float GetTypeDamageMultiplier(const Type defending_type,
const Type attacking_type) noexcept {
constexpr const auto table = detail::GenerateTypeDamageTable();
return table[static_cast<std::size_t>(defending_type) * NumberOfTypes +
static_cast<std::size_t>(attacking_type)];
}