| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769 |
- package gamelogic
- import (
- "encoding/json"
- "fmt"
- "bet24.com/log"
- task "bet24.com/servers/micros/task/proto"
- )
- // 公共数据定义
- const (
- GAMEID = 37
- GAME_NAME = "baloot"
- CHAIR_COUNT = 4
- SCORE_TO_WIN = 152
- LAST_WIN_SCORE = 10
- ALL_WIN_EXTRA_SCORE = 90
- HOKUM_TOTAL_SCORE = 152
- SUN_TOTAL_SCORE = 120
- MIN_OUT_MS = 500
- VALUE_DOUBLING_LEN = 15
- WINDUP_SCORE = 120
- MAX_DOUBLING_LIMIT = 256
- )
- // 任务类型定义
- const (
- TaskAction_Baloot80 = task.TaskAction_gameaction + 1
- TaskAction_Baloot100 = task.TaskAction_gameaction + 2
- TaskAction_Baloot120 = task.TaskAction_gameaction + 3
- TaskAction_Baloot_Sun = task.TaskAction_gameaction + 4
- )
- // 机器人默认动作时间
- const (
- MS_MinRobotNotFirstOut = 800 // 非首出最小时间(毫秒)
- MS_MaxRobotNotFirstOut = 1000 // 非首出最大时间(毫秒)
- MS_DiminishingNotFirstOut = 50 // 非首出递减时间(毫秒)
- MS_MinRobotFirstOut = 1200 // 首出最小时间(毫秒)
- MS_MaxRobotFirstOut = 1500 // 首出最大时间(毫秒)
- MS_DiminishingFirstOut = 100 // 首出递减时间(毫秒)
- )
- // 上报分数类型
- const (
- ScoreType_Bet = 0
- ScoreType_End = 1
- ScoreType_Return = 2
- ScoreType_Flee = 3
- scoreType_Surrender = 4
- )
- const (
- RobotChatAction_MuiltyTimeOut = iota
- RobotChatAction_LoseOverFive
- RobotChatAction_LoseOverEighty
- RobotChatAction_FriendGetBigProject
- RobotChatAction_SelfWinOverFive
- RobotChatAction_GoodHandCard
- RobotChatAction_BadHandCard
- RobotChatAction_EmenyGetBigProject
- RobotChatAction_EnterRoom
- RobotChatAction_Reply
- RobotChatAction_FriendWinOverFive
- )
- // commands
- const (
- CMD_ROOMINFO = "CMD_ROOMINFO"
- CMD_TABLECHAT = "CMD_TABLECHAT"
- CMD_CANCLE_AUTO = "CMD_CANCLE_AUTO"
- CMD_AUTO = "CMD_AUTO"
- CMD_ACTION = "CMD_ACTION"
- CMD_ACTION_FAILED = "CMD_ACTION_FAILED"
- CMD_SHOW_CARDTYPE = "CMD_SHOW_CARDTYPE"
- CMD_CALL_BALOOT = "CMD_CALL_BALOOT"
- CMD_SHOWDOUBLING = "CMD_SHOWDOUBLING"
- CMD_SYNCDATA = "CMD_SYNCDATA"
- CMD_SURRENDER = "CMD_SURRENDER"
- CMD_SURRENDER_RESULT = "CMD_SURRENDER_RESULT"
- CMD_LADDERINFO = "CMD_LADDERINFO"
- CMD_SMALL_RESULT = "CMD_SMALL_RESULT"
- )
- // 游戏阶段
- const (
- Phase_Free = iota
- Phase_Start // 发牌
- Phase_FirstBuy // 第一次买牌阶段
- Phase_SecondBuy // 第二次买牌阶段
- Phase_ChooseTrump // 选择花色
- Phase_Reshuffle // 是否重新洗牌
- Phase_Double // 加倍阶段
- Phase_CloseOpen // 开关阶段
- Phase_SendLeftCard // 发剩余牌阶段
- Phase_Play // 出牌
- Phase_GameEnd // 中间结算
- Phase_End // 结束
- Phase_Correct // 纠错模式
- )
- // 游戏阶段描述
- func getPhaseDesc(phase int) string {
- switch phase {
- case Phase_Free:
- return "Free"
- case Phase_Start:
- return "Start"
- case Phase_FirstBuy:
- return "FirstBuy"
- case Phase_SecondBuy:
- return "SecondBuy"
- case Phase_ChooseTrump:
- return "ChooseTrump"
- case Phase_Reshuffle:
- return "Reshuffle"
- case Phase_Double:
- return "Double"
- case Phase_CloseOpen:
- return "CloseOpen"
- case Phase_SendLeftCard:
- return "SendLeftCard"
- case Phase_Play:
- return "Play"
- case Phase_Correct:
- return "Correct"
- case Phase_GameEnd:
- return "GameEnd"
- case Phase_End:
- return "End"
- }
- return "Invalid"
- }
- // 定时器ID
- const (
- TIMER_READY_0 = iota
- TIMER_READY_1
- TIMER_READY_2
- TIMER_READY_3
- TIMER_GAME
- TIMER_REMOVE_ROBOT
- TIMER_ADD_ROBOT
- TIMER_SEND_LEFT_CARD
- TIMER_START_OUT_CARD
- TIMER_NEWROUND
- TIMER_ROBOT_ACTION_0
- TIMER_ROBOT_ACTION_1
- TIMER_ROBOT_ACTION_2
- TIMER_ROBOT_ACTION_3
- TIMER_AUTO_ACTION_0
- TIMER_AUTO_ACTION_1
- TIMER_AUTO_ACTION_2
- TIMER_AUTO_ACTION_3
- TIMER_ALL_PASS // 所有玩家两次都不买牌,延迟重新发牌
- TIMER_BUY_CHANGE
- TIMER_DOUBLE_CHANGE
- TIMER_DELAY_END
- TIMER_START_GAME
- TIMER_SAWA
- TIMER_CORRECTFINISH
- TIMER_CORRECTDELAY
- TIMER_SURRENDER
- TIMER_ROBOT_SURRENDER
- TIMER_ROBOT_REPLY
- TIMER_ROBOT_SEND_CHAT_0
- TIMER_ROBOT_SEND_CHAT_1
- TIMER_ROBOT_SEND_CHAT_2
- TIMER_ROBOT_SEND_CHAT_3
- )
- // 定时器时间
- const (
- SEC_READY = 60 * 1000 //准备计时
- SEC_START = 5000
- SEC_AUTO = 800
- SEC_SET_END = 3 * 1000
- SEC_ROBOT_CHAT = 7000
- SEC_SEND_LEFT_CARD = 1000
- SEC_START_OUT_CARD = 2000
- SEC_NEWROUND = 1000
- SEC_ALL_PASS = 100
- SEC_RESHUFFLE = 10 * 1000
- SEC_SAWA = 5000
- SEC_CORRECTFINISH = 5000
- SCE_CORRECT_DELAY = 3000
- )
- // 动作类型
- const (
- Action_Buy = iota // 买牌
- Action_ChooseTrump // 选择花色
- Action_Reshuffle // 重洗
- Action_Double // hokum模式下加倍操作
- Action_CloseOrOpen // 是否打开和关闭
- Action_OutCard // 出一张牌
- Action_Gawah // 把手中牌全部打出去(在玩家手中牌全部为最大的时候)
- Action_GameEnd
- Action_RoundEnd
- Action_RoundStart
- Action_CorrectionStart
- Action_CorrectionFinish
- Action_Sawa
- Action_Invalid
- )
- // 动作描述
- func getActionDesc(action int) string {
- switch action {
- case Action_Buy:
- return "buy"
- case Action_Double:
- return "dbl"
- case Action_Reshuffle:
- return "shuffle"
- case Action_ChooseTrump:
- return "cho"
- case Action_CloseOrOpen:
- return "clorop"
- case Action_Gawah:
- return "gawah"
- case Action_OutCard:
- return "out"
- case Action_CorrectionStart:
- return "correctStart"
- case Action_CorrectionFinish:
- return "correctFinish"
- case Action_Sawa:
- return "sawa"
- case Action_GameEnd:
- return "---game_end---"
- case Action_RoundEnd:
- return "--"
- }
- return "n/a"
- }
- // 买牌的操作Param
- const (
- Action_Buy_Pass = iota
- Action_Buy_Hokum
- Action_Buy_Sun
- Action_Buy_Ashkal
- Action_Buy_ConfirmHokum
- Action_Buy_SwitchSun
- Action_Buy_Double
- Action_Buy_Triple
- Action_Buy_Four
- Action_Buy_Coffee
- Action_Buy_Invaild
- )
- // 买牌的操作描述
- func getBuyActionDesc(action int) string {
- switch action {
- case Action_Buy_Pass:
- return "Pass"
- case Action_Buy_Hokum:
- return "Hokum"
- case Action_Buy_Sun:
- return "Sun"
- case Action_Buy_Ashkal:
- return "Ashkal"
- case Action_Buy_ConfirmHokum:
- return "ConfirmHokum"
- case Action_Buy_SwitchSun:
- return "SwitchSun"
- case Action_Buy_Double:
- return "Double"
- case Action_Buy_Triple:
- return "Triple"
- case Action_Buy_Four:
- return "Four"
- case Action_Buy_Coffee:
- return "Coffee"
- }
- return "Invalid"
- }
- // 游戏模式定义
- const (
- Suit_Hokum = iota // 有主
- Suit_Sun // 无主
- Suit_Ashkal // 无主公共牌给对友
- Suit_Invalid
- )
- // 游戏模式描述
- func getSuitDesc(suit int) string {
- switch suit {
- case Suit_Hokum:
- return "Hokum"
- case Suit_Sun:
- return "Sun"
- case Suit_Ashkal:
- return "Ashkal"
- }
- return "Invalid"
- }
- // 开关动作定义
- const (
- Action_Buy_Close = 1
- Action_Buy_Open = 2
- )
- // 开关动作描述
- func getCloseOrOpenDesc(data int) string {
- switch data {
- case Action_Buy_Close:
- return "close"
- case Action_Buy_Open:
- return "open"
- }
- return "Invalid"
- }
- // 重洗动作
- const (
- Reshuffle_None = iota
- Reshuffle_Pass // pass不重洗
- Reshuffle_Confirm // 确定重洗
- )
- // 重洗描述
- func getReshuffleDesc(action int) string {
- switch action {
- case Reshuffle_Pass:
- return "Pass"
- case Reshuffle_Confirm:
- return "Confirm"
- }
- return "Invalid"
- }
- // project 类型
- const (
- PROJECT_SIRA = iota
- PROJECT_FIFTY
- PROJECT_HUNDRED
- PROJECT_FOURHUNDRED
- PROJECT_BALOOT
- PROJECT_INVALID
- )
- var value_project = []int{20, 50, 100, 200, 20}
- var value_project_task = []int{20, 50, 100, 400, 20}
- // 项目数据定义
- type SingleProject struct {
- Type int
- Score int
- Cards []int
- taskScore int // 任务分
- }
- // 项目比较
- func (sp SingleProject) isBiggerThan(project SingleProject) bool {
- if sp.Type > project.Type {
- return true
- }
- if sp.Type < project.Type {
- return false
- }
- if getCardValue(sp.Cards[0]) > getCardValue(project.Cards[0]) {
- return true
- }
- if getCardValue(sp.Cards[0]) < getCardValue(project.Cards[0]) {
- return false
- }
- return getCardType(sp.Cards[0]) > getCardType(project.Cards[0])
- }
- // 项目描述
- func (sp SingleProject) getProjectHex() string {
- str := getCardsHex(sp.Cards)
- switch sp.Type {
- case PROJECT_SIRA:
- return "sira:" + str
- case PROJECT_FIFTY:
- return "50:" + str
- case PROJECT_HUNDRED:
- return "100:" + str
- case PROJECT_FOURHUNDRED:
- return "400:" + str
- case PROJECT_BALOOT:
- return "baloot:" + str
- }
- return ""
- }
- // 买牌和出牌的动作
- type CmdAction struct {
- Action int
- Param int
- Projects []int
- CorrectCards []int
- }
- // 玩家动作失败
- type CmdActionFailed struct {
- CmdAction
- ErrMsg string
- }
- // 纠错模式定义
- const (
- Correct_Normal = iota
- Correct_Sawa
- Correct_Invaild
- )
- // 纠错模式描述
- func getCorrectModeDesc(mode int) string {
- switch mode {
- case Correct_Normal:
- return "Normal"
- case Correct_Sawa:
- return "Sawa"
- }
- return "Invaild"
- }
- // 纠错类型定义
- const (
- CorrectType_SameType = iota // 手上有相同花色没有出
- CorrectType_BigCardInHokum // 在hokum模式下,这轮花色为主牌花色主牌,玩家手上有必须要出的BigCard却没出
- CorrectType_Close // 关闭状态下,第一个出牌的人出了主牌花色,但是其手上还有其他花色
- CorrectType_TrumpCard // 在hokum模式下,这轮花色为非主牌花色主牌,玩家手上有必须要出的BigCard却没出
- CorrectType_Invaild
- )
- func getCorrectTypeDesc(correctType int) string {
- switch correctType {
- case CorrectType_SameType:
- return "SameType"
- case CorrectType_BigCardInHokum:
- return "BigCardInHokum"
- case CorrectType_Close:
- return "Close"
- case CorrectType_TrumpCard:
- return "TrumpCard"
- }
- return "InvaildType"
- }
- // 翻倍类型定义
- const (
- Doubling_Project_Sira = iota
- Doubling_Project_Fifty
- Doubling_Project_Hundred
- Doubling_Project_FourHundred
- Doubling_Project_Baloot
- Doubling_PublicCard_J
- Doubling_Call_Double
- Doubling_Call_Triple
- Doubling_Call_Four
- Doubling_Call_Coffee
- Doubling_Hokum_to_Sun
- Doubling_Hokum_to_Ashkal
- Doubling_Ashkal_to_Sun
- Doubling_Sun_to_Sun
- Doubling_ConsecutiveWinOverFour
- )
- // 翻倍类型描述
- func getDoublingTypeHex(doublingType int) string {
- switch doublingType {
- case Doubling_Project_Sira:
- return "Project_Sira"
- case Doubling_Project_Fifty:
- return "Project_Fifty"
- case Doubling_Project_Hundred:
- return "Project_Hundred"
- case Doubling_Project_FourHundred:
- return "Project_FourHundred"
- case Doubling_Project_Baloot:
- return "Project_Baloot"
- case Doubling_PublicCard_J:
- return "PublicCard_J"
- case Doubling_Call_Double:
- return "Call_Double"
- case Doubling_Call_Triple:
- return "Call_Triple"
- case Doubling_Call_Four:
- return "Call_Four"
- case Doubling_Call_Coffee:
- return "Call_Coffee"
- case Doubling_Hokum_to_Sun:
- return "Doubling_Hokum_to_Sun"
- case Doubling_Hokum_to_Ashkal:
- return "Doubling_Hokum_to_Ashkal"
- case Doubling_Ashkal_to_Sun:
- return "Doubling_Ashkal_to_Sun"
- case Doubling_Sun_to_Sun:
- return "Doubling_Sun_to_Sun"
- case Doubling_ConsecutiveWinOverFour:
- return "ConsecutiveWinOverFour"
- }
- return "Invaild DoublingType"
- }
- var value_doubling = []int{2, 3, 4, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
- // 翻倍数据
- type DoublingData struct {
- DoublingType int
- DoublingTimes int
- }
- // 翻倍数据描述
- func (dd *DoublingData) dump() {
- log.Debug(" type[%s] times:%d", getDoublingTypeHex(dd.DoublingType), dd.DoublingTimes)
- }
- // 每轮赢牌方翻倍总分和对应轮数
- type DoublingDetail struct {
- RoundIndex int
- DoublingTotalTimes int
- }
- // 每轮赢牌方翻倍总分和对应轮数描述
- func (dd *DoublingDetail) dump() {
- log.Debug(" roundIndex:%d totalTimes:%d", dd.RoundIndex, dd.DoublingTotalTimes)
- }
- // CMD_SHOWDOUBLING数据结构
- type ShowDoubling struct {
- Index int
- Times int
- }
- // CMD_SHOW_CARDTYPE数据结构
- type ShowCardType struct {
- Type int // 展示的花色
- Chair int // 谁买的花色
- }
- // 上报回放数据结构
- type userAction struct {
- ChairId int
- Action int
- Data int
- ExtData []int
- }
- func isAllZero(data []int) bool {
- for i := 0; i < len(data); i++ {
- if data[i] > 0 {
- return false
- }
- }
- return true
- }
- // 上报回放数据描述
- func (ua *userAction) dump() {
- data := fmt.Sprintf("%d", ua.Data)
- if ua.Action == Action_RoundEnd {
- data = getTypeDesc(ua.Data)
- } else if ua.Action == Action_OutCard {
- data = getCardHex(ua.Data)
- if len(ua.ExtData) > 0 && !isAllZero(ua.ExtData) {
- data = fmt.Sprintf("%s%v", data, ua.ExtData)
- }
- } else if ua.Action == Action_Buy {
- data = getBuyActionDesc(ua.Data)
- } else if ua.Action == Action_ChooseTrump {
- data = getChooseTrumpDesc(ua.Data)
- } else if ua.Action == Action_CloseOrOpen {
- data = getCloseOrOpenDesc(ua.Data)
- } else if ua.Action == Action_Gawah {
- data = fmt.Sprintf("Gawah Chair[%d]", ua.Data)
- } else if ua.Action == Action_Double {
- data = getBuyActionDesc(ua.Data)
- } else if ua.Action == Action_Reshuffle {
- data = getReshuffleDesc(ua.Data)
- } else if ua.Action == Action_CorrectionStart {
- data = fmt.Sprintf("CorrectMode:%s", getCorrectModeDesc(ua.Data))
- } else if ua.Action == Action_Sawa {
- data = "CallSawa"
- } else if ua.Action == Action_CorrectionFinish {
- data = "[" + getCorrectTypeDesc(ua.Data) + "]" + getCardsHex(ua.ExtData)
- }
- if ua.Action == Action_GameEnd {
- log.Debug(" ------ game end %s", fmt.Sprintf("[%d,%d,%d,%d]",
- ua.Data/1000000000, (ua.Data/1000000)%1000, (ua.Data/1000)%1000, ua.Data%1000))
- return
- }
- if ua.Action == Action_RoundEnd {
- log.Debug(" ------- %s", data)
- return
- }
- if ua.Action == Action_RoundStart {
- log.Debug(" Chair[%d] Cards:%s", ua.ChairId, getCardsHex(ua.ExtData))
- return
- }
- log.Debug(" Chair[%d],Action[%s],Data[%s]", ua.ChairId, getActionDesc(ua.Action), data)
- }
- func isValidChair(chairId int) bool {
- return chairId >= 0 && chairId < CHAIR_COUNT
- }
- func isPreviousChair(preChair, curChair int) bool {
- return (preChair+CHAIR_COUNT-1)%CHAIR_COUNT == curChair
- }
- func isFriendChair(chair1, chair2 int) bool {
- return (chair1+2)%CHAIR_COUNT == chair2
- }
- func getFriendChair(chair int) int {
- return (chair + 2) % CHAIR_COUNT
- }
- func getPreviousChair(chair int) int {
- return (chair + CHAIR_COUNT - 1) % CHAIR_COUNT
- }
- func getNextChair(curChair int) int {
- return (curChair + 1) % CHAIR_COUNT
- }
- func isSameTeam(chair1, chair2 int) bool {
- return chair1%2 == chair2%2
- }
- type perRoundScores struct {
- positionScore0 int
- positionScore1 int
- }
- func getScoreHistoryDesc(scoreHistory []perRoundScores) string {
- ret := ""
- for i := 0; i < len(scoreHistory); i++ {
- ret += "["
- ret += fmt.Sprintf("%d", scoreHistory[i].positionScore0)
- ret += ": "
- ret += fmt.Sprintf("%d", scoreHistory[i].positionScore1)
- ret += "]"
- if i != (len(scoreHistory) - 1) {
- ret += ", "
- }
- }
- return ret
- }
- const (
- Surrender_None = 0 // 等待队友确认
- Surrender_Success = 1 // 成功
- Surrender_Failed = 2 // 失败
- )
- // 投降信息
- type SurrenderInfo struct {
- WhoseSurrender int // 谁发起的投降
- SurrenderResult int // 投降结果
- isSurrendering bool // 是否正在投降
- }
- func newSurrenderInfo() *SurrenderInfo {
- di := new(SurrenderInfo)
- di.initData()
- return di
- }
- func (di *SurrenderInfo) initData() {
- di.WhoseSurrender = -1
- di.SurrenderResult = Surrender_None
- di.isSurrendering = false
- }
- func (di *SurrenderInfo) getSurrenderInfo() string {
- d, _ := json.Marshal(di)
- return string(d)
- }
- func (di *SurrenderInfo) canDoSurrender(chairId int) bool {
- if !di.isSurrendering || !isValidChair(di.WhoseSurrender) {
- return false
- }
- return isSameTeam(chairId, di.WhoseSurrender) && di.SurrenderResult == Surrender_None
- }
- func (di *SurrenderInfo) isSurrenderEnd() bool {
- if !di.isSurrendering || !isValidChair(di.WhoseSurrender) {
- return false
- }
- return di.SurrenderResult == Surrender_Success
- }
- const (
- RobotType_Cautious = iota
- RobotType_LAGs
- RobotType_Playfulness
- )
- type weightInfo struct {
- chair int
- weight int
- }
- type robotChatActionList struct {
- round int
- action []robotChatAction
- }
- type robotChatAction struct {
- count int
- chatType int
- }
- func (r *robotChatAction) getDesc() string {
- switch r.chatType {
- case RobotChatAction_MuiltyTimeOut:
- return "有两次超过5秒没操作"
- case RobotChatAction_LoseOverFive:
- return "连续5回合没得分"
- case RobotChatAction_LoseOverEighty:
- return "回合结束相差超过80分"
- case RobotChatAction_FriendGetBigProject:
- return "队友获得50项目或以上时"
- case RobotChatAction_SelfWinOverFive:
- return "玩家连续五回合得分"
- case RobotChatAction_GoodHandCard:
- return "拿到牌之后,我赢的分数高的概率很高"
- case RobotChatAction_BadHandCard:
- return "手里的牌大部分都是10一下"
- case RobotChatAction_EmenyGetBigProject:
- return "对手拿到了100-400项目"
- case RobotChatAction_EnterRoom:
- return "发你好"
- case RobotChatAction_Reply:
- return "回你好"
- case RobotChatAction_FriendWinOverFive:
- return "机器人队友连续5回合赢"
- }
- return ""
- }
- func getRobotChatDesc(chatList []robotChatAction) string {
- ret := "["
- for _, v := range chatList {
- ret += fmt.Sprintf("%s: %d", v.getDesc(), v.count)
- ret += " "
- }
- ret += "]"
- return ret
- }
|