public static MapSpace Parse(char input, int location) { var result = new MapSpace(); switch (input) { case '#': return(null); case '.': break; case 'E': result.Unit = new Elf { CurrentLocation = result }; break; case 'G': result.Unit = new Goblin { CurrentLocation = result }; break; } result.Location = location; return(result); }
public static void MoveTo(this Unit unit, MapSpace targetSpace) { if (targetSpace.Unit != null) { throw new InvalidOperationException("Target space is already occupied"); } unit.CurrentLocation.Unit = null; unit.CurrentLocation = targetSpace; unit.CurrentLocation.Unit = unit; }
public static State Parse(string input) { string[] inputRows = input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); int yOffset = inputRows[0].Length; char[] mapChars = inputRows.SelectMany(x => x.ToCharArray()).ToArray(); MapSpace[] map = Enumerable.Range(0, mapChars.Length).Select(x => MapSpace.Parse(mapChars[x], x)).ToArray(); return(new State { Map = map, YOffset = yOffset, MaxY = inputRows.Length }); }
public static IEnumerable <MapSpace> GetAdjacentSpaces(this State state, MapSpace space) { // Note: because we know the caverns in question are walled all around, we // don't need to worry about bounds checking. If this wasn't the case we'd // need to check to see if the space we're looking at was on the edge of the // map before checking the adjacent spaces. int[] adjacentLocations = new[] { space.Location - state.YOffset, space.Location - 1, space.Location + 1, space.Location + state.YOffset, }; return(adjacentLocations.Select(x => state.Map[x]).Where(x => x != null)); }
public static void Move(this Unit unit, State state) { // Are we already in range? if (unit.InRangeEnemy(state) != null) { // We're going nowhere. return; } MapSpace[] inRangeSpaces = unit.FindSpacesInRangeOfAnEnemy(state); // Find the closest in range space MapSpace[] pathToClosestSpace = unit.GetPathToClosest(inRangeSpaces, state); // If we found a path, take a step towards it (otherwise stay here - this unit // is blocked from moving for some reason) if (pathToClosestSpace != null) { MapSpace targetSpace = pathToClosestSpace[1]; unit.MoveTo(targetSpace); } }
public static IEnumerable <MapSpace> GetEmptyAdjacentSpaces(this State state, MapSpace space) { return(state.GetAdjacentSpaces(space).Where(MapSpaceExtensions.IsEmpty)); }
public static bool IsEmpty(this MapSpace space) { return(space.Unit == null); }
public static MapSpace[] GetPathToClosest(this Unit unit, MapSpace[] targetSpaces, State currentState) { // We're doing a basic breadth first search where we'll track all the possible moves // until we hit a target space. var pathFindingQueue = new Queue <List <MapSpace> >(); pathFindingQueue.Enqueue(new List <MapSpace> { unit.CurrentLocation }); var visitedSpaces = new List <MapSpace>(currentState.YOffset * currentState.YOffset); while (pathFindingQueue.Count > 0) { List <MapSpace> currentPath = pathFindingQueue.Dequeue(); MapSpace currentSpace = currentPath[currentPath.Count - 1]; if (visitedSpaces.Contains(currentSpace)) { // We've been here already, and took less time to do it. So abandon this path continue; } else { visitedSpaces.Add(currentSpace); } // Get the adjacent spaces that haven't already been visited by any path before MapSpace[] adjacentSpaces = currentState.GetEmptyAdjacentSpaces(currentSpace).Where(x => !visitedSpaces.Contains(x)).ToArray(); if (adjacentSpaces.Length == 0) { // Dead end. continue; } // See if any of the adjacent spaces are in the list of target spaces MapSpace target = Array.Find(adjacentSpaces, x => targetSpaces.Contains(x)); if (target != null) { var resultingPath = new List <MapSpace>(currentPath) { target }; return(resultingPath.ToArray()); } // None of the adjacent spaces are in the list, so we'll continue searching foreach (MapSpace space in adjacentSpaces) { var newPath = new List <MapSpace>(currentPath) { space }; pathFindingQueue.Enqueue(newPath); } } // If we're here, we've exhausted our search. There's nothing in range return(null); }