/** * @brief Example demonstrating custom random selectors in WFC * * This example shows how to use different random selection strategies * in the Wave Function Collapse algorithm, including: * - Default constexpr random selector * - Advanced random selector with std::mt19937 * - Custom lambda-based selectors */ #include #include #include #include #include "../include/nd-wfc/wfc.hpp" // Simple test world for demonstration struct SimpleWorld { using ValueType = int; std::vector data; size_t grid_size; SimpleWorld(size_t size) : data(size * size, 0), grid_size(size) {} size_t size() const { return data.size(); } void setValue(size_t id, int value) { data[id] = value; } int getValue(size_t id) const { return data[id]; } void print() const { for (size_t i = 0; i < grid_size; ++i) { for (size_t j = 0; j < grid_size; ++j) { std::cout << data[i * grid_size + j] << " "; } std::cout << std::endl; } } }; int main() { std::cout << "=== WFC Random Selector Examples ===\n\n"; // Example 1: Using the default constexpr random selector std::cout << "1. Default Random Selector (constexpr-friendly):\n"; { WFC::DefaultRandomSelector selector(0x12345678); // Test with some sample values std::array values = {1, 2, 3, 4}; std::span span(values.data(), values.size()); std::cout << "Possible values: "; for (int v : values) std::cout << v << " "; std::cout << "\nSelected indices: "; for (int i = 0; i < 8; ++i) { size_t index = selector(span); std::cout << index << "(" << values[index] << ") "; } std::cout << "\n\n"; } // Example 2: Using the advanced random selector std::cout << "2. Advanced Random Selector (std::mt19937):\n"; { std::mt19937 rng(54321); WFC::AdvancedRandomSelector selector(rng); std::array values = {10, 20, 30, 40, 50}; std::span span(values.data(), values.size()); std::cout << "Possible values: "; for (int v : values) std::cout << v << " "; std::cout << "\nSelected values: "; for (int i = 0; i < 10; ++i) { size_t index = selector(span); std::cout << values[index] << " "; } std::cout << "\n\n"; } // Example 3: Custom lambda selector that always picks the first element std::cout << "3. Custom Lambda Selector (always first):\n"; { auto firstSelector = [](std::span values) -> size_t { return 0; // Always pick first }; std::array values = {100, 200, 300}; std::span span(values.data(), values.size()); std::cout << "Possible values: "; for (int v : values) std::cout << v << " "; std::cout << "\nSelected values: "; for (int i = 0; i < 5; ++i) { size_t index = firstSelector(span); std::cout << values[index] << " "; } std::cout << "\n\n"; } // Example 4: Stateful lambda selector with captured variables std::cout << "4. Stateful Lambda Selector (round-robin):\n"; { int callCount = 0; auto roundRobinSelector = [&callCount](std::span values) mutable -> size_t { return callCount++ % values.size(); }; std::array values = {1, 2, 3}; std::span span(values.data(), values.size()); std::cout << "Possible values: "; for (int v : values) std::cout << v << " "; std::cout << "\nRound-robin selection: "; for (int i = 0; i < 9; ++i) { size_t index = roundRobinSelector(span); std::cout << values[index] << " "; } std::cout << "\n\n"; } // Example 5: Custom selector with probability weighting std::cout << "5. Weighted Random Selector:\n"; { std::mt19937 rng(99999); auto weightedSelector = [&rng](std::span values) -> size_t { // Simple weighted selection - favor earlier indices std::vector weights; for (size_t i = 0; i < values.size(); ++i) { weights.push_back(1.0 / (i + 1.0)); // Higher weight for lower indices } std::discrete_distribution dist(weights.begin(), weights.end()); return dist(rng); }; std::array values = {1, 2, 3, 4}; std::span span(values.data(), values.size()); std::cout << "Possible values: "; for (int v : values) std::cout << v << " "; std::cout << "\nWeighted selection ( favors lower values): "; for (int i = 0; i < 12; ++i) { size_t index = weightedSelector(span); std::cout << values[index] << " "; } std::cout << "\n\n"; } // Example 6: Integration with WFC Builder std::cout << "6. WFC Builder Integration:\n"; { // Define a simple WFC setup with custom random selector using VariableMap = WFC::VariableIDMap; // Using default random selector using DefaultWFC = WFC::Builder ::SetRandomSelector> ::Build; // Using advanced random selector using AdvancedWFC = WFC::Builder ::SetRandomSelector> ::Build; // Note: Lambda types cannot be used directly as template parameters // Instead, you would create a custom selector class: // class CustomSelector { // public: // size_t operator()(std::span values) const { // return values.size() > 1 ? 1 : 0; // } // }; // using CustomWFC = WFC::Builder // ::SetRandomSelector // ::Build; std::cout << "Successfully created WFC types with different random selectors:\n"; std::cout << "- DefaultWFC with DefaultRandomSelector\n"; std::cout << "- AdvancedWFC with AdvancedRandomSelector\n"; std::cout << "- Custom selector classes can be created for lambda-like behavior\n"; } std::cout << "\n=== Examples completed successfully! ===\n"; return 0; }