From 04e00e530bffd8093c03c7f791a313b3013cdaa2 Mon Sep 17 00:00:00 2001 From: Dan Barber Date: Tue, 13 Jul 2021 18:21:12 -0500 Subject: [PATCH] Now we're correctly handling moves --- lib/chess/board.ex | 6 +- lib/chess/game_state.ex | 2 +- lib/chess/moves/pieces/king/castling.ex | 4 +- lib/chess_web/templates/game/board.html.leex | 8 +- lib/chess_web/views/live/board_live.ex | 79 +++++++++++++++----- test/chess/store/game_test.exs | 2 +- 6 files changed, 72 insertions(+), 29 deletions(-) diff --git a/lib/chess/board.ex b/lib/chess/board.ex index 8dc8d65..b34026a 100644 --- a/lib/chess/board.ex +++ b/lib/chess/board.ex @@ -42,8 +42,8 @@ defmodule Chess.Board do if castling_move?(piece, from_file, to_file) do board |> castling_move(%{ - "from" => [from_file, from_rank], - "to" => [to_file, to_rank] + from: {from_file, from_rank}, + to: {to_file, to_rank} }) |> Map.get(:board) else @@ -65,7 +65,7 @@ defmodule Chess.Board do 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, %{ "from" => [0, rank], "to" => [3, rank] diff --git a/lib/chess/game_state.ex b/lib/chess/game_state.ex index a220de2..76fa64f 100644 --- a/lib/chess/game_state.ex +++ b/lib/chess/game_state.ex @@ -68,7 +68,7 @@ defmodule Chess.GameState do |> Moves.available({file, rank}) |> Enum.all?(fn {to_file, to_rank} -> 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) |> king_in_check?(piece["colour"]) end) diff --git a/lib/chess/moves/pieces/king/castling.ex b/lib/chess/moves/pieces/king/castling.ex index 52ec48b..4aafa3d 100644 --- a/lib/chess/moves/pieces/king/castling.ex +++ b/lib/chess/moves/pieces/king/castling.ex @@ -79,7 +79,7 @@ defmodule Chess.Moves.Pieces.King.Castling do [{2, rank}, {3, rank}] |> Enum.any?(fn {to_file, to_rank} -> 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) |> GameState.king_in_check?(colour) end) @@ -89,7 +89,7 @@ defmodule Chess.Moves.Pieces.King.Castling do [{5, rank}, {6, rank}] |> Enum.any?(fn {to_file, to_rank} -> 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) |> GameState.king_in_check?(colour) end) diff --git a/lib/chess_web/templates/game/board.html.leex b/lib/chess_web/templates/game/board.html.leex index 437d2e6..c5d3ede 100644 --- a/lib/chess_web/templates/game/board.html.leex +++ b/lib/chess_web/templates/game/board.html.leex @@ -1,4 +1,4 @@ -
+
1
2
@@ -22,14 +22,14 @@
- <%= for rank <- 0..7 do %> + <%= for {rank, row} <- @board do %>
- <%= for file <- 0..7 do %> + <%= for {file, piece} <- row do %> <%= render ChessWeb.SquareView, "square.html", rank: rank, file: file, - piece: @game.board["#{file},#{rank}"], + piece: piece, selected: {file, rank} == @selected, available: {file, rank} in @available %> <% end %> diff --git a/lib/chess_web/views/live/board_live.ex b/lib/chess_web/views/live/board_live.ex index ff7612d..c834bb2 100644 --- a/lib/chess_web/views/live/board_live.ex +++ b/lib/chess_web/views/live/board_live.ex @@ -5,6 +5,7 @@ defmodule ChessWeb.BoardLive do alias Chess.Store.Game alias Chess.Repo alias Chess.Board + alias Chess.Moves import Chess.Auth, only: [get_user!: 1] @@ -19,11 +20,24 @@ defmodule ChessWeb.BoardLive do Game.for_user(user) |> Repo.get!(game_id) - {:ok, assign(socket, game: game, user: user, selected: nil, available: [])} + {:ok, assign(socket, default_assigns(game, user))} end 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 defp handle_click(socket, file, rank) do @@ -34,27 +48,56 @@ defmodule ChessWeb.BoardLive do colour = ChessWeb.GameView.player_colour(user, game) assigns = - case socket.assigns do - %{:selected => nil} -> - case Board.piece(board, {file, rank}) do - %{"colour" => ^colour} -> - [{:selected, selected(file, rank)}] + if colour == game.turn do + case socket.assigns do + %{selected: nil} -> + handle_selection(board, colour, file, rank) - _ -> - [] - end - - _ -> - [{:selected, nil}] + _ -> + handle_move(socket.assigns, file, rank) + end end assign(socket, assigns) end - defp selected(file, rank) do - { - String.to_integer(file), - String.to_integer(rank) - } + defp handle_selection(board, colour, file, rank) do + case Board.piece(board, {file, rank}) do + %{"colour" => ^colour} -> + [ + {: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 diff --git a/test/chess/store/game_test.exs b/test/chess/store/game_test.exs index 47de511..a841b37 100644 --- a/test/chess/store/game_test.exs +++ b/test/chess/store/game_test.exs @@ -90,7 +90,7 @@ defmodule Chess.Store.GameTest do opponent_id: opponent.id }) - move_params = %{"from" => [4, 1], "to" => [4, 3]} + move_params = %{from: {4, 1}, to: {4, 3}} changeset = Game.move_changeset(