bibi/bitboard
The bibi/bitboard module provides the ability to create and manipulate bitboards. Bitboards have a defined width and height, and an integer that represents the state of the bitboard when in binary
Suppose you are representing a game of tic-tac-toe that looks like
X | O | _
- + - + -
O | X | _
- + - + -
O | _ | X
Representing the X’s as a bitboard, it would look like
100
010
001
In binary, this would be 001010100
, which translates to 84
Notice that the positions of the 1’s when the bitboard is translated into its binary integer format
The following diagram shows how the individual bits are ordered from right to left
6 7 8
3 4 5
0 1 2
To disambiguate between the bitwise shift operations in the int
modules and bitboard shifts
we use cardinal directions when describing and manipulating bitboards.
north
000
west 000 east
000
south
Types
Functions
pub fn antidiagonal(
bitboard: Bitboard,
antidiagonal_no: Int,
) -> Result(Bitboard, String)
Antidiagonals are made up of squares that touch at thr corners, and stretch from the south eastern corner and towards the north western corner.
In rectangular bitboards, the anti-diagonals will appear as follows
1000
0100
0010
Antidiagonals are indexed in the rank + file
. In a bitboard of width 3 and
height 4, the anti-diagonals will be indexed as
. . 5
. . 4
. . 3
0 1 2
A anti-diagonal of index 3 in the above bitboard will look like this
100
010
001
000
pub fn bitboard_and(
bitboard_1: Bitboard,
bitboard_2: Bitboard,
) -> Result(Bitboard, String)
Perfroms the and
operation on two bitboards and returns a new bitboard.
If a square is occupied on both bitboards, it will be occupied in the
resulting bitboard. Both bitboards must have the same width and height.
010 000 000
010 and 111 --> 010
010 000 000
pub fn bitboard_not(bitboard: Bitboard) -> Bitboard
Performs the not
operation on a bitboard. All occupied squares will become unoccupied,
and vice versa.
i.e.
010 101
101 -> 010
010 101
pub fn bitboard_or(
bitboard_1: Bitboard,
bitboard_2: Bitboard,
) -> Result(Bitboard, String)
Perfroms the or
operation on two bitboards and returns a new bitboard.
If a square is occupied on both bitboards, it will be occupied in the
resulting bitboard. Both bitboards must have the same width and height.
010 000 010
010 and 111 --> 111
010 000 010
pub fn bitboard_xor(
bitboard_1: Bitboard,
bitboard_2: Bitboard,
) -> Result(Bitboard, String)
Perfroms the xor
operation on two bitboards and returns a new bitboard.
If a square is occupied only on on of the two bitboards, it will be occupied in the
resulting bitboard. Both bitboards must have the same width and height.
010 000 010
010 and 111 --> 101
010 000 010
pub fn diagonal(
bitboard: Bitboard,
diagonal_no: Int,
) -> Result(Bitboard, String)
Diagonals are made up of squares that touch at thr corners, and stretch from the south eastern corner and towards the north western corner.
In rectangular bitboards, the diagonals will appear as follows
0010
0100
1000
Diagonals are indexed in the width + rank - file
. In a bitboard of width 3 and
height 4, the diagonals will be indexed as
5 . .
4 . .
3 . .
2 1 0
A diagonal of index 3 in the above bitboard will look like this
001
010
100
000
pub fn file(
bitboard: Bitboard,
file_no: Int,
) -> Result(Bitboard, String)
Returns a bitboard with the nth file occupied of the provided bitboard Files are indexed from 0 to width - 1, and start from the west side of the board
i.e.
010
file(Bitboard(3, 3, 1)) --> 010
010
pub fn flip_horizontally(bitboard: Bitboard) -> Bitboard
Flips a bitboard horizontally
i.e
100 001
100 -> 001
100 001
pub fn flip_vertically(bitboard: Bitboard) -> Bitboard
Flips a bitboard vertically
i.e
111 000
000 -> 000
000 111
pub fn from_base2(
width: Int,
height: Int,
bits: String,
) -> Result(Bitboard, String)
Create a bitboard of a given width and height, and a binary string
i.e.
from_base2(3, 3, "000000111")
–> Bitboard(width: 3, height: 3, val: 7)
pub fn from_coords(
width: Int,
height: Int,
coords: Coords,
) -> Result(Bitboard, String)
Create a bitboard of a given width and height, and a Coords
i.e.
from_coords(3, 3, Coords(0, 0))
–> Bitboard(width: 3, height: 3, val: 1)
pub fn from_list_of_coords(
width: Int,
height: Int,
coords_list: List(Coords),
) -> Result(Bitboard, String)
Create a bitboard of a given width and height, and a list of Coords
i.e.
from_coords(3, 3, [Coords(0, 0), Coords(1, 0)])
–> Bitboard(width: 3, height: 3, val: 3)
pub fn from_square(
width: Int,
height: Int,
square: Int,
) -> Result(Bitboard, String)
Create a bitboard of a given with and height, and the nth square
i.e. from_square(3, 3, 1)
–> Bitboard(width: 3, height: 3, val: 2)
Squares are indexed from bottom left to top right. A 3 by 3 bitboard will be indexed as follows
6 7 8
3 4 5
0 1 2
pub fn full_mask(b: Bitboard) -> Bitboard
This returns a bitboard that is fully occupied
i.e.
111
full_mask(Bitboard(3, 3, 1)) --> 111
111
pub fn new(width: Int, height: Int) -> Result(Bitboard, String)
Create an empty bitboard of a given width and height
pub fn rank(
bitboard: Bitboard,
rank_no: Int,
) -> Result(Bitboard, String)
Returns a bitboard with the nth rank occupied of the provided bitboard. Ranks are indexed from 0 to height - 1, and start from the north side of the board.
i.e.
000
rank(Bitboard(3, 3, 1)) --> 111
000
pub fn shift_east(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire board towards the east by i
. Note that eastwards
shifts will result in eastmost occupied squares to be removed completely
i.e. shift_east by 1
111 011
000 -> 000
000 000
pub fn shift_north(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire board towards the north by i
i.e. shift_north by 1
100 100
100 -> 100
100 000
pub fn shift_northeast(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire boards towards the northeast by i
.
i.e. shift_northeast by 1
001 001
011 -> 000
000 000
pub fn shift_northwest(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire boards towards the northwest by i
.
i.e. shift_northwest by 1
001 110
011 -> 000
000 000
pub fn shift_south(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire board towards the south by i
i.e. shift_south by 1
100 000
100 -> 100
100 100
pub fn shift_southeast(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire boards towards the southeast by i
.
i.e. shift_southeast by 1
001 000
011 -> 000
000 001
pub fn shift_southwest(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire boards towards the southwest by i
.
i.e. shift_southwest by 1
001 000
011 -> 010
000 110
pub fn shift_west(
bitboard: Bitboard,
by i: Int,
) -> Result(Bitboard, String)
Shifts the entire board towards the west by i
. Note that westwards
shifts will result in westmost occupied squares to be removed completely
i.e. shift_west by 1
111 110
000 -> 000
000 000
pub fn to_bools(b: Bitboard) -> List(Bool)
Convers a bitboard into a list of booleans representing where a square is occupied
i.e
to_bools(Bitboard(width: 3, height: 3, val: 3))
–> [True, True, False,... ]
(False repeats 7 times in this example)
pub fn to_squares(b: Bitboard) -> List(Int)
Converts a bitboard into a list of integers representing where a square is occupied
i.e to_squares(Bitboard(width: 3, height: 3, val: 3))
–> [0, 1]