freespin.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package slotpanda
  2. import (
  3. "bet24.com/log"
  4. "bet24.com/servers/micros/slotsservice/handler/slotcommon/slotcount"
  5. "encoding/json"
  6. "math/rand"
  7. )
  8. type FreeSlotChange struct {
  9. SlotId int
  10. Chance int
  11. }
  12. // 每组的15个slot信息
  13. type FreeSlots struct {
  14. Slots []int // 实际Slot
  15. ChangedRows []int // 被变换的列
  16. Lines []Result // 中奖连线
  17. WinAmount int
  18. }
  19. type FreeSpinResult struct {
  20. BetAmount int
  21. Slots []FreeSlots
  22. TotalFreeCount int // 总free次数
  23. LeftFreeCount int // 当前free次数
  24. MaxScatter int // 最大数量
  25. CurScatter int // 当前数量
  26. ReFreeInner int // 当scatter满了后,产生新的轮盘
  27. ReFreeOuter int
  28. }
  29. func (fr *FreeSpinResult) getWinAmount() int {
  30. ret := 0
  31. for _, v := range fr.Slots {
  32. ret += v.WinAmount
  33. }
  34. return ret
  35. }
  36. func (fr *FreeSpinResult) getDesc() string {
  37. d, _ := json.Marshal(fr.Slots)
  38. return string(d)
  39. }
  40. type FreeSpinInfo struct {
  41. userId int
  42. freeSlotCount *slotcount.MultipleSlotCountManager
  43. slotmgr *slotmanager
  44. winShapes []WinShape
  45. wins []Win
  46. Changes []FreeSlotChange
  47. BetAmount int
  48. TotalCount int
  49. LeftCount int
  50. MaxScatter int // 最大数量
  51. CurScatter int // 当前数量
  52. scatterId int
  53. bonusId int
  54. wildId int
  55. level int
  56. isChipRoom bool
  57. }
  58. func newFreeSpinInfo(userId int, freeSlotCount *slotcount.MultipleSlotCountManager, winShapes []WinShape, wins []Win, slotmgr *slotmanager, changes []FreeSlotChange) *FreeSpinInfo {
  59. ret := new(FreeSpinInfo)
  60. ret.userId = userId
  61. ret.freeSlotCount = freeSlotCount
  62. ret.winShapes = winShapes
  63. ret.wins = wins
  64. ret.slotmgr = slotmgr
  65. ret.MaxScatter = 100
  66. ret.scatterId = slotmgr.getScatterSlotId()
  67. ret.bonusId = slotmgr.getBonusSlotId()
  68. ret.wildId = slotmgr.getWildSlotId()
  69. ret.Changes = changes
  70. return ret
  71. }
  72. func (f *FreeSpinInfo) useFreeSpin() (bool, FreeSpinResult, bool) {
  73. var ret FreeSpinResult
  74. if f.LeftCount <= 0 {
  75. return false, ret, false
  76. }
  77. level := 0
  78. sc := f.freeSlotCount.GetMgr(level)
  79. f.LeftCount--
  80. ret.MaxScatter = f.MaxScatter
  81. ret.CurScatter = f.CurScatter
  82. ret.TotalFreeCount = f.TotalCount
  83. ret.LeftFreeCount = f.LeftCount
  84. ret.BetAmount = f.BetAmount
  85. // 产生4组
  86. // 变化为同一个素材
  87. changedSlotId := f.getChangeSlot()
  88. for i := 0; i < 4; i++ {
  89. var fs FreeSlots
  90. slots := sc.Get15Slots(f.level)
  91. // 随机一列发
  92. faLineCount := 1
  93. r := rand.Intn(100)
  94. if r < 50 {
  95. faLineCount = 1
  96. } else if r < 85 {
  97. faLineCount = 2
  98. } else {
  99. faLineCount = 3
  100. }
  101. firstFaLine := -1
  102. for i := 0; i < faLineCount; i++ {
  103. line := rand.Intn(5)
  104. for {
  105. if line == firstFaLine {
  106. line = rand.Intn(5)
  107. } else {
  108. break
  109. }
  110. }
  111. /*
  112. if changedSlotId == -1 {
  113. changedSlotId = slots[line]
  114. }
  115. // 如果素材为scatter,bonus,wild,则不能变成一列,需要重新找一个新的元素
  116. if changedSlotId == f.scatterId || changedSlotId == f.bonusId || changedSlotId == f.wildId {
  117. changedSlotId = -1
  118. continue
  119. }
  120. */
  121. firstFaLine = line
  122. slots[line] = changedSlotId
  123. slots[line+5] = slots[line]
  124. slots[line+10] = slots[line]
  125. fs.ChangedRows = append(fs.ChangedRows, line)
  126. }
  127. fs.Slots = slots
  128. // 添加scatter
  129. for _, v := range slots {
  130. if v == f.scatterId {
  131. inner, outer := f.addScatter()
  132. if inner > 0 {
  133. ret.ReFreeInner = inner
  134. ret.ReFreeOuter = outer
  135. }
  136. }
  137. }
  138. // 计算结果
  139. shapeCount := len(f.winShapes)
  140. for k, v := range f.winShapes {
  141. // 查看每条连线的数量
  142. s := make([]Slot, RESULT_COUNT)
  143. for i := 0; i < 15; i++ {
  144. s[i] = f.slotmgr.getSlot(slots[i])
  145. }
  146. slotID, slotCount, _ := v.getCount(s)
  147. // 查看结果
  148. result := f.getOneResult(slotID, slotCount, k)
  149. if result != nil {
  150. // 中奖了
  151. fs.WinAmount += f.BetAmount * result.WinRate / shapeCount
  152. fs.Lines = append(fs.Lines, *result)
  153. }
  154. }
  155. ret.Slots = append(ret.Slots, fs)
  156. }
  157. return true, ret, f.isChipRoom
  158. }
  159. func (f *FreeSpinInfo) getFreeCount() int {
  160. return f.LeftCount
  161. }
  162. func (f *FreeSpinInfo) addScatter() (int, int) {
  163. f.CurScatter++
  164. if f.CurScatter >= f.MaxScatter {
  165. f.CurScatter = 0
  166. inner, outer := f.getMultiple()
  167. f.TotalCount += inner * outer
  168. f.LeftCount += inner * outer
  169. log.Release("slotpanda.FreeSpinInfo.addScatter %d", f.TotalCount)
  170. return inner, outer
  171. }
  172. return 0, 0
  173. }
  174. // 获得免费奖励
  175. func (f *FreeSpinInfo) initFree(betAmount int, slots []int, isChipRoom bool) (int, int) {
  176. scatterCount := 0
  177. for _, v := range slots {
  178. if v == f.scatterId {
  179. scatterCount++
  180. }
  181. }
  182. if scatterCount < 3 {
  183. return 0, 0
  184. }
  185. f.BetAmount = betAmount
  186. inner, outer := f.getMultiple()
  187. f.TotalCount = inner * outer
  188. f.LeftCount = f.TotalCount
  189. f.CurScatter = 0
  190. f.isChipRoom = isChipRoom
  191. log.Release("slotpanda.FreeSpinInfo.initFree %d", f.TotalCount)
  192. return inner, outer
  193. }
  194. func (f *FreeSpinInfo) removeFreeTimes(times int) {
  195. f.TotalCount -= times
  196. f.LeftCount -= times
  197. if f.TotalCount < 0 {
  198. f.TotalCount = 0
  199. }
  200. if f.LeftCount < 0 {
  201. f.LeftCount = 0
  202. }
  203. }
  204. func (f *FreeSpinInfo) getMultiple() (inner, outer int) {
  205. inner = rand.Intn(3) + 1
  206. r := rand.Intn(100)
  207. if r < 35 {
  208. outer = 4
  209. return
  210. }
  211. r -= 35
  212. if r < 35 {
  213. outer = 8
  214. return
  215. }
  216. r -= 35
  217. if r < 20 {
  218. outer = 12
  219. return
  220. }
  221. outer = 16
  222. return
  223. }
  224. func (f *FreeSpinInfo) getOneResult(slotID, slotCount, shapeID int) *Result {
  225. for _, v := range f.wins {
  226. if v.SlotID != slotID {
  227. continue
  228. }
  229. for _, rate := range v.Rates {
  230. if rate.Count == slotCount {
  231. return &Result{SlotID: slotID, SlotCount: slotCount, WinShapeID: shapeID, WinRate: rate.Win}
  232. }
  233. }
  234. }
  235. return nil
  236. }
  237. func (f *FreeSpinInfo) getChangeSlot() int {
  238. if len(f.Changes) == 0 {
  239. return 3
  240. }
  241. total := 0
  242. for _, v := range f.Changes {
  243. total += v.Chance
  244. }
  245. r := rand.Intn(total)
  246. for _, v := range f.Changes {
  247. if r < v.Chance {
  248. return v.SlotId
  249. }
  250. r -= v.Chance
  251. }
  252. log.Release("FreeSpinInfo.getChangeSlot should not come here")
  253. return 3
  254. }