diff --git a/modules/generative_grammar/grammar.cpp b/modules/generative_grammar/grammar.cpp index a527233a34..e576120d42 100644 --- a/modules/generative_grammar/grammar.cpp +++ b/modules/generative_grammar/grammar.cpp @@ -18,10 +18,21 @@ bool Sentence::is_terminal() const { } Symbol Sentence::get_at(Vector2i coord) const { + if (this->read_transposed) { + int x{ coord.x }; + coord.x = coord.y; + coord.y = x; + } + if (this->read_flip_h) { + coord.x = this->size.x - (coord.x + 1); + } + if (this->read_flip_v) { + coord.y = this->size.y - (coord.y + 1); + } ERR_FAIL_COND_V_EDMSG(coord.x >= this->size.x, NonTerminals::Invalid, vformat("Sentence::get_at: invalid coordinate x:%d, size.x:%d", coord.x, this->size.x)); ERR_FAIL_COND_V_EDMSG(coord.y >= this->size.y, NonTerminals::Invalid, vformat("Sentence::get_at: invalid coordinate y:%d size.y:%d", coord.y, this->size.y)); int idx{ coord.x + (coord.y * this->size.x) }; - ERR_FAIL_COND_V_EDMSG(idx >= this->symbols.size(), NonTerminals::Invalid, vformat("Sentence::get_at: invalid coordinate x:%d y:%d idx:%d size:%d,%d len:%d", coord.x, coord.y, idx, this->size.x, this->size.y, this->symbols.size())); + ERR_FAIL_COND_V_EDMSG(idx >= this->symbols.size(), NonTerminals::Invalid, vformat("Sentence::get_at: invalid coordinate x:%d y:%d idx:%d size:%d,%d len:%d h:%s v:%s t:%s", coord.x, coord.y, idx, this->size.x, this->size.y, this->symbols.size(), this->read_flip_h, this->read_flip_v, this->read_transposed)); return this->symbols.get(idx); } @@ -95,7 +106,7 @@ void Sentence::set_size(Vector2i value) { } Vector2i Sentence::get_size() const { - return this->size; + return this->read_transposed ? Vector2i{ this->size.y, this->size.x } : this->size; } void CompositeRule::_bind_methods() { @@ -147,13 +158,13 @@ void ReplaceRule::_bind_methods() { 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())); } -bool ReplaceRule::try_apply(Ref sentence) { +bool ReplaceRule::try_match(Ref sentence, Vector2i &out) { ERR_FAIL_COND_V_EDMSG(this->results.size() == 0, false, "ReplaceRule::try_apply failed, no results in list"); Vector2i max{ sentence->get_size() - this->pattern->get_size() }; 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->results[Math::rand() % this->results.size()].first); // TODO pick based on weighed random + out = pos; return true; } } @@ -162,6 +173,69 @@ bool ReplaceRule::try_apply(Ref sentence) { return false; } +void ReplaceRule::write_result(Ref to, Vector2i at) { + Ref result{ this->results[Math::rand() % this->results.size()].first }; + result->read_flip_h = this->pattern->read_flip_h; + result->read_flip_v = this->pattern->read_flip_v; + result->read_transposed = this->pattern->read_transposed; + to->write_subsentence(at, result); + result->read_flip_h = false; + result->read_flip_v = false; + result->read_transposed = false; +} + +bool ReplaceRule::try_apply_all(Ref sentence) { + Vector2i at{}; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + this->pattern->read_flip_h = true; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + this->pattern->read_flip_v = true; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + this->pattern->read_transposed = true; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + this->pattern->read_flip_h = false; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + this->pattern->read_flip_v = false; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + this->pattern->read_flip_h = true; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + this->pattern->read_transposed = false; + if (try_match(sentence, at)) { + write_result(sentence, at); + return true; + } + return false; +} + +bool ReplaceRule::try_apply(Ref sentence) { + bool success{ try_apply_all(sentence) }; + this->pattern->read_flip_h = false; + this->pattern->read_flip_v = false; + this->pattern->read_transposed = false; + return success; +} + void ReplaceRule::set_results_dict(Dictionary dict) { this->results.clear(); for (KeyValue var : dict) { diff --git a/modules/generative_grammar/grammar.h b/modules/generative_grammar/grammar.h index da961cb55c..1be4783ace 100644 --- a/modules/generative_grammar/grammar.h +++ b/modules/generative_grammar/grammar.h @@ -40,6 +40,9 @@ public: public: Vector symbols{}; Vector2i size{ 0, 0 }; + bool read_transposed{ false }; + bool read_flip_h{ false }; + bool read_flip_v{ false }; public: void set_symbols_string(String value); @@ -86,9 +89,12 @@ public: class ReplaceRule : public Rule { GDCLASS(ReplaceRule, Rule); static void _bind_methods(); + bool try_match(Ref graph, Vector2i &out); + void write_result(Ref to, Vector2i at); + bool try_apply_all(Ref sentence); public: - bool try_apply(Ref graph) override; + bool try_apply(Ref sentence) override; private: Ref pattern{}; diff --git a/project/scenes/levels/dungeon.tscn b/project/scenes/levels/dungeon.tscn index 18e82004d3..821d4a9f55 100644 --- a/project/scenes/levels/dungeon.tscn +++ b/project/scenes/levels/dungeon.tscn @@ -43,7 +43,7 @@ uuuuuuuuuuuuuuuuuuuu" size = Vector2i(5, 3) symbols_string = "uuuuu uuuuu -#####" +*###*" [sub_resource type="Sentence" id="Sentence_yc5ro"] size = Vector2i(5, 3) @@ -51,18 +51,6 @@ symbols_string = "uuuuu uxpxu *pup*" -[sub_resource type="Sentence" id="Sentence_7f72c"] -size = Vector2i(5, 3) -symbols_string = "#p#p# -uuuuu -uuuuu" - -[sub_resource type="Sentence" id="Sentence_pbld3"] -size = Vector2i(5, 3) -symbols_string = "*pup* -upxpu -uuuuu" - [sub_resource type="Sentence" id="Sentence_wyxho"] size = Vector2i(5, 5) symbols_string = "uuuuu @@ -74,50 +62,66 @@ uuuuu" [sub_resource type="Sentence" id="Sentence_q0ye3"] size = Vector2i(5, 5) symbols_string = "uuuuu -upxpu +uppxu #pup# -upxpu +uxppu uuuuu" +[sub_resource type="Sentence" id="Sentence_7f72c"] +size = Vector2i(5, 3) +symbols_string = "u#u#u +u#u#u +u#u#u" + [sub_resource type="Sentence" id="Sentence_w0mg0"] -size = Vector2i(4, 5) -symbols_string = "uuuu -##u* -u##* -##u* -uuuu" +size = Vector2i(5, 3) +symbols_string = "u#p#u +uuu#u +u#p#u" + +[sub_resource type="Sentence" id="Sentence_pbld3"] +size = Vector2i(5, 5) +symbols_string = "u#u#u +*###* +uu#uu +*###* +u#u#u" [sub_resource type="Sentence" id="Sentence_06kf8"] -size = Vector2i(4, 5) -symbols_string = "uuuu -##pp -uuu# -##pp -uuuu" - -[sub_resource type="Sentence" id="Sentence_wail4"] -size = Vector2i(5, 3) -symbols_string = "uuuuu -uuuuu -#####" - -[sub_resource type="Sentence" id="Sentence_srduu"] -size = Vector2i(5, 3) -symbols_string = "upxpu +size = Vector2i(5, 5) +symbols_string = "u#u#u +*#u#* upupu -##u##" +*#u#* +u#u#u" [sub_resource type="Sentence" id="Sentence_c7dwr"] -size = Vector2i(5, 3) -symbols_string = "uuu#* -uuu#* -uuu#*" +size = Vector2i(5, 5) +symbols_string = "u#u#u +*###* +upuuu +*###* +u#u#u" [sub_resource type="Sentence" id="Sentence_ohg4i"] -size = Vector2i(5, 3) -symbols_string = "uxp#* -upuu* -uxp#*" +size = Vector2i(6, 4) +symbols_string = "uuuuuu +u###uu +u#u#uu +*#u#u*" + +[sub_resource type="Sentence" id="Sentence_b4io3"] +size = Vector2i(6, 4) +symbols_string = "uuuuuu +u###pu +u#uupu +*#upp*" + +[sub_resource type="Sentence" id="Sentence_eijdf"] +size = Vector2i(4, 3) +symbols_string = "#### +uu#u +###*" [node name="Dungeon" type="Node3D" unique_id=719313039] @@ -147,32 +151,30 @@ results_dict = { SubResource("Sentence_yc5ro"): 1.0 } -[node name="ZagDown" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=1665850421] -pattern = SubResource("Sentence_7f72c") -results_dict = { -SubResource("Sentence_pbld3"): 1.0 -} - [node name="Split" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=222066055] pattern = SubResource("Sentence_wyxho") results_dict = { SubResource("Sentence_q0ye3"): 1.0 } -[node name="StretchLoop" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=995556959] -pattern = SubResource("Sentence_w0mg0") +[node name="Bridge" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=233403765] +pattern = SubResource("Sentence_7f72c") results_dict = { -SubResource("Sentence_06kf8"): 1.0 +SubResource("Sentence_w0mg0"): 1.0 } -[node name="ExtendLoop" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=1207681043] -pattern = SubResource("Sentence_wail4") +[node name="ConnectLoops" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=874341993] +pattern = SubResource("Sentence_pbld3") results_dict = { -SubResource("Sentence_srduu"): 1.0 +SubResource("Sentence_06kf8"): 1.0, +SubResource("Sentence_c7dwr"): 1.0 } -[node name="SplitVertical" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=1220297709] -pattern = SubResource("Sentence_c7dwr") +[node name="WidenLoops" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=2024540398] +pattern = SubResource("Sentence_ohg4i") results_dict = { -SubResource("Sentence_ohg4i"): 1.0 +SubResource("Sentence_b4io3"): 0.0 } + +[node name="CloseGaps" type="ReplaceRule" parent="Generator/RepeatRuleUntilFailure/InitialLayout" unique_id=370907114] +pattern = SubResource("Sentence_eijdf")