Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update roll command, added joinNumbers #58

Merged
merged 15 commits into from
Nov 12, 2023
74 changes: 49 additions & 25 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,45 +526,69 @@ func (b *bot) ban(m dggchat.Message, s *dggchat.Session) {
}
}

// !roll sides [count] - roll dice
func (b *bot) roll(m dggchat.Message, s *dggchat.Session) {
if !strings.HasPrefix(m.Message, "!roll") {
return
func computeRoll(input string) (int, error) {

// Define a regular expression to extract dice rolling information
regexPattern := `^!rolls?\s+(\d+)d(\d+)\s*([+\-]\s*\d+)?(.*?)$`
regex := regexp.MustCompile(regexPattern)

// Match the regular expression against the input string
matches := regex.FindStringSubmatch(input)

if matches == nil {
return 0, fmt.Errorf("Invalid input format: %s", input)
}

parts := strings.Split(m.Message, " ")
if len(parts) < 2 {
return
// Extract matched values
numDice, _ := strconv.Atoi(matches[1])
numSides, _ := strconv.Atoi(matches[2])
modifierStr := matches[3]
checkMod := modifierStr != ""

var modifier int
if checkMod {
modifier, _ = strconv.Atoi(modifierStr)
}

args := parts[1:]
if numSides <= 0 || numDice <= 0 || modifier > math.MaxInt64 {
return 0, fmt.Errorf("Sides, count or modifier too large")
}

// parse XdY
if strings.Contains(parts[1], "d") {
parts := strings.Split(parts[1], "d")
args = []string{parts[1], parts[0]}
if math.MaxInt64/numSides < numDice ||
(modifier > 0 && math.MaxInt64-numSides*numDice < modifier) ||
(modifier < 0 && math.MinInt64-numSides*numDice > modifier) {
return 0, fmt.Errorf("Sides, count or modifier too large")
}

sides, _ := strconv.ParseUint(args[0], 10, 64)
if sides < 2 {
return
// Roll the dice
result := 0
for i := 0; i < numDice; i++ {
result += rand.Intn(numSides) + 1
}

count := uint64(1)
if len(args) > 1 {
c, _ := strconv.ParseUint(args[1], 10, 64)
if c != 0 {
count = c
}
// Apply the modifier if present
if checkMod {
result += modifier
}

if math.MaxInt64/count <= sides || count > 100 {
return result, nil
}

// !roll sides [count] - roll dice
func (b *bot) roll(m dggchat.Message, s *dggchat.Session) {
if !strings.HasPrefix(m.Message, "!roll") {
return
}

var sum int64
for i := uint64(0); i < count; i++ {
sum += rand.Int63n(int64(sides)) + 1
parts := strings.Split(m.Message, " ")
if len(parts) < 2 {
return
}

var sum, err = computeRoll(m.Message)

if err != nil {
return
}

b.sendMessageDedupe(fmt.Sprintf("%s rolled %d", m.Sender.Nick, sum), s)
Expand Down
27 changes: 27 additions & 0 deletions commands_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"testing"
)

Expand All @@ -20,3 +21,29 @@ func TestParseModifiers(t *testing.T) {
}
// fmt.Println(err.Error())
}

func TestComputeRoll(t *testing.T) {
testInputs := [11]string{
"!roll 2d2+100 foo biz baz",
"!roll 2d2 + 100",
"!roll 2d2 +100",
"!roll 2d2+ 100",
"!roll 2d2-100",
"!roll 2d2 - 100",
"!roll 2d2 -100",
"!roll 2d2- 100",
"!roll 2d2- 100 foo biz baz",
"!roll 23904823904823904823490d20 +1",
"!roll 2d20"}

for _, input := range testInputs {
result, err := computeRoll(input)
errorMessage := fmt.Sprintf("%v", err)
if err != nil {
if errorMessage != "Sides, count or modifier too large" {
t.Error(fmt.Sprintf("Error: %v\n %d", err, result))
}
}
}

}
Loading