diff --git a/lib/islands_engine/rules.ex b/lib/islands_engine/rules.ex index 4357bcd..001db91 100644 --- a/lib/islands_engine/rules.ex +++ b/lib/islands_engine/rules.ex @@ -4,35 +4,70 @@ defmodule IslandEngine.Rules do """ alias __MODULE__ - defstruct state: :initialized + defstruct state: :initialized, + player1: :islands_not_set, + player2: :islands_not_set + @spec new() :: %IslandEngine.Rules{ + player1: :islands_not_set, + player2: :islands_not_set, + state: :initialized + } @doc """ Gives game rules. - Returns ``. + Returns `%Rules{}`. ## Examples iex> IslandEngine.Island.new() - %{} + %IslandEngine.Rules{ + state: :initialized, + player1: :islands_not_set, + player2: :islands_not_set + } """ def new(), do: %Rules{} + @doc """ + Gives game rules and transitions states and actions. Pattern matches for the current game state and actions possible in that state. For any state/event combination that ends up in catchall, we don’t want to transition the state. + + Returns `{:ok, rules}`. + + ## Examples + + iex> IslandEngine.Island.check(%Rules{state: :initialized} = rules, :add_player) + {:ok, %Rules{rules | state: :players_set}} + + """ def check(%Rules{state: :initialized} = rules, :add_player) do + # It makes a decision about whether it’s okay to add another player based on the current state of the game. Does not actually add a player. Calling the check/2 function with :add_player when we’re in the :initialized state returns {:ok, } and moves us into the :players_set state {:ok, %Rules{rules | state: :players_set}} end - @doc """ - For any state/event combination that ends up in this catchall, we don’t want to transition the state. By simply returning :error, we don’t transform the value of the :state key. Leaving it unchanged keeps the game in the same state. + def check(%Rules{state: :players_set} = rules, {:position_islands, player}) do + case Map.fetch!(rules, player) do + # If the value for the player key is :islands_not_set, it’s fine for that player to move her islands, so we return {:ok, rules}. If the values is :islands_set, it’s not okay for her to move her islands, so we return :error + :islands_set -> :error + :islands_not_set -> {:ok, rules} + end + end - Returns ``. + def check(%Rules{state: :players_set} = rules, {:set_islands, player}) do + rules = Map.put(rules, player, :islands_set) - ## Examples + case both_players_islands_set?(rules) do + true -> + {:ok, %Rules{rules | state: :player1_turn}} - iex> IslandEngine.Island.new() - %{} + false -> + {:ok, rules} + end + end - """ def check(_state, _action), do: :error + + defp both_players_islands_set?(rules), + do: rules.player1 == :islands_set && rules.player2 == :islands_set end