Packages
islands_client_input
0.1.49
0.1.49
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.3
0.1.2
0.1.1
0.1.0
Prompts and accepts a move in the Game of Islands.
Current section
Files
Jump to
Current section
Files
lib/islands/client/input/parser.ex
defmodule Islands.Client.Input.Parser do
@moduledoc """
Parses the prompted input and, if valid, updates the client state struct.
"""
use PersistConfig
alias IO.ANSI.Plus, as: ANSI
alias Islands.Client.Input.Prompter
alias Islands.Client.{GameOver, Input, RandomGuess, State}
@coord_range 1..10
@island_type_codes ["a", "d", "l", "s", "q"]
@messages get_env(:messages)
@pause_range 0..10_000
@doc """
Parses the prompted input and, if valid, updates the client state struct.
"""
@spec parse_input(Input.t(), State.t()) :: State.t() | no_return
def parse_input({:error, reason} = _input, state) do
ANSI.puts([:aqua, "Game stopping: ", :light_white, "#{inspect(reason)}"])
force_stop(state)
end
def parse_input(input = :eof, state) do
ANSI.puts([:aqua, "Game stopping: ", :light_white, "#{inspect(input)}"])
force_stop(state)
end
def parse_input(input, %State{} = state) do
input
|> String.split()
|> case do
[code, row, col] when code in @island_type_codes ->
with {row, ""} when row in @coord_range <- Integer.parse(row),
{col, ""} when col in @coord_range <- Integer.parse(col) do
put_in(state.move, [code, row, col])
else
_ -> Prompter.accept_move(state, @messages.bad_move)
end
["auto", pause] ->
with {pause, ""} when pause in @pause_range <- Integer.parse(pause) do
%State{state | mode: :auto, pause: pause}
|> Prompter.accept_move(@messages.auto_mode)
else
_ -> Prompter.accept_move(state, @messages.bad_move)
end
[row, col] ->
with {row, ""} when row in @coord_range <- Integer.parse(row),
{col, ""} when col in @coord_range <- Integer.parse(col) do
put_in(state.move, [row, col])
else
_ -> Prompter.accept_move(state, @messages.bad_move)
end
[] ->
parse_input(RandomGuess.new(state), state)
[move] when move in ["all", "set", "stop"] ->
put_in(state.move, [move])
["help"] ->
Prompter.accept_move(state, @messages.help)
[":eof"] ->
parse_input(:eof, state)
[":error" | reason] ->
# E.g. :error 'whatever the reason'
reason = Enum.join(reason, " ")
{reason, []} = Code.eval_string(reason)
parse_input({:error, reason}, state)
_other ->
Prompter.accept_move(state, @messages.bad_move)
end
end
## Private functions
@spec force_stop(State.t()) :: State.t() | no_return
defp force_stop(state) when state.tally.game_state == :players_set do
state = put_in(state.tally.request, {:stop, state.player_id})
put_in(state.tally.response, {:ok, :stopping}) |> GameOver.exit()
end
defp force_stop(state) do
parse_input("stop", state)
end
end