s2ga/s2ga.hpp

153 lines
4.1 KiB
C++
Raw Normal View History

2025-03-09 23:28:43 +03:00
#include <random>
2025-03-12 18:49:28 +03:00
#include <bitset>
#include <magic_enum/magic_enum.hpp>
#include <type_traits>
#include <iostream>
#include <format>
2025-03-09 23:28:43 +03:00
namespace s2ga
2025-03-08 20:37:26 +03:00
{
2025-03-09 23:28:43 +03:00
template<class... T>
struct always_false: std::false_type
{
};
class lehmer64
{
public:
lehmer64(__uint128_t seed = 0)
{
this->seed(seed);
}
void seed(__uint128_t z)
{
if(z == 0)
{
z = 0xC0FFEE;
}
s = z;
}
uint64_t operator()() noexcept
{
s *= 0xda942042e4dd58b5;
return s >> 64;
}
static constexpr uint64_t min()
{
return 0;
}
2025-03-08 20:37:26 +03:00
2025-03-09 23:28:43 +03:00
static constexpr uint64_t max()
{
return UINT64_MAX;
}
template<typename T>
T random(T min, T max)
{
if constexpr(std::is_integral_v<T>)
{
return std::uniform_int_distribution<T>(min, max)(*this);
}
else if constexpr(std::is_floating_point_v<T>)
{
return std::uniform_real_distribution<T>(min, max)(*this);
}
else
{
static_assert(always_false<T>::value,
"unsupported distribution type");
}
}
private:
__uint128_t s;
};
static_assert(std::uniform_random_bit_generator<lehmer64>);
2025-03-12 18:49:28 +03:00
template<typename E, typename... Args>
requires std::is_enum_v<E> && ((std::is_same_v<E, Args>), ...)
std::bitset<magic_enum::enum_count<E>()> bm(const Args&... v) //aka "bitmask"
{
constexpr size_t N = magic_enum::enum_count<E>();
std::bitset<N> bitmask;
((bitmask.set(magic_enum::enum_integer(v))), ...);
return bitmask;
}
template<typename E>
requires std::is_enum_v<E>
struct action
{
static constexpr size_t N = magic_enum::enum_count<E>();
std::string name = "ACTION";
float cost = 1.0f;
std::bitset<N> positive_effects{};
std::bitset<N> negative_effects{};
std::bitset<N> positive_preconds{};
std::bitset<N> negative_preconds{};
bool preconds_met(const std::bitset<N>& state) const
{
return ((state & positive_preconds) == positive_preconds) &&
(state & ~negative_preconds).none();
}
std::bitset<N> apply(const std::bitset<N>& state) const
{
return (state | positive_effects) & ~negative_effects;
}
void print()
{
std::cout << std::format("[{}, {}]", name, cost) << std::endl;
if(positive_effects.any() || negative_effects.any())
{
std::cout << "Effects:" << std::endl;
for(size_t i = 0; i < N; ++i)
{
if(positive_effects.test(i) || negative_effects.test(i))
{
auto enum_value = magic_enum::enum_cast<E>(i).value();
auto value_name = magic_enum::enum_name(enum_value);
std::cout << std::format(" {}{}",
negative_effects.test(i) ? "-" : "+",
value_name) << std::endl;
}
}
}
if(positive_preconds.any() || negative_preconds.any())
{
std::cout << "Preconditions:" << std::endl;
for(size_t i = 0; i < N; ++i)
{
if(positive_preconds.test(i) || negative_preconds.test(i))
{
auto enum_value = magic_enum::enum_cast<E>(i).value();
auto value_name = magic_enum::enum_name(enum_value);
std::cout << std::format(" {}{}",
negative_preconds.test(i) ? "-" : "+",
value_name) << std::endl;
}
}
}
}
};
2025-03-09 23:28:43 +03:00
}; // namespace s2ga
inline void foo()
{
2025-03-08 20:37:26 +03:00
}