341 lines
9.8 KiB
Go
341 lines
9.8 KiB
Go
package fight
|
||
|
||
import (
|
||
"fmt"
|
||
"math"
|
||
"math/rand"
|
||
"time"
|
||
)
|
||
|
||
// 异常状态类型
|
||
const (
|
||
StatusNormal = iota
|
||
StatusParalysis
|
||
StatusPoison
|
||
StatusSleep
|
||
StatusFreeze
|
||
)
|
||
|
||
// 异常状态倍率
|
||
var statusBonuses = map[int]float64{
|
||
StatusNormal: 1.0,
|
||
StatusParalysis: 1.5,
|
||
StatusPoison: 1.5,
|
||
StatusSleep: 2.0,
|
||
StatusFreeze: 2.0,
|
||
}
|
||
|
||
// 胶囊配置(ItemID -> Bonus)
|
||
var capsuleBonuses = map[int]float64{
|
||
300001: 1.0, // 普通精灵胶囊
|
||
300002: 1.5, // 中级精灵胶囊
|
||
300003: 2.0, // 高级精灵胶囊
|
||
300004: 3.0, // 超级精灵胶囊
|
||
300005: 4.0, // 特级精灵胶囊
|
||
300006: 256.0, // 无敌精灵胶囊
|
||
300007: 256.0, // 超能胶囊
|
||
300008: 2.0, // 赫星精灵胶囊
|
||
300009: 256.0, // 时空精灵胶囊
|
||
300010: 256.0, // 无敌精灵胶囊Ω
|
||
}
|
||
|
||
// PlayerCaptureContext 用户捕捉上下文(每次登录创建)
|
||
type PlayerCaptureContext struct {
|
||
random *rand.Rand
|
||
denominator int // 统一分母=1000
|
||
decayFactor float64 // 衰减系数
|
||
minDecayNum int // 衰减分子最小值
|
||
guarantees map[int]int // 每种精灵的保底分子 map[petId]numerator
|
||
}
|
||
|
||
// CaptureParams 捕捉参数
|
||
type CaptureParams struct {
|
||
PetID int // 精灵ID
|
||
MaxHP int // 目标最大HP
|
||
CurrentHP int // 目标当前HP
|
||
CatchRate int // 目标捕获率
|
||
ItemID int // 使用的道具ID
|
||
StatusType int // 状态类型
|
||
OwnedCount int // 已拥有数量(-1=保底,0=锁定,≥1=衰减)
|
||
}
|
||
|
||
// NewPlayerCaptureContext 创建用户捕捉上下文(每次登录调用)
|
||
func NewPlayerCaptureContext(decayFactor float64, minDecayNum int) *PlayerCaptureContext {
|
||
if minDecayNum <= 0 {
|
||
minDecayNum = 1
|
||
}
|
||
if decayFactor <= 0 || decayFactor >= 1 {
|
||
decayFactor = 0.3
|
||
}
|
||
return &PlayerCaptureContext{
|
||
random: rand.New(rand.NewSource(time.Now().UnixNano())),
|
||
denominator: 1000, // 统一分母=1000
|
||
decayFactor: decayFactor,
|
||
minDecayNum: minDecayNum,
|
||
guarantees: make(map[int]int), // 初始化map
|
||
}
|
||
}
|
||
|
||
// getItemBonus 获取道具倍率
|
||
func getItemBonus(itemID int) float64 {
|
||
if bonus, ok := capsuleBonuses[itemID]; ok {
|
||
return bonus
|
||
}
|
||
return 1.0 // 默认普通胶囊倍率
|
||
}
|
||
|
||
// GetStatusBonus 获取状态倍率
|
||
func GetStatusBonus(statusType int) float64 {
|
||
if bonus, ok := statusBonuses[statusType]; ok {
|
||
return bonus
|
||
}
|
||
return statusBonuses[StatusNormal]
|
||
}
|
||
|
||
// calcBaseA 按公式计算a值
|
||
func (c *PlayerCaptureContext) calcBaseA(params CaptureParams) int {
|
||
catchRate := params.CatchRate
|
||
if catchRate < 3 {
|
||
catchRate = 3
|
||
}
|
||
if params.MaxHP <= 0 {
|
||
params.MaxHP = 1
|
||
}
|
||
currentHP := params.CurrentHP
|
||
if currentHP <= 0 {
|
||
currentHP = 1
|
||
}
|
||
|
||
hpRatio := (3.0*float64(params.MaxHP) - 2.0*float64(currentHP)) / (3.0 * float64(params.MaxHP))
|
||
if hpRatio < 0 {
|
||
hpRatio = 0
|
||
}
|
||
|
||
itemBonus := getItemBonus(params.ItemID)
|
||
statusBonus := GetStatusBonus(params.StatusType)
|
||
|
||
return int(hpRatio * float64(catchRate) * itemBonus * statusBonus)
|
||
}
|
||
|
||
// calcBaseRate 按公式计算基础成功率
|
||
func (c *PlayerCaptureContext) calcBaseRate(params CaptureParams) float64 {
|
||
// Bonus >= 255 必定成功
|
||
if getItemBonus(params.ItemID) >= 255 {
|
||
return 1.0
|
||
}
|
||
|
||
a := c.calcBaseA(params)
|
||
|
||
if a >= 255 {
|
||
return 1.0
|
||
}
|
||
|
||
g := int(1048560.0 / math.Floor(math.Sqrt(math.Floor(math.Sqrt(math.Floor(16711680.0/float64(a)))))))
|
||
|
||
return math.Pow(float64(g)/65536.0, 4.0)
|
||
}
|
||
|
||
// getGuaranteeNumerator 获取指定精灵的保底分子(默认1)
|
||
func (c *PlayerCaptureContext) getGuaranteeNumerator(petID int) int {
|
||
if num, ok := c.guarantees[petID]; ok {
|
||
return num
|
||
}
|
||
return 1
|
||
}
|
||
|
||
// setGuaranteeNumerator 设置指定精灵的保底分子
|
||
func (c *PlayerCaptureContext) setGuaranteeNumerator(petID, numerator int) {
|
||
c.guarantees[petID] = numerator
|
||
}
|
||
|
||
// applyModeModifier 应用模式修正(保底/衰减/锁定)
|
||
func (c *PlayerCaptureContext) applyModeModifier(baseRate float64, params CaptureParams) (float64, string, float64) {
|
||
guaranteeBonus := 0.0
|
||
switch {
|
||
case params.OwnedCount == 0:
|
||
// 锁定模式:成功率0
|
||
return 0.0, "锁定模式(ownedCount=0)", 0.0
|
||
case params.OwnedCount > 0:
|
||
// 衰减模式:已拥有数量越多,成功率越低
|
||
decay := math.Pow(1-c.decayFactor, float64(params.OwnedCount))
|
||
modified := baseRate * decay
|
||
if modified < 0 {
|
||
modified = 0
|
||
}
|
||
return modified, "衰减模式", 0.0
|
||
default: // params.OwnedCount == -1
|
||
// 保底模式:失败叠加分子(按精灵ID独立计算)
|
||
num := c.getGuaranteeNumerator(params.PetID)
|
||
guaranteeBonus = float64(num) / float64(c.denominator) // 分母=1000
|
||
modified := baseRate + guaranteeBonus
|
||
if modified > 1.0 {
|
||
modified = 1.0
|
||
}
|
||
return modified, "保底模式", guaranteeBonus * 100 // 百分比形式
|
||
}
|
||
}
|
||
|
||
// Capture 执行捕捉
|
||
func (c *PlayerCaptureContext) Capture(params CaptureParams) (bool, CaptureDetails) {
|
||
// 记录当前保底值(用于显示)
|
||
currentGuarantee := c.getGuaranteeNumerator(params.PetID)
|
||
|
||
// 特殊胶囊必定成功(Bonus>=255)
|
||
if getItemBonus(params.ItemID) >= 255 {
|
||
// 若是保底模式,成功后重置该精灵的保底分子
|
||
if params.OwnedCount == -1 {
|
||
c.setGuaranteeNumerator(params.PetID, 1)
|
||
}
|
||
return true, CaptureDetails{
|
||
Success: true,
|
||
Mode: "特殊胶囊必定成功",
|
||
BaseRate: 100.0,
|
||
ModifiedRate: 100.0,
|
||
GuaranteeBonus: float64(currentGuarantee) / float64(c.denominator) * 100,
|
||
Details: fmt.Sprintf("道具ID=%d,必定成功", params.ItemID),
|
||
}
|
||
}
|
||
|
||
// 锁定模式直接失败
|
||
if params.OwnedCount == 0 {
|
||
return false, CaptureDetails{
|
||
Success: false,
|
||
Mode: "锁定模式(ownedCount=0)",
|
||
BaseRate: 0.0,
|
||
ModifiedRate: 0.0,
|
||
GuaranteeBonus: 0.0,
|
||
Details: "已拥有数量为0,无法捕捉",
|
||
}
|
||
}
|
||
|
||
baseRate := c.calcBaseRate(params)
|
||
modifiedRate, mode, guaranteeBonus := c.applyModeModifier(baseRate, params)
|
||
|
||
// 随机判定
|
||
success := c.random.Float64() < modifiedRate
|
||
|
||
// 更新保底状态(仅对保底模式)
|
||
if params.OwnedCount == -1 {
|
||
if success {
|
||
// 成功:重置该精灵的保底分子为1
|
||
c.setGuaranteeNumerator(params.PetID, 1)
|
||
} else {
|
||
// 失败:该精灵的保底分子+1
|
||
c.setGuaranteeNumerator(params.PetID, currentGuarantee+1)
|
||
}
|
||
}
|
||
|
||
return success, CaptureDetails{
|
||
Success: success,
|
||
Mode: mode,
|
||
BaseRate: baseRate * 100,
|
||
ModifiedRate: modifiedRate * 100,
|
||
GuaranteeBonus: guaranteeBonus,
|
||
Details: fmt.Sprintf("a=%d, g=%.0f, 分母=1000, 当前保底分子=%d",
|
||
c.calcBaseA(params),
|
||
math.Floor(math.Sqrt(math.Floor(math.Sqrt(math.Floor(16711680.0/float64(c.calcBaseA(params))))))),
|
||
currentGuarantee),
|
||
}
|
||
}
|
||
|
||
// CaptureDetails 捕捉详情
|
||
type CaptureDetails struct {
|
||
Success bool
|
||
Mode string
|
||
BaseRate float64
|
||
ModifiedRate float64
|
||
GuaranteeBonus float64 // 百分比
|
||
Details string
|
||
}
|
||
|
||
func main() {
|
||
// 每次登录创建用户捕捉上下文
|
||
ctx := NewPlayerCaptureContext(0.1, 1)
|
||
|
||
fmt.Println("=== 测试三种模式 ===")
|
||
|
||
// 测试1:保底模式(ownedCount=-1)- 不同精灵独立计算
|
||
fmt.Println("\n--- 保底模式测试(不同精灵独立计算) ---")
|
||
paramsA := CaptureParams{
|
||
PetID: 1001, // 精灵A
|
||
MaxHP: 20,
|
||
CurrentHP: 1,
|
||
CatchRate: 45,
|
||
ItemID: 300003, // 高级精灵胶囊
|
||
StatusType: StatusNormal,
|
||
OwnedCount: -1, // 保底模式
|
||
}
|
||
|
||
paramsB := CaptureParams{
|
||
PetID: 1002, // 精灵B
|
||
MaxHP: 50,
|
||
CurrentHP: 5,
|
||
CatchRate: 60,
|
||
ItemID: 300002, // 中级精灵胶囊
|
||
StatusType: StatusNormal,
|
||
OwnedCount: -1, // 保底模式
|
||
}
|
||
|
||
// 交替捕捉精灵A和精灵B,验证保底分子独立
|
||
for i := 1; i <= 10; i++ {
|
||
successA, detailsA := ctx.Capture(paramsA)
|
||
fmt.Printf("第%d轮-精灵A:%v | 模式=%s | 基础=%.2f%% | 实际=%.2f%% | 保底加成=%.2f%%\n",
|
||
i, successA, detailsA.Mode, detailsA.BaseRate, detailsA.ModifiedRate, detailsA.GuaranteeBonus)
|
||
|
||
successB, detailsB := ctx.Capture(paramsB)
|
||
fmt.Printf("第%d轮-精灵B:%v | 模式=%s | 基础=%.2f%% | 实际=%.2f%% | 保底加成=%.2f%%\n",
|
||
i, successB, detailsB.Mode, detailsB.BaseRate, detailsB.ModifiedRate, detailsB.GuaranteeBonus)
|
||
}
|
||
|
||
// 测试2:衰减模式(ownedCount递增)
|
||
fmt.Println("\n--- 衰减模式测试(ownedCount递增) ---")
|
||
paramsDecay := CaptureParams{
|
||
PetID: 2001,
|
||
MaxHP: 100,
|
||
CurrentHP: 10,
|
||
CatchRate: 3,
|
||
ItemID: 300003, // 高级精灵胶囊
|
||
StatusType: StatusSleep,
|
||
OwnedCount: 1, // 衰减模式起始
|
||
}
|
||
|
||
for i := 1; i <= 50; i++ {
|
||
paramsDecay.OwnedCount = 2
|
||
success, details := ctx.Capture(paramsDecay)
|
||
fmt.Printf("拥有%d只:%v | 模式=%s | 基础=%.2f%% | 实际=%.2f%%\n",
|
||
paramsDecay.OwnedCount, success, details.Mode, details.BaseRate, details.ModifiedRate)
|
||
}
|
||
|
||
// 测试3:锁定模式(ownedCount=0)
|
||
fmt.Println("\n--- 锁定模式测试 ---")
|
||
paramsLock := CaptureParams{
|
||
PetID: 3001,
|
||
MaxHP: 100,
|
||
CurrentHP: 1,
|
||
CatchRate: 255,
|
||
ItemID: 300004, // 超级精灵胶囊
|
||
StatusType: StatusFreeze,
|
||
OwnedCount: 0, // 锁定模式
|
||
}
|
||
|
||
successLock, detailsLock := ctx.Capture(paramsLock)
|
||
fmt.Printf("捕捉结果:%v | 模式=%s | 基础=%.2f%% | 实际=%.2f%%\n",
|
||
successLock, detailsLock.Mode, detailsLock.BaseRate, detailsLock.ModifiedRate)
|
||
|
||
// 测试4:特殊胶囊必定成功
|
||
fmt.Println("\n--- 特殊胶囊测试 ---")
|
||
paramsSpecial := CaptureParams{
|
||
PetID: 4001,
|
||
MaxHP: 1000,
|
||
CurrentHP: 1000,
|
||
CatchRate: 1,
|
||
ItemID: 300006, // 无敌精灵胶囊
|
||
StatusType: StatusNormal,
|
||
OwnedCount: -1, // 保底模式
|
||
}
|
||
|
||
successSpecial, detailsSpecial := ctx.Capture(paramsSpecial)
|
||
fmt.Printf("捕捉结果:%v | 模式=%s | 基础=%.2f%% | 实际=%.2f%% | 保底加成=%.2f%%\n",
|
||
successSpecial, detailsSpecial.Mode, detailsSpecial.BaseRate, detailsSpecial.ModifiedRate, detailsSpecial.GuaranteeBonus)
|
||
}
|