/// <summary>
        /// Fills a region with a given tile.
        /// </summary>
        /// <param name="map">WorldMap to use</param>
        /// <param name="X">X coordinate of starting point</param>
        /// <param name="Y">Y coordinate of starting point</param>
        /// <param name="From">Tile to replace</param>
        /// <param name="To">Tile to replace with</param>
        /// <returns>Amount of tiles filled</returns>
        static List <Point> FloodFill(WorldMap map, int X, int Y, WorldMap.TileType From, WorldMap.TileType To)
        {
            List <Point> points = new List <Point>();

            if (X < 0 || Y < 0 || X >= map.Width || Y >= map.Height)
            {
                return(points);
            }
            if (map.TileData[X, Y] != From)
            {
                return(points);
            }
            map.TileData[X, Y] = To;

            points.Add(new Point(X, Y));
            Queue <Point> Q = new Queue <Point>();

            Q.Enqueue(new Point(X, Y));

            while (Q.Count() > 0)
            {
                Point n = Q.Dequeue();
                X = n.X;
                Y = n.Y;
                if (X + 1 < map.Width && Y < map.Height && map.TileData[X + 1, Y] == From)
                {
                    map.TileData[X + 1, Y] = To;
                    points.Add(new Point(X + 1, Y));
                    Q.Enqueue(new Point(X + 1, Y));
                }
                if (X >= 0 && Y + 1 < map.Height && map.TileData[X, Y + 1] == From)
                {
                    map.TileData[X, Y + 1] = To;
                    points.Add(new Point(X, Y + 1));
                    Q.Enqueue(new Point(X, Y + 1));
                }
                if (X - 1 >= 0 && Y >= 0 && map.TileData[X - 1, Y] == From)
                {
                    map.TileData[X - 1, Y] = To;
                    points.Add(new Point(X - 1, Y));
                    Q.Enqueue(new Point(X - 1, Y));
                }
                if (X < map.Width && Y - 1 >= 0 && map.TileData[X, Y - 1] == From)
                {
                    map.TileData[X, Y - 1] = To;
                    points.Add(new Point(X, Y - 1));
                    Q.Enqueue(new Point(X, Y - 1));
                }
            }
            return(points);

            /*
             * FloodFill(map, X + 1, Y + 1, From, To);
             * FloodFill(map, X + 1, Y - 1, From, To);
             * FloodFill(map, X - 1, Y - 1, From, To);
             * FloodFill(map, X - 1, Y + 1, From, To);
             * //*/
        }
 /// <summary>
 /// Simple search and replace.
 /// </summary>
 /// <param name="map">Working map</param>
 /// <param name="From">Tile to replace</param>
 /// <param name="To">Replacement tile</param>
 public static void Replace(WorldMap map, WorldMap.TileType From, WorldMap.TileType To)
 {
     for (int x = 0; x < map.Width; x++)
     {
         for (int y = 0; y < map.Height; y++)
         {
             if (map.TileData[x, y] == From)
             {
                 map.TileData[x, y] = To;
             }
         }
     }
 }
        /// <summary>
        /// Check for presence of a specific tile type in a specific direction (orthogonal)
        /// </summary>
        /// <param name="map">Working map</param>
        /// <param name="X">Starting point</param>
        /// <param name="Y">Starting point</param>
        /// <param name="Direction">Direction 0,1,2,3 - West is 0 and then clockwise</param>
        /// <param name="distance">Maximum distance to look</param>
        /// <param name="Tile"></param>
        /// <returns>distance or 9999 if not found</returns>
        public static int LookRayTile(WorldMap map, int X, int Y, int Direction, int distance, WorldMap.TileType Tile)
        {
            int D  = 9999;
            int dX = 0;
            int dY = 0;

            if (Direction == DIR_E)
            {
                dX = 1;
            }
            if (Direction == DIR_W)
            {
                dX = -1;
            }
            if (Direction == DIR_N)
            {
                dY = -1;
            }
            if (Direction == DIR_S)
            {
                dY = 1;
            }
            for (int i = 0; i < distance; i++)
            {
                X += dX;
                Y += dY;
                if (X < 0 || X >= map.Width || Y < 0 || Y > map.Height)
                {
                    return(D);
                }
                WorldMap.TileType Target = map.TileData[X, Y];
                if (Target == Tile)
                {
                    return(i);
                }
            }

            return(D);
        }
        /// <summary>
        /// Places mountain tiles
        /// </summary>
        /// <param name="map">Working map</param>
        /// <param name="amount">Amount to place - currently unused</param>
        public static void DoMountains(WorldMap map, int amount)
        {
            int   cutoff                   = 200;
            int   cutoff2                  = 160;
            int   cutoff3                  = 128;
            float MountainSizeDivisor      = 1f / 32f;
            float MountainSpreadDivisor    = 1f / 128f;
            float MountainFrequencyDivisor = 1f / 512f;
            float Noise1                   = 1f / 4f;
            float Noise2                   = 1f / 6f;

            for (int x = 1; x < map.Width - 1; x++)
            {
                for (int y = 1; y < map.Height - 1; y++)
                {
                    int H  = (int)Simplex.CalcPixel2D(x, y, MountainSizeDivisor);
                    int M  = (int)Simplex.CalcPixel2D(x, y, MountainFrequencyDivisor);
                    int S  = (int)Simplex.CalcPixel2D(x, y, MountainSpreadDivisor);
                    int N1 = (int)Simplex.CalcPixel2D(x, y, Noise1);
                    int N2 = (int)Simplex.CalcPixel2D(x, y, Noise2);
                    if (H > cutoff && M > cutoff2 && S > cutoff3 && N1 > cutoff3 && N2 > cutoff3)
                    {
                        WorldMap.TileType Target = map.TileData[x, y];
                        if (Target != WorldMap.TileType.Ocean && Target != WorldMap.TileType.River)
                        {
                            map.TileData[x, y] = WorldMap.TileType.Mountain;
                            //greatly raise actual mountain tiles
                            map.ElevationData[x, y] = (float)Math.Pow((MathHelper.Clamp(map.ElevationData[x, y], 0f, 999f)), 1f / 10f);
                            //raise tiles around them too
                            if (map.TileData[x - 1, y] != WorldMap.TileType.Mountain)
                            {
                                map.ElevationData[x - 1, y] = (float)Math.Pow((MathHelper.Clamp(map.ElevationData[x - 1, y], 0f, 999f)), 1f / 3f);
                            }
                            if (map.TileData[x + 1, y] != WorldMap.TileType.Mountain)
                            {
                                map.ElevationData[x + 1, y] = (float)Math.Pow((MathHelper.Clamp(map.ElevationData[x + 1, y], 0f, 999f)), 1f / 3f);
                            }
                            if (map.TileData[x, y - 1] != WorldMap.TileType.Mountain)
                            {
                                map.ElevationData[x, y - 1] = (float)Math.Pow((MathHelper.Clamp(map.ElevationData[x, y - 1], 0f, 999f)), 1f / 3f);
                            }
                            if (map.TileData[x, y + 1] != WorldMap.TileType.Mountain)
                            {
                                map.ElevationData[x, y + 1] = (float)Math.Pow((MathHelper.Clamp(map.ElevationData[x, y + 1], 0f, 999f)), 1f / 3f);
                            }
                        }
                    }
                }
            }

            /*/
             * for (int i=0;i<amount;i++)
             * {
             *  int X = RNG.NextInt(0, map.Width);
             *  int Y = RNG.NextInt(0, map.Height);
             *  WorldMap.TileType Target = map.TileData[X, Y];
             *  if (Target != WorldMap.TileType.Ocean && Target != WorldMap.TileType.River)
             *      map.TileData[X, Y] = WorldMap.TileType.Mountain;
             * }
             * //*/
        }
        /// <summary>
        /// Populates a float 2D array with distance values on a given map from given tile type
        /// </summary>
        /// <param name="map">Working map</param>
        /// <param name="DistanceField">Initial 2D distance field</param>
        /// <param name="Target">Tile to calculate distances from</param>
        /// <returns>Computed 2D array distance field</returns>
        public static float[,] DoDistanceField(WorldMap map, float[,] DistanceField, WorldMap.TileType Target)
        {
            //pass 1: set all to something stupid like 9999 except target
            float MAX     = 9999f;
            float Highest = 0f;

            float[] neighbourhood = new float[8];
            for (int x = 0; x < map.Width; x++)
            {
                for (int y = 0; y < map.Height; y++)
                {
                    if (map.TileData[x, y] == Target)
                    {
                        DistanceField[x, y] = 0;
                    }
                    else
                    {
                        DistanceField[x, y] = MAX;
                    }
                }
            }
            //pass 2 & 3: pathfind
            for (int x = 1; x < map.Width - 1; x++)
            {
                for (int y = 1; y < map.Height - 1; y++)
                {
                    //iterate over 8 neighbours, pick the smallest, add 1
                    neighbourhood[0] = DistanceField[x - 1, y - 1];
                    neighbourhood[1] = DistanceField[x, y - 1];
                    neighbourhood[2] = DistanceField[x + 1, y - 1];
                    neighbourhood[3] = DistanceField[x - 1, y];
                    neighbourhood[4] = DistanceField[x + 1, y];
                    neighbourhood[5] = DistanceField[x - 1, y + 1];
                    neighbourhood[6] = DistanceField[x, y + 1];
                    neighbourhood[7] = DistanceField[x + 1, y + 1];
                    float smallest = neighbourhood.Min();
                    //do not make any changes if no neighbours are lower and not the default value
                    if (smallest < MAX && smallest < DistanceField[x, y])
                    {
                        DistanceField[x, y] = smallest + 1;
                    }
                }
            }
            //go from the other direction now
            for (int x = map.Width - 2; x > 0; x--)
            {
                for (int y = map.Height - 2; y > 0; y--)
                {
                    //iterate over 8 neighbours, pick the smallest, add 1
                    neighbourhood[0] = DistanceField[x - 1, y - 1];
                    neighbourhood[1] = DistanceField[x, y - 1];
                    neighbourhood[2] = DistanceField[x + 1, y - 1];
                    neighbourhood[3] = DistanceField[x - 1, y];
                    neighbourhood[4] = DistanceField[x + 1, y];
                    neighbourhood[5] = DistanceField[x - 1, y + 1];
                    neighbourhood[6] = DistanceField[x, y + 1];
                    neighbourhood[7] = DistanceField[x + 1, y + 1];
                    float smallest = neighbourhood.Min();
                    //do not make any changes if no neighbours are lower and not the default value
                    if (smallest < MAX && smallest < DistanceField[x, y])
                    {
                        //add 1 to the distance - regardless if diagonal or straight
                        DistanceField[x, y] = smallest + 1;
                        //find the furthest value - use it for scaling down to highest being 1.0f and lowest being 0.0f
                        if (Highest < smallest + 1)
                        {
                            Highest = smallest + 1;
                        }
                    }
                }
            }
            //pass 4: normalisation
            if (Highest != 0)
            {
                for (int x = 1; x < map.Width - 1; x++)
                {
                    for (int y = 1; y < map.Height - 1; y++)
                    {
                        DistanceField[x, y] /= Highest;
                    }
                }
            }
            return(DistanceField);
        }