RPG Dialogue
Mix.install([
{:kino, github: "livebook-dev/kino", override: true},
{:kino_lab, "~> 0.1.0-dev", github: "jonatanklosko/kino_lab"},
{:vega_lite, "~> 0.1.4"},
{:kino_vega_lite, "~> 0.1.1"},
{:benchee, "~> 0.1"},
{:ecto, "~> 3.7"},
{:math, "~> 0.7.0"},
{:faker, "~> 0.17.0"},
{:utils, path: "#{__DIR__}/../utils"},
{:tested_cell, git: "https://github.com/BrooklinJazz/tested_cell"}
])
Navigation
Overview
In this exercise, you’re going to generate dialogue for an RPG (Role Playing Game). This lesson is designed to provide you an opportunity to practice structs and control flow.
Create A Character Struct
In the Elixir cell below, define a Character
struct with a :name
, :class
, and :weapon
.
Enforce that the :name
property exists.
ExUnit.start(auto_run: false)
defmodule Assertion do
use ExUnit.Case
test "" do
defmodule Character do
end
assert Keyword.get(Character.__info__(:functions), :__struct__),
"Ensure you use `defstruct`"
assert match?(%{name: nil, class: nil, weapon: nil}, struct(Character)),
"Ensure you use `defstruct` with :name, :class, and :weapon"
assert_raise ArgumentError, fn ->
struct!(Character, %{weapon: "", class: ""})
end
end
end
ExUnit.run()
# Make variables and modules defined in the test available.
# Also allows for exploration using the output of the cell.
defmodule Character do
end
Create character structs with the following information:
classDiagram
class Arthur {
class: "warrior"
weapon: "sword"
}
class Gandalf {
class: "wizard"
weapon: "staff"
}
class Jarlaxle {
class: "rogue"
weapon: "daggers"
}
Replace nil
with each struct.
ExUnit.start(auto_run: false)
defmodule Assertion do
use ExUnit.Case
test "" do
arthur = nil
gandalf = nil
jarlaxle = nil
assert is_struct(arthur), "Ensure `arthur` is a struct."
assert is_struct(gandalf), "Ensure `gandalf` is a struct."
assert is_struct(jarlaxle), "Ensure `jarlaxle` is a struct."
assert %{name: "Arthur", weapon: "sword", class: "warrior"} = arthur
assert %{name: "Gandalf", weapon: "staff", class: "wizard"} = gandalf
assert %{name: "Jarlaxle", weapon: "daggers", class: "rogue"} = jarlaxle
end
end
ExUnit.run()
# Make variables and modules defined in the test available.
# Also allows for exploration using the output of the cell.
arthur = nil
gandalf = nil
jarlaxle = nil
Create A Dialogue Module
In the Elixir cell below.
-
Create a
Dialogue.greet/1
function which accepts a character struct and returns the following dialogue.
character = %Character{name: "Peter"}
Dialogue.greet(character)
"Hello, my name is Peter."
-
Create a
Dialogue.attack/2
function which accepts a character and returns the following dialogue.
character = %Character{name: "Arthur", weapon: "sword"}
enemy = "Mordred"
Dialogue.attack(character, enemy)
"Arthur attacks Mordred with a sword."
-
Create a
Dialogue.relinquish_weapon/1
function which returns different dialogue depending on the character’s class.-
"rogue"
:"Fine, have my #{character.weapon}. I have more hidden anyway."
-
"wizard"
:"You would not part an old man from his walking stick?"
-
"warrior"
:"Have my #{character.weapon} then!"
-
any other class:
"My precious!"
-
For example,
character = %Character{name: "Vax", class: "rogue", weapon: "daggers"}
Dialogue.relinquish_weapon(character)
"Fine, have my daggers. I have more hidden anyway."
-
Create a function
Dialogue.matching_weapon/1
that returns different dialogue depending on the character’s class and weapon.-
"wizard"
and"staff"
:"My lovely magical staff."
-
"rogue"
and"daggers"
:"Hidden and deadly."
-
"warrior"
and"sword"
:"My noble sword!"
-
any class and no weapon (
nil
):"I'm unarmed!"
-
any other combination:
"I'm not sure a #{character.weapon} suits a #{character.class}."
-
For example,
character = %Character{name: "Vax", class: "rogue", weapon: "daggers"}
Dialogue.matching_weapon(character)
"Hidden and deadly."
character = %Character{name: "Taako", class: "wizard", weapon: "mace"}
Dialogue.matching_weapon(character)
"I'm not sure a mace suits a wizard."
ExUnit.start(auto_run: false)
defmodule Assertion do
use ExUnit.Case
test "" do
defmodule Dialogue do
def greet(character) do
end
def attack(character, enemy) do
end
def relinquish_weapon(character) do
end
def matching_weapon(character) do
end
end
character_permutations =
for class <- ["wizard", "rogue", "warrior", nil],
weapon <- ["daggers", "sword", "staff", nil],
name <- [Utils.Factory.name(), nil] do
%{class: class, weapon: weapon, name: name}
end
enemy = Utils.Factory.name()
Enum.each(character_permutations, fn character ->
assert Dialogue.greet(character) == "Hello, my name is #{character.name}."
assert Dialogue.attack(character, enemy) ==
"#{character.name} attacks #{enemy} with a #{character.weapon}."
relinquish_weapon_dialogue =
case character.class do
"rogue" -> "Fine, have my #{character.weapon}. I have more hidden anyway."
"wizard" -> "You would not part an old man from his walking stick?"
"warrior" -> "Have my #{character.weapon} then!"
_ -> "My precious!"
end
assert Dialogue.relinquish_weapon(character) == relinquish_weapon_dialogue
matching_weapon_dialogue =
case {character.class, character.weapon} do
{"wizard", "staff"} -> "My lovely magical staff."
{"rogue", "daggers"} -> "Hidden and deadly."
{"warrior", "sword"} -> "My noble sword!"
{_, nil} -> "I'm unarmed!"
{_, _} -> "I'm not sure a #{character.weapon} suits a #{character.class}."
end
assert Dialogue.matching_weapon(character) == matching_weapon_dialogue
end)
end
end
ExUnit.run()
# Make variables and modules defined in the test available.
# Also allows for exploration using the output of the cell.
defmodule Dialogue do
def greet(character) do
end
def attack(character, enemy) do
end
def relinquish_weapon(character) do
end
def matching_weapon(character) do
end
end
Commit Your Progress
Run the following in your command line from the project folder to track and save your progress in a Git commit.
$ git add .
$ git commit -m "finish rpg dialogue exercise"