继上次使用遗传算法计算蓄意轰拳最高伤害出装后,为纪念本人于2024年5月13日的大乱斗派克一局双五杀,遂使用人工蜂群算法计算派克斩杀线最大化出装,由于派克大招伤害收到很多方面影响,所以数据预处理较为麻烦,这里笔者省略了一些不必要的步骤。
派克
派克的被动会将额外生命值转化为攻击力(每14额外生命值转化为1攻击力),但是派克生命上限不会变,15级一直为2400
派克大招:
直接击败 550+80%*额外攻击力+250%*穿甲 生命值以下敌人
R = 550+80%*(Σx+Σy/14)+2.5*Σz
而 额外攻击力 = 攻击力加成+额外生命值/14
此外,派克大招只收到固定穿甲的加成,与百分比穿甲无关!
15级时,基础攻击力为113 用于计算血手的额外攻击加成
装备
装备名称 | 攻击力(x)+血量(y)/14 | 血量(y) | 穿甲(z) |
守护天使 | 40 | 0 | 0 |
饮血剑 | 50+(11-25) | 0 | 0 |
暮刃 | 55 | 0 | 18 |
凡性的提醒 | 30 | 0 | 0 |
魔宗 | 25 | 0 | 0 |
黑切 | 40 | 350 | 0 |
三相 | 30 | 250 | 0 |
饮魔刀 | 55 | 0 | 0 |
死亡之舞 | 35 | 0 | 0 |
幻影之舞 | 25 | 0 | 0 |
吸蓝刀(特殊被动) | 40 | 0 | 0 |
岚切 | 40 | 0 | 0 |
赛瑞尔达 | 40 | 0 | 0 |
迅刃 | 45 | 0 | 0 |
夜之锋刃 | 50 | 250 | 8 |
神分 | 25 | 425 | 0 |
巨蛇之牙 | 50 | 0 | 15 |
盾攻 | 40 | 0 | 0 |
收集者 | 40 | 0 | 10 |
炼金锯 | 45 | 250 | 0 |
青龙刀 | 50 | 300 | 0 |
幽梦 | 55 | 0 | 15+(3-6) |
破败王者之刃 | 20 | 0 | 0 |
无尽 | 55 | -5(5-50) | 0 |
界弓 | 40 | 0 | 0 |
巨九(特殊装备) | 15+2.5%Σx | 550 | 0 |
血手 | 57 (50%基础攻击) | 400 | 0 |
日炎 | 0 | 500 | 0 |
振奋铠甲 | 0 | 350 | 0 |
兰盾 | 0 | 400 | 0 |
反甲 | 0 | 200 | 0 |
亡者的板甲 | 0 | 250 | 0 |
冰拳 | 0 | 250 | 0 |
深渊面具 | 0 | 300 | 0 |
基克的聚合 | 0 | 300 | 0 |
守护之誓 | 0 | 350 | 0 |
冬之降临 | 0 | 350+(%8*最大法力值) 448 | 0 |
自然之力 | 0 | 350 | 0 |
种子罐 | 0 | 425 | 0 |
午时斗篷 | 0 | 200 | 0 |
炽光之冠 | 0 | 300 | 0 |
心之钢 | 0 | 700 | 0 |
狂徒 | 0 | 700 | 0 |
炽阳法袍 | 0 | 250 | 0 |
纳什之牙 | 30 | 0 | 0 |
鞋子(这里列出的是简单筛选出的)
装备名称 | 攻击力(x) | 血量(y) | 穿甲(z) |
爆发之靴 | 30 | 0 | 10 |
水银鞋 | 0 | 200 | 0 |
贪婪之靴 | 35 | 0 | 0 |
6件装备 除去鞋子 5件装备
筛选
只加攻击前五
这里对数据进行预处理,提前额外生命值转化为攻击力
装备名称 | 攻击力(x) | 血量(y) | 穿甲(z) |
守护天使 | 40 | 0 | 0 |
饮血剑 | 50+(11-25) 75 | 0 | 0 |
暮刃 | 55 | 0 | 18 |
凡性的提醒 | 30 | 0 | 0 |
魔宗 | 25 | 0 | 0 |
黑切 | 65 | 350 | 0 |
三相 | 48 | 250 | 0 |
饮魔刀 | 55 | 0 | 0 |
死亡之舞 | 35 | 0 | 0 |
幻影之舞 | 25 | 0 | 0 |
吸蓝刀(特殊被动) | 40 | 0 | 0 |
岚切 | 40 | 0 | 0 |
赛瑞尔达 | 40 | 0 | 0 |
迅刃 | 45 | 0 | 0 |
夜之锋刃 | 68 | 250 | 8 |
神分 | 56 | 425 | 0 |
巨蛇之牙 | 50 | 0 | 15 |
盾攻 | 40 | 0 | 0 |
收集者 | 40 | 0 | 10 |
炼金锯 | 63 | 250 | 0 |
青龙刀 | 72 | 300 | 0 |
幽梦 | 55 | 0 | 15+(3-6) |
破败王者之刃 | 20 | 0 | 0 |
无尽 | 55 | -5(5-50) | 0 |
界弓 | 40 | 0 | 0 |
巨九(特殊装备) | 55+2.5%Σy | 550 | 0 |
血手 | 57 (50%基础攻击) 86 | 400 | 0 |
日炎 | 36 | 500 | 0 |
振奋铠甲 | 25 | 350 | 0 |
兰盾 | 29 | 400 | 0 |
反甲 | 15 | 200 | 0 |
亡者的板甲 | 18 | 250 | 0 |
冰拳 | 18 | 250 | 0 |
深渊面具 | 22 | 300 | 0 |
基克的聚合 | 22 | 300 | 0 |
守护之誓 | 25 | 350 | 0 |
冬之降临 | 32 | 350+(%8*最大法力值) 448 | 0 |
自然之力 | 25 | 350 | 0 |
种子罐 | 31 | 425 | 0 |
午时斗篷 | 15 | 200 | 0 |
炽光之冠 | 22 | 300 | 0 |
心之钢 | 50+y/14 | 700 | 0 |
狂徒 | 50 | 700 | 0 |
炽阳法袍 | 18 | 250 | 0 |
纳什之牙 | 30 | 0 | 0 |
以下给出筛选出的装备
这里给出攻击力加成前五的装备
装备名称 | 攻击力(x)+血量(y)/14 | 穿甲(z) |
饮血剑 | 75 | 0 |
青龙刀 | 72 | 0 |
血手 | 86 | 0 |
黑切 | 65 | 0 |
炼金锯 | 63 | 0 |
由于没有只加穿甲的装备,这里列出所有加穿甲的装备
装备名称 | 攻击力(x)+血量(y)/14 | 穿甲(z) |
暮刃 | 55 | 18 |
夜之锋刃 | 68 | 8 |
巨蛇之牙 | 50 | 15 |
收集者 | 40 | 10 |
幽梦 | 55 | 21 |
鞋子(初步筛选)
鞋子名称 | 攻击力(x)+血量(y)/14 | 穿甲(z) |
爆发之靴 | 30 | 10 |
贪婪之靴 | 35 | 0 |
这里饮血剑和幽梦的加成,为血量高于50%且充能满状态,即取得最大值时
还有两件特殊装备
装备名称 | 攻击力(x)+血量(y)/14 | 穿甲(z) |
心之刚 | 50+{g/14} | 0 |
巨型九头蛇 | 55+2.5%Σy | 0 |
这里g指心之刚层数
但由于派克没有额外生命加成,所以巨九被动失效,单纯属性不能拍到前五
只需要考虑心之刚
代码如下
import random
import numpy as np
import math
equip_name = ["饮血剑", "青龙刀", "血手", "黑切", "炼金锯", "暮刃", "夜之锋刃", "巨蛇之牙", "收集者", "幽梦", "心之刚"]
shoes_name = ["爆发之靴", "贪婪之靴"]
def objective_function(population, equip, shoes):
totalx = sum(equip[i][0] for i in population[0]) + shoes[population[1]][0]
totaly = sum(equip[i][1] for i in population[0]) + shoes[population[1]][1]
r = 550 + 0.8 * totalx + 2.5 * totaly
return math.ceil(r)
def create_population():
pope = random.sample(range(11), 5)
pops = random.randint(0, 1)
return [pope, pops]
class ArtificialBeeColony:
def __init__(self, objective, num_variables, num_bees, num_scouts, max_iter, gang):
self.objective = objective
self.num_variables = num_variables
self.num_bees = num_bees
self.num_scouts = num_scouts
self.max_iter = max_iter
self.population = []
self.best_solution = None
self.best_fitness = float('-inf') # 初始化为负无穷大
self.gang = gang
self.equip = [[75, 0], [72, 0], [85, 0], [65, 0], [63, 0], [55, 18], [68, 8], [50, 15], [40, 10], [55, 21], [50 + math.ceil(gang / 14), 0]]
self.shoes = [[30, 10], [35, 0]]
def initialize(self):
for _ in range(self.num_bees):
solution = create_population()
fitness = self.objective(solution, self.equip, self.shoes)
self.population.append({'solution': solution, 'fitness': fitness})
if fitness > self.best_fitness:
self.best_solution = solution
self.best_fitness = fitness
print(f'目前最佳装备索引: {self.best_solution} 对应输出伤害 {self.best_fitness}')
print(f'装备名称{[equip_name[i] for i in self.best_solution[0]]},鞋子名称{shoes_name[self.best_solution[1]]}')
print(f"此时心之刚层数为:{self.gang}")
def mutate(self, solution):
unique_numbers = set() # 用于跟踪已经使用过的数字
for num in solution[0]:
unique_numbers.add(num)
idx1, idx2 = random.sample(range(len(solution[0])), 2)
solution[0][idx1] = random.randint(0, 10)
while solution[0][idx1] in unique_numbers:
solution[0][idx1] = random.randint(0, 10)
unique_numbers.add(solution[0][idx1])
solution[0][idx2] = random.randint(0, 10)
while solution[0][idx2] in unique_numbers:
solution[0][idx2] = random.randint(0, 10)
unique_numbers.add(solution[0][idx2])
new_solution = [solution[0], solution[1]] # 直接使用原始解的形式来初始化新解
return new_solution
def employ_bees(self):
for bee in self.population:
candidate = self.mutate(bee['solution'])
fitness = self.objective(candidate, self.equip, self.shoes)
if fitness > bee['fitness']:
bee['solution'] = candidate
bee['fitness'] = fitness
if fitness > self.best_fitness:
self.best_solution = candidate
self.best_fitness = fitness
print(f'目前最佳装备索引: {self.best_solution} 对应输出伤害 {self.best_fitness}')
print(f'装备名称{[equip_name[i] for i in self.best_solution[0]]},鞋子名称{shoes_name[self.best_solution[1]]}')
print(f"此时心之刚层数为:{self.gang}")
def onlooker_bees(self):
fitnesses = [1 / (1 + bee['fitness']) for bee in self.population]
total_fitness = sum(fitnesses)
probs = [f / total_fitness for f in fitnesses]
for i in range(self.num_bees):
index = np.random.choice(range(self.num_bees), p=probs)
bee = self.population[index]
candidate = self.mutate(bee['solution'])
fitness = self.objective(candidate, self.equip, self.shoes)
if fitness > bee['fitness']:
bee['solution'] = candidate
bee['fitness'] = fitness
if fitness > self.best_fitness:
self.best_solution = candidate
self.best_fitness = fitness
print(f'目前最佳装备索引: {self.best_solution} 对应输出伤害 {self.best_fitness}')
print(f'装备名称{[equip_name[i] for i in self.best_solution[0]]},鞋子名称{shoes_name[self.best_solution[1]]}')
print(f"此时心之刚层数为:{self.gang}")
def scout_bees(self):
for bee in self.population:
if random.random() < 0.1: # 10%的概率执行侦查行动
bee['solution'] = create_population()
bee['fitness'] = self.objective(bee['solution'], self.equip, self.shoes)
if bee['fitness'] > self.best_fitness:
self.best_solution = bee['solution']
self.best_fitness = bee['fitness']
print(f'目前最佳装备索引: {self.best_solution} 对应输出伤害 {self.best_fitness}')
print(f'装备名称:{[equip_name[i] for i in self.best_solution[0]]},鞋子名称:{shoes_name[self.best_solution[1]]}')
print(f"此时心之刚层数为:{self.gang}")
def optimize(self):
self.initialize()
for _ in range(self.max_iter):
self.employ_bees()
self.onlooker_bees()
self.scout_bees()
abc = ArtificialBeeColony(objective_function, 3, 50, 5, 100, 490)
abc.optimize()
# 当心之刚层数超过490,心之刚将成为更好选择
进入游戏发现确实为1005,这里要注意,幽梦一定要充能完毕,否则斩杀线达不到1005,只有990左右。