private static Path GetBestPathFrom(Board b, Options o, int y, int x) { Path bestPath = new Path(); Stack<Tuple<Board, Path>> paths = new Stack<Tuple<Board, Path>>(); paths.Push(new Tuple<Board, Path>(b, new Path { Start = new Tuple<int, int>(y, x), Current = new Tuple<int, int>(y, x), Depth = 1, Score = b.Score(BoardScorer.Options.Horus) })); while (paths.Any()) { var cur = paths.Pop(); var curPath = cur.Item2; var curBoard = cur.Item1; if (curPath.Score > bestPath.Score) bestPath = curPath; if (curPath.Depth == o.MaxDepth) continue; //if (paths.Count() > o.WhenToPrune) //{ // var newPaths = new Stack<Tuple<Board, Path>>(); // foreach (var path in paths.OrderByDescending(p => p.Item2.Score).Take(o.NumToKeep).Reverse()) // newPaths.Push(path); // paths = newPaths; //} foreach (var direction in Board.MoveDirections) { if (curPath.Length != 0 && curPath.Actions.Last()[0] == -direction[0] && curPath.Actions.Last()[1] == -direction[1]) continue; var newY = curPath.Current.Item1 + direction[0]; var newX = curPath.Current.Item2 + direction[1]; if (newY < 0 || newY >= b.Height || newX < 0 || newX >= b.Width) continue; Board newBoard = new Board(curBoard); Orb tempOrb = newBoard.Orbs[newY, newX]; newBoard.Orbs[newY, newX] = newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2]; newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2] = tempOrb; var newPath = new List<int[]>(curPath.Actions); newPath.Add(direction); paths.Push(new Tuple<Board, Path>(newBoard, new Path { Start = curPath.Start, Current = new Tuple<int, int>(newY, newX), Depth = curPath.Depth + 1, Score = newBoard.Score(BoardScorer.Options.Horus) - curPath.Depth / 100, Actions = newPath })); } } return bestPath; }
public static Path GetBestPath(Board b, Options o) { Path bestPath = new Path(); object pathLock = new Object(); Parallel.For(0, b.Height, i => { //for (int i = 0; i < b.Height; i++) Parallel.For(0, b.Width, j => { //for (int j = 0; j < b.Width; j++) var curPath = GetBestPathFrom(b, o, i, j); lock (pathLock) { if (curPath.Score > bestPath.Score) bestPath = curPath; } var c = b.GetBoardsAfterPath(curPath.Start.Item1, curPath.Start.Item2, curPath.Actions); var curPath2 = GetBestPathFrom(c.Item1, o, curPath.Current.Item1, curPath.Current.Item2); var actions = new List<int[]>(curPath.Actions); actions.AddRange(curPath2.Actions); curPath2.Actions = actions; lock (pathLock) { if (curPath2.Score > bestPath.Score) curPath = bestPath = new Path { Start = curPath.Start, Current = curPath2.Current, Depth = curPath.Depth + curPath2.Depth, Score = curPath2.Score, Actions = curPath2.Actions }; } }); }); var cc = b.GetBoardsAfterPath(bestPath.Start.Item1, bestPath.Start.Item2, bestPath.Actions); var bestPath2 = GetBestPathFrom(cc.Item1, o, bestPath.Current.Item1, bestPath.Current.Item2); var actions2 = new List<int[]>(bestPath.Actions); actions2.AddRange(bestPath2.Actions); bestPath2.Actions = actions2; lock (pathLock) { if (bestPath2.Score > bestPath.Score) bestPath = new Path { Start = bestPath.Start, Current = bestPath2.Current, Depth = bestPath.Depth + bestPath2.Depth, Score = bestPath2.Score, Actions = bestPath2.Actions }; } return bestPath; }
public static Board BoardFromBitmap(int rows, int columns, int height, int width, int h_off, int w_off, Bitmap bmp) { PadImage pi = new PadImage(bmp, rows, columns, height, width, h_off, w_off); Board b = new Board(rows, columns); for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { b.Orbs[i, j] = pi.GetOrb(i, j); } Console.WriteLine(b.ToString()); return b; }
public void Configure(IApplicationBuilder app) { app.UseMvc(); return; app.Run(async (context) => { try { Board b = new Board(4, 4); Array vals = Enum.GetValues(typeof(Orb)); for (int i = 0; i < b.Height; i++) for (int j = 0; j < b.Width; j++) { b.Orbs[i, j] = (i + j) % 2 == 0 ? Orb.Red : Orb.Blue; b.Orbs[i, j] = (Orb) vals.GetValue(1 + (i + j) % 5); } var p = DfsSolver.GetBestPath(b); var b2 = b.GetBoardsAfterPath(p.Start.Item1, p.Start.Item2, p.Actions); Board opt = SAASSolver.GetOptimalBoards(b, SAASSolver.Options.Default, BoardScorer.Options.Horus).First(); var b3 = new Board(opt); b3.GetCombos(false); var p2 = SAASSolver.GetBestPath(b, SAASSolver.Options.Default, BoardScorer.Options.Horus); var b4 = b.GetBoardsAfterPath(p2.Start.Item1, p2.Start.Item2, p2.Actions); //await context.Response.WriteAsync(JsonConvert.SerializeObject(p)); //return; await context.Response.WriteAsync("" //+ JsonConvert.SerializeObject(p) //+ "\n\n\n" //+ JsonConvert.SerializeObject(b) //+ "\n\n\n" //+ JsonConvert.SerializeObject(b2) + b.ToString() + b2.Item1.ToString() + b2.Item2.ToString() + "\n\n" + b2.Item1.Score(BoardScorer.Options.Horus) + "\n\nSAAS optimal:" + opt.ToString() + b3.ToString() + "\n\n" + opt.Score(BoardScorer.Options.Horus) + "\n\n" + JsonConvert.SerializeObject(p2) + b4.Item1.ToString() + b4.Item2.ToString() ); } catch (Exception ex) { await context.Response.WriteAsync(ex.ToString()); } }); }
public string SolveBoardOne(string path, int rows, int cols, int width, int height, int w_off, int h_off) { Board b = new Board(5, 6); b.Orbs = new Orb[,] { { Orb.Green, Orb.Heal, Orb.Light, Orb.Green, Orb.Green, Orb.Red }, { Orb.Dark, Orb.Blue, Orb.Red, Orb.Red, Orb.Blue, Orb.Light }, { Orb.Heal, Orb.Red, Orb.Heal, Orb.Dark, Orb.Blue, Orb.Blue}, { Orb.Green, Orb.Green, Orb.Dark, Orb.Light, Orb.Dark, Orb.Dark}, { Orb.Dark, Orb.Green, Orb.Dark, Orb.Light, Orb.Red, Orb.Green} }; return JsonConvert.SerializeObject(BeamDfs.GetBestPath(b, BoardScorer.Options.Horus)); }
public bool EqualsBoard(Board b, bool ignoreNone = false) { for (int i = 0; i < Height; i++) for (int j = 0; j < Width; j++) { if (ignoreNone && (Orbs[i, j] == Orb.None || b.Orbs[i, j] == Orb.None)) continue; if (Orbs[i, j] != b.Orbs[i, j] || Enhancements[i, j] != b.Enhancements[i, j]) return false; } return true; }
public bool TestBoardEq() { Board b = new Board(4, 4); Board b2 = new Board(b); Array vals = Enum.GetValues(typeof(Orb)); for (int i = 0; i < b.Height; i++) for (int j = 0; j < b.Width; j++) { b.Orbs[i, j] = (i + j) % 2 == 0 ? Orb.Red : Orb.Blue; b.Orbs[i, j] = (Orb)vals.GetValue(1 + (i + j) % 5); if (i == 0) b2.Orbs[i, j] = b.Orbs[i, j]; } return b2.EqualsBoard(b, false); }
public Tuple<Board, Board, List<Combo>> GetBoardsAfterPath(int y, int x, List<int[]> path) { Board b = new Board(this); foreach (var direction in path) { var newY = y + direction[0]; var newX = x + direction[1]; Orb temp = b.Orbs[newY, newX]; b.Orbs[newY, newX] = b.Orbs[y, x]; b.Orbs[y, x] = temp; y = newY; x = newX; } Board clear = new Board(b); var combos = clear.GetCombos(false); return new Tuple<Board, Board, List<Combo>>(b, clear, combos); }
public string TestHeuristic() { Board b = new Board(6, 6); Array vals = Enum.GetValues(typeof(Orb)); for (int i = 0; i < b.Height; i++) for (int j = 0; j < b.Width; j++) b.Orbs[i, j] = Orb.Red; Board b2 = new Board(b); b.Orbs[0, 0] = Orb.Blue; b.Orbs[3, 3] = Orb.Blue; b2.Orbs[1, 1] = Orb.Blue; b2.Orbs[2, 2] = Orb.Blue; b.Orbs[3, 0] = Orb.Green; b.Orbs[0, 3] = Orb.Green; b2.Orbs[1, 2] = Orb.Green; b2.Orbs[2, 1] = Orb.Green; SAASSolver.Heuristic h = SAASSolver.Options.Default.HeuristicGen(b); return h(b2).ToString(); }
public static Path GetBestPath(Board b, Options o, BoardScorer.Options bso) { Path bestPath = new Path(); object pathLock = new object(); Parallel.For(0, b.Height, i => { //for (int i = 0; i < b.Height; i++) Parallel.For(0, b.Width, j => { //for (int j = 0; j < b.Width; j++) var curPath = GetBestPathFrom(b, o, i, j, bso); lock (pathLock) { if (curPath.Score > bestPath.Score) bestPath = curPath; } }); }); return bestPath; }
public string TestSAAS(string path, int rows, int cols, int width, int height, int w_off, int h_off) { path = Uri.UnescapeDataString(path); Console.WriteLine(path); Bitmap bmp = new Bitmap(path); Board b = PadImage.BoardFromBitmap(rows, cols, height, width, h_off, w_off, bmp); Board opt = SAASSolver.GetOptimalBoards(b, SAASSolver.Options.Default, BoardScorer.Options.Horus).First(); var b3 = new Board(opt); b3.GetCombos(false); //var p2 = SAASSolver.GetBestPathSA(b, SAASSolver.Options.Default, BoardScorer.Options.Horus); //var b4 = b.GetBoardsAfterPath(p2.Start.Item1, p2.Start.Item2, p2.Actions); return "" + b.ToString() + "\n\nSAAS optimal:" + opt.ToString() + b3.ToString() + "\n\n" + opt.Score(BoardScorer.Options.Horus) + "\n\n"; // + JsonConvert.SerializeObject(p2) // + b4.Item1.ToString() // + b4.Item2.ToString(); }
private static Path GetBestPathFrom(Board b, Options o, int y, int x, BoardScorer.Options bso) { Path bestPath = new Path(); PriorityQueue<Tuple<Board, Path>, double> paths = new PriorityQueue<Tuple<Board, Path>, double>(); paths.Enqueue(new Tuple<Board, Path>(b, new Path { Start = new Tuple<int, int>(y, x), Current = new Tuple<int, int>(y, x), Depth = 1, Score = b.Score(bso) })); int depth = 0; while (depth++ < o.MaxDepth) { // Console.WriteLine("currently at depth {0}...", depth); PriorityQueue<Tuple<Board, Path>, double> newPaths = new PriorityQueue<Tuple<Board, Path>, double>(); while (paths.Count != 0) { var cur = paths.Dequeue(); var curPath = cur.Item2; var curBoard = cur.Item1; if (curPath.Score > bestPath.Score) bestPath = curPath; //if (paths.Count() > o.WhenToPrune) //{ // var newPaths = new Stack<Tuple<Board, Path>>(); // foreach (var path in paths.OrderByDescending(p => p.Item2.Score).Take(o.NumToKeep).Reverse()) // newPaths.Push(path); // paths = newPaths; //} foreach (var direction in Board.MoveDirections) { if (curPath.Length != 0 && curPath.Actions.Last()[0] == -direction[0] && curPath.Actions.Last()[1] == -direction[1]) continue; var newY = curPath.Current.Item1 + direction[0]; var newX = curPath.Current.Item2 + direction[1]; if (newY < 0 || newY >= b.Height || newX < 0 || newX >= b.Width) continue; Board newBoard = new Board(curBoard); Orb tempOrb = newBoard.Orbs[newY, newX]; newBoard.Orbs[newY, newX] = newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2]; newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2] = tempOrb; var newPath = new List<int[]>(curPath.Actions); newPath.Add(direction); double score = newBoard.Score(bso) - curPath.Depth / 100; newPaths.Enqueue(new Tuple<Board, Path>(newBoard, new Path { Start = curPath.Start, Current = new Tuple<int, int>(newY, newX), Depth = curPath.Depth + 1, Score = score, Actions = newPath }), score); } } paths = newPaths.TrimToSize(o.BeamWidth); } return bestPath; }
public Board(Board b) : this(b.Height, b.Width) { Array.Copy(b.Orbs, Orbs, b.Height * b.Width); Array.Copy(b.Enhancements, Enhancements, b.Height * b.Width); }
public static Path GetBestPath(Board b) { return GetBestPath(b, Options.Default); }
public List<Combo> GetCombos(bool copy = true) { Board copyBoard = new Board(this); if (!copy) copyBoard = this; List<Combo> combos = new List<Combo>(); List<Combo> lastComboSet = new List<Combo>(); do { lastComboSet = copyBoard.GetCombosWithoutGravity(); combos.AddRange(lastComboSet); copyBoard.GravityFill(); } while (lastComboSet.Any()); return combos; }
public static Path GetBestPath(Board b, BoardScorer.Options bso) { return GetBestPath(b, Options.Default, bso); }
// this function changes the board! make a copy before calling it private List<Combo> GetCombosWithoutGravity() { List<Combo> combos = new List<Combo>(); Board comboBoard = new Board(Height, Width); for (int i = 0; i < Height; i++) for (int j = 1; j < Width - 1; j++) { if (Orbs[i, j] == Orb.None) continue; if (Orbs[i, j - 1] == Orbs[i, j] && Orbs[i, j] == Orbs[i, j + 1]) { comboBoard.Orbs[i, j - 1] = Orbs[i, j]; comboBoard.Orbs[i, j] = Orbs[i, j]; comboBoard.Orbs[i, j + 1] = Orbs[i, j]; } } for (int i = 1; i < Height - 1; i++) for (int j = 0; j < Width; j++) { if (Orbs[i, j] == Orb.None) continue; if (Orbs[i - 1, j] == Orbs[i, j] && Orbs[i, j] == Orbs[i + 1, j]) { comboBoard.Orbs[i - 1, j] = Orbs[i, j]; comboBoard.Orbs[i, j] = Orbs[i, j]; comboBoard.Orbs[i + 1, j] = Orbs[i, j]; } } // row check bool[] isRows = new bool[Height]; for (int i = 0; i < isRows.Length; i++) isRows[i] = true; for (int i = 0; i < Height; i++) for (int j = 1; j < Width; j++) isRows[i] = isRows[i] ? Orbs[i, j] == Orbs[i, 0] : false; Stack<Tuple<int, int>> orbStack = new Stack<Tuple<int, int>>(); HashSet<Tuple<int, int>> visited = new HashSet<Tuple<int, int>>(); for (int i = 0; i < Height; i++) for (int j = 0; j < Width; j++) { int comboNumOrbs = 0; int comboNumEnhances = 0; bool isRow = true; Orb orbType = Orbs[i, j]; if (comboBoard.Orbs[i, j] == Orb.None) continue; orbStack.Clear(); orbStack.Push(new Tuple<int, int>(i, j)); while (orbStack.Any()) { var curLoc = orbStack.Pop(); if (visited.Contains(new Tuple<int, int>(curLoc.Item1, curLoc.Item2))) continue; comboBoard.Orbs[curLoc.Item1, curLoc.Item2] = Orb.None; Orbs[curLoc.Item1, curLoc.Item2] = Orb.None; comboNumOrbs++; if (Enhancements[curLoc.Item1, curLoc.Item2]) comboNumEnhances++; isRow = isRow ? isRows[curLoc.Item1] : false; visited.Add(curLoc); foreach (var direction in MatchDirections) { var newY = curLoc.Item1 + direction[0]; var newX = curLoc.Item2 + direction[1]; if (newY < 0 || newY >= Height || newX < 0 || newX >= Width || visited.Contains(new Tuple<int, int>(newY, newX)) || orbType != comboBoard.Orbs[newY, newX]) continue; orbStack.Push(new Tuple<int, int>(newY, newX)); } } combos.Add(new Combo { OrbType = orbType, NumOrbs = comboNumOrbs, NumEnahcements = comboNumEnhances, IsRow = isRow }); } return combos; }