mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
Add Wild Draw Four challenge mechanic and bot bluffing
- When a WD4 is played, the victim can challenge or accept - Challenge succeeds if the WD4 player had a card matching the previous color — they draw 4 instead - Challenge fails: victim draws 6 (4 + 2 penalty) - Bot as victim: challenges probabilistically based on opponent hand size (10-70% chance, more cards = more likely to challenge) - Bot as player: 20% chance to illegally play WD4 when it has matching color cards, making challenges meaningful against it - Auto-play defaults to accepting (safe option) - Challenge phase integrates with existing turn timer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1030,6 +1030,13 @@ func botPickNormal(hand []unoCard, topColor unoColor, playable []int, opponentMi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sometimes play WD4 even when we have other options (20% chance)
|
||||||
|
// This makes the challenge mechanic meaningful against the bot.
|
||||||
|
if len(wd4s) > 0 && (len(actions) > 0 || len(numbers) > 0) && rand.IntN(5) == 0 {
|
||||||
|
idx := wd4s[0]
|
||||||
|
return hand[idx], idx
|
||||||
|
}
|
||||||
|
|
||||||
// Save WD4 unless opponent is close to winning
|
// Save WD4 unless opponent is close to winning
|
||||||
if opponentMinCards > 3 {
|
if opponentMinCards > 3 {
|
||||||
if len(actions) > 0 {
|
if len(actions) > 0 {
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ import (
|
|||||||
type unoMultiPhase int
|
type unoMultiPhase int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
unoMultiPhasePlay unoMultiPhase = iota
|
unoMultiPhasePlay unoMultiPhase = iota
|
||||||
unoMultiPhaseChooseColor // active player must pick a color
|
unoMultiPhaseChooseColor // active player must pick a color
|
||||||
unoMultiPhaseDrawnPlayable // active player drew a playable card, yes/no
|
unoMultiPhaseDrawnPlayable // active player drew a playable card, yes/no
|
||||||
|
unoMultiPhaseChallenge // next player may challenge a Wild Draw Four
|
||||||
)
|
)
|
||||||
|
|
||||||
type unoMultiPlayer struct {
|
type unoMultiPlayer struct {
|
||||||
@@ -46,8 +47,13 @@ type unoMultiGame struct {
|
|||||||
discardTop unoCard
|
discardTop unoCard
|
||||||
topColor unoColor
|
topColor unoColor
|
||||||
phase unoMultiPhase
|
phase unoMultiPhase
|
||||||
drawnCard *unoCard // card drawn this turn
|
drawnCard *unoCard // card drawn this turn
|
||||||
pendingCard *unoCard // wild waiting for color
|
pendingCard *unoCard // wild waiting for color
|
||||||
|
|
||||||
|
// Wild Draw Four challenge state
|
||||||
|
wd4Player *unoMultiPlayer // who played the WD4
|
||||||
|
wd4Victim *unoMultiPlayer // who can challenge
|
||||||
|
wd4PrevColor unoColor // color before the wild was played
|
||||||
turns int
|
turns int
|
||||||
turnID int // monotonic, used to invalidate stale timers
|
turnID int // monotonic, used to invalidate stale timers
|
||||||
startedAt time.Time
|
startedAt time.Time
|
||||||
@@ -717,6 +723,9 @@ func (p *UnoPlugin) handleMultiDMInput(ctx MessageContext, game *unoMultiGame) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch game.phase {
|
switch game.phase {
|
||||||
|
case unoMultiPhaseChallenge:
|
||||||
|
return p.handleMultiChallengeInput(game, player, input)
|
||||||
|
|
||||||
case unoMultiPhaseChooseColor:
|
case unoMultiPhaseChooseColor:
|
||||||
return p.handleMultiColorChoice(game, player, input)
|
return p.handleMultiColorChoice(game, player, input)
|
||||||
|
|
||||||
@@ -748,6 +757,20 @@ func (p *UnoPlugin) handleMultiDMInput(ctx MessageContext, game *unoMultiGame) e
|
|||||||
// Play handlers
|
// Play handlers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func (p *UnoPlugin) handleMultiChallengeInput(game *unoMultiGame, player *unoMultiPlayer, input string) error {
|
||||||
|
switch input {
|
||||||
|
case "challenge", "c":
|
||||||
|
name := p.unoDisplayName(player.userID)
|
||||||
|
p.SendMessage(game.roomID, fmt.Sprintf("⚡ %s challenges the Wild Draw Four!", name))
|
||||||
|
p.resolveWD4Challenge(game, true)
|
||||||
|
case "accept", "a":
|
||||||
|
p.resolveWD4Challenge(game, false)
|
||||||
|
default:
|
||||||
|
p.SendMessage(player.dmRoomID, "Type **challenge** or **accept**.")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *UnoPlugin) handleMultiPlayerPlay(game *unoMultiGame, player *unoMultiPlayer, idx int) error {
|
func (p *UnoPlugin) handleMultiPlayerPlay(game *unoMultiGame, player *unoMultiPlayer, idx int) error {
|
||||||
card := player.hand[idx]
|
card := player.hand[idx]
|
||||||
|
|
||||||
@@ -784,6 +807,9 @@ func (p *UnoPlugin) handleMultiPlayerPlay(game *unoMultiGame, player *unoMultiPl
|
|||||||
// Wild — need color choice
|
// Wild — need color choice
|
||||||
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
||||||
game.pendingCard = &card
|
game.pendingCard = &card
|
||||||
|
if card.Value == unoWildDrawFour {
|
||||||
|
game.wd4PrevColor = game.topColor
|
||||||
|
}
|
||||||
game.phase = unoMultiPhaseChooseColor
|
game.phase = unoMultiPhaseChooseColor
|
||||||
p.SendMessage(player.dmRoomID,
|
p.SendMessage(player.dmRoomID,
|
||||||
fmt.Sprintf("You played **%s**! Choose a color:\n1. 🟥 Red\n2. 🟦 Blue\n3. 🟨 Yellow\n4. 🟩 Green", card.Value))
|
fmt.Sprintf("You played **%s**! Choose a color:\n1. 🟥 Red\n2. 🟦 Blue\n3. 🟨 Yellow\n4. 🟩 Green", card.Value))
|
||||||
@@ -906,6 +932,9 @@ func (p *UnoPlugin) handleMultiDrawnPlayable(game *unoMultiGame, player *unoMult
|
|||||||
|
|
||||||
if drawnCard.Value == unoWildCard || drawnCard.Value == unoWildDrawFour {
|
if drawnCard.Value == unoWildCard || drawnCard.Value == unoWildDrawFour {
|
||||||
game.pendingCard = &drawnCard
|
game.pendingCard = &drawnCard
|
||||||
|
if drawnCard.Value == unoWildDrawFour {
|
||||||
|
game.wd4PrevColor = game.topColor
|
||||||
|
}
|
||||||
game.phase = unoMultiPhaseChooseColor
|
game.phase = unoMultiPhaseChooseColor
|
||||||
p.SendMessage(player.dmRoomID,
|
p.SendMessage(player.dmRoomID,
|
||||||
fmt.Sprintf("You played **%s**! Choose a color:\n1. 🟥 Red\n2. 🟦 Blue\n3. 🟨 Yellow\n4. 🟩 Green", drawnCard.Value))
|
fmt.Sprintf("You played **%s**! Choose a color:\n1. 🟥 Red\n2. 🟦 Blue\n3. 🟨 Yellow\n4. 🟩 Green", drawnCard.Value))
|
||||||
@@ -932,9 +961,10 @@ func (p *UnoPlugin) handleMultiDrawnPlayable(game *unoMultiGame, player *unoMult
|
|||||||
|
|
||||||
// cardEffectResult describes what happened when a card's effects were applied.
|
// cardEffectResult describes what happened when a card's effects were applied.
|
||||||
type cardEffectResult struct {
|
type cardEffectResult struct {
|
||||||
skippedName string // non-empty if a player was skipped
|
skippedName string // non-empty if a player was skipped
|
||||||
reversed bool // true if direction was reversed
|
reversed bool // true if direction was reversed
|
||||||
drawnCount int // cards drawn by the victim (2 or 4)
|
drawnCount int // cards drawn by the victim (2 or 4)
|
||||||
|
needsChallenge bool // true if WD4 challenge phase should start
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyCardEffects applies skip/reverse/draw effects and advances the turn.
|
// applyCardEffects applies skip/reverse/draw effects and advances the turn.
|
||||||
@@ -979,13 +1009,8 @@ func (p *UnoPlugin) applyCardEffects(game *unoMultiGame, card unoCard) cardEffec
|
|||||||
game.turnID++
|
game.turnID++
|
||||||
|
|
||||||
case unoWildDrawFour:
|
case unoWildDrawFour:
|
||||||
drawn := game.draw(4)
|
result.needsChallenge = true
|
||||||
nextPlayer.hand = append(nextPlayer.hand, drawn...)
|
|
||||||
result.skippedName = nextName
|
result.skippedName = nextName
|
||||||
result.drawnCount = 4
|
|
||||||
game.currentIdx = nextIdx
|
|
||||||
game.currentIdx = game.nextActiveIdx()
|
|
||||||
game.turnID++
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
game.currentIdx = game.nextActiveIdx()
|
game.currentIdx = game.nextActiveIdx()
|
||||||
@@ -997,7 +1022,9 @@ func (p *UnoPlugin) applyCardEffects(game *unoMultiGame, card unoCard) cardEffec
|
|||||||
|
|
||||||
// writeEffectLines appends human-readable effect descriptions to a string builder.
|
// writeEffectLines appends human-readable effect descriptions to a string builder.
|
||||||
func writeEffectLines(sb *strings.Builder, eff cardEffectResult) {
|
func writeEffectLines(sb *strings.Builder, eff cardEffectResult) {
|
||||||
if eff.drawnCount > 0 {
|
if eff.needsChallenge {
|
||||||
|
sb.WriteString(fmt.Sprintf("\n %s may challenge! ⚡", eff.skippedName))
|
||||||
|
} else if eff.drawnCount > 0 {
|
||||||
sb.WriteString(fmt.Sprintf("\n %s draws %d and is skipped!", eff.skippedName, eff.drawnCount))
|
sb.WriteString(fmt.Sprintf("\n %s draws %d and is skipped!", eff.skippedName, eff.drawnCount))
|
||||||
} else if eff.skippedName != "" && eff.reversed {
|
} else if eff.skippedName != "" && eff.reversed {
|
||||||
sb.WriteString(fmt.Sprintf("\n %s is skipped! (reverse)", eff.skippedName))
|
sb.WriteString(fmt.Sprintf("\n %s is skipped! (reverse)", eff.skippedName))
|
||||||
@@ -1017,6 +1044,18 @@ func (p *UnoPlugin) applyAndAnnounce(game *unoMultiGame, player *unoMultiPlayer,
|
|||||||
eff := p.applyCardEffects(game, card)
|
eff := p.applyCardEffects(game, card)
|
||||||
writeEffectLines(&roomMsg, eff)
|
writeEffectLines(&roomMsg, eff)
|
||||||
|
|
||||||
|
// UNO announcement
|
||||||
|
if len(player.hand) == 1 && player.calledUno {
|
||||||
|
roomMsg.WriteString(fmt.Sprintf("\n %s calls UNO! 🔥", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wild Draw Four — enter challenge phase
|
||||||
|
if eff.needsChallenge {
|
||||||
|
p.SendMessage(game.roomID, roomMsg.String())
|
||||||
|
p.startWD4Challenge(game, player)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Book state commentary (occasionally)
|
// Book state commentary (occasionally)
|
||||||
if game.turns%4 == 0 {
|
if game.turns%4 == 0 {
|
||||||
if changed := game.updateBookState(); changed {
|
if changed := game.updateBookState(); changed {
|
||||||
@@ -1028,11 +1067,6 @@ func (p *UnoPlugin) applyAndAnnounce(game *unoMultiGame, player *unoMultiPlayer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UNO announcement
|
|
||||||
if len(player.hand) == 1 && player.calledUno {
|
|
||||||
roomMsg.WriteString(fmt.Sprintf("\n %s calls UNO! 🔥", name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next player
|
// Next player
|
||||||
nextUp := game.currentPlayer()
|
nextUp := game.currentPlayer()
|
||||||
nextUpName := p.unoDisplayName(nextUp.userID)
|
nextUpName := p.unoDisplayName(nextUp.userID)
|
||||||
@@ -1045,6 +1079,127 @@ func (p *UnoPlugin) applyAndAnnounce(game *unoMultiGame, player *unoMultiPlayer,
|
|||||||
p.executeMultiTurn(game)
|
p.executeMultiTurn(game)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Wild Draw Four challenge
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// startWD4Challenge enters the challenge phase. The victim can challenge or accept.
|
||||||
|
// Caller must hold game.mu.
|
||||||
|
func (p *UnoPlugin) startWD4Challenge(game *unoMultiGame, wd4Player *unoMultiPlayer) {
|
||||||
|
nextIdx := game.nextActiveIdx()
|
||||||
|
victim := game.players[nextIdx]
|
||||||
|
|
||||||
|
game.wd4Player = wd4Player
|
||||||
|
game.wd4Victim = victim
|
||||||
|
game.phase = unoMultiPhaseChallenge
|
||||||
|
game.currentIdx = nextIdx
|
||||||
|
game.turnID++
|
||||||
|
|
||||||
|
playerName := p.unoDisplayName(wd4Player.userID)
|
||||||
|
if wd4Player.isBot {
|
||||||
|
playerName = unoBotName()
|
||||||
|
}
|
||||||
|
|
||||||
|
if victim.isBot {
|
||||||
|
// Bot decides whether to challenge
|
||||||
|
p.botHandleWD4Challenge(game)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.SendMessage(victim.dmRoomID,
|
||||||
|
fmt.Sprintf("⚡ **%s** played Wild Draw Four!\nYou can **challenge** — if they had a %s %s card, they draw 4 instead.\nIf the challenge fails, you draw 6.\n\nType **challenge** or **accept**.",
|
||||||
|
playerName, game.wd4PrevColor.Emoji(), game.wd4PrevColor))
|
||||||
|
p.startMultiAutoPlayTimer(game)
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolveWD4Challenge resolves the challenge. Caller must hold game.mu.
|
||||||
|
func (p *UnoPlugin) resolveWD4Challenge(game *unoMultiGame, challenged bool) {
|
||||||
|
wd4Player := game.wd4Player
|
||||||
|
victim := game.wd4Victim
|
||||||
|
wd4Name := p.unoDisplayName(wd4Player.userID)
|
||||||
|
if wd4Player.isBot {
|
||||||
|
wd4Name = unoBotName()
|
||||||
|
}
|
||||||
|
victimName := p.unoDisplayName(victim.userID)
|
||||||
|
if victim.isBot {
|
||||||
|
victimName = unoBotName()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear challenge state
|
||||||
|
game.wd4Player = nil
|
||||||
|
game.wd4Victim = nil
|
||||||
|
game.phase = unoMultiPhasePlay
|
||||||
|
|
||||||
|
if !challenged {
|
||||||
|
// Victim accepts — draw 4, get skipped
|
||||||
|
drawn := game.draw(4)
|
||||||
|
victim.hand = append(victim.hand, drawn...)
|
||||||
|
p.SendMessage(game.roomID,
|
||||||
|
fmt.Sprintf("🃏 %s accepts the Wild Draw Four. Draws 4 and is skipped!", victimName))
|
||||||
|
game.currentIdx = game.nextActiveIdx()
|
||||||
|
game.turnID++
|
||||||
|
p.executeMultiTurn(game)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the WD4 player had a card matching the previous color
|
||||||
|
hadMatch := false
|
||||||
|
for _, c := range wd4Player.hand {
|
||||||
|
if c.Color == game.wd4PrevColor {
|
||||||
|
hadMatch = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hadMatch {
|
||||||
|
// Challenge succeeds — WD4 player drew illegally, they draw 4
|
||||||
|
drawn := game.draw(4)
|
||||||
|
wd4Player.hand = append(wd4Player.hand, drawn...)
|
||||||
|
p.SendMessage(game.roomID,
|
||||||
|
fmt.Sprintf("⚡ **Challenge successful!** %s had a %s %s card. %s draws 4!",
|
||||||
|
wd4Name, game.wd4PrevColor.Emoji(), game.wd4PrevColor, wd4Name))
|
||||||
|
// Victim is NOT skipped — turn continues from victim
|
||||||
|
game.turnID++
|
||||||
|
p.executeMultiTurn(game)
|
||||||
|
} else {
|
||||||
|
// Challenge fails — victim draws 6 (4 + 2 penalty)
|
||||||
|
drawn := game.draw(6)
|
||||||
|
victim.hand = append(victim.hand, drawn...)
|
||||||
|
p.SendMessage(game.roomID,
|
||||||
|
fmt.Sprintf("⚡ **Challenge failed!** %s played legally. %s draws 6!",
|
||||||
|
wd4Name, victimName))
|
||||||
|
// Victim is skipped
|
||||||
|
game.currentIdx = game.nextActiveIdx()
|
||||||
|
game.turnID++
|
||||||
|
p.executeMultiTurn(game)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// botHandleWD4Challenge decides whether the bot challenges a WD4. Caller must hold game.mu.
|
||||||
|
func (p *UnoPlugin) botHandleWD4Challenge(game *unoMultiGame) {
|
||||||
|
// More cards = more likely they had a matching color = more likely to challenge.
|
||||||
|
// 1-3 cards: 10%, 4-5: 30%, 6-7: 50%, 8+: 70%
|
||||||
|
cards := len(game.wd4Player.hand)
|
||||||
|
threshold := 10
|
||||||
|
if cards >= 8 {
|
||||||
|
threshold = 70
|
||||||
|
} else if cards >= 6 {
|
||||||
|
threshold = 50
|
||||||
|
} else if cards >= 4 {
|
||||||
|
threshold = 30
|
||||||
|
}
|
||||||
|
challenged := rand.IntN(100) < threshold
|
||||||
|
bn := unoBotName()
|
||||||
|
|
||||||
|
if challenged {
|
||||||
|
p.SendMessage(game.roomID, fmt.Sprintf("⚡ %s challenges the Wild Draw Four!", bn))
|
||||||
|
} else {
|
||||||
|
p.SendMessage(game.roomID, fmt.Sprintf("🃏 %s accepts the Wild Draw Four.", bn))
|
||||||
|
}
|
||||||
|
|
||||||
|
p.resolveWD4Challenge(game, challenged)
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Bot turn (multiplayer)
|
// Bot turn (multiplayer)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -1104,6 +1259,9 @@ func (p *UnoPlugin) botMultiTurn(game *unoMultiGame, roomBuf *strings.Builder) {
|
|||||||
|
|
||||||
// Wild color choice
|
// Wild color choice
|
||||||
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
||||||
|
if card.Value == unoWildDrawFour {
|
||||||
|
game.wd4PrevColor = game.topColor
|
||||||
|
}
|
||||||
game.topColor = botPickColor(bot.hand)
|
game.topColor = botPickColor(bot.hand)
|
||||||
} else {
|
} else {
|
||||||
game.topColor = card.Color
|
game.topColor = card.Color
|
||||||
@@ -1149,6 +1307,17 @@ func (p *UnoPlugin) botMultiTurn(game *unoMultiGame, roomBuf *strings.Builder) {
|
|||||||
eff := p.applyCardEffects(game, card)
|
eff := p.applyCardEffects(game, card)
|
||||||
writeEffectLines(roomBuf, eff)
|
writeEffectLines(roomBuf, eff)
|
||||||
|
|
||||||
|
// WD4 challenge — flush buffer and enter challenge phase
|
||||||
|
if eff.needsChallenge {
|
||||||
|
if roomBuf.Len() > 0 {
|
||||||
|
p.SendMessage(game.roomID, roomBuf.String())
|
||||||
|
roomBuf.Reset()
|
||||||
|
}
|
||||||
|
game.turns++
|
||||||
|
p.startWD4Challenge(game, bot)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
game.turns++
|
game.turns++
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1249,6 +1418,13 @@ func (p *UnoPlugin) autoPlayMultiTurn(game *unoMultiGame, player *unoMultiPlayer
|
|||||||
name := p.unoDisplayName(player.userID)
|
name := p.unoDisplayName(player.userID)
|
||||||
|
|
||||||
switch game.phase {
|
switch game.phase {
|
||||||
|
case unoMultiPhaseChallenge:
|
||||||
|
// Auto-play: accept the WD4 (safe default)
|
||||||
|
p.SendMessage(player.dmRoomID, "*Auto-played:* Accepted Wild Draw Four.")
|
||||||
|
p.SendMessage(game.roomID, fmt.Sprintf("🃏 *%s was auto-played.* Accepts the Wild Draw Four.", name))
|
||||||
|
p.resolveWD4Challenge(game, false)
|
||||||
|
return
|
||||||
|
|
||||||
case unoMultiPhaseChooseColor:
|
case unoMultiPhaseChooseColor:
|
||||||
// Auto-pick most common color
|
// Auto-pick most common color
|
||||||
color := botPickColor(player.hand)
|
color := botPickColor(player.hand)
|
||||||
@@ -1287,6 +1463,9 @@ func (p *UnoPlugin) autoPlayMultiTurn(game *unoMultiGame, player *unoMultiPlayer
|
|||||||
game.turns++
|
game.turns++
|
||||||
|
|
||||||
if drawnCard.Value == unoWildCard || drawnCard.Value == unoWildDrawFour {
|
if drawnCard.Value == unoWildCard || drawnCard.Value == unoWildDrawFour {
|
||||||
|
if drawnCard.Value == unoWildDrawFour {
|
||||||
|
game.wd4PrevColor = game.topColor
|
||||||
|
}
|
||||||
color := botPickColor(player.hand)
|
color := botPickColor(player.hand)
|
||||||
game.topColor = color
|
game.topColor = color
|
||||||
p.SendMessage(player.dmRoomID, fmt.Sprintf("*Auto-played:* %s (chose %s %s).", drawnCard.Display(), color.Emoji(), color))
|
p.SendMessage(player.dmRoomID, fmt.Sprintf("*Auto-played:* %s (chose %s %s).", drawnCard.Display(), color.Emoji(), color))
|
||||||
@@ -1343,6 +1522,9 @@ func (p *UnoPlugin) autoPlayMultiTurn(game *unoMultiGame, player *unoMultiPlayer
|
|||||||
game.turns++
|
game.turns++
|
||||||
|
|
||||||
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
||||||
|
if card.Value == unoWildDrawFour {
|
||||||
|
game.wd4PrevColor = game.topColor
|
||||||
|
}
|
||||||
color := botPickColor(player.hand)
|
color := botPickColor(player.hand)
|
||||||
game.topColor = color
|
game.topColor = color
|
||||||
p.SendMessage(player.dmRoomID, fmt.Sprintf("*Auto-played:* %s (chose %s %s).", card.Display(), color.Emoji(), color))
|
p.SendMessage(player.dmRoomID, fmt.Sprintf("*Auto-played:* %s (chose %s %s).", card.Display(), color.Emoji(), color))
|
||||||
@@ -1398,6 +1580,9 @@ func (p *UnoPlugin) autoPlayMultiTurn(game *unoMultiGame, player *unoMultiPlayer
|
|||||||
game.turns++
|
game.turns++
|
||||||
|
|
||||||
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
if card.Value == unoWildCard || card.Value == unoWildDrawFour {
|
||||||
|
if card.Value == unoWildDrawFour {
|
||||||
|
game.wd4PrevColor = game.topColor
|
||||||
|
}
|
||||||
color := botPickColor(player.hand)
|
color := botPickColor(player.hand)
|
||||||
game.topColor = color
|
game.topColor = color
|
||||||
p.SendMessage(player.dmRoomID, fmt.Sprintf("*Auto-played:* Drew and played %s (chose %s %s).", card.Display(), color.Emoji(), color))
|
p.SendMessage(player.dmRoomID, fmt.Sprintf("*Auto-played:* Drew and played %s (chose %s %s).", card.Display(), color.Emoji(), color))
|
||||||
@@ -1425,8 +1610,12 @@ func (p *UnoPlugin) autoPlayMultiTurn(game *unoMultiGame, player *unoMultiPlayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// applyAutoEffects applies card effects after an auto-play and advances the turn.
|
// applyAutoEffects applies card effects after an auto-play and advances the turn.
|
||||||
func (p *UnoPlugin) applyAutoEffects(game *unoMultiGame, _ *unoMultiPlayer, card unoCard) {
|
func (p *UnoPlugin) applyAutoEffects(game *unoMultiGame, player *unoMultiPlayer, card unoCard) {
|
||||||
p.applyCardEffects(game, card)
|
eff := p.applyCardEffects(game, card)
|
||||||
|
if eff.needsChallenge {
|
||||||
|
p.startWD4Challenge(game, player)
|
||||||
|
return
|
||||||
|
}
|
||||||
p.executeMultiTurn(game)
|
p.executeMultiTurn(game)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user