Ejemplo n.º 1
0
        /// <summary>
        /// While the actual controls are still visible, create and place (invisible) placeholders at new locations.
        /// These placeholders are used for reserving free areas in the maze.
        /// </summary>
        private void PreparePlaceholderControls()
        {
            visibleControls.Clear();
            placeholderControls.Clear();

            PreparePlaceholderControl(this.outerInfoPanel, RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_SHOW_DETAILS_BOX));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Add an outline shape to the maze.
        /// </summary>
        private bool AddOutlineShape()
        {
            int percentage = (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_OUTLINE_SHAPES) ? 80 : 0);

            if (random.Next(100) < percentage)
            {
                OutlineShape shape = mazeUserControl.RandomShape(0.3, 0.7, random);
                mazeUserControl.Maze.OutlineShape = shape;

                return(true);
            }

            return(false);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Place reserved areas into the maze.
        /// This method is called from the MazeUserControl before actually building the maze.
        /// </summary>
        /// <param name="maze"></param>
        public override void MakeReservedAreas(Maze maze)
        {
            base.MakeReservedAreas(maze);

            #region Info Panel (and other controls)

            for (int i = 0; i < placeholderControls.Count; i++)
            {
                mazeUserControl.ReserveArea(placeholderControls[i]);
            }

            #endregion

            #region Images and other adornments

            // Images.
            if (!mazeUserControl.HasPreparedImages)
            {
                this.PrepareImages();
            }
            mazeUserControl.ReserveAreaForImages();

            // The remaining adornments are not applied to the first maze.
            if (loadingFirstMaze == false)
            {
                bool hasEmbeddedShape = false;

                if (!hasEmbeddedShape)
                {
                    // Embedded mazes.
                    hasEmbeddedShape |= this.AddEmbeddedMaze();
                }

                if (!hasEmbeddedShape)
                {
                    // Outline shapes.
                    hasEmbeddedShape |= this.AddOutlineShape();
                }

                // Irregular maze shapes.
                if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_IRREGULAR_MAZES) && random.Next(100) < 10)
                {
                    maze.Irregular    = true;
                    maze.Irregularity = 80;
                }
            }

            #endregion
        }
Ejemplo n.º 4
0
        private void LoadSettings()
        {
            // General tab.
            checkBoxDetailsBox.Checked          = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_SHOW_DETAILS_BOX);
            checkBoxBlinking.Checked            = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_BLINKING);
            checkBoxEfficientSolvers.Checked    = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_EFFICIENT_SOLVERS);
            textBoxStepsPerSecond.Text          = RegisteredOptions.GetIntSetting(RegisteredOptions.OPT_STEPS_PER_SECOND).ToString();
            checkBoxLogSolverStatistics.Checked = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_LOG_SOLVER_STATISTICS);

#if !DEBUG
            // No logging in Release version
            checkBoxLogSolverStatistics.Visible = false;
#endif

            // Images tab.
            imageNumberNumericUpDown.Value = RegisteredOptions.GetIntSetting(RegisteredOptions.OPT_IMAGE_NUMBER);
            InitImageSizeCtrl(imageMinSizeNumericUpDown, RegisteredOptions.OPT_IMAGE_MIN_SIZE, RegisteredOptions.OPT_IMAGE_MIN_SIZE_PCT);
            InitImageSizeCtrl(imageMaxSizeNumericUpDown, RegisteredOptions.OPT_IMAGE_MAX_SIZE, RegisteredOptions.OPT_IMAGE_MAX_SIZE_PCT);
            imageFolderTextBox.Text = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_IMAGE_FOLDER);
            subtractImagesBackgroundCheckBox.Checked = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_IMAGE_SUBTRACT_BACKGROUND);

            // Background tab.
            checkBoxBackgroundImage.Checked   = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_BACKGROUND_IMAGES);
            backgroundImageFolderTextBox.Text = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_BACKGROUND_IMAGE_FOLDER);

            if (backgroundImageFolderTextBox.Text == "")
            {
                checkBoxDifferentBackgroundImageFolder.Checked = false;
                backgroundImageFolderTextBox.Enabled           = false;
                selectBackgroundImageFolderButton.Enabled      = false;
                backgroundImageFolderTextBox.Text = imageFolderTextBox.Text;
            }
            else
            {
                checkBoxDifferentBackgroundImageFolder.Checked = true;
                backgroundImageFolderTextBox.Enabled           = true;
                selectBackgroundImageFolderButton.Enabled      = true;
            }

            // Extras tab.
            checkBoxPaintAllWalls.Checked  = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_PAINT_ALL_WALLS);
            checkBoxOutlineShapes.Checked  = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_OUTLINE_SHAPES);
            checkBoxIrregularMazes.Checked = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_IRREGULAR_MAZES);
            checkBoxMultipleMazes.Checked  = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_MULTIPLE_MAZES);
            imageBackgroundFuzzinessNumericUpDown.Value = RegisteredOptions.GetIntSetting(RegisteredOptions.OPT_IMAGE_BACKGROUND_FUZZINESS);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Place reserved areas into the maze.
        /// This method is called from the MazeUserControl before actually building the maze.
        /// </summary>
        /// <param name="maze"></param>
        public void MakeReservedAreas(Maze maze)
        {
            if (infoPanelPainter != null)
            {
                infoPanelPainter.ChooseLocation(mazeUserControl.Size, this.random);
                mazeUserControl.ReserveArea(infoPanelPainter.Panel);
            }

            #region Images and other adornments

            // Images.
            if (!mazeUserControl.HasPreparedImages)
            {
                this.PrepareImages();
            }
            mazeUserControl.ReserveAreaForImages();

            // The remaining adornments are not applied to the first maze.
            if (loadingFirstMaze == false)
            {
                bool hasEmbeddedShape = false;

                if (!hasEmbeddedShape)
                {
                    // Embedded mazes.
                    hasEmbeddedShape |= this.AddEmbeddedMaze();
                }

                if (!hasEmbeddedShape)
                {
                    // Outline shapes.
                    hasEmbeddedShape |= this.AddOutlineShape();
                }

                // Irregular maze shapes.
                if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_IRREGULAR_MAZES) && random.Next(100) < 10)
                {
                    maze.Irregular    = true;
                    maze.Irregularity = 80;
                }
            }

            #endregion
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Creates the embedded mazes, as defined in embeddedMazeShapes.
        /// </summary>
        /// Note: The algorithm must provide that all mazes (main and embedded) are totally connected.
        private void FixEmbeddedMazes()
        {
            for (int i = 0; i < embeddedMazeShapes.Count; i++)
            {
                int embeddedMazeId = this.MazeId + 1 + i;

                if (embeddedMazeId > MazeSquare.MaxMazeId)
                {
                    break;
                }

                // We need a test that regards the reserved squares and current embedded mazes as the "inside" of a shape.
                OutlineShape.InsideShapeDelegate regularTest = delegate(int x, int y)
                {
                    return(this.squares[x, y].MazeId != MazeSquare.PrimaryMazeId);
                };

                // This test ensures that the border of the main maze must also not be covered.
                OutlineShape.InsideShapeDelegate conservativeTest = delegate(int x, int y)
                {
                    if (x - 2 < 0 || x + 2 >= this.XSize || y - 2 < 0 || y + 2 >= this.YSize)
                    {
                        return(true);
                    }
                    return(this.squares[x, y].MazeId != MazeSquare.PrimaryMazeId);
                };

                OutlineShape originalShape  = embeddedMazeShapes[i];
                OutlineShape connectedShape = originalShape.ConnectedSubset(conservativeTest).Closure(regularTest);

                // Discard the shape if the connected subset is too small.
                if (connectedShape.Area >= 0.3 * originalShape.Area)
                {
                    EmbeddedMaze embeddedMaze = new EmbeddedMaze(this, embeddedMazeId, connectedShape);
                    this.embeddedMazes.Add(embeddedMaze);
                }

                if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_OUTLINE_SHAPES))
                {
                    // The disconnected and enclosed parts of the original shape are handled as a regular outline shape.
                    FixOutline(originalShape);
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Returns an ImageLoader configured with the screen saver parameters from the registry
        /// or null if the "image number" option is 0.
        /// </summary>
        /// <returns></returns>
        public static ImageLoader GetScreenSaverImageLoader(Rectangle screenBounds)
        {
            int    count            = RegisteredOptions.GetIntSetting(RegisteredOptions.OPT_IMAGE_NUMBER);
            int    minSize          = ImageSize(screenBounds, RegisteredOptions.OPT_IMAGE_MIN_SIZE, RegisteredOptions.OPT_IMAGE_MIN_SIZE_PCT);
            int    maxSize          = ImageSize(screenBounds, RegisteredOptions.OPT_IMAGE_MAX_SIZE, RegisteredOptions.OPT_IMAGE_MAX_SIZE_PCT);
            string imageFolder      = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_IMAGE_FOLDER);
            bool   backgroundImages = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_BACKGROUND_IMAGES);

            if (count > 0)
            {
                ImageLoader result = new ImageLoader(minSize, maxSize, false, imageFolder, count + 2, "FGIL");
                result.YieldNullPercentage = (backgroundImages ? 5 : 0);
                return(result);
            }
            else
            {
                return(null);
            }
        }
Ejemplo n.º 8
0
        private void ScreenSaverForm_Load(object sender, EventArgs e)
        {
            // Switch auto repeat mode on.
            ariadneController.RepeatMode = true;

            if (fullScreenMode)
            {
                SetupFullscreenScreenSaver();

                // Let the MazeUserControl cover the whole form.
                this.mazeUserControl.Location = new Point(0, 0);
                this.mazeUserControl.Size     = this.Size;
            }
            else
            {
                // Let the MazeUserControl cover most of the form.
                this.mazeUserControl.Location = new Point(0, 0);
                this.mazeUserControl.Size     = this.DisplayRectangle.Size;
            }
            this.mazeUserControl.BringToFront();

            // Other optional controls need to be displayed in front of the maze.
            this.outerInfoPanel.BringToFront();

            // Load background images.
            if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_BACKGROUND_IMAGES))
            {
                string imageFolder = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_BACKGROUND_IMAGE_FOLDER);
                if (imageFolder == "")
                {
                    imageFolder = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_IMAGE_FOLDER);
                }
                int percentage = ((RegisteredOptions.GetIntSetting(RegisteredOptions.OPT_IMAGE_NUMBER) > 0) ? 20 : 100);
                this.mazeUserControl.MazePainter.CreateBackgroundImageLoader(imageFolder, percentage);
            }

            this.OnNew(null, null);
            this.OnStart(null, null);

            // Now the first maze has been loaded.
            this.loadingFirstMaze = false;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Returns a desired image size (minimum or maximum size in pixels, width or height)
        /// corresponding to the given option names.
        /// If the option for showing a details box is active, this will be considered by
        /// reducing the given screenBounds height.
        /// </summary>
        /// <returns>The size.</returns>
        /// <param name="screenBounds">Contains the screen (or drawing area) size.</param>
        /// <param name="optNamePx">Opt name for a Pixel parameter.</param>
        /// <param name="optNamePct">Opt name for a Percentage parameter.</param>
        private static int ImageSize(Rectangle screenBounds, string optNamePx, string optNamePct)
        {
            // Before version 3.5: image sizes are given in pixels
            int result = RegisteredOptions.GetIntSetting(optNamePx);

            // Since version 3.5: image sizes are given as a percentage of the screen size
            int pct = RegisteredOptions.GetIntSetting(optNamePct);

            if (pct > 0)
            {
                int detailsBoxMargin = 0;
                if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_SHOW_DETAILS_BOX))
                {
                    detailsBoxMargin = 60;
                }
                int screenSize = Math.Min(screenBounds.Width, screenBounds.Height);
                result = pct * (screenSize - detailsBoxMargin) / 100;
            }

            return(result);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns a new MazeSolver.
        /// A (reasonably) intelligent strategy is chosen randomly.
        /// </summary>
        /// <param name="maze"></param>
        /// <returns></returns>
        private static IMazeSolver CreateSolver(Maze maze, IMazeDrawer mazeDrawer)
        {
            Random r = SWA.Utilities.RandomFactory.CreateRandom();

            while (true)
            {
                Type t = solverTypes[r.Next(solverTypes.Length)];
                bool shouldBeEfficient = (r.Next(2) == 0);
                shouldBeEfficient &= RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_EFFICIENT_SOLVERS);
                bool shouldUseHeuristic = (r.Next(2) == 0);
                // Note: There is currently no equivaelnt OPT_HEURISTIC_SOLVERS option.

                if (t == typeof(RandomWalker))
                {
                    // too dumb
                    continue;
                }

                if (t == typeof(MasterSolver))
                {
                    // too smart
                    continue;
                }

                IMazeSolver result = CreateSolver(t, maze, mazeDrawer);

                if (shouldBeEfficient && HasEfficientVariant(t))
                {
                    result.MakeEfficient();
                }
                if (shouldUseHeuristic && HasHeuristicVariant(t))
                {
                    result.UseHeuristic();
                }

                return(result);
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Start a solver.
        /// </summary>
        public void Start()
        {
            stepTimer          = new Timer();
            stepTimer.Interval = (1000 / 60); // 60 frames per second
            stepTimer.Tick    += new EventHandler(this.OnStepTimer);
            stepTimer.Start();

            blinkTimer          = new Timer();
            blinkTimer.Interval = 600; // ms
            blinkTimer.Tick    += new EventHandler(this.OnBlinkTimer);
            if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_BLINKING))
            {
                blinkTimer.Start();
            }

            ResetCounters();

            solverController.Start();
            this.finishedStrategyName = solverController.StrategyName;
            client.NotifyControllerStateChanged();

            lapStartTime = System.DateTime.Now;
        }
Ejemplo n.º 12
0
        public ScreenSaverForm(bool fullScreenMode, ImageLoader imageLoader)
        {
            InitializeComponent();

            if (fullScreenMode)
            {
                this.Text += "/" + Process.GetCurrentProcess().Id; // make it unique
            }

            this.fullScreenMode = fullScreenMode;
            this.imageLoader    = imageLoader;
            this.ShowInTaskbar  = !this.fullScreenMode;
            this.DoubleBuffered = false;

            // Initially, the (optionally) displayed controls should be invisible until the maze has been built.
            this.outerInfoPanel.Visible = false;

            if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_PAINT_ALL_WALLS) == false)
            {
                this.mazeUserControl.RandomizeWallVisibility = true;
            }
            ContourImage.DisplayProcessedImage = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_IMAGE_SUBTRACT_BACKGROUND);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Add an embedded maze.
        /// </summary>
        private bool AddEmbeddedMaze()
        {
            int percentage = (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_MULTIPLE_MAZES) ? 15 : 0);

            if (random.Next(100) < percentage)
            {
                OutlineShape shape = null;
                int          area = mazeUserControl.Maze.XSize * mazeUserControl.Maze.YSize;
                int          minArea = (int)(0.1 * area), maxArea = (int)(0.5 * area);

                while (true)
                {
                    shape = mazeUserControl.RandomShape(0.2, 1.0, random);

                    // Discard shapes that are too small or too large.
                    if (minArea > shape.Area || shape.Area > maxArea)
                    {
                        continue;
                    }

                    // Discard shapes that cover the whole maze.
                    if (shape.BoundingBox.Width >= mazeUserControl.Maze.XSize || shape.BoundingBox.Height >= mazeUserControl.Maze.YSize)
                    {
                        continue;
                    }

                    break; // Terminate the loop.
                }

                mazeUserControl.Maze.AddEmbeddedMaze(shape);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Advance a single step.
        /// The traveled steps are not rendered until FinishPath() is called.
        /// Returns the number of steps actually executed.
        /// </summary>
        /// <returns></returns>
        public int DoStep()
        {
            int result = 0;

            if (RunParallelSolvers)
            {
                // All controllers run in parallel.
                // Forward the message to the embedded controllers.
                foreach (EmbeddedSolverController item in embeddedControllers)
                {
                    if (item.IsActive)
                    {
                        result += item.DoStep();
                    }
                }
            }
            else
            {
                SolverController ctrl = ChooseDueController();

                if (ctrl != this)
                {
                    return(ctrl.DoStep());
                }
            }

            if (this.Maze.IsSolved)
            {
                return(result);
            }

            MazeSquare sq1, sq2;
            bool       forward;

            solver.Step(out sq1, out sq2, out forward);
            mazePainter.DrawStep(sq1, sq2, forward);
            ++result;

            // Increment the step counter.
            ++countSteps;

            // Increment forward and backward counters.
            if (forward)
            {
                ++countForward;
                if (visitedProgressBar != null)
                {
                    visitedProgressBar.PerformStep(); // next visited square
                }

                // Let all embedded controllers know how far we have advanced.
                foreach (EmbeddedSolverController ctrl in embeddedControllers)
                {
                    ctrl.HostStep(sq2);
                }
            }
            else
            {
                ++countBackward;
            }

            currentBackwardSquare = (forward ? null : sq2);

            if (this.Maze.IsSolved)
            {
                FinishPath();
                mazePainter.DrawSolvedPath(solutionPath);
                currentBackwardSquare = null;

                if (this.Maze.MazeId != MazeSquare.PrimaryMazeId)
                {
                    mazePainter.DrawRemainingSquares();
                }

#if DEBUG
                if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_LOG_SOLVER_STATISTICS))
                {
                    LogSolverStatistics();
                }
#endif
            }

            // Draw the background image inside the reserved areas.
            // If the background image was covered by a ContourImage, that border will be drawn smoothly instead of jagged.
            if (this.Maze.MazeId == MazeSquare.PrimaryMazeId && this.Maze.IsFinished)
            {
                mazePainter.DrawRemainingBackgroundSquares(MazeSquare.ReservedMazeId);
            }

            return(result);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Creates a ScreenSaverController instance,
        /// draws an initial maze
        /// and starts an AriadneController.
        /// </summary>
        /// <param name="windowHandleArg">The MazePainter will draw on this window.</param>
        /// <remarks>
        /// If this is not the primary screen, no cotroller is started,
        /// the application will terminate and the screen will stay blank.
        /// </remarks>
        public ScreenSaverController(string windowHandleArg)
        {
            #region Evaluate the given window's properties.
            var windowHandle    = (IntPtr)UInt32.Parse(windowHandleArg);
            var targetGraphics  = Graphics.FromHwnd(windowHandle);
            var targetRectangle = Platform.GetClientRectangle(windowHandle);
            //Log.WriteLine("targetRectangle = " + targetRectangle, true); // {X=0,Y=0,Width=1366,Height=768}
            #endregion

#if true
            #region Blank secondary screen(s).
            // ... because more than one of these mazes is just too distracting.  :-)
            if (!IsOnPrimaryScreen(windowHandle))
            {
                // We don't have to do anything, really.
                // xscreensaver has given us a blank (black) window and we may
                // terminate the application
                //Log.WriteLine("Goodbye on " + targetRectangle, true);
                //Application.Run();
                Application.Exit();
            }
            #endregion
#endif

            // Create an ImageLoader, now that it is clear that we will need it.
            Directory.ResultValidForSeconds = -1;
            var imageLoader = ImageLoader.GetScreenSaverImageLoader(Screen.PrimaryScreen.Bounds);

            #region Create a MazePainter.
            this.painter = new MazePainter(targetGraphics, targetRectangle, this as IMazePainterClient);
            #endregion

            #region Create a MazeUserControl.
            this.mazeUserControl             = new MazeUserControl(painter, targetRectangle.Size);
            this.mazeUserControl.ImageLoader = imageLoader;
            this.mazeUserControl.MazeForm    = this;
            #endregion

            #region Apply some registered options.
            if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_PAINT_ALL_WALLS) == false)
            {
                painter.RandomizeWallVisibility = true;
            }
            ContourImage.DisplayProcessedImage = RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_IMAGE_SUBTRACT_BACKGROUND);

            // Load background images.
            if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_BACKGROUND_IMAGES))
            {
                string imageFolder = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_BACKGROUND_IMAGE_FOLDER);
                if (imageFolder == "")
                {
                    imageFolder = RegisteredOptions.GetStringSetting(RegisteredOptions.OPT_IMAGE_FOLDER);
                }
                int percentage = ((RegisteredOptions.GetIntSetting(RegisteredOptions.OPT_IMAGE_NUMBER) > 0) ? 20 : 100);
                painter.CreateBackgroundImageLoader(imageFolder, percentage);
            }

            if (RegisteredOptions.GetBoolSetting(RegisteredOptions.OPT_SHOW_DETAILS_BOX))
            {
                this.infoPanelPainter = new InfoPanelPainter(painter);
            }
            #endregion

            // Create and display the first maze.
            this.OnNew(null, null);

            #region Create and start an AriadneController.
            SolverController controller = new SolverController(this, painter, null);
            this.ariadneController       = new AriadneController(this, controller);
            ariadneController.RepeatMode = true;
            ariadneController.Start();
            #endregion
        }