Hi! You might know that I’m writing a book about the Toy Robot exercise in Elixir: The Elixir Toy Robot (self-published). I’ve written an extra chapter at the end of this book that uses GenServers, Supervisors and Registry to build a single-player Toy Robot.
I thought I could figure out on my own how to turn this into a multi-player Toy Robot, but I’m struggling with how to code this in Elixir in an easy-to-understand way.
For a bit of context, here is the code as it stands today at the end of this single-player chapter: https://github.com/radar/toy_robot_elixir/commit/175f80c2e3ea64a46cc695ced4bcf145e160723a.
What I’m thinking I need here is a Game
module that tracks the table that the players would move around on, as well as the current placement for all players. Something like this:
use GenServer
alias ToyRobot.Table
alias ToyRobot.Game.PlayerSupervisor
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def init([north_boundary: north_boundary, east_boundary: east_boundary]) do
table = %Table{
north_boundary: north_boundary,
east_boundary: east_boundary,
}
{:ok, %{table: table, players: %{}}}
end
def add_player(name, position) do
GenServer.call(__MODULE__, {:add_player, name, position})
end
def handle_call({:add_player, name, position}, from, state) do
if space_occupied?(state.players, position) do
{:reply, {:error, :occupied}, state}
else
{:ok, player} = PlayerSupervisor.start_child(position, name)
players = state.players |> Map.put(name, position)
{:reply, {:ok, player}, %{state | players: players}}
end
end
def space_occupied?(players, position) do
positions = players |> Map.values |> Enum.map(&coordinates/1)
(position |> coordinates) in positions
end
defp coordinates(position), do: position |> Map.take([:north, :east])
end
This handles the initial placement of the players on the game table. A small detail not handled here is validating that the specified position is within the boundaries of the table. That’s something I know how to do, so don’t worry about that one.
What I am worried about here is what happens when a player’s process dies. This can happen if a player’s robot moves past the boundaries of the table. What I would like to be prevented here is two robots occupying the same space and that means also preventing that when the robot respawns.
How should I do this? Should I get the Player
server here to know about Game
and know how to ask questions like “is my initial spawn point taken?” and then to somehow pick a random position on the board to spawn in? Or is there something else that I am overlooking here?
Any advice would be greatly appreciated!