public static void Normalize(int min, int max)
 {
     Console.WriteLine("Normalizing...");
     Console.WriteLine("Before - Max is: " + Map.max() + ", min is: " + Map.min());
     Map = Map.normalize(min, max);
     Console.WriteLine("After - Max is: " + Map.max() + ", min is: " + Map.min());
 }
        //from here: http://terraineer.sourceforge.net/plugins/hills.php
        public static Heightmap Hills(Heightmap seed, int numHills, double Steepness = 1, double ValleyProb = 0, int MaxRadius = 25, bool ellipse = false, HashSet<Point> holds = null, Random Random = null)
        {
            Map = new Heightmap(seed.Map, holds??new HashSet<Point>());
            Random rand = Random??new Random();

            for (int c = 0; c < numHills; c++)
            {
                Hill(Steepness, ValleyProb, MaxRadius, ellipse, rand);
            }

            return Map;
        }
        //From here: http://terraineer.sourceforge.net/plugins/fault.php
        public static Heightmap Faults(Heightmap seed, int numFaults, int Displacement = 2, HashSet<Point> holds = null, Random random = null)
        {
            Map = new Heightmap(seed.Map, holds ?? new HashSet<Point>());
            Random rand = random ?? new Random();

            for (int f = 0; f < numFaults; f++)
            {
                Fault(Displacement, rand);
            }

            return Map;
        }
        /// <summary>
        /// Generates a heightmap using the diamond-square method explained here: http://www.gameprogrammer.com/fractal.html
        /// For any given input size, it returns a square heightmap of dimension 2^size + 1
        /// </summary>
        /// <param name="ReqSize">The size of the resultant heightmap; it will be 2^size+1</param>
        /// <param name="variability">The initial variability in height</param>
        /// <param name="seed">The seeded values</param>
        /// <param name="roughness">How quickly the variability drops off; should be less than one</param>
        /// <param name="holds">Set of points whose seeded value should be maintained</param>
        /// <returns></returns>
        public static Heightmap DiamondSquare(int ReqSize, int variability, double roughness, Heightmap seed = null, HashSet<Point> holds = null, Random Random = null)
        {
            int size = (1 << ReqSize);

            List<List<int>> map = (seed ?? new Heightmap(size)).Map;

            for (int i = 0; i < size; i++)
            {
                if (map.Count <= i)
                {
                    map.Add(new List<int>(size));
                }

                if (map[i].Count < size)
                {
                    for (int j = 0; j < size; j++)
                    {
                        map[i].Add(0);
                    }
                }
            }
            if(seed == null)
            {
                //A default seeding - mountains in the "middle" (actually corners, but whatever).
                map[0][0] = 1000;
                map[0][size-1] = 1000;
                map[size-1][0] = 1000;
                map[size-1][size-1] = 1000;
            }

            int step = size/2;
            Map = new Heightmap(map);
            Holds = holds ?? new HashSet<Point>();
            vstep = roughness;
            rand = Random??new Random();
            DiamondSquare_Recursive(step, variability, size/2, size/2);

            return Map;
        }
        public static List<List<Heightmap>> ChopHeightmap(int SquareSize, Heightmap input)
        {
            List<List<Heightmap>> ret = new List<List<Heightmap>>();
            List<List<int>> rawmap = input.Map;

            IEnumerable<List<int>> RestColumns;
            IEnumerable<IEnumerable<int>> RestRows;
            RestColumns = rawmap;
            int count = 0;
            do
            {
                IEnumerable<List<int>> CurrentColumns = RestColumns.Take(SquareSize);
                RestColumns = RestColumns.Skip(SquareSize);

                ret.Add(new List<Heightmap>());
                RestRows = CurrentColumns;

                do
                {

                    IEnumerable<IEnumerable<int>> CurrentRows = RestRows.Select((x) => x.Take(SquareSize));
                    RestRows = RestRows.Select((x) => x.Skip(SquareSize));

                    List<List<int>> CurrentMap = CurrentRows.Select((x) => x.ToList()).ToList();
                    ret[count].Add(new Heightmap(CurrentMap));
                } while (RestRows.Max((x)=>x.Count()) > 0);

                count++;

            } while (RestColumns.Count() > 0);

            return ret;
        }
        //Executes various different heightmap forming functions at random
        public static Heightmap Arbitrary(Heightmap seed, SortedList<double, Action> functions, int iterations = 10000, Random random = null, Func<int, bool> StepCallback = null)
        {
            Map = seed;
            Random rand = random ?? new Random();

            //Want to make sure that they're sorted in descending order and normalized.
            double total = functions.Aggregate<KeyValuePair<double, Action>, double>(0, (current, next) => current + next.Key);
            var actionsSorted = (from kvp in functions select new {Key = kvp.Key/total,
                                                                  Value = kvp.Value}).OrderBy((x)=>x.Key);

            List<int> actionsDone = new List<int>(functions.Count);
            for (int i = 0; i < functions.Count; i++)
            {
                actionsDone.Add(0);
            }

            for (int i = 0; i < iterations; i++)
            {
                //try to "roll under" the key value; we perform the first action whose key + cumulative value is higher than this value.
                double randomValue = rand.NextDouble();
                double cumulativeValue = 0;

                for(int j = 0; j < actionsSorted.Count(); j++)
                {
                    var kvp = actionsSorted.ElementAt(j);
                    cumulativeValue += kvp.Key;
                    if (randomValue < cumulativeValue)
                    {
                        actionsDone[j]++;
                        kvp.Value();
                        break;
                    }
                }

                if (StepCallback != null)
                {
                    bool Continue = StepCallback(i);
                    if (!Continue)
                        break;
                }
            }

            return Map;
        }