public void Maze_Quality_Test_1()
        {
            Random rand = new Random();

            PM_Maze maze = new PM_Maze(2, 2);

            Assert.IsTrue(maze.NumCells__All() == 4);
            Assert.IsTrue(maze.NumCells__OfSpecificDirections(Directions_Ortho_2D.None) == 4);

            Assert.IsTrue(maze.IsFullyExpanded() == false);
            Assert.IsTrue(maze.IsFullyConnected() == false);
            Assert.IsTrue(maze.IsCyclic() == false);
            Assert.IsTrue(maze.Islands(rand).Count == 4);
            Assert.IsTrue(maze.All_ActiveEdges_List().Count == 0);
            Assert.IsTrue(maze.All_ActiveEdges_Set().Count == 0);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_List().Count == 4);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_Set().Count == 4);
            //Assert.IsTrue(maze.All_ExpansionEdges_List().Count == 0);

            Vec2i bottom_left  = new Vec2i(0, 0);
            Vec2i bottom_right = new Vec2i(1, 0);
            Vec2i top_left     = new Vec2i(0, 1);
            Vec2i top_right    = new Vec2i(1, 1);

            maze.OP_AddEdge(new UEdge2i(bottom_left, bottom_right));
            Assert.IsTrue(maze.IsFullyExpanded() == false);
            Assert.IsTrue(maze.IsFullyConnected() == false);
            Assert.IsTrue(maze.IsCyclic() == false);
            Assert.IsTrue(maze.Islands(rand).Count == 3);
            Assert.IsTrue(maze.All_ActiveEdges_List().Count == 1);
            Assert.IsTrue(maze.All_ActiveEdges_Set().Count == 1);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_List().Count == 3);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_Set().Count == 3);

            maze.OP_AddEdge(new UEdge2i(top_left, top_right));
            Assert.IsTrue(maze.IsFullyExpanded() == true);
            Assert.IsTrue(maze.IsFullyConnected() == false);
            Assert.IsTrue(maze.IsCyclic() == false);
            Assert.IsTrue(maze.Islands(rand).Count == 2);
            Assert.IsTrue(maze.All_ActiveEdges_List().Count == 2);
            Assert.IsTrue(maze.All_ActiveEdges_Set().Count == 2);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_List().Count == 2);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_Set().Count == 2);

            maze.OP_AddEdge(new UEdge2i(bottom_left, top_left));
            Assert.IsTrue(maze.IsFullyExpanded() == true);
            Assert.IsTrue(maze.IsFullyConnected() == true);
            Assert.IsTrue(maze.IsCyclic() == false);
            Assert.IsTrue(maze.Islands(rand).Count == 1);
            Assert.IsTrue(maze.All_ActiveEdges_List().Count == 3);
            Assert.IsTrue(maze.All_ActiveEdges_Set().Count == 3);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_List().Count == 1);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_Set().Count == 1);

            maze.OP_AddEdge(new UEdge2i(bottom_right, top_right));
            Assert.IsTrue(maze.IsFullyExpanded() == true);
            Assert.IsTrue(maze.IsFullyConnected() == true);
            Assert.IsTrue(maze.IsCyclic() == true);
            Assert.IsTrue(maze.Islands(rand).Count == 1);
            Assert.IsTrue(maze.All_ActiveEdges_List().Count == 4);
            Assert.IsTrue(maze.All_ActiveEdges_Set().Count == 4);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_List().Count == 0);
            Assert.IsTrue(maze.All_InactiveEdges_InBounds_Set().Count == 0);
        }
        /// <summary>
        /// Wall thickness is an inteeger, between 0 and ....
        /// The
        /// </summary>
        /// <param name="maze"></param>
        /// <param name="background_color"></param>
        /// <param name="wall_color"></param>
        /// <param name="wall_thickness"></param>
        /// <param name="cell_size"></param>
        /// <returns></returns>
        public static Bitmap Draw_2(
            this PM_Maze maze,
            Random rand,
            int cell_size,
            int wall_thickness,
            Color background_color,
            Color disconnected_cell_color,
            Color wall_color,
            bool draw_solution,
            bool draw_islands
            )
        {
            int maze_width  = maze.Q_Width();
            int maze_height = maze.Q_Height();

            //int wall_thickness = 1;

            int image_width  = maze_width * cell_size;
            int image_height = maze_height * cell_size;

            int wall_actual_thickness = (wall_thickness - 1) * 2 + 1;

            Bitmap image = new Bitmap(image_width, image_height);

            using (Graphics buffer_graphics = Graphics.FromImage(image))
                using (Pen wall_pen = new Pen(wall_color, wall_actual_thickness))
                    using (SolidBrush disconnected_cells_brush = new SolidBrush(disconnected_cell_color))
                        using (SolidBrush islands_brush = new SolidBrush(Color.Black))
                        {
                            buffer_graphics.Clear(background_color);
                            //bufferGraphics.FillRectangle(Brushes.Black, 0, 0, this.Width, this.Height);
                            Vec2i offset = new Vec2i(cell_size / 2, cell_size / 2);

                            //Pen hardPen = new Pen(wall_color, wall_thickness);
                            wall_pen.SetLineCap(
                                System.Drawing.Drawing2D.LineCap.Square,
                                System.Drawing.Drawing2D.LineCap.Square,
                                System.Drawing.Drawing2D.DashCap.Flat
                                );

                            var cells_coordinates = maze.CellsPositions_All_List();

                            if (draw_islands)
                            {
                                var islands = maze.Islands(rand);
                                if (islands.Count > 1)
                                {
                                    List <Color> colors_per_island = new List <Color>();
                                    foreach (var island in islands)
                                    {
                                        int   r = rand.Next(0, 256);
                                        int   g = rand.Next(0, 256);
                                        int   b = rand.Next(0, 256);
                                        Color c = Color.FromArgb(r, g, b);
                                        colors_per_island.Add(c);
                                    }

                                    for (int i = 0; i < islands.Count; i++)
                                    {
                                        islands_brush.Color = colors_per_island[i];
                                        foreach (var island_cell in islands[i])
                                        {
                                            // draw that cell with that color
                                            buffer_graphics.FillRectangle(
                                                islands_brush,
                                                island_cell.x * cell_size,
                                                island_cell.y * cell_size,
                                                cell_size,
                                                cell_size
                                                );
                                        }
                                    }
                                }
                            }

                            // draw the disconnected cells
                            foreach (var cell_coordinates in cells_coordinates)
                            {
                                int position_x = cell_coordinates.x * cell_size;
                                int position_y = cell_coordinates.y * cell_size;

                                var cell_directions = maze.Q_Cell_Directions(cell_coordinates);

                                if (cell_directions == Directions_Ortho_2D.None)
                                {
                                    buffer_graphics.FillRectangle(
                                        disconnected_cells_brush,
                                        position_x,
                                        position_y,
                                        cell_size,
                                        cell_size
                                        );
                                }
                            }

                            foreach (var cell_coordinates in cells_coordinates)
                            {
                                int position_x = cell_coordinates.x * cell_size;
                                int position_y = cell_coordinates.y * cell_size;

                                Point bottom_left = new Point(
                                    position_x + wall_thickness - 1,
                                    position_y + wall_thickness - 1
                                    );

                                Point bottom_right = new Point(
                                    position_x + cell_size - wall_thickness,
                                    position_y + wall_thickness - 1
                                    );

                                Point top_left = new Point(
                                    position_x + wall_thickness - 1,
                                    position_y + cell_size - wall_thickness
                                    );

                                Point top_right = new Point(
                                    position_x + cell_size - wall_thickness,
                                    position_y + cell_size - wall_thickness
                                    );

                                var cell_directions = maze.Q_Cell_Directions(cell_coordinates);

                                // up - wall
                                if (cell_directions.HasFlag(Directions_Ortho_2D.U) == false)
                                {
                                    buffer_graphics.DrawLine(wall_pen, top_left, top_right);
                                }

                                if (cell_directions.HasFlag(Directions_Ortho_2D.D) == false)
                                {
                                    buffer_graphics.DrawLine(wall_pen, bottom_left, bottom_right);
                                }

                                if (cell_directions.HasFlag(Directions_Ortho_2D.L) == false)
                                {
                                    buffer_graphics.DrawLine(wall_pen, bottom_left, top_left);
                                }

                                if (cell_directions.HasFlag(Directions_Ortho_2D.R) == false)
                                {
                                    buffer_graphics.DrawLine(wall_pen, bottom_right, top_right);
                                }
                            }

                            if (draw_solution)
                            {
                                List <Vec2i> solution = maze.BFS_ShortestPath(new Vec2i(0, 0), new Vec2i(maze.Q_Width() - 1, maze.Q_Height() - 1));
                                using (Pen solution_pen = new Pen(Color.Red, wall_thickness))
                                {
                                    solution_pen.SetLineCap(
                                        System.Drawing.Drawing2D.LineCap.Round,
                                        System.Drawing.Drawing2D.LineCap.Round,
                                        System.Drawing.Drawing2D.DashCap.Round
                                        );

                                    for (int i = 0; i < solution.Count - 1; i++)
                                    {
                                        Vec2i pt1 = solution[i];
                                        Vec2i pt2 = solution[i + 1];

                                        int   posX_1 = pt1.x * cell_size + cell_size / 2;
                                        int   posY_1 = pt1.y * cell_size + cell_size / 2;
                                        Point p1     = new Point(posX_1, posY_1);

                                        int   posX_2 = pt2.x * cell_size + cell_size / 2;
                                        int   posY_2 = pt2.y * cell_size + cell_size / 2;
                                        Point p2     = new Point(posX_2, posY_2);

                                        buffer_graphics.DrawLine(solution_pen, p1, p2);
                                    }
                                }
                            }
                        }

            return(image);
        }