711 lines
24 KiB
Go
711 lines
24 KiB
Go
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)
|
||
}
|
||
}
|