tablesink_robot.go 8.2 KB

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