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.
173 lines
4.5 KiB
173 lines
4.5 KiB
package game |
|
|
|
import ( |
|
"errors" |
|
"sync" |
|
"texas-poker-bk/api" |
|
"texas-poker-bk/tool/collect" |
|
) |
|
|
|
type Table struct { |
|
TableNo int32 // 牌桌编号 |
|
MasterId int64 // 房主Id |
|
RoundTimes int32 // 回合次数 |
|
Stage int32 // 游戏阶段: 1等待玩家准备;2游戏开始(自动扣大小盲注,发牌,轮流下注) [2(开始发牌)下大盲注;3下小盲注;4发公共牌;] 5发第四张公共牌,轮流下注;6发第五张公共牌,轮流下注,7比牌结算,9已解散 |
|
|
|
Chip int32 // 牌桌当前筹码 |
|
robotChip int32 // 牌桌当前机器人下注筹码 |
|
Dealer *Dealer // 发牌员 |
|
PublicCards [5]*Card // 公共牌 |
|
|
|
PlayerNum int32 // 玩家数 |
|
RobotNum int32 // 机器人数 |
|
Players []*Player // 玩家 |
|
Robots []*Robot |
|
BigBlindPos int // 大盲注位 |
|
SmallBlindPos int // 小盲注位 |
|
|
|
PlayersLock *sync.Mutex |
|
ChipLock *sync.Mutex // 桌面筹码更新锁 |
|
// TODO game logs7 |
|
} |
|
|
|
func (t *Table) PlayerCount() int32 { |
|
var count int32 = 0 |
|
for _, p := range t.Players { |
|
if p != nil { |
|
count++ |
|
} |
|
} |
|
return count |
|
} |
|
|
|
func (t *Table) NextPosPlayer(current int) int { |
|
for i := current + 1; i < len(t.Players); i++ { |
|
if t.Players[i] == nil { |
|
continue |
|
} |
|
return i |
|
} |
|
for i, p := range t.Players { |
|
if p != nil { |
|
return i |
|
} |
|
} |
|
return 0 |
|
} |
|
|
|
func (t *Table) FindPlayerPos(player *Player) int32 { |
|
for i, p := range t.Players { |
|
if p != nil && p.Id == player.Id { |
|
return int32(i) |
|
} |
|
} |
|
return -1 |
|
} |
|
|
|
func (t *Table) JoinPlayer(player *Player) error { |
|
t.PlayersLock.Lock() |
|
defer t.PlayersLock.Unlock() |
|
for i := range t.Players { |
|
// 找个空位坐下 |
|
if t.Players[i] == nil { |
|
t.Players[i] = player |
|
return nil |
|
} |
|
} |
|
return errors.New("牌桌玩家已满") |
|
} |
|
|
|
// BuildResGameFullStatus 构建牌桌当前游戏状态消息 |
|
func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus { |
|
resGame := &api.ResGameFullStatus{ |
|
InGame: collect.In(t.Stage, 2, 3, 4, 5, 6, 7), |
|
TableNo: t.TableNo, |
|
GameStage: t.Stage, |
|
Chip: t.Chip, |
|
RoundTimes: t.RoundTimes, |
|
BigBlindPos: int32(t.BigBlindPos), |
|
SmallBlindPos: int32(t.SmallBlindPos), |
|
} |
|
|
|
// 公共牌 |
|
resGame.PublicCard = make([]*api.Card, len(t.PublicCards)) |
|
for i, card := range t.PublicCards { |
|
if card == nil { |
|
resGame.PublicCard[i] = nil |
|
continue |
|
} |
|
resGame.PublicCard[i] = &api.Card{Dot: int32(card.Dot), Suit: CardColors[card.Suit]} |
|
} |
|
// 牌桌玩家 |
|
resGame.Players = make([]*api.TablePlayer, len(t.Players)) |
|
for i, p := range t.Players { |
|
if p == nil { |
|
resGame.Players[i] = nil |
|
continue |
|
} |
|
player := &api.TablePlayer{ |
|
Robot: false, |
|
Id: p.Id, |
|
Username: p.Username, |
|
Avatar: p.Avatar, |
|
Chip: p.Chip, |
|
Status: p.Status, |
|
LastStatus: p.LastStatus, |
|
Master: t.MasterId == p.Id, |
|
HandCard: make([]*api.Card, 2), |
|
} |
|
// 玩家手牌 |
|
for j, card := range p.Cards { |
|
if card == nil { |
|
player.HandCard[j] = nil |
|
continue |
|
} |
|
player.HandCard[j] = &api.Card{Dot: int32(card.Dot), Suit: CardColors[card.Suit]} |
|
} |
|
resGame.Players[i] = player |
|
} |
|
// TODO 机器人 |
|
|
|
return resGame |
|
} |
|
|
|
func (t *Table) NoticeGameFullStatus() { |
|
// 发送当前游戏状态消息到牌桌所有用户 |
|
for _, player := range t.Players { |
|
if player != nil && player.ProtoWriter != nil { |
|
resGame := t.BuildResGameFullStatus() |
|
resGame.PlayerId = player.Id |
|
// 只返回自己的手牌 TODO 结算时全部返回 |
|
for _, p := range resGame.Players { |
|
if p != nil && p.Id != player.Id { |
|
p.HandCard[0] = nil |
|
p.HandCard[1] = nil |
|
} |
|
} |
|
player.ProtoWriter.Write(resGame) |
|
} |
|
} |
|
} |
|
|
|
// NoticeGamePlayerCall TODO 发送(下注信息、下注人、下一位下注人)到牌桌所有用户 |
|
//func (t *Table) NoticeGamePlayerCall() { |
|
// |
|
//} |
|
|
|
type Stage int |
|
|
|
func (s *Stage) String() string { |
|
return stageNames[*s] |
|
} |
|
|
|
// 游戏阶段名称 |
|
var stageNames = []string{"Stage00WaitBegin", "Stage10Perflop", "Stage20Flop", "Stage30Turn", "Stage40River"} |
|
|
|
// 游戏阶段 |
|
const ( |
|
Stage00WaitBegin Stage = iota // 等待游戏开始 |
|
Stage10Perflop Stage = iota // 下大小盲注,然后没人发2张底牌,大盲注后面第一个玩家跟注、加注或放弃,依次顺时针表态 |
|
Stage20Flop Stage = iota // 发三张公牌,由小盲注开始顺时针表态 |
|
Stage30Turn Stage = iota // 发第四张公共牌,由小盲注开始顺时针表态 |
|
Stage40River Stage = iota // 发第五张牌,由小盲注开始顺时针表态,然后亮牌比大小 |
|
)
|
|
|