BrotherCrow

BrotherCrow

Creating a dice-roller in Elixir. D-10 and D-100 giving me fits.

I’m very new to programming, and elixir is my first language. If my verbage or vocabulary are slightly off, I appreciate your understanding.

The Scope:

I’m working on an RNG modeled on tabletop dice. A d2, d4, d6, d8, d10, d12, d20 and d100. These will be called by functions needing to draw from charts, and will hopefully be rolled direclty by users as needed. As such, I need the results to be consistant and usable.

The Problem:

Anything over d8 is giving me fits in its result. It produces random seeming letters or punctuation instead of a numerical result.

I understand this is an artifact of how elixir and erlang sort of… co-mingle numbers and letters. The details and specifics of that are still a bit beyond me, I confess. I solved this issue in one specific instance, by piping the result of a single d100 into an Enum.sum. This doesn’t work for multiple dice, and won’t work globally.

The Code
Dice Module:

defmodule Plotgenerator.Dice do

@moduledoc """

Dice Functions

The basic dice functions are very simple, but effective.


A function call for 'Dice.dX(Y)', where X is the sides on the die and Y is the number being rolled, will return a list of results. This works by feeding the sides and count argument to Dice.roll, which in turn, calls on the Dice.d(sides) function.

The Dice.dX functions can be bypassed by using roll directly and providing it with the sides and count arguments.

Additionally, a functioncall of Dice.dX() with no arguments, will cause a single result of the die-type to be generated and returned.
"""

# NOTE this format replicates the process for d2(count) and provides a count of 1 for a d2 function with no argument.
  def d2(), do: d2(1)


  # NOTE this d2 command is the standard, providing a
  def d2(count) do
    roll(2, count)
  end


 # NOTE this format replicates the process for d2(), but provides a default value for the count. This is more complicated than the previous two iterations. We are not using it, but I am providing it for completeness.
  #
  #  def d2(count \\ 1) do
  #   roll(2, count)
  # end

# NOTE FOR ELIXIR FORUM - I have cut the other dice rollers from this, because they are exact formulaeic copies of the above examples, save for different numerals. 
  
# NOTE the defp deffinition means its private and can only be called by this module. This keeps other modules from accidentally calling it. Only use it if there is no other case in which another module may -need- to call it.
  defp d(sides) do
   Enum.random(1..sides)
  end

  @spec roll(pos_integer, pos_integer) :: list
  def roll(sides, count) when is_integer(count) and count > 0 and is_integer(sides) and sides > 1 do
    (1..count |> Enum.map(fn _-> d(sides) end))
  end

Thats the die rolling module.

Here is where I am trying to use it, and initially ran into the problem.

    def create(attributes \\ %{}) do
      defaults = %{
        shape: Plotgenerator.pick("traps/effect_shape"),
        size: area_select(),
        damage: Plotgenerator.pick("traps/damage_type"),
        difficulty: Enum.random(1..10),
        effect: Plotgenerator.pick("traps/trap_effect"),
        trigger_point: Plotgenerator.pick("traps/trap_locations"),
        control_point: Plotgenerator.pick("traps/trap_locations"),
        focal_point: Plotgenerator.pick("traps/trap_locations"),
        mechanism_point: Plotgenerator.pick("traps/trap_locations"),
        object: Plotgenerator.pick("traps/trigger_objects"),
        reset: Plotgenerator.pick("traps/reset_type"),
        time: Plotgenerator.pick("traps/reset_time"),
        triggered_by: Plotgenerator.pick("traps/trigger_action")
      }
      struct(__MODULE__, Map.merge(defaults, attributes))
    end

    # NOTE: when returning this value initially, it was printing as random characters. Thats because a list of numbers have corrolation to charlist, and it was offering that. By adding enum.sum to the end of it, we ensure it returns a number.

    def area_select() do
      Plotgenerator.Dice.d100(1) |> Enum.sum
    end

I solved the issue with the enum.sum on area_select(), but this is not a workable solution on the whole. Below is an example of the return, when I do not engage the enum.sum function on the result.

Note: I know the text doesn’t make a lot of sense. This is still getting the information to populate properly. I’ll clean up the template later.

If triggered, this trap has the effect of Illusion. If triggered, this trap effects a Geometric shaped area, with a size of E. This area is centered on Floor. The lethality of the trap is 8 out of 10. 

If triggered, this trap has the effect of Damage. If triggered, this trap effects a Cone shaped area, with a size of ;. This area is centered on Window, drain or vent. The lethality of the trap is 3 out of 10. 

If triggered, this trap has the effect of Alarm. If triggered, this trap effects a Wall shaped area, with a size of %. This area is centered on Stairs. The lethality of the trap is 6 out of 10. 

If triggered, this trap has the effect of Spell. If triggered, this trap effects a Wall shaped area, with a size of +. This area is centered on Stairs. The lethality of the trap is 6 out of 10. 

If triggered, this trap has the effect of Illusion. If triggered, this trap effects a Wall shaped area, with a size of M. This area is centered on Stairs. The lethality of the trap is 6 out of 10. 

Thank you for any suggestions, solutions or feedback you can offer.

Most Liked

ruslandoga

ruslandoga

Sorry, I haven’t read the whole discussion but still thought I’d chime in …

Inspecting lists of integers might still result in unexpected output:

iex(1)> "some string with #{inspect([50, 51])}"
"some string with '23'"

# can be "fixed" with `[charlists: :as:lists]` option, for more see https://hexdocs.pm/elixir/1.12/Inspect.Opts.html
iex(2)> "some string with #{inspect([50, 51], charlists: :as_lists)}"
"some string with [50, 51]"

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement