// ToString for debugging purposes
    public override string ToString()
    {
        string ret = "";

        for (int j = size - 1; j >= 0; j--)
        {
            for (int i = 0; i < size; i++)
            {
                InitObstacle iob = grid [i] [j];
                if (iob == null)
                {
                    ret += "\t.";
                }
                else
                {
                    ret += "\tO";
                }
                if (curPosition.x == i && curPosition.y == j)
                {
                    ret += "P";
                }
            }
            ret += "\n";
        }

        return(ret);
    }
    // Returns true if the recently "moved-to" space can be moved to validly
    private bool IsValid()
    {
        // Take care of out of bounds issues
        if (curPosition.x < 0 || curPosition.y < 0 || curPosition.x >= size || curPosition.y >= size)
        {
            return(false);
        }

        InitObstacle recentlyPlaced = grid[(int)curPosition.x][(int)curPosition.y];

        return(recentlyPlaced == null);
    }
 //Constructor to be used in the GameManager script
 public LayoutValidator(int dim)
 {
     size = dim;
     // Generate the grid
     grid = new InitObstacle[dim][];
     for (int i = 0; i < dim; i++)
     {
         grid[i] = new InitObstacle[dim];
     }
     // Reset visited List
     visited = new ArrayList();
 }
 // Adds the InitObstacle to the grid of the LayoutValidator
 public void AddObstacle(InitObstacle iob)
 {
     grid[iob.getRow()][iob.getCol()] = iob;
 }
Beispiel #5
0
    // Uses the InitObstacles from the initList to generate a queue of InitObjects to be
    // Initialized later. After this step, all Queued InitObjects should be valid and ready to place.
    private void QueueInitObstacles()
    {
        initQueue = new Queue();
        ArrayList       occupiedCoordinates = new ArrayList();               // Contains Vector2s representing the occupied spaces in the grid
        LayoutValidator validator           = new LayoutValidator(boardDim); // The validator that will validate the layout of the objects in the queue after they are placed

        occupiedCoordinates.Add(new Vector2(0, 0));                          // Occupy player spawn
        occupiedCoordinates.Add(new Vector2(boardDim - 1, boardDim - 1));    // Occupy goal

        //Occupy one block adjacent to player start and finish to increase chance of successful generation
        Vector2 playerStartOcc;

        playerStartOcc = Random.Range(0, 1) > 0 ?  new Vector2(1f, 0f) : new Vector2(0f, 1f);
        Vector2 playerFinishOcc;

        playerFinishOcc = Random.Range(0, 1) > 0 ?  new Vector2(boardDim - 1, boardDim - 2) : new Vector2(boardDim - 2, boardDim - 1);
        occupiedCoordinates.Add(playerFinishOcc);
        occupiedCoordinates.Add(playerStartOcc);

        InitObstacle iob;

        while (preInitQueue.Count > 0)
        {
            iob = (InitObstacle)preInitQueue.Dequeue();
            Vector2 iobCoords = new Vector2(iob.getRow(), iob.getCol());

            if (!iob.OutOfBounds(boardDim) && !ContainsCoords(occupiedCoordinates, iobCoords))
            {
                initQueue.Enqueue(iob);
                occupiedCoordinates.Add(iobCoords); // Occupy this object's coordinates
                validator.AddObstacle(iob);
            }
            else if (!debug)
            {
                // Add a new initObstacle of the same type to the initList
                int randRow = Random.Range(0, boardDim);
                int randCol = Random.Range(0, boardDim);
                preInitQueue.Enqueue(new InitObstacle(iob.GetCode(), randRow, randCol));
            }
            else
            {
                Debug.Log(iob + " Not added to initQueue.");
            }
        }

        // Place the Button and Door if needed

        Debug.Log("Validator:\n" + validator.ToString());

        IOrderedEnumerable <Vector2> doorPlaces = validator.FindDoorPlacement().OrderBy(e => Random.Range(0, 100));

        foreach (Vector2 pos in doorPlaces)
        {
            // See if adding the door would make the new layout unsolvable
            // but use an blocking obstacle to test if the door would have any affect
            iob = new InitObstacle('b', (int)pos.x, (int)pos.y);

            validator.AddObstacle(iob);
            validator.ResetVisited();

            // If it is not solvable, then placing the door at the location makes it required to pass
            if (!validator.IsSolvable())
            {
                iob = new InitObstacle('d', (int)pos.x, (int)pos.y);

                // Determine places the button can be placed
                List <Vector2> visited = new ArrayList(validator.GetVisited()).Cast <Vector2>().ToList(); // Copy visited list so we can remove elements later
                visited.RemoveAll(e => e.x < 0 || e.x >= boardDim);                                       // Remove all x out of bounds
                visited.RemoveAll(e => e.y < 0 || e.y >= boardDim);                                       // Remove all y out of bounds
                visited.RemoveAll(e => e.x + e.y < 2);                                                    // Remove spaces adjacent to player spawn
                visited.RemoveAll(e => e == pos);                                                         // Remove location of the door itself
                visited.RemoveAll(e => !validator.NullAtPos(e));                                          // Remove all occupied spaces


                if (visited.Count > 0)
                {
                    buttonPos = visited[Random.Range(0, visited.Count)];
                    initQueue.Enqueue(iob);
                    Debug.Log("ButtonPos: " + buttonPos);
                    Debug.Log("DoorPos: " + pos);
                }
                else
                {
                    Debug.Log("Button not instantiated! No Valid places for it.");
                }

                validator.RemoveAtPos(pos); // remove so break works
                break;
            }

            validator.RemoveAtPos(pos); // remove so it can be solvable going forward
        }

        // Place coins if in progression mode
        GameObject progressionManager = GameObject.Find("ProgressionManager");
        int        numCoins;

        if (progressionManager != null)
        {
            validator.ResetVisited();
            numCoins = progressionManager.GetComponent <ProgressionManager>().GetNumberOfCoins();
            List <Vector2> coinPlaces = validator.FindCoinPlacement();
            coinPlaces.Remove(new Vector2(0, 0));
            coinPlaces.Remove(new Vector2(boardDim - 1, boardDim - 1));

            Vector2 curPlace;
            int     randomPos;
            for (int i = 0; i < numCoins && coinPlaces.Count > 0; i++)
            {
                randomPos = Random.Range(0, coinPlaces.Count - 1);
                curPlace  = coinPlaces[randomPos];
                initQueue.Enqueue(new InitObstacle('c', (int)curPlace.x, (int)curPlace.y));
                coinPlaces.RemoveAt(randomPos);
            }
        }

        // Determine if a valid configuration was generated
        if (!debug)
        {
            validator.ResetVisited();
            if (!validator.IsSolvable())
            {
                Debug.Log("Invalid configuration generated!\n" + validator.ToString());
                generationFailures++;
                if (generationFailures >= failGenerationsTimeoutCount)
                {
                    Debug.Log("Generation timed out after " + generationFailures + " failures.");
                    return;                     // Exit if maximum generation failures is met
                }
                RandomList();
                QueueInitObstacles();
                return;
            }
        }
        Debug.Log("Queueing finished successfully");
    }