public SolverNode Init(Puzzle puzzle, ISolverQueue queue) { var root = CreateRoot(puzzle); queue.Enqueue(root); return(root); }
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); }
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); }
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); }
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; }
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; }
public ThreadSafeSolverQueueWrapper(ISolverQueue inner) { this.inner = inner; }
public SolverNode Init(Puzzle puzzle, ISolverQueue queue) { var root = SolverHelper.CreateRoot(puzzle); queue.Enqueue(root); return root; }
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; }
public abstract bool Evaluate(SolverState state, ISolverQueue queue, ISolverPool pool, ISolverPool solutionPool, SolverNode node);
public abstract SolverNode Init(Puzzle puzzle, ISolverQueue queue);