feat: 指令支持单独distinct配置,为zhg的s指令添加快捷方式s1,10(最大10)

main
NorthLan 3 years ago
parent 12bf4d3bed
commit fb7c0d4e63

@ -34,12 +34,13 @@ Game:
# 1元=10 Coin (1元40个步兵)
CoinFoodRatio: 4
OutbreakCount: 3
OutbreakMaxCount: 10 # 3x10=30
OutbreakBaseCost: 5
OutbreakCostDict:
1: 3 # 步兵
2: 7 # 骑兵
3: 4 # 弓箭手
4: 3 # 法师
1: 1 # 步兵
2: 2.333 # 骑兵
3: 1.333 # 弓箭手
4: 1 # 法师
Zhghz:
Zhgfb:
Zhgzd:

@ -40,10 +40,11 @@ type (
AdminUserId []int64 // 管理员ID
// Zhg 指挥官PvP模式
Zhg struct {
CoinFoodRatio float32 // 硬币到粮草的转换系数(乘)
OutbreakCount int64 // 每次暴兵数量
OutbreakBaseCost int64 // 默认每次暴兵消耗(不限兵种)
OutbreakCostDict map[int]int64 // 暴兵消耗表
CoinFoodRatio float32 // 硬币到粮草的转换系数(乘)
OutbreakCount int64 // 默认暴兵指令每次暴兵数量
OutbreakMaxCount int64 // 单次暴兵数量最大限制
OutbreakBaseCost int64 // 默认每次暴兵消耗(不限兵种)
OutbreakCostDict map[int]float64 // 暴兵消耗表(单个兵)
}
// Zhghz 指挥官海战模式
Zhghz struct {

@ -1,6 +1,7 @@
package live_logic
import (
"database/sql"
"dcg/app/user_center/usercenter"
"dcg/config"
"dcg/game/manager"
@ -16,6 +17,7 @@ import (
"git.noahlan.cn/northlan/ntools-go/logger"
"github.com/shopspring/decimal"
"strconv"
"strings"
)
type ZhgGameLogic struct {
@ -24,57 +26,60 @@ type ZhgGameLogic struct {
}
func NewZhgLiveGameLogic(svcCtx *svc.ServiceContext) *LiveGameLogic {
cmdParser := cmd.NewCMDParser(
cmd.Pattern{
Prefix: "q",
Alias: []string{"查询"},
ContentMaxLen: 0,
},
cmd.Pattern{
Prefix: "j",
Alias: []string{"加入", "加入游戏"},
ContentMaxLen: 0,
}, cmd.Pattern{
Prefix: "c",
Alias: []string{"换兵"},
ContentMaxLen: 1,
}, cmd.Pattern{
Prefix: "w",
Alias: []string{"我在哪"},
ContentMaxLen: 0,
}, cmd.Pattern{
Prefix: "s",
ContentMaxLen: 4,
Distinct: sql.NullBool{Bool: false, Valid: true},
}, cmd.Pattern{
Prefix: "m",
ContentMaxLen: 1,
}, cmd.Pattern{
Prefix: "r",
ContentMaxLen: 1,
}, cmd.Pattern{
Prefix: "bq",
Alias: []string{"购买粮草", "买粮草"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "bw",
Alias: []string{"购买精英", "买精英"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "zw",
Alias: []string{"装备精英"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "zz",
Alias: []string{"使用称号"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "结算",
Alias: nil,
ContentMaxLen: 2,
},
)
cmdParser.SetDistinct(true)
resp := &ZhgGameLogic{
svcCtx: svcCtx,
LiveGameLogic: NewLiveGameLogic(pbRoom.GameType_ZHG, cmd.NewCMDParser(
cmd.Pattern{
Prefix: "q",
Alias: []string{"查询"},
ContentMaxLen: 0,
},
cmd.Pattern{
Prefix: "j",
Alias: []string{"加入", "加入游戏"},
ContentMaxLen: 0,
}, cmd.Pattern{
Prefix: "c",
Alias: []string{"换兵"},
ContentMaxLen: 1,
}, cmd.Pattern{
Prefix: "w",
Alias: []string{"我在哪"},
ContentMaxLen: 0,
}, cmd.Pattern{
Prefix: "s",
ContentMaxLen: 1,
}, cmd.Pattern{
Prefix: "m",
ContentMaxLen: 1,
}, cmd.Pattern{
Prefix: "r",
ContentMaxLen: 1,
}, cmd.Pattern{
Prefix: "bq",
Alias: []string{"购买粮草", "买粮草"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "bw",
Alias: []string{"购买精英", "买精英"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "zw",
Alias: []string{"装备精英"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "zz",
Alias: []string{"使用称号"},
ContentMaxLen: 2,
}, cmd.Pattern{
Prefix: "结算",
Alias: nil,
ContentMaxLen: 2,
},
)),
svcCtx: svcCtx,
LiveGameLogic: NewLiveGameLogic(pbRoom.GameType_ZHG, cmdParser),
}
resp.RegisterCMDHandler(resp.handleQuery, "q")
resp.RegisterCMDHandler(resp.handleJoinGame, "j")
@ -219,26 +224,54 @@ func (h *ZhgGameLogic) handleOutbreakFood(room *manager.Room, content []rune, us
if len(content) < 1 {
return
}
zhgCfg := config.Config.Game.Zhg
// s1,10s2,10s3,10s4,10 11,0 111,
contentStr := string(content)
var unitTypeStr string
var count int64
var err error
idxSplit := strings.IndexRune(contentStr, ',')
if idxSplit == -1 {
// 没有分隔符,判断内容位数?
unitTypeStr = string(content)
count = zhgCfg.OutbreakCount
} else {
unitTypeStr = string(content[:idxSplit])
if idxSplit == len(content)-1 {
count = zhgCfg.OutbreakCount
} else {
count, err = strconv.ParseInt(string(content[idxSplit+1:]), 10, 0)
if err != nil {
return
}
}
if count > zhgCfg.OutbreakMaxCount {
count = zhgCfg.OutbreakMaxCount
}
if count <= 0 {
count = zhgCfg.OutbreakCount
}
}
logger.SLog.Debugf("用户 [%s] 粮草暴兵", user.Username)
unitTypeStr := string(content[0])
unitType, err := strconv.Atoi(unitTypeStr)
if err != nil {
return
}
zhgCfg := config.Config.Game.Zhg
var cost int64
if unitCost, ok := zhgCfg.OutbreakCostDict[unitType]; ok {
cost = unitCost
// 四舍五入计算
cost = decimal.NewFromInt(count).Mul(decimal.NewFromFloat(unitCost)).Round(0).IntPart()
} else {
cost = zhgCfg.OutbreakBaseCost
return
}
logger.SLog.Debugf("用户 [%s] 粮草暴兵", user.Username)
room.Broadcast(pb.PushZhgOutbreakFood, &pbGameZhg.OutbreakFood{
User: user,
UnitType: unitTypeStr,
Count: int32(zhgCfg.OutbreakCount),
Count: int32(count),
Cost: cost,
})
}

@ -1,6 +1,7 @@
package cmd
import (
"database/sql"
"git.noahlan.cn/northlan/ntools-go/stringn/ac"
"strings"
)
@ -16,16 +17,17 @@ type (
}
Parser struct {
ac ac.AhoCorasick // ac自动机
distinct bool // 命令是否去重
distinct bool // 命令是否去重(总开关)
patterns []Pattern // 匹配规则
}
Pattern struct {
Prefix string // 前缀
Alias []string // 前缀别名
ContentMaxLen int // 内容最大长度,以rune数组长度计算
isAlias bool // alias
realPattern *Pattern // 作为Alias时指向的实际Pattern
Prefix string // 前缀
Alias []string // 前缀别名
ContentMaxLen int // 内容最大长度,以rune数组长度计算
Distinct sql.NullBool // Distinct 命令是否去重 单个权重大于总开关
isAlias bool // alias
realPattern *Pattern // 作为Alias时指向的实际Pattern
}
)
@ -60,6 +62,7 @@ func (p *Parser) initPattern(patterns []Pattern) []string {
Prefix: pattern.Prefix,
Alias: pattern.Alias,
ContentMaxLen: pattern.ContentMaxLen,
Distinct: pattern.Distinct,
},
})
result = append(result, alias)
@ -98,13 +101,22 @@ func (p *Parser) Parse(msg string) CMD {
tmpNext := iter.Next()
// 避免同类型指令重复
if p.distinct {
if pattern.Distinct.Valid && pattern.Distinct.Bool {
for _, m := range resp.Matches {
if m.Prefix == pattern.Prefix {
goto end // continue out for
}
}
}
if p.distinct {
if !pattern.Distinct.Valid || pattern.Distinct.Bool {
for _, m := range resp.Matches {
if m.Prefix == pattern.Prefix {
goto end // continue out for
}
}
}
}
if tmpNext != nil {
//nextPattern := p.patterns[tmpNext.Pattern()]

@ -1,7 +1,11 @@
package cmd
import (
"database/sql"
"fmt"
"github.com/shopspring/decimal"
"strconv"
"strings"
"testing"
)
@ -19,7 +23,8 @@ var p = NewCMDParser(Pattern{
ContentMaxLen: 0,
}, Pattern{
Prefix: "s",
ContentMaxLen: 1,
ContentMaxLen: 4,
Distinct: sql.NullBool{Bool: false, Valid: true},
}, Pattern{
Prefix: "m",
ContentMaxLen: 1,
@ -77,8 +82,10 @@ func TestParse(t *testing.T) {
}
func TestA(t *testing.T) {
p.SetDistinct(false)
cmd := p.Parse("jc2j加入c2jc2加入游戏dq4654购买粮草9999购买精英1m1r2zz1zw2wss1")
p.SetDistinct(true)
//cmd := p.Parse("jc2j加入c2jc2加入游戏dq4654购买粮草9999购买精英1m1r2zz1zw2wss1s3s5")
//cmd := p.Parse("输入j 加入游戏哦")
cmd := p.Parse("s1#10s2s3")
fmt.Println(cmd.IsCMD)
for _, match := range cmd.Matches {
@ -86,6 +93,42 @@ func TestA(t *testing.T) {
}
}
func TestOutbreak(t *testing.T) {
content := []rune("111,")
contentStr := string(content)
var unitTypeStr string
var count int64
var err error
idxSplit := strings.IndexRune(contentStr, ',')
if idxSplit == -1 {
// 没有分隔符,判断内容位数?
unitTypeStr = string(content)
count = 3
} else {
unitTypeStr = string(content[:idxSplit])
if idxSplit == len(content)-1 {
count = 3
} else {
count, err = strconv.ParseInt(string(content[idxSplit+1:]), 10, 0)
if err != nil {
return
}
}
if count > 30 {
count = 30
}
if count <= 0 {
count = 3
}
}
cost := decimal.NewFromInt(count).Mul(decimal.NewFromFloat(1.3)).Round(0).IntPart()
fmt.Println(unitTypeStr, count, cost)
}
func BenchmarkCmd(b *testing.B) {
content := "jc2"

Loading…
Cancel
Save