Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 13 additions & 0 deletions lib/chess/table/board.ex
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions lib/chess/table/empty_board.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
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
37 changes: 37 additions & 0 deletions lib/chess/table/game.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule Chess.Table.Game do
def start() do
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
117 changes: 117 additions & 0 deletions lib/chess/table/pawn.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
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
13 changes: 13 additions & 0 deletions lib/chess/table/piece.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule Chess.Table.Piece do
@enforce_keys [
:name,
:position,
:color
]
defstruct [
:name,
:position,
:color,
alive: true
]
end
38 changes: 38 additions & 0 deletions lib/chess/table/pieces.ex
Original file line number Diff line number Diff line change
@@ -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
105 changes: 105 additions & 0 deletions lib/chess/table/rook.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
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
25 changes: 25 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -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"},
}
Loading