playerinfo.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package gamelogic
  2. import (
  3. "bet24.com/log"
  4. )
  5. type PlayerInfo struct {
  6. IsValid bool //是否有效玩家
  7. Dropped bool //是否已弃牌
  8. AutoOut bool //托管标志
  9. userId int
  10. chairId int
  11. enterGold int
  12. Planes []Plane
  13. LastAction int
  14. Number int //骰子点数
  15. ContinueSixPoint int //连续6点次数
  16. Kills int //击杀次数
  17. Death int //死亡次数
  18. SixPointTotal int //出现6点次数
  19. Place int //名次
  20. Score int //奖金
  21. OpenChannel bool //打开最后的通道
  22. LevelValue int //经验值
  23. round int //回合
  24. hope int //期待点数
  25. hopeRound int //期待回合
  26. isShakeOutHope bool //最近几轮内是否摇出期待点数
  27. writtenScore bool // 是否已写分
  28. bet int //投注金额
  29. isRobot bool //是否机器人
  30. }
  31. func (p *PlayerInfo) initData(chairId, userId, enterGold int) {
  32. p.gameInit()
  33. p.IsValid = false
  34. p.Dropped = false
  35. p.chairId = chairId
  36. p.enterGold = enterGold
  37. p.userId = userId
  38. p.LevelValue = 0
  39. }
  40. func (p *PlayerInfo) gameInit() {
  41. p.AutoOut = false
  42. p.Kills = 0
  43. p.Death = 0
  44. p.SixPointTotal = 0
  45. p.ContinueSixPoint = 0
  46. p.Place = -1
  47. p.Score = 0
  48. p.LastAction = Action_Move // 初始化成move,用于判断第一个动作
  49. p.OpenChannel = false //默认封禁
  50. p.Planes = make([]Plane, PLANE_COUNT)
  51. for i := 0; i < PLANE_COUNT; i++ {
  52. p.Planes[i].Id = i
  53. //前面2个棋子位置设置成1并且可以移动
  54. if i < 2 {
  55. p.Planes[i].Position = 1
  56. p.Planes[i].CanMove = true
  57. } else {
  58. p.Planes[i].CanMove = false
  59. p.Planes[i].Position = 0
  60. }
  61. }
  62. p.round = 0
  63. p.hope = 6 //默认期待起飞点数6
  64. p.hopeRound = 0
  65. p.isShakeOutHope = false
  66. p.writtenScore = false
  67. p.bet = 0
  68. }
  69. func (p *PlayerInfo) dump(chairId int) {
  70. robot := ""
  71. if p.isRobot {
  72. robot = "ROBOT"
  73. }
  74. if p.IsValid {
  75. log.Debug(" ----Player [%d] chair [%d] enterGold:%d dropped:%v IsValid:%v %s", p.userId, chairId, p.enterGold, p.Dropped, p.IsValid, robot)
  76. log.Debug(" OpenChannel[%v] LevelValue[%v] Planes[%v],Place[%d],Score[%d]", p.OpenChannel, p.LevelValue, p.Planes, p.Place, p.Score)
  77. log.Debug(" LastAction[%d],Number[%d]", p.LastAction, p.Number)
  78. log.Debug(" +++++++++++++++++")
  79. }
  80. }
  81. // 可移动棋子不同坐标数量
  82. func (p *PlayerInfo) canMovePlaneCountByPosition() int {
  83. samePosition := make(map[int]int)
  84. for _, v := range p.Planes {
  85. if v.CanMove {
  86. samePosition[v.Position] = 1
  87. }
  88. }
  89. return len(samePosition)
  90. }
  91. // 找可以移动的飞机
  92. func (p *PlayerInfo) canMovePlane(planeId int) (ok bool, Id int, isReach bool, stepCount int, oldPosition int) {
  93. ok = false
  94. Id = planeId
  95. isReach = false
  96. stepCount = -1
  97. if !isValidPlane(planeId) {
  98. log.Release("PlayerInfo.movePlane invalid PlaneId %d", planeId)
  99. return
  100. }
  101. oldPosition = p.Planes[planeId].Position
  102. number := p.Number
  103. if p.Planes[planeId].Position == 0 {
  104. if number != 6 {
  105. log.Release("PlayerInfo.movePlane plane is not take off %d,%d", planeId, number)
  106. return
  107. } else {
  108. p.Planes[planeId].Position = 1 // 起飞
  109. stepCount = 1
  110. ok = true
  111. return
  112. }
  113. }
  114. // 如果不封锁的情况 判断是否超出
  115. if p.OpenChannel && p.Planes[planeId].Position+number > MAX_STEP {
  116. log.Release("PlayerInfo.movePlane Position[%d] + number[%d] > MAX_STEP[%d]", p.Planes[planeId].Position, number, MAX_STEP)
  117. ok = false
  118. return
  119. }
  120. stepCount = number
  121. //限制通过 or 已经超过入口
  122. if !p.OpenChannel || p.Planes[planeId].Position == LOOP_START {
  123. if p.Planes[planeId].Position+number > LOOP_START {
  124. //计算差值剩余的步数由1开始计算
  125. number = number - (LOOP_START - p.Planes[planeId].Position) - 1
  126. p.Planes[planeId].Position = 1
  127. }
  128. p.Planes[planeId].Position += number
  129. } else {
  130. //如果通道打开则不走52
  131. if p.Planes[planeId].Position < LOOP_START && p.Planes[planeId].Position+number >= LOOP_START {
  132. number = number - (LOOP_START - p.Planes[planeId].Position)
  133. p.Planes[planeId].Position = SAFE_START
  134. }
  135. p.Planes[planeId].Position += number
  136. }
  137. ok = true
  138. if p.Planes[planeId].Position == MAX_STEP {
  139. log.Release("PlayerInfo.movePlane Arrive End Position[%d] == MAX_STEP[%d]", p.Planes[planeId].Position, MAX_STEP)
  140. isReach = true
  141. }
  142. return
  143. }
  144. func (p *PlayerInfo) setRollNumber(number int) bool {
  145. p.Number = number
  146. //当骰子连续三次掷出6点时,会自动跳过操作,轮到下一名玩家操作
  147. if number == 6 && p.ContinueSixPoint >= 2 {
  148. p.ContinueSixPoint = 0
  149. p.SixPointTotal++
  150. for i := 0; i < PLANE_COUNT; i++ {
  151. p.Planes[i].CanMove = false
  152. }
  153. return false
  154. }
  155. if number == 6 {
  156. p.ContinueSixPoint++
  157. p.SixPointTotal++
  158. }
  159. for i := 0; i < PLANE_COUNT; i++ {
  160. p.Planes[i].resetCanMove(number)
  161. }
  162. return true
  163. }
  164. func (p *PlayerInfo) isWin() bool {
  165. for _, v := range p.Planes {
  166. //这个版本的逻辑是有一个到达就算赢
  167. if v.isLanded() {
  168. return true
  169. }
  170. }
  171. return false
  172. }
  173. func (p *PlayerInfo) isCanMove() bool {
  174. for _, v := range p.Planes {
  175. if v.CanMove {
  176. return true
  177. }
  178. }
  179. return false
  180. }
  181. // 判断期望点是否可以抵达
  182. func (p *PlayerInfo) isHopeCanArrive() bool {
  183. if p.hope == 6 {
  184. return false
  185. }
  186. for _, v := range p.Planes {
  187. if v.Position+p.hope == MAX_STEP {
  188. return true
  189. }
  190. }
  191. return false
  192. }
  193. // 判断是否即将获胜
  194. func (p *PlayerInfo) isWillWin() {
  195. count := 0
  196. for _, v := range p.Planes {
  197. if p.OpenChannel && v.isWillArrive() {
  198. count++
  199. }
  200. }
  201. if count < 1 {
  202. return
  203. }
  204. //判断当前的期待点数是否可以到达
  205. if p.OpenChannel && p.isHopeCanArrive() {
  206. return
  207. }
  208. hopePoint := p.getArriveHopePoint()
  209. if p.OpenChannel && hopePoint > 0 && hopePoint < 6 && p.hope != hopePoint {
  210. p.hope = hopePoint
  211. p.isShakeOutHope = false
  212. }
  213. }
  214. // 获得即将抵达终点总点数
  215. func (p *PlayerInfo) getArriveHopePoint() int {
  216. if !p.OpenChannel {
  217. return 0
  218. }
  219. validPoints := make(map[int]int)
  220. for _, v := range p.Planes {
  221. distance := v.calculateArriveDistance()
  222. if distance > 0 && distance < 6 {
  223. validPoints[v.Id] = distance
  224. }
  225. }
  226. //Map随机获取
  227. for _, v := range validPoints {
  228. return v
  229. }
  230. return 0
  231. }
  232. // 检查是否撞机
  233. func (p *PlayerInfo) checkCrashed(chairId int, pos int) []*Plane {
  234. var crashed []*Plane
  235. for i := 0; i < PLANE_COUNT; i++ {
  236. if isCrash(chairId, pos, p.chairId, p.Planes[i].Position) {
  237. crashed = append(crashed, &p.Planes[i])
  238. }
  239. }
  240. return crashed
  241. }
  242. // 检查该对手的所有棋子 与自己棋子坐标的关系 0相对安全 1追赶 2超过
  243. func (p *PlayerInfo) checkChairPosition(chairId int, pos int) int {
  244. temp := 0
  245. if pos == 0 || pos >= SAFE_START {
  246. return temp
  247. }
  248. chair1pos := (chairId*13 + pos) % LOOP_START //自己的棋子操作后的位置
  249. for i := 0; i < PLANE_COUNT; i++ {
  250. //这里不能考虑对手位置是否安全 只需要考虑对手是否起飞和进入最后阶段
  251. if p.Planes[i].Position == 0 || p.Planes[i].Position >= SAFE_START {
  252. continue
  253. }
  254. chair2pos := (p.chairId*13 + p.Planes[i].Position) % LOOP_START //棋盘上对手的位置
  255. if chair1pos == chair2pos {
  256. continue
  257. }
  258. //超过对手
  259. if chair1pos > chair2pos && chair1pos-chair2pos <= 6 {
  260. return 2
  261. } else if chair2pos > chair1pos && chair2pos-chair1pos <= 6 {
  262. temp = 1
  263. }
  264. }
  265. return temp
  266. }
  267. // 检查是否在相同位置数量
  268. func (p *PlayerInfo) checkSamePositionCount(position, planeId int) int {
  269. myPlaneCount := 0
  270. for i := 0; i < PLANE_COUNT; i++ {
  271. if p.Planes[i].Id == planeId {
  272. continue
  273. }
  274. if p.Planes[i].Position == 0 {
  275. continue
  276. }
  277. if p.Planes[i].Position == position {
  278. myPlaneCount++
  279. }
  280. }
  281. return myPlaneCount
  282. }
  283. // 计算总位置点数
  284. func (p *PlayerInfo) calculatePosition() int {
  285. //只考虑最远端
  286. farthest := 0
  287. for i := 0; i < PLANE_COUNT; i++ {
  288. if p.Planes[i].Position == 0 {
  289. continue
  290. }
  291. if p.Planes[i].Position > farthest {
  292. farthest = p.Planes[i].Position
  293. }
  294. }
  295. return farthest
  296. }
  297. func (p *PlayerInfo) checkTookOffCount() (int, int) {
  298. tookOff := 0
  299. //离开起飞区
  300. leave := 0
  301. for i := 0; i < PLANE_COUNT; i++ {
  302. if p.Planes[i].isTookOff() {
  303. tookOff++
  304. if p.Planes[i].Position >= 10 {
  305. leave++
  306. }
  307. }
  308. }
  309. return tookOff, leave
  310. }
  311. // 转换棋子坐标
  312. func (p *PlayerInfo) convertPlanePosition(pos int) int {
  313. return (p.chairId*13 + pos) % LOOP_START
  314. }