Esempio n. 1
0
        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);
        }
Esempio n. 2
0
 // 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);
 }
Esempio n. 3
0
        /// <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);
        }
Esempio n. 4
0
        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);
        }