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

Now we're correctly handling moves

This commit is contained in:
Daniel Barber 2021-07-13 18:21:12 -05:00
parent 7e2c841b59
commit 04e00e530b
6 changed files with 72 additions and 29 deletions

View File

@ -42,8 +42,8 @@ defmodule Chess.Board do
if castling_move?(piece, from_file, to_file) do if castling_move?(piece, from_file, to_file) do
board board
|> castling_move(%{ |> castling_move(%{
"from" => [from_file, from_rank], from: {from_file, from_rank},
"to" => [to_file, to_rank] to: {to_file, to_rank}
}) })
|> Map.get(:board) |> Map.get(:board)
else else
@ -65,7 +65,7 @@ defmodule Chess.Board do
def castling_move?(_, _, _), do: false def castling_move?(_, _, _), do: false
def castling_move(board, %{"from" => [4, rank], "to" => [2, _rank]}) do def castling_move(board, %{from: {4, rank}, to: {2, _rank}}) do
move_piece(board, %{ move_piece(board, %{
"from" => [0, rank], "from" => [0, rank],
"to" => [3, rank] "to" => [3, rank]

View File

@ -68,7 +68,7 @@ defmodule Chess.GameState do
|> Moves.available({file, rank}) |> Moves.available({file, rank})
|> Enum.all?(fn {to_file, to_rank} -> |> Enum.all?(fn {to_file, to_rank} ->
board board
|> Board.move_piece(%{"from" => [file, rank], "to" => [to_file, to_rank]}) |> Board.move_piece(%{from: {file, rank}, to: {to_file, to_rank}})
|> Map.get(:board) |> Map.get(:board)
|> king_in_check?(piece["colour"]) |> king_in_check?(piece["colour"])
end) end)

View File

@ -79,7 +79,7 @@ defmodule Chess.Moves.Pieces.King.Castling do
[{2, rank}, {3, rank}] [{2, rank}, {3, rank}]
|> Enum.any?(fn {to_file, to_rank} -> |> Enum.any?(fn {to_file, to_rank} ->
board board
|> Board.move_piece(%{"from" => [4, rank], "to" => [to_file, to_rank]}) |> Board.move_piece(%{from: {4, rank}, to: {to_file, to_rank}})
|> Map.get(:board) |> Map.get(:board)
|> GameState.king_in_check?(colour) |> GameState.king_in_check?(colour)
end) end)
@ -89,7 +89,7 @@ defmodule Chess.Moves.Pieces.King.Castling do
[{5, rank}, {6, rank}] [{5, rank}, {6, rank}]
|> Enum.any?(fn {to_file, to_rank} -> |> Enum.any?(fn {to_file, to_rank} ->
board board
|> Board.move_piece(%{"from" => [4, rank], "to" => [to_file, to_rank]}) |> Board.move_piece(%{from: {4, rank}, to: {to_file, to_rank}})
|> Map.get(:board) |> Map.get(:board)
|> GameState.king_in_check?(colour) |> GameState.king_in_check?(colour)
end) end)

View File

@ -1,4 +1,4 @@
<div class="board board--black-to-move board--player-is-<%= player_colour(@user, @game) %>"> <div class="board board--<%= @game.turn %>-to-move board--player-is-<%= player_colour(@user, @game) %>">
<div class="board__rank-labels"> <div class="board__rank-labels">
<div class="board__label">1</div> <div class="board__label">1</div>
<div class="board__label">2</div> <div class="board__label">2</div>
@ -22,14 +22,14 @@
</div> </div>
<div class="board__body"> <div class="board__body">
<%= for rank <- 0..7 do %> <%= for {rank, row} <- @board do %>
<div class="board__row"> <div class="board__row">
<%= for file <- 0..7 do %> <%= for {file, piece} <- row do %>
<%= render ChessWeb.SquareView, <%= render ChessWeb.SquareView,
"square.html", "square.html",
rank: rank, rank: rank,
file: file, file: file,
piece: @game.board["#{file},#{rank}"], piece: piece,
selected: {file, rank} == @selected, selected: {file, rank} == @selected,
available: {file, rank} in @available %> available: {file, rank} in @available %>
<% end %> <% end %>

View File

@ -5,6 +5,7 @@ defmodule ChessWeb.BoardLive do
alias Chess.Store.Game alias Chess.Store.Game
alias Chess.Repo alias Chess.Repo
alias Chess.Board alias Chess.Board
alias Chess.Moves
import Chess.Auth, only: [get_user!: 1] import Chess.Auth, only: [get_user!: 1]
@ -19,11 +20,24 @@ defmodule ChessWeb.BoardLive do
Game.for_user(user) Game.for_user(user)
|> Repo.get!(game_id) |> Repo.get!(game_id)
{:ok, assign(socket, game: game, user: user, selected: nil, available: [])} {:ok, assign(socket, default_assigns(game, user))}
end end
def handle_event("click", %{"rank" => rank, "file" => file}, socket) do def handle_event("click", %{"rank" => rank, "file" => file}, socket) do
{:noreply, socket |> handle_click(file, rank)} {
:noreply,
socket |> handle_click(String.to_integer(file), String.to_integer(rank))
}
end
defp default_assigns(game, user) do
%{
board: Board.transform(game.board),
game: game,
user: user,
selected: nil,
available: []
}
end end
defp handle_click(socket, file, rank) do defp handle_click(socket, file, rank) do
@ -34,27 +48,56 @@ defmodule ChessWeb.BoardLive do
colour = ChessWeb.GameView.player_colour(user, game) colour = ChessWeb.GameView.player_colour(user, game)
assigns = assigns =
if colour == game.turn do
case socket.assigns do case socket.assigns do
%{:selected => nil} -> %{selected: nil} ->
case Board.piece(board, {file, rank}) do handle_selection(board, colour, file, rank)
%{"colour" => ^colour} ->
[{:selected, selected(file, rank)}]
_ -> _ ->
[] handle_move(socket.assigns, file, rank)
end end
_ ->
[{:selected, nil}]
end end
assign(socket, assigns) assign(socket, assigns)
end end
defp selected(file, rank) do defp handle_selection(board, colour, file, rank) do
{ case Board.piece(board, {file, rank}) do
String.to_integer(file), %{"colour" => ^colour} ->
String.to_integer(rank) [
} {:selected, {file, rank}},
{:available, Moves.available(board, {file, rank})}
]
_ ->
[]
end
end
defp handle_move(
%{game: game, available: available, selected: selected},
file,
rank
) do
if {file, rank} in available do
new_game =
game
|> Moves.make_move(%{from: selected, to: {file, rank}})
|> case do
{:ok, %{game: new_game}} ->
new_game
end
new_board = Board.transform(new_game.board)
[
{:selected, nil},
{:available, []},
{:board, new_board},
{:game, new_game}
]
else
[{:selected, nil}, {:available, []}]
end
end end
end end

View File

@ -90,7 +90,7 @@ defmodule Chess.Store.GameTest do
opponent_id: opponent.id opponent_id: opponent.id
}) })
move_params = %{"from" => [4, 1], "to" => [4, 3]} move_params = %{from: {4, 1}, to: {4, 3}}
changeset = changeset =
Game.move_changeset( Game.move_changeset(