| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176 |
- package gamelogic
- import (
- "math/rand"
- "sort"
- "bet24.com/log"
- )
- type correction struct {
- correctCard int
- correctType int
- suggestCards []int
- }
- type fakerInfo struct {
- handCards []int // 手牌
- currentCard int // 当前轮次的出牌
- winCardScore int // 每一小局赢牌得分
- projects []SingleProject // 项目数据
- correctionList []correction // 玩家出牌对错表
- bigCards []int // 大牌
- cardTypesRecord []int // 按照人的思维记录玩家所有牌花色是否有打完
- outedCards []int // 玩家已出牌
- consecutiveWinCardCount int // 连续赢牌次数
- actionProb int // 机器人动作概率
- }
- // 初始化数据
- func (f *fakerInfo) initData() {
- f.handCards = []int{}
- f.winCardScore = 0
- f.currentCard = CARD_COUNT
- f.projects = []SingleProject{}
- f.correctionList = []correction{}
- f.bigCards = []int{}
- f.cardTypesRecord = make([]int, 4)
- f.outedCards = make([]int, NORMAL_HOLD_CARD)
- f.consecutiveWinCardCount = 0
- f.actionProb = 100
- }
- // 初始化先判定玩家每个花色的牌都是存在的
- func (f *fakerInfo) initCardTypesReccord() {
- for i := 0; i < CHAIR_COUNT; i++ {
- f.cardTypesRecord[i] = 1
- }
- }
- // 更新某个花色牌已经不存在
- func (f *fakerInfo) updataACardTypeToNotExist(cardType int) {
- if cardType >= CardType_Diamond && cardType <= CardType_Spade {
- f.cardTypesRecord[cardType] = 0
- }
- }
- // 分析手牌中的项目,并做保存
- func (f *fakerInfo) analysisProject(suit int) {
- cardList := make([]int, len(f.handCards))
- copy(cardList, f.handCards)
- projects := []SingleProject{}
- for i := PROJECT_FOURHUNDRED; i >= PROJECT_SIRA; i-- {
- if suit == Suit_Hokum && i == PROJECT_FOURHUNDRED {
- continue
- }
- for n := 0; n < 2; n++ {
- cards, bInclude := isIncludeTheProject(cardList, i, suit)
- if bInclude {
- cardList = removeCards(cardList, cards)
- projects = append(projects, SingleProject{
- Type: i,
- Score: value_project[i],
- Cards: cards,
- })
- }
- }
- }
- if len(projects) > 0 {
- f.projects = projects
- }
- }
- func (f *fakerInfo) isExistTheCardInOutedCards(card int) bool {
- for i := 0; i < len(f.outedCards); i++ {
- if f.outedCards[i] == card {
- return true
- }
- }
- return false
- }
- // 检查是否有baloot项目
- func (f *fakerInfo) haveBaloot(trumpType int) bool {
- haveTrumpQ := false
- haveTrumpK := false
- for i := 0; i < len(f.handCards); i++ {
- if f.handCards[i] == trumpType*8+CardValueQ {
- haveTrumpQ = true
- }
- if f.handCards[i] == trumpType*8+CardValueK {
- haveTrumpK = true
- }
- }
- return haveTrumpQ && haveTrumpK
- }
- // 从手牌中删除打出的牌,并记录每轮打出的牌
- func (f *fakerInfo) removeCard(card int) {
- for i := 0; i < len(f.handCards); i++ {
- if f.handCards[i] == card {
- f.handCards = append(f.handCards[:i], f.handCards[i+1:]...)
- f.currentCard = card
- f.outedCards = append(f.outedCards, card)
- break
- }
- }
- }
- // 每轮打完牌后初始化压牌列表
- func (f *fakerInfo) initBigCards(cards []int) {
- f.bigCards = []int{}
- if len(cards) > 0 {
- f.bigCards = append(f.bigCards, cards...)
- }
- }
- // 判断是否出的是压牌中的数据
- func (f *fakerInfo) isOutBigCards(card int) bool {
- if len(f.bigCards) == 0 {
- return true
- }
- for i := 0; i < len(f.bigCards); i++ {
- if card == f.bigCards[i] {
- return true
- }
- }
- return false
- }
- // 每轮赢牌分累加
- func (f *fakerInfo) addScore(score int) {
- f.winCardScore += score
- }
- // 获取项目得分
- func (f *fakerInfo) getProjectScore() int {
- score := 0
- for i := 0; i < len(f.projects); i++ {
- score += f.projects[i].Score
- }
- return score
- }
- // 在纠错模式下,检查玩家是否有不合法出牌
- func (f *fakerInfo) haveWrongAction() bool {
- if len(f.correctionList) == 0 {
- return false
- }
- for i := 0; i < len(f.correctionList); i++ {
- if f.correctionList[i].correctCard != -1 {
- return true
- }
- }
- return false
- }
- // 纠错数据校验
- func (f *fakerInfo) isWrongData(correctType int, cards []int) bool {
- wrongCard := CARD_COUNT
- for n := 0; n < len(cards); n++ {
- for i := 0; i < len(f.correctionList); i++ {
- if f.correctionList[i].correctCard == cards[n] && correctType == f.correctionList[i].correctType {
- wrongCard = cards[n]
- otherCard := CARD_COUNT
- for m := 0; m < len(cards); m++ {
- if cards[m] != wrongCard {
- otherCard = cards[m]
- break
- }
- }
- for j := 0; j < len(f.correctionList[i].suggestCards); j++ {
- if otherCard == f.correctionList[i].suggestCards[j] {
- return true
- }
- }
- }
- }
- }
- return false
- }
- func (f *fakerInfo) isExistTheCardTypeInHand(cardType int) bool {
- for i := 0; i < len(f.handCards); i++ {
- if getCardType(f.handCards[i]) == cardType {
- return true
- }
- }
- return false
- }
- type simulatorScene struct {
- suit int // 模式
- roundType int // 当前圈牌色
- trumpType int // 主牌花色,Sun或Ashkal模式下为CardType_Invalid
- buyChair int // 买牌位置
- baseTimes int // 加倍分
- isBO1 bool // 是否一把定胜负
- isClose bool // 为true表示本局在每一轮第一个出牌时不能出主牌(除了手上全是主牌的情况)
- lastWinChair int // 最后一轮赢牌玩家
- buyWinScore int // 买牌方赢分
- gameOutCardHistory []int // 本轮已出的牌
- fakers []fakerInfo // 玩家信息
- }
- func newSimulatorScene() *simulatorScene {
- ss := new(simulatorScene)
- ss.fakers = make([]fakerInfo, CHAIR_COUNT)
- for i := 0; i < CHAIR_COUNT; i++ {
- ss.fakers[i].initData()
- }
- ss.roundType = CardType_Invalid
- ss.gameOutCardHistory = []int{}
- ss.trumpType = CardType_Invalid
- ss.suit = Suit_Invalid
- ss.buyChair = CHAIR_COUNT
- ss.baseTimes = 1
- ss.isBO1 = false
- ss.lastWinChair = CHAIR_COUNT
- ss.buyWinScore = 0
- ss.isClose = false
- return ss
- }
- /******************************** 模拟场景流程的函数 START ********************************/
- // 初始化数据
- func (ss *simulatorScene) initData(trumpType, suit, buyChair, baseTimes int, isBo1, isClose bool) {
- ss.trumpType = trumpType
- ss.suit = suit
- ss.buyChair = buyChair
- ss.baseTimes = baseTimes
- ss.isBO1 = isBo1
- ss.isClose = isClose
- for i := 0; i < CHAIR_COUNT; i++ {
- ss.fakers[i].initCardTypesReccord()
- }
- }
- // 检查项目
- func (ss *simulatorScene) checkProject() {
- for i := 0; i < CHAIR_COUNT; i++ {
- ss.fakers[i].analysisProject(ss.suit)
- }
- }
- // 比较项目
- func (ss *simulatorScene) compareProject() {
- buyProject := []SingleProject{}
- playerProject := []SingleProject{}
- for i := 0; i < CHAIR_COUNT; i++ {
- if len(ss.fakers[i].projects) == 0 {
- continue
- }
- if isSameTeam(i, ss.buyChair) {
- buyProject = append(buyProject, ss.fakers[i].projects[0])
- } else {
- playerProject = append(playerProject, ss.fakers[i].projects[0])
- }
- }
- if len(buyProject) == 0 || len(playerProject) == 0 {
- return
- }
- // 从大到小排序
- sort.Slice(buyProject, func(i, j int) bool {
- return buyProject[i].isBiggerThan(buyProject[j])
- })
- sort.Slice(playerProject, func(i, j int) bool {
- return playerProject[i].isBiggerThan(playerProject[j])
- })
- isBuyTeamBig := buyProject[0].isBiggerThan(playerProject[0])
- for i := 0; i < CHAIR_COUNT; i++ {
- if len(ss.fakers[i].projects) == 0 {
- continue
- }
- if isSameTeam(i, ss.buyChair) {
- if !isBuyTeamBig {
- ss.fakers[i].projects = []SingleProject{}
- }
- } else {
- if isBuyTeamBig {
- ss.fakers[i].projects = []SingleProject{}
- }
- }
- }
- }
- // 获取已出牌玩家人数
- func (ss *simulatorScene) getRoundOutedPlayerCount() int {
- outedCount := 0
- for _, v := range ss.fakers {
- if v.currentCard != CARD_COUNT {
- outedCount++
- }
- }
- return outedCount
- }
- // 获取每轮出牌
- func (ss *simulatorScene) getRoundCards() []int {
- ret := make([]int, CHAIR_COUNT)
- for i := 0; i < CHAIR_COUNT; i++ {
- ret[i] = ss.fakers[i].currentCard
- }
- return ret
- }
- // 获取每轮出牌赢家
- func (ss *simulatorScene) getWinner(outCards []int, referType int) int {
- ranks := make([]int, CHAIR_COUNT)
- winner := -1
- bestRank := -2
- for i := 0; i < CHAIR_COUNT; i++ {
- ranks[i] = ss.getCardRank(outCards[i], referType)
- if ranks[i] > bestRank {
- bestRank = ranks[i]
- winner = i
- }
- }
- return winner
- }
- // 判断每轮是否出牌结束
- func (ss *simulatorScene) isRoundEnd() bool {
- return ss.getRoundOutedPlayerCount() == CHAIR_COUNT
- }
- func (ss *simulatorScene) haveWrongAction(correctMode, sawaChair int) bool {
- if correctMode == Correct_Sawa {
- for n := 0; n < CHAIR_COUNT; n++ {
- if n == sawaChair {
- continue
- }
- for i := 0; i < len(ss.fakers[sawaChair].handCards); i++ {
- card := ss.fakers[sawaChair].handCards[i]
- if !ss.isBiggerThanAll(card, getCardType(card), ss.fakers[n].handCards) {
- return true
- }
- }
- }
- return false
- }
- for i := 0; i < CHAIR_COUNT; i++ {
- if ss.fakers[i].haveWrongAction() {
- return true
- }
- }
- return false
- }
- func (ss *simulatorScene) checkWrongActionInSawa(sawaChair int, cards []int) int {
- sawaCount := 0
- sawaCard := CARD_COUNT
- otherCard := CARD_COUNT
- for i := 0; i < len(cards); i++ {
- for n := 0; n < len(ss.fakers[sawaChair].handCards); n++ {
- if cards[i] == ss.fakers[sawaChair].handCards[n] {
- sawaCount++
- sawaCard = cards[i]
- break
- }
- }
- }
- if sawaCount != 1 {
- return 0
- }
- for i := 0; i < len(cards); i++ {
- if sawaCard != cards[i] {
- otherCard = cards[i]
- break
- }
- }
- for i := 0; i < CHAIR_COUNT; i++ {
- if i == sawaChair {
- continue
- }
- for n := 0; n < len(ss.fakers[i].handCards); n++ {
- if otherCard == ss.fakers[i].handCards[n] {
- if ss.getCardRank(sawaCard, getCardType(sawaCard)) < ss.getCardRank(otherCard, getCardType(sawaCard)) {
- return 1
- } else {
- return 0
- }
- }
- }
- }
- return 0
- }
- func (ss *simulatorScene) checkWrongActionInNormal(whose, correctType int, cards []int) int {
- wrongChair := CHAIR_COUNT
- for i := 0; i < CHAIR_COUNT; i++ {
- if !ss.fakers[i].haveWrongAction() {
- continue
- }
- if ss.fakers[i].isWrongData(correctType, cards) {
- wrongChair = i
- break
- }
- }
- if !isValidChair(wrongChair) {
- return 0
- }
- if !isSameTeam(wrongChair, whose) {
- return 1
- }
- return 0
- }
- // 每一轮结束,计算得分和赢家
- func (ss *simulatorScene) endAOutCardRound(winner int) {
- winScore := 0
- for i := 0; i < CHAIR_COUNT; i++ {
- score := getCardPoint(ss.fakers[i].currentCard, ss.trumpType)
- winScore += score
- ss.gameOutCardHistory = append(ss.gameOutCardHistory, ss.fakers[i].currentCard)
- ss.fakers[i].currentCard = CARD_COUNT
- ss.fakers[i].initBigCards([]int{})
- }
- for i := 0; i < CHAIR_COUNT; i++ {
- if i == winner {
- ss.fakers[i].addScore(winScore)
- }
- }
- ss.roundType = CardType_Invalid
- ss.lastWinChair = winner
- }
- // 是否小局结束
- func (ss *simulatorScene) isGameEnd() bool {
- for _, v := range ss.fakers {
- if len(v.handCards) > 0 {
- return false
- }
- }
- return true
- }
- // 获取必压的大牌
- func (ss *simulatorScene) getCanOutCards(chairId int, isFriendCallBiggest bool) []int {
- bigCards := []int{}
- ss.fakers[chairId].bigCards = []int{}
- // 1.我方队友出大牌
- // 2.不打有主模式
- // 3.玩家第一个出牌
- // 以上不去限制玩家出牌
- if isFriendCallBiggest || ss.suit != Suit_Hokum || ss.roundType == CardType_Invalid {
- return bigCards
- }
- // 4.队友目前赢牌 不去限制玩家出牌
- winner := ss.getWinner(ss.getRoundCards(), ss.roundType)
- if isSameTeam(chairId, winner) {
- return bigCards
- }
- // 5.敌方目前赢牌,这轮出牌的roundType为副牌,当前玩家手上还有相同花色的牌,不去限制玩家出牌
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- if ss.roundType != ss.trumpType && len(sortedCards[ss.roundType]) > 0 {
- return bigCards
- }
- biggestCard := ss.fakers[winner].currentCard
- r := ss.getCardRank(biggestCard, ss.roundType)
- for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
- r1 := ss.getCardRank(ss.fakers[chairId].handCards[i], ss.roundType)
- if r1 > r {
- bigCards = append(bigCards, ss.fakers[chairId].handCards[i])
- }
- }
- return bigCards
- }
- // 模拟结算,看买牌输赢
- func (ss *simulatorScene) calcBuyWinScore() {
- buyPoint := 0
- playerPoint := 0
- buyWinCardScore := 0
- playerWinCardScore := 0
- for i := 0; i < CHAIR_COUNT; i++ {
- if isSameTeam(i, ss.buyChair) {
- buyPoint += ss.fakers[i].getProjectScore()
- buyPoint += ss.fakers[i].winCardScore
- buyWinCardScore += ss.fakers[i].winCardScore
- } else {
- playerPoint += ss.fakers[i].getProjectScore()
- playerPoint += ss.fakers[i].winCardScore
- playerWinCardScore += ss.fakers[i].winCardScore
- }
- }
- ss.fakers[ss.lastWinChair].winCardScore += LAST_WIN_SCORE
- if isSameTeam(ss.buyChair, ss.lastWinChair) {
- buyPoint += LAST_WIN_SCORE
- buyWinCardScore += LAST_WIN_SCORE
- } else {
- playerPoint += LAST_WIN_SCORE
- playerWinCardScore += LAST_WIN_SCORE
- }
- playerAbnat := playerPoint
- // 如果买的一方输的情况
- if (buyPoint == playerPoint && (ss.baseTimes > 1 || ss.isBO1)) || buyPoint < playerPoint {
- playerPoint += buyPoint
- if ss.fakers[ss.buyChair].winCardScore == 0 {
- playerPoint += ALL_WIN_EXTRA_SCORE
- }
- buyPoint = 0
- } else {
- if ss.fakers[getNextChair(ss.buyChair)].winCardScore == 0 {
- buyPoint += ALL_WIN_EXTRA_SCORE
- playerPoint = 0
- }
- if ss.isBO1 || ss.baseTimes > 1 {
- buyPoint += playerAbnat
- playerPoint = 0
- }
- }
- finalBuyPoint := calcFinalPonit(buyPoint)
- finalPlayerPoint := calcFinalPonit(playerPoint)
- if ss.suit != Suit_Hokum {
- finalBuyPoint *= 2
- finalPlayerPoint *= 2
- if buyWinCardScore%10 == 5 && playerWinCardScore%10 == 5 && buyPoint > 0 && playerPoint > 0 {
- finalBuyPoint++
- finalPlayerPoint++
- }
- } else {
- if buyWinCardScore%10 == 6 && playerWinCardScore%10 == 6 && buyPoint > 0 && playerPoint > 0 {
- finalPlayerPoint--
- }
- }
- finalBuyPoint *= ss.baseTimes
- finalPlayerPoint *= ss.baseTimes
- if ss.isBO1 {
- if finalBuyPoint > finalPlayerPoint {
- finalBuyPoint = SCORE_TO_WIN
- finalPlayerPoint = 0
- } else {
- finalBuyPoint = 0
- finalPlayerPoint = SCORE_TO_WIN
- }
- }
- ss.buyWinScore = finalBuyPoint - finalPlayerPoint
- }
- func (ss *simulatorScene) isWinScoreBigThanFriend() bool {
- return (ss.fakers[ss.buyChair].winCardScore - ss.fakers[getFriendChair(ss.buyChair)].winCardScore) >= 40
- }
- func (ss *simulatorScene) calcProject() {
- ss.checkProject()
- ss.compareProject()
- if ss.suit == Suit_Hokum {
- for i := 0; i < CHAIR_COUNT; i++ {
- if ss.fakers[i].haveBaloot(ss.trumpType) {
- ss.fakers[i].projects = append(ss.fakers[i].projects, SingleProject{
- Type: PROJECT_BALOOT,
- Score: value_project[PROJECT_BALOOT],
- Cards: []int{genACard(ss.trumpType, CardValueQ), genACard(ss.trumpType, CardValueK)},
- })
- break
- }
- }
- }
- }
- // 开始模拟出牌场景,得出最终得分,走的机器人出牌策略
- func (ss *simulatorScene) startSimulatorScene(startChair int, isQuickOrLadder bool) {
- ss.calcProject()
- outCardChair := startChair
- for {
- outCard := ss.getBestOutCard(outCardChair, isQuickOrLadder)
- if !isValidCard(outCard) {
- ss.dump(outCardChair)
- if len(ss.fakers[outCardChair].bigCards) > 0 {
- outCard = ss.fakers[outCardChair].bigCards[0]
- } else {
- outCard = ss.worstCard(outCardChair)
- }
- }
- if !isValidCard(outCard) {
- return
- }
- ss.fakers[outCardChair].removeCard(outCard)
- if ss.roundType != CardType_Invalid && getCardType(outCard) != ss.roundType {
- ss.fakers[outCardChair].updataACardTypeToNotExist(ss.roundType)
- }
- if ss.roundType == CardType_Invalid {
- ss.roundType = getCardType(outCard)
- }
- if ss.isRoundEnd() {
- outCards := ss.getRoundCards()
- winner := ss.getWinner(outCards, ss.roundType)
- ss.endAOutCardRound(winner)
- outCardChair = winner
- } else {
- outCardChair = getPreviousChair(outCardChair)
- isFriendCallBiggest := false
- if ss.suit == Suit_Hokum && ss.getRoundOutedPlayerCount() == 2 {
- card := ss.fakers[getFriendChair(outCardChair)].currentCard
- if isValidCard(card) && getCardType(card) != ss.trumpType {
- if !isBiggestCard(card, ss.trumpType) {
- if isScoreCard(card, []int{}, ss.gameOutCardHistory, ss.trumpType) {
- isFriendCallBiggest = true
- }
- } else {
- isFriendCallBiggest = true
- }
- }
- }
- bigCards := ss.getCanOutCards(outCardChair, isFriendCallBiggest)
- ss.fakers[outCardChair].initBigCards(bigCards)
- }
- if ss.isGameEnd() {
- break
- }
- }
- ss.calcBuyWinScore()
- }
- /******************************** 模拟场景流程的函数 END ********************************/
- /******************************** 辅助计算函数 START ********************************/
- func (ss *simulatorScene) getCardRank(card int, referType int) int {
- if !isValidCard(card) {
- return -2
- }
- cardType := getCardType(card)
- cardScore := 0
- if cardType == ss.trumpType {
- cardScore += 100
- } else if cardType != referType {
- return -1
- }
- value := getCardCompareValue(card, ss.trumpType)
- return cardScore + value
- }
- func (ss *simulatorScene) worstCard(chairId int) int {
- if len(ss.fakers[chairId].handCards) == 0 {
- return CARD_COUNT
- }
- if len(ss.fakers[chairId].handCards) == 1 {
- return ss.fakers[chairId].handCards[0]
- }
- // 先按花色存储
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- if ss.roundType != CardType_Invalid && len(sortedCards[ss.roundType]) > 0 {
- return sortedCards[ss.roundType][0]
- }
- typeCounts := make([]int, 4)
- minIndex := -1
- minCount := 8
- maxIndex := -1
- maxCount := 0
- for i := 0; i < len(typeCounts); i++ {
- typeCounts[i] = len(sortedCards[i])
- if i == ss.trumpType || typeCounts[i] == 0 {
- continue
- }
- if typeCounts[i] < minCount {
- minCount = typeCounts[i]
- minIndex = i
- }
- if typeCounts[i] > maxCount {
- maxCount = typeCounts[i]
- maxIndex = i
- }
- }
- // 如果我有主,则丢一张最少花色的牌 否则丢最多花色的牌
- if ss.trumpType == CardType_Invalid {
- if maxIndex > 0 {
- return sortedCards[maxIndex][0]
- }
- return ss.fakers[chairId].handCards[0]
- }
- if typeCounts[ss.trumpType] == 0 {
- if maxIndex > 0 {
- return sortedCards[maxIndex][0]
- }
- } else {
- if minIndex >= 0 {
- if ss.isClose &&
- minIndex == ss.trumpType &&
- ss.roundType == CardType_Invalid {
- for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
- if getCardType(ss.fakers[chairId].handCards[i]) != ss.trumpType {
- return ss.fakers[chairId].handCards[i]
- }
- }
- } else {
- return sortedCards[minIndex][0]
- }
- }
- }
- return ss.fakers[chairId].handCards[0]
- }
- func (ss *simulatorScene) isBiggerThanAll(card int, cardType int, cards []int) bool {
- r := ss.getCardRank(card, cardType)
- for _, v := range cards {
- if !isValidCard(v) {
- continue
- }
- if r <= ss.getCardRank(v, cardType) {
- return false
- }
- }
- return true
- }
- func (ss *simulatorScene) canOut(card int, cardType int, handCards []int) bool {
- found := false
- for _, v := range handCards {
- if v == card {
- found = true
- }
- }
- if !found {
- return false
- }
- if cardType == CardType_Invalid {
- return true
- }
- t := getCardType(card)
- if t == cardType {
- return true
- }
- foundSameType := false
- for _, v := range handCards {
- if cardType == getCardType(v) {
- foundSameType = true
- }
- }
- return !foundSameType
- }
- func (ss *simulatorScene) getMaxValueCardInCards(cards []int, isNeedOutBigCard bool) int {
- outCard := CARD_COUNT
- maxCardValue := -1
- for i := 0; i < len(cards); i++ {
- value := getCardPoint(cards[i], ss.trumpType)
- if value > maxCardValue && (!isBiggestCard(cards[i], ss.trumpType) || isNeedOutBigCard) {
- maxCardValue = value
- outCard = cards[i]
- }
- }
- if isValidCard(outCard) {
- return outCard
- }
- for i := 0; i < len(cards); i++ {
- value := getCardPoint(cards[i], ss.trumpType)
- if value > maxCardValue {
- maxCardValue = value
- outCard = cards[i]
- }
- }
- return outCard
- }
- func (ss *simulatorScene) getMinValueCardInCards(cards []int) int {
- outCard := CARD_COUNT
- minCardValue := 100
- for i := 0; i < len(cards); i++ {
- value := getCardPoint(cards[i], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- outCard = cards[i]
- }
- }
- return outCard
- }
- func (ss *simulatorScene) getCardsExpectMaxCardsInBigCards(bigCards, maxCards []int) []int {
- cards := []int{}
- for i := 0; i < len(bigCards); i++ {
- bFound := false
- for j := 0; j < len(maxCards); j++ {
- if bigCards[i] == maxCards[j] {
- bFound = true
- break
- }
- }
- if !bFound {
- cards = append(cards, bigCards[i])
- }
- }
- return cards
- }
- func (ss *simulatorScene) canOutMiniCardWhileFirstOut(cards []int, chairId int) bool {
- if len(cards) != 2 {
- return true
- }
- isExistTen := false
- otherCard := 0
- for i := 0; i < len(cards); i++ {
- if getCardValue(cards[i]) == CardValue10 {
- isExistTen = true
- } else {
- otherCard = cards[i]
- }
- }
- if !isExistTen {
- return true
- }
- isEmenyExistA := false
- isEmenyExistBigThanOther := false
- for j := 0; j < CHAIR_COUNT; j++ {
- if isSameTeam(j, chairId) {
- continue
- }
- for n := 0; n < len(ss.fakers[j].handCards); n++ {
- if getCardType(otherCard) == getCardType(ss.fakers[j].handCards[n]) &&
- getCardValue(ss.fakers[j].handCards[n]) == CardValueA {
- isEmenyExistA = true
- }
- if getCardType(otherCard) == getCardType(ss.fakers[j].handCards[n]) &&
- getCardValue(ss.fakers[j].handCards[n]) != CardValueA &&
- getCardPoint(ss.fakers[j].handCards[n], ss.trumpType) > getCardPoint(otherCard, ss.trumpType) {
- isEmenyExistBigThanOther = true
- }
- }
- }
- return (!isEmenyExistA || !isEmenyExistBigThanOther)
- }
- func (ss *simulatorScene) dump(whoseTurn int) {
- log.Debug("suit[%s], roundType[%d], trump[%d], isClose[%v], whoseTurn[%d]",
- getSuitDesc(ss.suit), ss.roundType, ss.trumpType, ss.isClose, whoseTurn)
- log.Debug("gameOutCardHistory:%s", getCardsHex(ss.gameOutCardHistory))
- log.Debug("OutedCardCount:[%d]", ss.getRoundOutedPlayerCount())
- for i := 0; i < CHAIR_COUNT; i++ {
- if isValidCard(ss.fakers[i].currentCard) {
- log.Debug("chair[%d], currentCard[%s], handCards:%s", i, getCardHex(ss.fakers[i].currentCard),
- getCardsHex(ss.fakers[i].handCards))
- } else {
- log.Debug("chair[%d], handCards%s", i, getCardsHex(ss.fakers[i].handCards))
- }
- if i == whoseTurn {
- log.Debug("bigCards:%s", getCardsHex(ss.fakers[i].bigCards))
- }
- }
- }
- /******************************** 辅助计算函数 END ********************************/
- /******************************** 机器人出牌策略 START ********************************/
- func (ss *simulatorScene) getBestOutCard(chairId int, isQuickOrLadder bool) int {
- outCard := ss.getOutCardWhileLastCardIsBiggest(chairId, isQuickOrLadder)
- if isValidCard(outCard) {
- return outCard
- }
- if ss.suit != Suit_Hokum {
- outCard = ss.getBestOutCardInSun(chairId)
- } else {
- outCard = ss.getBestOutCardInHokum(chairId)
- }
- return outCard
- }
- // 在Hokum模式下,获取能保证最后一手牌得分的出牌
- func (ss *simulatorScene) getOutCardWhileLastCardIsBiggest(chairId int, isQuickOrLadder bool) int {
- isPenult := len(ss.fakers[chairId].handCards) == 2 && ss.suit == Suit_Hokum &&
- (len(ss.fakers[chairId].bigCards) == 0 || len(ss.fakers[chairId].bigCards) == 2)
- if !isPenult {
- return CARD_COUNT
- }
- for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
- isBiggest := true
- card := ss.fakers[chairId].handCards[i]
- if getCardType(card) != ss.trumpType {
- continue
- }
- for n := 0; n < CHAIR_COUNT; n++ {
- if isSameTeam(n, chairId) {
- continue
- }
- if !ss.isBiggerThanAll(card, ss.trumpType, ss.fakers[n].handCards) {
- isBiggest = false
- break
- }
- }
- if isBiggest {
- for n := 0; n < len(ss.fakers[chairId].handCards); n++ {
- outCard := ss.fakers[chairId].handCards[n]
- if outCard == card {
- continue
- }
- if ss.canOut(outCard, ss.roundType, ss.fakers[chairId].handCards) {
- if !isQuickOrLadder {
- return outCard
- }
- outCards := ss.getRoundCards()
- outCards[chairId] = outCard
- roundType := ss.roundType
- if roundType == CardType_Invalid {
- roundType = getCardType(outCard)
- }
- for j := 0; j < CHAIR_COUNT; j++ {
- if outCards[j] == CARD_COUNT {
- outCards[j] = ss.getMaxCanOutCardInHokum(roundType, j)
- }
- }
- if isSameTeam(chairId, ss.getWinner(outCards, roundType)) {
- return outCard
- }
- if !ss.isNeedConsecutiveWin(chairId) {
- return outCard
- }
- }
- }
- }
- }
- return CARD_COUNT
- }
- func (ss *simulatorScene) getMaxCanOutCardInHokum(cardType, chairId int) int {
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- if len(sortedCards[cardType]) > 0 {
- maxValue := -1
- card := CARD_COUNT
- for i := 0; i < len(sortedCards[cardType]); i++ {
- v := getCardCompareValue(sortedCards[cardType][i], ss.trumpType)
- if v > maxValue {
- card = sortedCards[cardType][i]
- maxValue = v
- }
- }
- return card
- }
- if len(sortedCards[ss.trumpType]) == 0 {
- return ss.fakers[chairId].handCards[0]
- }
- maxValue := -1
- card := CARD_COUNT
- for i := 0; i < len(sortedCards[ss.trumpType]); i++ {
- v := getCardCompareValue(sortedCards[ss.trumpType][i], ss.trumpType)
- if v > maxValue {
- card = sortedCards[ss.trumpType][i]
- maxValue = v
- }
- }
- return card
- }
- func (ss *simulatorScene) isNeedConsecutiveWin(chairId int) bool {
- if ss.fakers[chairId].consecutiveWinCardCount < 4 {
- return false
- }
- ourScore := 0
- emeneyScore := 0
- for i := 0; i < CHAIR_COUNT; i++ {
- if isSameTeam(i, chairId) {
- ourScore += ss.fakers[i].getProjectScore()
- ourScore += ss.fakers[i].winCardScore
- } else {
- emeneyScore += ss.fakers[i].getProjectScore()
- emeneyScore += ss.fakers[i].winCardScore
- }
- }
- return ss.fakers[chairId].winCardScore > 81 && ourScore > emeneyScore
- }
- /****************************** Sun START ******************************/
- func (ss *simulatorScene) getBestOutCardInSun(chairId int) int {
- outCard := CARD_COUNT
- outedCount := ss.getRoundOutedPlayerCount()
- r := rand.Intn(100)
- if outedCount == 0 {
- priorityList := []int{1, 1, 1, 1}
- for i := CardType_Diamond; i <= CardType_Spade; i++ {
- if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValueA)) {
- priorityList[i] = 2
- } else {
- if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValue10)) {
- priorityList[i] = 0
- }
- }
- }
- // 自己得分,找到敌方两人都要不起的所有大牌
- bigCards := ss.getBigCardsThanAllEnemyHandCardsInSun(chairId, ss.roundType)
- if len(bigCards) > 0 {
- for l := 2; l >= 0; l-- {
- cards := []int{}
- for i := 0; i < len(bigCards); i++ {
- if priorityList[getCardType(bigCards[i])] == l {
- cards = append(cards, bigCards[i])
- }
- }
- if len(cards) > 0 {
- return cards[rand.Intn(len(cards))]
- }
- }
- return bigCards[rand.Intn(len(bigCards))]
- }
- if r < ss.fakers[chairId].actionProb {
- // 队友得分,找到敌方两人都要不起的所有大牌,并找出对应的花色中最大牌值的牌
- bigCards = ss.getBigCardsThanAllEnemyHandCardsInSun(getFriendChair(chairId), ss.roundType)
- if len(bigCards) > 0 {
- for l := 2; l >= 0; l-- {
- cards := []int{}
- for i := 0; i < len(bigCards); i++ {
- if priorityList[getCardType(bigCards[i])] == l {
- cards = append(cards, bigCards[i])
- }
- }
- if len(cards) == 0 {
- continue
- }
- outCard = ss.getMinValueCardWhileFriendHaveBigCardsInSun(chairId, cards)
- if isValidCard(outCard) {
- break
- }
- }
- }
- }
- } else if outedCount == 1 {
- // 自己得分
- enemyChairOfNotOutCard := getPreviousChair(chairId)
- outCard = ss.getOutCardWhileSelfCanWinInSun(chairId, enemyChairOfNotOutCard)
- if isValidCard(outCard) {
- return outCard
- }
- if r < ss.fakers[chairId].actionProb {
- // 队友得分
- outCard = ss.getOutCardWhileFriendCanWinInSun(chairId)
- }
- } else if outedCount == 2 || outedCount == 3 {
- // 队友得分
- outCard = ss.getOutCardWhileFriendCanWinInSun(chairId)
- if isValidCard(outCard) {
- return outCard
- }
- // 自己得分
- enemyChairOfNotOutCard := getPreviousChair(chairId)
- if outedCount == 3 {
- enemyChairOfNotOutCard = -1
- }
- if r < ss.fakers[chairId].actionProb {
- outCard = ss.getOutCardWhileSelfCanWinInSun(chairId, enemyChairOfNotOutCard)
- }
- }
- // 不得分
- if !isValidCard(outCard) {
- outCard = ss.getMinValueCardInSun(chairId)
- }
- return outCard
- }
- func (ss *simulatorScene) getBigCardsThanAllEnemyHandCardsInSun(chairId, roundType int) []int {
- bigCards := []int{}
- for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
- card := ss.fakers[chairId].handCards[i]
- cardType := roundType
- if roundType == CardType_Invalid {
- cardType = getCardType(card)
- }
- isAllBig := true
- for n := 0; n < CHAIR_COUNT; n++ {
- //if isSameTeam(n, chairId) {
- if n == chairId {
- continue
- }
- if !ss.isBiggerThanAll(card, cardType, ss.fakers[n].handCards) {
- isAllBig = false
- break
- }
- }
- if isAllBig {
- bigCards = append(bigCards, card)
- }
- }
- return bigCards
- }
- /* 暂时做屏蔽,先取getMinValueCardWhileFriendHaveBigCardsInSun让机器人做正常思维
- func (ss *simulatorScene) getMaxValueCardWhileFriendHaveBigCardsInSun(chairId int, bigCards []int) int {
- outCard := CARD_COUNT
- maxCardValue := -1
- for i := 0; i < len(bigCards); i++ {
- for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
- if getCardType(ss.fakers[chairId].handCards[j]) != getCardType(bigCards[i]) {
- continue
- }
- value := getCardCompareValue(ss.fakers[chairId].handCards[j], ss.trumpType)
- if value > maxCardValue {
- maxCardValue = value
- outCard = ss.fakers[chairId].handCards[j]
- }
- }
- }
- return outCard
- }
- */
- func (ss *simulatorScene) getMinValueCardWhileFriendHaveBigCardsInSun(chairId int, bigCards []int) int {
- outCard := CARD_COUNT
- minCardValue := 100
- for i := 0; i < len(bigCards); i++ {
- for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
- if getCardType(ss.fakers[chairId].handCards[j]) != getCardType(bigCards[i]) {
- continue
- }
- value := getCardCompareValue(ss.fakers[chairId].handCards[j], ss.trumpType)
- if value < minCardValue && getCardValue(ss.fakers[chairId].handCards[j]) != CardValue10 {
- minCardValue = value
- outCard = ss.fakers[chairId].handCards[j]
- }
- }
- }
- return outCard
- }
- func (ss *simulatorScene) getOutCardWhileSelfCanWinInSun(chairId, enemyChairOfNotOutCard int) int {
- bigCards := ss.getBigCardsThanOutCardsInSun(chairId)
- if len(bigCards) == 0 {
- return CARD_COUNT
- }
- newBigCards := []int{}
- if enemyChairOfNotOutCard == -1 {
- newBigCards = append(newBigCards, bigCards...)
- } else {
- for i := 0; i < len(bigCards); i++ {
- if ss.isBiggerThanAll(bigCards[i], ss.roundType, ss.fakers[enemyChairOfNotOutCard].handCards) {
- newBigCards = append(newBigCards, bigCards[i])
- }
- }
- }
- if len(newBigCards) == 0 {
- return CARD_COUNT
- }
- maxCards := []int{}
- if enemyChairOfNotOutCard == -1 {
- maxCards = ss.getBigCardsThanAllEnemyHandCardsInSun(chairId, ss.roundType)
- } else {
- enemyChairOfOutedCard := getFriendChair(enemyChairOfNotOutCard)
- for i := 0; i < len(newBigCards); i++ {
- if ss.isBiggerThanAll(newBigCards[i], ss.roundType, ss.fakers[enemyChairOfOutedCard].handCards) {
- maxCards = append(maxCards, newBigCards[i])
- }
- }
- }
- if len(maxCards) == 0 {
- return ss.getMaxValueCardInCards(newBigCards, true)
- }
- cards := ss.getCardsExpectMaxCardsInBigCards(newBigCards, maxCards)
- if len(cards) == 0 {
- return newBigCards[0]
- }
- return ss.getMaxValueCardInCards(cards, true)
- }
- func (ss *simulatorScene) getBigCardsThanOutCardsInSun(chairId int) []int {
- bigCards := []int{}
- for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
- if getCardType(ss.fakers[chairId].handCards[i]) != ss.roundType {
- continue
- }
- if ss.isBiggerThanAll(ss.fakers[chairId].handCards[i], ss.roundType, ss.getRoundCards()) {
- bigCards = append(bigCards, ss.fakers[chairId].handCards[i])
- }
- }
- return bigCards
- }
- func (ss *simulatorScene) getOutCardWhileFriendCanWinInSun(chairId int) int {
- outCards := ss.getRoundCards()
- isFriendBig := false
- if outCards[getFriendChair(chairId)] == CARD_COUNT {
- if ss.isBiggerThanAll(outCards[getNextChair(chairId)], ss.roundType, ss.fakers[getFriendChair(chairId)].handCards) {
- return CARD_COUNT
- }
- for i := 0; i < len(ss.fakers[getFriendChair(chairId)].handCards); i++ {
- if getCardType(ss.fakers[getFriendChair(chairId)].handCards[i]) != ss.roundType {
- continue
- }
- if ss.isBiggerThanAll(ss.fakers[getFriendChair(chairId)].handCards[i], ss.roundType,
- ss.fakers[getPreviousChair(chairId)].handCards) {
- isFriendBig = true
- break
- }
- }
- } else {
- winner := ss.getWinner(outCards, ss.roundType)
- if !isSameTeam(winner, chairId) {
- return CARD_COUNT
- }
- if outCards[getPreviousChair(chairId)] != CARD_COUNT {
- isFriendBig = true
- } else {
- if ss.isBiggerThanAll(outCards[getFriendChair(chairId)], ss.roundType,
- ss.fakers[getPreviousChair(chairId)].handCards) {
- isFriendBig = true
- }
- }
- }
- if !isFriendBig {
- return CARD_COUNT
- }
- if ss.getRoundOutedPlayerCount() < 3 {
- return ss.getMinValueCardInSun(chairId)
- }
- cardType := ss.roundType
- bRoundType := true
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- if len(sortedCards[ss.roundType]) == 0 {
- cardType = CardType_Invalid
- bRoundType = false
- }
- bigCards := ss.getBigCardsThanAllEnemyHandCardsInSun(chairId, cardType)
- return ss.getMaxValueCardExpectBigCardsInSun(chairId, bigCards, bRoundType)
- }
- func (ss *simulatorScene) getMaxValueCardExpectBigCardsInSun(chairId int, bigCards []int, haveRoundType bool) int {
- outCard := CARD_COUNT
- maxValue := -1
- for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
- card := ss.fakers[chairId].handCards[i]
- if getCardType(card) != ss.roundType && haveRoundType {
- continue
- }
- bFound := false
- for j := 0; j < len(bigCards); j++ {
- if card == bigCards[j] {
- bFound = true
- break
- }
- }
- if !bFound {
- value := getCardPoint(card, ss.trumpType)
- if value > maxValue {
- maxValue = value
- outCard = card
- }
- }
- }
- return outCard
- }
- func (ss *simulatorScene) getMinValueCardInSun(chairId int) int {
- minCardValue := 100
- card := CARD_COUNT
- if ss.roundType == CardType_Invalid && len(ss.fakers[chairId].handCards) > 2 {
- sortedCard := sortCards(ss.fakers[chairId].handCards)
- for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
- if len(sortedCard[getCardType(ss.fakers[chairId].handCards[j])]) == 2 &&
- !ss.canOutMiniCardWhileFirstOut(sortedCard[getCardType(ss.fakers[chairId].handCards[j])], chairId) {
- continue
- }
- value := getCardPoint(ss.fakers[chairId].handCards[j], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = ss.fakers[chairId].handCards[j]
- }
- }
- if isValidCard(card) {
- return card
- }
- }
- for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
- if getCardType(ss.fakers[chairId].handCards[j]) != ss.roundType {
- continue
- }
- value := getCardPoint(ss.fakers[chairId].handCards[j], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = ss.fakers[chairId].handCards[j]
- }
- }
- if isValidCard(card) {
- return card
- }
- if ss.roundType == CardType_Invalid {
- priorityList := []int{1, 1, 1, 1}
- for i := CardType_Diamond; i <= CardType_Spade; i++ {
- if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValueA)) {
- priorityList[i] = 2
- } else {
- if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValue10)) {
- priorityList[i] = 0
- }
- }
- }
- for l := 2; l >= 0; l-- {
- for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
- if priorityList[getCardType(ss.fakers[chairId].handCards[i])] == l {
- value := getCardPoint(ss.fakers[chairId].handCards[i], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = ss.fakers[chairId].handCards[i]
- }
- }
- }
- if isValidCard(card) {
- return card
- }
- }
- }
- for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
- value := getCardPoint(ss.fakers[chairId].handCards[j], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = ss.fakers[chairId].handCards[j]
- }
- }
- return card
- }
- /****************************** Sun End ******************************/
- /****************************** Hokum START ******************************/
- func (ss *simulatorScene) getBestOutCardInHokum(chairId int) int {
- outCard := CARD_COUNT
- outedCount := ss.getRoundOutedPlayerCount()
- r := rand.Intn(100)
- if outedCount == 0 {
- // 先出主牌大牌
- trumpBigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.trumpType, ss.isClose, !ss.isClose, true)
- maxTrumpCards := []int{}
- for n := 0; n < len(trumpBigCards); n++ {
- if ss.isBiggerThanAll(trumpBigCards[n], ss.trumpType, ss.fakers[getFriendChair(chairId)].handCards) {
- maxTrumpCards = append(maxTrumpCards, trumpBigCards[n])
- }
- }
- if len(maxTrumpCards) > 0 && !ss.isClose && ss.isOtherPlayerHaveTrumpCardInHokum(chairId) {
- return maxTrumpCards[rand.Intn(len(maxTrumpCards))]
- }
- // 自己得分
- bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, CardType_Invalid, ss.isClose, !ss.isClose, true)
- if len(bigCards) > 0 {
- // 再出非主牌大牌
- sortedCards := sortCards(bigCards)
- randStartType := rand.Intn(CHAIR_COUNT)
- for i := CardType_Diamond; i <= CardType_Spade; i++ {
- t := (randStartType + i) % CHAIR_COUNT
- if t == ss.trumpType || len(sortedCards[t]) == 0 {
- continue
- }
- if len(sortedCards[t]) == 1 {
- return sortedCards[t][0]
- }
- if !ss.canBigOnNextRoundInHokum(chairId, t) {
- return ss.getMaxValueCardInCards(sortedCards[t], true)
- } else {
- return sortedCards[t][rand.Intn(len(sortedCards[t]))]
- }
- }
- cardType := CardType_Invalid
- // 再去判断队友能大且是出非主牌
- cardType = ss.getCardTypeWhileFriendCanWinInHokum(chairId)
- if cardType != CardType_Invalid && cardType != ss.trumpType {
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- return ss.getMinValueCardInCards(sortedCards[cardType])
- }
- // 最后出主牌大牌,如果敌方有主牌就出最小大牌
- if ss.isEnemyExistTrumpTypeInHokum(chairId) {
- return bigCards[0]
- } else {
- return ss.getMinValueCardInHokum(chairId)
- }
- }
- if r < ss.fakers[chairId].actionProb {
- // 队友得分
- cardType := ss.getCardTypeWhileFriendCanWinInHokum(chairId)
- if cardType != CardType_Invalid && (cardType != ss.trumpType || len(ss.fakers[chairId].handCards) < NORMAL_HOLD_CARD-1) {
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- return ss.getMinValueCardInCards(sortedCards[cardType])
- }
- }
- } else if outedCount == 1 {
- // 自己得分
- outCard = ss.getOutCardWhileSelfCanWinInHokum(chairId)
- if isValidCard(outCard) {
- // 如果自己出的是主牌,则判断队友能否赢牌,且队友赢牌的出牌花色不为主牌花色
- if getCardType(outCard) == ss.trumpType && ss.roundType != ss.trumpType {
- card, cardType := ss.getOutCardWhileFriendCanWinInHokum(chairId)
- if isValidCard(card) && cardType != ss.trumpType {
- return card
- }
- }
- return outCard
- }
- if r < ss.fakers[chairId].actionProb {
- // 队友得分
- outCard, _ = ss.getOutCardWhileFriendCanWinInHokum(chairId)
- }
- } else if outedCount == 2 {
- // 队友得分
- outCard, _ = ss.getOutCardWhileFriendCanWinInHokum(chairId)
- if isValidCard(outCard) {
- return outCard
- }
- if r < ss.fakers[chairId].actionProb {
- // 自己得分
- outCard = ss.getOutCardWhileSelfCanWinInHokum(chairId)
- }
- } else if outedCount == 3 {
- // 队友得分
- outCards := ss.getRoundCards()
- winner := ss.getWinner(outCards, ss.roundType)
- if isSameTeam(winner, chairId) {
- return ss.getOutCardWhileFriendIsWinnerInHokum(chairId)
- }
- if r < ss.fakers[chairId].actionProb {
- // 自己得分
- outCard = ss.getOutCardWhileSelfCanWinInHokum(chairId)
- }
- }
- // 不得分
- if !isValidCard(outCard) {
- outCard = ss.getMinValueCardInHokum(chairId)
- }
- return outCard
- }
- func (ss *simulatorScene) isOtherPlayerHaveTrumpCardInHokum(chairId int) bool {
- isEnemeyTrumpHaveRecord := false
- for i := 0; i < CHAIR_COUNT; i++ {
- if isSameTeam(chairId, i) {
- continue
- }
- if ss.fakers[i].cardTypesRecord[ss.trumpType] == 1 {
- isEnemeyTrumpHaveRecord = true
- }
- }
- if !isEnemeyTrumpHaveRecord {
- return false
- }
- for i := 0; i < CHAIR_COUNT; i++ {
- if i == chairId {
- continue
- }
- if ss.fakers[i].isExistTheCardTypeInHand(ss.trumpType) {
- return true
- }
- }
- return false
- }
- func (ss *simulatorScene) isEnemyExistTrumpTypeInHokum(chairId int) bool {
- for i := 0; i < CHAIR_COUNT; i++ {
- if isSameTeam(i, chairId) {
- continue
- }
- sortedCards := sortCards(ss.fakers[i].handCards)
- if len(sortedCards[ss.trumpType]) > 0 {
- return true
- }
- }
- return false
- }
- func (ss *simulatorScene) getBigCardsThanAllEnemyHandCardsInHokum(chairId, roundType int, isClose, isIncludeTrump,
- isCheckAllEnemy bool) []int {
- bigCards := []int{}
- handCards := []int{}
- if len(ss.fakers[chairId].bigCards) == 0 {
- handCards = append(handCards, ss.fakers[chairId].handCards...)
- } else {
- handCards = append(handCards, ss.fakers[chairId].bigCards...)
- }
- isAllTrump := true
- // 如果roundType为CardType_Invaild,则是先找非主牌花色中的大牌,如果roundType不为CardType_Invaild,则是找相同花色的大牌
- for i := 0; i < len(handCards); i++ {
- if getCardType(handCards[i]) == ss.trumpType {
- continue
- }
- isAllTrump = false
- if roundType != CardType_Invalid && getCardType(handCards[i]) != roundType {
- continue
- }
- isAllBig := true
- for j := 0; j < CHAIR_COUNT; j++ {
- if isSameTeam(chairId, j) {
- //if j == chairId {
- continue
- }
- // 如果isCheckAllEnemy为true,则不找已出牌玩家
- if ss.fakers[j].currentCard != CARD_COUNT && !isCheckAllEnemy {
- continue
- }
- sortedCards := sortCards(ss.fakers[j].handCards)
- if len(sortedCards[getCardType(handCards[i])]) == 0 && !isSameTeam(chairId, j) && len(sortedCards[ss.trumpType]) > 0 {
- isAllBig = false
- break
- }
- if !ss.isBiggerThanAll(handCards[i], getCardType(handCards[i]), sortedCards[getCardType(handCards[i])]) {
- isAllBig = false
- break
- }
- }
- if isAllBig {
- bigCards = append(bigCards, handCards[i])
- }
- }
- if len(bigCards) > 0 {
- return bigCards
- }
- // 能否出主牌
- if isClose && !isAllTrump {
- return bigCards
- }
- // 是否去找主牌
- if !isIncludeTrump {
- return bigCards
- }
- // 去找主牌能否有大牌
- for i := 0; i < len(handCards); i++ {
- if getCardType(handCards[i]) != ss.trumpType {
- continue
- }
- isAllBig := true
- for j := 0; j < CHAIR_COUNT; j++ {
- if isSameTeam(chairId, j) {
- //if chairId == j {
- continue
- }
- if ss.fakers[j].currentCard != CARD_COUNT && !isCheckAllEnemy {
- continue
- }
- sortedCards := sortCards(ss.fakers[j].handCards)
- if !ss.isBiggerThanAll(handCards[i], ss.trumpType, sortedCards[ss.trumpType]) {
- isAllBig = false
- break
- }
- }
- if isAllBig {
- bigCards = append(bigCards, handCards[i])
- }
- }
- return bigCards
- }
- // 玩家首出情况下,获取队友可赢牌的花色
- func (ss *simulatorScene) getCardTypeWhileFriendCanWinInHokum(chairId int) int {
- friendBigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(getFriendChair(chairId), CardType_Invalid, false, true, false)
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- // 我出非主牌,队友出相同非主牌可赢
- if len(friendBigCards) > 0 {
- for i := 0; i < len(friendBigCards); i++ {
- if getCardType(friendBigCards[i]) == ss.trumpType {
- continue
- }
- if len(sortedCards[getCardType(friendBigCards[i])]) == 1 &&
- getCardValue(sortedCards[getCardType(friendBigCards[i])][0]) == CardValue10 {
- continue
- }
- if len(sortedCards[getCardType(friendBigCards[i])]) > 0 {
- return getCardType(friendBigCards[i])
- }
- }
- }
- // 我出非主牌,队友出主牌可赢
- friendSortedCards := sortCards(ss.fakers[getFriendChair(chairId)].handCards)
- if len(friendSortedCards[ss.trumpType]) == 0 {
- return CardType_Invalid
- }
- for cardType := CardType_Diamond; cardType <= CardType_Spade; cardType++ {
- if cardType == ss.trumpType {
- continue
- }
- if len(sortedCards[cardType]) == 0 {
- continue
- }
- if len(friendSortedCards[cardType]) > 0 {
- continue
- }
- // 队友出主牌大于敌方
- if ss.isExistTrumpCardBiggerThanAllEmenyInHokum(friendSortedCards[ss.trumpType], chairId, cardType) {
- if len(sortedCards[cardType]) > 1 || getCardValue(sortedCards[cardType][0]) != CardValue10 {
- return cardType
- }
- }
- }
- // 我出主牌,队友出主牌可赢
- if (ss.isClose && len(sortedCards[ss.trumpType]) != len(ss.fakers[chairId].handCards)) ||
- len(sortedCards[ss.trumpType]) == 0 {
- return CardType_Invalid
- }
- for i := 0; i < len(friendBigCards); i++ {
- if getCardType(friendBigCards[i]) == ss.trumpType {
- if value_trump[getCardValue(sortedCards[ss.trumpType][0])] < value_trump[CardValue10] {
- return ss.trumpType
- }
- }
- }
- return CardType_Invalid
- }
- func (ss *simulatorScene) isExistTrumpCardBiggerThanAllEmenyInHokum(trumpCards []int, chairId, roundType int) bool {
- for i := 0; i < len(trumpCards); i++ {
- if getCardType(trumpCards[i]) != ss.trumpType {
- continue
- }
- isBig := true
- for n := 0; n < CHAIR_COUNT; n++ {
- if isSameTeam(chairId, n) {
- continue
- }
- sortedCards := sortCards(ss.fakers[n].handCards)
- if len(sortedCards[roundType]) > 0 || len(sortedCards[ss.trumpType]) == 0 {
- continue
- }
- if !ss.isBiggerThanAll(trumpCards[i], roundType, sortedCards[ss.trumpType]) {
- isBig = false
- break
- }
- }
- if isBig {
- return true
- }
- }
- return false
- }
- func (ss *simulatorScene) getOutCardWhileSelfCanWinInHokum(chairId int) int {
- outedCards := ss.getRoundCards()
- // 先找相同花色比未出牌敌方玩家大的牌
- bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.roundType, false, ss.roundType == ss.trumpType, false)
- if len(bigCards) > 0 {
- // 再找比所有敌方玩家相同花色都大的牌
- maxCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.roundType, false, ss.roundType == ss.trumpType, true)
- // 没出牌的敌方只剩最后一张牌,且有主牌,出最大牌或者出牌的玩家出的是最后一张牌
- if ss.roundType != ss.trumpType && len(maxCards) > 0 {
- enemySortedCards1 := sortCards(ss.fakers[getPreviousChair(chairId)].handCards)
- enemySortedCards2 := sortCards(ss.fakers[getNextChair(chairId)].handCards)
- if (outedCards[getPreviousChair(chairId)] == CARD_COUNT &&
- ((len(enemySortedCards1[ss.roundType]) == 1 && len(enemySortedCards1[ss.trumpType]) > 0) ||
- (len(enemySortedCards2[ss.roundType]) == 0 && len(enemySortedCards2[ss.trumpType]) > 0))) ||
- (outedCards[getPreviousChair(chairId)] != CARD_COUNT &&
- ((len(enemySortedCards1[ss.roundType]) == 0 && len(enemySortedCards1[ss.trumpType]) > 0) ||
- (len(enemySortedCards2[ss.roundType]) == 0 && len(enemySortedCards2[ss.trumpType]) > 0))) {
- maxValue := -1
- outCard := CARD_COUNT
- for i := 0; i < len(maxCards); i++ {
- outedCards[chairId] = maxCards[i]
- if chairId == ss.getWinner(outedCards, ss.roundType) {
- value := getCardPoint(maxCards[i], ss.trumpType)
- if value > maxValue {
- maxValue = value
- outCard = maxCards[i]
- }
- }
- outedCards[chairId] = CARD_COUNT
- }
- if isValidCard(outCard) {
- return outCard
- }
- }
- }
- cards := ss.getCardsExpectMaxCardsInBigCards(bigCards, maxCards)
- if len(cards) > 0 {
- maxValue := -1
- outCard := CARD_COUNT
- for i := 0; i < len(cards); i++ {
- outedCards[chairId] = cards[i]
- if chairId == ss.getWinner(outedCards, ss.roundType) {
- value := getCardPoint(cards[i], ss.trumpType)
- if value > maxValue {
- maxValue = value
- outCard = cards[i]
- }
- }
- outedCards[chairId] = CARD_COUNT
- }
- if isValidCard(outCard) {
- return outCard
- }
- }
- for i := 0; i < len(bigCards); i++ {
- outedCards[chairId] = bigCards[i]
- if chairId == ss.getWinner(outedCards, ss.roundType) {
- return bigCards[i]
- }
- outedCards[chairId] = CARD_COUNT
- }
- }
- handCards := []int{}
- if len(ss.fakers[chairId].bigCards) == 0 {
- handCards = append(handCards, ss.fakers[chairId].handCards...)
- } else {
- handCards = append(handCards, ss.fakers[chairId].bigCards...)
- }
- sortedCards := sortCards(handCards)
- if len(sortedCards[ss.roundType]) > 0 {
- return CARD_COUNT
- }
- if len(sortedCards[ss.trumpType]) == 0 {
- return CARD_COUNT
- }
- // 没有相同花色,roundType为非主牌,我有主牌大于未出牌的敌方
- bigCards = ss.getTrumpCardBiggerThanAllEmenyInHokum(sortedCards[ss.trumpType], chairId, ss.roundType)
- if len(bigCards) > 0 {
- // 查找我是否主牌大于所有敌方玩家手牌
- maxCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.trumpType, false, true, true)
- cards := ss.getCardsExpectMaxCardsInBigCards(bigCards, maxCards)
- if len(cards) > 0 {
- maxValue := -1
- outCard := CARD_COUNT
- for i := 0; i < len(cards); i++ {
- outedCards[chairId] = cards[i]
- if chairId == ss.getWinner(outedCards, ss.roundType) {
- value := getCardPoint(cards[i], ss.trumpType)
- if value > maxValue {
- maxValue = value
- outCard = cards[i]
- }
- }
- outedCards[chairId] = CARD_COUNT
- }
- if isValidCard(outCard) {
- return outCard
- }
- }
- for i := 0; i < len(bigCards); i++ {
- outedCards[chairId] = bigCards[i]
- if chairId == ss.getWinner(outedCards, ss.roundType) {
- return bigCards[i]
- }
- outedCards[chairId] = CARD_COUNT
- }
- }
- return CARD_COUNT
- }
- func (ss *simulatorScene) getTrumpCardBiggerThanAllEmenyInHokum(trumpCards []int, chairId, roundType int) []int {
- bigCards := []int{}
- for i := 0; i < len(trumpCards); i++ {
- if getCardType(trumpCards[i]) != ss.trumpType {
- continue
- }
- isBig := true
- for n := 0; n < CHAIR_COUNT; n++ {
- if isSameTeam(chairId, n) {
- //if chairId == n {
- continue
- }
- if ss.fakers[n].currentCard != CARD_COUNT {
- continue
- }
- sortedCards := sortCards(ss.fakers[n].handCards)
- if roundType == ss.trumpType && len(sortedCards[ss.trumpType]) == 0 {
- continue
- }
- if (len(sortedCards[roundType]) > 0 || len(sortedCards[ss.trumpType]) == 0) && roundType != ss.trumpType {
- continue
- }
- if !ss.isBiggerThanAll(trumpCards[i], roundType, sortedCards[ss.trumpType]) {
- isBig = false
- break
- }
- }
- if isBig {
- bigCards = append(bigCards, trumpCards[i])
- }
- }
- return bigCards
- }
- func (ss *simulatorScene) getOutCardWhileFriendCanWinInHokum(chairId int) (int, int) {
- outedCards := ss.getRoundCards()
- if outedCards[getFriendChair(chairId)] == CARD_COUNT {
- // 先找相同花色比未出牌玩家大的牌
- bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(getFriendChair(chairId), ss.roundType, false,
- ss.roundType == ss.trumpType, false)
- sortedCards := sortCards(ss.fakers[getFriendChair(chairId)].handCards)
- if len(bigCards) == 0 && len(sortedCards[ss.roundType]) > 0 {
- return CARD_COUNT, CardType_Invalid
- }
- for i := 0; i < len(bigCards); i++ {
- outedCards[getFriendChair(chairId)] = bigCards[i]
- if getFriendChair(chairId) == ss.getWinner(outedCards, ss.roundType) {
- return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(bigCards[i])
- }
- outedCards[getFriendChair(chairId)] = CARD_COUNT
- }
- if len(sortedCards[ss.roundType]) > 0 {
- return CARD_COUNT, CardType_Invalid
- }
- if len(sortedCards[ss.trumpType]) == 0 {
- return CARD_COUNT, CardType_Invalid
- }
- // 没有相同花色,roundType为非主牌,我有主牌大于未出牌的敌方
- bigCards = ss.getTrumpCardBiggerThanAllEmenyInHokum(sortedCards[ss.trumpType], chairId, ss.roundType)
- if len(bigCards) == 0 {
- return CARD_COUNT, CardType_Invalid
- }
- for i := 0; i < len(bigCards); i++ {
- outedCards[getFriendChair(chairId)] = bigCards[i]
- if getFriendChair(chairId) == ss.getWinner(outedCards, ss.roundType) {
- return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(bigCards[i])
- }
- outedCards[getFriendChair(chairId)] = CARD_COUNT
- }
- return CARD_COUNT, CardType_Invalid
- }
- if ss.getWinner(outedCards, ss.roundType) != getFriendChair(chairId) {
- return CARD_COUNT, CardType_Invalid
- }
- enemySortedCards := sortCards(ss.fakers[getPreviousChair(chairId)].handCards)
- if len(enemySortedCards[ss.roundType]) > 0 {
- if !ss.isBiggerThanAll(outedCards[getFriendChair(chairId)], ss.roundType, enemySortedCards[ss.roundType]) {
- return CARD_COUNT, CardType_Invalid
- }
- return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(outedCards[getFriendChair(chairId)])
- }
- if ss.isBiggerThanAll(outedCards[getFriendChair(chairId)], ss.roundType, enemySortedCards[ss.trumpType]) {
- return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(outedCards[getFriendChair(chairId)])
- }
- return CARD_COUNT, CardType_Invalid
- }
- func (ss *simulatorScene) getOutCardWhileFriendIsWinnerInHokum(chairId int) int {
- sortedCards := sortCards(ss.fakers[chairId].handCards)
- if len(sortedCards[ss.roundType]) > 0 {
- maxCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.roundType, false,
- ss.roundType == ss.trumpType, true)
- if len(maxCards) == 0 {
- return ss.getMaxValueCardInCards(sortedCards[ss.roundType], false)
- }
- if !ss.canBigOnNextRoundInHokum(chairId, ss.roundType) {
- return ss.getMaxValueCardInCards(sortedCards[ss.roundType], false)
- }
- cards := ss.getCardsExpectMaxCardsInBigCards(sortedCards[ss.roundType], maxCards)
- if len(cards) == 0 {
- return ss.getMinValueCardInCards(maxCards)
- }
- return ss.getMaxValueCardInCards(cards, false)
- }
- bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, CardType_Invalid, false, true, true)
- return ss.getMaxValueCardExpectBigCardsInHokum(chairId, bigCards)
- }
- func (ss *simulatorScene) canBigOnNextRoundInHokum(chairId, roundType int) bool {
- if ss.trumpType == roundType {
- return true
- }
- outedCards := ss.getRoundCards()
- for n := 0; n < CHAIR_COUNT; n++ {
- if isSameTeam(n, chairId) {
- //if n == chairId {
- continue
- }
- enemySortedCards := sortCards(ss.fakers[n].handCards)
- if outedCards[n] != CARD_COUNT && len(enemySortedCards[roundType]) == 0 && len(enemySortedCards[ss.trumpType]) > 0 {
- return false
- }
- if outedCards[n] == CARD_COUNT && len(enemySortedCards[roundType]) <= 1 && len(enemySortedCards[ss.trumpType]) > 0 {
- return false
- }
- }
- return true
- }
- func (ss *simulatorScene) getMaxValueCardExpectBigCardsInHokum(chairId int, bigCards []int) int {
- handCards := []int{}
- if len(ss.fakers[chairId].bigCards) == 0 {
- handCards = append(handCards, ss.fakers[chairId].handCards...)
- } else {
- handCards = append(handCards, ss.fakers[chairId].bigCards...)
- }
- outCard := CARD_COUNT
- maxValue := -1
- for i := 0; i < len(handCards); i++ {
- if getCardType(handCards[i]) == ss.trumpType {
- continue
- }
- bFound := false
- for j := 0; j < len(bigCards); j++ {
- if handCards[i] == bigCards[j] {
- bFound = true
- break
- }
- }
- if !bFound {
- value := getCardPoint(handCards[i], ss.trumpType)
- if value > maxValue && getCardValue(handCards[i]) != CardValueA {
- maxValue = value
- outCard = handCards[i]
- }
- }
- }
- if isValidCard(outCard) {
- return outCard
- }
- for i := 0; i < len(handCards); i++ {
- if getCardType(handCards[i]) == ss.trumpType {
- continue
- }
- bFound := false
- for j := 0; j < len(bigCards); j++ {
- if handCards[i] == bigCards[j] {
- bFound = true
- break
- }
- }
- if !bFound {
- value := getCardPoint(handCards[i], ss.trumpType)
- if value > maxValue {
- maxValue = value
- outCard = handCards[i]
- }
- }
- }
- if isValidCard(outCard) {
- return outCard
- }
- minValue := 100
- for j := 0; j < len(bigCards); j++ {
- if getCardType(bigCards[j]) == ss.trumpType {
- continue
- }
- value := getCardPoint(bigCards[j], ss.trumpType)
- if value < minValue {
- minValue = value
- outCard = bigCards[j]
- }
- }
- if isValidCard(outCard) {
- return outCard
- }
- for j := 0; j < len(handCards); j++ {
- value := getCardPoint(handCards[j], ss.trumpType)
- if value < minValue {
- minValue = value
- outCard = handCards[j]
- }
- }
- return outCard
- }
- func (ss *simulatorScene) getMinValueCardInHokum(chairId int) int {
- minCardValue := 100
- card := CARD_COUNT
- handCards := []int{}
- if len(ss.fakers[chairId].bigCards) == 0 {
- handCards = append(handCards, ss.fakers[chairId].handCards...)
- } else {
- handCards = append(handCards, ss.fakers[chairId].bigCards...)
- }
- // 首出时手牌不少于2张,如果手上有10只剩两张该花色牌,且该花色A没有打出来,则不优先出该花色牌
- if ss.roundType == CardType_Invalid && len(ss.fakers[chairId].handCards) > 2 {
- sortedCards := sortCards(handCards)
- for j := 0; j < len(handCards); j++ {
- if getCardType(handCards[j]) == ss.trumpType {
- continue
- }
- if len(sortedCards[getCardType(handCards[j])]) == 2 &&
- !ss.canOutMiniCardWhileFirstOut(sortedCards[getCardType(handCards[j])], chairId) {
- continue
- }
- value := getCardPoint(handCards[j], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = handCards[j]
- }
- }
- if isValidCard(card) {
- return card
- }
- }
- for j := 0; j < len(handCards); j++ {
- if getCardType(handCards[j]) != ss.roundType {
- continue
- }
- value := getCardPoint(handCards[j], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = handCards[j]
- }
- }
- if isValidCard(card) {
- return card
- }
- for j := 0; j < len(handCards); j++ {
- if getCardType(handCards[j]) == ss.trumpType {
- continue
- }
- value := getCardPoint(handCards[j], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = handCards[j]
- }
- }
- if isValidCard(card) {
- return card
- }
- for j := 0; j < len(handCards); j++ {
- value := getCardPoint(handCards[j], ss.trumpType)
- if value < minCardValue {
- minCardValue = value
- card = handCards[j]
- }
- }
- return card
- }
- /****************************** Hokum END ******************************/
- /*************************** 机器人出牌策略 end *************************/
|