Skip to content

Commit

Permalink
Merge branch 'feature/game_state'
Browse files Browse the repository at this point in the history
  • Loading branch information
jrowah committed Nov 4, 2024
2 parents 0072f14 + dd786b9 commit 44e469f
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib/battle_ship/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defmodule BattleShip.Application do

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
:ets.new(:game_state, [:public, :named_table])
opts = [strategy: :one_for_one, name: BattleShip.Supervisor]
Supervisor.start_link(children, opts)
end
Expand Down
34 changes: 30 additions & 4 deletions lib/battle_ship/game.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ defmodule BattleShip.Game do
rules: struct()
}}
def init(name) do
player1 = %{name: name, board: Board.new(), guesses: Guesses.new()}
player2 = %{name: nil, board: Board.new(), guesses: Guesses.new()}
{:ok, %{player1: player1, player2: player2, rules: %Rules{}}, @timeout}
send(self(), {:set_state, name})
{:ok, fresh_state(name)}
end

@spec add_player(pid(), binary()) :: :error | {:reply, :ok, %{}}
Expand All @@ -61,6 +60,13 @@ defmodule BattleShip.Game do
def guess_coordinate(game, player, row, col) when player in @players,
do: GenServer.call(game, {:guess_coordinate, player, row, col})

def terminate({:shutdown, :timeout}, state_data) do
:ets.delete(:game_state, state_data.player1.name)
:ok
end

def terminate(_reason, _state), do: :ok

def handle_call({:guess_coordinate, player, row, col}, _from, state_data) do
opponent = opponent(player)
opponent_board = player_board(state_data, opponent)
Expand Down Expand Up @@ -141,11 +147,25 @@ defmodule BattleShip.Game do
{:stop, {:shutdown, :timeout}, state_data}
end

def handle_info({:set_state, name}, _state_data) do
state_data =
case :ets.lookup(:game_state, name) do
[] -> fresh_state(name)
[{_key, state}] -> state
end

:ets.insert(:game_state, {name, state_data})
{:noreply, state_data, @timeout}
end

defp update_player2_name(state_data, name), do: put_in(state_data.player2.name, name)

defp update_rules(state_data, rules), do: %{state_data | rules: rules}

defp reply_success(state_data, reply), do: {:reply, reply, state_data, @timeout}
defp reply_success(state_data, reply) do
:ets.insert(:game_state, {state_data.player1.name, state_data})
{:reply, reply, state_data, @timeout}
end

defp update_board(state_data, player, board),
do: Map.update!(state_data, player, fn player -> %{player | board: board} end)
Expand All @@ -160,4 +180,10 @@ defmodule BattleShip.Game do
Guesses.add(guesses, hit_or_miss, coordinate)
end)
end

defp fresh_state(name) do
player1 = %{name: name, board: Board.new(), guesses: Guesses.new()}
player2 = %{name: nil, board: Board.new(), guesses: Guesses.new()}
%{player1: player1, player2: player2, rules: %Rules{}}
end
end
1 change: 1 addition & 0 deletions lib/battle_ship/game_supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule BattleShip.GameSupervisor do
def start_game(name), do: Supervisor.start_child(GameSupervisor, [name])

def stop_game(name) do
:ets.delete(:game_state, name)
Supervisor.terminate_child(GameSupervisor, pid_from_name(name))
end

Expand Down

0 comments on commit 44e469f

Please sign in to comment.