Esempio n. 1
0
            public override bool[] PreferredDirections(MazeSquare sq)
            {
                bool[] result = new bool[4];

                for (int p = 0; p < 4; p++)
                {
                    MazeSquare sq1 = sq.NeighborSquare((WallPosition)p);
                    if (sq1 != null)
                    {
                        result[p] = ((shape[sq.XPos, sq.YPos] == shape[sq1.XPos, sq1.YPos]) == preferStayingInside);
                    }
                }

                return(result);
            }
Esempio n. 2
0
        /// <summary>
        /// Initialize all squares in the mazeExtension (everything but trajectoryDistance).
        /// </summary>
        /// <param name="maze"></param>
        private void InitializeMazeExtension(Maze maze)
        {
            for (int i = 0; i < maze.XSize; i++)
            {
                for (int j = 0; j < maze.YSize; j++)
                {
                    MazeSquare          sq  = maze[i, j];
                    MazeSquareExtension sqe = mazeExtension[i, j];

                    // extendedSquare:
                    sqe.extendedSquare = sq;

                    if (sq.isReserved)
                    {
                        // isDeadEnd:
                        sqe.isDeadEnd          = true;
                        sqe.trajectoryDistance = -1;
                    }
                    else
                    {
                        // neighbors:
                        sqe.neighbors = new List <MazeSquareExtension>(4);

                        for (WallPosition wp = WallPosition.WP_MIN; wp <= WallPosition.WP_MAX; wp++)
                        {
                            MazeSquare sq2 = sq.NeighborSquare(wp);

                            if (sq2 != null && !sq2.isReserved)
                            {
                                sqe.neighbors.Add(mazeExtension[sq2.XPos, sq2.YPos]);
                            }
                        }

                        // Negative values mean: not initialized
                        sqe.trajectoryDistance = int.MinValue;
                    }
                }
            }
        }
Esempio n. 3
0
        /// <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
        }