These new versions of listMoves() depart somewhat from the original Fhourstones code. Perhaps the ideas included are worth exploring.
// this version is same speed as original (it just uses a couple more bitboard ideas)
int[] listMoves() {
int[] moves;
long TOP = 0b0100000_0100000_0100000_0100000_0100000_0100000_0100000L; // top playable row
long bb = bitboard[0] | bitboard[1]; // combine both players
for(int col = 0; col <= 6; col++) {
if ((bb & 0b0100000) == 0) moves.push(col); // check single column
bb >>= 7; // shift next column into left-most position
}
return moves;
}
// this version is slower in the worst case (but potentially much faster on larger boards with many full columns)
int[] listMoves() {
int[] moves;
long TOP = 0b0100000_0100000_0100000_0100000_0100000_0100000_0100000L; // top playable row
long bb = bitboard[0] | bitboard[1]; // combine both players
bb ~= bb; // invert bits (0 for piece, 1 for empty)
bb &= TOP; // mask player pieces with TOP row bits
bb >>= 5; // bring top row bits to bottom row
while(bb != 0) { // loop over bits (not columns)
int index = numberOfTrailingZeros(bb); // count zeros before first set bit (e.g. __builtin_ctzll)
moves.push(index / 7); // convert index to column number
bb &= bb - 1; // clear first set bit (e.g. 0b11100 - 1 == 0b11011)
}
return moves;
}
// same but four lines written as one line
int[] listMoves() {
int[] moves;
long TOP = 0b0100000_0100000_0100000_0100000_0100000_0100000_0100000L; // top playable row
long bb = (~(bitboard[0] | bitboard[1]) & TOP) >> 5; // combine, invert, mask, shift
while(bb != 0) { // loop over bits (not columns)
int index = numberOfTrailingZeros(bb); // count zeros before first set bit (e.g. __builtin_ctzll)
moves.push(index / 7); // convert index to column number
bb &= bb - 1; // clear first set bit (e.g. 0b11100 - 1 == 0b11011)
}
return moves;
}
These new versions of listMoves() depart somewhat from the original Fhourstones code. Perhaps the ideas included are worth exploring.