public override bool[] PreferredDirections(MazeSquare sq) { if (outline[sq.XPos, sq.YPos] == true) { return(inside.PreferredDirections(sq)); } else { return(outside.PreferredDirections(sq)); } }
/// <summary> /// Returns the preferred directions, as determined by one of the fields. /// </summary> /// <param name="sq"></param> /// <returns></returns> public override bool[] PreferredDirections(MazeSquare sq) { // Size of one field. int m = ((this.maze.XSize - 1) / this.fields.GetLength(0)) + 1; int n = ((this.maze.YSize - 1) / this.fields.GetLength(1)) + 1; // Index of this field. int i = sq.XPos / m; int j = sq.YPos / n; IrregularMazeShape shape = this.fields[i, j]; return(shape.PreferredDirections(sq)); }
/// <summary> /// Convert all undecided walls to either closed or open. /// In the resulting maze, there must be a path from every square to every other square. /// There must not be any circles, i.e. the maze must have a tree-like structure. /// </summary> private void BuildMaze() { // We hold a number of active squares in a stack. // Make the initial capacity sufficient to hold all squares. // Stack <MazeSquare> stack = new Stack <MazeSquare>(xSize * ySize); List <MazeSquare> outlineSquares = new List <MazeSquare>(); List <WallPosition> outlineWalls = new List <WallPosition>(); #region Start with a single random cell in the stack. while (true) { int x = random.Next(xSize); int y = random.Next(ySize); MazeSquare sq = this[x, y]; if (sq.MazeId == this.MazeId) { sq.isConnected = true; stack.Push(sq); break; } } #endregion #region Extend the maze by visiting the cells next to those in the stack. while (stack.Count > 0) { List <WallPosition> unresolvedWalls = new List <WallPosition>((int)WallPosition.WP_NUM); MazeSquare sq0 = stack.Pop(); // Collect the unfixed walls of sq0. // for (WallPosition wp = WallPosition.WP_MIN; wp <= WallPosition.WP_MAX; wp++) { switch (sq0[wp]) { case WallState.WS_MAYBE: MazeSquare sq = sq0.NeighborSquare(wp); if (sq.isConnected || sq.MazeId != sq0.MazeId) { sq0[wp] = sq[MazeSquare.OppositeWall(wp)] = WallState.WS_CLOSED; } else { unresolvedWalls.Add(wp); } break; // WS_MAYBE case WallState.WS_OUTLINE: outlineSquares.Add(sq0); outlineWalls.Add(wp); break; // WS_OUTLINE } } // foreach wp // Discard this square if it has no unresolved walls. if (unresolvedWalls.Count == 0) { // Note: This is the only place that may end the loop. // If the stack is empty: Open one outline wall. if (stack.Count == 0) { while (outlineSquares.Count > 0) { // Select a random square with an outline wall. int p = random.Next(outlineSquares.Count); MazeSquare sq = outlineSquares[p]; WallPosition wp = outlineWalls[p]; outlineSquares.RemoveAt(p); outlineWalls.RemoveAt(p); if (sq[wp] == WallState.WS_OUTLINE) { sq[wp] = WallState.WS_MAYBE; stack.Push(sq); // This square will be used in the next iteration. break; // from while(outlineSquares) } } } continue; // no walls to choose from } // Add the current cell to the stack. // Note: Do this before replacing unresolvedWalls with preferredWalls. if (unresolvedWalls.Count > 1) { stack.Push(sq0); } // Use only preferred wall positions. if (unresolvedWalls.Count > 1 && irregularMazeShape != null && (random.Next(100) < irregularMazeShape.ApplicationPercentage(this.irregularity))) { bool[] preferredPositions = irregularMazeShape.PreferredDirections(sq0); List <WallPosition> preferredWalls = new List <WallPosition>(unresolvedWalls.Count); foreach (WallPosition p in unresolvedWalls) { if (preferredPositions[(int)p]) { preferredWalls.Add(p); } } if (preferredWalls.Count > 0) { unresolvedWalls = preferredWalls; } } // Choose one wall. WallPosition wp0 = unresolvedWalls[random.Next(unresolvedWalls.Count)]; MazeSquare sq1 = sq0.NeighborSquare(wp0); // Open the wall. sq0[wp0] = sq1[MazeSquare.OppositeWall(wp0)] = WallState.WS_OPEN; // Add the new cell to the stack. sq1.isConnected = true; stack.Push(sq1); } // while stack is not empty #endregion }