gamescene.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. package gamelogic
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "sort"
  6. "bet24.com/log"
  7. "bet24.com/servers/games/baloot/config"
  8. ladder "bet24.com/servers/micros/ladderservice/proto"
  9. )
  10. type GameScene struct {
  11. Banker int // 庄家
  12. FirstActionChair int // 第一个操作的玩家,用作标识
  13. Phase int // 场景阶段
  14. PhaseIndex int // 场景阶段索引
  15. BuyChair int // 当前买牌玩家
  16. BuyAction int // 当前买公共牌动作
  17. FinalClub int // 最终模式
  18. WhoseTurn int // 当前轮到谁操作
  19. LastTurn int // 上个操作的玩家
  20. Players []PlayerInfo // 玩家信息
  21. userActions []userAction // 玩家动作用作回放数据
  22. tableId int // 桌子ID
  23. Index int // 场景索引
  24. GameIndex int // 第几局
  25. ScoreToWin int // 达到多少分就赢,负数表示打多少局
  26. PublicCard int // 本局公共牌
  27. RoundType int // 当前圈牌色
  28. RoundWinner int // 本圈赢家
  29. RoundIndex int // 第几轮出牌
  30. LeftSec int // 剩余时间
  31. BaseTimes int // 本轮倍数
  32. TrumpType int // 主牌花色,Sun或Ashkal模式下为CardType_Invalid
  33. IsBO1 bool // 本轮是否一局定胜负
  34. IsClose bool // 为true表示本局在每一轮第一个出牌时不能出主牌(除了手上全是主牌的情况)
  35. ShowAllCards bool // 是否要展示所有人的牌,用于玩家选择全部打出剩余牌的时候
  36. LastWinChair int // 最后一轮赢牌玩家
  37. DoublingDetails []DoublingData // 加倍详情
  38. GameOutCardHistory []int // 已出的牌
  39. CorrectMode int // 纠错模式
  40. SawaChair int // 做了Sawa的玩家
  41. CorrectResult int // 胜利结果
  42. CorrectCards []int // 纠错牌
  43. CorrectType int // 纠错类型
  44. CanCorrect bool // 能否质疑
  45. LeftSurrenderCount int // 剩余投降次数
  46. isCorrectEnd bool // 是否是纠错结束
  47. isEnterAshkal bool // 是否有人选过Ashkal
  48. reshuffleResult int // 进入重洗前的买牌结果
  49. reshufflePhase int // 进入重新前的场景阶段
  50. buyPhase int // 确定买牌阶段
  51. scoreHistory []perRoundScores
  52. currentRoundDoubling int
  53. maxDoublingTime int
  54. robotSendChatCount int
  55. robotSendChatMaxCount int
  56. robotChatList []robotChatAction
  57. statics []robotChatActionList
  58. isSendChat bool
  59. }
  60. func (gs *GameScene) addAction(chairId int, action int, data int) {
  61. gs.userActions = append(gs.userActions, userAction{ChairId: chairId, Action: action, Data: data})
  62. gs.Index++
  63. }
  64. func (gs *GameScene) addOutCardAction(chairId int, action int, data int, projects []int) {
  65. gs.userActions = append(gs.userActions, userAction{ChairId: chairId, Action: action, Data: data, ExtData: projects})
  66. gs.Index++
  67. gs.PhaseIndex++
  68. }
  69. func (gs *GameScene) addCorrectAction(chairId int, action int, correctType int, correctCards []int) {
  70. gs.userActions = append(gs.userActions, userAction{ChairId: chairId, Action: action, Data: correctType, ExtData: correctCards})
  71. gs.Index++
  72. }
  73. func newGameScene(tableId int, winpoint int, leftSurrenderCount int) *GameScene {
  74. gs := new(GameScene)
  75. gs.ctor()
  76. gs.Banker = rand.Intn(CHAIR_COUNT)
  77. gs.initData(tableId, winpoint, leftSurrenderCount)
  78. gs.GameIndex = 0
  79. gs.robotSendChatMaxCount = 12
  80. if winpoint == -1 {
  81. gs.robotSendChatMaxCount = 6
  82. }
  83. return gs
  84. }
  85. func (gs *GameScene) ctor() {
  86. gs.Players = make([]PlayerInfo, CHAIR_COUNT)
  87. for i := 0; i < CHAIR_COUNT; i++ {
  88. gs.Players[i].isEndToStart = false
  89. }
  90. }
  91. func (gs *GameScene) initData(tableId int, winpoint int, leftSurrenderCount int) {
  92. gs.userActions = []userAction{}
  93. gs.scoreHistory = []perRoundScores{}
  94. gs.LeftSurrenderCount = leftSurrenderCount
  95. gs.robotSendChatCount = 0
  96. gs.robotChatList = []robotChatAction{}
  97. gs.statics = []robotChatActionList{}
  98. // 比赛场海选赛打的一场,ScoreToWin为1,淘汰赛打三场,ScoreToWin为-3,
  99. // 做统一处理:当ScoreToWin<0时表示打多少场
  100. initScore := 0
  101. if winpoint <= 2 {
  102. if winpoint > 0 {
  103. winpoint = -winpoint
  104. }
  105. gs.ScoreToWin = winpoint
  106. } else {
  107. // gs.ScoreToWin = SCORE_TO_WIN
  108. // initScore = SCORE_TO_WIN - winpoint
  109. gs.ScoreToWin = winpoint
  110. }
  111. gs.Index = 0
  112. for i := 0; i < CHAIR_COUNT; i++ {
  113. gs.Players[i].initData(0, 0, initScore)
  114. }
  115. gs.tableId = tableId
  116. gs.maxDoublingTime = -1
  117. gs.gameInit(-1)
  118. }
  119. func (gs *GameScene) gameInit(whoseTurn int) {
  120. gs.BuyChair = -1
  121. gs.BuyAction = -1
  122. gs.Phase = Phase_Free
  123. gs.PhaseIndex = 0
  124. gs.WhoseTurn = whoseTurn
  125. gs.FirstActionChair = whoseTurn
  126. gs.LastTurn = -1
  127. gs.PublicCard = CARD_COUNT
  128. gs.RoundType = CardType_Invalid
  129. gs.RoundWinner = CHAIR_COUNT
  130. gs.GameOutCardHistory = []int{}
  131. gs.RoundIndex = 0
  132. gs.BaseTimes = 1
  133. gs.TrumpType = CardType_Invalid
  134. gs.IsBO1 = false
  135. gs.FinalClub = Suit_Invalid
  136. gs.IsClose = false
  137. gs.ShowAllCards = false
  138. gs.LastWinChair = -1
  139. gs.reshuffleResult = -1
  140. gs.reshufflePhase = Phase_Free
  141. gs.isCorrectEnd = false
  142. gs.isEnterAshkal = false
  143. gs.DoublingDetails = []DoublingData{}
  144. gs.CorrectMode = Correct_Invaild
  145. gs.SawaChair = CHAIR_COUNT
  146. gs.CorrectResult = -1
  147. gs.CorrectCards = []int{}
  148. gs.CanCorrect = false
  149. gs.buyPhase = Phase_FirstBuy
  150. gs.currentRoundDoubling = 0
  151. gs.isSendChat = false
  152. for i := 0; i < CHAIR_COUNT; i++ {
  153. gs.Players[i].gameInit()
  154. }
  155. }
  156. func (gs *GameScene) initAllPlayerLastAction() {
  157. for i := 0; i < CHAIR_COUNT; i++ {
  158. gs.Players[i].intLastAction()
  159. }
  160. }
  161. func (gs *GameScene) canDouble(chairId int) bool {
  162. return gs.Players[chairId].TotalScore > 100 && gs.Players[getNextChair(chairId)].TotalScore < 100
  163. }
  164. func (gs *GameScene) canDoubleInSun() bool {
  165. if gs.FinalClub == Suit_Hokum {
  166. return false
  167. }
  168. return gs.Players[gs.BuyChair].TotalScore > 100 && gs.Players[getNextChair(gs.BuyChair)].TotalScore < 100
  169. }
  170. func (gs *GameScene) checkProject(chairId int, projects []int) {
  171. gs.Players[chairId].analysisProject(projects, gs.FinalClub)
  172. }
  173. func (gs *GameScene) initAllPlayerTime() {
  174. for i := 0; i < CHAIR_COUNT; i++ {
  175. gs.Players[i].ininTime()
  176. }
  177. }
  178. func (gs *GameScene) isBuySunEnterDouble(buyAction, buyChairId int) bool {
  179. if buyAction != Action_Buy_Sun {
  180. return false
  181. }
  182. if gs.BuyAction == Action_Buy_Hokum {
  183. return false
  184. }
  185. if gs.isEnterAshkal && buyChairId != gs.FirstActionChair {
  186. return false
  187. }
  188. return gs.canDouble(buyChairId)
  189. }
  190. // 0 表示继续买牌或者直接进入double阶段,1表示结束买牌阶段,进入发剩余牌阶段
  191. func (gs *GameScene) resetBuyActionOfChangeBuyChair(buyAction, buyChairId int) int {
  192. // 先把做完买牌玩家可做动作清空
  193. gs.Players[buyChairId].setPlayerOperators([]int{})
  194. // 如果玩家选择pass且当前都没有人买牌
  195. if buyAction == Action_Buy_Pass {
  196. // 如果当前买牌的人为庄家,则进入第二次买牌阶段
  197. if buyChairId == gs.Banker && gs.Phase == Phase_FirstBuy {
  198. gs.Phase = Phase_SecondBuy
  199. gs.PhaseIndex = 0
  200. }
  201. gs.WhoseTurn = getPreviousChair(gs.WhoseTurn)
  202. for i := 0; i < CHAIR_COUNT; i++ {
  203. buyList := []int{}
  204. if i == gs.WhoseTurn {
  205. buyList = append(buyList, Action_Buy_Pass, Action_Buy_Hokum, Action_Buy_Sun)
  206. if i == gs.Banker || isPreviousChair(i, gs.Banker) {
  207. buyList = append(buyList, Action_Buy_Ashkal)
  208. }
  209. gs.Players[i].setPlayerOperators(buyList)
  210. } else {
  211. gs.Players[i].setPlayerOperators(buyList)
  212. }
  213. }
  214. return 0
  215. }
  216. // 如果玩家选择hokum
  217. if buyAction == Action_Buy_Hokum {
  218. gs.BuyAction = buyAction
  219. gs.BuyChair = buyChairId
  220. for i := 0; i < CHAIR_COUNT; i++ {
  221. buyList := []int{}
  222. if i == gs.BuyChair {
  223. continue
  224. }
  225. buyList = append(buyList, Action_Buy_Pass, Action_Buy_Sun)
  226. if i == gs.Banker || isPreviousChair(i, gs.Banker) {
  227. buyList = append(buyList, Action_Buy_Ashkal)
  228. }
  229. gs.Players[i].setPlayerOperators(buyList)
  230. gs.Players[i].intLastAction()
  231. }
  232. gs.WhoseTurn = -1
  233. return 0
  234. }
  235. // 如果玩家选择Action_Buy_Sun或者Action_Buy_Ashkal
  236. result := 1
  237. if buyAction == Action_Buy_Sun || buyAction == Action_Buy_Ashkal {
  238. if buyAction == Action_Buy_Ashkal {
  239. gs.isEnterAshkal = true
  240. }
  241. bOnlyOnePlayer := false
  242. isBeforeBuyHokum := (gs.BuyAction == Action_Buy_Hokum)
  243. if !isBeforeBuyHokum {
  244. bOnlyOnePlayer = true
  245. gs.BuyAction = buyAction
  246. gs.BuyChair = buyChairId
  247. for i := 0; i < CHAIR_COUNT; i++ {
  248. gs.Players[i].setPlayerOperators([]int{})
  249. }
  250. } else {
  251. result = 0
  252. if isFriendChair(gs.BuyChair, buyChairId) && buyAction == Action_Buy_Ashkal {
  253. result = 1
  254. gs.BuyAction = buyAction
  255. gs.BuyChair = buyChairId
  256. for i := 0; i < CHAIR_COUNT; i++ {
  257. gs.Players[i].setPlayerOperators([]int{})
  258. }
  259. bOnlyOnePlayer = true
  260. } else {
  261. for i := 0; i < CHAIR_COUNT; i++ {
  262. buyList := []int{}
  263. if i == gs.BuyChair {
  264. buyList = append(buyList, Action_Buy_Pass, Action_Buy_Sun)
  265. if (i == gs.Banker || isPreviousChair(i, gs.Banker)) && !gs.isEnterAshkal {
  266. buyList = append(buyList, Action_Buy_Ashkal)
  267. }
  268. if gs.BuyChair == getNextChair(buyChairId) {
  269. bOnlyOnePlayer = true
  270. }
  271. }
  272. gs.Players[i].setPlayerOperators(buyList)
  273. }
  274. gs.WhoseTurn = gs.BuyChair
  275. gs.BuyAction = buyAction
  276. gs.BuyChair = buyChairId
  277. }
  278. }
  279. buyList := []int{}
  280. buyList = append(buyList, Action_Buy_Pass, Action_Buy_Sun)
  281. if buyAction == Action_Buy_Ashkal {
  282. result = 0
  283. if bOnlyOnePlayer {
  284. gs.WhoseTurn = getNextChair(buyChairId)
  285. } else {
  286. gs.WhoseTurn = -1
  287. }
  288. gs.Players[getNextChair(buyChairId)].setPlayerOperators(buyList)
  289. }
  290. if gs.isEnterAshkal && buyAction == Action_Buy_Sun && buyChairId != gs.FirstActionChair {
  291. result = 0
  292. if bOnlyOnePlayer {
  293. gs.WhoseTurn = getNextChair(buyChairId)
  294. } else {
  295. gs.WhoseTurn = -1
  296. }
  297. gs.Players[getNextChair(buyChairId)].setPlayerOperators(buyList)
  298. }
  299. }
  300. if result == 1 {
  301. gs.setFinalSuit()
  302. gs.TrumpType = CardType_Invalid
  303. // sun模式下,判断玩家能不能买double
  304. if gs.canDoubleInSun() {
  305. for i := 0; i < CHAIR_COUNT; i++ {
  306. buyList := []int{}
  307. if isSameTeam(i, gs.BuyChair) {
  308. gs.Players[i].setPlayerOperators(buyList)
  309. continue
  310. }
  311. buyList = append(buyList, Action_Buy_Pass, Action_Buy_Double)
  312. gs.Players[i].setPlayerOperators(buyList)
  313. }
  314. gs.WhoseTurn = -1
  315. gs.Phase = Phase_Double
  316. gs.PhaseIndex = 0
  317. result = 0
  318. }
  319. }
  320. return result
  321. }
  322. func (gs *GameScene) isBuyChairWin() bool {
  323. if !isValidChair(gs.BuyChair) {
  324. return false
  325. }
  326. return gs.Players[gs.BuyChair].FinalCalcScore >= gs.Players[getNextChair(gs.BuyChair)].FinalCalcScore
  327. }
  328. func (gs *GameScene) isAllPlayerPass() bool {
  329. for i := 0; i < CHAIR_COUNT; i++ {
  330. if i == gs.BuyChair {
  331. continue
  332. }
  333. if !gs.Players[i].isBuyPass() {
  334. return false
  335. }
  336. }
  337. return true
  338. }
  339. func (gs *GameScene) isAllCanDoReshufflePlayerPass() bool {
  340. for i := 0; i < CHAIR_COUNT; i++ {
  341. if !gs.Players[i].CanDoReshuffle {
  342. continue
  343. }
  344. if gs.Players[i].ReshuffleAction != Reshuffle_Pass {
  345. return false
  346. }
  347. }
  348. return true
  349. }
  350. func (gs *GameScene) setFinalSuit() {
  351. switch gs.BuyAction {
  352. case Action_Buy_Hokum:
  353. gs.FinalClub = Suit_Hokum
  354. case Action_Buy_Sun:
  355. gs.FinalClub = Suit_Sun
  356. case Action_Buy_Ashkal:
  357. gs.FinalClub = Suit_Ashkal
  358. }
  359. }
  360. func (gs *GameScene) setBaseTimes(buyAction int) {
  361. if buyAction < Action_Buy_Double || buyAction > Action_Buy_Four {
  362. return
  363. }
  364. time := buyAction - Action_Buy_Double + 2
  365. if time < 2 {
  366. time = 2
  367. }
  368. gs.BaseTimes = time
  369. if gs.BaseTimes > 4 {
  370. gs.BaseTimes = 4
  371. }
  372. }
  373. func (gs *GameScene) havePlayerConfirmReshuffle(chairId int) bool {
  374. for i := 0; i < CHAIR_COUNT; i++ {
  375. if chairId == i {
  376. continue
  377. }
  378. if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction == Reshuffle_Confirm {
  379. return true
  380. }
  381. }
  382. return false
  383. }
  384. func (gs *GameScene) canReshuffle(buyAction, chairId int) bool {
  385. if buyAction <= Action_Buy_Pass {
  386. return false
  387. }
  388. for i := 0; i < CHAIR_COUNT; i++ {
  389. if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction > Reshuffle_None {
  390. return false
  391. }
  392. }
  393. canReshuffle := false
  394. for i := 0; i < CHAIR_COUNT; i++ {
  395. if i == chairId {
  396. continue
  397. }
  398. if gs.Players[i].needReshuffle() {
  399. canReshuffle = true
  400. }
  401. }
  402. return canReshuffle
  403. }
  404. func (gs *GameScene) isEnterReshuffle(buyAction int) bool {
  405. if buyAction <= Action_Buy_Pass {
  406. return false
  407. }
  408. for i := 0; i < CHAIR_COUNT; i++ {
  409. if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction > Reshuffle_None {
  410. return false
  411. }
  412. }
  413. canReshuffle := false
  414. for i := 0; i < CHAIR_COUNT; i++ {
  415. if i == gs.BuyChair {
  416. continue
  417. }
  418. if gs.Players[i].isAllZeroScoreCard() {
  419. canReshuffle = true
  420. }
  421. }
  422. if canReshuffle {
  423. gs.reshufflePhase = gs.Phase
  424. gs.Phase = Phase_Reshuffle
  425. gs.PhaseIndex = 0
  426. }
  427. return canReshuffle
  428. }
  429. func (gs *GameScene) isPlayerCanAction() bool {
  430. for i := 0; i < CHAIR_COUNT; i++ {
  431. if len(gs.Players[i].CanAction) > 0 {
  432. return true
  433. }
  434. }
  435. return false
  436. }
  437. // 0表示继续等待其他人操作,1表示进入选花色或者加倍阶段或者继续买牌二次确认阶段,2表示进入发剩余牌阶段
  438. func (gs *GameScene) resetBuyActionOfNotChangeBuyChair(buyChair, buyAction int) int {
  439. result := 0
  440. // 先把做完买牌玩家可做动作清空
  441. gs.Players[buyChair].setPlayerOperators([]int{})
  442. // 已经有人买牌,当前玩家没有抢牌
  443. if buyAction == Action_Buy_Pass {
  444. if !gs.isEnterAshkal {
  445. if gs.isAllPlayerPass() {
  446. for i := 0; i < CHAIR_COUNT; i++ {
  447. if i == buyChair {
  448. continue
  449. }
  450. gs.Players[i].setPlayerOperators([]int{})
  451. }
  452. if gs.BuyAction == Action_Buy_Hokum {
  453. buyList := []int{}
  454. buyList = append(buyList, Action_Buy_ConfirmHokum, Action_Buy_SwitchSun)
  455. gs.Players[gs.BuyChair].setPlayerOperators(buyList)
  456. gs.WhoseTurn = gs.BuyChair
  457. result = 1
  458. } else {
  459. gs.setFinalSuit()
  460. gs.TrumpType = CardType_Invalid
  461. result = 2
  462. }
  463. }
  464. } else {
  465. if !gs.isPlayerCanAction() {
  466. gs.setFinalSuit()
  467. gs.TrumpType = CardType_Invalid
  468. result = 2
  469. }
  470. }
  471. }
  472. if buyAction == Action_Buy_ConfirmHokum {
  473. result = 1
  474. gs.WhoseTurn = -1
  475. gs.setFinalSuit()
  476. if gs.Phase == Phase_SecondBuy {
  477. gs.Phase = Phase_ChooseTrump
  478. gs.PhaseIndex = 0
  479. gs.WhoseTurn = gs.BuyChair
  480. gs.Players[gs.BuyChair].setPlayerOperators([]int{})
  481. return result
  482. }
  483. gs.TrumpType = getCardType(gs.PublicCard)
  484. for i := 0; i < CHAIR_COUNT; i++ {
  485. sort.Slice(gs.Players[i].HandCards, func(m, n int) bool {
  486. return getCardSortValue(gs.Players[i].HandCards[m], gs.TrumpType) <
  487. getCardSortValue(gs.Players[i].HandCards[n], gs.TrumpType)
  488. })
  489. buyList := []int{}
  490. if isSameTeam(i, gs.BuyChair) {
  491. gs.Players[i].setPlayerOperators(buyList)
  492. continue
  493. }
  494. buyList = append(buyList, Action_Buy_Pass, Action_Buy_Double)
  495. gs.Players[i].setPlayerOperators(buyList)
  496. }
  497. gs.initAllPlayerLastAction()
  498. gs.Phase = Phase_Double
  499. gs.PhaseIndex = 0
  500. }
  501. if buyAction == Action_Buy_SwitchSun {
  502. for i := 0; i < CHAIR_COUNT; i++ {
  503. gs.Players[i].setPlayerOperators([]int{})
  504. }
  505. gs.BuyAction = Action_Buy_Sun
  506. gs.TrumpType = CardType_Invalid
  507. gs.setFinalSuit()
  508. result = 2
  509. }
  510. if result == 2 && gs.FinalClub != Suit_Hokum {
  511. if gs.canDoubleInSun() {
  512. for i := 0; i < CHAIR_COUNT; i++ {
  513. buyList := []int{}
  514. if isSameTeam(i, gs.BuyChair) {
  515. gs.Players[i].setPlayerOperators(buyList)
  516. continue
  517. }
  518. buyList = append(buyList, Action_Buy_Pass, Action_Buy_Double)
  519. gs.Players[i].setPlayerOperators(buyList)
  520. }
  521. gs.WhoseTurn = -1
  522. gs.Phase = Phase_Double
  523. gs.PhaseIndex = 0
  524. result = 1
  525. }
  526. }
  527. return result
  528. }
  529. func (gs *GameScene) setNextBanker() {
  530. for i := 1; i < CHAIR_COUNT; i++ {
  531. next := (gs.Banker + CHAIR_COUNT - i) % CHAIR_COUNT
  532. if gs.Players[next].IsValid {
  533. gs.Banker = next
  534. break
  535. }
  536. }
  537. }
  538. // 本圈已出牌人数
  539. func (gs *GameScene) getRoundOutedPlayerCount() int {
  540. outedCount := 0
  541. for _, v := range gs.Players {
  542. if v.CurrentCard != CARD_COUNT {
  543. outedCount++
  544. }
  545. }
  546. return outedCount
  547. }
  548. func (gs *GameScene) isRoundEnd() bool {
  549. return gs.getRoundOutedPlayerCount() == CHAIR_COUNT
  550. }
  551. func (gs *GameScene) nextChair() {
  552. gs.LastTurn = gs.WhoseTurn
  553. gs.WhoseTurn = getPreviousChair(gs.LastTurn)
  554. }
  555. // 获取本圈玩家出牌
  556. func (gs *GameScene) getRoundCards() []int {
  557. ret := make([]int, CHAIR_COUNT)
  558. for i := 0; i < CHAIR_COUNT; i++ {
  559. ret[i] = gs.Players[i].CurrentCard
  560. }
  561. return ret
  562. }
  563. func (gs *GameScene) endAOutCardRound(winner int) int {
  564. winScore := 0
  565. for i := 0; i < CHAIR_COUNT; i++ {
  566. score := getCardPoint(gs.Players[i].CurrentCard, gs.TrumpType)
  567. winScore += score
  568. gs.Players[i].CurrentCard = CARD_COUNT
  569. gs.Players[i].BigCards = []int{}
  570. }
  571. gs.Players[winner].winCardScore += winScore
  572. for i := 0; i < CHAIR_COUNT; i++ {
  573. if isSameTeam(i, winner) {
  574. gs.Players[i].addScore(winScore)
  575. } else {
  576. gs.Players[i].addScore(0)
  577. }
  578. }
  579. gs.Players[winner].WinCardNumber += 4
  580. gs.RoundWinner = winner
  581. gs.WhoseTurn = -1
  582. gs.addAction(-1, Action_RoundEnd, gs.RoundType)
  583. return winScore
  584. }
  585. // 本局是否已结束
  586. func (gs *GameScene) isGameEnd() bool {
  587. for _, v := range gs.Players {
  588. if len(v.HandCards) > 0 {
  589. return false
  590. }
  591. }
  592. return true
  593. }
  594. func (gs *GameScene) newOutCardRound() {
  595. gs.RoundIndex++
  596. gs.RoundType = CardType_Invalid
  597. if !isValidChair(gs.RoundWinner) {
  598. log.Debug("Wrong RoundWinner:%d", gs.RoundWinner)
  599. return
  600. }
  601. if !gs.ShowAllCards {
  602. for i := 0; i < CHAIR_COUNT; i++ {
  603. gs.Players[i].CurrentCard = CARD_COUNT
  604. }
  605. } else {
  606. gs.ShowAllCards = false
  607. }
  608. if gs.isGameEnd() {
  609. gs.LastWinChair = gs.RoundWinner
  610. }
  611. if gs.RoundIndex == 2 {
  612. gs.compareProject()
  613. }
  614. for i := 0; i < CHAIR_COUNT; i++ {
  615. gs.Players[i].CallProject = PROJECT_INVALID
  616. gs.Players[i].IsCallBiggest = false
  617. }
  618. gs.LastTurn = -1
  619. gs.WhoseTurn = gs.RoundWinner
  620. gs.RoundWinner = CHAIR_COUNT
  621. }
  622. func (gs *GameScene) checkCanGawah() {
  623. handLen := len(gs.Players[gs.WhoseTurn].HandCards)
  624. if handLen <= 1 || handLen == 8 {
  625. gs.Players[gs.WhoseTurn].CanGawah = false
  626. return
  627. }
  628. gs.Players[gs.WhoseTurn].CanGawah = checkCanGawah(gs.getAllPlayerCards(), gs.WhoseTurn, gs.TrumpType)
  629. }
  630. func (gs *GameScene) compareProject() {
  631. buyProject := []SingleProject{}
  632. playerProject := []SingleProject{}
  633. for i := 0; i < CHAIR_COUNT; i++ {
  634. if gs.Players[i].CallProject == PROJECT_INVALID || len(gs.Players[i].Projects) == 0 {
  635. continue
  636. }
  637. if isSameTeam(i, gs.BuyChair) {
  638. buyProject = append(buyProject, gs.Players[i].Projects[0])
  639. } else {
  640. playerProject = append(playerProject, gs.Players[i].Projects[0])
  641. }
  642. }
  643. if len(buyProject) == 0 || len(playerProject) == 0 {
  644. return
  645. }
  646. // 从大到小排序
  647. sort.Slice(buyProject, func(i, j int) bool {
  648. return buyProject[i].isBiggerThan(buyProject[j])
  649. })
  650. sort.Slice(playerProject, func(i, j int) bool {
  651. return playerProject[i].isBiggerThan(playerProject[j])
  652. })
  653. isBuyBig := buyProject[0].isBiggerThan(playerProject[0])
  654. for i := 0; i < CHAIR_COUNT; i++ {
  655. if gs.Players[i].CallProject == PROJECT_INVALID {
  656. continue
  657. }
  658. if isSameTeam(i, gs.BuyChair) {
  659. if !isBuyBig {
  660. gs.Players[i].Projects = []SingleProject{}
  661. }
  662. } else {
  663. if isBuyBig {
  664. gs.Players[i].Projects = []SingleProject{}
  665. }
  666. }
  667. }
  668. }
  669. func (gs *GameScene) gameEnd() {
  670. gs.Phase = Phase_GameEnd
  671. gs.PhaseIndex = 0
  672. scores := make([]int, CHAIR_COUNT)
  673. // 这里计算Buy方和player方得分
  674. buyPoint := 0
  675. playerPoint := 0
  676. for i := 0; i < CHAIR_COUNT; i++ {
  677. if isSameTeam(i, gs.BuyChair) {
  678. buyPoint += gs.Players[i].getProjectScore()
  679. } else {
  680. playerPoint += gs.Players[i].getProjectScore()
  681. }
  682. }
  683. if !isValidCard(gs.BuyChair) {
  684. log.Debug("Serious Error Buy Chair:%d", gs.BuyChair)
  685. return
  686. }
  687. buyWinCardScore := gs.Players[gs.BuyChair].WinCardScore
  688. playerWinCardScore := gs.Players[getNextChair(gs.BuyChair)].WinCardScore
  689. buyPoint += gs.Players[gs.BuyChair].WinCardScore
  690. playerPoint += gs.Players[getNextChair(gs.BuyChair)].WinCardScore
  691. gs.Players[gs.LastWinChair].winCardScore += LAST_WIN_SCORE
  692. if isSameTeam(gs.BuyChair, gs.LastWinChair) {
  693. buyPoint += LAST_WIN_SCORE
  694. buyWinCardScore += LAST_WIN_SCORE
  695. } else {
  696. playerPoint += LAST_WIN_SCORE
  697. playerWinCardScore += LAST_WIN_SCORE
  698. }
  699. buyAbnat := buyPoint
  700. playerAbnat := playerPoint
  701. // 如果买的一方输的情况
  702. if (buyPoint == playerPoint && (gs.BaseTimes > 1 || gs.IsBO1)) || buyPoint < playerPoint {
  703. playerPoint += buyPoint
  704. if gs.Players[gs.BuyChair].WinCardScore == 0 && !gs.isCorrectEnd {
  705. playerPoint += ALL_WIN_EXTRA_SCORE
  706. }
  707. buyPoint = 0
  708. } else {
  709. if gs.Players[getNextChair(gs.BuyChair)].WinCardScore == 0 && !gs.isCorrectEnd {
  710. buyPoint += ALL_WIN_EXTRA_SCORE
  711. playerPoint = 0
  712. }
  713. if gs.IsBO1 || gs.BaseTimes > 1 {
  714. buyPoint += playerAbnat
  715. playerPoint = 0
  716. }
  717. }
  718. finalBuyPoint := calcFinalPonit(buyPoint)
  719. finalPlayerPoint := calcFinalPonit(playerPoint)
  720. if gs.FinalClub != Suit_Hokum {
  721. finalBuyPoint *= 2
  722. finalPlayerPoint *= 2
  723. if buyWinCardScore%10 == 5 && playerWinCardScore%10 == 5 && buyPoint > 0 && playerPoint > 0 {
  724. finalBuyPoint++
  725. finalPlayerPoint++
  726. }
  727. } else {
  728. if buyWinCardScore%10 == 6 && playerWinCardScore%10 == 6 && buyPoint > 0 && playerPoint > 0 {
  729. finalPlayerPoint--
  730. }
  731. }
  732. finalBuyPoint *= gs.BaseTimes
  733. finalPlayerPoint *= gs.BaseTimes
  734. for i := 0; i < CHAIR_COUNT; i++ {
  735. if isSameTeam(i, gs.BuyChair) {
  736. scores[i] = finalBuyPoint
  737. } else {
  738. scores[i] = finalPlayerPoint
  739. }
  740. }
  741. var scoreData = 0
  742. for i := 0; i < CHAIR_COUNT; i++ {
  743. scoreData += int(scores[i])
  744. if i != CHAIR_COUNT-1 {
  745. scoreData *= 1000
  746. }
  747. }
  748. isBuyChairBO1Win := false
  749. isPlayerBO1Win := false
  750. if gs.IsBO1 {
  751. isBuyChairBO1Win = (finalBuyPoint > finalPlayerPoint)
  752. if isBuyChairBO1Win {
  753. finalPlayerPoint = 0
  754. } else {
  755. finalBuyPoint = 0
  756. isPlayerBO1Win = true
  757. }
  758. }
  759. totalTimes := gs.getDoublingTotalTimes()
  760. if totalTimes > 1 {
  761. gs.currentRoundDoubling = totalTimes
  762. }
  763. gs.userActions = append(gs.userActions, userAction{ChairId: -1, Action: Action_GameEnd, Data: scoreData})
  764. for i := 0; i < CHAIR_COUNT; i++ {
  765. if isSameTeam(i, gs.BuyChair) {
  766. gs.Players[i].addEndScore(finalBuyPoint, buyAbnat, isBuyChairBO1Win, SCORE_TO_WIN)
  767. if finalBuyPoint >= finalPlayerPoint && totalTimes > 1 {
  768. gs.Players[i].addDoublingData(gs.GameIndex, totalTimes)
  769. }
  770. } else {
  771. gs.Players[i].addEndScore(finalPlayerPoint, playerAbnat, isPlayerBO1Win, SCORE_TO_WIN)
  772. if finalBuyPoint < finalPlayerPoint && totalTimes > 1 {
  773. gs.Players[i].addDoublingData(gs.GameIndex, totalTimes)
  774. }
  775. }
  776. }
  777. gs.WhoseTurn = -1
  778. }
  779. func (gs *GameScene) getDoublingTotalTimes() int {
  780. totalTimes := 1
  781. for n := 0; n < len(gs.DoublingDetails); n++ {
  782. totalTimes *= gs.DoublingDetails[n].DoublingTimes
  783. }
  784. return totalTimes
  785. }
  786. func (gs *GameScene) isPlayerWinInQuickGame(chairId int) bool {
  787. if gs.Players[chairId].FinalCalcScore < gs.Players[getNextChair(chairId)].FinalCalcScore {
  788. return false
  789. }
  790. if gs.Players[chairId].FinalCalcScore == gs.Players[getNextChair(chairId)].FinalCalcScore &&
  791. !isSameTeam(chairId, gs.BuyChair) {
  792. return false
  793. }
  794. return true
  795. }
  796. func (gs *GameScene) isFirstOutCardInCloseMode() bool {
  797. return gs.FinalClub == Suit_Hokum && gs.RoundType == CardType_Invalid && gs.IsClose
  798. }
  799. func (gs *GameScene) isGameFinish() bool {
  800. if gs.IsBO1 && gs.ScoreToWin > 0 {
  801. return true
  802. }
  803. // ScoreToWin小于0表示大多少局结束
  804. if gs.ScoreToWin < 0 {
  805. if (gs.ScoreToWin + gs.GameIndex) >= -1 {
  806. return true
  807. }
  808. } else {
  809. for i := 0; i < CHAIR_COUNT; i++ {
  810. if gs.Players[i].getTotalScore() >= gs.ScoreToWin &&
  811. gs.Players[i].getTotalScore() != gs.Players[getNextChair(i)].getTotalScore() {
  812. return true
  813. }
  814. }
  815. }
  816. return false
  817. }
  818. // 如果已经要结算了,在返回FALSE
  819. func (gs *GameScene) nextGame(isSurrenderFinish bool) bool {
  820. if isSurrenderFinish {
  821. return false
  822. }
  823. gs.GameIndex++
  824. if gs.IsBO1 && gs.ScoreToWin > 0 {
  825. return false
  826. }
  827. // ScoreToWin小于0表示大多少局结束
  828. if gs.ScoreToWin < 0 {
  829. if (gs.ScoreToWin + gs.GameIndex) >= 0 {
  830. return false
  831. }
  832. } else {
  833. for i := 0; i < CHAIR_COUNT; i++ {
  834. if gs.Players[i].getTotalScore() >= gs.ScoreToWin &&
  835. gs.Players[i].getTotalScore() != gs.Players[getNextChair(i)].getTotalScore() {
  836. return false
  837. }
  838. }
  839. }
  840. gs.setNextBanker()
  841. gs.gameInit(getPreviousChair(gs.Banker))
  842. return true
  843. }
  844. func (gs *GameScene) getWinner() []int {
  845. var ret []int
  846. var biggestScore int = -10000
  847. biggestChair := CHAIR_COUNT
  848. for i := 0; i < CHAIR_COUNT; i++ {
  849. if !gs.Players[i].IsValid {
  850. continue
  851. }
  852. chairScore := gs.Players[i].getTotalScore()
  853. if biggestChair == CHAIR_COUNT || chairScore > biggestScore {
  854. biggestChair = i
  855. biggestScore = chairScore
  856. }
  857. }
  858. for i := 0; i < CHAIR_COUNT; i++ {
  859. if !gs.Players[i].IsValid {
  860. continue
  861. }
  862. if gs.Players[i].getTotalScore() == biggestScore {
  863. ret = append(ret, i)
  864. }
  865. }
  866. if len(ret) == CHAIR_COUNT {
  867. ret = []int{}
  868. for i := 0; i < CHAIR_COUNT; i++ {
  869. if !gs.Players[i].IsValid {
  870. continue
  871. }
  872. if isSameTeam(i, gs.BuyChair) {
  873. ret = append(ret, i)
  874. }
  875. }
  876. }
  877. return ret
  878. }
  879. func (gs *GameScene) pointsToEndScore() {
  880. for i := 0; i < CHAIR_COUNT; i++ {
  881. if !gs.Players[i].IsValid {
  882. continue
  883. }
  884. gs.Players[i].pointsToEndScore()
  885. }
  886. }
  887. func (gs *GameScene) initMaxDoubling(isDoublingMode bool) {
  888. if !isDoublingMode || gs.Players[0].enterGold == 0 || gs.Players[0].bet == 0 {
  889. return
  890. }
  891. maxTimes := gs.Players[0].enterGold / gs.Players[0].bet
  892. for i := 1; i < CHAIR_COUNT; i++ {
  893. times := gs.Players[i].enterGold / gs.Players[i].bet
  894. if maxTimes > times {
  895. maxTimes = times
  896. }
  897. }
  898. gs.maxDoublingTime = maxTimes
  899. }
  900. func (gs *GameScene) getTotalBet(winner int) int {
  901. ret := 0
  902. baseTimes := 0
  903. for n := 0; n < len(gs.Players[winner].Doublings); n++ {
  904. baseTimes += gs.Players[winner].Doublings[n].DoublingTotalTimes
  905. }
  906. if baseTimes > gs.maxDoublingTime && gs.maxDoublingTime != -1 {
  907. baseTimes = gs.maxDoublingTime
  908. }
  909. for i := 0; i < CHAIR_COUNT; i++ {
  910. if !gs.Players[i].IsValid {
  911. continue
  912. }
  913. playerBet := gs.Players[i].bet
  914. if baseTimes > 0 && !isSameTeam(winner, i) {
  915. playerBet *= baseTimes
  916. gs.Players[i].EndScore = gs.Players[i].bet - playerBet
  917. }
  918. ret += playerBet
  919. }
  920. return ret
  921. }
  922. func (gs *GameScene) getValidUserCount() int {
  923. ret := 0
  924. for i := 0; i < CHAIR_COUNT; i++ {
  925. if gs.Players[i].IsValid {
  926. ret++
  927. }
  928. }
  929. return ret
  930. }
  931. func (gs *GameScene) getUserCount() int {
  932. ret := 0
  933. for i := 0; i < CHAIR_COUNT; i++ {
  934. if !gs.Players[i].isRobot {
  935. ret++
  936. }
  937. }
  938. return ret
  939. }
  940. func (gs *GameScene) getControlRobot() int {
  941. team1RobotCount := 0
  942. team2RobotCount := 0
  943. for i := 0; i < CHAIR_COUNT; i++ {
  944. if gs.Players[i].isRobot && isSameTeam(i, 0) {
  945. team1RobotCount++
  946. }
  947. if gs.Players[i].isRobot && isSameTeam(i, 1) {
  948. team2RobotCount++
  949. }
  950. }
  951. if team1RobotCount == team2RobotCount {
  952. return -1
  953. }
  954. controlRobot := -1
  955. if team1RobotCount > team2RobotCount {
  956. for i := 0; i < CHAIR_COUNT; i++ {
  957. if gs.Players[i].isRobot && isSameTeam(i, 0) {
  958. controlRobot = i
  959. break
  960. }
  961. }
  962. } else {
  963. for i := 0; i < CHAIR_COUNT; i++ {
  964. if gs.Players[i].isRobot && isSameTeam(i, 1) {
  965. controlRobot = i
  966. break
  967. }
  968. }
  969. }
  970. return controlRobot
  971. }
  972. func (gs *GameScene) dump(includeAction bool) {
  973. log.Debug("====GameScene Table[%d] Index[%d] GameIndex[%d] ScoreToWin[%d]====",
  974. gs.tableId, gs.Index, gs.GameIndex, gs.ScoreToWin)
  975. log.Debug(" Phase[%s],PhaseIndex[%d],BuyChair[%d], WhoseTurn[%d],LastTurn[%d],Banker[%d],FirstActionChair[%d]",
  976. getPhaseDesc(gs.Phase), gs.PhaseIndex, gs.BuyChair, gs.WhoseTurn, gs.LastTurn, gs.Banker, gs.FirstActionChair)
  977. log.Debug(" BuyAction[%d],FinalClub[%s],RoundType[%d],RoundIndex[%d], RoundWinner[%d]",
  978. gs.BuyAction, getSuitDesc(gs.FinalClub), gs.RoundType, gs.RoundIndex, gs.RoundWinner)
  979. log.Debug(" PublicCard[%s],BaseTimes[%d],TrumpType[%d],IsBO1[%v],IsClose[%v], ShowAllCards[%v], LastWinChair[%d]",
  980. getCardHex(gs.PublicCard), gs.BaseTimes, gs.TrumpType, gs.IsBO1, gs.IsClose, gs.ShowAllCards, gs.LastWinChair)
  981. log.Debug(" reshuffleResult[%d], reshufflePhase[%d]", gs.reshuffleResult, gs.reshufflePhase)
  982. log.Debug(" isCorrectEnd[%v], isEnterAshkal[%v]", gs.isCorrectEnd, gs.isEnterAshkal)
  983. log.Debug(" GameOutCardHistory%s", getCardsHex(gs.GameOutCardHistory))
  984. log.Debug(" CorrectMode[%s], SawaChair[%d], CorrectResult[%d], CorrectCards%s, CorrectType[%s], CanCorrect[%v]",
  985. getCorrectModeDesc(gs.CorrectMode), gs.SawaChair, gs.CorrectResult, getCardsHex(gs.CorrectCards),
  986. getCorrectTypeDesc(gs.CorrectType), gs.CanCorrect)
  987. log.Debug(" doublingDetails:")
  988. for n := 0; n < len(gs.DoublingDetails); n++ {
  989. gs.DoublingDetails[n].dump()
  990. }
  991. log.Debug(" Users:%d", gs.getValidUserCount())
  992. for i := 0; i < CHAIR_COUNT; i++ {
  993. gs.Players[i].dump(i)
  994. }
  995. if includeAction && len(gs.userActions) > 0 {
  996. log.Debug(" Actions:%d", len(gs.userActions))
  997. for _, v := range gs.userActions {
  998. v.dump()
  999. }
  1000. }
  1001. log.Debug("---------------------------")
  1002. }
  1003. func (gs *GameScene) getPlayerLadderInfo() string {
  1004. type GameUserLadderInfo struct {
  1005. UserID int
  1006. LadderInfo ladder.UserLadderInfo
  1007. }
  1008. var ret []GameUserLadderInfo
  1009. for i := 0; i < CHAIR_COUNT; i++ {
  1010. if gs.Players[i].userID == 0 {
  1011. continue
  1012. }
  1013. ret = append(ret, GameUserLadderInfo{
  1014. UserID: gs.Players[i].userID,
  1015. LadderInfo: gs.Players[i].LadderInfo,
  1016. })
  1017. }
  1018. d, _ := json.Marshal(ret)
  1019. return string(d)
  1020. }
  1021. func (gs *GameScene) getCopy() GameScene {
  1022. var ret GameScene
  1023. d, _ := json.Marshal(gs)
  1024. json.Unmarshal(d, &ret)
  1025. return ret
  1026. }
  1027. func (gs *GameScene) getScene(chairId int, isPlayer bool, isOwnerWatCh bool) string {
  1028. tmp := gs.getCopy()
  1029. if gs.Phase == Phase_GameEnd && gs.ScoreToWin < -1 && (gs.ScoreToWin+gs.GameIndex) < -1 && config.Server.IsLadderRoom == 1 {
  1030. tmp.Phase = Phase_End
  1031. }
  1032. if isOwnerWatCh {
  1033. /*for i := 0; i < CHAIR_COUNT; i++ {
  1034. tmp.Players[i].hideSecretData()
  1035. }*/
  1036. d, _ := json.Marshal(tmp)
  1037. return string(d)
  1038. }
  1039. for i := 0; i < CHAIR_COUNT; i++ {
  1040. if gs.Phase == Phase_End || gs.Phase == Phase_GameEnd {
  1041. continue
  1042. }
  1043. if gs.ShowAllCards {
  1044. continue
  1045. }
  1046. if gs.Players[i].CanDoReshuffle && gs.Players[i].ReshuffleAction == Reshuffle_Confirm && gs.Phase == Phase_Reshuffle {
  1047. continue
  1048. }
  1049. if chairId == i {
  1050. continue
  1051. }
  1052. tmp.Players[i].hideSecretData()
  1053. tmp.Players[i].ProjectTips = []int{0, 0, 0, 0}
  1054. }
  1055. d, _ := json.Marshal(tmp)
  1056. return string(d)
  1057. }
  1058. func (gs *GameScene) getAllPlayerCards() [][]int {
  1059. var ret [][]int
  1060. for i := 0; i < CHAIR_COUNT; i++ {
  1061. ret = append(ret, gs.Players[i].HandCards)
  1062. }
  1063. return ret
  1064. }
  1065. func (gs *GameScene) onAllCardsSent() {
  1066. // 插入所有玩家的牌
  1067. for i := 0; i < CHAIR_COUNT; i++ {
  1068. cardList := make([]int, len(gs.Players[i].HandCards))
  1069. copy(cardList, gs.Players[i].HandCards)
  1070. gs.userActions = append(gs.userActions, userAction{
  1071. ChairId: i,
  1072. Action: Action_RoundStart,
  1073. Data: 0,
  1074. ExtData: cardList,
  1075. })
  1076. }
  1077. }
  1078. func (gs *GameScene) getLeftScore() int {
  1079. leftScore := 0
  1080. if gs.FinalClub == Suit_Hokum {
  1081. leftScore = HOKUM_TOTAL_SCORE - gs.Players[0].WinCardScore - gs.Players[1].WinCardScore
  1082. } else {
  1083. leftScore = SUN_TOTAL_SCORE - gs.Players[0].WinCardScore - gs.Players[1].WinCardScore
  1084. }
  1085. return leftScore
  1086. }
  1087. func (gs *GameScene) getLeftCardNumber() int {
  1088. leftCard := CARD_COUNT
  1089. for i := 0; i < CHAIR_COUNT; i++ {
  1090. leftCard -= gs.Players[i].WinCardNumber
  1091. }
  1092. return leftCard
  1093. }