-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrando_bcc.py
157 lines (136 loc) · 5.68 KB
/
rando_bcc.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
#!/usr/bin/python
from megadata import *
from bccdata import Element
from distribution import getValWithVar, getPoissonRandom
import configparser
import random
from typing import Callable
def randomizeChips(data: bytearray, config: configparser.ConfigParser):
type = DataType.Chip
for variance, R in (
(config["ChipRange"], Library.standardChipRange()),
(config["NaviRange"], Library.naviChipRange()),
):
for i in R:
obj = type.parse(data, i)
weakerInd = 0
if config["ChipGlobal"]["preserveOrdering"]:
# Preserve the relative power of chips
weakerInd = Library.getWeakerChip(i + 1)
for key, _val in variance.items():
val = int(_val)
if val == 0:
# variance of 0, continue
continue
floorVal = (
getattr(type.parse(data, weakerInd - 1), key)
if weakerInd != 0
else 0
)
newVal = getValWithVar(getattr(obj, key), float(val), floorVal)
setattr(obj, key, newVal)
type.rewrite(data, i, obj)
if key == "ap" and newVal != 0:
# Update the descriptions to agree with the new values
# we have set
for desc in [DataType.EffectDesc, DataType.ChipDesc]:
ind = i + (1 if desc == DataType.ChipDesc else 0)
descObj = desc.parse(data, ind)
assert isinstance(descObj, StringT)
descObj.changeAttackPower(newVal)
desc.rewrite(data, ind, descObj)
def randomizeNames(data: bytearray, config: configparser.ConfigParser):
nameConf = config["Names"]
if not nameConf.getboolean("randomizeNames"):
return
nameFile = open(nameConf["chipNames"])
randoNames = [name.strip() for name in nameFile.readlines()]
type = DataType.ChipName
for i in Library.standardChipRange():
obj = type.parse(data, i)
assert isinstance(obj, StringT)
obj.assign(random.choice(randoNames))
type.rewrite(data, i, obj)
def isBoostable(booster: ChipT, boosted: ChipT) -> bool:
if boosted.ap == 0:
return False
elif booster.getElement() == Element.Normal:
return True
else:
return booster.getElement() == boosted.getElement()
def hasBadAtkBooster(chipMap, enc: EncounterT, j: int) -> bool:
"""
Returns True iff index j in this encounter contains a chp that enhances
a next attack which has no followup attack to run after it
"""
chipDetails = chipMap[enc.chips[j] - 1]
chipPlusRange = range(0, 5)
naviPlusRange = range(5, 10)
if chipDetails.isChipPlus() and not j in chipPlusRange:
return True
elif chipDetails.isNaviPlus() and not j in naviPlusRange:
return True
elif chipDetails.isChipPlus() and j in chipPlusRange:
colLen = 2 if j < 2 else 3
nextChips = (j + colLen, j + colLen + 1)
boostedChips = []
for idx in nextChips:
if enc.chips[idx] != 0:
boostedChips.append(chipMap[enc.chips[idx] - 1])
return not any(isBoostable(chipDetails, tgtChip) for tgtChip in boostedChips)
return False
def randomizeEncounters(data: bytearray, config: configparser.ConfigParser):
choices = config["Encounters"]
mbMap = Library.getMBMap(data)
chipMap = Library.getChipMap(data)
type = DataType.Encounter
shuffledEncs = list(range(type.getArrayLength()))
doAtkFilter = choices.getboolean("smartAtkPlus")
randomOp = choices.getboolean("randomizeOperators")
fillChips = choices.getboolean("fillChips")
randomizeNavi = choices.getboolean("randomizeNavi")
poissonParam = choices.getfloat("upgradeChipParam", 0)
if choices.getboolean("shuffle"):
random.shuffle(shuffledEncs)
writeEncs = []
def randomizeChipList(chipArr: List[int], rejectCB: Callable[[int], bool]):
for j, chip in enumerate(chipArr):
if chip == 0:
if not fillChips:
continue
sourceMb = 0
else:
sourceMb = chipMap[chip - 1].mb
sourceMb = max(10, sourceMb + 10 * getPoissonRandom(poissonParam))
origSouceMb = sourceMb
myMap: List[int] = []
while len(myMap) == 0 and sourceMb > 0:
if sourceMb in mbMap:
myMap = mbMap[sourceMb]
sourceMb -= 10
if len(myMap) == 0:
chipArr[j] = 0
else:
while True:
chipArr[j] = 1 + random.choice(myMap)
if not rejectCB(j):
break
if config["ChipGlobal"].getboolean("randomizeStartingChips", fallback=True):
startingChips = DataType.StartingChips.parse(data, 0)
assert isinstance(startingChips, StartingChipsT)
randomizeChipList(startingChips.chips, lambda x: False)
DataType.StartingChips.rewrite(data, 0, startingChips)
for i in range(type.getArrayLength()):
i = shuffledEncs[i]
enc = type.parse(data, i)
assert isinstance(enc, EncounterT)
if randomOp:
enc.op = random.randint(0, 125)
filterCB = lambda ind: doAtkFilter and hasBadAtkBooster(chipMap, enc, ind)
randomizeChipList(enc.chips, filterCB)
if randomizeNavi:
enc.navi = random.choice(list(Library.naviChipRange()))
if choices.getboolean("randomizeChips"):
writeEncs.append(enc)
for i, enc in enumerate(writeEncs):
type.rewrite(data, i, enc)