Current section

Files

Jump to
islands_player lib islands player.ex
Raw

lib/islands/player.ex

# ┌────────────────────────────────────────────────────────────────────┐
# │ Based on the book "Functional Web Development" by Lance Halvorsen. │
# └────────────────────────────────────────────────────────────────────┘
defmodule Islands.Player do
@moduledoc """
Creates a `player` struct for the _Game of Islands_.
##### Based on the book [Functional Web Development](https://pragprog.com/book/lhelph/functional-web-development-with-elixir-otp-and-phoenix) by Lance Halvorsen.
"""
alias __MODULE__
alias Islands.{Board, Guesses}
@default_options %{basic: false}
@genders [:f, :m]
@derive {Poison.Encoder, only: [:name, :gender, :board, :guesses]}
@derive {Jason.Encoder, only: [:name, :gender, :board, :guesses]}
@enforce_keys [:name, :gender, :pid, :board, :guesses]
defstruct [:name, :gender, :pid, :board, :guesses]
@type gender :: :f | :m
@type name :: String.t()
@type t :: %Player{
name: name,
gender: gender,
pid: pid | nil,
board: Board.t() | nil,
guesses: Guesses.t() | nil
}
@spec new(name, gender, pid | nil, Keyword.t()) :: t | {:error, atom}
def new(name, gender, pid, options \\ [])
def new(name, gender, pid, options)
when is_binary(name) and gender in @genders and is_list(options) and
(is_pid(pid) or is_nil(pid)) do
%{basic: basic?} = parse(options)
%Player{
name: name,
gender: gender,
pid: pid,
board: if(basic?, do: nil, else: Board.new()),
guesses: if(basic?, do: nil, else: Guesses.new())
}
end
def new(_name, _gender, _pid, _options), do: {:error, :invalid_player_args}
## Private functions
@spec parse(Keyword.t()) :: map
defp parse(options), do: parse(options, @default_options)
@spec parse(Keyword.t(), map) :: map
defp parse([], options), do: options
defp parse([{:basic, basic?} | rest], options) when is_boolean(basic?),
do: parse(rest, %{options | basic: basic?})
defp parse([_bad_option | rest], options), do: parse(rest, options)
end