diff --git a/src/experimental/tiles_wfc.scad b/src/experimental/tiles_wfc.scad index e1479606..5980d223 100644 --- a/src/experimental/tiles_wfc.scad +++ b/src/experimental/tiles_wfc.scad @@ -1,5 +1,7 @@ use ; use ; +use ; +use ; use ; use ; use ; @@ -91,16 +93,71 @@ function wf_remove(wf, x, y, removedStates) = ) ]; +function wf_collapse(wf, x, y) = + let( + weights = wf_weights(wf), + states_xy = wf_eigenstates_at(wf, x, y), + weights_xy = hashmap([ + for(state = hashmap_keys(weights)) + if(has(states_xy, state)) + [state, hashmap_get(weights, state)] + ]), + totalWeights = sum(hashmap_values(weights_xy)), + threshold = rand() * totalWeights, + states_weights = hashmap_entries(weights_xy) + ) + _wf_collapse(wf, x, y, states_weights, len(states_weights), threshold); + +function _wf_collapse(wf, x, y, states_weights, leng, threshold, i = 0) = + i == leng ? wf : + let( + state = states_weights[i][0], + weight = states_weights[i][1], + t = threshold - weight + ) + t < 0 ? _oneStateAt(wf, x, y, state) : _wf_collapse(wf, x, y, states_weights, leng, t, i + 1); + +function _oneStateAt(wf, x, y, state) = + let( + eigenstates = wf_eigenstates(wf), + rowsBeforeY = slice(eigenstates, 0, y), + rowY = eigenstates[y], + rowsAfterY = slice(eigenstates, y + 1), + statesBeforeX = slice(rowY, 0, x), + states = [state], + statesAfterX = slice(rowY, x + 1), + newRowY = concat( + statesBeforeX, + [[state]], + statesAfterX + ) + ) + [ + wf_width(wf), + wf_height(wf), + wf_weights(wf), + concat( + rowsBeforeY, + [newRowY], + rowsAfterY + ) + ]; + width = len(sample[0]); height = len(sample); weights = weightsOfTiles(sample); wf = waveFunction(width, height, weights); -eigenstates = initialEigenstates(width, height, weights); assert(wf_width(wf) == width); assert(wf_height(wf) == height); -assert(wf_eigenstates(wf) == eigenstates); +assert(wf_eigenstates(wf) == initialEigenstates(width, height, weights)); assert(wf_isAllCollapsed(wf) == false); assert(wf_remove(wf, 0, 0, []) == wf); assert(wf_eigenstates_at(wf_remove(wf, 0, 0, ["CE"]), 0, 0) == ["C0", "C1", "CS", "C2", "C3", "S", "CW", "CN", "L"]); +for(y = [0:height - 1]) { + for(x = [0:width - 1]) { + assert(len(wf_eigenstates_at(wf_collapse(wf, x, y), x, y)) == 1); + } +} +