mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-16 08:52:42 +00:00
Add UNO Show 'Em No Mercy game mode
168-card deck with new card types (Skip Everyone, Discard All, Wild Reverse Draw Four, Wild Draw Six/Ten, Wild Color Roulette), draw stacking, draw-until-playable, mercy elimination at 25 cards, and optional 7-0 hand swap/rotation rule. Works in both solo and multiplayer. Includes blackjack max player increase to 4. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
614
internal/plugin/uno_nomercy.go
Normal file
614
internal/plugin/uno_nomercy.go
Normal file
@@ -0,0 +1,614 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No Mercy helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// cardDrawValue returns the draw penalty for a card (0 if not a draw card).
|
||||
func cardDrawValue(v unoValue) int {
|
||||
switch v {
|
||||
case unoDrawTwo:
|
||||
return 2
|
||||
case unoDrawFour, unoWildReverseDraw4:
|
||||
return 4
|
||||
case unoWildDrawSix:
|
||||
return 6
|
||||
case unoWildDrawTen:
|
||||
return 10
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func isDrawCard(v unoValue) bool {
|
||||
return cardDrawValue(v) > 0
|
||||
}
|
||||
|
||||
// canPlayOnStacking checks if a card can be played during a stacking phase.
|
||||
// Only draw cards with value >= stackMinValue are allowed.
|
||||
// Wild draws always match; colored draws must match topColor.
|
||||
func (c unoCard) canPlayOnStacking(topColor unoColor, stackMinValue int) bool {
|
||||
dv := cardDrawValue(c.Value)
|
||||
if dv < stackMinValue {
|
||||
return false
|
||||
}
|
||||
if c.isWild() {
|
||||
return true
|
||||
}
|
||||
return c.Color == topColor
|
||||
}
|
||||
|
||||
// hasStackableCard returns true if the hand contains a card that can be stacked.
|
||||
func hasStackableCard(hand []unoCard, topColor unoColor, stackMinValue int) bool {
|
||||
for _, c := range hand {
|
||||
if c.canPlayOnStacking(topColor, stackMinValue) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No Mercy deck (168 cards)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func newNoMercyDeck() []unoCard {
|
||||
var cards []unoCard
|
||||
colors := []unoColor{unoRed, unoBlue, unoYellow, unoGreen}
|
||||
|
||||
for _, color := range colors {
|
||||
// Numbers 0-9: ×2 each
|
||||
for v := unoZero; v <= unoNine; v++ {
|
||||
cards = append(cards, unoCard{color, v})
|
||||
cards = append(cards, unoCard{color, v})
|
||||
}
|
||||
// Skip ×3
|
||||
for i := 0; i < 3; i++ {
|
||||
cards = append(cards, unoCard{color, unoSkip})
|
||||
}
|
||||
// Skip Everyone ×2
|
||||
for i := 0; i < 2; i++ {
|
||||
cards = append(cards, unoCard{color, unoSkipEveryone})
|
||||
}
|
||||
// Reverse ×4
|
||||
for i := 0; i < 4; i++ {
|
||||
cards = append(cards, unoCard{color, unoReverse})
|
||||
}
|
||||
// Draw Two ×2
|
||||
for i := 0; i < 2; i++ {
|
||||
cards = append(cards, unoCard{color, unoDrawTwo})
|
||||
}
|
||||
// Draw Four (colored) ×2
|
||||
for i := 0; i < 2; i++ {
|
||||
cards = append(cards, unoCard{color, unoDrawFour})
|
||||
}
|
||||
// Discard All ×3
|
||||
for i := 0; i < 3; i++ {
|
||||
cards = append(cards, unoCard{color, unoDiscardAll})
|
||||
}
|
||||
}
|
||||
|
||||
// Wild Reverse Draw Four ×8
|
||||
for i := 0; i < 8; i++ {
|
||||
cards = append(cards, unoCard{unoWild, unoWildReverseDraw4})
|
||||
}
|
||||
// Wild Draw Six ×4
|
||||
for i := 0; i < 4; i++ {
|
||||
cards = append(cards, unoCard{unoWild, unoWildDrawSix})
|
||||
}
|
||||
// Wild Draw Ten ×4
|
||||
for i := 0; i < 4; i++ {
|
||||
cards = append(cards, unoCard{unoWild, unoWildDrawTen})
|
||||
}
|
||||
// Wild Color Roulette ×8
|
||||
for i := 0; i < 8; i++ {
|
||||
cards = append(cards, unoCard{unoWild, unoWildColorRoulette})
|
||||
}
|
||||
|
||||
rand.Shuffle(len(cards), func(i, j int) { cards[i], cards[j] = cards[j], cards[i] })
|
||||
return cards
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mercy Rule
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const mercyLimit = 25
|
||||
|
||||
// checkSoloMercyElimination checks if the player or bot has 25+ cards.
|
||||
// Returns true if someone was eliminated (game ends).
|
||||
func (p *UnoPlugin) checkSoloMercyElimination(game *unoGame) bool {
|
||||
if !game.noMercy {
|
||||
return false
|
||||
}
|
||||
if len(game.playerHand) >= mercyLimit {
|
||||
p.SendMessage(game.dmRoomID,
|
||||
fmt.Sprintf("💀 **MERCY KILL!** You have %d cards — eliminated!", len(game.playerHand)))
|
||||
p.botWins(game)
|
||||
return true
|
||||
}
|
||||
if len(game.botHand) >= mercyLimit {
|
||||
bn := unoBotName()
|
||||
p.SendMessage(game.dmRoomID,
|
||||
fmt.Sprintf("💀 **MERCY KILL!** %s has %d cards — eliminated!", bn, len(game.botHand)))
|
||||
p.playerWins(game)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// checkMultiMercyElimination checks if a multiplayer player has 25+ cards.
|
||||
// Returns true if the player was eliminated.
|
||||
func (p *UnoPlugin) checkMultiMercyElimination(game *unoMultiGame, player *unoMultiPlayer) bool {
|
||||
if !game.noMercy || len(player.hand) < mercyLimit {
|
||||
return false
|
||||
}
|
||||
|
||||
player.active = false
|
||||
name := p.unoDisplayName(player.userID)
|
||||
if player.isBot {
|
||||
name = unoBotName()
|
||||
}
|
||||
|
||||
// Shuffle cards back into draw pile
|
||||
game.drawPile = append(game.drawPile, player.hand...)
|
||||
rand.Shuffle(len(game.drawPile), func(i, j int) { game.drawPile[i], game.drawPile[j] = game.drawPile[j], game.drawPile[i] })
|
||||
player.hand = nil
|
||||
|
||||
p.SendMessage(game.roomID,
|
||||
fmt.Sprintf("💀 **MERCY KILL!** %s had %d+ cards — eliminated!\n\n%s",
|
||||
name, mercyLimit, pickNoMercyCommentary("mercy_kill")))
|
||||
|
||||
if !player.isBot {
|
||||
p.SendMessage(player.dmRoomID,
|
||||
fmt.Sprintf("💀 You've been mercy-killed! (%d+ cards)", mercyLimit))
|
||||
}
|
||||
|
||||
// Check if game should end
|
||||
active := game.activePlayers()
|
||||
if len(active) <= 1 {
|
||||
if len(active) == 1 {
|
||||
winner := active[0]
|
||||
if winner.isBot {
|
||||
p.multiBotWins(game)
|
||||
} else {
|
||||
p.multiPlayerWins(game, winner)
|
||||
}
|
||||
} else {
|
||||
game.done = true
|
||||
p.SendMessage(game.roomID, "🃏 Game ended — no players remaining.")
|
||||
p.cleanupMultiGame(game)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Draw-until-playable helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// formatDrawnCards formats a list of drawn cards for display.
|
||||
func formatDrawnCards(cards []unoCard) string {
|
||||
if len(cards) == 1 {
|
||||
return cards[0].Display()
|
||||
}
|
||||
var parts []string
|
||||
for _, c := range cards {
|
||||
parts = append(parts, c.Display())
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Color Roulette
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// executeColorRoulette flips cards from draw pile until the chosen color appears.
|
||||
// All flipped cards are added to the target's hand.
|
||||
// Returns the flipped cards for display.
|
||||
func (p *UnoPlugin) executeColorRouletteSolo(game *unoGame, targetIsPlayer bool, chosenColor unoColor) []unoCard {
|
||||
var flipped []unoCard
|
||||
for {
|
||||
if len(game.drawPile) == 0 {
|
||||
game.reshuffleDiscard()
|
||||
}
|
||||
if len(game.drawPile) == 0 {
|
||||
break
|
||||
}
|
||||
card := game.drawPile[0]
|
||||
game.drawPile = game.drawPile[1:]
|
||||
flipped = append(flipped, card)
|
||||
if targetIsPlayer {
|
||||
game.playerHand = append(game.playerHand, card)
|
||||
} else {
|
||||
game.botHand = append(game.botHand, card)
|
||||
}
|
||||
if card.Color == chosenColor {
|
||||
break
|
||||
}
|
||||
}
|
||||
return flipped
|
||||
}
|
||||
|
||||
func (p *UnoPlugin) executeColorRouletteMulti(game *unoMultiGame, target *unoMultiPlayer, chosenColor unoColor) []unoCard {
|
||||
var flipped []unoCard
|
||||
for {
|
||||
if len(game.drawPile) == 0 {
|
||||
game.reshuffleDiscard()
|
||||
}
|
||||
if len(game.drawPile) == 0 {
|
||||
break
|
||||
}
|
||||
card := game.drawPile[0]
|
||||
game.drawPile = game.drawPile[1:]
|
||||
flipped = append(flipped, card)
|
||||
target.hand = append(target.hand, card)
|
||||
if card.Color == chosenColor {
|
||||
break
|
||||
}
|
||||
}
|
||||
return flipped
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 7-0 Rule helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// rotateHandsMulti rotates all active players' hands in the play direction.
|
||||
func rotateHandsMulti(game *unoMultiGame) {
|
||||
active := game.activePlayers()
|
||||
if len(active) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
// Build ordered list of active players by turn order in current direction
|
||||
n := len(game.players)
|
||||
var ordered []*unoMultiPlayer
|
||||
idx := game.currentIdx
|
||||
for i := 0; i < n; i++ {
|
||||
p := game.players[idx]
|
||||
if p.active {
|
||||
ordered = append(ordered, p)
|
||||
}
|
||||
idx = (idx + game.direction + n) % n
|
||||
}
|
||||
|
||||
if len(ordered) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
// Save all hands
|
||||
hands := make([][]unoCard, len(ordered))
|
||||
for i, p := range ordered {
|
||||
hands[i] = p.hand
|
||||
}
|
||||
|
||||
// Rotate: each player gets the hand of the player behind them (opposite of direction)
|
||||
for i := range ordered {
|
||||
prev := (i - 1 + len(ordered)) % len(ordered)
|
||||
ordered[i].hand = hands[prev]
|
||||
}
|
||||
}
|
||||
|
||||
// swapHandsSolo swaps player and bot hands.
|
||||
func swapHandsSolo(game *unoGame) {
|
||||
game.playerHand, game.botHand = game.botHand, game.playerHand
|
||||
}
|
||||
|
||||
// swapHandsMulti swaps two players' hands.
|
||||
func swapHandsMulti(a, b *unoMultiPlayer) {
|
||||
a.hand, b.hand = b.hand, a.hand
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Discard All helper
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// discardAllOfColor removes all cards of the given color from the hand.
|
||||
// Returns the count of additional cards removed (not counting the played card).
|
||||
func discardAllOfColor(hand *[]unoCard, color unoColor) int {
|
||||
var kept []unoCard
|
||||
removed := 0
|
||||
for _, c := range *hand {
|
||||
if c.Color == color {
|
||||
removed++
|
||||
} else {
|
||||
kept = append(kept, c)
|
||||
}
|
||||
}
|
||||
*hand = kept
|
||||
return removed
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No Mercy Bot AI
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// botPickCardNoMercy selects the best card for bot in No Mercy mode.
|
||||
func botPickCardNoMercy(hand []unoCard, discardTop unoCard, topColor unoColor, bookDown bool, opponentMinCards int, stackMinValue int) (unoCard, int) {
|
||||
// During stacking, only stackable cards are valid
|
||||
if stackMinValue > 0 {
|
||||
return botPickStackCard(hand, topColor, stackMinValue)
|
||||
}
|
||||
|
||||
var playable []int
|
||||
for i, c := range hand {
|
||||
if c.canPlayOn(discardTop, topColor) {
|
||||
playable = append(playable, i)
|
||||
}
|
||||
}
|
||||
if len(playable) == 0 {
|
||||
return unoCard{}, -1
|
||||
}
|
||||
|
||||
if bookDown {
|
||||
return botPickAggressiveNoMercy(hand, topColor, playable)
|
||||
}
|
||||
return botPickNormalNoMercy(hand, topColor, playable, opponentMinCards)
|
||||
}
|
||||
|
||||
func botPickStackCard(hand []unoCard, topColor unoColor, stackMinValue int) (unoCard, int) {
|
||||
var stackable []int
|
||||
for i, c := range hand {
|
||||
if c.canPlayOnStacking(topColor, stackMinValue) {
|
||||
stackable = append(stackable, i)
|
||||
}
|
||||
}
|
||||
if len(stackable) == 0 {
|
||||
return unoCard{}, -1 // bot must absorb
|
||||
}
|
||||
// Play the lowest-value stackable card to preserve bigger weapons
|
||||
bestIdx := stackable[0]
|
||||
bestVal := cardDrawValue(hand[bestIdx].Value)
|
||||
for _, i := range stackable[1:] {
|
||||
dv := cardDrawValue(hand[i].Value)
|
||||
if dv < bestVal {
|
||||
bestIdx = i
|
||||
bestVal = dv
|
||||
}
|
||||
}
|
||||
return hand[bestIdx], bestIdx
|
||||
}
|
||||
|
||||
func botPickNormalNoMercy(hand []unoCard, topColor unoColor, playable []int, opponentMinCards int) (unoCard, int) {
|
||||
var draws, actions, numbers, discardAlls, skipEveryones, roulettes []int
|
||||
|
||||
for _, i := range playable {
|
||||
c := hand[i]
|
||||
switch {
|
||||
case isDrawCard(c.Value):
|
||||
draws = append(draws, i)
|
||||
case c.Value == unoDiscardAll:
|
||||
discardAlls = append(discardAlls, i)
|
||||
case c.Value == unoSkipEveryone:
|
||||
skipEveryones = append(skipEveryones, i)
|
||||
case c.Value == unoWildColorRoulette:
|
||||
roulettes = append(roulettes, i)
|
||||
case c.Value.isAction():
|
||||
actions = append(actions, i)
|
||||
default:
|
||||
numbers = append(numbers, i)
|
||||
}
|
||||
}
|
||||
|
||||
// Prioritize Discard All if we have 3+ cards of that color
|
||||
for _, i := range discardAlls {
|
||||
color := hand[i].Color
|
||||
count := 0
|
||||
for _, c := range hand {
|
||||
if c.Color == color {
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count >= 3 {
|
||||
return hand[i], i
|
||||
}
|
||||
}
|
||||
|
||||
// If opponent close to winning, go aggressive with draw cards
|
||||
if opponentMinCards <= 3 {
|
||||
if len(draws) > 0 {
|
||||
// Play highest draw value
|
||||
bestIdx := draws[0]
|
||||
bestVal := cardDrawValue(hand[bestIdx].Value)
|
||||
for _, i := range draws[1:] {
|
||||
dv := cardDrawValue(hand[i].Value)
|
||||
if dv > bestVal {
|
||||
bestIdx = i
|
||||
bestVal = dv
|
||||
}
|
||||
}
|
||||
return hand[bestIdx], bestIdx
|
||||
}
|
||||
if len(skipEveryones) > 0 {
|
||||
return hand[skipEveryones[0]], skipEveryones[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Normal priority: numbers > actions > discard all > skip everyone > draws > roulettes
|
||||
if len(numbers) > 0 {
|
||||
// Prefer color match
|
||||
for _, i := range numbers {
|
||||
if hand[i].Color == topColor {
|
||||
return hand[i], i
|
||||
}
|
||||
}
|
||||
return hand[numbers[0]], numbers[0]
|
||||
}
|
||||
if len(actions) > 0 {
|
||||
return hand[actions[0]], actions[0]
|
||||
}
|
||||
if len(discardAlls) > 0 {
|
||||
return hand[discardAlls[0]], discardAlls[0]
|
||||
}
|
||||
if len(skipEveryones) > 0 {
|
||||
return hand[skipEveryones[0]], skipEveryones[0]
|
||||
}
|
||||
if len(draws) > 0 {
|
||||
// Play lowest draw to save bigger ones
|
||||
bestIdx := draws[0]
|
||||
bestVal := cardDrawValue(hand[bestIdx].Value)
|
||||
for _, i := range draws[1:] {
|
||||
dv := cardDrawValue(hand[i].Value)
|
||||
if dv < bestVal {
|
||||
bestIdx = i
|
||||
bestVal = dv
|
||||
}
|
||||
}
|
||||
return hand[bestIdx], bestIdx
|
||||
}
|
||||
if len(roulettes) > 0 {
|
||||
return hand[roulettes[0]], roulettes[0]
|
||||
}
|
||||
return hand[playable[0]], playable[0]
|
||||
}
|
||||
|
||||
func botPickAggressiveNoMercy(hand []unoCard, topColor unoColor, playable []int) (unoCard, int) {
|
||||
var draws, actions, others []int
|
||||
|
||||
for _, i := range playable {
|
||||
c := hand[i]
|
||||
switch {
|
||||
case isDrawCard(c.Value):
|
||||
draws = append(draws, i)
|
||||
case c.Value.isAction():
|
||||
actions = append(actions, i)
|
||||
default:
|
||||
others = append(others, i)
|
||||
}
|
||||
}
|
||||
|
||||
// Aggressive: play highest draw card first
|
||||
if len(draws) > 0 {
|
||||
bestIdx := draws[0]
|
||||
bestVal := cardDrawValue(hand[bestIdx].Value)
|
||||
for _, i := range draws[1:] {
|
||||
dv := cardDrawValue(hand[i].Value)
|
||||
if dv > bestVal {
|
||||
bestIdx = i
|
||||
bestVal = dv
|
||||
}
|
||||
}
|
||||
return hand[bestIdx], bestIdx
|
||||
}
|
||||
if len(actions) > 0 {
|
||||
return hand[actions[0]], actions[0]
|
||||
}
|
||||
if len(others) > 0 {
|
||||
return hand[others[0]], others[0]
|
||||
}
|
||||
return hand[playable[0]], playable[0]
|
||||
}
|
||||
|
||||
// botChooseSwapTarget picks the player with the fewest cards (to steal a small hand).
|
||||
func botChooseSwapTarget(game *unoMultiGame, bot *unoMultiPlayer) *unoMultiPlayer {
|
||||
var best *unoMultiPlayer
|
||||
bestCards := 999
|
||||
for _, p := range game.players {
|
||||
if p == bot || !p.active {
|
||||
continue
|
||||
}
|
||||
if len(p.hand) < bestCards {
|
||||
bestCards = len(p.hand)
|
||||
best = p
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
// botRouletteColor picks a color the bot has least of (to maximize damage).
|
||||
func botRouletteColor(hand []unoCard) unoColor {
|
||||
counts := map[unoColor]int{}
|
||||
for _, c := range hand {
|
||||
if c.Color != unoWild {
|
||||
counts[c.Color]++
|
||||
}
|
||||
}
|
||||
// Pick color with fewest cards (opponent likely has fewer too)
|
||||
best := unoRed
|
||||
bestCount := 999
|
||||
for _, color := range []unoColor{unoRed, unoBlue, unoYellow, unoGreen} {
|
||||
if counts[color] < bestCount {
|
||||
bestCount = counts[color]
|
||||
best = color
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No Mercy commentary
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
var noMercyCommentary = map[string][]string{
|
||||
"nomercy_start": {
|
||||
"*GogoBee sets the book down. Not gently.*\n\n\"No mercy? Fine. 💛\"\n\n*deals cards with unsettling precision*",
|
||||
"*GogoBee marks the page, closes the book with a snap.*\n\n\"Oh, you want to play *that* version. Okay. 💛\"\n\n*shuffles 168 cards without breaking eye contact*",
|
||||
},
|
||||
"mercy_kill": {
|
||||
"\"Sometimes the kindest thing is the quickest. 💛\" *doesn't look up*",
|
||||
"\"That's what mercy looks like. 💛\"",
|
||||
"\"...and that's why they call it No Mercy. 💛\"",
|
||||
},
|
||||
"stack_absorbed": {
|
||||
"\"That's a lot of cards. 💛\" *turns a page*",
|
||||
"\"Ouch. 💛\"",
|
||||
},
|
||||
"color_roulette": {
|
||||
"\"Let's see what fate has in store. 💛\"",
|
||||
"\"Flip, flip, flip... 💛\" *watches with mild interest*",
|
||||
},
|
||||
"discard_all": {
|
||||
"\"Oh, that's efficient. 💛\"",
|
||||
},
|
||||
"skip_everyone": {
|
||||
"\"Nobody gets a turn. How fun. 💛\"",
|
||||
},
|
||||
"hand_swap": {
|
||||
"\"Musical chairs, card edition. 💛\"",
|
||||
"\"Surprise. 💛\"",
|
||||
},
|
||||
"hand_rotate": {
|
||||
"\"Everyone pass your cards. Yes, all of them. 💛\"",
|
||||
},
|
||||
}
|
||||
|
||||
func pickNoMercyCommentary(key string) string {
|
||||
lines := noMercyCommentary[key]
|
||||
if len(lines) == 0 {
|
||||
return ""
|
||||
}
|
||||
line := lines[rand.IntN(len(lines))]
|
||||
return strings.ReplaceAll(line, "GogoBee", unoBotName())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No Mercy mode flags parser
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// parseNoMercyFlags parses "nomercy [7-0] €amount" and returns noMercy, sevenZeroRule, and remaining amount string.
|
||||
func parseNoMercyFlags(args string) (noMercy bool, sevenZeroRule bool, amountStr string) {
|
||||
lower := strings.ToLower(strings.TrimSpace(args))
|
||||
|
||||
if !strings.HasPrefix(lower, "nomercy") {
|
||||
return false, false, args
|
||||
}
|
||||
|
||||
rest := strings.TrimSpace(args[7:]) // len("nomercy") == 7
|
||||
lowerRest := strings.ToLower(rest)
|
||||
|
||||
if strings.HasPrefix(lowerRest, "7-0") {
|
||||
return true, true, strings.TrimSpace(rest[3:])
|
||||
}
|
||||
|
||||
return true, false, rest
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user