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.Board
|
||||||
alias Chess.Store.Game
|
alias Chess.Store.Game
|
||||||
|
alias Chess.GameState
|
||||||
|
|
||||||
schema "games" do
|
schema "games" do
|
||||||
field :board, :map, default: Board.default()
|
field :board, :map, default: Board.default()
|
||||||
@ -49,7 +50,7 @@ defmodule Chess.Store.Game do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_king_in_check(changeset, %Game{turn: turn}, %{board: board}) do
|
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
|
changeset
|
||||||
|> add_error(
|
|> add_error(
|
||||||
:board,
|
: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