samba/server/truco/room/trucoRobotEvaluation.go

711 lines
24 KiB
Go
Raw Normal View History

2025-06-04 09:51:39 +08:00
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)
}
}