package main import ( "flag" "fmt" "math/rand" "os" "strings" "time" ) var ( surfaces, modifier, diceThrows, attacks int advantage, disadvantage, coin bool ) type Color string const ( ColorBlack Color = "\u001b[30m" ColorRed = "\u001b[31m" ColorGreen = "\u001b[32m" ColorYellow = "\u001b[33m" ColorBlue = "\u001b[34m" ColorMagenta = "\u001b[35m" ColorReset = "\u001b[0m" ) func main() { rand.Seed(time.Now().Unix()) ParseFlags() switch { // few basic checks case attacks < 1: fmt.Println("Attack amount cannot be below 1") os.Exit(1) case surfaces < 2: fmt.Println("Die surfaces cannot be below 2") os.Exit(1) case diceThrows < 1: fmt.Println("Dice thrown cannot be below 1") os.Exit(1) // die with 2 sides might as well be a coin case surfaces == 2 || coin: TossCoin(diceThrows) case advantage: if modifier > 0 { fmt.Printf("%sRolling 1d20 + %d with advantage...%s\n", Color(ColorGreen), modifier, Color(ColorReset)) } else { fmt.Printf("%sRolling 1d20 with advantage...%s\n", Color(ColorGreen), Color(ColorReset)) } fmt.Printf("\t%s%d%s\n", Color(ColorGreen), Advantage(SimpleCast(), SimpleCast()), Color(ColorReset)) case disadvantage: if modifier != 0 { fmt.Printf("%sRolling 1d20 + %d with disadvantage...%s\n", Color(ColorRed), modifier, Color(ColorReset)) } else { fmt.Printf("%sRolling 1d20 with disadvantage...%s\n", Color(ColorRed), Color(ColorReset)) } fmt.Printf("\t%s%d%s\n", Color(ColorRed), Disadvantage(SimpleCast(), SimpleCast()), Color(ColorReset)) case attacks > 1: for i := 0; i < attacks; i++ { fmt.Printf("%sAttack %d:%s\n", Color(ColorBlue), i+1, Color(ColorReset)) Cast(surfaces, diceThrows) } default: Cast(surfaces, diceThrows) } } func ParseFlags() { flag.IntVar(&surfaces, "surfaces", 20, "Use to specify die surfaces, does not apply to advantage and disadvantage") flag.IntVar(&surfaces, "s", 20, "Use to specify die surfaces, defaults to 20") flag.IntVar(&diceThrows, "throws", 1, "Specify amount of dice to cast") flag.IntVar(&diceThrows, "c", 1, "Specify amount of dice to cast") flag.IntVar(&modifier, "modifier", 0, "Add modifier to result of rolls") flag.IntVar(&modifier, "m", 0, "Add modifier to result of rolls") flag.IntVar(&attacks, "attacks", 1, "Roll a set rules multiple times, does not apply to advantage and disadvantage") flag.IntVar(&attacks, "a", 1, "Roll a set rules multiple times, does not apply to advantage and disadvantage") flag.BoolVar(&advantage, "advantage", false, "Roll with advantage") flag.BoolVar(&disadvantage, "disadvantage", false, "Roll with disadvantage") flag.BoolVar(&coin, "coin", false, "Toss a coin, same as '-s 2'") flag.Parse() } func TossCoin(castAmount int) { var ( coins []string coin string coinState int ) for i := 0; i < castAmount; i++ { coinState = rand.Intn(2) if coinState == 0 { coin = ColorYellow + "heads" + ColorReset } else { coin = ColorBlue + "tails" + ColorReset } coins = append(coins, coin) } if castAmount > 1 { fmt.Printf("%sTossing %d coins...%s\n", ColorYellow, castAmount, ColorReset) } else { fmt.Printf("%sTossing coin...%s\n", ColorYellow, ColorReset) } fmt.Printf("\t%s\n", strings.Trim(fmt.Sprint(coins), "[]")) } func Cast(dieSurfaces, castAmount int) { var ( casts []int cast, total int ) for i := 0; i < castAmount; i++ { cast = rand.Intn(dieSurfaces) + 1 casts = append(casts, cast) total += cast } switch { case modifier != 0: fmt.Printf("%sRolling %dd%d + %d...\n%s", ColorYellow, diceThrows, surfaces, modifier, ColorReset) default: fmt.Printf("%sRolling %dd%d...\n%s", ColorYellow, diceThrows, surfaces, ColorReset) } if castAmount > 1 { fmt.Println(Color(ColorMagenta), "\tIndividual rolls:", strings.Trim(fmt.Sprint(casts), "[]"), Color(ColorReset)) } if modifier != 0 { fmt.Println("\tWithout modifier:", total) fmt.Println(Color(ColorGreen), "\tWith modifier:", total+modifier, Color(ColorReset)) } else { fmt.Printf("%s\t%d%s\n", Color(ColorGreen), total, Color(ColorReset)) } } func SimpleCast() int { var cast = rand.Intn(20) + 1 if modifier != 0 { fmt.Println("Without modifier:", cast) } return cast + modifier } func Advantage(x, y int) int { fmt.Println("\tx:", x) fmt.Println("\tY:", y) if x > y { return x } else { return y } } func Disadvantage(x, y int) int { fmt.Println("\tx:", x) fmt.Println("\tY:", y) if x < y { return x } else { return y } }