package game import ( "math" "slices" ) type UpgradeCalc struct { Cost map[Tech]float64 } func (uc UpgradeCalc) UpgradeCost(ships uint) float64 { var sum float64 for _, v := range uc.Cost { sum += v } return sum * float64(ships) } func (uc UpgradeCalc) UpgradeMaxShips(resources float64) uint { return uint(math.Floor(resources / uc.UpgradeCost(1))) } func BlockUpgradeCost(blockMass, currentBlockTech, targetBlockTech float64) float64 { if blockMass == 0 || targetBlockTech <= currentBlockTech { return 0 } return (1 - currentBlockTech/targetBlockTech) * 10 * blockMass } func GroupUpgradeCost(sg *ShipGroup, st ShipType, drive, weapons, shields, cargo float64) UpgradeCalc { uc := &UpgradeCalc{Cost: make(map[Tech]float64)} if drive > 0 { uc.Cost[TechDrive] = BlockUpgradeCost(st.DriveBlockMass(), sg.TechLevel(TechDrive).F(), drive) } if weapons > 0 { uc.Cost[TechWeapons] = BlockUpgradeCost(st.WeaponsBlockMass(), sg.TechLevel(TechWeapons).F(), weapons) } if shields > 0 { uc.Cost[TechShields] = BlockUpgradeCost(st.ShieldsBlockMass(), sg.TechLevel(TechShields).F(), shields) } if cargo > 0 { uc.Cost[TechCargo] = BlockUpgradeCost(st.CargoBlockMass(), sg.TechLevel(TechCargo).F(), cargo) } return *uc } func CurrentUpgradingLevel(sg *ShipGroup, tech Tech) float64 { if sg.StateUpgrade == nil { return 0 } ti := slices.IndexFunc(sg.StateUpgrade.UpgradeTech, func(pref UpgradePreference) bool { return pref.Tech == tech }) if ti >= 0 { return sg.StateUpgrade.UpgradeTech[ti].Level } return 0 } func FutureUpgradeLevel(raceLevel, groupLevel, limit float64) float64 { target := limit if target == 0 || target > raceLevel { target = raceLevel } if groupLevel == target { return 0 } return target } func UpgradeGroupPreference(sg ShipGroup, st ShipType, tech Tech, v float64) ShipGroup { if v <= 0 || st.BlockMass(tech) == 0 || sg.TechLevel(tech).F() >= v { return sg } var su InUpgrade if sg.StateUpgrade != nil { su = *sg.StateUpgrade } else { su = InUpgrade{UpgradeTech: []UpgradePreference{}} } ti := slices.IndexFunc(su.UpgradeTech, func(pref UpgradePreference) bool { return pref.Tech == tech }) if ti < 0 { su.UpgradeTech = append(su.UpgradeTech, UpgradePreference{Tech: tech}) ti = len(su.UpgradeTech) - 1 } su.UpgradeTech[ti].Level = v su.UpgradeTech[ti].Cost = BlockUpgradeCost(st.BlockMass(tech), sg.TechLevel(tech).F(), v) * float64(sg.Number) sg.StateUpgrade = &su return sg }