#include "generator.h" #include "core/config/engine.h" #include "core/math/math_funcs.h" #include "core/math/vector2i.h" #include "core/object/class_db.h" #include "macros.h" void Generator::_bind_methods() { BIND_HPROPERTY(Variant::OBJECT, state, PROPERTY_HINT_RESOURCE_TYPE, "Sentence"); BIND_HPROPERTY(Variant::DICTIONARY, tiles_dict, PROPERTY_HINT_DICTIONARY_TYPE, vformat("String;PackedScene")); BIND_PROPERTY(Variant::FLOAT, tile_size); } void Generator::initialise_state() { print_line("Filling state with unknown"); for (int i{ 0 }; i < this->state->symbols.size(); ++i) { this->state->symbols.set(i, Terminals::Undefined); } #if 0 print_line("Writing borders X"); 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); } print_line("Writing borders Y"); 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); } #endif print_line("Writing path"); int y{ (Math::abs((int)Math::rand()) % (this->state->size.y - 6)) + 3 }; print_line("Path at y =", y); for (int i{ 1 }; i < this->state->size.x - 2; ++i) { this->state->set_at({ i, y }, Terminals::Path); } print_line("Writing start & goal"); this->state->set_at({ 0, y }, Terminals::Start); #if 0 this->state->set_at({ this->state->size.x - 1, y }, Terminals::Goal); #endif } void Generator::ready() { initialise_state(); print_line("STATE:"); print_line(this->state->get_symbols_string()); // TODO: repeat until terminal state this->rule->try_apply(this->state); print_line("STATE:"); print_line(this->state->get_symbols_string()); for (Vector2i at{ 0, 0 }; at.y < this->state->size.y; ++at.y) { for (; at.x < this->state->size.x; ++at.x) { Symbol s{ this->state->get_at(at) }; if (this->tiles.has(s)) { if (Node * node{ this->tiles.get(s)->instantiate() }) { if (Node3D * node3d{ cast_to(node) }) { node3d->set_position(Vector3{ (float)at.x, 0, (float)at.y } * this->tile_size); } this->add_child(node); } } } at.x = 0; } } void Generator::_notification(int what) { if (Engine::get_singleton()->is_editor_hint()) { return; } switch (what) { default: return; case NOTIFICATION_READY: ready(); case NOTIFICATION_CHILD_ORDER_CHANGED: for (Variant child : get_children()) { if (Rule * rule{ cast_to(child) }) { this->rule = rule; return; } } return; } } void Generator::set_tiles_dict(Dictionary dict) { this->tiles.clear(); for (KeyValue kvp : dict) { String key{ kvp.key }; Ref value{ kvp.value }; if (key.is_empty() || value.is_null()) { continue; } this->tiles.insert(key.get(0), value); } } Dictionary Generator::get_tiles_dict() const { Dictionary dict{}; for (TileMap::KV kvp : this->tiles) { dict.set(String() + kvp.key, kvp.value); } return dict; }