Risk里面打仗的规则很有意思:攻守双方靠掷骰子比大小来决定各死几个人。攻 方最多出三个人;守方最多出两个人。打的时候双方都可能会死人,而就用点数 的大小来决定死几个人。比较时,把攻方掷出的骰子排序,守方也排序,再一一 比最高的几个。每次比较时,决定死的这个人来自哪方:只有攻方的点数严格大 于守方的,才算攻方胜(不用死人);否则攻方就输,需要死一个人。
举个例子:假设攻方要出三个人,守方出两个人。攻方掷出了3、4、5,守方是3, 和5。这样各方排序之后,经过比较,双方各死一个人。
攻 | 守 | |
5 | 5 | 守方胜 |
4 | 3 | 攻方胜 |
3 |
这种游戏规则和平时见到的比大小很不一样,因为攻守优劣势很不明显。一方面, 守方的优势在于点数天然就会更大一号;但另外一方面,攻方如果人多的时候就 更容易出现大的点数。那这样一来,到底谁更占优?
心算不出来,写个程序模拟一下,试试攻守双方不同人数的组合:
-
双方大概每次打仗会死多少人(期望)
-
打仗时双方各自获胜的概率
import random
import numpy
import tabulate
def ComputeWinningStats(off_size, def_size, N_sim=100000):
"""Compute the winning stats by simulation.
"""
rand = random.Random()
my_losses = []
opp_losses = []
wins = []
for _ in range(N_sim):
we_win = False
my_rolls = sorted([rand.choice(range(6)) for i in range(off_size)], reverse=True)
opp_rolls = sorted([rand.choice(range(6)) for i in range(def_size)], reverse=True)
my_loss, opp_loss = 0, 0
for my, opp in zip(my_rolls, opp_rolls):
if my > opp:
opp_loss += 1
else:
my_loss += 1
if opp_loss == def_size:
we_win = True
my_losses.append(my_loss)
opp_losses.append(opp_loss)
wins.append(we_win)
return {
"off_size": off_size,
"def_size": def_size,
"off_losses": numpy.mean(my_losses),
"def_losses": numpy.mean(opp_losses),
"win_rate": numpy.mean(wins)
}
results = []
for off_size in range(1, 4):
for def_size in range(1, 3):
results.append(ComputeWinningStats(off_size, def_size))
print(tabulate.tabulate(results, headers="keys"))
运行结果如下:
off_size def_size off_losses def_losses win_rate
---------- ---------- ------------ ------------ ----------
1 1 0.58313 0.41687 0.41687
1 2 0.74467 0.25533 0
2 1 0.41997 0.58003 0.58003
2 2 1.21831 0.78169 0.2298
3 1 0.33808 0.66192 0.66192
3 2 0.91986 1.08014 0.37183
表中每行能看出进攻方和防守方的人数(off_size, def_size),以及各方死亡人 数(off_losses, def_losses),还有进攻方获胜的概率。
我看到这个表对于打法的指导意义:
-
如果我是防守方,有两个子,就一定要拿这两个子做防御。这样相比两次拿 一个子做防御,死的人会少20%左右。
-
如果我是进攻方,每次进攻时应该尽量拿更多的子进攻。这样在消耗敌方同 样的子的情况下,我方伤亡最小。
-
在进攻时,如果我方的人和对方差不多多,都大于3个,那我可以不停去攻, 因为平均每局我的伤亡要小一点点(0.92 v.s. 1.08)。