Current section

Files

Jump to
binbo src binbo_movegen.erl
Raw

src/binbo_movegen.erl

%% Copyright (c) 2019, Sergei Semichev <chessvegas@chessvegas.com>. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-module(binbo_movegen).
-export([all_valid_moves/2, has_valid_moves/2]).
%%%------------------------------------------------------------------------------
%%% Includes
%%%------------------------------------------------------------------------------
-include("binbo_board.hrl").
%%%------------------------------------------------------------------------------
%%% Types
%%%------------------------------------------------------------------------------
-type bb() :: binbo_bb:bb().
-type piece() :: binbo_board:piece().
-type color() :: binbo_board:color().
-type bb_game() :: binbo_position:bb_game().
-type sq_idx() :: binbo_board:square_index().
-type many() :: all | any.
%%%------------------------------------------------------------------------------
%%% API
%%%------------------------------------------------------------------------------
%% all_valid_moves/2
%% Note: function 'all_valid_moves/2' returns just a bitboard of all *target* squares.
%% If it should be used for a chess engine, it should be reworked to return a desired value.
-spec all_valid_moves(color(), bb_game()) -> bb().
all_valid_moves(Color, Game) ->
valid_moves(Color, Game, all).
%% has_valid_moves/2
-spec has_valid_moves(color(), bb_game()) -> boolean().
has_valid_moves(Color, Game) ->
(any_valid_move(Color, Game) > ?EMPTY_BB).
%%%------------------------------------------------------------------------------
%%% Internal functions
%%%------------------------------------------------------------------------------
%% any_valid_move/2
-spec any_valid_move(color(), bb_game()) -> bb().
any_valid_move(Color, Game) ->
valid_moves(Color, Game, any).
%% valid_moves/3
-spec valid_moves(color(), bb_game(), many()) -> bb().
valid_moves(Color, Game, Many) ->
FromSquares = binbo_position:get_side_indexes(Color, Game),
valid_moves_from(FromSquares, Game, Many).
%% valid_moves_from/3
-spec valid_moves_from([sq_idx()], bb_game(), many()) -> bb().
valid_moves_from(FromSquares, Game, Many) ->
valid_moves_from(FromSquares, Game, Many, ?EMPTY_BB).
%% valid_moves_from/4
-spec valid_moves_from([sq_idx()], bb_game(), many(), bb()) -> bb().
valid_moves_from([], _Game, _Many, MovesBB) ->
MovesBB;
valid_moves_from([FromIdx | Tail], Game, Many, MovesBB) ->
Piece = binbo_position:get_piece(FromIdx, Game),
true = ?IS_PIECE(Piece), % ensure piece
PieceMovesBB = valid_piece_moves(FromIdx, Piece, Game, Many),
case PieceMovesBB > ?EMPTY_BB of
true when (Many =:= any) ->
PieceMovesBB;
true ->
valid_moves_from(Tail, Game, Many, MovesBB bor PieceMovesBB);
false ->
valid_moves_from(Tail, Game, Many, MovesBB)
end.
%% valid_piece_moves/4
-spec valid_piece_moves(sq_idx(), piece(), bb_game(), many()) -> bb().
valid_piece_moves(FromIdx, Piece, Game, Many) ->
PieceMovesBB = position_piece_moves_bb(FromIdx, Piece, Game),
ToSquares = binbo_bb:to_index_list(PieceMovesBB),
valid_piece_moves_from_to(FromIdx, ToSquares, Piece, Game, Many, ?EMPTY_BB).
%% valid_piece_moves_from_to/6
-spec valid_piece_moves_from_to(sq_idx(), [sq_idx()], piece(), bb_game(), many(), bb()) -> bb().
valid_piece_moves_from_to(_FromIdx, [], _Piece, _Game, _Many, MovesBB) ->
MovesBB;
valid_piece_moves_from_to(FromIdx, [ToIdx | Tail], Piece, Game, Many, MovesBB) ->
Validate = binbo_move:validate_move(Game, Piece, FromIdx, ToIdx, ?QUEEN),
case Validate of
{ok, _, _} ->
case Many of
any ->
?SQUARE_BB(ToIdx);
all ->
MovesBB2 = MovesBB bor ?SQUARE_BB(ToIdx),
valid_piece_moves_from_to(FromIdx, Tail, Piece, Game, Many, MovesBB2)
end;
{error, _} ->
valid_piece_moves_from_to(FromIdx, Tail, Piece, Game, Many, MovesBB)
end.
%% position_piece_moves_bb/3
-spec position_piece_moves_bb(sq_idx(), piece(), bb_game()) -> bb().
position_piece_moves_bb(FromIdx, Piece, Game) ->
case ?PIECE_TYPE(Piece) of
?PAWN -> binbo_position:pawn_moves_bb(FromIdx, ?COLOR(Piece), Game);
?KNIGHT -> binbo_position:knight_moves_bb(FromIdx, ?COLOR(Piece), Game);
?BISHOP -> binbo_position:bishop_moves_bb(FromIdx, Game);
?ROOK -> binbo_position:rook_moves_bb(FromIdx, Game);
?QUEEN -> binbo_position:queen_moves_bb(FromIdx, Game);
?KING -> binbo_position:king_moves_bb(FromIdx, ?COLOR(Piece), Game)
end.