mirror of
https://github.com/danbee/chess
synced 2025-03-04 08:39:06 +00:00
Notification if move would result in check
This commit is contained in:
parent
048db4c71c
commit
49540d72bd
@ -34,7 +34,10 @@ class Channel {
|
||||
}
|
||||
|
||||
sendMove(move) {
|
||||
this.channel.push("game:move", move);
|
||||
this.channel.push("game:move", move)
|
||||
.receive("error", resp => {
|
||||
alert(resp.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -54,14 +54,17 @@ defmodule Chess.Moves.Piece do
|
||||
defp _attacked?(_board, {7, _rank}, {1, _}, _), do: false
|
||||
defp _attacked?(_board, {_file, 7}, {_, 1}, _), do: false
|
||||
defp _attacked?(board, {file, rank}, {fv, rv}, pieces) do
|
||||
{file, rank} =
|
||||
board
|
||||
|> Generator.moves({file, rank}, {fv, rv})
|
||||
|> List.last
|
||||
board
|
||||
|> Generator.moves({file, rank}, {fv, rv})
|
||||
|> List.last
|
||||
|> case do
|
||||
{file, rank} ->
|
||||
piece = board["#{file},#{rank}"]
|
||||
|
||||
piece = board["#{file},#{rank}"]
|
||||
|
||||
Enum.any?(pieces, &(match?(%{"type" => ^&1}, piece)))
|
||||
Enum.any?(pieces, &(match?(%{"type" => ^&1}, piece)))
|
||||
nil ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp _attacked?(board, {file, rank}, pattern, piece_type) do
|
||||
|
||||
@ -28,6 +28,12 @@ defmodule Chess.Store.Game do
|
||||
|> foreign_key_constraint(:opponent_id)
|
||||
end
|
||||
|
||||
def move_changeset(struct, params \\ %{}) do
|
||||
struct
|
||||
|> cast(params, required_attrs())
|
||||
|> validate_king_in_check(struct, params)
|
||||
end
|
||||
|
||||
def change_turn("black"), do: "white"
|
||||
def change_turn("white"), do: "black"
|
||||
|
||||
@ -41,6 +47,20 @@ defmodule Chess.Store.Game do
|
||||
or_where: game.opponent_id == ^user_id
|
||||
end
|
||||
|
||||
def validate_king_in_check(changeset, %Game{turn: turn}, %{board: board}) do
|
||||
case Board.king_in_check?(board, turn) do
|
||||
true ->
|
||||
changeset
|
||||
|> add_error(
|
||||
:board,
|
||||
"That move would result in your king being in check"
|
||||
)
|
||||
_ ->
|
||||
changeset
|
||||
end
|
||||
end
|
||||
def validate_king_in_check(changeset, _, _), do: changeset
|
||||
|
||||
def ordered(query) do
|
||||
query
|
||||
|> order_by([game], desc: game.inserted_at)
|
||||
|
||||
@ -24,7 +24,9 @@ defmodule ChessWeb.GameChannel do
|
||||
board: Board.transform(game.board),
|
||||
turn: game.turn
|
||||
}
|
||||
push(socket, "game:update", payload)
|
||||
|
||||
socket
|
||||
|> push("game:update", payload)
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
@ -35,7 +37,7 @@ defmodule ChessWeb.GameChannel do
|
||||
|> Game.for_user_id()
|
||||
|> Repo.get!(socket.assigns.game_id)
|
||||
|
||||
changeset = Game.changeset(
|
||||
changeset = Game.move_changeset(
|
||||
game, %{
|
||||
board: Board.move_piece(game.board, move_params),
|
||||
turn: Game.change_turn(game.turn)
|
||||
@ -46,7 +48,11 @@ defmodule ChessWeb.GameChannel do
|
||||
{:ok, game} ->
|
||||
send_update(game)
|
||||
|
||||
{:noreply, socket}
|
||||
{:noreply, socket}
|
||||
{:error, changeset} ->
|
||||
{message, _} = changeset.errors[:board]
|
||||
|
||||
{:reply, {:error, %{message: message}}, socket}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -21,6 +21,16 @@ defmodule Chess.Moves.PieceTest do
|
||||
refute Piece.attacked?(board, {4, 0})
|
||||
end
|
||||
|
||||
test "piece next to another piece is being attacked" do
|
||||
board = %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"4,1" => %{"type" => "pawn", "colour" => "white"},
|
||||
"7,3" => %{"type" => "bishop", "colour" => "black"},
|
||||
}
|
||||
|
||||
assert Piece.attacked?(board, {4, 0})
|
||||
end
|
||||
|
||||
test "piece is not being attacked by piece of its own colour" do
|
||||
board = %{
|
||||
"4,5" => %{"type" => "king", "colour" => "white"},
|
||||
|
||||
@ -115,6 +115,75 @@ defmodule Chess.MovesTest do
|
||||
|> assert_has(square_containing("f4-r3", "white.pawn"))
|
||||
end
|
||||
|
||||
test "cannot move the king into a position that would result in check",
|
||||
%{session: session} do
|
||||
user = insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
})
|
||||
opponent = insert(:user, %{
|
||||
name: "Zelda",
|
||||
email: "zelda@hyrule.com",
|
||||
password: "ganonsucks"
|
||||
})
|
||||
insert(:game, %{
|
||||
board: %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"3,7" => %{"type" => "queen", "colour" => "black"},
|
||||
},
|
||||
user_id: user.id,
|
||||
opponent_id: opponent.id,
|
||||
turn: "white",
|
||||
})
|
||||
|
||||
session
|
||||
|> login("link@hyrule.com", "ilovezelda")
|
||||
|> visit("/games")
|
||||
|> click(link("Game with Zelda"))
|
||||
|
||||
session
|
||||
|> click(css("#f4-r0"))
|
||||
|> click(css("#f3-r0"))
|
||||
|> refute_has(square_containing("f3-r0", "white.king"))
|
||||
|> assert_has(square_containing("f4-r0", "white.king"))
|
||||
end
|
||||
|
||||
test "cannot make a move that would place the king in check",
|
||||
%{session: session} do
|
||||
user = insert(:user, %{
|
||||
name: "Link",
|
||||
email: "link@hyrule.com",
|
||||
password: "ilovezelda"
|
||||
})
|
||||
opponent = insert(:user, %{
|
||||
name: "Zelda",
|
||||
email: "zelda@hyrule.com",
|
||||
password: "ganonsucks"
|
||||
})
|
||||
insert(:game, %{
|
||||
board: %{
|
||||
"4,0" => %{"type" => "king", "colour" => "white"},
|
||||
"4,1" => %{"type" => "rook", "colour" => "white"},
|
||||
"4,7" => %{"type" => "queen", "colour" => "black"},
|
||||
},
|
||||
user_id: user.id,
|
||||
opponent_id: opponent.id,
|
||||
turn: "white",
|
||||
})
|
||||
|
||||
session
|
||||
|> login("link@hyrule.com", "ilovezelda")
|
||||
|> visit("/games")
|
||||
|> click(link("Game with Zelda"))
|
||||
|
||||
session
|
||||
|> click(css("#f4-r1"))
|
||||
|> click(css("#f2-r1"))
|
||||
|> refute_has(square_containing("f2-r1", "white.rook"))
|
||||
|> assert_has(square_containing("f4-r1", "white.rook"))
|
||||
end
|
||||
|
||||
defp square_selected(square) do
|
||||
css("##{square}.selected")
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user