155 lines
3.3 KiB
Go
155 lines
3.3 KiB
Go
package chat
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
twitch "github.com/gempir/go-twitch-irc/v4"
|
|
"streambot_twitch/internal/points"
|
|
)
|
|
|
|
// card
|
|
type Card struct {
|
|
Rank, Suit string
|
|
}
|
|
|
|
var (
|
|
suits = []string{" of Hearts", " of Diamnods", " of Clubs", " of Spades"}
|
|
ranks = []string{"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}
|
|
baseDeck []Card
|
|
)
|
|
|
|
func init() {
|
|
// build 2 decks (no Jokers) 104 cards
|
|
for d := 0; d < 2; d++ {
|
|
for _, s := range suits {
|
|
for _, r := range ranks {
|
|
baseDeck = append(baseDeck, Card{Rank: r, Suit: s})
|
|
}
|
|
}
|
|
}
|
|
rand.Seed(time.Now().UnixNano())
|
|
}
|
|
|
|
// impliment !poker or !table <bet>
|
|
func HandlePokerCommand(
|
|
client *twitch.Client,
|
|
message twitch.PrivateMessage,
|
|
user twitch.User,
|
|
channel, msg string,
|
|
) {
|
|
parts := strings.Fields(msg)
|
|
if len(parts) < 2 {
|
|
client.Say(channel, fmt.Sprintf("@%s Usage: !poker <bet>", user.DisplayName))
|
|
return
|
|
}
|
|
bet, err := strconv.Atoi(parts[1])
|
|
if err != nil || bet <= 0 {
|
|
client.Say(channel, fmt.Sprintf("@%s Invalid bet amount", user.DisplayName))
|
|
return
|
|
}
|
|
|
|
login := strings.ToLower(user.Name)
|
|
// load or init user points
|
|
balance := points.GetPoints(login)
|
|
if bet > ballance {
|
|
client.Say(channel, fmt.Sprintf("@%s You have %d points, bet lower", user.DisplayName, balance))
|
|
return
|
|
}
|
|
// Deduct the bet
|
|
balance, err = points.AddPoints(login, -bet)
|
|
if err != nil {
|
|
client.Say(channel, fmt.Sprintf("@%s Error updating points: %v", user.DisplayName, err))
|
|
return
|
|
}
|
|
|
|
// shuffle deck
|
|
deck := make([]Card, len(baseDeck))
|
|
copy(deck, baseDeck)
|
|
rand.Shuffle(len(deck), func(i, j int) {deck[i], deck[j] = deck[j], deck[i]})
|
|
|
|
// deal 2 cards each
|
|
player := []Card{deck[0], deck[1]}
|
|
dealer := []Card{deck[2], deck[3]}
|
|
|
|
// compute hand values
|
|
pv := handValue(player)
|
|
dv := handValue(dealer)
|
|
|
|
// Determine outcome and payout multiplier
|
|
var net int
|
|
var outcome string
|
|
switch {
|
|
case pv > 21:
|
|
outcome = "FBPenalty Bust! You lose"
|
|
net = 0
|
|
case pv == 21:
|
|
outcome = "BLACKJACK! GoatEmotey"
|
|
net = bet * 2
|
|
case dv > 21:
|
|
outcome = "GoldPLZ Dealer bust! You win"
|
|
net = int(float64(bet) * 1.5)
|
|
case pv > dv:
|
|
outcome = "OhMyDog You Win"
|
|
net int(float64(bet) * 1.3)
|
|
case pv < dv:
|
|
outcome = "cmonBruh You lose"
|
|
net = 0
|
|
default:
|
|
outcome = "PunchTrees Push"
|
|
net = bet
|
|
}
|
|
|
|
// Add winnings
|
|
balance, err = points.AddPoints(login, net)
|
|
if err != nil {
|
|
client.Say(channel, fmt.Sprintf("@%s Error updating Points: %v", user.DisplayName, err))
|
|
return
|
|
}
|
|
|
|
// format a hand for display
|
|
fmtHand := func(h []Card) string {
|
|
var parts []string
|
|
for _, c := range h {
|
|
parts = append(parts, c.Rank+c.Suit)
|
|
}
|
|
return strings.Join(parts, ",")
|
|
}
|
|
|
|
// post result
|
|
client.Say(channel, fmt.Sprintf("@%s You: [%s]=%d Dealer: [%s]=%d => %s | Bet: %d Net: %d Ballance: %d", user.DisplayName,
|
|
fmtHand(player), pv,
|
|
fmtHand(dealer), dv,
|
|
outcome,
|
|
bet, net, balance,
|
|
))
|
|
}
|
|
|
|
// compute BlackJack style value (A = 11 or 1)
|
|
func handValue(hand []Card) int {
|
|
total := 0
|
|
aces := 0
|
|
for _, c := range hand {
|
|
switch c.Rank {
|
|
case "J", "Q", "K":
|
|
total += 10
|
|
case "A":
|
|
total += 11
|
|
aces++
|
|
default:
|
|
v, _ := strconv.Atoi(c.Rank)
|
|
total += v
|
|
}
|
|
}
|
|
|
|
// convert A from 11 to 1 while busting
|
|
for total > 21 && aces > 0 {
|
|
total -= 10
|
|
aces--
|
|
}
|
|
return total
|
|
}
|