mirror of
https://github.com/danbee/chess
synced 2025-03-04 08:39:06 +00:00
Checks whether a player is checkmated
This commit is contained in:
parent
e2826fdbce
commit
6b31491ad4
@ -1,21 +0,0 @@
|
||||
defmodule Chess.Game do
|
||||
@moduledoc false
|
||||
|
||||
alias Chess.Board
|
||||
alias Chess.Moves.Piece
|
||||
|
||||
def player_checkmated?(board, colour) do
|
||||
board
|
||||
|> Board.search(%{"colour" => colour})
|
||||
end
|
||||
|
||||
def king_in_check?(board, colour) do
|
||||
king =
|
||||
board
|
||||
|> Board.search(%{"type" => "king", "colour" => colour})
|
||||
|> List.first
|
||||
|
||||
board
|
||||
|> Piece.attacked?(king)
|
||||
end
|
||||
end
|
||||
40
lib/chess/game_state.ex
Normal file
40
lib/chess/game_state.ex
Normal file
@ -0,0 +1,40 @@
|
||||
defmodule Chess.GameState do
|
||||
@moduledoc false
|
||||
|
||||
alias Chess.Board
|
||||
alias Chess.Moves
|
||||
alias Chess.Moves.Piece
|
||||
|
||||
def player_checkmated?(board, colour) do
|
||||
board
|
||||
|> Board.search(%{"colour" => colour})
|
||||
|> Enum.all?(fn({file, rank}) ->
|
||||
board
|
||||
|> cannot_escape_check?({file, rank})
|
||||
end)
|
||||
end
|
||||
|
||||
def cannot_escape_check?(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]})
|
||||
|> king_in_check?(piece["colour"])
|
||||
end)
|
||||
end
|
||||
|
||||
def king_in_check?(board, colour) do
|
||||
king =
|
||||
board
|
||||
|> Board.search(%{"type" => "king", "colour" => colour})
|
||||
|> List.first
|
||||
|
||||
board
|
||||
|> Piece.attacked?(king)
|
||||
end
|
||||
end
|
||||
@ -10,6 +10,7 @@ defmodule Chess.Store.Game do
|
||||
|
||||
alias Chess.Board
|
||||
alias Chess.Store.Game
|
||||
alias Chess.GameState
|
||||
|
||||
schema "games" do
|
||||
field :board, :map, default: Board.default()
|
||||
@ -49,7 +50,7 @@ defmodule Chess.Store.Game do
|
||||
end
|
||||
|
||||
def validate_king_in_check(changeset, %Game{turn: turn}, %{board: board}) do
|
||||
if Board.king_in_check?(board, turn) do
|
||||
if GameState.king_in_check?(board, turn) do
|
||||
changeset
|
||||
|> add_error(
|
||||
:board,
|
||||
|
||||
94
test/chess/game_state_test.exs
Normal file
94
test/chess/game_state_test.exs
Normal file
@ -0,0 +1,94 @@
|
||||
defmodule Chess.GameStateTest do
|
||||
@moduledoc false
|
||||
|
||||
use Chess.DataCase
|
||||
|
||||
alias Chess.GameState
|
||||
|
||||
test "king is in check" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"4,7" => %{"type" => "queen", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert GameState.king_in_check?(board, "white")
|
||||
end
|
||||
|
||||
test "king is not in check" do
|
||||
board = %{
|
||||
"5,0" => %{"type" => "king", "colour" => "white"},
|
||||
"4,7" => %{"type" => "queen", "colour" => "black"},
|
||||
}
|
||||
|
||||
refute GameState.king_in_check?(board, "white")
|
||||
end
|
||||
|
||||
test "king is in check by a knight" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"3,2" => %{"type" => "knight", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert GameState.king_in_check?(board, "white")
|
||||
end
|
||||
|
||||
test "king is in check by a pawn" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"3,1" => %{"type" => "pawn", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert GameState.king_in_check?(board, "white")
|
||||
end
|
||||
|
||||
test "king is in checkmate by queen and rook" do
|
||||
board = %{
|
||||
"0,0" => %{"type" => "king", "colour" => "white"},
|
||||
"0,4" => %{"type" => "queen", "colour" => "black"},
|
||||
"1,4" => %{"type" => "rook", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert GameState.player_checkmated?(board, "white")
|
||||
end
|
||||
|
||||
test "king is not in checkmate by a queen" do
|
||||
board = %{
|
||||
"0,0" => %{"type" => "king", "colour" => "white"},
|
||||
"0,4" => %{"type" => "queen", "colour" => "black"},
|
||||
}
|
||||
|
||||
refute GameState.player_checkmated?(board, "white")
|
||||
end
|
||||
|
||||
test "king is checkmate by a queen and a knight" do
|
||||
board = %{
|
||||
"0,0" => %{"type" => "king", "colour" => "white"},
|
||||
"1,1" => %{"type" => "queen", "colour" => "black"},
|
||||
"2,3" => %{"type" => "knight", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert GameState.player_checkmated?(board, "white")
|
||||
end
|
||||
|
||||
test "knight can block checkmate by queen and rook" do
|
||||
board = %{
|
||||
"0,0" => %{"type" => "king", "colour" => "white"},
|
||||
"2,0" => %{"type" => "knight", "colour" => "white"},
|
||||
"0,5" => %{"type" => "queen", "colour" => "black"},
|
||||
"1,5" => %{"type" => "rook", "colour" => "black"},
|
||||
}
|
||||
|
||||
refute GameState.player_checkmated?(board, "white")
|
||||
end
|
||||
|
||||
test "bishop can take checking queen" do
|
||||
board = %{
|
||||
"0,0" => %{"type" => "king", "colour" => "white"},
|
||||
"2,3" => %{"type" => "bishop", "colour" => "white"},
|
||||
"0,5" => %{"type" => "queen", "colour" => "black"},
|
||||
"1,5" => %{"type" => "rook", "colour" => "black"},
|
||||
}
|
||||
|
||||
refute GameState.player_checkmated?(board, "white")
|
||||
end
|
||||
end
|
||||
@ -1,43 +0,0 @@
|
||||
defmodule Chess.GameTest do
|
||||
@moduledoc false
|
||||
|
||||
use Chess.DataCase
|
||||
|
||||
alias Chess.Game
|
||||
|
||||
test "recognise when the king is in check" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"4,7" => %{"type" => "queen", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert Game.king_in_check?(board, "white")
|
||||
end
|
||||
|
||||
test "recognise when the king is not in check" do
|
||||
board = %{
|
||||
"5,0" => %{"type" => "king", "colour" => "white"},
|
||||
"4,7" => %{"type" => "queen", "colour" => "black"},
|
||||
}
|
||||
|
||||
refute Game.king_in_check?(board, "white")
|
||||
end
|
||||
|
||||
test "recognize when the king is in check by a knight" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"3,2" => %{"type" => "knight", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert Game.king_in_check?(board, "white")
|
||||
end
|
||||
|
||||
test "recognize when the king is in check by a pawn" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"3,1" => %{"type" => "pawn", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert Game.king_in_check?(board, "white")
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user