tablesink_robot.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. package gamelogic
  2. import (
  3. "encoding/json"
  4. "math/rand"
  5. "time"
  6. "bet24.com/log"
  7. "bet24.com/servers/games/luckyfruit_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.WinGoldRankingUsers, userId, 2) {
  50. return true
  51. }
  52. return common.IsInTopN(ts.score_users.BetGoldRankingUsers, userId, 6)
  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
  125. // 下注概率
  126. r := rand.Intn(100)
  127. noBid := true //是否不下注
  128. zoneIndex := 0
  129. //随机下注1-4个区域
  130. numAreasToBet = rand.Intn(4) + 1
  131. switch {
  132. case isInBoard:
  133. noBid = r < 10
  134. //上榜用户随机下注2-4个区域
  135. numAreasToBet = rand.Intn(3) + 2
  136. zoneIndex = 0
  137. case money >= 10000000:
  138. noBid = r < 95
  139. zoneIndex = 5
  140. case money >= 8000000:
  141. noBid = r < 90
  142. zoneIndex = 4
  143. case money >= 5000000:
  144. noBid = r < 85
  145. zoneIndex = 3
  146. case money >= 2000000:
  147. noBid = r < 80
  148. zoneIndex = 2
  149. case money >= 1000000:
  150. noBid = r < 70
  151. zoneIndex = 1
  152. default:
  153. zoneIndex = 0
  154. noBid = r < 50
  155. }
  156. if noBid {
  157. return
  158. }
  159. // 下注区域
  160. bidZone := [][]int{
  161. //Orange Banana Grape Watermelon Apple
  162. {25, 20, 20, 20, 15}, // < 1m
  163. {15, 15, 25, 25, 20}, // < 2m
  164. {25, 20, 20, 15, 20}, // < 5m
  165. {20, 20, 20, 20, 20}, // < 8m
  166. {15, 15, 25, 25, 20}, // < 10m
  167. {15, 20, 20, 30, 15}, // < 15m
  168. {15, 10, 20, 30, 25}, // >= 15m
  169. }
  170. betIds = ts.getRandomIndexesFromArray(bidZone[zoneIndex], numAreasToBet)
  171. bidAmountZone := [][]int{
  172. // 5% 10% %20 %40 %60
  173. {50, 30, 15, 5, 0}, // < 1m
  174. {50, 40, 10, 0, 0}, // < 2m
  175. {40, 30, 30, 0, 0}, // < 5m
  176. {30, 40, 30, 0, 0}, // < 8m
  177. {40, 20, 40, 0, 0}, // < 10m
  178. {30, 50, 20, 0, 0}, // < 15m
  179. {60, 40, 0, 0, 0}, // >= 15m
  180. }
  181. // 选金额
  182. bidAmountPercent := []int{2, 5, 10, 20, 40}
  183. chipAmounts := []int{100, 1000, 5000, 10000, 100000}
  184. //用最大可以下注额下注
  185. bidAmount := maxBet / 100 * bidAmountPercent[ts.getRandomIndexFromArray(bidAmountZone[zoneIndex])]
  186. bidAmount = maxBet / 100 * (50 + rand.Intn(30))
  187. percentage := 100
  188. betPercentages := make([]int, len(betIds))
  189. for i := 0; i < len(betIds)-1; i++ { // 对除了最后一个区域之外的区域进行随机分配
  190. min := 10 // 最低百分比
  191. max := percentage - min*(len(betIds)-i-1) // 最高百分比,保证剩余的区域都能有最低百分比
  192. if max < min {
  193. max = min
  194. }
  195. betPercentages[i] = min + rand.Intn(max-min+1) // 生成一个[min, max]之间的随机整数
  196. percentage -= betPercentages[i] // 更新剩余的总配比
  197. }
  198. betPercentages[len(betIds)-1] = percentage
  199. for i := 0; i < len(betIds); i++ {
  200. amountsForBet := []int{}
  201. curPercentage := betPercentages[i]
  202. // 使用百分比计算金额
  203. amount := int(float64(bidAmount*curPercentage) / 100)
  204. if amount < ts.roomInfo.MinBet { // 如果低于最低下注额,就设为最低下注额
  205. amount = ts.roomInfo.MinBet
  206. }
  207. partialAmount := amount
  208. //fmt.Printf("第%d次下注,百分比是%d%%,金额是%d\n", i+1, curPercentage, partialAmount)
  209. for i := len(chipAmounts) - 1; i >= 0; i-- {
  210. if partialAmount >= chipAmounts[i] {
  211. chip := chipAmounts[i]
  212. count := partialAmount / chip
  213. if count < 3 {
  214. continue
  215. }
  216. for j := 0; j < count; j++ {
  217. amountsForBet = append(amountsForBet, chip)
  218. }
  219. partialAmount %= chip
  220. }
  221. }
  222. amounts = append(amounts, amountsForBet)
  223. }
  224. //打印日志
  225. //log.Release("机器人下注 betIds:%v amounts:%v ", betIds, amounts)
  226. return
  227. }
  228. func (ts *tablesink) getRandomIndexesFromArray(a []int, n int) []int {
  229. if len(a) <= 1 {
  230. return []int{0}
  231. }
  232. total := 0
  233. for _, v := range a {
  234. total += v
  235. }
  236. if total == 0 {
  237. return []int{0}
  238. }
  239. if n > len(a) {
  240. n = len(a)
  241. }
  242. indexes := make([]int, 0, n)
  243. used := make(map[int]bool)
  244. for len(indexes) < n {
  245. r := rand.Intn(total)
  246. index := 0
  247. for i := 0; i < len(a); i++ {
  248. index += a[i]
  249. if r < index && !used[i] {
  250. indexes = append(indexes, i)
  251. used[i] = true
  252. break
  253. }
  254. }
  255. }
  256. return indexes
  257. }
  258. func (ts *tablesink) getRandomIndexFromArray(a []int) int {
  259. if len(a) <= 1 {
  260. return 0
  261. }
  262. total := 0
  263. for _, v := range a {
  264. total += v
  265. }
  266. if total == 0 {
  267. return 0
  268. }
  269. r := rand.Intn(total)
  270. index := 0
  271. for i := 0; i < len(a); i++ {
  272. index += a[i]
  273. if r < index {
  274. return i
  275. }
  276. }
  277. return 0
  278. }
  279. func (ts *tablesink) checkRobotAction() bool {
  280. now := time.Now().UnixNano() / 1000000
  281. ts.robotLock.Lock()
  282. defer ts.robotLock.Unlock()
  283. for i := 0; i < len(ts.robotActions); {
  284. if ts.robotActions[i].actionTime <= now {
  285. go ts.doRobotAction(ts.robotActions[i])
  286. ts.robotActions = append(ts.robotActions[:i], ts.robotActions[i+1:]...)
  287. } else {
  288. i++
  289. }
  290. }
  291. return len(ts.robotActions) == 0
  292. }
  293. func (ts *tablesink) doRobotAction(action robot_action) {
  294. go ts.handleBet(action.robot, action.userId, action.bidCmd)
  295. }
  296. func (ts *tablesink) startRobotPoll() {
  297. if gs.GetRobotCount() == 0 {
  298. return
  299. }
  300. //if ts.robotStopEvent == nil {
  301. ts.robotStopEvent = make(chan bool)
  302. //}
  303. ticker := time.NewTicker(50 * time.Millisecond)
  304. go func(t *time.Ticker) {
  305. for { //循环
  306. select {
  307. case <-ts.robotStopEvent:
  308. t.Stop()
  309. log.Debug("robotStopEvent")
  310. ts.robotStopEvent = nil
  311. return
  312. case <-t.C:
  313. if ts.checkRobotAction() {
  314. t.Stop()
  315. ts.robotStopEvent = nil
  316. return
  317. }
  318. }
  319. }
  320. }(ticker)
  321. ts.robotStopEvent = nil
  322. }
  323. func (ts *tablesink) stopRobotPoll() {
  324. if ts.robotStopEvent == nil {
  325. return
  326. }
  327. //log.Debug("stopRobotPoll called")
  328. ts.robotStopEvent <- true
  329. ts.robotStopEvent = nil
  330. }