Refactor RPS/RPSLS

This commit is contained in:
Ryan Cavicchioni 2022-09-18 14:57:15 -05:00
parent 6139db889d
commit b8b994157e
Signed by: ryanc
GPG Key ID: 877EEDAF9245103D
3 changed files with 74 additions and 34 deletions

View File

@ -1,20 +1,14 @@
package bot package bot
import ( import (
"fmt"
"strings" "strings"
"git.kill0.net/chill9/beepboop/lib"
"git.kill0.net/chill9/beepboop/lib/rps" "git.kill0.net/chill9/beepboop/lib/rps"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
) )
func (b *Bot) RpsCommand() CommandFunc { func (b *Bot) RpsCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error { return func(args []string, m *discordgo.MessageCreate) error {
var (
bc, pc, be, pe string
)
if len(args) != 1 { if len(args) != 1 {
b.Session.ChannelMessageSend( b.Session.ChannelMessageSend(
m.ChannelID, "help: `!rps (rock | paper | scissors)`", m.ChannelID, "help: `!rps (rock | paper | scissors)`",
@ -22,23 +16,21 @@ func (b *Bot) RpsCommand() CommandFunc {
return nil return nil
} }
pc = strings.ToLower(args[0]) pc := strings.ToLower(args[0]) // player's choice
_, ok := rps.EmojiMapRps[pc] // player's choice g := rps.NewGame(rps.RulesRps, rps.EmojiMapRps)
if !ok {
bc := g.Rand() // bot's choice
s, err := g.Play(bc, pc)
if _, ok := err.(rps.InvalidChoiceError); ok {
b.Session.ChannelMessageSend( b.Session.ChannelMessageSend(
m.ChannelID, "help: `!rps (rock | paper | scissors)`", m.ChannelID, "help: `!rps (rock | paper | scissors)`",
) )
return nil
} }
bc = lib.MapRandKey(rps.EmojiMapRps) // bot's choice b.Session.ChannelMessageSend(m.ChannelID, s)
pe = rps.EmojiMapRps[pc] // player's emoji
be = rps.EmojiMapRps[bc] // bot's emoji
b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf(
"%s v %s: %s", pe, be, rps.Play(rps.RulesRps, bc, pc),
))
return nil return nil
} }
} }

View File

@ -1,44 +1,36 @@
package bot package bot
import ( import (
"fmt"
"strings" "strings"
"git.kill0.net/chill9/beepboop/lib"
"git.kill0.net/chill9/beepboop/lib/rps" "git.kill0.net/chill9/beepboop/lib/rps"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
) )
func (b *Bot) RpslsCommand() CommandFunc { func (b *Bot) RpslsCommand() CommandFunc {
return func(args []string, m *discordgo.MessageCreate) error { return func(args []string, m *discordgo.MessageCreate) error {
var (
bc, pc, be, pe string
)
if len(args) != 1 { if len(args) != 1 {
b.Session.ChannelMessageSend( b.Session.ChannelMessageSend(
m.ChannelID, "help: `!rpsls (rock | paper | scissors | lizard | spock)`", m.ChannelID, "help: `!rps (rock | paper | scissors | lizard | spock)`",
) )
return nil return nil
} }
pc = strings.ToLower(args[0]) pc := strings.ToLower(args[0]) // player's choice
_, ok := rps.EmojiMapRpsls[pc] // player's choice g := rps.NewGame(rps.RulesRpsls, rps.EmojiMapRpsls)
if !ok {
bc := g.Rand() // bot's choice
s, err := g.Play(bc, pc)
if _, ok := err.(rps.InvalidChoiceError); ok {
b.Session.ChannelMessageSend( 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 b.Session.ChannelMessageSend(m.ChannelID, s)
pe = rps.EmojiMapRpsls[pc] // player's emoji
be = rps.EmojiMapRpsls[bc] // bot's emoji
b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf(
"%s v %s: %s", pe, be, rps.Play(rps.RulesRpsls, bc, pc),
))
return nil return nil
} }
} }

View File

@ -2,6 +2,9 @@ package rps
import ( import (
"fmt" "fmt"
"strings"
"git.kill0.net/chill9/beepboop/lib"
) )
type ( 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 ( var (
RulesRps [][]string = [][]string{ RulesRps [][]string = [][]string{
{"rock", "scissors", "crushes"}, {"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 { func Play(rules [][]string, c1, c2 string) string {
for _, rule := range rules { for _, rule := range rules {
if c1 == c2 { if c1 == c2 {