コード例 #1
0
        public SolverNode Init(Puzzle puzzle, ISolverQueue queue)
        {
            var root = CreateRoot(puzzle);

            queue.Enqueue(root);
            return(root);
        }
コード例 #2
0
        public override bool Evaluate(
            SolverState state,
            ISolverQueue queue,
            ISolverPool pool,
            ISolverPool solutionPool,
            SolverNode node)
        {
            if (node.HasChildren)
            {
                throw new InvalidOperationException();
            }


            node.Status = SolverNodeStatus.Evaluting;
            var toEnqueue = new List <SolverNode>(); // TODO: Could be reused
            var toPool    = new List <SolverNode>(); // TODO: Could be reused

            var solution = false;

            foreach (var move in node.MoveMap.TruePositions())
            {
                foreach (var dir in VectorInt2.Directions)
                {
                    var p   = move;
                    var pp  = p + dir;
                    var ppp = pp + dir;
                    if (node.CrateMap[pp] &&                                 // crate to push
                        state.StaticMaps.FloorMap[ppp] && !node.CrateMap[ppp] && // into free space?
                        !state.StaticMaps.DeadMap[ppp])                      // Valid Push
                    {
                        EvaluateValidPush(state, pool, solutionPool, node, pp, ppp, p, dir, toEnqueue, toPool, ref solution);
                    }
                }
            }

            if (solution)
            {
                node.Status = SolverNodeStatus.SolutionPath;
            }
            else if (node.HasChildren)
            {
                node.Status = SolverNodeStatus.Evaluted;
                state.Statistics.TotalDead += node.CheckDead();    // Children may be evaluated as dead already
            }
            else
            {
                node.Status = SolverNodeStatus.Dead;
                state.Statistics.TotalDead++;
                if (node.Parent != null)
                {
                    state.Statistics.TotalDead += node.Parent.CheckDead();
                }
            }

            queue.Enqueue(toEnqueue);
            pool.Add(toPool);

            return(solution);
        }
コード例 #3
0
        public bool Evaluate(SolverState state, ISolverQueue queue, ISolverPool myPool,
                             ISolverPool solutionPool, SolverNode node)
        {
            if (node.HasChildren)
            {
                throw new InvalidOperationException();
            }

            node.Status = SolverNodeStatus.Evaluting;

            var solution  = false;
            var toEnqueue = new List <SolverNode>();

            foreach (var move in node.MoveMap.TruePositions())
            {
                foreach (var dir in VectorInt2.Directions)
                {
                    var p  = move;
                    var pc = p + dir;
                    var pp = p - dir;
                    if (node.CrateMap[pc] && // crate to push
                        state.StaticMaps.FloorMap[pp] && !node.CrateMap[p] &&
                        !CheckDeadReverse(state, pp))
                    {
                        EvaluateValidPull(state, myPool, solutionPool, node, pc, p, pp, toEnqueue, ref solution);
                    }
                }
            }

            if (solution)
            {
                node.Status = SolverNodeStatus.SolutionPath;
            }
            else if (node.HasChildren)
            {
                node.Status = SolverNodeStatus.Evaluted;
                state.Statistics.TotalDead += node.CheckDead(); // Children may be evaluated as dead already
            }
            else
            {
                node.Status = SolverNodeStatus.Dead;
                state.Statistics.TotalDead++;
                if (node.Parent != null)
                {
                    state.Statistics.TotalDead += node.Parent.CheckDead();
                }
            }


            queue.Enqueue(toEnqueue);
            myPool.Add(toEnqueue);

            return(solution);
        }
コード例 #4
0
        public SolverNode Init(Puzzle puzzle, ISolverQueue queue)
        {
            var solution = puzzle.ToMap(puzzle.Definition.AllGoals); // START with a solution
            var walls    = puzzle.ToMap(puzzle.Definition.Wall);
            // The is only one start, but MANY end soutions. Hence a single root is not a valid representation
            // We use a placeholder node (not an actualy move to hold solutions)
            var root = new SolverNodeRootReverse(
                new VectorInt2(), new VectorInt2(),
                puzzle.ToMap(puzzle.Definition.AllGoals),
                new Bitmap(puzzle.Width, puzzle.Height),
                this,
                puzzle
                );

            foreach (var crateBefore in solution.TruePositions())
            {
                foreach (var dir in VectorInt2.Directions)
                {
                    // ss
                    var posPlayer      = crateBefore + dir;
                    var posPlayerAfter = posPlayer + dir;
                    var crateAfter     = crateBefore + dir;

                    // Remember: In reverse mode goals are crates, and crate may be floor
                    if ((puzzle[posPlayer] == puzzle.Definition.Floor ||
                         puzzle[posPlayer] == puzzle.Definition.Player ||
                         puzzle[posPlayer] == puzzle.Definition.Crate)
                        &&
                        (puzzle[posPlayerAfter] == puzzle.Definition.Floor ||
                         puzzle[posPlayerAfter] == puzzle.Definition.Player ||
                         puzzle[posPlayer] == puzzle.Definition.Crate))
                    {
                        // var crate = new Bitmap(solution);
                        // crate[crateBefore] = false;
                        // crate[crateAfter] = true;
                        // var move = FloodFill.Fill(walls.BitwiseOR(crate), posPlayerAfter);
                        // var node = nodeFactory.CreateInstance(posPlayer, posPlayerAfter - posPlayer, crate, move);
                        var node = nodeFactory.CreateFromPull(root, solution, walls, crateBefore, crateAfter, posPlayerAfter);

                        if (node.MoveMap.Count > 0)
                        {
                            root.Add(node);
                            queue.Enqueue(node);
                        }
                    }
                }
            }

            return(root);
        }
コード例 #5
0
        public bool Evaluate(SolverCommandResult state, ISolverQueue queue, ISolverNodeLookup myPool, ISolverNodeLookup solutionPool, SolverNode node)
        {
            if (node.HasChildren) throw new InvalidOperationException();

            node.Status = SolverNodeStatus.Evaluting;

            var solution = false;
            var toEnqueue = new List<SolverNode>();

            foreach (var move in node.MoveMap.TruePositions())
            {
                foreach (var dir in VectorInt2.Directions)
                {
                    var p = move;
                    var pc = p + dir;
                    var pp = p - dir;
                    if (node.CrateMap[pc]) // crate to push
                    {
                        if (state.StaticMaps.FloorMap[pp] && !node.CrateMap[p])
                        {
                            if (!CheckDeadReverse(state, pp))
                            {
                                var newKid = new SolverNode
                                {
                                    PlayerBefore = p,
                                    PlayerAfter = pp,

                                    CrateBefore = pc,
                                    CrateAfter = p,

                                    CrateMap = new Bitmap(node.CrateMap),
                                    Evaluator = this,
                                };
                                newKid.CrateMap[pc] = false;
                                newKid.CrateMap[p] = true;

                                var boundry = state.StaticMaps.WallMap.BitwiseOR(newKid.CrateMap);
                                newKid.MoveMap = FloodFill.Fill(boundry, pp);

                                newKid.Goals = newKid.CrateMap.BitwiseAND(state.StaticMaps.GoalMap).Count();

                                // Optimisation: PreCalc hash
                                newKid.EnsureHash();

                                // Cycle Check: Does this node exist already?
                                var dup = myPool.FindMatch(newKid);
                                if (dup != null)
                                {
                                    // NOTE: newKid is NOT added as a ChildNode (which means less memory usage)

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

                                    if (IsDebugMode)
                                    {
                                        node.AddDuplicate(dup);
                                    }
                                }
                                else
                                {

                                    SolverNode match = null;
                                    if (solutionPool != null) match = solutionPool.FindMatch(newKid);

                                    if (match != null)
                                    {
                                        // Add to tree / itterator
                                        node.Add(newKid);

                                        // Solution
                                        if (state.SolutionsWithReverse == null) state.SolutionsWithReverse = new List<SolutionChain>();
                                        var pair = new SolutionChain()
                                        {
                                            ForwardNode = match,
                                            ReverseNode = newKid,
                                            FoundUsing = this
                                        };
                                        state.SolutionsWithReverse.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 / itterator
                                        node.Add(newKid);

                                        if (DeadMapAnalysis.DynamicCheck(state.StaticMaps, node))
                                        {
                                            newKid.Status = SolverNodeStatus.Dead;
                                        }
                                        else
                                        {
                                            toEnqueue.Add(newKid);
                                            if (newKid.CrateMap.BitwiseAND(state.StaticMaps.CrateStart).Equals(newKid.CrateMap))
                                            {
                                                // Possible Solution: Did we start in a valid position
                                                if (CheckValidSolutions(state, newKid))
                                                {
                                                    state.Solutions.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
                                                {
                                                    newKid.Status = SolverNodeStatus.InvalidSolution;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            node.Status = node.HasChildren ? SolverNodeStatus.Evaluted : SolverNodeStatus.Dead;
            if (node.Status == SolverNodeStatus.Dead  && node.Parent != null)
            {
                var p = (SolverNode)node.Parent;
                p.CheckDead();
            }

            queue.Enqueue(toEnqueue);
            myPool.Add(toEnqueue);

            return solution;
        }
コード例 #6
0
        public SolverNode Init(Puzzle puzzle, ISolverQueue queue)
        {
            var solution = puzzle.ToMap(puzzle.Definition.AllGoals);  // START with a solution
            var walls = puzzle.ToMap(puzzle.Definition.Wall);
            // The is only one start, but MANY end soutions. Hence a single root is not a valid representation
            // We use a placeholder node (not an actualy move to hold solutions)
            var root = new SingleThreadedReverseSolver.SyntheticReverseNode()
            {
                CrateMap = puzzle.ToMap(puzzle.Definition.AllGoals),
                MoveMap = new Bitmap(puzzle.Width, puzzle.Height)
            };

            foreach (var crateBefore in solution.TruePositions())
            {
                foreach (var dir in VectorInt2.Directions)
                {
                    // ss
                    var posPlayer = crateBefore + dir;
                    var posPlayerAfter = posPlayer + dir;
                    var crateAfter = crateBefore + dir;

                    // Remember: In reverse mode goals are crates, and crate may be floor
                    if ((puzzle[posPlayer] == puzzle.Definition.Floor
                        || puzzle[posPlayer] == puzzle.Definition.Player
                        || puzzle[posPlayer] == puzzle.Definition.Crate
                        )
                        &&
                        (puzzle[posPlayerAfter] == puzzle.Definition.Floor
                        || puzzle[posPlayerAfter] == puzzle.Definition.Player
                        || puzzle[posPlayer] == puzzle.Definition.Crate
                        )
                        )
                    {

                            var crate = new Bitmap(solution);
                            crate[crateBefore] = false;
                            crate[crateAfter] = true;

                            var node = new SolverNode()
                            {
                                CrateBefore = crateBefore,
                                CrateAfter = crateAfter,

                                PlayerBefore = posPlayer,
                                PlayerAfter = posPlayerAfter,

                                CrateMap = crate,
                                MoveMap = FloodFill.Fill(walls.BitwiseOR(crate), posPlayerAfter)
                            };

                            if (node.MoveMap.Count > 0)
                            {
                                root.Add(node);
                                queue.Enqueue(node);
                            }

                    }
                }
            }
            return root;
        }
コード例 #7
0
 public ThreadSafeSolverQueueWrapper(ISolverQueue inner)
 {
     this.inner = inner;
 }
コード例 #8
0
 public SolverNode Init(Puzzle puzzle, ISolverQueue queue)
 {
     var root = SolverHelper.CreateRoot(puzzle);
     queue.Enqueue(root);
     return root;
 }
コード例 #9
0
ファイル: SolverBase.cs プロジェクト: guylangston/SokoSolve
        protected virtual bool Tick(SolverCommand command, CommandResult state, ISolverQueue queue, out SolverCommandResult solve)
        {
            state.Statistics.DepthCompleted = queue.Statistics.DepthCompleted;
            state.Statistics.DepthMax = queue.Statistics.DepthMax;

            if (command.Progress != null)
            {
                command.Progress.Update(this, state, state.Statistics);
            }

            if (command.CheckAbort != null)
            {
                if (command.CheckAbort(command))
                {
                    state.Exit = ExitConditions.Conditions.Aborted;
                    state.EarlyExit = true;
                    state.Statistics.Completed = DateTime.Now;
                    solve = state;
                    return true;
                }
            }

            var check = command.ExitConditions.ShouldExit(state);
            if (check != ExitConditions.Conditions.Continue)
            {
                state.EarlyExit = true;
                state.Statistics.Completed = DateTime.Now;
                state.Exit = check;
                solve = state;
                return true;

            }
            solve = null;
            return false;
        }
コード例 #10
0
ファイル: NodeEvaluator.cs プロジェクト: danisky94/SokoSolve
 public abstract bool Evaluate(SolverState state, ISolverQueue queue, ISolverPool pool, ISolverPool solutionPool, SolverNode node);
コード例 #11
0
ファイル: NodeEvaluator.cs プロジェクト: danisky94/SokoSolve
 public abstract SolverNode Init(Puzzle puzzle, ISolverQueue queue);