private Tuple <State, BoardUndo> MoveOneStep(Point dir, BoardUndo undo = null) { var newPosition = Position + dir; var item = Board.Get(newPosition); if (item == Board.Wall && (DrillTime == 0 || !Board.IsInBounds(newPosition))) { return(null); } Position = newPosition; undo = undo ?? new BoardUndo(); if (item == Board.Wall) { Board.Set(newPosition, Board.Empty, undo); } else if ("BFLR".Contains(item)) { Boosts = Boosts.ToList(); Boosts.Add(item); Board.Set(newPosition, Board.IsPainted(newPosition) ? Board.Empty : Board.UnpaintedEmpty, undo); ++BoostsCollected; } Paint(undo); return(Tuple.Create(this, undo)); }
public void Set(Point p, char c, BoardUndo undo) { if (IsInBounds(p) && Map[p.X, p.Y] != c) { undo.Points.Add(Tuple.Create(p, Map[p.X, p.Y])); Map[p.X, p.Y] = c; } }
public BoardUndo Redo(BoardUndo undo) { var ans = new BoardUndo(); foreach (var i in undo.Points) { Set(i.Item1, i.Item2, ans); } return(ans); }
public BoardUndo GetRedo(BoardUndo undo) { var ans = new BoardUndo(); if (undo != null) { ans.Points = undo.Points .Select(p => Tuple.Create(p.Item1, Map[p.Item1.X, p.Item1.Y])) .ToList(); } return(ans); }
private void Paint(BoardUndo undo) { var initialCount = undo.Count; Board.Paint(Position, undo); foreach (var dir in Robot) { if (Blockers(dir).All(i => !Board.IsWall(Position + i))) { Board.Paint(Position + dir, undo); } } UnpaintedCount -= undo.Count - initialCount; }
public static Board GenerateBoard(MapSpecification spec) { var random = new Random(); var board = new Board(spec.Size, spec.Size); var fill = 100;// spec.Size * spec.Size / 3; var middle = new Point(spec.Size / 2, spec.Size / 2); foreach (var p in spec.ExcludePoints) { board.Set(p, Board.Wall, new BoardUndo()); } foreach (var i in Enumerable.Range(0, fill)) { var allowedPoints = board.AllPoints .Where(p => !spec.IncludePoints.Contains(p)) .Where(p => !board.IsWall(p) && p.AdjacentPoints().Any(board.IsWall)) .ToList(); while (allowedPoints.Any()) { var index = random.Next() % allowedPoints.Count; var chosenPoint = allowedPoints[index]; var undo = new BoardUndo(); board.Set(chosenPoint, Board.Wall, undo); if (chosenPoint.AdjacentPoints().All(p => board.IsWall(p) || board.PathFind(p, middle) != null)) { break; } board.Undo(undo); allowedPoints.RemoveAt(index); } if (!allowedPoints.Any()) { break; } } return(board); }
public void Undo(BoardUndo undo) { if (undo == null) { return; } var reversePoints = undo.Points.ToList(); reversePoints.Reverse(); foreach (var i in reversePoints) { Map[i.Item1.X, i.Item1.Y] = i.Item2; } }
public Tuple <State, BoardUndo> AddManipulator(Point where) { var oldBoard = Board.Clone(); var newState = CloneNextStep(); newState.Robot = newState.Robot.ToList(); newState.Robot.Add(where); newState.Boosts = newState.Boosts.ToList(); newState.Boosts.Remove(Board.Manipulator); var undo = new BoardUndo(); newState.Paint(undo); Board = oldBoard; return(Tuple.Create(newState, undo)); }
public void TestPathFinding() { var board = new Board(30, 30); var undo = new BoardUndo(); board.Set(new Point(0, 1), Board.Wall, undo); board.Set(new Point(1, 0), Board.Wall, undo); var middle = new Point(15, 15); var bottomLeft = new Point(0, 0); var topRight = new Point(29, 29); var path = board.PathFind(bottomLeft, middle); Assert.IsNull(path); path = board.PathFind(topRight, middle); Assert.AreEqual(29, path.Count); Assert.AreEqual(path.First(), topRight); Assert.AreEqual(path.Last(), middle); }
// Returns null if move is possible or state does not change // Mutates this.Board -- returns a BoardUndo that can revert the changes public Tuple <State, BoardUndo> Move(char move) { State newState; BoardUndo undo = null; switch (move) { case 'W': // up return(Move(new Point(0, 1))); case 'S': // down return(Move(new Point(0, -1))); case 'A': // left return(Move(new Point(-1, 0))); case 'D': // right return(Move(new Point(1, 0))); case 'E': // CW case 'Q': // CCW newState = CloneNextStep(); newState.Robot = newState.Robot .Select(p => move == 'E' ? p.RotateRight() : p.RotateLeft()) .ToList(); newState.Direction = (newState.Direction + (move == 'E' ? 1 : 3)) % 4; undo = new BoardUndo(); newState.Paint(undo); return(Tuple.Create(newState, undo)); case 'F': // fast wheels if (!Boosts.Any(i => i == Board.FastWheels)) { return(null); } newState = CloneNextStep(); newState.FastWheelsTime = Math.Max(newState.FastWheelsTime + 50, 50); newState.Boosts = newState.Boosts.ToList(); newState.Boosts.Remove(Board.FastWheels); return(Tuple.Create(newState, undo)); case 'L': // drill if (!Boosts.Any(i => i == Board.Drill)) { return(null); } newState = CloneNextStep(); newState.DrillTime = Math.Max(newState.DrillTime + 30, 30); newState.Boosts = newState.Boosts.ToList(); newState.Boosts.Remove(Board.Drill); return(Tuple.Create(newState, undo)); case 'R': // teleport if (!Boosts.Any(i => i == Board.Teleport)) { return(null); } newState = CloneNextStep(); newState.Boosts = newState.Boosts.ToList(); newState.Boosts.Remove(Board.Teleport); newState.Teleports = newState.Teleports.ToList(); newState.Teleports.Add(Position); return(Tuple.Create(newState, (BoardUndo)null)); case 'Z': return(Tuple.Create(CloneNextStep(), (BoardUndo)null)); } return(null); }
public void Paint(Point p, BoardUndo undo) { Set(p, char.ToUpperInvariant(Get(p)), undo); }