commit f263d4f82db1f1a8744db7b4e57670fa12a3d152
parent 692d9327f0f12a32238a2d6abd8e75fafaac8a49
Author: n0tr1v <n0tr1v@protonmail.com>
Date: Tue, 5 Dec 2023 21:13:53 -0500
cleanup
Diffstat:
1 file changed, 257 insertions(+), 253 deletions(-)
diff --git a/pkg/web/handlers/poker/poker.go b/pkg/web/handlers/poker/poker.go
@@ -179,317 +179,321 @@ func NewOngoing(g *PokerGame) *Ongoing {
return &Ongoing{Deck: deck, Players: players, WaitTurnEvent: PokerWaitTurnEvent{Idx: -1}}
}
-func (g *PokerGame) Deal(roomID string) {
+func dealerThread(g *PokerGame, roomID string) {
roomTopic := "room_" + roomID
- if g.Ongoing != nil {
- if !g.IsGameOver {
- fmt.Println("game already ongoing")
- return
- } else {
- g.IsGameOver = false
- PokerPubSub.Pub(roomTopic, ResetCardsEvent{})
- time.Sleep(time.Second)
- }
- }
- if g.CountSeated() < 2 {
- fmt.Println("need at least 2 players")
- return
- }
+ waitPlayersActionFn := func() bool {
+ lastRisePlayerIdx := -1
+ minBet := 0
- g.Ongoing = NewOngoing(g)
-
- go func() {
- waitPlayersActionFn := func() bool {
- lastRisePlayerIdx := -1
- minBet := 0
-
- playerAlive := 0
- for _, p := range g.Ongoing.Players {
- if p != nil && !p.Folded {
- playerAlive++
- }
+ playerAlive := 0
+ for _, p := range g.Ongoing.Players {
+ if p != nil && !p.Folded {
+ playerAlive++
}
+ }
- // TODO: implement maximum re-rise
- OUTER:
- for { // Loop until the round is settled
- for i, p := range g.Ongoing.Players {
- if p == nil {
- continue
- }
- if i == lastRisePlayerIdx {
- break OUTER
- }
- player := g.Ongoing.GetPlayer(p.Username)
- if player.Folded {
- continue
- }
- evt := PokerWaitTurnEvent{Idx: i}
- PokerPubSub.Pub(roomTopic, evt)
- g.Ongoing.WaitTurnEvent = evt
-
- // Maximum time allowed for the player to send his action
- waitCh := time.After(MaxUserCountdown * time.Second)
- LOOP:
- for { // Repeat until we get an event from the player we're interested in
- var evt PlayerEvent
-
- select {
- case evt = <-g.PlayersEventCh:
- case <-waitCh:
- // Waited too long, either auto-check or auto-fold
- if p.Cash == 0 { // all-in
- break LOOP
- }
- if p.Bet < minBet {
- player.Folded = true
- PokerPubSub.Pub(roomTopic, PlayerFoldEvent{Card1Idx: player.Cards[0].Idx, Card2Idx: player.Cards[1].Idx})
- playerAlive--
- if playerAlive == 1 {
- break OUTER
- }
- }
+ // TODO: implement maximum re-rise
+ OUTER:
+ for { // Loop until the round is settled
+ for i, p := range g.Ongoing.Players {
+ if p == nil {
+ continue
+ }
+ if i == lastRisePlayerIdx {
+ break OUTER
+ }
+ player := g.Ongoing.GetPlayer(p.Username)
+ if player.Folded {
+ continue
+ }
+ evt := PokerWaitTurnEvent{Idx: i}
+ PokerPubSub.Pub(roomTopic, evt)
+ g.Ongoing.WaitTurnEvent = evt
+
+ // Maximum time allowed for the player to send his action
+ waitCh := time.After(MaxUserCountdown * time.Second)
+ LOOP:
+ for { // Repeat until we get an event from the player we're interested in
+ var evt PlayerEvent
+
+ select {
+ case evt = <-g.PlayersEventCh:
+ case <-waitCh:
+ // Waited too long, either auto-check or auto-fold
+ if p.Cash == 0 { // all-in
break LOOP
}
-
- if evt.Player != p.Username {
- continue
- }
- roomUserTopic := "room_" + roomID + "_" + p.Username
- if evt.Fold {
+ if p.Bet < minBet {
player.Folded = true
PokerPubSub.Pub(roomTopic, PlayerFoldEvent{Card1Idx: player.Cards[0].Idx, Card2Idx: player.Cards[1].Idx})
playerAlive--
if playerAlive == 1 {
break OUTER
}
- } else if evt.Check {
- if p.Bet < minBet {
- msg := fmt.Sprintf("Need to bet %d", minBet-p.Bet)
- PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg})
- continue
- }
- } else if evt.Call {
- bet := minBet - p.Bet
- if p.Cash < bet {
- bet = p.Cash
- p.Bet += bet
- p.Cash = 0
- // All in
- } else {
- p.Bet += bet
- p.Cash -= bet
- }
- PokerPubSub.Pub(roomTopic, PlayerBetEvent{PlayerIdx: i, Player: p.Username, Bet: bet, TotalBet: p.Bet, Cash: p.Cash})
- } else if evt.Bet > 0 {
- if (p.Bet + evt.Bet) < minBet {
- msg := fmt.Sprintf("Bet (%d) is too low. Must bet at least %d", evt.Bet, minBet-p.Bet)
- PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg})
- continue
- }
- if (p.Bet + evt.Bet) > minBet {
- lastRisePlayerIdx = i
- }
- minBet = p.Bet + evt.Bet
- p.Bet += evt.Bet
- p.Cash -= evt.Bet
- PokerPubSub.Pub(roomTopic, PlayerBetEvent{PlayerIdx: i, Player: p.Username, Bet: evt.Bet, TotalBet: p.Bet, Cash: p.Cash})
}
- break
+ break LOOP
}
- }
- // All settle when all players have the same bet amount
- if isRoundSettled(g.Ongoing.Players) {
+ if evt.Player != p.Username {
+ continue
+ }
+ roomUserTopic := "room_" + roomID + "_" + p.Username
+ if evt.Fold {
+ player.Folded = true
+ PokerPubSub.Pub(roomTopic, PlayerFoldEvent{Card1Idx: player.Cards[0].Idx, Card2Idx: player.Cards[1].Idx})
+ playerAlive--
+ if playerAlive == 1 {
+ break OUTER
+ }
+ } else if evt.Check {
+ if p.Bet < minBet {
+ msg := fmt.Sprintf("Need to bet %d", minBet-p.Bet)
+ PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg})
+ continue
+ }
+ } else if evt.Call {
+ bet := minBet - p.Bet
+ if p.Cash < bet {
+ bet = p.Cash
+ p.Bet += bet
+ p.Cash = 0
+ // All in
+ } else {
+ p.Bet += bet
+ p.Cash -= bet
+ }
+ PokerPubSub.Pub(roomTopic, PlayerBetEvent{PlayerIdx: i, Player: p.Username, Bet: bet, TotalBet: p.Bet, Cash: p.Cash})
+ } else if evt.Bet > 0 {
+ if (p.Bet + evt.Bet) < minBet {
+ msg := fmt.Sprintf("Bet (%d) is too low. Must bet at least %d", evt.Bet, minBet-p.Bet)
+ PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: msg})
+ continue
+ }
+ if (p.Bet + evt.Bet) > minBet {
+ lastRisePlayerIdx = i
+ }
+ minBet = p.Bet + evt.Bet
+ p.Bet += evt.Bet
+ p.Cash -= evt.Bet
+ PokerPubSub.Pub(roomTopic, PlayerBetEvent{PlayerIdx: i, Player: p.Username, Bet: evt.Bet, TotalBet: p.Bet, Cash: p.Cash})
+ }
break
}
}
- // Transfer players bets into the main pot
- for i := range g.Ongoing.Players {
- if g.Ongoing.Players[i] != nil {
- g.Ongoing.MainPot += g.Ongoing.Players[i].Bet
- g.Ongoing.Players[i].Bet = 0
- }
+ // All settle when all players have the same bet amount
+ if isRoundSettled(g.Ongoing.Players) {
+ break
}
+ }
- evt := PokerWaitTurnEvent{Idx: -1, MainPot: g.Ongoing.MainPot}
- PokerPubSub.Pub(roomTopic, evt)
- g.Ongoing.WaitTurnEvent = evt
-
- return playerAlive == 1
+ // Transfer players bets into the main pot
+ for i := range g.Ongoing.Players {
+ if g.Ongoing.Players[i] != nil {
+ g.Ongoing.MainPot += g.Ongoing.Players[i].Bet
+ g.Ongoing.Players[i].Bet = 0
+ }
}
- type Seat struct {
- Top int
- Left int
- Angle string
- Top2 int
- Left2 int
+ evt := PokerWaitTurnEvent{Idx: -1, MainPot: g.Ongoing.MainPot}
+ PokerPubSub.Pub(roomTopic, evt)
+ g.Ongoing.WaitTurnEvent = evt
+
+ return playerAlive == 1
+ }
+
+ type Seat struct {
+ Top int
+ Left int
+ Angle string
+ Top2 int
+ Left2 int
+ }
+ seats := []Seat{
+ {Top: 50, Left: 600, Top2: 50 + 5, Left2: 600 + 5, Angle: "-90deg"},
+ {Top: 150, Left: 574, Top2: 150 + 5, Left2: 574 + 3, Angle: "-80deg"},
+ {Top: 250, Left: 530, Top2: 250 + 5, Left2: 530 + 1, Angle: "-70deg"},
+ }
+
+ var card string
+ idx := 0
+
+ burnCard := func(pos int) {
+ card = g.Ongoing.Deck[idx]
+ idx++
+ evt := PokerEvent{
+ ID: "card" + itoa(idx),
+ Name: "",
+ Idx: idx,
+ Top: BurnStackY + (pos * 2),
+ Left: BurnStackX + (pos * 4),
}
- seats := []Seat{
- {Top: 50, Left: 600, Top2: 50 + 5, Left2: 600 + 5, Angle: "-90deg"},
- {Top: 150, Left: 574, Top2: 150 + 5, Left2: 574 + 3, Angle: "-80deg"},
- {Top: 250, Left: 530, Top2: 250 + 5, Left2: 530 + 1, Angle: "-70deg"},
+ PokerPubSub.Pub(roomTopic, evt)
+ g.Ongoing.Events = append(g.Ongoing.Events, evt)
+ }
+
+ dealCard := func(pos int) {
+ card = g.Ongoing.Deck[idx]
+ idx++
+ evt := PokerEvent{
+ ID: "card" + itoa(idx),
+ Name: card,
+ Idx: idx,
+ Top: 150,
+ Left: 100 + (pos * 55),
+ Reveal: true,
}
+ PokerPubSub.Pub(roomTopic, evt)
+ g.Ongoing.Events = append(g.Ongoing.Events, evt)
+ }
- var card string
- idx := 0
+ deckHash := utils.MD5([]byte(strings.Join(g.Ongoing.Deck, "")))
+ PokerPubSub.Pub(roomTopic, GameStartedEvent{DeckHash: deckHash})
- burnCard := func(pos int) {
- card = g.Ongoing.Deck[idx]
- idx++
- evt := PokerEvent{
- ID: "card" + itoa(idx),
- Name: "",
- Idx: idx,
- Top: BurnStackY + (pos * 2),
- Left: BurnStackX + (pos * 4),
+ // Deal cards
+ for j := 1; j <= 2; j++ {
+ for i, p := range g.Ongoing.Players {
+ if p == nil {
+ continue
}
- PokerPubSub.Pub(roomTopic, evt)
- g.Ongoing.Events = append(g.Ongoing.Events, evt)
- }
-
- dealCard := func(pos int) {
+ if p.Cash == 0 {
+ continue
+ }
+ d := seats[i]
+ time.Sleep(time.Second)
card = g.Ongoing.Deck[idx]
idx++
+ name := ""
+ left := d.Left
+ top := d.Top
+ if j == 2 {
+ left = d.Left2
+ top = d.Top2
+ }
evt := PokerEvent{
- ID: "card" + itoa(idx),
- Name: card,
- Idx: idx,
- Top: 150,
- Left: 100 + (pos * 55),
- Reveal: true,
+ ID: "card" + itoa(idx),
+ Name: name,
+ Idx: idx,
+ Top: top,
+ Left: left,
+ Angle: d.Angle,
}
+ g.Ongoing.Players[i].Cards = append(g.Ongoing.Players[i].Cards, PlayerCard{Idx: idx, Name: card})
PokerPubSub.Pub(roomTopic, evt)
+ PokerPubSub.Pub(roomTopic+"_"+p.Username, YourCardEvent{Idx: j, Name: card})
g.Ongoing.Events = append(g.Ongoing.Events, evt)
}
+ }
- deckHash := utils.MD5([]byte(strings.Join(g.Ongoing.Deck, "")))
- PokerPubSub.Pub(roomTopic, GameStartedEvent{DeckHash: deckHash})
+ // Wait for players to bet/call/check/fold...
+ time.Sleep(time.Second)
+ if waitPlayersActionFn() {
+ goto END
+ }
- // Deal cards
- for j := 1; j <= 2; j++ {
- for i, p := range g.Ongoing.Players {
- if p == nil {
- continue
- }
- if p.Cash == 0 {
- continue
- }
- d := seats[i]
- time.Sleep(time.Second)
- card = g.Ongoing.Deck[idx]
- idx++
- name := ""
- left := d.Left
- top := d.Top
- if j == 2 {
- left = d.Left2
- top = d.Top2
- }
- evt := PokerEvent{
- ID: "card" + itoa(idx),
- Name: name,
- Idx: idx,
- Top: top,
- Left: left,
- Angle: d.Angle,
- }
- g.Ongoing.Players[i].Cards = append(g.Ongoing.Players[i].Cards, PlayerCard{Idx: idx, Name: card})
- PokerPubSub.Pub(roomTopic, evt)
- PokerPubSub.Pub(roomTopic+"_"+p.Username, YourCardEvent{Idx: j, Name: card})
- g.Ongoing.Events = append(g.Ongoing.Events, evt)
- }
- }
+ // Burn
+ time.Sleep(time.Second)
+ burnCard(0)
- // Wait for players to bet/call/check/fold...
+ // Flop (3 first cards)
+ for i := 1; i <= 3; i++ {
time.Sleep(time.Second)
- if waitPlayersActionFn() {
- goto END
- }
+ dealCard(i)
+ }
- // Burn
- time.Sleep(time.Second)
- burnCard(0)
+ // Wait for players to bet/call/check/fold...
+ time.Sleep(time.Second)
+ if waitPlayersActionFn() {
+ goto END
+ }
- // Flop (3 first cards)
- for i := 1; i <= 3; i++ {
- time.Sleep(time.Second)
- dealCard(i)
- }
+ // Burn
+ time.Sleep(time.Second)
+ burnCard(1)
- // Wait for players to bet/call/check/fold...
- time.Sleep(time.Second)
- if waitPlayersActionFn() {
- goto END
- }
+ // Turn (4th card)
+ time.Sleep(time.Second)
+ dealCard(4)
- // Burn
- time.Sleep(time.Second)
- burnCard(1)
+ // Wait for players to bet/call/check/fold...
+ time.Sleep(time.Second)
+ if waitPlayersActionFn() {
+ goto END
+ }
- // Turn (4th card)
- time.Sleep(time.Second)
- dealCard(4)
+ // Burn
+ time.Sleep(time.Second)
+ burnCard(2)
- // Wait for players to bet/call/check/fold...
- time.Sleep(time.Second)
- if waitPlayersActionFn() {
- goto END
- }
+ // River (5th card)
+ time.Sleep(time.Second)
+ dealCard(5)
- // Burn
- time.Sleep(time.Second)
- burnCard(2)
+ // Wait for players to bet/call/check/fold...
+ time.Sleep(time.Second)
+ if waitPlayersActionFn() {
+ goto END
+ }
- // River (5th card)
- time.Sleep(time.Second)
- dealCard(5)
+ // Show cards
+ for _, p := range g.Ongoing.Players {
+ if p != nil && !p.Folded {
+ fmt.Println(p.Username, p.Cards)
+ PokerPubSub.Pub(roomTopic, ShowCardsEvent{Cards: p.Cards})
+ }
+ }
- // Wait for players to bet/call/check/fold...
- time.Sleep(time.Second)
- if waitPlayersActionFn() {
- goto END
+END:
+
+ // TODO: evaluate hands, and crown winner
+ var winner *PokerPlayer
+ for _, p := range g.Ongoing.Players {
+ if p != nil {
+ winner = p
+ break
}
+ }
+ winner.Cash += g.Ongoing.MainPot
+ g.Ongoing.MainPot = 0
- // Show cards
- for _, p := range g.Ongoing.Players {
- if p != nil && !p.Folded {
- fmt.Println(p.Username, p.Cards)
- PokerPubSub.Pub(roomTopic, ShowCardsEvent{Cards: p.Cards})
- }
+ // Sync "ongoing players" with "room players" objects
+ for idx := range g.Players {
+ if g.Ongoing.Players[idx] != nil && g.Players[idx] != nil {
+ g.Players[idx].Cash = g.Ongoing.Players[idx].Cash
}
+ }
- END:
+ g.IsGameDone = true
+ PokerPubSub.Pub(roomTopic, GameIsDoneEvent{DeckStr: strings.Join(g.Ongoing.Deck, "")})
- // TODO: evaluate hands, and crown winner
- var winner *PokerPlayer
- for _, p := range g.Ongoing.Players {
- if p != nil {
- winner = p
- break
- }
- }
- winner.Cash += g.Ongoing.MainPot
- g.Ongoing.MainPot = 0
+ // Wait a minimum of X seconds before allowing a new game
+ time.Sleep(MinTimeAfterGame * time.Second)
+ g.IsGameOver = true
+ fmt.Println("GAME IS OVER")
+}
- // Sync "ongoing players" with "room players" objects
- for idx := range g.Players {
- if g.Ongoing.Players[idx] != nil && g.Players[idx] != nil {
- g.Players[idx].Cash = g.Ongoing.Players[idx].Cash
- }
+func (g *PokerGame) Deal(roomID string) {
+ roomTopic := "room_" + roomID
+
+ if g.Ongoing != nil {
+ if !g.IsGameOver {
+ fmt.Println("game already ongoing")
+ return
+ } else {
+ g.IsGameOver = false
+ PokerPubSub.Pub(roomTopic, ResetCardsEvent{})
+ time.Sleep(time.Second)
}
+ }
+ if g.CountSeated() < 2 {
+ fmt.Println("need at least 2 players")
+ return
+ }
- g.IsGameDone = true
- PokerPubSub.Pub(roomTopic, GameIsDoneEvent{DeckStr: strings.Join(g.Ongoing.Deck, "")})
+ g.Ongoing = NewOngoing(g)
- // Wait a minimum of X seconds before allowing a new game
- time.Sleep(MinTimeAfterGame * time.Second)
- g.IsGameOver = true
- fmt.Println("GAME IS OVER")
- }()
+ go dealerThread(g, roomID)
}
func (g *PokerGame) CountSeated() (count int) {