/// <summary> /// Reserves a rectangular area for the given image in this.Maze. /// The chosen location is remembered in this.imageLocations. /// Returns true if the reservation was successful. /// </summary> /// <param name="contourImage"></param> /// <returns></returns> private bool AddImage(ContourImage contourImage) { Image img = contourImage.DisplayedImage; int padding = MazePainter.ApplyScaleFactor(8) + this.wallWidth; int sqW = (img.Width + padding) / this.gridWidth + 1; int sqH = (img.Height + padding) / this.gridWidth + 1; int xOffsetImg = (sqW * gridWidth - img.Width) / 2; int yOffsetImg = (sqH * gridWidth - img.Height) / 2; OutlineShape shape = (ContourImage.DisplayProcessedImage ? contourImage.GetCoveredShape(gridWidth, wallWidth, xOffsetImg, yOffsetImg) : null); Rectangle rect; if (Maze.ReserveRectangle(sqW, sqH, 2, shape, out rect)) { // Remember the image data and location. It will be painted in PaintMaze(). int x = rect.X * gridWidth + xOffset + xOffsetImg; int y = rect.Y * gridWidth + yOffset + yOffsetImg; imageLocations.Add(new Rectangle(x, y, img.Width, img.Height)); return(true); } else { return(false); } }
public MixedIrregularMazeShape(OutlineShape outline, IrregularMazeShape inside, IrregularMazeShape outside) : base(Kind.Mixed) { this.outline = outline; this.inside = inside; this.outside = outside; }
/// <summary> /// Reserves a rectangular region of the given dimensions at a random location. /// The area must not touch any other reserved ares. /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="borderDistance">minimum number of squares between the reserved area and the maze border</param> /// <param name="rect"></param> /// <returns>true if the reservation was successful</returns> public bool ReserveRectangle(int width, int height, int borderDistance, OutlineShape shape, out Rectangle rect) { // Reject very large areas. if (width < 2 || height < 2 || width > xSize - Math.Max(4, 2 * borderDistance) || height > ySize - Math.Max(4, 2 * borderDistance)) { rect = new Rectangle(); return(false); } for (int nTries = 0; nTries < 100; nTries++) { // Choose a random location. // The resulting rectangle may touch the borders. int x = random.Next(borderDistance, xSize - width - borderDistance); int y = random.Next(borderDistance, ySize - height - borderDistance); if (ReserveRectangle(x, y, width, height, shape)) { rect = new Rectangle(x, y, width, height); return(true); } } rect = new Rectangle(); return(false); }
/// <summary> /// Take all modifyable parameters from the given data object. /// </summary> /// <param name="data"></param> public void TakeParametersFrom(AriadneSettingsData data) { // The Auto... flags for Width and Height have already been checked by the MazeUserControl. this.xSize = Math.Max(dimensionsObj.MinSize, Math.Min(dimensionsObj.MaxXSize, data.MazeWidth)); this.ySize = Math.Max(dimensionsObj.MinSize, Math.Min(dimensionsObj.MaxYSize, data.MazeHeight)); if (!data.AutoSeed) { this.seed = Math.Max(0, Math.Min(codeObj.SeedLimit - 1, data.Seed)); } else { Random r = RandomFactory.CreateRandom(); this.seed = r.Next(codeObj.SeedLimit); } this.random = RandomFactory.CreateRandom(seed); this.reservedAreas.Clear(); this.reservedAreaShapes.Clear(); this.outlineShape = null; this.embeddedMazeShapes.Clear(); this.embeddedMazes.Clear(); this.Irregular = data.IrregularMaze; this.Irregularity = data.Irregularity; // Decode(data.Code); }
private void FixOutline(OutlineShape shape) { // We need a test for the "inside" of an OutlineShape. OutlineShape.InsideShapeDelegate test = delegate(int x, int y) { return(shape[x, y]); }; FixOutline(test, WallState.WS_OUTLINE); }
/// <summary> /// Mark the defined outline walls. /// </summary> private void FixOutlineShape() { if (outlineShape != null) { OutlineShape shape = outlineShape; FixOutline(shape); } }
private static void TestHalfArea(string testObject, Bitmap bitmap, RotateFlipType rft, int scale) { int xSize = Math.Max(bitmap.Width, bitmap.Height) * scale; int ySize = xSize; OutlineShape actual = SWA_Ariadne_Outlines_TilesOutlineShapeAccessor.FromBitmap(xSize, ySize, bitmap, rft, scale); Assert.AreEqual(xSize * ySize / 2, actual.Area, testObject + " " + rft.ToString() + ": incorrect Area"); }
/// <summary> /// Returns the shape of a ContourImage or null if none of the images has a real contour. /// </summary> public OutlineShape SuggestOutlineShape(Random r, double offCenter, double size) { foreach (ContourImage img in this.images) { if (img.HasContour) { // Use img.GetCoveredShape() as an OutlineShapeBuilder. return(OutlineShape.RandomInstance(r, img.GetCoveredShape, this.XSize, this.YSize, offCenter, size)); } } return(null); }
/// <summary> /// Overwrites the mazeId of every square inside the shape. /// </summary> /// <param name="shape"></param> private void InstallInHost(OutlineShape shape) { for (int x = 0; x < xSize; x++) { for (int y = 0; y < ySize; y++) { if (shape[x, y] && !this[x, y].isReserved) { this[x, y].MazeId = this.mazeId; } } } }
/// <summary> /// Returns an irregular pattern that is only applied to the inside/outside of the given OutlineShape. /// The remainder is a regular pattern (without preferred directions). /// </summary> /// <param name="r"></param> /// <param name="maze"></param> /// <param name="outline"></param> /// <param name="confinedToInside"> /// When true: only the inside is irregular. /// When false: only the outside is irregular. /// </param> /// <returns></returns> private static IrregularMazeShape ConfinedInstance(Random r, Maze maze, OutlineShape outline, bool confinedToInside) { IrregularMazeShape regular = new PreferNothing(); IrregularMazeShape irregular = SimpleInstance(r, maze); if (confinedToInside) { return(new MixedIrregularMazeShape(outline, irregular, regular)); } else { return(new MixedIrregularMazeShape(outline, regular, irregular)); } }
/// <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); }
/// <summary> /// Returns a randomly chosen instance. /// Some patterns are "simple", applied to the whole maze area. /// Some patterns are "mixed", with two different patterns on the inside/outside of an OutlineShape. /// </summary> /// <param name="r"></param> /// <returns></returns> public static IrregularMazeShape RandomInstance(Random r, Maze maze) { if (maze.OutlineShape != null && r.Next(100) < 10) { // Build a mixed instance, using the OutlineShape laid into the maze. if (r.Next(100) < 50) { // two different patterns inside and outside of the OutlineShape return(MixedInstance(r, maze, maze.OutlineShape)); } else if (r.Next(100) < 66) { // the outside of the OutlineShape is regular return(ConfinedInstance(r, maze, maze.OutlineShape, true)); } else { // the inside of the OutlineShape is regular return(ConfinedInstance(r, maze, maze.OutlineShape, false)); } } else if (maze.OutlineShape == null && r.Next(100) < 20) { // Build a mixed instance, using a new OutlineShape. OutlineShape outline = OutlineShape.RandomInstance(r, maze.XSize, maze.YSize, 0.3, 0.9); if (r.Next(100) < 20) { // two different patterns inside and outside of the OutlineShape return(MixedInstance(r, maze, outline)); } else if (r.Next(100) < 50) { // the outside of the OutlineShape is regular return(ConfinedInstance(r, maze, outline, true)); } else { // the inside of the OutlineShape is regular return(ConfinedInstance(r, maze, outline, false)); } } else { return(SimpleInstance(r, maze)); } }
/// <summary> /// Reserves a rectanglurar region of the given dimensions. /// The area must not touch any other reserved areas. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="width"></param> /// <param name="height"></param> /// <returns>true if the reservation was successful</returns> public bool ReserveRectangle(int x, int y, int width, int height, OutlineShape shape) { // Restrict to the actual maze area. if (x < 0) { width += x; x = 0; } if (y < 0) { height += y; y = 0; } width = Math.Min(xSize - x, width); height = Math.Min(ySize - y, height); // Reject very large areas. if (width < 1 || height < 1 || width > xSize - 4 || height > ySize - 4) { return(false); } // The candidate rectangle. Rectangle candidate = new Rectangle(x, y, width, height); // The candidate, extended with two squares around all four edges. Rectangle extendedCandidate = new Rectangle(x - 2, y - 2, width + 4, height + 4); bool reject = false; foreach (Rectangle rect in this.reservedAreas) { // Reject the candidate if its extension would intersect with another reserved area. if (extendedCandidate.IntersectsWith(rect)) { reject = true; } } if (!reject) { reservedAreas.Add(candidate); reservedAreaShapes.Add(shape); return(true); } return(false); }
/// <summary> /// Creates a maze that is embedded in the hostMaze. /// The maze is formed by all squares inside the given shape. /// </summary> /// <param name="hostMaze"></param> /// <param name="mazeId"></param> /// <param name="shape"></param> public EmbeddedMaze(Maze hostMaze, int mazeId, OutlineShape shape) : base(hostMaze.XSize, hostMaze.YSize) { if (mazeId <= MazeSquare.PrimaryMazeId || mazeId > MazeSquare.MaxMazeId) { throw new Exception("invalid maze ID: " + mazeId.ToString()); } this.hostMaze = hostMaze; this.mazeId = mazeId; // We want to share the host's Random generator. this.random = hostMaze.Random; this.InstallInHost(shape); }
/// <summary> /// Returns a combination of two different patterns on the inside/outside of the given OutlineShape. /// </summary> /// <param name="r"></param> /// <param name="maze"></param> /// <param name="outline"></param> /// <returns></returns> private static IrregularMazeShape MixedInstance(Random r, Maze maze, OutlineShape outline) { IrregularMazeShape inside = null, outside = null; do { inside = SimpleInstance(r, maze); outside = SimpleInstance(r, maze); } while (inside.kind <= Kind.Neutral || outside.kind <= Kind.Neutral || inside.kind == outside.kind || (inside.kind != Kind.Zigzags && outside.kind != Kind.Zigzags) ); return(new MixedIrregularMazeShape(outline, inside, outside)); }
/// <summary> /// Returns an OutlineShape for the given location and size. /// If one of the displayed images has a defined contour, /// the shape is preferrably derived from that contour. /// </summary> /// <param name="offCenter">A fraction of the control's size.</param> /// <param name="size">A fraction of the control's size.</param> public OutlineShape RandomShape(double offCenter, double size, Random random) { OutlineShape result = null; // We may suggest a shape based on the displayed ContourImage. if (random.Next(100) < (ContourImage.DisplayProcessedImage ? 12 : 25)) { result = SuggestOutlineShape(random, offCenter, size); } if (result == null) { result = OutlineShape.RandomInstance(random, Maze.XSize, Maze.YSize, offCenter, size); } return(result); }
/// <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); } } }
public static MazeTestForm.MazeConfiguratorDelegate DistortedPolygonConfiguratorDelegate(int corners, int windings, double slant, double centerX, double centerY, double shapeSize, double distortionWinding) { MazeTestForm.MazeConfiguratorDelegate mazeConfigurator = delegate(Maze maze) { int xSize = maze.XSize, ySize = maze.YSize; OutlineShape baseShape = SWA_Ariadne_Outlines_PolygonOutlineShapeAccessor.CreatePrivate(corners, windings, slant, xSize, ySize, centerX, centerY, shapeSize); SWA_Ariadne_Outlines_SmoothOutlineShapeAccessor baseShapeAccessor = new SWA_Ariadne_Outlines_SmoothOutlineShapeAccessor(baseShape); double xCenter, yCenter, size; SWA_Ariadne_Outlines_OutlineShapeAccessor.ConvertParameters(xSize, ySize, centerX, centerY, shapeSize, out xCenter, out yCenter, out size); SWA_Ariadne_Outlines_DistortedOutlineShape_DistortionAccessor distortion = SWA_Ariadne_Outlines_DistortedOutlineShapeAccessor.SpiralDistortion(xCenter, yCenter, size, distortionWinding); OutlineShape targetShape = SWA_Ariadne_Outlines_DistortedOutlineShapeAccessor.CreatePrivate(xSize, ySize, baseShapeAccessor, distortion); maze.OutlineShape = targetShape; }; return(mazeConfigurator); }
/// <summary> /// Mark the squares inside the reserved areas. /// </summary> private void FixReservedAreas() { for (int i = 0; i < this.reservedAreas.Count; i++) { Rectangle rect = this.reservedAreas[i]; OutlineShape shape = this.reservedAreaShapes[i]; for (int x = rect.Left; x < rect.Right; x++) { for (int y = rect.Top; y < rect.Bottom; y++) { if (shape == null || shape[x - rect.Left, y - rect.Top] == true) { this.squares[x, y].isReserved = true; } } } } }
public void ItemTest() { int xSize = 0; // TODO: Initialize to an appropriate value int ySize = 0; // TODO: Initialize to an appropriate value SWA.Ariadne.Outlines.Tests.SWA_Ariadne_Outlines_SmoothOutlineShapeAccessor baseShape = null; // TODO: Initialize to an appropriate value SWA.Ariadne.Outlines.Tests.SWA_Ariadne_Outlines_DistortedOutlineShape_DistortionAccessor distortion = null; // TODO: Initialize to an appropriate value OutlineShape target = SWA.Ariadne.Outlines.Tests.SWA_Ariadne_Outlines_DistortedOutlineShapeAccessor.CreatePrivate(xSize, ySize, baseShape, distortion); bool val = false; // TODO: Assign to an appropriate value for the property SWA.Ariadne.Outlines.Tests.SWA_Ariadne_Outlines_DistortedOutlineShapeAccessor accessor = new SWA.Ariadne.Outlines.Tests.SWA_Ariadne_Outlines_DistortedOutlineShapeAccessor(target); double x = 0; // TODO: Initialize to an appropriate value double y = 0; // TODO: Initialize to an appropriate value Assert.AreEqual(val, accessor[x, y], "SWA.Ariadne.Outlines.DistortedOutlineShape.this was not set correctly."); Assert.Inconclusive("Verify the correctness of this test method."); }
/// <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); }
private void AddOutlineShape(AriadneSettingsData data) { Random r = Maze.Random; double offCenter = data.OutlineOffCenter / 100.0; double size = data.OutlineSize / 100.0; OutlineShape.OutlineShapeBuilder shapeBuilderDelegate = null; switch (data.OutlineKind) { case AriadneSettingsData.OutlineKindEnum.Random: shapeBuilderDelegate = OutlineShape.RandomOutlineShapeBuilder(r); break; case AriadneSettingsData.OutlineKindEnum.Circle: shapeBuilderDelegate = OutlineShape.Circle; break; case AriadneSettingsData.OutlineKindEnum.Diamond: shapeBuilderDelegate = OutlineShape.Diamond; break; case AriadneSettingsData.OutlineKindEnum.Character: shapeBuilderDelegate = OutlineShape.Character; break; case AriadneSettingsData.OutlineKindEnum.Symbol: shapeBuilderDelegate = OutlineShape.Symbol; break; case AriadneSettingsData.OutlineKindEnum.Polygon: shapeBuilderDelegate = OutlineShape.Polygon; break; case AriadneSettingsData.OutlineKindEnum.Function: shapeBuilderDelegate = OutlineShape.Function; break; case AriadneSettingsData.OutlineKindEnum.Bitmap: shapeBuilderDelegate = OutlineShape.Bitmap; break; case AriadneSettingsData.OutlineKindEnum.Tiles: shapeBuilderDelegate = OutlineShape.Tiles; break; case AriadneSettingsData.OutlineKindEnum.Rectangles: shapeBuilderDelegate = OutlineShape.Rectangles; break; case AriadneSettingsData.OutlineKindEnum.Grid: shapeBuilderDelegate = OutlineShape.Grid; break; case AriadneSettingsData.OutlineKindEnum.GridElement: shapeBuilderDelegate = OutlineShape.GridElement; break; case AriadneSettingsData.OutlineKindEnum.Maze: shapeBuilderDelegate = OutlineShape.Maze; break; case AriadneSettingsData.OutlineKindEnum.Lines: shapeBuilderDelegate = OutlineShape.Lines; break; case AriadneSettingsData.OutlineKindEnum.Circles: shapeBuilderDelegate = OutlineShape.Circles; break; } if (shapeBuilderDelegate != null) { OutlineShape shape = OutlineShape.RandomInstance(r, shapeBuilderDelegate, XSize, YSize, offCenter, size); if (data.DistortedOutlines) { shape = shape.DistortedCopy(r); } if (data.AsEmbeddedMaze) { Maze.AddEmbeddedMaze(shape); } else { Maze.OutlineShape = shape; } } }
public bool AddEmbeddedMaze(OutlineShape shape) { this.embeddedMazeShapes.Add(shape); return(true); }
public PreferTiledPattern(Random r) : base(Kind.Other) { this.shape = TilesOutlineShape.FromSmallBitmap(r); this.preferStayingInside = (r.Next(2) == 0); }