Current section

Files

Jump to
islands_engine lib islands engine ie.ex
Raw

lib/islands/engine/ie.ex

defmodule Islands.Engine.IE do
@moduledoc false
## Example of an IEx session in a named node...
#
# iex --sname islands_engine -S mix (Xterm colors)
#
# use Islands.Engine.IE
# print_tiles()
# DemoProc.loop_test()
# guesses = Guesses.new()
# {:ok, coord1} = Coord.new(1, 1)
# {:ok, coord2} = Coord.new(2, 2)
# guesses = update_in(guesses.hits, &MapSet.put(&1, coord1))
# guesses = update_in(guesses.hits, &MapSet.put(&1, coord2))
# guesses = update_in(guesses.hits, &MapSet.put(&1, coord1))
# {:ok, coord} = Coord.new(4, 6)
# Island.new(:l_shape, coord)
# Island.new(:wrong, coord)
# {:ok, coord} = Coord.new(10, 10)
# Island.new(:l_shape, coord)
# Island.new(:dot, coord)
## Example of IEx sessions in different nodes...
#
# iex --sname c1 -S mix (Xterm colors)
#
# Islands.Text.Client.start("Eden", "Adam", :m, mode: :auto)
#
# iex --sname c2 -S mix (Xterm colors)
#
# Islands.Text.Client.join("Eden", "Eve", :f, mode: :auto)
## Example of an IEx session...
#
# iex -S mix (Xterm colors)
#
# use Islands.Engine.IE
# import Engine, only: [position_all_islands: 2]
# :observer.start
# pid = self()
# {:ok, red_sun_pid} = Engine.new_game("red-sun", "Ed", :m, pid)
# {:error, error} = Engine.new_game("red-sun", "Al", :m, pid)
# error == {:already_started, red_sun_pid}
# {:ok, icy_moon_pid} = Engine.new_game("icy-moon", "Eve", :f, pid)
# red_sun_pid == Engine.game_pid("red-sun")
# icy_moon_pid == Engine.game_pid("icy-moon")
# ["icy-moon", "red-sun"] == Engine.game_names
# game_names = :ets.match(Ets, {{GameServer, :"$1"}, :_})
# [["icy-moon"], ["red-sun"]] == game_names
# %Tally{} = Engine.add_player("red-sun", "Liz", :f, pid)
# :ok = position_all_islands("red-sun", :player1) |> Tally.summary(:player1)
use PersistConfig
alias Islands.Grid.Tile
alias Islands.{Coord, Engine, Game, Island, Player, PlayerID, Tally}
defmacro __using__(_options) do
quote do
import unquote(__MODULE__)
alias unquote(__MODULE__)
alias IO.ANSI.Plus, as: ANSI
alias Log.Reset
alias Islands.Engine.GameServer.{
AddPlayer,
GuessCoord,
PositionAllIslands,
PositionIsland,
ReplyTuple,
SetIslands,
Stop
}
alias Islands.Engine.{
DemoProc,
DynGameSup,
Ets,
GameRecovery,
GameServer,
GenServerProxy,
Log,
TopSup
}
alias Islands.Board.{Cache, Response}
alias Islands.Grid.Tile
alias Islands.Island.Offsets
alias Islands.{
Board,
Coord,
Engine,
Game,
Grid,
Guesses,
Island,
Player,
PlayerID,
Request,
Response,
Score,
State,
Tally
}
:ok
end
end
## Example of an IEx session...
#
# iex -S mix (Xterm colors)
#
# use Islands.Engine.IE
# import Engine, only: [position_all_islands: 2]
# :observer.start # optional
# pid = self()
# new_games(2) # starts 2 new games with last called "blue-moon"
# :ets.match(Ets, {{GameServer, :"$1"}, :_})
# Engine.game_names
# %Tally{} = Engine.add_player(blue_moon, "Liz", :f, pid)
# :ok = position_all_islands(blue_moon, :player1) |> Tally.summary(:player1)
# Reset.reset_logs([:debug]) # optional
# :ok = position_island(blue_moon, 3, 2, +500) # and check the logs
# :ok = Engine.tally(blue_moon, :player1) |> Tally.summary(:player1)
## Example of an IEx session...
#
# iex -S mix (Xterm colors)
#
# use Islands.Engine.IE
# import Engine, only: [position_all_islands: 2]
# :observer.start # optional
# pid = self()
# new_games(166) # starts 166 new games with last called "blue-moon"
# :ets.match(Ets, {{GameServer, :"$1"}, :_})
# Engine.game_names
# %Tally{} = Engine.add_player(blue_moon, "Liz", :f, pid)
# :ok = position_all_islands(blue_moon, :player1) |> Tally.summary(:player1)
# Reset.reset_logs([:debug]) # optional
# :ok = position_island(DynGameSup, 3, 2, +333) # and check the logs
# :ok = Engine.tally(blue_moon, :player1) |> Tally.summary(:player1)
@spec print_tiles :: :ok
def print_tiles do
IO.puts(":atoll => #{Tile.new(:atoll)}")
IO.puts(":dot => #{Tile.new(:dot)}")
IO.puts(":l_shape => #{Tile.new(:l_shape)}")
IO.puts(":s_shape => #{Tile.new(:s_shape)}")
IO.puts(":square => #{Tile.new(:square)}")
IO.puts(":atoll_hit => #{Tile.new(:atoll_hit)}")
IO.puts(":dot_hit => #{Tile.new(:dot_hit)}")
IO.puts(":l_shape_hit => #{Tile.new(:l_shape_hit)}")
IO.puts(":s_shape_hit => #{Tile.new(:s_shape_hit)}")
IO.puts(":square_hit => #{Tile.new(:square_hit)}")
IO.puts(":board_miss => #{Tile.new(:board_miss)}")
IO.puts(":hit => #{Tile.new(:hit)}")
IO.puts(":miss => #{Tile.new(:miss)}")
IO.puts(":ocean => #{Tile.new(nil)}")
end
@spec player_name :: Player.name()
def player_name, do: "Ray"
@spec gender :: Player.gender()
def gender, do: :m
@spec pid :: pid
def pid, do: self()
@spec player_id :: PlayerID.t()
def player_id, do: :player1
@spec island_type :: Island.type()
def island_type, do: :atoll
@spec blue_moon :: Game.name()
def blue_moon, do: "blue-moon"
@spec keep_killing(atom | binary, integer) :: pid
def keep_killing(name, more_ms \\ 0)
when (is_atom(name) or is_binary(name)) and is_integer(more_ms) do
spawn(fn ->
for _ <- Stream.cycle([:ok]) do
pid(name)
|> IO.inspect(label: "Killing #{inspect(name)}")
|> Process.exit(:kill)
pause(name, more_ms)
|> IO.inspect(label: "Between kills (ms)")
|> Process.sleep()
end
end)
end
@spec new_games(pos_integer) :: [{Game.name(), Supervisor.on_start_child()}]
def new_games(count) when count in 2..500 do
Enum.reduce(0..(count - 2), [blue_moon()], fn _, acc ->
[Game.haiku_name() | acc]
end)
|> Enum.map(fn name ->
{name, Engine.new_game(name, player_name(), gender(), pid())}
end)
end
@spec position_island(atom | binary, Coord.row(), Coord.col(), integer) :: :ok
def position_island(target, row, col, more_ms \\ 0)
when (is_atom(target) or is_binary(target)) and row in 1..10 and
col in 1..10 and is_integer(more_ms) do
keep_killing(target, more_ms) |> do_position_island(row, col)
end
## Private functions
@spec do_position_island(pid, Coord.row(), Coord.col()) :: :ok
defp do_position_island(killer_pid, row, col) do
for _ <- 1..10 do
Engine.position_island(blue_moon(), player_id(), island_type(), row, col)
Process.sleep(10)
Engine.game_pid(blue_moon())
end
|> Enum.any?(&is_nil/1)
|> if(
do: print_summary(killer_pid),
else: do_position_island(killer_pid, row, col)
)
end
@spec print_summary(pid) :: :ok
defp print_summary(killer_pid) do
true = Process.exit(killer_pid, :kill)
:ok = Engine.tally(blue_moon(), player_id()) |> Tally.summary(player_id())
end
@spec pid(atom | binary) :: pid
defp pid(name) when is_atom(name) do
case Process.whereis(name) do
pid when is_pid(pid) ->
pid
nil ->
snooze() |> Process.sleep()
pid(name)
end
end
defp pid(name) when is_binary(name) do
case Engine.game_pid(name) do
pid when is_pid(pid) ->
pid
nil ->
snooze() |> Process.sleep()
pid(name)
end
end
@spec pause(atom | binary, integer) :: pos_integer
defp pause(sup_or_server, adjustment)
defp pause(Islands.Engine.DynGameSup, adjustment),
do: get_env(:between_dyn_sup_kills) + adjustment
defp pause(Islands.Engine.GameSup, adjustment),
do: get_env(:between_sup_kills) + adjustment
defp pause(_server, adjustment),
do: get_env(:between_server_kills) + adjustment
@spec snooze :: pos_integer
defp snooze, do: get_env(:between_registration_checks)
end