542 lines
15 KiB
Go
542 lines
15 KiB
Go
package wat
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"fmt"
|
|
"math/big"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-irc/irc"
|
|
)
|
|
|
|
type WatGame struct {
|
|
bot *WatBot
|
|
db *WatDb
|
|
me Player
|
|
commands map[string](func(*Player, []string) string)
|
|
lifeCommands map[string](func(*Player, []string) string)
|
|
}
|
|
|
|
var currency = "watcoin"
|
|
var currencys = "watcoins"
|
|
var unconscious = "wat, your hands fumble and fail you. try resting, weakling."
|
|
|
|
func NewWatGame(bot *WatBot, db *WatDb) *WatGame {
|
|
g := WatGame{bot, db, Player{}, nil, nil}
|
|
g.me = g.db.User(bot.Nick, "tripsit/user/"+bot.Nick, true)
|
|
g.commands = map[string](func(*Player, []string) string){
|
|
"wat": g.megaWat,
|
|
"watch": g.Watch,
|
|
"coins": g.Balance,
|
|
"send": g.Send,
|
|
"rest": g.Rest,
|
|
"leech": g.Leech,
|
|
"roll": g.Roll,
|
|
"flip": g.Roll,
|
|
"dice": g.Dice,
|
|
"mine": g.Mine,
|
|
}
|
|
g.lifeCommands = map[string](func(*Player, []string) string){
|
|
"riot": g.Riot,
|
|
"bench": g.Bench,
|
|
"heal": g.Heal,
|
|
"steal": g.Steal,
|
|
"frame": g.Frame,
|
|
"punch": g.Punch,
|
|
"quest": g.QuestStart,
|
|
}
|
|
return &g
|
|
}
|
|
|
|
func (g *WatGame) Msg(m *irc.Message, player *Player, fields []string) {
|
|
command := strings.ToLower(fields[0])
|
|
reply := ""
|
|
if g.commands[command] != nil {
|
|
reply = g.commands[command](player, fields)
|
|
} else {
|
|
// one liners
|
|
switch strings.ToLower(command) {
|
|
case "help":
|
|
reply = g.help()
|
|
case "toplost":
|
|
reply = fmt.Sprintf("%s losers: %s", currency, g.TopLost())
|
|
case "topten":
|
|
reply = fmt.Sprintf("%s holders: %s", currency, g.TopTen())
|
|
case "source":
|
|
reply = "https://git.circuitco.de/self/watbot"
|
|
case "butt":
|
|
reply = "I LOVE BUTTS"
|
|
}
|
|
}
|
|
if g.lifeCommands[command] != nil {
|
|
if !player.Conscious() {
|
|
reply = unconscious
|
|
} else {
|
|
reply = g.lifeCommands[command](player, fields)
|
|
}
|
|
}
|
|
g.bot.reply(m, reply)
|
|
}
|
|
|
|
func (g *WatGame) help() string {
|
|
ret := ""
|
|
for cmd, _ := range g.commands {
|
|
if len(ret) > 0 {
|
|
ret += ", "
|
|
}
|
|
ret += cmd
|
|
}
|
|
for cmd, _ := range g.lifeCommands {
|
|
if len(ret) > 0 {
|
|
ret += ", "
|
|
}
|
|
ret += cmd
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (g *WatGame) RandInt(max int64) uint64 {
|
|
i, _ := rand.Int(rand.Reader, big.NewInt(max))
|
|
return i.Uint64()
|
|
}
|
|
|
|
func (g *WatGame) Heal(player *Player, fields []string) string {
|
|
multiplier := int64(5)
|
|
if len(fields) < 3 {
|
|
return "#heal <player> <coins> - sacrifice your money to me, peasant! i might heal someone!"
|
|
}
|
|
target, e := g.GetTarget("", fields[1])
|
|
if e != "" {
|
|
return e
|
|
}
|
|
a, err := g.Int(fields[2])
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
if a > player.Coins {
|
|
return "u poor lol"
|
|
}
|
|
amount := int64(a)
|
|
if amount < multiplier {
|
|
return fmt.Sprintf("too cheap lol at least %d", multiplier)
|
|
}
|
|
target.Health += amount / multiplier
|
|
player.Coins -= a
|
|
if target.Nick == player.Nick {
|
|
target.Coins -= a
|
|
g.db.Update(target)
|
|
} else {
|
|
g.db.Update(target, player)
|
|
}
|
|
fmtStr := "%s throws %d on the dirt. %s picks it up and waves their hand across %s, healing them. %s now has %d health."
|
|
return fmt.Sprintf(fmtStr, player.Nick, amount, g.bot.Nick, target.Nick, target.Nick, target.Health)
|
|
}
|
|
|
|
func (g *WatGame) Dice(player *Player, fields []string) string {
|
|
roll := uint64(6)
|
|
if len(fields) > 1 {
|
|
i, e := g.Int(fields[1])
|
|
if e == nil {
|
|
roll = i
|
|
}
|
|
}
|
|
answer := g.RandInt(int64(roll)) + 1
|
|
return fmt.Sprintf("1d%d - %d", roll, answer)
|
|
}
|
|
|
|
type PositiveError struct{}
|
|
type ParseIntError struct {
|
|
original string
|
|
}
|
|
|
|
func (e PositiveError) Error() string { return "i don't do negative numbers lol" }
|
|
func (e ParseIntError) Error() string { return fmt.Sprintf("wat kinda number is %s", e.original) }
|
|
|
|
func (g *WatGame) Int(str string) (uint64, error) {
|
|
i, e := strconv.ParseUint(str, 10, 64)
|
|
if i < 0 {
|
|
return 0, PositiveError{}
|
|
}
|
|
if e != nil {
|
|
e = ParseIntError{str}
|
|
}
|
|
return i, e
|
|
}
|
|
|
|
func (g *WatGame) Roll(player *Player, fields []string) string {
|
|
if len(fields) < 2 {
|
|
return fmt.Sprintf("roll <%s> pls - u must score < 50 if u want 2 win", currency)
|
|
}
|
|
amount, e := g.Int(fields[1])
|
|
if e != nil {
|
|
return e.Error()
|
|
}
|
|
if amount > player.Coins {
|
|
return "wat? brokeass"
|
|
}
|
|
n := g.RandInt(100) + 1
|
|
ret := fmt.Sprintf("%s rolls a 1d100... %d! ", player.Nick, n)
|
|
if n < 50 {
|
|
player.Coins += amount
|
|
ret += fmt.Sprintf("You win! total: %d %s", player.Coins, currency)
|
|
} else {
|
|
player.LoseCoins(amount)
|
|
g.me.Coins += amount
|
|
g.db.Update(g.me)
|
|
ret += fmt.Sprintf("You lose! %d %s left...", player.Coins, currency)
|
|
}
|
|
g.db.Update(player)
|
|
return ret
|
|
}
|
|
|
|
func (g *WatGame) Punch(player *Player, fields []string) string {
|
|
if len(fields) < 2 {
|
|
return "punch <target> pls"
|
|
}
|
|
target, err := g.GetTarget(player.Nick, fields[1])
|
|
if err != "" {
|
|
return err
|
|
}
|
|
if !target.Conscious() {
|
|
return "wat? you're punching someone who is already unconscious. u crazy?"
|
|
}
|
|
chance := g.RandInt(6) + 1
|
|
dmg := g.RandInt(6) + 1
|
|
ret := fmt.Sprintf("%s rolls a d6... %s ", player.Nick, player.Nick)
|
|
dmg += uint64(player.Level(player.Anarchy))
|
|
if chance > 3 {
|
|
ret += fmt.Sprintf("hits %s for %d points of damage! ", target.Nick, dmg)
|
|
target.Health -= int64(dmg)
|
|
g.db.Update(target)
|
|
if target.Health <= 0 {
|
|
ret += target.Nick + " has fallen unconscious."
|
|
} else {
|
|
ret += fmt.Sprintf("%s has %dHP left", target.Nick, target.Health)
|
|
}
|
|
} else {
|
|
ret += fmt.Sprintf("fumbles, and punches themselves in confusion! %d self-damage. ", dmg)
|
|
player.Health -= int64(dmg * 2)
|
|
player.Anarchy -= 1
|
|
if player.Health <= 0 {
|
|
ret += player.Nick + " has fallen unconscious."
|
|
} else {
|
|
ret += fmt.Sprintf("%s has %dHP left", player.Nick, player.Health)
|
|
}
|
|
g.db.Update(player)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (g *WatGame) Frame(player *Player, fields []string) string {
|
|
if len(fields) < 3 {
|
|
return fmt.Sprintf("frame <nick> <%s> - d6 roll. Sneaky? You force the target to pay me. Clumsy? You pay a fine to the target and myself.", currency)
|
|
}
|
|
amount, e := g.Int(fields[2])
|
|
if e != nil {
|
|
return e.Error()
|
|
}
|
|
if player.Coins < amount {
|
|
return "wat? you too poor for that."
|
|
}
|
|
target, err := g.GetTarget(player.Nick, fields[1])
|
|
if err != "" {
|
|
return err
|
|
}
|
|
if target.Coins < amount {
|
|
return fmt.Sprintf("wat? %s is too poor for this.", target.Nick)
|
|
}
|
|
n := g.RandInt(6) + 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)
|
|
if n < 3 {
|
|
ret += fmt.Sprintf("You frame %s for a minor crime. They pay me %d.", target.Nick, amount)
|
|
player.Anarchy += 1
|
|
target.Coins -= amount
|
|
} else {
|
|
ret += fmt.Sprintf("You were caught and pay them %d. %s gets the rest.", (amount / 2), g.bot.Nick)
|
|
player.LoseCoins(amount)
|
|
target.Coins += amount / 2
|
|
g.me.Coins += amount / 2
|
|
g.db.Update(g.me)
|
|
}
|
|
g.db.Update(player, target)
|
|
return ret
|
|
}
|
|
|
|
func (g *WatGame) Steal(player *Player, fields []string) string {
|
|
if len(fields) < 3 {
|
|
return fmt.Sprintf("steal <nick> <%s> - d6 roll. If you fail, you pay double the %s to %s", currency, currency, g.bot.Nick)
|
|
}
|
|
amount, e := g.Int(fields[2])
|
|
if e != nil {
|
|
return e.Error()
|
|
}
|
|
if player.Coins < amount*2 {
|
|
return "wat? you need double what ur trying 2 steal or you'll go bankrupt..."
|
|
}
|
|
target, err := g.GetTarget(player.Nick, fields[1])
|
|
if target == nil {
|
|
return err
|
|
}
|
|
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)
|
|
}
|
|
n := g.RandInt(6) + 1
|
|
ret := fmt.Sprintf("%s is trying to steal %d %s from %s... ", player.Nick, amount, currency, target.Nick)
|
|
if n < 3 {
|
|
ret += "You did it! Sneaky bastard!"
|
|
player.Coins += amount
|
|
player.Anarchy += 1
|
|
target.Coins -= amount
|
|
g.db.Update(target)
|
|
} else {
|
|
ret += fmt.Sprintf("You were caught and I took %d %s from your pocket.", (amount * 2), currency)
|
|
player.LoseCoins(amount * 2)
|
|
g.me.Coins += amount * 2
|
|
g.db.Update(g.me)
|
|
}
|
|
g.db.Update(player)
|
|
return ret
|
|
}
|
|
|
|
func (g *WatGame) GetTarget(player, target string) (*Player, string) {
|
|
t := g.db.User(strings.ToLower(target), "", false)
|
|
if t.Nick == "" {
|
|
return nil, "Who? wat?"
|
|
}
|
|
if t.Nick == player {
|
|
return nil, "You can't do that to yourself, silly."
|
|
}
|
|
return &t, ""
|
|
}
|
|
|
|
func (g *WatGame) Leech(player *Player, fields []string) string {
|
|
divisor := uint64(10)
|
|
if len(fields) < 3 {
|
|
return fmt.Sprintf("leech <nick> <%s> - using your wealth, you steal the life force of another player", currency)
|
|
}
|
|
amount, er := g.Int(fields[2])
|
|
if amount < divisor {
|
|
return fmt.Sprintf("wat? its %d %s for 1 hp", divisor, currency)
|
|
}
|
|
if player.Coins < amount || er != nil {
|
|
return "wat great fortune do you think you have? poor wats shouldn't be doing this, wat a waste..."
|
|
}
|
|
target, err := g.GetTarget(player.Nick, fields[1])
|
|
if err != "" {
|
|
return err
|
|
}
|
|
r := g.RandInt(10) + 1
|
|
reply := fmt.Sprintf("You muster your wealth and feed it to %s. ", g.bot.Nick)
|
|
hpDown := amount / divisor
|
|
player.Coins -= amount
|
|
if r < 5 {
|
|
target.Health -= int64(hpDown)
|
|
player.Health += int64(hpDown)
|
|
player.Anarchy += 1
|
|
reply += fmt.Sprintf("The deal is done, you took %d HP from %s. They now have %d HP, you have %d.", hpDown, target.Nick, target.Health, player.Health)
|
|
g.db.Update(target, player)
|
|
} else {
|
|
reply += "The gods do not smile upon you this waturday. Your money vanishes and nothing happens."
|
|
}
|
|
return reply
|
|
}
|
|
|
|
func (g *WatGame) Rest(player *Player, fields []string) string {
|
|
minRest := int64(43200)
|
|
delta := time.Now().Unix() - player.LastRested
|
|
ret := ""
|
|
if player.LastRested == 0 {
|
|
ret = "you've never slept before - you sleep so well, your injuries are cured and your health is restored to 10"
|
|
player.Health = 10
|
|
player.LastRested = time.Now().Unix()
|
|
g.db.Update(player)
|
|
} else if delta < minRest {
|
|
ret = fmt.Sprintf("wat were you thinking, sleeping at a time like this (%d until next rest)", minRest-delta)
|
|
} else {
|
|
value := g.RandInt(10) + 1
|
|
ret = fmt.Sprintf("wat a nap - have back a random amount of hitpoints (this time it's %d)", value)
|
|
player.LastRested = time.Now().Unix()
|
|
player.Health += int64(value)
|
|
g.db.Update(player)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (g *WatGame) CanAct(player *Player, action ActionType, minTime int64) bool {
|
|
delta := g.db.LastActed(player, action)
|
|
if minTime != 0 && delta != 0 && time.Now().Unix()-delta < minTime {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (g *WatGame) Bench(player *Player, fields []string) string {
|
|
minTime := int64(2400)
|
|
if !g.CanAct(player, Action_Lift, minTime) {
|
|
return "you're tired. no more lifting for now."
|
|
}
|
|
return "ok"
|
|
weight := g.RandInt(370) + 50
|
|
reps := g.RandInt(10)
|
|
value := int64(0)
|
|
reply := fmt.Sprintf("%s benches %dwatts for %d reps, ", player.Nick, weight, reps)
|
|
if weight < 150 {
|
|
reply += "do u even lift bro?"
|
|
return reply
|
|
} else if weight < 250 {
|
|
value = 1
|
|
} else if weight < 420 {
|
|
value = 2
|
|
} else if weight == 420 {
|
|
value = 10
|
|
reply += "four twenty blaze it bro! "
|
|
}
|
|
g.db.Act(player, Action_Lift)
|
|
player.Anarchy += value
|
|
g.db.Update(player)
|
|
reply += fmt.Sprintf("ur %d stronger lol", value)
|
|
return reply
|
|
}
|
|
|
|
func (g *WatGame) Riot(player *Player, fields []string) string {
|
|
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)"
|
|
}
|
|
r := g.RandInt(100)
|
|
reply := ""
|
|
if r > 30 {
|
|
player.Anarchy += 10
|
|
reply = fmt.Sprintf("You have successfully smashed the state! The brogeoise have been toppled. You're now a little more anarchistic (lv %d / exp %d)", player.Anarchy, player.Level(player.Anarchy))
|
|
} else {
|
|
player.Health -= 3
|
|
reply = fmt.Sprintf("The proletariat have been hunted down by the secret police and had their faces smashed in! Your rebellion fails and you lose 3HP.")
|
|
}
|
|
g.db.Act(player, Action_Riot)
|
|
g.db.Update(player)
|
|
return reply
|
|
}
|
|
|
|
func (g *WatGame) QuestStart(player *Player, fields []string) string {
|
|
// Begin a quest with some people. It will involve multiple dice rolls.
|
|
return ""
|
|
}
|
|
|
|
func (g *WatGame) Send(player *Player, fields []string) string {
|
|
if len(fields) < 3 {
|
|
return fmt.Sprintf("You forgot somethin'. send <nick> <%s>", currency)
|
|
}
|
|
amount, err := g.Int(fields[2])
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
if amount > player.Coins {
|
|
return "wat? you're too poor!"
|
|
}
|
|
target, str := g.GetTarget(player.Nick, fields[1])
|
|
if target == nil {
|
|
return str
|
|
}
|
|
player.Coins -= amount
|
|
target.Coins += amount
|
|
g.db.Update(player, target)
|
|
return fmt.Sprintf("%s sent %s %d %s. %s has %d %s, %s has %d %s", player.Nick, target.Nick, amount, currency, player.Nick, player.Coins, currency, target.Nick, target.Coins, currency)
|
|
}
|
|
|
|
func (g *WatGame) Mine(player *Player, _ []string) string {
|
|
delta := uint64(time.Now().Unix() - player.LastMined)
|
|
minDelta := uint64(600)
|
|
if delta < minDelta {
|
|
return fmt.Sprintf("wat? 2 soon. u earn more when u wait long (%d)", delta)
|
|
}
|
|
value := uint64(0)
|
|
if delta < 36000 {
|
|
value = delta / minDelta
|
|
} else if delta < 86400 {
|
|
value = 25
|
|
} else if delta < 2592000 {
|
|
value = 50
|
|
} else {
|
|
value = 1000
|
|
}
|
|
msg := ""
|
|
if player.LastMined == 0 {
|
|
msg = fmt.Sprintf("u forgot ur pickaxe but it's okay i'll give you one in %d", minDelta)
|
|
value = 0
|
|
} else {
|
|
player.Coins += value
|
|
msg = fmt.Sprintf("%s mined %d %s for %d and has %d %s", player.Nick, value, currency, delta, player.Coins, currency)
|
|
}
|
|
player.LastMined = time.Now().Unix()
|
|
g.db.Update(player)
|
|
return msg
|
|
}
|
|
|
|
func (g *WatGame) Watch(player *Player, fields []string) string {
|
|
if len(fields) > 1 {
|
|
maybePlayer, err := g.GetTarget("", fields[1])
|
|
if err != "" {
|
|
return err
|
|
}
|
|
player = maybePlayer
|
|
}
|
|
return fmt.Sprintf("%s's Watting: %d (%d) / Strength: %d (%d) / Trickery: %d (%d) / Coins: %d / Health: %d", player.Nick, player.Level(player.Watting), player.Watting, player.Level(player.Anarchy), player.Anarchy, player.Trickery, player.Trickery, player.Coins, player.Health)
|
|
}
|
|
|
|
func (g *WatGame) Balance(player *Player, fields []string) string {
|
|
balStr := "%s's %s balance: %d. Mining time credit: %d. Total lost: %d."
|
|
balPlayer := player
|
|
if len(fields) > 1 {
|
|
var err string
|
|
balPlayer, err = g.GetTarget("", fields[1])
|
|
if err != "" {
|
|
return err
|
|
}
|
|
}
|
|
return fmt.Sprintf(balStr, balPlayer.Nick, currency, balPlayer.Coins, time.Now().Unix()-balPlayer.LastMined, balPlayer.CoinsLost)
|
|
}
|
|
|
|
func (g *WatGame) TopLost() string {
|
|
players := g.db.TopLost()
|
|
ret := ""
|
|
for _, p := range players {
|
|
ret += PrintTwo(p.Nick, p.CoinsLost)
|
|
}
|
|
return ret
|
|
}
|
|
func (g *WatGame) TopTen() string {
|
|
players := g.db.TopTen()
|
|
ret := ""
|
|
for _, p := range players {
|
|
ret += PrintTwo(p.Nick, p.Coins)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func PrintTwo(nick string, value uint64) string {
|
|
return fmt.Sprintf("%s (%d) ", CleanNick(nick), value)
|
|
}
|
|
|
|
func (g *WatGame) megaWat(player *Player, _ []string) string {
|
|
mega := g.RandInt(1000000) + 1
|
|
kilo := g.RandInt(1000) + 1
|
|
ten := g.RandInt(100) + 1
|
|
reply := ""
|
|
if mega == 23 {
|
|
player.Coins += 1000000
|
|
reply = fmt.Sprintf("OMGWATWATWAT!!!! %s has won the MegaWat lottery and gains 1000000 %s!", player.Nick, currency)
|
|
}
|
|
if kilo == 5 {
|
|
player.Coins += 1000
|
|
reply = fmt.Sprintf("OMGWAT! %s has won the KiloWat lottery and gains 1000 %s!", player.Nick, currency)
|
|
}
|
|
if ten == 10 {
|
|
player.Coins += 10
|
|
reply = fmt.Sprintf("%s won the regular wattery. This one only pays 10 %s.", player.Nick, currency)
|
|
}
|
|
player.Watting += 1
|
|
g.db.Update(player)
|
|
return reply
|
|
}
|