random generator bugfix
This commit is contained in:
@@ -47,27 +47,39 @@ int main() {
|
||||
|
||||
auto [x, y] = world.getCoord(index);
|
||||
|
||||
// enable walls in 3x3 area around floor (without center)
|
||||
// must come before Exclude to avoid collapsing then un-collapsing cells
|
||||
for (int dy = -1; dy <= 1; ++dy) {
|
||||
for (int dx = -1; dx <= 1; ++dx) {
|
||||
if (dx == 0 && dy == 0) continue;
|
||||
constrainer.template Include<Tile::Wall>(world.getCoordOffset(x, y, dx, dy));
|
||||
}
|
||||
}
|
||||
|
||||
// floor cannot be adjacent to empty space
|
||||
constrainer.template Exclude<Tile::Empty>(world.getCoordOffset(x, y, -1, 0)); // Left
|
||||
constrainer.template Exclude<Tile::Empty>(world.getCoordOffset(x, y, 1, 0)); // Right
|
||||
constrainer.template Exclude<Tile::Empty>(world.getCoordOffset(x, y, 0, -1)); // Up
|
||||
constrainer.template Exclude<Tile::Empty>(world.getCoordOffset(x, y, 0, 1)); // Down
|
||||
})>
|
||||
::SetInitialState<decltype([](World& world, auto& constrainer, auto& rng) constexpr {
|
||||
::SetInitialState<decltype([](World& world, auto& constrainer, auto&) constexpr {
|
||||
// disable walls everywhere by default
|
||||
for (size_t i = 0; i < world.size(); ++i) {
|
||||
constrainer.template Exclude<Tile::Wall>(i);
|
||||
}
|
||||
// make it impossible for the edge to be floor
|
||||
for (size_t x = 0; x < world.width(); ++x) {
|
||||
constrainer.template Exclude<Tile::Floor>(world.getId({static_cast<int>(x), 0}));
|
||||
constrainer.template Exclude<Tile::Floor>(world.getId({static_cast<int>(x), static_cast<int>(world.height() - 1)}));
|
||||
}
|
||||
for (size_t y = 0; y < world.height(); ++y) {
|
||||
constrainer.template Exclude<Tile::Wall>(world.getId({0, static_cast<int>(y)}));
|
||||
constrainer.template Exclude<Tile::Wall>(world.getId({static_cast<int>(world.width() - 1), static_cast<int>(y)}));
|
||||
}
|
||||
// seed floor tiles to kick-start dungeon generation
|
||||
constrainer.template Only<Tile::Floor>(world.getId({2, 2}));
|
||||
})>
|
||||
::SetRandomSelector<WFC::AdvancedRandomSelector<Tile>>
|
||||
::Build;
|
||||
|
||||
World world{};
|
||||
bool success = WFC::Run<DungeonBuilder>(world, 0xDEADBEEF);
|
||||
bool success = WFC::Run<DungeonBuilder>(world, std::random_device{}());
|
||||
if (!success) {
|
||||
std::cout << "WFC solver failed!\n";
|
||||
}
|
||||
|
||||
@@ -117,6 +117,23 @@ public:
|
||||
ApplyMask(cellId, 1 << value.InternalIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Re-enable specific values for a cell (OR bits back in)
|
||||
* @param cellId The ID of the cell to modify
|
||||
*/
|
||||
template <typename IDMapT::Type ... IncludedValues>
|
||||
void Include(size_t cellId) {
|
||||
static_assert(sizeof...(IncludedValues) > 0, "At least one included value must be provided");
|
||||
if (m_wave.IsCollapsed(cellId)) return; // don't un-collapse decided cells
|
||||
auto indices = IDMapT::template ValuesToIndices<IncludedValues...>();
|
||||
m_wave.Enable(cellId, BitContainerT::GetMask(indices));
|
||||
}
|
||||
|
||||
void Include(WorldValue<typename IDMapT::Type> value, size_t cellId) {
|
||||
if (m_wave.IsCollapsed(cellId)) return;
|
||||
m_wave.Enable(cellId, 1 << value.InternalIndex);
|
||||
}
|
||||
|
||||
private:
|
||||
void ApplyMask(size_t cellId, MaskType mask) {
|
||||
bool wasCollapsed = m_wave.IsCollapsed(cellId);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace WFC {
|
||||
|
||||
/**
|
||||
@@ -27,13 +29,13 @@ public:
|
||||
template <typename VarT>
|
||||
class AdvancedRandomSelector {
|
||||
private:
|
||||
std::mt19937& m_rng;
|
||||
mutable std::mt19937 m_rng;
|
||||
|
||||
public:
|
||||
explicit AdvancedRandomSelector(std::mt19937& rng) : m_rng(rng) {}
|
||||
explicit AdvancedRandomSelector(uint32_t seed = 0x12345678) : m_rng(seed) {}
|
||||
|
||||
uint32_t rng(uint32_t max) const {
|
||||
std::uniform_int_distribution<uint32_t> dist(0, max);
|
||||
std::uniform_int_distribution<uint32_t> dist(0, max - 1);
|
||||
return dist(m_rng);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
|
||||
public:
|
||||
void Collapse(size_t index, ElementT mask) { m_data[index] &= mask; }
|
||||
void Enable(size_t index, ElementT mask) { m_data[index] |= mask; }
|
||||
size_t size() const { return m_data.size(); }
|
||||
size_t Entropy(size_t index) const { return std::popcount(m_data[index]); }
|
||||
bool IsCollapsed(size_t index) const { return Entropy(index) == 1; }
|
||||
|
||||
Reference in New Issue
Block a user