From 24b1adf7bf0d7fe9647cd78ef57da4c777059821 Mon Sep 17 00:00:00 2001 From: Dustin Pianalto Date: Thu, 10 Sep 2020 11:10:19 -0800 Subject: [PATCH] Roller v1 done --- .gitignore | 2 + exts/dice_commands.go | 52 ++++++++++++++ go.mod | 5 ++ go.sum | 10 +++ main.go | 1 + pkg/roller/roller.go | 153 +++++++++++++++++++++++++++++++++++++++++- 6 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 go.sum diff --git a/.gitignore b/.gitignore index 66fd13c..7a834b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.env + # Binaries for programs and plugins *.exe *.exe~ diff --git a/exts/dice_commands.go b/exts/dice_commands.go index e69de29..7613b1c 100644 --- a/exts/dice_commands.go +++ b/exts/dice_commands.go @@ -0,0 +1,52 @@ +package exts + +import ( + "fmt" + "log" + "regexp" + "strings" + + "github.com/bwmarrin/discordgo" + "github.com/dustinpianalto/dice/pkg/roller" +) + +func DiceCommand(session *discordgo.Session, m *discordgo.MessageCreate) { + if m.Author.Bot { + return + } + + content := strings.ToLower(m.Content) + r := regexp.MustCompile(`[^ "]+|"([^"]*)"`) + parts := r.FindAllString(content, -1) + var outString string + for _, part := range parts { + var label string + var die string + if strings.Contains(part, ":") { + ps := strings.Split(part, ":") + if len(ps) > 1 { + label = strings.Join(ps[1:], ":") + } + die = ps[0] + } else { + die = part + } + i, s, err := roller.ParseRollString(die) + if label != "" { + outString += label + ": " + } + if err != nil && i != -2 { + return + } else if err != nil { + outString = err.Error() + break + } + outString += fmt.Sprintf("`%d` %s\n", i, s) + } + + channel, err := session.Channel(m.ChannelID) + if err != nil { + log.Printf("Could not find channel %s\n", m.ChannelID) + } + session.ChannelMessageSend(channel.ID, outString) +} diff --git a/go.mod b/go.mod index d72e53f..12da191 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module github.com/dustinpianalto/dice go 1.15 + +require ( + github.com/bwmarrin/discordgo v0.22.0 + github.com/dustinpianalto/disgoman v0.0.12 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..441a734 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/bwmarrin/discordgo v0.20.2/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= +github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM= +github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= +github.com/dustinpianalto/disgoman v0.0.12 h1:dLptU2ZTUZJaLBOKeE6qjuL8gqdAr6ehHSOtfHmUpL8= +github.com/dustinpianalto/disgoman v0.0.12/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/main.go b/main.go index 7234bb2..8d47e32 100644 --- a/main.go +++ b/main.go @@ -55,6 +55,7 @@ func main() { exts.AddCommands(&handler) dg.AddHandler(handler.OnMessage) + dg.AddHandler(exts.DiceCommand) dg.AddHandler(handler.StatusManager.OnReady) err = dg.Open() diff --git a/pkg/roller/roller.go b/pkg/roller/roller.go index 67a3575..7594cc7 100644 --- a/pkg/roller/roller.go +++ b/pkg/roller/roller.go @@ -1,5 +1,156 @@ package roller -func ParseRollString(s string) int { +import ( + "crypto/rand" + "errors" + "fmt" + "math/big" + "strconv" + "strings" +) +func ParseRollString(s string) (int64, string, error) { + s = strings.ReplaceAll(s, "-", "+-") + parts := strings.Split(s, "+") + var out int64 + var outString string = " <= " + for i, part := range parts { + adv := false + dis := false + if strings.HasSuffix(part, "a") { + adv = true + } else if strings.HasSuffix(part, "d") { + dis = true + } + part = strings.TrimSuffix(part, "a") + part = strings.TrimSuffix(part, "d") + if c, err := strconv.ParseInt(part, 10, 64); err == nil && i != 0 { + out += c + if c < 0 { + outString += " - " + strconv.FormatInt(-1*c, 10) + } else { + outString += " + " + strconv.FormatInt(c, 10) + } + } else { + i, s, err := processDie(part, adv, dis) + if err != nil { + return i, outString, err + } + out += i + outString += s + } + } + return out, strings.Replace(outString, " <= + ", " <= ", 1), nil +} + +func processDie(part string, adv, dis bool) (int64, string, error) { + var mult int64 = 1 + var size int64 + var outString string = "" + var val int64 + if strings.HasPrefix(part, "-") { + mult = -1 + part = strings.TrimPrefix(part, "-") + } + if strings.Contains(part, "d") { + ps := strings.Split(part, "d") + count, err := strconv.Atoi(ps[0]) + if err != nil { + count = 1 + } + size, err = strconv.ParseInt(ps[1], 10, 64) + if err != nil { + return -1, outString, errors.New("invalid format") + } + for i := 0; i < count; i++ { + i, s, err := rollDie(size, adv, dis) + if err != nil { + return i, outString, err + } + val += i * mult + if mult > 0 { + outString += " + " + s + } else if mult < 0 { + outString += " - " + s + } else if mult > 0 { + outString += s + } + } + } else if strings.Contains(part, "x") { + ps := strings.Split(part, "x") + if len(ps) < 2 { + return -1, outString, errors.New("invalid format") + } + modifer, err := strconv.ParseInt(ps[0], 10, 64) + if err != nil { + return -1, outString, errors.New("invalid format") + } + multiple, err := strconv.ParseInt(ps[1], 10, 64) + if err != nil { + return -1, outString, errors.New("invalid format") + } + out := modifer * multiple * mult + if out < 0 { + outString += " - " + strconv.FormatInt(-1*out, 10) + } else { + outString += " + " + strconv.FormatInt(out, 10) + } + val += out + } else { + size, err := strconv.ParseInt(part, 10, 64) + if err != nil { + return -1, outString, err + } + i, s, err := rollDie(size, adv, dis) + if err != nil { + return i, outString, err + } + val += i * mult + if mult > 0 { + outString += " + " + s + } else if mult < 0 { + outString += " - " + s + } else if mult > 0 { + outString += s + } + } + return val, outString, nil +} + +func rollDie(i int64, adv, dis bool) (int64, string, error) { + if i <= 1 { + return -2, "", errors.New("invalid die") + } + size := big.NewInt(i) + one := big.NewInt(1) + num, err := rand.Int(rand.Reader, size) + if err != nil { + return -1, "", errors.New("can't get die roll") + } + num.Add(num, one) + if i == 10 && num.Cmp(big.NewInt(10)) == 0 { + num = big.NewInt(0) + } + if adv { + num2, err := rand.Int(rand.Reader, size) + if err != nil { + return -1, "", errors.New("can't get die roll") + } + num2.Add(num2, one) + if num2.Cmp(num) == 1 { + return num2.Int64(), fmt.Sprintf("{ ~~%s~~ %s }", num.String(), num2.String()), nil + } + return num.Int64(), fmt.Sprintf("{ ~~%s~~ %s }", num2.String(), num.String()), nil + } else if dis { + num2, err := rand.Int(rand.Reader, size) + if err != nil { + return -1, "", errors.New("can't get die roll") + } + num2.Add(num2, one) + if num2.Cmp(num) == -1 { + return num2.Int64(), fmt.Sprintf("{ ~~%s~~ %s }", num.String(), num2.String()), nil + } + return num.Int64(), fmt.Sprintf("{ ~~%s~~ %s }", num2.String(), num.String()), nil + } + return num.Int64(), fmt.Sprintf("{ %s }", num.String()), nil }