sand/include/sand.h
2026-04-21 18:31:38 -04:00

122 lines
2.4 KiB
C++

#ifndef SAND_H
#define SAND_H
#include <cstdint>
#include <functional>
#include <string>
#include <unordered_map>
#include <vector>
namespace sand
{
struct type
{
uint16_t id;
uint16_t default_result;
};
using type_map = std::unordered_map<std::string, type>;
class RulesBuilder;
class TypeBuilder
{
friend RulesBuilder;
public:
TypeBuilder();
TypeBuilder& add_type(const std::string& name);
TypeBuilder& add_type(const std::string& name,
const std::string& default_result);
RulesBuilder finish();
private:
uint16_t next_type_id = 0;
type_map types;
}; // class TypeBuilder
class Rule;
class Sand;
class RulesBuilder
{
friend TypeBuilder;
friend Rule;
friend Sand;
public:
Rule add_rule(const std::string& source_name, const std::string& to);
Sand build(uint16_t width, uint16_t height, const std::string& initial);
private:
RulesBuilder(const TypeBuilder& type_builder);
void finish_rule(const Rule& rule);
type_map types;
std::unordered_map<uint16_t,
std::vector<std::pair<unsigned __int128, uint16_t>>>
rules;
}; // class RulesBuilder
class Rule
{
friend RulesBuilder;
public:
using match_fn = std::function<bool(const std::string&)>;
~Rule();
Rule& top_left(match_fn match);
Rule& top_middle(match_fn match);
Rule& top_right(match_fn match);
Rule& middle_left(match_fn match);
Rule& middle_right(match_fn match);
Rule& bottom_left(match_fn match);
Rule& bottom_middle(match_fn match);
Rule& bottom_right(match_fn match);
private:
Rule(RulesBuilder& builder, uint16_t source, uint16_t to);
RulesBuilder& builder;
uint16_t source;
uint16_t to;
match_fn matches[8];
}; // class RuleBuilder
class Sand
{
friend RulesBuilder;
public:
void set(uint16_t x, uint16_t y, const std::string& type);
uint16_t get(uint16_t x, uint16_t y);
void update();
private:
Sand(const RulesBuilder& builder, uint16_t width, uint16_t height,
const std::string& initial);
uint16_t apply_rule(uint16_t tile, unsigned __int128 key) const;
static unsigned __int128 apply_mask(unsigned __int128 key, uint8_t mask);
uint16_t width;
uint16_t height;
type_map types;
std::unordered_map<uint16_t, uint16_t> default_conversions;
std::unordered_map<uint16_t,
std::vector<std::pair<unsigned __int128, uint16_t>>>
rules;
std::vector<uint16_t> elements;
bool iter;
}; // class Sand
} // namespace sand
#endif // SAND_H