gamedefs.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. package gamelogic
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "bet24.com/log"
  6. task "bet24.com/servers/micros/task/proto"
  7. )
  8. // 公共数据定义
  9. const (
  10. GAMEID = 37
  11. GAME_NAME = "baloot"
  12. CHAIR_COUNT = 4
  13. SCORE_TO_WIN = 152
  14. LAST_WIN_SCORE = 10
  15. ALL_WIN_EXTRA_SCORE = 90
  16. HOKUM_TOTAL_SCORE = 152
  17. SUN_TOTAL_SCORE = 120
  18. MIN_OUT_MS = 500
  19. VALUE_DOUBLING_LEN = 15
  20. WINDUP_SCORE = 120
  21. MAX_DOUBLING_LIMIT = 256
  22. )
  23. // 任务类型定义
  24. const (
  25. TaskAction_Baloot80 = task.TaskAction_gameaction + 1
  26. TaskAction_Baloot100 = task.TaskAction_gameaction + 2
  27. TaskAction_Baloot120 = task.TaskAction_gameaction + 3
  28. TaskAction_Baloot_Sun = task.TaskAction_gameaction + 4
  29. )
  30. // 机器人默认动作时间
  31. const (
  32. MS_MinRobotNotFirstOut = 800 // 非首出最小时间(毫秒)
  33. MS_MaxRobotNotFirstOut = 1000 // 非首出最大时间(毫秒)
  34. MS_DiminishingNotFirstOut = 50 // 非首出递减时间(毫秒)
  35. MS_MinRobotFirstOut = 1200 // 首出最小时间(毫秒)
  36. MS_MaxRobotFirstOut = 1500 // 首出最大时间(毫秒)
  37. MS_DiminishingFirstOut = 100 // 首出递减时间(毫秒)
  38. )
  39. // 上报分数类型
  40. const (
  41. ScoreType_Bet = 0
  42. ScoreType_End = 1
  43. ScoreType_Return = 2
  44. ScoreType_Flee = 3
  45. scoreType_Surrender = 4
  46. )
  47. const (
  48. RobotChatAction_MuiltyTimeOut = iota
  49. RobotChatAction_LoseOverFive
  50. RobotChatAction_LoseOverEighty
  51. RobotChatAction_FriendGetBigProject
  52. RobotChatAction_SelfWinOverFive
  53. RobotChatAction_GoodHandCard
  54. RobotChatAction_BadHandCard
  55. RobotChatAction_EmenyGetBigProject
  56. RobotChatAction_EnterRoom
  57. RobotChatAction_Reply
  58. RobotChatAction_FriendWinOverFive
  59. )
  60. // commands
  61. const (
  62. CMD_ROOMINFO = "CMD_ROOMINFO"
  63. CMD_TABLECHAT = "CMD_TABLECHAT"
  64. CMD_CANCLE_AUTO = "CMD_CANCLE_AUTO"
  65. CMD_AUTO = "CMD_AUTO"
  66. CMD_ACTION = "CMD_ACTION"
  67. CMD_ACTION_FAILED = "CMD_ACTION_FAILED"
  68. CMD_SHOW_CARDTYPE = "CMD_SHOW_CARDTYPE"
  69. CMD_CALL_BALOOT = "CMD_CALL_BALOOT"
  70. CMD_SHOWDOUBLING = "CMD_SHOWDOUBLING"
  71. CMD_SYNCDATA = "CMD_SYNCDATA"
  72. CMD_SURRENDER = "CMD_SURRENDER"
  73. CMD_SURRENDER_RESULT = "CMD_SURRENDER_RESULT"
  74. CMD_LADDERINFO = "CMD_LADDERINFO"
  75. CMD_SMALL_RESULT = "CMD_SMALL_RESULT"
  76. )
  77. // 游戏阶段
  78. const (
  79. Phase_Free = iota
  80. Phase_Start // 发牌
  81. Phase_FirstBuy // 第一次买牌阶段
  82. Phase_SecondBuy // 第二次买牌阶段
  83. Phase_ChooseTrump // 选择花色
  84. Phase_Reshuffle // 是否重新洗牌
  85. Phase_Double // 加倍阶段
  86. Phase_CloseOpen // 开关阶段
  87. Phase_SendLeftCard // 发剩余牌阶段
  88. Phase_Play // 出牌
  89. Phase_GameEnd // 中间结算
  90. Phase_End // 结束
  91. Phase_Correct // 纠错模式
  92. )
  93. // 游戏阶段描述
  94. func getPhaseDesc(phase int) string {
  95. switch phase {
  96. case Phase_Free:
  97. return "Free"
  98. case Phase_Start:
  99. return "Start"
  100. case Phase_FirstBuy:
  101. return "FirstBuy"
  102. case Phase_SecondBuy:
  103. return "SecondBuy"
  104. case Phase_ChooseTrump:
  105. return "ChooseTrump"
  106. case Phase_Reshuffle:
  107. return "Reshuffle"
  108. case Phase_Double:
  109. return "Double"
  110. case Phase_CloseOpen:
  111. return "CloseOpen"
  112. case Phase_SendLeftCard:
  113. return "SendLeftCard"
  114. case Phase_Play:
  115. return "Play"
  116. case Phase_Correct:
  117. return "Correct"
  118. case Phase_GameEnd:
  119. return "GameEnd"
  120. case Phase_End:
  121. return "End"
  122. }
  123. return "Invalid"
  124. }
  125. // 定时器ID
  126. const (
  127. TIMER_READY_0 = iota
  128. TIMER_READY_1
  129. TIMER_READY_2
  130. TIMER_READY_3
  131. TIMER_GAME
  132. TIMER_REMOVE_ROBOT
  133. TIMER_ADD_ROBOT
  134. TIMER_SEND_LEFT_CARD
  135. TIMER_START_OUT_CARD
  136. TIMER_NEWROUND
  137. TIMER_ROBOT_ACTION_0
  138. TIMER_ROBOT_ACTION_1
  139. TIMER_ROBOT_ACTION_2
  140. TIMER_ROBOT_ACTION_3
  141. TIMER_AUTO_ACTION_0
  142. TIMER_AUTO_ACTION_1
  143. TIMER_AUTO_ACTION_2
  144. TIMER_AUTO_ACTION_3
  145. TIMER_ALL_PASS // 所有玩家两次都不买牌,延迟重新发牌
  146. TIMER_BUY_CHANGE
  147. TIMER_DOUBLE_CHANGE
  148. TIMER_DELAY_END
  149. TIMER_START_GAME
  150. TIMER_SAWA
  151. TIMER_CORRECTFINISH
  152. TIMER_CORRECTDELAY
  153. TIMER_SURRENDER
  154. TIMER_ROBOT_SURRENDER
  155. TIMER_ROBOT_REPLY
  156. TIMER_ROBOT_SEND_CHAT_0
  157. TIMER_ROBOT_SEND_CHAT_1
  158. TIMER_ROBOT_SEND_CHAT_2
  159. TIMER_ROBOT_SEND_CHAT_3
  160. )
  161. // 定时器时间
  162. const (
  163. SEC_READY = 60 * 1000 //准备计时
  164. SEC_START = 5000
  165. SEC_AUTO = 800
  166. SEC_SET_END = 3 * 1000
  167. SEC_ROBOT_CHAT = 7000
  168. SEC_SEND_LEFT_CARD = 1000
  169. SEC_START_OUT_CARD = 2000
  170. SEC_NEWROUND = 1000
  171. SEC_ALL_PASS = 100
  172. SEC_RESHUFFLE = 10 * 1000
  173. SEC_SAWA = 5000
  174. SEC_CORRECTFINISH = 5000
  175. SCE_CORRECT_DELAY = 3000
  176. )
  177. // 动作类型
  178. const (
  179. Action_Buy = iota // 买牌
  180. Action_ChooseTrump // 选择花色
  181. Action_Reshuffle // 重洗
  182. Action_Double // hokum模式下加倍操作
  183. Action_CloseOrOpen // 是否打开和关闭
  184. Action_OutCard // 出一张牌
  185. Action_Gawah // 把手中牌全部打出去(在玩家手中牌全部为最大的时候)
  186. Action_GameEnd
  187. Action_RoundEnd
  188. Action_RoundStart
  189. Action_CorrectionStart
  190. Action_CorrectionFinish
  191. Action_Sawa
  192. Action_Invalid
  193. )
  194. // 动作描述
  195. func getActionDesc(action int) string {
  196. switch action {
  197. case Action_Buy:
  198. return "buy"
  199. case Action_Double:
  200. return "dbl"
  201. case Action_Reshuffle:
  202. return "shuffle"
  203. case Action_ChooseTrump:
  204. return "cho"
  205. case Action_CloseOrOpen:
  206. return "clorop"
  207. case Action_Gawah:
  208. return "gawah"
  209. case Action_OutCard:
  210. return "out"
  211. case Action_CorrectionStart:
  212. return "correctStart"
  213. case Action_CorrectionFinish:
  214. return "correctFinish"
  215. case Action_Sawa:
  216. return "sawa"
  217. case Action_GameEnd:
  218. return "---game_end---"
  219. case Action_RoundEnd:
  220. return "--"
  221. }
  222. return "n/a"
  223. }
  224. // 买牌的操作Param
  225. const (
  226. Action_Buy_Pass = iota
  227. Action_Buy_Hokum
  228. Action_Buy_Sun
  229. Action_Buy_Ashkal
  230. Action_Buy_ConfirmHokum
  231. Action_Buy_SwitchSun
  232. Action_Buy_Double
  233. Action_Buy_Triple
  234. Action_Buy_Four
  235. Action_Buy_Coffee
  236. Action_Buy_Invaild
  237. )
  238. // 买牌的操作描述
  239. func getBuyActionDesc(action int) string {
  240. switch action {
  241. case Action_Buy_Pass:
  242. return "Pass"
  243. case Action_Buy_Hokum:
  244. return "Hokum"
  245. case Action_Buy_Sun:
  246. return "Sun"
  247. case Action_Buy_Ashkal:
  248. return "Ashkal"
  249. case Action_Buy_ConfirmHokum:
  250. return "ConfirmHokum"
  251. case Action_Buy_SwitchSun:
  252. return "SwitchSun"
  253. case Action_Buy_Double:
  254. return "Double"
  255. case Action_Buy_Triple:
  256. return "Triple"
  257. case Action_Buy_Four:
  258. return "Four"
  259. case Action_Buy_Coffee:
  260. return "Coffee"
  261. }
  262. return "Invalid"
  263. }
  264. // 游戏模式定义
  265. const (
  266. Suit_Hokum = iota // 有主
  267. Suit_Sun // 无主
  268. Suit_Ashkal // 无主公共牌给对友
  269. Suit_Invalid
  270. )
  271. // 游戏模式描述
  272. func getSuitDesc(suit int) string {
  273. switch suit {
  274. case Suit_Hokum:
  275. return "Hokum"
  276. case Suit_Sun:
  277. return "Sun"
  278. case Suit_Ashkal:
  279. return "Ashkal"
  280. }
  281. return "Invalid"
  282. }
  283. // 开关动作定义
  284. const (
  285. Action_Buy_Close = 1
  286. Action_Buy_Open = 2
  287. )
  288. // 开关动作描述
  289. func getCloseOrOpenDesc(data int) string {
  290. switch data {
  291. case Action_Buy_Close:
  292. return "close"
  293. case Action_Buy_Open:
  294. return "open"
  295. }
  296. return "Invalid"
  297. }
  298. // 重洗动作
  299. const (
  300. Reshuffle_None = iota
  301. Reshuffle_Pass // pass不重洗
  302. Reshuffle_Confirm // 确定重洗
  303. )
  304. // 重洗描述
  305. func getReshuffleDesc(action int) string {
  306. switch action {
  307. case Reshuffle_Pass:
  308. return "Pass"
  309. case Reshuffle_Confirm:
  310. return "Confirm"
  311. }
  312. return "Invalid"
  313. }
  314. // project 类型
  315. const (
  316. PROJECT_SIRA = iota
  317. PROJECT_FIFTY
  318. PROJECT_HUNDRED
  319. PROJECT_FOURHUNDRED
  320. PROJECT_BALOOT
  321. PROJECT_INVALID
  322. )
  323. var value_project = []int{20, 50, 100, 200, 20}
  324. var value_project_task = []int{20, 50, 100, 400, 20}
  325. // 项目数据定义
  326. type SingleProject struct {
  327. Type int
  328. Score int
  329. Cards []int
  330. taskScore int // 任务分
  331. }
  332. // 项目比较
  333. func (sp SingleProject) isBiggerThan(project SingleProject) bool {
  334. if sp.Type > project.Type {
  335. return true
  336. }
  337. if sp.Type < project.Type {
  338. return false
  339. }
  340. if getCardValue(sp.Cards[0]) > getCardValue(project.Cards[0]) {
  341. return true
  342. }
  343. if getCardValue(sp.Cards[0]) < getCardValue(project.Cards[0]) {
  344. return false
  345. }
  346. return getCardType(sp.Cards[0]) > getCardType(project.Cards[0])
  347. }
  348. // 项目描述
  349. func (sp SingleProject) getProjectHex() string {
  350. str := getCardsHex(sp.Cards)
  351. switch sp.Type {
  352. case PROJECT_SIRA:
  353. return "sira:" + str
  354. case PROJECT_FIFTY:
  355. return "50:" + str
  356. case PROJECT_HUNDRED:
  357. return "100:" + str
  358. case PROJECT_FOURHUNDRED:
  359. return "400:" + str
  360. case PROJECT_BALOOT:
  361. return "baloot:" + str
  362. }
  363. return ""
  364. }
  365. // 买牌和出牌的动作
  366. type CmdAction struct {
  367. Action int
  368. Param int
  369. Projects []int
  370. CorrectCards []int
  371. }
  372. // 玩家动作失败
  373. type CmdActionFailed struct {
  374. CmdAction
  375. ErrMsg string
  376. }
  377. // 纠错模式定义
  378. const (
  379. Correct_Normal = iota
  380. Correct_Sawa
  381. Correct_Invaild
  382. )
  383. // 纠错模式描述
  384. func getCorrectModeDesc(mode int) string {
  385. switch mode {
  386. case Correct_Normal:
  387. return "Normal"
  388. case Correct_Sawa:
  389. return "Sawa"
  390. }
  391. return "Invaild"
  392. }
  393. // 纠错类型定义
  394. const (
  395. CorrectType_SameType = iota // 手上有相同花色没有出
  396. CorrectType_BigCardInHokum // 在hokum模式下,这轮花色为主牌花色主牌,玩家手上有必须要出的BigCard却没出
  397. CorrectType_Close // 关闭状态下,第一个出牌的人出了主牌花色,但是其手上还有其他花色
  398. CorrectType_TrumpCard // 在hokum模式下,这轮花色为非主牌花色主牌,玩家手上有必须要出的BigCard却没出
  399. CorrectType_Invaild
  400. )
  401. func getCorrectTypeDesc(correctType int) string {
  402. switch correctType {
  403. case CorrectType_SameType:
  404. return "SameType"
  405. case CorrectType_BigCardInHokum:
  406. return "BigCardInHokum"
  407. case CorrectType_Close:
  408. return "Close"
  409. case CorrectType_TrumpCard:
  410. return "TrumpCard"
  411. }
  412. return "InvaildType"
  413. }
  414. // 翻倍类型定义
  415. const (
  416. Doubling_Project_Sira = iota
  417. Doubling_Project_Fifty
  418. Doubling_Project_Hundred
  419. Doubling_Project_FourHundred
  420. Doubling_Project_Baloot
  421. Doubling_PublicCard_J
  422. Doubling_Call_Double
  423. Doubling_Call_Triple
  424. Doubling_Call_Four
  425. Doubling_Call_Coffee
  426. Doubling_Hokum_to_Sun
  427. Doubling_Hokum_to_Ashkal
  428. Doubling_Ashkal_to_Sun
  429. Doubling_Sun_to_Sun
  430. Doubling_ConsecutiveWinOverFour
  431. )
  432. // 翻倍类型描述
  433. func getDoublingTypeHex(doublingType int) string {
  434. switch doublingType {
  435. case Doubling_Project_Sira:
  436. return "Project_Sira"
  437. case Doubling_Project_Fifty:
  438. return "Project_Fifty"
  439. case Doubling_Project_Hundred:
  440. return "Project_Hundred"
  441. case Doubling_Project_FourHundred:
  442. return "Project_FourHundred"
  443. case Doubling_Project_Baloot:
  444. return "Project_Baloot"
  445. case Doubling_PublicCard_J:
  446. return "PublicCard_J"
  447. case Doubling_Call_Double:
  448. return "Call_Double"
  449. case Doubling_Call_Triple:
  450. return "Call_Triple"
  451. case Doubling_Call_Four:
  452. return "Call_Four"
  453. case Doubling_Call_Coffee:
  454. return "Call_Coffee"
  455. case Doubling_Hokum_to_Sun:
  456. return "Doubling_Hokum_to_Sun"
  457. case Doubling_Hokum_to_Ashkal:
  458. return "Doubling_Hokum_to_Ashkal"
  459. case Doubling_Ashkal_to_Sun:
  460. return "Doubling_Ashkal_to_Sun"
  461. case Doubling_Sun_to_Sun:
  462. return "Doubling_Sun_to_Sun"
  463. case Doubling_ConsecutiveWinOverFour:
  464. return "ConsecutiveWinOverFour"
  465. }
  466. return "Invaild DoublingType"
  467. }
  468. var value_doubling = []int{2, 3, 4, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
  469. // 翻倍数据
  470. type DoublingData struct {
  471. DoublingType int
  472. DoublingTimes int
  473. }
  474. // 翻倍数据描述
  475. func (dd *DoublingData) dump() {
  476. log.Debug(" type[%s] times:%d", getDoublingTypeHex(dd.DoublingType), dd.DoublingTimes)
  477. }
  478. // 每轮赢牌方翻倍总分和对应轮数
  479. type DoublingDetail struct {
  480. RoundIndex int
  481. DoublingTotalTimes int
  482. }
  483. // 每轮赢牌方翻倍总分和对应轮数描述
  484. func (dd *DoublingDetail) dump() {
  485. log.Debug(" roundIndex:%d totalTimes:%d", dd.RoundIndex, dd.DoublingTotalTimes)
  486. }
  487. // CMD_SHOWDOUBLING数据结构
  488. type ShowDoubling struct {
  489. Index int
  490. Times int
  491. }
  492. // CMD_SHOW_CARDTYPE数据结构
  493. type ShowCardType struct {
  494. Type int // 展示的花色
  495. Chair int // 谁买的花色
  496. }
  497. // 上报回放数据结构
  498. type userAction struct {
  499. ChairId int
  500. Action int
  501. Data int
  502. ExtData []int
  503. }
  504. func isAllZero(data []int) bool {
  505. for i := 0; i < len(data); i++ {
  506. if data[i] > 0 {
  507. return false
  508. }
  509. }
  510. return true
  511. }
  512. // 上报回放数据描述
  513. func (ua *userAction) dump() {
  514. data := fmt.Sprintf("%d", ua.Data)
  515. if ua.Action == Action_RoundEnd {
  516. data = getTypeDesc(ua.Data)
  517. } else if ua.Action == Action_OutCard {
  518. data = getCardHex(ua.Data)
  519. if len(ua.ExtData) > 0 && !isAllZero(ua.ExtData) {
  520. data = fmt.Sprintf("%s%v", data, ua.ExtData)
  521. }
  522. } else if ua.Action == Action_Buy {
  523. data = getBuyActionDesc(ua.Data)
  524. } else if ua.Action == Action_ChooseTrump {
  525. data = getChooseTrumpDesc(ua.Data)
  526. } else if ua.Action == Action_CloseOrOpen {
  527. data = getCloseOrOpenDesc(ua.Data)
  528. } else if ua.Action == Action_Gawah {
  529. data = fmt.Sprintf("Gawah Chair[%d]", ua.Data)
  530. } else if ua.Action == Action_Double {
  531. data = getBuyActionDesc(ua.Data)
  532. } else if ua.Action == Action_Reshuffle {
  533. data = getReshuffleDesc(ua.Data)
  534. } else if ua.Action == Action_CorrectionStart {
  535. data = fmt.Sprintf("CorrectMode:%s", getCorrectModeDesc(ua.Data))
  536. } else if ua.Action == Action_Sawa {
  537. data = "CallSawa"
  538. } else if ua.Action == Action_CorrectionFinish {
  539. data = "[" + getCorrectTypeDesc(ua.Data) + "]" + getCardsHex(ua.ExtData)
  540. }
  541. if ua.Action == Action_GameEnd {
  542. log.Debug(" ------ game end %s", fmt.Sprintf("[%d,%d,%d,%d]",
  543. ua.Data/1000000000, (ua.Data/1000000)%1000, (ua.Data/1000)%1000, ua.Data%1000))
  544. return
  545. }
  546. if ua.Action == Action_RoundEnd {
  547. log.Debug(" ------- %s", data)
  548. return
  549. }
  550. if ua.Action == Action_RoundStart {
  551. log.Debug(" Chair[%d] Cards:%s", ua.ChairId, getCardsHex(ua.ExtData))
  552. return
  553. }
  554. log.Debug(" Chair[%d],Action[%s],Data[%s]", ua.ChairId, getActionDesc(ua.Action), data)
  555. }
  556. func isValidChair(chairId int) bool {
  557. return chairId >= 0 && chairId < CHAIR_COUNT
  558. }
  559. func isPreviousChair(preChair, curChair int) bool {
  560. return (preChair+CHAIR_COUNT-1)%CHAIR_COUNT == curChair
  561. }
  562. func isFriendChair(chair1, chair2 int) bool {
  563. return (chair1+2)%CHAIR_COUNT == chair2
  564. }
  565. func getFriendChair(chair int) int {
  566. return (chair + 2) % CHAIR_COUNT
  567. }
  568. func getPreviousChair(chair int) int {
  569. return (chair + CHAIR_COUNT - 1) % CHAIR_COUNT
  570. }
  571. func getNextChair(curChair int) int {
  572. return (curChair + 1) % CHAIR_COUNT
  573. }
  574. func isSameTeam(chair1, chair2 int) bool {
  575. return chair1%2 == chair2%2
  576. }
  577. type perRoundScores struct {
  578. positionScore0 int
  579. positionScore1 int
  580. }
  581. func getScoreHistoryDesc(scoreHistory []perRoundScores) string {
  582. ret := ""
  583. for i := 0; i < len(scoreHistory); i++ {
  584. ret += "["
  585. ret += fmt.Sprintf("%d", scoreHistory[i].positionScore0)
  586. ret += ": "
  587. ret += fmt.Sprintf("%d", scoreHistory[i].positionScore1)
  588. ret += "]"
  589. if i != (len(scoreHistory) - 1) {
  590. ret += ", "
  591. }
  592. }
  593. return ret
  594. }
  595. const (
  596. Surrender_None = 0 // 等待队友确认
  597. Surrender_Success = 1 // 成功
  598. Surrender_Failed = 2 // 失败
  599. )
  600. // 投降信息
  601. type SurrenderInfo struct {
  602. WhoseSurrender int // 谁发起的投降
  603. SurrenderResult int // 投降结果
  604. isSurrendering bool // 是否正在投降
  605. }
  606. func newSurrenderInfo() *SurrenderInfo {
  607. di := new(SurrenderInfo)
  608. di.initData()
  609. return di
  610. }
  611. func (di *SurrenderInfo) initData() {
  612. di.WhoseSurrender = -1
  613. di.SurrenderResult = Surrender_None
  614. di.isSurrendering = false
  615. }
  616. func (di *SurrenderInfo) getSurrenderInfo() string {
  617. d, _ := json.Marshal(di)
  618. return string(d)
  619. }
  620. func (di *SurrenderInfo) canDoSurrender(chairId int) bool {
  621. if !di.isSurrendering || !isValidChair(di.WhoseSurrender) {
  622. return false
  623. }
  624. return isSameTeam(chairId, di.WhoseSurrender) && di.SurrenderResult == Surrender_None
  625. }
  626. func (di *SurrenderInfo) isSurrenderEnd() bool {
  627. if !di.isSurrendering || !isValidChair(di.WhoseSurrender) {
  628. return false
  629. }
  630. return di.SurrenderResult == Surrender_Success
  631. }
  632. const (
  633. RobotType_Cautious = iota
  634. RobotType_LAGs
  635. RobotType_Playfulness
  636. )
  637. type weightInfo struct {
  638. chair int
  639. weight int
  640. }
  641. type robotChatActionList struct {
  642. round int
  643. action []robotChatAction
  644. }
  645. type robotChatAction struct {
  646. count int
  647. chatType int
  648. }
  649. func (r *robotChatAction) getDesc() string {
  650. switch r.chatType {
  651. case RobotChatAction_MuiltyTimeOut:
  652. return "有两次超过5秒没操作"
  653. case RobotChatAction_LoseOverFive:
  654. return "连续5回合没得分"
  655. case RobotChatAction_LoseOverEighty:
  656. return "回合结束相差超过80分"
  657. case RobotChatAction_FriendGetBigProject:
  658. return "队友获得50项目或以上时"
  659. case RobotChatAction_SelfWinOverFive:
  660. return "玩家连续五回合得分"
  661. case RobotChatAction_GoodHandCard:
  662. return "拿到牌之后,我赢的分数高的概率很高"
  663. case RobotChatAction_BadHandCard:
  664. return "手里的牌大部分都是10一下"
  665. case RobotChatAction_EmenyGetBigProject:
  666. return "对手拿到了100-400项目"
  667. case RobotChatAction_EnterRoom:
  668. return "发你好"
  669. case RobotChatAction_Reply:
  670. return "回你好"
  671. case RobotChatAction_FriendWinOverFive:
  672. return "机器人队友连续5回合赢"
  673. }
  674. return ""
  675. }
  676. func getRobotChatDesc(chatList []robotChatAction) string {
  677. ret := "["
  678. for _, v := range chatList {
  679. ret += fmt.Sprintf("%s: %d", v.getDesc(), v.count)
  680. ret += " "
  681. }
  682. ret += "]"
  683. return ret
  684. }