WIKI冒险团明确声明不支持涉及代练和账号买卖的现金交易活动。
参与者应自行承担对应后果。

全站通知:

战力测试终极算法(代码向)

阅读

    

2023-07-27更新

    

最新编辑:欣酱是萌欣吖

阅读:

  

更新日期:2023-07-27

  

最新编辑:欣酱是萌欣吖

来自地下城堡2WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索
页面贡献者 :
欣酱是萌欣吖

前言

  本攻略更新于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();
}