Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

RPG Dialogue

rpg_dialogue.livemd

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

Return Home Report An Issue

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"