Prevent dice overflow
rand.Int() would panic when the max value is <= 0, which happens when big.NewInt() was fed with a too large number. Avoid this by validating the big.NewInt() return beforehand. Add error handling to all callers to both gracefully return to IRC and to log an error message. Rename the shadowed "max" variable whilst at it to avoid confusion. Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
This commit is contained in:
parent
e300f71370
commit
5560c59614
109
wat/game.go
109
wat/game.go
@ -121,9 +121,17 @@ func (g *WatGame) help() string {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *WatGame) RandInt(max int64) uint64 {
|
func (g *WatGame) RandInt(maxx int64) (uint64, error) {
|
||||||
i, _ := rand.Int(rand.Reader, big.NewInt(max))
|
bi := big.NewInt(maxx)
|
||||||
return i.Uint64()
|
// prevent panic of rand.Int on big numbers
|
||||||
|
if bi.BitLen() < 2 {
|
||||||
|
return 0, fmt.Errorf("overflow, got %d", bi)
|
||||||
|
}
|
||||||
|
i, err := rand.Int(rand.Reader, bi)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return i.Uint64(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *WatGame) Heal(player *Player, fields []string) string {
|
func (g *WatGame) Heal(player *Player, fields []string) string {
|
||||||
@ -166,8 +174,11 @@ func (g *WatGame) Dice(player *Player, fields []string) string {
|
|||||||
roll = i
|
roll = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
answer := g.RandInt(int64(roll)) + 1
|
answer, err := g.RandInt(int64(roll))
|
||||||
return fmt.Sprintf("1d%d - %d", roll, answer)
|
if e := handleError(err); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("1d%d - %d", roll + 1, answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PositiveError struct{}
|
type PositiveError struct{}
|
||||||
@ -206,12 +217,20 @@ func (g *WatGame) Roll(player *Player, fields []string) string {
|
|||||||
}
|
}
|
||||||
lotteryNum := int64(-1)
|
lotteryNum := int64(-1)
|
||||||
if dieSize > 100 {
|
if dieSize > 100 {
|
||||||
lotteryNum = int64(g.RandInt(dieSize)) + 1
|
lotteryNumRand, randErr := g.RandInt(dieSize)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
lotteryNum = int64(lotteryNumRand) + 1
|
||||||
}
|
}
|
||||||
if amount > player.Coins {
|
if amount > player.Coins {
|
||||||
return "wat? brokeass"
|
return "wat? brokeass"
|
||||||
}
|
}
|
||||||
n := int64(g.RandInt(dieSize)) + 1
|
nRand, randErr := g.RandInt(dieSize)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
n := int64(nRand) + 1
|
||||||
ret := fmt.Sprintf("%s rolls the %d sided die... %d! ", player.Nick, dieSize, n)
|
ret := fmt.Sprintf("%s rolls the %d sided die... %d! ", player.Nick, dieSize, n)
|
||||||
if n == lotteryNum {
|
if n == lotteryNum {
|
||||||
player.Coins += player.Coins
|
player.Coins += player.Coins
|
||||||
@ -255,11 +274,18 @@ func (g *WatGame) Punch(player *Player, fields []string) string {
|
|||||||
if !target.Conscious() {
|
if !target.Conscious() {
|
||||||
return "wat? you're punching someone who is already unconscious. u crazy?"
|
return "wat? you're punching someone who is already unconscious. u crazy?"
|
||||||
}
|
}
|
||||||
chance := g.RandInt(6) + 1
|
chance, randErr := g.RandInt(6)
|
||||||
dmg := g.RandInt(6) + 1
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
dmg, randErr := g.RandInt(6)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
dmg = dmg + 1
|
||||||
ret := fmt.Sprintf("%s rolls a d6... %s ", player.Nick, player.Nick)
|
ret := fmt.Sprintf("%s rolls a d6... %s ", player.Nick, player.Nick)
|
||||||
dmg += uint64(player.Level(player.Anarchy))
|
dmg += uint64(player.Level(player.Anarchy))
|
||||||
if chance > 3 {
|
if chance + 1 > 3 {
|
||||||
ret += fmt.Sprintf("hits %s for %d points of damage! ", target.Nick, dmg)
|
ret += fmt.Sprintf("hits %s for %d points of damage! ", target.Nick, dmg)
|
||||||
target.Health -= int64(dmg)
|
target.Health -= int64(dmg)
|
||||||
g.db.Update(target)
|
g.db.Update(target)
|
||||||
@ -300,7 +326,11 @@ func (g *WatGame) Frame(player *Player, fields []string) string {
|
|||||||
if target.Coins < amount {
|
if target.Coins < amount {
|
||||||
return fmt.Sprintf("wat? %s is too poor for this.", target.Nick)
|
return fmt.Sprintf("wat? %s is too poor for this.", target.Nick)
|
||||||
}
|
}
|
||||||
n := g.RandInt(6) + 1
|
n, randErr := g.RandInt(6)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
n = n + 1
|
||||||
ret := fmt.Sprintf("%s rolls a d6 to frame %s with %d %s: It's a %d! (<3 wins). ", player.Nick, target.Nick, amount, currency, n)
|
ret := fmt.Sprintf("%s rolls a d6 to frame %s with %d %s: It's a %d! (<3 wins). ", player.Nick, target.Nick, amount, currency, n)
|
||||||
if n < 3 {
|
if n < 3 {
|
||||||
ret += fmt.Sprintf("You frame %s for a minor crime. They pay me %d.", target.Nick, amount)
|
ret += fmt.Sprintf("You frame %s for a minor crime. They pay me %d.", target.Nick, amount)
|
||||||
@ -335,7 +365,11 @@ func (g *WatGame) Steal(player *Player, fields []string) string {
|
|||||||
if target.Coins < amount {
|
if target.Coins < amount {
|
||||||
return fmt.Sprintf("wat? %s is poor and doesn't have that much to steal. (%d %s)", target.Nick, target.Coins, currency)
|
return fmt.Sprintf("wat? %s is poor and doesn't have that much to steal. (%d %s)", target.Nick, target.Coins, currency)
|
||||||
}
|
}
|
||||||
n := g.RandInt(6) + 1
|
n, randErr := g.RandInt(6)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
n = n + 1
|
||||||
ret := fmt.Sprintf("%s is trying to steal %d %s from %s... ", player.Nick, amount, currency, target.Nick)
|
ret := fmt.Sprintf("%s is trying to steal %d %s from %s... ", player.Nick, amount, currency, target.Nick)
|
||||||
if n < 3 {
|
if n < 3 {
|
||||||
ret += "You did it! Sneaky bastard!"
|
ret += "You did it! Sneaky bastard!"
|
||||||
@ -380,7 +414,11 @@ func (g *WatGame) Leech(player *Player, fields []string) string {
|
|||||||
if err != "" {
|
if err != "" {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r := g.RandInt(10) + 1
|
r, randErr := g.RandInt(10)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
r = r + 1
|
||||||
reply := fmt.Sprintf("You muster your wealth and feed it to %s. ", g.bot.Nick)
|
reply := fmt.Sprintf("You muster your wealth and feed it to %s. ", g.bot.Nick)
|
||||||
hpDown := amount / divisor
|
hpDown := amount / divisor
|
||||||
player.Coins -= amount
|
player.Coins -= amount
|
||||||
@ -408,7 +446,11 @@ func (g *WatGame) Rest(player *Player, fields []string) string {
|
|||||||
} else if delta < minRest {
|
} else if delta < minRest {
|
||||||
ret = fmt.Sprintf("wat were you thinking, sleeping at a time like this (%d until next rest)", minRest-delta)
|
ret = fmt.Sprintf("wat were you thinking, sleeping at a time like this (%d until next rest)", minRest-delta)
|
||||||
} else {
|
} else {
|
||||||
value := g.RandInt(10) + 1
|
value, randErr := g.RandInt(10)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
value = value + 1
|
||||||
if player.Health < -5 {
|
if player.Health < -5 {
|
||||||
player.Health = 1
|
player.Health = 1
|
||||||
ret = fmt.Sprintf("wow ur beat up. i pity u, ur health is now 1.")
|
ret = fmt.Sprintf("wow ur beat up. i pity u, ur health is now 1.")
|
||||||
@ -435,8 +477,15 @@ func (g *WatGame) Bench(player *Player, fields []string) string {
|
|||||||
if !g.CanAct(player, Action_Lift, minTime) {
|
if !g.CanAct(player, Action_Lift, minTime) {
|
||||||
return "you're tired. no more lifting for now."
|
return "you're tired. no more lifting for now."
|
||||||
}
|
}
|
||||||
weight := g.RandInt(370) + 50
|
weight, randErr := g.RandInt(370)
|
||||||
reps := g.RandInt(10)
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
weight = weight + 50
|
||||||
|
reps, randErr := g.RandInt(10)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
value := int64(0)
|
value := int64(0)
|
||||||
reply := fmt.Sprintf("%s benches %dwatts for %d reps, ", player.Nick, weight, reps)
|
reply := fmt.Sprintf("%s benches %dwatts for %d reps, ", player.Nick, weight, reps)
|
||||||
if weight < 150 {
|
if weight < 150 {
|
||||||
@ -452,7 +501,10 @@ func (g *WatGame) Bench(player *Player, fields []string) string {
|
|||||||
}
|
}
|
||||||
if g.roid[player.Nick] != 0 {
|
if g.roid[player.Nick] != 0 {
|
||||||
delete(g.roid, player.Nick)
|
delete(g.roid, player.Nick)
|
||||||
success := g.RandInt(2)
|
success, randErr := g.RandInt(2)
|
||||||
|
if randErr != nil {
|
||||||
|
return "woops"
|
||||||
|
}
|
||||||
if success != 0 {
|
if success != 0 {
|
||||||
player.Health = 0
|
player.Health = 0
|
||||||
player.Anarchy -= 10
|
player.Anarchy -= 10
|
||||||
@ -475,7 +527,10 @@ func (g *WatGame) Riot(player *Player, fields []string) string {
|
|||||||
if !g.CanAct(player, Action_Riot, int64((48 * time.Hour).Seconds())) {
|
if !g.CanAct(player, Action_Riot, int64((48 * time.Hour).Seconds())) {
|
||||||
return "Planning a riot takes time and the right circumstances. Be prepared. (nothing happens)"
|
return "Planning a riot takes time and the right circumstances. Be prepared. (nothing happens)"
|
||||||
}
|
}
|
||||||
r := g.RandInt(100)
|
r, randErr := g.RandInt(100)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e
|
||||||
|
}
|
||||||
reply := ""
|
reply := ""
|
||||||
if r > 40 {
|
if r > 40 {
|
||||||
player.Anarchy += 3
|
player.Anarchy += 3
|
||||||
@ -621,9 +676,21 @@ func PrintTwo(nick string, value uint64) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *WatGame) megaWat(player *Player, _ []string) string {
|
func (g *WatGame) megaWat(player *Player, _ []string) string {
|
||||||
mega := g.RandInt(1000000) + 1
|
mega, randErr := g.RandInt(1000000)
|
||||||
kilo := g.RandInt(1000) + 1
|
if e := handleError(randErr); e != "" {
|
||||||
ten := g.RandInt(100) + 1
|
return e + " mega fail"
|
||||||
|
}
|
||||||
|
mega = mega + 1
|
||||||
|
kilo, randErr := g.RandInt(1000)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e + " kilo fail"
|
||||||
|
}
|
||||||
|
kilo = kilo + 1
|
||||||
|
ten, randErr := g.RandInt(100)
|
||||||
|
if e := handleError(randErr); e != "" {
|
||||||
|
return e + " ten fail"
|
||||||
|
}
|
||||||
|
ten = ten + 1
|
||||||
reply := ""
|
reply := ""
|
||||||
if mega == 23 {
|
if mega == 23 {
|
||||||
player.Coins += 1000000
|
player.Coins += 1000000
|
||||||
|
22
wat/utils.go
Normal file
22
wat/utils.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package wat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleError(err error) string {
|
||||||
|
if err != nil {
|
||||||
|
pc, _, _, ok := runtime.Caller(1)
|
||||||
|
details := runtime.FuncForPC(pc)
|
||||||
|
var cFun string
|
||||||
|
if ok && details != nil {
|
||||||
|
cFun = details.Name()
|
||||||
|
} else {
|
||||||
|
cFun = "???"
|
||||||
|
}
|
||||||
|
fmt.Printf("caught error in %s: %v\n", cFun, err)
|
||||||
|
return "u wat"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user