bool removePatternUpdatingHeap(int x, int y, PatternId id, WfcContext cx, Solver solver) { if (cx.state.removePatternUpdatingEntropy(x, y, id, cx.model.patterns)) { return(true); } solver.updateHeap(x, y, cx.state.entropies[x, y].entropyWithNoise()); this.removals.Push(new TileRemoval(x, y, id)); return(false); }
// TODO: on lockin, just remove patterns for performance and then propagate /// <summary>True if contradicted. Recursively propagates all the removals</summary> public bool propagateAll(WfcContext cx, Solver solver) { // propagate the effect of a removal while (this.removals.Count > 0) { if (this.propagateRemoval(this.removals.Pop(), cx, solver)) { return(true); } } return(false); }
/// <summary>Reduces enabler counts around the cell. True if contradicted</summary> bool propagateRemoval(TileRemoval removal, WfcContext cx, Solver solver) { int nPatterns = cx.model.patterns.len; var gridSize = cx.model.gridSize; var nb = new Neighbor { }; for (int dirIndex = 0; dirIndex < 4; dirIndex++) { nb.pos = removal.pos + dirVecs[dirIndex]; if (cx.model.filterPos(nb.pos.x, nb.pos.y)) { continue; } // for periodic output nb.pos += gridSize; nb.pos %= gridSize; var dirFromNeighbor = ((Dir4)dirIndex).opposite(); for (int i = 0; i < nPatterns; i++) { nb.id = new PatternId(i); // skip some combinations (not an enabler or already removed) if (!cx.model.rule.isLegal(nb.id, dirFromNeighbor, removal.id)) { continue; } if (!cx.state.isPossible(nb.pos.x, nb.pos.y, nb.id)) { continue; } // decrement the enabler count for the compatible pattern if (!cx.state.enablerCounts.decrement(nb.pos.x, nb.pos.y, nb.id, dirFromNeighbor)) { continue; } if (this.removePatternUpdatingHeap(nb.pos.x, nb.pos.y, nb.id, cx, solver)) { return(true); } } } return(false); }
public WfcContext.AdvanceStatus advance(WfcContext cx) { if (this.nUnSolved <= 0) { return(WfcContext.AdvanceStatus.Success); // every cell is decided } var(pos, isContradicted) = Solver.selectNextCellToDecide(ref this.heap, cx.state); if (isContradicted) { System.Console.WriteLine("Unreachable. The heap is empty, but there are remaining cells"); return(WfcContext.AdvanceStatus.Fail); } var id = Solver.selectPatternForCell(pos.x, pos.y, cx.state, cx.model.patterns, cx.random); Solver.solveCellWithPattern(pos.x, pos.y, id, cx.state, cx.model.patterns, this.propagator); this.nUnSolved -= 1; return(this.propagator.propagateAll(cx, this) ? WfcContext.AdvanceStatus.Fail : WfcContext.AdvanceStatus.Continue); }