Browse Source

betting logic

master
tangmingyou 4 years ago
parent
commit
fb52115883
  1. 6
      api/poker.proto
  2. 35
      internal/game/player.go
  3. 151
      internal/game/table.go
  4. 167
      internal/service/table.go

6
api/poker.proto

@ -130,7 +130,6 @@ message ResGameFullStatus { // 玩家当前游戏状态: 断线,重新登录....
int32 tableNo = 2; // int32 tableNo = 2; //
int32 gameStage = 3; // int32 gameStage = 3; //
int32 chip = 4; // int32 chip = 4; //
int32 roundTimes = 5; //
int64 playerId = 6; // id int64 playerId = 6; // id
int32 bigBlindPos = 7; // int32 bigBlindPos = 7; //
int32 smallBlindPos = 8; // int32 smallBlindPos = 8; //
@ -204,3 +203,8 @@ message ResGameEndSettle {
message ResCalcWinnerChip { message ResCalcWinnerChip {
map<int64, int32> playersWinChip = 9; map<int64, int32> playersWinChip = 9;
} }
//
message ResGameNextRound {
int32 round = 1;
}

35
internal/game/player.go

@ -5,6 +5,10 @@ import (
"texas-poker-bk/internal/letter" "texas-poker-bk/internal/letter"
) )
var (
emptyOpts = make([]int32, 0)
)
// Player 游戏玩家 // Player 游戏玩家
type Player struct { type Player struct {
PosIndex int // 座位索引 PosIndex int // 座位索引
@ -15,7 +19,7 @@ type Player struct {
Cards [2]*Card // 手牌 Cards [2]*Card // 手牌
Chip int32 // 玩家筹码 Chip int32 // 玩家筹码
TotalBetChip int32 // 本次游戏已下注筹码 TotalBetChip int32 // 本次游戏已下注筹码
Status int32 // 状态: 1待准备开始,2已准备开始,3等待其他玩家动作,4第一回合小盲注跟注, [5待大盲注,5待小盲注,] 6待跟注,7已弃牌 Status int32 // 状态: 1待准备开始,2已准备开始,3等待其他玩家动作,[4第一回合小盲注跟注,5待大盲注,5待小盲注,] 6待跟注,7已弃牌
LastStatus int32 // 变化前一个状态 LastStatus int32 // 变化前一个状态
BetOpts []int32 // status=[4,6]时下注可操作按钮: 1跟注,2加注(-[0]+),3All-In,4弃牌,5过牌 BetOpts []int32 // status=[4,6]时下注可操作按钮: 1跟注,2加注(-[0]+),3All-In,4弃牌,5过牌
BetMin int32 // 最低下注额 BetMin int32 // 最低下注额
@ -39,18 +43,43 @@ func (p *Player) RoundInit() {
p.SetStatus(1) p.SetStatus(1)
p.BetMin = 0 p.BetMin = 0
p.BetMax = 0 p.BetMax = 0
p.BetOpts = make([]int32, 0) p.BetOpts = emptyOpts
p.TotalBetChip = 0 p.TotalBetChip = 0
p.Hand = nil p.Hand = nil
p.Cards[0] = nil p.Cards[0] = nil
p.Cards[1] = nil p.Cards[1] = nil
p.RoundInit() }
// WaitBet 将状态置为:3等待下注
func (p *Player) WaitBet() {
if p.Status == 7 {
return
}
p.SetStatus(3)
p.BetOpts = emptyOpts
p.BetMin = 0
p.BetMax = 0
} }
func (p *Player) SetStatus(status int32) { func (p *Player) SetStatus(status int32) {
p.StatusLock.Lock() p.StatusLock.Lock()
defer p.StatusLock.Unlock() defer p.StatusLock.Unlock()
switch status {
case 1:
fallthrough
case 2:
fallthrough
case 3: // 等待其他玩家
fallthrough
case 7: // 弃牌
p.BetMin = 0
p.BetMax = 0
if len(p.BetOpts) > 0 {
p.BetOpts = emptyOpts
}
}
p.LastStatus = p.Status p.LastStatus = p.Status
p.Status = status p.Status = status
} }

151
internal/game/table.go

@ -11,8 +11,8 @@ import (
type Table struct { type Table struct {
TableNo int32 // 牌桌编号 TableNo int32 // 牌桌编号
MasterId int64 // 房主Id MasterId int64 // 房主Id
RoundTimes int32 // 回合次数 GameTimes int32 // 游戏次数
Stage int32 // 游戏阶段: 1等待玩家准备;2游戏开始(自动扣大小盲注,发牌,轮流下注) [2(开始发牌)下大盲注;3下小盲注;4发公共牌;] 5发第四张公共牌,轮流下注;6发第五张公共牌,轮流下注,7比牌结算,9已解散 Stage int32 // 游戏阶段: 1等待玩家准备;2游戏开始(自动扣大小盲注,发手牌,轮流下注); 3:发3张公共牌 4:发第四张公共牌,轮流下注;5:发第五张公共牌,轮流下注,7比牌结算,9已解散
Chip int32 // 牌桌当前筹码 Chip int32 // 牌桌当前筹码
robotChip int32 // 牌桌当前机器人下注筹码 robotChip int32 // 牌桌当前机器人下注筹码
@ -33,8 +33,8 @@ type Table struct {
LastPosBetChip int32 // 上家下注金额 LastPosBetChip int32 // 上家下注金额
RoundRaiseTimes int32 // 该轮押注圈加注次数 RoundRaiseTimes int32 // 该轮押注圈加注次数
Lock *sync.Mutex // 牌桌锁
PlayersLock *sync.Mutex PlayersLock *sync.Mutex
ChipLock *sync.Mutex // 桌面筹码更新锁
// TODO game logs7 // TODO game logs7
} }
@ -43,8 +43,8 @@ func (t *Table) InitGameAndPlayerStatus() {
if t.PlayersLock == nil { if t.PlayersLock == nil {
t.PlayersLock = &sync.Mutex{} t.PlayersLock = &sync.Mutex{}
} }
if t.ChipLock == nil { if t.Lock == nil {
t.ChipLock = &sync.Mutex{} t.Lock = &sync.Mutex{}
} }
t.PublicCards = [5]*Card{nil, nil, nil, nil, nil} t.PublicCards = [5]*Card{nil, nil, nil, nil, nil}
if t.Dealer == nil { if t.Dealer == nil {
@ -92,8 +92,9 @@ func (t *Table) NextPlayerPos(current int) int {
// NextHoldingCardPlayerPos 下一个未弃牌玩家 // NextHoldingCardPlayerPos 下一个未弃牌玩家
func (t *Table) NextHoldingCardPlayerPos(current int) int { func (t *Table) NextHoldingCardPlayerPos(current int) int {
nextPos := current
for i := 0; i < 999; i++ { for i := 0; i < 999; i++ {
nextPos := t.NextPlayerPos(current) nextPos = t.NextPlayerPos(nextPos)
if nextPos == current { if nextPos == current {
return current return current
} }
@ -133,7 +134,6 @@ func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus {
TableNo: t.TableNo, TableNo: t.TableNo,
GameStage: t.Stage, GameStage: t.Stage,
Chip: t.Chip, Chip: t.Chip,
RoundTimes: t.RoundTimes,
BigBlindPos: int32(t.BigBlindPos), BigBlindPos: int32(t.BigBlindPos),
SmallBlindPos: int32(t.SmallBlindPos), SmallBlindPos: int32(t.SmallBlindPos),
} }
@ -172,7 +172,8 @@ func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus {
BetOpts: p.BetOpts, BetOpts: p.BetOpts,
}, },
} }
// 玩家手牌 // 未到结算时不展示其他玩家手牌
if !collect.In(t.Stage, 7, 9) {
for j, card := range p.Cards { for j, card := range p.Cards {
if card == nil { if card == nil {
player.HandCard[j] = nil player.HandCard[j] = nil
@ -180,6 +181,7 @@ func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus {
} }
player.HandCard[j] = &api.Card{Dot: int32(card.Dot), Suit: CardColors[card.Suit]} player.HandCard[j] = &api.Card{Dot: int32(card.Dot), Suit: CardColors[card.Suit]}
} }
}
resGame.Players[i] = player resGame.Players[i] = player
} }
return resGame return resGame
@ -215,37 +217,16 @@ func (t *Table) NoticeAllPlayer(message proto.Message) {
// RoundOver 当前回合结束 // RoundOver 当前回合结束
func (t *Table) RoundOver() error { func (t *Table) RoundOver() error {
// 游戏结束,开牌结算 // 游戏结束,开牌结算
if t.RoundTimes >= 4 || 1 == len(collect.Filter(t.Players, func(i int, p *Player) bool { if t.Stage == 5 || 1 == len(collect.Filter(t.Players, func(i int, p *Player) bool {
return p != nil && p.Status != 7 return p != nil && p.Status != 7
})) { })) {
return t.cardFightAndSettle() return t.cardFightAndSettle()
} }
// 开启下一回合, 重置一些状态 // 开启下一回合, 根据回合发公共牌
t.RoundRaiseTimes = 0 switch t.Stage {
t.RoundTimes++
for _, p := range t.Players {
if p != nil {
p.RoundBetTimes = 0
p.TotalBetChip = 0
p.BetMin = 0
p.BetMax = 0
p.BetOpts = []int32{}
p.SetStatus(3)
}
}
// 由小盲注或小盲注后第一个未弃牌玩家开始
nextBegin := t.SmallBlindPos
if t.Players[t.SmallBlindPos].Status == 7 {
nextBegin = t.NextHoldingCardPlayerPos(nextBegin)
}
begin := t.Players[nextBegin]
begin.SetStatus(6)
begin.BetOpts = []int32{1, 2, 4, 5}
// 根据回合发公共牌
switch t.RoundTimes {
case 2: // 发3张公共牌(翻牌) case 2: // 发3张公共牌(翻牌)
t.Stage = 3
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
if i < 3 { if i < 3 {
t.PublicCards[i] = t.Dealer.Deal() t.PublicCards[i] = t.Dealer.Deal()
@ -255,23 +236,115 @@ func (t *Table) RoundOver() error {
t.PublicCards[i] = nil t.PublicCards[i] = nil
} }
case 3: // 发第4张公共牌(转牌turn) case 3: // 发第4张公共牌(转牌turn)
t.Stage = 4
t.PublicCards[3] = t.Dealer.Deal() t.PublicCards[3] = t.Dealer.Deal()
t.Stage = 5
case 4: // 发第5张公共牌(河牌river) case 4: // 发第5张公共牌(河牌river)
t.Stage = 5
t.PublicCards[4] = t.Dealer.Deal() t.PublicCards[4] = t.Dealer.Deal()
t.Stage = 6
} }
// 重置一些状态
t.RoundRaiseTimes = 0
for _, p := range t.Players {
if p != nil {
p.RoundBetTimes = 0
p.WaitBet()
}
}
// 由小盲注或小盲注后第一个未弃牌玩家开始
nextPos := t.SmallBlindPos
if t.Players[t.SmallBlindPos].Status == 7 {
nextPos = t.NextHoldingCardPlayerPos(nextPos)
}
nextPlayer := t.Players[nextPos]
nextPlayer.SetStatus(6)
nextPlayer.BetOpts = []int32{1, 2, 4, 5}
return nil return nil
} }
// SetNextPlayerWithRoundStart 回合开始, 设置下一个下注玩家
func (t *Table) SetNextPlayerWithRoundStart() {
nextPos := t.SmallBlindPos
if t.Stage == 2 { // TODO 第一回合第一轮由大盲注后一个玩家下注
nextPos = t.NextPlayerPos(t.BigBlindPos)
}
if t.Players[nextPos].Status == 7 {
nextPos = t.NextHoldingCardPlayerPos(nextPos)
}
// 重置其他玩家状态为等待
for _, p := range t.Players {
if p == nil || p.Status == 7 {
continue
}
if p.PosIndex != nextPos {
p.WaitBet()
}
}
nextP := t.Players[nextPos]
nextP.SetStatus(6)
nextP.BetOpts = []int32{2, 4}
nextP.BetMin = t.BigBlindChip
switch t.TexasType {
case 2: // 底池限注
nextP.BetMax = t.Chip + t.LastPosBetChip*2
case 3: // 无限注
nextP.BetOpts = append(nextP.BetOpts, 3) // 可 all in
nextP.BetMax = -1
case 1: // 限注
fallthrough
default:
// 第1,2回合跟注加注需和大盲注相同, 3,4回合两倍
nextP.BetMax = t.BigBlindChip * (t.Stage/2 + 1)
}
// 如果下一玩家是大小盲注第一次下注
if t.Stage == 2 && nextP.RoundBetTimes == 0 {
switch nextP.PosIndex {
case t.SmallBlindPos:
nextP.BetMin -= t.SmallBlindChip
if t.TexasType != 3 {
nextP.BetMax -= t.SmallBlindChip
}
case t.BigBlindPos:
nextP.BetMin -= t.BigBlindChip
nextP.BetOpts = append(nextP.BetOpts, 5)
if t.TexasType != 3 {
nextP.BetMax -= t.BigBlindChip
}
}
}
}
// SetNextPlayer 查找下一个下注玩家, TODO 并计算最大最小下注额
func (t *Table) SetNextPlayer(current int) {
// 找下一个拿牌玩家
var nextPos = t.NextHoldingCardPlayerPos(current)
// 其他玩家状态等待
for _, p := range t.Players {
if p == nil || p.Status == 7 {
continue
}
if p.PosIndex != nextPos {
p.WaitBet()
}
}
nextP := t.Players[nextPos]
nextP.SetStatus(6)
// 最大最小下注额
nextP.BetMin = t.LastPosBetChip
}
// cardFightAndSettle 斗牌并结算 // cardFightAndSettle 斗牌并结算
func (t *Table) cardFightAndSettle() error { func (t *Table) cardFightAndSettle() error {
var winners []*Player = nil var winners []*Player = nil
leftPlayers := collect.Filter(t.Players, func(i int, p *Player) bool { leftPlayers := collect.Filter(t.Players, func(i int, p *Player) bool {
return p != nil && p.Status != 7 return p != nil && p.Status != 7
}) })
if t.Stage != 5 && 1 < len(leftPlayers) {
if t.RoundTimes < 4 && 1 < len(leftPlayers) {
return errors.New("未到最后一轮下注且由1一个以上玩家持有牌") return errors.New("未到最后一轮下注且由1一个以上玩家持有牌")
} }
t.Stage = 7 t.Stage = 7
@ -282,7 +355,7 @@ func (t *Table) cardFightAndSettle() error {
} else { } else {
// 剩余玩家大于1: 比牌 // 剩余玩家大于1: 比牌
for _, p := range t.Players { for _, p := range t.Players {
if p != nil { if p == nil {
continue continue
} }
hand, err := AnalyzeMaxHand(p.Cards, t.PublicCards) hand, err := AnalyzeMaxHand(p.Cards, t.PublicCards)
@ -337,7 +410,7 @@ func (t *Table) cardFightAndSettle() error {
// TODO 通知输赢金额 // TODO 通知输赢金额
// TODO 初始化牌桌及状态 // TODO 初始化牌桌及状态
t.InitGameAndPlayerStatus(); t.InitGameAndPlayerStatus()
go func() { go func() {
// TODO 等前端展示3秒钟后,牌桌回到初始状态,剔除掉线玩家 // TODO 等前端展示3秒钟后,牌桌回到初始状态,剔除掉线玩家

167
internal/service/table.go

@ -135,8 +135,8 @@ func HandleReqJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (pro
} }
table := store.LobbyTables[msg.TableNo] table := store.LobbyTables[msg.TableNo]
table.ChipLock.Lock() table.Lock.Lock()
defer table.ChipLock.Unlock() defer table.Lock.Unlock()
if table == nil { if table == nil {
return &api.ResFail{Msg: "牌桌不存在"}, nil return &api.ResFail{Msg: "牌桌不存在"}, nil
} }
@ -297,8 +297,8 @@ func HandleReqCancelReady(player *game.Player, msg *api.ReqCancelReady) (proto.M
// HandleReqDismissGameTable 解散牌桌 // HandleReqDismissGameTable 解散牌桌
func HandleReqDismissGameTable(player *game.Player, msg *api.ReqDismissGameTable) (proto.Message, error) { func HandleReqDismissGameTable(player *game.Player, msg *api.ReqDismissGameTable) (proto.Message, error) {
player.GameTable.ChipLock.Lock() player.GameTable.Lock.Lock()
defer player.GameTable.ChipLock.Unlock() defer player.GameTable.Lock.Unlock()
if player.GameTable.Stage != 1 { if player.GameTable.Stage != 1 {
return &api.ResFail{Msg: fmt.Sprintf("#%d,牌局进行中", player.GameTable.Stage)}, nil return &api.ResFail{Msg: fmt.Sprintf("#%d,牌局进行中", player.GameTable.Stage)}, nil
} }
@ -322,8 +322,8 @@ func HandleReqDismissGameTable(player *game.Player, msg *api.ReqDismissGameTable
// HandleReqGameStart 游戏开始,初始化,扣除大小盲注,每个玩家发2张牌 // HandleReqGameStart 游戏开始,初始化,扣除大小盲注,每个玩家发2张牌
func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Message, error) { func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Message, error) {
player.GameTable.ChipLock.Lock() player.GameTable.Lock.Lock()
defer player.GameTable.ChipLock.Unlock() defer player.GameTable.Lock.Unlock()
// 锁定牌桌所有玩家 // 锁定牌桌所有玩家
for _, p := range player.GameTable.Players { for _, p := range player.GameTable.Players {
if p != nil { if p != nil {
@ -349,7 +349,7 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa
// 游戏状态开始 // 游戏状态开始
table.Stage = 2 table.Stage = 2
// 小盲注位 // 小盲注位
if table.RoundTimes == 0 { if table.GameTimes == 0 {
// 第一轮由庄家左手边第一个作为小盲注 // 第一轮由庄家左手边第一个作为小盲注
table.SmallBlindPos = table.NextPlayerPos(0) table.SmallBlindPos = table.NextPlayerPos(0)
} else { } else {
@ -358,17 +358,18 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa
// 大盲注位 // 大盲注位
table.BigBlindPos = table.NextPlayerPos(table.SmallBlindPos) table.BigBlindPos = table.NextPlayerPos(table.SmallBlindPos)
// 回合数+1 // 回合数+1
table.RoundTimes++ table.GameTimes++
// 扣除大小盲注金额 // 扣除大小盲注金额
table.Players[table.SmallBlindPos].Chip -= table.SmallBlindChip table.Players[table.SmallBlindPos].Chip -= table.SmallBlindChip
table.Players[table.SmallBlindPos].TotalBetChip += table.SmallBlindChip table.Players[table.SmallBlindPos].TotalBetChip += table.SmallBlindChip
table.Players[table.BigBlindPos].Chip -= table.BigBlindChip table.Players[table.BigBlindPos].Chip -= table.BigBlindChip
table.Players[table.BigBlindPos].TotalBetChip += table.BigBlindChip table.Players[table.BigBlindPos].TotalBetChip += table.BigBlindChip
table.Chip += table.BigBlindChip + table.SmallBlindChip // 桌面筹码
table.Chip = table.BigBlindChip + table.SmallBlindChip
// 回合下注次数 // 回合下注次数
table.Players[table.BigBlindPos].RoundBetTimes++ // table.Players[table.BigBlindPos].RoundBetTimes++
// table.Players[table.SmallBlindPos].RoundBetTimes++ // table.Players[table.SmallBlindPos].RoundBetTimes++
// 初始上次下注金额为大盲注 // 初始上次下注金额为大盲注
@ -386,8 +387,6 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa
} }
table.NoticeAllPlayer(msgSmallBlind) table.NoticeAllPlayer(msgSmallBlind)
table.NoticeAllPlayer(msgBigBlind) table.NoticeAllPlayer(msgBigBlind)
//table.Players[table.BigBlindPos].ProtoWriter.Write(&api.ResBigBlindChip{Chip: game.BigBlindChip})
//table.Players[table.SmallBlindPos].ProtoWriter.Write(&api.ResSmallBlindChip{Chip: game.SmallBlinds})
// 开始发牌(手牌,公共牌) // 开始发牌(手牌,公共牌)
table.Dealer.Init() // 初始化发牌员 table.Dealer.Init() // 初始化发牌员
@ -405,47 +404,8 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa
// 待大盲注位下一位玩家下注 // 待大盲注位下一位玩家下注
optPos := table.NextPlayerPos(table.BigBlindPos) optPos := table.NextPlayerPos(table.BigBlindPos)
optPlayer := table.Players[optPos] optPlayer := table.Players[optPos]
optPlayer.SetStatus(4) optPlayer.SetStatus(3)
optPlayer.BetOpts = []int32{2, 4} optPlayer.BetOpts = []int32{2, 4}
optPlayer.BetMax = table.BigBlindChip
// 游戏类型处理最大下注额
switch table.TexasType {
case 2: // 底池限注
optPlayer.BetMax = table.Chip + table.LastPosBetChip*2
case 3: // 无限注
optPlayer.BetOpts = append(optPlayer.BetOpts, 3) // 可 all in
optPlayer.BetMax = -1
case 1: // 限注
fallthrough
default:
// 第1,2回合跟注加注需和大盲注相同, 3,4回合两倍
optPlayer.BetMax = table.BigBlindChip * 2
}
// 根据玩家类型计算最小下注额,最大下注额
switch optPos {
case table.SmallBlindPos:
optPlayer.BetMin = table.BigBlindChip - table.SmallBlindChip
if table.TexasType != 3 {
optPlayer.BetMax = optPlayer.BetMax - optPlayer.BetMin
}
case table.BigBlindPos:
optPlayer.BetMin = 0
optPlayer.BetOpts = append(optPlayer.BetOpts, 5)
if table.TexasType != 3 {
optPlayer.BetMax = optPlayer.BetMax - table.BigBlindChip
}
default:
optPlayer.BetMin = table.BigBlindChip
}
// 其他玩家暂不可操作
for pos, p := range table.Players {
if p != nil && pos != optPos {
p.Status = 3
p.BetOpts = make([]int32, 0)
p.BetMin = 0
p.BetMax = 0
}
}
// 广播牌桌状态 // 广播牌桌状态
table.NoticeGameFullStatus() table.NoticeGameFullStatus()
@ -467,10 +427,10 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa
func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message, error) { func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message, error) {
player.Lock.Lock() player.Lock.Lock()
defer player.Lock.Unlock() defer player.Lock.Unlock()
player.GameTable.ChipLock.Lock() player.GameTable.Lock.Lock()
defer player.GameTable.ChipLock.Unlock() defer player.GameTable.Lock.Unlock()
if !collect.In(player.Status, 4, 6) { if player.Status != 6 {
return &api.ResFail{Msg: "当前未轮到您下注"}, nil return &api.ResFail{Msg: "当前未轮到您下注"}, nil
} }
if !collect.In(msg.BetType, player.BetOpts...) { if !collect.In(msg.BetType, player.BetOpts...) {
@ -483,17 +443,19 @@ func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message,
table := player.GameTable table := player.GameTable
var raise bool // 是否加注 var raise bool // 是否加注
playerBettingChip := msg.BetChip // 当前玩家加注/跟注金额
betNotice := &api.ResNoticePlayerLine{PlayerId: player.Id} betNotice := &api.ResNoticePlayerLine{PlayerId: player.Id}
switch msg.BetType { switch msg.BetType {
case 1: // 跟注 case 1: // 跟注
if msg.BetChip != player.BetMin { if msg.BetChip > player.BetMin {
return &api.ResFail{Msg: fmt.Sprintf("投注大于应跟注金额#%d", player.BetMin)}, nil return &api.ResFail{Msg: fmt.Sprintf("投注大于应跟注金额#%d", player.BetMin)}, nil
} }
fallthrough fallthrough
case 2: // 加注 case 2: // 加注
if table.LastPosBetChip < 0 { //if table.LastPosBetChip < 0 {
return &api.ResFail{Msg: "您当前只能All-In或弃牌"}, nil // return &api.ResFail{Msg: "您当前只能All-In或弃牌"}, nil
} //}
if msg.BetChip < player.BetMin { if msg.BetChip < player.BetMin {
return &api.ResFail{Msg: fmt.Sprintf("小于当前最低投注额#%d", player.BetMin)}, nil return &api.ResFail{Msg: fmt.Sprintf("小于当前最低投注额#%d", player.BetMin)}, nil
} }
@ -504,15 +466,35 @@ func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message,
if table.TexasType == 1 && msg.BetChip > player.BetMin && table.RoundRaiseTimes >= 3 { if table.TexasType == 1 && msg.BetChip > player.BetMin && table.RoundRaiseTimes >= 3 {
return &api.ResFail{Msg: "该轮不可再加注"}, nil return &api.ResFail{Msg: "该轮不可再加注"}, nil
} }
// TODO 加注判断 if table.Stage == 2 && player.RoundBetTimes == 0 {
if msg.BetChip > table.LastPosBetChip { // 如果是第一圈第一次大小盲注玩家下注,下注额算加上盲注
switch player.PosIndex {
case table.SmallBlindPos:
playerBettingChip += table.SmallBlindChip
case table.BigBlindPos:
playerBettingChip += table.BigBlindChip
}
}
// 加注判断
raise = msg.BetChip > player.BetMin
if raise {
table.RoundRaiseTimes++ table.RoundRaiseTimes++
} }
player.RoundBetTimes++ player.RoundBetTimes++
raise = msg.BetChip > player.BetMin
table.LastPosBetChip = msg.BetChip table.LastPosBetChip = msg.BetChip
table.Chip += msg.BetChip table.Chip += msg.BetChip
player.Chip -= msg.BetChip player.Chip -= msg.BetChip
player.TotalBetChip += msg.BetChip
betNotice.Line1 = fmt.Sprintf("+%d", msg.BetChip)
if playerBettingChip == player.BetMin {
betNotice.Line2 = "跟注"
} else {
betNotice.Line2 = fmt.Sprintf("加注:%d", msg.BetChip-player.BetMin)
if player.BetMin > 0 {
betNotice.Line2 = fmt.Sprintf("跟注:%d", player.BetMin)
}
}
case 3: // All-In TODO 边池 case 3: // All-In TODO 边池
player.RoundBetTimes++ player.RoundBetTimes++
@ -520,12 +502,12 @@ func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message,
table.Chip += player.Chip table.Chip += player.Chip
player.Chip = 0 player.Chip = 0
table.LastPosBetChip = msg.BetChip table.LastPosBetChip = playerBettingChip
case 4: // 弃牌 case 4: // 弃牌
player.SetStatus(7) player.SetStatus(7)
betNotice.Line1 = "弃牌" betNotice.Line2 = "弃牌"
// 剩余牌手数为1则结束 // 剩余玩家数为1则结束
leftPlayers := collect.Filter(player.GameTable.Players, func(i int, p *game.Player) bool { leftPlayers := collect.Filter(player.GameTable.Players, func(i int, p *game.Player) bool {
return p != nil && p.Status != 7 return p != nil && p.Status != 7
}) })
@ -534,61 +516,57 @@ func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message,
if err != nil { if err != nil {
return &api.ResFail{Code: 500, Msg: err.Error()}, nil return &api.ResFail{Code: 500, Msg: err.Error()}, nil
} }
player.GameTable.NoticeAllPlayer(betNotice)
return &api.ResSuccess{}, nil return &api.ResSuccess{}, nil
} }
case 5: // 过牌 case 5: // 过牌
player.RoundBetTimes++ player.RoundBetTimes++
betNotice.Line1 = "过牌" betNotice.Line2 = "过牌"
default: default:
return &api.ResFail{Msg: fmt.Sprintf("未知操作#%d", msg.BetType)}, nil return &api.ResFail{Msg: fmt.Sprintf("未知操作#%d", msg.BetType)}, nil
} }
player.TotalBetChip += msg.BetChip
// 通知下注结果 // 通知下注结果
if betNotice.Line1 != "" { if betNotice.Line1 != "" || betNotice.Line2 != "" {
player.GameTable.NoticeAllPlayer(betNotice) player.GameTable.NoticeAllPlayer(betNotice)
} }
if player.Status != 7 {
player.SetStatus(3) player.SetStatus(3)
}
// 下注完成:若还有玩家未下注、加注,下一玩家继续下注;若该轮下注完成,发牌开启下一轮下注 // 下注完成:若还有玩家未下注、加注,下一玩家继续下注;若该轮下注完成,发牌开启下一轮下注
// 下一位玩家:跟注 // 下一位玩家:跟注
nextPlayerPos := table.NextHoldingCardPlayerPos(player.PosIndex) nextPlayerPos := table.NextHoldingCardPlayerPos(player.PosIndex)
nextPlayer := table.Players[nextPlayerPos] nextPlayer := table.Players[nextPlayerPos]
if nextPlayer.Id == player.Id { //if nextPlayer.Id == player.Id {
// 开启下一轮 // // 开启下一轮
err := table.RoundOver() // err := table.RoundOver()
if err != nil { // if err != nil {
return &api.ResFail{Code: 500, Msg: err.Error()}, nil // return &api.ResFail{Code: 500, Msg: err.Error()}, nil
} // }
return &api.ResSuccess{}, nil // return &api.ResSuccess{}, nil
} //}
if !raise { if !raise {
// 当前玩家未加注, 判断是否结束本轮下注 // 当前玩家未加注, 判断是否结束本轮下注
if nextPlayer.RoundBetTimes > 0 { if nextPlayer.RoundBetTimes == player.RoundBetTimes {
// 开启下一轮 // 开启下一轮
err := table.RoundOver() err := table.RoundOver()
if err != nil { if err != nil {
return &api.ResFail{Code: 500, Msg: err.Error()}, nil return &api.ResFail{Code: 500, Msg: err.Error()}, nil
} }
return &api.ResSuccess{}, nil
} }
} }
// 判断下一玩家是否需要再下注: 下一玩家是否已下注,当前玩家是否跟注,
// 判断该轮下一玩家可下注情况 : 下一玩家是否已下注,当前玩家是否跟注,
nextPlayer.SetStatus(6) nextPlayer.SetStatus(6)
nextPlayer.BetMin = msg.BetChip nextPlayer.BetMin = playerBettingChip
nextPlayer.BetOpts = []int32{1, 4} nextPlayer.BetOpts = []int32{1, 4}
// 下一玩家需跟注 // 下一玩家需跟注
// 如果当前玩家是小盲注第一次下注
if player.RoundBetTimes == 1 && table.SmallBlindPos == player.PosIndex {
nextPlayer.BetMin += table.SmallBlindChip
}
// 如果下一玩家是大盲注第一次下注
if nextPlayer.RoundBetTimes == 0 && table.BigBlindPos == nextPlayerPos {
nextPlayer.BetMin -= table.BigBlindChip
}
// 游戏类型处理最大下注额 // 游戏类型处理最大下注额
switch table.TexasType { switch table.TexasType {
case 2: // 底池限注 case 2: // 底池限注
@ -604,13 +582,24 @@ func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message,
if table.RoundRaiseTimes < 3 { if table.RoundRaiseTimes < 3 {
nextPlayer.BetOpts = append(nextPlayer.BetOpts, 3) nextPlayer.BetOpts = append(nextPlayer.BetOpts, 3)
// 第1,2回合跟注加注需和大盲注相同, 3,4回合两倍 // 第1,2回合跟注加注需和大盲注相同, 3,4回合两倍
nextPlayer.BetMax = table.BigBlindChip * ((table.RoundTimes+1)/2 + 1) nextPlayer.BetMax = table.BigBlindChip * (table.Stage/2 + 1)
} else { } else {
// 只能跟注 // 只能跟注
nextPlayer.BetMax = msg.BetChip nextPlayer.BetMax = playerBettingChip
} }
} }
// 如果下一玩家是大小盲注第一次下注
if table.Stage == 2 && nextPlayer.RoundBetTimes == 0 {
switch nextPlayer.PosIndex {
case table.SmallBlindPos:
nextPlayer.BetMin -= table.SmallBlindChip
nextPlayer.BetMax -= table.SmallBlindChip
case table.BigBlindPos:
nextPlayer.BetMin -= table.BigBlindChip
nextPlayer.BetMax -= table.BigBlindChip
}
}
// 依赌场规则而异, // 依赌场规则而异,
// 若所余筹码All-in后仍低于最低加注金额,则此注仅视为跟注(call)而不能被当成加注(raise),亦及该圈若未有其他人再加注,则原加注者(此例中的第一位牌手)仅可跟注补齐或盖牌,于此圈不可再行加注 // 若所余筹码All-in后仍低于最低加注金额,则此注仅视为跟注(call)而不能被当成加注(raise),亦及该圈若未有其他人再加注,则原加注者(此例中的第一位牌手)仅可跟注补齐或盖牌,于此圈不可再行加注
// 亦有少部分赌场规定All-in后大于最低加注额的一半以上,原加注者即可重新加注。 // 亦有少部分赌场规定All-in后大于最低加注额的一半以上,原加注者即可重新加注。

Loading…
Cancel
Save