Compare commits
9 Commits
c357174e35
...
626486cadf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
626486cadf | ||
|
|
404faec921 | ||
|
|
2d1b318d0f | ||
|
|
a67fcac5fc | ||
|
|
8e6413e9ec | ||
|
|
0f3e857586 | ||
|
|
f1b6870dfd | ||
|
|
ee6daf36d7 | ||
|
|
00303ae3be |
@ -9,29 +9,34 @@
|
|||||||
|
|
||||||
namespace fractal {
|
namespace fractal {
|
||||||
|
|
||||||
|
constexpr size_t g_max_tokens = 16;
|
||||||
|
constexpr size_t g_max_groups = 8;
|
||||||
|
constexpr size_t g_max_wgroups = 4;
|
||||||
|
constexpr size_t g_max_branch_rules = 8;
|
||||||
|
constexpr size_t g_max_mark_rules = 4;
|
||||||
|
constexpr size_t g_max_cgroup_tokens = 16;
|
||||||
|
constexpr size_t g_max_wgroup_weights = 8;
|
||||||
|
|
||||||
using token_id_t = uint32_t;
|
using token_id_t = uint32_t;
|
||||||
using group_id_t = uint32_t;
|
using group_id_t = uint32_t;
|
||||||
using weighted_group_id_t = uint32_t;
|
using weighted_group_id_t = uint32_t;
|
||||||
using branch_rule_basic_id_t = uint32_t;
|
using branch_rule_id_t = uint32_t;
|
||||||
using branch_rule_marking_id_t = uint32_t;
|
using mark_rule_id_t = uint32_t;
|
||||||
|
|
||||||
enum class token_type_e {
|
enum class token_type_e {
|
||||||
none,
|
empty,
|
||||||
walk,
|
walk,
|
||||||
rotate,
|
rotate,
|
||||||
generate,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct token_t {
|
struct token_t {
|
||||||
token_type_e m_token = token_type_e::none;
|
token_type_e m_type = token_type_e::empty;
|
||||||
mtl::fixed m_value;
|
mtl::fixed m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct group_characteristic_t {
|
struct group_characteristic_t {
|
||||||
static constexpr size_t g_max_group_size = 32;
|
|
||||||
|
|
||||||
uint32_t m_factor; // Number of groups generated in succession
|
uint32_t m_factor; // Number of groups generated in succession
|
||||||
etl::vector<token_id_t, g_max_group_size> m_token_ids;
|
etl::vector<token_id_t, g_max_cgroup_tokens> m_token_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct marker_t {
|
struct marker_t {
|
||||||
@ -60,23 +65,174 @@ struct group_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct weighted_group_t {
|
struct weighted_group_t {
|
||||||
static constexpr size_t g_max_group_weights = 8;
|
etl::vector<group_id_t, g_max_wgroup_weights> m_groups;
|
||||||
|
etl::vector<uint32_t, g_max_wgroup_weights> m_weights;
|
||||||
etl::vector<group_id_t, g_max_group_weights> m_groups;
|
uint32_t m_weight_total; // Total needed for random selection
|
||||||
etl::vector<uint32_t, g_max_group_weights> m_weights;
|
// TODO: Control weight additions so m_weight_total = sum(m_weights) is invariant
|
||||||
uint32_t m_weight_total;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct branch_rule_basic_t {
|
struct branch_rule_t {
|
||||||
token_id_t m_match;
|
token_id_t m_match;
|
||||||
weighted_group_id_t m_weighted_group;
|
bool m_weighted;
|
||||||
|
|
||||||
|
union {
|
||||||
|
group_id_t basic;
|
||||||
|
weighted_group_id_t weighted;
|
||||||
|
} m_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct branch_rule_marking_t {
|
struct mark_rule_t {
|
||||||
token_id_t m_match;
|
token_id_t m_match;
|
||||||
uint32_t m_marker_id;
|
uint32_t m_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ruleset_t {
|
||||||
|
private:
|
||||||
|
etl::vector<token_t, g_max_tokens> m_tokens;
|
||||||
|
etl::vector<group_characteristic_t, g_max_groups> m_group_characteristics;
|
||||||
|
etl::vector<weighted_group_t, g_max_wgroups> m_weighted_groups;
|
||||||
|
|
||||||
|
etl::vector<branch_rule_t, g_max_branch_rules> m_branch_rules;
|
||||||
|
etl::vector<mark_rule_t, g_max_mark_rules> m_mark_rules;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Checks if the maximum number of tokens has been reached
|
||||||
|
*
|
||||||
|
* @ret @c true if the number of tokens in the ruleset equals @c g_max_tokens, @c false otherwise
|
||||||
|
*/
|
||||||
|
bool tokens_full() const {
|
||||||
|
return m_tokens.full();
|
||||||
|
}
|
||||||
|
bool valid_token(token_id_t tok) const {
|
||||||
|
return tok < m_tokens.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add new token variable that can be used in this ruleset
|
||||||
|
*
|
||||||
|
* @param type Type of the token to add
|
||||||
|
* @param value Value of the token, unused if @p type is @c token_type_e::empty
|
||||||
|
*
|
||||||
|
* @ret @c token_id_t of the newly added token, local to this ruleset
|
||||||
|
*
|
||||||
|
* @exception @c mtl::length_error if the maximum number of tokens is reached
|
||||||
|
*/
|
||||||
|
token_id_t add_token(token_type_e type, mtl::fixed value = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the maximum number of group characteristics has been reached
|
||||||
|
*
|
||||||
|
* @ret @c true if the number of group characteristics in the ruleset equals @c g_max_cgroups, @c false otherwise
|
||||||
|
*/
|
||||||
|
bool group_characteristics_full() const {
|
||||||
|
return m_group_characteristics.full();
|
||||||
|
}
|
||||||
|
bool valid_group_characteristic(group_id_t group) const {
|
||||||
|
return group < m_group_characteristics.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add new group characteristic
|
||||||
|
*
|
||||||
|
* @param tokens @c etl::ivector of @c token_id_t that should be generated inside this group
|
||||||
|
* @param factor The number of times the group's tokens are repeatedly generated
|
||||||
|
*
|
||||||
|
* @ret @c group_id_t of the newly added group characteristic, local to this ruleset
|
||||||
|
*
|
||||||
|
* @exception mtl::invalid_argument if an invalid token was encountered
|
||||||
|
* @exception mtl::length_error if the maximum number of groups is reached
|
||||||
|
*/
|
||||||
|
group_id_t add_group_characteristic(const etl::ivector<token_id_t>& tokens, uint32_t factor = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the maximum number of weighted groups has been reached
|
||||||
|
*
|
||||||
|
* @ret @c true if the number of weighted groups in the ruleset equals @c g_max_wgroups, @c false otherwise
|
||||||
|
*/
|
||||||
|
bool weighted_groups_full() const {
|
||||||
|
return m_weighted_groups.full();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add new weighted group
|
||||||
|
*
|
||||||
|
* Adds weighted group of groups, where each subgroup has a
|
||||||
|
* <tt>(weight) / (total weight)</tt> chance of being selected. Weights
|
||||||
|
* are represented as @c uint32_t.
|
||||||
|
*
|
||||||
|
* @param weights @c etl::ivector of @c etl::pair of @c group_id_t and their corresponding weights
|
||||||
|
*
|
||||||
|
* @ret @c weighted_group_id_t of the newly created group
|
||||||
|
*
|
||||||
|
* @exception @c mtl::invalid_argument if no groups were supplied, or an invalid group was encountered
|
||||||
|
* @exception @c mtl::length_error if the maximum number of groups is reached
|
||||||
|
*/
|
||||||
|
weighted_group_id_t add_weighted_group(const etl::ivector<etl::pair<group_id_t, uint32_t>>& weights);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the maximum number of branch rules has been reached
|
||||||
|
*
|
||||||
|
* @ret @c true if the number of branch rules in the ruleset equals @c g_max_branch_rules, @c false otherwise
|
||||||
|
*/
|
||||||
|
bool branch_rules_full() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a new unweighted branch rule to the ruleset
|
||||||
|
*
|
||||||
|
* Branch rules describe what groups can be generated given a token.
|
||||||
|
* Branch rules can use either plain groups or weighted groups as their output.
|
||||||
|
*
|
||||||
|
* @param match Token to match and generate the group in place of
|
||||||
|
* @param group Group to generate
|
||||||
|
*
|
||||||
|
* @ret @c branch_rule_id_t of the newly added branch rule
|
||||||
|
*
|
||||||
|
* @exception @c mtl::invalid_argument if an invalid token or group was supplied
|
||||||
|
* @exception @c mtl::length_error if the maximum number of branch rules was reached
|
||||||
|
*/
|
||||||
|
branch_rule_id_t add_branch_rule(token_id_t match, group_id_t group);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a new weighted branch rule to the ruleset
|
||||||
|
*
|
||||||
|
* Branch rules describe what groups can be generated given a token.
|
||||||
|
* Branch rules can use either plain groups or weighted groups as their output.
|
||||||
|
*
|
||||||
|
* @param match Token to match and generate the group in place of
|
||||||
|
* @param wgroup Weighted group to select from, only one subgroup is generated
|
||||||
|
*
|
||||||
|
* @ret @c branch_rule_id_t of the newly added branch rule
|
||||||
|
*
|
||||||
|
* @exception @c mtl::invalid_argument if an invalid token or group was supplied
|
||||||
|
* @exception @c mtl::length_error if the maximum number of branch rules was reached
|
||||||
|
*/
|
||||||
|
branch_rule_id_t add_branch_rule_weighted(token_id_t match, weighted_group_id_t wgroup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the maximum number of mark rules has been reached
|
||||||
|
*
|
||||||
|
* @ret @c true if the number of mark rules in the ruleset equals @c g_max_mark_rules, @c false otherwise
|
||||||
|
*/
|
||||||
|
bool mark_rules_full() const;
|
||||||
|
|
||||||
|
/** @brief Add a new marking rule to the ruleset
|
||||||
|
*
|
||||||
|
* Mark rules describe what tokens should have their positions output
|
||||||
|
* each generation. If a token has a match, its position and a tag is output.
|
||||||
|
*
|
||||||
|
* @param match Token to match and mark
|
||||||
|
* @param tag Marking identifier, does not need to be unique
|
||||||
|
*
|
||||||
|
* @ret @c mark_rule_id_t of the newly added mark rule
|
||||||
|
*
|
||||||
|
* @exception @c mtl::invalid_argument if an invalid token was supplied
|
||||||
|
* @exception @c mtl::length_error if the maximum number of mark rules was reached
|
||||||
|
*/
|
||||||
|
mark_rule_id_t add_mark_rule(token_id_t match, uint32_t tag);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
class generator_t {
|
class generator_t {
|
||||||
private:
|
private:
|
||||||
static constexpr size_t g_max_groups = 32;
|
static constexpr size_t g_max_groups = 32;
|
||||||
@ -291,6 +447,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool step_generation(const etl::ivector<marker_t>& out_markers) noexcept;
|
bool step_generation(const etl::ivector<marker_t>& out_markers) noexcept;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace fractal
|
} // namespace fractal
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,65 @@ namespace log = mtl::log;
|
|||||||
|
|
||||||
namespace fractal {
|
namespace fractal {
|
||||||
|
|
||||||
|
token_id_t ruleset_t::add_token(token_type_e type, mtl::fixed value) {
|
||||||
|
if (m_tokens.full()) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
token_t tok { .m_type = type, .m_value = value };
|
||||||
|
|
||||||
|
m_tokens.push_back(tok);
|
||||||
|
return m_tokens.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
group_id_t ruleset_t::add_group_characteristic(const etl::ivector<token_id_t>& tokens, uint32_t factor) {
|
||||||
|
if (m_group_characteristics.full()) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
if (tokens.size() > g_max_cgroup_tokens) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_group_characteristics.push_back(group_characteristic_t());
|
||||||
|
group_characteristic_t& chr = m_group_characteristics.back();
|
||||||
|
chr.m_factor = factor;
|
||||||
|
|
||||||
|
for (token_id_t tok : tokens) {
|
||||||
|
if (!valid_token(tok)) {
|
||||||
|
throw mtl::invalid_argument();
|
||||||
|
}
|
||||||
|
|
||||||
|
chr.m_token_ids.push_back(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_group_characteristics.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
weighted_group_id_t ruleset_t::add_weighted_group(const etl::ivector<etl::pair<group_id_t, uint32_t>>& weights) {
|
||||||
|
if (m_weighted_groups.full()) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
if (weights.size() > g_max_wgroup_weights) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_weighted_groups.push_back(weighted_group_t());
|
||||||
|
weighted_group_t& wgroup = m_weighted_groups.back();
|
||||||
|
|
||||||
|
for (const auto& weight : weights) {
|
||||||
|
if (!valid_group_characteristic(weight.first)) {
|
||||||
|
throw mtl::invalid_argument();
|
||||||
|
}
|
||||||
|
|
||||||
|
wgroup.m_groups.push_back(weight.first);
|
||||||
|
wgroup.m_weights.push_back(weight.second);
|
||||||
|
wgroup.m_weight_total += weight.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_weighted_groups.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
token_id_t generator_t::add_token(token_type_e type, mtl::fixed value) {
|
token_id_t generator_t::add_token(token_type_e type, mtl::fixed value) {
|
||||||
log::debug << "Adding token with type " << (int)type << endl;
|
log::debug << "Adding token with type " << (int)type << endl;
|
||||||
|
|
||||||
@ -199,6 +258,7 @@ void generator_t::set_initial_orientation(mtl::fixed orientation) noexcept {
|
|||||||
|
|
||||||
bool generator_t::step_generation(const etl::ivector<marker_t>& out_markers) noexcept {
|
bool generator_t::step_generation(const etl::ivector<marker_t>& out_markers) noexcept {
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace fractal
|
} // namespace fractal
|
||||||
|
|
||||||
|
|||||||
88
src/main.cpp
88
src/main.cpp
@ -8,92 +8,56 @@
|
|||||||
#include "fractal.hpp"
|
#include "fractal.hpp"
|
||||||
|
|
||||||
using namespace mtl;
|
using namespace mtl;
|
||||||
|
using namespace fractal;
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
REG_DISPCNT = DCNT_MODE3 | DCNT_BG2;
|
REG_DISPCNT = DCNT_MODE3 | DCNT_BG2;
|
||||||
|
|
||||||
log::debug << "Hello world!" << mtl::endl;
|
log::debug << "Hello world!" << mtl::endl;
|
||||||
|
|
||||||
fractal::generator_t gen;
|
ruleset_t rules;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fractal::token_id_t walk_petal_length = gen.add_token(fractal::token_type_e::walk, 8);
|
fixed branch_angle = M_PI_4;
|
||||||
fractal::token_id_t walk_petal_side = gen.add_token(fractal::token_type_e::walk, 4);
|
|
||||||
|
|
||||||
fractal::token_id_t rotate_axiom = gen.add_token(fractal::token_type_e::rotate, M_PI_2);
|
token_id_t walk_petal_length = rules.add_token(token_type_e::walk, 8);
|
||||||
fractal::token_id_t rotate_petal = gen.add_token(fractal::token_type_e::rotate, M_PI_2);
|
token_id_t walk_petal_side = rules.add_token(token_type_e::walk, 4);
|
||||||
fractal::token_id_t rotate_branchr = gen.add_token(fractal::token_type_e::rotate, -M_PI_4);
|
|
||||||
fractal::token_id_t rotate_branchl = gen.add_token(fractal::token_type_e::rotate, +M_PI_4);
|
|
||||||
|
|
||||||
fractal::token_id_t generate_seed = gen.add_token(fractal::token_type_e::generate);
|
token_id_t rotate_axiom = rules.add_token(token_type_e::rotate, M_PI_2);
|
||||||
fractal::token_id_t generate_petal = gen.add_token(fractal::token_type_e::generate);
|
token_id_t rotate_petal = rules.add_token(token_type_e::rotate, M_PI_2);
|
||||||
fractal::token_id_t generate_branchr = gen.add_token(fractal::token_type_e::generate);
|
token_id_t rotate_branchr = rules.add_token(token_type_e::rotate, branch_angle);
|
||||||
fractal::token_id_t generate_branchl = gen.add_token(fractal::token_type_e::generate);
|
token_id_t rotate_branchl = rules.add_token(token_type_e::rotate, branch_angle * -2);
|
||||||
fractal::token_id_t generate_mark = gen.add_token(fractal::token_type_e::generate);
|
|
||||||
|
token_id_t branch = rules.add_token(token_type_e::empty);
|
||||||
|
token_id_t petal = rules.add_token(token_type_e::empty);
|
||||||
|
token_id_t mark = rules.add_token(token_type_e::empty);
|
||||||
|
|
||||||
log::info << "Added tokens" << endl;
|
log::info << "Added tokens" << endl;
|
||||||
|
|
||||||
constexpr uint32_t axiom_factor = 4;
|
uint32_t axiom_factor = 4;
|
||||||
constexpr uint32_t branchr_factor = 1;
|
|
||||||
constexpr uint32_t branchl_factor = 1;
|
|
||||||
|
|
||||||
etl::vector axiom_characteristic{generate_seed, rotate_axiom};
|
etl::vector axiom_chr{ branch, rotate_axiom };
|
||||||
fractal::group_id_t group_axiom = gen.add_group_characteristic(axiom_factor, axiom_characteristic);
|
group_id_t axiom_grp = rules.add_group_characteristic(axiom_chr, axiom_factor);
|
||||||
|
|
||||||
etl::vector seed_characteristic{generate_petal, generate_branchl, generate_branchr};
|
etl::vector branch_chr{ petal, rotate_branchr, branch, rotate_branchl, branch };
|
||||||
fractal::group_id_t group_seed = gen.add_group_characteristic(seed_characteristic);
|
group_id_t branch_grp = rules.add_group_characteristic(branch_chr);
|
||||||
|
|
||||||
etl::vector petal_characteristic{generate_mark, walk_petal_length, generate_mark, rotate_petal, walk_petal_side, generate_mark};
|
etl::vector petal_chr{ mark, walk_petal_length, mark, rotate_petal, walk_petal_length, mark };
|
||||||
fractal::group_id_t group_petal = gen.add_group_characteristic(petal_characteristic);
|
group_id_t petal_grp = rules.add_group_characteristic(petal_chr);
|
||||||
|
|
||||||
etl::vector branchl_characteristic{rotate_branchl, generate_seed};
|
|
||||||
fractal::group_id_t group_branchl = gen.add_group_characteristic(branchl_factor, branchl_characteristic);
|
|
||||||
|
|
||||||
etl::vector branchr_characteristic{rotate_branchr, generate_seed};
|
|
||||||
fractal::group_id_t group_branchr = gen.add_group_characteristic(branchr_factor, branchr_characteristic);
|
|
||||||
|
|
||||||
log::info << "Added group characteristics" << endl;
|
log::info << "Added group characteristics" << endl;
|
||||||
|
|
||||||
etl::vector<etl::pair<fractal::group_id_t, uint32_t>, 1> axiom_weights{{group_axiom, 1}};
|
rules.add_branch_rule(branch, branch_grp);
|
||||||
fractal::weighted_group_id_t wgroup_axiom = gen.add_weighted_group(axiom_weights);
|
rules.add_branch_rule(petal, petal_grp);
|
||||||
|
rules.add_mark_rule(mark, 1);
|
||||||
|
|
||||||
fractal::weighted_group_id_t wgroup_seed = gen.add_weighted_group(group_seed);
|
log::info << "Added rules" << endl;
|
||||||
fractal::weighted_group_id_t wgroup_petal = gen.add_weighted_group(group_petal);
|
log::info << "Finished configuring ruleset" << endl;
|
||||||
fractal::weighted_group_id_t wgroup_branchl = gen.add_weighted_group(group_branchl);
|
|
||||||
fractal::weighted_group_id_t wgroup_branchr = gen.add_weighted_group(group_branchr);
|
|
||||||
|
|
||||||
log::info << "Added weighted groups" << endl;
|
|
||||||
|
|
||||||
gen.add_basic_branch_rule(generate_seed, wgroup_seed);
|
|
||||||
gen.add_basic_branch_rule(generate_petal, wgroup_petal);
|
|
||||||
gen.add_basic_branch_rule(generate_branchl, wgroup_branchl);
|
|
||||||
gen.add_basic_branch_rule(generate_branchr, wgroup_branchr);
|
|
||||||
gen.add_marking_branch_rule(generate_mark, 1);
|
|
||||||
|
|
||||||
log::info << "Added branch rules" << endl;
|
|
||||||
|
|
||||||
gen.set_axiom(wgroup_axiom);
|
|
||||||
|
|
||||||
log::info << "Successfully added generator values" << endl;
|
|
||||||
} catch(const mtl::exception&) {
|
} catch(const mtl::exception&) {
|
||||||
log::info << "Failed to create generator, caught exception" << endl;
|
log::info << "Failed to configure ruleset, caught exception" << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*gen.preprocess();
|
|
||||||
|
|
||||||
constexpr uint32_t num_generations = 3;
|
|
||||||
constexpr size_t max_markers = 128;
|
|
||||||
|
|
||||||
etl::vector<fractal::marker_t, max_markers> markers;
|
|
||||||
for (size_t i = 0; i < num_generations; ++i) {
|
|
||||||
markers.clear();
|
|
||||||
|
|
||||||
gen.step_generation(markers);
|
|
||||||
|
|
||||||
//draw_triangles(markers);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
vid_vsync();
|
vid_vsync();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user