如果你曾经冒风险,你就会熟悉掷骰子以确定战斗的结果。如果没有,这里有一个简短的概要:
确定玩家可以晃动多少骰子的规则如下:
决定掷骰子结果的规则如下:
如果攻击者或捍卫者只掷一个骰子,总共只会有一支军队丧生;在所有其他情况下,总共将失去两支军队。
我想分析每对模具卷的获胜/亏损频率。我可以遍历所有可能性,但我对使用ndarrays
和切片进行计算感兴趣。
例如,考虑攻击者掷出一个骰子并且防御者掷出一个骰子的情况。我们可以在ndarray
中安排所有可能的结果。
In [1]: import numpy as np
In [2]: x = np.tile(np.arange(1,7),(6,1))
In [3]: x
Out[3]:
array([[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6]])
如果防御者卷是列,而攻击者卷是行,则防御者获胜的区域是此数组的上三角部分
defence_win_region= array([[1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[0, 0, 1, 1, 1, 1],
[0, 0, 0, 1, 1, 1],
[0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 1]])
如何从像defence_win_region
这样的数组中获取x
之类的数组?如何将该方法扩展到更高维度的数组以分析2-1,3-1,3-2,1-2卷?
答案 0 :(得分:1)
import numpy as np
import scipy
import itertools
def riskRoll(ad,dd): #Never gonna give you up . . .
minD=min(ad,dd)
a=np.array(list(itertools.combinations_with_replacement(
np.arange(6,0,-1),ad)))
d=np.array(list(itertools.combinations_with_replacement(
np.arange(6,0,-1),dd)))
na=np.array([scipy.misc.factorial(ad)/np.prod(
scipy.misc.factorial(np.unique(roll,return_counts=True)[1])) for roll in a])
nd=np.array([scipy.misc.factorial(dd)/np.prod(
scipy.misc.factorial(np.unique(roll,return_counts=True)[1])) for roll in d])
a_wins= np.sum(p.where(a[None,:,0:minD]>d[:,None,0:minD],1,-1), axis=-1)+ad-dd
nd_count=na[:,None]*nd[None,:]
return a_wins*nd_count
工作原理:
C((6,ad)) x C((6,dd))
的矩阵,所有组合都按降序排列a_wins
中的值是攻击者获胜的数量,负数是防御性胜利。这包括无争议的骰子。nd_count
中的值是加权因子,等于6**ad x 6**dd
组合矩阵中组合存在的次数答案 1 :(得分:0)
关于2D阵列的具体问题的简短回答是:
np.where(x >= np.transpose(x), 1, 0)
但为了进一步推动这一点,您需要tile
以外的工具。准备样本空间的自然方法是meshgrid
:
die = np.arange(1, 7)
a, d = np.meshgrid(die, die)
现在a
和d
是包含攻击者和防御者分数的二维数组。和以前一样,np.where(a <= d, 1, 0)
产生1-0表(前一个表的转置,但这是选择的问题)。
让我们看看当每个掷两个骰子时会发生什么:
a1, a2, d1, d2 = np.meshgrid(die, die, die, die)
这是防守队员赢得第一轮(比较最高分)的地方:
np.where(np.maximum(a1, a2) <= np.maximum(d1, d2), 1, 0)
以下是最小值的比较,这是第二高分:
np.where(np.minimum(a1, a2) <= np.minimum(d1, d2), 1, 0)
两者都是4D阵列,因为样本空间是4维的。
当有人投掷3个或更多骰子时事情变得更加复杂,因为选择“第二高”不是像最大值这样简单的操作。它可以通过堆叠玩家的骰子并沿新轴排序,然后切片来完成:
a1, a2, a3, d1, d2 = np.meshgrid(die, die, die, die, die) # 3-2 roll
attack = np.stack([a1,a2,a3]) # stack attacker into a 6D array
attack.sort(axis=0) # sort their scores
attack_max = attack[-1,:,:,:,:,:] # maximum score
attack_2nd = attack[-2,:,:,:,:,:] # 2nd highest attack score
现在我们像以前一样比较:
defender_wins_1 = np.where(attack_max <= np.maximum(d1, d2), 1, 0)
defender_wins_2 = np.where(attack_2nd <= np.minimum(d1, d2), 1, 0)