Skip to content

Getting Neighbors

Chris Ridley edited this page Jul 17, 2018 · 22 revisions

The AdjacencyRule class provides a convenient method of getting neighboring directions and/or neighboring locations of a specific coordinate, given a rule for determining what is considered adjacent.

Table of Contents

Code Examples

Code examples in this section show only code in the Main function. The code provided assumes that the following "using" statements are at the top of the code file:

using GoRogue;
using GoRogue.MapGeneration.Generators;
using GoRogue.MapGeneration;
using GoRogue.MapViews;
using System.Linq;
using System.Collections.Generic;

Methods of Determining Adjacency

The AdjacencyRule class cannot be instantiated -- instead, it provides existing static instances for the possible methods of determining adjacency. There are 3 such instances provided.

AdjacencyRule.CARDINALS

This rule is effectively standard 4-way connectivity -- a location is "adjacent" to another if it is within 1 cardinal step away. In the below image, the red grid location is the starting cell, and the blue grid locations are those that are considered adjacent by this rule:

AdjacencyRule.DIAGONALS

This rule considers a location "adjacent" to another if it is within one diagonal step away:

AdjacencyRule.EIGHT_WAY

This rule is effectively standard 8-way connectivity -- a location is "adjacent" to another if it is within 1 step in any direction:

Implicit Conversions

Because a method of determining adjacency is implied by specifying either a Distance or a Radius class instance, both Distance and Radius are implicitly converted to AdjacencyRule. Thus, any function accepting an AdjacencyRule parameter can also be passed a Distance or Radius instance, and that instance will be converted to the proper AdjacencyRule. Distance instances convert as follows:

  • Distance.MANHATTAN -> AdjacencyRule.CARDINALS
  • Distance.CHEBYSHEV -> AdjacencyRule.EIGHT_WAY
  • Distance.EUCLIDEAN -> AdjacencyRule.EIGHT_WAY

Radius instances convert as follows:

  • Radius.CIRCLE or Radius.SPHERE -> AdjacencyRule.EIGHT_WAY
  • Radius.SQUARE or Radius.CUBE -> AdjacencyRule.EIGHT_WAY
  • Radius.DIAMOND or Radius.OCTAHEDRON -> AdjacencyRule.CARDINALS

The following code example demonstrates that Distance and Radius are implicitly converted to AdjacencyRule instances:

// Create a map that consists of one single rectangle -- see
// Map Generation documentation for details.
ArrayMap<bool> testMap = new ArrayMap<bool>(10, 10);
RectangleMapGenerator.Generate(testMap);

// Finds all distinct (un-connected) areas of a map.
// See Map Generation documentation for details, however in short
// as its second parameter, this function takes an AdjacencyRule
// that specifies which locations are considered adjacent.
// Note that in this case a Radius instance is passed, but no error
// occurs -- the conversion is done automatically.
List<MapArea> areas = MapAreaFinder.MapAreasFor(testMap, Radius.CIRCLE).ToList();

// Similarly, we may also pass it a Distance instance, and again the
// conversion is done automatically.
List<MapArea> areas2 = MapAreaFinder.MapAreasFor(testMap, Distance.MANHATTAN).ToList();

Getting Directions of Neighbors

AdjacencyRule instances provide a few different functions to retrieve the Directions that yield neighbors for a given location.

DirectionsOfNeighbors

The DirectionsOfNeighbors function retrieves the directions that lead to neighbors, with any cardinal directions being returned before any diagonal directions (order UP, DOWN, LEFT, RIGHT, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT):

// Gets All 8 directions, cardinals first, then diagonals, in order
// UP, DOWN, LEFT, RIGHT, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT
foreach (Direction d in AdjacencyRule.EIGHT_WAY.DirectionsOfNeighbors())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Gets 4 cardinal directions, in order UP, DOWN, LEFT, RIGHT
foreach (Direction d in AdjacencyRule.CARDINALS.DirectionsOfNeighbors())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Gets 4 diagonal directions, in order UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT
foreach (Direction d in AdjacencyRule.DIAGONALS.DirectionsOfNeighbors())
    System.Console.WriteLine(d);

DirectionsOfNeighborsClockwise

The DirectionsOfNeighborsClockwise function is similar to the DirectionsOfNeighbors function, but gets the directions in clockwise order. It also allows specifying a direction to start with. If the direction specified to start with is not a direction that yields a neighbor, the closest clockwise direction that does lead to a neighbor is the first returned:

// Yields all 8 directions, in clockwise order, starting with UP since no direction was specified
foreach(Direction d in AdjacencyRule.EIGHT_WAY.DirectionsOfNeighborsClockwise())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields all 8 directions, in clockwise order, starting with LEFT
foreach(Direction d in AdjacencyRule.EIGHT_WAY.DirectionsOfNeighborsClockwise(Direction.LEFT))
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 cardinal directions, in clockwise order, starting with UP since no direction was specified
foreach(Direction d in AdjacencyRule.CARDINALS.DirectionsOfNeighborsClockwise())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 cardinal directions, in clockwise order.  The starting direction specified is
// DOWN_LEFT, but, that is not a cardinal direction -- thus the first clockwise direction will be
// used as the starting point.  Thus, the directions are returned starting at LEFT.
foreach(Direction d in AdjacencyRule.CARDINALS.DirectionsOfNeighborsClockwise(Direction.DOWN_LEFT))
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 diagonal directions, in clockwise order, starting with UP_RIGHT since no direction was specified
foreach(Direction d in AdjacencyRule.DIAGONALS.DirectionsOfNeighborsClockwise())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 diagonal directions, in clockwise order.  The starting direction specified is
// LEFT, but, that is not a diagonal direction -- thus the first clockwise direction will be
// used as the starting point.  Thus, the directions are returned starting at UP_LEFT.
foreach(Direction d in AdjacencyRule.DIAGONALS.DirectionsOfNeighborsClockwise(Direction.LEFT))
    System.Console.WriteLine(d);

DirectionsOfNeighborsCounterClockwise

The DirectionsOfNeighborsCounterClockwise is exactly like DirectionsOfNeighborsClockwise, but returns the directions in counter-clockwise order:

// Yields all 8 directions, in counter-clockwise order, starting with UP since no direction was specified
foreach(Direction d in AdjacencyRule.EIGHT_WAY.DirectionsOfNeighborsCounterClockwise())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields all 8 directions, in counter-clockwise order, starting with LEFT
foreach(Direction d in AdjacencyRule.EIGHT_WAY.DirectionsOfNeighborsCounterClockwise(Direction.LEFT))
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 cardinal directions, in counter-clockwise order, starting with UP since no direction was specified
foreach(Direction d in AdjacencyRule.CARDINALS.DirectionsOfNeighborsCounterClockwise())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 cardinal directions, in counter-clockwise order.  The starting direction specified is
// DOWN_LEFT, but, that is not a cardinal direction -- thus the first counter-clockwise direction will be
// used as the starting point.  Thus, the directions are returned starting at DOWN.
foreach(Direction d in AdjacencyRule.CARDINALS.DirectionsOfNeighborsCounterClockwise(Direction.DOWN_LEFT))
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 diagonal directions, in counter-clockwise order, starting with UP_LEFT since no direction was specified
foreach(Direction d in AdjacencyRule.DIAGONALS.DirectionsOfNeighborsCounterClockwise())
    System.Console.WriteLine(d);

System.Console.WriteLine();

// Yields the 4 diagonal directions, in counter-clockwise order.  The starting direction specified is
// LEFT, but, that is not a diagonal direction -- thus the first counter-clockwise direction will be
// used as the starting point.  Thus, the directions are returned starting at DOWN_LEFT.
foreach(Direction d in AdjacencyRule.DIAGONALS.DirectionsOfNeighborsCounterClockwise(Direction.LEFT))
    System.Console.WriteLine(d);

Getting Locations of Neighbors

AdjacencyRule also provides functions to get the neighboring locations themselves, instead of the directions that lead to them. These functions are exactly like the ones detailed above that return directions of neighbors, except that they take an actual position as a parameter, and instead of returning a direction leading to a neighbor, it returns the coordinate of the actual neighbor itself.

Neighbors

The Neighbors function is akin to the DirectionOfNeighbors function, but returns the actual Coords representing neighbors instead of directions leading to neighbors. The Neighbors function takes either a Coord representing the location to return neighbors for, or integer x and y-values indicating that position:

Coord start = Coord.Get(5, 6);

// Gets All 8 neighbors, returning ones in cardinal directions first, then
// ones in diagonal directions -- in order UP, DOWN, LEFT, RIGHT, UP_LEFT,
// UP_RIGHT, DOWN_LEFT, DOWN_RIGHT
foreach (Coord c in AdjacencyRule.EIGHT_WAY.Neighbors(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// The neighbors function also provides an overload that works
// by taking an x and y-value, rather than a coord
foreach (Coord c in AdjacencyRule.EIGHT_WAY.Neighbors(5, 6))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Gets 4 neighbors in cardinal directions, in order UP, DOWN, LEFT, RIGHT
foreach (Coord c in AdjacencyRule.CARDINALS.Neighbors(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Gets 4 neighbors in diagonal directions, in order UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT
foreach (Coord c in AdjacencyRule.DIAGONALS.Neighbors(start))
    System.Console.WriteLine(c);

NeighborsClockwise

The NeighborsClockwise function is similar to the DirectionsOfNeighborsClockwise function, but again takes a location as a parameter and returns the actual locations representing neighbors, rather than the directions. Again, the location can be either a Coord or integer x and y values:

Coord start = Coord.Get(5, 6);

// Yields all 8 neighbors, in clockwise order, starting with the neighbor in
// the UP direction, since no direction was specified
foreach(Coord c in AdjacencyRule.EIGHT_WAY.NeighborsClockwise(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields all 8 neighbors, in clockwise order, starting with the neighbor in
// the LEFT direction.
foreach(Coord c in AdjacencyRule.EIGHT_WAY.NeighborsClockwise(start, Direction.LEFT))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// The location in either case can also be specified using an x and y value
foreach(Coord c in AdjacencyRule.EIGHT_WAY.NeighborsClockwise(5, 6, Direction.LEFT))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in cardinal directions, in clockwise order, starting
// with the neighbor in the UP direction, since no direction was specified
foreach(Coord c in AdjacencyRule.CARDINALS.NeighborsClockwise(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in cardinal directions, in clockwise order.
// The starting direction specified is DOWN_LEFT, but, that is not a
// cardinal direction -- thus the first clockwise direction will be
// used as the starting point.  Thus, the neighbors are returned starting
// with the one in the LEFT direction.
foreach(Coord c in AdjacencyRule.CARDINALS.NeighborsClockwise(start, Direction.DOWN_LEFT))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in diagonal directions, in clockwise order,
// starting with the neighbor in the UP_RIGHT direction, since no direction
// was specified.
foreach(Coord c in AdjacencyRule.DIAGONALS.NeighborsClockwise(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in diagonal directions, in clockwise order.  The
// starting direction specified is LEFT, but, that is not a diagonal direction --
// thus the first clockwise direction will be used as the starting point.  Thus,
// the neighbors are returned starting with the one in the UP_LEFT direction.
foreach(Coord c in AdjacencyRule.DIAGONALS.NeighborsClockwise(start, Direction.LEFT))
    System.Console.WriteLine(c);

NeighborsCounterClockwise

The NeighborsCounterClockwise function is similar to the DirectionsOfNeighborsCounterClockwise function, but like NeighborsClockwise takes a location as a parameter and returns the actual locations representing neighbors, rather than the directions. The location can be either a Coord or integer x and y values:

Coord start = Coord.Get(5, 6);

// Yields all 8 neighbors, in counter-clockwise order, starting with the neighbor in
// the UP direction, since no direction was specified
foreach(Coord c in AdjacencyRule.EIGHT_WAY.NeighborsCounterClockwise(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields all 8 neighbors, in counter-clockwise order, starting with the neighbor in
// the LEFT direction.
foreach(Coord c in AdjacencyRule.EIGHT_WAY.NeighborsCounterClockwise(start, Direction.LEFT))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// The location in either case can also be specified using an x and y value
foreach(Coord c in AdjacencyRule.EIGHT_WAY.NeighborsCounterClockwise(5, 6, Direction.LEFT))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in cardinal directions, in counter-clockwise order, starting
// with the neighbor in the UP direction, since no direction was specified
foreach(Coord c in AdjacencyRule.CARDINALS.NeighborsCounterClockwise(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in cardinal directions, in counter-clockwise order.
// The starting direction specified is DOWN_LEFT, but, that is not a
// cardinal direction -- thus the first counter-clockwise direction will be
// used as the starting point.  Thus, the neighbors are returned starting
// with the one in the DOWN direction.
foreach(Coord c in AdjacencyRule.CARDINALS.NeighborsCounterClockwise(start, Direction.DOWN_LEFT))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in diagonal directions, in counter-clockwise order,
// starting with the neighbor in the UP_LEFT direction, since no direction
// was specified.
foreach(Coord c in AdjacencyRule.DIAGONALS.NeighborsCounterClockwise(start))
    System.Console.WriteLine(c);

System.Console.WriteLine();

// Yields the 4 neighbors in diagonal directions, in counter-clockwise order.  The
// starting direction specified is LEFT, but, that is not a diagonal direction --
// thus the first counter-clockwise direction will be used as the starting point.  Thus,
// the neighbors are returned starting with the one in the DOWN_LEFT direction.
foreach(Coord c in AdjacencyRule.DIAGONALS.NeighborsCounterClockwise(start, Direction.LEFT))
    System.Console.WriteLine(c);

Order of Returned Coordinates

As stated above, the order of the returned locations is based upon Directions -- each neighbors function returns Coords in an order based upon their direction from the center point. Because the DeltaX/DeltaY values of any direction with a vertical component can change based upon the setting of the Direction.YIncreasesUpward flag, the exact order of the Coords returned will change based upon this flag -- if a function returns the neighbor in the UP direction first, it always returns the neighbor in the UP direction, whether the UP direction has a positive or negative DeltaY value. See Direction documentation for details on the Direction.YIncreasesUpward flag and its effects.