4

我必须模拟两个玩家之间的战斗。它可以持续一到六轮。攻击者可以拥有 13 种不同类型的宇宙飞船,防御者 - 额外的 9 种防御结构。问题是我要将模拟限制在每侧 1kk 个单位,所以它会非常大。

每个单元都将成为以下类的实例

class Unit()
{
    UInt16 id; // unit type
    Int32 structuralIntegrity;
    Int16 shieldPower;

    public Unit(UInt16 unitType, Int16 playerId)
    {
        id = unitType;
        switch (playerId)
            {
                case 0: {structuralIntegrity = player0BaseStructuralIntegrity[id]; shieldPower = player0BaseshieldPower[id];}
                case 1: {structuralIntegrity = player1BaseStructuralIntegrity[id]; shieldPower = player1BaseshieldPower[id];}
            }
    }
};

用于不变值的数组。

player1技术

  • 装甲技术
  • 盾牌技术
  • 武器技术

player2技术

  • 装甲技术
  • 盾牌技术
  • 武器技术

player1Base结构完整性

等于默认*装甲技术

等等...

然后我会用每个玩家单位传播两个列表。

一轮是这样的:

  1. 选择随机单位//实际上我认为它是否随机并不重要
  2. 选择随机目标
  3. 如果武器威力低于目标护盾的 1%,则不会造成伤害
  4. 目标的护盾吸收伤害,其余部分用于目标的结构完整性
  5. 如果目标的结构完整性低于其初始值的 30%,则它有 1-structuralIntegrity/baseStructuralIntegrity 爆炸的概率
  6. 检查快速射击的概率,如果命中则转到步骤 2
  7. 进入步骤 1 直到所有单位攻击 | 笔记!被摧毁的船只 - 结构完整性低于 1 的船只仍然可以受到攻击。编辑:他们也可以攻击这一轮
  8. 对对手重复步骤 1-7。
  9. 移除被摧毁的船只
  10. 恢复盾牌

战斗持续六轮或直到一方被击败。

让我们考虑一个由 100 架轰炸机和 200 架火箭发射器组成的攻击机队。轰炸机在攻击火箭发射器后有 95% 的几率再次开火。所以每个轰炸机平均会攻击 96 次,给我们 9600 次攻击。假设防守者很幸运,一个火箭发射器幸存了下来。他还摧毁了10架轰炸机。现在我们有 90 架轰炸机攻击一个火箭发射器,又给了我们 8640 次射击。想想 100k 轰炸机和 200k 火箭发射器。

您对如何改进这种模拟(性能)有什么建议吗?我应该运行多少次才能获得可信的平均结果?

更新

我想我可能会坚持我的模拟,因为即使你找到了一个数学解决方案,由于我目前的教育水平,我也不会理解它。

有人询问更多细节。

对应科技每升一级,初始值增加10%,但对模拟来说并不重要,所以假设双方玩家的科技都是0。让我们考虑一个由 1 个巡洋舰对 2 个导弹发射器 + 1 个重型激光器组成的攻击舰队。巡洋舰有 2700 结构完整性、50 盾和 400 武器。我会把它写成 2700:50:400

  • 巡洋舰 2700:50:400 x1
    对比
  • 导弹发射器 200:20:80 x2
  • 重型激光 800:100:250 x1

导弹发射器和重型激光没有快速射击。巡洋舰对重型激光的快速射击为 0,对导弹发射器的快速射击为 10,使其在攻击导弹发射器后再次开火的概率为(10-1)/10= 0.90 。

一种可能的结果可能如下:

第1轮

攻击者向防御者开火

巡洋舰以 2700:50:400 向 Missile Laucher 以 200:20:80 开火;结果是 Missile Laucher 与 -180:0:80

熊熊大火:

  • 巡洋舰对导弹发射器有快速射击。
  • 骰子为 0.62,与 0.90 相比:Cruiser 再次出手。

巡洋舰以 2700:50:400 向 Missile Laucher 以 200:20:80 开火;结果是 -180:0:80 的导弹发射器

熊熊大火:

  • 巡洋舰对导弹发射器有快速射击。
  • 骰子为 0.09,与 0.90 相比:Cruiser 再次出手。

巡洋舰 2700:50:400 以 -180:0:80 向导弹发射器开火;结果是 -580:0:80 的导弹发射器

熊熊大火:

  • 巡洋舰对导弹发射器有快速射击。
  • 骰子为 0.83,与 0.90 相比:Cruiser 再次出手。

巡洋舰以 2700:50:400 向重型激光发射 800:100:250;结果是 500:0:250 的重型激光

熊熊大火:

  • 巡洋舰对重型激光没有快速射击。

防御者向攻击者开火

Missile Laucher -580:0:80 以 2700:50:400 向 Cruiser 开火;结果是 2670:0:400 的 Cruiser

Missile Laucher -180:0:80 以 2670:0:400 向 Cruiser 开火;结果是 2590:0:400 的 Cruiser

500:0:250 的重型激光以 2590:0:400 向巡洋舰射击;结果是 2340:0:400 的 Cruiser

移除船只并恢复护盾

巡洋舰仍然有完整性,恢复它的盾牌。

Missile Laucher 失去了所有的完整性,将其从战斗中移除。

Missile Laucher 失去了所有的完整性,将其从战斗中移除。

重激光仍有完整性,恢复它的护盾。

第二轮

攻击者向防御者开火

巡洋舰以 2340:50:400 向重型激光发射 500:100:250;结果是 200:0:250 的重型激光

  • 爆炸概率为 75.00%(1-200/800):骰子值 0.30 与 0.75 相比:单位爆炸。

结果是 9:0:250 的重型激光

熊熊大火:

  • 巡洋舰对重型激光没有快速射击。

防御者向攻击者开火

9:0:250 的重型激光以 2340:50:400 向 Cruiser 开火;结果是 2140:0:400 的 Cruiser

移除船只并恢复盾牌。

巡洋舰仍然有完整性,恢复它的盾牌。

重型激光失去了所有完整性,将其从战斗中移除。

战斗在2回合后以攻击者获胜而结束。

4

2 回答 2

3

对于如此数量的单位,我相信采取(某种)统计的、通用的方法是有效的。

只需总结给定类型单位的所有统计数据,保留计数,然后计算总伤害,总防御,移除被伤害摧毁的对手单位数量占总防御的百分比。

我相信这是 Travian 或其他在线策略游戏使用的方法。对于如此大的数字,没有有效的方法。

特别案例

如果目标的结构完整性低于其初始值的 30%,则它有 1-structuralIntegrity/baseStructuralIntegrity 爆炸的概率

我相信您可以使用高斯分布来确定额外爆炸单位的数量。值越大σ,破坏的概率越大。

其他方法可能是销毁剩余船只的百分比。百分之多少?你的选择。

熊熊大火

由于您没有定义快速射击,因此我无法提供任何建议。但我建议添加一个特殊的战斗阶段,以考虑到这一点。您也可以通过快速射击概率确定的因素简单地增加伤害。

于 2013-06-05T08:55:50.910 回答
1

我认为您的模拟应该尝试代表每个独立且同时行动的单元。如果是这样,您将需要非常小心如何实现每一轮的模拟。您不希望玩家 1 通过削弱或摧毁对手的单位来获得优势,这样他们就无法仅仅因为轮到他们而反击。因此,所有的护盾更新、完整性和爆炸都需要在两个玩家都采取行动后存储和应用。

当你运行模拟时,你会得到一个或另一个玩家赢得那场战斗的结果。通过运行它任意次数,并计算玩家 1 的赢/(赢 + 输),您将估计在初始情况下玩家 1 获胜的次数百分比。这类似于扔硬币以确定它是否是公平的硬币(参见维基百科)。

您还可以计算误差的估计量并使用它来确定置信区间。这为您提供了包含玩家 1 在任意时间百分比(例如 95%)中赢得场景的真实概率的值范围。如果您想非常确信该范围包含真实值并且误差范围很小,那么您将在漫长的夜晚中度过,因为您需要运行许多模拟。如果战斗势均力敌,而不是更加片面,你还需要更多的模拟。

我根据维基百科关于投掷公平硬币的文章做了一些粗略的计算。如果您对 95% 的置信区间感到满意,并且希望最大误差为 0.01,那么如果获胜的概率为 50%,则需要 10000 次测试。如果只有 25%,那么您将需要大约 1350。如果只有 10%,那么您只需要 312。如果您想要 99% 的置信区间,那么您将需要大约 3 倍的测试。

编辑

我认为这个问题的分析解决方案将非常困难。我将建议您简化规则以使其更易于处理。

规则 3 - 攻击特定盾牌所需的最低武器威力不太可能对是否对单位造成任何结构性损坏产生太大影响,除非一方的人数超过另一方 100:1。如果没有此规则造成的任何少量伤害都将在回合结束时恢复护盾时得到治疗。我建议忽略这条规则。

规则 6 - 我认为如果你有 100 个爆能枪,有 10% 的机会快速射击,这与拥有 110 个不快速射击的爆能枪相同(从对敌人造成的平均伤害来看)。因此,要计算快速射击的效果,只需将平均伤害增加快速射击的百分比机会即可。

规则 5 - 这使情况显着复杂化,因为现在结构完整性值的差异会显着影响有多少单位存活到下一轮。如果没有此规则,您可以使用每个单位造成的平均伤害来估计对敌人造成的伤害量,类似于给出的其他建议。如果你想简化这一点,我认为它类似于在 85% 的情况下结构完整性降低 30% 的建模单元,这可以将所有单元的完整性降低 25.5%。

通过这样做,您将基本上遵循 Dariusz 的方法

Eg if you have 
Side A: 100k bombers and 200k rocket launchers 
Side B: 130k bombers and 150k rocket launchers

Expected total damage side A (ETDa)
ETDa = 100k*BomberDamage*(1+rapidfire%bomber) + 200k*RLDamage*(1+rapidfire%rocketlauncher)

This will be spread evenly between the units in side B based upon their percentage of the total number of units present.

Expected total damage to bombers on side B (ETDBombersB)
ETDBombersB = 130k/280k*ETDa
Similarly ETDRocketLaunchersB = 150k/280k*ETDa

Structural damage to bombers on side B is reduced by the amount of the bombers shields
ESDBombersB = ETDBombersB - 130k*BombersShields
Similarly ESDRocketLaunchersB = ETDRocketLaunchersB - 150k*RocketLaunchersShields

Rather than have partly damaged units at the end of a round, I suggest you treat all existing units as fully healed, and apply the damage to units in turn until it is all used up. As above I am reducing the  structural integrity by 25.5% to model the average chance of explosion.
% of bombers destroyed = ESDBombersB / StructuralIntegrityBombers*(1-0.255)*130k
% of rocket launchers destroyed = ESDRocketLauncherB / StructuralIntegrityRL*(1-0.255)*150k

另请注意,根据中心极限定理,当您在模拟中拥有大量单位时,您更有可能获得平均结果,一个单位造成的极端伤害往往会被其他单位造成的少量伤害所抵消. 即,掷一次骰子时获得极值 1 或 6 的可能性要远大于掷 3 次时获得总共 3 或 18 的可能性。因此,这可能会使统计上捏造的分析仍然相当有用。

但是,如果您试图模拟实际现有游戏中的情况,那么规则是指定的,您需要花时间进行最初描述的蒙特卡罗模拟以获得最准确的结果。

于 2013-06-05T08:33:07.853 回答