freespin.go 6.2 KB

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