diff --git a/bot/rps.go b/bot/rps.go index ccb7b5b..ffce5af 100644 --- a/bot/rps.go +++ b/bot/rps.go @@ -2,9 +2,9 @@ package bot import ( "fmt" - "math/rand" "strings" + "git.kill0.net/chill9/beepboop/lib" "github.com/bwmarrin/discordgo" ) @@ -15,10 +15,10 @@ const ( ) var ( - rpsVictoryMap map[int]int = map[int]int{ - Rock: Scissors, - Paper: Rock, - Scissors: Paper, + rpsVictoryMap map[int][]int = map[int][]int{ + Rock: {Scissors}, + Paper: {Rock}, + Scissors: {Paper}, } rpsChoiceMap map[string]int = map[string]int{ @@ -34,51 +34,49 @@ var ( } ) -func RpsRand() int { - n := rand.Intn(len(rpsVictoryMap)) - i := 0 - for _, v := range rpsChoiceMap { - if i == n { - return v - } - i++ - } - panic("unreachable") -} - func (b *Bot) RpsCommand() CommandFunc { return func(args []string, m *discordgo.MessageCreate) error { var ( - botChoice, playerChoice int - botEmoji, playerEmoji string - c string + bc, pc int + be, pe string + c string ) if len(args) != 1 { - b.Session.ChannelMessageSend(m.ChannelID, "help: `!rps (rock | paper | scissors)`") + b.Session.ChannelMessageSend( + m.ChannelID, "help: `!rps (rock | paper | scissors)`", + ) return nil } c = strings.ToLower(args[0]) - playerChoice, ok := rpsChoiceMap[c] + pc, ok := rpsChoiceMap[c] // player's choice if !ok { - b.Session.ChannelMessageSend(m.ChannelID, "help: `!rps (rock | paper | scissors)`") + b.Session.ChannelMessageSend( + m.ChannelID, "help: `!rps (rock | paper | scissors)`", + ) } - botChoice = RpsRand() - botEmoji = rpsEmojiMap[botChoice] - playerEmoji = rpsEmojiMap[playerChoice] + bc = lib.MapRand(rpsChoiceMap) // bot's choice + pe = rpsEmojiMap[pc] // player's emoji + be = rpsEmojiMap[bc] // bot's emoji - if botChoice == playerChoice { - b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%s v %s: draw", botEmoji, playerEmoji)) + if bc == pc { + b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf( + "%s v %s: draw", be, pe, + )) return nil - } else if rpsVictoryMap[botChoice] == playerChoice { - b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%s v %s: bot wins", botEmoji, playerEmoji)) + } else if lib.Contains(rpsVictoryMap[bc], pc) { + b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf( + "%s v %s: %s wins", be, pe, lib.MapKey(rpsChoiceMap, bc), + )) return nil } - b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%s v %s: you win", botEmoji, playerEmoji)) + b.Session.ChannelMessageSend(m.ChannelID, fmt.Sprintf( + "%s v %s: %s wins", be, pe, lib.MapKey(rpsChoiceMap, pc), + )) return nil } } diff --git a/lib/common.go b/lib/common.go index 6354c16..1932245 100644 --- a/lib/common.go +++ b/lib/common.go @@ -141,3 +141,21 @@ func SplitArgs(s string, n int) (args []string) { } return } + +func MapKeys[K comparable, V any](m map[K]V) []K { + keys := make([]K, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + return keys +} + +func MapKey[K comparable, V comparable](m map[K]V, v V) K { + var r K + for k := range m { + if m[k] == v { + return k + } + } + return r +} diff --git a/lib/common_test.go b/lib/common_test.go index 9a0a63b..1a0e446 100644 --- a/lib/common_test.go +++ b/lib/common_test.go @@ -123,3 +123,37 @@ func TestSplitArgs(t *testing.T) { } } } + +func TestMapKeys(t *testing.T) { + tables := []struct { + m map[string]int + want []string + }{ + {map[string]int{"a": 0, "b": 1, "c": 3}, []string{"a", "b", "c"}}, + } + + for _, table := range tables { + if got, want := MapKeys(table.m), table.want; !reflect.DeepEqual(got, want) { + t.Errorf("got: %#v, want: %#v", got, want) + } + } +} + +func TestMapKey(t *testing.T) { + tables := []struct { + m map[string]int + n int + want string + }{ + {map[string]int{"a": 0, "b": 1, "c": 2}, 0, "a"}, + {map[string]int{"a": 0, "b": 1, "c": 2}, 1, "b"}, + {map[string]int{"a": 0, "b": 1, "c": 2}, 2, "c"}, + {map[string]int{"a": 0, "b": 1, "c": 2, "d": 0}, 0, "a"}, + } + + for _, table := range tables { + if got, want := MapKey(table.m, table.n), table.want; got != want { + t.Errorf("got: %#v, want: %#v", got, want) + } + } +} diff --git a/lib/rand.go b/lib/rand.go index c391851..c88f55b 100644 --- a/lib/rand.go +++ b/lib/rand.go @@ -37,3 +37,15 @@ func SeedMathRand() error { func RandInt(min int, max int) int { return rand.Intn(max-min+1) + min } + +func MapRand[K comparable, V any](m map[K]V) V { + n := rand.Intn(len(m)) + i := 0 + for _, v := range m { + if i == n { + return v + } + i++ + } + panic("unreachable") +}