tablesink_robot.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. package gamelogic
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "time"
  6. "bet24.com/log"
  7. "bet24.com/servers/games/masharie_table/common"
  8. "bet24.com/servers/insecureframe/robot"
  9. "bet24.com/servers/user"
  10. )
  11. var numAreasToBet = 2
  12. type robot_action struct {
  13. bidCmd string
  14. actionTime int64
  15. robot int32
  16. userId int
  17. }
  18. func (ts *tablesink) checkRobot() {
  19. count := gs.GetRoomRobotCount(ts.roomInfo.RoomName)
  20. if count == 0 {
  21. return
  22. }
  23. needCount := count - ts.getRobotCount()
  24. if needCount <= 0 {
  25. return
  26. }
  27. goldMin, goldMax := gs.GetRoomRobotGoldLimit(ts.roomInfo.RoomName)
  28. tableId := ts.table.GetTableID()
  29. for i := 0; i < count; i++ {
  30. time.AfterFunc(time.Duration(rand.Intn(1000))*time.Millisecond, func() {
  31. robot.GetOneRobotEnterTable(tableId, goldMin, goldMax)
  32. })
  33. }
  34. }
  35. func (ts *tablesink) getRobotCount() int {
  36. userlist := ts.table.GetUserList()
  37. ret := 0
  38. for _, v := range userlist {
  39. if v.IsRobot() {
  40. ret++
  41. }
  42. }
  43. return ret
  44. }
  45. // 是否上榜
  46. func (ts *tablesink) isInRankBoard(userId int) bool {
  47. ts.lock.RLock()
  48. defer ts.lock.RUnlock()
  49. if common.IsInTopN(ts.score_users.LuckyStarUsers, userId, 1) {
  50. return true
  51. }
  52. return common.IsInTopN(ts.score_users.BetGoldRankingUsers, userId, 7)
  53. }
  54. func (ts *tablesink) arrangeRobotActions() {
  55. // 清理
  56. ts.robotLock.Lock()
  57. ts.robotActions = []robot_action{}
  58. ts.robotLock.Unlock()
  59. // 获取用户列表
  60. userlist := ts.table.GetUserList()
  61. var robotList []*user.UserInfo
  62. //真人数量
  63. userCount := 0
  64. for _, v := range userlist {
  65. if v.IsRobot() {
  66. robotList = append(robotList, v)
  67. } else {
  68. userCount++
  69. }
  70. }
  71. if len(robotList) == 0 {
  72. log.Debug("tablesink.arrangeRobotActions no robot")
  73. return
  74. }
  75. now := time.Now().UnixNano() / 1000000
  76. index := 0
  77. for _, v := range robotList {
  78. index++
  79. if userCount == 0 {
  80. //百分之60的概率跳过机器人下注
  81. if rand.Intn(100) < 60 {
  82. continue
  83. }
  84. }
  85. gold := ts.table.GetUserChipOrGoldByUser(v)
  86. isInBoard := ts.isInRankBoard(v.GetUserId())
  87. betIds, amounts := ts.getRobotAction(isInBoard, gold)
  88. // 如果没有投注区域或没有投注次数,则跳过这个机器人
  89. if len(betIds) == 0 || len(amounts) == 0 {
  90. continue
  91. }
  92. // 延迟时间 = 1-下注时间秒-2秒 + 0-100毫秒 + 50毫秒*投注索引
  93. delayTime := int64((rand.Intn(ts.roomInfo.BetTime-2)+1)*1000 + rand.Intn(100) + index*50)
  94. ts.robotLock.Lock()
  95. for i, betId := range betIds {
  96. //如果没有投注金额,则跳过这个投注区域
  97. if len(amounts[i]) == 0 {
  98. continue
  99. }
  100. for _, amount := range amounts[i] {
  101. cmdBid := common.Bet{
  102. UserId: v.GetUserId(),
  103. Index: index,
  104. BetBase: common.BetBase{
  105. BetId: betId,
  106. Amount: amount,
  107. },
  108. }
  109. d, _ := json.Marshal(cmdBid)
  110. ts.robotActions = append(ts.robotActions, robot_action{
  111. bidCmd: string(d),
  112. actionTime: now + delayTime + int64((50+rand.Intn(500))*i),
  113. robot: v.GetUserIndex(),
  114. userId: v.GetUserId(),
  115. })
  116. }
  117. }
  118. ts.robotLock.Unlock()
  119. }
  120. ts.startRobotPoll()
  121. }
  122. // 获取机器人动作
  123. func (ts *tablesink) getRobotAction(isInBoard bool, money int) (betIds []int, amounts [][]int) {
  124. maxBet := money / ts.roomInfo.PersonalBetRatio
  125. // 下注概率
  126. r := rand.Intn(100)
  127. noBid := true //是否不下注
  128. zoneIndex := 0
  129. if !isInBoard {
  130. //随机下注2-4个区域
  131. numAreasToBet = rand.Intn(3) + 2
  132. }
  133. switch {
  134. case isInBoard:
  135. noBid = r < 10
  136. //上榜用户随机下注1-4个区域
  137. numAreasToBet = rand.Intn(4) + 1
  138. zoneIndex = 0
  139. case money >= 10000000:
  140. noBid = r < 95
  141. zoneIndex = 5
  142. case money >= 8000000:
  143. noBid = r < 90
  144. zoneIndex = 4
  145. case money >= 5000000:
  146. noBid = r < 85
  147. zoneIndex = 3
  148. case money >= 2000000:
  149. noBid = r < 80
  150. zoneIndex = 2
  151. case money >= 1000000:
  152. noBid = r < 70
  153. zoneIndex = 1
  154. default:
  155. zoneIndex = 0
  156. noBid = r < 50
  157. }
  158. if noBid {
  159. return
  160. }
  161. // 下注区域
  162. bidZone := [][]int{
  163. // BidType_Diamond BidType_Club BidType_Heart BidType_Spade
  164. {25, 25, 25, 25}, // < 1m
  165. {25, 25, 25, 25}, // < 2m
  166. {25, 25, 25, 25}, // < 5m
  167. {25, 25, 25, 25}, // < 8m
  168. {25, 25, 25, 25}, // < 10m
  169. {25, 25, 25, 25}, // < 15m
  170. {25, 25, 25, 25}, // >= 15m
  171. }
  172. betIds = ts.getRandomIndexesFromArray(bidZone[zoneIndex], numAreasToBet)
  173. bidAmountZone := [][]int{
  174. // 5% 10% %20 %40 %60
  175. {50, 30, 15, 5, 0}, // < 1m
  176. {50, 40, 10, 0, 0}, // < 2m
  177. {40, 30, 30, 0, 0}, // < 5m
  178. {30, 40, 30, 0, 0}, // < 8m
  179. {40, 20, 40, 0, 0}, // < 10m
  180. {30, 50, 20, 0, 0}, // < 15m
  181. {60, 40, 0, 0, 0}, // >= 15m
  182. }
  183. // 选金额
  184. bidAmountPercent := []int{2, 5, 10, 20, 40}
  185. chipAmounts := []int{100, 1000, 5000, 10000, 100000}
  186. //用最大可以下注额下注
  187. bidAmount := maxBet / 100 * bidAmountPercent[ts.getRandomIndexFromArray(bidAmountZone[zoneIndex])]
  188. bidAmount = maxBet / 100 * (50 + rand.Intn(30))
  189. percentage := 100
  190. betPercentages := make([]int, len(betIds))
  191. for i := 0; i < len(betIds)-1; i++ { // 对除了最后一个区域之外的区域进行随机分配
  192. min := 10 // 最低百分比
  193. max := percentage - min*(len(betIds)-i-1) // 最高百分比,保证剩余的区域都能有最低百分比
  194. if max < min {
  195. max = min
  196. }
  197. betPercentages[i] = min + rand.Intn(max-min+1) // 生成一个[min, max]之间的随机整数
  198. percentage -= betPercentages[i] // 更新剩余的总配比
  199. }
  200. betPercentages[len(betIds)-1] = percentage
  201. for i := 0; i < len(betIds); i++ {
  202. amountsForBet := []int{}
  203. curPercentage := betPercentages[i]
  204. // 使用百分比计算金额
  205. amount := int(float64(bidAmount*curPercentage) / 100)
  206. if amount < ts.roomInfo.MinBet { // 如果低于最低下注额,就设为最低下注额
  207. amount = ts.roomInfo.MinBet
  208. }
  209. partialAmount := amount
  210. //fmt.Printf("第%d次下注,百分比是%d%%,金额是%d\n", i+1, curPercentage, partialAmount)
  211. for i := len(chipAmounts) - 1; i >= 0; i-- {
  212. if partialAmount >= chipAmounts[i] {
  213. chip := chipAmounts[i]
  214. count := partialAmount / chip
  215. if count < 3 {
  216. continue
  217. }
  218. for j := 0; j < count; j++ {
  219. amountsForBet = append(amountsForBet, chip)
  220. }
  221. partialAmount %= chip
  222. }
  223. }
  224. amounts = append(amounts, amountsForBet)
  225. }
  226. //打印日志
  227. //log.Release("机器人下注 betIds:%v amounts:%v ", betIds, amounts)
  228. return
  229. }
  230. func (ts *tablesink) getRandomIndexesFromArray(a []int, n int) []int {
  231. if len(a) <= 1 {
  232. return []int{0}
  233. }
  234. total := 0
  235. for _, v := range a {
  236. total += v
  237. }
  238. if total == 0 {
  239. return []int{0}
  240. }
  241. if n > len(a) {
  242. n = len(a)
  243. }
  244. indexes := make([]int, 0, n)
  245. used := make(map[int]bool)
  246. for len(indexes) < n {
  247. r := rand.Intn(total)
  248. index := 0
  249. for i := 0; i < len(a); i++ {
  250. index += a[i]
  251. if r < index && !used[i] {
  252. indexes = append(indexes, i)
  253. used[i] = true
  254. break
  255. }
  256. }
  257. }
  258. return indexes
  259. }
  260. func (ts *tablesink) getRandomIndexFromArray(a []int) int {
  261. if len(a) <= 1 {
  262. return 0
  263. }
  264. total := 0
  265. for _, v := range a {
  266. total += v
  267. }
  268. if total == 0 {
  269. return 0
  270. }
  271. r := rand.Intn(total)
  272. index := 0
  273. for i := 0; i < len(a); i++ {
  274. index += a[i]
  275. if r < index {
  276. return i
  277. }
  278. }
  279. return 0
  280. }
  281. func (ts *tablesink) checkRobotAction() bool {
  282. now := time.Now().UnixNano() / 1000000
  283. ts.robotLock.Lock()
  284. defer ts.robotLock.Unlock()
  285. for i := 0; i < len(ts.robotActions); {
  286. if ts.robotActions[i].actionTime <= now {
  287. go ts.doRobotAction(ts.robotActions[i])
  288. ts.robotActions = append(ts.robotActions[:i], ts.robotActions[i+1:]...)
  289. } else {
  290. i++
  291. }
  292. }
  293. return len(ts.robotActions) == 0
  294. }
  295. func (ts *tablesink) doRobotAction(action robot_action) {
  296. go ts.handleBet(action.robot, action.userId, action.bidCmd)
  297. }
  298. func (ts *tablesink) startRobotPoll() {
  299. if gs.GetRobotCount() == 0 {
  300. return
  301. }
  302. //if ts.robotStopEvent == nil {
  303. ts.robotStopEvent = make(chan bool)
  304. //}
  305. ticker := time.NewTicker(50 * time.Millisecond)
  306. go func(t *time.Ticker) {
  307. for { //循环
  308. select {
  309. case <-ts.robotStopEvent:
  310. t.Stop()
  311. log.Debug("robotStopEvent")
  312. ts.robotStopEvent = nil
  313. return
  314. case <-t.C:
  315. if ts.checkRobotAction() {
  316. t.Stop()
  317. ts.robotStopEvent = nil
  318. return
  319. }
  320. }
  321. }
  322. }(ticker)
  323. ts.robotStopEvent = nil
  324. }
  325. func (ts *tablesink) stopRobotPoll() {
  326. if ts.robotStopEvent == nil {
  327. return
  328. }
  329. //log.Debug("stopRobotPoll called")
  330. ts.robotStopEvent <- true
  331. ts.robotStopEvent = nil
  332. }