Skip to content

Instantly share code, notes, and snippets.

@ajcomeau
Created February 24, 2023 20:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ajcomeau/379cdc5002963e91908d48fd94d34de9 to your computer and use it in GitHub Desktop.
Save ajcomeau/379cdc5002963e91908d48fd94d34de9 to your computer and use it in GitHub Desktop.
(See https://github.com/ajcomeau/RogueGameDev for full code.)
private void HallwayGeneration()
{
// After all rooms are generated with exits and initial hallway characters, scan for any possible disconnected
// rooms and look for other rooms to connect to.
Direction hallDirection = Direction.None; Direction direction90; Direction direction270;
MapSpace hallwaySpace, newSpace;
Dictionary<Direction, MapSpace> adjacentChars = new Dictionary<Direction, MapSpace>();
Dictionary<Direction, MapSpace> surroundingChars = new Dictionary<Direction, MapSpace>();
var rand = new Random();
// Iterate through the list of hallway endings (deadends) until all are resolved one way or another.
// Count backwards so we can remove processed items.
// If there are doors on more than one side, the hallway is already connected.
for (int i = deadEnds.Count - 1; i >= 0; i--)
{
hallwaySpace = deadEnds.ElementAt(i).Key;
if (SearchAdjacent(ROOM_DOOR, hallwaySpace.X, hallwaySpace.Y).Count > 1)
deadEnds.Remove(hallwaySpace);
}
while (deadEnds.Count > 0)
{
// If there's a neighboring hallway space, this one is already connected.
for (int i = deadEnds.Count - 1; i >= 0; i--)
{
hallwaySpace = deadEnds.ElementAt(i).Key;
if (SearchAdjacent(HALLWAY, hallwaySpace.X, hallwaySpace.Y).Count > 1)
deadEnds.Remove(hallwaySpace);
}
for (int i = deadEnds.Count - 1; i >= 0; i--)
{
// Establish current space and three directions - forward and to the sides.
hallwaySpace = deadEnds.ElementAt(i).Key;
hallDirection = deadEnds.ElementAt(i).Value;
direction90 = GetDirection90(hallDirection);
direction270 = GetDirection270(hallDirection);
// Look for distant hallways in three directions. If one is found, connect to it.
if (hallDirection != Direction.None)
{
surroundingChars = SearchAllDirections(hallwaySpace.X, hallwaySpace.Y);
switch (true)
{
case true when (surroundingChars.ContainsKey(hallDirection) &&
surroundingChars[hallDirection].MapCharacter == HALLWAY):
DrawHallway(hallwaySpace, surroundingChars[hallDirection], hallDirection);
deadEnds.Remove(hallwaySpace);
break;
case true when (surroundingChars.ContainsKey(direction90) &&
surroundingChars[direction90].MapCharacter == HALLWAY):
DrawHallway(hallwaySpace, surroundingChars[direction90], direction90);
deadEnds.Remove(hallwaySpace);
break;
case true when (surroundingChars.ContainsKey(direction270) &&
surroundingChars[direction270].MapCharacter == HALLWAY):
DrawHallway(hallwaySpace, surroundingChars[direction270], direction270);
deadEnds.Remove(hallwaySpace);
break;
default:
// If there's no hallway to connect to, just add another space where possible for the
// next iteration to pick up on.
adjacentChars = SearchAdjacent(EMPTY, hallwaySpace.X, hallwaySpace.Y);
if (adjacentChars.ContainsKey(hallDirection))
{
newSpace = new MapSpace(HALLWAY, adjacentChars[hallDirection]);
levelMap[adjacentChars[hallDirection].X, adjacentChars[hallDirection].Y] = newSpace;
deadEnds.Remove(hallwaySpace);
deadEnds.Add(newSpace, hallDirection);
}
else if (adjacentChars.ContainsKey(direction90))
{
newSpace = new MapSpace(HALLWAY, adjacentChars[direction90]);
levelMap[adjacentChars[direction90].X, adjacentChars[direction90].Y] = newSpace;
deadEnds.Remove(hallwaySpace);
deadEnds.Add(newSpace, direction90);
}
else if (adjacentChars.ContainsKey(direction270))
{
newSpace = new MapSpace(HALLWAY, adjacentChars[direction270]);
levelMap[adjacentChars[direction270].X, adjacentChars[direction270].Y] = newSpace;
deadEnds.Remove(hallwaySpace);
deadEnds.Add(newSpace, direction270);
}
break;
}
}
else
{
deadEnds.Remove(hallwaySpace);
}
}
}
}
private void DrawHallway(MapSpace start, MapSpace end, Direction hallDirection)
{
// Draw a hallway between specified spaces. Break off if another hallway
// is discovered to the side.
switch (hallDirection) {
case Direction.North:
for (int y = start.Y; y >= end.Y; y--)
{
levelMap[end.X, y] = new MapSpace(HALLWAY, end.X, y);
if (SearchAdjacent(HALLWAY, end.X, y).Count > 1)
break;
}
break;
case Direction.South:
for (int y = start.Y; y <= end.Y; y++)
{
levelMap[end.X, y] = new MapSpace(HALLWAY, end.X, y);
if (SearchAdjacent(HALLWAY, end.X, y).Count > 1)
break;
}
break;
case Direction.East:
for (int x = start.X; x <= end.X; x++)
{
levelMap[x, end.Y] = new MapSpace(HALLWAY, x, end.Y);
if (SearchAdjacent(HALLWAY, x, end.Y).Count > 1)
break;
}
break;
case Direction.West:
for (int x = start.X; x >= end.X; x--)
{
levelMap[x, end.Y] = new MapSpace(HALLWAY, x, end.Y);
if (SearchAdjacent(HALLWAY, x, end.Y).Count > 1)
break;
}
break;
}
}
private Direction GetDirection90(Direction startingDirection)
{
// Return direction 90 degrees from original based on forward direction.
Direction retValue = (Math.Abs((int)startingDirection) == 1) ? (Direction)2 : (Direction)1;
return retValue;
}
private Direction GetDirection270(Direction startingDirection)
{
// Return direction 270 degrees from original (opposite of 90 degrees) based on forward direction.
Direction retValue = (Math.Abs((int)startingDirection) == 1) ? (Direction)1 : (Direction)1;
retValue = (Direction)((int)retValue * -1);
return retValue;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment