dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit 57bc06413e84c5621edd286b7f6904ed3c93f8c5
parent 0f4949bd06f819e056c95043e2eca6a257b2639a
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Mon, 18 Dec 2023 22:21:32 -0500

cleanup

Diffstat:
Mpkg/web/handlers/poker/poker.go | 393+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 203 insertions(+), 190 deletions(-)

diff --git a/pkg/web/handlers/poker/poker.go b/pkg/web/handlers/poker/poker.go @@ -579,6 +579,204 @@ type AutoAction struct { evt PlayerEvent } +func foldPlayer(g *PokerGame, p *PokerPlayer) { + roomTopic := g.RoomID.Topic() + p.Folded.Store(true) + var firstCardIdx, secondCardIdx int + p.Cards.RWith(func(pCards *[]PlayerCard) { + firstCardIdx = (*pCards)[0].Idx + secondCardIdx = (*pCards)[1].Idx + }) + evt1 := PokerEvent{ID: "card" + itoa(firstCardIdx), Name: "", Idx: firstCardIdx, Top: BurnStackY, Left: BurnStackX, Angle: "0deg", Reveal: false} + evt2 := PokerEvent{ID: "card" + itoa(secondCardIdx), Name: "", Idx: secondCardIdx, Top: BurnStackY, Left: BurnStackX, Angle: "0deg", Reveal: false} + PokerPubSub.Pub(roomTopic, evt1) + PokerPubSub.Pub(roomTopic, evt2) + g.Ongoing.AddEvent(evt1, evt2) +} + +func doTimeout(g *PokerGame, p *PokerPlayer, minBet database.PokerChip, playerAlive *int) int { + pUsername := p.Username + if p.GetBet() < minBet { + foldPlayer(g, p) + g.newLogEvent(fmt.Sprintf("%s auto fold", pUsername)) + + *playerAlive-- + if *playerAlive == 1 { + return breakRoundIsSettledLoop + } + return breakGetPlayerEventLoop + } + g.newLogEvent(fmt.Sprintf("%s auto check", pUsername)) + return breakGetPlayerEventLoop +} + +func doUnsit(g *PokerGame, p *PokerPlayer, playerAlive *int) int { + *playerAlive = g.Ongoing.CountAlivePlayers() + if *playerAlive == 1 { + p.countChancesToAction-- + return breakRoundIsSettledLoop + } + return continueGetPlayerEventLoop +} + +func doFold(g *PokerGame, p *PokerPlayer, playerAlive *int, roomUserTopic string) int { + foldPlayer(g, p) + g.newLogEvent(fmt.Sprintf("%s fold", p.Username)) + + *playerAlive-- + if *playerAlive == 1 { + PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: ""}) + return breakRoundIsSettledLoop + } + return doNothing +} + +func doCheck(g *PokerGame, p *PokerPlayer, minBet database.PokerChip, roomUserTopic string) int { + if p.GetBet() < minBet { + msg := fmt.Sprintf("Need to bet %d", minBet-p.GetBet()) + PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) + return continueGetPlayerEventLoop + } + g.newLogEvent(fmt.Sprintf("%s check", p.Username)) + return doNothing +} + +func doCall(g *PokerGame, p *PokerPlayer, db *database.DkfDB, minBet database.PokerChip, newlyAllInPlayers *[]*PokerPlayer, pokerTableID int64) int { + pUsername := p.Username + bet := utils.MinInt(minBet-p.GetBet(), p.GetCash()) + if bet == 0 { + g.newLogEvent(fmt.Sprintf("%s check", pUsername)) + } else { + p.doBetAndNotif(db, pokerTableID, bet, g.RoomID.Topic()) + logMsg := fmt.Sprintf("%s call (%d)", pUsername, bet) + if p.isAllIn() { + logMsg += " (all-in)" + *newlyAllInPlayers = append(*newlyAllInPlayers, p) + } + g.newLogEvent(logMsg) + } + return doNothing +} + +func doAllIn(g *PokerGame, p *PokerPlayer, db *database.DkfDB, minBet database.PokerChip, newlyAllInPlayers *[]*PokerPlayer, pokerTableID int64, lastRaisePlayerIdx *int, playerToPlayIdx int) int { + bet := p.GetCash() + if (p.GetBet() + bet) > minBet { + *lastRaisePlayerIdx = playerToPlayIdx + } + minBet = utils.MaxInt(p.GetBet()+bet, minBet) + p.doBetAndNotif(db, pokerTableID, bet, g.RoomID.Topic()) + logMsg := fmt.Sprintf("%s all-in (%d)", p.Username, bet) + if p.isAllIn() { + *newlyAllInPlayers = append(*newlyAllInPlayers, p) + } + g.newLogEvent(logMsg) + return doNothing +} + +func doBet(g *PokerGame, p *PokerPlayer, db *database.DkfDB, minBet database.PokerChip, newlyAllInPlayers *[]*PokerPlayer, pokerTableID int64, lastRaisePlayerIdx *int, playerToPlayIdx int, evt PlayerEvent) int { + roomTopic := g.RoomID.Topic() + roomUserTopic := g.RoomID.UserTopic(p.Username) + pokerTableMinBet := g.PokerTableMinBet + bet := evt.Bet + // Ensure the player cannot bet below the table minimum bet (amount of the big blind) + if p.GetBet()+bet != minBet && bet < pokerTableMinBet { + msg := fmt.Sprintf("Bet (%d) is too low. Must bet at least %d", bet, pokerTableMinBet) + PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) + return continueGetPlayerEventLoop + } + if (p.GetBet() + bet) < minBet { + msg := fmt.Sprintf("Bet (%d) is too low. Must bet at least %d", bet, minBet-p.GetBet()) + PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) + return continueGetPlayerEventLoop + } + if bet > p.GetCash() { + msg := fmt.Sprintf("Bet (%d) is too high. Must bet at most %d", bet, p.GetCash()) + PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) + return continueGetPlayerEventLoop + } + if (p.GetBet() + bet) > minBet { + *lastRaisePlayerIdx = playerToPlayIdx + } + minBet = utils.MaxInt(p.GetBet()+bet, minBet) + p.doBetAndNotif(db, pokerTableID, bet, roomTopic) + logMsg := fmt.Sprintf("%s bet %d", p.Username, bet) + if p.isAllIn() { + logMsg += " (all-in)" + *newlyAllInPlayers = append(*newlyAllInPlayers, p) + } + g.newLogEvent(logMsg) + return doNothing +} + +func handleAutoActionReceived(g *PokerGame, autoCache map[database.Username]AutoAction, roomID RoomID, evt PlayerEvent) int { + roomUserTopic := roomID.UserTopic(evt.Player) + autoAction := autoCache[evt.Player] + if evt.Fold && autoAction.action == FoldAction || + evt.Call && autoAction.action == CallAction || + evt.Check && autoAction.action == CheckAction { + delete(autoCache, evt.Player) + setAutoAction(g, roomUserTopic, "") + return continueGetPlayerEventLoop + } + + action := evt.getAction() + if action != NoAction { + autoCache[evt.Player] = AutoAction{action: action, evt: evt} + setAutoAction(g, roomUserTopic, "Will auto "+action.String()) + } + return continueGetPlayerEventLoop +} + +func applyAutoAction(g *PokerGame, p *PokerPlayer, db *database.DkfDB, minBet database.PokerChip, + newlyAllInPlayers *[]*PokerPlayer, pokerTableID int64, + lastRaisePlayerIdx, playerAlive *int, playerToPlayIdx int, autoAction AutoAction, + autoCache map[database.Username]AutoAction) (actionResult int) { + + roomUserTopic := g.RoomID.UserTopic(p.Username) + if autoAction.action > NoAction { + time.Sleep(500 * time.Millisecond) + p.LastActionTS = time.Now() + switch autoAction.action { + case NoAction: + case FoldAction: + actionResult = doFold(g, p, playerAlive, roomUserTopic) + case CheckAction: + actionResult = doCheck(g, p, minBet, roomUserTopic) + case CallAction: + actionResult = doCall(g, p, db, minBet, newlyAllInPlayers, pokerTableID) + case BetAction: + actionResult = doBet(g, p, db, minBet, newlyAllInPlayers, pokerTableID, lastRaisePlayerIdx, playerToPlayIdx, autoAction.evt) + case AllInAction: + actionResult = doAllIn(g, p, db, minBet, newlyAllInPlayers, pokerTableID, lastRaisePlayerIdx, playerToPlayIdx) + } + } + delete(autoCache, p.Username) + setAutoAction(g, roomUserTopic, "") + return +} + +func handlePlayerActionEvent(g *PokerGame, p *PokerPlayer, db *database.DkfDB, minBet database.PokerChip, + newlyAllInPlayers *[]*PokerPlayer, pokerTableID int64, + lastRaisePlayerIdx, playerAlive *int, playerToPlayIdx int, evt PlayerEvent) (actionResult int) { + + roomUserTopic := g.RoomID.UserTopic(p.Username) + p.LastActionTS = time.Now() + if evt.Fold { + actionResult = doFold(g, p, playerAlive, roomUserTopic) + } else if evt.Check { + actionResult = doCheck(g, p, minBet, roomUserTopic) + } else if evt.Call { + actionResult = doCall(g, p, db, minBet, newlyAllInPlayers, pokerTableID) + } else if evt.AllIn { + actionResult = doAllIn(g, p, db, minBet, newlyAllInPlayers, pokerTableID, lastRaisePlayerIdx, playerToPlayIdx) + } else if evt.Bet > 0 { + actionResult = doBet(g, p, db, minBet, newlyAllInPlayers, pokerTableID, lastRaisePlayerIdx, playerToPlayIdx, evt) + } else { + actionResult = continueGetPlayerEventLoop + } + return actionResult +} + // Return either or not the game ended because only 1 player left playing (or none) func execBettingRound(g *PokerGame, skip int, minBet database.PokerChip) bool { db := g.DB @@ -592,21 +790,6 @@ func execBettingRound(g *PokerGame, skip int, minBet database.PokerChip) bool { newlyAllInPlayers := make([]*PokerPlayer, 0) autoCache := make(map[database.Username]AutoAction) - foldPlayer := func(p *PokerPlayer) { - p.Folded.Store(true) - - var firstCardIdx, secondCardIdx int - p.Cards.RWith(func(pCards *[]PlayerCard) { - firstCardIdx = (*pCards)[0].Idx - secondCardIdx = (*pCards)[1].Idx - }) - evt1 := PokerEvent{ID: "card" + itoa(firstCardIdx), Name: "", Idx: firstCardIdx, Top: BurnStackY, Left: BurnStackX, Angle: "0deg", Reveal: false} - evt2 := PokerEvent{ID: "card" + itoa(secondCardIdx), Name: "", Idx: secondCardIdx, Top: BurnStackY, Left: BurnStackX, Angle: "0deg", Reveal: false} - PokerPubSub.Pub(roomTopic, evt1) - PokerPubSub.Pub(roomTopic, evt2) - ongoing.AddEvent(evt1, evt2) - } - playerAlive := ongoing.CountAlivePlayers() // Avoid asking for actions if only 1 player can do so (because others are all-in) @@ -640,176 +823,6 @@ RoundIsSettledLoop: setWaitTurn(g, p.SeatIdx) PokerPubSub.Pub(roomUserTopic, PokerYourTurnEvent{}) - doTimeout := func() int { - if p.GetBet() < minBet { - foldPlayer(p) - g.newLogEvent(fmt.Sprintf("%s auto fold", pUsername)) - - playerAlive-- - if playerAlive == 1 { - return breakRoundIsSettledLoop - } - return breakGetPlayerEventLoop - } - g.newLogEvent(fmt.Sprintf("%s auto check", pUsername)) - return breakGetPlayerEventLoop - } - - doUnsit := func() int { - playerAlive = ongoing.CountAlivePlayers() - if playerAlive == 1 { - p.countChancesToAction-- - return breakRoundIsSettledLoop - } - return continueGetPlayerEventLoop - } - - doFold := func() int { - foldPlayer(p) - g.newLogEvent(fmt.Sprintf("%s fold", pUsername)) - - playerAlive-- - if playerAlive == 1 { - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: ""}) - return breakRoundIsSettledLoop - } - return doNothing - } - - doCheck := func() int { - if p.GetBet() < minBet { - msg := fmt.Sprintf("Need to bet %d", minBet-p.GetBet()) - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) - return continueGetPlayerEventLoop - } - g.newLogEvent(fmt.Sprintf("%s check", pUsername)) - return doNothing - } - - doCall := func() int { - bet := utils.MinInt(minBet-p.GetBet(), p.GetCash()) - if bet == 0 { - g.newLogEvent(fmt.Sprintf("%s check", pUsername)) - } else { - p.doBetAndNotif(db, pokerTableID, bet, roomTopic) - logMsg := fmt.Sprintf("%s call (%d)", pUsername, bet) - if p.isAllIn() { - logMsg += " (all-in)" - newlyAllInPlayers = append(newlyAllInPlayers, p) - } - g.newLogEvent(logMsg) - } - return doNothing - } - - doAllIn := func() int { - bet := p.GetCash() - if (p.GetBet() + bet) > minBet { - lastRaisePlayerIdx = playerToPlayIdx - } - minBet = utils.MaxInt(p.GetBet()+bet, minBet) - p.doBetAndNotif(db, pokerTableID, bet, roomTopic) - logMsg := fmt.Sprintf("%s all-in (%d)", pUsername, bet) - if p.isAllIn() { - newlyAllInPlayers = append(newlyAllInPlayers, p) - } - g.newLogEvent(logMsg) - return doNothing - } - - doBet := func(evt PlayerEvent) int { - pokerTableMinBet := g.PokerTableMinBet - bet := evt.Bet - // Ensure the player cannot bet below the table minimum bet (amount of the big blind) - if p.GetBet()+bet != minBet && bet < pokerTableMinBet { - msg := fmt.Sprintf("Bet (%d) is too low. Must bet at least %d", bet, pokerTableMinBet) - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) - return continueGetPlayerEventLoop - } - if (p.GetBet() + bet) < minBet { - msg := fmt.Sprintf("Bet (%d) is too low. Must bet at least %d", bet, minBet-p.GetBet()) - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) - return continueGetPlayerEventLoop - } - if bet > p.GetCash() { - msg := fmt.Sprintf("Bet (%d) is too high. Must bet at most %d", bet, p.GetCash()) - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg}) - return continueGetPlayerEventLoop - } - if (p.GetBet() + bet) > minBet { - lastRaisePlayerIdx = playerToPlayIdx - } - minBet = utils.MaxInt(p.GetBet()+bet, minBet) - p.doBetAndNotif(db, pokerTableID, bet, roomTopic) - logMsg := fmt.Sprintf("%s bet %d", pUsername, bet) - if p.isAllIn() { - logMsg += " (all-in)" - newlyAllInPlayers = append(newlyAllInPlayers, p) - } - g.newLogEvent(logMsg) - return doNothing - } - - handleAutoActionReceived := func(evt PlayerEvent) int { - roomUserTopic := roomID.UserTopic(evt.Player) - autoAction := autoCache[evt.Player] - if evt.Fold && autoAction.action == FoldAction || - evt.Call && autoAction.action == CallAction || - evt.Check && autoAction.action == CheckAction { - delete(autoCache, evt.Player) - setAutoAction(g, roomUserTopic, "") - return continueGetPlayerEventLoop - } - - action := evt.getAction() - if action != NoAction { - autoCache[evt.Player] = AutoAction{action: action, evt: evt} - setAutoAction(g, roomUserTopic, "Will auto "+action.String()) - } - return continueGetPlayerEventLoop - } - - handlePlayerActionEvent := func(evt PlayerEvent) (actionResult int) { - p.LastActionTS = time.Now() - if evt.Fold { - actionResult = doFold() - } else if evt.Check { - actionResult = doCheck() - } else if evt.Call { - actionResult = doCall() - } else if evt.AllIn { - actionResult = doAllIn() - } else if evt.Bet > 0 { - actionResult = doBet(evt) - } else { - actionResult = continueGetPlayerEventLoop - } - return actionResult - } - - applyAutoAction := func(autoAction AutoAction) (actionResult int) { - if autoAction.action > NoAction { - time.Sleep(500 * time.Millisecond) - p.LastActionTS = time.Now() - switch autoAction.action { - case NoAction: - case FoldAction: - actionResult = doFold() - case CheckAction: - actionResult = doCheck() - case CallAction: - actionResult = doCall() - case BetAction: - actionResult = doBet(autoAction.evt) - case AllInAction: - actionResult = doAllIn() - } - } - delete(autoCache, pUsername) - setAutoAction(g, roomUserTopic, "") - return - } - // Maximum time allowed for the player to send his action waitCh := time.After(MaxUserCountdown * time.Second) GetPlayerEventLoop: @@ -819,28 +832,28 @@ RoundIsSettledLoop: // Check for pre-selected action if autoAction, ok := autoCache[pUsername]; ok { - actionResult = applyAutoAction(autoAction) + actionResult = applyAutoAction(g, p, db, minBet, &newlyAllInPlayers, pokerTableID, &lastRaisePlayerIdx, &playerAlive, playerToPlayIdx, autoAction, autoCache) goto checkActionResult } select { case evt = <-g.PlayersEventCh: case <-waitCh: // Waited too long, either auto-check or auto-fold - actionResult = doTimeout() + actionResult = doTimeout(g, p, minBet, &playerAlive) goto checkActionResult } if evt.Unsit { - actionResult = doUnsit() + actionResult = doUnsit(g, p, &playerAlive) goto checkActionResult } if evt.Player != pUsername { - actionResult = handleAutoActionReceived(evt) + actionResult = handleAutoActionReceived(g, autoCache, roomID, evt) goto checkActionResult } - actionResult = handlePlayerActionEvent(evt) + actionResult = handlePlayerActionEvent(g, p, db, minBet, &newlyAllInPlayers, pokerTableID, &lastRaisePlayerIdx, &playerAlive, playerToPlayIdx, evt) goto checkActionResult checkActionResult: