咒语施法-如何优化每秒伤害


23

假设我们有一个知道一些咒语的巫师。每个法术都有3个属性:伤害,冷却时间和施法时间。相当标准的RPG东西。

冷却时间:能够再次施放该法术所花费的时间(t)。咒语开始施放时便会持续进行“冷却”。

施法时间:使用咒语所需的时间(t)。向导施放某些东西时,无法施放其他咒语,并且不能将其取消。

问题是:在不同的法术组合下,您将如何最大化伤害?

很容易计算出每个施法时间的最高伤害。但是,如果有更多更好的选择,那么等待然后让“卡住”施放低伤害咒语的情况又如何呢?

例如,

  1. 火球:3000伤害,3秒施法时间,6秒冷却。

  2. 寒冰箭:20伤害,4秒施法时间,4秒冷却。

  3. 疾风:3伤害,3秒施法时间,3秒冷却。

在这种情况下,如果您选择使用较低的DPCT咒语(疾风)而不是冰霜箭,则每秒的伤害会更高。因此,我们必须考虑选择咒语的后果。 替代文字

在下面的示例中是“过度投放”和“等待”的情况。 替代文字


为什么在这种情况下我会做1-3-1?为什么不1-2-1?为什么不使用1-3-3-1不会杀死目标的1-2-3-1,比1-3-1-X更有效的呢?

@Joe Wreschnig:感谢您指出这一点。在我的例子中是一个错误。现在将其简化为2种情况。
aaronfarr

1
贪婪,尽可能选择最高的DPS拼写。忽略其他逻辑,即。等候。
aaronfarr

1
只是为了弄混水。考虑一个造成∞伤害但需要50秒施放的法术。它的dps / dpct是∞,但是如果可以在不到50秒的时间内用其他方法杀死目标,则永远不要选择它。
deft_code 2010年

Answers:


23

所有的AI都是搜索!

当你进入AI的胆量这是惊人的还真是多少呢搜索

  • 状态:所有可用法术的剩余冷却时间。
  • 适应度:造成的总伤害
  • 费用:总花费时间
  • 分支:任何已知的咒语。如果法术仍然处于冷却状态,只需将该值添加到施法时间。
  • 目标目标的总体健康状况。目标必须是有限的伤害,因此如果目标未知,则选择最大的生命值。
    或者,目标可以花费少于50秒,而搜索将找到可以在50秒内完成的最大伤害。

将这些参数插入统一成本搜索(UCS)并预先保存,以确保获得最佳作战计划。如果您能提出启发式搜索,使用A *或IDA *进行搜索,甚至会更好,那么您将更快地获得相同的答案。

使用UCS的其他优点是,与仅提供3个变量的情况相比,它可以为更复杂的情况找到最佳的浇铸顺序。可以轻松添加的其他一些方面:

  • 随着时间的推移而造成的损害
  • 刷新法术以减少其他法术的冷却时间
  • 急速咒语导致其他咒语施放更快。
  • 伤害助推器,造成其他法术造成更多伤害。

UCS不是万能的。它无法模拟保护法术的好处。为此,您必须升级到alpha-beta搜索或minimax。
而且,它不能很好地处理影响区域,而且群战效果非常好。在这些情况下,可以对UCS进行调整以提供合理的解决方案,但不能保证找到最佳的解决方案。


2

这是一个专门的组合优化问题。随着咒语数量的增加,寻找最佳咒语组合/样式的难度大大增加。类似于背包问题的启发式方法对于解决该问题非常有用。


1

您需要考虑“每铸造时间的损坏”(DPCT)-例如,投掷3秒并造成3000伤害的火球会造成1000 DPCT。

如果在铸造之前必须等待3秒进行冷却,那将使冷却时间降低至500 DPCT(3000伤害,除以总计6秒的时间,包括等待时间)

因此,您只需要确定每个法术的每次铸造时间伤害,包括等待冷却的所有剩余时间。选择具有最高DPCT的那个,如有必要,请等待,然后进行投射。重复直到老板死了:)


问题在于,DPCT可能会产生误导。举例来说,我们向火球组合中添加了2个法术:3000伤害,3秒施法,6秒冷却时间,DPCT:1000法术#2:20伤害,4秒施法,4秒冷却时间,DPCT:5法术#3:3伤害,3秒施法,3秒冷却,DPCT:1(请记住,冷却开始于施放咒语的那一刻开始)即使法术#3的DPCT较低,也会导致较高的DPS(1-3-1-3。 。),而不是法术2(1-2-1-2 ...)。
aaronfarr

1

使用您的示例,您可能希望这两个咒语在效果上更接近,但可能会给您带来不同的优势。较短的投放时间(或为此没有投放时间)将非常有用,因此即使损坏较少且再次使用需要较长时间,也值得使用。

您总是可以将其他元素强加到方程式中。法力/魔法点数可以达到这一目的,方法是让玩家确定使用这些点数是否值得。

总体而言,正如bluescrn所说,DPCT(或许多寻求最佳混音的玩家对其进行了高度调优和讨论的游戏中所称的DPS)确实是您想要平衡的主要元素,尤其是如果您有任何技术/技能树,允许不同的玩家使用不同的技能进步,同时能够在游戏中的给定位置造成相似数量的伤害。


0

弄清楚了这个算法对我来说很好用。

人们提出了一些要点。为其提供最终目标参数将允许常规搜索算法完成其任务。即。在t秒内造成最佳伤害,在最佳时间内造成x伤害。

我的算法仅返回具有最高DPS的咒语序列。这是一种快速的算法,因为它可以缩小正在遍历的集合的大小,并且不需要了解其他搜索树技术。

第一步是确定每个施法时间伤害最高的法术。由于该咒语保证每秒最高的伤害,因此它成为“基准”咒语。意思是,如果满足以下两个条件,则应始终施放此法术:1)基线法术可用(冷却时不可用)。2)您目前没有施法。

因此,当基线法术处于冷却状态时,这便成为填充其他法术的问题。在(播放时间)和(冷却时间-投放时间)之间。但是,可能会发生一些重叠(上述规则2为假)。

然后,就需要遍历所有非基准咒语,以找到不违反这两个规则的所有咒语序列。

对于确实重叠的咒语,您必须对它们可能造成的潜在伤害进行惩罚,以使基线咒语可能造成的伤害(最大伤害)。

以2个咒语为例

1:300伤害,3秒施法时间,10秒冷却

2:290伤害,3秒施法时间,3秒冷却

最多的伤害来自序列1-2-2-2。这会导致潜在的#1投射重叠2秒。但是,这仍然是有益的,因为如果您不施放第三个咒语(即1-2-2),则将在1秒内造成880点伤害。如果您施放额外的#2咒语,则将造成#1的1170-2秒,即200。因此,您的相对伤害是970伤害。


-2

您可以做一个简单的“安全级别”样式的开关盒。

这只是我的脑袋,所以要提防超出我疲倦状态的逻辑错误,但是我希望这可以帮助您入门。

假设您的时间是以整数为单位的,

// after casting spell
int remainingTime = (coolDown - castTime);
switch(spellJustCast)
{
  // assuming the cast method will have some input validation for whether the spell
  // is off cooldown or not, pass the time as a parameter
  case 3 : castSpell1(remainingTime);
           castSpell2(remainingTime);
           break;
  case 1 : castSpell2(remainingTime);
           castSpell3(remainingTime);
           break;
  case 2 : castSpell1(remainingTime);
           castSpell3(remainingTime);
           break;
  default: System.out.println("Debug!");
           break;
}

由于您的拼写时间,某些方法调用是不必要的,但是总是有这种更新的空间。

编辑:我刚刚意识到,您需要重置新咒语之后的剩余时间,可能最好使其成为类属性/字段,并通过castSpell方法中的调用对其进行设置。


我真的不知道您要在这里做什么,但是没有现代游戏引擎具有诸如castSpell1和castSpell2之类的功能。

1
@Joe Wreschnig我的意思是说它们是他自定义游戏类中自己的方法,这只是一个抽象示例,而不是详细示例。
2010年

1
是的,这不是咒语在现代引擎中的工作原理。有一个castSpell函数采用一个对象,该对象的字段是从文件中读取的。这样的switch语句将不可能在任何实际引擎中维护,并且需要某种计划算法。

@Joe Wreschnig我明白。我只是在提供一种解决问题的方法。这个例子是用Java编写的,不适用于引擎或特定框架。但是,如果您无法实现它,我的回答将是无效的。
2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.