Current section

Files

Jump to
gchess src board.erl
Raw

src/board.erl

-module(board).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([get_positions_inner/2, get_positions/1, get_all_positions/1, from_position/1, set_piece_at_position/3, get_piece_at_position/2, remove_piece_at_position/2]).
-export_type([board_bb/0]).
-type board_bb() :: {board_bb,
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
integer()}.
-spec get_positions_inner(integer(), integer()) -> {ok,
list(position:position())} |
{error, binary()}.
get_positions_inner(Bitboard, Count) ->
case Count < 0 of
true ->
{ok, []};
false ->
Just_first_bit_of_bb = bitboard:'and'(
Bitboard,
bitboard:new_bitboard(16#8000000000000000)
),
case Just_first_bit_of_bb of
0 ->
get_positions_inner(
bitboard:shift_left(Bitboard, 1),
Count - 1
);
_ ->
gleam@result:'try'(
position:from_int(Count),
fun(Position_dest) ->
gleam@result:'try'(
get_positions_inner(
bitboard:shift_left(Bitboard, 1),
Count - 1
),
fun(Positions_inner) ->
{ok, [Position_dest | Positions_inner]}
end
)
end
)
end
end.
-spec get_positions(integer()) -> {ok, list(position:position())} |
{error, binary()}.
get_positions(Bitboard) ->
Positions = [],
case Bitboard of
0 ->
{ok, Positions};
_ ->
Count = 63,
Just_first_bit_of_bb = bitboard:'and'(
Bitboard,
bitboard:new_bitboard(16#8000000000000000)
),
case Just_first_bit_of_bb of
0 ->
get_positions_inner(
bitboard:shift_left(Bitboard, 1),
Count - 1
);
_ ->
gleam@result:'try'(
position:from_int(Count),
fun(Position_dest) ->
gleam@result:'try'(
get_positions_inner(
bitboard:shift_left(Bitboard, 1),
Count - 1
),
fun(Positions_inner) ->
{ok, [Position_dest | Positions_inner]}
end
)
end
)
end
end.
-spec get_all_positions(board_bb()) -> {ok, list(position:position())} |
{error, any()}.
get_all_positions(Board) ->
List_of_bitboards = [erlang:element(2, Board),
erlang:element(3, Board),
erlang:element(4, Board),
erlang:element(5, Board),
erlang:element(6, Board),
erlang:element(7, Board),
erlang:element(8, Board),
erlang:element(9, Board),
erlang:element(10, Board),
erlang:element(11, Board),
erlang:element(12, Board),
erlang:element(13, Board)],
Positions@3 = gleam@list:fold(
List_of_bitboards,
gleam@set:new(),
fun(Acc, Bitboard) ->
Positions@1 = case get_positions(Bitboard) of
{ok, Positions} ->
Positions;
{error, _} ->
[]
end,
Positions@2 = gleam@set:from_list(Positions@1),
gleam@set:union(Acc, Positions@2)
end
),
{ok, gleam@set:to_list(Positions@3)}.
-spec from_position(position:position()) -> integer().
from_position(Position) ->
Bitboard = bitboard:shift_left(
bitboard:new_bitboard(1),
position:to_int(Position)
),
Bitboard.
-spec set_piece_at_position(board_bb(), position:position(), piece:piece()) -> board_bb().
set_piece_at_position(Board, Position, Piece) ->
Bitboard = from_position(Position),
New_board = case Piece of
{piece, Color, Kind} when (Color =:= white) andalso (Kind =:= king) ->
erlang:setelement(
8,
Board,
bitboard:'or'(Bitboard, erlang:element(8, Board))
);
{piece, Color@1, Kind@1} when (Color@1 =:= white) andalso (Kind@1 =:= queen) ->
erlang:setelement(
9,
Board,
bitboard:'or'(Bitboard, erlang:element(9, Board))
);
{piece, Color@2, Kind@2} when (Color@2 =:= white) andalso (Kind@2 =:= rook) ->
erlang:setelement(
10,
Board,
bitboard:'or'(Bitboard, erlang:element(10, Board))
);
{piece, Color@3, Kind@3} when (Color@3 =:= white) andalso (Kind@3 =:= bishop) ->
erlang:setelement(
11,
Board,
bitboard:'or'(Bitboard, erlang:element(11, Board))
);
{piece, Color@4, Kind@4} when (Color@4 =:= white) andalso (Kind@4 =:= knight) ->
erlang:setelement(
12,
Board,
bitboard:'or'(Bitboard, erlang:element(12, Board))
);
{piece, Color@5, Kind@5} when (Color@5 =:= white) andalso (Kind@5 =:= pawn) ->
erlang:setelement(
13,
Board,
bitboard:'or'(Bitboard, erlang:element(13, Board))
);
{piece, Color@6, Kind@6} when (Color@6 =:= black) andalso (Kind@6 =:= king) ->
erlang:setelement(
2,
Board,
bitboard:'or'(Bitboard, erlang:element(2, Board))
);
{piece, Color@7, Kind@7} when (Color@7 =:= black) andalso (Kind@7 =:= queen) ->
erlang:setelement(
3,
Board,
bitboard:'or'(Bitboard, erlang:element(3, Board))
);
{piece, Color@8, Kind@8} when (Color@8 =:= black) andalso (Kind@8 =:= rook) ->
erlang:setelement(
4,
Board,
bitboard:'or'(Bitboard, erlang:element(4, Board))
);
{piece, Color@9, Kind@9} when (Color@9 =:= black) andalso (Kind@9 =:= bishop) ->
erlang:setelement(
5,
Board,
bitboard:'or'(Bitboard, erlang:element(5, Board))
);
{piece, Color@10, Kind@10} when (Color@10 =:= black) andalso (Kind@10 =:= knight) ->
erlang:setelement(
6,
Board,
bitboard:'or'(Bitboard, erlang:element(6, Board))
);
{piece, Color@11, Kind@11} when (Color@11 =:= black) andalso (Kind@11 =:= pawn) ->
erlang:setelement(
7,
Board,
bitboard:'or'(Bitboard, erlang:element(7, Board))
);
_ ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid piece"/utf8>>,
module => <<"board"/utf8>>,
function => <<"set_piece_at_position"/utf8>>,
line => 268})
end,
New_board.
-spec get_piece_at_position(board_bb(), position:position()) -> gleam@option:option(piece:piece()).
get_piece_at_position(Board, Position) ->
Bitboard = from_position(Position),
Black_king_bb_compare = bitboard:'and'(erlang:element(2, Board), Bitboard),
Black_queen_bb_compare = bitboard:'and'(erlang:element(3, Board), Bitboard),
Black_rook_bb_compare = bitboard:'and'(erlang:element(4, Board), Bitboard),
Black_bishop_bb_compare = bitboard:'and'(erlang:element(5, Board), Bitboard),
Black_knight_bb_compare = bitboard:'and'(erlang:element(6, Board), Bitboard),
Black_pawns_bb_compare = bitboard:'and'(erlang:element(7, Board), Bitboard),
White_king_bb_compare = bitboard:'and'(erlang:element(8, Board), Bitboard),
White_queen_bb_compare = bitboard:'and'(erlang:element(9, Board), Bitboard),
White_rook_bb_compare = bitboard:'and'(erlang:element(10, Board), Bitboard),
White_bishop_bb_compare = bitboard:'and'(
erlang:element(11, Board),
Bitboard
),
White_knight_bb_compare = bitboard:'and'(
erlang:element(12, Board),
Bitboard
),
White_pawns_bb_compare = bitboard:'and'(erlang:element(13, Board), Bitboard),
Piece@1 = case Bitboard of
0 ->
none;
_ ->
Piece = case Bitboard of
_ when Bitboard =:= Black_king_bb_compare ->
{some, {piece, black, king}};
_ when Bitboard =:= Black_queen_bb_compare ->
{some, {piece, black, queen}};
_ when Bitboard =:= Black_rook_bb_compare ->
{some, {piece, black, rook}};
_ when Bitboard =:= Black_bishop_bb_compare ->
{some, {piece, black, bishop}};
_ when Bitboard =:= Black_knight_bb_compare ->
{some, {piece, black, knight}};
_ when Bitboard =:= Black_pawns_bb_compare ->
{some, {piece, black, pawn}};
_ when Bitboard =:= White_king_bb_compare ->
{some, {piece, white, king}};
_ when Bitboard =:= White_queen_bb_compare ->
{some, {piece, white, queen}};
_ when Bitboard =:= White_rook_bb_compare ->
{some, {piece, white, rook}};
_ when Bitboard =:= White_bishop_bb_compare ->
{some, {piece, white, bishop}};
_ when Bitboard =:= White_knight_bb_compare ->
{some, {piece, white, knight}};
_ when Bitboard =:= White_pawns_bb_compare ->
{some, {piece, white, pawn}};
_ ->
none
end,
Piece
end,
Piece@1.
-spec remove_piece_at_position(board_bb(), position:position()) -> {ok,
board_bb()} |
{error, binary()}.
remove_piece_at_position(Board, Position) ->
Bitboard = bitboard:'not'(from_position(Position)),
New_board = case get_piece_at_position(Board, Position) of
none ->
{error, <<"No piece at position"/utf8>>};
{some, {piece, Color, Kind}} when (Color =:= white) andalso (Kind =:= king) ->
{ok,
erlang:setelement(
8,
Board,
bitboard:'and'(Bitboard, erlang:element(8, Board))
)};
{some, {piece, Color@1, Kind@1}} when (Color@1 =:= white) andalso (Kind@1 =:= queen) ->
{ok,
erlang:setelement(
9,
Board,
bitboard:'and'(Bitboard, erlang:element(9, Board))
)};
{some, {piece, Color@2, Kind@2}} when (Color@2 =:= white) andalso (Kind@2 =:= rook) ->
{ok,
erlang:setelement(
10,
Board,
bitboard:'and'(Bitboard, erlang:element(10, Board))
)};
{some, {piece, Color@3, Kind@3}} when (Color@3 =:= white) andalso (Kind@3 =:= bishop) ->
{ok,
erlang:setelement(
11,
Board,
bitboard:'and'(Bitboard, erlang:element(11, Board))
)};
{some, {piece, Color@4, Kind@4}} when (Color@4 =:= white) andalso (Kind@4 =:= knight) ->
{ok,
erlang:setelement(
12,
Board,
bitboard:'and'(Bitboard, erlang:element(12, Board))
)};
{some, {piece, Color@5, Kind@5}} when (Color@5 =:= white) andalso (Kind@5 =:= pawn) ->
{ok,
erlang:setelement(
13,
Board,
bitboard:'and'(Bitboard, erlang:element(13, Board))
)};
{some, {piece, Color@6, Kind@6}} when (Color@6 =:= black) andalso (Kind@6 =:= king) ->
{ok,
erlang:setelement(
2,
Board,
bitboard:'and'(Bitboard, erlang:element(2, Board))
)};
{some, {piece, Color@7, Kind@7}} when (Color@7 =:= black) andalso (Kind@7 =:= queen) ->
{ok,
erlang:setelement(
3,
Board,
bitboard:'and'(Bitboard, erlang:element(3, Board))
)};
{some, {piece, Color@8, Kind@8}} when (Color@8 =:= black) andalso (Kind@8 =:= rook) ->
{ok,
erlang:setelement(
4,
Board,
bitboard:'and'(Bitboard, erlang:element(4, Board))
)};
{some, {piece, Color@9, Kind@9}} when (Color@9 =:= black) andalso (Kind@9 =:= bishop) ->
{ok,
erlang:setelement(
5,
Board,
bitboard:'and'(Bitboard, erlang:element(5, Board))
)};
{some, {piece, Color@10, Kind@10}} when (Color@10 =:= black) andalso (Kind@10 =:= knight) ->
{ok,
erlang:setelement(
6,
Board,
bitboard:'and'(Bitboard, erlang:element(6, Board))
)};
{some, {piece, Color@11, Kind@11}} when (Color@11 =:= black) andalso (Kind@11 =:= pawn) ->
{ok,
erlang:setelement(
7,
Board,
bitboard:'and'(Bitboard, erlang:element(7, Board))
)};
_ ->
erlang:error(#{gleam_error => panic,
message => <<"Invalid piece"/utf8>>,
module => <<"board"/utf8>>,
function => <<"remove_piece_at_position"/utf8>>,
line => 169})
end,
New_board.