game_sync/gamerule/dezhoupoker/dezhouPokerCardScore.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)
}