From 82fccc2b3a49c7e818b9cef955a21dfe46862803 Mon Sep 17 00:00:00 2001 From: Connor Date: Fri, 6 Feb 2026 12:34:16 +0900 Subject: [PATCH] bugfix std::integral --- include/nd-wfc/wfc.hpp | 64 +++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/include/nd-wfc/wfc.hpp b/include/nd-wfc/wfc.hpp index 021cc0c..cd3c80d 100644 --- a/include/nd-wfc/wfc.hpp +++ b/include/nd-wfc/wfc.hpp @@ -28,7 +28,7 @@ namespace WFC { template concept WorldType = requires(T world, typename T::ValueType value) { - { world.size() } -> std::is_integral; + { world.size() } -> std::integral; { world.setValue(static_cast(0), value) }; { world.getValue(static_cast(0)) } -> std::convertible_to; typename T::ValueType; @@ -48,7 +48,7 @@ template, typename ConstrainerFunctionMapT = ConstrainerFunctionMap, typename CallbacksT = Callbacks, - typename RandomSelectorT = DefaultRandomSelector, + typename RandomSelectorT = DefaultRandomSelector > class WFC { public: @@ -189,61 +189,56 @@ private: } } - static WorldSizeT FindMinimumEntropyCells(std::span& buffer, WaveType& wave) + static bool Branch(SolverState& state, WaveType& wave) { - auto entropyGetter = [&wave](size_t index) -> size_t { return wave.Entropy(index); }; - auto entropyFilter = [&wave](size_t entropy) -> bool { return entropy > 1; }; - auto minEntropyCell = *std::ranges::min_element(std::views::iota(0, wave.size()) | std::views::transform(entropyGetter) | std::views::filter(entropyFilter)); + constexpr_assert(state.m_propagationQueue.empty()); + + // Find cell with minimum entropy > 1 + WorldSizeT minEntropyCell = static_cast(-1); + size_t minEntropy = static_cast(-1); + + for (WorldSizeT i = 0; i < wave.size(); ++i) { + size_t entropy = wave.Entropy(i); + if (entropy > 1 && entropy < minEntropy) { + minEntropy = entropy; + minEntropyCell = i; + } + } + if (minEntropyCell == static_cast(-1)) return false; constexpr_assert(!wave.IsCollapsed(minEntropyCell)); // create a list of possible values - VariableIDT availableValues = wave.Entropy(minEntropyCell); + VariableIDT availableValues = static_cast(wave.Entropy(minEntropyCell)); + std::array possibleValues{}; MaskType mask = wave.GetMask(minEntropyCell); - for (size_t i = 0; i < availableValues; ++i) + for (size_t i = 0; i < availableValues; ++i) { VariableIDT index = static_cast(std::countr_zero(mask)); // get the index of the lowest set bit constexpr_assert(index < VariableIDMapT::size(), "Possible value went outside bounds"); - buffer[i] = index; + possibleValues[i] = index; constexpr_assert(((mask & (MaskType(1) << index)) != 0), "Possible value was not set"); mask = mask & (mask - 1); // turn off lowest set bit } - return minEntropyCell; - } - - using RandomGeneratorReturnType = decltype(RandomSelectorT{}.rng(static_cast(1))); - - static bool Branch(SolverState& state, WaveType& wave) - { - constexpr_assert(state.m_propagationQueue.empty()); - - std::array Buffer{}; - WorldSizeT minEntropyCell{}; - - minEntropyCell = FindMinimumEntropyCells(Buffer, wave); - // randomly select a value from possible values - while (Buffer.size()) + while (availableValues) { - size_t randomIndex; - VariableIDT selectedValue; - - randomIndex = state.m_randomSelector.rng(Buffer.size()); - selectedValue = Buffer[randomIndex]; - + size_t randomIndex = state.m_randomSelector.rng(availableValues); + VariableIDT selectedValue = possibleValues[randomIndex]; + { // copy the state and branch out auto stackFrame = state.m_allocator.createFrame(); auto queueFrame = state.m_propagationQueue.createBranchPoint(); - + auto newWave = wave; CollapseCell(state, newWave, minEntropyCell, selectedValue); state.m_propagationQueue.push(minEntropyCell); - if (RunLoop(state, newWave)) + if (RunLoop(state, newWave)) { // move the solution to the original state wave = newWave; @@ -258,8 +253,7 @@ private: constexpr_assert((wave.GetMask(minEntropyCell) & (MaskType(1) << selectedValue)) == 0, "Wave was not collapsed correctly"); // swap replacement value with the last value - std::swap(Buffer[randomIndex], Buffer[Buffer.size() - 1]); - Buffer = Buffer.subspan(0, Buffer.size() - 1); + std::swap(possibleValues[randomIndex], possibleValues[--availableValues]); } return false; @@ -278,7 +272,7 @@ private: VariableIDT variableID = wave.GetVariableID(cellId); ConstrainerType constrainer(wave, state.m_propagationQueue); - using ConstrainerFunctionPtrT = void(*)(WorldT&, WorldSizeT, WorldValue, ConstrainerType&); + using ConstrainerFunctionPtrT = void(*)(WorldT&, size_t, WorldValue, ConstrainerType&); ConstrainerFunctionMapT::template GetFunction(variableID)(state.m_world, cellId, WorldValue{VariableIDMapT::GetValue(variableID), variableID}, constrainer); }