From 4e189b663340aae07b7fe07d5b64650226ae633f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Ortu=C3=B1o?= Date: Wed, 19 Oct 2022 08:44:47 +0200 Subject: [PATCH 1/4] Pawn movements --- lib/chess/table/board.ex | 13 +++++ lib/chess/table/empty_board.ex | 8 +++ lib/chess/table/game.ex | 7 +++ lib/chess/table/pawn.ex | 87 ++++++++++++++++++++++++++++++++ lib/chess/table/piece.ex | 13 +++++ lib/chess/table/pieces.ex | 38 ++++++++++++++ mix.lock | 25 ++++++++++ test/chess/game_test.exs | 91 ++++++++++++++++++++++++++++++++++ 8 files changed, 282 insertions(+) create mode 100644 lib/chess/table/board.ex create mode 100644 lib/chess/table/empty_board.ex create mode 100644 lib/chess/table/game.ex create mode 100644 lib/chess/table/pawn.ex create mode 100644 lib/chess/table/piece.ex create mode 100644 lib/chess/table/pieces.ex create mode 100644 mix.lock create mode 100644 test/chess/game_test.exs diff --git a/lib/chess/table/board.ex b/lib/chess/table/board.ex new file mode 100644 index 0000000..957edbb --- /dev/null +++ b/lib/chess/table/board.ex @@ -0,0 +1,13 @@ +defmodule Chess.Table.Board do + def is_there_an_own_piece?(pieces, position, color) do + Enum.any?(pieces, fn piece -> + piece.position == position && piece.color == color && piece.alive + end) + end + + def is_there_an_oponent_piece?(pieces, position, color) do + Enum.any?(pieces, fn piece -> + piece.position == position && piece.color != color && piece.alive + end) + end +end diff --git a/lib/chess/table/empty_board.ex b/lib/chess/table/empty_board.ex new file mode 100644 index 0000000..93b9a72 --- /dev/null +++ b/lib/chess/table/empty_board.ex @@ -0,0 +1,8 @@ +defmodule Chess.Table.EmptyBoard do + @y_axis [1, 2, 3, 4, 5, 6, 7, 8] + @x_axis ["A", "B", "C", "D", "E", "F", "G", "H"] + + def x_axis, do: @x_axis + def y_axis, do: @y_axis + +end diff --git a/lib/chess/table/game.ex b/lib/chess/table/game.ex new file mode 100644 index 0000000..ba83030 --- /dev/null +++ b/lib/chess/table/game.ex @@ -0,0 +1,7 @@ +defmodule Chess.Table.Game do + def start() do + pieces = Chess.Table.Pieces.fresh_start + pieces + end + +end diff --git a/lib/chess/table/pawn.ex b/lib/chess/table/pawn.ex new file mode 100644 index 0000000..88a44d7 --- /dev/null +++ b/lib/chess/table/pawn.ex @@ -0,0 +1,87 @@ +defmodule Chess.Table.Pawn do + + def all_possible_moves(pieces, position, color) do + [column | [row | _]] = String.graphemes position + forward = moves_forward(pieces, column, row, color) + captures = captures(pieces, column, row, color) + forward ++ captures + end + + def captures(pieces, column, row, color) do + new_row = new_row(row, color) + positions = new_columns column, new_row + Enum.filter(positions, fn pos -> + Chess.Table.Board.is_there_an_oponent_piece?(pieces, pos, color) + end) + end + + def moves_forward(pieces, column, row, :white) when row == "2" do + next_row = new_row(row, :white) + position = "#{column}#{next_row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :white) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :white) + if(blocked) do + [] + else + list = [position] + next_row = new_row("#{next_row}", :white) + position = "#{column}#{next_row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :white) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :white) + if(!blocked) do + list ++ [position] + else + list + end + end + end + + def moves_forward(pieces, column, row, :black) when row == "7" do + next_row = new_row(row, :black) + position = "#{column}#{next_row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :black) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :black) + if(blocked) do + [] + else + list = [position] + next_row = new_row("#{next_row}", :black) + position = "#{column}#{next_row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :black) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :black) + if(!blocked) do + list ++ [position] + else + list + end + end + end + + def moves_forward(pieces, column, row, color) do + next_row = new_row(row, color) + position = "#{column}#{next_row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + if(blocked) do + [] + else + [position] + end + end + + defp new_row(row, color) do + {new_row, _} = Integer.parse row + case color do + :white -> new_row + 1 + :black -> new_row - 1 + end + end + + defp new_columns(column, row) do + column_index = Enum.find_index Chess.Table.EmptyBoard.x_axis, fn x -> x == column end + pos = position(column_index) + Enum.map(pos, fn x -> + new_column = Enum.at Chess.Table.EmptyBoard.x_axis, x + "#{new_column}#{row}" + end) + end + + defp position(x) when x == 0 do [x + 1] end + defp position(x) when x == 7 do [x - 1] end + defp position(x) do [x + 1, x - 1] end +end diff --git a/lib/chess/table/piece.ex b/lib/chess/table/piece.ex new file mode 100644 index 0000000..8969304 --- /dev/null +++ b/lib/chess/table/piece.ex @@ -0,0 +1,13 @@ +defmodule Chess.Table.Piece do + @enforce_keys [ + :name, + :position, + :color + ] + defstruct [ + :name, + :position, + :color, + alive: true, + ] +end diff --git a/lib/chess/table/pieces.ex b/lib/chess/table/pieces.ex new file mode 100644 index 0000000..a93f69b --- /dev/null +++ b/lib/chess/table/pieces.ex @@ -0,0 +1,38 @@ +defmodule Chess.Table.Pieces do + def fresh_start do + _pieces = [ + %Chess.Table.Piece{name: :rook, position: "A1", color: :white}, + %Chess.Table.Piece{name: :knight, position: "B1", color: :white}, + %Chess.Table.Piece{name: :bishop, position: "C1", color: :white}, + %Chess.Table.Piece{name: :queen, position: "D1", color: :white}, + %Chess.Table.Piece{name: :king, position: "E1", color: :white}, + %Chess.Table.Piece{name: :bishop, position: "F1", color: :white}, + %Chess.Table.Piece{name: :knight, position: "G1", color: :white}, + %Chess.Table.Piece{name: :rook, position: "H1", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "A2", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "B2", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "C2", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "D2", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "E2", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "F2", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "G2", color: :white}, + %Chess.Table.Piece{name: :pawn, position: "H2", color: :white}, + %Chess.Table.Piece{name: :rook, position: "A8", color: :black}, + %Chess.Table.Piece{name: :knight, position: "B8", color: :black}, + %Chess.Table.Piece{name: :bishop, position: "C8", color: :black}, + %Chess.Table.Piece{name: :queen, position: "D8", color: :black}, + %Chess.Table.Piece{name: :king, position: "E8", color: :black}, + %Chess.Table.Piece{name: :bishop, position: "F8", color: :black}, + %Chess.Table.Piece{name: :knight, position: "G8", color: :black}, + %Chess.Table.Piece{name: :rook, position: "H8", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "A7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "B7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "C7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "D7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "E7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "F7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "G7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "H7", color: :black}, + ] + end +end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..e827ca2 --- /dev/null +++ b/mix.lock @@ -0,0 +1,25 @@ +%{ + "castore": {:hex, :castore, "0.1.18", "deb5b9ab02400561b6f5708f3e7660fc35ca2d51bfc6a940d2f513f89c2975fc", [:mix], [], "hexpm", "61bbaf6452b782ef80b33cdb45701afbcf0a918a45ebe7e73f1130d661e66a06"}, + "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, + "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, + "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, + "esbuild": {:hex, :esbuild, "0.5.0", "d5bb08ff049d7880ee3609ed5c4b864bd2f46445ea40b16b4acead724fb4c4a3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "f183a0b332d963c4cfaf585477695ea59eef9a6f2204fdd0efa00e099694ffe5"}, + "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "floki": {:hex, :floki, "0.33.1", "f20f1eb471e726342b45ccb68edb9486729e7df94da403936ea94a794f072781", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "461035fd125f13fdf30f243c85a0b1e50afbec876cbf1ceefe6fddd2e6d712c6"}, + "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, + "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, + "mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"}, + "phoenix": {:hex, :phoenix, "1.6.14", "57678366dc1d5bad49832a0fc7f12c2830c10d3eacfad681bfe9602cd4445f04", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d48c0da00b3d4cd1aad6055387917491af9f6e1f1e96cedf6c6b7998df9dba26"}, + "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, + "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.12", "74f4c0ad02d7deac2d04f50b52827a5efdc5c6e7fac5cede145f5f0e4183aedc", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.0 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "af6dd5e0aac16ff43571f527a8e0616d62cb80b10eb87aac82170243e50d99c8"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, + "phoenix_view": {:hex, :phoenix_view, "1.1.2", "1b82764a065fb41051637872c7bd07ed2fdb6f5c3bd89684d4dca6e10115c95a", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "7ae90ad27b09091266f6adbb61e1d2516a7c3d7062c6789d46a7554ec40f3a56"}, + "plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"}, + "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, + "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, + "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, + "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, + "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, +} diff --git a/test/chess/game_test.exs b/test/chess/game_test.exs new file mode 100644 index 0000000..9469cb8 --- /dev/null +++ b/test/chess/game_test.exs @@ -0,0 +1,91 @@ +defmodule GameTest do + use ExUnit.Case + + setup do + pieces = Chess.Table.Game.start + %{pieces: pieces} + end + + test "all pieces of game", %{pieces: pieces} do + assert pieces == [ + %Chess.Table.Piece{name: :rook, position: "A1", color: :white, alive: true}, + %Chess.Table.Piece{name: :knight, position: "B1", color: :white, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "C1", color: :white, alive: true}, + %Chess.Table.Piece{name: :queen, position: "D1", color: :white, alive: true}, + %Chess.Table.Piece{name: :king, position: "E1", color: :white, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "F1", color: :white, alive: true}, + %Chess.Table.Piece{name: :knight, position: "G1", color: :white, alive: true}, + %Chess.Table.Piece{name: :rook, position: "H1", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "A2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "D2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "E2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "F2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "G2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "H2", color: :white, alive: true}, + %Chess.Table.Piece{name: :rook, position: "A8", color: :black, alive: true}, + %Chess.Table.Piece{name: :knight, position: "B8", color: :black, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "C8", color: :black, alive: true}, + %Chess.Table.Piece{name: :queen, position: "D8", color: :black, alive: true}, + %Chess.Table.Piece{name: :king, position: "E8", color: :black, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "F8", color: :black, alive: true}, + %Chess.Table.Piece{name: :knight, position: "G8", color: :black, alive: true}, + %Chess.Table.Piece{name: :rook, position: "H8", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "A7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "D7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "E7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "F7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "G7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "H7", color: :black, alive: true} + ] + end + + test "white pawn can move forward two steps", %{pieces: pieces} do + moves = Chess.Table.Pawn.all_possible_moves(pieces, "A2", :white) + assert moves === ["A3", "A4"] + end + + test "white pawn can move forward only one step" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "B4", color: :white, alive: true}, + ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B2", :white) + assert moves === ["B3"] + end + + test "white pawn can capture" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "A7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C7", color: :black, alive: true}, + ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B6", :white) + assert Enum.sort(moves) == ["A7", "C7"] + end + + test "black pawn can move forward only one step" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "B5", color: :white, alive: true}, + ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B7", :black) + assert moves === ["B6"] + end + + test "black pawn can move forward two steps", %{pieces: pieces} do + moves = Chess.Table.Pawn.all_possible_moves(pieces, "A7", :black) + assert moves === ["A6", "A5"] + end + + test "black pawn can capture" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "A2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C2", color: :white, alive: true}, + ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B3", :black) + assert Enum.sort(moves) == ["A2", "C2"] + end +end From 2f1338644963b6b6631a9e0ad889515a0bcabc25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Ortu=C3=B1o?= Date: Wed, 19 Oct 2022 11:14:16 +0200 Subject: [PATCH 2/4] Rook -> all possible moves --- lib/chess/table/rook.ex | 89 ++++++++++++++++++++++++++++++++++++++++ test/chess/game_test.exs | 77 ++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 lib/chess/table/rook.ex diff --git a/lib/chess/table/rook.ex b/lib/chess/table/rook.ex new file mode 100644 index 0000000..d8e7b2f --- /dev/null +++ b/lib/chess/table/rook.ex @@ -0,0 +1,89 @@ +defmodule Chess.Table.Rook do + def all_possible_moves(pieces, position, color) do + moves = [] + + moves + |> up_straight_moves(pieces, position, color) + |> right_moves(pieces, position, color) + |> down_straight_moves(pieces, position, color) + |> left_moves(pieces, position, color) + end + + defp up_straight_moves(moves, pieces, position, color) do + [column | [row | _]] = String.graphemes position + {row, _} = Integer.parse row + move_up_straight_one_step(pieces, column, row, moves, color) + end + + defp move_up_straight_one_step(_pieces, _column, row, moves, _color) when row == 8 do moves end + defp move_up_straight_one_step(pieces, column, row, moves, color) do + row = row + 1 + position = "#{column}#{row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) + oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do + blocked -> moves + oponent_field -> moves ++ [position] + true -> move_up_straight_one_step(pieces, column, row, moves ++ [position], color) + end + end + + defp right_moves(moves, pieces, position, color) do + [column | [row | _]] = String.graphemes position + column_index = Enum.find_index Chess.Table.EmptyBoard.x_axis, fn x -> x == column end + move_right_one_step(pieces, column_index, row, moves, color) + end + + defp move_right_one_step(_pieces, column_index, _row, moves, _color) when column_index == 7 do moves end + defp move_right_one_step(pieces, column_index, row, moves, color) do + column_index = column_index + 1 + column = Enum.at Chess.Table.EmptyBoard.x_axis, column_index + position = "#{column}#{row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) + oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do + blocked -> moves + oponent_field -> moves ++ [position] + true -> move_right_one_step(pieces, column_index, row, moves ++ [position], color) + end + end + + defp down_straight_moves(moves, pieces, position, color) do + [column | [row | _]] = String.graphemes position + {row, _} = Integer.parse row + move_down_straight_one_step(pieces, column, row, moves, color) + end + + defp move_down_straight_one_step(_pieces, _column, row, moves, _color) when row == 1 do moves end + defp move_down_straight_one_step(pieces, column, row, moves, color) do + row = row - 1 + position = "#{column}#{row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) + oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do + blocked -> moves + oponent_field -> moves ++ [position] + true -> move_down_straight_one_step(pieces, column, row, moves ++ [position], color) + end + end + + defp left_moves(moves, pieces, position, color) do + [column | [row | _]] = String.graphemes position + column_index = Enum.find_index Chess.Table.EmptyBoard.x_axis, fn x -> x == column end + move_left_one_step(pieces, column_index, row, moves, color) + end + + defp move_left_one_step(_pieces, column_index, _row, moves, _color) when column_index == 0 do moves end + defp move_left_one_step(pieces, column_index, row, moves, color) do + column_index = column_index - 1 + column = Enum.at Chess.Table.EmptyBoard.x_axis, column_index + position = "#{column}#{row}" + blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) + oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do + blocked -> moves + oponent_field -> moves ++ [position] + true -> move_left_one_step(pieces, column_index, row, moves ++ [position], color) + end + end +end diff --git a/test/chess/game_test.exs b/test/chess/game_test.exs index 9469cb8..0c62d4e 100644 --- a/test/chess/game_test.exs +++ b/test/chess/game_test.exs @@ -88,4 +88,81 @@ defmodule GameTest do moves = Chess.Table.Pawn.all_possible_moves(pieces, "B3", :black) assert Enum.sort(moves) == ["A2", "C2"] end + + test "white rook can move forward and right" do + pieces = [] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) + assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "A6", "A7", "A8", "B1", "C1", "D1", "E1", "F1", "G1", "H1"] + end + + test "white rook can move forward but is blocked in A5" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "A5", color: :white, alive: true}, + ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) + assert Enum.sort(moves) == ["A2", "A3", "A4", "B1", "C1", "D1", "E1", "F1", "G1", "H1"] + end + + test "white rook can move right but is blocked in E1" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "E1", color: :white, alive: true} + ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) + assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "A6", "A7", "A8", "B1", "C1", "D1"] + end + + test "black rook can move down and right" do + pieces = [] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A8", :black) + assert Enum.sort(moves) == ["A1", "A2", "A3", "A4", "A5", "A6", "A7", "B8", "C8", "D8", "E8", "F8", "G8", "H8"] + end + + test "black rook can move down but is blocked in A5" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "A5", color: :black, alive: true} + ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A8", :black) + assert Enum.sort(moves) == ["A6", "A7", "B8", "C8", "D8", "E8", "F8", "G8", "H8"] + end + + test "black rook can move right but is blocked in E8" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "E8", color: :black, alive: true} + ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A8", :black) + assert Enum.sort(moves) == ["A1", "A2", "A3", "A4", "A5", "A6", "A7", "B8", "C8", "D8"] + end + + test "black rook can move down and left and right" do + pieces = [] + moves = Chess.Table.Rook.all_possible_moves(pieces, "D8", :black) + assert Enum.sort(moves) == ["A8", "B8", "C8", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "E8", "F8", "G8", "H8"] + end + + test "white rook can move right but oponent is in A5" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "A5", color: :black, alive: true} + ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) + assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "B1", "C1", "D1", "E1", "F1", "G1", "H1"] + end + + test "white rook can move right but oponent is in A5 and D1" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "A5", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "D1", color: :black, alive: true} + ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) + assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "B1", "C1", "D1"] + end + + test "white rook is in D3 and is blocked in D2 and oponent is in D6 and F3" do + pieces = [ + %Chess.Table.Piece{name: :pawn, position: "D2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "D6", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "F3", color: :black, alive: true} + ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "D3", :white) + assert Enum.sort(moves) == ["A3", "B3", "C3", "D4", "D5", "D6", "E3", "F3"] + end end From 79c12f91289bc06b0e287e9ad9fa7ecd2bd6278f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Ortu=C3=B1o?= Date: Wed, 19 Oct 2022 11:14:30 +0200 Subject: [PATCH 3/4] Run tests --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 51b97fc..149ecce 100644 --- a/README.md +++ b/README.md @@ -64,3 +64,8 @@ The idea is that two players should be able to play a single game. You can make 8. Remember to push your code to your fork!!! **IMPORTANT:** No other dependencies than those listed in `mix.exs` are allowed. Any extra dependency must be approved by the jury. + + +## TESTS + + mix test test/chess/game_test.exs --trace From 61b91d025131fc75d767775791ecf584b742ba56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Ortu=C3=B1o?= Date: Wed, 19 Oct 2022 11:55:31 +0200 Subject: [PATCH 4/4] First move --- lib/chess/table/empty_board.ex | 1 - lib/chess/table/game.ex | 32 ++++++- lib/chess/table/pawn.ex | 58 +++++++++---- lib/chess/table/piece.ex | 2 +- lib/chess/table/pieces.ex | 2 +- lib/chess/table/rook.ex | 44 ++++++---- test/chess/game_test.exs | 148 +++++++++++++++++++++++---------- 7 files changed, 213 insertions(+), 74 deletions(-) diff --git a/lib/chess/table/empty_board.ex b/lib/chess/table/empty_board.ex index 93b9a72..581e311 100644 --- a/lib/chess/table/empty_board.ex +++ b/lib/chess/table/empty_board.ex @@ -4,5 +4,4 @@ defmodule Chess.Table.EmptyBoard do def x_axis, do: @x_axis def y_axis, do: @y_axis - end diff --git a/lib/chess/table/game.ex b/lib/chess/table/game.ex index ba83030..3d164ff 100644 --- a/lib/chess/table/game.ex +++ b/lib/chess/table/game.ex @@ -1,7 +1,37 @@ defmodule Chess.Table.Game do def start() do - pieces = Chess.Table.Pieces.fresh_start + pieces = Chess.Table.Pieces.fresh_start() pieces end + def move(pieces, color, from, to) do + check_from_position = Chess.Table.Board.is_there_an_own_piece?(pieces, from, color) + + cond do + check_from_position -> can_move(pieces, color, from, to) + true -> :fail + end + end + + defp can_move(pieces, color, from, to) do + [piece | _] = Enum.filter(pieces, fn p -> p.position == from end) + :fail + + possible_moves = + cond do + piece.name == :pawn -> Chess.Table.Pawn.all_possible_moves(pieces, from, color) + piece.name == :rook -> Chess.Table.Rook.all_possible_moves(pieces, from, color) + end + + status = + if(Enum.member?(possible_moves, to)) do + :ok + else + :fail + end + + pieces = Enum.drop_while(pieces, fn p -> p.position == from end) + + %{status: status, pieces: pieces ++ [%Chess.Table.Piece{name: piece.name, position: to, color: piece.color, alive: true}]} + end end diff --git a/lib/chess/table/pawn.ex b/lib/chess/table/pawn.ex index 88a44d7..51a13cd 100644 --- a/lib/chess/table/pawn.ex +++ b/lib/chess/table/pawn.ex @@ -1,7 +1,6 @@ defmodule Chess.Table.Pawn do - def all_possible_moves(pieces, position, color) do - [column | [row | _]] = String.graphemes position + [column | [row | _]] = String.graphemes(position) forward = moves_forward(pieces, column, row, color) captures = captures(pieces, column, row, color) forward ++ captures @@ -9,7 +8,8 @@ defmodule Chess.Table.Pawn do def captures(pieces, column, row, color) do new_row = new_row(row, color) - positions = new_columns column, new_row + positions = new_columns(column, new_row) + Enum.filter(positions, fn pos -> Chess.Table.Board.is_there_an_oponent_piece?(pieces, pos, color) end) @@ -18,14 +18,22 @@ defmodule Chess.Table.Pawn do def moves_forward(pieces, column, row, :white) when row == "2" do next_row = new_row(row, :white) position = "#{column}#{next_row}" - blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :white) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :white) + + blocked = + Chess.Table.Board.is_there_an_own_piece?(pieces, position, :white) || + Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :white) + if(blocked) do [] else list = [position] next_row = new_row("#{next_row}", :white) position = "#{column}#{next_row}" - blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :white) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :white) + + blocked = + Chess.Table.Board.is_there_an_own_piece?(pieces, position, :white) || + Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :white) + if(!blocked) do list ++ [position] else @@ -37,14 +45,22 @@ defmodule Chess.Table.Pawn do def moves_forward(pieces, column, row, :black) when row == "7" do next_row = new_row(row, :black) position = "#{column}#{next_row}" - blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :black) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :black) + + blocked = + Chess.Table.Board.is_there_an_own_piece?(pieces, position, :black) || + Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :black) + if(blocked) do [] else list = [position] next_row = new_row("#{next_row}", :black) position = "#{column}#{next_row}" - blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, :black) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :black) + + blocked = + Chess.Table.Board.is_there_an_own_piece?(pieces, position, :black) || + Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, :black) + if(!blocked) do list ++ [position] else @@ -56,7 +72,11 @@ defmodule Chess.Table.Pawn do def moves_forward(pieces, column, row, color) do next_row = new_row(row, color) position = "#{column}#{next_row}" - blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) || Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + + blocked = + Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) || + Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + if(blocked) do [] else @@ -65,7 +85,8 @@ defmodule Chess.Table.Pawn do end defp new_row(row, color) do - {new_row, _} = Integer.parse row + {new_row, _} = Integer.parse(row) + case color do :white -> new_row + 1 :black -> new_row - 1 @@ -73,15 +94,24 @@ defmodule Chess.Table.Pawn do end defp new_columns(column, row) do - column_index = Enum.find_index Chess.Table.EmptyBoard.x_axis, fn x -> x == column end + column_index = Enum.find_index(Chess.Table.EmptyBoard.x_axis(), fn x -> x == column end) pos = position(column_index) + Enum.map(pos, fn x -> - new_column = Enum.at Chess.Table.EmptyBoard.x_axis, x + new_column = Enum.at(Chess.Table.EmptyBoard.x_axis(), x) "#{new_column}#{row}" end) end - defp position(x) when x == 0 do [x + 1] end - defp position(x) when x == 7 do [x - 1] end - defp position(x) do [x + 1, x - 1] end + defp position(x) when x == 0 do + [x + 1] + end + + defp position(x) when x == 7 do + [x - 1] + end + + defp position(x) do + [x + 1, x - 1] + end end diff --git a/lib/chess/table/piece.ex b/lib/chess/table/piece.ex index 8969304..a64ed18 100644 --- a/lib/chess/table/piece.ex +++ b/lib/chess/table/piece.ex @@ -8,6 +8,6 @@ defmodule Chess.Table.Piece do :name, :position, :color, - alive: true, + alive: true ] end diff --git a/lib/chess/table/pieces.ex b/lib/chess/table/pieces.ex index a93f69b..48f8ed5 100644 --- a/lib/chess/table/pieces.ex +++ b/lib/chess/table/pieces.ex @@ -32,7 +32,7 @@ defmodule Chess.Table.Pieces do %Chess.Table.Piece{name: :pawn, position: "E7", color: :black}, %Chess.Table.Piece{name: :pawn, position: "F7", color: :black}, %Chess.Table.Piece{name: :pawn, position: "G7", color: :black}, - %Chess.Table.Piece{name: :pawn, position: "H7", color: :black}, + %Chess.Table.Piece{name: :pawn, position: "H7", color: :black} ] end end diff --git a/lib/chess/table/rook.ex b/lib/chess/table/rook.ex index d8e7b2f..56cff44 100644 --- a/lib/chess/table/rook.ex +++ b/lib/chess/table/rook.ex @@ -10,17 +10,21 @@ defmodule Chess.Table.Rook do end defp up_straight_moves(moves, pieces, position, color) do - [column | [row | _]] = String.graphemes position - {row, _} = Integer.parse row + [column | [row | _]] = String.graphemes(position) + {row, _} = Integer.parse(row) move_up_straight_one_step(pieces, column, row, moves, color) end - defp move_up_straight_one_step(_pieces, _column, row, moves, _color) when row == 8 do moves end + defp move_up_straight_one_step(_pieces, _column, row, moves, _color) when row == 8 do + moves + end + defp move_up_straight_one_step(pieces, column, row, moves, color) do row = row + 1 position = "#{column}#{row}" blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do blocked -> moves oponent_field -> moves ++ [position] @@ -29,18 +33,22 @@ defmodule Chess.Table.Rook do end defp right_moves(moves, pieces, position, color) do - [column | [row | _]] = String.graphemes position - column_index = Enum.find_index Chess.Table.EmptyBoard.x_axis, fn x -> x == column end + [column | [row | _]] = String.graphemes(position) + column_index = Enum.find_index(Chess.Table.EmptyBoard.x_axis(), fn x -> x == column end) move_right_one_step(pieces, column_index, row, moves, color) end - defp move_right_one_step(_pieces, column_index, _row, moves, _color) when column_index == 7 do moves end + defp move_right_one_step(_pieces, column_index, _row, moves, _color) when column_index == 7 do + moves + end + defp move_right_one_step(pieces, column_index, row, moves, color) do column_index = column_index + 1 - column = Enum.at Chess.Table.EmptyBoard.x_axis, column_index + column = Enum.at(Chess.Table.EmptyBoard.x_axis(), column_index) position = "#{column}#{row}" blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do blocked -> moves oponent_field -> moves ++ [position] @@ -49,17 +57,21 @@ defmodule Chess.Table.Rook do end defp down_straight_moves(moves, pieces, position, color) do - [column | [row | _]] = String.graphemes position - {row, _} = Integer.parse row + [column | [row | _]] = String.graphemes(position) + {row, _} = Integer.parse(row) move_down_straight_one_step(pieces, column, row, moves, color) end - defp move_down_straight_one_step(_pieces, _column, row, moves, _color) when row == 1 do moves end + defp move_down_straight_one_step(_pieces, _column, row, moves, _color) when row == 1 do + moves + end + defp move_down_straight_one_step(pieces, column, row, moves, color) do row = row - 1 position = "#{column}#{row}" blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do blocked -> moves oponent_field -> moves ++ [position] @@ -68,18 +80,22 @@ defmodule Chess.Table.Rook do end defp left_moves(moves, pieces, position, color) do - [column | [row | _]] = String.graphemes position - column_index = Enum.find_index Chess.Table.EmptyBoard.x_axis, fn x -> x == column end + [column | [row | _]] = String.graphemes(position) + column_index = Enum.find_index(Chess.Table.EmptyBoard.x_axis(), fn x -> x == column end) move_left_one_step(pieces, column_index, row, moves, color) end - defp move_left_one_step(_pieces, column_index, _row, moves, _color) when column_index == 0 do moves end + defp move_left_one_step(_pieces, column_index, _row, moves, _color) when column_index == 0 do + moves + end + defp move_left_one_step(pieces, column_index, row, moves, color) do column_index = column_index - 1 - column = Enum.at Chess.Table.EmptyBoard.x_axis, column_index + column = Enum.at(Chess.Table.EmptyBoard.x_axis(), column_index) position = "#{column}#{row}" blocked = Chess.Table.Board.is_there_an_own_piece?(pieces, position, color) oponent_field = Chess.Table.Board.is_there_an_oponent_piece?(pieces, position, color) + cond do blocked -> moves oponent_field -> moves ++ [position] diff --git a/test/chess/game_test.exs b/test/chess/game_test.exs index 0c62d4e..13f54db 100644 --- a/test/chess/game_test.exs +++ b/test/chess/game_test.exs @@ -2,45 +2,45 @@ defmodule GameTest do use ExUnit.Case setup do - pieces = Chess.Table.Game.start + pieces = Chess.Table.Game.start() %{pieces: pieces} end test "all pieces of game", %{pieces: pieces} do assert pieces == [ - %Chess.Table.Piece{name: :rook, position: "A1", color: :white, alive: true}, - %Chess.Table.Piece{name: :knight, position: "B1", color: :white, alive: true}, - %Chess.Table.Piece{name: :bishop, position: "C1", color: :white, alive: true}, - %Chess.Table.Piece{name: :queen, position: "D1", color: :white, alive: true}, - %Chess.Table.Piece{name: :king, position: "E1", color: :white, alive: true}, - %Chess.Table.Piece{name: :bishop, position: "F1", color: :white, alive: true}, - %Chess.Table.Piece{name: :knight, position: "G1", color: :white, alive: true}, - %Chess.Table.Piece{name: :rook, position: "H1", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "A2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "B2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "C2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "D2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "E2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "F2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "G2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "H2", color: :white, alive: true}, - %Chess.Table.Piece{name: :rook, position: "A8", color: :black, alive: true}, - %Chess.Table.Piece{name: :knight, position: "B8", color: :black, alive: true}, - %Chess.Table.Piece{name: :bishop, position: "C8", color: :black, alive: true}, - %Chess.Table.Piece{name: :queen, position: "D8", color: :black, alive: true}, - %Chess.Table.Piece{name: :king, position: "E8", color: :black, alive: true}, - %Chess.Table.Piece{name: :bishop, position: "F8", color: :black, alive: true}, - %Chess.Table.Piece{name: :knight, position: "G8", color: :black, alive: true}, - %Chess.Table.Piece{name: :rook, position: "H8", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "A7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "B7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "C7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "D7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "E7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "F7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "G7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "H7", color: :black, alive: true} - ] + %Chess.Table.Piece{name: :rook, position: "A1", color: :white, alive: true}, + %Chess.Table.Piece{name: :knight, position: "B1", color: :white, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "C1", color: :white, alive: true}, + %Chess.Table.Piece{name: :queen, position: "D1", color: :white, alive: true}, + %Chess.Table.Piece{name: :king, position: "E1", color: :white, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "F1", color: :white, alive: true}, + %Chess.Table.Piece{name: :knight, position: "G1", color: :white, alive: true}, + %Chess.Table.Piece{name: :rook, position: "H1", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "A2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "D2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "E2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "F2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "G2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "H2", color: :white, alive: true}, + %Chess.Table.Piece{name: :rook, position: "A8", color: :black, alive: true}, + %Chess.Table.Piece{name: :knight, position: "B8", color: :black, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "C8", color: :black, alive: true}, + %Chess.Table.Piece{name: :queen, position: "D8", color: :black, alive: true}, + %Chess.Table.Piece{name: :king, position: "E8", color: :black, alive: true}, + %Chess.Table.Piece{name: :bishop, position: "F8", color: :black, alive: true}, + %Chess.Table.Piece{name: :knight, position: "G8", color: :black, alive: true}, + %Chess.Table.Piece{name: :rook, position: "H8", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "A7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "D7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "E7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "F7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "G7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "H7", color: :black, alive: true} + ] end test "white pawn can move forward two steps", %{pieces: pieces} do @@ -50,8 +50,9 @@ defmodule GameTest do test "white pawn can move forward only one step" do pieces = [ - %Chess.Table.Piece{name: :pawn, position: "B4", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B4", color: :white, alive: true} ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B2", :white) assert moves === ["B3"] end @@ -60,16 +61,18 @@ defmodule GameTest do pieces = [ %Chess.Table.Piece{name: :pawn, position: "A7", color: :black, alive: true}, %Chess.Table.Piece{name: :pawn, position: "B7", color: :black, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "C7", color: :black, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C7", color: :black, alive: true} ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B6", :white) assert Enum.sort(moves) == ["A7", "C7"] end test "black pawn can move forward only one step" do pieces = [ - %Chess.Table.Piece{name: :pawn, position: "B5", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "B5", color: :white, alive: true} ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B7", :black) assert moves === ["B6"] end @@ -83,8 +86,9 @@ defmodule GameTest do pieces = [ %Chess.Table.Piece{name: :pawn, position: "A2", color: :white, alive: true}, %Chess.Table.Piece{name: :pawn, position: "B2", color: :white, alive: true}, - %Chess.Table.Piece{name: :pawn, position: "C2", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "C2", color: :white, alive: true} ] + moves = Chess.Table.Pawn.all_possible_moves(pieces, "B3", :black) assert Enum.sort(moves) == ["A2", "C2"] end @@ -92,13 +96,30 @@ defmodule GameTest do test "white rook can move forward and right" do pieces = [] moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) - assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "A6", "A7", "A8", "B1", "C1", "D1", "E1", "F1", "G1", "H1"] + + assert Enum.sort(moves) == [ + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ] end test "white rook can move forward but is blocked in A5" do pieces = [ - %Chess.Table.Piece{name: :pawn, position: "A5", color: :white, alive: true}, + %Chess.Table.Piece{name: :pawn, position: "A5", color: :white, alive: true} ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) assert Enum.sort(moves) == ["A2", "A3", "A4", "B1", "C1", "D1", "E1", "F1", "G1", "H1"] end @@ -107,6 +128,7 @@ defmodule GameTest do pieces = [ %Chess.Table.Piece{name: :pawn, position: "E1", color: :white, alive: true} ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "A6", "A7", "A8", "B1", "C1", "D1"] end @@ -114,13 +136,30 @@ defmodule GameTest do test "black rook can move down and right" do pieces = [] moves = Chess.Table.Rook.all_possible_moves(pieces, "A8", :black) - assert Enum.sort(moves) == ["A1", "A2", "A3", "A4", "A5", "A6", "A7", "B8", "C8", "D8", "E8", "F8", "G8", "H8"] + + assert Enum.sort(moves) == [ + "A1", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ] end test "black rook can move down but is blocked in A5" do pieces = [ %Chess.Table.Piece{name: :pawn, position: "A5", color: :black, alive: true} ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A8", :black) assert Enum.sort(moves) == ["A6", "A7", "B8", "C8", "D8", "E8", "F8", "G8", "H8"] end @@ -129,6 +168,7 @@ defmodule GameTest do pieces = [ %Chess.Table.Piece{name: :pawn, position: "E8", color: :black, alive: true} ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A8", :black) assert Enum.sort(moves) == ["A1", "A2", "A3", "A4", "A5", "A6", "A7", "B8", "C8", "D8"] end @@ -136,13 +176,30 @@ defmodule GameTest do test "black rook can move down and left and right" do pieces = [] moves = Chess.Table.Rook.all_possible_moves(pieces, "D8", :black) - assert Enum.sort(moves) == ["A8", "B8", "C8", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "E8", "F8", "G8", "H8"] + + assert Enum.sort(moves) == [ + "A8", + "B8", + "C8", + "D1", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "E8", + "F8", + "G8", + "H8" + ] end test "white rook can move right but oponent is in A5" do pieces = [ %Chess.Table.Piece{name: :pawn, position: "A5", color: :black, alive: true} ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "B1", "C1", "D1", "E1", "F1", "G1", "H1"] end @@ -152,6 +209,7 @@ defmodule GameTest do %Chess.Table.Piece{name: :pawn, position: "A5", color: :black, alive: true}, %Chess.Table.Piece{name: :pawn, position: "D1", color: :black, alive: true} ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "A1", :white) assert Enum.sort(moves) == ["A2", "A3", "A4", "A5", "B1", "C1", "D1"] end @@ -162,7 +220,13 @@ defmodule GameTest do %Chess.Table.Piece{name: :pawn, position: "D6", color: :black, alive: true}, %Chess.Table.Piece{name: :pawn, position: "F3", color: :black, alive: true} ] + moves = Chess.Table.Rook.all_possible_moves(pieces, "D3", :white) assert Enum.sort(moves) == ["A3", "B3", "C3", "D4", "D5", "D6", "E3", "F3"] end + + test "first move", %{pieces: pieces} do + move = Chess.Table.Game.move(pieces, :white, "D2", "D4") + assert move.status == :ok + end end