Example #1
0
        private SolverNode Assemble(
            SolverNode parent,
            StagingSolverNode flat,
            ImmutableDictionary <int, StagingSolverNode> all,
            ImmutableDictionary <int, ImmutableArray <StagingSolverNode> > parents)
        {
            var n = new SolverNode(parent,
                                   new VectorInt2(flat.PlayerBeforeX, flat.PlayerBeforeY),
                                   new VectorInt2(flat.PushX, flat.PushY),
                                   flat.CrateMap,
                                   flat.MoveMap,
                                   flat.SolverNodeId
                                   );

            n.Status = (SolverNodeStatus)flat.Status;

            if (parents.TryGetValue(flat.SolverNodeId, out var kids))
            {
                foreach (var kid in kids)
                {
                    n.Add(Assemble(n, kid, all, parents));
                }
            }



            return(n);
        }
        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;
        }