package game import ( "fmt" "math" "math/rand" "time" "github.com/denisovdennis/autohero/internal/model" "github.com/denisovdennis/autohero/internal/tuning" ) // TryAutoEquipInMemory equips the item if the slot is empty or the new item improves combat // rating by at least the runtime-configured threshold. Mutates hero.Gear. Does not touch the database. func TryAutoEquipInMemory(hero *model.Hero, item *model.GearItem, now time.Time) bool { hero.EnsureGearMap() current := hero.Gear[item.Slot] if current == nil { hero.Gear[item.Slot] = item return true } oldRating := hero.CombatRatingAt(now) hero.Gear[item.Slot] = item if hero.CombatRatingAt(now) >= oldRating*tuning.Get().AutoEquipThreshold { return true } hero.Gear[item.Slot] = current return false } // TryEquipOrStashOffline runs TryAutoEquipInMemory; if not equipped, appends to inventory // or invokes onDiscard with an adventure-log message when the backpack is full. func TryEquipOrStashOffline(hero *model.Hero, item *model.GearItem, now time.Time, onDiscard func(string)) { hero.EnsureInventorySlice() if TryAutoEquipInMemory(hero, item, now) { return } if len(hero.Inventory) >= model.MaxInventorySlots { if onDiscard != nil { onDiscard(fmt.Sprintf("Inventory full — dropped %s (%s)", item.Name, item.Rarity)) } return } hero.Inventory = append(hero.Inventory, item) } // AutoSellRandomInventoryShare sells a random share of inventory items. // At least minShare (0..1) of current inventory is sold; returns sold count and gold gained. func AutoSellRandomInventoryShare(hero *model.Hero, minShare float64, rng *rand.Rand) (int, int64) { if hero == nil { return 0, 0 } hero.EnsureInventorySlice() n := len(hero.Inventory) if n == 0 { return 0, 0 } if minShare < 0 { minShare = 0 } if minShare > 1 { minShare = 1 } minSell := int(math.Ceil(float64(n) * minShare)) if minSell < 1 { minSell = 1 } if minSell > n { minSell = n } var soldCount int if n == minSell { soldCount = n } else if rng == nil { soldCount = minSell + rand.Intn(n-minSell+1) } else { soldCount = minSell + rng.Intn(n-minSell+1) } perm := make([]int, n) for i := 0; i < n; i++ { perm[i] = i } if rng == nil { rand.Shuffle(n, func(i, j int) { perm[i], perm[j] = perm[j], perm[i] }) } else { rng.Shuffle(n, func(i, j int) { perm[i], perm[j] = perm[j], perm[i] }) } sold := make(map[int]struct{}, soldCount) for i := 0; i < soldCount; i++ { sold[perm[i]] = struct{}{} } kept := make([]*model.GearItem, 0, n-soldCount) var goldGained int64 for i, item := range hero.Inventory { if _, ok := sold[i]; ok { if item != nil { goldGained += model.AutoSellPrice(item.Rarity) } continue } kept = append(kept, item) } hero.Inventory = kept hero.Gold += goldGained return soldCount, goldGained }