WIKI冒险团明确声明不支持涉及代练和账号买卖的现金交易活动。
参与者应自行承担对应后果。
战力测试终极算法(代码向)
阅读
2023-07-27更新
最新编辑:欣酱是萌欣吖
阅读:
更新日期:2023-07-27
最新编辑:欣酱是萌欣吖
前言
本攻略更新于2023.7.27,以后即使夜莺装备变化,方法殊途同归,C++代码的参数不会更新,请自行理解修改。
在状态自相似中,我们通过求解多元一次方程组,找到夜莺状态迁移的平衡态,进而近似计算得概率。
它只计算了期望,没有能够计算伤害的分布,并且没有考虑战测的开始和结束的时候。
现在我弄出来了一个能够精确计算夜莺伤害分布的算法,无论是手操还是自动。这个算法执行的时间大约是5秒钟(手操),我用C++实现出来之后把结果导入到wiki上的js代码里,所以wiki的计算器始终保持两个优雅的特性:立马出结果,和绝对的精准。
战力测试终极算法(代码向)
这是一个纯计算机算法,纸笔玩家,手机计算器玩家可以骂骂咧咧离场了。
可直接移步计算器使用现成的结果。
把夜莺的战测视为一个马尔可夫过程,用状态记录夜莺的所有信息和历史信息。
struct state {
float p;
int focus;
int cd;
int amounta;
int timea;
int amountb;
int timeb;
float dot;
float h1;
float h2;
float h3;
};
它们分别表示这个状态出现的概率,专注剩余持续时间,技能冷却,流血伤害倍率,流血剩余时间,瘟疫伤害倍率,瘟疫剩余时间,总dot伤害倍率,和123技能释放次数
在战测的任意时刻,只要这些确定,那么以后的情况也就确定,而不用去关注历史。这就是一个马尔可夫过程。
如果使用矩阵推衍这个过程,看上去很帅,其实有很多状态不会出现,会耗费大量时间(几乎无穷)。
我做的最主要的优化,是把能合并的状态合并
bool Equal(state& a, state& b) {
if (a.focus == b.focus && a.cd == b.cd && a.amounta == b.amounta && a.timea == b.timea && a.amountb == b.amountb && a.timeb == b.timeb && a.dot == b.dot)return 1;
if (a.focus == b.focus && a.cd == b.cd && a.amounta == b.amountb && a.timea == b.timeb && a.amountb == b.amounta && a.timeb == b.timea && a.dot == b.dot)return 1;
return 0;
}
这个函数判断两个状态能否合并。第二行是一个对称的情况,也可以合并。
然后就是用if语句推进马尔可夫过程的演化。
注释掉的部分可以计算手动。事实上任意的手操策略只要稍微修改代码就能计算。最后得到的vector里面就是所有状态的分布。完全精确。
最后我有做一些怪异的处理,因为要导入到wiki上面的战测计算器。
重点关注合并时dot和h的更新,是以概率为权重的加权平均。
最终的dot那个数值,除以4,乘开局技巧爆发2.2*1.3,乘技能系数1.1,乘环,乘技巧,就是最终dot伤害。
vector<state> states, nexts;
int main() {
states.push_back({ 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0 });
for (int t = 0; t < 2000; t++) {
for (int i = 0; i < states.size(); i++) {
if (states[i].timea > 0) states[i].timea--;
if (states[i].timea % 10 == 0) states[i].dot += states[i].amounta;
if (states[i].timea == 0) states[i].amounta = 0;
if (states[i].timeb > 0) states[i].timeb--;
if (states[i].timeb % 10 == 0) states[i].dot += states[i].amountb;
if (states[i].timeb == 0) states[i].amountb = 0;
if (states[i].focus > 0) states[i].focus--;
if (states[i].cd > 0) {
states[i].cd--;
nexts.push_back(states[i]);
}
else {
/*
if (states[i].timea == 0 || states[i].timea < states[i].timeb && states[i].focus > 0) {
states[i].h1++;
states[i].cd = 36;
states[i].timea = 80;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.95;
nexts[nexts.size() - 1].amounta = (states[i].focus > 0) ? 9 : 6;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.75;
nexts[nexts.size() - 1].amounta = (states[i].focus > 0) ? 6 : 4;
nexts[nexts.size() - 1].focus = 81;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.25;
nexts[nexts.size() - 1].amounta = (states[i].focus > 0) ? 6 : 4;
}
else if (min(states[i].timea, states[i].timeb) > 0 && states[i].focus == 0) {
states[i].h2++;
states[i].cd = 5;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.75;
nexts[nexts.size() - 1].focus = 81;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= (0.95 + 0.05 * 0.25);
}
else if (states[i].timeb == 0 || states[i].timeb < states[i].timea && states[i].focus > 0) {
states[i].h3++;
states[i].cd = 36;
states[i].timeb = 80;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.95;
nexts[nexts.size() - 1].amountb = (states[i].focus > 0) ? 9 : 6;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.75;
nexts[nexts.size() - 1].amountb = (states[i].focus > 0) ? 6 : 4;
nexts[nexts.size() - 1].focus = 81;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.25;
nexts[nexts.size() - 1].amountb = (states[i].focus > 0) ? 6 : 4;
}
*/
if (states[i].timea == 0 || states[i].timea < states[i].timeb) {
states[i].h1++;
states[i].cd = 36;
states[i].timea = 80;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.95;
nexts[nexts.size() - 1].amounta = (states[i].focus > 0) ? 9 : 6;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.75;
nexts[nexts.size() - 1].amounta = (states[i].focus > 0) ? 6 : 4;
nexts[nexts.size() - 1].focus = 81;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.25;
nexts[nexts.size() - 1].amounta = (states[i].focus > 0) ? 6 : 4;
}
else {
states[i].h3++;
states[i].cd = 36;
states[i].timeb = 80;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.95;
nexts[nexts.size() - 1].amountb = (states[i].focus > 0) ? 9 : 6;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.75;
nexts[nexts.size() - 1].amountb = (states[i].focus > 0) ? 6 : 4;
nexts[nexts.size() - 1].focus = 81;
nexts.push_back(states[i]);
nexts[nexts.size() - 1].p *= 0.05 * 0.25;
nexts[nexts.size() - 1].amountb = (states[i].focus > 0) ? 6 : 4;
}
}
}
states.clear();
for (int i = 0; i < nexts.size(); i++) {
bool found = 0;
for (int j = 0; j < states.size() && found == 0; j++) {
if (Equal(nexts[i], states[j])) {
states[j].h1 = (states[j].h1 * states[j].p + nexts[i].h1 * nexts[i].p) / (states[j].p + nexts[i].p);
states[j].h2 = (states[j].h2 * states[j].p + nexts[i].h2 * nexts[i].p) / (states[j].p + nexts[i].p);
states[j].h3 = (states[j].h3 * states[j].p + nexts[i].h3 * nexts[i].p) / (states[j].p + nexts[i].p);
states[j].dot = (states[j].dot * states[j].p + nexts[i].dot * nexts[i].p) / (states[j].p + nexts[i].p);
states[j].p += nexts[i].p;
found = 1;
}
}
if (found == 0) {
states.push_back(nexts[i]);
}
}
nexts.clear();
}
float skill = 10000;
float force = 2000;
float th1 = 0, th2 = 0, th3 = 0, tdot = 0;
float night[4000] = {0};
for (int i = 0; i < states.size(); i++) {
night[int(states[i].dot + 0.5)] += states[i].p;
if (states[i].p * states[i].h1 > 0)th1 += states[i].p * states[i].h1; if (states[i].p * states[i].h2 > 0)th2 += states[i].p * states[i].h2; if (states[i].p * states[i].h3 > 0)th3 += states[i].p * states[i].h3; tdot += states[i].p * states[i].dot;
}
for (int i = 0; i < 4000; i++) {
if (night[i] != 0) {
cout << " night[" << i << "] = " << night[i] << ";\n";
}
}
cout << th1 << " " << th2 << " " << th3 << " " << tdot <<endl;
cout << states.size();
}

沪公网安备 31011002002714 号