106 lines
1.9 KiB
Go
106 lines
1.9 KiB
Go
|
package dice
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"math/rand"
|
||
|
"regexp"
|
||
|
"sort"
|
||
|
"strconv"
|
||
|
)
|
||
|
|
||
|
type StdRoller struct{}
|
||
|
|
||
|
var stdPattern = regexp.MustCompile(`([0-9]+)d([0-9]+)((k|d|kh|dl|kl|dh)([0-9]+))?([+-][0-9]+)?($|\s)`)
|
||
|
|
||
|
func (StdRoller) Pattern() *regexp.Regexp { return stdPattern }
|
||
|
|
||
|
type StdResult struct {
|
||
|
basicRollResult
|
||
|
Rolls []int
|
||
|
Dropped []int
|
||
|
Total int
|
||
|
}
|
||
|
|
||
|
func (r StdResult) String() string {
|
||
|
return fmt.Sprintf("%d %v (%v)", r.Total, r.Rolls, r.Dropped)
|
||
|
}
|
||
|
|
||
|
func (r StdResult) Int() int {
|
||
|
return r.Total
|
||
|
}
|
||
|
|
||
|
func (StdRoller) Roll(matches []string) (RollResult, error) {
|
||
|
dice, err := strconv.ParseInt(matches[1], 10, 0)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
sides, err := strconv.ParseInt(matches[2], 10, 0)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
keep := ""
|
||
|
num := 0
|
||
|
if matches[4] != "" {
|
||
|
number, err := strconv.ParseInt(matches[5], 10, 0)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
num = int(number)
|
||
|
keep = matches[4]
|
||
|
}
|
||
|
|
||
|
result := StdResult{
|
||
|
basicRollResult: basicRollResult{matches[0]},
|
||
|
Rolls: make([]int, dice),
|
||
|
Dropped: nil,
|
||
|
Total: 0,
|
||
|
}
|
||
|
|
||
|
if matches[6] != "" {
|
||
|
bonus, err := strconv.ParseInt(matches[6], 10, 0)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
result.Total += int(bonus)
|
||
|
}
|
||
|
|
||
|
for i := 0; i < len(result.Rolls); i++ {
|
||
|
roll := rand.Intn(int(sides)) + 1
|
||
|
result.Rolls[i] = roll
|
||
|
}
|
||
|
|
||
|
sort.Ints(result.Rolls)
|
||
|
size := len(result.Rolls)
|
||
|
|
||
|
switch keep {
|
||
|
case "k":
|
||
|
fallthrough
|
||
|
case "kh":
|
||
|
result.Dropped = result.Rolls[:size-num]
|
||
|
result.Rolls = result.Rolls[size-num:]
|
||
|
case "d":
|
||
|
fallthrough
|
||
|
case "dl":
|
||
|
result.Dropped = result.Rolls[:num]
|
||
|
result.Rolls = result.Rolls[num:]
|
||
|
case "kl":
|
||
|
result.Dropped = result.Rolls[num:]
|
||
|
result.Rolls = result.Rolls[:num]
|
||
|
case "dh":
|
||
|
result.Dropped = result.Rolls[size-num:]
|
||
|
result.Rolls = result.Rolls[:size-num]
|
||
|
}
|
||
|
|
||
|
for i := 0; i < len(result.Rolls); i++ {
|
||
|
result.Total += result.Rolls[i]
|
||
|
}
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
addRollHandler(StdRoller{})
|
||
|
}
|