You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
7.8 KiB
280 lines
7.8 KiB
package game |
|
|
|
import ( |
|
"errors" |
|
"fmt" |
|
"github.com/golang/protobuf/proto" |
|
"texas-poker-bk/api" |
|
"texas-poker-bk/tool/collect" |
|
) |
|
|
|
type PlayerBetting struct { |
|
betHandlers map[int32]func(player *Player, betChip int32) proto.Message |
|
|
|
SetNextPlayer func(roundStart bool, t *Table, current *Player) |
|
|
|
IsRoundOver func(current *Player, currentBetOp int32) bool |
|
} |
|
|
|
// GetBetHandler 获取下注类型对应 handler |
|
// betOp: 1跟注,2加注,3All-In,4弃牌,5过牌 |
|
func (betting *PlayerBetting) GetBetHandler(betOp int32) (func(player *Player, betChip int32) proto.Message, error) { |
|
handler := betting.betHandlers[betOp] |
|
if handler == nil { |
|
return nil, errors.New(fmt.Sprintf("未知操作#%d", betOp)) |
|
} |
|
return handler, nil |
|
} |
|
|
|
var ( |
|
LimitedBetting *PlayerBetting |
|
) |
|
|
|
// var LimitedActions map[int32]func(player *Player, betChip int32) proto.Message |
|
|
|
func init() { |
|
// 1跟注,2加注,3All-In,4弃牌,5过牌 |
|
LimitedActions := make(map[int32]func(player *Player, betChip int32) proto.Message, 7) |
|
LimitedActions[1] = Call4Limited |
|
LimitedActions[2] = Raise4Limited |
|
LimitedActions[3] = AllIn4Limited |
|
LimitedActions[4] = Fold4Limited |
|
LimitedActions[5] = Check4Limited |
|
LimitedBetting = &PlayerBetting{ |
|
betHandlers: LimitedActions, |
|
SetNextPlayer: SetNextPlayer4Limited, |
|
IsRoundOver: IsRoundOver4Limited, |
|
} |
|
|
|
} |
|
|
|
func Call4Limited(player *Player, betChip int32) proto.Message { |
|
if betChip > player.BetMin { |
|
return &api.ResFail{Msg: fmt.Sprintf("投注金额大于跟注金额:%d", player.BetMin)} |
|
} |
|
return Raise4Limited(player, betChip) |
|
} |
|
|
|
// Raise4Limited 限注加注处理 |
|
func Raise4Limited(player *Player, betChip int32) proto.Message { |
|
table := player.GameTable |
|
if betChip < player.BetMin { |
|
return &api.ResFail{Msg: fmt.Sprintf("小于当前最低投注额:%d", player.BetMin)} |
|
} |
|
if player.BetMax > 0 && betChip > player.BetMax { |
|
return &api.ResFail{Msg: fmt.Sprintf("大于当前最大投注额:%d", player.BetMax)} |
|
} |
|
// 限注式加注3次判断 |
|
if table.TexasType == 1 && betChip > player.BetMin && table.RoundRaiseTimes >= 3 { |
|
return &api.ResFail{Msg: "限加注3次,当前只能跟注"} |
|
} |
|
var raise bool // 是否加注 |
|
betNotice := &api.ResNoticePlayerLine{PlayerId: player.Id} |
|
|
|
//if table.Stage == 2 && player.RoundBetTimes == 0 { |
|
// // 如果是第一圈第一次大小盲注玩家下注,下注额算加上盲注 |
|
// switch player.PosIndex { |
|
// case table.SmallBlindPos: |
|
// playerBettingChip += table.SmallBlindChip |
|
// case table.BigBlindPos: |
|
// playerBettingChip += table.BigBlindChip |
|
// } |
|
//} |
|
// 加注判断 |
|
raise = betChip > player.BetMin |
|
if raise { |
|
table.RoundRaiseTimes++ |
|
table.LastPosBetOp = 2 |
|
} else { |
|
table.LastPosBetOp = 1 |
|
} |
|
player.RoundBetTimes++ |
|
table.LastPosBetChip = betChip |
|
table.Chip += betChip |
|
player.Chip -= betChip |
|
player.TotalBetChip += betChip |
|
|
|
betNotice.Line1 = fmt.Sprintf("+%d", betChip) |
|
if betChip == player.BetMin { |
|
betNotice.Line2 = fmt.Sprintf("跟注%d", player.BetMin) |
|
} else { |
|
betNotice.Line2 = fmt.Sprintf("加注:%d", betChip-player.BetMin) |
|
if player.BetMin > 0 { |
|
betNotice.Line3 = fmt.Sprintf("跟注:%d", player.BetMin) |
|
} |
|
} |
|
// 通知下注结果 |
|
table.NoticeAllPlayer(betNotice) |
|
|
|
return &api.ResSuccess{} |
|
} |
|
|
|
func AllIn4Limited(player *Player, betChip int32) proto.Message { |
|
return &api.ResFail{Msg: "限注牌桌不可AllIn"} |
|
} |
|
|
|
// Fold4Limited 弃牌限注局 |
|
func Fold4Limited(player *Player, betChip int32) proto.Message { |
|
table := player.GameTable |
|
table.LastPosBetOp = 4 |
|
table.LastPosBetChip = 0 |
|
|
|
betNotice := &api.ResNoticePlayerLine{PlayerId: player.Id} |
|
|
|
player.SetStatus(7) |
|
betNotice.Line2 = "弃牌" |
|
// 剩余玩家数为1则结束 |
|
leftPlayers := collect.Filter(player.GameTable.Players, func(i int, p *Player) bool { |
|
return p != nil && p.Status != 7 |
|
}) |
|
if len(leftPlayers) == 1 { |
|
err := table.RoundOver() |
|
if err != nil { |
|
return &api.ResFail{Code: 500, Msg: err.Error()} |
|
} |
|
player.GameTable.NoticeAllPlayer(betNotice) |
|
return &api.ResSuccess{} |
|
} |
|
player.GameTable.NoticeAllPlayer(betNotice) |
|
return nil |
|
} |
|
|
|
func Check4Limited(player *Player, betChip int32) proto.Message { |
|
table := player.GameTable |
|
table.LastPosBetOp = 5 |
|
table.LastPosBetChip = 0 |
|
betNotice := &api.ResNoticePlayerLine{PlayerId: player.Id} |
|
|
|
player.RoundBetTimes++ |
|
betNotice.Line2 = "过牌" |
|
|
|
// 第一轮只有未加注时大盲注可过牌,大盲注了不算只过牌 |
|
player.RoundCheckRaiseOnly = table.Stage != 2 |
|
|
|
player.GameTable.NoticeAllPlayer(betNotice) |
|
return nil |
|
} |
|
|
|
// IsRoundOver4Limited 判断回合是否结束 |
|
func IsRoundOver4Limited(current *Player, currentBetOp int32) bool { |
|
table := current.GameTable |
|
// 当前玩家弃牌, 判断剩余玩家数1结束 |
|
if currentBetOp == 4 { |
|
if 1 == len(table.HoldingCardPlayers()) { |
|
return true |
|
} |
|
} |
|
// 判断下注轮 和 下注金额 |
|
if collect.IsEmptyMap(table.RoundBetOps) || |
|
collect.IsEmptyMap(table.RoundBetChips) { |
|
return false |
|
} |
|
// 当前玩家加注, 继续 |
|
if currentBetOp == 2 { |
|
return false |
|
} |
|
var totalTemp int32 = -1 // 所有玩家投入相同筹码回合结束 |
|
for _, p := range table.Players { |
|
if p == nil || p.Status == 7 { |
|
continue |
|
} |
|
// 还有玩家未下注 |
|
if collect.IsEmptySlice(table.RoundBetOps[p.Id]) { |
|
return false |
|
} |
|
// 计算玩家下注额 |
|
if totalTemp == -1 { |
|
totalTemp = table.RoundBetTotal[p.Id] |
|
continue |
|
} |
|
if totalTemp != table.RoundBetTotal[p.Id] { |
|
return false |
|
} |
|
} |
|
|
|
// 判断当前玩家和下一玩家 回合是否结束 |
|
nextPlayerPos := table.NextHoldingCardPlayerPos(current.PosIndex) |
|
nextPlayer := table.Players[nextPlayerPos] |
|
if table.Stage == 2 && nextPlayerPos == table.BigBlindPos && |
|
len(table.RoundBetOps[nextPlayer.Id]) == 1 { // 大盲注玩家还下注一次 |
|
return false |
|
} |
|
//// 投注金额相同 |
|
//currentBetTotal := table.RoundBetTotal[current.Id] |
|
//if currentBetTotal == 0 { |
|
// if currentBetOp == 5 && // 当前玩家过牌且下一位玩家已过牌 |
|
// collect.Tail(table.RoundBetOps[nextPlayer.Id], 0) == 5 { |
|
// return true |
|
// } |
|
// |
|
//} else if table.RoundBetTotal[nextPlayer.Id] == currentBetTotal { |
|
// // 下一玩家已投入等量筹码 |
|
// return true |
|
//} |
|
|
|
//var total int32 = -1 |
|
//for uid, betTotal := range table.RoundBetTotal { |
|
// player := table.GetPlayerById(uid) |
|
// if player == nil || player.Status == 7 { |
|
// continue |
|
// } |
|
// if total == -1 { |
|
// total = betTotal |
|
// continue |
|
// } |
|
// if total != betTotal { |
|
// return false |
|
// } |
|
//} |
|
|
|
// TODO 判断剩余牌手All-In情况 |
|
return true |
|
} |
|
|
|
func SetNextPlayer4Limited(roundStart bool, t *Table, current *Player) { |
|
var nextPos int = t.SmallBlindPos |
|
if !roundStart { |
|
// 非回合开始 |
|
nextPos = t.NextHoldingCardPlayerPos(current.PosIndex) |
|
} else { |
|
// 回合开始 |
|
if t.Stage == 2 { // 第一轮由大盲注后一个玩家下注 |
|
nextPos = t.NextPlayerPos(t.BigBlindPos) |
|
|
|
} else 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{4} |
|
|
|
// 回合最大下注额 减 下一玩家总下注额 |
|
roundMaxBet := collect.Max(collect.MapValues(t.RoundBetTotal), 0) |
|
nextP.BetMin = roundMaxBet - t.RoundBetTotal[nextP.Id] |
|
// 第1,2回合跟注加注需和大盲注相同, 3,4回合两倍 |
|
nextP.BetMax = t.BigBlindChip * (t.Stage/2 + 1) |
|
if nextP.BetMin == 0 { // 过牌 |
|
nextP.BetOpts = append(nextP.BetOpts, 5) |
|
} else if nextP.BetMin > 0 { // 跟注 |
|
nextP.BetOpts = append(nextP.BetOpts, 1) |
|
} |
|
if nextP.BetMax > nextP.BetMin { // 加注 |
|
nextP.BetOpts = append(nextP.BetOpts, 2) |
|
} |
|
} |
|
|
|
func AllIn4NoLimited(player *Player, betChip int32) proto.Message { |
|
|
|
return nil |
|
}
|
|
|