fixed an issue with calculating lowest and highest dice roll numbers
This commit is contained in:
+20
-8
@@ -44,9 +44,9 @@ func expandDiceNotation(expression string) (string, string, error) {
|
|||||||
result := expression
|
result := expression
|
||||||
diceRollsStr := expression
|
diceRollsStr := expression
|
||||||
|
|
||||||
// Pattern to match dice notation: [count]d[sides][H|L]
|
// Pattern to match dice notation: [H|L]?[count]d[sides][H|L]?
|
||||||
// Examples: d20, 2d6, 3d6H, 4d8L, dx (where x is placeholder)
|
// Examples: d20, 2d6, 3d6H, 4d8L, h2d20, l3d6, dx (where x is placeholder)
|
||||||
dicePattern := regexp.MustCompile(`(\d+)?d(\d+|x)([HL])?`)
|
dicePattern := regexp.MustCompile(`([HL])?(\d+)?d(\d+|x)([HL])?`)
|
||||||
|
|
||||||
// Process all dice matches
|
// Process all dice matches
|
||||||
matches := dicePattern.FindAllStringSubmatchIndex(result, -1)
|
matches := dicePattern.FindAllStringSubmatchIndex(result, -1)
|
||||||
@@ -58,14 +58,26 @@ func expandDiceNotation(expression string) (string, string, error) {
|
|||||||
end := match[1]
|
end := match[1]
|
||||||
|
|
||||||
// Extract components
|
// Extract components
|
||||||
countStr := ""
|
prefixModifier := ""
|
||||||
if match[2] != -1 {
|
if match[2] != -1 {
|
||||||
countStr = result[match[2]:match[3]]
|
prefixModifier = result[match[2]:match[3]]
|
||||||
}
|
}
|
||||||
sidesStr := result[match[4]:match[5]]
|
countStr := ""
|
||||||
|
if match[4] != -1 {
|
||||||
|
countStr = result[match[4]:match[5]]
|
||||||
|
}
|
||||||
|
sidesStr := result[match[6]:match[7]]
|
||||||
|
suffixModifier := ""
|
||||||
|
if match[8] != -1 {
|
||||||
|
suffixModifier = result[match[8]:match[9]]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine which modifier to use (priority: suffix > prefix)
|
||||||
modifier := ""
|
modifier := ""
|
||||||
if match[6] != -1 {
|
if suffixModifier != "" {
|
||||||
modifier = result[match[6]:match[7]]
|
modifier = suffixModifier
|
||||||
|
} else if prefixModifier != "" {
|
||||||
|
modifier = prefixModifier
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine count (default is 1)
|
// Determine count (default is 1)
|
||||||
|
|||||||
+45
-7
@@ -85,14 +85,20 @@ type Term struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseTerms parses a dice expression into terms
|
// parseTerms parses a dice expression into terms
|
||||||
|
// parseTerms parses a dice expression into terms, handling H/L flexibly
|
||||||
func parseTerms(expression string) ([]Term, error) {
|
func parseTerms(expression string) ([]Term, error) {
|
||||||
var terms []Term
|
var terms []Term
|
||||||
|
|
||||||
// Split by + and -, keeping the operators
|
// Remove spaces
|
||||||
|
expression = strings.TrimSpace(expression)
|
||||||
|
|
||||||
|
// Split by + and - while keeping the operators
|
||||||
parts := regexp.MustCompile(`([+\-])`).Split(expression, -1)
|
parts := regexp.MustCompile(`([+\-])`).Split(expression, -1)
|
||||||
|
|
||||||
currentOp := "+"
|
currentOp := "+"
|
||||||
dicePattern := regexp.MustCompile(`^(\d*)d(\d+)([HL])?$`)
|
pendingModifier := "" // Store H or L to apply to the next dice roll
|
||||||
|
// Pattern to match: optional H/L prefix, count, d, sides, optional H/L suffix
|
||||||
|
dicePattern := regexp.MustCompile(`^([HL])?(\d*)d(\d+)([HL])?$`)
|
||||||
|
|
||||||
for _, part := range parts {
|
for _, part := range parts {
|
||||||
part = strings.TrimSpace(part)
|
part = strings.TrimSpace(part)
|
||||||
@@ -107,19 +113,32 @@ func parseTerms(expression string) ([]Term, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for standalone H or L modifier
|
||||||
|
if part == "H" || part == "L" {
|
||||||
|
pendingModifier = part
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Try to match dice notation
|
// Try to match dice notation
|
||||||
matches := dicePattern.FindStringSubmatch(part)
|
matches := dicePattern.FindStringSubmatch(part)
|
||||||
|
|
||||||
if matches != nil {
|
if matches != nil {
|
||||||
|
// Extract components
|
||||||
|
prefixModifier := matches[1] // H or L before the dice
|
||||||
|
countStr := matches[2]
|
||||||
|
sidesStr := matches[3]
|
||||||
|
suffixModifier := matches[4] // H or L after the dice
|
||||||
|
|
||||||
count := 1
|
count := 1
|
||||||
if matches[1] != "" {
|
if countStr != "" {
|
||||||
c, err := strconv.Atoi(matches[1])
|
c, err := strconv.Atoi(countStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
count = c
|
count = c
|
||||||
}
|
}
|
||||||
|
|
||||||
sides, err := strconv.Atoi(matches[2])
|
sides, err := strconv.Atoi(sidesStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -128,7 +147,15 @@ func parseTerms(expression string) ([]Term, error) {
|
|||||||
return nil, fmt.Errorf("invalid dice: %dd%d", count, sides)
|
return nil, fmt.Errorf("invalid dice: %dd%d", count, sides)
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier := matches[3]
|
// Determine which modifier to use (priority: suffix > prefix > pending)
|
||||||
|
modifier := ""
|
||||||
|
if suffixModifier != "" {
|
||||||
|
modifier = suffixModifier
|
||||||
|
} else if prefixModifier != "" {
|
||||||
|
modifier = prefixModifier
|
||||||
|
} else if pendingModifier != "" {
|
||||||
|
modifier = pendingModifier
|
||||||
|
}
|
||||||
|
|
||||||
terms = append(terms, Term{
|
terms = append(terms, Term{
|
||||||
isDice: true,
|
isDice: true,
|
||||||
@@ -137,9 +164,15 @@ func parseTerms(expression string) ([]Term, error) {
|
|||||||
modifier: modifier,
|
modifier: modifier,
|
||||||
op: currentOp,
|
op: currentOp,
|
||||||
})
|
})
|
||||||
|
|
||||||
currentOp = "+"
|
currentOp = "+"
|
||||||
|
pendingModifier = ""
|
||||||
} else {
|
} else {
|
||||||
// Try to parse as constant
|
// Try to parse as constant (but reset pending modifier if it was set)
|
||||||
|
if pendingModifier != "" {
|
||||||
|
return nil, fmt.Errorf("modifier %s can only be applied to dice rolls", pendingModifier)
|
||||||
|
}
|
||||||
|
|
||||||
val, err := strconv.Atoi(part)
|
val, err := strconv.Atoi(part)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid term: %s", part)
|
return nil, fmt.Errorf("invalid term: %s", part)
|
||||||
@@ -154,6 +187,11 @@ func parseTerms(expression string) ([]Term, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we ended with a pending modifier, that's an error
|
||||||
|
if pendingModifier != "" {
|
||||||
|
return nil, fmt.Errorf("modifier %s at end of expression with no dice roll to apply to", pendingModifier)
|
||||||
|
}
|
||||||
|
|
||||||
return terms, nil
|
return terms, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user