private void Weather(int width, int height, float T, Vector2[] neighbs, float[,] buffer)
        {
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    buffer[x, y] = Overworld.Map.Map[x, y].Height * Overworld.Map.Map[x, y].Faults;
                }
            }

            int weatheringIters = 10;

            for (int iter = 0; iter < weatheringIters; iter++)
            {
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        Vector2 p              = new Vector2(x, y);
                        Vector2 maxDiffNeigh   = Vector2.Zero;
                        float   maxDiff        = 0;
                        float   totalDiff      = 0;
                        float   h              = OverworldImageOperations.GetHeight(buffer, p);
                        float   lowestNeighbor = 0.0f;
                        for (int i = 0; i < 4; i++)
                        {
                            float nh   = OverworldImageOperations.GetHeight(buffer, p + neighbs[i]);
                            float diff = h - nh;
                            totalDiff += diff;
                            if (diff > maxDiff)
                            {
                                maxDiffNeigh   = neighbs[i];
                                maxDiff        = diff;
                                lowestNeighbor = nh;
                            }
                        }

                        if (maxDiff > T)
                        {
                            OverworldImageOperations.AddValue(Overworld.Map.Map, p + maxDiffNeigh, OverworldField.Weathering, (float)(maxDiff * 0.4f));
                            OverworldImageOperations.AddValue(Overworld.Map.Map, p, OverworldField.Weathering, (float)(-maxDiff * 0.4f));
                        }
                    }
                }

                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        Vector2 p = new Vector2(x, y);
                        float   w = OverworldImageOperations.GetValue(Overworld.Map.Map, p, OverworldField.Weathering);
                        OverworldImageOperations.AddHeight(buffer, p, w);
                        Overworld.Map.Map[x, y].Weathering = 0.0f;
                    }
                }
            }

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Overworld.Map.Map[x, y].Weathering = buffer[x, y] - Overworld.Map.Map[x, y].Height * Overworld.Map.Map[x, y].Faults;
                }
            }
        }
        private void Erode(int width, int height, float seaLevel, OverworldCell[,] heightMap, int numRains, int rainLength, int numRainSamples, float[,] buffer)
        {
            float remaining = 1.0f - Progress - 0.2f;
            float orig      = Progress;

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    buffer[x, y] = heightMap[x, y].Height;
                }
            }

            for (int i = 0; i < numRains; i++)
            {
                Progress = orig + remaining * ((float)i / (float)numRains);
                Vector2 currentPos = new Vector2(0, 0);
                Vector2 bestPos    = currentPos;
                float   bestHeight = 0.0f;
                for (int k = 0; k < numRainSamples; k++)
                {
                    int randX = Random.Next(1, width - 1);
                    int randY = Random.Next(1, height - 1);

                    currentPos = new Vector2(randX, randY);
                    float h = OverworldImageOperations.GetHeight(buffer, currentPos);

                    if (h > bestHeight)
                    {
                        bestHeight = h;
                        bestPos    = currentPos;
                    }
                }

                currentPos = bestPos;

                const float erosionRate = 0.9f;
                Vector2     velocity    = Vector2.Zero;
                for (int j = 0; j < rainLength; j++)
                {
                    Vector2 g = OverworldImageOperations.GetMinNeighbor(buffer, currentPos);

                    float h = OverworldImageOperations.GetHeight(buffer, currentPos);

                    if (h < seaLevel || g.LengthSquared() < 1e-12)
                    {
                        break;
                    }

                    OverworldImageOperations.MinBlend(Overworld.Map.Map, currentPos, erosionRate * OverworldImageOperations.GetValue(Overworld.Map.Map, currentPos, OverworldField.Erosion), OverworldField.Erosion);

                    velocity    = 0.1f * g + 0.7f * velocity + 0.2f * MathFunctions.RandVector2Circle();
                    currentPos += velocity;
                }
            }
        }