-
Notifications
You must be signed in to change notification settings - Fork 0
/
StarRailWishSupport.py
183 lines (178 loc) · 7.82 KB
/
StarRailWishSupport.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import sys
def main():
#单次抽卡的概率
#角色池
def percent_character(x):
if x <=73:
return 0.006
elif x <= 89:
return (0.006+0.06*(x-73))
else:
return 1
#武器池
def percent_weapon(x):
if x <=66:
return 0.008
elif x <= 70:
return (0.008+0.112*(x-66))
elif x <= 79:
return (0.456+0.056*(x-70))
else:
return 1
#初始化一个零矩阵
size = 180*ExpectedCharacterNum+160*ExpectedWeaponNum+1 #这里加上1是为了让最后一行表示达成抽卡预期的状态
TPmatrix = np.zeros((size, size))
#角色池的初始状态设置
CharacterPoolOffset = 0
if ExpectedCharacterNum != 0:
if CharacterPoolGuarantee == False:
CharacterPoolOffset = CharacterPoolStage
elif CharacterPoolGuarantee == True:
CharacterPoolOffset = CharacterPoolStage+90
#生成转移概率矩阵(矩阵前面的行是武器,后面的行是角色,最后一行表示的状态是已经达成抽卡预期)
#这一部分代码生成抽武器的状态,如果要抽的武器数为0,那么就不会运行这一部分代码
for i in range(0, ExpectedWeaponNum):
offset = 160*i
for j in range(0, 80):
x = j % 80 + 1
if i == ExpectedWeaponNum-1:
#该行属于要抽的最后一把武器的部分,那么如果出限定就会进入角色部分,要加上角色池的初始偏移量
TPmatrix[offset+j, offset+160+CharacterPoolOffset] = percent_weapon(x)*0.75
else:
#该行不属于要抽的最后一把武器的部分,那么抽完会进入下一把武器
TPmatrix[offset+j, offset+160] = percent_weapon(x)*0.75
TPmatrix[offset+j, offset+80] = percent_weapon(x)*0.25
if j != 79:
TPmatrix[offset+j, offset+j+1] = 1-percent_weapon(x)
for j in range(80, 160):
x = j % 80 + 1
if i == ExpectedWeaponNum-1:
TPmatrix[offset+j, offset+160+CharacterPoolOffset] = percent_weapon(x)
else:
TPmatrix[offset+j, offset+160] = percent_weapon(x)
if j != 159:
TPmatrix[offset+j, offset+j+1] = 1-percent_weapon(x)
#这一部分代码生成抽角色的状态,如果要抽的角色数为0,那么就不会运行这一部分代码
for i in range(0, ExpectedCharacterNum):
offset = 180*i+ExpectedWeaponNum*160
for j in range(0, 90):
x = j % 90 + 1
TPmatrix[offset+j, offset+180] = percent_character(x)*0.5
TPmatrix[offset+j, offset+90] = percent_character(x)*0.5
if j != 89:
TPmatrix[offset+j, offset+j+1] = 1-percent_character(x)
for j in range(90, 180):
x = j % 90 + 1
TPmatrix[offset+j, offset+180] = percent_character(x)
if j != 179:
TPmatrix[offset+j, offset+j+1] = 1-percent_character(x)
#最后一行表示已经达成抽卡预期,所以从该状态到其他状态的概率都是0,到自身的概率为1
TPmatrix[size-1, size-1] = 1
#生成初始状态向量,如果抽武器,那么和武器池水位有关,否则和角色池水位有关
initVector = np.zeros((size))
if ExpectedWeaponNum != 0:
if WeaponPoolGuarantee == False:
initVector[WeaponPoolStage] = 1
elif WeaponPoolGuarantee == True:
initVector[WeaponPoolStage+80] = 1
else:#这里是不抽武器的情况,和角色池水位有关
initVector[CharacterPoolOffset] = 1
#存储达到10%、25%、50%、75%、90%概率时的抽数
percent10num = 0
percent25num = 0
percent50num = 0
percent75num = 0
percent90num = 0
percentlist = []
percentlist.append(0)
#存储达到预期次数的概率
percentRes = -1
resultVector = initVector
for i in range(0, 1500):
#将初始状态向量和转移概率矩阵不断相乘,相乘的次数为抽数,得到预期次数后状态的概率分布
resultVector = resultVector@TPmatrix
result = resultVector[size-1]
percentlist.append(result)
if i == IntertwinedFateNum - 1:
percentRes = result
if result > 0.1 and percent10num == 0:
percent10num = i+1
if result > 0.25 and percent25num == 0:
percent25num = i+1
if result > 0.5 and percent50num == 0:
percent50num = i+1
if result > 0.75 and percent75num == 0:
percent75num = i+1
if result > 0.9 and percent90num == 0:
percent90num = i+1
if result > 0.98 and (percentRes != -1 or IntertwinedFateNum == 0):
break
#画一幅概率曲线图并保存到当前文件夹下
ax = plt.axes()
ax.yaxis.set_major_locator(ticker.MultipleLocator(0.1))
ax.yaxis.set_minor_locator(ticker.MultipleLocator(0.025))
if len(percentlist) > 500:
ax.xaxis.set_major_locator(ticker.MultipleLocator(100))
ax.xaxis.set_minor_locator(ticker.MultipleLocator(25))
elif len(percentlist) > 200:
ax.xaxis.set_major_locator(ticker.MultipleLocator(50))
ax.xaxis.set_minor_locator(ticker.MultipleLocator(12.5))
elif len(percentlist) > 80:
ax.xaxis.set_major_locator(ticker.MultipleLocator(20))
ax.xaxis.set_minor_locator(ticker.MultipleLocator(5))
elif len(percentlist) > 30:
ax.xaxis.set_major_locator(ticker.MultipleLocator(10))
ax.xaxis.set_minor_locator(ticker.MultipleLocator(2.5))
ax.set_title('StarRail Warp Probability')
ax.grid(True)
plt.plot(percentlist)
plt.xlim(xmin=0,xmax=len(percentlist)+5)
plt.ylim(ymin=0,ymax=1)
if IntertwinedFateNum != 0:
plt.vlines(x=IntertwinedFateNum, ymin=0, ymax=percentRes, label='', linestyles='dashed')
plt.hlines(y=percentRes, xmin=0, xmax=IntertwinedFateNum, label='', linestyles='dashed')
#保存图片,根据图片名称来标记
plt.savefig("data/StarRailPercent/%d,%d,%d,%d,%d,%d,%d.png" %(IntertwinedFateNum,ExpectedCharacterNum,CharacterPoolGuarantee,CharacterPoolStage,ExpectedWeaponNum,WeaponPoolGuarantee,WeaponPoolStage))
percentRes = str(np.round(percentRes*100,2))
#传输给js脚本
print("%s %d %d %d %d %d" % (percentRes, percent10num, percent25num, percent50num, percent75num, percent90num),end = '')
sys.stdout.flush()
#拥有的纠缠之缘数量
IntertwinedFateNum = int(sys.argv[1])
########################## 下为角色池部分 ##########################
#期望抽到角色数(0-7)
ExpectedCharacterNum = int(sys.argv[2])
#当前是否大保底(True/False)
CharacterPoolGuarantee = bool(int(sys.argv[3]))
#角色池的水位(0-89)
CharacterPoolStage = int(sys.argv[4])
########################## 下为武器池部分 ##########################
#期望抽到武器数(0-5)
ExpectedWeaponNum = int(sys.argv[5])
#当前是否大保底(True/False)
WeaponPoolGuarantee = bool(int(sys.argv[6]))
#武器池的水位(0-79)
WeaponPoolStage = int(sys.argv[7])
#命定值(0-2)铁道没有命定值
# BindingNum = int(sys.argv[8])
# #调试用
# #拥有的纠缠之缘数量
# IntertwinedFateNum = 200
# ########################## 下为角色池部分 ##########################
# #期望抽到角色数(0-7)
# ExpectedCharacterNum = 7
# #当前是否大保底(True/False)
# CharacterPoolGuarantee = 0
# #角色池的水位(0-89)
# CharacterPoolStage = 0
# ########################## 下为武器池部分 ##########################
# #期望抽到武器数(0-5)
# ExpectedWeaponNum = 5
# #当前是否大保底(True/False)
# WeaponPoolGuarantee = 0
# #武器池的水位(0-79)
# WeaponPoolStage = 0
main()