예제 #1
0
        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;
        }
예제 #3
0
        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
            });
        }
예제 #4
0
        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);
            }
        }
예제 #6
0
 public static IEnumerable <MapSpace> GetEmptyAdjacentSpaces(this State state, MapSpace space)
 {
     return(state.GetAdjacentSpaces(space).Where(MapSpaceExtensions.IsEmpty));
 }
예제 #7
0
 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);
        }