1
0
mirror of https://github.com/danbee/chess synced 2025-03-04 08:39:06 +00:00
chess/lib/chess/game_state.ex

73 lines
1.5 KiB
Elixir

defmodule Chess.GameState do
@moduledoc false
alias Chess.Board
alias Chess.Moves
alias Chess.Moves.Piece
def game_over?(game) do
game.state == "checkmate" ||
game.state == "stalemate"
end
def state(board, colour) do
cond do
player_checkmated?(board, colour) ->
"checkmate"
player_stalemated?(board, colour) ->
"stalemate"
king_in_check?(board, colour) ->
"check"
true -> nil
end
end
def player_checkmated?(board, colour) do
king_in_check?(board, colour) &&
player_cannot_move?(board, colour)
end
def player_stalemated?(board, colour) do
!king_in_check?(board, colour) &&
player_cannot_move?(board, colour)
end
def king_in_check?(board, colour) do
king =
board
|> Board.search(%{"type" => "king", "colour" => colour})
|> List.first
if is_nil(king) do
raise "There is no #{colour} king!"
end
board
|> Piece.attacked?(king)
end
def player_cannot_move?(board, colour) do
board
|> Board.search(%{"colour" => colour})
|> Enum.all?(fn({file, rank}) ->
board
|> piece_cannot_move?({file, rank})
end)
end
def piece_cannot_move?(board, {file, rank}) do
piece =
board
|> Board.piece({file, rank})
board
|> Moves.available({file, rank})
|> Enum.all?(fn({to_file, to_rank}) ->
board
|> Board.move_piece(%{"from" => [file, rank], "to" => [to_file, to_rank]})
|> Map.get(:board)
|> king_in_check?(piece["colour"])
end)
end
end