// 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; }
// 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"); }