Packages
islands_engine
0.2.4
0.2.65
0.2.64
0.2.63
0.2.62
0.2.61
0.2.60
0.2.59
0.2.58
0.2.56
0.2.55
0.2.54
0.2.53
0.2.52
0.2.51
0.2.50
0.2.49
0.2.48
0.2.47
0.2.46
0.2.45
0.2.44
0.2.43
0.2.42
0.2.41
0.2.40
0.2.39
0.2.38
0.2.37
0.2.36
0.2.35
0.2.34
0.2.33
0.2.32
0.2.31
0.2.30
0.2.29
0.2.28
0.2.27
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.13
0.2.12
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.81
0.1.80
0.1.79
0.1.78
0.1.77
0.1.76
0.1.75
0.1.73
0.1.72
0.1.71
0.1.70
0.1.69
0.1.68
0.1.67
0.1.66
0.1.65
0.1.64
0.1.63
0.1.62
0.1.61
0.1.60
0.1.59
0.1.58
0.1.57
0.1.56
0.1.55
0.1.54
0.1.53
0.1.52
0.1.51
0.1.50
0.1.49
0.1.48
0.1.47
0.1.46
0.1.45
0.1.44
0.1.43
0.1.42
0.1.41
0.1.40
0.1.39
0.1.38
0.1.37
0.1.36
0.1.35
0.1.34
0.1.33
0.1.32
0.1.31
0.1.30
0.1.29
0.1.28
0.1.27
0.1.26
0.1.25
0.1.24
0.1.23
0.1.22
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.0
Models the Game of Islands.
Current section
Files
Jump to
Current section
Files
lib/islands/engine.ex
# ┌────────────────────────────────────────────────────────────────────┐
# │ Based on the book "Functional Web Development" by Lance Halvorsen. │
# └────────────────────────────────────────────────────────────────────┘
defmodule Islands.Engine do
use GenServer.Proxy
use PersistConfig
@book_ref Application.get_env(@app, :book_ref)
@moduledoc """
Models the _Game of Islands_.
\n##### #{@book_ref}
"""
alias Islands.Engine.Game.{DynSup, Server, Tally}
alias Islands.Engine.{Coord, Game, Island}
@board_range Application.get_env(@app, :board_range)
@island_types Application.get_env(@app, :island_types)
@player_ids Application.get_env(@app, :player_ids)
@doc """
Starts a new game.
"""
@spec new_game(String.t(), String.t(), pid) :: Supervisor.on_start_child()
def new_game(game_name, player1_name, player1_pid)
when is_binary(game_name) and is_binary(player1_name) and
is_pid(player1_pid) do
import DynamicSupervisor, only: [start_child: 2]
start_child(DynSup, {Server, {game_name, player1_name, player1_pid}})
end
@doc """
Ends a game.
"""
@spec end_game(String.t()) :: :ok
def end_game(game_name) when is_binary(game_name),
do: stop(:shutdown, game_name)
@doc """
Stops a game.
"""
@spec stop_game(String.t(), Game.player_id()) :: Tally.t() | :ok
def stop_game(game_name, player_id)
when is_binary(game_name) and player_id in @player_ids,
do: call({:stop, player_id}, game_name)
@doc """
Adds the second player of a game.
"""
@spec add_player(String.t(), String.t(), pid) :: Tally.t() | :ok
def add_player(game_name, player2_name, player2_pid)
when is_binary(game_name) and is_binary(player2_name) and
is_pid(player2_pid),
do: call({:add_player, player2_name, player2_pid}, game_name)
@doc """
Positions an island on a player's board.
"""
@spec position_island(
String.t(),
Game.player_id(),
Island.type(),
Coord.row(),
Coord.col()
) :: Tally.t() | :ok
def position_island(game_name, player_id, island_type, row, col)
when is_binary(game_name) and player_id in @player_ids and
island_type in @island_types and row in @board_range and
col in @board_range,
do: call({:position_island, player_id, island_type, row, col}, game_name)
@doc """
Positions all islands on a player's board.
"""
@spec position_all_islands(String.t(), Game.player_id()) :: Tally.t() | :ok
def position_all_islands(game_name, player_id)
when is_binary(game_name) and player_id in @player_ids,
do: call({:position_all_islands, player_id}, game_name)
@doc """
Declares all islands set for a player.
"""
@spec set_islands(String.t(), Game.player_id()) :: Tally.t() | :ok
def set_islands(game_name, player_id)
when is_binary(game_name) and player_id in @player_ids,
do: call({:set_islands, player_id}, game_name)
@doc """
Allows a player to guess a coordinate.
"""
@spec guess_coord(String.t(), Game.player_id(), Coord.row(), Coord.col()) ::
Tally.t() | :ok
def guess_coord(game_name, player_id, row, col)
when is_binary(game_name) and player_id in @player_ids and
row in @board_range and col in @board_range,
do: call({:guess_coord, player_id, row, col}, game_name)
@doc """
Returns the tally of a game for a given player.
"""
@spec tally(String.t(), Game.player_id()) :: Tally.t() | :ok
def tally(game_name, player_id)
when is_binary(game_name) and player_id in @player_ids,
do: call({:tally, player_id}, game_name)
@doc """
Returns a sorted list of registered game names.
"""
@spec game_names :: [String.t()]
def game_names do
:global.registered_names()
|> Enum.filter(&(is_tuple(&1) and elem(&1, 0) == Server))
|> Enum.map(&elem(&1, 1))
end
@doc """
Returns the `pid` of the game server process registered under the
given `game_name`, or `nil` if no process is registered.
"""
@spec game_pid(String.t()) :: pid | nil
def game_pid(game_name), do: game_name |> Server.via() |> GenServer.whereis()
end