前言
在学习了一个星期的Python基础之后,正巧碰上方舟的限定卡池开放,便想着用自己的一个星期所学知识来做一个(很久之前就想做的)抽卡模拟器,以此来巩固和运用自己学到的东西。敲了一个晚上之后就完成了。
卡池规则:
想做卡池模拟抽卡,那就要了解卡池的规则。明日方舟这款游戏的限定卡池规则如下:
-
卡池的基本出率:六星干员2%、五星干员8%、四星干员50%、三星干员40%。
- 每次获得的六星干员中,有70%的概率获得【纯烬艾雅法拉】、【琳琅诗怀雅】这两位干员中的一个。
- 剩余30%的其他六星干员中,【百炼嘉维尔】与【假日威龙陈】出现概率位其他单个六星干员的5倍。
-
每次获得的五星干员中,有50%的概率获得【青枳】干员。
-
如果累计50抽都没有获得六星干员,那么从下一抽开始,获得六星干员的概率会随着抽数的增加而逐步增加+2%,获得六星干员后重置为2%。(例如第51抽出现六星干员的概率为4%,第52抽出现六星干员的概率为6%,以此类推)
-
首次十连必定出现五星以上的干员(包括五星),仅限一次生效。
思路分析
我自己的思路是这样的:首先按照卡池列出的概率先抽稀有度,然后再按照每个稀有度的出率再进行一次具体干员判定。这样的好处是不需要考虑太多,按照卡池规则走就好了(方舟的卡池出率描述比较清晰,隔壁某游戏只给出单抽出货概率,并且给出概率都是包含保底出率的)。坏处就是卡池更新难度大,每次更新需要重新往程序里塞干员,繁杂且易出错(后面会讲到一个比较轻松的导入干员的土办法),并且代码分支可能较多。
首先第一条规则的思路
卡池的基本出率:六星干员2%、五星干员8%、四星干员50%、三星干员40%。
- 每次获得的六星干员中,有70%的概率获得【纯烬艾雅法拉】、【琳琅诗怀雅】这两位干员中的一个。
- 剩余30%的其他六星干员中,【百炼嘉维尔】与【假日威龙陈】出现概率位其他单个六星干员的5倍。
每次获得的五星干员中,有50%的概率获得【青枳】干员。
基本出率很好实现,只需要用random模块的random.randint生成一个1到100的数,然后根据数的大小判定稀有度就可以了。
chance = random.randint(1,100)
if chance <= 2:
print("六星干员")
elif chance <= 10:
print("五星干员")
elif chance <= 60:
print("四星干员")
elif chance <= 100:
print("三星干员")
然后是是否获得up干员的判定,这个也简单,建立几个列表用来存储干员以及up干员,在进行稀有度判定之后再进行一次random.uniform(1,100)的判定,如果小于70就从六星up干员列表中random.choice一个出来就好了。
Star6_Operator_Rate_Up = ['纯烬艾雅法拉', '琳琅诗怀雅']
Star6_Operator = ['歪了']
Star5_Operator_Rate_Up = ['青枳']
Star5_Operator = ['歪了']
Star4_Operator = ['蓝天']
Star3_Operator = ['白云']
chance = random.uniform(1,100)
if chance <= 2:
print("六星干员:")
Up_check = random.randint(1,100)
if Up_check <= 70:
Result = random.choice(Star6_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star6_Operator)
print(Result)
elif chance <= 10:
print("五星干员:")
Up_check = random.randint(1,100)
if Up_check <= 50:
Result = random.choice(Star5_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star5_Operator)
print(Result)
elif chance <= 60:
print("四星干员:")
Result = random.choice(Star4_Operator)
print(Result)
elif chance <= 100:
print("三星干员:")
Result = random.choice(Star3_Operator)
print(Result)
最后是以往夏日限定的干员【百炼嘉维尔】和【假日威龙陈】,这个五倍权值也很好实现,只需要在普通的六星干员的列表里面赋值五个【百炼嘉维尔】和【假日威龙陈】就好了。这个会在后面的干员导入中一起实现。
然后是第二条规则,也就是抽卡手游基本都存在的保底机制(不同游戏的保底机制可能不一样)。
如果累计50抽都没有获得六星干员,那么从下一抽开始,获得六星干员的概率会随着抽数的增加而逐步增加+2%,获得六星干员后重置为2%。(例如第51抽出现六星干员的概率为4%,第52抽出现六星干员的概率为6%,以此类推)
实现的思路是增加一个表示没有获得六星干员的次数的参数No_Six_Count,初始为0,然后在获得三四五星干员的时候给这个参数+1,然后在获得六星干员的时候重置为0。在进行抽卡前先进行判定No_Six_Count是否小于50,是就走正常的抽卡流程,不是就走保底流程。
No_Six_Count = 0
chance = random.randint(1,100)
if No_Six_Count <= 50:
if chance <= 2:
print("六星干员:")
Up_check = random.randint(1,100)
if Up_check <= 70:
Result = random.choice(Star6_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star6_Operator)
print(Result)
No_Six_Count = 0
elif chance <= 10:
print("五星干员:")
Up_check = random.randint(1,100)
if Up_check <= 50:
Result = random.choice(Star5_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star5_Operator)
print(Result)
No_Six_Count += 1
elif chance <= 60:
print("四星干员:")
Result = random.choice(Star4_Operator)
print(Result)
No_Six_Count += 1
elif chance <= 100:
print("三星干员:")
Result = random.choice(Star3_Operator)
print(Result)
No_Six_Count += 1
else:
if chance <= No_Six_Count - 48:
print("六星干员:")
Up_check = random.randint(1,100)
if Up_check <= 70:
Result = random.choice(Star6_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star6_Operator)
print(Result)
No_Six_Count = 0
elif chance <= (148 - No_Six_Count)*2/23:
print("五星干员:")
Up_check = random.randint(1,100)
if Up_check <= 50:
Result = random.choice(Star5_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star5_Operator)
print(Result)
No_Six_Count += 1
elif chance <= (148 - No_Six_Count)*25/46:
print("四星干员:")
Result = random.choice(Star4_Operator)
print(Result)
No_Six_Count += 1
elif chance <= (148 - No_Six_Count)*10/23:
print("三星干员:")
Result = random.choice(Star3_Operator)
print(Result)
No_Six_Count += 1
注意这里的保底流程的概率判定,明日方舟并没有明说在保底流程中,六星干员获取概率的增加是从哪里扣除的。这里我就自己武断认为是每次六星增加概率,剩余的概率中五星、四星与三星的出率与原来保持一致。在非保底情况下不出六星的98%概率中,五星有8%,四星有50%,三星有40%,我假设在保底的流程中,在不出六星的96%、94%等情况下,五星四星三星总保持一个8:50:40的比例。
按照以上思路得出的判定条件如下:
六星干员的判定:No_Six_Count - 48
五星干员的判定:chance <= (148 - No_Six_Count)*2/23
四星干员的判定:chance <= (148 - No_Six_Count)*25/46
三星干员的判定:chance <= (148 - No_Six_Count)*10/23
这样我们的保底机制也就写好了,接下来是首次十连保底机制。
首次十连必定出现五星以上的干员(包括五星),仅限一次生效。
这个规则并没有说在这首次十连中,五星出现的概率是随着抽数越来越高还是前九次不是五星,第十次就必定是五六星。因此我(再一次)认定,前九次没有出现五六星,那么第十次必定出现五六星。其中五星与六星按照正常卡池中五六星的比例计算出率。也就是80%获得五星,20%获得六星。
Five_Stars_Least = 1
if draw_time == 10 and Five_Stars_Least == 1:
if chance <= 20:
print("六星干员:")
Up_check = random.randint(1,100)
if Up_check <= 70:
Result = random.choice(Star6_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star6_Operator)
print(Result)
No_Six_Count = 0
Five_Stars_Least = 0
else:
print("五星干员:")
Up_check = random.randint(1,100)
if Up_check <= 50:
Result = random.choice(Star5_Operator_Rate_Up)
print(Result)
else:
Result = random.choice(Star5_Operator)
print(Result)
No_Six_Count += 1
Five_Stars_Least =