private void add_all_natural_features(List<NaturalFeature.Feature_Type> features)
        {
            for (int i = 0; i < features.Count; i++)
            {
                if (features[i] == NaturalFeature.Feature_Type.River ||
                    features[i] == NaturalFeature.Feature_Type.Chasm)
                {
                    int feature_length_side1 = randGen.Next(15, 26);
                    int feature_length_side2 = randGen.Next(15, 26);

                    gridCoordinate feature_center = random_valid_position(current_floorsize);
                    gridCoordinate feature_start = new gridCoordinate(-1, -1);
                    gridCoordinate feature_end = new gridCoordinate(-1, -1);
                    bool valid_feature = false;

                    while (!valid_feature)
                    {
                        //Start with a random valid position
                        feature_center = random_valid_position(current_floorsize);
                        //Generate direction vectors for each side of the feature.
                        float side_xVector = (float)Math.Cos(randGen.NextDouble() * Math.PI * 2);
                        float side_yVector = (float)Math.Sin(randGen.NextDouble() * Math.PI * 2);
                        Vector2 side_directionVector = new Vector2(side_xVector, side_yVector);

                        //Adjust the endpoints.
                        feature_start = new gridCoordinate(feature_center);
                        feature_end = new gridCoordinate(feature_center);
                        feature_start.add_vector2(side_directionVector * feature_length_side1);
                        feature_end.add_vector2(side_directionVector * feature_length_side2 * -1);

                        //Force the values to be safe.
                        feature_start.force_safe_value(current_floorsize);
                        feature_end.force_safe_value(current_floorsize);

                        //Check to see whether the values are okay. All river values are accepted
                        //Chasm values are rerolled if they're too close to the edge.
                        if (features[i] == NaturalFeature.Feature_Type.River)
                            valid_feature = true;
                        else if (features[i] == NaturalFeature.Feature_Type.Chasm)
                        {
                            if (feature_start.x > 4 && feature_start.x < 47 &&
                               feature_start.y > 4 && feature_start.y < 47 &&
                               feature_end.x > 4 && feature_end.x < 47 &&
                               feature_end.y > 4 && feature_end.y < 47)
                                valid_feature = true;
                        }
                    }

                    if (features[i] == NaturalFeature.Feature_Type.River)
                    {
                        //Add the new river
                        int deepwater_thickness = randGen.Next(2);
                        int shallows_thickness = 1 + randGen.Next(3);
                        int banks_thickness = 1 + randGen.Next(2);
                        featurelayout.Add(new NaturalFeature(feature_start, feature_end, NaturalFeature.River_Type.Normal,
                                                                                         deepwater_thickness,
                                                                                         shallows_thickness,
                                                                                         banks_thickness));
                    }
                    else if (features[i] == NaturalFeature.Feature_Type.Chasm)
                    {
                        //Add the new chasm
                        int max_thickness = randGen.Next(6, 13);
                        featurelayout.Add(new NaturalFeature(feature_start, feature_end, max_thickness));
                    }
                }
                else if (features[i] == NaturalFeature.Feature_Type.Lake)
                {
                    gridCoordinate feature_center = random_valid_position(current_floorsize);

                    int xSize = randGen.Next(11, 18);
                    int ySize = randGen.Next(11, 18);
                    int room_thickness = 1 + randGen.Next(2);
                    int shore_thickness = 1 + randGen.Next(2);
                    int shallows_thickness = 1 + randGen.Next(2);

                    gridCoordinate feature_start = new gridCoordinate(feature_center.x - xSize / 2, feature_center.y - ySize / 2);
                    gridCoordinate feature_end = new gridCoordinate(feature_center.x + xSize / 2, feature_center.y + ySize / 2);
                    feature_start.force_safe_value(current_floorsize);
                    feature_end.force_safe_value(current_floorsize);

                    featurelayout.Add(new NaturalFeature(feature_start, feature_end, room_thickness, shore_thickness, shallows_thickness));
                }
            }
        }
        public void draw_linear_feature(ref List<List<Tile>> grid, 
                                        ref List<Fl_Special_Event> event_list, Random rGen,
                                        Tile.Tile_Type[] feature_tiletypes,
                                        Texture2D general_sheet,
                                        Texture2D dungeon_sheet,
                                        List<KeyValuePair<Tile.Tile_Type, gridCoordinate>> texture_map)
        {
            //First determine whether it's a mostly horizontal or vertical river.
            //Get differences.
            int abs_xDif = Math.Abs(feature_startCoord.x - feature_endCoord.x);
            int abs_yDif = Math.Abs(feature_startCoord.y - feature_endCoord.y);
            int xDif = feature_startCoord.x - feature_endCoord.x;
            int yDif = feature_startCoord.y - feature_endCoord.y;
            //Get Vector points.
            Vector2 end_position = new Vector2(feature_endCoord.x * 32, feature_endCoord.y * 32);
            //Get pixel differences
            double xPixels = xDif * 32;
            double yPixels = yDif * 32;

            gridCoordinate[,] dirs =  {{new gridCoordinate(1, 0), new gridCoordinate(-1, 0)},
                                       {new gridCoordinate(0, 1), new gridCoordinate(0, -1)}};
            //Vertical
            int direct = 0;
            gridCoordinate.coord xy = gridCoordinate.coord.xCoord;
            //If x difference > y difference, it's a horizontally drawn feature
            if (abs_xDif > abs_yDif)
            {
                direct = 1;
                xy = gridCoordinate.coord.yCoord;
            }

            Vector2 c_position = new Vector2(feature_startCoord.x * 32, feature_startCoord.y * 32);
            double c_xvalue = c_position.X;
            double c_yvalue = c_position.Y;
            bool done = false;
            gridCoordinate current_position = new gridCoordinate(-1, -1);
            gridCoordinate previous_position = new gridCoordinate(-1, -1);
            int length_completed = 0;
            while (!done)
            {
                done = is_river_finished(c_xvalue, c_yvalue);
                current_position = new gridCoordinate((int)(c_xvalue / 32), (int)(c_yvalue / 32));

                bool good_to_draw = false;
                if (xy == gridCoordinate.coord.yCoord && current_position.x != previous_position.x)
                    good_to_draw = true;
                if (xy == gridCoordinate.coord.xCoord && current_position.y != previous_position.y)
                    good_to_draw = true;

                if (good_to_draw)
                {
                    //Determine whether or not the upcoming section of the river is a crossing point.
                    length_completed += 1;
                    bool crossing_point = false;
                    if (my_fType == Feature_Type.River)
                    {
                        for (int i = 0; i < crossing_points.Count; i++)
                            if (length_completed == crossing_points[i])
                                crossing_point = true;
                    }

                    //Get the sizes of the right edge
                    int[] rr = { };
                    if (my_fType == Feature_Type.River)
                    {
                        rr = new int[] {rGen.Next(deepwater_thickness+1) + 1,
                                        rGen.Next(1, shallow_thickness+1),
                                        rGen.Next(1, banks_thickness+1)};
                    }
                    else if (my_fType == Feature_Type.Chasm)
                    {
                        double v = (double)length_completed / (double)chasm_length;
                        int width = (int)((1.0 - Math.Abs(Math.Sin(v * Math.PI - (Math.PI / 2)))) * maximum_thickness);
                        width /= 2;
                        rr = new int[] { width + 1, 2 + rGen.Next(2) };
                    }
                    //Translate to actual coordinates.
                    int[] rEdge = new int[1];
                    if (my_fType == Feature_Type.River)
                    {
                        rEdge = new int[3];
                        rEdge[0] = current_position.get_a_coord(xy) + 1 + rr[0];
                        rEdge[1] = rEdge[0] + rr[1];
                        rEdge[2] = rEdge[1] + rr[2];
                    }
                    else if (my_fType == Feature_Type.Chasm)
                    {
                        rEdge = new int[2];
                        rEdge[0] = current_position.get_a_coord(xy) + 1 + rr[0];
                        rEdge[1] = rEdge[0] + rr[1];
                    }

                    //Use deep water unless it's a crossing point.
                    Tile.Tile_Type first_tiletype = feature_tiletypes[0];
                    if (my_fType == Feature_Type.River && crossing_point)
                        first_tiletype = feature_tiletypes[1];

                    //Fill in the center coordinate.
                    grid[current_position.x][current_position.y].set_tile_type(first_tiletype, general_sheet, dungeon_sheet, texture_map);
                    int redge_max = rEdge[rEdge.Count() - 1];
                    //Fill in the right edge.
                    for (gridCoordinate i = new gridCoordinate(current_position);
                         i.get_a_coord(xy) < redge_max;
                         i.combineCoords(dirs[direct, 0]))
                    {
                        if (i.get_a_coord(xy) >= grid.Count)
                            break;

                        if (i.get_a_coord(xy) < rEdge[0])
                            grid[i.x][i.y].set_tile_type(first_tiletype, general_sheet, dungeon_sheet, texture_map);
                        else if (i.get_a_coord(xy) < rEdge[1])
                            grid[i.x][i.y].set_tile_type(feature_tiletypes[1], general_sheet, dungeon_sheet, texture_map);
                        else
                            grid[i.x][i.y].set_tile_type(feature_tiletypes[2], general_sheet, dungeon_sheet, texture_map);
                    }

                    //Get the sizes of the left edge
                    int[] lr = { };
                    if (my_fType == Feature_Type.River)
                    {
                        lr = new int[] {rGen.Next(deepwater_thickness+1) + 1,
                                        rGen.Next(1, shallow_thickness+1),
                                        rGen.Next(1, banks_thickness+1)};
                    }
                    else if (my_fType == Feature_Type.Chasm)
                    {
                        double v = (double)length_completed / (double)chasm_length;
                        int width = (int)((1.0 - Math.Abs(Math.Sin(v * Math.PI - (Math.PI / 2)))) * maximum_thickness);
                        width /= 2;
                        lr = new int[] { width + 1, 2 + rGen.Next(2) };
                    }
                    //Translate to actual coodinates
                    int[] lEdge = new int[1];
                    if (my_fType == Feature_Type.River)
                    {
                        lEdge = new int[3];
                        lEdge[0] = current_position.get_a_coord(xy) - 1 - lr[0];
                        lEdge[1] = lEdge[0] - lr[1];
                        lEdge[2] = lEdge[1] - lr[2];
                    }
                    else if (my_fType == Feature_Type.Chasm)
                    {
                        lEdge = new int[2];
                        lEdge[0] = current_position.get_a_coord(xy) - 1 - lr[0];
                        lEdge[1] = lEdge[0] - lr[1];
                    }

                    //Fill in the left edge.
                    int ledge_max = lEdge[lEdge.Count() - 1];
                    for (gridCoordinate i = new gridCoordinate(current_position);
                         i.get_a_coord(xy) > ledge_max;
                         i.combineCoords(dirs[direct, 1]))
                    {
                        if (i.get_a_coord(xy) < 0)
                            break;

                        if (i.get_a_coord(xy) > lEdge[0])
                            grid[i.x][i.y].set_tile_type(first_tiletype, general_sheet, dungeon_sheet, texture_map);
                        else if (i.get_a_coord(xy) > lEdge[1])
                            grid[i.x][i.y].set_tile_type(feature_tiletypes[1], general_sheet, dungeon_sheet, texture_map);
                        else
                            grid[i.x][i.y].set_tile_type(feature_tiletypes[2], general_sheet, dungeon_sheet, texture_map);
                    }

                    if (my_fType == Feature_Type.Chasm && length_completed == cavern_point)
                    {
                        int x_position = 0;
                        int y_position = 0;

                        //Horizontal
                        if (direct == 1)
                        {
                            x_position = current_position.x;
                            if (cavern_right)
                                y_position = redge_max;
                            else
                                y_position = ledge_max;
                        }
                        //Vertical
                        else
                        {
                            y_position = current_position.y;
                            if (cavern_right)
                                x_position = redge_max;
                            else
                                x_position = ledge_max;
                        }

                        gridCoordinate cavern_entrance_coord = new gridCoordinate(x_position, y_position);
                        cavern_entrance_coord.force_safe_value(grid.Count);
                        grid[cavern_entrance_coord.x][cavern_entrance_coord.y].set_tile_type(Tile.Tile_Type.Cavern_Exit, general_sheet, dungeon_sheet, texture_map);
                        event_list.Add(new Fl_Special_Event(Fl_Special_Event.event_triggers.player_in_area, Fl_Special_Event.event_type.spawn_weak_monster, 6, 3, true, cavern_entrance_coord));
                    }
                }

                Vector2 direction = end_position - c_position;
                direction.Normalize();

                c_xvalue += direction.X;
                c_yvalue += direction.Y;

                previous_position = current_position;
            }
        }