-module(game). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([to_fen/1, new_game_without_status/0, new_game/0, from_fen_string/1, apply_move_raw/2, disable_status/1, undo_move/1, print_board/1, print_board_from_fen/1, all_legal_moves/1, apply_move/2, apply_move_san_string/2, load_pgn/1, apply_move_uci/2]). -export_type([game/0]). -type game() :: {game, board:board_bb(), color:color(), list(move:move_with_capture()), gleam@option:option(status:status()), integer(), castle_rights:castle_rights(), castle_rights:castle_rights(), castle_rights:castle_rights(), castle_rights:castle_rights(), gleam@option:option(position:position())}. -spec to_fen(game()) -> binary(). to_fen(Game) -> Halfmove@1 = case erlang:element(5, Game) of none -> 0; {some, {in_progress, Halfmove, _}} -> Halfmove; {some, {draw, _}} -> 0; {some, _} -> 0 end, Game_fen = {fen, erlang:element(2, Game), erlang:element(3, Game), {castling_status, castle_rights:to_bool(erlang:element(7, Game)), castle_rights:to_bool(erlang:element(8, Game)), castle_rights:to_bool(erlang:element(9, Game)), castle_rights:to_bool(erlang:element(10, Game))}, erlang:element(11, Game), Halfmove@1, (erlang:element(6, Game) div 2) + 1}, fen:to_string(Game_fen). -spec new_game_without_status() -> game(). new_game_without_status() -> White_king_bitboard = 2#0000000000000000000000000000000000000000000000000000000000001000, White_queen_bitboard = 2#0000000000000000000000000000000000000000000000000000000000010000, White_rook_bitboard = 2#0000000000000000000000000000000000000000000000000000000010000001, White_bishop_bitboard = 2#0000000000000000000000000000000000000000000000000000000000100100, White_knight_bitboard = 2#0000000000000000000000000000000000000000000000000000000001000010, White_pawns_bitboard = 2#0000000000000000000000000000000000000000000000001111111100000000, Black_king_bitboard = 2#0000100000000000000000000000000000000000000000000000000000000000, Black_queen_bitboard = 2#0001000000000000000000000000000000000000000000000000000000000000, Black_rook_bitboard = 2#1000000100000000000000000000000000000000000000000000000000000000, Black_bishop_bitboard = 2#0010010000000000000000000000000000000000000000000000000000000000, Black_knight_bitboard = 2#0100001000000000000000000000000000000000000000000000000000000000, Black_pawns_bitboard = 2#0000000011111111000000000000000000000000000000000000000000000000, Board = {board_bb, Black_king_bitboard, Black_queen_bitboard, Black_rook_bitboard, Black_bishop_bitboard, Black_knight_bitboard, Black_pawns_bitboard, White_king_bitboard, White_queen_bitboard, White_rook_bitboard, White_bishop_bitboard, White_knight_bitboard, White_pawns_bitboard}, Turn = white, History = [], Status = none, Ply = 0, {game, Board, Turn, History, Status, Ply, yes, yes, yes, yes, none}. -spec new_game() -> game(). new_game() -> White_king_bitboard = 2#0000000000000000000000000000000000000000000000000000000000010000, White_queen_bitboard = 2#0000000000000000000000000000000000000000000000000000000000001000, White_rook_bitboard = 2#0000000000000000000000000000000000000000000000000000000010000001, White_bishop_bitboard = 2#0000000000000000000000000000000000000000000000000000000000100100, White_knight_bitboard = 2#0000000000000000000000000000000000000000000000000000000001000010, White_pawns_bitboard = 2#0000000000000000000000000000000000000000000000001111111100000000, Black_king_bitboard = 2#0001000000000000000000000000000000000000000000000000000000000000, Black_queen_bitboard = 2#0000100000000000000000000000000000000000000000000000000000000000, Black_rook_bitboard = 2#1000000100000000000000000000000000000000000000000000000000000000, Black_bishop_bitboard = 2#0010010000000000000000000000000000000000000000000000000000000000, Black_knight_bitboard = 2#0100001000000000000000000000000000000000000000000000000000000000, Black_pawns_bitboard = 2#0000000011111111000000000000000000000000000000000000000000000000, Board = {board_bb, Black_king_bitboard, Black_queen_bitboard, Black_rook_bitboard, Black_bishop_bitboard, Black_knight_bitboard, Black_pawns_bitboard, White_king_bitboard, White_queen_bitboard, White_rook_bitboard, White_bishop_bitboard, White_knight_bitboard, White_pawns_bitboard}, Turn = white, History = [], Status = {in_progress, 0, gleam@dict:new()}, Ply = 0, {game, Board, Turn, History, {some, Status}, Ply, yes, yes, yes, yes, none}. -spec from_fen_string(binary()) -> {ok, game()} | {error, any()}. from_fen_string(Fen_string) -> Fen = fen:from_string(Fen_string), Status = {in_progress, erlang:element(6, Fen), gleam@dict:new()}, Ply = case erlang:element(3, Fen) of white -> (erlang:element(7, Fen) - 1) * 2; black -> ((erlang:element(7, Fen) - 1) * 2) + 1 end, White_kingside_castle = case erlang:element(2, erlang:element(4, Fen)) of true -> yes; false -> {no, 1} end, White_queenside_castle = case erlang:element(3, erlang:element(4, Fen)) of true -> yes; false -> {no, 1} end, Black_kingside_castle = case erlang:element(4, erlang:element(4, Fen)) of true -> yes; false -> {no, 2} end, Black_queenside_castle = case erlang:element(5, erlang:element(4, Fen)) of true -> yes; false -> {no, 2} end, {ok, {game, erlang:element(2, Fen), erlang:element(3, Fen), [], {some, Status}, Ply, White_kingside_castle, White_queenside_castle, Black_kingside_castle, Black_queenside_castle, erlang:element(5, Fen)}}. -spec look_up_knight_target_bb(position:position()) -> integer(). look_up_knight_target_bb(Origin_square) -> case Origin_square of {position, a, one} -> 2#0000000000000000000000000000000000000000000000100000010000000000; {position, a, two} -> 2#0000000000000000000000000000000000000010000001000000000000000100; {position, a, three} -> 2#0000000000000000000000000000001000000100000000000000010000000010; {position, a, four} -> 2#0000000000000000000000100000010000000000000001000000001000000000; {position, a, five} -> 2#0000000000000010000001000000000000000100000000100000000000000000; {position, a, six} -> 2#0000001000000100000000000000010000000010000000000000000000000000; {position, a, seven} -> 2#0000010000000000000001000000001000000000000000000000000000000000; {position, a, eight} -> 2#0000000000000100000000100000000000000000000000000000000000000000; {position, b, one} -> 2#0000000000000000000000000000000000000000000001010000100000000000; {position, b, two} -> 2#0000000000000000000000000000000000000101000010000000000000001000; {position, b, three} -> 2#0000000000000000000000000000010100001000000000000000100000000101; {position, b, four} -> 2#0000000000000000000001010000100000000000000010000000010100000000; {position, b, five} -> 2#0000000000000101000010000000000000001000000001010000000000000000; {position, b, six} -> 2#0000010100001000000000000000100000000101000000000000000000000000; {position, b, seven} -> 2#0000100000000000000010000000010100000000000000000000000000000000; {position, b, eight} -> 2#0000000000001000000001010000000000000000000000000000000000000000; {position, c, one} -> 2#0000000000000000000000000000000000000000000010100001000100000000; {position, c, two} -> 2#0000000000000000000000000000000000001010000100010000000000010001; {position, c, three} -> 2#0000000000000000000000000000101000010001000000000001000100001010; {position, c, four} -> 2#0000000000000000000010100001000100000000000100010000101000000000; {position, c, five} -> 2#0000000000001010000100010000000000010001000010100000000000000000; {position, c, six} -> 2#0000101000010001000000000001000100001010000000000000000000000000; {position, c, seven} -> 2#0001000100000000000100010000101000000000000000000000000000000000; {position, c, eight} -> 2#0000000000010001000010100000000000000000000000000000000000000000; {position, d, one} -> 2#0000000000000000000000000000000000000000000101000010001000000000; {position, d, two} -> 2#0000000000000000000000000000000000010100001000100000000000100010; {position, d, three} -> 2#0000000000000000000000000001010000100010000000000010001000010100; {position, d, four} -> 2#0000000000000000000101000010001000000000001000100001010000000000; {position, d, five} -> 2#0000000000010100001000100000000000100010000101000000000000000000; {position, d, six} -> 2#0001010000100010000000000010001000010100000000000000000000000000; {position, d, seven} -> 2#0010001000000000001000100001010000000000000000000000000000000000; {position, d, eight} -> 2#0000000000100010000101000000000000000000000000000000000000000000; {position, e, one} -> 2#0000000000000000000000000000000000000000001010000100010000000000; {position, e, two} -> 2#0000000000000000000000000000000000101000010001000000000001000100; {position, e, three} -> 2#0000000000000000000000000010100001000100000000000100010000101000; {position, e, four} -> 2#0000000000000000001010000100010000000000010001000010100000000000; {position, e, five} -> 2#0000000000101000010001000000000001000100001010000000000000000000; {position, e, six} -> 2#0010100001000100000000000100010000101000000000000000000000000000; {position, e, seven} -> 2#0100010000000000010001000010100000000000000000000000000000000000; {position, e, eight} -> 2#0000000001000100001010000000000000000000000000000000000000000000; {position, f, one} -> 2#0000000000000000000000000000000000000000010100001000100000000000; {position, f, two} -> 2#0000000000000000000000000000000001010000100010000000000010001000; {position, f, three} -> 2#0000000000000000000000000101000010001000000000001000100001010000; {position, f, four} -> 2#0000000000000000010100001000100000000000100010000101000000000000; {position, f, five} -> 2#0000000001010000100010000000000010001000010100000000000000000000; {position, f, six} -> 2#0101000010001000000000001000100001010000000000000000000000000000; {position, f, seven} -> 2#1000100000000000100010000101000000000000000000000000000000000000; {position, f, eight} -> 2#0000000010001000010100000000000000000000000000000000000000000000; {position, g, one} -> 2#0000000000000000000000000000000000000000101000000001000000000000; {position, g, two} -> 2#0000000000000000000000000000000010100000000100000000000000010000; {position, g, three} -> 2#0000000000000000000000001010000000010000000000000001000010100000; {position, g, four} -> 2#0000000000000000101000000001000000000000000100001010000000000000; {position, g, five} -> 2#0000000010100000000100000000000000010000101000000000000000000000; {position, g, six} -> 2#1010000000010000000000000001000010100000000000000000000000000000; {position, g, seven} -> 2#0001000000000000000100001010000000000000000000000000000000000000; {position, g, eight} -> 2#0000000000010000101000000000000000000000000000000000000000000000; {position, h, one} -> 2#0000000000000000000000000000000000000000010000000010000000000000; {position, h, two} -> 2#0000000000000000000000000000000001000000001000000000000000100000; {position, h, three} -> 2#0000000000000000000000000100000000100000000000000010000001000000; {position, h, four} -> 2#0000000000000000010000000010000000000000001000000100000000000000; {position, h, five} -> 2#0000000001000000001000000000000000100000010000000000000000000000; {position, h, six} -> 2#0100000000100000000000000010000001000000000000000000000000000000; {position, h, seven} -> 2#0010000000000000001000000100000000000000000000000000000000000000; {position, h, eight} -> 2#0000000000100000010000000000000000000000000000000000000000000000 end. -spec look_up_east_ray_bb(position:position()) -> integer(). look_up_east_ray_bb(Origin_square) -> case Origin_square of {position, a, one} -> 2#0000000000000000000000000000000000000000000000000000000011111110; {position, a, two} -> 2#0000000000000000000000000000000000000000000000001111111000000000; {position, a, three} -> 2#0000000000000000000000000000000000000000111111100000000000000000; {position, a, four} -> 2#0000000000000000000000000000000011111110000000000000000000000000; {position, a, five} -> 2#0000000000000000000000001111111000000000000000000000000000000000; {position, a, six} -> 2#0000000000000000111111100000000000000000000000000000000000000000; {position, a, seven} -> 2#0000000011111110000000000000000000000000000000000000000000000000; {position, a, eight} -> 2#1111111000000000000000000000000000000000000000000000000000000000; {position, b, one} -> 2#0000000000000000000000000000000000000000000000000000000011111100; {position, b, two} -> 2#0000000000000000000000000000000000000000000000001111110000000000; {position, b, three} -> 2#0000000000000000000000000000000000000000111111000000000000000000; {position, b, four} -> 2#0000000000000000000000000000000011111100000000000000000000000000; {position, b, five} -> 2#0000000000000000000000001111110000000000000000000000000000000000; {position, b, six} -> 2#0000000000000000111111000000000000000000000000000000000000000000; {position, b, seven} -> 2#0000000011111100000000000000000000000000000000000000000000000000; {position, b, eight} -> 2#1111110000000000000000000000000000000000000000000000000000000000; {position, c, one} -> 2#0000000000000000000000000000000000000000000000000000000011111000; {position, c, two} -> 2#0000000000000000000000000000000000000000000000001111100000000000; {position, c, three} -> 2#0000000000000000000000000000000000000000111110000000000000000000; {position, c, four} -> 2#0000000000000000000000000000000011111000000000000000000000000000; {position, c, five} -> 2#0000000000000000000000001111100000000000000000000000000000000000; {position, c, six} -> 2#0000000000000000111110000000000000000000000000000000000000000000; {position, c, seven} -> 2#0000000011111000000000000000000000000000000000000000000000000000; {position, c, eight} -> 2#1111100000000000000000000000000000000000000000000000000000000000; {position, d, one} -> 2#0000000000000000000000000000000000000000000000000000000011110000; {position, d, two} -> 2#0000000000000000000000000000000000000000000000001111000000000000; {position, d, three} -> 2#0000000000000000000000000000000000000000111100000000000000000000; {position, d, four} -> 2#0000000000000000000000000000000011110000000000000000000000000000; {position, d, five} -> 2#0000000000000000000000001111000000000000000000000000000000000000; {position, d, six} -> 2#0000000000000000111100000000000000000000000000000000000000000000; {position, d, seven} -> 2#0000000011110000000000000000000000000000000000000000000000000000; {position, d, eight} -> 2#1111000000000000000000000000000000000000000000000000000000000000; {position, e, one} -> 2#0000000000000000000000000000000000000000000000000000000011100000; {position, e, two} -> 2#0000000000000000000000000000000000000000000000001110000000000000; {position, e, three} -> 2#0000000000000000000000000000000000000000111000000000000000000000; {position, e, four} -> 2#0000000000000000000000000000000011100000000000000000000000000000; {position, e, five} -> 2#0000000000000000000000001110000000000000000000000000000000000000; {position, e, six} -> 2#0000000000000000111000000000000000000000000000000000000000000000; {position, e, seven} -> 2#0000000011100000000000000000000000000000000000000000000000000000; {position, e, eight} -> 2#1110000000000000000000000000000000000000000000000000000000000000; {position, f, one} -> 2#0000000000000000000000000000000000000000000000000000000011000000; {position, f, two} -> 2#0000000000000000000000000000000000000000000000001100000000000000; {position, f, three} -> 2#0000000000000000000000000000000000000000110000000000000000000000; {position, f, four} -> 2#0000000000000000000000000000000011000000000000000000000000000000; {position, f, five} -> 2#0000000000000000000000001100000000000000000000000000000000000000; {position, f, six} -> 2#0000000000000000110000000000000000000000000000000000000000000000; {position, f, seven} -> 2#0000000011000000000000000000000000000000000000000000000000000000; {position, f, eight} -> 2#1100000000000000000000000000000000000000000000000000000000000000; {position, g, one} -> 2#0000000000000000000000000000000000000000000000000000000010000000; {position, g, two} -> 2#0000000000000000000000000000000000000000000000001000000000000000; {position, g, three} -> 2#0000000000000000000000000000000000000000100000000000000000000000; {position, g, four} -> 2#0000000000000000000000000000000010000000000000000000000000000000; {position, g, five} -> 2#0000000000000000000000001000000000000000000000000000000000000000; {position, g, six} -> 2#0000000000000000100000000000000000000000000000000000000000000000; {position, g, seven} -> 2#0000000010000000000000000000000000000000000000000000000000000000; {position, g, eight} -> 2#1000000000000000000000000000000000000000000000000000000000000000; {position, h, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, two} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, three} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, four} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, five} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, six} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, seven} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000 end. -spec look_up_north_ray_bb(position:position()) -> integer(). look_up_north_ray_bb(Origin_square) -> case Origin_square of {position, a, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, seven} -> 2#0000000100000000000000000000000000000000000000000000000000000000; {position, a, six} -> 2#0000000100000001000000000000000000000000000000000000000000000000; {position, a, five} -> 2#0000000100000001000000010000000000000000000000000000000000000000; {position, a, four} -> 2#0000000100000001000000010000000100000000000000000000000000000000; {position, a, three} -> 2#0000000100000001000000010000000100000001000000000000000000000000; {position, a, two} -> 2#0000000100000001000000010000000100000001000000010000000000000000; {position, a, one} -> 2#0000000100000001000000010000000100000001000000010000000100000000; {position, b, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, b, seven} -> 2#0000001000000000000000000000000000000000000000000000000000000000; {position, b, six} -> 2#0000001000000010000000000000000000000000000000000000000000000000; {position, b, five} -> 2#0000001000000010000000100000000000000000000000000000000000000000; {position, b, four} -> 2#0000001000000010000000100000001000000000000000000000000000000000; {position, b, three} -> 2#0000001000000010000000100000001000000010000000000000000000000000; {position, b, two} -> 2#0000001000000010000000100000001000000010000000100000000000000000; {position, b, one} -> 2#0000001000000010000000100000001000000010000000100000001000000000; {position, c, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, c, seven} -> 2#0000010000000000000000000000000000000000000000000000000000000000; {position, c, six} -> 2#0000010000000100000000000000000000000000000000000000000000000000; {position, c, five} -> 2#0000010000000100000001000000000000000000000000000000000000000000; {position, c, four} -> 2#0000010000000100000001000000010000000000000000000000000000000000; {position, c, three} -> 2#0000010000000100000001000000010000000100000000000000000000000000; {position, c, two} -> 2#0000010000000100000001000000010000000100000001000000000000000000; {position, c, one} -> 2#0000010000000100000001000000010000000100000001000000010000000000; {position, d, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, d, seven} -> 2#0000100000000000000000000000000000000000000000000000000000000000; {position, d, six} -> 2#0000100000001000000000000000000000000000000000000000000000000000; {position, d, five} -> 2#0000100000001000000010000000000000000000000000000000000000000000; {position, d, four} -> 2#0000100000001000000010000000100000000000000000000000000000000000; {position, d, three} -> 2#0000100000001000000010000000100000001000000000000000000000000000; {position, d, two} -> 2#0000100000001000000010000000100000001000000010000000000000000000; {position, d, one} -> 2#0000100000001000000010000000100000001000000010000000100000000000; {position, e, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, e, seven} -> 2#0001000000000000000000000000000000000000000000000000000000000000; {position, e, six} -> 2#0001000000010000000000000000000000000000000000000000000000000000; {position, e, five} -> 2#0001000000010000000100000000000000000000000000000000000000000000; {position, e, four} -> 2#0001000000010000000100000001000000000000000000000000000000000000; {position, e, three} -> 2#0001000000010000000100000001000000010000000000000000000000000000; {position, e, two} -> 2#0001000000010000000100000001000000010000000100000000000000000000; {position, e, one} -> 2#0001000000010000000100000001000000010000000100000001000000000000; {position, f, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, f, seven} -> 2#0010000000000000000000000000000000000000000000000000000000000000; {position, f, six} -> 2#0010000000100000000000000000000000000000000000000000000000000000; {position, f, five} -> 2#0010000000100000001000000000000000000000000000000000000000000000; {position, f, four} -> 2#0010000000100000001000000010000000000000000000000000000000000000; {position, f, three} -> 2#0010000000100000001000000010000000100000000000000000000000000000; {position, f, two} -> 2#0010000000100000001000000010000000100000001000000000000000000000; {position, f, one} -> 2#0010000000100000001000000010000000100000001000000010000000000000; {position, g, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, g, seven} -> 2#0100000000000000000000000000000000000000000000000000000000000000; {position, g, six} -> 2#0100000001000000000000000000000000000000000000000000000000000000; {position, g, five} -> 2#0100000001000000010000000000000000000000000000000000000000000000; {position, g, four} -> 2#0100000001000000010000000100000000000000000000000000000000000000; {position, g, three} -> 2#0100000001000000010000000100000001000000000000000000000000000000; {position, g, two} -> 2#0100000001000000010000000100000001000000010000000000000000000000; {position, g, one} -> 2#0100000001000000010000000100000001000000010000000100000000000000; {position, h, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, seven} -> 2#1000000000000000000000000000000000000000000000000000000000000000; {position, h, six} -> 2#1000000010000000000000000000000000000000000000000000000000000000; {position, h, five} -> 2#1000000010000000100000000000000000000000000000000000000000000000; {position, h, four} -> 2#1000000010000000100000001000000000000000000000000000000000000000; {position, h, three} -> 2#1000000010000000100000001000000010000000000000000000000000000000; {position, h, two} -> 2#1000000010000000100000001000000010000000100000000000000000000000; {position, h, one} -> 2#1000000010000000100000001000000010000000100000001000000000000000 end. -spec look_up_west_ray_bb(position:position()) -> integer(). look_up_west_ray_bb(Origin_square) -> case Origin_square of {position, h, eight} -> 2#0111111100000000000000000000000000000000000000000000000000000000; {position, h, seven} -> 2#0000000001111111000000000000000000000000000000000000000000000000; {position, h, six} -> 2#0000000000000000011111110000000000000000000000000000000000000000; {position, h, five} -> 2#0000000000000000000000000111111100000000000000000000000000000000; {position, h, four} -> 2#0000000000000000000000000000000001111111000000000000000000000000; {position, h, three} -> 2#0000000000000000000000000000000000000000011111110000000000000000; {position, h, two} -> 2#0000000000000000000000000000000000000000000000000111111100000000; {position, h, one} -> 2#0000000000000000000000000000000000000000000000000000000001111111; {position, g, eight} -> 2#0011111100000000000000000000000000000000000000000000000000000000; {position, g, seven} -> 2#0000000000111111000000000000000000000000000000000000000000000000; {position, g, six} -> 2#0000000000000000001111110000000000000000000000000000000000000000; {position, g, five} -> 2#0000000000000000000000000011111100000000000000000000000000000000; {position, g, four} -> 2#0000000000000000000000000000000000111111000000000000000000000000; {position, g, three} -> 2#0000000000000000000000000000000000000000001111110000000000000000; {position, g, two} -> 2#0000000000000000000000000000000000000000000000000011111100000000; {position, g, one} -> 2#0000000000000000000000000000000000000000000000000000000000111111; {position, f, eight} -> 2#0001111100000000000000000000000000000000000000000000000000000000; {position, f, seven} -> 2#0000000000011111000000000000000000000000000000000000000000000000; {position, f, six} -> 2#0000000000000000000111110000000000000000000000000000000000000000; {position, f, five} -> 2#0000000000000000000000000001111100000000000000000000000000000000; {position, f, four} -> 2#0000000000000000000000000000000000011111000000000000000000000000; {position, f, three} -> 2#0000000000000000000000000000000000000000000111110000000000000000; {position, f, two} -> 2#0000000000000000000000000000000000000000000000000001111100000000; {position, f, one} -> 2#0000000000000000000000000000000000000000000000000000000000011111; {position, e, eight} -> 2#0000111100000000000000000000000000000000000000000000000000000000; {position, e, seven} -> 2#0000000000001111000000000000000000000000000000000000000000000000; {position, e, six} -> 2#0000000000000000000011110000000000000000000000000000000000000000; {position, e, five} -> 2#0000000000000000000000000000111100000000000000000000000000000000; {position, e, four} -> 2#0000000000000000000000000000000000001111000000000000000000000000; {position, e, three} -> 2#0000000000000000000000000000000000000000000011110000000000000000; {position, e, two} -> 2#0000000000000000000000000000000000000000000000000000111100000000; {position, e, one} -> 2#0000000000000000000000000000000000000000000000000000000000001111; {position, d, eight} -> 2#0000011100000000000000000000000000000000000000000000000000000000; {position, d, seven} -> 2#0000000000000111000000000000000000000000000000000000000000000000; {position, d, six} -> 2#0000000000000000000001110000000000000000000000000000000000000000; {position, d, five} -> 2#0000000000000000000000000000011100000000000000000000000000000000; {position, d, four} -> 2#0000000000000000000000000000000000000111000000000000000000000000; {position, d, three} -> 2#0000000000000000000000000000000000000000000001110000000000000000; {position, d, two} -> 2#0000000000000000000000000000000000000000000000000000011100000000; {position, d, one} -> 2#0000000000000000000000000000000000000000000000000000000000000111; {position, c, eight} -> 2#0000001100000000000000000000000000000000000000000000000000000000; {position, c, seven} -> 2#0000000000000011000000000000000000000000000000000000000000000000; {position, c, six} -> 2#0000000000000000000000110000000000000000000000000000000000000000; {position, c, five} -> 2#0000000000000000000000000000001100000000000000000000000000000000; {position, c, four} -> 2#0000000000000000000000000000000000000011000000000000000000000000; {position, c, three} -> 2#0000000000000000000000000000000000000000000000110000000000000000; {position, c, two} -> 2#0000000000000000000000000000000000000000000000000000001100000000; {position, c, one} -> 2#0000000000000000000000000000000000000000000000000000000000000011; {position, b, eight} -> 2#0000000100000000000000000000000000000000000000000000000000000000; {position, b, seven} -> 2#0000000000000001000000000000000000000000000000000000000000000000; {position, b, six} -> 2#0000000000000000000000010000000000000000000000000000000000000000; {position, b, five} -> 2#0000000000000000000000000000000100000000000000000000000000000000; {position, b, four} -> 2#0000000000000000000000000000000000000001000000000000000000000000; {position, b, three} -> 2#0000000000000000000000000000000000000000000000010000000000000000; {position, b, two} -> 2#0000000000000000000000000000000000000000000000000000000100000000; {position, b, one} -> 2#0000000000000000000000000000000000000000000000000000000000000001; {position, a, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, seven} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, six} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, five} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, four} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, three} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, two} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000 end. -spec look_up_south_ray_bb(position:position()) -> integer(). look_up_south_ray_bb(Origin_square) -> case Origin_square of {position, a, eight} -> 2#0000000000000001000000010000000100000001000000010000000100000001; {position, a, seven} -> 2#0000000000000000000000010000000100000001000000010000000100000001; {position, a, six} -> 2#0000000000000000000000000000000100000001000000010000000100000001; {position, a, five} -> 2#0000000000000000000000000000000000000001000000010000000100000001; {position, a, four} -> 2#0000000000000000000000000000000000000000000000010000000100000001; {position, a, three} -> 2#0000000000000000000000000000000000000000000000000000000100000001; {position, a, two} -> 2#0000000000000000000000000000000000000000000000000000000000000001; {position, a, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, b, eight} -> 2#0000000000000010000000100000001000000010000000100000001000000010; {position, b, seven} -> 2#0000000000000000000000100000001000000010000000100000001000000010; {position, b, six} -> 2#0000000000000000000000000000001000000010000000100000001000000010; {position, b, five} -> 2#0000000000000000000000000000000000000010000000100000001000000010; {position, b, four} -> 2#0000000000000000000000000000000000000000000000100000001000000010; {position, b, three} -> 2#0000000000000000000000000000000000000000000000000000001000000010; {position, b, two} -> 2#0000000000000000000000000000000000000000000000000000000000000010; {position, b, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, c, eight} -> 2#0000000000000100000001000000010000000100000001000000010000000100; {position, c, seven} -> 2#0000000000000000000001000000010000000100000001000000010000000100; {position, c, six} -> 2#0000000000000000000000000000010000000100000001000000010000000100; {position, c, five} -> 2#0000000000000000000000000000000000000100000001000000010000000100; {position, c, four} -> 2#0000000000000000000000000000000000000000000001000000010000000100; {position, c, three} -> 2#0000000000000000000000000000000000000000000000000000010000000100; {position, c, two} -> 2#0000000000000000000000000000000000000000000000000000000000000100; {position, c, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, d, eight} -> 2#0000000000001000000010000000100000001000000010000000100000001000; {position, d, seven} -> 2#0000000000000000000010000000100000001000000010000000100000001000; {position, d, six} -> 2#0000000000000000000000000000100000001000000010000000100000001000; {position, d, five} -> 2#0000000000000000000000000000000000001000000010000000100000001000; {position, d, four} -> 2#0000000000000000000000000000000000000000000010000000100000001000; {position, d, three} -> 2#0000000000000000000000000000000000000000000000000000100000001000; {position, d, two} -> 2#0000000000000000000000000000000000000000000000000000000000001000; {position, d, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, e, eight} -> 2#0000000000010000000100000001000000010000000100000001000000010000; {position, e, seven} -> 2#0000000000000000000100000001000000010000000100000001000000010000; {position, e, six} -> 2#0000000000000000000000000001000000010000000100000001000000010000; {position, e, five} -> 2#0000000000000000000000000000000000010000000100000001000000010000; {position, e, four} -> 2#0000000000000000000000000000000000000000000100000001000000010000; {position, e, three} -> 2#0000000000000000000000000000000000000000000000000001000000010000; {position, e, two} -> 2#0000000000000000000000000000000000000000000000000000000000010000; {position, e, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, f, eight} -> 2#0000000000100000001000000010000000100000001000000010000000100000; {position, f, seven} -> 2#0000000000000000001000000010000000100000001000000010000000100000; {position, f, six} -> 2#0000000000000000000000000010000000100000001000000010000000100000; {position, f, five} -> 2#0000000000000000000000000000000000100000001000000010000000100000; {position, f, four} -> 2#0000000000000000000000000000000000000000001000000010000000100000; {position, f, three} -> 2#0000000000000000000000000000000000000000000000000010000000100000; {position, f, two} -> 2#0000000000000000000000000000000000000000000000000000000000100000; {position, f, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, g, eight} -> 2#0000000001000000010000000100000001000000010000000100000001000000; {position, g, seven} -> 2#0000000000000000010000000100000001000000010000000100000001000000; {position, g, six} -> 2#0000000000000000000000000100000001000000010000000100000001000000; {position, g, five} -> 2#0000000000000000000000000000000001000000010000000100000001000000; {position, g, four} -> 2#0000000000000000000000000000000000000000010000000100000001000000; {position, g, three} -> 2#0000000000000000000000000000000000000000000000000100000001000000; {position, g, two} -> 2#0000000000000000000000000000000000000000000000000000000001000000; {position, g, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, eight} -> 2#0000000010000000100000001000000010000000100000001000000010000000; {position, h, seven} -> 2#0000000000000000100000001000000010000000100000001000000010000000; {position, h, six} -> 2#0000000000000000000000001000000010000000100000001000000010000000; {position, h, five} -> 2#0000000000000000000000000000000010000000100000001000000010000000; {position, h, four} -> 2#0000000000000000000000000000000000000000100000001000000010000000; {position, h, three} -> 2#0000000000000000000000000000000000000000000000001000000010000000; {position, h, two} -> 2#0000000000000000000000000000000000000000000000000000000010000000; {position, h, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000 end. -spec look_up_south_west_ray_bb(position:position()) -> integer(). look_up_south_west_ray_bb(Origin_square) -> case Origin_square of {position, a, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, seven} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, six} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, five} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, four} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, three} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, two} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, b, eight} -> 2#0000000000000001000000000000000000000000000000000000000000000000; {position, b, seven} -> 2#0000000000000000000000010000000000000000000000000000000000000000; {position, b, six} -> 2#0000000000000000000000000000000100000000000000000000000000000000; {position, b, five} -> 2#0000000000000000000000000000000000000001000000000000000000000000; {position, b, four} -> 2#0000000000000000000000000000000000000000000000010000000000000000; {position, b, three} -> 2#0000000000000000000000000000000000000000000000000000000100000000; {position, b, two} -> 2#0000000000000000000000000000000000000000000000000000000000000001; {position, b, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, c, eight} -> 2#0000000000000010000000010000000000000000000000000000000000000000; {position, c, seven} -> 2#0000000000000000000000100000000100000000000000000000000000000000; {position, c, six} -> 2#0000000000000000000000000000001000000001000000000000000000000000; {position, c, five} -> 2#0000000000000000000000000000000000000010000000010000000000000000; {position, c, four} -> 2#0000000000000000000000000000000000000000000000100000000100000000; {position, c, three} -> 2#0000000000000000000000000000000000000000000000000000001000000001; {position, c, two} -> 2#0000000000000000000000000000000000000000000000000000000000000010; {position, c, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, d, eight} -> 2#0000000000000100000000100000000100000000000000000000000000000000; {position, d, seven} -> 2#0000000000000000000001000000001000000001000000000000000000000000; {position, d, six} -> 2#0000000000000000000000000000010000000010000000010000000000000000; {position, d, five} -> 2#0000000000000000000000000000000000000100000000100000000100000000; {position, d, four} -> 2#0000000000000000000000000000000000000000000001000000001000000001; {position, d, three} -> 2#0000000000000000000000000000000000000000000000000000010000000010; {position, d, two} -> 2#0000000000000000000000000000000000000000000000000000000000000100; {position, d, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, e, eight} -> 2#0000000000001000000001000000001000000001000000000000000000000000; {position, e, seven} -> 2#0000000000000000000010000000010000000010000000010000000000000000; {position, e, six} -> 2#0000000000000000000000000000100000000100000000100000000100000000; {position, e, five} -> 2#0000000000000000000000000000000000001000000001000000001000000001; {position, e, four} -> 2#0000000000000000000000000000000000000000000010000000010000000010; {position, e, three} -> 2#0000000000000000000000000000000000000000000000000000100000000100; {position, e, two} -> 2#0000000000000000000000000000000000000000000000000000000000001000; {position, e, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, f, eight} -> 2#0000000000010000000010000000010000000010000000010000000000000000; {position, f, seven} -> 2#0000000000000000000100000000100000000100000000100000000100000000; {position, f, six} -> 2#0000000000000000000000000001000000001000000001000000001000000001; {position, f, five} -> 2#0000000000000000000000000000000000010000000010000000010000000010; {position, f, four} -> 2#0000000000000000000000000000000000000000000100000000100000000100; {position, f, three} -> 2#0000000000000000000000000000000000000000000000000001000000001000; {position, f, two} -> 2#0000000000000000000000000000000000000000000000000000000000010000; {position, f, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, g, eight} -> 2#0000000000100000000100000000100000000100000000100000000100000000; {position, g, seven} -> 2#0000000000000000001000000001000000001000000001000000001000000001; {position, g, six} -> 2#0000000000000000000000000010000000010000000010000000010000000010; {position, g, five} -> 2#0000000000000000000000000000000000100000000100000000100000000100; {position, g, four} -> 2#0000000000000000000000000000000000000000001000000001000000001000; {position, g, three} -> 2#0000000000000000000000000000000000000000000000000010000000010000; {position, g, two} -> 2#0000000000000000000000000000000000000000000000000000000000100000; {position, g, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, eight} -> 2#0000000001000000001000000001000000001000000001000000001000000001; {position, h, seven} -> 2#0000000000000000010000000010000000010000000010000000010000000010; {position, h, six} -> 2#0000000000000000000000000100000000100000000100000000100000000100; {position, h, five} -> 2#0000000000000000000000000000000001000000001000000001000000001000; {position, h, four} -> 2#0000000000000000000000000000000000000000010000000010000000010000; {position, h, three} -> 2#0000000000000000000000000000000000000000000000000100000000100000; {position, h, two} -> 2#0000000000000000000000000000000000000000000000000000000001000000; {position, h, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000 end. -spec look_up_south_east_ray_bb(position:position()) -> integer(). look_up_south_east_ray_bb(Origin_square) -> case Origin_square of {position, a, eight} -> 2#0000000000000010000001000000100000010000001000000100000010000000; {position, a, seven} -> 2#0000000000000000000000100000010000001000000100000010000001000000; {position, a, six} -> 2#0000000000000000000000000000001000000100000010000001000000100000; {position, a, five} -> 2#0000000000000000000000000000000000000010000001000000100000010000; {position, a, four} -> 2#0000000000000000000000000000000000000000000000100000010000001000; {position, a, three} -> 2#0000000000000000000000000000000000000000000000000000001000000100; {position, a, two} -> 2#0000000000000000000000000000000000000000000000000000000000000010; {position, a, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, b, eight} -> 2#0000000000000100000010000001000000100000010000001000000000000000; {position, b, seven} -> 2#0000000000000000000001000000100000010000001000000100000010000000; {position, b, six} -> 2#0000000000000000000000000000010000001000000100000010000001000000; {position, b, five} -> 2#0000000000000000000000000000000000000100000010000001000000100000; {position, b, four} -> 2#0000000000000000000000000000000000000000000001000000100000010000; {position, b, three} -> 2#0000000000000000000000000000000000000000000000000000010000001000; {position, b, two} -> 2#0000000000000000000000000000000000000000000000000000000000000100; {position, b, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, c, eight} -> 2#0000000000001000000100000010000001000000100000000000000000000000; {position, c, seven} -> 2#0000000000000000000010000001000000100000010000001000000000000000; {position, c, six} -> 2#0000000000000000000000000000100000010000001000000100000010000000; {position, c, five} -> 2#0000000000000000000000000000000000001000000100000010000001000000; {position, c, four} -> 2#0000000000000000000000000000000000000000000010000001000000100000; {position, c, three} -> 2#0000000000000000000000000000000000000000000000000000100000010000; {position, c, two} -> 2#0000000000000000000000000000000000000000000000000000000000001000; {position, c, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, d, eight} -> 2#0000000000010000001000000100000010000000000000000000000000000000; {position, d, seven} -> 2#0000000000000000000100000010000001000000100000000000000000000000; {position, d, six} -> 2#0000000000000000000000000001000000100000010000001000000000000000; {position, d, five} -> 2#0000000000000000000000000000000000010000001000000100000010000000; {position, d, four} -> 2#0000000000000000000000000000000000000000000100000010000001000000; {position, d, three} -> 2#0000000000000000000000000000000000000000000000000001000000100000; {position, d, two} -> 2#0000000000000000000000000000000000000000000000000000000000010000; {position, d, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, e, eight} -> 2#0000000000100000010000001000000000000000000000000000000000000000; {position, e, seven} -> 2#0000000000000000001000000100000010000000000000000000000000000000; {position, e, six} -> 2#0000000000000000000000000010000001000000100000000000000000000000; {position, e, five} -> 2#0000000000000000000000000000000000100000010000001000000000000000; {position, e, four} -> 2#0000000000000000000000000000000000000000001000000100000010000000; {position, e, three} -> 2#0000000000000000000000000000000000000000000000000010000001000000; {position, e, two} -> 2#0000000000000000000000000000000000000000000000000000000000100000; {position, e, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, f, eight} -> 2#0000000001000000100000000000000000000000000000000000000000000000; {position, f, seven} -> 2#0000000000000000010000001000000000000000000000000000000000000000; {position, f, six} -> 2#0000000000000000000000000100000010000000000000000000000000000000; {position, f, five} -> 2#0000000000000000000000000000000001000000100000000000000000000000; {position, f, four} -> 2#0000000000000000000000000000000000000000010000001000000000000000; {position, f, three} -> 2#0000000000000000000000000000000000000000000000000100000010000000; {position, f, two} -> 2#0000000000000000000000000000000000000000000000000000000001000000; {position, f, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, g, eight} -> 2#0000000010000000000000000000000000000000000000000000000000000000; {position, g, seven} -> 2#0000000000000000100000000000000000000000000000000000000000000000; {position, g, six} -> 2#0000000000000000000000001000000000000000000000000000000000000000; {position, g, five} -> 2#0000000000000000000000000000000010000000000000000000000000000000; {position, g, four} -> 2#0000000000000000000000000000000000000000100000000000000000000000; {position, g, three} -> 2#0000000000000000000000000000000000000000000000001000000000000000; {position, g, two} -> 2#0000000000000000000000000000000000000000000000000000000010000000; {position, g, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, seven} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, six} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, five} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, four} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, three} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, two} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000 end. -spec look_up_north_east_ray_bb(position:position()) -> integer(). look_up_north_east_ray_bb(Origin_square) -> case Origin_square of {position, a, one} -> 2#1000000001000000001000000001000000001000000001000000001000000000; {position, a, two} -> 2#0100000000100000000100000000100000000100000000100000000000000000; {position, a, three} -> 2#0010000000010000000010000000010000000010000000000000000000000000; {position, a, four} -> 2#0001000000001000000001000000001000000000000000000000000000000000; {position, a, five} -> 2#0000100000000100000000100000000000000000000000000000000000000000; {position, a, six} -> 2#0000010000000010000000000000000000000000000000000000000000000000; {position, a, seven} -> 2#0000001000000000000000000000000000000000000000000000000000000000; {position, a, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, b, one} -> 2#0000000010000000010000000010000000010000000010000000010000000000; {position, b, two} -> 2#1000000001000000001000000001000000001000000001000000000000000000; {position, b, three} -> 2#0100000000100000000100000000100000000100000000000000000000000000; {position, b, four} -> 2#0010000000010000000010000000010000000000000000000000000000000000; {position, b, five} -> 2#0001000000001000000001000000000000000000000000000000000000000000; {position, b, six} -> 2#0000100000000100000000000000000000000000000000000000000000000000; {position, b, seven} -> 2#0000010000000000000000000000000000000000000000000000000000000000; {position, b, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, c, one} -> 2#0000000000000000100000000100000000100000000100000000100000000000; {position, c, two} -> 2#0000000010000000010000000010000000010000000010000000000000000000; {position, c, three} -> 2#1000000001000000001000000001000000001000000000000000000000000000; {position, c, four} -> 2#0100000000100000000100000000100000000000000000000000000000000000; {position, c, five} -> 2#0010000000010000000010000000000000000000000000000000000000000000; {position, c, six} -> 2#0001000000001000000000000000000000000000000000000000000000000000; {position, c, seven} -> 2#0000100000000000000000000000000000000000000000000000000000000000; {position, c, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, d, one} -> 2#0000000000000000000000001000000001000000001000000001000000000000; {position, d, two} -> 2#0000000000000000100000000100000000100000000100000000000000000000; {position, d, three} -> 2#0000000010000000010000000010000000010000000000000000000000000000; {position, d, four} -> 2#1000000001000000001000000001000000000000000000000000000000000000; {position, d, five} -> 2#0100000000100000000100000000000000000000000000000000000000000000; {position, d, six} -> 2#0010000000010000000000000000000000000000000000000000000000000000; {position, d, seven} -> 2#0001000000000000000000000000000000000000000000000000000000000000; {position, d, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, e, one} -> 2#0000000000000000000000000000000010000000010000000010000000000000; {position, e, two} -> 2#0000000000000000000000001000000001000000001000000000000000000000; {position, e, three} -> 2#0000000000000000100000000100000000100000000000000000000000000000; {position, e, four} -> 2#0000000010000000010000000010000000000000000000000000000000000000; {position, e, five} -> 2#1000000001000000001000000000000000000000000000000000000000000000; {position, e, six} -> 2#0100000000100000000000000000000000000000000000000000000000000000; {position, e, seven} -> 2#0010000000000000000000000000000000000000000000000000000000000000; {position, e, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, f, one} -> 2#0000000000000000000000000000000000000000100000000100000000000000; {position, f, two} -> 2#0000000000000000000000000000000010000000010000000000000000000000; {position, f, three} -> 2#0000000000000000000000001000000001000000000000000000000000000000; {position, f, four} -> 2#0000000000000000100000000100000000000000000000000000000000000000; {position, f, five} -> 2#0000000010000000010000000000000000000000000000000000000000000000; {position, f, six} -> 2#1000000001000000000000000000000000000000000000000000000000000000; {position, f, seven} -> 2#0100000000000000000000000000000000000000000000000000000000000000; {position, f, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, g, one} -> 2#0000000000000000000000000000000000000000000000001000000000000000; {position, g, two} -> 2#0000000000000000000000000000000000000000100000000000000000000000; {position, g, three} -> 2#0000000000000000000000000000000010000000000000000000000000000000; {position, g, four} -> 2#0000000000000000000000001000000000000000000000000000000000000000; {position, g, five} -> 2#0000000000000000100000000000000000000000000000000000000000000000; {position, g, six} -> 2#0000000010000000000000000000000000000000000000000000000000000000; {position, g, seven} -> 2#1000000000000000000000000000000000000000000000000000000000000000; {position, g, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, one} -> 2#0000000000000000000000000000000000000000000000000000000010000000; {position, h, two} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, three} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, four} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, five} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, six} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, seven} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000 end. -spec look_up_north_west_ray_bb(position:position()) -> integer(). look_up_north_west_ray_bb(Origin_square) -> case Origin_square of {position, a, one} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, two} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, three} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, four} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, five} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, six} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, seven} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, a, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, b, one} -> 2#0000000000000000000000000000000000000000000000000000000100000000; {position, b, two} -> 2#0000000000000000000000000000000000000000000000010000000000000000; {position, b, three} -> 2#0000000000000000000000000000000000000001000000000000000000000000; {position, b, four} -> 2#0000000000000000000000000000000100000000000000000000000000000000; {position, b, five} -> 2#0000000000000000000000010000000000000000000000000000000000000000; {position, b, six} -> 2#0000000000000001000000000000000000000000000000000000000000000000; {position, b, seven} -> 2#0000000100000000000000000000000000000000000000000000000000000000; {position, b, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, c, one} -> 2#0000000000000000000000000000000000000000000000010000001000000000; {position, c, two} -> 2#0000000000000000000000000000000000000001000000100000000000000000; {position, c, three} -> 2#0000000000000000000000000000000100000010000000000000000000000000; {position, c, four} -> 2#0000000000000000000000010000001000000000000000000000000000000000; {position, c, five} -> 2#0000000000000001000000100000000000000000000000000000000000000000; {position, c, six} -> 2#0000000100000010000000000000000000000000000000000000000000000000; {position, c, seven} -> 2#0000001000000000000000000000000000000000000000000000000000000000; {position, c, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, d, one} -> 2#0000000000000000000000000000000000000001000000100000010000000000; {position, d, two} -> 2#0000000000000000000000000000000100000010000001000000000000000000; {position, d, three} -> 2#0000000000000000000000010000001000000100000000000000000000000000; {position, d, four} -> 2#0000000000000001000000100000010000000000000000000000000000000000; {position, d, five} -> 2#0000000100000010000001000000000000000000000000000000000000000000; {position, d, six} -> 2#0000001000000100000000000000000000000000000000000000000000000000; {position, d, seven} -> 2#0000010000000000000000000000000000000000000000000000000000000000; {position, d, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, e, one} -> 2#0000000000000000000000000000000100000010000001000000100000000000; {position, e, two} -> 2#0000000000000000000000010000001000000100000010000000000000000000; {position, e, three} -> 2#0000000000000001000000100000010000001000000000000000000000000000; {position, e, four} -> 2#0000000100000010000001000000100000000000000000000000000000000000; {position, e, five} -> 2#0000001000000100000010000000000000000000000000000000000000000000; {position, e, six} -> 2#0000010000001000000000000000000000000000000000000000000000000000; {position, e, seven} -> 2#0000100000000000000000000000000000000000000000000000000000000000; {position, e, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, f, one} -> 2#0000000000000000000000010000001000000100000010000001000000000000; {position, f, two} -> 2#0000000000000001000000100000010000001000000100000000000000000000; {position, f, three} -> 2#0000000100000010000001000000100000010000000000000000000000000000; {position, f, four} -> 2#0000001000000100000010000001000000000000000000000000000000000000; {position, f, five} -> 2#0000010000001000000100000000000000000000000000000000000000000000; {position, f, six} -> 2#0000100000010000000000000000000000000000000000000000000000000000; {position, f, seven} -> 2#0001000000000000000000000000000000000000000000000000000000000000; {position, f, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, g, one} -> 2#0000000000000001000000100000010000001000000100000010000000000000; {position, g, two} -> 2#0000000100000010000001000000100000010000001000000000000000000000; {position, g, three} -> 2#0000001000000100000010000001000000100000000000000000000000000000; {position, g, four} -> 2#0000010000001000000100000010000000000000000000000000000000000000; {position, g, five} -> 2#0000100000010000001000000000000000000000000000000000000000000000; {position, g, six} -> 2#0001000000100000000000000000000000000000000000000000000000000000; {position, g, seven} -> 2#0010000000000000000000000000000000000000000000000000000000000000; {position, g, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000; {position, h, one} -> 2#0000000100000010000001000000100000010000001000000100000000000000; {position, h, two} -> 2#0000001000000100000010000001000000100000010000000000000000000000; {position, h, three} -> 2#0000010000001000000100000010000001000000000000000000000000000000; {position, h, four} -> 2#0000100000010000001000000100000000000000000000000000000000000000; {position, h, five} -> 2#0001000000100000010000000000000000000000000000000000000000000000; {position, h, six} -> 2#0010000001000000000000000000000000000000000000000000000000000000; {position, h, seven} -> 2#0100000000000000000000000000000000000000000000000000000000000000; {position, h, eight} -> 2#0000000000000000000000000000000000000000000000000000000000000000 end. -spec occupied_squares(board:board_bb()) -> integer(). occupied_squares(Board) -> List_of_all_piece_bitboards = [erlang:element(8, Board), erlang:element(9, Board), erlang:element(10, Board), erlang:element(11, Board), erlang:element(12, Board), erlang:element(13, Board), erlang:element(2, Board), erlang:element(3, Board), erlang:element(4, Board), erlang:element(5, Board), erlang:element(6, Board), erlang:element(7, Board)], gleam@list:fold( List_of_all_piece_bitboards, 0, fun(Collector, Next) -> bitboard:'or'(Collector, Next) end ). -spec occupied_squares_white(board:board_bb()) -> integer(). occupied_squares_white(Board) -> List_of_all_piece_bitboards = [erlang:element(8, Board), erlang:element(9, Board), erlang:element(10, Board), erlang:element(11, Board), erlang:element(12, Board), erlang:element(13, Board)], gleam@list:fold( List_of_all_piece_bitboards, 0, fun(Collector, Next) -> bitboard:'or'(Collector, Next) end ). -spec occupied_squares_black(board:board_bb()) -> integer(). occupied_squares_black(Board) -> List_of_all_piece_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)], gleam@list:fold( List_of_all_piece_bitboards, 0, fun(Collector, Next) -> bitboard:'or'(Collector, Next) end ). -spec pawn_squares(color:color(), board:board_bb()) -> integer(). pawn_squares(Color, Board) -> case Color of white -> erlang:element(13, Board); black -> erlang:element(7, Board) end. -spec generate_queen_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_queen_pseudo_legal_move_list(Color, Game) -> Queen_bitboard = case Color of white -> erlang:element(9, erlang:element(2, Game)); black -> erlang:element(3, erlang:element(2, Game)) end, gleam@result:'try'( board:get_positions(Queen_bitboard), fun(Queen_origin_squares) -> gleam@list:fold( Queen_origin_squares, {ok, []}, fun(Collector, Queen_origin_square) -> South_mask_bb = look_up_south_ray_bb(Queen_origin_square), East_mask_bb = look_up_east_ray_bb(Queen_origin_square), North_mask_bb = look_up_north_ray_bb(Queen_origin_square), West_mask_bb = look_up_west_ray_bb(Queen_origin_square), Occupied_squares_bb = occupied_squares( erlang:element(2, Game) ), South_blockers_bb = bitboard:'and'( South_mask_bb, Occupied_squares_bb ), East_blockers_bb = bitboard:'and'( East_mask_bb, Occupied_squares_bb ), North_blockers_bb = bitboard:'and'( North_mask_bb, Occupied_squares_bb ), West_blockers_bb = bitboard:'and'( West_mask_bb, Occupied_squares_bb ), First_blocker_south = position:from_int( bitboard:bitscan_backward(South_blockers_bb) ), First_blocker_east = position:from_int( bitboard:bitscan_forward(East_blockers_bb) ), First_blocker_north = position:from_int( bitboard:bitscan_forward(North_blockers_bb) ), First_blocker_west = position:from_int( bitboard:bitscan_backward(West_blockers_bb) ), First_blocker_south_mask_bb = case First_blocker_south of {error, _} -> 0; {ok, Position} -> look_up_south_ray_bb(Position) end, First_blocker_east_mask_bb = case First_blocker_east of {error, _} -> 0; {ok, Position@1} -> look_up_east_ray_bb(Position@1) end, First_blocker_north_mask_bb = case First_blocker_north of {error, _} -> 0; {ok, Position@2} -> look_up_north_ray_bb(Position@2) end, First_blocker_west_mask_bb = case First_blocker_west of {error, _} -> 0; {ok, Position@3} -> look_up_west_ray_bb(Position@3) end, South_ray_bb_with_blocker = bitboard:exclusive_or( South_mask_bb, First_blocker_south_mask_bb ), East_ray_bb_with_blocker = bitboard:exclusive_or( East_mask_bb, First_blocker_east_mask_bb ), North_ray_bb_with_blocker = bitboard:exclusive_or( North_mask_bb, First_blocker_north_mask_bb ), West_ray_bb_with_blocker = bitboard:exclusive_or( West_mask_bb, First_blocker_west_mask_bb ), South_ray_bb = case Color of white -> bitboard:'and'( South_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( South_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, East_ray_bb = case Color of white -> bitboard:'and'( East_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( East_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, North_ray_bb = case Color of white -> bitboard:'and'( North_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( North_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, West_ray_bb = case Color of white -> bitboard:'and'( West_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( West_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, Rook_moves = gleam@list:fold( [South_ray_bb, East_ray_bb, North_ray_bb, West_ray_bb], {ok, []}, fun(Collector@1, Next) -> Captures = case Color of white -> bitboard:'and'( Next, occupied_squares_black( erlang:element(2, Game) ) ); black -> bitboard:'and'( Next, occupied_squares_white( erlang:element(2, Game) ) ) end, Rook_simple_moves = case Color of white -> bitboard:exclusive_or(Next, Captures); black -> bitboard:exclusive_or(Next, Captures) end, gleam@result:'try'( board:get_positions(Rook_simple_moves), fun(Rook_simple_moves_positions) -> Simple_moves = gleam@list:map( Rook_simple_moves_positions, fun(Dest) -> {normal, Queen_origin_square, Dest, none} end ), gleam@result:'try'( board:get_positions(Captures), fun(Captures_positions) -> Captures@1 = gleam@list:map( Captures_positions, fun(Dest@1) -> {normal, Queen_origin_square, Dest@1, none} end ), gleam@result:'try'( Collector@1, fun(Collector@2) -> Simple_moves@1 = gleam@list:append( Collector@2, Simple_moves ), All_moves = gleam@list:append( Simple_moves@1, Captures@1 ), {ok, All_moves} end ) end ) end ) end ), South_west_mask_bb = look_up_south_west_ray_bb( Queen_origin_square ), South_east_mask_bb = look_up_south_east_ray_bb( Queen_origin_square ), North_east_mask_bb = look_up_north_east_ray_bb( Queen_origin_square ), North_west_mask_bb = look_up_north_west_ray_bb( Queen_origin_square ), Occupied_squares_bb@1 = occupied_squares( erlang:element(2, Game) ), South_west_blockers_bb = bitboard:'and'( South_west_mask_bb, Occupied_squares_bb@1 ), South_east_blockers_bb = bitboard:'and'( South_east_mask_bb, Occupied_squares_bb@1 ), North_east_blockers_bb = bitboard:'and'( North_east_mask_bb, Occupied_squares_bb@1 ), North_west_blockers_bb = bitboard:'and'( North_west_mask_bb, Occupied_squares_bb@1 ), First_blocker_south_west = position:from_int( bitboard:bitscan_backward(South_west_blockers_bb) ), First_blocker_south_east = position:from_int( bitboard:bitscan_backward(South_east_blockers_bb) ), First_blocker_north_east = position:from_int( bitboard:bitscan_forward(North_east_blockers_bb) ), First_blocker_north_west = position:from_int( bitboard:bitscan_forward(North_west_blockers_bb) ), First_blocker_south_west_mask_bb = case First_blocker_south_west of {error, _} -> 0; {ok, Position@4} -> look_up_south_west_ray_bb(Position@4) end, First_blocker_south_east_mask_bb = case First_blocker_south_east of {error, _} -> 0; {ok, Position@5} -> look_up_south_east_ray_bb(Position@5) end, First_blocker_north_east_mask_bb = case First_blocker_north_east of {error, _} -> 0; {ok, Position@6} -> look_up_north_east_ray_bb(Position@6) end, First_blocker_north_west_mask_bb = case First_blocker_north_west of {error, _} -> 0; {ok, Position@7} -> look_up_north_west_ray_bb(Position@7) end, South_west_ray_bb_with_blocker = bitboard:exclusive_or( South_west_mask_bb, First_blocker_south_west_mask_bb ), South_east_ray_bb_with_blocker = bitboard:exclusive_or( South_east_mask_bb, First_blocker_south_east_mask_bb ), North_east_ray_bb_with_blocker = bitboard:exclusive_or( North_east_mask_bb, First_blocker_north_east_mask_bb ), North_west_ray_bb_with_blocker = bitboard:exclusive_or( North_west_mask_bb, First_blocker_north_west_mask_bb ), South_west_ray_bb = case Color of white -> bitboard:'and'( South_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( South_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, South_east_ray_bb = case Color of white -> bitboard:'and'( South_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( South_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, North_east_ray_bb = case Color of white -> bitboard:'and'( North_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( North_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, North_west_ray_bb = case Color of white -> bitboard:'and'( North_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( North_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, Bishop_moves = gleam@list:fold( [South_west_ray_bb, South_east_ray_bb, North_east_ray_bb, North_west_ray_bb], {ok, []}, fun(Collector@3, Next@1) -> Captures@2 = case Color of white -> bitboard:'and'( Next@1, occupied_squares_black( erlang:element(2, Game) ) ); black -> bitboard:'and'( Next@1, occupied_squares_white( erlang:element(2, Game) ) ) end, Rook_simple_moves@1 = case Color of white -> bitboard:exclusive_or(Next@1, Captures@2); black -> bitboard:exclusive_or(Next@1, Captures@2) end, gleam@result:'try'( board:get_positions(Rook_simple_moves@1), fun(Rook_simple_moves_positions@1) -> Simple_moves@2 = gleam@list:map( Rook_simple_moves_positions@1, fun(Dest@2) -> {normal, Queen_origin_square, Dest@2, none} end ), gleam@result:'try'( board:get_positions(Captures@2), fun(Captures_positions@1) -> Captures@3 = gleam@list:map( Captures_positions@1, fun(Dest@3) -> {normal, Queen_origin_square, Dest@3, none} end ), gleam@result:'try'( Collector@3, fun(Collector@4) -> Simple_moves@3 = gleam@list:append( Collector@4, Simple_moves@2 ), All_moves@1 = gleam@list:append( Simple_moves@3, Captures@3 ), {ok, All_moves@1} end ) end ) end ) end ), gleam@result:'try'( Rook_moves, fun(Rook_moves@1) -> gleam@result:'try'( Bishop_moves, fun(Bishop_moves@1) -> gleam@result:'try'( Collector, fun(Collector@5) -> All_moves@2 = gleam@list:append( gleam@list:append( Collector@5, Rook_moves@1 ), Bishop_moves@1 ), {ok, All_moves@2} end ) end ) end ) end ) end ). -spec generate_rook_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_rook_pseudo_legal_move_list(Color, Game) -> Rook_bitboard = case Color of white -> erlang:element(10, erlang:element(2, Game)); black -> erlang:element(4, erlang:element(2, Game)) end, gleam@result:'try'( board:get_positions(Rook_bitboard), fun(Rook_origin_squares) -> gleam@list:fold( Rook_origin_squares, {ok, []}, fun(Collector, Rook_origin_square) -> South_mask_bb = look_up_south_ray_bb(Rook_origin_square), East_mask_bb = look_up_east_ray_bb(Rook_origin_square), North_mask_bb = look_up_north_ray_bb(Rook_origin_square), West_mask_bb = look_up_west_ray_bb(Rook_origin_square), Occupied_squares_bb = occupied_squares( erlang:element(2, Game) ), South_blockers_bb = bitboard:'and'( South_mask_bb, Occupied_squares_bb ), East_blockers_bb = bitboard:'and'( East_mask_bb, Occupied_squares_bb ), North_blockers_bb = bitboard:'and'( North_mask_bb, Occupied_squares_bb ), West_blockers_bb = bitboard:'and'( West_mask_bb, Occupied_squares_bb ), First_blocker_south = position:from_int( bitboard:bitscan_backward(South_blockers_bb) ), First_blocker_east = position:from_int( bitboard:bitscan_forward(East_blockers_bb) ), First_blocker_north = position:from_int( bitboard:bitscan_forward(North_blockers_bb) ), First_blocker_west = position:from_int( bitboard:bitscan_backward(West_blockers_bb) ), First_blocker_south_mask_bb = case First_blocker_south of {error, _} -> 0; {ok, Position} -> look_up_south_ray_bb(Position) end, First_blocker_east_mask_bb = case First_blocker_east of {error, _} -> 0; {ok, Position@1} -> look_up_east_ray_bb(Position@1) end, First_blocker_north_mask_bb = case First_blocker_north of {error, _} -> 0; {ok, Position@2} -> look_up_north_ray_bb(Position@2) end, First_blocker_west_mask_bb = case First_blocker_west of {error, _} -> 0; {ok, Position@3} -> look_up_west_ray_bb(Position@3) end, South_ray_bb_with_blocker = bitboard:exclusive_or( South_mask_bb, First_blocker_south_mask_bb ), East_ray_bb_with_blocker = bitboard:exclusive_or( East_mask_bb, First_blocker_east_mask_bb ), North_ray_bb_with_blocker = bitboard:exclusive_or( North_mask_bb, First_blocker_north_mask_bb ), West_ray_bb_with_blocker = bitboard:exclusive_or( West_mask_bb, First_blocker_west_mask_bb ), South_ray_bb = case Color of white -> bitboard:'and'( South_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( South_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, East_ray_bb = case Color of white -> bitboard:'and'( East_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( East_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, North_ray_bb = case Color of white -> bitboard:'and'( North_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( North_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, West_ray_bb = case Color of white -> bitboard:'and'( West_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( West_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, Rook_moves = gleam@list:fold( [South_ray_bb, East_ray_bb, North_ray_bb, West_ray_bb], {ok, []}, fun(Collector@1, Next) -> Rook_captures = case Color of white -> bitboard:'and'( Next, occupied_squares_black( erlang:element(2, Game) ) ); black -> bitboard:'and'( Next, occupied_squares_white( erlang:element(2, Game) ) ) end, Rook_simple_moves = case Color of white -> bitboard:exclusive_or(Next, Rook_captures); black -> bitboard:exclusive_or(Next, Rook_captures) end, gleam@result:'try'( board:get_positions(Rook_simple_moves), fun(Rook_simple_moves_positions) -> Simple_moves = gleam@list:map( Rook_simple_moves_positions, fun(Dest) -> {normal, Rook_origin_square, Dest, none} end ), gleam@result:'try'( board:get_positions(Rook_captures), fun(Rook_captures_positions) -> Captures = gleam@list:map( Rook_captures_positions, fun(Dest@1) -> {normal, Rook_origin_square, Dest@1, none} end ), gleam@result:'try'( Collector@1, fun(Collector@2) -> Simple_moves@1 = gleam@list:append( Collector@2, Simple_moves ), All_moves = gleam@list:append( Simple_moves@1, Captures ), {ok, All_moves} end ) end ) end ) end ), gleam@result:'try'( Rook_moves, fun(Rook_moves@1) -> gleam@result:'try'( Collector, fun(Collector@3) -> {ok, gleam@list:append( Collector@3, Rook_moves@1 )} end ) end ) end ) end ). -spec piece_at_position(game(), position:position()) -> gleam@option:option(piece:piece()). piece_at_position(Game, Position) -> Position_bb_masked = bitboard:'and'( position:to_bitboard(Position), occupied_squares(erlang:element(2, Game)) ), Position_white_king = bitboard:'and'( Position_bb_masked, erlang:element(8, erlang:element(2, Game)) ), Position_white_queen = bitboard:'and'( Position_bb_masked, erlang:element(9, erlang:element(2, Game)) ), Position_white_rook = bitboard:'and'( Position_bb_masked, erlang:element(10, erlang:element(2, Game)) ), Position_white_bishop = bitboard:'and'( Position_bb_masked, erlang:element(11, erlang:element(2, Game)) ), Position_white_knight = bitboard:'and'( Position_bb_masked, erlang:element(12, erlang:element(2, Game)) ), Position_white_pawn = bitboard:'and'( Position_bb_masked, erlang:element(13, erlang:element(2, Game)) ), Position_black_king = bitboard:'and'( Position_bb_masked, erlang:element(2, erlang:element(2, Game)) ), Position_black_queen = bitboard:'and'( Position_bb_masked, erlang:element(3, erlang:element(2, Game)) ), Position_black_rook = bitboard:'and'( Position_bb_masked, erlang:element(4, erlang:element(2, Game)) ), Position_black_bishop = bitboard:'and'( Position_bb_masked, erlang:element(5, erlang:element(2, Game)) ), Position_black_knight = bitboard:'and'( Position_bb_masked, erlang:element(6, erlang:element(2, Game)) ), Position_black_pawn = bitboard:'and'( Position_bb_masked, erlang:element(7, erlang:element(2, Game)) ), case Position_bb_masked of 0 -> none; _ when Position_white_king =/= 0 -> {some, {piece, white, king}}; _ when Position_white_queen =/= 0 -> {some, {piece, white, queen}}; _ when Position_white_rook =/= 0 -> {some, {piece, white, rook}}; _ when Position_white_bishop =/= 0 -> {some, {piece, white, bishop}}; _ when Position_white_knight =/= 0 -> {some, {piece, white, knight}}; _ when Position_white_pawn =/= 0 -> {some, {piece, white, pawn}}; _ when Position_black_king =/= 0 -> {some, {piece, black, king}}; _ when Position_black_queen =/= 0 -> {some, {piece, black, queen}}; _ when Position_black_rook =/= 0 -> {some, {piece, black, rook}}; _ when Position_black_bishop =/= 0 -> {some, {piece, black, bishop}}; _ when Position_black_knight =/= 0 -> {some, {piece, black, knight}}; _ when Position_black_pawn =/= 0 -> {some, {piece, black, pawn}}; _ -> erlang:error(#{gleam_error => panic, message => <<"panic expression evaluated"/utf8>>, module => <<"game"/utf8>>, function => <<"piece_at_position"/utf8>>, line => 2583}) end. -spec apply_move_raw(game(), move:move()) -> {ok, game()} | {error, binary()}. apply_move_raw(Game, Move) -> case Move of {normal, From, To, Promo_piece} -> gleam@result:'try'( case board:get_piece_at_position(erlang:element(2, Game), From) of {some, Piece} -> {ok, Piece}; none -> {error, <<"No piece at from position"/utf8>>} end, fun(Moving_piece) -> Captured_piece = piece_at_position(Game, To), gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, Game), From ), fun(New_board) -> New_game_state = erlang:setelement( 2, Game, New_board ), gleam@result:'try'(case Captured_piece of none -> {ok, New_game_state}; {some, _} -> gleam@result:'try'( board:remove_piece_at_position( erlang:element( 2, New_game_state ), To ), fun(New_board@1) -> {ok, erlang:setelement( 2, New_game_state, New_board@1 )} end ) end, fun(New_game_state@1) -> New_game_state@2 = case Promo_piece of none -> erlang:setelement( 2, New_game_state@1, board:set_piece_at_position( erlang:element( 2, New_game_state@1 ), To, Moving_piece ) ); {some, Promo_piece@1} -> erlang:setelement( 2, New_game_state@1, board:set_piece_at_position( erlang:element( 2, New_game_state@1 ), To, Promo_piece@1 ) ) end, New_ply = erlang:element( 6, New_game_state@2 ) + 1, New_white_king_castle = case erlang:element( 3, Game ) of white -> case erlang:element(7, Game) of yes -> case From of {position, e, one} -> {no, New_ply}; {position, h, one} -> {no, New_ply}; _ -> yes end; {no, Some_ply} -> {no, Some_ply} end; black -> erlang:element(7, Game) end, New_white_queen_castle = case erlang:element( 3, Game ) of white -> case erlang:element(8, Game) of yes -> case From of {position, e, one} -> {no, New_ply}; {position, a, one} -> {no, New_ply}; _ -> yes end; {no, Some_ply@1} -> {no, Some_ply@1} end; black -> erlang:element(8, Game) end, New_black_king_castle = case erlang:element( 3, Game ) of white -> erlang:element(9, Game); black -> case erlang:element(9, Game) of yes -> case From of {position, e, eight} -> {no, New_ply}; {position, h, eight} -> {no, New_ply}; _ -> yes end; {no, Some_ply@2} -> {no, Some_ply@2} end end, New_black_queen_castle = case erlang:element( 3, Game ) of white -> erlang:element(10, Game); black -> case erlang:element(10, Game) of yes -> case From of {position, e, eight} -> {no, New_ply}; {position, a, eight} -> {no, New_ply}; _ -> yes end; {no, Some_ply@3} -> {no, Some_ply@3} end end, New_turn = (case erlang:element(3, Game) of white -> black; black -> white end), Move_with_capture = {move_with_capture, Move, Captured_piece}, New_history = [Move_with_capture | erlang:element(4, Game)], New_en_passant = case Moving_piece of {piece, Color, pawn} -> case Color of white -> case From of {position, _, two} -> case To of {position, _, four} -> {some, {position, erlang:element( 2, From ), three}}; _ -> none end; _ -> none end; black -> case From of {position, _, seven} -> case To of {position, _, five} -> {some, {position, erlang:element( 2, From ), six}}; _ -> none end; _ -> none end end; _ -> none end, New_game_state@3 = erlang:setelement( 11, erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@2, New_turn ), New_history ), New_ply ), New_white_king_castle ), New_white_queen_castle ), New_black_king_castle ), New_black_queen_castle ), New_en_passant ), {ok, New_game_state@3} end) end ) end ); {castle, From@1, To@1} -> gleam@result:'try'( board:remove_piece_at_position(erlang:element(2, Game), From@1), fun(New_board@2) -> New_game_state@4 = erlang:setelement(2, Game, New_board@2), New_game_state@5 = erlang:setelement( 2, New_game_state@4, board:set_piece_at_position( erlang:element(2, New_game_state@4), To@1, {piece, erlang:element(3, New_game_state@4), king} ) ), gleam@result:'try'(case To@1 of {position, g, one} -> {ok, {position, f, one}}; {position, g, eight} -> {ok, {position, f, eight}}; {position, c, one} -> {ok, {position, d, one}}; {position, c, eight} -> {ok, {position, d, eight}}; _ -> {error, <<"Invalid castle move"/utf8>>} end, fun(Rook_castling_target_square) -> New_turn@1 = (case erlang:element(3, Game) of white -> black; black -> white end), New_game_state@6 = erlang:setelement( 2, New_game_state@5, board:set_piece_at_position( erlang:element(2, New_game_state@5), Rook_castling_target_square, {piece, erlang:element(3, Game), rook} ) ), gleam@result:'try'(case To@1 of {position, g, one} -> {ok, {position, h, one}}; {position, g, eight} -> {ok, {position, h, eight}}; {position, c, one} -> {ok, {position, a, one}}; {position, c, eight} -> {ok, {position, a, eight}}; _ -> {error, <<"Invalid castle move"/utf8>>} end, fun(Rook_castling_origin_square) -> gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, New_game_state@6), Rook_castling_origin_square ), fun(New_board@3) -> New_game_state@7 = erlang:setelement( 2, New_game_state@6, New_board@3 ), New_ply@1 = erlang:element( 6, New_game_state@7 ) + 1, gleam@result:'try'( case erlang:element(3, Game) of white -> {ok, {{no, New_ply@1}, {no, New_ply@1}, erlang:element( 9, Game ), erlang:element( 10, Game )}}; black -> {ok, {erlang:element( 7, Game ), erlang:element( 8, Game ), {no, New_ply@1}, {no, New_ply@1}}} end, fun(_use0) -> {New_white_king_castle@1, New_white_queen_castle@1, New_black_king_castle@1, New_black_queen_castle@1} = _use0, Move_with_capture@1 = {move_with_capture, Move, none}, New_history@1 = [Move_with_capture@1 | erlang:element(4, Game)], New_en_passant@1 = none, New_game_state@8 = erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 11, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@7, New_turn@1 ), New_history@1 ), New_ply@1 ), New_en_passant@1 ), New_white_king_castle@1 ), New_white_queen_castle@1 ), New_black_king_castle@1 ), New_black_queen_castle@1 ), {ok, New_game_state@8} end ) end ) end) end) end ); {en_passant, From@2, To@2} -> New_game_state@9 = erlang:setelement( 2, Game, board:set_piece_at_position( erlang:element(2, Game), To@2, {piece, erlang:element(3, Game), pawn} ) ), gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, New_game_state@9), From@2 ), fun(New_board@4) -> New_game_state@10 = erlang:setelement( 2, New_game_state@9, New_board@4 ), gleam@result:'try'(case To@2 of {position, a, three} -> {ok, {position, a, four}}; {position, a, six} -> {ok, {position, a, five}}; {position, b, three} -> {ok, {position, b, four}}; {position, b, six} -> {ok, {position, b, five}}; {position, c, three} -> {ok, {position, c, four}}; {position, c, six} -> {ok, {position, c, five}}; {position, d, three} -> {ok, {position, d, four}}; {position, d, six} -> {ok, {position, d, five}}; {position, e, three} -> {ok, {position, e, four}}; {position, e, six} -> {ok, {position, e, five}}; {position, f, three} -> {ok, {position, f, four}}; {position, f, six} -> {ok, {position, f, five}}; {position, g, three} -> {ok, {position, g, four}}; {position, g, six} -> {ok, {position, g, five}}; {position, h, three} -> {ok, {position, h, four}}; {position, h, six} -> {ok, {position, h, five}}; _ -> {error, <<"Invalid en passant move"/utf8>>} end, fun(Captured_pawn_square) -> gleam@result:'try'( case board:remove_piece_at_position( erlang:element(2, New_game_state@10), Captured_pawn_square ) of {ok, New_board@5} -> {ok, New_board@5}; {error, _} -> {error, <<"Invalid en passant move"/utf8>>} end, fun(New_board@6) -> New_ply@2 = erlang:element( 6, New_game_state@10 ) + 1, New_turn@2 = (case erlang:element(3, Game) of white -> black; black -> white end), New_game_state@11 = erlang:setelement( 2, New_game_state@10, New_board@6 ), Move_with_capture@2 = {move_with_capture, Move, {some, {piece, New_turn@2, pawn}}}, New_history@2 = [Move_with_capture@2 | erlang:element(4, Game)], New_en_passant@2 = none, New_game_state@12 = erlang:setelement( 11, erlang:setelement( 6, erlang:setelement( 3, erlang:setelement( 4, New_game_state@11, New_history@2 ), New_turn@2 ), New_ply@2 ), New_en_passant@2 ), {ok, New_game_state@12} end ) end) end ) end. -spec generate_bishop_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_bishop_pseudo_legal_move_list(Color, Game) -> Bishop_bitboard = case Color of white -> erlang:element(11, erlang:element(2, Game)); black -> erlang:element(5, erlang:element(2, Game)) end, gleam@result:'try'( board:get_positions(Bishop_bitboard), fun(Bishop_origin_squares) -> gleam@list:fold( Bishop_origin_squares, {ok, []}, fun(Collector, Bishop_origin_square) -> South_west_mask_bb = look_up_south_west_ray_bb( Bishop_origin_square ), South_east_mask_bb = look_up_south_east_ray_bb( Bishop_origin_square ), North_east_mask_bb = look_up_north_east_ray_bb( Bishop_origin_square ), North_west_mask_bb = look_up_north_west_ray_bb( Bishop_origin_square ), Occupied_squares_bb = occupied_squares( erlang:element(2, Game) ), South_west_blockers_bb = bitboard:'and'( South_west_mask_bb, Occupied_squares_bb ), South_east_blockers_bb = bitboard:'and'( South_east_mask_bb, Occupied_squares_bb ), North_east_blockers_bb = bitboard:'and'( North_east_mask_bb, Occupied_squares_bb ), North_west_blockers_bb = bitboard:'and'( North_west_mask_bb, Occupied_squares_bb ), First_blocker_south_west = position:from_int( bitboard:bitscan_backward(South_west_blockers_bb) ), First_blocker_south_east = position:from_int( bitboard:bitscan_backward(South_east_blockers_bb) ), First_blocker_north_east = position:from_int( bitboard:bitscan_forward(North_east_blockers_bb) ), First_blocker_north_west = position:from_int( bitboard:bitscan_forward(North_west_blockers_bb) ), First_blocker_south_west_mask_bb = case First_blocker_south_west of {error, _} -> 0; {ok, Position} -> look_up_south_west_ray_bb(Position) end, First_blocker_south_east_mask_bb = case First_blocker_south_east of {error, _} -> 0; {ok, Position@1} -> look_up_south_east_ray_bb(Position@1) end, First_blocker_north_east_mask_bb = case First_blocker_north_east of {error, _} -> 0; {ok, Position@2} -> look_up_north_east_ray_bb(Position@2) end, First_blocker_north_west_mask_bb = case First_blocker_north_west of {error, _} -> 0; {ok, Position@3} -> look_up_north_west_ray_bb(Position@3) end, South_west_ray_bb_with_blocker = bitboard:exclusive_or( South_west_mask_bb, First_blocker_south_west_mask_bb ), South_east_ray_bb_with_blocker = bitboard:exclusive_or( South_east_mask_bb, First_blocker_south_east_mask_bb ), North_east_ray_bb_with_blocker = bitboard:exclusive_or( North_east_mask_bb, First_blocker_north_east_mask_bb ), North_west_ray_bb_with_blocker = bitboard:exclusive_or( North_west_mask_bb, First_blocker_north_west_mask_bb ), South_west_ray_bb = case Color of white -> bitboard:'and'( South_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( South_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, South_east_ray_bb = case Color of white -> bitboard:'and'( South_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( South_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, North_east_ray_bb = case Color of white -> bitboard:'and'( North_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( North_east_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, North_west_ray_bb = case Color of white -> bitboard:'and'( North_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_white( erlang:element(2, Game) ) ) ); black -> bitboard:'and'( North_west_ray_bb_with_blocker, bitboard:'not'( occupied_squares_black( erlang:element(2, Game) ) ) ) end, Bishop_moves = gleam@list:fold( [South_west_ray_bb, South_east_ray_bb, North_east_ray_bb, North_west_ray_bb], {ok, []}, fun(Collector@1, Next) -> Captures = case Color of white -> bitboard:'and'( Next, occupied_squares_black( erlang:element(2, Game) ) ); black -> bitboard:'and'( Next, occupied_squares_white( erlang:element(2, Game) ) ) end, Rook_simple_moves = case Color of white -> bitboard:exclusive_or(Next, Captures); black -> bitboard:exclusive_or(Next, Captures) end, gleam@result:'try'( board:get_positions(Rook_simple_moves), fun(Rook_simple_moves_positions) -> gleam@result:'try'( board:get_positions(Captures), fun(Captures_positions) -> Simple_moves = gleam@list:map( Rook_simple_moves_positions, fun(Dest) -> {normal, Bishop_origin_square, Dest, none} end ), Captures@1 = gleam@list:map( Captures_positions, fun(Dest@1) -> {normal, Bishop_origin_square, Dest@1, none} end ), gleam@result:'try'( Collector@1, fun(Collector@2) -> Simple_moves@1 = gleam@list:append( Collector@2, Simple_moves ), All_moves = gleam@list:append( Simple_moves@1, Captures@1 ), {ok, All_moves} end ) end ) end ) end ), gleam@result:'try'( Bishop_moves, fun(Bishop_moves@1) -> gleam@result:'try'( Collector, fun(Collector@3) -> {ok, gleam@list:append( Collector@3, Bishop_moves@1 )} end ) end ) end ) end ). -spec generate_pawn_non_capture_move_bitboard(color:color(), game()) -> integer(). generate_pawn_non_capture_move_bitboard(Color, Game) -> case Color of white -> White_pawn_target_squares = bitboard:shift_left( erlang:element(13, erlang:element(2, Game)), 8 ), List_of_enemy_piece_bitboards = [erlang:element( 2, erlang:element(2, Game) ), erlang:element(3, erlang:element(2, Game)), erlang:element(4, erlang:element(2, Game)), erlang:element(5, erlang:element(2, Game)), erlang:element(6, erlang:element(2, Game)), erlang:element(7, erlang:element(2, Game))], Occupied_squares_white = occupied_squares_white( erlang:element(2, Game) ), Enemy_pieces = gleam@list:fold( List_of_enemy_piece_bitboards, 0, fun(Collector, Next) -> bitboard:'or'(Collector, Next) end ), Moves = bitboard:exclusive_or( White_pawn_target_squares, Enemy_pieces ), Moves@1 = bitboard:'and'(Moves, White_pawn_target_squares), Moves@2 = bitboard:'and'( Moves@1, bitboard:'not'(Occupied_squares_white) ), Moves@2; black -> Black_pawn_target_squares = bitboard:shift_right( erlang:element(7, erlang:element(2, Game)), 8 ), List_of_enemy_piece_bitboards@1 = [erlang:element( 8, erlang:element(2, Game) ), erlang:element(9, erlang:element(2, Game)), erlang:element(10, erlang:element(2, Game)), erlang:element(11, erlang:element(2, Game)), erlang:element(12, erlang:element(2, Game)), erlang:element(13, erlang:element(2, Game))], Occupied_squares_black = occupied_squares_black( erlang:element(2, Game) ), Enemy_pieces@1 = gleam@list:fold( List_of_enemy_piece_bitboards@1, 0, fun(Collector@1, Next@1) -> bitboard:'or'(Collector@1, Next@1) end ), Moves@3 = bitboard:exclusive_or( Black_pawn_target_squares, Enemy_pieces@1 ), Moves@4 = bitboard:'and'(Moves@3, Black_pawn_target_squares), Moves@5 = bitboard:'and'( Moves@4, bitboard:'not'(Occupied_squares_black) ), Moves@5 end. -spec bitboard_repr_to_map_repr(board:board_bb()) -> {ok, gleam@dict:dict(position:position(), gleam@option:option(piece:piece()))} | {error, binary()}. bitboard_repr_to_map_repr(Board) -> White_king_bitboard = erlang:element(8, Board), White_queen_bitboard = erlang:element(9, Board), White_rook_bitboard = erlang:element(10, Board), White_bishop_bitboard = erlang:element(11, Board), White_knight_bitboard = erlang:element(12, Board), White_pawns_bitboard = erlang:element(13, Board), Black_king_bitboard = erlang:element(2, Board), Black_queen_bitboard = erlang:element(3, Board), Black_rook_bitboard = erlang:element(4, Board), Black_bishop_bitboard = erlang:element(5, Board), Black_knight_bitboard = erlang:element(6, Board), Black_pawns_bitboard = erlang:element(7, Board), Board_map = maps:from_list( [{{position, a, one}, none}, {{position, b, one}, none}, {{position, c, one}, none}, {{position, d, one}, none}, {{position, e, one}, none}, {{position, f, one}, none}, {{position, g, one}, none}, {{position, h, one}, none}, {{position, a, two}, none}, {{position, b, two}, none}, {{position, c, two}, none}, {{position, d, two}, none}, {{position, e, two}, none}, {{position, f, two}, none}, {{position, g, two}, none}, {{position, h, two}, none}, {{position, a, three}, none}, {{position, b, three}, none}, {{position, c, three}, none}, {{position, d, three}, none}, {{position, e, three}, none}, {{position, f, three}, none}, {{position, g, three}, none}, {{position, h, three}, none}, {{position, a, four}, none}, {{position, b, four}, none}, {{position, c, four}, none}, {{position, d, four}, none}, {{position, e, four}, none}, {{position, f, four}, none}, {{position, g, four}, none}, {{position, h, four}, none}, {{position, a, five}, none}, {{position, b, five}, none}, {{position, c, five}, none}, {{position, d, five}, none}, {{position, e, five}, none}, {{position, f, five}, none}, {{position, g, five}, none}, {{position, h, five}, none}, {{position, a, six}, none}, {{position, b, six}, none}, {{position, c, six}, none}, {{position, d, six}, none}, {{position, e, six}, none}, {{position, f, six}, none}, {{position, g, six}, none}, {{position, h, six}, none}, {{position, a, seven}, none}, {{position, b, seven}, none}, {{position, c, seven}, none}, {{position, d, seven}, none}, {{position, e, seven}, none}, {{position, f, seven}, none}, {{position, g, seven}, none}, {{position, h, seven}, none}, {{position, a, eight}, none}, {{position, b, eight}, none}, {{position, c, eight}, none}, {{position, d, eight}, none}, {{position, e, eight}, none}, {{position, f, eight}, none}, {{position, g, eight}, none}, {{position, h, eight}, none}] ), gleam@result:'try'( board:get_positions(White_king_bitboard), fun(White_king_positions) -> gleam@result:'try'( board:get_positions(White_queen_bitboard), fun(White_queen_positions) -> gleam@result:'try'( board:get_positions(White_rook_bitboard), fun(White_rook_positions) -> gleam@result:'try'( board:get_positions(White_bishop_bitboard), fun(White_bishop_positions) -> gleam@result:'try'( board:get_positions( White_knight_bitboard ), fun(White_knight_positions) -> gleam@result:'try'( board:get_positions( White_pawns_bitboard ), fun(White_pawns_positions) -> gleam@result:'try'( board:get_positions( Black_king_bitboard ), fun( Black_king_positions ) -> gleam@result:'try'( board:get_positions( Black_queen_bitboard ), fun( Black_queen_positions ) -> gleam@result:'try'( board:get_positions( Black_rook_bitboard ), fun( Black_rook_positions ) -> gleam@result:'try'( board:get_positions( Black_bishop_bitboard ), fun( Black_bishop_positions ) -> gleam@result:'try'( board:get_positions( Black_knight_bitboard ), fun( Black_knight_positions ) -> gleam@result:'try'( board:get_positions( Black_pawns_bitboard ), fun( Black_pawns_positions ) -> Board_map@2 = gleam@list:fold( White_king_positions, Board_map, fun( Board_map@1, Position ) -> gleam@dict:insert( Board_map@1, Position, {some, {piece, white, king}} ) end ), Board_map@4 = gleam@list:fold( White_queen_positions, Board_map@2, fun( Board_map@3, Position@1 ) -> gleam@dict:insert( Board_map@3, Position@1, {some, {piece, white, queen}} ) end ), Board_map@6 = gleam@list:fold( White_rook_positions, Board_map@4, fun( Board_map@5, Position@2 ) -> gleam@dict:insert( Board_map@5, Position@2, {some, {piece, white, rook}} ) end ), Board_map@8 = gleam@list:fold( White_bishop_positions, Board_map@6, fun( Board_map@7, Position@3 ) -> gleam@dict:insert( Board_map@7, Position@3, {some, {piece, white, bishop}} ) end ), Board_map@10 = gleam@list:fold( White_knight_positions, Board_map@8, fun( Board_map@9, Position@4 ) -> gleam@dict:insert( Board_map@9, Position@4, {some, {piece, white, knight}} ) end ), Board_map@12 = gleam@list:fold( White_pawns_positions, Board_map@10, fun( Board_map@11, Position@5 ) -> gleam@dict:insert( Board_map@11, Position@5, {some, {piece, white, pawn}} ) end ), Board_map@14 = gleam@list:fold( Black_king_positions, Board_map@12, fun( Board_map@13, Position@6 ) -> gleam@dict:insert( Board_map@13, Position@6, {some, {piece, black, king}} ) end ), Board_map@16 = gleam@list:fold( Black_queen_positions, Board_map@14, fun( Board_map@15, Position@7 ) -> gleam@dict:insert( Board_map@15, Position@7, {some, {piece, black, queen}} ) end ), Board_map@18 = gleam@list:fold( Black_rook_positions, Board_map@16, fun( Board_map@17, Position@8 ) -> gleam@dict:insert( Board_map@17, Position@8, {some, {piece, black, rook}} ) end ), Board_map@20 = gleam@list:fold( Black_bishop_positions, Board_map@18, fun( Board_map@19, Position@9 ) -> gleam@dict:insert( Board_map@19, Position@9, {some, {piece, black, bishop}} ) end ), Board_map@22 = gleam@list:fold( Black_knight_positions, Board_map@20, fun( Board_map@21, Position@10 ) -> gleam@dict:insert( Board_map@21, Position@10, {some, {piece, black, knight}} ) end ), Board_map@24 = gleam@list:fold( Black_pawns_positions, Board_map@22, fun( Board_map@23, Position@11 ) -> gleam@dict:insert( Board_map@23, Position@11, {some, {piece, black, pawn}} ) end ), {ok, Board_map@24} end ) end ) end ) end ) end ) end ) end ) end ) end ) end ) end ) end ). -spec disable_status(game()) -> game(). disable_status(Game) -> erlang:setelement(5, Game, none). -spec undo_move(game()) -> {ok, game()} | {error, binary()}. undo_move(Game) -> case erlang:element(5, Game) of {some, {in_progress, _, _}} -> case erlang:element(4, Game) of [] -> {ok, Game}; [Move | Rest] -> case Move of {move_with_capture, {normal, From, To, Promo_piece}, Captured_piece} -> Moving_piece = case board:get_piece_at_position( erlang:element(2, Game), To ) of none -> erlang:error(#{gleam_error => panic, message => <<"Undoing Normal Move: Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4409}); {some, Piece} -> Piece end, Moving_piece@1 = case Promo_piece of none -> Moving_piece; {some, _} -> {piece, erlang:element(2, Moving_piece), pawn} end, New_turn = (case erlang:element(3, Game) of white -> black; black -> white end), gleam@result:'try'(case Captured_piece of none -> gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, Game), To ), fun(New_board) -> {ok, erlang:setelement( 2, Game, New_board )} end ); {some, Piece@1} -> gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, Game), To ), fun(New_board@1) -> New_board@2 = board:set_piece_at_position( New_board@1, To, Piece@1 ), {ok, erlang:setelement( 2, Game, New_board@2 )} end ) end, fun(New_game_state) -> New_board@3 = board:set_piece_at_position( erlang:element(2, New_game_state), From, Moving_piece@1 ), New_game_state@1 = erlang:setelement( 2, New_game_state, New_board@3 ), New_ply = erlang:element(6, Game) - 1, New_white_kingside_castle = case erlang:element( 7, Game ) of yes -> yes; {no, Ply} -> case Ply =:= erlang:element(6, Game) of true -> yes; false -> {no, Ply} end end, New_white_queenside_castle = case erlang:element( 8, Game ) of yes -> yes; {no, Ply@1} -> case Ply@1 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@1} end end, New_black_kingside_castle = case erlang:element( 9, Game ) of yes -> yes; {no, Ply@2} -> case Ply@2 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@2} end end, New_black_queenside_castle = case erlang:element( 10, Game ) of yes -> yes; {no, Ply@3} -> case Ply@3 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@3} end end, New_history = Rest, New_en_passant = case Rest of [] -> none; [Move@1] -> case Move@1 of {move_with_capture, {normal, {position, _, two}, {position, File, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@2 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File, four} ) of {some, Piece@2} -> Piece@2; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move: Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4527} ) end, case Moving_piece@2 of {piece, _, pawn} -> {some, {position, File, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@1, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@3 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File@1, five} ) of {some, Piece@3} -> Piece@3; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move:Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4552} ) end, case Moving_piece@3 of {piece, _, pawn} -> {some, {position, File@1, six}}; _ -> none end; _ -> none end; [Move@1 | _] -> case Move@1 of {move_with_capture, {normal, {position, _, two}, {position, File, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@2 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File, four} ) of {some, Piece@2} -> Piece@2; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move: Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4527} ) end, case Moving_piece@2 of {piece, _, pawn} -> {some, {position, File, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@1, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@3 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File@1, five} ) of {some, Piece@3} -> Piece@3; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move:Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4552} ) end, case Moving_piece@3 of {piece, _, pawn} -> {some, {position, File@1, six}}; _ -> none end; _ -> none end end, New_status = case erlang:element(5, Game) of none -> none; {some, {in_progress, Fifty_move_rule, Threefold_repetition_rule}} -> New_fifty_move_rule = case Fifty_move_rule of 0 -> 0; _ -> Fifty_move_rule - 1 end, Threefold_position = {three_fold_position, erlang:element(3, Game), erlang:element(2, Game), erlang:element(11, Game), erlang:element(7, Game), erlang:element(8, Game), erlang:element(9, Game), erlang:element(10, Game)}, New_threefold_repetition_rule = case gleam@dict:get( Threefold_repetition_rule, Threefold_position ) of {error, nil} -> Threefold_repetition_rule; {ok, 0} -> gleam@dict:delete( Threefold_repetition_rule, Threefold_position ); {ok, 1} -> gleam@dict:delete( Threefold_repetition_rule, Threefold_position ); {ok, Count} -> gleam@dict:insert( Threefold_repetition_rule, Threefold_position, Count - 1 ) end, {some, {in_progress, New_fifty_move_rule, New_threefold_repetition_rule}}; {some, _} -> erlang:error(#{gleam_error => panic, message => <<"Undoing Normal Move: trying to undo a move in a finished game is not possible"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4604}) end, New_game_state@2 = erlang:setelement( 11, erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 5, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@1, New_turn ), New_history ), New_ply ), New_status ), New_white_kingside_castle ), New_white_queenside_castle ), New_black_kingside_castle ), New_black_queenside_castle ), New_en_passant ), {ok, New_game_state@2} end); {move_with_capture, {castle, From@1, To@1}, _} -> Rook_castling_target_square = case To@1 of {position, g, one} -> {position, f, one}; {position, g, eight} -> {position, f, eight}; {position, c, one} -> {position, d, one}; {position, c, eight} -> {position, d, eight}; _ -> erlang:error(#{gleam_error => panic, message => <<"Undoing Castle Move: Invalid castle move"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4636}) end, gleam@result:'try'( case board:remove_piece_at_position( erlang:element(2, Game), Rook_castling_target_square ) of {ok, Board} -> {ok, Board}; {error, _} -> {error, <<"Undoing Castle Move: Could not remove piece at position"/utf8>>} end, fun(New_board@4) -> New_game_state@3 = erlang:setelement( 2, Game, New_board@4 ), gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, New_game_state@3), To@1 ), fun(New_board@5) -> New_game_state@4 = erlang:setelement( 2, New_game_state@3, New_board@5 ), Rook_castling_origin_square = case To@1 of {position, g, one} -> {position, h, one}; {position, g, eight} -> {position, h, eight}; {position, c, one} -> {position, a, one}; {position, c, eight} -> {position, a, eight}; _ -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: Invalid castle move"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4668} ) end, New_turn@1 = (case erlang:element( 3, New_game_state@4 ) of white -> black; black -> white end), New_game_state@5 = erlang:setelement( 2, New_game_state@4, board:set_piece_at_position( erlang:element( 2, New_game_state@4 ), From@1, {piece, New_turn@1, king} ) ), New_game_state@6 = erlang:setelement( 2, New_game_state@5, board:set_piece_at_position( erlang:element( 2, New_game_state@5 ), Rook_castling_origin_square, {piece, New_turn@1, rook} ) ), New_ply@1 = erlang:element(6, Game) - 1, New_white_kingside_castle@1 = case erlang:element( 7, Game ) of yes -> yes; {no, Ply@4} -> case Ply@4 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@4} end end, New_white_queenside_castle@1 = case erlang:element( 8, Game ) of yes -> yes; {no, Ply@5} -> case Ply@5 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@5} end end, New_black_kingside_castle@1 = case erlang:element( 9, Game ) of yes -> yes; {no, Ply@6} -> case Ply@6 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@6} end end, New_black_queenside_castle@1 = case erlang:element( 10, Game ) of yes -> yes; {no, Ply@7} -> case Ply@7 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@7} end end, New_history@1 = Rest, New_en_passant@1 = case Rest of [] -> none; [Move@2] -> case Move@2 of {move_with_capture, {normal, {position, _, two}, {position, File@2, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@4 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@2, four} ) of {some, Piece@4} -> Piece@4; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 1"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4767} ) end, case Moving_piece@4 of {piece, _, pawn} -> {some, {position, File@2, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@3, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@5 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@3, five} ) of {some, Piece@5} -> Piece@5; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 2"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4792} ) end, case Moving_piece@5 of {piece, _, pawn} -> {some, {position, File@3, six}}; _ -> none end; _ -> none end; [Move@2 | _] -> case Move@2 of {move_with_capture, {normal, {position, _, two}, {position, File@2, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@4 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@2, four} ) of {some, Piece@4} -> Piece@4; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 1"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4767} ) end, case Moving_piece@4 of {piece, _, pawn} -> {some, {position, File@2, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@3, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@5 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@3, five} ) of {some, Piece@5} -> Piece@5; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 2"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4792} ) end, case Moving_piece@5 of {piece, _, pawn} -> {some, {position, File@3, six}}; _ -> none end; _ -> none end end, New_status@1 = case erlang:element( 5, Game ) of none -> none; {some, {in_progress, Fifty_move_rule@1, Threefold_repetition_rule@1}} -> case Fifty_move_rule@1 of 0 -> {some, {in_progress, 0, Threefold_repetition_rule@1}}; _ -> {some, {in_progress, Fifty_move_rule@1 - 1, Threefold_repetition_rule@1}} end; {some, _} -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: Trying to undo a move in a finished game"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4820} ) end, New_game_state@7 = erlang:setelement( 11, erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 5, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@6, New_turn@1 ), New_history@1 ), New_ply@1 ), New_status@1 ), New_white_kingside_castle@1 ), New_white_queenside_castle@1 ), New_black_kingside_castle@1 ), New_black_queenside_castle@1 ), New_en_passant@1 ), {ok, New_game_state@7} end ) end ); {move_with_capture, {en_passant, From@2, To@2}, _} -> gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, Game), To@2 ), fun(New_board@6) -> New_game_state@8 = erlang:setelement( 2, Game, New_board@6 ), New_game_state@9 = case erlang:element( 3, Game ) of black -> erlang:setelement( 2, New_game_state@8, board:set_piece_at_position( erlang:element( 2, New_game_state@8 ), From@2, {piece, white, pawn} ) ); white -> erlang:setelement( 2, New_game_state@8, board:set_piece_at_position( erlang:element( 2, New_game_state@8 ), From@2, {piece, black, pawn} ) ) end, New_game_state@10 = case erlang:element( 3, Game ) of black -> erlang:setelement( 2, New_game_state@9, board:set_piece_at_position( erlang:element( 2, New_game_state@9 ), {position, erlang:element(2, To@2), five}, {piece, black, pawn} ) ); white -> erlang:setelement( 2, New_game_state@9, board:set_piece_at_position( erlang:element( 2, New_game_state@9 ), {position, erlang:element(2, To@2), four}, {piece, white, pawn} ) ) end, New_ply@2 = erlang:element(6, Game) - 1, New_white_kingside_castle@2 = case erlang:element( 7, Game ) of yes -> yes; {no, Ply@8} -> case Ply@8 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@8} end end, New_white_queenside_castle@2 = case erlang:element( 8, Game ) of yes -> yes; {no, Ply@9} -> case Ply@9 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@9} end end, New_black_kingside_castle@2 = case erlang:element( 9, Game ) of yes -> yes; {no, Ply@10} -> case Ply@10 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@10} end end, New_black_queenside_castle@2 = case erlang:element( 10, Game ) of yes -> yes; {no, Ply@11} -> case Ply@11 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@11} end end, New_turn@2 = (case erlang:element(3, Game) of white -> black; black -> white end), New_history@2 = Rest, New_en_passant@2 = To@2, New_status@2 = case erlang:element(5, Game) of none -> none; {some, {in_progress, Fifty_move_rule@2, Threefold_repetition_rule@2}} -> case Fifty_move_rule@2 of 0 -> {some, {in_progress, 0, Threefold_repetition_rule@2}}; _ -> {some, {in_progress, Fifty_move_rule@2 - 1, Threefold_repetition_rule@2}} end; {some, _} -> erlang:error(#{gleam_error => panic, message => <<"Undoing En Passant Move: Trying to undo a move in a finished game"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4962}) end, New_game_state@11 = erlang:setelement( 11, erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 5, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@10, New_turn@2 ), New_history@2 ), New_ply@2 ), New_status@2 ), New_white_kingside_castle@2 ), New_white_queenside_castle@2 ), New_black_kingside_castle@2 ), New_black_queenside_castle@2 ), {some, New_en_passant@2} ), {ok, New_game_state@11} end ) end end; none -> case erlang:element(4, Game) of [] -> {ok, Game}; [Move | Rest] -> case Move of {move_with_capture, {normal, From, To, Promo_piece}, Captured_piece} -> Moving_piece = case board:get_piece_at_position( erlang:element(2, Game), To ) of none -> erlang:error(#{gleam_error => panic, message => <<"Undoing Normal Move: Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4409}); {some, Piece} -> Piece end, Moving_piece@1 = case Promo_piece of none -> Moving_piece; {some, _} -> {piece, erlang:element(2, Moving_piece), pawn} end, New_turn = (case erlang:element(3, Game) of white -> black; black -> white end), gleam@result:'try'(case Captured_piece of none -> gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, Game), To ), fun(New_board) -> {ok, erlang:setelement( 2, Game, New_board )} end ); {some, Piece@1} -> gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, Game), To ), fun(New_board@1) -> New_board@2 = board:set_piece_at_position( New_board@1, To, Piece@1 ), {ok, erlang:setelement( 2, Game, New_board@2 )} end ) end, fun(New_game_state) -> New_board@3 = board:set_piece_at_position( erlang:element(2, New_game_state), From, Moving_piece@1 ), New_game_state@1 = erlang:setelement( 2, New_game_state, New_board@3 ), New_ply = erlang:element(6, Game) - 1, New_white_kingside_castle = case erlang:element( 7, Game ) of yes -> yes; {no, Ply} -> case Ply =:= erlang:element(6, Game) of true -> yes; false -> {no, Ply} end end, New_white_queenside_castle = case erlang:element( 8, Game ) of yes -> yes; {no, Ply@1} -> case Ply@1 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@1} end end, New_black_kingside_castle = case erlang:element( 9, Game ) of yes -> yes; {no, Ply@2} -> case Ply@2 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@2} end end, New_black_queenside_castle = case erlang:element( 10, Game ) of yes -> yes; {no, Ply@3} -> case Ply@3 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@3} end end, New_history = Rest, New_en_passant = case Rest of [] -> none; [Move@1] -> case Move@1 of {move_with_capture, {normal, {position, _, two}, {position, File, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@2 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File, four} ) of {some, Piece@2} -> Piece@2; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move: Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4527} ) end, case Moving_piece@2 of {piece, _, pawn} -> {some, {position, File, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@1, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@3 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File@1, five} ) of {some, Piece@3} -> Piece@3; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move:Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4552} ) end, case Moving_piece@3 of {piece, _, pawn} -> {some, {position, File@1, six}}; _ -> none end; _ -> none end; [Move@1 | _] -> case Move@1 of {move_with_capture, {normal, {position, _, two}, {position, File, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@2 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File, four} ) of {some, Piece@2} -> Piece@2; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move: Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4527} ) end, case Moving_piece@2 of {piece, _, pawn} -> {some, {position, File, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@1, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@3 = case board:get_piece_at_position( erlang:element( 2, New_game_state@1 ), {position, File@1, five} ) of {some, Piece@3} -> Piece@3; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Normal Move:Could not get piece at position"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4552} ) end, case Moving_piece@3 of {piece, _, pawn} -> {some, {position, File@1, six}}; _ -> none end; _ -> none end end, New_status = case erlang:element(5, Game) of none -> none; {some, {in_progress, Fifty_move_rule, Threefold_repetition_rule}} -> New_fifty_move_rule = case Fifty_move_rule of 0 -> 0; _ -> Fifty_move_rule - 1 end, Threefold_position = {three_fold_position, erlang:element(3, Game), erlang:element(2, Game), erlang:element(11, Game), erlang:element(7, Game), erlang:element(8, Game), erlang:element(9, Game), erlang:element(10, Game)}, New_threefold_repetition_rule = case gleam@dict:get( Threefold_repetition_rule, Threefold_position ) of {error, nil} -> Threefold_repetition_rule; {ok, 0} -> gleam@dict:delete( Threefold_repetition_rule, Threefold_position ); {ok, 1} -> gleam@dict:delete( Threefold_repetition_rule, Threefold_position ); {ok, Count} -> gleam@dict:insert( Threefold_repetition_rule, Threefold_position, Count - 1 ) end, {some, {in_progress, New_fifty_move_rule, New_threefold_repetition_rule}}; {some, _} -> erlang:error(#{gleam_error => panic, message => <<"Undoing Normal Move: trying to undo a move in a finished game is not possible"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4604}) end, New_game_state@2 = erlang:setelement( 11, erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 5, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@1, New_turn ), New_history ), New_ply ), New_status ), New_white_kingside_castle ), New_white_queenside_castle ), New_black_kingside_castle ), New_black_queenside_castle ), New_en_passant ), {ok, New_game_state@2} end); {move_with_capture, {castle, From@1, To@1}, _} -> Rook_castling_target_square = case To@1 of {position, g, one} -> {position, f, one}; {position, g, eight} -> {position, f, eight}; {position, c, one} -> {position, d, one}; {position, c, eight} -> {position, d, eight}; _ -> erlang:error(#{gleam_error => panic, message => <<"Undoing Castle Move: Invalid castle move"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4636}) end, gleam@result:'try'( case board:remove_piece_at_position( erlang:element(2, Game), Rook_castling_target_square ) of {ok, Board} -> {ok, Board}; {error, _} -> {error, <<"Undoing Castle Move: Could not remove piece at position"/utf8>>} end, fun(New_board@4) -> New_game_state@3 = erlang:setelement( 2, Game, New_board@4 ), gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, New_game_state@3), To@1 ), fun(New_board@5) -> New_game_state@4 = erlang:setelement( 2, New_game_state@3, New_board@5 ), Rook_castling_origin_square = case To@1 of {position, g, one} -> {position, h, one}; {position, g, eight} -> {position, h, eight}; {position, c, one} -> {position, a, one}; {position, c, eight} -> {position, a, eight}; _ -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: Invalid castle move"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4668} ) end, New_turn@1 = (case erlang:element( 3, New_game_state@4 ) of white -> black; black -> white end), New_game_state@5 = erlang:setelement( 2, New_game_state@4, board:set_piece_at_position( erlang:element( 2, New_game_state@4 ), From@1, {piece, New_turn@1, king} ) ), New_game_state@6 = erlang:setelement( 2, New_game_state@5, board:set_piece_at_position( erlang:element( 2, New_game_state@5 ), Rook_castling_origin_square, {piece, New_turn@1, rook} ) ), New_ply@1 = erlang:element(6, Game) - 1, New_white_kingside_castle@1 = case erlang:element( 7, Game ) of yes -> yes; {no, Ply@4} -> case Ply@4 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@4} end end, New_white_queenside_castle@1 = case erlang:element( 8, Game ) of yes -> yes; {no, Ply@5} -> case Ply@5 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@5} end end, New_black_kingside_castle@1 = case erlang:element( 9, Game ) of yes -> yes; {no, Ply@6} -> case Ply@6 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@6} end end, New_black_queenside_castle@1 = case erlang:element( 10, Game ) of yes -> yes; {no, Ply@7} -> case Ply@7 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@7} end end, New_history@1 = Rest, New_en_passant@1 = case Rest of [] -> none; [Move@2] -> case Move@2 of {move_with_capture, {normal, {position, _, two}, {position, File@2, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@4 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@2, four} ) of {some, Piece@4} -> Piece@4; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 1"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4767} ) end, case Moving_piece@4 of {piece, _, pawn} -> {some, {position, File@2, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@3, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@5 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@3, five} ) of {some, Piece@5} -> Piece@5; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 2"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4792} ) end, case Moving_piece@5 of {piece, _, pawn} -> {some, {position, File@3, six}}; _ -> none end; _ -> none end; [Move@2 | _] -> case Move@2 of {move_with_capture, {normal, {position, _, two}, {position, File@2, four}, none}, _} when erlang:element( 3, Game ) =:= white -> Moving_piece@4 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@2, four} ) of {some, Piece@4} -> Piece@4; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 1"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4767} ) end, case Moving_piece@4 of {piece, _, pawn} -> {some, {position, File@2, three}}; _ -> none end; {move_with_capture, {normal, {position, _, seven}, {position, File@3, five}, none}, _} when erlang:element( 3, Game ) =:= black -> Moving_piece@5 = case board:get_piece_at_position( erlang:element( 2, New_game_state@6 ), {position, File@3, five} ) of {some, Piece@5} -> Piece@5; none -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: could not get piece at position 2"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4792} ) end, case Moving_piece@5 of {piece, _, pawn} -> {some, {position, File@3, six}}; _ -> none end; _ -> none end end, New_status@1 = case erlang:element( 5, Game ) of none -> none; {some, {in_progress, Fifty_move_rule@1, Threefold_repetition_rule@1}} -> case Fifty_move_rule@1 of 0 -> {some, {in_progress, 0, Threefold_repetition_rule@1}}; _ -> {some, {in_progress, Fifty_move_rule@1 - 1, Threefold_repetition_rule@1}} end; {some, _} -> erlang:error( #{gleam_error => panic, message => <<"Undoing Castle Move: Trying to undo a move in a finished game"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4820} ) end, New_game_state@7 = erlang:setelement( 11, erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 5, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@6, New_turn@1 ), New_history@1 ), New_ply@1 ), New_status@1 ), New_white_kingside_castle@1 ), New_white_queenside_castle@1 ), New_black_kingside_castle@1 ), New_black_queenside_castle@1 ), New_en_passant@1 ), {ok, New_game_state@7} end ) end ); {move_with_capture, {en_passant, From@2, To@2}, _} -> gleam@result:'try'( board:remove_piece_at_position( erlang:element(2, Game), To@2 ), fun(New_board@6) -> New_game_state@8 = erlang:setelement( 2, Game, New_board@6 ), New_game_state@9 = case erlang:element( 3, Game ) of black -> erlang:setelement( 2, New_game_state@8, board:set_piece_at_position( erlang:element( 2, New_game_state@8 ), From@2, {piece, white, pawn} ) ); white -> erlang:setelement( 2, New_game_state@8, board:set_piece_at_position( erlang:element( 2, New_game_state@8 ), From@2, {piece, black, pawn} ) ) end, New_game_state@10 = case erlang:element( 3, Game ) of black -> erlang:setelement( 2, New_game_state@9, board:set_piece_at_position( erlang:element( 2, New_game_state@9 ), {position, erlang:element(2, To@2), five}, {piece, black, pawn} ) ); white -> erlang:setelement( 2, New_game_state@9, board:set_piece_at_position( erlang:element( 2, New_game_state@9 ), {position, erlang:element(2, To@2), four}, {piece, white, pawn} ) ) end, New_ply@2 = erlang:element(6, Game) - 1, New_white_kingside_castle@2 = case erlang:element( 7, Game ) of yes -> yes; {no, Ply@8} -> case Ply@8 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@8} end end, New_white_queenside_castle@2 = case erlang:element( 8, Game ) of yes -> yes; {no, Ply@9} -> case Ply@9 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@9} end end, New_black_kingside_castle@2 = case erlang:element( 9, Game ) of yes -> yes; {no, Ply@10} -> case Ply@10 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@10} end end, New_black_queenside_castle@2 = case erlang:element( 10, Game ) of yes -> yes; {no, Ply@11} -> case Ply@11 =:= erlang:element( 6, Game ) of true -> yes; false -> {no, Ply@11} end end, New_turn@2 = (case erlang:element(3, Game) of white -> black; black -> white end), New_history@2 = Rest, New_en_passant@2 = To@2, New_status@2 = case erlang:element(5, Game) of none -> none; {some, {in_progress, Fifty_move_rule@2, Threefold_repetition_rule@2}} -> case Fifty_move_rule@2 of 0 -> {some, {in_progress, 0, Threefold_repetition_rule@2}}; _ -> {some, {in_progress, Fifty_move_rule@2 - 1, Threefold_repetition_rule@2}} end; {some, _} -> erlang:error(#{gleam_error => panic, message => <<"Undoing En Passant Move: Trying to undo a move in a finished game"/utf8>>, module => <<"game"/utf8>>, function => <<"undo_move"/utf8>>, line => 4962}) end, New_game_state@11 = erlang:setelement( 11, erlang:setelement( 10, erlang:setelement( 9, erlang:setelement( 8, erlang:setelement( 7, erlang:setelement( 5, erlang:setelement( 6, erlang:setelement( 4, erlang:setelement( 3, New_game_state@10, New_turn@2 ), New_history@2 ), New_ply@2 ), New_status@2 ), New_white_kingside_castle@2 ), New_white_queenside_castle@2 ), New_black_kingside_castle@2 ), New_black_queenside_castle@2 ), {some, New_en_passant@2} ), {ok, New_game_state@11} end ) end end; {some, _} -> {ok, Game} end. -spec print_board(game()) -> {ok, binary()} | {error, binary()}. print_board(Game) -> gleam@result:'try'( bitboard_repr_to_map_repr(erlang:element(2, Game)), fun(Board_map) -> gleam@io:print(<<"\n"/utf8>>), gleam@io:print(<<"\n"/utf8>>), gleam@io:print(<<" +---+---+---+---+---+---+---+---+"/utf8>>), gleam@list:each( [{position, a, eight}, {position, b, eight}, {position, c, eight}, {position, d, eight}, {position, e, eight}, {position, f, eight}, {position, g, eight}, {position, h, eight}, {position, a, seven}, {position, b, seven}, {position, c, seven}, {position, d, seven}, {position, e, seven}, {position, f, seven}, {position, g, seven}, {position, h, seven}, {position, a, six}, {position, b, six}, {position, c, six}, {position, d, six}, {position, e, six}, {position, f, six}, {position, g, six}, {position, h, six}, {position, a, five}, {position, b, five}, {position, c, five}, {position, d, five}, {position, e, five}, {position, f, five}, {position, g, five}, {position, h, five}, {position, a, four}, {position, b, four}, {position, c, four}, {position, d, four}, {position, e, four}, {position, f, four}, {position, g, four}, {position, h, four}, {position, a, three}, {position, b, three}, {position, c, three}, {position, d, three}, {position, e, three}, {position, f, three}, {position, g, three}, {position, h, three}, {position, a, two}, {position, b, two}, {position, c, two}, {position, d, two}, {position, e, two}, {position, f, two}, {position, g, two}, {position, h, two}, {position, a, one}, {position, b, one}, {position, c, one}, {position, d, one}, {position, e, one}, {position, f, one}, {position, g, one}, {position, h, one}], fun(Pos) -> Piece_to_print = gleam@result:unwrap( gleam@dict:get(Board_map, Pos), none ), case erlang:element(2, Pos) of a -> gleam@io:print(<<"\n"/utf8>>), gleam@io:print( <<<<" "/utf8, (gleam@int:to_string( position:rank_to_int( erlang:element(3, Pos) ) + 1 ))/binary>>/binary, " | "/utf8>> ), gleam@io:print(case Piece_to_print of {some, {piece, white, pawn}} -> <<"♙"/utf8>>; {some, {piece, white, knight}} -> <<"♘"/utf8>>; {some, {piece, white, bishop}} -> <<"♗"/utf8>>; {some, {piece, white, rook}} -> <<"♖"/utf8>>; {some, {piece, white, queen}} -> <<"♕"/utf8>>; {some, {piece, white, king}} -> <<"♔"/utf8>>; {some, {piece, black, pawn}} -> <<"♟"/utf8>>; {some, {piece, black, knight}} -> <<"♞"/utf8>>; {some, {piece, black, bishop}} -> <<"♝"/utf8>>; {some, {piece, black, rook}} -> <<"♜"/utf8>>; {some, {piece, black, queen}} -> <<"♛"/utf8>>; {some, {piece, black, king}} -> <<"♚"/utf8>>; none -> <<" "/utf8>> end), gleam@io:print(<<" | "/utf8>>); h -> gleam@io:print(case Piece_to_print of {some, {piece, white, pawn}} -> <<"♙"/utf8>>; {some, {piece, white, knight}} -> <<"♘"/utf8>>; {some, {piece, white, bishop}} -> <<"♗"/utf8>>; {some, {piece, white, rook}} -> <<"♖"/utf8>>; {some, {piece, white, queen}} -> <<"♕"/utf8>>; {some, {piece, white, king}} -> <<"♔"/utf8>>; {some, {piece, black, pawn}} -> <<"♟"/utf8>>; {some, {piece, black, knight}} -> <<"♞"/utf8>>; {some, {piece, black, bishop}} -> <<"♝"/utf8>>; {some, {piece, black, rook}} -> <<"♜"/utf8>>; {some, {piece, black, queen}} -> <<"♛"/utf8>>; {some, {piece, black, king}} -> <<"♚"/utf8>>; none -> <<" "/utf8>> end), gleam@io:print(<<" | "/utf8>>), gleam@io:print(<<"\n"/utf8>>), gleam@io:print( <<" +---+---+---+---+---+---+---+---+"/utf8>> ); _ -> gleam@io:print(case Piece_to_print of {some, {piece, white, pawn}} -> <<"♙"/utf8>>; {some, {piece, white, knight}} -> <<"♘"/utf8>>; {some, {piece, white, bishop}} -> <<"♗"/utf8>>; {some, {piece, white, rook}} -> <<"♖"/utf8>>; {some, {piece, white, queen}} -> <<"♕"/utf8>>; {some, {piece, white, king}} -> <<"♔"/utf8>>; {some, {piece, black, pawn}} -> <<"♟"/utf8>>; {some, {piece, black, knight}} -> <<"♞"/utf8>>; {some, {piece, black, bishop}} -> <<"♝"/utf8>>; {some, {piece, black, rook}} -> <<"♜"/utf8>>; {some, {piece, black, queen}} -> <<"♛"/utf8>>; {some, {piece, black, king}} -> <<"♚"/utf8>>; none -> <<" "/utf8>> end), gleam@io:print(<<" | "/utf8>>) end end ), gleam@io:print(<<"\n"/utf8>>), gleam@io:print(<<" a b c d e f g h\n"/utf8>>), {ok, <<"Successfully Printed Board"/utf8>>} end ). -spec print_board_from_fen(binary()) -> {ok, binary()} | {error, binary()}. print_board_from_fen(Fen) -> Parsed_fen = fen:from_string(Fen), gleam@result:'try'( bitboard_repr_to_map_repr(erlang:element(2, Parsed_fen)), fun(Board_map) -> gleam@io:print(<<"\n"/utf8>>), gleam@io:print(<<" +---+---+---+---+---+---+---+---+"/utf8>>), gleam@list:each( [{position, a, eight}, {position, b, eight}, {position, c, eight}, {position, d, eight}, {position, e, eight}, {position, f, eight}, {position, g, eight}, {position, h, eight}, {position, a, seven}, {position, b, seven}, {position, c, seven}, {position, d, seven}, {position, e, seven}, {position, f, seven}, {position, g, seven}, {position, h, seven}, {position, a, six}, {position, b, six}, {position, c, six}, {position, d, six}, {position, e, six}, {position, f, six}, {position, g, six}, {position, h, six}, {position, a, five}, {position, b, five}, {position, c, five}, {position, d, five}, {position, e, five}, {position, f, five}, {position, g, five}, {position, h, five}, {position, a, four}, {position, b, four}, {position, c, four}, {position, d, four}, {position, e, four}, {position, f, four}, {position, g, four}, {position, h, four}, {position, a, three}, {position, b, three}, {position, c, three}, {position, d, three}, {position, e, three}, {position, f, three}, {position, g, three}, {position, h, three}, {position, a, two}, {position, b, two}, {position, c, two}, {position, d, two}, {position, e, two}, {position, f, two}, {position, g, two}, {position, h, two}, {position, a, one}, {position, b, one}, {position, c, one}, {position, d, one}, {position, e, one}, {position, f, one}, {position, g, one}, {position, h, one}], fun(Pos) -> Piece_to_print = gleam@result:unwrap( gleam@dict:get(Board_map, Pos), none ), case erlang:element(2, Pos) of a -> gleam@io:print(<<"\n"/utf8>>), gleam@io:print( <<<<" "/utf8, (gleam@int:to_string( position:rank_to_int( erlang:element(3, Pos) ) + 1 ))/binary>>/binary, " | "/utf8>> ), gleam@io:print(case Piece_to_print of {some, {piece, white, pawn}} -> <<"♙"/utf8>>; {some, {piece, white, knight}} -> <<"♘"/utf8>>; {some, {piece, white, bishop}} -> <<"♗"/utf8>>; {some, {piece, white, rook}} -> <<"♖"/utf8>>; {some, {piece, white, queen}} -> <<"♕"/utf8>>; {some, {piece, white, king}} -> <<"♔"/utf8>>; {some, {piece, black, pawn}} -> <<"♟"/utf8>>; {some, {piece, black, knight}} -> <<"♞"/utf8>>; {some, {piece, black, bishop}} -> <<"♝"/utf8>>; {some, {piece, black, rook}} -> <<"♜"/utf8>>; {some, {piece, black, queen}} -> <<"♛"/utf8>>; {some, {piece, black, king}} -> <<"♚"/utf8>>; none -> <<" "/utf8>> end), gleam@io:print(<<" | "/utf8>>); h -> gleam@io:print(case Piece_to_print of {some, {piece, white, pawn}} -> <<"♙"/utf8>>; {some, {piece, white, knight}} -> <<"♘"/utf8>>; {some, {piece, white, bishop}} -> <<"♗"/utf8>>; {some, {piece, white, rook}} -> <<"♖"/utf8>>; {some, {piece, white, queen}} -> <<"♕"/utf8>>; {some, {piece, white, king}} -> <<"♔"/utf8>>; {some, {piece, black, pawn}} -> <<"♟"/utf8>>; {some, {piece, black, knight}} -> <<"♞"/utf8>>; {some, {piece, black, bishop}} -> <<"♝"/utf8>>; {some, {piece, black, rook}} -> <<"♜"/utf8>>; {some, {piece, black, queen}} -> <<"♛"/utf8>>; {some, {piece, black, king}} -> <<"♚"/utf8>>; none -> <<" "/utf8>> end), gleam@io:print(<<" | "/utf8>>), gleam@io:print(<<"\n"/utf8>>), gleam@io:print( <<" +---+---+---+---+---+---+---+---+"/utf8>> ); _ -> gleam@io:print(case Piece_to_print of {some, {piece, white, pawn}} -> <<"♙"/utf8>>; {some, {piece, white, knight}} -> <<"♘"/utf8>>; {some, {piece, white, bishop}} -> <<"♗"/utf8>>; {some, {piece, white, rook}} -> <<"♖"/utf8>>; {some, {piece, white, queen}} -> <<"♕"/utf8>>; {some, {piece, white, king}} -> <<"♔"/utf8>>; {some, {piece, black, pawn}} -> <<"♟"/utf8>>; {some, {piece, black, knight}} -> <<"♞"/utf8>>; {some, {piece, black, bishop}} -> <<"♝"/utf8>>; {some, {piece, black, rook}} -> <<"♜"/utf8>>; {some, {piece, black, queen}} -> <<"♛"/utf8>>; {some, {piece, black, king}} -> <<"♚"/utf8>>; none -> <<" "/utf8>> end), gleam@io:print(<<" | "/utf8>>) end end ), gleam@io:print(<<"\n"/utf8>>), gleam@io:print(<<" a b c d e f g h\n"/utf8>>), {ok, <<"Successfully printed board"/utf8>>} end ). -spec generate_en_passant_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_en_passant_pseudo_legal_move_list(Color, Game) -> case erlang:element(11, Game) of none -> {ok, []}; {some, Ep_position} -> Ep_bitboard = position:to_bitboard(Ep_position), Pawn_bitboard = pawn_squares(Color, erlang:element(2, Game)), Ep_attacker_bitboard = case Color of white -> West_east_attacker_bb = bitboard:'and'( bitboard:'and'( bitboard:shift_right(Ep_bitboard, 7), Pawn_bitboard ), 2#1111111011111110111111101111111011111110111111101111111011111110 ), East_west_attacker_bb = bitboard:'and'( bitboard:'and'( bitboard:shift_right(Ep_bitboard, 9), Pawn_bitboard ), 2#0111111101111111011111110111111101111111011111110111111101111111 ), bitboard:'or'(West_east_attacker_bb, East_west_attacker_bb); black -> West_east_attacker_bb@1 = bitboard:'and'( bitboard:'and'( bitboard:shift_left(Ep_bitboard, 7), Pawn_bitboard ), 2#0111111101111111011111110111111101111111011111110111111101111111 ), East_west_attacker_bb@1 = bitboard:'and'( bitboard:'and'( bitboard:shift_left(Ep_bitboard, 9), Pawn_bitboard ), 2#1111111011111110111111101111111011111110111111101111111011111110 ), bitboard:'or'( West_east_attacker_bb@1, East_west_attacker_bb@1 ) end, gleam@result:'try'( board:get_positions(Ep_attacker_bitboard), fun(Ep_attacker_positions) -> Ep_moves = gleam@list:map( Ep_attacker_positions, fun(Position) -> {en_passant, Position, Ep_position} end ), {ok, Ep_moves} end ) end. -spec generate_king_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_king_pseudo_legal_move_list(Color, Game) -> King_bitboard = case Color of white -> erlang:element(8, erlang:element(2, Game)); black -> erlang:element(2, erlang:element(2, Game)) end, gleam@result:'try'( board:get_positions(King_bitboard), fun(King_origin_squares) -> gleam@list:fold( King_origin_squares, {ok, []}, fun(Collector, Origin) -> King_bitboard@1 = board:from_position(Origin), North_west_north_east_target_squares = bitboard:'or'( bitboard:'and'( bitboard:shift_left(King_bitboard@1, 9), 2#1111111011111110111111101111111011111110111111101111111011111110 ), bitboard:'and'( bitboard:shift_left(King_bitboard@1, 7), 2#0111111101111111011111110111111101111111011111110111111101111111 ) ), South_west_south_east_target_squares = bitboard:'or'( bitboard:'and'( bitboard:shift_right(King_bitboard@1, 9), 2#0111111101111111011111110111111101111111011111110111111101111111 ), bitboard:'and'( bitboard:shift_right(King_bitboard@1, 7), 2#1111111011111110111111101111111011111110111111101111111011111110 ) ), West_east_target_squares = bitboard:'or'( bitboard:'and'( bitboard:shift_left(King_bitboard@1, 1), 2#1111111011111110111111101111111011111110111111101111111011111110 ), bitboard:'and'( bitboard:shift_right(King_bitboard@1, 1), 2#0111111101111111011111110111111101111111011111110111111101111111 ) ), North_south_target_squares = bitboard:'or'( bitboard:shift_left(King_bitboard@1, 8), bitboard:shift_right(King_bitboard@1, 8) ), King_target_squares = bitboard:'or'( bitboard:'or'( North_west_north_east_target_squares, South_west_south_east_target_squares ), bitboard:'or'( West_east_target_squares, North_south_target_squares ) ), List_of_friendly_piece_bitboards = case Color of white -> [erlang:element(8, erlang:element(2, Game)), erlang:element(9, erlang:element(2, Game)), erlang:element(10, erlang:element(2, Game)), erlang:element(11, erlang:element(2, Game)), erlang:element(12, erlang:element(2, Game)), erlang:element(13, erlang:element(2, Game))]; black -> [erlang:element(2, erlang:element(2, Game)), erlang:element(3, erlang:element(2, Game)), erlang:element(4, erlang:element(2, Game)), erlang:element(5, erlang:element(2, Game)), erlang:element(6, erlang:element(2, Game)), erlang:element(7, erlang:element(2, Game))] end, Friendly_pieces = gleam@list:fold( List_of_friendly_piece_bitboards, 0, fun(Collector@1, Next) -> bitboard:'or'(Collector@1, Next) end ), King_unblocked_target_square_bb = bitboard:'and'( King_target_squares, bitboard:'not'(Friendly_pieces) ), Captures = case Color of white -> bitboard:'and'( King_unblocked_target_square_bb, occupied_squares_black(erlang:element(2, Game)) ); black -> bitboard:'and'( King_unblocked_target_square_bb, occupied_squares_white(erlang:element(2, Game)) ) end, Simple_moves = case Color of white -> bitboard:exclusive_or( King_unblocked_target_square_bb, Captures ); black -> bitboard:exclusive_or( King_unblocked_target_square_bb, Captures ) end, gleam@result:'try'( board:get_positions(Simple_moves), fun(Simple_moves_positions) -> Simple_moves@1 = gleam@list:map( Simple_moves_positions, fun(Dest) -> {normal, Origin, Dest, none} end ), gleam@result:'try'( board:get_positions(Captures), fun(Captures_positions) -> Captures@1 = gleam@list:map( Captures_positions, fun(Dest@1) -> {normal, Origin, Dest@1, none} end ), All_moves = gleam@list:append( Simple_moves@1, Captures@1 ), gleam@result:'try'( Collector, fun(Collector@2) -> {ok, gleam@list:append( Collector@2, All_moves )} end ) end ) end ) end ) end ). -spec generate_knight_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_knight_pseudo_legal_move_list(Color, Game) -> Knight_bitboard = case Color of white -> erlang:element(12, erlang:element(2, Game)); black -> erlang:element(6, erlang:element(2, Game)) end, gleam@result:'try'( board:get_positions(Knight_bitboard), fun(Knight_origin_squares) -> gleam@list:fold( Knight_origin_squares, {ok, []}, fun(Collector, Origin) -> Knight_bitboard@1 = board:from_position(Origin), North_target_squares = bitboard:'or'( bitboard:'and'( bitboard:shift_left(Knight_bitboard@1, 17), 2#1111111011111110111111101111111011111110111111101111111011111110 ), bitboard:'and'( bitboard:shift_left(Knight_bitboard@1, 15), 2#0111111101111111011111110111111101111111011111110111111101111111 ) ), South_target_squares = bitboard:'or'( bitboard:'and'( bitboard:shift_right(Knight_bitboard@1, 17), 2#0111111101111111011111110111111101111111011111110111111101111111 ), bitboard:'and'( bitboard:shift_right(Knight_bitboard@1, 15), 2#1111111011111110111111101111111011111110111111101111111011111110 ) ), West_target_squares = bitboard:'or'( bitboard:'and'( bitboard:'and'( bitboard:shift_right(Knight_bitboard@1, 10), 2#0111111101111111011111110111111101111111011111110111111101111111 ), 2#1011111110111111101111111011111110111111101111111011111110111111 ), bitboard:'and'( bitboard:'and'( bitboard:shift_left(Knight_bitboard@1, 6), 2#0111111101111111011111110111111101111111011111110111111101111111 ), 2#1011111110111111101111111011111110111111101111111011111110111111 ) ), East_target_squares = bitboard:'or'( bitboard:'and'( bitboard:'and'( bitboard:shift_right(Knight_bitboard@1, 6), 2#1111111011111110111111101111111011111110111111101111111011111110 ), 2#1111110111111101111111011111110111111101111111011111110111111101 ), bitboard:'and'( bitboard:'and'( bitboard:shift_left(Knight_bitboard@1, 10), 2#1111111011111110111111101111111011111110111111101111111011111110 ), 2#1111110111111101111111011111110111111101111111011111110111111101 ) ), Knight_target_squares = bitboard:'or'( bitboard:'or'( North_target_squares, South_target_squares ), bitboard:'or'(West_target_squares, East_target_squares) ), List_of_friendly_piece_bitboards = case Color of white -> [erlang:element(8, erlang:element(2, Game)), erlang:element(9, erlang:element(2, Game)), erlang:element(10, erlang:element(2, Game)), erlang:element(11, erlang:element(2, Game)), erlang:element(12, erlang:element(2, Game)), erlang:element(13, erlang:element(2, Game))]; black -> [erlang:element(2, erlang:element(2, Game)), erlang:element(3, erlang:element(2, Game)), erlang:element(4, erlang:element(2, Game)), erlang:element(5, erlang:element(2, Game)), erlang:element(6, erlang:element(2, Game)), erlang:element(7, erlang:element(2, Game))] end, Friendly_pieces = gleam@list:fold( List_of_friendly_piece_bitboards, 0, fun(Collector@1, Next) -> bitboard:'or'(Collector@1, Next) end ), Knight_unblocked_target_square_bb = bitboard:'and'( Knight_target_squares, bitboard:'not'(Friendly_pieces) ), Captures = case Color of white -> bitboard:'and'( Knight_unblocked_target_square_bb, occupied_squares_black(erlang:element(2, Game)) ); black -> bitboard:'and'( Knight_unblocked_target_square_bb, occupied_squares_white(erlang:element(2, Game)) ) end, Simple_moves = case Color of white -> bitboard:exclusive_or( Knight_unblocked_target_square_bb, Captures ); black -> bitboard:exclusive_or( Knight_unblocked_target_square_bb, Captures ) end, gleam@result:'try'( board:get_positions(Simple_moves), fun(Simple_moves_positions) -> Simple_moves@1 = gleam@list:map( Simple_moves_positions, fun(Dest) -> {normal, Origin, Dest, none} end ), gleam@result:'try'( board:get_positions(Captures), fun(Captures_positions) -> Captures@1 = gleam@list:map( Captures_positions, fun(Dest@1) -> {normal, Origin, Dest@1, none} end ), All_moves = gleam@list:append( Simple_moves@1, Captures@1 ), gleam@result:'try'( Collector, fun(Collector@2) -> {ok, gleam@list:append( Collector@2, All_moves )} end ) end ) end ) end ) end ). -spec generate_pawn_attack_set(integer(), color:color()) -> integer(). generate_pawn_attack_set(Pawn_bitboard, Color) -> case Color of white -> East_attack = bitboard:'and'( bitboard:shift_left(Pawn_bitboard, 9), 2#1111111011111110111111101111111011111110111111101111111011111110 ), West_attack = bitboard:'and'( bitboard:shift_left(Pawn_bitboard, 7), 2#0111111101111111011111110111111101111111011111110111111101111111 ), All_attacks = bitboard:'or'(East_attack, West_attack), All_attacks; black -> East_attack@1 = bitboard:'and'( bitboard:shift_right(Pawn_bitboard, 7), 2#1111111011111110111111101111111011111110111111101111111011111110 ), West_attack@1 = bitboard:'and'( bitboard:shift_right(Pawn_bitboard, 9), 2#0111111101111111011111110111111101111111011111110111111101111111 ), All_attacks@1 = bitboard:'or'(East_attack@1, West_attack@1), All_attacks@1 end. -spec generate_pawn_capture_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_pawn_capture_move_list(Color, Game) -> Pawn_attack_set = case Color of white -> generate_pawn_attack_set( erlang:element(13, erlang:element(2, Game)), Color ); black -> generate_pawn_attack_set( erlang:element(7, erlang:element(2, Game)), Color ) end, generate_pawn_attack_set(erlang:element(13, erlang:element(2, Game)), Color), List_of_enemy_piece_bitboards = case Color of white -> [erlang:element(2, erlang:element(2, Game)), erlang:element(3, erlang:element(2, Game)), erlang:element(4, erlang:element(2, Game)), erlang:element(5, erlang:element(2, Game)), erlang:element(6, erlang:element(2, Game)), erlang:element(7, erlang:element(2, Game))]; black -> [erlang:element(8, erlang:element(2, Game)), erlang:element(9, erlang:element(2, Game)), erlang:element(10, erlang:element(2, Game)), erlang:element(11, erlang:element(2, Game)), erlang:element(12, erlang:element(2, Game)), erlang:element(13, erlang:element(2, Game))] end, Enemy_pieces = gleam@list:fold( List_of_enemy_piece_bitboards, 0, fun(Collector, Next) -> bitboard:'or'(Collector, Next) end ), Pawn_capture_destination_set = bitboard:'and'(Pawn_attack_set, Enemy_pieces), {East_origins@2, West_origins@2} = case Color of white -> East_origins = bitboard:'and'( bitboard:shift_right(Pawn_capture_destination_set, 9), 2#0111111101111111011111110111111101111111011111110111111101111111 ), West_origins = bitboard:'and'( bitboard:shift_right(Pawn_capture_destination_set, 7), 2#1111111011111110111111101111111011111110111111101111111011111110 ), {bitboard:'and'( East_origins, erlang:element(13, erlang:element(2, Game)) ), bitboard:'and'( West_origins, erlang:element(13, erlang:element(2, Game)) )}; black -> West_origins@1 = bitboard:'and'( bitboard:shift_left(Pawn_capture_destination_set, 9), 2#1111111011111110111111101111111011111110111111101111111011111110 ), East_origins@1 = bitboard:'and'( bitboard:shift_left(Pawn_capture_destination_set, 7), 2#0111111101111111011111110111111101111111011111110111111101111111 ), {bitboard:'and'( East_origins@1, erlang:element(7, erlang:element(2, Game)) ), bitboard:'and'( West_origins@1, erlang:element(7, erlang:element(2, Game)) )} end, Pawn_capture_origin_set = bitboard:'or'(East_origins@2, West_origins@2), gleam@result:'try'( board:get_positions(Pawn_capture_origin_set), fun(Pawn_capture_origin_list) -> gleam@result:'try'( board:get_positions(Pawn_capture_destination_set), fun(Pawn_capture_destination_list) -> Pawn_capture_move_list = gleam@list:fold( Pawn_capture_origin_list, {ok, []}, fun(Collector@1, Position) -> gleam@result:'try'(case Color of white -> board:get_positions( bitboard:'and'( bitboard:shift_left( position:to_bitboard( Position ), 9 ), 2#1111111011111110111111101111111011111110111111101111111011111110 ) ); black -> board:get_positions( bitboard:'and'( bitboard:shift_right( position:to_bitboard( Position ), 7 ), 2#1111111011111110111111101111111011111110111111101111111011111110 ) ) end, fun(East_attack) -> East_moves@2 = case East_attack of [] -> []; [East_attack@1] -> East_attack_in_dest_list = gleam@list:contains( Pawn_capture_destination_list, East_attack@1 ), East_moves@1 = case East_attack_in_dest_list of false -> []; true -> East_moves = case East_attack@1 of {position, _, eight} when Color =:= white -> [{normal, Position, East_attack@1, {some, {piece, Color, queen}}}, {normal, Position, East_attack@1, {some, {piece, Color, rook}}}, {normal, Position, East_attack@1, {some, {piece, Color, bishop}}}, {normal, Position, East_attack@1, {some, {piece, Color, knight}}}]; {position, _, one} when Color =:= black -> [{normal, Position, East_attack@1, {some, {piece, Color, queen}}}, {normal, Position, East_attack@1, {some, {piece, Color, rook}}}, {normal, Position, East_attack@1, {some, {piece, Color, bishop}}}, {normal, Position, East_attack@1, {some, {piece, Color, knight}}}]; _ -> [{normal, Position, East_attack@1, none}] end, East_moves end, East_moves@1; _ -> erlang:error(#{gleam_error => panic, message => <<"panic expression evaluated"/utf8>>, module => <<"game"/utf8>>, function => <<"generate_pawn_capture_move_list"/utf8>>, line => 3380}) end, gleam@result:'try'(case Color of white -> board:get_positions( bitboard:'and'( bitboard:shift_left( position:to_bitboard( Position ), 7 ), 2#0111111101111111011111110111111101111111011111110111111101111111 ) ); black -> board:get_positions( bitboard:'and'( bitboard:shift_right( position:to_bitboard( Position ), 9 ), 2#0111111101111111011111110111111101111111011111110111111101111111 ) ) end, fun(West_attack) -> West_moves@2 = case West_attack of [] -> []; [West_attack@1] -> West_attack_in_dest_list = gleam@list:contains( Pawn_capture_destination_list, West_attack@1 ), West_moves@1 = case West_attack_in_dest_list of false -> []; true -> West_moves = case West_attack@1 of {position, _, eight} when Color =:= white -> [{normal, Position, West_attack@1, {some, {piece, Color, queen}}}, {normal, Position, West_attack@1, {some, {piece, Color, rook}}}, {normal, Position, West_attack@1, {some, {piece, Color, bishop}}}, {normal, Position, West_attack@1, {some, {piece, Color, knight}}}]; {position, _, one} when Color =:= black -> [{normal, Position, West_attack@1, {some, {piece, Color, queen}}}, {normal, Position, West_attack@1, {some, {piece, Color, rook}}}, {normal, Position, West_attack@1, {some, {piece, Color, bishop}}}, {normal, Position, West_attack@1, {some, {piece, Color, knight}}}]; _ -> [{normal, Position, West_attack@1, none}] end, West_moves end, West_moves@1; _ -> erlang:error( #{gleam_error => panic, message => <<"panic expression evaluated"/utf8>>, module => <<"game"/utf8>>, function => <<"generate_pawn_capture_move_list"/utf8>>, line => 3461} ) end, gleam@result:'try'( Collector@1, fun(Collector@2) -> {ok, gleam@list:append( gleam@list:append( Collector@2, East_moves@2 ), West_moves@2 )} end ) end) end) end ), Pawn_capture_move_list end ) end ). -spec generate_pawn_starting_rank_double_move_bitboard(color:color(), game()) -> integer(). generate_pawn_starting_rank_double_move_bitboard(Color, Game) -> case Color of white -> White_pawn_target_squares = bitboard:'and'( erlang:element(13, erlang:element(2, Game)), 2#0000000000000000000000000000000000000000000000001111111100000000 ), White_pawn_target_squares@1 = bitboard:'or'( bitboard:shift_left(White_pawn_target_squares, 16), bitboard:shift_left(White_pawn_target_squares, 8) ), Occupied_squares = occupied_squares(erlang:element(2, Game)), Moves = bitboard:'and'( Occupied_squares, White_pawn_target_squares@1 ), Moves@1 = bitboard:'or'( bitboard:shift_left( bitboard:'and'( Moves, 2#0000000000000000000000000000000000000000111111110000000000000000 ), 8 ), Moves ), Moves@2 = bitboard:exclusive_or( Moves@1, White_pawn_target_squares@1 ), Moves@3 = bitboard:'and'( Moves@2, bitboard:'not'( 2#0000000000000000000000000000000000000000111111110000000000000000 ) ), Moves@3; black -> Black_pawn_target_squares = bitboard:'and'( erlang:element(7, erlang:element(2, Game)), 2#0000000011111111000000000000000000000000000000000000000000000000 ), Black_pawn_target_squares@1 = bitboard:'or'( bitboard:shift_right(Black_pawn_target_squares, 16), bitboard:shift_right(Black_pawn_target_squares, 8) ), Occupied_squares@1 = occupied_squares(erlang:element(2, Game)), Moves@4 = bitboard:'and'( Occupied_squares@1, Black_pawn_target_squares@1 ), Moves@5 = bitboard:'or'( bitboard:shift_right( bitboard:'and'( Moves@4, 2#0000000000000000111111110000000000000000000000000000000000000000 ), 8 ), Moves@4 ), Moves@6 = bitboard:exclusive_or( Moves@5, Black_pawn_target_squares@1 ), Moves@7 = bitboard:'and'( Moves@6, bitboard:'not'( 2#0000000000000000111111110000000000000000000000000000000000000000 ) ), Moves@7 end. -spec generate_pawn_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_pawn_pseudo_legal_move_list(Color, Game) -> gleam@result:'try'( generate_pawn_capture_move_list(Color, Game), fun(Capture_list) -> Moves_no_captures = generate_pawn_non_capture_move_bitboard( Color, Game ), gleam@result:'try'( board:get_positions(Moves_no_captures), fun(Non_capture_dest_list) -> Non_capture_move_list = gleam@list:fold( Non_capture_dest_list, [], fun(Acc, Dest) -> Origin = position:get_rear_position(Dest, Color), Moves = case Dest of {position, _, eight} when Color =:= white -> [{normal, Origin, Dest, {some, {piece, Color, queen}}}, {normal, Origin, Dest, {some, {piece, Color, rook}}}, {normal, Origin, Dest, {some, {piece, Color, bishop}}}, {normal, Origin, Dest, {some, {piece, Color, knight}}}]; {position, _, one} when Color =:= black -> [{normal, Origin, Dest, {some, {piece, Color, queen}}}, {normal, Origin, Dest, {some, {piece, Color, rook}}}, {normal, Origin, Dest, {some, {piece, Color, bishop}}}, {normal, Origin, Dest, {some, {piece, Color, knight}}}]; _ -> [{normal, Origin, Dest, none}] end, gleam@list:append(Acc, Moves) end ), Initial_rank_double_move_list = generate_pawn_starting_rank_double_move_bitboard( Color, Game ), gleam@result:'try'( board:get_positions(Initial_rank_double_move_list), fun(Initial_rank_double_dest_list) -> Initial_rank_double_move_list@1 = gleam@list:map( Initial_rank_double_dest_list, fun(Dest@1) -> case Color of white -> case erlang:element(2, Dest@1) of a -> {normal, {position, a, two}, Dest@1, none}; b -> {normal, {position, b, two}, Dest@1, none}; c -> {normal, {position, c, two}, Dest@1, none}; d -> {normal, {position, d, two}, Dest@1, none}; e -> {normal, {position, e, two}, Dest@1, none}; f -> {normal, {position, f, two}, Dest@1, none}; g -> {normal, {position, g, two}, Dest@1, none}; h -> {normal, {position, h, two}, Dest@1, none} end; black -> case erlang:element(2, Dest@1) of a -> {normal, {position, a, seven}, Dest@1, none}; b -> {normal, {position, b, seven}, Dest@1, none}; c -> {normal, {position, c, seven}, Dest@1, none}; d -> {normal, {position, d, seven}, Dest@1, none}; e -> {normal, {position, e, seven}, Dest@1, none}; f -> {normal, {position, f, seven}, Dest@1, none}; g -> {normal, {position, g, seven}, Dest@1, none}; h -> {normal, {position, h, seven}, Dest@1, none} end end end ), {ok, gleam@list:append( gleam@list:append( Capture_list, Non_capture_move_list ), Initial_rank_double_move_list@1 )} end ) end ) end ). -spec is_king_in_check(game(), color:color()) -> {ok, boolean()} | {error, binary()}. is_king_in_check(Game, Color) -> Enemy_color = (case Color of white -> black; black -> white end), gleam@result:'try'( begin King_bb = case Color of white -> erlang:element(8, erlang:element(2, Game)); black -> erlang:element(2, erlang:element(2, Game)) end, gleam@result:'try'(case board:get_positions(King_bb) of {ok, [King_pos]} -> {ok, King_pos}; _ -> {error, <<"Invalid king position"/utf8>>} end, fun(King_pos@1) -> Rook_bb = case Color of white -> erlang:element(4, erlang:element(2, Game)); black -> erlang:element(10, erlang:element(2, Game)) end, King_rook_ray_bb = begin _pipe = bitboard:'or'( look_up_east_ray_bb(King_pos@1), look_up_west_ray_bb(King_pos@1) ), _pipe@1 = bitboard:'or'( _pipe, look_up_north_ray_bb(King_pos@1) ), bitboard:'or'(_pipe@1, look_up_south_ray_bb(King_pos@1)) end, Viable_attacking_rook_bb = bitboard:'and'( Rook_bb, King_rook_ray_bb ), gleam@result:'try'(case Viable_attacking_rook_bb of 0 -> {ok, []}; _ -> generate_rook_pseudo_legal_move_list( Enemy_color, Game ) end, fun(Rook_move_list) -> Bishop_bb = case Color of white -> erlang:element(5, erlang:element(2, Game)); black -> erlang:element(11, erlang:element(2, Game)) end, King_bishop_ray_bb = begin _pipe@2 = bitboard:'or'( look_up_north_east_ray_bb(King_pos@1), look_up_north_west_ray_bb(King_pos@1) ), _pipe@3 = bitboard:'or'( _pipe@2, look_up_south_east_ray_bb(King_pos@1) ), bitboard:'or'( _pipe@3, look_up_south_west_ray_bb(King_pos@1) ) end, Viable_attacking_bishop_bb = bitboard:'and'( Bishop_bb, King_bishop_ray_bb ), gleam@result:'try'( case Viable_attacking_bishop_bb of 0 -> {ok, []}; _ -> generate_bishop_pseudo_legal_move_list( Enemy_color, Game ) end, fun(Bishop_move_list) -> Queen_bb = case Color of white -> erlang:element( 3, erlang:element(2, Game) ); black -> erlang:element( 9, erlang:element(2, Game) ) end, King_queen_ray_bb = bitboard:'or'( King_rook_ray_bb, King_bishop_ray_bb ), Viable_attacking_queen_bb = bitboard:'and'( Queen_bb, King_queen_ray_bb ), gleam@result:'try'( case Viable_attacking_queen_bb of 0 -> {ok, []}; _ -> generate_queen_pseudo_legal_move_list( Enemy_color, Game ) end, fun(Queen_move_list) -> Knight_bb = case Color of white -> erlang:element( 6, erlang:element(2, Game) ); black -> erlang:element( 12, erlang:element(2, Game) ) end, King_knight_target_bb = look_up_knight_target_bb( King_pos@1 ), Viable_attacking_knight_bb = bitboard:'and'( Knight_bb, King_knight_target_bb ), gleam@result:'try'( case Viable_attacking_knight_bb of 0 -> {ok, []}; _ -> generate_knight_pseudo_legal_move_list( Enemy_color, Game ) end, fun(Knight_move_list) -> gleam@result:'try'( generate_pawn_pseudo_legal_move_list( Enemy_color, Game ), fun(Pawn_move_list) -> gleam@result:'try'( generate_king_pseudo_legal_move_list( Enemy_color, Game ), fun( Enemy_king_move_list ) -> List_of_move_lists = [Rook_move_list, Bishop_move_list, Queen_move_list, Knight_move_list, Pawn_move_list, Enemy_king_move_list], Move_list = gleam@list:fold( List_of_move_lists, [], fun( Collector, Next ) -> gleam@list:append( Collector, Next ) end ), {ok, Move_list} end ) end ) end ) end ) end ) end) end) end, fun(Enemy_move_list) -> gleam@result:'try'( ({ok, begin _pipe@4 = Enemy_move_list, gleam@list:filter( _pipe@4, fun(Move) -> Piece = piece_at_position( Game, erlang:element(3, Move) ), case Piece of none -> false; {some, Piece@1} -> (erlang:element(2, Piece@1) =:= Color) andalso (erlang:element(3, Piece@1) =:= king) end end ) end}), fun(Enemy_move_list@1) -> {ok, gleam@list:length(Enemy_move_list@1) > 0} end ) end ). -spec is_move_legal(game(), move:move()) -> {ok, boolean()} | {error, binary()}. is_move_legal(Game, Move) -> gleam@result:'try'( apply_move_raw(Game, Move), fun(New_game_state) -> case Move of {normal, _, _, _} -> gleam@result:'try'( is_king_in_check( New_game_state, erlang:element(3, Game) ), fun(Is_king_in_check) -> {ok, not Is_king_in_check} end ); {en_passant, _, _} -> gleam@result:'try'( is_king_in_check( New_game_state, erlang:element(3, Game) ), fun(Is_king_in_check) -> {ok, not Is_king_in_check} end ); {castle, _, To} -> gleam@result:'try'( is_king_in_check(Game, erlang:element(3, Game)), fun(Is_king_in_check_ok) -> case Is_king_in_check_ok of true -> {ok, false}; false -> gleam@result:'try'( is_king_in_check( New_game_state, erlang:element(3, Game) ), fun(Is_king_in_check_ok@1) -> case Is_king_in_check_ok@1 of true -> {ok, false}; false -> King_castling_target_square = case To of {position, g, one} -> {ok, {position, f, one}}; {position, g, eight} -> {ok, {position, f, eight}}; {position, c, one} -> {ok, {position, d, one}}; {position, c, eight} -> {ok, {position, d, eight}}; _ -> {error, <<"Invalid castle move"/utf8>>} end, case King_castling_target_square of {error, _} -> {ok, false}; {ok, King_castling_target_square@1} -> New_game_state@1 = erlang:setelement( 2, New_game_state, board:set_piece_at_position( erlang:element( 2, New_game_state ), King_castling_target_square@1, {piece, erlang:element( 3, Game ), king} ) ), gleam@result:'try'( board:remove_piece_at_position( erlang:element( 2, New_game_state@1 ), To ), fun(New_board) -> New_game_state@2 = erlang:setelement( 2, New_game_state@1, New_board ), gleam@result:'try'( is_king_in_check( New_game_state@2, erlang:element( 3, Game ) ), fun( Is_king_in_check_ok@2 ) -> case Is_king_in_check_ok@2 of true -> {ok, false}; false -> {ok, true} end end ) end ) end end end ) end end ) end end ). -spec generate_castling_pseudo_legal_move_list(color:color(), game()) -> {ok, list(move:move())} | {error, binary()}. generate_castling_pseudo_legal_move_list(Color, Game) -> King_bitboard = case Color of white -> erlang:element(8, erlang:element(2, Game)); black -> erlang:element(2, erlang:element(2, Game)) end, gleam@result:'try'(case board:get_positions(King_bitboard) of {ok, []} -> {error, <<"No king found on the board"/utf8>>}; {ok, [Position]} -> {ok, Position}; _ -> {error, <<"More than one king found on the board"/utf8>>} end, fun(King_position) -> King_position_flag = case King_position of {position, e, one} when Color =:= white -> true; {position, e, eight} when Color =:= black -> true; _ -> false end, Rook_bitboard = case Color of white -> erlang:element(10, erlang:element(2, Game)); black -> erlang:element(4, erlang:element(2, Game)) end, Queenside_rook_flag = case Color of white -> case bitboard:'and'( bitboard:'and'( Rook_bitboard, 2#0000000100000001000000010000000100000001000000010000000100000001 ), 2#0000000000000000000000000000000000000000000000000000000011111111 ) of 0 -> false; _ -> true end; black -> case bitboard:'and'( bitboard:'and'( Rook_bitboard, 2#0000000100000001000000010000000100000001000000010000000100000001 ), 2#1111111100000000000000000000000000000000000000000000000000000000 ) of 0 -> false; _ -> true end end, Kingside_rook_flag = case Color of white -> case bitboard:'and'( bitboard:'and'( Rook_bitboard, 2#1000000010000000100000001000000010000000100000001000000010000000 ), 2#0000000000000000000000000000000000000000000000000000000011111111 ) of 0 -> false; _ -> true end; black -> case bitboard:'and'( bitboard:'and'( Rook_bitboard, 2#1000000010000000100000001000000010000000100000001000000010000000 ), 2#1111111100000000000000000000000000000000000000000000000000000000 ) of 0 -> false; _ -> true end end, Queenside_clear_flag = case Color of white -> case bitboard:'and'( 2#0000000000000000000000000000000000000000000000000000000000001110, occupied_squares(erlang:element(2, Game)) ) of 0 -> true; _ -> false end; black -> case bitboard:'and'( 2#0000111000000000000000000000000000000000000000000000000000000000, occupied_squares(erlang:element(2, Game)) ) of 0 -> true; _ -> false end end, Kingside_clear_flag = case Color of white -> case bitboard:'and'( 2#0000000000000000000000000000000000000000000000000000000001100000, occupied_squares(erlang:element(2, Game)) ) of 0 -> true; _ -> false end; black -> case bitboard:'and'( 2#0110000000000000000000000000000000000000000000000000000000000000, occupied_squares(erlang:element(2, Game)) ) of 0 -> true; _ -> false end end, Queenside_castle = case Color of white -> erlang:element(8, Game); black -> erlang:element(10, Game) end, Kingside_castle = case Color of white -> erlang:element(7, Game); black -> erlang:element(9, Game) end, Castling_moves = gleam@list:append( case [Queenside_rook_flag, Queenside_clear_flag, King_position_flag] of [true, true, true] when Queenside_castle =:= yes -> case Color of white -> [{castle, King_position, {position, c, one}}]; black -> [{castle, King_position, {position, c, eight}}] end; _ -> [] end, case [Kingside_rook_flag, Kingside_clear_flag, King_position_flag] of [true, true, true] when Kingside_castle =:= yes -> case Color of white -> [{castle, King_position, {position, g, one}}]; black -> [{castle, King_position, {position, g, eight}}] end; _ -> [] end ), {ok, Castling_moves} end). -spec generate_pseudo_legal_move_list(game(), color:color()) -> {ok, list(move:move())} | {error, binary()}. generate_pseudo_legal_move_list(Game, Color) -> gleam@result:'try'( generate_queen_pseudo_legal_move_list(Color, Game), fun(Queen_pseudo_legal_move_list) -> gleam@result:'try'( generate_king_pseudo_legal_move_list(Color, Game), fun(King_pseudo_legal_move_list) -> gleam@result:'try'( generate_castling_pseudo_legal_move_list(Color, Game), fun(Castling_pseudo_legal_move_list) -> gleam@result:'try'( generate_en_passant_pseudo_legal_move_list( Color, Game ), fun(En_passant_pseudo_legal_move_list) -> gleam@result:'try'( generate_rook_pseudo_legal_move_list( Color, Game ), fun(Rook_pseudo_legal_move_list) -> gleam@result:'try'( generate_pawn_pseudo_legal_move_list( Color, Game ), fun(Pawn_pseudo_legal_move_list) -> gleam@result:'try'( generate_knight_pseudo_legal_move_list( Color, Game ), fun( Knight_pseudo_legal_move_list ) -> gleam@result:'try'( generate_bishop_pseudo_legal_move_list( Color, Game ), fun( Bishop_pseudo_legal_move_list ) -> List_of_move_lists = [Rook_pseudo_legal_move_list, Bishop_pseudo_legal_move_list, Knight_pseudo_legal_move_list, Pawn_pseudo_legal_move_list, Queen_pseudo_legal_move_list, King_pseudo_legal_move_list, Castling_pseudo_legal_move_list, En_passant_pseudo_legal_move_list], Move_list = gleam@list:fold( List_of_move_lists, [], fun( Collector, Next ) -> gleam@list:append( Collector, Next ) end ), {ok, Move_list} end ) end ) end ) end ) end ) end ) end ) end ). -spec all_legal_moves(game()) -> {ok, list(move:move())} | {error, binary()}. all_legal_moves(Game) -> case erlang:element(5, Game) of {some, {in_progress, _, _}} -> Legal_moves = (gleam@result:'try'( generate_pseudo_legal_move_list(Game, erlang:element(3, Game)), fun(Pseudo_legal_move_list) -> {ok, begin _pipe = Pseudo_legal_move_list, gleam@list:filter( _pipe, fun(Move) -> case is_move_legal(Game, Move) of {ok, Legality} -> Legality; {error, _} -> false end end ) end} end )), Legal_moves; none -> Legal_moves = (gleam@result:'try'( generate_pseudo_legal_move_list(Game, erlang:element(3, Game)), fun(Pseudo_legal_move_list) -> {ok, begin _pipe = Pseudo_legal_move_list, gleam@list:filter( _pipe, fun(Move) -> case is_move_legal(Game, Move) of {ok, Legality} -> Legality; {error, _} -> false end end ) end} end )), Legal_moves; {some, _} -> {ok, []} end. -spec has_moves(game()) -> {ok, boolean()} | {error, binary()}. has_moves(Game) -> gleam@result:'try'( all_legal_moves(Game), fun(Move_list) -> {ok, not gleam@list:is_empty(Move_list)} end ). -spec apply_move(game(), move:move()) -> {ok, game()} | {error, binary()}. apply_move(Game, Move) -> case erlang:element(5, Game) of none -> gleam@result:'try'( (gleam@result:'try'( generate_pseudo_legal_move_list( Game, erlang:element(3, Game) ), fun(Pseudo_legal_move_list) -> {ok, begin _pipe = Pseudo_legal_move_list, gleam@list:filter( _pipe, fun(Move@1) -> case is_move_legal(Game, Move@1) of {ok, Legality} -> Legality; {error, _} -> false end end ) end} end )), fun(Legal_moves) -> New_game_state@1 = case gleam@list:contains( Legal_moves, Move ) of true -> New_game_state = apply_move_raw(Game, Move), New_game_state; false -> {ok, Game} end, New_game_state@1 end ); {some, {in_progress, _, _}} -> gleam@result:'try'( (gleam@result:'try'( generate_pseudo_legal_move_list( Game, erlang:element(3, Game) ), fun(Pseudo_legal_move_list@1) -> {ok, begin _pipe@1 = Pseudo_legal_move_list@1, gleam@list:filter( _pipe@1, fun(Move@2) -> case is_move_legal(Game, Move@2) of {ok, Legality@1} -> Legality@1; {error, _} -> false end end ) end} end )), fun(Legal_moves@1) -> New_game_state@3 = case gleam@list:contains( Legal_moves@1, Move ) of true -> New_game_state@2 = apply_move_raw(Game, Move), New_game_state@2; false -> {ok, Game} end, gleam@result:'try'( New_game_state@3, fun(New_game_state@4) -> gleam@result:'try'( has_moves(New_game_state@4), fun(Has_moves) -> gleam@result:'try'( is_king_in_check( New_game_state@4, erlang:element(3, New_game_state@4) ), fun(Is_king_in_check) -> New_game_state@6 = case [Is_king_in_check, Has_moves] of [true, false] -> Winner = case erlang:element( 3, New_game_state@4 ) of white -> black; black -> white end, {ok, erlang:setelement( 5, New_game_state@4, {some, {win, Winner, <<"Checkmate"/utf8>>}} )}; [true, true] -> New_status@2 = case Move of {normal, From, To, _} -> gleam@result:'try'( case board:get_piece_at_position( erlang:element( 2, Game ), From ) of {some, Piece} -> {ok, Piece}; none -> {error, <<"no piece at from position"/utf8>>} end, fun( Moving_piece ) -> case erlang:element( 5, Game ) of none -> {ok, none}; {some, {in_progress, Fifty_move_rule, Threefold_repetition_rule}} -> Captured_piece = piece_at_position( Game, To ), New_fifty_move_rule = case Captured_piece of {some, _} -> 0; none -> case Moving_piece of {piece, _, pawn} -> 0; _ -> Fifty_move_rule + 1 end end, New_status = case (New_fifty_move_rule div 2) + 1 of 50 -> {some, {draw, fifty_move_rule}}; _ -> {some, {in_progress, New_fifty_move_rule, Threefold_repetition_rule}} end, {New_threefold_repetition_rule@3, Count@2} = case Captured_piece of {some, _} -> {Threefold_repetition_rule, 0}; none -> New_threefold_position = {three_fold_position, erlang:element( 3, Game ), erlang:element( 2, Game ), erlang:element( 11, Game ), erlang:element( 7, Game ), erlang:element( 8, Game ), erlang:element( 9, Game ), erlang:element( 10, Game )}, {New_threefold_repetition_rule@2, Count@1} = case gleam@dict:get( Threefold_repetition_rule, New_threefold_position ) of {error, _} -> New_threefold_repetition_rule = gleam@dict:insert( Threefold_repetition_rule, New_threefold_position, 1 ), {New_threefold_repetition_rule, 1}; {ok, Count} -> New_threefold_repetition_rule@1 = gleam@dict:insert( Threefold_repetition_rule, New_threefold_position, Count + 1 ), {New_threefold_repetition_rule@1, Count + 1} end, {New_threefold_repetition_rule@2, Count@1} end, New_status@1 = case New_status of {some, {in_progress, Fifty_move_rule@1, _}} -> case Count@2 of 3 -> {some, {draw, threefold_repetition}}; _ -> {some, {in_progress, Fifty_move_rule@1, New_threefold_repetition_rule@3}} end; _ -> New_status end, {ok, New_status@1}; {some, _} -> {error, <<"game is over, unable to apply moves to board"/utf8>>} end end ); {castle, _, _} -> case erlang:element( 5, Game ) of none -> {ok, none}; {some, {in_progress, Fifty_move_rule@2, Threefold_repetition_rule@1}} -> New_fifty_move_rule@1 = Fifty_move_rule@2 + 1, case (New_fifty_move_rule@1 div 2) + 1 of 50 -> {ok, {some, {draw, fifty_move_rule}}}; _ -> {ok, {some, {in_progress, New_fifty_move_rule@1, Threefold_repetition_rule@1}}} end; {some, _} -> erlang:error( #{gleam_error => panic, message => <<"game is over, unable to apply moves to board"/utf8>>, module => <<"game"/utf8>>, function => <<"apply_move"/utf8>>, line => 3952} ) end; {en_passant, _, _} -> case erlang:element( 5, Game ) of none -> {ok, none}; {some, {in_progress, _, Threefold_repetition_rule@2}} -> {ok, {some, {in_progress, 0, Threefold_repetition_rule@2}}}; {some, _} -> {error, <<"game is over, unable to apply moves to board"/utf8>>} end end, gleam@result:'try'( New_status@2, fun(New_status@3) -> New_game_state@5 = erlang:setelement( 5, New_game_state@4, New_status@3 ), {ok, New_game_state@5} end ); [false, true] -> New_status@2 = case Move of {normal, From, To, _} -> gleam@result:'try'( case board:get_piece_at_position( erlang:element( 2, Game ), From ) of {some, Piece} -> {ok, Piece}; none -> {error, <<"no piece at from position"/utf8>>} end, fun( Moving_piece ) -> case erlang:element( 5, Game ) of none -> {ok, none}; {some, {in_progress, Fifty_move_rule, Threefold_repetition_rule}} -> Captured_piece = piece_at_position( Game, To ), New_fifty_move_rule = case Captured_piece of {some, _} -> 0; none -> case Moving_piece of {piece, _, pawn} -> 0; _ -> Fifty_move_rule + 1 end end, New_status = case (New_fifty_move_rule div 2) + 1 of 50 -> {some, {draw, fifty_move_rule}}; _ -> {some, {in_progress, New_fifty_move_rule, Threefold_repetition_rule}} end, {New_threefold_repetition_rule@3, Count@2} = case Captured_piece of {some, _} -> {Threefold_repetition_rule, 0}; none -> New_threefold_position = {three_fold_position, erlang:element( 3, Game ), erlang:element( 2, Game ), erlang:element( 11, Game ), erlang:element( 7, Game ), erlang:element( 8, Game ), erlang:element( 9, Game ), erlang:element( 10, Game )}, {New_threefold_repetition_rule@2, Count@1} = case gleam@dict:get( Threefold_repetition_rule, New_threefold_position ) of {error, _} -> New_threefold_repetition_rule = gleam@dict:insert( Threefold_repetition_rule, New_threefold_position, 1 ), {New_threefold_repetition_rule, 1}; {ok, Count} -> New_threefold_repetition_rule@1 = gleam@dict:insert( Threefold_repetition_rule, New_threefold_position, Count + 1 ), {New_threefold_repetition_rule@1, Count + 1} end, {New_threefold_repetition_rule@2, Count@1} end, New_status@1 = case New_status of {some, {in_progress, Fifty_move_rule@1, _}} -> case Count@2 of 3 -> {some, {draw, threefold_repetition}}; _ -> {some, {in_progress, Fifty_move_rule@1, New_threefold_repetition_rule@3}} end; _ -> New_status end, {ok, New_status@1}; {some, _} -> {error, <<"game is over, unable to apply moves to board"/utf8>>} end end ); {castle, _, _} -> case erlang:element( 5, Game ) of none -> {ok, none}; {some, {in_progress, Fifty_move_rule@2, Threefold_repetition_rule@1}} -> New_fifty_move_rule@1 = Fifty_move_rule@2 + 1, case (New_fifty_move_rule@1 div 2) + 1 of 50 -> {ok, {some, {draw, fifty_move_rule}}}; _ -> {ok, {some, {in_progress, New_fifty_move_rule@1, Threefold_repetition_rule@1}}} end; {some, _} -> erlang:error( #{gleam_error => panic, message => <<"game is over, unable to apply moves to board"/utf8>>, module => <<"game"/utf8>>, function => <<"apply_move"/utf8>>, line => 3952} ) end; {en_passant, _, _} -> case erlang:element( 5, Game ) of none -> {ok, none}; {some, {in_progress, _, Threefold_repetition_rule@2}} -> {ok, {some, {in_progress, 0, Threefold_repetition_rule@2}}}; {some, _} -> {error, <<"game is over, unable to apply moves to board"/utf8>>} end end, gleam@result:'try'( New_status@2, fun(New_status@3) -> New_game_state@5 = erlang:setelement( 5, New_game_state@4, New_status@3 ), {ok, New_game_state@5} end ); [false, false] -> {ok, erlang:setelement( 5, New_game_state@4, {some, {draw, stalemate}} )}; _ -> {error, <<"This panic should be unreachable"/utf8>>} end, New_game_state@6 end ) end ) end ) end ); {some, _} -> {error, <<"Game is over, unable to apply moves to board"/utf8>>} end. -spec apply_move_san_string(game(), binary()) -> {ok, game()} | {error, binary()}. apply_move_san_string(Game, Move) -> Move_san = move_san:from_string(Move), case Move_san of {ok, Move_san@1} -> case Move_san@1 of {normal, _, To, Moving_piece, _, Promotion, _} -> Promotion@2 = case Promotion of {some, Promotion@1} -> {some, {piece, erlang:element(3, Game), Promotion@1}}; none -> none end, Move@5 = (gleam@result:'try'( all_legal_moves(Game), fun(All_legal_moves_ok) -> Potential_moves = gleam@list:filter( All_legal_moves_ok, fun(Move@1) -> case Move@1 of {normal, _, To_legal, Promo_legal} when (To_legal =:= To) andalso (Promo_legal =:= Promotion@2) -> true; _ -> false end end ), case Potential_moves of [] -> {error, <<"No potential moves found"/utf8>>}; [Move@2] -> case Move@2 of {normal, _, _, _} -> {ok, Move@2}; _ -> erlang:error(#{gleam_error => panic, message => <<"This panic should be unreachable"/utf8>>, module => <<"game"/utf8>>, function => <<"apply_move_san_string"/utf8>>, line => 4032}) end; Move_list -> Maybe_move = gleam@list:filter( Move_list, fun(Move@3) -> case Move@3 of {normal, From, _, _} -> case board:get_piece_at_position( erlang:element(2, Game), From ) of {some, Piece} -> erlang:element( 3, Piece ) =:= Moving_piece; none -> false end; _ -> false end end ), case Maybe_move of [] -> {error, <<"Move not found"/utf8>>}; [Move@4] -> {ok, Move@4}; _ -> erlang:error(#{gleam_error => panic, message => <<"This panic should be unreachable"/utf8>>, module => <<"game"/utf8>>, function => <<"apply_move_san_string"/utf8>>, line => 4056}) end end end )), case Move@5 of {ok, Move@6} -> New_game_state = apply_move(Game, Move@6), New_game_state; {error, Error} -> {error, Error} end; {castle, Side, _} -> Move@7 = case Side of king_side -> case erlang:element(3, Game) of white -> {castle, {position, e, one}, {position, g, one}}; black -> {castle, {position, e, eight}, {position, g, eight}} end; queen_side -> case erlang:element(3, Game) of white -> {castle, {position, e, one}, {position, c, one}}; black -> {castle, {position, e, eight}, {position, c, eight}} end end, apply_move(Game, Move@7); {en_passant, From@1, To@1, _} -> gleam@result:'try'( all_legal_moves(Game), fun(All_legal_moves_ok@1) -> Ep_moves = gleam@list:filter( All_legal_moves_ok@1, fun(Move@8) -> case Move@8 of {en_passant, _, To_legal@1} when To_legal@1 =:= To@1 -> true; _ -> false end end ), case Ep_moves of [] -> {error, <<"Illegal move"/utf8>>}; [Move@9] -> apply_move(Game, Move@9); [Move_1, Move_2] -> case From@1 of {some, {position_san, {some, File}, _}} when File =:= erlang:element( 2, erlang:element(2, Move_1) ) -> apply_move(Game, Move_1); {some, {position_san, {some, File@1}, _}} when File@1 =:= erlang:element( 2, erlang:element(2, Move_2) ) -> apply_move(Game, Move_2); _ -> {error, <<"Illegal move"/utf8>>} end; _ -> {error, <<"Illegal move"/utf8>>} end end ) end; {error, _} -> {error, <<"Invalid move"/utf8>>} end. -spec load_pgn(binary()) -> {ok, game()} | {error, binary()}. load_pgn(Pgn) -> Game = new_game(), Pgn@1 = gleam@string:trim(Pgn), Pgn@2 = pgn:remove_tags(Pgn@1), List_of_movetext = pgn:split_movetext(Pgn@2), gleam@list:fold( List_of_movetext, {ok, Game}, fun(Game@1, Movetext) -> gleam@result:'try'( Game@1, fun(Game@2) -> Game@6 = case gleam@string:split(Movetext, <<" "/utf8>>) of [White_ply, Black_ply] -> Game@3 = apply_move_san_string(Game@2, White_ply), case Game@3 of {ok, Game@4} -> apply_move_san_string(Game@4, Black_ply); {error, Message} -> {error, Message} end; [White_ply@1] -> Game@5 = apply_move_san_string(Game@2, White_ply@1), Game@5; [] -> {error, <<"Invalid PGN"/utf8>>}; _ -> {error, <<"Invalid PGN"/utf8>>} end, Game@6 end ) end ). -spec apply_move_uci(game(), binary()) -> {ok, game()} | {error, binary()}. apply_move_uci(Game, Move) -> case erlang:element(5, Game) of {some, {in_progress, _, _}} -> case gleam@string:length(Move) of 4 -> Move_chars = gleam@string:to_graphemes(Move), From_file = case gleam@list:first(Move_chars) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse origin file"/utf8>>} end, case gleam@list:rest(Move_chars) of {ok, Move_chars@1} -> From_rank = case gleam@list:first(Move_chars@1) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse origin rank"/utf8>>} end, case gleam@list:rest(Move_chars@1) of {ok, Move_chars@2} -> To_file = case gleam@list:first( Move_chars@2 ) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse destination file"/utf8>>} end, case gleam@list:rest(Move_chars@2) of {ok, Move_chars@3} -> To_rank = case gleam@list:first( Move_chars@3 ) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse destination rank"/utf8>>} end, case {From_file, From_rank, To_file, To_rank} of {{ok, From_file@1}, {ok, From_rank@1}, {ok, To_file@1}, {ok, To_rank@1}} -> Promo = case gleam@string:slice( Move, 4, 1 ) of <<"q"/utf8>> -> {some, queen}; <<"r"/utf8>> -> {some, rook}; <<"b"/utf8>> -> {some, bishop}; <<"n"/utf8>> -> {some, knight}; _ -> none end, gleam@result:'try'( case piece_at_position( Game, {position, From_file@1, From_rank@1} ) of {some, Piece} -> {ok, Piece}; none -> {error, <<"No piece at origin"/utf8>>} end, fun(Piece@1) -> Maybe_enemy_piece = piece_at_position( Game, {position, To_file@1, To_rank@1} ), Move@1 = case Promo of {some, Promo@1} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, {some, {piece, erlang:element( 3, Game ), Promo@1}}}; none -> case Piece@1 of {piece, _, pawn} -> case From_file@1 =:= To_file@1 of true -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; false -> case Maybe_enemy_piece of {some, _} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; none -> {en_passant, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}} end end; {piece, _, king} -> case position:file_to_int( From_file@1 ) - position:file_to_int( To_file@1 ) of 2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; -2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end end, New_game_state = apply_move( Game, Move@1 ), New_game_state end ); {From_file_result, From_rank_result, To_file_result, To_rank_result} -> {_, File_errors} = gleam@result:partition( [From_file_result, To_file_result] ), {_, Rank_errors} = gleam@result:partition( [From_rank_result, To_rank_result] ), Errors = gleam@list:concat( [File_errors, Rank_errors] ), {error, gleam@string:join( Errors, <<", "/utf8>> )} end; _ -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; 5 -> Move_chars = gleam@string:to_graphemes(Move), From_file = case gleam@list:first(Move_chars) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse origin file"/utf8>>} end, case gleam@list:rest(Move_chars) of {ok, Move_chars@1} -> From_rank = case gleam@list:first(Move_chars@1) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse origin rank"/utf8>>} end, case gleam@list:rest(Move_chars@1) of {ok, Move_chars@2} -> To_file = case gleam@list:first( Move_chars@2 ) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse destination file"/utf8>>} end, case gleam@list:rest(Move_chars@2) of {ok, Move_chars@3} -> To_rank = case gleam@list:first( Move_chars@3 ) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse destination rank"/utf8>>} end, case {From_file, From_rank, To_file, To_rank} of {{ok, From_file@1}, {ok, From_rank@1}, {ok, To_file@1}, {ok, To_rank@1}} -> Promo = case gleam@string:slice( Move, 4, 1 ) of <<"q"/utf8>> -> {some, queen}; <<"r"/utf8>> -> {some, rook}; <<"b"/utf8>> -> {some, bishop}; <<"n"/utf8>> -> {some, knight}; _ -> none end, gleam@result:'try'( case piece_at_position( Game, {position, From_file@1, From_rank@1} ) of {some, Piece} -> {ok, Piece}; none -> {error, <<"No piece at origin"/utf8>>} end, fun(Piece@1) -> Maybe_enemy_piece = piece_at_position( Game, {position, To_file@1, To_rank@1} ), Move@1 = case Promo of {some, Promo@1} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, {some, {piece, erlang:element( 3, Game ), Promo@1}}}; none -> case Piece@1 of {piece, _, pawn} -> case From_file@1 =:= To_file@1 of true -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; false -> case Maybe_enemy_piece of {some, _} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; none -> {en_passant, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}} end end; {piece, _, king} -> case position:file_to_int( From_file@1 ) - position:file_to_int( To_file@1 ) of 2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; -2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end end, New_game_state = apply_move( Game, Move@1 ), New_game_state end ); {From_file_result, From_rank_result, To_file_result, To_rank_result} -> {_, File_errors} = gleam@result:partition( [From_file_result, To_file_result] ), {_, Rank_errors} = gleam@result:partition( [From_rank_result, To_rank_result] ), Errors = gleam@list:concat( [File_errors, Rank_errors] ), {error, gleam@string:join( Errors, <<", "/utf8>> )} end; _ -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; _ -> {error, <<"Invalid move"/utf8>>} end; none -> case gleam@string:length(Move) of 4 -> Move_chars = gleam@string:to_graphemes(Move), From_file = case gleam@list:first(Move_chars) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse origin file"/utf8>>} end, case gleam@list:rest(Move_chars) of {ok, Move_chars@1} -> From_rank = case gleam@list:first(Move_chars@1) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse origin rank"/utf8>>} end, case gleam@list:rest(Move_chars@1) of {ok, Move_chars@2} -> To_file = case gleam@list:first( Move_chars@2 ) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse destination file"/utf8>>} end, case gleam@list:rest(Move_chars@2) of {ok, Move_chars@3} -> To_rank = case gleam@list:first( Move_chars@3 ) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse destination rank"/utf8>>} end, case {From_file, From_rank, To_file, To_rank} of {{ok, From_file@1}, {ok, From_rank@1}, {ok, To_file@1}, {ok, To_rank@1}} -> Promo = case gleam@string:slice( Move, 4, 1 ) of <<"q"/utf8>> -> {some, queen}; <<"r"/utf8>> -> {some, rook}; <<"b"/utf8>> -> {some, bishop}; <<"n"/utf8>> -> {some, knight}; _ -> none end, gleam@result:'try'( case piece_at_position( Game, {position, From_file@1, From_rank@1} ) of {some, Piece} -> {ok, Piece}; none -> {error, <<"No piece at origin"/utf8>>} end, fun(Piece@1) -> Maybe_enemy_piece = piece_at_position( Game, {position, To_file@1, To_rank@1} ), Move@1 = case Promo of {some, Promo@1} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, {some, {piece, erlang:element( 3, Game ), Promo@1}}}; none -> case Piece@1 of {piece, _, pawn} -> case From_file@1 =:= To_file@1 of true -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; false -> case Maybe_enemy_piece of {some, _} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; none -> {en_passant, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}} end end; {piece, _, king} -> case position:file_to_int( From_file@1 ) - position:file_to_int( To_file@1 ) of 2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; -2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end end, New_game_state = apply_move( Game, Move@1 ), New_game_state end ); {From_file_result, From_rank_result, To_file_result, To_rank_result} -> {_, File_errors} = gleam@result:partition( [From_file_result, To_file_result] ), {_, Rank_errors} = gleam@result:partition( [From_rank_result, To_rank_result] ), Errors = gleam@list:concat( [File_errors, Rank_errors] ), {error, gleam@string:join( Errors, <<", "/utf8>> )} end; _ -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; 5 -> Move_chars = gleam@string:to_graphemes(Move), From_file = case gleam@list:first(Move_chars) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse origin file"/utf8>>} end, case gleam@list:rest(Move_chars) of {ok, Move_chars@1} -> From_rank = case gleam@list:first(Move_chars@1) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse origin rank"/utf8>>} end, case gleam@list:rest(Move_chars@1) of {ok, Move_chars@2} -> To_file = case gleam@list:first( Move_chars@2 ) of {ok, <<"a"/utf8>>} -> {ok, a}; {ok, <<"b"/utf8>>} -> {ok, b}; {ok, <<"c"/utf8>>} -> {ok, c}; {ok, <<"d"/utf8>>} -> {ok, d}; {ok, <<"e"/utf8>>} -> {ok, e}; {ok, <<"f"/utf8>>} -> {ok, f}; {ok, <<"g"/utf8>>} -> {ok, g}; {ok, <<"h"/utf8>>} -> {ok, h}; _ -> {error, <<"Could not parse destination file"/utf8>>} end, case gleam@list:rest(Move_chars@2) of {ok, Move_chars@3} -> To_rank = case gleam@list:first( Move_chars@3 ) of {ok, <<"1"/utf8>>} -> {ok, one}; {ok, <<"2"/utf8>>} -> {ok, two}; {ok, <<"3"/utf8>>} -> {ok, three}; {ok, <<"4"/utf8>>} -> {ok, four}; {ok, <<"5"/utf8>>} -> {ok, five}; {ok, <<"6"/utf8>>} -> {ok, six}; {ok, <<"7"/utf8>>} -> {ok, seven}; {ok, <<"8"/utf8>>} -> {ok, eight}; _ -> {error, <<"Could not parse destination rank"/utf8>>} end, case {From_file, From_rank, To_file, To_rank} of {{ok, From_file@1}, {ok, From_rank@1}, {ok, To_file@1}, {ok, To_rank@1}} -> Promo = case gleam@string:slice( Move, 4, 1 ) of <<"q"/utf8>> -> {some, queen}; <<"r"/utf8>> -> {some, rook}; <<"b"/utf8>> -> {some, bishop}; <<"n"/utf8>> -> {some, knight}; _ -> none end, gleam@result:'try'( case piece_at_position( Game, {position, From_file@1, From_rank@1} ) of {some, Piece} -> {ok, Piece}; none -> {error, <<"No piece at origin"/utf8>>} end, fun(Piece@1) -> Maybe_enemy_piece = piece_at_position( Game, {position, To_file@1, To_rank@1} ), Move@1 = case Promo of {some, Promo@1} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, {some, {piece, erlang:element( 3, Game ), Promo@1}}}; none -> case Piece@1 of {piece, _, pawn} -> case From_file@1 =:= To_file@1 of true -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; false -> case Maybe_enemy_piece of {some, _} -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none}; none -> {en_passant, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}} end end; {piece, _, king} -> case position:file_to_int( From_file@1 ) - position:file_to_int( To_file@1 ) of 2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; -2 -> {castle, {position, e, From_rank@1}, {position, To_file@1, To_rank@1}}; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end; _ -> {normal, {position, From_file@1, From_rank@1}, {position, To_file@1, To_rank@1}, none} end end, New_game_state = apply_move( Game, Move@1 ), New_game_state end ); {From_file_result, From_rank_result, To_file_result, To_rank_result} -> {_, File_errors} = gleam@result:partition( [From_file_result, To_file_result] ), {_, Rank_errors} = gleam@result:partition( [From_rank_result, To_rank_result] ), Errors = gleam@list:concat( [File_errors, Rank_errors] ), {error, gleam@string:join( Errors, <<", "/utf8>> )} end; _ -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; {error, _} -> {error, <<"Invalid move"/utf8>>} end; _ -> {error, <<"Invalid move"/utf8>>} end; {some, _} -> {ok, Game} end.