Esempio n. 1
0
        public void DynamicDeadMap()
        {
            // Init
            var p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#...XX...#",
                "#...X#...#",
                "#.P......#",
                "##########"
            });
            var stat = new StaticAnalysisMaps(p);

            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));


            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#...#X...#",
                "#...X#...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));

            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#...##...#",
                "#...XX...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));

            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#........#",
                "#...XX...#",
                "#...##...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));

            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#........#",
                "#...XX...#",
                "#...X#...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));



            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#........#",
                "#...$$...#",
                "#...X#...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));

            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#........#",
                "#...$$...#",
                "#...#X...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));

            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#........#",
                "#...#X...#",
                "#...$$...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.True(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));


            // NOT_DEAD
            p = Puzzle.Builder.FromLines(
                new[]
            {
                "##########",
                "#........#",
                "#...$$...#",
                "#...$#...#",
                "#.P......#",
                "##########"
            });
            stat = new StaticAnalysisMaps(p);
            Assert.False(DeadMapAnalysis.DynamicCheck(stat, StateMaps.Create(p)));
        }
Esempio n. 2
0
        private bool EvaluateValidPull(
            SolverState state,
            ISolverPool myPool,
            ISolverPool solutionPool,
            SolverNode node,
            VectorInt2 pc,
            VectorInt2 p,
            VectorInt2 pp,
            List <SolverNode> toEnqueue,
            ref bool solution)
        {
            state.Statistics.TotalNodes++;


            var newKid = nodeFactory.CreateFromPull(node, node.CrateMap, state.StaticMaps.WallMap, pc, p, pp);


            // Cycle Check: Does this node exist already?
            var dup = myPool.FindMatch(newKid);

            if (dup != null)
            {
                if (object.ReferenceEquals(dup, newKid))
                {
                    throw new InvalidDataException();
                }
                if (dup.SolverNodeId == newKid.SolverNodeId)
                {
                    throw new InvalidDataException();
                }

                // Duplicate
                newKid.Status = SolverNodeStatus.Duplicate;
                state.Statistics.Duplicates++;

                if (state.Command.DuplicateMode == DuplicateMode.AddAsChild)
                {
                    node.Add(newKid);
                    newKid.Duplicate = dup;
                }
                else if (state.Command.DuplicateMode == DuplicateMode.ReuseInPool)
                {
                    nodeFactory.ReturnInstance(newKid); // Add to pool for later re-use?
                }
                else // DuplicateMode.Discard
                {
                }
            }
            else
            {
                var match = solutionPool?.FindMatch(newKid);
                if (match != null)
                {
                    // Add to tree / itterator
                    node.Add(newKid);

                    // Solution
                    state.SolutionsNodesReverse ??= new List <SolutionChain>();
                    var pair = new SolutionChain
                    {
                        ForwardNode = match,
                        ReverseNode = newKid,
                        FoundUsing  = this
                    };
                    state.SolutionsNodesReverse.Add(pair);
                    solution = true;
                    state.Command.Debug.Raise(this, SolverDebug.Solution, pair);

                    foreach (var n in newKid.PathToRoot().Union(match.PathToRoot()))
                    {
                        n.Status = SolverNodeStatus.SolutionPath;
                    }
                    newKid.Status = SolverNodeStatus.Solution;
                    match.Status  = SolverNodeStatus.Solution;
                    if (state.Command.ExitConditions.StopOnSolution)
                    {
                        return(true);
                    }
                }
                else
                {
                    // Add to tree / iterator
                    node.Add(newKid);  // Thread-safe: As all kids get created in this method (forward / reverse)

                    if (DeadMapAnalysis.DynamicCheck(state.StaticMaps, node))
                    {
                        newKid.Status = SolverNodeStatus.Dead;
                    }
                    else
                    {
                        toEnqueue.Add(newKid);
                        if (newKid.IsSolutionReverse(state.StaticMaps))
                        {
                            // Possible Solution: Did we start in a valid position
                            if (CheckValidSolutions(state, newKid))
                            {
                                state.SolutionsNodes.Add(newKid);
                                state.Command.Debug.Raise(this, SolverDebug.Solution, newKid);
                                solution = true;

                                foreach (var n in newKid.PathToRoot())
                                {
                                    n.Status = SolverNodeStatus.SolutionPath;
                                }
                                newKid.Status = SolverNodeStatus.Solution;
                            }
                            else
                            {
                                // We started in the wrong place; ignore and continue
                            }
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 3
0
        private bool EvaluateValidPush(
            SolverState state,
            ISolverPool pool,
            ISolverPool reversePool,
            SolverNode node,
            VectorInt2 pp,
            VectorInt2 ppp,
            VectorInt2 p,
            VectorInt2 push,
            List <SolverNode> toEnqueue,
            ref bool solution)
        {
            state.Statistics.TotalNodes++;


            var newKid = nodeFactory.CreateFromPush(node, node.CrateMap, state.StaticMaps.WallMap, p, pp, ppp, push);

            // Cycle Check: Does this node exist already?
            var dup = pool.FindMatch(newKid);

            if (dup != null)
            {
                if (object.ReferenceEquals(dup, newKid))
                {
                    throw new InvalidDataException();
                }
                if (dup.SolverNodeId == newKid.SolverNodeId)
                {
                    throw new InvalidDataException();
                }

                // Duplicate
                newKid.Status = SolverNodeStatus.Duplicate;
                state.Statistics.Duplicates++;

                if (state.Command.DuplicateMode == DuplicateMode.AddAsChild)
                {
                    node.Add(newKid);
                    newKid.Duplicate = dup;
                }
                else if (state.Command.DuplicateMode == DuplicateMode.ReuseInPool)
                {
                    nodeFactory.ReturnInstance(newKid); // Add to pool for later re-use?
                }
                else // DuplicateMode.Discard
                {
                }
            }
            else
            {
                node.Add(newKid);

                // If there is a reverse solver, checks its pool for a match, hence a Forward <-> Reverse chain, hence a solution
                var match = reversePool?.FindMatch(newKid);
                if (match != null)
                {
                    // Solution!
                    NewSolutionChain(state, out solution, newKid, match);

                    if (state.Command.ExitConditions.StopOnSolution)
                    {
                        return(true);
                    }
                }
                else
                {
                    if (DeadMapAnalysis.DynamicCheck(state.StaticMaps, node))
                    {
                        newKid.Status = SolverNodeStatus.Dead;
                        state.Statistics.TotalDead++;
                    }
                    else
                    {
                        toEnqueue.Add(newKid);

                        if (newKid.IsSolutionForward(state.StaticMaps))
                        {
                            // Solution
                            solution = true;
                            state.SolutionsNodes.Add(newKid);
                            state.Command.Debug.Raise(this, SolverDebug.Solution, newKid);
                            foreach (var n in newKid.PathToRoot())
                            {
                                n.Status = SolverNodeStatus.SolutionPath;
                            }
                            newKid.Status = SolverNodeStatus.Solution;

                            if (state.Command.ExitConditions.StopOnSolution)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 4
0
        private bool EvaluateValidPull(
            SolverState state,
            ISolverPool pool,
            ISolverPool solutionPool,
            SolverNode node,
            VectorInt2 pc,
            VectorInt2 p,
            VectorInt2 pp,
            List <SolverNode> toEnqueue,
            List <SolverNode> toPool,
            ref bool solution)
        {
            state.Statistics.TotalNodes++;


            var newKid = nodeFactory.CreateFromPull(node, node.CrateMap, state.StaticMaps.WallMap, pc, p, pp);

            if (state.Command.Inspector != null && state.Command.Inspector(newKid))
            {
                state.Command.Report?.WriteLine(newKid.ToString());
            }

            // Cycle Check: Does this node exist already?
            var dup = pool.FindMatch(newKid);

            if (SafeMode && dup == null)
            {
                dup = ConfirmDupLookup(pool, node, toEnqueue, newKid); // Fix or Throw
            }
            if (dup != null)
            {
                if (object.ReferenceEquals(dup, newKid))
                {
                    throw new InvalidDataException();
                }
                if (dup.SolverNodeId == newKid.SolverNodeId)
                {
                    throw new InvalidDataException();
                }

                // Duplicate
                newKid.Status = SolverNodeStatus.Duplicate;
                state.Statistics.Duplicates++;

                if (state.Command.DuplicateMode == DuplicateMode.AddAsChild)
                {
                    node.Add(newKid);
                    if (newKid is ISolverNodeDuplicateLink dupLink)
                    {
                        dupLink.Duplicate = dup;
                    }
                }
                else if (state.Command.DuplicateMode == DuplicateMode.ReuseInPool)
                {
                    nodeFactory.ReturnInstance(newKid); // Add to pool for later re-use?
                }
                else // DuplicateMode.Discard
                {
                }
            }
            else
            {
                // These two should always be the same
                node.Add(newKid); toPool.Add(newKid);

                // If there is a reverse solver, checks its pool for a match, hence a Forward <-> Reverse chain, hence a solution
                var match = solutionPool?.FindMatch(newKid);
                if (match != null)
                {
                    // Solution
                    state.SolutionsNodesReverse ??= new List <SolutionChain>();
                    var pair = new SolutionChain
                    {
                        ForwardNode = match,
                        ReverseNode = newKid,
                        FoundUsing  = this
                    };
                    state.SolutionsNodesReverse.Add(pair);
                    solution = true;
                    state.Command.Debug.Raise(this, SolverDebug.Solution, pair);

                    foreach (var n in newKid.PathToRoot().Union(match.PathToRoot()))
                    {
                        n.Status = SolverNodeStatus.SolutionPath;
                    }
                    newKid.Status = SolverNodeStatus.Solution;
                    match.Status  = SolverNodeStatus.Solution;
                    if (state.Command.ExitConditions.StopOnSolution)
                    {
                        return(true);
                    }
                }
                else
                {
                    if (DeadMapAnalysis.DynamicCheck(state.StaticMaps, node))
                    {
                        newKid.Status = SolverNodeStatus.Dead;
                    }
                    else
                    {
                        toEnqueue.Add(newKid);
                        if (newKid.IsSolutionReverse(state.StaticMaps))
                        {
                            // Possible Solution: Did we start in a valid position
                            if (CheckValidSolutions(state, newKid))
                            {
                                state.SolutionsNodes.Add(newKid);
                                state.Command.Debug.Raise(this, SolverDebug.Solution, newKid);
                                solution = true;

                                foreach (var n in newKid.PathToRoot())
                                {
                                    n.Status = SolverNodeStatus.SolutionPath;
                                }
                                newKid.Status = SolverNodeStatus.Solution;
                            }
                            else
                            {
                                // We started in the wrong place; ignore and continue
                            }
                        }
                    }
                }
            }

            return(false);
        }