122 lines
2.4 KiB
C++
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
|