exercism/elixir/bread-and-potions/lib/rpg.ex

59 lines
1.6 KiB
Elixir

defmodule RPG do
defmodule Character do
defstruct health: 100, mana: 0
end
defmodule LoafOfBread do
defstruct []
end
defmodule ManaPotion do
defstruct strength: 10
end
defmodule Poison do
defstruct []
end
defmodule EmptyBottle do
defstruct []
end
# Add code to define the protocol and its implementations below here...
defprotocol Edible do
@moduledoc """
Protocol definition for interaction between Characters and Items
"""
@type item() :: LoafOfBread.t() | ManaPotion.t() | Poison.t() | EmptyBottle.t()
@spec eat(item(), Character.t()) :: {nil | item(), Character.t()}
def eat(item, character)
end
defimpl Edible, for: LoafOfBread do
@moduledoc """
Edible implimentation for LoafOfBread
"""
@spec eat(LoafOfBread.t(), Character.t()) :: {nil, Character.t()}
def eat(%LoafOfBread{}, %Character{health: health} = character),
do: {nil, %{character | health: health + 5}}
end
defimpl Edible, for: ManaPotion do
@moduledoc """
Edible implimentation for ManaPotion
"""
@spec eat(ManaPotion.t(), Character.t()) :: {EmptyBottle.t(), Character.t()}
def eat(%ManaPotion{strength: strength}, %Character{mana: mana} = character),
do: {%EmptyBottle{}, %{character | mana: mana + strength}}
end
defimpl Edible, for: Poison do
@moduledoc """
Edible implimentation for Poison
"""
@spec eat(Poison.t(), Character.t()) :: {EmptyBottle.t(), Character.t()}
def eat(%Poison{}, %Character{} = character),
do: {%EmptyBottle{}, %{character | health: 0}}
end
end