diff --git a/generate_l_system.rb b/generate_l_system.rb new file mode 100644 index 0000000..538920f --- /dev/null +++ b/generate_l_system.rb @@ -0,0 +1,107 @@ +symbols = ['S'] + +# Generates a replacement rule. Returns ["rule string", [new used_symbols]] +def random_replacement_rule(all_symbols, used_symbols, rule_symbols) + # We can't redefine rule symbols. + return ["", used_symbols, rule_symbols] if used_symbols.length == rule_symbols.length + start = used_symbols.sample() + start = used_symbols.sample() while rule_symbols.include?(start) + rule_symbols << start + replacement_size = [2, 3, 3, 3, 4, 5].sample() + replacement = "" + replacement_size.times do + # Only choose a new symbol 1/3rd of the time. (Tehcnically less, since all + # symbols will include the used ones. + if (used_symbols.length < 3) || (rand() < 0.3) + symbol = all_symbols.sample() + used_symbols << symbol if !used_symbols.include?(symbol) + else + symbol = used_symbols.sample() + end + if rand() < 0.01 + # 1% of the time do a push & pop + replacement += "(" + symbol + ")" + else + replacement += symbol + end + end + rule_string = start + " " + replacement + [rule_string, used_symbols, rule_symbols] +end + +def get_move_action() + "move_forward %.03f" % [rand()] +end + +def get_rotate_action() + action = ["rotate", "pitch", "roll"].sample() + angle = 180.0 - (360.0 * rand()) + "%s %.03f" % [action, angle] +end + +def get_setcolor_action() + channel = ["r", "g", "b"].sample() + "set_color_%s %.03f" % [channel, rand()] +end + +# Returns an array of random action strings, NOT including push and pop. +def generate_random_actions() + moves = ["move"] * 6 + rotates = ["rotate"] * 4 + set_colors = ["set_color"] * 2 + action_types = moves + rotates + set_colors + actions_not_move = rotates + set_colors + to_return = [] + action_count = rand(8) + prev_was_move = false + action_count.times do + if prev_was_move + action_type = actions_not_move.sample() + else + action_type = action_types.sample() + end + prev_was_move = false + if action_type == "move" + prev_was_move = true + to_return << get_move_action() + elsif action_type == "rotate" + to_return << get_rotate_action() + elsif action_type == "set_color" + to_return << get_setcolor_action() + end + end + to_return +end + +# Don't include the start symbol in all_symbols +all_symbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".chars +used_symbols = ["S"] +rule_symbols = [] +puts "init S" +10.times do + tmp = random_replacement_rule(all_symbols, used_symbols, rule_symbols) + puts tmp[0] + used_symbols = tmp[1] + rule_symbols = tmp[2] +end + +puts "\nactions +( +push_color 0.0 +push_position 0.0 + +) +pop_color 0.0 +pop_position 0.0 + +" + +used_symbols.each do |s| + # Only generate actions for about 1/3rd of the symbols + next if rand() < 0.3 + puts "#{s}" + actions = generate_random_actions() + actions.each {|a| puts a} + puts "" +end + diff --git a/l_system_3d.c b/l_system_3d.c index e9893f8..cbbf6bf 100644 --- a/l_system_3d.c +++ b/l_system_3d.c @@ -184,6 +184,19 @@ static int IncreaseIterations(ApplicationState *s) { return 1; } +// Sets the current number of iterations to 0. Used after reloading the config. +static int SetIterationsTo0(ApplicationState *s) { + free(s->l_system_string); + s->l_system_string = (uint8_t *) strdup(s->config->init); + if (!s->l_system_string) { + printf("Failed copying the initial L-system string.\n"); + return 0; + } + s->l_system_length = strlen(s->config->init); + s->l_system_iterations = 0; + return 1; +} + // Reduces the L-system iterations by one. Unfortunately, this is implemented // by recomputing the entire thing. Does nothing if we're already at 0 // iterations. @@ -194,14 +207,7 @@ static int DecreaseIterations(ApplicationState *s) { return 1; } target_iterations = s->l_system_iterations - 1; - free(s->l_system_string); - s->l_system_string = (uint8_t *) strdup(s->config->init); - if (!s->l_system_string) { - printf("Failed copying the initial L-system string.\n"); - return 0; - } - s->l_system_length = strlen(s->config->init); - s->l_system_iterations = 0; + if (!SetIterationsTo0(s)) return 0; for (i = 0; i < target_iterations; i++) { if (!IncreaseIterations(s)) return 0; } @@ -222,6 +228,10 @@ static void ReloadConfig(ApplicationState *s) { s->config = new_config; DestroyLSystemConfig(old_config); printf("Config %s updated OK.\n", s->config_file_path); + if (!(SetIterationsTo0(s) && GenerateVertices(s))) { + printf("Failed re-generating image.\n"); + exit(1); + } } static void PrintMemoryUsage(ApplicationState *s) {