diff --git a/bot/rps.go b/bot/rps.go index 9ce5deb..706de07 100644 --- a/bot/rps.go +++ b/bot/rps.go @@ -1,20 +1,14 @@ package bot import ( - "fmt" "strings" - "git.kill0.net/chill9/beepboop/lib" "git.kill0.net/chill9/beepboop/lib/rps" "github.com/bwmarrin/discordgo" ) func (b *Bot) RpsCommand() CommandFunc { return func(args []string, m *discordgo.MessageCreate) error { - var ( - bc, pc, be, pe string - ) - if len(args) != 1 { b.Session.ChannelMessageSend( m.ChannelID, "help: `!rps (rock | paper | scissors)`", @@ -22,23 +16,21 @@ func (b *Bot) RpsCommand() CommandFunc { return nil } - pc = strings.ToLower(args[0]) + pc := strings.ToLower(args[0]) // player's choice - _, ok := rps.EmojiMapRps[pc] // player's choice - if !ok { + g := rps.NewGame(rps.RulesRps, rps.EmojiMapRps) + + bc := g.Rand() // bot's choice + + s, err := g.Play(bc, pc) + if _, ok := err.(rps.InvalidChoiceError); ok { b.Session.ChannelMessageSend( m.ChannelID, "help: `!rps (rock | paper | scissors)`", ) - return nil } - bc = lib.MapRandKey(rps.EmojiMapRps) // bot's choice - pe = rps.EmojiMapRps[pc] // player's emoji - be = rps.EmojiMapRps[bc] // bot's emoji + b.Session.ChannelMessageSend(m.ChannelID, s) - b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf( - "%s v %s: %s", pe, be, rps.Play(rps.RulesRps, bc, pc), - )) return nil } } diff --git a/bot/rpsls.go b/bot/rpsls.go index a0e244f..2d46bd7 100644 --- a/bot/rpsls.go +++ b/bot/rpsls.go @@ -1,44 +1,36 @@ package bot import ( - "fmt" "strings" - "git.kill0.net/chill9/beepboop/lib" "git.kill0.net/chill9/beepboop/lib/rps" "github.com/bwmarrin/discordgo" ) func (b *Bot) RpslsCommand() CommandFunc { return func(args []string, m *discordgo.MessageCreate) error { - var ( - bc, pc, be, pe string - ) - if len(args) != 1 { b.Session.ChannelMessageSend( - m.ChannelID, "help: `!rpsls (rock | paper | scissors | lizard | spock)`", + m.ChannelID, "help: `!rps (rock | paper | scissors | lizard | spock)`", ) return nil } - pc = strings.ToLower(args[0]) + pc := strings.ToLower(args[0]) // player's choice - _, ok := rps.EmojiMapRpsls[pc] // player's choice - if !ok { + g := rps.NewGame(rps.RulesRpsls, rps.EmojiMapRpsls) + + bc := g.Rand() // bot's choice + + s, err := g.Play(bc, pc) + if _, ok := err.(rps.InvalidChoiceError); ok { b.Session.ChannelMessageSend( - m.ChannelID, "help: `!rpsls (rock | paper | scissors | lizard | spock)`", + m.ChannelID, "help: `!rps (rock | paper | scissors | lizard | spock)`", ) - return nil } - bc = lib.MapRandKey(rps.EmojiMapRpsls) // bot's choice - pe = rps.EmojiMapRpsls[pc] // player's emoji - be = rps.EmojiMapRpsls[bc] // bot's emoji + b.Session.ChannelMessageSend(m.ChannelID, s) - b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf( - "%s v %s: %s", pe, be, rps.Play(rps.RulesRpsls, bc, pc), - )) return nil } } diff --git a/lib/rps/rps.go b/lib/rps/rps.go index 814d45d..c705bc6 100644 --- a/lib/rps/rps.go +++ b/lib/rps/rps.go @@ -2,6 +2,9 @@ package rps import ( "fmt" + "strings" + + "git.kill0.net/chill9/beepboop/lib" ) type ( @@ -11,6 +14,14 @@ type ( } ) +type InvalidChoiceError struct { + s string +} + +func (e InvalidChoiceError) Error() string { + return fmt.Sprintf("%q is an invalid choice", e.s) +} + var ( RulesRps [][]string = [][]string{ {"rock", "scissors", "crushes"}, @@ -46,6 +57,51 @@ var ( } ) +func NewGame(rules [][]string, emojiMap map[string]string) *Game { + return &Game{rules: rules, emojiMap: emojiMap} +} + +func (g *Game) Rand() string { + return lib.MapRandKey(g.emojiMap) +} + +func (g *Game) Play(c1, c2 string) (string, error) { + var b strings.Builder + + if !g.Valid(c1) { + return "", InvalidChoiceError{s: c1} + } + if !g.Valid(c2) { + return "", InvalidChoiceError{s: c2} + } + + fmt.Fprintf(&b, "%s v %s: ", g.emojiMap[c1], g.emojiMap[c2]) + + for _, rule := range g.rules { + verb := rule[2] + + if c1 == c2 { + fmt.Fprintf(&b, "draw") + return b.String(), nil + } + + if c1 == rule[0] && c2 == rule[1] { + fmt.Fprintf(&b, "%s %s %s", c1, verb, c2) + return b.String(), nil + } else if c2 == rule[0] && c1 == rule[1] { + fmt.Fprintf(&b, "%s %s %s", c2, verb, c1) + return b.String(), nil + } + } + + return b.String(), nil +} + +func (g *Game) Valid(c string) bool { + _, ok := g.emojiMap[c] + return ok +} + func Play(rules [][]string, c1, c2 string) string { for _, rule := range rules { if c1 == c2 {