forked from erudnick-cohen/Pokemon-Crystal-Item-Randomizer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PokemonRandomizer.py
199 lines (193 loc) · 6.61 KB
/
PokemonRandomizer.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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import csv
from collections import defaultdict
import random
import yaml
import copy
#returns a function to randomly generate pokemon
def generateRandomMonFun(stateDist,locations):
#first we loop through the set of various locations
#so that we know the min requirements for the important moves
moveDict = {}
moveDict['Strength'] = 1000
moveDict['Surf'] = 1000
moveDict['Whirlpool'] = 1000
moveDict['Waterfall'] = 1000
moveDict['Cut'] = 1000
moveDict['Flash'] = 1000
moveDict['Rock Smash'] = 1000
for i in stateDist:
for j in moveDict:
if(i in locations):
if j in locations[i].requirementsNeeded(defaultdict(lambda: False)):
moveDict[j] = min(moveDict[j],stateDist[j])
#next we load in the learnset database
monMove = defaultdict(lambda: [])
bstMap = {}
csvMap = {}
csvMap['Flash'] = 3
csvMap['Cut'] = 4
csvMap['Strength'] = 5
csvMap['Surf'] = 6
csvMap['Whirlpool'] = 7
csvMap['Waterfall'] = 8
csvMap['Rock Smash'] = 9
with open('pokedex.csv', newline='') as csvfile:
reader = csv.reader(csvfile)
for i in reader:
for j in moveDict:
if(i[csvMap[j]] == 'Yes'):
monMove[j].append(str(i[1].upper()))
bstMap[i[1].upper()] = int(i[2])
#create function for providing a random feasible pokemon
def monLookupFun(original,dist,range):
bst = bstMap[original]
monlist = list(bstMap.keys())
random.shuffle(monlist)
reqList = []
#build list of required moves for this distance and mon
for i in moveDict:
if dist<moveDict[i] and original in monMove[i]:
reqList.append(i)
ok = False
iter = 0
mon = "INVALID"
while not ok:
mon = monlist[iter]
ok = True
if abs(bstMap[mon]-bst) <= range:
for i in reqList:
if mon not in monMove[i]:
ok = False
else:
ok = False
iter = iter + 1
return mon
return monLookupFun
#returns a randomized dictionary of the trainer data, with a specified range for base stat variation
#the randomized entries are put in a new entry in the dict called newCode
#banMap is a dict mapping specific trainers that cannot have other trainers pokemon, primarily for early gym leaders and lance
def randomizeTrainers(locations, bstrange,monFun,rivalFix = False,banMap = defaultdict(lambda: [])):
#if the users specifies it, the rival will be homogenized
#across one of his three possibilities per encounter
#this prevents him from polluting the shuffle pool
skipList = []
tmapdict = {}
if(rivalFix):
rsets = []
rsets.append(['RIVAL1 7','RIVAL1 8','RIVAL1 9'])
rsets.append(['RIVAL1 10','RIVAL1 11','RIVAL1 12'])
rsets.append(['RIVAL1 13','RIVAL1 14','RIVAL1 15'])
rsets.append(['RIVAL2 1','RIVAL2 2','RIVAL2 3'])
for i in rsets:
random.shuffle(i)
tmapdict[i[1]] = i[0]
tmapdict[i[2]] = i[0]
skipList.append(i[1])
skipList.append(i[2])
else:
tmapfun = lambda x: x
#build list of reachable trainers
trainerList = []
for i in locations:
if locations[i].Trainers is not None:
for j in locations[i].Trainers:
trainerList.append(j)
bstMap = {}
#load in base stat information
with open('pokedex.csv', newline='') as csvfile:
reader = csv.reader(csvfile)
for i in reader:
bstMap[i[1].upper()] = int(i[2])
#load up the trainer data
yamlfile = open("TrainerData/Trainers.yaml")
yamltext = yamlfile.read()
trainerData = yaml.load(yamltext, Loader=yaml.FullLoader)
#for trainers who don't have moves, randomizing the trainer file is just randomizing pokemon
#for trainers who DO have moves, we SHUFFLE their pokemon with those of other trainers with moves
mList = []
for i in trainerData:
if(i in trainerList and i not in skipList):
if(trainerData[i]['Type'] == '1'):
for j in range(0,len(trainerData[i]["Pokemon"])):
mList.append((i,j,bstMap[trainerData[i]["Pokemon"][j]["Pokemon"]]))
else:
for q in range(0,len(trainerData[i]['Pokemon'])):
k = trainerData[i]['Pokemon'][q]
newcode = k['Code']
pokemon = monFun(k['Pokemon'])
level = k['Level']
newlevel = level
newcode = newcode.replace("db "+str(level)+", "+k['Pokemon'],"db "+str(newlevel)+", "+pokemon)
trainerData[i]['Pokemon'][q]['NewCode'] = newcode
#find a viable shuffle of the pokemon with moves
shuffleDict = {}
monList = copy.copy(mList)
random.shuffle(monList)
random.shuffle(mList)
stuckList = []
notStuck = []
for i in mList:
shuffleDict[i] = None
for j in monList:
if(abs(i[2]-j[2]) < bstrange and j[0] not in banMap[i[0]]):
shuffleDict[i] = j
monList.remove(j)
notStuck.append(j)
break
else:
stuckList.append(i)
#for some reason this is needed
for i in shuffleDict:
if shuffleDict[i] is None and i in notStuck:
notStuck.remove(i)
if i not in stuckList:
stuckList.append(i)
#perform feasible swaps with things in the stuck list to fix everything
while(len(stuckList)>0):
print(stuckList)
random.shuffle(notStuck)
for i in stuckList:
for j in notStuck:
print(j)
if(abs(j[2]-i[2]) < bstrange):
if(abs(shuffleDict[j][2]-i[2]) < bstrange and j[0] not in banMap[i[0]]):
#perform swap
print('swap')
print(i)
print(j)
old = shuffleDict[j]
shuffleDict[j] = i
shuffleDict[i] = old
notStuck.append(i)
stuckList.remove(i)
break
# else:
# #can't swap, so put the old thing into the list of things that are stuck
# old = shuffleDict[j]
# shuffleDict[j] = i
# stuckList.append(old)
# #notStuck.remove(old)
# stuckList.remove(i)
# notStuck.append(i)
# random.shuffle(notStuck)
# print('swap')
# print(i)
# print(j)
# break
#finally, rewrite code for each entry
for i in mList:
print(str(i) +' has '+ str(shuffleDict[i]))
basemon = trainerData[i[0]]["Pokemon"][i[1]]["Code"]
newMon = trainerData[shuffleDict[i][0]]["Pokemon"][shuffleDict[i][1]]["Code"]
#change level of new mon to match what the original was
newMon = newMon.replace("db "+str(trainerData[shuffleDict[i][0]]["Pokemon"][shuffleDict[i][1]]["Level"]), "db "+ str(trainerData[i[0]]["Pokemon"][i[1]]["Level"]))
trainerData[i[0]]["Pokemon"][i[1]]["NewCode"] = newMon
#if we have any remappped trainers like the rival, update their entries
for i in tmapdict:
for q in range(0,len(trainerData[i]['Pokemon'])):
trainerData[i]['Pokemon'][q]["Pokemon"] = trainerData[tmapdict[i]]['Pokemon'][q]["Pokemon"]
trainerData[i]['Pokemon'][q]["Level"] = trainerData[tmapdict[i]]['Pokemon'][q]["Level"]
trainerData[i]['Pokemon'][q]["Item"] = trainerData[tmapdict[i]]['Pokemon'][q]["Item"]
trainerData[i]['Pokemon'][q]["Moves"] = trainerData[tmapdict[i]]['Pokemon'][q]["Moves"]
trainerData[i]['Pokemon'][q]["NewCode"] = trainerData[tmapdict[i]]['Pokemon'][q]["NewCode"]
return trainerData