feat: continuing grammar

This commit is contained in:
Sara Gerretsen 2026-03-30 00:52:51 +02:00
parent e4c41bbeda
commit 31c1c4cfbe
5 changed files with 80 additions and 19 deletions

View file

@ -7,7 +7,30 @@ void Generator::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, state, PROPERTY_HINT_RESOURCE_TYPE, "Sentence");
}
void Generator::initialise_state() {
for (int i{ 0 }; i < this->state->symbols.size(); ++i) {
this->state->symbols.set(i, NonTerminals::Undefined);
}
for (int i{ 0 }; i < this->state->size.x; ++i) {
this->state->set_at({ i, 0 }, NonTerminals::Blocked);
this->state->set_at({ i, this->state->size.y - 1 }, NonTerminals::Blocked);
}
for (int i{ 0 }; i < this->state->size.y; ++i) {
this->state->set_at({ 0, i }, NonTerminals::Blocked);
this->state->set_at({ this->state->size.x - 1, i }, NonTerminals::Blocked);
}
int y{ (int)Math::rand() % this->state->size.y - 4 };
for (int i{ 1 }; i < this->state->size.x - 1; ++i) {
this->state->set_at({ i, y }, NonTerminals::Path);
}
this->state->set_at({ 0, y }, NonTerminals::Start);
this->state->set_at({ this->state->size.x - 1, y }, NonTerminals::Goal);
}
void Generator::ready() {
initialise_state();
// TODO: repeat until terminal state
this->rule->try_apply(this->state);
}
void Generator::_notification(int what) {

View file

@ -6,6 +6,7 @@
class Generator : public Node3D {
GDCLASS(Generator, Node3D);
static void _bind_methods();
void initialise_state();
void ready();
protected:

View file

@ -4,8 +4,8 @@
#include "macros.h"
void Sentence::_bind_methods() {
BIND_HPROPERTY(Variant::STRING, symbols_string, PROPERTY_HINT_MULTILINE_TEXT);
BIND_PROPERTY(Variant::VECTOR2I, size);
BIND_HPROPERTY(Variant::STRING, symbols_string, PROPERTY_HINT_MULTILINE_TEXT);
}
bool Sentence::is_terminal() const {
@ -58,7 +58,7 @@ void Sentence::set_symbols_string(String value) {
int size{ this->size.x * this->size.y };
int writer{ 0 };
for (int reader{ 0 }; writer < size; ++reader) {
char32_t c{ value.length() >= reader ? value[reader] : (char32_t)'B' };
char32_t c{ reader < value.length() ? value[reader] : (char32_t)'B' };
if (c != '\n') {
this->symbols.set(writer, c);
++writer;
@ -81,9 +81,6 @@ void Sentence::set_size(Vector2i value) {
this->size = value;
this->symbols.clear();
this->symbols.resize_initialized(this->size.x * this->size.y);
for (int i{ 0 }; i < this->symbols.size(); ++i) {
this->symbols.set(i, 'B');
}
}
Vector2i Sentence::get_size() const {
@ -112,10 +109,11 @@ void CompositeRule::try_apply(Ref<Sentence> sentence) {
void ReplaceRule::_bind_methods() {
BIND_HPROPERTY(Variant::OBJECT, pattern, PROPERTY_HINT_RESOURCE_TYPE, Sentence::get_class_static());
BIND_HPROPERTY(Variant::OBJECT, result, PROPERTY_HINT_RESOURCE_TYPE, Sentence::get_class_static());
BIND_HPROPERTY(Variant::DICTIONARY, results_dict, PROPERTY_HINT_DICTIONARY_TYPE, vformat("%s/%s:%s;float", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, Sentence::get_class_static()));
}
void ReplaceRule::try_apply(Ref<Sentence> sentence) {
ERR_FAIL_COND_EDMSG(this->results.size() == 0, "ReplaceRule::try_apply failed, no results in list");
Vector2i max{ sentence->get_size() - this->pattern->get_size() };
if (max.x < 0 || max.y < 0) {
return; // cannot continue, no area in sentence big enough
@ -123,13 +121,32 @@ void ReplaceRule::try_apply(Ref<Sentence> sentence) {
for (Vector2i pos{ 0, 0 }; pos.y < max.y; ++pos.y) {
for (; pos.x < max.x; ++pos.x) {
if (sentence->check_match_at(pos, this->pattern)) {
sentence->write_subsentence(pos, this->result);
sentence->write_subsentence(pos, this->results[Math::rand() % this->results.size()].first); // TODO pick based on weighed random
}
}
pos.x = 0;
}
}
void ReplaceRule::set_results_dict(Dictionary dict) {
this->results.clear();
for (KeyValue<Variant, Variant> var : dict) {
Ref<Sentence> key{ var.key };
if (key.is_valid() && var.value.is_num()) {
float value{ var.value };
this->results.push_back({ key, value });
}
}
}
Dictionary ReplaceRule::get_results_dict() const {
Dictionary dict;
for (KeyValue<Ref<Sentence>, float> kvp : this->results) {
dict[kvp.key] = kvp.value;
}
return dict;
}
void ResizeRule::_bind_methods() {
BIND_PROPERTY(Variant::INT, factor);
}

View file

@ -7,15 +7,20 @@ typedef char32_t Symbol;
namespace NonTerminals {
enum : Symbol {
Start = 'S',
Blocked = 'B',
Invalid = '!',
Start = L'S',
Goal = L'G',
Undefined = L'U',
Path = L'P',
Blocked = L'B',
Invalid = L'!',
};
};
namespace Terminals {
enum : Symbol {
Invalid = '!',
Invalid = L'!',
Wall = L'w',
Path = L'p'
};
};
@ -76,11 +81,14 @@ public:
private:
Ref<Sentence> pattern{};
Ref<Sentence> result{};
Vector<Pair<Ref<Sentence>, float>> results{};
public:
GET_SET_FNS(Ref<Sentence>, pattern);
GET_SET_FNS(Ref<Sentence>, result);
void set_results(Vector<Pair<Ref<Sentence>, float>> value) { this->results = value; }
Vector<Pair<Ref<Sentence>, float>> get_results() { return this->results; }
void set_results_dict(Dictionary value);
Dictionary get_results_dict() const;
};
class ResizeRule : public CompositeRule {

View file

@ -1,12 +1,23 @@
[gd_scene format=3 uid="uid://cak2tf2adjv8j"]
[sub_resource type="Sentence" id="Sentence_bb2w7"]
symbols_string = "BBBBB
BBBBB
BBBBB
BBBBB
BBBBB"
size = Vector2i(5, 5)
size = Vector2i(10, 10)
symbols_string = "BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB
BBBBBBBBBB"
[sub_resource type="Sentence" id="Sentence_wail4"]
size = Vector2i(3, 3)
symbols_string = "BBB
BBB
BBB"
[node name="Dungeon" type="Node3D" unique_id=719313039]
@ -14,3 +25,4 @@ size = Vector2i(5, 5)
state = SubResource("Sentence_bb2w7")
[node name="ReplaceRule" type="ReplaceRule" parent="Generator" unique_id=1787373751]
pattern = SubResource("Sentence_wail4")