330 lines
8.8 KiB
Go
330 lines
8.8 KiB
Go
package dezhoupoker
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"mongo.games.com/algorithm"
|
|
)
|
|
|
|
var cardKindValue = make(map[int32]int32)
|
|
|
|
/*
|
|
散牌分值=散牌里单牌分值最大的分数
|
|
一对子分值=对子分值
|
|
二对分值=对子1分值+对子2分值+单张分值
|
|
三条分值=三张分值+两个单张分值
|
|
顺子分值=对应顺子分值
|
|
同花分值=对应同花分值
|
|
葫芦分值=(三张分值+对子分值)*2
|
|
四条分值=四张分值+单张分值
|
|
同花顺分值=同花顺分值
|
|
皇家同花顺=皇家同花顺分值
|
|
*/
|
|
func CalCardsKindScore(cardsInfo *CardsInfo) int32 {
|
|
switch cardsInfo.Kind {
|
|
case KindOfCard_RoyalFlush:
|
|
return CalScoreByKindAndCard(KindOfCard_RoyalFlush, cardsInfo.KindCards[4])
|
|
case KindOfCard_StraightFlush:
|
|
return CalScoreByKindAndCard(KindOfCard_StraightFlush, cardsInfo.KindCards[4])
|
|
case KindOfCard_FourKind:
|
|
return CalScoreByKindAndCard(KindOfCard_FourKind, cardsInfo.KindCards[0]) + CalScoreByKindAndCard(KindOfCard_HighCard, cardsInfo.KindCards[4])
|
|
case KindOfCard_Fullhouse:
|
|
return (CalScoreByKindAndCard(KindOfCard_ThreeKind, cardsInfo.KindCards[0]) + CalScoreByKindAndCard(KindOfCard_TwoPair, cardsInfo.KindCards[3])) * 2
|
|
case KindOfCard_Flush:
|
|
return CalScoreByKindAndCard(KindOfCard_Flush, cardsInfo.KindCards[0])
|
|
case KindOfCard_Straight:
|
|
return CalScoreByKindAndCard(KindOfCard_Straight, cardsInfo.KindCards[4])
|
|
case KindOfCard_ThreeKind:
|
|
return CalScoreByKindAndCard(KindOfCard_ThreeKind, cardsInfo.KindCards[0]) + CalScoreByKindAndCard(KindOfCard_HighCard, cardsInfo.KindCards[3]) + CalScoreByKindAndCard(KindOfCard_HighCard, cardsInfo.KindCards[4])
|
|
case KindOfCard_TwoPair:
|
|
return CalScoreByKindAndCard(KindOfCard_OnePair, cardsInfo.KindCards[0]) + CalScoreByKindAndCard(KindOfCard_OnePair, cardsInfo.KindCards[2]) + CalScoreByKindAndCard(KindOfCard_HighCard, cardsInfo.KindCards[4])
|
|
case KindOfCard_OnePair:
|
|
return CalScoreByKindAndCard(KindOfCard_OnePair, cardsInfo.KindCards[0])
|
|
case KindOfCard_HighCard:
|
|
return CalScoreByKindAndCard(KindOfCard_HighCard, cardsInfo.KindCards[0])
|
|
default:
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func MakeCardKindKey(kind int32, card int32) int32 {
|
|
return kind*10000 + card
|
|
}
|
|
|
|
func SetCardKindValue(key, value int32) {
|
|
cardKindValue[key] = value
|
|
}
|
|
|
|
func CalScoreByKindAndCard(kind int32, card int32) int32 {
|
|
if v, exist := cardKindValue[MakeCardKindKey(kind, card)]; exist {
|
|
return v
|
|
}
|
|
return 0
|
|
}
|
|
|
|
type PlayerCard struct {
|
|
HandCard []int32
|
|
UserData interface{}
|
|
WinningProbability int32
|
|
AllCardKind [KindOfCard_Max]int32
|
|
WinCardKind [KindOfCard_Max]int32
|
|
winTimes int32
|
|
CI *CardsInfo
|
|
}
|
|
|
|
type GameCtx struct {
|
|
PlayerCards []*PlayerCard
|
|
CommonCard []int32
|
|
RestCard []int32
|
|
CommonCardCnt int
|
|
Possibilities int
|
|
}
|
|
|
|
func (gctx *GameCtx) GetMaxKindOfCard() int32 {
|
|
maxKind := KindOfCard_HighCard
|
|
for _, pc := range gctx.PlayerCards {
|
|
if pc != nil && pc.CI != nil && pc.CI.Kind > maxKind {
|
|
maxKind = pc.CI.Kind
|
|
}
|
|
}
|
|
return maxKind
|
|
}
|
|
|
|
func (gctx *GameCtx) GetMaxCardInfo() *CardsInfo {
|
|
var max *CardsInfo
|
|
for _, pc := range gctx.PlayerCards {
|
|
if pc != nil && pc.CI != nil {
|
|
if max == nil {
|
|
max = pc.CI
|
|
} else if pc.CI.Value > max.Value {
|
|
max = pc.CI
|
|
}
|
|
}
|
|
}
|
|
return max
|
|
}
|
|
|
|
func CalWinningProbability(ctx *GameCtx) {
|
|
if ctx == nil {
|
|
return
|
|
}
|
|
|
|
possibilities := uint64(0)
|
|
max := int64(0)
|
|
maxIdx := make([]int, 0, len(ctx.PlayerCards))
|
|
oldCC := len(ctx.CommonCard)
|
|
m := 5 - oldCC
|
|
if m == 0 { //手牌和公牌全部确定
|
|
for k := 0; k < len(ctx.PlayerCards); k++ {
|
|
ctx.PlayerCards[k].CI = KindOfCardFigureUpSington.figureUp(ctx.PlayerCards[k].HandCard, ctx.CommonCard)
|
|
ctx.PlayerCards[k].CI.CalValue()
|
|
if ctx.PlayerCards[k].CI.Value > max {
|
|
max = ctx.PlayerCards[k].CI.Value
|
|
maxIdx = maxIdx[0:0]
|
|
maxIdx = append(maxIdx, k)
|
|
} else if ctx.PlayerCards[k].CI.Value == max {
|
|
maxIdx = append(maxIdx, k)
|
|
}
|
|
ctx.PlayerCards[k].AllCardKind[ctx.PlayerCards[k].CI.Kind]++
|
|
}
|
|
if len(maxIdx) != 0 {
|
|
for _, idx := range maxIdx {
|
|
ctx.PlayerCards[idx].winTimes++
|
|
ctx.PlayerCards[idx].WinCardKind[ctx.PlayerCards[idx].CI.Kind]++
|
|
}
|
|
}
|
|
|
|
possibilities = uint64(len(maxIdx))
|
|
} else { //计算各种组合的可能
|
|
//先填充够5张公牌的位置
|
|
for i := oldCC; i < 5; i++ {
|
|
ctx.CommonCard = append(ctx.CommonCard, -1)
|
|
}
|
|
|
|
n := len(ctx.RestCard)
|
|
atable := make([]int32, n)
|
|
for i := 0; i < n; i++ {
|
|
atable[i] = int32(i)
|
|
}
|
|
|
|
possibilities = algorithm.CombNumber(uint64(n), uint64(m))
|
|
if possibilities > 10000 {
|
|
possibilities = 10000
|
|
}
|
|
|
|
c := algorithm.CombinerSelectUseRecursion(atable, m)
|
|
if len(c) > int(possibilities) {
|
|
for i := 0; i < int(possibilities); i++ {
|
|
r := rand.Intn(len(c))
|
|
//设置公牌
|
|
for j := 0; j < len(c[r]); j++ {
|
|
ctx.CommonCard[oldCC+j] = ctx.RestCard[c[r][j]]
|
|
}
|
|
|
|
max = 0
|
|
maxIdx = maxIdx[0:0]
|
|
for k := 0; k < len(ctx.PlayerCards); k++ {
|
|
ctx.PlayerCards[k].CI = KindOfCardFigureUpSington.figureUp(ctx.PlayerCards[k].HandCard, ctx.CommonCard)
|
|
ctx.PlayerCards[k].CI.CalValue()
|
|
if ctx.PlayerCards[k].CI.Value > max {
|
|
max = ctx.PlayerCards[k].CI.Value
|
|
maxIdx = maxIdx[0:0]
|
|
maxIdx = append(maxIdx, k)
|
|
} else if ctx.PlayerCards[k].CI.Value == max {
|
|
maxIdx = append(maxIdx, k)
|
|
}
|
|
ctx.PlayerCards[k].AllCardKind[ctx.PlayerCards[k].CI.Kind]++
|
|
}
|
|
if len(maxIdx) != 0 {
|
|
for _, idx := range maxIdx {
|
|
ctx.PlayerCards[idx].winTimes++
|
|
ctx.PlayerCards[idx].WinCardKind[ctx.PlayerCards[idx].CI.Kind]++
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for i := 0; i < len(c); i++ {
|
|
//设置公牌
|
|
for j := 0; j < len(c[i]); j++ {
|
|
ctx.CommonCard[oldCC+j] = ctx.RestCard[c[i][j]]
|
|
}
|
|
|
|
max = 0
|
|
maxIdx = maxIdx[0:0]
|
|
for k := 0; k < len(ctx.PlayerCards); k++ {
|
|
ctx.PlayerCards[k].CI = KindOfCardFigureUpSington.figureUp(ctx.PlayerCards[k].HandCard, ctx.CommonCard)
|
|
ctx.PlayerCards[k].CI.CalValue()
|
|
if ctx.PlayerCards[k].CI.Value > max {
|
|
max = ctx.PlayerCards[k].CI.Value
|
|
maxIdx = maxIdx[0:0]
|
|
maxIdx = append(maxIdx, k)
|
|
} else if ctx.PlayerCards[k].CI.Value == max {
|
|
maxIdx = append(maxIdx, k)
|
|
}
|
|
ctx.PlayerCards[k].AllCardKind[ctx.PlayerCards[k].CI.Kind]++
|
|
}
|
|
if len(maxIdx) != 0 {
|
|
for _, idx := range maxIdx {
|
|
ctx.PlayerCards[idx].winTimes++
|
|
ctx.PlayerCards[idx].WinCardKind[ctx.PlayerCards[idx].CI.Kind]++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Printf("Common Card:")
|
|
if oldCC > 0 {
|
|
for i := 0; i < oldCC; i++ {
|
|
fmt.Printf("%s", Card(ctx.CommonCard[i]))
|
|
}
|
|
ci := KindOfCardFigureUpExSington.FigureUpByCard(ctx.CommonCard[:oldCC])
|
|
if ci != nil {
|
|
fmt.Printf(":%s", ci.KindStr())
|
|
}
|
|
}
|
|
fmt.Println()
|
|
|
|
ctx.Possibilities = int(possibilities)
|
|
for i := 0; i < len(ctx.PlayerCards); i++ {
|
|
ctx.PlayerCards[i].WinningProbability = int32(int64(ctx.PlayerCards[i].winTimes) * 10000 / int64(possibilities))
|
|
fmt.Printf("UserData<%#v> %s%s WinningProbability=%.2f%% \n", ctx.PlayerCards[i].UserData, Card(ctx.PlayerCards[i].HandCard[0]), Card(ctx.PlayerCards[i].HandCard[1]), float32(ctx.PlayerCards[i].WinningProbability)/100)
|
|
}
|
|
}
|
|
|
|
func PossibleKindOfCards(ctx *GameCtx) []int32 {
|
|
kinds := make([]int32, KindOfCard_Max)
|
|
if ctx == nil {
|
|
return kinds
|
|
}
|
|
|
|
if ctx.CommonCardCnt < 5 {
|
|
return kinds
|
|
}
|
|
|
|
n := len(ctx.RestCard)
|
|
atable := make([]int32, n)
|
|
for i := 0; i < n; i++ {
|
|
atable[i] = int32(i)
|
|
}
|
|
|
|
var handCard [2]int32
|
|
c := algorithm.CombinerSelectUseRecursion(atable, 2)
|
|
for i := 0; i < len(c); i++ {
|
|
//设置公牌
|
|
for j := 0; j < len(c[i]); j++ {
|
|
handCard[j] = ctx.RestCard[c[i][j]]
|
|
}
|
|
|
|
ci := KindOfCardFigureUpSington.figureUp(handCard[:], ctx.CommonCard)
|
|
if ci != nil {
|
|
kinds[ci.Kind]++
|
|
}
|
|
}
|
|
return kinds
|
|
}
|
|
|
|
func CaculKindOfCardCount(kinds []int32, expectKind []int32) (int32, int32) {
|
|
var cnt int32
|
|
for _, k := range expectKind {
|
|
cnt += kinds[k]
|
|
}
|
|
var total int32
|
|
for _, v := range kinds {
|
|
total += v
|
|
}
|
|
return total, cnt
|
|
}
|
|
|
|
func CaculGreaterKindOfCardCount(kinds []int32, cmpKind int32) (int32, int32) {
|
|
var cnt int32
|
|
var total int32
|
|
for k, v := range kinds {
|
|
total += v
|
|
if k >= int(cmpKind) {
|
|
cnt++
|
|
}
|
|
}
|
|
return total, cnt
|
|
}
|
|
|
|
func PossibleGreaterKindOfCards(ctx *GameCtx, cmpCI *CardsInfo) (int, int) {
|
|
if ctx == nil {
|
|
return 0, 1
|
|
}
|
|
|
|
if ctx.CommonCardCnt < 5 {
|
|
return 0, 1
|
|
}
|
|
|
|
if cmpCI == nil {
|
|
return 0, 1
|
|
}
|
|
|
|
n := len(ctx.RestCard)
|
|
atable := make([]int32, n)
|
|
for i := 0; i < n; i++ {
|
|
atable[i] = int32(i)
|
|
}
|
|
|
|
var cnt int
|
|
var handCard [2]int32
|
|
c := algorithm.CombinerSelectUseRecursion(atable, 2)
|
|
for i := 0; i < len(c); i++ {
|
|
//设置公牌
|
|
for j := 0; j < len(c[i]); j++ {
|
|
handCard[j] = ctx.RestCard[c[i][j]]
|
|
}
|
|
|
|
ci := KindOfCardFigureUpSington.figureUp(handCard[:], ctx.CommonCard)
|
|
if ci != nil {
|
|
ci.CalValue()
|
|
}
|
|
|
|
if ci.Value > cmpCI.Value {
|
|
cnt++
|
|
}
|
|
}
|
|
return cnt, len(c)
|
|
}
|