When working on Hive and Proximity, we’re dealing with boards of hexagons. If you look at a bunch of hexagons together, you’ll notice that they don’t sit next to each other in a way that’s a straightforward analog to square pieces like you’d find in a chess board.

In the process of working on these two games, I came up with a system of mapping all the pieces to a 2-dimensional array (rows and columns).

As shown in the diagram: if you offset every other row by half of a tile, you can address every space using normal row/column coordinates. The red arrows show a path of traversing across columns in the same row and the blue arrows show a path moving down rows in the same column. In a board with square pieces such as chess, these would both just be straight paths instead of the blue lines zig-zagging. As an exercise, can you see where the next column to the right of the blue lines would be? The second column would start at (1, 0) and would go to (1,1), then back to (1,2), then (1, 3) and so-on. Not so complicated! ðŸ™‚

The math for finding the coordinates of a space in a specific direction from a starting-space is still slightly more complex than normal square boards because the calculation is different based on which row you start in. To completely remove the necessity for doing these calculations more than once, I started using helper functions to help get a piece in any direction or to get a collection of all adjacent spaces.

As you might be aware, Proximity is Open Source, so you can check out exactly how we handled things.

To make things quicker, I’ll post a peek at some of the helper functions we used in Proximity. One quick note: this code forces all pieces to have positive-integer coordinates because the board for Proximity is a predetermined size. Since Hive is a bit more dynamic, that game doesn’t have those restrictions. Fortunately, this coordinate system still works fine with negative coordinates.

Here is the helper-code for Proximity (in javascript):

[crayon lang=”js”]

/***** DIRECTIONAL HELPER FUNCTIONS *****/

this.leftOf = function( row, col ) { return new Proximity.Coords( row, col-1 ); }

this.topOf = function( row, col ) { return new Proximity.Coords( row-2, col); } // need to jump two rows in the array to work visually

this.rightOf = function( row, col ) { return new Proximity.Coords( row, col+1); }

this.bottomOf = function( row, col ) { return new Proximity.Coords( row+2, col); }

this.topLeftOf = function( row, col ) {

var coords;

if( row % 2 == 0 ){

coords = new Proximity.Coords( row-1, col-1 );

} else {

coords = new Proximity.Coords( row-1, col );

}

return coords;

}

this.topRightOf = function( row, col ) {

var coords;

if( row % 2 == 0 ){

coords = new Proximity.Coords( row-1, col );

} else {

coords = new Proximity.Coords( row-1, col+1 );

}

return coords;

}

this.bottomLeftOf = function( row, col ) {

var coords;

if( row % 2 == 0 ){

coords = new Proximity.Coords( row+1, col-1 );

} else {

coords = new Proximity.Coords( row+1, col );

}

return coords;

}

this.bottomRightOf = function( row, col ) {

var coords;

if( row % 2 == 0 ){

coords = new Proximity.Coords( row+1, col );

} else {

coords = new Proximity.Coords( row+1, col+1 );

}

return coords;

}

/**

* Returns an array of all of the coordinates surrounding the given coordinates.

*/

this.getSurroundingCoords = function( row, col ){

var allSurroundingCoords = [

self.topLeftOf(row,col),

self.topOf(row,col),

self.topRightOf(row,col),

self.bottomRightOf(row,col),

self.bottomOf(row,col),

self.bottomLeftOf(row,col),

];

// Only return coordinates which are on the board (not off the edge).

var validSurroundingCoords = [];

for(var index in allSurroundingCoords){

var coords = allSurroundingCoords[index];

if((coords.row >= 0) && (coords.col >= 0)

&& (coords.row < self.getNumRows()) && (coords.col < self.getNumCols())){
validSurroundingCoords.push( coords );
}
}
return validSurroundingCoords;
};
[/crayon]