Skip to content

Commit

Permalink
Flatten hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
christhekeele committed Mar 2, 2023
1 parent bb31a45 commit e56e47c
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 132 deletions.
2 changes: 1 addition & 1 deletion .iex.exs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import Dice
import Dice.Expression
97 changes: 62 additions & 35 deletions README.md

Large diffs are not rendered by default.

71 changes: 67 additions & 4 deletions lib/dice.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,72 @@
defmodule Dice do
def expression(expression) do
expression |> Dice.Expression.new
defstruct [:faces]

def roll(%__MODULE__{} = dice) do
case dice.faces do
number when is_integer(number) and number > 0 -> :rand.uniform(number)
%Range{} = range -> Enum.random(range)
faces when is_list(faces) -> Enum.random(faces)
end
end

def to_string(%__MODULE__{} = dice) do
case dice.faces do
number when is_integer(number) -> "d#{Integer.to_string(number)}"
%Range{} = range -> "d[#{range.first}..#{range.last}]"
faces when is_list(faces) -> "d{#{Enum.join(faces, ", ")}}"
end
end

def roll(expression) do
expression |> Dice.Expression.new |> Dice.Expression.evaluate
def combinator do
import NimbleParsec
import Dice.Expression.Literals

dice_value_descriptor = non_negative_integer_literal()

dice_range_descriptor =
ignore(left_bracket_literal())
|> concat(unwrap_and_tag(integer_literal(), :first))
|> concat(ignore(range_literal()))
|> concat(unwrap_and_tag(integer_literal(), :last))
|> concat(right_bracket_literal())
|> post_traverse({__MODULE__, :dice_range_constructor, []})

dice_set_descriptor =
ignore(left_brace_literal())
|> concat(unwrap_and_tag(integer_literal(), :number))
|> repeat(concat(ignore(comma_literal()), unwrap_and_tag(integer_literal(), :number)))
|> concat(ignore(right_brace_literal()))
|> post_traverse({__MODULE__, :dice_set_constructor, []})

numeric_dice_descriptor = [
dice_value_descriptor,
dice_range_descriptor,
dice_set_descriptor
]

concat(ignore(dice_literal()), unwrap_and_tag(choice(numeric_dice_descriptor), :faces))
|> post_traverse({__MODULE__, :combinator_constructor, []})
end

def combinator_constructor(rest, args, context, _line, _offset) do
faces = Keyword.fetch!(args, :faces)

numeric_dice = %__MODULE__{faces: faces}

{rest, [numeric_dice], context}
end

def dice_range_constructor(rest, args, context, _line, _offset) do
first = Keyword.fetch!(args, :first)
last = Keyword.fetch!(args, :last)

{rest, [Range.new(first, last)], context}
end

def dice_set_constructor(rest, args, context, _line, _offset) do
numbers = Keyword.get_values(args, :number) |> :lists.reverse

{rest, [numbers], context}
end

end
4 changes: 4 additions & 0 deletions lib/dice/expression.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ defmodule Dice.Expression do
expression |> parse
end

def roll(expression) when is_binary(expression) do
expression |> new |> evaluate
end

def generate do
{__MODULE__.Parser, :parse}
|> NimbleParsec.parsec
Expand Down
77 changes: 0 additions & 77 deletions lib/dice/expression/dice/numeric/dice.ex

This file was deleted.

6 changes: 3 additions & 3 deletions lib/dice/expression/term.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Dice.Expression.Term do
def evaluate(%__MODULE__{} = term) do
result = case term.term do
%Dice.Expression.Constant{} = constant -> Dice.Expression.Constant.evaluate(constant)
%Dice.Expression.Dice.Numeric.Dice.Roll{} = numeric_roll -> Dice.Expression.Dice.Numeric.Dice.Roll.evaluate(numeric_roll)
%Dice.Pool{} = numeric_roll -> Dice.Pool.evaluate(numeric_roll)
end

case term.sign do
Expand All @@ -21,7 +21,7 @@ defmodule Dice.Expression.Term do
end,
case term.term do
%Dice.Expression.Constant{} = constant -> Dice.Expression.Constant.to_string(constant)
%Dice.Expression.Dice.Numeric.Dice.Roll{} = numeric_roll -> Dice.Expression.Dice.Numeric.Dice.Roll.to_string(numeric_roll)
%Dice.Pool{} = numeric_roll -> Dice.Pool.to_string(numeric_roll)
end
])
end
Expand All @@ -31,7 +31,7 @@ defmodule Dice.Expression.Term do
import Dice.Expression.Literals

terms = [
Dice.Expression.Dice.Numeric.Dice.Roll.combinator(),
Dice.Pool.combinator(),
Dice.Expression.Constant.combinator()
]

Expand Down
20 changes: 10 additions & 10 deletions ...dice/expression/dice/numeric/dice/roll.ex → lib/dice/pool.ex
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
defmodule Dice.Expression.Dice.Numeric.Dice.Roll do
defmodule Dice.Pool do
defstruct [:dice, number: 1, modifiers: []]

def evaluate(%__MODULE__{} = roll) do
rolls = for _ <- 1..roll.number do
Dice.Expression.Dice.Numeric.Dice.roll(roll.dice)
Dice.roll(roll.dice)
end

Enum.reduce(roll.modifiers, rolls, fn modifier, rolls ->
case modifier do
%Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Keep{} = modifier -> Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Keep.modify(modifier, rolls)
%Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Drop{} = modifier -> Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Drop.modify(modifier, rolls)
%Dice.Pool.Modifier.Keep{} = modifier -> Dice.Pool.Modifier.Keep.modify(modifier, rolls)
%Dice.Pool.Modifier.Drop{} = modifier -> Dice.Pool.Modifier.Drop.modify(modifier, rolls)
end
end)
|> Enum.sum
Expand All @@ -18,11 +18,11 @@ defmodule Dice.Expression.Dice.Numeric.Dice.Roll do
def to_string(%__MODULE__{} = roll) do
Enum.join([
(if roll.number == 1, do: "", else: Integer.to_string(roll.number)),
Dice.Expression.Dice.Numeric.Dice.to_string(roll.dice)
Dice.to_string(roll.dice)
] ++ Enum.map(roll.modifiers, fn modifier ->
case modifier do
%Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Keep{} = modifier -> Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Keep.to_string(modifier)
%Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Drop{} = modifier -> Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Drop.to_string(modifier)
%Dice.Pool.Modifier.Keep{} = modifier -> Dice.Pool.Modifier.Keep.to_string(modifier)
%Dice.Pool.Modifier.Drop{} = modifier -> Dice.Pool.Modifier.Drop.to_string(modifier)
end
end))
end
Expand All @@ -32,12 +32,12 @@ defmodule Dice.Expression.Dice.Numeric.Dice.Roll do
import Dice.Expression.Literals

numeric_dice_modifiers = [
Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Keep.combinator(),
Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Drop.combinator()
Dice.Pool.Modifier.Keep.combinator(),
Dice.Pool.Modifier.Drop.combinator()
]

optional(unwrap_and_tag(non_negative_integer_literal(), :number))
|> concat(unwrap_and_tag(Dice.Expression.Dice.Numeric.Dice.combinator(), :dice))
|> concat(unwrap_and_tag(Dice.combinator(), :dice))
|> concat(optional(repeat(unwrap_and_tag(choice(numeric_dice_modifiers), :modifier))))
|> post_traverse({__MODULE__, :combinator_constructor, []})
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Drop do
defmodule Dice.Pool.Modifier.Drop do
defstruct [:number, mode: :random]

def modify(%__MODULE__{} = drop, rolls) do
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Dice.Expression.Dice.Numeric.Dice.Roll.Modifier.Keep do
defmodule Dice.Pool.Modifier.Keep do
defstruct [:number, mode: :random]

def modify(%__MODULE__{} = keep, rolls) do
Expand Down

0 comments on commit e56e47c

Please sign in to comment.