cardcommon.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. package gamelogic
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "runtime/debug"
  6. "sort"
  7. "bet24.com/log"
  8. )
  9. /* 牌的排列顺序为
  10. 方块 梅花 红心 黑桃
  11. */
  12. const (
  13. CardType_Diamond = iota
  14. CardType_Club
  15. CardType_Heart
  16. CardType_Spade
  17. CardType_Invalid
  18. )
  19. const (
  20. CardValue7 = iota
  21. CardValue8
  22. CardValue9
  23. CardValue10
  24. CardValueJ
  25. CardValueQ
  26. CardValueK
  27. CardValueA
  28. )
  29. const (
  30. CARD_COUNT = 32 // 牌数量
  31. BUY_PHRSE_HOLD_CARD = 5 // 买牌阶段手持牌
  32. SURPLUS_SEND_CARD = 3 // 剩余发牌数量
  33. NORMAL_HOLD_CARD = 8 // 正常手持牌
  34. PUBLIC_CARD_POS = 20 // 公共牌位置
  35. )
  36. var type_desc = []string{"♦", "♣", "♥", "♠", ""}
  37. var value_desc = []string{"7", "8", "9", "10", "J", "Q", "K", "A"}
  38. var value_regular = []int{0, 0, 0, 10, 2, 3, 4, 11}
  39. var value_trump = []int{0, 0, 14, 10, 20, 3, 4, 11}
  40. func isValidCard(card int) bool {
  41. return card >= 0 && card < CARD_COUNT
  42. }
  43. func getCardHex(card int) string {
  44. if !isValidCard(card) {
  45. return "n/a"
  46. }
  47. return fmt.Sprintf("%s%s", type_desc[getCardType(card)], value_desc[getCardValue(card)])
  48. }
  49. func getCardsHex(cards []int) string {
  50. ret := "["
  51. for _, v := range cards {
  52. ret += getCardHex(v)
  53. ret += " "
  54. }
  55. ret += "]"
  56. return ret
  57. }
  58. func getCardType(card int) int {
  59. if !isValidCard(card) {
  60. log.Debug("%s", debug.Stack())
  61. return CardType_Invalid
  62. }
  63. return card / 8
  64. }
  65. func getCardValue(card int) int {
  66. if !isValidCard(card) {
  67. log.Debug("%s", debug.Stack())
  68. return -1
  69. }
  70. return card % 8
  71. }
  72. func getCardValueByDesc(desc string) int {
  73. for i := 0; i < len(value_desc); i++ {
  74. if desc == value_desc[i] {
  75. return i
  76. }
  77. }
  78. return -1
  79. }
  80. func getCardCompareValue(card, trumpType int) int {
  81. value := getCardValue(card)
  82. t := getCardType(card)
  83. if trumpType != CardType_Invalid && t == trumpType {
  84. // 因为主牌9比A大,比J小,但是9的value + value_trump[value]值为16,J为24
  85. // 但是A为18,所以这里为了提高9的比值,做个+4的特殊处理
  86. if value == CardValue9 {
  87. return (value + value_trump[value] + 4)
  88. }
  89. return (value + value_trump[value])
  90. }
  91. return (value + value_regular[value])
  92. }
  93. func getCardPoint(card, trumpType int) int {
  94. value := getCardValue(card)
  95. t := getCardType(card)
  96. if trumpType != CardType_Invalid && t == trumpType {
  97. return value_trump[value]
  98. }
  99. return value_regular[value]
  100. }
  101. func getCardSortValue(card, trumpType int) int {
  102. return getCardType(card)*100 + getCardCompareValue(card, trumpType)
  103. }
  104. func getTypeDesc(t int) string {
  105. if t >= CardType_Invalid {
  106. return "n/a"
  107. }
  108. return type_desc[t]
  109. }
  110. func getCardCount(cards []int, card int) int {
  111. if !isValidCard(card) {
  112. return 0
  113. }
  114. ret := 0
  115. for _, v := range cards {
  116. if v == card {
  117. ret++
  118. }
  119. }
  120. return ret
  121. }
  122. func getChooseTrumpDesc(data int) string {
  123. if data >= CardType_Invalid {
  124. return "SwitchSun"
  125. }
  126. return type_desc[data]
  127. }
  128. func isIncludeTheProject(handCards []int, projectType int, suit int) ([]int, bool) {
  129. cards := []int{}
  130. bInclude := false
  131. switch projectType {
  132. case PROJECT_FOURHUNDRED:
  133. if haveFourA(handCards) {
  134. bInclude = true
  135. for i := CardType_Diamond; i <= CardType_Spade; i++ {
  136. card := CardValueA + i*8
  137. cards = append(cards, card)
  138. }
  139. }
  140. case PROJECT_HUNDRED:
  141. return haveHundred(handCards, suit)
  142. case PROJECT_FIFTY:
  143. return haveFifty(handCards)
  144. case PROJECT_SIRA:
  145. return haveSira(handCards)
  146. }
  147. return cards, bInclude
  148. }
  149. func haveSira(handCards []int) ([]int, bool) {
  150. value := -1
  151. cards := []int{}
  152. bHaveSerial := false
  153. value, bHaveSerial = haveSerial(3, handCards)
  154. if bHaveSerial {
  155. for n := value - 2; n <= value; n++ {
  156. cards = append(cards, n)
  157. }
  158. }
  159. return cards, bHaveSerial
  160. }
  161. func haveFifty(handCards []int) ([]int, bool) {
  162. value := -1
  163. cards := []int{}
  164. bHaveSerial := false
  165. value, bHaveSerial = haveSerial(4, handCards)
  166. if bHaveSerial {
  167. for n := value - 3; n <= value; n++ {
  168. cards = append(cards, n)
  169. }
  170. }
  171. return cards, bHaveSerial
  172. }
  173. func haveHundred(handCards []int, suit int) ([]int, bool) {
  174. value := -1
  175. bHaveFour := false
  176. cards := []int{}
  177. bHaveSerial := false
  178. value, bHaveSerial = haveSerial(5, handCards)
  179. if bHaveSerial {
  180. for n := value - 4; n <= value; n++ {
  181. cards = append(cards, n)
  182. }
  183. return cards, true
  184. }
  185. for i := CardValue10; i <= CardValueA; i++ {
  186. if suit != Suit_Hokum && i == CardValueA {
  187. continue
  188. }
  189. count := 0
  190. for n := 0; n < len(handCards); n++ {
  191. if handCards[n]%8 == i {
  192. count++
  193. }
  194. }
  195. if count == 4 {
  196. value = i
  197. bHaveFour = true
  198. break
  199. }
  200. }
  201. if bHaveFour {
  202. for i := 0; i < 4; i++ {
  203. card := value + i*8
  204. cards = append(cards, card)
  205. }
  206. }
  207. return cards, bHaveFour
  208. }
  209. func haveSerial(length int, handCards []int) (int, bool) {
  210. bHave := false
  211. start := -1
  212. for i := CardType_Spade; i >= CardType_Diamond; i-- {
  213. bHave, start = haveSerialInAType(i, length, handCards)
  214. if bHave {
  215. break
  216. }
  217. }
  218. return start, bHave
  219. }
  220. func haveSerialInAType(cardType int, length int, handCards []int) (bool, int) {
  221. cards := []int{}
  222. for i := 0; i < len(handCards); i++ {
  223. if handCards[i]/8 == cardType {
  224. cards = append(cards, handCards[i])
  225. }
  226. }
  227. if len(cards) < length {
  228. return false, -1
  229. }
  230. sort.Slice(cards, func(i, j int) bool {
  231. return cards[i] > cards[j]
  232. })
  233. start := 0
  234. bExist := false
  235. for n := 0; n < len(cards); n++ {
  236. start = cards[n]
  237. if (n + length) > len(cards) {
  238. break
  239. }
  240. end := cards[n+length-1]
  241. if (start - end) == (length - 1) {
  242. bExist = true
  243. break
  244. }
  245. }
  246. return bExist, start
  247. }
  248. func haveFourA(handCards []int) bool {
  249. count := 0
  250. for i := 0; i < len(handCards); i++ {
  251. if handCards[i]%8 == CardValueA {
  252. count++
  253. }
  254. }
  255. return count == 4
  256. }
  257. func removeCards(handCards []int, delCards []int) []int {
  258. for j := 0; j < len(delCards); j++ {
  259. for i := 0; i < len(handCards); {
  260. if handCards[i] == delCards[j] {
  261. handCards = append(handCards[:i], handCards[i+1:]...)
  262. break
  263. } else {
  264. i++
  265. }
  266. }
  267. }
  268. return handCards
  269. }
  270. func sortCards(cards []int) [][]int {
  271. sortedCards := make([][]int, 4)
  272. for i := 0; i < len(cards); i++ {
  273. t := getCardType(cards[i])
  274. sortedCards[t] = append(sortedCards[t], cards[i])
  275. }
  276. return sortedCards
  277. }
  278. func haveCard(cards []int, card int) bool {
  279. return getCardCount(cards, card) > 0
  280. }
  281. func isScoreCard(card int, handCards []int, outedCards []int, trumpType int) bool {
  282. v := getCardValue(card)
  283. t := getCardType(card)
  284. rv := getCardCompareValue(card, trumpType)
  285. if (v == CardValueA && t != trumpType) || (v == CardValueJ && t == trumpType) {
  286. return true
  287. }
  288. for i := CardValue7; i <= CardValueA; i++ {
  289. if i == v {
  290. continue
  291. }
  292. checkCard := i + t*8
  293. if getCardCompareValue(checkCard, trumpType) < rv {
  294. continue
  295. }
  296. if !haveCard(handCards, checkCard) && !haveCard(outedCards, checkCard) {
  297. return false
  298. }
  299. }
  300. return true
  301. }
  302. func getScoreCards(handCards []int, outedCards []int, trumpType int, isFirstOutCardClose bool) []int {
  303. var scoreCards []int
  304. for i := 0; i < len(handCards); i++ {
  305. v := handCards[i]
  306. if isFirstOutCardClose && getCardType(v) == trumpType {
  307. continue
  308. }
  309. if isScoreCard(v, handCards, outedCards, trumpType) {
  310. scoreCards = append(scoreCards, v)
  311. }
  312. }
  313. return scoreCards
  314. }
  315. func getBestTrumpType(cards []int, publicCard int) int {
  316. bestType := CardType_Invalid
  317. most := -1
  318. counts := make([]int, 4)
  319. for _, v := range cards {
  320. if getCardType(v) == getCardType(publicCard) {
  321. continue
  322. }
  323. counts[getCardType(v)]++
  324. }
  325. scoreCounts := make([]int, 4)
  326. for i := 0; i < CardType_Invalid; i++ {
  327. if i == getCardType(publicCard) {
  328. continue
  329. }
  330. scoreCards := getScoreCards(cards, []int{}, i, false)
  331. for _, v := range scoreCards {
  332. scoreCounts[getCardType(v)]++
  333. }
  334. }
  335. for i := 0; i < len(counts); i++ {
  336. if i == getCardType(publicCard) {
  337. continue
  338. }
  339. if counts[i] > most {
  340. most = counts[i]
  341. bestType = i
  342. }
  343. if counts[i] > most && scoreCounts[i] > scoreCounts[bestType] {
  344. // 比较得分牌,多的优先
  345. most = counts[i]
  346. bestType = i
  347. }
  348. }
  349. if bestType != getCardType(publicCard) && (most > 4 || (most > 3 && haveCard(cards, CardValueJ+bestType*8))) {
  350. return bestType
  351. }
  352. if bestType == CardType_Invalid {
  353. for i := 0; i < CardType_Invalid; i++ {
  354. if i != getCardType(publicCard) {
  355. continue
  356. }
  357. if most == counts[i] {
  358. bestType = i
  359. break
  360. }
  361. }
  362. }
  363. return bestType
  364. }
  365. func getLAGsBestTrumpType(cards []int, publicCard int) int {
  366. bestType := CardType_Invalid
  367. most := -1
  368. counts := make([]int, 4)
  369. for _, v := range cards {
  370. if getCardType(v) == getCardType(publicCard) {
  371. continue
  372. }
  373. counts[getCardType(v)]++
  374. }
  375. scoreCounts := make([]int, 4)
  376. for i := 0; i < CardType_Invalid; i++ {
  377. if i == getCardType(publicCard) {
  378. continue
  379. }
  380. scoreCards := getScoreCards(cards, []int{}, i, false)
  381. for _, v := range scoreCards {
  382. scoreCounts[getCardType(v)]++
  383. }
  384. }
  385. startType := rand.Intn(4)
  386. for i := 0; i < len(counts); i++ {
  387. t := (startType + i) % 4
  388. if t == getCardType(publicCard) {
  389. continue
  390. }
  391. if counts[t] > most {
  392. most = counts[t]
  393. bestType = t
  394. }
  395. if counts[t] > most && scoreCounts[t] > scoreCounts[bestType] {
  396. // 比较得分牌,多的优先
  397. most = counts[t]
  398. bestType = t
  399. }
  400. }
  401. if bestType == getCardType(publicCard) {
  402. return CardType_Invalid
  403. }
  404. if most < 3 {
  405. return CardType_Invalid
  406. }
  407. return bestType
  408. }
  409. func calcFinalPonit(point int) int {
  410. var ret int
  411. if point%10 > 5 {
  412. point = point/10 + 1
  413. ret = point
  414. } else {
  415. point /= 10
  416. ret = point
  417. }
  418. return ret
  419. }
  420. // 判断是否最大的牌,非Hokom为A,Hokom为J
  421. func isBiggestCard(card int, trumpType int) bool {
  422. v := getCardValue(card)
  423. t := getCardType(card)
  424. if trumpType != CardType_Invalid && t == trumpType {
  425. return v == CardValueJ
  426. }
  427. return v == CardValueA
  428. }
  429. func checkCanGawah(allplayerHandCards [][]int, chairId int, trumpType int) bool {
  430. if chairId >= CHAIR_COUNT {
  431. return false
  432. }
  433. handCards := allplayerHandCards[chairId]
  434. var otherHandCards []int
  435. for i := 0; i < CHAIR_COUNT; i++ {
  436. if i == chairId {
  437. continue
  438. }
  439. otherHandCards = append(otherHandCards, allplayerHandCards[i]...)
  440. }
  441. for _, v := range handCards {
  442. if !isBiggerThanAll(v, otherHandCards, trumpType) {
  443. return false
  444. }
  445. }
  446. return true
  447. }
  448. func isBiggerThanAll(card int, cards []int, trumpType int) bool {
  449. t := getCardType(card)
  450. for _, v := range cards {
  451. t1 := getCardType(v)
  452. // 如果对面有主牌,我的不是主牌
  453. if t != trumpType && t1 == trumpType {
  454. return false
  455. }
  456. // 不同花色不比较
  457. if t1 != t {
  458. continue
  459. }
  460. if getCardCompareValue(card, trumpType) < getCardCompareValue(v, trumpType) {
  461. return false
  462. }
  463. }
  464. return true
  465. }
  466. func genACard(cardType, cardValue int) int {
  467. return cardType*8 + cardValue
  468. }
  469. func isExistCardInHand(card int, cards []int) bool {
  470. for i := 0; i < len(cards); i++ {
  471. if cards[i] == card {
  472. return true
  473. }
  474. }
  475. return false
  476. }
  477. func getScoreCardNum(cards []int, cardType int, isTrumpType bool) int {
  478. scoreCardNum := 0
  479. cardList2 := []int{CardValueA, CardValue10, CardValueK, CardValueQ, CardValueJ, CardValue9, CardValue8, CardValue7}
  480. cardList1 := []int{CardValueJ, CardValue9, CardValueA, CardValue10, CardValueK, CardValueQ, CardValue8, CardValue7}
  481. if isTrumpType {
  482. for i := 0; i < len(cardList1); i++ {
  483. card := cardList1[i] + cardType*8
  484. if !isExistCardInHand(card, cards) {
  485. break
  486. }
  487. scoreCardNum++
  488. }
  489. } else {
  490. for i := 0; i < len(cardList2); i++ {
  491. card := cardList2[i] + cardType*8
  492. if !isExistCardInHand(card, cards) {
  493. break
  494. }
  495. scoreCardNum++
  496. }
  497. }
  498. return scoreCardNum
  499. }
  500. func isBothInclude9J(cards []int) bool {
  501. bInclude9 := false
  502. bIncludeJ := false
  503. for i := 0; i < len(cards); i++ {
  504. if cards[i]%8 == CardValue9 {
  505. bInclude9 = true
  506. }
  507. if cards[i]%8 == CardValueJ {
  508. bIncludeJ = true
  509. }
  510. }
  511. return bInclude9 && bIncludeJ
  512. }
  513. func isMostOverKInHandCard(cards []int, trumpType int) bool {
  514. bigCount := 0
  515. for i := 0; i < len(cards); i++ {
  516. if getCardCompareValue(cards[i], trumpType) > 4 {
  517. bigCount++
  518. }
  519. }
  520. return bigCount > 4
  521. }
  522. func isAllBelow10InHandCard(cards []int) bool {
  523. smallCount := 0
  524. for i := 0; i < len(cards); i++ {
  525. if getCardCompareValue(cards[i], CardType_Invalid) < 10 {
  526. smallCount++
  527. }
  528. }
  529. return smallCount <= 2
  530. }