/// <summary>
        /// Main search algorithm. Attempts to locate
        /// a route to the destination location.
        /// </summary>
        /// <param name="start">The start location.</param>
        /// <returns></returns>
        bool TryFindPath(Location start)
        {
            Queue<Location> queue = new Queue<Location>();
            queue.Enqueue(start);
            Dictionary<Location, Location> previousSteps = new Dictionary<Location, Location>();
            Location location;

            while (queue.Count > 0)
            {
                location = queue.Dequeue();

                if (location.Equals(destination))
                {
                    Location parentLocation;
                    Location childLocation = location;
                    List<Move> moves = new List<Move>();
                    while (previousSteps.TryGetValue(childLocation, out parentLocation))
                    {
                        /* Create the move and add to route.*/
                        Direction dir = parentLocation.GetDirection(childLocation);
                        moves.Add(new Move(dir));
                        childLocation = parentLocation;
                    }
                    moves.Reverse(); /* The moves are back to front. */
                    route = moves.ToArray();
                    return true;
                }
                else
                {
                    for (int i = 0; i < 4; i++)
                    {
                        Direction direction = GetDirection(i);
                        Location neighbour = location.GetAdjacentLocation(direction);
                        if (level[neighbour].CanEnter && !previousSteps.ContainsKey(neighbour))
                        {
                            previousSteps.Add(neighbour, location);
                            queue.Enqueue(neighbour);
                        }
                    }
                }
            }
            return false;
        }
 /// <summary>
 /// Tests whether the specified location is within 
 /// the Level grid.
 /// </summary>
 /// <param name="location">The location to test
 /// whether it is within the level grid.</param>
 /// <returns><code>true</code> if the location
 /// is within the <see cref="Level"/>; 
 /// <code>false</code> otherwise.</returns>
 public bool InBounds(Location location)
 {
     return Level.InBounds(location);
 }
        List<Cell> BuildCells(string rowText, int rowNumber)
        {
            List<Cell> row = new List<Cell>(rowText.Length);

            int columnNumber = 0;

            foreach (char c in rowText)
            {
                Location location = new Location(rowNumber, columnNumber++);
                switch (c)
                {
                    case '#': /* Wall. */
                        row.Add(new WallCell(location, this));
                        break;
                    case ' ': /* Empty. */
                        row.Add(new FloorCell(location, this));
                        break;
                    case '$': /* Treasure in a square. */
                        row.Add(new FloorCell(location, this, new Treasure(location, this)));
                        break;
                    case '*': /* Treasure in a Goal. */
                        GoalCell goalCellWithTreasure = new GoalCell(location, this, new Treasure(location, this));
                        goalCellWithTreasure.CompletedGoalChanged += new EventHandler(GoalCell_CompletedGoalChanged);
                        goals.Add(goalCellWithTreasure);
                        row.Add(goalCellWithTreasure);
                        break;
                    case '.': /* Goal. */
                        GoalCell goalCell = new GoalCell(location, this);
                        goalCell.CompletedGoalChanged += new EventHandler(GoalCell_CompletedGoalChanged);
                        goals.Add(goalCell);
                        row.Add(goalCell);
                        break;
                    case '@': /* Actor in a floor cell. */
                        Actor actor = new Actor(location, this);
                        row.Add(new FloorCell(location, this, actor));
                        Actor = actor;
                        break;
                    case '!': /* Space. */
                        row.Add(new SpaceCell(location, this));
                        break;
                    default:
                        throw new FormatException("Invalid Level symbol found: " + c);
                }
            }
            return row;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="SearchPathFinder"/> class.
 /// </summary>
 /// <param name="start">The start cell. Presumably where
 /// the <see cref="Actor"/> is located.</param>
 /// <param name="destination">Where we would like to get.</param>
 public SearchPathFinder(Cell start, Location destination)
 {
     this.destination = destination;
     startCell = start;
     level = start.Level;
 }
 /// <summary>
 /// Tests whether the specified location is within 
 /// the Level grid.
 /// </summary>
 /// <param name="location">The location to test
 /// whether it is within the level grid.</param>
 /// <returns><code>true</code> if the location
 /// is within the <see cref="Level"/>; 
 /// <code>false</code> otherwise.</returns>
 public bool InBounds(Location location)
 {
     return (location.RowNumber >= 0
         && location.RowNumber < RowCount
         && location.ColumnNumber >= 0
         && location.ColumnNumber < ColumnCount);
 }
 /// <summary>
 /// Gets the <see cref="Orpius.Sokoban.Cell"/> with the specified location.
 /// </summary>
 /// <value>The cell at the specified location.</value>
 public Cell this[Location location]
 {
     get
     {
         if (InBounds(location))
         {
             return this[location.RowNumber, location.ColumnNumber];
         }
         return null;
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="GoalCell"/> class.
 /// </summary>
 /// <param name="location">The location of the goal
 /// on the level grid.</param>
 /// <param name="level">The level grid where this cell
 /// is located.</param>
 /// <param name="contents">The contents of this goal cell.</param>
 public GoalCell(Location location, Level level, CellContents contents)
     : base(cellName, location, level, contents)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="GoalCell"/> class.
 /// </summary>
 /// <param name="location">The location of the goal
 /// on the level grid.</param>
 /// <param name="level">The level grid where this cell
 /// is located.</param>
 public GoalCell(Location location, Level level)
     : base(cellName, location, level)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="Actor"/> class.
 /// </summary>
 /// <param name="location">The location.</param>
 /// <param name="level">The level.</param>
 public Actor(Location location, Level level)
     : base("Actor", location, level)
 {
 }