public void TestDstar() { GameManager.SpecialPathNode pTile = Player.GetTileOn(); GameManager.SpecialPathNode eTile = this.GetTileOn(); dstar.InitializeGoals(eTile.X, eTile.Y, pTile.X, pTile.Y); dstar.Replan(); List <GameManager.SpecialPathNode> p = dstar.GetPath(); string s_p = ""; foreach (GameManager.SpecialPathNode n in p) { s_p += "(" + n.X + ", " + n.Y + ") "; n.tile.GetComponent <SpriteRenderer>().color = Color.red; } Debug.Log(s_p); dstar.UpdateStart(GameManager.ExitTile.X, GameManager.ExitTile.Y); dstar.Replan(); List <GameManager.SpecialPathNode> p2 = dstar.GetPath(); string s_e = ""; foreach (GameManager.SpecialPathNode n in p2) { s_e += "(" + n.X + ", " + n.Y + ") "; n.tile.GetComponent <SpriteRenderer>().color = Color.blue; } Debug.Log(s_e); }
/* * LayoutBoardFromArray creates the board area inside the outer wall layer according to * an input 2D setupArray[x,y] of int values. The following key should be used for the setup array: * -2 : empty (for unreachable area) * -1 : obstacle * 0 : floor * 1 : base enemy * 2 : boss enemy * * Note: this function does not affect placement of doors or player. */ GameManager.SpecialPathNode[,] LayoutBoardFromArray(int[,] setupArray, GameManager.SpecialPathNode[,] boardArray) { int numRows = setupArray.GetLength(0); int numCols = setupArray.GetLength(1); for (int c = 0; c < numCols; c++) { for (int r = 0; r < numRows; r++) { GameObject toInstantiate = null; bool wall = false; bool IsEnemy = false; switch (setupArray[c, r]) { case 0: toInstantiate = floorTile; break; case -1: toInstantiate = obstacleTile; wall = true; break; case 1: toInstantiate = enemy; wall = true; IsEnemy = true; break; case 2: toInstantiate = boss; break; } if (toInstantiate != null) { GameObject instance = Instantiate(toInstantiate, new Vector3(c, r, 0f), Quaternion.identity) as GameObject; //r,numRows-1-c,0f), Quaternion.identity) as GameObject; instance.transform.SetParent(boardHolder); if (IsEnemy) { Enemy thisEnemy = instance.GetComponent <Enemy>(); if (Enemies == null) { Enemies = new List <Enemy>(); } Enemies.Add(thisEnemy); thisEnemy.TileX = c + 1; thisEnemy.TileY = r + 1; } GameManager.SpecialPathNode thisNode = new GameManager.SpecialPathNode(); thisNode.X = c + 1; thisNode.Y = r + 1; thisNode.tile = instance; thisNode.IsWall = wall; boardArray[c + 1, r + 1] = thisNode; } } } return(boardArray); }
private void MoveToDstarNode(GameManager.SpecialPathNode node) { if (node != null) { IsMoving = true; CurrentDstarNode = node; GoalPos = node.tile.transform.position; } }
GameObject[,] LayoutObjectAtRandom(GameObject tile, int min, int max, GameObject[,] boardArray, bool IsWall) { int objectCount = Random.Range(min, max + 1); for (int i = 0; i < objectCount; i++) { Vector3 randomPosition = RandomPosition(); GameObject instance = Instantiate(tile, randomPosition, Quaternion.identity) as GameObject; GameManager.SpecialPathNode thisNode = new GameManager.SpecialPathNode(); thisNode.X = (int)(randomPosition.x) + 1; thisNode.Y = (int)(randomPosition.y) + 1; thisNode.tile = instance; thisNode.IsWall = IsWall; boardArray[(int)(randomPosition.x) + 1, (int)(randomPosition.y) + 1] = instance; } return(boardArray); }
public void MoveToTileDstar(GameManager.SpecialPathNode tile) { GameManager.SpecialPathNode eTile = this.GetTileOn(); CurDstarIndex = 0; if (DstarPath.Count == 0) { //First time dstar.InitializeGoals(eTile.X, eTile.Y, tile.X, tile.Y); dstar.Replan(); DstarPath = dstar.GetPath(); DstarPath.Add(tile); } else { //Debug.Log("Replanning"); dstar.UpdateStart(eTile.X, eTile.Y); dstar.UpdateGoal(tile.X, tile.Y); dstar.Replan(); DstarPath = dstar.GetPath(); DstarPath.Add(tile); } if (DstarPath.Count > 1) { //Debug.Log("Found path"); //Debug.Log(DstarPath[0].X + ", " + DstarPath[0].Y); //Debug.Log(eTile.X + ", " + eTile.Y); IsMoving = true; GoalPos = DstarPath[1].tile.transform.position; CurrentDstarNode = DstarPath[1]; CurDstarIndex = 1; /* * string s_e = ""; * foreach (GameManager.SpecialPathNode n in DstarPath) * { * s_e += "(" + n.X + ", " + n.Y + ") "; * //n.tile.GetComponent<SpriteRenderer>().color = Color.blue; * }*/ //Debug.Log(s_e); //CurrentGoalNode = DstarPath[0]; //LinkedListNode<GameManager.SpecialPathNode> next = path.First; } }
public bool MoveToTile(GameManager.SpecialPathNode tile) { path = aStar.Search(TileX, TileY, tile.X, tile.Y, null); //Debug.Log("Enemy: " + TileX + ", " + TileY + "; Player: " + tile.X + ", " + tile.Y); if (path != null && path.Count > 0) { IsMoving = true; GoalPos = path.First.Value.tile.transform.position; CurrentGoalNode = path.First; LinkedListNode <GameManager.SpecialPathNode> next = path.First; /* * string pathStr = ""; * while (next != null) * { * pathStr += "(" + next.Value.X + ", " + next.Value.Y + "); "; * next = next.Next; * } * //Debug.Log(pathStr);*/ return(true); } return(false); }
public override void Update() { Bullet target = null; Enemy attacked = null; //Debug.Log("CURRENT DECISION: " + curDecision); prevDecision = curDecision; //Determine if player tile changed prevPlayerTile = nTile; nTile = Player.GetTileOn(); //Only calculate distance change if new tile. if (nTile != prevPlayerTile) { // } //Get bullet if close to move to target = BulletVisibleDecision(); PlayerHPDecision(); attacked = FriendlyEnemyHasSight(); EnemyHPDecision(); //Only need to recalculate distance to player if the player changes tiles if (prevBulletDecision.value != bulletClose.value || nTile != prevPlayerTile || curDecision == "DONEMOVINGTOBULLET" || curDecision == "DONEMOVINGTOENEMY") { //Prevents too many decisions from happening if ((Time.time > nextActionTime)) { nextActionTime = Time.time + period; //We have to perform the decision even distance result is the same, to make sure the enemy paths to the newest player position //If we did not, the enemy could just stay in range but never be hit by the enemy string dis = DistanceToPlayerDecision(); if (dis == "FAR") { if (curDecision != "MOVINGTOBULLET")// && curDecision != "MOVINGTOENEMY") { //Debug.Log("Making a decision"); curDecision = MakeDecision.MakeDecision(new List <AttributeValue <string> >() { playerDist, bulletClose, playerHPDecision, enemyAttackedDecision, thisHPDecision }); } } else { //Debug.Log("Making a decision"); curDecision = MakeDecision.MakeDecision(new List <AttributeValue <string> >() { playerDist, bulletClose, playerHPDecision, enemyAttackedDecision, thisHPDecision }); } } } //Execute decision if (curDecision == "CHASE") { GameManager.SpecialPathNode playerTile = Player.GetTileOn(); if (DoDstarLite) { this.MoveToTileDstar(playerTile); } else { this.MoveToTile(playerTile); } //To make sure it keeps moving, rather than sitting on "CHASE" curDecision = "FINDINGPLAYER"; } else if (curDecision == "STAY") { IsMoving = false; } else if (curDecision == "FINDBULLET") { if (target != null) { Debug.Log(target); if (DoDstarLite) { this.MoveToTileDstar(target.GetTileOn()); } else { this.MoveToTile(target.GetTileOn()); } curDecision = "MOVINGTOBULLET"; } } else if (curDecision == "DEFENDGOAL") { print("ENEMY DEFENDING GOAL"); GameManager.SpecialPathNode exitTile = GameManager.ExitTile; //Debug.Log("EXit: " + exitTile.X + ", " + exitTile.Y); if (DoDstarLite) { this.MoveToTileDstar(exitTile); } else { this.MoveToTile(exitTile); } curDecision = "DEFENDINGGOAL"; } else if (curDecision == "DEFENDINGGOAL") { float dist = Vector3.Distance(this.transform.position, GameManager.ExitTile.tile.transform.position); if (dist < 2.0f) { IsMoving = false; curDecision = "ATGOAL"; } } else if (curDecision == "FINDENEMY") { if (attacked != null) { if (DoDstarLite) { this.MoveToTileDstar(attacked.GetTileOn()); } else { this.MoveToTile(attacked.GetTileOn()); } curDecision = "MOVINGTOENEMY"; } } Position = transform.position; if (DoDstarLite) { if ((CurrentDstarNode != null) && IsAtGoal(CurrentDstarNode.tile.transform.position)) { CurDstarIndex++; if (CurDstarIndex >= DstarPath.Count) { Debug.Log("Final Node found"); //end of nodes IsMoving = false; if (curDecision == "MOVINGTOBULLET") { curDecision = "DONEMOVINGTOBULLET"; } if (curDecision == "MOVINGTOENEMY") { curDecision = "DONEMOVINGTOENEMY"; } CurrentDstarNode = null; } else { GameManager.SpecialPathNode next = DstarPath[CurDstarIndex]; MoveToDstarNode(next); } } else { if (CurrentDstarNode != null) { TileX = CurrentDstarNode.X; TileY = CurrentDstarNode.Y; } } } else { if ((CurrentGoalNode != null) && IsAtGoal(CurrentGoalNode.Value.tile.transform.position)) { LinkedListNode <GameManager.SpecialPathNode> next = CurrentGoalNode.Next; if (next == null) { //Debug.Log("Final node found"); //end of list IsMoving = false; if (curDecision == "MOVINGTOBULLET") { curDecision = "DONEMOVINGTOBULLET"; } if (curDecision == "MOVINGTOENEMY") { curDecision = "DONEMOVINGTOENEMY"; } } else { MoveToNode(next); } } else { if (CurrentGoalNode != null) { TileX = CurrentGoalNode.Value.X; TileY = CurrentGoalNode.Value.Y; } } } if (IsMoving) { //Debug.Log("goal: " + GoalPos); transform.position = Vector3.MoveTowards(transform.position, GoalPos, Speed * Time.deltaTime); } if (DoDstarLite) { /* * string s_e = ""; * foreach (GameManager.SpecialPathNode n in DstarPath) * { * s_e += "(" + n.X + ", " + n.Y + ") "; * n.tile.GetComponent<SpriteRenderer>().color = Color.blue; * }*/ } }
private void MoveToDstarNode(GameManager.SpecialPathNode node) { if (node != null) { IsMoving = true; CurrentDstarNode = node; GoalPos = node.tile.transform.position; } }
public override void Update() { Bullet target = null; Enemy attacked = null; //Debug.Log("CURRENT DECISION: " + curDecision); prevDecision = curDecision; //Determine if player tile changed prevPlayerTile = nTile; nTile = Player.GetTileOn(); //Only calculate distance change if new tile. if (nTile != prevPlayerTile) { // } //Get bullet if close to move to target = BulletVisibleDecision(); PlayerHPDecision(); attacked = FriendlyEnemyHasSight(); EnemyHPDecision(); //Only need to recalculate distance to player if the player changes tiles if (prevBulletDecision.value != bulletClose.value || nTile != prevPlayerTile || curDecision == "DONEMOVINGTOBULLET" || curDecision == "DONEMOVINGTOENEMY") { //Prevents too many decisions from happening if ((Time.time > nextActionTime)) { nextActionTime = Time.time + period; //We have to perform the decision even distance result is the same, to make sure the enemy paths to the newest player position //If we did not, the enemy could just stay in range but never be hit by the enemy string dis = DistanceToPlayerDecision(); if (dis == "FAR") { if (curDecision != "MOVINGTOBULLET")// && curDecision != "MOVINGTOENEMY") { //Debug.Log("Making a decision"); curDecision = MakeDecision.MakeDecision(new List<AttributeValue<string>>() { playerDist, bulletClose, playerHPDecision, enemyAttackedDecision, thisHPDecision }); } } else { //Debug.Log("Making a decision"); curDecision = MakeDecision.MakeDecision(new List<AttributeValue<string>>() { playerDist, bulletClose, playerHPDecision, enemyAttackedDecision, thisHPDecision }); } } } //Execute decision if (curDecision == "CHASE") { GameManager.SpecialPathNode playerTile = Player.GetTileOn(); if (DoDstarLite) { this.MoveToTileDstar(playerTile); } else { this.MoveToTile(playerTile); } //To make sure it keeps moving, rather than sitting on "CHASE" curDecision = "FINDINGPLAYER"; } else if (curDecision == "STAY") { IsMoving = false; } else if (curDecision == "FINDBULLET") { if (target != null) { Debug.Log(target); if (DoDstarLite) { this.MoveToTileDstar(target.GetTileOn()); } else { this.MoveToTile(target.GetTileOn()); } curDecision = "MOVINGTOBULLET"; } } else if (curDecision == "DEFENDGOAL") { print ("ENEMY DEFENDING GOAL"); GameManager.SpecialPathNode exitTile = GameManager.ExitTile; //Debug.Log("EXit: " + exitTile.X + ", " + exitTile.Y); if (DoDstarLite) { this.MoveToTileDstar(exitTile); } else { this.MoveToTile(exitTile); } curDecision = "DEFENDINGGOAL"; } else if (curDecision == "DEFENDINGGOAL") { float dist = Vector3.Distance(this.transform.position, GameManager.ExitTile.tile.transform.position); if (dist < 2.0f) { IsMoving = false; curDecision = "ATGOAL"; } } else if (curDecision == "FINDENEMY") { if (attacked != null) { if (DoDstarLite) { this.MoveToTileDstar(attacked.GetTileOn()); } else { this.MoveToTile(attacked.GetTileOn()); } curDecision = "MOVINGTOENEMY"; } } Position = transform.position; if (DoDstarLite) { if ((CurrentDstarNode != null) && IsAtGoal(CurrentDstarNode.tile.transform.position)) { CurDstarIndex++; if (CurDstarIndex >= DstarPath.Count) { Debug.Log("Final Node found"); //end of nodes IsMoving = false; if (curDecision == "MOVINGTOBULLET") { curDecision = "DONEMOVINGTOBULLET"; } if (curDecision == "MOVINGTOENEMY") { curDecision = "DONEMOVINGTOENEMY"; } CurrentDstarNode = null; } else { GameManager.SpecialPathNode next = DstarPath[CurDstarIndex]; MoveToDstarNode(next); } } else { if (CurrentDstarNode != null) { TileX = CurrentDstarNode.X; TileY = CurrentDstarNode.Y; } } } else { if ((CurrentGoalNode != null) && IsAtGoal(CurrentGoalNode.Value.tile.transform.position)) { LinkedListNode<GameManager.SpecialPathNode> next = CurrentGoalNode.Next; if (next == null) { //Debug.Log("Final node found"); //end of list IsMoving = false; if (curDecision == "MOVINGTOBULLET") { curDecision = "DONEMOVINGTOBULLET"; } if (curDecision == "MOVINGTOENEMY") { curDecision = "DONEMOVINGTOENEMY"; } } else { MoveToNode(next); } } else { if (CurrentGoalNode != null) { TileX = CurrentGoalNode.Value.X; TileY = CurrentGoalNode.Value.Y; } } } if (IsMoving) { //Debug.Log("goal: " + GoalPos); transform.position = Vector3.MoveTowards(transform.position, GoalPos, Speed * Time.deltaTime); } if (DoDstarLite) { /* string s_e = ""; foreach (GameManager.SpecialPathNode n in DstarPath) { s_e += "(" + n.X + ", " + n.Y + ") "; n.tile.GetComponent<SpriteRenderer>().color = Color.blue; }*/ } }
public void MoveToTileDstar(GameManager.SpecialPathNode tile) { GameManager.SpecialPathNode eTile = this.GetTileOn(); CurDstarIndex = 0; if (DstarPath.Count == 0) { //First time dstar.InitializeGoals(eTile.X, eTile.Y, tile.X, tile.Y); dstar.Replan(); DstarPath = dstar.GetPath(); DstarPath.Add(tile); } else { //Debug.Log("Replanning"); dstar.UpdateStart(eTile.X, eTile.Y); dstar.UpdateGoal(tile.X, tile.Y); dstar.Replan(); DstarPath = dstar.GetPath(); DstarPath.Add(tile); } if (DstarPath.Count > 1) { //Debug.Log("Found path"); //Debug.Log(DstarPath[0].X + ", " + DstarPath[0].Y); //Debug.Log(eTile.X + ", " + eTile.Y); IsMoving = true; GoalPos = DstarPath[1].tile.transform.position; CurrentDstarNode = DstarPath[1]; CurDstarIndex = 1; /* string s_e = ""; foreach (GameManager.SpecialPathNode n in DstarPath) { s_e += "(" + n.X + ", " + n.Y + ") "; //n.tile.GetComponent<SpriteRenderer>().color = Color.blue; }*/ //Debug.Log(s_e); //CurrentGoalNode = DstarPath[0]; //LinkedListNode<GameManager.SpecialPathNode> next = path.First; } }
///* /// GenerateBlankBlobMap uses a procedural generation algorithm (cell automaton) to create the /// base floor layout of a map with a number of floor tiles equal to the input area. /// NOTE: should output blank map with format blankMap[x,y] ///* GameManager.SpecialPathNode[,] GenerateBlankBlobMap(int area, int optSeed = int.MinValue) { if (optSeed != int.MinValue) { Random.seed = optSeed; } print("blob map seed:" + Random.seed); Dictionary <Vector3, Cell> activeCells = new Dictionary <Vector3, Cell>(); Vector3 startLoc = new Vector3(0, 0, 0f); activeCells.Add(startLoc, new Cell(startLoc)); int currArea = 1; List <Cell> toBeActivated = new List <Cell>(); while (currArea < area) { toBeActivated.Clear(); List <Cell> allActive = activeCells.Values.ToList(); for (int i = 0; i < allActive.Count; i++) { List <Cell> neighbors = GetNeighbors(allActive[i], activeCells, false); if (neighbors.Count >= 4 && neighbors.Count > 0) //If this active cell has 4 or less active neighbors, add one randomly. { toBeActivated.Add(neighbors[Random.Range(0, neighbors.Count)]); //Get a random inactive neighbor and set it to be active on the next generation. } } if (toBeActivated.Count == 0) { List <Cell> neighbors = GetNeighbors(allActive[Random.Range(0, allActive.Count)], activeCells, false); if (neighbors.Count > 0) { toBeActivated.Add(neighbors[Random.Range(0, neighbors.Count)]); } } for (int j = 0; j < toBeActivated.Count; j++) { Cell c = toBeActivated[j]; if (!activeCells.ContainsKey(c.location)) { c.activate(); activeCells.Add(c.location, c); currArea++; } } } ////Now there is a dictionary full of cells to be turned into floor tiles, create the output array. //First, figure out how big the 2d array needs to be to contain the map, then create the empty array. List <Vector3> sortByX = activeCells.Keys.ToList(); sortByX.Sort((a, b) => a.x.CompareTo(b.x)); int minX = (int)sortByX[0].x; int xNum = (int)sortByX[sortByX.Count - 1].x - minX + 1; List <Vector3> sortByY = activeCells.Keys.ToList(); sortByY.Sort((a, b) => a.y.CompareTo(b.y)); int minY = (int)sortByY[0].y; int yNum = (int)sortByY[sortByY.Count - 1].y - minY + 1; GameManager.SpecialPathNode[,] blankMap = new GameManager.SpecialPathNode[xNum + 2, yNum + 2]; //Now convert the cells to the correct data type and fill the array. List <Cell> cells = activeCells.Values.ToList(); for (int k = 0; k < cells.Count; k++) { GameManager.SpecialPathNode node = new GameManager.SpecialPathNode(); //Calculate adjusted x-y coords so that all values are >0 (-minX/Y) and there is room for boundary around (+1). int adjustedX = (int)cells[k].location.x - minX + 1; int adjustedY = (int)cells[k].location.y - minY + 1; node.X = adjustedX; node.Y = adjustedY; node.tile = floorTile; node.IsWall = false; blankMap[adjustedX, adjustedY] = node; //y-minY+1,x-minX+1] = node; //+1 here shifts the tiles so there is room to add the walls around them. } return(blankMap); }
///* /// BoardSetup creates the floor and outer walls of the level and places the exit and enter doors on the /// upper and lower walls, respectively. If no exitLoc and/or enterLoc is specified, the door /// will be placed at a random horizontal location on the upper/lower wall. /// NOTE: This function is only used to build the default map. ///* GameManager.SpecialPathNode[,] BoardSetup(int exitLoc = -1, int enterLoc = -1) { if (exitLoc == -1) { exitLoc = Random.Range(0, columns); } if (enterLoc == -1) { enterLoc = Random.Range(0, columns); } boardHolder = new GameObject("Board").transform; GameManager.SpecialPathNode[,] boardArray = new GameManager.SpecialPathNode[columns + 2, rows + 2]; for (int x = -1; x < columns + 1; x++) { for (int y = -1; y < rows + 1; y++) { GameObject toInstantiate = floorTile; if (y == -1) { if (x == enterLoc) { toInstantiate = entrance; Instantiate(player, new Vector3(x, y + 1, 0f), Quaternion.identity); /** * Debug.Log("player stuff: " + player.transform.position + ", " + new Vector3(x, y + 1, 0f) + ", " + (y + 1 + 1) + ", " + (x)); * PlayerLoc = new GameManager.SpecialPathNode(); * PlayerLoc.X = x + 1; * PlayerLoc.Y = y + 1 + 1; * PlayerLoc.tile = player; * PlayerLoc.IsWall = false;*/ } else { toInstantiate = obstacleTile; } } else if (y == rows) { if (x == exitLoc) { toInstantiate = exit; } else { toInstantiate = obstacleTile; } } else if (x == -1 || x == columns) { toInstantiate = obstacleTile; } GameObject instance = Instantiate(toInstantiate, new Vector3(x, y, 0f), Quaternion.identity) as GameObject; instance.transform.SetParent(boardHolder); GameManager.SpecialPathNode thisNode = new GameManager.SpecialPathNode(); thisNode.X = x + 1; thisNode.Y = y + 1; thisNode.tile = instance; thisNode.IsWall = true; boardArray[x + 1, y + 1] = thisNode; } } return(boardArray); }
bool isFloorNode(GameManager.SpecialPathNode node) { return(node != null && node.tile == floorTile); }
/*////////////////////PROCEDURAL MAP GENERATION FUNCTIONS////////////////////////////////*/ /// /// Adds walls, doors, and enemies to the border of an input blank map. Places the /// enter door on a south-most wall, and places the exit door on one of the /// north-most walls. The number of enemies placed corresponds to the input level. /// NOTE: input blankMap should be array of nodes in blankMap[x,y] format /// GameManager.SpecialPathNode[,] FillBlankMap(GameManager.SpecialPathNode[,] blankMap, int level, int optSeed = int.MinValue) { if (optSeed != int.MinValue) { Random.seed = optSeed; } print("walls/doors seed:" + Random.seed); GameManager.SpecialPathNode[,] walledMap = blankMap; int xNum = walledMap.GetLength(0); int yNum = walledMap.GetLength(1); for (int x = 0; x < xNum; x++) { int leftInd = (x > 0)?(x - 1):(0); int rightInd = (x < xNum - 1)?(x + 1):(xNum - 1); for (int y = 0; y < yNum; y++) { int downInd = (y > 0)?(y - 1):(0); int upInd = (y < yNum - 1)?(y + 1):(yNum - 1); int[,] cases = new int[4, 2] { //Four cases with (x,y) in each { leftInd, y }, //Case 0: right edge of floor { rightInd, y }, //Case 1: left edge of floor { x, downInd }, //Case 2: upper edge of floor { x, upInd } }; //Case 3: lower edge of floor //If any of the cases are true create an obstacle tile. for (int caseNum = 0; caseNum < cases.GetLength(0); caseNum++) { int caseX = cases[caseNum, 0]; int caseY = cases[caseNum, 1]; if (isFloorNode(blankMap[caseX, caseY]) && blankMap[x, y] == null) //current cell is empty and one above it is floor { GameManager.SpecialPathNode node = new GameManager.SpecialPathNode(); node.X = x; node.Y = y; node.tile = obstacleTile; node.IsWall = true; walledMap[x, y] = node; } } } } //Now add the enter and exit doors... bool[,] travSpace = getTraversableSpace(walledMap); //Exit door: int exitY = walledMap.GetLength(1); List <int> exitOptions = new List <int>(); while (exitOptions.Count == 0 && exitY > 0) { exitY--; for (int i = 0; i < walledMap.GetLength(0); i++) { if (walledMap[i, exitY] != null && walledMap[i, exitY].tile == obstacleTile && travSpace[i, exitY - 1]) { exitOptions.Add(i); } } } int exitX = exitOptions[Random.Range(0, exitOptions.Count)]; walledMap[exitX, exitY].tile = exit; //Enter door: int enterY = -1; List <int> enterOptions = new List <int>(); while (enterOptions.Count == 0 && enterY < walledMap.GetLength(1) - 1) { enterY++; for (int i = 0; i < walledMap.GetLength(0); i++) { if (walledMap[i, enterY] != null && walledMap[i, enterY].tile == obstacleTile && travSpace[i, enterY + 1]) { enterOptions.Add(i); } } } int enterX = enterOptions[Random.Range(0, enterOptions.Count)]; walledMap[enterX, enterY].tile = entrance; //Now place the player and enemies on the map based on the level and traversable space. Vector3 playerLoc = new Vector3(enterX, enterY + 1, 0f); Instantiate(player, playerLoc, Quaternion.identity); int numEnemies = level * 2; //Mathf.Max((int)(Mathf.Log(level, 2f)+1)*level/3,level); for (int i = 0; i < numEnemies; i++) { int randX = -1; int randY = -1; Vector3 randVec = new Vector3(randX, randY, 0f); while (randX == -1 || randY == -1 || !travSpace[randX, randY] || Vector3.Distance(randVec, playerLoc) < 10) { randX = Random.Range(0, travSpace.GetLength(0)); randY = Random.Range(0, travSpace.GetLength(1)); randVec = new Vector3(randX, randY, 0f); } GameObject instance = Instantiate(enemy, randVec, Quaternion.identity) as GameObject; Enemy thisEnemy = instance.GetComponent <Enemy>(); if (Enemies == null) { Enemies = new List <Enemy>(); } Enemies.Add(thisEnemy); } return(walledMap); }