I am struggling to find an efficient way of calculating a 64-bit representation of a square's diagonals.
The game in question is a board game called Othello or Reversi. I am currently working on a method to determine the stability of a piece. A stable piece can be defined as a piece which cannot be flipped. The current problem I'm working on can be defined by: "a piece cannot be flipped if all squares in all four directions are occupied."
Thus, for example, the piece labelled A cannot be captured if the board looks as follows:
/* 1 2 3 4 5 6 7 8
* 1 . . x . . . x .
* 2 . . x . . x . .
* 3 x . x . x . . .
* 4 . x x x . . . .
* 5 x x A x x x x x
* 6 . x x x . . . .
* 7 x . x . x . . .
* 8 . . x . . x . .
*/
Where x denotes that there exists a piece in that posistion (regardless of its colour). Because the piece is surrounded by pieces in all directions it cannot be captured.
The vertical lines are easy to calculate. In a nested for-loop of 8x8, the next vertical line can be found by ver0 >> j, while the next horizontal line can be found by hor0 >> i*8.
const unsigned long long hor0 = 255ULL;
const unsigned long long ver0 = 72340172838076673ULL;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
currHor = hor0 << i;
currVer = ver0 << j;
}
}
As a visual example, hor0 looks like:
/* 1 2 3 4 5 6 7 8
* 1 x x x x x x x x
* 2 . . . . . . . .
* 3 . . . . . . . .
* 4 . . . . . . . .
* 5 . . . . . . . .
* 6 . . . . . . . .
* 7 . . . . . . . .
* 8 . . . . . . . .
*/
so a shift by 8 would move the line down by one.
ver0 looks like:
/* 1 2 3 4 5 6 7 8
* 1 x . . . . . . .
* 2 x . . . . . . .
* 3 x . . . . . . .
* 4 x . . . . . . .
* 5 x . . . . . . .
* 6 x . . . . . . .
* 7 x . . . . . . .
* 8 x . . . . . . .
*/
So a shift by one would move the line right by one.
To find their combined cursor I simply OR the results:
currCursor = (currHor | currVer);
Now the real problem starts. In order to determine stability, I need all four directions. I'm not sure how to calculate the diagonal lines feasibly with only the (i, j) position.
My first attempt was to use bit shifts. This failed horribly as the shifts resulted in mirroring when I don't want garbage bits.
My second attempt was to simply place all of the diagonal lines in an array and use the indexes to find the corresponding line. The array is quite big but here is an example of how some of the elements look (only the left diagonals):
const unsigned long long rightDiagonals[15] = { \
9241421688590303745ULL, \
/* 1 2 3 4 5 6 7 8
* 1 x . . . . . . .
* 2 . x . . . . . .
* 3 . . x . . . . .
* 4 . . . x . . . .
* 5 . . . . x . . .
* 6 . . . . . x . .
* 7 . . . . . . x .
* 8 . . . . . . . x
* [0] //This is the index in the array.
*/
36099303471055874ULL, \
/* 1 2 3 4 5 6 7 8
* 1 . x . . . . . .
* 2 . . x . . . . .
* 3 . . . x . . . .
* 4 . . . . x . . .
* 5 . . . . . x . .
* 6 . . . . . . x .
* 7 . . . . . . . x
* 8 . . . . . . . .
* [1]
*/
...
144396663052566528ULL, \
/* 1 2 3 4 5 6 7 8
* 1 . . . . . . . .
* 2 . . . . . . . .
* 3 . . . . . . . .
* 4 . . . . . . . .
* 5 . . . . . . . .
* 6 . . . . . . . .
* 7 x . . . . . . .
* 8 . x . . . . . .
* [13]
*/
72057594037927936ULL}
/* 1 2 3 4 5 6 7 8
* 1 . . . . . . . .
* 2 . . . . . . . .
* 3 . . . . . . . .
* 4 . . . . . . . .
* 5 . . . . . . . .
* 6 . . . . . . . .
* 7 . . . . . . . .
* 8 x . . . . . . .
* [14]
*/
I don't know how to match the index of the array with the (i, j) index. For example, if a square is on the index (2, 1), the corresponding index should be [1] in the array. But if a square is on (3, 2) the index is the array should also be [1]. And if a square is on (1,1), ... (7, 7), (8, 8), the index should be [0].
I can't determine a way to easily find the line. One thing I thought of is to get the 64-bit representation of the current square and OR it with the intersection of two lines. The problem is that this would require a for loop and this operation will be executed thousands of times, which is computationally not optimal.
Does anybody know of a way to compute diagonals from a single square or a method to calculate the corresponding index in the array of diagonals?
Your help is greatly appreciated.