private int checkCrossing(QVector2Int currentPosition, QVector2Int newPosition, List <QMazeOutput> newPositionOutputs, QMazeOutputDirection dir)
        {
            if (QMath.getRandom() < piecePack.getPiece(QMazePieceType.Crossing).frequency&&
                newPositionOutputs != null &&
                newPositionOutputs.Count == 1 &&
                newPositionOutputs[0].outputDirList.Count == 2 &&
                !newPositionOutputs[0].outputDirList.Contains(dir) &&
                !newPositionOutputs[0].outputDirList.Contains(QMazeOutput.opposite[dir]))
            {
                QVector2Int newPosition2 = newPosition.clone();
                newPosition2.x += QMazeOutput.dx[dir];
                newPosition2.y += QMazeOutput.dy[dir];

                if (pointInMaze(newPosition2) &&
                    mazeArray[newPosition2.x][newPosition2.y] == null)
                {
                    QMazeOutput output = mazeArray[currentPosition.x][currentPosition.y][mazeArray[currentPosition.x][currentPosition.y].Count - 1];
                    output.outputDirList.Add(dir);

                    mazeArray[newPosition.x][newPosition.y][0].outputDirList.Add(dir);
                    mazeArray[newPosition.x][newPosition.y][0].outputDirList.Add(QMazeOutput.opposite[dir]);

                    output = new QMazeOutput();
                    output.outputDirList.Add(QMazeOutput.opposite[dir]);
                    mazeArray[newPosition2.x][newPosition2.y] = new List <QMazeOutput>();
                    mazeArray[newPosition2.x][newPosition2.y].Add(output);

                    path.Add(new QVector2Int(newPosition2.x, newPosition2.y));
                    lastDirection = dir;

                    return(CHECK_BREAK);
                }
            }
            return(CHECK_FAILED);
        }
        private int checkDoubleCorner(QVector2Int currentPosition, QVector2Int newPosition, List <QMazeOutput> newPositionOutputs, QMazeOutputDirection dir)
        {
            if (QMath.getRandom() < piecePack.getPiece(QMazePieceType.DoubleCorner).frequency&&
                newPositionOutputs.Count == 1 &&
                newPositionOutputs[0].outputDirList.Count == 2 &&
                newPositionOutputs[0].outputDirList.Contains(dir) &&
                !newPositionOutputs[0].outputDirList.Contains(QMazeOutput.opposite[dir]))
            {
                QVector2Int newPos1 = new QVector2Int(newPosition.x + QMazeOutput.dx[QMazeOutput.rotateCW[dir]],
                                                      newPosition.y + QMazeOutput.dy[QMazeOutput.rotateCW[dir]]);
                QVector2Int newPos2 = new QVector2Int(newPosition.x + QMazeOutput.dx[QMazeOutput.rotateCCW[dir]],
                                                      newPosition.y + QMazeOutput.dy[QMazeOutput.rotateCCW[dir]]);

                if ((pointInMaze(newPos1) && mazeArray[newPos1.x][newPos1.y] == null && newPositionOutputs[0].outputDirList.Contains(QMazeOutput.rotateCCW[dir])) ||
                    (pointInMaze(newPos2) && mazeArray[newPos2.x][newPos2.y] == null && newPositionOutputs[0].outputDirList.Contains(QMazeOutput.rotateCW [dir])))
                {
                    QMazeOutputDirection dir2 = dir;

                    QMazeOutput output = mazeArray[currentPosition.x][currentPosition.y][mazeArray[currentPosition.x][currentPosition.y].Count - 1];
                    output.outputDirList.Add(dir);

                    output = new QMazeOutput();
                    output.outputDirList.Add(QMazeOutput.opposite[dir]);
                    if (!mazeArray[newPosition.x][newPosition.y][0].outputDirList.Contains(QMazeOutput.rotateCW[dir]))
                    {
                        output.outputDirList.Add(QMazeOutput.rotateCW[dir]);
                        dir2 = QMazeOutput.rotateCW[dir];
                    }
                    else
                    {
                        output.outputDirList.Add(QMazeOutput.rotateCCW[dir]);
                        dir2 = QMazeOutput.rotateCCW[dir];
                    }
                    mazeArray[newPosition.x][newPosition.y].Add(output);

                    newPosition.x += QMazeOutput.dx[dir2];
                    newPosition.y += QMazeOutput.dy[dir2];

                    output = new QMazeOutput();
                    output.outputDirList.Add(QMazeOutput.opposite[dir2]);
                    mazeArray[newPosition.x][newPosition.y] = new List <QMazeOutput>();
                    mazeArray[newPosition.x][newPosition.y].Add(output);

                    path.Add(new QVector2Int(newPosition.x, newPosition.y));
                    lastDirection = dir2;

                    return(CHECK_BREAK);
                }
            }
            return(CHECK_FAILED);
        }
Beispiel #3
0
        public static void Shuffle <T>(List <T> list)
        {
            int count     = list.Count;
            int halfCount = count / 2;

            for (int i = 0; i < halfCount; i++)
            {
                int j = QMath.getRandom(i, count);

                T temp = list[i];
                list[i] = list[j];
                list[j] = temp;
            }
        }
        private int checkTripple(QVector2Int currentPosition, QVector2Int newPosition, List <QMazeOutput> newPositionOutputs, QMazeOutputDirection dir)
        {
            if (QMath.getRandom() < piecePack.getPiece(QMazePieceType.Triple).frequency&&
                newPositionOutputs.Count == 1 &&
                newPositionOutputs[0].outputDirList.Count == 2 &&
                newPositionOutputs[0].outputDirList.Contains(dir) &&
                !newPositionOutputs[0].outputDirList.Contains(QMazeOutput.opposite[dir]))
            {
                QMazeOutput output = mazeArray[currentPosition.x][currentPosition.y][mazeArray[currentPosition.x][currentPosition.y].Count - 1];
                output.outputDirList.Add(dir);

                newPositionOutputs[newPositionOutputs.Count - 1].outputDirList.Add(QMazeOutput.opposite[dir]);

                return(CHECK_CONTINUE);
            }
            return(CHECK_FAILED);
        }
 private void generateFinishPoint()
 {
     if (generateFinishCount > 0)
     {
         finishPointList.Clear();
     }
     for (int i = 0; i < generateFinishCount; i++)
     {
         QVector2Int newFinishPoint = new QVector2Int(QMath.getRandom(0, mazeWidth), QMath.getRandom(0, mazeHeight));
         while (QListUtil.has(startPointList, newFinishPoint) || QListUtil.has(finishPointList, newFinishPoint))
         {
             newFinishPoint.x = QMath.getRandom(0, mazeWidth);
             newFinishPoint.y = QMath.getRandom(0, mazeHeight);
         }
         finishPointList.Add(newFinishPoint);
     }
 }
        private int checkCornerDeadlock2(QVector2Int currentPosition, QVector2Int newPosition, List <QMazeOutput> newPositionOutputs, QMazeOutputDirection dir)
        {
            if (QMath.getRandom() < piecePack.getPiece(QMazePieceType.CornerDeadlock2).frequency&&
                newPositionOutputs.Count == 1 &&
                newPositionOutputs[0].outputDirList.Count == 2 &&
                newPositionOutputs[0].outputDirList.Contains(dir) &&
                newPositionOutputs[0].outputDirList.Contains(QMazeOutput.rotateCCW[dir]))
            {
                QMazeOutput output = mazeArray[currentPosition.x][currentPosition.y][mazeArray[currentPosition.x][currentPosition.y].Count - 1];
                output.outputDirList.Add(dir);

                output = new QMazeOutput();
                output.outputDirList.Add(QMazeOutput.opposite[dir]);
                mazeArray[newPosition.x][newPosition.y].Add(output);

                return(CHECK_CONTINUE);
            }
            return(CHECK_FAILED);
        }
        private int checkEmpty(QVector2Int currentPosition, QVector2Int newPosition, List <QMazeOutput> newPositionOutputs, QMazeOutputDirection dir)
        {
            if (QMath.getRandom() < piecePack.getPiece(QMazePieceType.Empty).frequency&&
                newPositionOutputs.Count == 1 &&
                newPositionOutputs[0].outputDirList.Count == 1 &&
                newPositionOutputs[0].outputDirList.Contains(QMazeOutput.opposite[dir]))
            {
                newPositionOutputs.Clear();
                newPositionOutputs.Add(new QMazeOutput());

                List <QMazeOutput> currentOutputs = mazeArray[currentPosition.x][currentPosition.y];
                for (int i = 0; i < currentOutputs.Count; i++)
                {
                    currentOutputs[i].outputDirList.Remove(dir);
                }

                return(CHECK_BREAK);
            }
            return(CHECK_FAILED);
        }
        public void generateMaze(bool generateWithGeometry = true, bool asynchronous = true, float maxTime = 0.1f)
        {
            if (useSeed)
            {
                QMath.setSeed(seed);
            }

            if (asynchronous)
            {
                StartCoroutine(generate(generateWithGeometry, asynchronous, maxTime));
            }
            else
            {
                IEnumerator generationEnumerator = generate(generateWithGeometry, asynchronous, maxTime);
                while (generationEnumerator.MoveNext())
                {
                    ;
                }
            }
        }
        private IEnumerator generate(bool generateWithGeometry = true, bool asynchronous = true, float maxTime = 0.1f)
        {
            generationProgress = 0;

            generateStartPoint();
            generateFinishPoint();

            QVector2Int startGenerationPoint = new QVector2Int(QMath.getRandom(0, mazeWidth), QMath.getRandom(0, mazeHeight));

            while (QListUtil.has(startPointList, startGenerationPoint) ||
                   QListUtil.has(finishPointList, startGenerationPoint) ||
                   QListUtil.has(obstaclePointList, startGenerationPoint))
            {
                startGenerationPoint.x = QMath.getRandom(0, mazeWidth);
                startGenerationPoint.y = QMath.getRandom(0, mazeHeight);
            }

            path      = new List <QVector2Int>();
            mazeArray = new List <QMazeOutput> [mazeWidth][];
            for (int px = 0; px < mazeWidth; px++)
            {
                mazeArray[px] = new List <QMazeOutput> [mazeHeight];
            }

            lastDirection = QMazeOutputDirection.None;
            QVector2Int currentPosition = new QVector2Int(startGenerationPoint.x, startGenerationPoint.y);

            QMazeOutput output = new QMazeOutput();

            mazeArray[currentPosition.x][currentPosition.y] = new List <QMazeOutput>();
            mazeArray[currentPosition.x][currentPosition.y].Add(output);

            path.Add(new QVector2Int(currentPosition.x, currentPosition.y));

            checkTaskList.Clear();
            if (startPointList.Count > 0 || finishPointList.Count > 0)
            {
                checkTaskList.Add(checkStartFinishPoint);
            }
            checkTaskList.Add(checkStandard);
            if (piecePack.getPiece(QMazePieceType.Intersection).use)
            {
                checkTaskList.Add(checkUnder);
            }
            if (piecePack.getPiece(QMazePieceType.Crossing).use&& !onlyWay)
            {
                checkTaskList.Add(checkCrossing);
            }
            if (piecePack.getPiece(QMazePieceType.Triple).use&& !onlyWay)
            {
                checkTaskList.Add(checkTripple);
            }
            if (piecePack.getPiece(QMazePieceType.DoubleCorner).use)
            {
                checkTaskList.Add(checkDoubleCorner);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockCorner).use)
            {
                checkTaskList.Add(checkDeadlockCorner);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockLine).use)
            {
                checkTaskList.Add(checkDeadlockLine);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockTriple).use)
            {
                checkTaskList.Add(checkDeadlockTriple);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockCrossing).use)
            {
                checkTaskList.Add(checkDeadlockCrossing);
            }
            if (piecePack.getPiece(QMazePieceType.TripleDeadlock).use)
            {
                checkTaskList.Add(checkTripleDeadlock);
            }
            if (piecePack.getPiece(QMazePieceType.LineDeadlock).use)
            {
                checkTaskList.Add(checkLineDeadlock);
            }
            if (piecePack.getPiece(QMazePieceType.LineDeadlockLine).use)
            {
                checkTaskList.Add(checkLineDeadlockLine);
            }
            if (piecePack.getPiece(QMazePieceType.CornerDeadlock1).use)
            {
                checkTaskList.Add(checkCornerDeadlock1);
            }
            if (piecePack.getPiece(QMazePieceType.CornerDeadlock2).use)
            {
                checkTaskList.Add(checkCornerDeadlock2);
            }
            if (piecePack.getPiece(QMazePieceType.CornerDeadlockCorner).use)
            {
                checkTaskList.Add(checkCornerDeadlockCorner);
            }
            if (piecePack.getPiece(QMazePieceType.Empty).use)
            {
                checkTaskList.Add(checkEmpty);
            }

            float time = Time.realtimeSinceStartup;

            do
            {
                int lastPathIndex = path.Count - 1;
                currentPosition.set(path[lastPathIndex].x, path[lastPathIndex].y);

                lastDirection = QMazeOutputDirection.None;
                QMazeOutput outputArray = QMazeOutput.getShuffleOutput();

                foreach (QMazeOutputDirection dir in outputArray.outputDirList)
                {
                    QVector2Int newPosition = new QVector2Int(currentPosition.x + QMazeOutput.dx[dir], currentPosition.y + QMazeOutput.dy[dir]);
                    if (pointInMaze(newPosition))
                    {
                        if (mazeArray[currentPosition.x][currentPosition.y].Count == 1)
                        {
                            List <QMazeOutput> newPositionOutputs = mazeArray[newPosition.x][newPosition.y];

                            int checkResult = 0;
                            for (int i = 0; i < checkTaskList.Count; i++)
                            {
                                CheckTask checkTask = checkTaskList[i];
                                checkResult = checkTask(currentPosition, newPosition, newPositionOutputs, dir);
                                if (checkResult != CHECK_FAILED)
                                {
                                    break;
                                }
                            }

                            if (checkResult == CHECK_CONTINUE)
                            {
                                continue;
                            }
                            if (checkResult == CHECK_BREAK)
                            {
                                generationProgress++;
                                break;
                            }
                        }
                    }
                    else if (QListUtil.has(exitPointList, newPosition))
                    {
                        if (!mazeArray[currentPosition.x][currentPosition.y][0].outputDirList.Contains(dir))
                        {
                            mazeArray[currentPosition.x][currentPosition.y][0].outputDirList.Add(dir);
                        }
                    }
                }

                if (lastDirection == QMazeOutputDirection.None)
                {
                    path.RemoveAt(path.Count - 1);
                }

                if (asynchronous && Time.realtimeSinceStartup - time > maxTime)
                {
                    time = Time.realtimeSinceStartup;
                    yield return(null);
                }
            }while (path.Count > 0);

            if (generateWithGeometry && mazeGeometryGenerator != null)
            {
                if (asynchronous)
                {
                    yield return(StartCoroutine(mazeGeometryGenerator.generateGeometry(this, mazeArray, maxTime)));
                }
                else
                {
                    IEnumerator geometryCreatorEnumerator = mazeGeometryGenerator.generateGeometry(this, mazeArray, maxTime);
                    while (geometryCreatorEnumerator.MoveNext())
                    {
                        ;
                    }
                }
            }
        }
Beispiel #10
0
        public IEnumerator generateGeometry(QMazeEngine mazeEngine, List <QMazeOutput>[][] mazeArray, float maxTime = 0.1f)
        {
            Vector3    transformPosition = transform.position;
            Quaternion transformRotation = transform.rotation;

            transform.rotation = Quaternion.identity;

            float time       = Time.realtimeSinceStartup;
            int   mazeWidth  = mazeEngine.mazeWidth;
            int   mazeHeight = mazeEngine.mazeHeight;
            float mazeSize   = mazeWidth * mazeHeight;
            float count      = 0;

            instantiatingProgress = 0;
            bool wasError = false;

            QMazePiecePack    piecePack = mazeEngine.piecePack;
            List <QMazePiece> pieces    = piecePack.toMazePieceList();

            for (int i = 0; i < pieces.Count; i++)
            {
                if ((!pieces[i].use && !pieces[i].require) ||
                    pieces[i].type == QMazePieceType.Start ||
                    pieces[i].type == QMazePieceType.Finish)
                {
                    pieces.RemoveAt(i);
                    i--;
                }
            }

            for (int ix = 0; ix < mazeWidth; ix++)
            {
                for (int iy = 0; iy < mazeHeight; iy++)
                {
                    List <QMazeOutput> mazeOutputData = mazeArray[ix][iy];

                    QMazePiece targetPiece = null;

                    if (QListUtil.has(mazeEngine.startPointList, ix, iy) && mazeOutputData != null && piecePack.getPiece(QMazePieceType.Start).checkFit(mazeOutputData))
                    {
                        targetPiece = piecePack.getPiece(QMazePieceType.Start);
                    }
                    else if (QListUtil.has(mazeEngine.finishPointList, ix, iy) && mazeOutputData != null && piecePack.getPiece(QMazePieceType.Finish).checkFit(mazeOutputData))
                    {
                        targetPiece = piecePack.getPiece(QMazePieceType.Finish);
                    }
                    else
                    {
                        QListUtil.Shuffle <QMazePiece>(pieces);
                        for (int i = 0; i < pieces.Count; i++)
                        {
                            if (pieces[i].checkFit(mazeOutputData))
                            {
                                targetPiece = pieces[i];
                                break;
                            }
                        }
                    }

                    if (targetPiece == null)
                    {
                        if (mazeEngine.pointInMaze(new QVector2Int(ix, iy)) || mazeEngine.obstacleIsEmpty)
                        {
                            targetPiece = piecePack.getPiece(QMazePieceType.Empty);
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else if (targetPiece.geometryList.Count == 0)
                    {
                        if (mazeEngine.pointInMaze(new QVector2Int(ix, iy)))
                        {
                            if (!wasError)
                            {
                                wasError = true;
                                Debug.LogWarning("QMaze: Geometry for " + targetPiece.type + " piece is not found. Please check that geometry is specified for it in the piece pack.");
                            }
                        }
                        continue;
                    }

                    GameObject prefab = targetPiece.geometryList[QMath.getRandom(0, targetPiece.geometryList.Count)];
                    GameObject go;
                                        #if UNITY_EDITOR
                    if (Application.isPlaying)
                    {
                        go = (GameObject)GameObject.Instantiate(prefab, new Vector3(), Quaternion.AngleAxis(randomPiecesRotation ? ((int)(UnityEngine.Random.value * 360 / 90)) * 90 : -targetPiece.getRotation(), Vector3.up));
                    }
                    else
                    {
                        go = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                        go.transform.rotation = Quaternion.AngleAxis(randomPiecesRotation ? ((int)(UnityEngine.Random.value * 360 / 90)) * 90 : -targetPiece.getRotation(), Vector3.up);
                    }
                                        #else
                    go = (GameObject)GameObject.Instantiate(prefab, new Vector3(), Quaternion.AngleAxis(randomPiecesRotation ? ((int)(UnityEngine.Random.value * 360 / 90)) * 90 : -targetPiece.getRotation(), Vector3.up));
                                        #endif
                    go.transform.position = transformPosition + new Vector3(ix * mazeEngine.mazePieceWidth, 0, -iy * mazeEngine.mazePieceHeight);
                    Vector3 scale = go.transform.localScale;
                    go.transform.parent     = transform;
                    go.transform.localScale = scale;

                    count++;
                    instantiatingProgress = count / mazeSize;

                    if (Time.realtimeSinceStartup - time > maxTime)
                    {
                        time = Time.realtimeSinceStartup;
                        yield return(null);
                    }
                }
            }

            transform.rotation = transformRotation;
        }