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) } }