samba/server/truco/room/trucoRobotEvaluation.go
2025-06-04 09:51:39 +08:00

711 lines
24 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package room
import (
"math/rand"
"samba/pkg/log"
"samba/proto"
"samba/server/game/baseroom"
"samba/server/truco/poker"
"samba/stub"
"samba/util/model"
"samba/util/util"
"sort"
"time"
)
// RobotEvaluation 带有评价函数的机器人
type RobotEvaluation struct {
*BaseRobot
unknownPokers []*poker.Poker // 未知的牌
knownPokers []*poker.Poker // 已知牌
lastRate int
}
func NewRobotEvaluation(cnf stub.RobotTemper, userInfo *model.UserInfo, seat *TrucoSeat, room *TrucoRoom) *RobotEvaluation {
return &RobotEvaluation{
BaseRobot: NewBaseRobot(cnf, userInfo, seat, room),
}
}
func (r *RobotEvaluation) OnMessage(msgId string, iMsg interface{}) {
switch msgId {
case proto.RspEnterRoomId:
r.NewTimer(baseroom.TtEnterRoom, time.Second*time.Duration(RobotOnMsgTime), func() {
r.sendReady(r.room)
})
case proto.NtfDealPokersId:
r.sortPokers()
msg := iMsg.(*proto.NtfDealPokers)
r.initUnknownAndKnownPokers(r.room, msg)
r.lastRate = 0
if util.RandHappened(50) {
break
}
r.NewSecretEmoteTimer(time.Second*time.Duration(rand.Int()%2+RobotOnMsgTime+3), func() {
r.sendSecretEmote(r.room, msg)
})
case proto.NtfDecidingGameId:
msg := iMsg.(*proto.NtfDecidingGame)
if TeamColor(msg.TeamColor) == r.room.teamColor(r.seat.No()) {
if r.lastRate == 0 {
r.lastRate = r.evaluation()
}
r.NewTimer(baseroom.TtDecidingGame, time.Second*time.Duration(rand.Int()%RobotOnMsgRandTime+RobotOnMsgTime), func() {
r.onDecidingAct(r.room, msg)
})
}
case proto.NtfPlayerActId:
msg := iMsg.(*proto.NtfPlayerAct)
if msg.Seat == r.seat.No() {
r.NewTimer(baseroom.TtPlayerAct, time.Second*time.Duration(rand.Int()%RobotOnMsgRandTime+RobotOnMsgTime), func() {
if r.lastRate == 0 {
r.lastRate = r.evaluation()
}
r.onPlayerAct(r.room, msg)
})
}
case proto.NtfPlayerOutPokerId:
r.updateUnknownAndKnownPokers(iMsg)
case proto.NtfPlayerRspRaiseId:
msg := iMsg.(*proto.NtfPlayerRspRaise)
if TeamColor(msg.TeamColor) != r.room.teamColor(r.seat.No()) {
return
}
r.NewTimer(baseroom.TtPlayerRspRaise, time.Second*time.Duration(rand.Int()%RobotOnMsgRandTime+RobotOnMsgTime), func() {
if r.lastRate == 0 {
r.lastRate = r.evaluation()
}
r.onRspRaise(r.room, msg)
})
case proto.NtfEmoteId:
r.onEmote(iMsg.(*proto.NtfEmote))
case proto.NtfRoundSettleId:
r.lastRate = 0
case proto.NtfUserDisbandRoomId:
msg := iMsg.(*proto.NtfUserDisbandRoom)
if len(msg.Agree) == r.room.SeatPlayerNum() {
r.GameClean()
}
case proto.NtfGameSettleId, proto.NtfMaintainId:
r.lastRate = 0
r.GameClean()
}
}
func (r *RobotEvaluation) outPokerRound1ByPos0(room *TrucoRoom, _ interface{}) *poker.Poker {
// 胜率大于50且手牌比队友大出最大牌否则出最小牌
if r.lastRate > stub.GGlobalAI.TrucoEvaluationOutPoker && r.handlePokerBiggerThenTeammate(room) {
return r.outMaxPoker(room)
} else {
return r.outMinPoker(room)
}
}
func (r *RobotEvaluation) outPokerRound1ByPos1(room *TrucoRoom, _ interface{}) *poker.Poker {
if r.room.IsMVM() {
if r.canBigger(room) {
return r.outMaxPoker(room)
} else {
return r.outMinPoker(room)
}
} else {
if r.canBigger(room) {
return r.outBiggerPoker(room)
} else {
return r.outMinPoker(room)
}
}
}
func (r *RobotEvaluation) outPokerRound1ByPos2(room *TrucoRoom, _ interface{}) *poker.Poker {
if bigger, big := r.teammateBigger(room); bigger {
if big {
return r.outMinPoker(room)
} else {
if r.canBigger(room) {
return r.outMaxPoker(room)
} else {
return r.outMinPoker(room)
}
}
} else {
if r.canBigger(room) {
return r.outMaxPoker(room)
} else {
return r.outMinPoker(room)
}
}
}
func (r *RobotEvaluation) outPokerRound1ByPos3(room *TrucoRoom, _ interface{}) *poker.Poker {
if bigger, _ := r.teammateBigger(room); bigger {
return r.outMinPoker(room)
} else {
if r.canBigger(room) {
return r.outBiggerPoker(room)
} else {
return r.outMinPoker(room)
}
}
}
func (r *RobotEvaluation) outPokerRound1(room *TrucoRoom, msg interface{}) {
var outPoker *poker.Poker
pos := r.positionInOutPoker(room)
if pos == 0 {
outPoker = r.outPokerRound1ByPos0(room, msg)
} else if pos == 1 {
outPoker = r.outPokerRound1ByPos1(room, msg)
} else if pos == 2 || pos == 4 {
outPoker = r.outPokerRound1ByPos2(room, msg)
} else {
outPoker = r.outPokerRound1ByPos3(room, msg)
}
if outPoker != nil {
req := &proto.ReqPlayerOutPoker{Poker: outPoker.ToInt()}
msg := util.MakeMessage(proto.ReqPlayerOutPokerId, req, r.UID, room.Id())
room.OnMessage(proto.ReqPlayerOutPokerId, msg)
} else {
log.Error(r.room.SeatLog(r.seat, "ai error"))
}
}
func (r *RobotEvaluation) outPokerRound2(room *TrucoRoom, _ interface{}) {
var outPoker *poker.Poker
pos := r.positionInOutPoker(room)
if pos == 0 {
// 第一位行动,要么平,要么胜
// 第一轮胜预估胜率大于50且手牌比队友大出最大手牌
if r.roundWinLose(room, 0) != poker.CppEqual {
if r.lastRate > stub.GGlobalAI.TrucoEvaluationOutPoker && r.handlePokerBiggerThenTeammate(room) {
outPoker = r.outMaxPoker(room)
} else {
outPoker = r.outMinPoker(room)
}
} else {
if r.handlePokerBiggerThenTeammate(room) {
outPoker = r.outMaxPoker(room)
} else {
outPoker = r.outMinPoker(room)
}
}
} else if pos == 1 {
if r.roundWinLose(room, 0) != poker.CppEqual {
outPoker = r.outMaxPoker(room)
} else {
if r.handlePokerBiggerThenTeammate(room) {
outPoker = r.outMaxPoker(room)
} else {
outPoker = r.outMinPoker(room)
}
}
//if r.canBigger(room) {
// outPoker = r.outMaxPoker(room)
//} else {
// outPoker = r.outMinPoker(room)
//}
} else if pos == 2 || pos == 4 {
if bigger, big := r.teammateBigger(room); bigger {
if big {
outPoker = r.outMinPoker(room)
} else {
if r.canBigger(room) {
outPoker = r.outMaxPoker(room)
} else {
outPoker = r.outMinPoker(room)
}
}
} else {
if r.canBigger(room) {
outPoker = r.outMaxPoker(room)
} else {
outPoker = r.outMinPoker(room)
}
}
} else {
if bigger, _ := r.teammateBigger(room); bigger {
outPoker = r.outMinPoker(room)
} else {
if r.canBigger(room) {
outPoker = r.outBiggerPoker(room)
} else {
outPoker = r.outMinPoker(room)
}
}
}
if outPoker != nil {
req := &proto.ReqPlayerOutPoker{Poker: outPoker.ToInt()}
msg := util.MakeMessage(proto.ReqPlayerOutPokerId, req, r.UID, room.Id())
room.OnMessage(proto.ReqPlayerOutPokerId, msg)
} else {
log.Error(r.room.SeatLog(r.seat, "ai error"))
}
}
func (r *RobotEvaluation) outPokerRound3(room *TrucoRoom, _ interface{}) {
if len(r.seat.Pokers) > 0 {
outPoker := r.seat.Pokers[0]
req := &proto.ReqPlayerOutPoker{Poker: outPoker.ToInt()}
msg := util.MakeMessage(proto.ReqPlayerOutPokerId, req, r.UID, room.Id())
room.OnMessage(proto.ReqPlayerOutPokerId, msg)
} else {
log.Error(r.room.SeatLog(r.seat, "ai error"))
}
}
func (r *RobotEvaluation) outPoker(room *TrucoRoom, msg interface{}) {
if r.getRound() == 0 {
r.outPokerRound1(room, msg)
} else if r.getRound() == 1 {
r.outPokerRound2(room, msg)
} else {
r.outPokerRound3(room, msg)
}
}
// 根据评估函数尝试叫,不叫分则出牌
func (r *RobotEvaluation) tryRaise(room *TrucoRoom, msg *proto.NtfPlayerAct) bool {
if !r.canRaise(msg) {
return false
}
if r.getRound() == 0 {
return r.tryRaiseRound0(room, msg)
} else if r.getRound() == 1 {
return r.tryRaiseRound1(room, msg)
} else {
return r.tryRaiseRound2(room, msg)
}
}
// 第1轮尝试叫分
func (r *RobotEvaluation) tryRaiseRound0(room *TrucoRoom, msg *proto.NtfPlayerAct) bool {
log.Debug(room.SeatLog(r.seat, "主动操作,概率:%v", r.lastRate))
// 预估胜率大于80或50主动喊truco
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound1_2 {
r.sendRaise(room, IntToActType(msg.CanCall), true)
return true
}
return false
}
// 第2轮尝试叫分
func (r *RobotEvaluation) tryRaiseRound1(room *TrucoRoom, msg *proto.NtfPlayerAct) bool {
log.Debug(room.SeatLog(r.seat, "主动操作,概率:%v", r.lastRate))
winRound0 := r.roundWinLose(room, 0)
if winRound0 == poker.CppEqual {
// 第一轮平,预估胜率>80或者50主动喊truco
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound2_2 {
r.sendRaise(room, IntToActType(msg.CanCall), true)
return true
}
} else if winRound0 == poker.CppBig {
// 第一轮胜,预估胜率>80或者50主动喊truco
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound2_3 {
r.sendRaise(room, IntToActType(msg.CanCall), true)
return true
}
} else {
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound2_4 {
r.sendRaise(room, IntToActType(msg.CanCall), true)
return true
}
return false
}
return false
}
// 第3轮尝试叫分
func (r *RobotEvaluation) tryRaiseRound2(room *TrucoRoom, msg *proto.NtfPlayerAct) bool {
log.Debug(room.SeatLog(r.seat, "主动操作,概率:%v", r.lastRate))
winRound0 := r.roundWinLose(room, 0)
winRound1 := r.roundWinLose(room, 1)
if winRound0 == poker.CppEqual && winRound1 == poker.CppEqual {
// 第两轮平平预估胜率50主动喊truco
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound3_1 {
r.sendRaise(room, IntToActType(msg.CanCall), true)
return true
}
} else if winRound0 == poker.CppBig && winRound1 == poker.CppSmall {
// 第两轮胜负预估胜率50主动喊truco
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound3_2 {
r.sendRaise(room, IntToActType(msg.CanCall), true)
return true
}
} else {
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound3_3 {
r.sendRaise(room, IntToActType(msg.CanCall), true)
return true
}
}
return false
}
func (r *RobotEvaluation) onPlayerAct(room *TrucoRoom, msg *proto.NtfPlayerAct) {
if !r.tryRaise(room, msg) {
r.outPoker(room, msg)
}
}
// 第一轮回应加注
func (r *RobotEvaluation) rspRaiseRound0(room *TrucoRoom, msg *proto.NtfPlayerRspRaise) {
log.Debug(room.SeatLog(r.seat, "回应操作,概率:%v", r.lastRate))
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound1_1 {
// 对面喊truco则能加注就加注不能加注就同意
if len(room.actTypes) <= 2 {
if msg.CanRaise > 0 {
r.sendRaise(room, IntToActType(msg.CanRaise), false)
} else {
r.sendRaise(room, AtAgree, false)
}
} else {
if rand.Int()%100 > 49 && msg.CanRaise > 0 {
r.sendRaise(room, IntToActType(msg.CanRaise), false)
} else {
r.sendRaise(room, AtAgree, false)
}
}
} else if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound1_2 {
r.sendRaise(room, AtAgree, false)
} else {
r.sendRaise(room, AtGiveUp, false)
}
}
// 第2轮回应加注
func (r *RobotEvaluation) rspRaiseRound1(room *TrucoRoom, msg *proto.NtfPlayerRspRaise) {
log.Debug(room.SeatLog(r.seat, "回应操作,概率:%v", r.lastRate))
winRound0 := r.roundWinLose(room, 0)
if winRound0 == poker.CppEqual {
// 第一轮平预估胜率大于80对面喊truco则能加注就加注不能加注就同意
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound2_1 {
if len(room.actTypes) <= 2 {
if msg.CanRaise > 0 {
r.sendRaise(room, IntToActType(msg.CanRaise), false)
} else {
r.sendRaise(room, AtAgree, false)
}
} else {
// 对面继续加注对面继续加注则能50%加注
if rand.Int()%100 > 49 && msg.CanRaise > 0 {
r.sendRaise(room, IntToActType(msg.CanRaise), false)
} else {
r.sendRaise(room, AtAgree, false)
}
}
} else if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound2_2 {
// 第一轮平预估胜率大于50对面喊truco则同意
r.sendRaise(room, AtAgree, false)
} else {
r.sendRaise(room, AtGiveUp, false)
}
} else if winRound0 == poker.CppBig {
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound2_3 {
// 第一轮胜预估胜率大于50对面喊truco则能加注就加注不能加注就同意
if len(room.actTypes) <= 2 {
if msg.CanRaise > 0 {
r.sendRaise(room, IntToActType(msg.CanRaise), false)
} else {
r.sendRaise(room, AtAgree, false)
}
} else {
// 第一轮胜预估胜率大于50对面继续加注则能50%加注
if rand.Int()%100 > 49 && msg.CanRaise > 0 {
r.sendRaise(room, IntToActType(msg.CanRaise), false)
} else {
r.sendRaise(room, AtAgree, false)
}
}
} else {
// 第一轮胜预估胜率低于50对面喊truco就放弃
r.sendRaise(room, AtGiveUp, false)
}
} else {
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound2_4 {
// 第一轮负预估胜率大于90对面喊truco则能加注就加注不能加注就同意
if msg.CanRaise > 0 {
r.sendRaise(room, IntToActType(msg.CanRaise), false)
} else {
r.sendRaise(room, AtAgree, false)
}
} else {
r.sendRaise(room, AtGiveUp, false)
}
}
}
// 第3轮回应加注
func (r *RobotEvaluation) rspRaiseRound2(room *TrucoRoom, _ *proto.NtfPlayerRspRaise) {
log.Debug(room.SeatLog(r.seat, "回应操作,概率:%v", r.lastRate))
winRound0 := r.roundWinLose(room, 0)
winRound1 := r.roundWinLose(room, 1)
if winRound0 == poker.CppEqual && winRound1 == poker.CppEqual {
// 前两轮平平预估胜率大于50主动喊truco对面喊truco则同意
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound3_1 {
r.sendRaise(room, AtAgree, false)
} else {
r.sendRaise(room, AtGiveUp, false)
}
} else if winRound0 == poker.CppBig && winRound1 == poker.CppSmall {
// 前两轮胜负预估胜率大于50主动喊truco对面喊truco则同意
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound3_2 {
r.sendRaise(room, AtAgree, false)
} else {
r.sendRaise(room, AtGiveUp, false)
}
} else {
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound3_4 {
// 前两轮负胜预估胜率大于50对面喊truco则同意
r.sendRaise(room, AtAgree, false)
} else {
r.sendRaise(room, AtGiveUp, false)
}
}
}
func (r *RobotEvaluation) onRspRaise(room *TrucoRoom, msg *proto.NtfPlayerRspRaise) {
if r.getRound() == 0 {
r.rspRaiseRound0(room, msg)
} else if r.getRound() == 1 {
r.rspRaiseRound1(room, msg)
} else {
r.rspRaiseRound2(room, msg)
}
}
// 初始化未知牌
func (r *RobotEvaluation) initUnknownAndKnownPokers(room *TrucoRoom, msg *proto.NtfDealPokers) {
r.unknownPokers = r.unknownPokers[:0]
r.knownPokers = r.knownPokers[:0]
for _, pk2 := range r.seat.Pokers {
r.knownPokers = append(r.knownPokers, pk2)
}
r.knownPokers = append(r.knownPokers, poker.NewPoker(msg.CuttingPoker))
for _, pk := range room.pokers.Pokers() {
exist := false
for _, pk2 := range r.knownPokers {
if pk.ToInt() == pk2.ToInt() {
exist = true
break
}
}
if !exist {
r.unknownPokers = append(r.unknownPokers, pk)
}
}
}
// 更新未知牌
func (r *RobotEvaluation) updateUnknownAndKnownPokers(iMsg interface{}) {
msg := iMsg.(*proto.NtfPlayerOutPoker)
if r.seat.No() == msg.CurrentSeat {
return
}
for pos, pk2 := range r.unknownPokers {
if msg.Poker == pk2.ToInt() {
r.knownPokers = append(r.knownPokers, pk2)
r.unknownPokers = append(r.unknownPokers[:pos], r.unknownPokers[pos+1:]...)
break
}
}
}
// 评估胜率函数
func (r *RobotEvaluation) evaluation() int {
if r.getRound() == 0 {
return r.evaluation0()
} else if r.getRound() == 1 {
return r.evaluation1()
} else {
return r.evaluation2()
}
}
func (r *RobotEvaluation) sortHandlePoker() []*poker.Poker {
var pks []*poker.Poker
if r.seat.OutPoker != nil {
pks = append(pks, r.seat.OutPoker)
}
pks = append(pks, r.seat.Pokers...)
if len(pks) <= 1 {
return pks
}
sort.Slice(pks, func(i, j int) bool {
return r.room.pokers.Cmp(pks[i], pks[j]) == poker.CppBig
})
return pks
}
func (r *RobotEvaluation) biggerInPokers(pk *poker.Poker, pokers []*poker.Poker) int {
debug := ""
num := 0
for _, pk2 := range pokers {
if r.room.pokers.Cmp(pk2, pk) == poker.CppBig {
num++
debug += " " + pk2.ToString()
}
}
log.Debug(r.room.SeatLog(r.seat, "比该牌:%v大的牌有:%v", pk.ToString(), debug))
return num
}
func (r *RobotEvaluation) biggerOrEqInPokers(pk *poker.Poker, pokers []*poker.Poker) int {
debug := ""
num := 0
for _, pk2 := range pokers {
if r.room.pokers.Cmp(pk2, pk) != poker.CppSmall {
num++
debug += " " + pk2.ToString()
}
}
log.Debug(r.room.SeatLog(r.seat, "比该牌:%v大的或相等的牌有:%v", pk.ToString(), debug))
return num
}
func (r *RobotEvaluation) smallInPokers(pk *poker.Poker, pokers []*poker.Poker) int {
num := 0
for _, pk2 := range pokers {
if r.room.pokers.Cmp(pk2, pk) == poker.CppSmall {
num++
}
}
return num
}
func (r *RobotEvaluation) evaluation0() int {
sortPks := r.sortHandlePoker()
// 预估胜率=1-未知牌中>=①的数量/未知牌数量)*[1-(未知牌中>=②的数量-1/(未知牌数量-1)]
factor := 10000
rate1 := int64(factor - factor*r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)/len(r.unknownPokers))
log.Debug(r.room.SeatLog(r.seat, "sortPks[0]=%v", sortPks[0].ToString()))
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)=%v", len(r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[0], r.unknownPokersSize)=%v", r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "rate1=%v", rate1))
rate2 := int64(factor - factor*(r.biggerOrEqInPokers(sortPks[1], r.unknownPokers)-1)/(len(r.unknownPokers)-1))
log.Debug(r.room.SeatLog(r.seat, "sortPks[1]=%v", sortPks[1].ToString()))
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)-1=%v", len(r.unknownPokers)-1))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[1], r.unknownPokersSize)-1=%v", r.biggerOrEqInPokers(sortPks[1], r.unknownPokers)-1))
log.Debug(r.room.SeatLog(r.seat, "rate2=%v", rate2))
rate := (rate1 * rate2) * 100 / int64(factor*factor)
if rate > 100 {
log.Error(r.room.SeatLog(r.seat, "概率错误.rate:%v", rate))
return 100
}
return int(rate)
}
func (r *RobotEvaluation) evaluation1() int {
sortPks := r.sortHandlePoker()
winRound0 := r.roundWinLose(r.room, 0)
//winRound1 := r.roundWinLose(room, 1)
if winRound0 == poker.CppEqual {
// 第一轮平时:胜率=1-未知牌中>=①的数量/未知牌数量
rate := r.biggerOrEqInPokers(sortPks[0], r.unknownPokers) * 100 / len(r.unknownPokers)
log.Debug(r.room.SeatLog(r.seat, "sortPks[0]=%v", sortPks[0].ToString()))
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)=%v", len(r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[0], r.unknownPokersSize)=%v", r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "rate=%v", rate))
if rate > 100 {
log.Error(r.room.SeatLog(r.seat, "概率错误.rate:%v", rate))
return 0
}
return 100 - rate
} else if winRound0 == poker.CppBig {
// 第一轮胜时:胜率=1-(未知牌中>=①的数量)*(未知牌中>=②的数量-1/[未知牌数量!/(未知牌数-2]
rate := int64(0)
if len(sortPks) < 2 {
log.Error(r.room.SeatLog(r.seat, "sortPks:%v size is less", poker.PokersToString(sortPks)))
rate = 0
} else {
rate = int64(r.biggerOrEqInPokers(sortPks[0], r.unknownPokers) * (r.biggerOrEqInPokers(sortPks[1], r.unknownPokers) - 1))
log.Debug(r.room.SeatLog(r.seat, "sortPks[0]=%v", sortPks[0].ToString()))
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)=%v", len(r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[0], r.unknownPokersSize)=%v", r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[1], r.unknownPokersSize) - 1)=%v", r.biggerOrEqInPokers(sortPks[1], r.unknownPokers)-1))
log.Debug(r.room.SeatLog(r.seat, "(未知牌中>=①的数量)*(未知牌中>=②的数量-1=%v", rate))
log.Debug(r.room.SeatLog(r.seat, " 未知牌数量!/(未知牌数-2=%v", int64(len(r.unknownPokers))*int64(len(r.unknownPokers)-1)))
}
//rate = rate * r.factorial(int64(len(r.unknownPokers)-2)) * 100
rate = rate * 100 / (int64(len(r.unknownPokers)) * int64(len(r.unknownPokers)-1))
log.Debug(r.room.SeatLog(r.seat, "胜率=1-(未知牌中>=①的数量)*(未知牌中>=②的数量-1/[未知牌数量!/(未知牌数-2]=%v", rate))
//log.Debug(r.room.SeatLog(r.seat, "r.factorial(int64(len(r.unknownPokersSize)-2))=%v", r.factorial(int64(len(r.unknownPokers)-2))))
//log.Debug(r.room.SeatLog(r.seat, "rate=%v", rate))
//rate = rate / r.factorial(int64(len(r.unknownPokers)))
//
//log.Debug(r.room.SeatLog(r.seat, "r.factorial(int64(len(r.unknownPokersSize)))=%v", r.factorial(int64(len(r.unknownPokers)))))
//log.Debug(r.room.SeatLog(r.seat, "rate=%v", rate))
if rate > 100 {
log.Error(r.room.SeatLog(r.seat, "概率错误.rate:%v", rate))
return 0
}
return 100 - int(rate)
} else {
// 第一轮负时:胜率=1-未知牌中>=①的数量/未知牌数量)*[1-(未知牌中>=②的数量-1/(未知牌数量-1)]
// 第一轮负时:胜率=1-未知牌中>=①的数量/未知牌数量)*[1-(未知牌中>=②的数量-1/(未知牌数量-1)]
factor := 10000
rate1 := int64(factor - factor*r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)/len(r.unknownPokers))
rate2 := int64(factor - factor*(r.biggerOrEqInPokers(sortPks[1], r.unknownPokers)-1)/(len(r.unknownPokers)-1))
rate := (rate1 * rate2) * 100 / int64(factor*factor)
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)=%v", len(r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[0], r.unknownPokersSize)=%v", r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[1], r.unknownPokersSize)-1=%v", r.biggerOrEqInPokers(sortPks[1], r.unknownPokers)-1))
if rate > 100 {
log.Error(r.room.SeatLog(r.seat, "概率错误.rate:%v", rate))
return 0
}
return int(rate)
}
}
func (r *RobotEvaluation) evaluation2() int {
sortPks := r.sortHandlePoker()
winRound0 := r.roundWinLose(r.room, 0)
winRound1 := r.roundWinLose(r.room, 1)
if winRound0 == poker.CppEqual && winRound1 == poker.CppEqual {
// 平平:胜率=1-未知牌中>=①的数量/未知牌数量
rate := r.biggerOrEqInPokers(sortPks[0], r.unknownPokers) * 100 / len(r.unknownPokers)
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)=%v", len(r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[0], r.unknownPokersSize)=%v", r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)))
return 100 - rate
} else if winRound0 == poker.CppBig {
// 胜负:胜率=1-未知牌中>①的数量/未知牌数量
rate := r.biggerInPokers(sortPks[0], r.unknownPokers) * 100 / len(r.unknownPokers)
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)=%v", len(r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerInPokers(sortPks[0], r.unknownPokersSize)=%v", r.biggerInPokers(sortPks[0], r.unknownPokers)))
return 100 - rate
} else {
// 胜率=1-未知牌中>=①的数量/未知牌数量
rate := r.biggerOrEqInPokers(sortPks[0], r.unknownPokers) * 100 / len(r.unknownPokers)
log.Debug(r.room.SeatLog(r.seat, "len(r.unknownPokersSize)=%v", len(r.unknownPokers)))
log.Debug(r.room.SeatLog(r.seat, "r.biggerOrEqInPokers(sortPks[0], r.unknownPokersSize)=%v", r.biggerOrEqInPokers(sortPks[0], r.unknownPokers)))
return 100 - rate
}
}
func (r *RobotEvaluation) onDecidingAct(room *TrucoRoom, _ *proto.NtfDecidingGame) {
log.Debug(room.SeatLog(r.seat, "决胜局主动操作,概率:%v", r.lastRate))
if r.lastRate > stub.GGlobalAI.TrucoEvaluationRaiseRound1_2 {
r.sendRaise(room, AtAgree, true)
} else {
r.sendRaise(room, AtGiveUp, true)
}
}