1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
/* Copyright (C) 2011, 2013-2014, 2017 Luke Shumaker <lukeshu@lukeshu.com> */
package main
import (
"crypto/rand"
"fmt"
"math/big"
"os"
"regexp"
"strconv"
"strings"
)
func usage() {
fmt.Printf("Usage: %s <SPECSLIST>...\n", os.Args[0])
fmt.Println("SPECLIST = [-]SPEC[<<+|->SPEC>...]")
fmt.Println("SPEC = [<COUNT>]d<SIZE> | <MOD>")
}
func rollDie(size int) int {
num, err := rand.Int(rand.Reader, big.NewInt(int64(size)))
if err != nil {
panic(err)
}
return int(num.Int64()) + 1
}
var parser = regexp.MustCompile("^(([0-9]*)d)?([0-9]+)$")
func rollSpec(spec string) (string, int) {
parts := parser.FindStringSubmatch(spec)
if len(parts) < 4 {
usage()
os.Exit(1)
}
var str string
var num int
if parts[1] == "" {
str = parts[3]
num, _ = strconv.Atoi(str)
} else {
dice, _ := strconv.Atoi(parts[2])
die_size, _ := strconv.Atoi(parts[3])
if dice < 1 {
dice = 1
}
var rolls []string
for i := 0; i < dice; i++ {
v := rollDie(die_size)
rolls = append(rolls, strconv.Itoa(v))
num += v
}
str = "(" + strings.Join(rolls, "+") + ")"
}
return str, num
}
func roll(speclist string) {
var strs []string
var total int
neg := strings.HasPrefix(speclist, "-")
speclist = strings.TrimPrefix(speclist, "-")
for {
sep := strings.IndexAny(speclist, "+-")
var spec string
if sep < 0 {
spec = speclist
} else {
spec = speclist[:sep]
}
str, num := rollSpec(spec)
if neg {
str = "-" + str
num = -num
}
strs = append(strs, str)
total += num
if sep < 0 {
break
}
neg = speclist[sep] == '-'
speclist = speclist[sep+1:]
}
fmt.Printf("%s = %d\n", strings.Join(strs, " + "), total)
}
func main() {
if len(os.Args) < 2 {
usage()
}
for _, arg := range os.Args[1:] {
roll(arg)
}
}
|