/// <summary> /// Tries to find a place for the wall in the specified rectangle. /// </summary> /// <returns>An integer which describes the x coordinate where the wall should be placed</returns> private int TryPlaceWallVertical(MazeCoordinate recUpperleft, MazeCoordinate recDownright, Strategy strategy) { // first collect all possible coordinates int from = recUpperleft.X + 2; int to = recDownright.X - 2; int count = to - from; if (count <= 0) { return(-1); } var possibleVerticalCoordinates = Enumerable.Range(from, to - from).ToList(); while (possibleVerticalCoordinates.Count() > 0) { //try them one by one int coordinateToTest = ChooseCoordinateBasedOnStrategy(strategy, possibleVerticalCoordinates); // will it cover a corridor? if (!(CurrentMaze.IsCorridor(new MazeCoordinate(coordinateToTest, recUpperleft.Y)) || CurrentMaze.IsCorridor(new MazeCoordinate(coordinateToTest, recDownright.Y)))) { // found valid coordinate return(coordinateToTest); } possibleVerticalCoordinates.Remove(coordinateToTest); } // Failed to find a good coordinate. return(-1); }
internal override MazeTransformationStep TryPlaceExit() { List <MazeCoordinate> possibleExits = new List <MazeCoordinate>(); // collect all possible exits for (int y = CurrentMaze.GetHeight() - 2; y >= CurrentMaze.GetHeight() / 2; y--) { possibleExits.Add(new MazeCoordinate(0, y)); } // check in random order if exit is valid while (possibleExits.Count > 0) { var possibleExit = possibleExits.ElementAt(Random.Next(possibleExits.Count)); if (this.CurrentMaze.GetMazeTypeOnPos(1, possibleExit.Y) == MazeFieldType.Corridor) { return(this.CurrentMaze.SetMazeTypeOnPos(0, possibleExit.Y, MazeFieldType.Exit)); } else { possibleExits.Remove(possibleExit); } } throw new Exception("Could not place a valid exit."); }
private bool IsValidWay(MazeCoordinate point, MazeCoordinate comeFrom) { if (!this.CurrentMaze.IsPointInMaze(point)) { return(false); } // Already something other than a wall? if (this.CurrentMaze.GetMazeTypeOnPos(point) != MazeFieldType.Wall) { return(false); } // Make sure we do not create a way through a wall. MazeCoordinate up = new MazeCoordinate(point.X, point.Y - 1); MazeCoordinate right = new MazeCoordinate(point.X + 1, point.Y); MazeCoordinate down = new MazeCoordinate(point.X, point.Y + 1); MazeCoordinate left = new MazeCoordinate(point.X - 1, point.Y); MazeCoordinate[] pointsToCheck = { up, right, down, left }; for (int i = 0; i < pointsToCheck.Length; i++) { if (!pointsToCheck[i].Equals(comeFrom)) { if (CurrentMaze.GetMazeTypeOnPos(pointsToCheck[i]) == MazeFieldType.Corridor) { return(false); } } } return(true); }
internal override IEnumerable <MazeTransformationStep> InternalGenerateMazeFullSize() { InitializeMaze(); entrance = new MazeCoordinate(upperleft.X + 1 + Random.Next(this.CurrentMaze.GetWidth() - 2), upperleft.Y); pointStack.Push(entrance); Nullable <MazeCoordinate> newCorridor; while (pointStack.Count() != 0) { newCorridor = FindWay(); if (newCorridor == null) { newCorridor = pointStack.Pop(); // One step back if (newCorridor != null && CurrentMaze.WouldChangeMazeFieldType(newCorridor.Value, MazeFieldType.Corridor)) { yield return(CurrentMaze.SetMazeTypeOnPos(newCorridor.Value, MazeFieldType.Corridor)); } } else { pointStack.Push(newCorridor.Value); yield return(CurrentMaze.SetMazeTypeOnPos(newCorridor.Value, MazeFieldType.Corridor)); } } yield return(TryPlaceEntrance()); yield return(TryPlaceExit()); }
internal override MazeTransformationStep TryPlaceExit() { List <MazeCoordinate> possibleExits = new List <MazeCoordinate>(); // collect all possible exits for (int i = CurrentMaze.GetWidth() - 2; i >= 1; i--) { possibleExits.Add(new MazeCoordinate(i, downright.Y)); } // check in random order if exit is valid while (possibleExits.Count > 0) { var possibleExit = possibleExits.ElementAt(Random.Next(possibleExits.Count)); if (CurrentMaze.GetMazeTypeOnPos(possibleExit.X, possibleExit.Y + 1) == MazeFieldType.Corridor) { return(CurrentMaze.SetMazeTypeOnPos(possibleExit, MazeFieldType.Exit)); } else { possibleExits.Remove(possibleExit); } } // TODO Maybe not the best way to handle this, but the maze is useless without valid exit. throw new Exception("Could not find a suitable exit position."); }
public override IEnumerable <MazeTransformationStep> InitializeMaze() { downright = new MazeCoordinate(CurrentMaze.GetWidth() - 1, 0); upperleft = new MazeCoordinate(0, CurrentMaze.GetHeight() - 1); CurrentMaze.OverrideAllMazeFields(MazeFieldType.Wall); return(null); }
// This method will handle the room traversal. Find the chosen room, check it to // see if it's close to the current. Check for locks, monsters, is it final, etc. // At last remove 5 health from the user. public void GoRoom(string room) { Room desiredLocation = (Room)CurrentMaze.GetRoom(room); if (desiredLocation != null) { if (CurrentMaze.IsNeighbor(desiredLocation, (Room)CurrentLocation)) { if (desiredLocation.IsLocked == true) { Console.WriteLine("--------------LOCKED----------------"); Console.WriteLine("Room is locked. You need a key to enter."); Console.WriteLine("--------------LOCKED----------------"); return; } this.Health -= 5; if (this.Health <= 0) { this.Die(); return; } CurrentLocation = desiredLocation; if (CurrentLocation.HasMonster) { this.Fight(); } this.ShowLocation(); if (CurrentLocation.IsFinalRoom) // Check for potential win. { CurrentMaze.LevelPassed(); } return; } else { Console.WriteLine("You can't walk through walls."); return; } } Console.WriteLine("Invalid location."); }
// Try to unlock the chosen room. User needs a key. public void Unlock(string roomName) { var chosenRoom = CurrentMaze.GetRoom(roomName); if (chosenRoom == null) { Console.WriteLine("No such room"); return; } if (!CurrentMaze.IsNeighbor(chosenRoom, this.CurrentLocation)) { Console.WriteLine("You can't walk through walls"); } else { if (chosenRoom.IsLocked) { foreach (var item in this.Bag) { if (item is ISpecial) { chosenRoom.IsLocked = false; this.Bag.Remove(item); Console.WriteLine("--------------UNLOCKED----------------"); Console.WriteLine("Room unlocked."); Console.WriteLine("--------------UNLOCKED----------------"); return; } } Console.WriteLine("You don't have a key."); } else { Console.WriteLine("Room is not locked."); } } }
internal override MazeTransformationStep TryPlaceEntrance() { // no need to check, the nature of the algorithm will guarantee that all positions on this side are valid entrances. return(this.CurrentMaze.SetMazeTypeOnPos(Random.Next(1, CurrentMaze.GetWidth() - 2), 0, MazeFieldType.Entrance)); }
public override IEnumerable <MazeTransformationStep> InitializeMaze() { CurrentMaze.OverrideAllMazeFields(MazeFieldType.Wall); return(null); }
private bool checkIfWallDividesTwoCorridors(MazeCoordinate target) { MazeCoordinate[] temp = MazeCoordinate.GetHorizontalVerticalAdjacentCoordinates(target); int TargetWallAlignsWithCorridors = 0; foreach (MazeCoordinate c in temp) { if (this.CurrentMaze.GetMazeTypeOnPos(c) == MazeFieldType.Corridor) { if (target.X == c.X || target.Y == c.Y) { TargetWallAlignsWithCorridors++; } } } // direct connection if (TargetWallAlignsWithCorridors > 2) { return(true); } temp = MazeCoordinate.GetAllAdjacentCoordinates(target); int CorridorFieldsInCloseProximity = 0; HashSet <MazeCoordinate> inProximity = new HashSet <MazeCoordinate>(); foreach (MazeCoordinate c in temp) { if (CurrentMaze.GetMazeTypeOnPos(c) != MazeFieldType.Wall) { CorridorFieldsInCloseProximity++; inProximity.Add(c); } } // This value can be reduced to create more narrow sideways, maybe make it configurable ? if (CorridorFieldsInCloseProximity >= 3) { return(true); } if (CorridorFieldsInCloseProximity == 2) { // check if the corridors are adjacent each other then its OK. foreach (MazeCoordinate c in inProximity) { var subset = inProximity.Where(x => x != c).AsEnumerable(); bool allAdjacent = subset.All(x => x.IsAdjacentTo(c)); if (allAdjacent) { return(false); } } return(true); } if (TargetWallAlignsWithCorridors > 1 && CorridorFieldsInCloseProximity >= 2) { return(true); } else { return(false); } }
public void startMaze(MazeGraph theMaze) { myMaze = new CurrentMaze(theMaze); }
private IEnumerable <MazeTransformationStep> RekursiveDiv(MazeCoordinate recUpperleft, MazeCoordinate recDownright, bool horizontal) { int width = recDownright.X - recUpperleft.X; int height = recUpperleft.Y - recDownright.Y; int minSize = 0; Strategy currentStrategy = CheckWhichStrategyToUse(width, height); if (!(width < minSize && height < minSize)) { // Override the random decision for horizontal/vertical wall placement, this reduces long stretched corridors if (width > height) { horizontal = false; } else { horizontal = true; } if (horizontal) {// Horizontal int newWallY = TryPlaceWallHorizontal(recUpperleft, recDownright, currentStrategy); if (newWallY > 0) { for (int i = 1; i < width; i++) { // Create wall yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(recUpperleft.X + i, newWallY), MazeFieldType.Wall)); } // Place corridor int randX = FindHorizontalCorridor(ref recUpperleft, ref recDownright); yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(randX, newWallY), MazeFieldType.Corridor)); // up MazeCoordinate upperleftNew = new MazeCoordinate(recUpperleft.X, recUpperleft.Y); MazeCoordinate downrightNew = new MazeCoordinate(recDownright.X, newWallY); foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0)) { yield return(recursiveResult); } // down upperleftNew = new MazeCoordinate(recUpperleft.X, newWallY); downrightNew = new MazeCoordinate(recDownright.X, recDownright.Y); foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0)) { yield return(recursiveResult); } } } else {// Vertical int newWallX = TryPlaceWallVertical(recUpperleft, recDownright, currentStrategy); if (newWallX > 0) { for (int i = 1; i < height; i++) { // Create Wall yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(newWallX, recDownright.Y + i), MazeFieldType.Wall)); } // Place corridor int randY = FindVerticalCorridor(ref recUpperleft, ref recDownright); yield return(CurrentMaze.SetMazeTypeOnPos(new MazeCoordinate(newWallX, randY), MazeFieldType.Corridor)); //left MazeCoordinate upperleftNew = new MazeCoordinate(recUpperleft.X, recUpperleft.Y); MazeCoordinate downrightNew = new MazeCoordinate(newWallX, recDownright.Y); foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0)) { yield return(recursiveResult); } //right upperleftNew = new MazeCoordinate(newWallX, recUpperleft.Y); downrightNew = new MazeCoordinate(recDownright.X, recDownright.Y); foreach (var recursiveResult in RekursiveDiv(upperleftNew, downrightNew, Random.Next(2) > 0)) { yield return(recursiveResult); } } } } }