aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--go.mod3
-rw-r--r--main.go62
3 files changed, 66 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e8b747f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+roll
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..c68aa93
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module bnbl.io/roll
+
+go 1.13
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..dd83503
--- /dev/null
+++ b/main.go
@@ -0,0 +1,62 @@
+package main
+
+import (
+ "crypto/rand"
+ "fmt"
+ "math/big"
+ "os"
+ "strconv"
+ "strings"
+)
+
+func main() {
+ if len(os.Args) != 2 {
+ fmt.Printf("usage: %s <die[+die...]>\n", os.Args[0])
+ os.Exit(1)
+ }
+ dice := strings.Split(os.Args[1], "+")
+ var sum int64
+ for _, die := range dice {
+ if result, err := resolve(die); err != nil {
+ fmt.Printf("%v\n", err)
+ os.Exit(1)
+ } else {
+ sum += result
+ }
+ }
+ fmt.Printf("%d\n", sum)
+}
+
+func resolve(die string) (int64, error) {
+ // try parsing as a die e.g. 2d6
+ var (
+ num int
+ sides int64
+ )
+ if fields, err := fmt.Sscanf(die, "%dd%d", &num, &sides); err == nil && fields == 2 {
+ var sum int64
+ for i := 0; i < num; i++ {
+ if r, err := roll(sides); err != nil {
+ return 0, err
+ } else {
+ sum += r
+ }
+ }
+ return sum, nil
+ }
+
+ // try just parsing as a number, e.g. +5
+ if x, err := strconv.Atoi(die); err != nil {
+ return 0, fmt.Errorf("unrecognized die: %s", die)
+ } else {
+ return int64(x), nil
+ }
+}
+
+func roll(sides int64) (int64, error) {
+ r, err := rand.Int(rand.Reader, big.NewInt(sides))
+ if err != nil {
+ return 0, err
+ }
+ return 1 + r.Int64(), nil
+}