simulator.go 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176
  1. package gamelogic
  2. import (
  3. "math/rand"
  4. "sort"
  5. "bet24.com/log"
  6. )
  7. type correction struct {
  8. correctCard int
  9. correctType int
  10. suggestCards []int
  11. }
  12. type fakerInfo struct {
  13. handCards []int // 手牌
  14. currentCard int // 当前轮次的出牌
  15. winCardScore int // 每一小局赢牌得分
  16. projects []SingleProject // 项目数据
  17. correctionList []correction // 玩家出牌对错表
  18. bigCards []int // 大牌
  19. cardTypesRecord []int // 按照人的思维记录玩家所有牌花色是否有打完
  20. outedCards []int // 玩家已出牌
  21. consecutiveWinCardCount int // 连续赢牌次数
  22. actionProb int // 机器人动作概率
  23. }
  24. // 初始化数据
  25. func (f *fakerInfo) initData() {
  26. f.handCards = []int{}
  27. f.winCardScore = 0
  28. f.currentCard = CARD_COUNT
  29. f.projects = []SingleProject{}
  30. f.correctionList = []correction{}
  31. f.bigCards = []int{}
  32. f.cardTypesRecord = make([]int, 4)
  33. f.outedCards = make([]int, NORMAL_HOLD_CARD)
  34. f.consecutiveWinCardCount = 0
  35. f.actionProb = 100
  36. }
  37. // 初始化先判定玩家每个花色的牌都是存在的
  38. func (f *fakerInfo) initCardTypesReccord() {
  39. for i := 0; i < CHAIR_COUNT; i++ {
  40. f.cardTypesRecord[i] = 1
  41. }
  42. }
  43. // 更新某个花色牌已经不存在
  44. func (f *fakerInfo) updataACardTypeToNotExist(cardType int) {
  45. if cardType >= CardType_Diamond && cardType <= CardType_Spade {
  46. f.cardTypesRecord[cardType] = 0
  47. }
  48. }
  49. // 分析手牌中的项目,并做保存
  50. func (f *fakerInfo) analysisProject(suit int) {
  51. cardList := make([]int, len(f.handCards))
  52. copy(cardList, f.handCards)
  53. projects := []SingleProject{}
  54. for i := PROJECT_FOURHUNDRED; i >= PROJECT_SIRA; i-- {
  55. if suit == Suit_Hokum && i == PROJECT_FOURHUNDRED {
  56. continue
  57. }
  58. for n := 0; n < 2; n++ {
  59. cards, bInclude := isIncludeTheProject(cardList, i, suit)
  60. if bInclude {
  61. cardList = removeCards(cardList, cards)
  62. projects = append(projects, SingleProject{
  63. Type: i,
  64. Score: value_project[i],
  65. Cards: cards,
  66. })
  67. }
  68. }
  69. }
  70. if len(projects) > 0 {
  71. f.projects = projects
  72. }
  73. }
  74. func (f *fakerInfo) isExistTheCardInOutedCards(card int) bool {
  75. for i := 0; i < len(f.outedCards); i++ {
  76. if f.outedCards[i] == card {
  77. return true
  78. }
  79. }
  80. return false
  81. }
  82. // 检查是否有baloot项目
  83. func (f *fakerInfo) haveBaloot(trumpType int) bool {
  84. haveTrumpQ := false
  85. haveTrumpK := false
  86. for i := 0; i < len(f.handCards); i++ {
  87. if f.handCards[i] == trumpType*8+CardValueQ {
  88. haveTrumpQ = true
  89. }
  90. if f.handCards[i] == trumpType*8+CardValueK {
  91. haveTrumpK = true
  92. }
  93. }
  94. return haveTrumpQ && haveTrumpK
  95. }
  96. // 从手牌中删除打出的牌,并记录每轮打出的牌
  97. func (f *fakerInfo) removeCard(card int) {
  98. for i := 0; i < len(f.handCards); i++ {
  99. if f.handCards[i] == card {
  100. f.handCards = append(f.handCards[:i], f.handCards[i+1:]...)
  101. f.currentCard = card
  102. f.outedCards = append(f.outedCards, card)
  103. break
  104. }
  105. }
  106. }
  107. // 每轮打完牌后初始化压牌列表
  108. func (f *fakerInfo) initBigCards(cards []int) {
  109. f.bigCards = []int{}
  110. if len(cards) > 0 {
  111. f.bigCards = append(f.bigCards, cards...)
  112. }
  113. }
  114. // 判断是否出的是压牌中的数据
  115. func (f *fakerInfo) isOutBigCards(card int) bool {
  116. if len(f.bigCards) == 0 {
  117. return true
  118. }
  119. for i := 0; i < len(f.bigCards); i++ {
  120. if card == f.bigCards[i] {
  121. return true
  122. }
  123. }
  124. return false
  125. }
  126. // 每轮赢牌分累加
  127. func (f *fakerInfo) addScore(score int) {
  128. f.winCardScore += score
  129. }
  130. // 获取项目得分
  131. func (f *fakerInfo) getProjectScore() int {
  132. score := 0
  133. for i := 0; i < len(f.projects); i++ {
  134. score += f.projects[i].Score
  135. }
  136. return score
  137. }
  138. // 在纠错模式下,检查玩家是否有不合法出牌
  139. func (f *fakerInfo) haveWrongAction() bool {
  140. if len(f.correctionList) == 0 {
  141. return false
  142. }
  143. for i := 0; i < len(f.correctionList); i++ {
  144. if f.correctionList[i].correctCard != -1 {
  145. return true
  146. }
  147. }
  148. return false
  149. }
  150. // 纠错数据校验
  151. func (f *fakerInfo) isWrongData(correctType int, cards []int) bool {
  152. wrongCard := CARD_COUNT
  153. for n := 0; n < len(cards); n++ {
  154. for i := 0; i < len(f.correctionList); i++ {
  155. if f.correctionList[i].correctCard == cards[n] && correctType == f.correctionList[i].correctType {
  156. wrongCard = cards[n]
  157. otherCard := CARD_COUNT
  158. for m := 0; m < len(cards); m++ {
  159. if cards[m] != wrongCard {
  160. otherCard = cards[m]
  161. break
  162. }
  163. }
  164. for j := 0; j < len(f.correctionList[i].suggestCards); j++ {
  165. if otherCard == f.correctionList[i].suggestCards[j] {
  166. return true
  167. }
  168. }
  169. }
  170. }
  171. }
  172. return false
  173. }
  174. func (f *fakerInfo) isExistTheCardTypeInHand(cardType int) bool {
  175. for i := 0; i < len(f.handCards); i++ {
  176. if getCardType(f.handCards[i]) == cardType {
  177. return true
  178. }
  179. }
  180. return false
  181. }
  182. type simulatorScene struct {
  183. suit int // 模式
  184. roundType int // 当前圈牌色
  185. trumpType int // 主牌花色,Sun或Ashkal模式下为CardType_Invalid
  186. buyChair int // 买牌位置
  187. baseTimes int // 加倍分
  188. isBO1 bool // 是否一把定胜负
  189. isClose bool // 为true表示本局在每一轮第一个出牌时不能出主牌(除了手上全是主牌的情况)
  190. lastWinChair int // 最后一轮赢牌玩家
  191. buyWinScore int // 买牌方赢分
  192. gameOutCardHistory []int // 本轮已出的牌
  193. fakers []fakerInfo // 玩家信息
  194. }
  195. func newSimulatorScene() *simulatorScene {
  196. ss := new(simulatorScene)
  197. ss.fakers = make([]fakerInfo, CHAIR_COUNT)
  198. for i := 0; i < CHAIR_COUNT; i++ {
  199. ss.fakers[i].initData()
  200. }
  201. ss.roundType = CardType_Invalid
  202. ss.gameOutCardHistory = []int{}
  203. ss.trumpType = CardType_Invalid
  204. ss.suit = Suit_Invalid
  205. ss.buyChair = CHAIR_COUNT
  206. ss.baseTimes = 1
  207. ss.isBO1 = false
  208. ss.lastWinChair = CHAIR_COUNT
  209. ss.buyWinScore = 0
  210. ss.isClose = false
  211. return ss
  212. }
  213. /******************************** 模拟场景流程的函数 START ********************************/
  214. // 初始化数据
  215. func (ss *simulatorScene) initData(trumpType, suit, buyChair, baseTimes int, isBo1, isClose bool) {
  216. ss.trumpType = trumpType
  217. ss.suit = suit
  218. ss.buyChair = buyChair
  219. ss.baseTimes = baseTimes
  220. ss.isBO1 = isBo1
  221. ss.isClose = isClose
  222. for i := 0; i < CHAIR_COUNT; i++ {
  223. ss.fakers[i].initCardTypesReccord()
  224. }
  225. }
  226. // 检查项目
  227. func (ss *simulatorScene) checkProject() {
  228. for i := 0; i < CHAIR_COUNT; i++ {
  229. ss.fakers[i].analysisProject(ss.suit)
  230. }
  231. }
  232. // 比较项目
  233. func (ss *simulatorScene) compareProject() {
  234. buyProject := []SingleProject{}
  235. playerProject := []SingleProject{}
  236. for i := 0; i < CHAIR_COUNT; i++ {
  237. if len(ss.fakers[i].projects) == 0 {
  238. continue
  239. }
  240. if isSameTeam(i, ss.buyChair) {
  241. buyProject = append(buyProject, ss.fakers[i].projects[0])
  242. } else {
  243. playerProject = append(playerProject, ss.fakers[i].projects[0])
  244. }
  245. }
  246. if len(buyProject) == 0 || len(playerProject) == 0 {
  247. return
  248. }
  249. // 从大到小排序
  250. sort.Slice(buyProject, func(i, j int) bool {
  251. return buyProject[i].isBiggerThan(buyProject[j])
  252. })
  253. sort.Slice(playerProject, func(i, j int) bool {
  254. return playerProject[i].isBiggerThan(playerProject[j])
  255. })
  256. isBuyTeamBig := buyProject[0].isBiggerThan(playerProject[0])
  257. for i := 0; i < CHAIR_COUNT; i++ {
  258. if len(ss.fakers[i].projects) == 0 {
  259. continue
  260. }
  261. if isSameTeam(i, ss.buyChair) {
  262. if !isBuyTeamBig {
  263. ss.fakers[i].projects = []SingleProject{}
  264. }
  265. } else {
  266. if isBuyTeamBig {
  267. ss.fakers[i].projects = []SingleProject{}
  268. }
  269. }
  270. }
  271. }
  272. // 获取已出牌玩家人数
  273. func (ss *simulatorScene) getRoundOutedPlayerCount() int {
  274. outedCount := 0
  275. for _, v := range ss.fakers {
  276. if v.currentCard != CARD_COUNT {
  277. outedCount++
  278. }
  279. }
  280. return outedCount
  281. }
  282. // 获取每轮出牌
  283. func (ss *simulatorScene) getRoundCards() []int {
  284. ret := make([]int, CHAIR_COUNT)
  285. for i := 0; i < CHAIR_COUNT; i++ {
  286. ret[i] = ss.fakers[i].currentCard
  287. }
  288. return ret
  289. }
  290. // 获取每轮出牌赢家
  291. func (ss *simulatorScene) getWinner(outCards []int, referType int) int {
  292. ranks := make([]int, CHAIR_COUNT)
  293. winner := -1
  294. bestRank := -2
  295. for i := 0; i < CHAIR_COUNT; i++ {
  296. ranks[i] = ss.getCardRank(outCards[i], referType)
  297. if ranks[i] > bestRank {
  298. bestRank = ranks[i]
  299. winner = i
  300. }
  301. }
  302. return winner
  303. }
  304. // 判断每轮是否出牌结束
  305. func (ss *simulatorScene) isRoundEnd() bool {
  306. return ss.getRoundOutedPlayerCount() == CHAIR_COUNT
  307. }
  308. func (ss *simulatorScene) haveWrongAction(correctMode, sawaChair int) bool {
  309. if correctMode == Correct_Sawa {
  310. for n := 0; n < CHAIR_COUNT; n++ {
  311. if n == sawaChair {
  312. continue
  313. }
  314. for i := 0; i < len(ss.fakers[sawaChair].handCards); i++ {
  315. card := ss.fakers[sawaChair].handCards[i]
  316. if !ss.isBiggerThanAll(card, getCardType(card), ss.fakers[n].handCards) {
  317. return true
  318. }
  319. }
  320. }
  321. return false
  322. }
  323. for i := 0; i < CHAIR_COUNT; i++ {
  324. if ss.fakers[i].haveWrongAction() {
  325. return true
  326. }
  327. }
  328. return false
  329. }
  330. func (ss *simulatorScene) checkWrongActionInSawa(sawaChair int, cards []int) int {
  331. sawaCount := 0
  332. sawaCard := CARD_COUNT
  333. otherCard := CARD_COUNT
  334. for i := 0; i < len(cards); i++ {
  335. for n := 0; n < len(ss.fakers[sawaChair].handCards); n++ {
  336. if cards[i] == ss.fakers[sawaChair].handCards[n] {
  337. sawaCount++
  338. sawaCard = cards[i]
  339. break
  340. }
  341. }
  342. }
  343. if sawaCount != 1 {
  344. return 0
  345. }
  346. for i := 0; i < len(cards); i++ {
  347. if sawaCard != cards[i] {
  348. otherCard = cards[i]
  349. break
  350. }
  351. }
  352. for i := 0; i < CHAIR_COUNT; i++ {
  353. if i == sawaChair {
  354. continue
  355. }
  356. for n := 0; n < len(ss.fakers[i].handCards); n++ {
  357. if otherCard == ss.fakers[i].handCards[n] {
  358. if ss.getCardRank(sawaCard, getCardType(sawaCard)) < ss.getCardRank(otherCard, getCardType(sawaCard)) {
  359. return 1
  360. } else {
  361. return 0
  362. }
  363. }
  364. }
  365. }
  366. return 0
  367. }
  368. func (ss *simulatorScene) checkWrongActionInNormal(whose, correctType int, cards []int) int {
  369. wrongChair := CHAIR_COUNT
  370. for i := 0; i < CHAIR_COUNT; i++ {
  371. if !ss.fakers[i].haveWrongAction() {
  372. continue
  373. }
  374. if ss.fakers[i].isWrongData(correctType, cards) {
  375. wrongChair = i
  376. break
  377. }
  378. }
  379. if !isValidChair(wrongChair) {
  380. return 0
  381. }
  382. if !isSameTeam(wrongChair, whose) {
  383. return 1
  384. }
  385. return 0
  386. }
  387. // 每一轮结束,计算得分和赢家
  388. func (ss *simulatorScene) endAOutCardRound(winner int) {
  389. winScore := 0
  390. for i := 0; i < CHAIR_COUNT; i++ {
  391. score := getCardPoint(ss.fakers[i].currentCard, ss.trumpType)
  392. winScore += score
  393. ss.gameOutCardHistory = append(ss.gameOutCardHistory, ss.fakers[i].currentCard)
  394. ss.fakers[i].currentCard = CARD_COUNT
  395. ss.fakers[i].initBigCards([]int{})
  396. }
  397. for i := 0; i < CHAIR_COUNT; i++ {
  398. if i == winner {
  399. ss.fakers[i].addScore(winScore)
  400. }
  401. }
  402. ss.roundType = CardType_Invalid
  403. ss.lastWinChair = winner
  404. }
  405. // 是否小局结束
  406. func (ss *simulatorScene) isGameEnd() bool {
  407. for _, v := range ss.fakers {
  408. if len(v.handCards) > 0 {
  409. return false
  410. }
  411. }
  412. return true
  413. }
  414. // 获取必压的大牌
  415. func (ss *simulatorScene) getCanOutCards(chairId int, isFriendCallBiggest bool) []int {
  416. bigCards := []int{}
  417. ss.fakers[chairId].bigCards = []int{}
  418. // 1.我方队友出大牌
  419. // 2.不打有主模式
  420. // 3.玩家第一个出牌
  421. // 以上不去限制玩家出牌
  422. if isFriendCallBiggest || ss.suit != Suit_Hokum || ss.roundType == CardType_Invalid {
  423. return bigCards
  424. }
  425. // 4.队友目前赢牌 不去限制玩家出牌
  426. winner := ss.getWinner(ss.getRoundCards(), ss.roundType)
  427. if isSameTeam(chairId, winner) {
  428. return bigCards
  429. }
  430. // 5.敌方目前赢牌,这轮出牌的roundType为副牌,当前玩家手上还有相同花色的牌,不去限制玩家出牌
  431. sortedCards := sortCards(ss.fakers[chairId].handCards)
  432. if ss.roundType != ss.trumpType && len(sortedCards[ss.roundType]) > 0 {
  433. return bigCards
  434. }
  435. biggestCard := ss.fakers[winner].currentCard
  436. r := ss.getCardRank(biggestCard, ss.roundType)
  437. for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
  438. r1 := ss.getCardRank(ss.fakers[chairId].handCards[i], ss.roundType)
  439. if r1 > r {
  440. bigCards = append(bigCards, ss.fakers[chairId].handCards[i])
  441. }
  442. }
  443. return bigCards
  444. }
  445. // 模拟结算,看买牌输赢
  446. func (ss *simulatorScene) calcBuyWinScore() {
  447. buyPoint := 0
  448. playerPoint := 0
  449. buyWinCardScore := 0
  450. playerWinCardScore := 0
  451. for i := 0; i < CHAIR_COUNT; i++ {
  452. if isSameTeam(i, ss.buyChair) {
  453. buyPoint += ss.fakers[i].getProjectScore()
  454. buyPoint += ss.fakers[i].winCardScore
  455. buyWinCardScore += ss.fakers[i].winCardScore
  456. } else {
  457. playerPoint += ss.fakers[i].getProjectScore()
  458. playerPoint += ss.fakers[i].winCardScore
  459. playerWinCardScore += ss.fakers[i].winCardScore
  460. }
  461. }
  462. ss.fakers[ss.lastWinChair].winCardScore += LAST_WIN_SCORE
  463. if isSameTeam(ss.buyChair, ss.lastWinChair) {
  464. buyPoint += LAST_WIN_SCORE
  465. buyWinCardScore += LAST_WIN_SCORE
  466. } else {
  467. playerPoint += LAST_WIN_SCORE
  468. playerWinCardScore += LAST_WIN_SCORE
  469. }
  470. playerAbnat := playerPoint
  471. // 如果买的一方输的情况
  472. if (buyPoint == playerPoint && (ss.baseTimes > 1 || ss.isBO1)) || buyPoint < playerPoint {
  473. playerPoint += buyPoint
  474. if ss.fakers[ss.buyChair].winCardScore == 0 {
  475. playerPoint += ALL_WIN_EXTRA_SCORE
  476. }
  477. buyPoint = 0
  478. } else {
  479. if ss.fakers[getNextChair(ss.buyChair)].winCardScore == 0 {
  480. buyPoint += ALL_WIN_EXTRA_SCORE
  481. playerPoint = 0
  482. }
  483. if ss.isBO1 || ss.baseTimes > 1 {
  484. buyPoint += playerAbnat
  485. playerPoint = 0
  486. }
  487. }
  488. finalBuyPoint := calcFinalPonit(buyPoint)
  489. finalPlayerPoint := calcFinalPonit(playerPoint)
  490. if ss.suit != Suit_Hokum {
  491. finalBuyPoint *= 2
  492. finalPlayerPoint *= 2
  493. if buyWinCardScore%10 == 5 && playerWinCardScore%10 == 5 && buyPoint > 0 && playerPoint > 0 {
  494. finalBuyPoint++
  495. finalPlayerPoint++
  496. }
  497. } else {
  498. if buyWinCardScore%10 == 6 && playerWinCardScore%10 == 6 && buyPoint > 0 && playerPoint > 0 {
  499. finalPlayerPoint--
  500. }
  501. }
  502. finalBuyPoint *= ss.baseTimes
  503. finalPlayerPoint *= ss.baseTimes
  504. if ss.isBO1 {
  505. if finalBuyPoint > finalPlayerPoint {
  506. finalBuyPoint = SCORE_TO_WIN
  507. finalPlayerPoint = 0
  508. } else {
  509. finalBuyPoint = 0
  510. finalPlayerPoint = SCORE_TO_WIN
  511. }
  512. }
  513. ss.buyWinScore = finalBuyPoint - finalPlayerPoint
  514. }
  515. func (ss *simulatorScene) isWinScoreBigThanFriend() bool {
  516. return (ss.fakers[ss.buyChair].winCardScore - ss.fakers[getFriendChair(ss.buyChair)].winCardScore) >= 40
  517. }
  518. func (ss *simulatorScene) calcProject() {
  519. ss.checkProject()
  520. ss.compareProject()
  521. if ss.suit == Suit_Hokum {
  522. for i := 0; i < CHAIR_COUNT; i++ {
  523. if ss.fakers[i].haveBaloot(ss.trumpType) {
  524. ss.fakers[i].projects = append(ss.fakers[i].projects, SingleProject{
  525. Type: PROJECT_BALOOT,
  526. Score: value_project[PROJECT_BALOOT],
  527. Cards: []int{genACard(ss.trumpType, CardValueQ), genACard(ss.trumpType, CardValueK)},
  528. })
  529. break
  530. }
  531. }
  532. }
  533. }
  534. // 开始模拟出牌场景,得出最终得分,走的机器人出牌策略
  535. func (ss *simulatorScene) startSimulatorScene(startChair int, isQuickOrLadder bool) {
  536. ss.calcProject()
  537. outCardChair := startChair
  538. for {
  539. outCard := ss.getBestOutCard(outCardChair, isQuickOrLadder)
  540. if !isValidCard(outCard) {
  541. ss.dump(outCardChair)
  542. if len(ss.fakers[outCardChair].bigCards) > 0 {
  543. outCard = ss.fakers[outCardChair].bigCards[0]
  544. } else {
  545. outCard = ss.worstCard(outCardChair)
  546. }
  547. }
  548. if !isValidCard(outCard) {
  549. return
  550. }
  551. ss.fakers[outCardChair].removeCard(outCard)
  552. if ss.roundType != CardType_Invalid && getCardType(outCard) != ss.roundType {
  553. ss.fakers[outCardChair].updataACardTypeToNotExist(ss.roundType)
  554. }
  555. if ss.roundType == CardType_Invalid {
  556. ss.roundType = getCardType(outCard)
  557. }
  558. if ss.isRoundEnd() {
  559. outCards := ss.getRoundCards()
  560. winner := ss.getWinner(outCards, ss.roundType)
  561. ss.endAOutCardRound(winner)
  562. outCardChair = winner
  563. } else {
  564. outCardChair = getPreviousChair(outCardChair)
  565. isFriendCallBiggest := false
  566. if ss.suit == Suit_Hokum && ss.getRoundOutedPlayerCount() == 2 {
  567. card := ss.fakers[getFriendChair(outCardChair)].currentCard
  568. if isValidCard(card) && getCardType(card) != ss.trumpType {
  569. if !isBiggestCard(card, ss.trumpType) {
  570. if isScoreCard(card, []int{}, ss.gameOutCardHistory, ss.trumpType) {
  571. isFriendCallBiggest = true
  572. }
  573. } else {
  574. isFriendCallBiggest = true
  575. }
  576. }
  577. }
  578. bigCards := ss.getCanOutCards(outCardChair, isFriendCallBiggest)
  579. ss.fakers[outCardChair].initBigCards(bigCards)
  580. }
  581. if ss.isGameEnd() {
  582. break
  583. }
  584. }
  585. ss.calcBuyWinScore()
  586. }
  587. /******************************** 模拟场景流程的函数 END ********************************/
  588. /******************************** 辅助计算函数 START ********************************/
  589. func (ss *simulatorScene) getCardRank(card int, referType int) int {
  590. if !isValidCard(card) {
  591. return -2
  592. }
  593. cardType := getCardType(card)
  594. cardScore := 0
  595. if cardType == ss.trumpType {
  596. cardScore += 100
  597. } else if cardType != referType {
  598. return -1
  599. }
  600. value := getCardCompareValue(card, ss.trumpType)
  601. return cardScore + value
  602. }
  603. func (ss *simulatorScene) worstCard(chairId int) int {
  604. if len(ss.fakers[chairId].handCards) == 0 {
  605. return CARD_COUNT
  606. }
  607. if len(ss.fakers[chairId].handCards) == 1 {
  608. return ss.fakers[chairId].handCards[0]
  609. }
  610. // 先按花色存储
  611. sortedCards := sortCards(ss.fakers[chairId].handCards)
  612. if ss.roundType != CardType_Invalid && len(sortedCards[ss.roundType]) > 0 {
  613. return sortedCards[ss.roundType][0]
  614. }
  615. typeCounts := make([]int, 4)
  616. minIndex := -1
  617. minCount := 8
  618. maxIndex := -1
  619. maxCount := 0
  620. for i := 0; i < len(typeCounts); i++ {
  621. typeCounts[i] = len(sortedCards[i])
  622. if i == ss.trumpType || typeCounts[i] == 0 {
  623. continue
  624. }
  625. if typeCounts[i] < minCount {
  626. minCount = typeCounts[i]
  627. minIndex = i
  628. }
  629. if typeCounts[i] > maxCount {
  630. maxCount = typeCounts[i]
  631. maxIndex = i
  632. }
  633. }
  634. // 如果我有主,则丢一张最少花色的牌 否则丢最多花色的牌
  635. if ss.trumpType == CardType_Invalid {
  636. if maxIndex > 0 {
  637. return sortedCards[maxIndex][0]
  638. }
  639. return ss.fakers[chairId].handCards[0]
  640. }
  641. if typeCounts[ss.trumpType] == 0 {
  642. if maxIndex > 0 {
  643. return sortedCards[maxIndex][0]
  644. }
  645. } else {
  646. if minIndex >= 0 {
  647. if ss.isClose &&
  648. minIndex == ss.trumpType &&
  649. ss.roundType == CardType_Invalid {
  650. for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
  651. if getCardType(ss.fakers[chairId].handCards[i]) != ss.trumpType {
  652. return ss.fakers[chairId].handCards[i]
  653. }
  654. }
  655. } else {
  656. return sortedCards[minIndex][0]
  657. }
  658. }
  659. }
  660. return ss.fakers[chairId].handCards[0]
  661. }
  662. func (ss *simulatorScene) isBiggerThanAll(card int, cardType int, cards []int) bool {
  663. r := ss.getCardRank(card, cardType)
  664. for _, v := range cards {
  665. if !isValidCard(v) {
  666. continue
  667. }
  668. if r <= ss.getCardRank(v, cardType) {
  669. return false
  670. }
  671. }
  672. return true
  673. }
  674. func (ss *simulatorScene) canOut(card int, cardType int, handCards []int) bool {
  675. found := false
  676. for _, v := range handCards {
  677. if v == card {
  678. found = true
  679. }
  680. }
  681. if !found {
  682. return false
  683. }
  684. if cardType == CardType_Invalid {
  685. return true
  686. }
  687. t := getCardType(card)
  688. if t == cardType {
  689. return true
  690. }
  691. foundSameType := false
  692. for _, v := range handCards {
  693. if cardType == getCardType(v) {
  694. foundSameType = true
  695. }
  696. }
  697. return !foundSameType
  698. }
  699. func (ss *simulatorScene) getMaxValueCardInCards(cards []int, isNeedOutBigCard bool) int {
  700. outCard := CARD_COUNT
  701. maxCardValue := -1
  702. for i := 0; i < len(cards); i++ {
  703. value := getCardPoint(cards[i], ss.trumpType)
  704. if value > maxCardValue && (!isBiggestCard(cards[i], ss.trumpType) || isNeedOutBigCard) {
  705. maxCardValue = value
  706. outCard = cards[i]
  707. }
  708. }
  709. if isValidCard(outCard) {
  710. return outCard
  711. }
  712. for i := 0; i < len(cards); i++ {
  713. value := getCardPoint(cards[i], ss.trumpType)
  714. if value > maxCardValue {
  715. maxCardValue = value
  716. outCard = cards[i]
  717. }
  718. }
  719. return outCard
  720. }
  721. func (ss *simulatorScene) getMinValueCardInCards(cards []int) int {
  722. outCard := CARD_COUNT
  723. minCardValue := 100
  724. for i := 0; i < len(cards); i++ {
  725. value := getCardPoint(cards[i], ss.trumpType)
  726. if value < minCardValue {
  727. minCardValue = value
  728. outCard = cards[i]
  729. }
  730. }
  731. return outCard
  732. }
  733. func (ss *simulatorScene) getCardsExpectMaxCardsInBigCards(bigCards, maxCards []int) []int {
  734. cards := []int{}
  735. for i := 0; i < len(bigCards); i++ {
  736. bFound := false
  737. for j := 0; j < len(maxCards); j++ {
  738. if bigCards[i] == maxCards[j] {
  739. bFound = true
  740. break
  741. }
  742. }
  743. if !bFound {
  744. cards = append(cards, bigCards[i])
  745. }
  746. }
  747. return cards
  748. }
  749. func (ss *simulatorScene) canOutMiniCardWhileFirstOut(cards []int, chairId int) bool {
  750. if len(cards) != 2 {
  751. return true
  752. }
  753. isExistTen := false
  754. otherCard := 0
  755. for i := 0; i < len(cards); i++ {
  756. if getCardValue(cards[i]) == CardValue10 {
  757. isExistTen = true
  758. } else {
  759. otherCard = cards[i]
  760. }
  761. }
  762. if !isExistTen {
  763. return true
  764. }
  765. isEmenyExistA := false
  766. isEmenyExistBigThanOther := false
  767. for j := 0; j < CHAIR_COUNT; j++ {
  768. if isSameTeam(j, chairId) {
  769. continue
  770. }
  771. for n := 0; n < len(ss.fakers[j].handCards); n++ {
  772. if getCardType(otherCard) == getCardType(ss.fakers[j].handCards[n]) &&
  773. getCardValue(ss.fakers[j].handCards[n]) == CardValueA {
  774. isEmenyExistA = true
  775. }
  776. if getCardType(otherCard) == getCardType(ss.fakers[j].handCards[n]) &&
  777. getCardValue(ss.fakers[j].handCards[n]) != CardValueA &&
  778. getCardPoint(ss.fakers[j].handCards[n], ss.trumpType) > getCardPoint(otherCard, ss.trumpType) {
  779. isEmenyExistBigThanOther = true
  780. }
  781. }
  782. }
  783. return (!isEmenyExistA || !isEmenyExistBigThanOther)
  784. }
  785. func (ss *simulatorScene) dump(whoseTurn int) {
  786. log.Debug("suit[%s], roundType[%d], trump[%d], isClose[%v], whoseTurn[%d]",
  787. getSuitDesc(ss.suit), ss.roundType, ss.trumpType, ss.isClose, whoseTurn)
  788. log.Debug("gameOutCardHistory:%s", getCardsHex(ss.gameOutCardHistory))
  789. log.Debug("OutedCardCount:[%d]", ss.getRoundOutedPlayerCount())
  790. for i := 0; i < CHAIR_COUNT; i++ {
  791. if isValidCard(ss.fakers[i].currentCard) {
  792. log.Debug("chair[%d], currentCard[%s], handCards:%s", i, getCardHex(ss.fakers[i].currentCard),
  793. getCardsHex(ss.fakers[i].handCards))
  794. } else {
  795. log.Debug("chair[%d], handCards%s", i, getCardsHex(ss.fakers[i].handCards))
  796. }
  797. if i == whoseTurn {
  798. log.Debug("bigCards:%s", getCardsHex(ss.fakers[i].bigCards))
  799. }
  800. }
  801. }
  802. /******************************** 辅助计算函数 END ********************************/
  803. /******************************** 机器人出牌策略 START ********************************/
  804. func (ss *simulatorScene) getBestOutCard(chairId int, isQuickOrLadder bool) int {
  805. outCard := ss.getOutCardWhileLastCardIsBiggest(chairId, isQuickOrLadder)
  806. if isValidCard(outCard) {
  807. return outCard
  808. }
  809. if ss.suit != Suit_Hokum {
  810. outCard = ss.getBestOutCardInSun(chairId)
  811. } else {
  812. outCard = ss.getBestOutCardInHokum(chairId)
  813. }
  814. return outCard
  815. }
  816. // 在Hokum模式下,获取能保证最后一手牌得分的出牌
  817. func (ss *simulatorScene) getOutCardWhileLastCardIsBiggest(chairId int, isQuickOrLadder bool) int {
  818. isPenult := len(ss.fakers[chairId].handCards) == 2 && ss.suit == Suit_Hokum &&
  819. (len(ss.fakers[chairId].bigCards) == 0 || len(ss.fakers[chairId].bigCards) == 2)
  820. if !isPenult {
  821. return CARD_COUNT
  822. }
  823. for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
  824. isBiggest := true
  825. card := ss.fakers[chairId].handCards[i]
  826. if getCardType(card) != ss.trumpType {
  827. continue
  828. }
  829. for n := 0; n < CHAIR_COUNT; n++ {
  830. if isSameTeam(n, chairId) {
  831. continue
  832. }
  833. if !ss.isBiggerThanAll(card, ss.trumpType, ss.fakers[n].handCards) {
  834. isBiggest = false
  835. break
  836. }
  837. }
  838. if isBiggest {
  839. for n := 0; n < len(ss.fakers[chairId].handCards); n++ {
  840. outCard := ss.fakers[chairId].handCards[n]
  841. if outCard == card {
  842. continue
  843. }
  844. if ss.canOut(outCard, ss.roundType, ss.fakers[chairId].handCards) {
  845. if !isQuickOrLadder {
  846. return outCard
  847. }
  848. outCards := ss.getRoundCards()
  849. outCards[chairId] = outCard
  850. roundType := ss.roundType
  851. if roundType == CardType_Invalid {
  852. roundType = getCardType(outCard)
  853. }
  854. for j := 0; j < CHAIR_COUNT; j++ {
  855. if outCards[j] == CARD_COUNT {
  856. outCards[j] = ss.getMaxCanOutCardInHokum(roundType, j)
  857. }
  858. }
  859. if isSameTeam(chairId, ss.getWinner(outCards, roundType)) {
  860. return outCard
  861. }
  862. if !ss.isNeedConsecutiveWin(chairId) {
  863. return outCard
  864. }
  865. }
  866. }
  867. }
  868. }
  869. return CARD_COUNT
  870. }
  871. func (ss *simulatorScene) getMaxCanOutCardInHokum(cardType, chairId int) int {
  872. sortedCards := sortCards(ss.fakers[chairId].handCards)
  873. if len(sortedCards[cardType]) > 0 {
  874. maxValue := -1
  875. card := CARD_COUNT
  876. for i := 0; i < len(sortedCards[cardType]); i++ {
  877. v := getCardCompareValue(sortedCards[cardType][i], ss.trumpType)
  878. if v > maxValue {
  879. card = sortedCards[cardType][i]
  880. maxValue = v
  881. }
  882. }
  883. return card
  884. }
  885. if len(sortedCards[ss.trumpType]) == 0 {
  886. return ss.fakers[chairId].handCards[0]
  887. }
  888. maxValue := -1
  889. card := CARD_COUNT
  890. for i := 0; i < len(sortedCards[ss.trumpType]); i++ {
  891. v := getCardCompareValue(sortedCards[ss.trumpType][i], ss.trumpType)
  892. if v > maxValue {
  893. card = sortedCards[ss.trumpType][i]
  894. maxValue = v
  895. }
  896. }
  897. return card
  898. }
  899. func (ss *simulatorScene) isNeedConsecutiveWin(chairId int) bool {
  900. if ss.fakers[chairId].consecutiveWinCardCount < 4 {
  901. return false
  902. }
  903. ourScore := 0
  904. emeneyScore := 0
  905. for i := 0; i < CHAIR_COUNT; i++ {
  906. if isSameTeam(i, chairId) {
  907. ourScore += ss.fakers[i].getProjectScore()
  908. ourScore += ss.fakers[i].winCardScore
  909. } else {
  910. emeneyScore += ss.fakers[i].getProjectScore()
  911. emeneyScore += ss.fakers[i].winCardScore
  912. }
  913. }
  914. return ss.fakers[chairId].winCardScore > 81 && ourScore > emeneyScore
  915. }
  916. /****************************** Sun START ******************************/
  917. func (ss *simulatorScene) getBestOutCardInSun(chairId int) int {
  918. outCard := CARD_COUNT
  919. outedCount := ss.getRoundOutedPlayerCount()
  920. r := rand.Intn(100)
  921. if outedCount == 0 {
  922. priorityList := []int{1, 1, 1, 1}
  923. for i := CardType_Diamond; i <= CardType_Spade; i++ {
  924. if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValueA)) {
  925. priorityList[i] = 2
  926. } else {
  927. if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValue10)) {
  928. priorityList[i] = 0
  929. }
  930. }
  931. }
  932. // 自己得分,找到敌方两人都要不起的所有大牌
  933. bigCards := ss.getBigCardsThanAllEnemyHandCardsInSun(chairId, ss.roundType)
  934. if len(bigCards) > 0 {
  935. for l := 2; l >= 0; l-- {
  936. cards := []int{}
  937. for i := 0; i < len(bigCards); i++ {
  938. if priorityList[getCardType(bigCards[i])] == l {
  939. cards = append(cards, bigCards[i])
  940. }
  941. }
  942. if len(cards) > 0 {
  943. return cards[rand.Intn(len(cards))]
  944. }
  945. }
  946. return bigCards[rand.Intn(len(bigCards))]
  947. }
  948. if r < ss.fakers[chairId].actionProb {
  949. // 队友得分,找到敌方两人都要不起的所有大牌,并找出对应的花色中最大牌值的牌
  950. bigCards = ss.getBigCardsThanAllEnemyHandCardsInSun(getFriendChair(chairId), ss.roundType)
  951. if len(bigCards) > 0 {
  952. for l := 2; l >= 0; l-- {
  953. cards := []int{}
  954. for i := 0; i < len(bigCards); i++ {
  955. if priorityList[getCardType(bigCards[i])] == l {
  956. cards = append(cards, bigCards[i])
  957. }
  958. }
  959. if len(cards) == 0 {
  960. continue
  961. }
  962. outCard = ss.getMinValueCardWhileFriendHaveBigCardsInSun(chairId, cards)
  963. if isValidCard(outCard) {
  964. break
  965. }
  966. }
  967. }
  968. }
  969. } else if outedCount == 1 {
  970. // 自己得分
  971. enemyChairOfNotOutCard := getPreviousChair(chairId)
  972. outCard = ss.getOutCardWhileSelfCanWinInSun(chairId, enemyChairOfNotOutCard)
  973. if isValidCard(outCard) {
  974. return outCard
  975. }
  976. if r < ss.fakers[chairId].actionProb {
  977. // 队友得分
  978. outCard = ss.getOutCardWhileFriendCanWinInSun(chairId)
  979. }
  980. } else if outedCount == 2 || outedCount == 3 {
  981. // 队友得分
  982. outCard = ss.getOutCardWhileFriendCanWinInSun(chairId)
  983. if isValidCard(outCard) {
  984. return outCard
  985. }
  986. // 自己得分
  987. enemyChairOfNotOutCard := getPreviousChair(chairId)
  988. if outedCount == 3 {
  989. enemyChairOfNotOutCard = -1
  990. }
  991. if r < ss.fakers[chairId].actionProb {
  992. outCard = ss.getOutCardWhileSelfCanWinInSun(chairId, enemyChairOfNotOutCard)
  993. }
  994. }
  995. // 不得分
  996. if !isValidCard(outCard) {
  997. outCard = ss.getMinValueCardInSun(chairId)
  998. }
  999. return outCard
  1000. }
  1001. func (ss *simulatorScene) getBigCardsThanAllEnemyHandCardsInSun(chairId, roundType int) []int {
  1002. bigCards := []int{}
  1003. for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
  1004. card := ss.fakers[chairId].handCards[i]
  1005. cardType := roundType
  1006. if roundType == CardType_Invalid {
  1007. cardType = getCardType(card)
  1008. }
  1009. isAllBig := true
  1010. for n := 0; n < CHAIR_COUNT; n++ {
  1011. //if isSameTeam(n, chairId) {
  1012. if n == chairId {
  1013. continue
  1014. }
  1015. if !ss.isBiggerThanAll(card, cardType, ss.fakers[n].handCards) {
  1016. isAllBig = false
  1017. break
  1018. }
  1019. }
  1020. if isAllBig {
  1021. bigCards = append(bigCards, card)
  1022. }
  1023. }
  1024. return bigCards
  1025. }
  1026. /* 暂时做屏蔽,先取getMinValueCardWhileFriendHaveBigCardsInSun让机器人做正常思维
  1027. func (ss *simulatorScene) getMaxValueCardWhileFriendHaveBigCardsInSun(chairId int, bigCards []int) int {
  1028. outCard := CARD_COUNT
  1029. maxCardValue := -1
  1030. for i := 0; i < len(bigCards); i++ {
  1031. for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
  1032. if getCardType(ss.fakers[chairId].handCards[j]) != getCardType(bigCards[i]) {
  1033. continue
  1034. }
  1035. value := getCardCompareValue(ss.fakers[chairId].handCards[j], ss.trumpType)
  1036. if value > maxCardValue {
  1037. maxCardValue = value
  1038. outCard = ss.fakers[chairId].handCards[j]
  1039. }
  1040. }
  1041. }
  1042. return outCard
  1043. }
  1044. */
  1045. func (ss *simulatorScene) getMinValueCardWhileFriendHaveBigCardsInSun(chairId int, bigCards []int) int {
  1046. outCard := CARD_COUNT
  1047. minCardValue := 100
  1048. for i := 0; i < len(bigCards); i++ {
  1049. for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
  1050. if getCardType(ss.fakers[chairId].handCards[j]) != getCardType(bigCards[i]) {
  1051. continue
  1052. }
  1053. value := getCardCompareValue(ss.fakers[chairId].handCards[j], ss.trumpType)
  1054. if value < minCardValue && getCardValue(ss.fakers[chairId].handCards[j]) != CardValue10 {
  1055. minCardValue = value
  1056. outCard = ss.fakers[chairId].handCards[j]
  1057. }
  1058. }
  1059. }
  1060. return outCard
  1061. }
  1062. func (ss *simulatorScene) getOutCardWhileSelfCanWinInSun(chairId, enemyChairOfNotOutCard int) int {
  1063. bigCards := ss.getBigCardsThanOutCardsInSun(chairId)
  1064. if len(bigCards) == 0 {
  1065. return CARD_COUNT
  1066. }
  1067. newBigCards := []int{}
  1068. if enemyChairOfNotOutCard == -1 {
  1069. newBigCards = append(newBigCards, bigCards...)
  1070. } else {
  1071. for i := 0; i < len(bigCards); i++ {
  1072. if ss.isBiggerThanAll(bigCards[i], ss.roundType, ss.fakers[enemyChairOfNotOutCard].handCards) {
  1073. newBigCards = append(newBigCards, bigCards[i])
  1074. }
  1075. }
  1076. }
  1077. if len(newBigCards) == 0 {
  1078. return CARD_COUNT
  1079. }
  1080. maxCards := []int{}
  1081. if enemyChairOfNotOutCard == -1 {
  1082. maxCards = ss.getBigCardsThanAllEnemyHandCardsInSun(chairId, ss.roundType)
  1083. } else {
  1084. enemyChairOfOutedCard := getFriendChair(enemyChairOfNotOutCard)
  1085. for i := 0; i < len(newBigCards); i++ {
  1086. if ss.isBiggerThanAll(newBigCards[i], ss.roundType, ss.fakers[enemyChairOfOutedCard].handCards) {
  1087. maxCards = append(maxCards, newBigCards[i])
  1088. }
  1089. }
  1090. }
  1091. if len(maxCards) == 0 {
  1092. return ss.getMaxValueCardInCards(newBigCards, true)
  1093. }
  1094. cards := ss.getCardsExpectMaxCardsInBigCards(newBigCards, maxCards)
  1095. if len(cards) == 0 {
  1096. return newBigCards[0]
  1097. }
  1098. return ss.getMaxValueCardInCards(cards, true)
  1099. }
  1100. func (ss *simulatorScene) getBigCardsThanOutCardsInSun(chairId int) []int {
  1101. bigCards := []int{}
  1102. for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
  1103. if getCardType(ss.fakers[chairId].handCards[i]) != ss.roundType {
  1104. continue
  1105. }
  1106. if ss.isBiggerThanAll(ss.fakers[chairId].handCards[i], ss.roundType, ss.getRoundCards()) {
  1107. bigCards = append(bigCards, ss.fakers[chairId].handCards[i])
  1108. }
  1109. }
  1110. return bigCards
  1111. }
  1112. func (ss *simulatorScene) getOutCardWhileFriendCanWinInSun(chairId int) int {
  1113. outCards := ss.getRoundCards()
  1114. isFriendBig := false
  1115. if outCards[getFriendChair(chairId)] == CARD_COUNT {
  1116. if ss.isBiggerThanAll(outCards[getNextChair(chairId)], ss.roundType, ss.fakers[getFriendChair(chairId)].handCards) {
  1117. return CARD_COUNT
  1118. }
  1119. for i := 0; i < len(ss.fakers[getFriendChair(chairId)].handCards); i++ {
  1120. if getCardType(ss.fakers[getFriendChair(chairId)].handCards[i]) != ss.roundType {
  1121. continue
  1122. }
  1123. if ss.isBiggerThanAll(ss.fakers[getFriendChair(chairId)].handCards[i], ss.roundType,
  1124. ss.fakers[getPreviousChair(chairId)].handCards) {
  1125. isFriendBig = true
  1126. break
  1127. }
  1128. }
  1129. } else {
  1130. winner := ss.getWinner(outCards, ss.roundType)
  1131. if !isSameTeam(winner, chairId) {
  1132. return CARD_COUNT
  1133. }
  1134. if outCards[getPreviousChair(chairId)] != CARD_COUNT {
  1135. isFriendBig = true
  1136. } else {
  1137. if ss.isBiggerThanAll(outCards[getFriendChair(chairId)], ss.roundType,
  1138. ss.fakers[getPreviousChair(chairId)].handCards) {
  1139. isFriendBig = true
  1140. }
  1141. }
  1142. }
  1143. if !isFriendBig {
  1144. return CARD_COUNT
  1145. }
  1146. if ss.getRoundOutedPlayerCount() < 3 {
  1147. return ss.getMinValueCardInSun(chairId)
  1148. }
  1149. cardType := ss.roundType
  1150. bRoundType := true
  1151. sortedCards := sortCards(ss.fakers[chairId].handCards)
  1152. if len(sortedCards[ss.roundType]) == 0 {
  1153. cardType = CardType_Invalid
  1154. bRoundType = false
  1155. }
  1156. bigCards := ss.getBigCardsThanAllEnemyHandCardsInSun(chairId, cardType)
  1157. return ss.getMaxValueCardExpectBigCardsInSun(chairId, bigCards, bRoundType)
  1158. }
  1159. func (ss *simulatorScene) getMaxValueCardExpectBigCardsInSun(chairId int, bigCards []int, haveRoundType bool) int {
  1160. outCard := CARD_COUNT
  1161. maxValue := -1
  1162. for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
  1163. card := ss.fakers[chairId].handCards[i]
  1164. if getCardType(card) != ss.roundType && haveRoundType {
  1165. continue
  1166. }
  1167. bFound := false
  1168. for j := 0; j < len(bigCards); j++ {
  1169. if card == bigCards[j] {
  1170. bFound = true
  1171. break
  1172. }
  1173. }
  1174. if !bFound {
  1175. value := getCardPoint(card, ss.trumpType)
  1176. if value > maxValue {
  1177. maxValue = value
  1178. outCard = card
  1179. }
  1180. }
  1181. }
  1182. return outCard
  1183. }
  1184. func (ss *simulatorScene) getMinValueCardInSun(chairId int) int {
  1185. minCardValue := 100
  1186. card := CARD_COUNT
  1187. if ss.roundType == CardType_Invalid && len(ss.fakers[chairId].handCards) > 2 {
  1188. sortedCard := sortCards(ss.fakers[chairId].handCards)
  1189. for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
  1190. if len(sortedCard[getCardType(ss.fakers[chairId].handCards[j])]) == 2 &&
  1191. !ss.canOutMiniCardWhileFirstOut(sortedCard[getCardType(ss.fakers[chairId].handCards[j])], chairId) {
  1192. continue
  1193. }
  1194. value := getCardPoint(ss.fakers[chairId].handCards[j], ss.trumpType)
  1195. if value < minCardValue {
  1196. minCardValue = value
  1197. card = ss.fakers[chairId].handCards[j]
  1198. }
  1199. }
  1200. if isValidCard(card) {
  1201. return card
  1202. }
  1203. }
  1204. for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
  1205. if getCardType(ss.fakers[chairId].handCards[j]) != ss.roundType {
  1206. continue
  1207. }
  1208. value := getCardPoint(ss.fakers[chairId].handCards[j], ss.trumpType)
  1209. if value < minCardValue {
  1210. minCardValue = value
  1211. card = ss.fakers[chairId].handCards[j]
  1212. }
  1213. }
  1214. if isValidCard(card) {
  1215. return card
  1216. }
  1217. if ss.roundType == CardType_Invalid {
  1218. priorityList := []int{1, 1, 1, 1}
  1219. for i := CardType_Diamond; i <= CardType_Spade; i++ {
  1220. if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValueA)) {
  1221. priorityList[i] = 2
  1222. } else {
  1223. if ss.fakers[getFriendChair(chairId)].isExistTheCardInOutedCards(genACard(i, CardValue10)) {
  1224. priorityList[i] = 0
  1225. }
  1226. }
  1227. }
  1228. for l := 2; l >= 0; l-- {
  1229. for i := 0; i < len(ss.fakers[chairId].handCards); i++ {
  1230. if priorityList[getCardType(ss.fakers[chairId].handCards[i])] == l {
  1231. value := getCardPoint(ss.fakers[chairId].handCards[i], ss.trumpType)
  1232. if value < minCardValue {
  1233. minCardValue = value
  1234. card = ss.fakers[chairId].handCards[i]
  1235. }
  1236. }
  1237. }
  1238. if isValidCard(card) {
  1239. return card
  1240. }
  1241. }
  1242. }
  1243. for j := 0; j < len(ss.fakers[chairId].handCards); j++ {
  1244. value := getCardPoint(ss.fakers[chairId].handCards[j], ss.trumpType)
  1245. if value < minCardValue {
  1246. minCardValue = value
  1247. card = ss.fakers[chairId].handCards[j]
  1248. }
  1249. }
  1250. return card
  1251. }
  1252. /****************************** Sun End ******************************/
  1253. /****************************** Hokum START ******************************/
  1254. func (ss *simulatorScene) getBestOutCardInHokum(chairId int) int {
  1255. outCard := CARD_COUNT
  1256. outedCount := ss.getRoundOutedPlayerCount()
  1257. r := rand.Intn(100)
  1258. if outedCount == 0 {
  1259. // 先出主牌大牌
  1260. trumpBigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.trumpType, ss.isClose, !ss.isClose, true)
  1261. maxTrumpCards := []int{}
  1262. for n := 0; n < len(trumpBigCards); n++ {
  1263. if ss.isBiggerThanAll(trumpBigCards[n], ss.trumpType, ss.fakers[getFriendChair(chairId)].handCards) {
  1264. maxTrumpCards = append(maxTrumpCards, trumpBigCards[n])
  1265. }
  1266. }
  1267. if len(maxTrumpCards) > 0 && !ss.isClose && ss.isOtherPlayerHaveTrumpCardInHokum(chairId) {
  1268. return maxTrumpCards[rand.Intn(len(maxTrumpCards))]
  1269. }
  1270. // 自己得分
  1271. bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, CardType_Invalid, ss.isClose, !ss.isClose, true)
  1272. if len(bigCards) > 0 {
  1273. // 再出非主牌大牌
  1274. sortedCards := sortCards(bigCards)
  1275. randStartType := rand.Intn(CHAIR_COUNT)
  1276. for i := CardType_Diamond; i <= CardType_Spade; i++ {
  1277. t := (randStartType + i) % CHAIR_COUNT
  1278. if t == ss.trumpType || len(sortedCards[t]) == 0 {
  1279. continue
  1280. }
  1281. if len(sortedCards[t]) == 1 {
  1282. return sortedCards[t][0]
  1283. }
  1284. if !ss.canBigOnNextRoundInHokum(chairId, t) {
  1285. return ss.getMaxValueCardInCards(sortedCards[t], true)
  1286. } else {
  1287. return sortedCards[t][rand.Intn(len(sortedCards[t]))]
  1288. }
  1289. }
  1290. cardType := CardType_Invalid
  1291. // 再去判断队友能大且是出非主牌
  1292. cardType = ss.getCardTypeWhileFriendCanWinInHokum(chairId)
  1293. if cardType != CardType_Invalid && cardType != ss.trumpType {
  1294. sortedCards := sortCards(ss.fakers[chairId].handCards)
  1295. return ss.getMinValueCardInCards(sortedCards[cardType])
  1296. }
  1297. // 最后出主牌大牌,如果敌方有主牌就出最小大牌
  1298. if ss.isEnemyExistTrumpTypeInHokum(chairId) {
  1299. return bigCards[0]
  1300. } else {
  1301. return ss.getMinValueCardInHokum(chairId)
  1302. }
  1303. }
  1304. if r < ss.fakers[chairId].actionProb {
  1305. // 队友得分
  1306. cardType := ss.getCardTypeWhileFriendCanWinInHokum(chairId)
  1307. if cardType != CardType_Invalid && (cardType != ss.trumpType || len(ss.fakers[chairId].handCards) < NORMAL_HOLD_CARD-1) {
  1308. sortedCards := sortCards(ss.fakers[chairId].handCards)
  1309. return ss.getMinValueCardInCards(sortedCards[cardType])
  1310. }
  1311. }
  1312. } else if outedCount == 1 {
  1313. // 自己得分
  1314. outCard = ss.getOutCardWhileSelfCanWinInHokum(chairId)
  1315. if isValidCard(outCard) {
  1316. // 如果自己出的是主牌,则判断队友能否赢牌,且队友赢牌的出牌花色不为主牌花色
  1317. if getCardType(outCard) == ss.trumpType && ss.roundType != ss.trumpType {
  1318. card, cardType := ss.getOutCardWhileFriendCanWinInHokum(chairId)
  1319. if isValidCard(card) && cardType != ss.trumpType {
  1320. return card
  1321. }
  1322. }
  1323. return outCard
  1324. }
  1325. if r < ss.fakers[chairId].actionProb {
  1326. // 队友得分
  1327. outCard, _ = ss.getOutCardWhileFriendCanWinInHokum(chairId)
  1328. }
  1329. } else if outedCount == 2 {
  1330. // 队友得分
  1331. outCard, _ = ss.getOutCardWhileFriendCanWinInHokum(chairId)
  1332. if isValidCard(outCard) {
  1333. return outCard
  1334. }
  1335. if r < ss.fakers[chairId].actionProb {
  1336. // 自己得分
  1337. outCard = ss.getOutCardWhileSelfCanWinInHokum(chairId)
  1338. }
  1339. } else if outedCount == 3 {
  1340. // 队友得分
  1341. outCards := ss.getRoundCards()
  1342. winner := ss.getWinner(outCards, ss.roundType)
  1343. if isSameTeam(winner, chairId) {
  1344. return ss.getOutCardWhileFriendIsWinnerInHokum(chairId)
  1345. }
  1346. if r < ss.fakers[chairId].actionProb {
  1347. // 自己得分
  1348. outCard = ss.getOutCardWhileSelfCanWinInHokum(chairId)
  1349. }
  1350. }
  1351. // 不得分
  1352. if !isValidCard(outCard) {
  1353. outCard = ss.getMinValueCardInHokum(chairId)
  1354. }
  1355. return outCard
  1356. }
  1357. func (ss *simulatorScene) isOtherPlayerHaveTrumpCardInHokum(chairId int) bool {
  1358. isEnemeyTrumpHaveRecord := false
  1359. for i := 0; i < CHAIR_COUNT; i++ {
  1360. if isSameTeam(chairId, i) {
  1361. continue
  1362. }
  1363. if ss.fakers[i].cardTypesRecord[ss.trumpType] == 1 {
  1364. isEnemeyTrumpHaveRecord = true
  1365. }
  1366. }
  1367. if !isEnemeyTrumpHaveRecord {
  1368. return false
  1369. }
  1370. for i := 0; i < CHAIR_COUNT; i++ {
  1371. if i == chairId {
  1372. continue
  1373. }
  1374. if ss.fakers[i].isExistTheCardTypeInHand(ss.trumpType) {
  1375. return true
  1376. }
  1377. }
  1378. return false
  1379. }
  1380. func (ss *simulatorScene) isEnemyExistTrumpTypeInHokum(chairId int) bool {
  1381. for i := 0; i < CHAIR_COUNT; i++ {
  1382. if isSameTeam(i, chairId) {
  1383. continue
  1384. }
  1385. sortedCards := sortCards(ss.fakers[i].handCards)
  1386. if len(sortedCards[ss.trumpType]) > 0 {
  1387. return true
  1388. }
  1389. }
  1390. return false
  1391. }
  1392. func (ss *simulatorScene) getBigCardsThanAllEnemyHandCardsInHokum(chairId, roundType int, isClose, isIncludeTrump,
  1393. isCheckAllEnemy bool) []int {
  1394. bigCards := []int{}
  1395. handCards := []int{}
  1396. if len(ss.fakers[chairId].bigCards) == 0 {
  1397. handCards = append(handCards, ss.fakers[chairId].handCards...)
  1398. } else {
  1399. handCards = append(handCards, ss.fakers[chairId].bigCards...)
  1400. }
  1401. isAllTrump := true
  1402. // 如果roundType为CardType_Invaild,则是先找非主牌花色中的大牌,如果roundType不为CardType_Invaild,则是找相同花色的大牌
  1403. for i := 0; i < len(handCards); i++ {
  1404. if getCardType(handCards[i]) == ss.trumpType {
  1405. continue
  1406. }
  1407. isAllTrump = false
  1408. if roundType != CardType_Invalid && getCardType(handCards[i]) != roundType {
  1409. continue
  1410. }
  1411. isAllBig := true
  1412. for j := 0; j < CHAIR_COUNT; j++ {
  1413. if isSameTeam(chairId, j) {
  1414. //if j == chairId {
  1415. continue
  1416. }
  1417. // 如果isCheckAllEnemy为true,则不找已出牌玩家
  1418. if ss.fakers[j].currentCard != CARD_COUNT && !isCheckAllEnemy {
  1419. continue
  1420. }
  1421. sortedCards := sortCards(ss.fakers[j].handCards)
  1422. if len(sortedCards[getCardType(handCards[i])]) == 0 && !isSameTeam(chairId, j) && len(sortedCards[ss.trumpType]) > 0 {
  1423. isAllBig = false
  1424. break
  1425. }
  1426. if !ss.isBiggerThanAll(handCards[i], getCardType(handCards[i]), sortedCards[getCardType(handCards[i])]) {
  1427. isAllBig = false
  1428. break
  1429. }
  1430. }
  1431. if isAllBig {
  1432. bigCards = append(bigCards, handCards[i])
  1433. }
  1434. }
  1435. if len(bigCards) > 0 {
  1436. return bigCards
  1437. }
  1438. // 能否出主牌
  1439. if isClose && !isAllTrump {
  1440. return bigCards
  1441. }
  1442. // 是否去找主牌
  1443. if !isIncludeTrump {
  1444. return bigCards
  1445. }
  1446. // 去找主牌能否有大牌
  1447. for i := 0; i < len(handCards); i++ {
  1448. if getCardType(handCards[i]) != ss.trumpType {
  1449. continue
  1450. }
  1451. isAllBig := true
  1452. for j := 0; j < CHAIR_COUNT; j++ {
  1453. if isSameTeam(chairId, j) {
  1454. //if chairId == j {
  1455. continue
  1456. }
  1457. if ss.fakers[j].currentCard != CARD_COUNT && !isCheckAllEnemy {
  1458. continue
  1459. }
  1460. sortedCards := sortCards(ss.fakers[j].handCards)
  1461. if !ss.isBiggerThanAll(handCards[i], ss.trumpType, sortedCards[ss.trumpType]) {
  1462. isAllBig = false
  1463. break
  1464. }
  1465. }
  1466. if isAllBig {
  1467. bigCards = append(bigCards, handCards[i])
  1468. }
  1469. }
  1470. return bigCards
  1471. }
  1472. // 玩家首出情况下,获取队友可赢牌的花色
  1473. func (ss *simulatorScene) getCardTypeWhileFriendCanWinInHokum(chairId int) int {
  1474. friendBigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(getFriendChair(chairId), CardType_Invalid, false, true, false)
  1475. sortedCards := sortCards(ss.fakers[chairId].handCards)
  1476. // 我出非主牌,队友出相同非主牌可赢
  1477. if len(friendBigCards) > 0 {
  1478. for i := 0; i < len(friendBigCards); i++ {
  1479. if getCardType(friendBigCards[i]) == ss.trumpType {
  1480. continue
  1481. }
  1482. if len(sortedCards[getCardType(friendBigCards[i])]) == 1 &&
  1483. getCardValue(sortedCards[getCardType(friendBigCards[i])][0]) == CardValue10 {
  1484. continue
  1485. }
  1486. if len(sortedCards[getCardType(friendBigCards[i])]) > 0 {
  1487. return getCardType(friendBigCards[i])
  1488. }
  1489. }
  1490. }
  1491. // 我出非主牌,队友出主牌可赢
  1492. friendSortedCards := sortCards(ss.fakers[getFriendChair(chairId)].handCards)
  1493. if len(friendSortedCards[ss.trumpType]) == 0 {
  1494. return CardType_Invalid
  1495. }
  1496. for cardType := CardType_Diamond; cardType <= CardType_Spade; cardType++ {
  1497. if cardType == ss.trumpType {
  1498. continue
  1499. }
  1500. if len(sortedCards[cardType]) == 0 {
  1501. continue
  1502. }
  1503. if len(friendSortedCards[cardType]) > 0 {
  1504. continue
  1505. }
  1506. // 队友出主牌大于敌方
  1507. if ss.isExistTrumpCardBiggerThanAllEmenyInHokum(friendSortedCards[ss.trumpType], chairId, cardType) {
  1508. if len(sortedCards[cardType]) > 1 || getCardValue(sortedCards[cardType][0]) != CardValue10 {
  1509. return cardType
  1510. }
  1511. }
  1512. }
  1513. // 我出主牌,队友出主牌可赢
  1514. if (ss.isClose && len(sortedCards[ss.trumpType]) != len(ss.fakers[chairId].handCards)) ||
  1515. len(sortedCards[ss.trumpType]) == 0 {
  1516. return CardType_Invalid
  1517. }
  1518. for i := 0; i < len(friendBigCards); i++ {
  1519. if getCardType(friendBigCards[i]) == ss.trumpType {
  1520. if value_trump[getCardValue(sortedCards[ss.trumpType][0])] < value_trump[CardValue10] {
  1521. return ss.trumpType
  1522. }
  1523. }
  1524. }
  1525. return CardType_Invalid
  1526. }
  1527. func (ss *simulatorScene) isExistTrumpCardBiggerThanAllEmenyInHokum(trumpCards []int, chairId, roundType int) bool {
  1528. for i := 0; i < len(trumpCards); i++ {
  1529. if getCardType(trumpCards[i]) != ss.trumpType {
  1530. continue
  1531. }
  1532. isBig := true
  1533. for n := 0; n < CHAIR_COUNT; n++ {
  1534. if isSameTeam(chairId, n) {
  1535. continue
  1536. }
  1537. sortedCards := sortCards(ss.fakers[n].handCards)
  1538. if len(sortedCards[roundType]) > 0 || len(sortedCards[ss.trumpType]) == 0 {
  1539. continue
  1540. }
  1541. if !ss.isBiggerThanAll(trumpCards[i], roundType, sortedCards[ss.trumpType]) {
  1542. isBig = false
  1543. break
  1544. }
  1545. }
  1546. if isBig {
  1547. return true
  1548. }
  1549. }
  1550. return false
  1551. }
  1552. func (ss *simulatorScene) getOutCardWhileSelfCanWinInHokum(chairId int) int {
  1553. outedCards := ss.getRoundCards()
  1554. // 先找相同花色比未出牌敌方玩家大的牌
  1555. bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.roundType, false, ss.roundType == ss.trumpType, false)
  1556. if len(bigCards) > 0 {
  1557. // 再找比所有敌方玩家相同花色都大的牌
  1558. maxCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.roundType, false, ss.roundType == ss.trumpType, true)
  1559. // 没出牌的敌方只剩最后一张牌,且有主牌,出最大牌或者出牌的玩家出的是最后一张牌
  1560. if ss.roundType != ss.trumpType && len(maxCards) > 0 {
  1561. enemySortedCards1 := sortCards(ss.fakers[getPreviousChair(chairId)].handCards)
  1562. enemySortedCards2 := sortCards(ss.fakers[getNextChair(chairId)].handCards)
  1563. if (outedCards[getPreviousChair(chairId)] == CARD_COUNT &&
  1564. ((len(enemySortedCards1[ss.roundType]) == 1 && len(enemySortedCards1[ss.trumpType]) > 0) ||
  1565. (len(enemySortedCards2[ss.roundType]) == 0 && len(enemySortedCards2[ss.trumpType]) > 0))) ||
  1566. (outedCards[getPreviousChair(chairId)] != CARD_COUNT &&
  1567. ((len(enemySortedCards1[ss.roundType]) == 0 && len(enemySortedCards1[ss.trumpType]) > 0) ||
  1568. (len(enemySortedCards2[ss.roundType]) == 0 && len(enemySortedCards2[ss.trumpType]) > 0))) {
  1569. maxValue := -1
  1570. outCard := CARD_COUNT
  1571. for i := 0; i < len(maxCards); i++ {
  1572. outedCards[chairId] = maxCards[i]
  1573. if chairId == ss.getWinner(outedCards, ss.roundType) {
  1574. value := getCardPoint(maxCards[i], ss.trumpType)
  1575. if value > maxValue {
  1576. maxValue = value
  1577. outCard = maxCards[i]
  1578. }
  1579. }
  1580. outedCards[chairId] = CARD_COUNT
  1581. }
  1582. if isValidCard(outCard) {
  1583. return outCard
  1584. }
  1585. }
  1586. }
  1587. cards := ss.getCardsExpectMaxCardsInBigCards(bigCards, maxCards)
  1588. if len(cards) > 0 {
  1589. maxValue := -1
  1590. outCard := CARD_COUNT
  1591. for i := 0; i < len(cards); i++ {
  1592. outedCards[chairId] = cards[i]
  1593. if chairId == ss.getWinner(outedCards, ss.roundType) {
  1594. value := getCardPoint(cards[i], ss.trumpType)
  1595. if value > maxValue {
  1596. maxValue = value
  1597. outCard = cards[i]
  1598. }
  1599. }
  1600. outedCards[chairId] = CARD_COUNT
  1601. }
  1602. if isValidCard(outCard) {
  1603. return outCard
  1604. }
  1605. }
  1606. for i := 0; i < len(bigCards); i++ {
  1607. outedCards[chairId] = bigCards[i]
  1608. if chairId == ss.getWinner(outedCards, ss.roundType) {
  1609. return bigCards[i]
  1610. }
  1611. outedCards[chairId] = CARD_COUNT
  1612. }
  1613. }
  1614. handCards := []int{}
  1615. if len(ss.fakers[chairId].bigCards) == 0 {
  1616. handCards = append(handCards, ss.fakers[chairId].handCards...)
  1617. } else {
  1618. handCards = append(handCards, ss.fakers[chairId].bigCards...)
  1619. }
  1620. sortedCards := sortCards(handCards)
  1621. if len(sortedCards[ss.roundType]) > 0 {
  1622. return CARD_COUNT
  1623. }
  1624. if len(sortedCards[ss.trumpType]) == 0 {
  1625. return CARD_COUNT
  1626. }
  1627. // 没有相同花色,roundType为非主牌,我有主牌大于未出牌的敌方
  1628. bigCards = ss.getTrumpCardBiggerThanAllEmenyInHokum(sortedCards[ss.trumpType], chairId, ss.roundType)
  1629. if len(bigCards) > 0 {
  1630. // 查找我是否主牌大于所有敌方玩家手牌
  1631. maxCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.trumpType, false, true, true)
  1632. cards := ss.getCardsExpectMaxCardsInBigCards(bigCards, maxCards)
  1633. if len(cards) > 0 {
  1634. maxValue := -1
  1635. outCard := CARD_COUNT
  1636. for i := 0; i < len(cards); i++ {
  1637. outedCards[chairId] = cards[i]
  1638. if chairId == ss.getWinner(outedCards, ss.roundType) {
  1639. value := getCardPoint(cards[i], ss.trumpType)
  1640. if value > maxValue {
  1641. maxValue = value
  1642. outCard = cards[i]
  1643. }
  1644. }
  1645. outedCards[chairId] = CARD_COUNT
  1646. }
  1647. if isValidCard(outCard) {
  1648. return outCard
  1649. }
  1650. }
  1651. for i := 0; i < len(bigCards); i++ {
  1652. outedCards[chairId] = bigCards[i]
  1653. if chairId == ss.getWinner(outedCards, ss.roundType) {
  1654. return bigCards[i]
  1655. }
  1656. outedCards[chairId] = CARD_COUNT
  1657. }
  1658. }
  1659. return CARD_COUNT
  1660. }
  1661. func (ss *simulatorScene) getTrumpCardBiggerThanAllEmenyInHokum(trumpCards []int, chairId, roundType int) []int {
  1662. bigCards := []int{}
  1663. for i := 0; i < len(trumpCards); i++ {
  1664. if getCardType(trumpCards[i]) != ss.trumpType {
  1665. continue
  1666. }
  1667. isBig := true
  1668. for n := 0; n < CHAIR_COUNT; n++ {
  1669. if isSameTeam(chairId, n) {
  1670. //if chairId == n {
  1671. continue
  1672. }
  1673. if ss.fakers[n].currentCard != CARD_COUNT {
  1674. continue
  1675. }
  1676. sortedCards := sortCards(ss.fakers[n].handCards)
  1677. if roundType == ss.trumpType && len(sortedCards[ss.trumpType]) == 0 {
  1678. continue
  1679. }
  1680. if (len(sortedCards[roundType]) > 0 || len(sortedCards[ss.trumpType]) == 0) && roundType != ss.trumpType {
  1681. continue
  1682. }
  1683. if !ss.isBiggerThanAll(trumpCards[i], roundType, sortedCards[ss.trumpType]) {
  1684. isBig = false
  1685. break
  1686. }
  1687. }
  1688. if isBig {
  1689. bigCards = append(bigCards, trumpCards[i])
  1690. }
  1691. }
  1692. return bigCards
  1693. }
  1694. func (ss *simulatorScene) getOutCardWhileFriendCanWinInHokum(chairId int) (int, int) {
  1695. outedCards := ss.getRoundCards()
  1696. if outedCards[getFriendChair(chairId)] == CARD_COUNT {
  1697. // 先找相同花色比未出牌玩家大的牌
  1698. bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(getFriendChair(chairId), ss.roundType, false,
  1699. ss.roundType == ss.trumpType, false)
  1700. sortedCards := sortCards(ss.fakers[getFriendChair(chairId)].handCards)
  1701. if len(bigCards) == 0 && len(sortedCards[ss.roundType]) > 0 {
  1702. return CARD_COUNT, CardType_Invalid
  1703. }
  1704. for i := 0; i < len(bigCards); i++ {
  1705. outedCards[getFriendChair(chairId)] = bigCards[i]
  1706. if getFriendChair(chairId) == ss.getWinner(outedCards, ss.roundType) {
  1707. return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(bigCards[i])
  1708. }
  1709. outedCards[getFriendChair(chairId)] = CARD_COUNT
  1710. }
  1711. if len(sortedCards[ss.roundType]) > 0 {
  1712. return CARD_COUNT, CardType_Invalid
  1713. }
  1714. if len(sortedCards[ss.trumpType]) == 0 {
  1715. return CARD_COUNT, CardType_Invalid
  1716. }
  1717. // 没有相同花色,roundType为非主牌,我有主牌大于未出牌的敌方
  1718. bigCards = ss.getTrumpCardBiggerThanAllEmenyInHokum(sortedCards[ss.trumpType], chairId, ss.roundType)
  1719. if len(bigCards) == 0 {
  1720. return CARD_COUNT, CardType_Invalid
  1721. }
  1722. for i := 0; i < len(bigCards); i++ {
  1723. outedCards[getFriendChair(chairId)] = bigCards[i]
  1724. if getFriendChair(chairId) == ss.getWinner(outedCards, ss.roundType) {
  1725. return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(bigCards[i])
  1726. }
  1727. outedCards[getFriendChair(chairId)] = CARD_COUNT
  1728. }
  1729. return CARD_COUNT, CardType_Invalid
  1730. }
  1731. if ss.getWinner(outedCards, ss.roundType) != getFriendChair(chairId) {
  1732. return CARD_COUNT, CardType_Invalid
  1733. }
  1734. enemySortedCards := sortCards(ss.fakers[getPreviousChair(chairId)].handCards)
  1735. if len(enemySortedCards[ss.roundType]) > 0 {
  1736. if !ss.isBiggerThanAll(outedCards[getFriendChair(chairId)], ss.roundType, enemySortedCards[ss.roundType]) {
  1737. return CARD_COUNT, CardType_Invalid
  1738. }
  1739. return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(outedCards[getFriendChair(chairId)])
  1740. }
  1741. if ss.isBiggerThanAll(outedCards[getFriendChair(chairId)], ss.roundType, enemySortedCards[ss.trumpType]) {
  1742. return ss.getOutCardWhileFriendIsWinnerInHokum(chairId), getCardType(outedCards[getFriendChair(chairId)])
  1743. }
  1744. return CARD_COUNT, CardType_Invalid
  1745. }
  1746. func (ss *simulatorScene) getOutCardWhileFriendIsWinnerInHokum(chairId int) int {
  1747. sortedCards := sortCards(ss.fakers[chairId].handCards)
  1748. if len(sortedCards[ss.roundType]) > 0 {
  1749. maxCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, ss.roundType, false,
  1750. ss.roundType == ss.trumpType, true)
  1751. if len(maxCards) == 0 {
  1752. return ss.getMaxValueCardInCards(sortedCards[ss.roundType], false)
  1753. }
  1754. if !ss.canBigOnNextRoundInHokum(chairId, ss.roundType) {
  1755. return ss.getMaxValueCardInCards(sortedCards[ss.roundType], false)
  1756. }
  1757. cards := ss.getCardsExpectMaxCardsInBigCards(sortedCards[ss.roundType], maxCards)
  1758. if len(cards) == 0 {
  1759. return ss.getMinValueCardInCards(maxCards)
  1760. }
  1761. return ss.getMaxValueCardInCards(cards, false)
  1762. }
  1763. bigCards := ss.getBigCardsThanAllEnemyHandCardsInHokum(chairId, CardType_Invalid, false, true, true)
  1764. return ss.getMaxValueCardExpectBigCardsInHokum(chairId, bigCards)
  1765. }
  1766. func (ss *simulatorScene) canBigOnNextRoundInHokum(chairId, roundType int) bool {
  1767. if ss.trumpType == roundType {
  1768. return true
  1769. }
  1770. outedCards := ss.getRoundCards()
  1771. for n := 0; n < CHAIR_COUNT; n++ {
  1772. if isSameTeam(n, chairId) {
  1773. //if n == chairId {
  1774. continue
  1775. }
  1776. enemySortedCards := sortCards(ss.fakers[n].handCards)
  1777. if outedCards[n] != CARD_COUNT && len(enemySortedCards[roundType]) == 0 && len(enemySortedCards[ss.trumpType]) > 0 {
  1778. return false
  1779. }
  1780. if outedCards[n] == CARD_COUNT && len(enemySortedCards[roundType]) <= 1 && len(enemySortedCards[ss.trumpType]) > 0 {
  1781. return false
  1782. }
  1783. }
  1784. return true
  1785. }
  1786. func (ss *simulatorScene) getMaxValueCardExpectBigCardsInHokum(chairId int, bigCards []int) int {
  1787. handCards := []int{}
  1788. if len(ss.fakers[chairId].bigCards) == 0 {
  1789. handCards = append(handCards, ss.fakers[chairId].handCards...)
  1790. } else {
  1791. handCards = append(handCards, ss.fakers[chairId].bigCards...)
  1792. }
  1793. outCard := CARD_COUNT
  1794. maxValue := -1
  1795. for i := 0; i < len(handCards); i++ {
  1796. if getCardType(handCards[i]) == ss.trumpType {
  1797. continue
  1798. }
  1799. bFound := false
  1800. for j := 0; j < len(bigCards); j++ {
  1801. if handCards[i] == bigCards[j] {
  1802. bFound = true
  1803. break
  1804. }
  1805. }
  1806. if !bFound {
  1807. value := getCardPoint(handCards[i], ss.trumpType)
  1808. if value > maxValue && getCardValue(handCards[i]) != CardValueA {
  1809. maxValue = value
  1810. outCard = handCards[i]
  1811. }
  1812. }
  1813. }
  1814. if isValidCard(outCard) {
  1815. return outCard
  1816. }
  1817. for i := 0; i < len(handCards); i++ {
  1818. if getCardType(handCards[i]) == ss.trumpType {
  1819. continue
  1820. }
  1821. bFound := false
  1822. for j := 0; j < len(bigCards); j++ {
  1823. if handCards[i] == bigCards[j] {
  1824. bFound = true
  1825. break
  1826. }
  1827. }
  1828. if !bFound {
  1829. value := getCardPoint(handCards[i], ss.trumpType)
  1830. if value > maxValue {
  1831. maxValue = value
  1832. outCard = handCards[i]
  1833. }
  1834. }
  1835. }
  1836. if isValidCard(outCard) {
  1837. return outCard
  1838. }
  1839. minValue := 100
  1840. for j := 0; j < len(bigCards); j++ {
  1841. if getCardType(bigCards[j]) == ss.trumpType {
  1842. continue
  1843. }
  1844. value := getCardPoint(bigCards[j], ss.trumpType)
  1845. if value < minValue {
  1846. minValue = value
  1847. outCard = bigCards[j]
  1848. }
  1849. }
  1850. if isValidCard(outCard) {
  1851. return outCard
  1852. }
  1853. for j := 0; j < len(handCards); j++ {
  1854. value := getCardPoint(handCards[j], ss.trumpType)
  1855. if value < minValue {
  1856. minValue = value
  1857. outCard = handCards[j]
  1858. }
  1859. }
  1860. return outCard
  1861. }
  1862. func (ss *simulatorScene) getMinValueCardInHokum(chairId int) int {
  1863. minCardValue := 100
  1864. card := CARD_COUNT
  1865. handCards := []int{}
  1866. if len(ss.fakers[chairId].bigCards) == 0 {
  1867. handCards = append(handCards, ss.fakers[chairId].handCards...)
  1868. } else {
  1869. handCards = append(handCards, ss.fakers[chairId].bigCards...)
  1870. }
  1871. // 首出时手牌不少于2张,如果手上有10只剩两张该花色牌,且该花色A没有打出来,则不优先出该花色牌
  1872. if ss.roundType == CardType_Invalid && len(ss.fakers[chairId].handCards) > 2 {
  1873. sortedCards := sortCards(handCards)
  1874. for j := 0; j < len(handCards); j++ {
  1875. if getCardType(handCards[j]) == ss.trumpType {
  1876. continue
  1877. }
  1878. if len(sortedCards[getCardType(handCards[j])]) == 2 &&
  1879. !ss.canOutMiniCardWhileFirstOut(sortedCards[getCardType(handCards[j])], chairId) {
  1880. continue
  1881. }
  1882. value := getCardPoint(handCards[j], ss.trumpType)
  1883. if value < minCardValue {
  1884. minCardValue = value
  1885. card = handCards[j]
  1886. }
  1887. }
  1888. if isValidCard(card) {
  1889. return card
  1890. }
  1891. }
  1892. for j := 0; j < len(handCards); j++ {
  1893. if getCardType(handCards[j]) != ss.roundType {
  1894. continue
  1895. }
  1896. value := getCardPoint(handCards[j], ss.trumpType)
  1897. if value < minCardValue {
  1898. minCardValue = value
  1899. card = handCards[j]
  1900. }
  1901. }
  1902. if isValidCard(card) {
  1903. return card
  1904. }
  1905. for j := 0; j < len(handCards); j++ {
  1906. if getCardType(handCards[j]) == ss.trumpType {
  1907. continue
  1908. }
  1909. value := getCardPoint(handCards[j], ss.trumpType)
  1910. if value < minCardValue {
  1911. minCardValue = value
  1912. card = handCards[j]
  1913. }
  1914. }
  1915. if isValidCard(card) {
  1916. return card
  1917. }
  1918. for j := 0; j < len(handCards); j++ {
  1919. value := getCardPoint(handCards[j], ss.trumpType)
  1920. if value < minCardValue {
  1921. minCardValue = value
  1922. card = handCards[j]
  1923. }
  1924. }
  1925. return card
  1926. }
  1927. /****************************** Hokum END ******************************/
  1928. /*************************** 机器人出牌策略 end *************************/