· 6 years ago · Dec 21, 2019, 11:52 PM
1from copy import copy
2import itertools
3import numpy as np
4
5"""
6
7- This script does NOT handle spawners (except for rupee clusters)
8- This script does NOT handle scarecrow memory leak
9
10- This script does not account for ISoT memory leak for solution options
11
12
13FOR DEKU PALACE, THIS DOES NOT ACCOUNT FOR SOME ROOMS BEING ABLE TO SPAWN SIGNS
14ALSO DOES NOT ACCOUNT FOR POTENTIALLY NEEDING TO BREAK A POT FOR THE SUPERSLIDE
15
16THIS SCRIPT DOES NOT ACCOUNT FOR SKULLTULA TOKENS OR SPAWNING GOLD SKULLTULAS BY
17SHOOTING OCEANSIDE SKULLKID PAINTINGS... IF IT SAYS YOU DEALLOCATE A GOLD SKULLTULA,
18THEN IT ASSUMES YOU PICKED UP THE TOKEN
19
20
21"""
22
23
24
25"""
26
27Note: Node size is 0x10 = 16 on English and 0x30 = 48 on JP
28
29"""
30
31version = 'English'
32
33if version == 'English':
34 node_size = 0x10
35elif version == 'JP':
36 nodesize = 0x30
37else:
38 print('Error: Invalid Version (choose "English" or "JP" )')
39
40
41
42class Actor:
43
44 """
45
46 name: name of the actor, some string
47
48 Id: Actor id, string of 4 integers
49
50 size: the size of an actor instance for this actor (number of bytes, in decimal)
51
52 category: the actor category (category 5 is treated differently than others)
53 For now, giving everything not category 5 a category of 0
54
55 overlay_type: determines where the AF loads in the heap
56
57 unloadable: a boolean for whether or not it is possible to deallocate this actor without changing rooms
58
59 address: the memory address of the actor in decimal (can convert to a hex string for output)
60 Note: The earliest address we handle is 0x40B150 = 4239696. All addresses must be multiples of 16
61
62 room_number: the number of the room these actors are associated with; if the actor is a transition (i..e Plane
63 or Door), then set room_numer = False
64
65
66 priority: an index to differentiate copies of the same instance
67
68 from_spawner: True or False (True if it is from a spawner, like rupees from a cluster; False otherwise)
69
70 transition: False is the actor is not a Loading Plane or a Door. Otherwise, it is a list of the rooms that the transition actor connects, ordered from least to greatest room number
71
72 clearable: True if it is possible to set a flag to make this actor not respawn upon reloading the room (though, unless it it Category 5, it will attempt to reload and then immediately deallocate), False otherwise
73
74 cleared: True if the flag was set to clear this actor, False otherwise
75
76 """
77
78 def __init__(self, name, Id, size, category, overlay_type, unloadable, address, room_number, priority, from_spawner, transition, clearable, cleared):
79 self.name = name
80 self.Id = Id
81 self.size = size
82 self.category = category
83 self.overlay_type = overlay_type
84 self.unloadable = unloadable
85 self.address = address
86 self.room_number = room_number
87 self.priority = priority
88 self.from_spawner = from_spawner
89 self.transition = transition
90 self.clearable = clearable
91 self.cleared = cleared
92
93class Room:
94
95 """
96
97 number: the room number (i.e. Room 0 has number 0)
98
99 priority_queue: this will be the list of actor instances of the room, in order
100
101 clock_exists: boolean for whether or not the clock is an actor in the queue
102
103 clock_priority: if clock_exists == False, then clock_priority will be a number
104 to determine where in the queue the clock should be loaded, for
105 example, if clock_priority is 2, then it means that the clock
106 should be the 3rd actor to appear in the queue (first index is 0)
107
108 """
109
110 def __init__(self, number, priority_queue, clock_exists, clock_priority):
111 self.number = number
112 self.priority_queue = priority_queue
113 self.clock_exists = clock_exists
114 self.clock_priority = clock_priority
115
116class Node:
117
118 """
119 address: which address in memory the node is at (as a base-10 integer for now)
120
121 size: nodes should be 16 bytes (english), so input 16
122
123 """
124
125 def __init__(self, address, size):
126 self.address = address
127 self.size = size
128
129class Overlay:
130
131 def __init__(self, address, Id, size):
132 self.address = address
133 self.Id = Id
134 self.size = size
135
136
137"""
138
139We define the Clock actor ahead of time as it is not necessarily present in each room
140
141"""
142
143
144Clock = Actor(name='Clock', Id='015A', size=340, category=0, overlay_type='A', unloadable=False, address=0, room_number=False, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
145
146###############################################################################
147
148Oceanside_Room3_queue = [
149 Actor(name='Loading Plane', Id='0018', size=332, category=0, overlay_type='B', unloadable=False, address=0, room_number=False, priority=0, from_spawner=False, transition=[3,4], clearable=False, cleared=False),
150 Actor(name='Wooden Door', Id='0005', size=0x1CC, category=0, overlay_type='B', unloadable=False, address=0, room_number=False, priority=0, from_spawner=False, transition=[2,3], clearable=False, cleared=False),
151 Actor(name='Stalchild (Oceanside Spider House)', Id='02A5', size=0x3EC, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
152 Actor(name='Stalchild (Oceanside Spider House)', Id='02A5', size=0x3EC, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
153 Actor(name='Stalchild (Oceanside Spider House)', Id='02A5', size=0x3EC, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=2, from_spawner=False, transition=False, clearable=False, cleared=False),
154 Actor(name='Stalchild (Oceanside Spider House)', Id='02A5', size=0x3EC, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=3, from_spawner=False, transition=False, clearable=False, cleared=False),
155 Actor(name='Pot', Id='0082', size=0x19C, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
156 Actor(name='Pot', Id='0082', size=0x19C, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
157 Actor(name='Oceanside Spider House Skull Kid Painting', Id='0210', size=0x244, category=0, overlay_type='A', unloadable=False, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
158 Actor(name='Oceanside Spider House Skull Kid Painting', Id='0210', size=0x244, category=0, overlay_type='A', unloadable=False, address=0, room_number=3, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
159 Actor(name='Oceanside Spider House Skull Kid Painting', Id='0210', size=0x244, category=0, overlay_type='A', unloadable=False, address=0, room_number=3, priority=2, from_spawner=False, transition=False, clearable=False, cleared=False),
160 Actor(name='Oceanside Spider House Skull Kid Painting', Id='0210', size=0x244, category=0, overlay_type='A', unloadable=False, address=0, room_number=3, priority=3, from_spawner=False, transition=False, clearable=False, cleared=False),
161 Actor(name='Gold Skulltula', Id='0050', size=0x4A4, category=5, overlay_type='A', unloadable=True, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=True, cleared=False),
162 Actor(name='Spiderweb', Id='0125', size=0x2FC, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=True, cleared=False),
163 Actor(name='Gold Skulltula', Id='0050', size=0x4A4, category=5, overlay_type='A', unloadable=True, address=0, room_number=3, priority=1, from_spawner=False, transition=False, clearable=True, cleared=False),
164 Actor(name='Bonk Actor (01E7)', Id='01E7', size=0x148, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
165 Actor(name='Gold Skulltula', Id='0050', size=0x4A4, category=5, overlay_type='A', unloadable=True, address=0, room_number=3, priority=2, from_spawner=False, transition=False, clearable=True, cleared=False),
166 Actor(name='Bonk Actor (01E7)', Id='01E7', size=0x148, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
167 Actor(name='Gold Skulltula', Id='0050', size=0x4A4, category=5, overlay_type='A', unloadable=True, address=0, room_number=3, priority=3, from_spawner=False, transition=False, clearable=True, cleared=False),
168 Actor(name='Bonk Actor (01E7)', Id='01E7', size=0x148, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=2, from_spawner=False, transition=False, clearable=False, cleared=False),
169 Actor(name='Tent-Shaped Spider Web', Id='01F4', size=0x3CC, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=True, cleared=False),
170 Actor(name='Oceanside Spider House Fireplace Grate', Id='020F', size=0x284, category=0, overlay_type='A', unloadable=False, address=0, room_number=3, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
171 Actor(name='Gold Skulltula', Id='0050', size=0x4A4, category=5, overlay_type='A', unloadable=True, address=0, room_number=3, priority=4, from_spawner=False, transition=False, clearable=True, cleared=False),
172 Actor(name='Bonk Actor (01E7)', Id='01E7', size=0x148, category=0, overlay_type='A', unloadable=True, address=0, room_number=3, priority=3, from_spawner=False, transition=False, clearable=False, cleared=False)
173 ]
174
175
176Oceanside_Room4_queue = [
177 Oceanside_Room3_queue[0],
178 Actor(name='Skulltula', Id='0024', size=0x550, category=5, overlay_type='A', unloadable=True, address=0, room_number=4, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
179 Actor(name='Chest', Id='0006', size=548, category=0, overlay_type='A', unloadable=False, address=0, room_number=4, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
180 ]
181
182
183
184
185
186###############################################################################
187
188Room0_queue = [
189 Actor(name='Wooden Door', Id='0005', size=460, category=0, overlay_type='B', unloadable=False, address=0, room_number=False, priority=0, from_spawner=False, transition=[0,3], clearable=False, cleared=False),
190 Actor(name='Loading Plane', Id='0018', size=332, category=0, overlay_type='B', unloadable=False, address=0, room_number=False, priority=0, from_spawner=False, transition=[0,1], clearable=False, cleared=False),
191 Actor(name='Rupee Cluster', Id='00E8', size=360, category=0, overlay_type='A', unloadable=True, address=0, room_number=0, priority=0, from_spawner=False, transition=False, clearable=True, cleared=False),
192 Actor(name='Dripping Water Effect', Id='0170', size=3644, category=0, overlay_type='A', unloadable=False, address=0, room_number=0, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
193 Actor(name='Dripping Water Effect', Id='0170', size=3644, category=0, overlay_type='A', unloadable=False, address=0, room_number=0, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
194 Actor(name='Torch Stand (Generic)', Id='0039', size=500, category=0, overlay_type='A', unloadable=False, address=0, room_number=0, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
195 Actor(name='Pot', Id='0082', size=412, category=0, overlay_type='A', unloadable=True, address=0, room_number=0, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
196 Actor(name='Pot', Id='0082', size=412, category=0, overlay_type='A', unloadable=True, address=0, room_number=0, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
197 Actor(name='Pot', Id='0082', size=412, category=0, overlay_type='A', unloadable=True, address=0, room_number=0, priority=2, from_spawner=False, transition=False, clearable=False, cleared=False),
198 Actor(name='???0158', Id='0158', size=328, category=0, overlay_type='A', unloadable=False, address=0, room_number=0, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
199 ]
200
201
202Room1_queue = [
203 Actor(name='Door Shutter', Id='001E', size=360, category=0, overlay_type='B', unloadable=False, address=0, room_number=False, priority=0, from_spawner=False, transition=[1,2], clearable=False, cleared=False),
204 Room0_queue[1],
205 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=0, from_spawner=False, transition=False, clearable=True, cleared=False),
206 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=1, from_spawner=False, transition=False, clearable=True, cleared=False),
207 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=2, from_spawner=False, transition=False, clearable=True, cleared=False),
208 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=3, from_spawner=False, transition=False, clearable=True, cleared=False),
209 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=4, from_spawner=False, transition=False, clearable=True, cleared=False),
210 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=5, from_spawner=False, transition=False, clearable=True, cleared=False),
211 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=6, from_spawner=False, transition=False, clearable=True, cleared=False),
212 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=7, from_spawner=False, transition=False, clearable=True, cleared=False),
213 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=8, from_spawner=False, transition=False, clearable=True, cleared=False),
214 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=9, from_spawner=False, transition=False, clearable=True, cleared=False),
215 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=10, from_spawner=False, transition=False, clearable=True, cleared=False),
216 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=11, from_spawner=False, transition=False, clearable=True, cleared=False),
217 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=12, from_spawner=False, transition=False, clearable=True, cleared=False),
218 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=13, from_spawner=False, transition=False, clearable=True, cleared=False),
219 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=14, from_spawner=False, transition=False, clearable=True, cleared=False),
220 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=15, from_spawner=False, transition=False, clearable=True, cleared=False),
221 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=16, from_spawner=False, transition=False, clearable=True, cleared=False),
222 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=17, from_spawner=False, transition=False, clearable=True, cleared=False),
223 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=18, from_spawner=False, transition=False, clearable=True, cleared=False),
224 Actor(name='Bad Bat', Id='015B', size=476, category=5, overlay_type='A', unloadable=True, address=0, room_number=1, priority=19, from_spawner=False, transition=False, clearable=True, cleared=False),
225 Actor(name='Torch Stand (Generic)', Id='0039', size=500, category=0, overlay_type='A', unloadable=False, address=0, room_number=1, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
226 Actor(name='Torch Stand (Generic)', Id='0039', size=500, category=0, overlay_type='A', unloadable=False, address=0, room_number=1, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
227 Actor(name='Torch Stand (Generic)', Id='0039', size=500, category=0, overlay_type='A', unloadable=False, address=0, room_number=1, priority=2, from_spawner=False, transition=False, clearable=False, cleared=False),
228 Actor(name='Pot', Id='0082', size=412, category=0, overlay_type='A', unloadable=True, address=0, room_number=1, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False),
229 Actor(name='Pot', Id='0082', size=412, category=0, overlay_type='A', unloadable=True, address=0, room_number=1, priority=1, from_spawner=False, transition=False, clearable=False, cleared=False),
230 Actor(name='Pot', Id='0082', size=412, category=0, overlay_type='A', unloadable=True, address=0, room_number=1, priority=2, from_spawner=False, transition=False, clearable=False, cleared=False),
231 Actor(name='Chest', Id='0006', size=548, category=0, overlay_type='A', unloadable=False, address=0, room_number=1, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
232 ]
233
234###############################################################################
235
236Room0 = Room(0, Room0_queue, False, 2)
237Room1 = Room(1, Room1_queue, False, 2)
238
239
240Oceanside_Room3 = Room(3, Oceanside_Room3_queue, False, 2)
241Oceanside_Room4 = Room(4, Oceanside_Room4_queue, False, 1)
242
243"""
244
245Define the list of Rooms that we consider
246
247"""
248
249Room_List = [Room0, Room1]
250
251Oceanside_Room_List = [Oceanside_Room3, Oceanside_Room4]
252
253
254"""
255
256In Overlay_dict we collect all of the Overlays of Type A, where the keys are
257the corresponding actor ids
258
259"""
260
261# NOTE: This must be named "Overlay_dict" because it is hardcoded in some functions, like the Deallocate() function
262Overlay_dict = {
263 '015A' : Overlay(address=0, Id='015A', size=6000),
264 '00E8' : Overlay(address=0, Id='00E8', size=1984),
265 '0170' : Overlay(address=0, Id='0170', size=10688),
266 '0039' : Overlay(address=0, Id='0039', size=3552),
267 '0082' : Overlay(address=0, Id='0082', size=9040),
268 '0158' : Overlay(address=0, Id='0158', size=1104),
269 '015B' : Overlay(address=0, Id='015B', size=6048),
270 '0006' : Overlay(address=0, Id='0006', size=8640),
271 '0017' : Overlay(address=0, Id='0017', size=10432),
272 '017B' : Overlay(address=0, Id='017B', size=14320),
273 '007B' : Overlay(address=0, Id='007B', size=5104),
274 '00A2' : Overlay(address=0, Id='00A2', size=24448),
275 '02A5' : Overlay(address=0, Id='02A5', size=0x2660),
276 '0210' : Overlay(address=0, Id='0210', size=0xB90),
277 '0050' : Overlay(address=0, Id='0050', size=0x3540),
278 '0125' : Overlay(address=0, Id='0125', size=0x1490),
279 '01E7' : Overlay(address=0, Id='01E7', size=0x450),
280 '01F4' : Overlay(address=0, Id='01F4', size=0x1A80),
281 '020F' : Overlay(address=0, Id='020F', size=0x780),
282 '0024' : Overlay(address=0, Id='0024', size=0x28E0)
283 }
284
285"""
286
287Here we collect a list of the actors that we allow ourselves to spawn
288
289Notes:
290 'Zora Fins' means 2 fins
291 'Bugs' means a set of 3 bugs
292
293
294"""
295
296Allocation_List = [
297 'Nothing',
298 'Bomb',
299 'Smoke',
300 'Arrow',
301 'Hookshot',
302 'Charged Spin Attack',
303 'Chu',
304 'Zora Fins',
305 'Fish',
306 'Bugs'
307 ]
308
309######
310
311
312"""
313
314NOTE: We NEED to have 'Hookshot' and 'Charged Spin Attack' as the last two options
315in order to consider all cases
316
317Don't have 'Bomb' before 'Smoke' to ensure that the Smoke always gets allocated first
318
319maybe in the future you could jumble/randomize the order of things in this list at each step
320of the solver
321
322"""
323Hardcoded_Allocation_List = [
324 'Smoke',
325 'Smoke',
326 'Smoke',
327 'Chu',
328 'Chu',
329 'Chu',
330 'Arrow',
331 'Arrow',
332 'Arrow',
333 'Arrow',
334 'Arrow',
335 'Bomb',
336 'Bomb',
337 'Bomb',
338 'Zora Fins',
339 'Fish',
340 'Fish',
341 'Bugs',
342 'Bugs',
343 'Hookshot',
344 'Charged Spin Attack'
345 ]
346
347"""
348
349Here we collect a list of the Ids grabbable actors that we can use for superslide SRM
350So far this includes:
351
352 0082: Pot
353
354"""
355
356Grabbable_Actors = ['0082']
357
358
359"""
360
361Here we collect a list of Actor Ids for spawners. So far this includes:
362
363 00E8: Rupee Cluster
364
365"""
366
367Spawner_Ids = ['00E8']
368
369
370"""
371
372We initialize the Heap as a list, putting a node with address 0x40B140 in the 0th entry
373and we place a dummy node at the end of the Heap so that there will always exist two
374consecutive nodes for us to define a condition for which free space in the Heap exists
375
376Keep in mind that the 0x5FFFFF address in the dummy node will not reflect the actual
377address of the corresponding node in-game, but it also isn't relevant to heap manipulation
378since it is so far down
379
380"""
381
382
383Heap = [Node(0x40B140, node_size), Node(0x5FFFFF, node_size)]
384
385
386
387def Overlay_In_Heap(Heap, overlay):
388
389 """
390
391 Overlay is the overlay that we want to check whether or not it is in the Heap
392
393 This function will return True if Overlay is in the Heap and False otherwise
394
395 """
396
397 overlay_in_heap = False
398
399 for entry in Heap:
400
401 if type(entry) == Overlay and entry.Id == overlay.Id:
402
403 overlay_in_heap = True
404
405 return overlay_in_heap
406
407
408def Actor_Id_In_Heap(Heap, actor_id):
409
410 """
411
412 actor_id is the Id that we want to check for
413
414 This function will return True if there exists an Actor in the Heap that
415 has actor_id as its Id and it will return False otherwise
416
417 """
418
419 actor_id_in_heap = False
420
421 for entry in Heap:
422
423 if type(entry) == Actor and entry.Id == actor_id:
424
425 actor_id_in_heap = True
426
427 return actor_id_in_heap
428
429
430def Find_Gaps(Heap):
431
432 """
433
434 This function will find all consecutive nodes and output a list of 4-tuples
435 where the first two entries correspond to the indices of each node in the list
436 and the last two entries correspond to the addresses of each node
437
438 The list should be in order, from the start of the Heap to the end of the Heap
439
440 """
441
442 consecutive_node_count = 0
443
444 node_1_address = 0
445 node_2_address = 0
446 node_1_index = 0
447 node_2_index = 0
448
449 consecutive_node_list = []
450 for entry in Heap:
451 if type(entry) == Node and consecutive_node_count == 0:
452 node_1_address = entry.address
453 node_1_index = Heap.index(entry)
454 consecutive_node_count += 1
455 elif type(entry) == Node and consecutive_node_count == 1:
456 node_2_address = entry.address
457 node_2_index = Heap.index(entry)
458
459 consecutive_node_list.append((node_1_index, node_2_index, node_1_address, node_2_address))
460
461 consecutive_node_count += 1
462 elif type(entry) != Node:
463 consecutive_node_count = 0
464 elif type(entry) == Node and consecutive_node_count > 1:
465 consecutive_node_count += 1
466 print("ERROR: More than 2 consecutive nodes!! (Find_Gaps() Error Message)")
467
468
469 return consecutive_node_list
470
471
472
473
474def Allocate(Heap, actor, Overlay_Dict):
475
476 """
477
478 actor is the actor that we want to allocate into the Heap
479
480 Overlay_Dict is a dictionary where the keys are the actor ids which point to the corresponding Overlays
481
482 This function will account for placing nodes and overlays
483
484 """
485
486
487 #Overlay = Overlay_Dict[actor.Id]
488
489 #Overlay_Allocated = False
490
491 #if Overlay_In_Heap(Heap, Overlay) == True:
492 # Overlay_Allocated = True
493
494 Actor_Allocated = False
495
496 """
497 ##### Not yet defined, not sure if I will bother; not really necessary. Probably should for debugging
498 if Actor_In_Heap == True:
499 print('Error: This Actor is already allocated!! (Error message from Allocate() function)')
500 """
501
502 gap_list = Find_Gaps(Heap)
503
504 # Because we initialize the Heap with 2 nodes, there should always be at least one gap
505 if len(gap_list) < 1:
506 print('ERROR: len(gap_list) < 1 in Allocate() function')
507
508
509 # If the Overlay is type A and the Overlay is not already in the Heap, then we want to allocate the overlay first
510 if actor.overlay_type == 'A':
511
512 ##### We only define Overlay for Type A overlays because Overlay_Dict only has Type A overlays
513 Overlay = Overlay_Dict[actor.Id]
514 Overlay_Allocated = False
515
516 if Overlay_In_Heap(Heap, Overlay) == True:
517 Overlay_Allocated = True
518
519
520 if Overlay_In_Heap(Heap, Overlay) == False:
521
522 for gap in gap_list:
523
524 if Overlay_Allocated == True:
525 break ##### This ensures we don't add in the same Overlay multiple times
526
527 node_2_index = gap[1]
528 node_1_address = gap[2]
529 node_2_address = gap[3]
530
531 gap_size = node_2_address - node_1_address - node_size
532
533 ##### Case 1: the Overlay can fit, but there is NOT enough space for an extra node
534 # Note that gap_size is always a multiple of 16
535
536 if Overlay.size <= gap_size and Overlay.size > gap_size - 2*node_size:
537
538 Overlay.address = node_1_address + node_size
539 Heap.insert(node_2_index, Overlay)
540 Overlay_Allocated = True
541
542
543 ##### Case 2: the Overlay can fit and a new node can also fit
544
545 elif Overlay.size <= gap_size and Overlay.size <= gap_size - 2*node_size:
546
547 Overlay.address = node_1_address + node_size
548 Heap.insert(node_2_index, Overlay)
549
550 ########### ADD IN THE NODE HERE
551 if Overlay.size%16 > 0:
552 Heap.insert(node_2_index + 1, Node(address=Overlay.address + Overlay.size + (16 - Overlay.size%16), size=node_size))
553 elif Overlay.size%16 == 0:
554 Heap.insert(node_2_index + 1, Node(address=Overlay.address + Overlay.size, size=node_size))
555
556 Overlay_Allocated = True
557
558 ############ Now the overlay (if applicable) has been allocated. Now we need to allocate the actor.
559
560 ##### We need to update the gaps_list to account for the overlay being allocated in the Heap already
561 gap_list = Find_Gaps(Heap)
562
563 for gap in gap_list:
564
565 if Actor_Allocated == True:
566 break ##### This ensures we don't add in the same Actor multiple times
567
568 node_2_index = gap[1]
569 node_1_address = gap[2]
570 node_2_address = gap[3]
571
572 gap_size = node_2_address - node_1_address - node_size
573
574 ##### Case 1: the Actor can fit, but there is NOT enough space for an extra node
575 # Note that gap_size is always a multiple of 16
576
577 if actor.size <= gap_size and actor.size > gap_size - 2*node_size:
578
579 actor.address = node_1_address + node_size
580 Heap.insert(node_2_index, actor)
581 Actor_Allocated = True
582
583
584 ##### Case 2: the Actor can fit and a new node can also fit
585
586 elif actor.size <= gap_size and actor.size <= gap_size - 2*node_size:
587
588 actor.address = node_1_address + node_size
589 Heap.insert(node_2_index, actor)
590
591 ########### ADD IN THE NODE HERE
592 if actor.size%16 > 0:
593 Heap.insert(node_2_index + 1, Node(address=actor.address + actor.size + (16 - actor.size%16), size=node_size))
594 elif actor.size%16 == 0:
595 Heap.insert(node_2_index + 1, Node(address=actor.address + actor.size, size=node_size))
596
597 Actor_Allocated = True
598
599def Borders_Node(Heap, entry):
600
601 """
602
603 This function takes an entry of the Heap as input and determines whether or
604 not this entry is adjacent to a node in the heap (the purpose of this is to
605 check if a node is bordering another node since actors and overlays should
606 be bordering two nodes under every circumstance)
607
608 Returns True if the entry is bordering a node, returns False otherwise
609
610 """
611
612 borders_node = False
613
614 entry_index = Heap.index(entry)
615
616 border_1_is_node = False
617 border_2_is_node = False
618
619 if entry_index != 0:
620 border_1 = Heap[entry_index - 1]
621 if type(border_1) == Node:
622 border_1_is_node = True
623
624 if entry_index != len(Heap) - 1:
625 border_2 = Heap[entry_index + 1]
626 if type(border_2) == Node:
627 border_2_is_node = True
628
629 if border_1_is_node == True or border_2_is_node == True:
630 borders_node = True
631
632 return borders_node
633
634
635
636def Deallocate(Heap, actor, Overlay_dict):
637
638
639 """
640
641 actor is the actor that we want to be deallocated from the Heap
642
643 This function will account for removing nodes and overlays
644
645 ##### Remove the actor AND node if applicable
646 ##### Check if any actors with the same Id are still in the Heap
647 ##### if not (and the actor has overlay Type A), then remove the overlay
648
649 We only remove a node if it is part of a gap before deallocating the actor
650 That is, we only remove a node if it borders another node before the actor is deallocated
651
652 """
653
654 if type(actor) != Actor:
655 print("ERROR: Attempted to deallocate something other than an Actor (Deallocate() function error message)")
656
657 # The index of where the actor is in the Heap before being deallocated; this will change after we remove the first node
658 actor_index = Heap.index(actor)
659
660 ##### First check the node above the actor in the Heap
661 node_1 = Heap[actor_index - 1]
662 if type(node_1) != Node:
663 print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
664
665 if Borders_Node(Heap, node_1) == True:
666 Heap.remove(node_1)
667
668 ########## Now the first node has been removed and the indices of the Heap shift
669
670 ##### Now we check the node below the actor in the Heap
671
672 # The index of where the actor is in the Heap before being deallocated; this will change after we remove the first node
673 actor_index = Heap.index(actor)
674
675 node_2 = Heap[actor_index + 1]
676 if type(node_2) != Node:
677 print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
678
679 if Borders_Node(Heap, node_2) == True:
680 Heap.remove(node_2)
681
682 ###########################################################################
683 ##### Now we have removed both of the nodes, if applicable and we must remove the actor itself
684
685 Heap.remove(actor)
686
687 """
688
689 Now if the actor has a Type A overlay, then we must check if the Heap contains
690 any other actors that have the same Id as actor and if not, then we must also
691 remove its overlay from the Heap
692
693 We must also account for removing the nodes around the overlay, if applicable
694
695 """
696
697 if actor.overlay_type == 'A' and Actor_Id_In_Heap(Heap, actor.Id) == False:
698
699 ##### First check the node above the overlay
700 overlay_index = Heap.index(Overlay_dict[actor.Id])
701 node1 = Heap[overlay_index - 1]
702
703 if type(node1) != Node:
704 print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
705
706 if Borders_Node(Heap, node1) == True:
707 Heap.remove(node1)
708
709
710 ##### Now we check the node below the overlay
711 overlay_index = Heap.index(Overlay_dict[actor.Id])
712 node2 = Heap[overlay_index + 1]
713
714 if type(node2) != Node:
715 print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
716
717 if Borders_Node(Heap, node2) == True:
718 Heap.remove(node2)
719
720 ###########################################################################
721 ##### Now we have removed both of the nodes, if applicable and we must remove the overlay itself
722
723 Heap.remove(Overlay_dict[actor.Id])
724
725
726
727def Load_Scene(Heap, room, Overlay_dict):
728
729 if len(Heap) != 2:
730 print("ERROR: Attempted to use Load_Scene() with an inappropriate Heap")
731
732 entry_count = 0
733 for entry in room.priority_queue:
734
735 ##### If the clock is not in the room's set of actors, then we must allocate the clock at the appropriate time when we load the scene
736 if entry_count == room.clock_priority and room.clock_exists == False:
737
738 ##### Allocate the 3-Day Clock actor
739 Allocate(Heap, Clock, Overlay_dict)
740 entry_count += 1
741
742 ##### Allocate the entry in the room's priority queue
743 Allocate(Heap, entry, Overlay_dict)
744
745 entry_count += 1
746
747 ##### Now that all of the actors have been allocated, we want to add in all of the actors that the spawners spawn
748
749 """
750
751 NOTE: THIS DOES NOT HANDLE SPAWNERS OTHER THAN RUPEE CLUSTERS AT THE MOMENT
752
753 In the future, it will need to be considered how the actors created by spawners
754 prioritize over each other... Spring MV is maybe the only place where this really matters
755
756 """
757
758 ##### Check for Rupee Cluster
759 if Overlay_In_Heap(Heap, Overlay_dict['00E8']) == True:
760
761 for j in range(7):
762 rupee = Actor(name='Collectible (Rupee from Rupee Cluster)', Id='000E', size=424, category=0, overlay_type='B', unloadable=True, address=0, room_number=room.number, priority=j, from_spawner=True, transition=False, clearable=True, cleared=False)
763
764 Allocate(Heap, rupee, Overlay_dict)
765
766
767
768def Actor_From_Room_In_Heap(Heap, Room_Number):
769
770 """
771
772 This function takes the Heap and the number of the Room in question as input
773 It returns True if there exists an Actor in the Heap with the inputted Room_Number and False otherwise
774
775 """
776
777 actor_from_room_in_heap = False
778
779 for entry in Heap:
780
781 if type(entry) == Actor and entry.room_number is Room_Number:
782
783 actor_from_room_in_heap = True
784
785 return actor_from_room_in_heap
786
787def Cleared_Actor_In_Heap(Heap):
788
789 """
790
791 This function returns True if there is a cleared actor in the Heap and False otherwise
792
793 """
794
795 cleared_actor_in_heap = False
796
797 for entry in Heap:
798
799 if type(entry) == Actor and entry.cleared == True:
800
801 cleared_actor_in_heap = True
802
803 return cleared_actor_in_heap
804
805
806def Shared_Transition_Count(Heap, Room_Number_1, Room_Number_2):
807
808 """
809
810 This function returns the number of transitions (Planes/Doors) that are shared between
811 the two rooms with room numbers Room_Number_1 and Room_Number_2
812
813 """
814
815 shared_transition_count = 0
816
817 for entry in Heap:
818
819 if type(entry) == Actor and entry.transition != False:
820
821 if (entry.transition[0] == Room_Number_1 and entry.transition[1] == Room_Number_2) or (entry.transition[0] == Room_Number_2 and entry.transition[1] == Room_Number_1):
822
823 shared_transition_count += 1
824
825 return shared_transition_count
826
827def Is_Shared_Transition(actor, Room_Number_1, Room_Number_2):
828
829 """
830
831 If actor is a transition shared between Rooms with numbers Room_Number_1 and Room_Number_2,
832 then this function returns True. Otherwise it returns False
833
834 """
835
836 is_shared_transition = False
837
838 if type(actor) == Actor and actor.transition != False:
839
840 if (actor.transition[0] == Room_Number_1 and actor.transition[1] == Room_Number_2) or (actor.transition[0] == Room_Number_2 and actor.transition[1] == Room_Number_1):
841
842 is_shared_transition = True
843
844 return is_shared_transition
845
846
847def Transition_Is_In_Room(actor, Room_Number):
848
849 transition_is_in_room = False
850
851 if type(actor) == Actor and actor.transition != False:
852
853 if actor.transition[0] == Room_Number or actor.transition[1] == Room_Number:
854
855 transition_is_in_room = True
856
857 return transition_is_in_room
858
859
860def Find_Clock_List(Heap):
861
862 """
863
864 This function finds all clock actor instances in the Heap and returns a list of them, in order
865
866 """
867
868 clock_list = []
869
870 for entry in Heap:
871
872 if type(entry) == Actor and entry.Id == '015A':
873
874 clock_list.append(entry)
875
876 return clock_list
877
878
879def Load_Room(Heap, room, transition, Overlay_dict):
880
881
882 """
883
884 This function updates the Heap after you enter room through transition
885 For example, you might enter Room0 through Plane1 or Door3
886
887 Before executing the script, should probably define Plane1, Plane2, ...
888 Door1, Door2, ..., etc. as the corresponding entries from the room queues.
889 This will make the code more readable when looking for solutions
890
891
892 * First we load all of the actors from the new room
893 * Next, we deallocate everything (well, not literally everything...) from the previous room
894
895
896 Things that this function needs to handle:
897
898 - make sure that you check if each actor was cleared or not (if clearable == True, otherwise it isn't applicable)
899 and then check if it is Category 5 to determine if it loads and immediately deallocates or not
900
901 - checking which clock to deallocate (i.e. deallocate the one that comes later
902 on in the Heap if there are more than one). Maybe define a Find_Clocks function
903
904 - make sure transition never deallocates and never attempts to allocate
905
906 - make sure that the other Transitions unload and then reload (if applicable) after all of
907 the stuff from the previous room deallocated
908
909 - when deallocating stuff from the room that isn't the room you're entering, be sure
910 not to deallocate the clock. Also be careful of relevant Transitions as they don't have
911 actual room numbers (replaced with False)
912
913 - allocate stuff from spawners after the fact (even after planes)
914
915
916 """
917
918 if transition not in Heap:
919 print('2222222222')
920
921 if transition not in room.priority_queue:
922 print('44444444')
923
924 if (transition not in Heap) or (transition not in room.priority_queue):
925 print("ERROR: Attempted to use Load_Room() with an invalid transition")
926
927 current_room_number = -1
928 new_room_number = room.number
929
930 if transition.transition[0] == room.number:
931 current_room_number = transition.transition[1]
932 elif transition.transition[1] == room.number:
933 current_room_number = transition.transition[0]
934 else:
935 print("ERROR: Error with transition list (Load_Room() error message)")
936
937 """
938 First we load all of the actors from the new room, EXCEPT for: the plane/door
939 we pass through AND any other shared transitions AND any actors with both
940 cleared == True and Category == 5 (these ones never attempt to load)
941 """
942
943 for actor in room.priority_queue:
944
945 ### If the actor is not a Transition OR if the actor is a transition but doesn't connect to the current room
946 if (actor.transition == False) or (actor.transition != False and actor.transition[0] != current_room_number and actor.transition[1] != current_room_number):
947
948 ### If the actor is Category 5, then only attempt to load it if it has not been cleared
949 if actor.category != 5 or actor.cleared == False:
950
951 Allocate(Heap, actor, Overlay_dict)
952
953 """
954 - Now all of the relevant actors from the new room have been allocated
955 - Now we need to immediately deallocate any actors with Clearable == True and Cleared == True
956 - We also need to deallocate any transitions which are shared between the current room and the new room
957 EXCEPT for transition itself (the transition that we passed through to get to the new room)
958 - We also need to deallocate the second clock actor in the Heap if it exists (do this after everything else for simplicity)
959
960 Note that "current_room_number" is the room number of the room we were in before loading the new room
961 """
962
963 while Actor_From_Room_In_Heap(Heap, current_room_number) == True or Cleared_Actor_In_Heap(Heap) == True or Shared_Transition_Count(Heap, current_room_number, new_room_number) > 1:
964
965 for entry in Heap:
966
967 if (type(entry) == Actor) and (entry.room_number is current_room_number or entry.cleared == True or Is_Shared_Transition(entry, current_room_number, new_room_number) == True or (entry.transition != False and Transition_Is_In_Room(entry, new_room_number) == False ) ) and (entry != transition):
968
969 Deallocate(Heap, entry, Overlay_dict)
970
971 ########## Now we will find all of the clocks and deallocate the second clock if it exists (and report error if more than two clocks)
972
973 Clock_List = Find_Clock_List(Heap)
974
975 if len(Clock_List) > 2:
976 print("ERROR: More than 2 Clocks in the Actor Heap (Load_Room() Error Message)")
977 elif len(Clock_List) < 1:
978 print("ERROR: No Clock Actor Instance in the Actor Heap (Load_Room() Error Message)")
979
980 ##### If there are two clocks, then we deallocate the second clock that appears in the Heap
981 if len(Clock_List) > 1:
982
983 Deallocate(Heap, Clock_List[1], Overlay_dict)
984
985
986 ##### Now we allocate any shared transitions EXCEPT for transition itself (the door/plane we entered to get into this room)
987
988 for entry in room.priority_queue:
989
990 # If entry is a shared transition and is NOT the transition that we passed through
991 if (type(entry) == Actor) and (entry.transition != False) and Is_Shared_Transition(entry, current_room_number, new_room_number) == True and (entry != transition):
992
993 Allocate(Heap, entry, Overlay_dict)
994
995 ###################################### Now we only have to account for allocating things from spawners
996
997
998 """
999
1000 NOTE: THIS DOES NOT HANDLE SPAWNERS OTHER THAN RUPEE CLUSTERS AT THE MOMENT
1001
1002 In the future, it will need to be considered how the actors created by spawners
1003 prioritize over each other... Spring MV is maybe the only place where this really matters
1004
1005 """
1006
1007 ##### Check for Rupee Cluster
1008 if Overlay_In_Heap(Heap, Overlay_dict['00E8']) == True:
1009
1010 for j in range(7):
1011 rupee = Actor(name='Collectible (Rupee from Rupee Cluster)', Id='000E', size=424, category=0, overlay_type='B', unloadable=True, address=0, room_number=room.number, priority=j, from_spawner=True, transition=False, clearable=True, cleared=False)
1012
1013 Allocate(Heap, rupee, Overlay_dict)
1014
1015
1016
1017
1018
1019def Display_Heap(Heap):
1020
1021 for entry in Heap:
1022
1023 if type(entry) == Node:
1024
1025 print(hex(entry.address) + '-----' + 'NODE-----------------')
1026
1027 elif type(entry) == Overlay:
1028
1029 print(hex(entry.address) + ' ' + entry.Id + ' ' + 'OVERLAY')
1030
1031 elif type(entry) == Actor:
1032
1033 print(hex(entry.address) + ' ' + entry.Id + ' ' + 'INSTANCE')
1034
1035 else:
1036 print("ERROR!!! Unexpected Entry Type in Heap!!!!!!!!!")
1037
1038
1039###############################################################################
1040###############################################################################
1041###############################################################################
1042###############################################################################
1043###############################################################################
1044###############################################################################
1045
1046def Allocate_Fish(Heap, Room_Number, Overlay_dict):
1047
1048 Fish = Actor(name='Fish', Id='0017', size=636, category=0, overlay_type='A', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1049
1050 Allocate(Heap, Fish, Overlay_dict)
1051
1052
1053def Allocate_Bugs(Heap, Room_Number, Overlay_dict):
1054
1055 """
1056
1057 This function allocates a set of 3 bugs to the Heap
1058
1059 """
1060
1061 for i in range(3):
1062 Bug = Actor(name='Bug', Id='017B', size=884, category=0, overlay_type='A', unloadable=True, address=0, room_number=Room_Number, priority=i, from_spawner=False, transition=False, clearable=False, cleared=False)
1063
1064 Allocate(Heap, Bug, Overlay_dict)
1065
1066
1067def Allocate_Bomb(Heap, Room_Number, Overlay_dict):
1068
1069 Bomb = Actor(name='Bomb', Id='0009', size=516, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1070
1071 Allocate(Heap, Bomb, Overlay_dict)
1072
1073
1074def Allocate_Smoke(Heap, Room_Number, Overlay_dict):
1075
1076 """
1077
1078 This function allocates a bomb, then allocates smoke (this happens when the bomb explodes)
1079 and then deallocates the bomb (we bothered allocating the bomb to ensure that the smoke
1080 appears in the right spot in the Heap)
1081
1082 Note that we should never allow ourselves to allocate smoke AFTER calling Allocate_Bomb()
1083 because in reality the first bomb would explode first (this isn't strictly true, but we should
1084 do it this way at least in the simple script)
1085
1086 """
1087
1088 Bomb = Actor(name='Bomb', Id='0009', size=516, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1089
1090 Allocate(Heap, Bomb, Overlay_dict)
1091
1092 Smoke = Actor(name='Smoke', Id='00A2', size=11908, category=0, overlay_type='A', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1093
1094 Allocate(Heap, Smoke, Overlay_dict)
1095
1096 Deallocate(Heap, Bomb, Overlay_dict)
1097
1098def Allocate_Arrow(Heap, Room_Number, Overlay_dict):
1099
1100 """
1101
1102 This function allocates an arrow into the heap. Note that Deku Bubbles are
1103 the same actor as arrows (in that they're both 000F)
1104
1105 """
1106
1107 Arrow = Actor(name='Arrow', Id='000F', size=632, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1108
1109 Allocate(Heap, Arrow, Overlay_dict)
1110
1111
1112def Allocate_Hookshot(Heap, Room_Number, Overlay_dict):
1113
1114 Hookshot = Actor(name='Hookshot', Id='003D', size=528, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1115
1116 Allocate(Heap, Hookshot, Overlay_dict)
1117
1118
1119def Allocate_Chu(Heap, Room_Number, Overlay_dict):
1120
1121 Chu = Actor(name='Chu', Id='006A', size=480, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1122
1123 Allocate(Heap, Chu, Overlay_dict)
1124
1125
1126def Allocate_Zora_Fins(Heap, Room_Number, Overlay_dict):
1127
1128 """
1129
1130 This function allocates 2 Zora Fin actor instances
1131
1132 """
1133
1134 for i in range(2):
1135
1136 Zora_Fin = Actor(name='Zora Fin', Id='0020', size=500, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1137
1138 Allocate(Heap, Zora_Fin, Overlay_dict)
1139
1140
1141def Allocate_Charged_Spin_Attack(Heap, Room_Number, Overlay_dict):
1142
1143 """
1144
1145 This functions allocates the Spin Attack & Sword Beam Effects and then the
1146 Spin Attack Charge Particles (This is the order they get allocated in when
1147 you charge a spin attack)
1148
1149 """
1150
1151 Spin_Attack_and_Sword_Beam_Effects = Actor(name='Spin Attack & Sword Beam Effects', Id='0035', size=452, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1152
1153 Allocate(Heap, Spin_Attack_and_Sword_Beam_Effects, Overlay_dict)
1154
1155 Spin_Attack_Charge_Particles = Actor(name='Spin Attack Charge Particles', Id='007B', size=1367, category=0, overlay_type='A', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
1156
1157 Allocate(Heap, Spin_Attack_Charge_Particles, Overlay_dict)
1158
1159
1160
1161"""
1162
1163Before proceeding, we should define all of the transitions we plan on passing through
1164
1165Since "Beneath the Graveyard" is relatively simple and I currently only want to consider
1166passing through a single plane, I will just define Plane_1 to be the plane shared between
1167Room0 and Room1
1168
1169This loading plane happens the be the second element in Room0_queue, so I will define it based on that
1170
1171"""
1172
1173Plane_1 = Room0_queue[1]
1174
1175
1176Transition_List= [Plane_1]
1177
1178
1179"""
1180
1181 Grabbable_dict is a dictionary of the grabbable actors (such as pots) that
1182 we want to attempt to use for superslide SRM where the keys are the grabbable
1183 actors and the values are lists with 3-bit strings where each bit means:
1184
1185 100 : Possible to enter Plane with both Bomb and Smoke loaded
1186 010 : Possible to enter Plane with Smoke loaded, but no Bomb loaded
1187 001 : Possible to enter Plane with no Smoke loaded
1188
1189 and Transitions, where the transitions are the ones you can superslide through
1190
1191
1192
1193"""
1194
1195Grabbable_dict = {
1196 Room0_queue[6] : ['100', Plane_1],
1197 Room0_queue[7] : ['100', Plane_1],
1198 Room1_queue[25] : ['110', Plane_1],
1199 Room1_queue[26] : ['100', Plane_1],
1200 Room1_queue[27] : ['011', Plane_1]
1201 }
1202
1203
1204"""
1205
1206Below this we can consider a sequence of Room loads and then display the Heap
1207
1208"""
1209
1210
1211#Load_Scene(Heap, Room0)
1212
1213
1214#Load_Room(Heap, Room1, Plane_1, Overlay_dict)
1215
1216#Load_Room(Heap, Room0, Plane_1, Overlay_dict)
1217
1218#Load_Room(Heap, Room1, Plane_1, Overlay_dict)
1219
1220#Load_Room(Heap, Room0, Plane_1, Overlay_dict)
1221
1222
1223#Display_Heap(Heap)
1224
1225###############################################################################
1226###############################################################################
1227###############################################################################
1228###############################################################################
1229###############################################################################
1230###############################################################################
1231
1232
1233def Grabbable_In_Room(room, grabbable_actor_list):
1234
1235 """
1236
1237 This function checks the inputted room to see if it contains a grabbale actor
1238 that we can use for the superslide for SRM (in theory at least...)
1239
1240 """
1241
1242 grabbable_in_room = False
1243
1244 for actor in room.priority_queue:
1245
1246 if type(actor) == Actor and actor.Id in grabbable_actor_list:
1247
1248 grabbable_in_room = True
1249
1250 return grabbable_in_room
1251
1252
1253def Valid_Grabbable_In_Room(room, grabbable_actor_dict):
1254
1255 """
1256
1257 This function checks the inputted room to see if it contains a grabbale actor
1258 that we can use for the superslide for SRM
1259
1260 """
1261
1262 valid_grabbable_in_room = False
1263
1264 for actor in room.priority_queue:
1265
1266 if actor in grabbable_actor_dict.keys():
1267
1268 valid_grabbable_in_room = True
1269
1270 return valid_grabbable_in_room
1271
1272
1273def Chest_In_Room(room):
1274
1275 """
1276
1277 This function checks the inputted room to see if it contains a chest
1278
1279 """
1280
1281 chest_in_room = False
1282
1283 for actor in room.priority_queue:
1284
1285 if type(actor) == Actor and actor.Id == '0006':
1286
1287 chest_in_room = True
1288
1289 return chest_in_room
1290
1291
1292def Deku_Guard_In_Room(room):
1293
1294 """
1295
1296 This function checks the inputted room to see if it contains a Deku Guard
1297
1298 """
1299
1300 deku_guard_in_room = False
1301
1302 for actor in room.priority_queue:
1303
1304 if type(actor) == Actor and actor.Id == '017A':
1305
1306 deku_guard_in_room = True
1307
1308 return deku_guard_in_room
1309
1310
1311def Transition_List(room):
1312
1313 """
1314
1315 This function takes a room as input and returns a list of all of its transitions
1316 (i.e. doors/loading planes that lead to other rooms)
1317
1318 """
1319
1320 transition_list = []
1321
1322 for actor in room.priority_queue:
1323
1324 if actor.transition != False:
1325
1326 transition_list.append(actor)
1327
1328 return transition_list
1329
1330
1331def Shared_Transitions(room1, room2):
1332
1333 """
1334
1335 This function takes two Rooms as input and returns a list of their shared transitions
1336 (essentially returns the edges connecting these rooms if we view the rooms are nodes
1337 in a graph)
1338
1339 """
1340
1341 shared_transitions = []
1342
1343 for transition in Transition_List(room1):
1344
1345 if Is_Shared_Transition(transition, room1.number, room2.number) == True:
1346
1347 shared_transitions.append(transition)
1348
1349 return shared_transitions
1350
1351
1352def Shared_Transition_Exists(room1, room2):
1353
1354 """
1355
1356 This function takes two Rooms as input and returns True if they share a transition
1357 and False otherwise
1358
1359 """
1360
1361 shared_transition_exists = False
1362
1363 for transition in Transition_List(room1):
1364
1365 if Is_Shared_Transition(transition, room1.number, room2.number) == True:
1366
1367 shared_transition_exists = True
1368
1369 return shared_transition_exists
1370
1371
1372def Neighbors(room, Room_List):
1373
1374 """
1375
1376 This function takes a room as input along with a list of all potential rooms
1377 and returns a list of all rooms that share a transition with this room (excluding itself)
1378
1379 """
1380
1381 neighbors = []
1382
1383 for ROOM in Room_List:
1384
1385 if ROOM != room and Shared_Transition_Exists(room, ROOM) == True:
1386
1387 neighbors.append(ROOM)
1388
1389 return neighbors
1390
1391
1392def New_Room(room, transition, Room_List):
1393
1394 """
1395
1396 This function takes a room, a transition, and a list of all available rooms
1397 as input and returns the room that you would be in if you started in room
1398 and passed through transition
1399
1400 """
1401
1402 if transition not in Transition_List(room):
1403 print("ERROR: Invalid input into New_Room() function; transition is not in room")
1404
1405 for ROOM in Room_List:
1406
1407 if ROOM != room and (transition.transition[0] == ROOM.number or transition.transition[1] == ROOM.number) and ROOM.number != room.number:
1408
1409 new_room = ROOM
1410
1411 return new_room
1412
1413
1414def Current_Room(Room_Load_Permutation, Room_List):
1415
1416 """
1417
1418 Room_Load_Permutation is a list whose first element is the initial room that is started at
1419
1420 All subsequent entries are transitions (Actor class objects with transition != False)
1421
1422
1423 Room_List is a list of all available Rooms
1424
1425
1426 This function returns what Room you would be in after entering every transition listed in
1427 the permutation, assuming that you start in the initial room
1428
1429 """
1430
1431 if type(Room_Load_Permutation[0]) != Room:
1432 print("ERROR: no initial room in permutation (Current_Room() function error message)")
1433
1434 current_room = Room_Load_Permutation[0]
1435
1436 if len(Room_Load_Permutation) > 1:
1437
1438 for transition in Room_Load_Permutation[1:len(Room_Load_Permutation)]:
1439
1440 current_room = New_Room(current_room, transition, Room_List)
1441
1442 return current_room
1443
1444
1445def Room_Order_List(Room_Load_Permutation, Room_List):
1446
1447 """
1448
1449 Room_Load_Permutation is a list whose first element is the initial room that is started at
1450
1451 All subsequent entries are transitions (Actor class objects with transition != False)
1452
1453
1454 Room_List is a list of all available Rooms
1455
1456
1457 This function returns a list of what Room you would be in at each step of
1458 entering transitions
1459
1460 """
1461
1462 if type(Room_Load_Permutation[0]) != Room:
1463 print("ERROR: no initial room in permutation (Get_Room_Load_List() function error message)")
1464
1465 room_order_list = []
1466
1467 for i in range(0, len(Room_Load_Permutation)):
1468
1469 current_room = Current_Room(Room_Load_Permutation[0:i+1], Room_List)
1470
1471 room_order_list.append(current_room)
1472
1473 return room_order_list
1474
1475
1476def Generate_Room_Load_Permutations(Initial_Room, Room_List, Max_Transition_Count):
1477
1478 """
1479
1480 TODO: Debug this function... try calling: Generate_Room_Load_Permutations(Room0, Room_List, 1)
1481
1482
1483 This function seems to run for now, but it is untested for when we have multiple planes
1484 I will test this once I do Deku Palace input
1485
1486 """
1487
1488 """
1489
1490 This function takes as input the initial room (Initial_Room) that the scene was loaded in
1491 the list of all Rooms we want to consider visiting (Room_List), and Max_Transition_Count
1492 which is the maximum number of times we want to allow ourselves to load a new room
1493
1494 This function returns a list of all permutations of ways to enter new rooms after starting
1495 from the initial room (while limiting the number of room loads we do to be exactly Max_Transition_Count)
1496 where each permutation is a list in the form [Initial_Room, Transition1, Transition2, Transition3, ..., TransitionX]
1497 for X = Max_Transition_Count (so to get all permutations for X <= Max_Transition_Count, just
1498 use a for loop and call this function in each iteration of the foor loop and concatenate the lists)
1499
1500 """
1501
1502 if Max_Transition_Count == 0:
1503
1504 new_permutation_list = [[Initial_Room]]
1505
1506 return new_permutation_list
1507
1508
1509 else:
1510
1511 new_permutation_list = []
1512 permutation_list = Generate_Room_Load_Permutations(Initial_Room, Room_List, Max_Transition_Count - 1)
1513
1514 for permutation in permutation_list:
1515 for room in Neighbors(Current_Room(permutation, Room_List), Room_List):
1516 for transition in Shared_Transitions(Current_Room(permutation, Room_List), room):
1517 new_permutation = copy(permutation)
1518 new_permutation.append(transition)
1519 #permutation_list.append(new_permutation)
1520 new_permutation_list.append(new_permutation)
1521
1522 return new_permutation_list
1523
1524
1525def Generate_All_Room_Load_Permutations(Initial_Room, Room_List, Max_Transition_Count):
1526
1527 """
1528
1529 This function returns all permutations of ways to load a room starting from the initial room
1530 where the number of room loads is <= Max_Transition_Count
1531
1532 """
1533
1534 permutation_list = []
1535
1536 for N in range(Max_Transition_Count):
1537
1538 new_permutation_list = Generate_Room_Load_Permutations(Initial_Room, Room_List, N)
1539 permutation_list = permutation_list + new_permutation_list
1540
1541 return permutation_list
1542
1543
1544def Generate_Almost_All_Room_Load_Permutations(Initial_Room, Room_List, Max_Transition_Count):
1545
1546 """
1547
1548 This function returns all permutations of ways to load a room starting from the initial room
1549 where the number of room loads is <= Max_Transition_Count
1550
1551 this will always output a list with length at least 2, which is why it is different
1552 from Generate_All_Room_Load_Permutations
1553
1554 """
1555
1556 permutation_list = []
1557
1558 for N in range(1, Max_Transition_Count):
1559
1560 new_permutation_list = Generate_Room_Load_Permutations(Initial_Room, Room_List, N)
1561 permutation_list = permutation_list + new_permutation_list
1562
1563 return permutation_list
1564
1565
1566def Generate_All_Room_Order_Lists(Initial_Room, Room_List, Max_Transition_Count):
1567
1568 """
1569
1570 This function returns all permutations of ways to traverse through rooms, starting
1571 from the initial room where the number of room loads is <= Max_Transition_Count
1572
1573 The distinction between this and Generate_All_Room_Load_Permutations is that
1574 this will, instead of listing transitions, list the Room you're currently in
1575 at each step
1576
1577 """
1578
1579 room_order_permutation_list = []
1580
1581 room_load_permutation_list = Generate_All_Room_Load_Permutations(Initial_Room, Room_List, Max_Transition_Count)
1582
1583
1584 iteration_count = 0
1585 for room_load_permutation in room_load_permutation_list:
1586
1587 print("Generate_All_Room_Order_Lists: %d out of %d" %(iteration_count, len(room_load_permutation_list)))
1588 iteration_count += 1
1589
1590 room_order_list = Room_Order_List(room_load_permutation, Room_List)
1591
1592 room_order_permutation_list.append(room_order_list)
1593
1594 return room_order_permutation_list
1595
1596
1597def Generate_Allocation_Permutations(allocation_list):
1598
1599 """
1600
1601 Whatever, I'm just hardcoding a list of all of the actor names I want to allow
1602 and then using itertools to make a list of all of the permutations
1603
1604 """
1605
1606 """
1607
1608 TODO: Finish this function, also generalize it in the future
1609
1610 """
1611
1612 """
1613
1614 THIS FUNCTION IS SIMPLIFIED AT THE MOMENT AND COULD BE IMPROVED TO GENERATE
1615 EVEN MORE POSSIBLE PERMUTATIONS
1616
1617 allocation_list is a list of strings of things to allocate
1618
1619 for example:
1620
1621 allocation_list = [
1622 'Nothing',
1623 'Bomb',
1624 'Smoke',
1625 'Arrow',
1626 'Hookshot',
1627 'Charged Spin Attack',
1628 'Chu',
1629 'Zora Fins',
1630 'Fish',
1631 'Bugs'
1632 ]
1633
1634 """
1635
1636 allocation_permutation_list = []
1637
1638
1639 for i in range(len(allocation_list) + 1):
1640
1641 print("Generate_Allocation_Permutations: %d out of %d" %(i, len(allocation_list)))
1642
1643
1644 Permutations = list(itertools.permutations(allocation_list, i))
1645
1646 allocation_permutation_list = allocation_permutation_list + Permutations
1647
1648 return allocation_permutation_list
1649
1650
1651def Clear_Instances(actor_id, room):
1652
1653 """
1654
1655 This function takes an actor_id and room as input and sets actor.cleared = True
1656 for all actors with actor.id == actor_id in room
1657
1658 Call this before loading the scene or anything if you want some specific
1659 actor cleared already. For example, I'd call Clear_Instances('015B', Room1)
1660 to clear all of the bad bats in Beneath the Graveyard
1661
1662 """
1663
1664 for actor in room.priority_queue:
1665
1666 if actor.Id == actor_id and actor.clearable == True:
1667
1668 actor.cleared = True
1669
1670
1671def Clear_Instance(actor, room):
1672
1673 """
1674
1675 This function takes a specific actor in a room as input and sets
1676 actor.cleared = True
1677
1678 """
1679
1680 if actor.clearable == True:
1681
1682 actor.cleared = True
1683
1684
1685def Generate_Deallocation_Combinations(room):
1686
1687 """
1688 ##### Note: we actually get combinations instead of permutations because
1689 the order in which we deallocate actors doesn't matter
1690
1691 This function returns a list of combinations (stored as tuples of Actors)
1692
1693
1694
1695 Some things this (or maybe some other) function needs to account for:
1696
1697 if any rupee from a rupee cluster is deallocated in a deallocation step,
1698 then clear the rupee cluster actor instance (00E8) [note that there is
1699 at most one rupee cluster instance in every room in the game, so there is
1700 no need to check which cluster the rupees are associated with]
1701
1702 if all bad bats are deallocated on the same deallocation step, then they
1703 must all be cleared... actually, stronger: if all Category 5 actors with
1704 the same Id in a given room are deallocated on the same deallocation step,
1705 then clear all instances... actually this isn't good enough (need to add
1706 this into the input I believe or just treat bad bats as a special case)
1707
1708
1709 """
1710
1711 deallocation_list = []
1712
1713 for actor in room.priority_queue:
1714
1715 if actor.cleared == False and actor.unloadable == True:
1716
1717 deallocation_list.append(actor)
1718
1719 ##### Now we have a list of all actors in room that we have the option of deallocationg
1720
1721 ##### Now want want to generate a list of permutations
1722 ########## ACTUALLY, order doesn't matter for deallocation, so all combinations suffices
1723
1724 combination_list = []
1725
1726 for i in range(len(deallocation_list) + 1):
1727
1728 Combinations = list(itertools.combinations(deallocation_list, i))
1729
1730 combination_list = combination_list + Combinations
1731
1732 return combination_list
1733
1734
1735
1736
1737def Build_Room_Deallocation_Combination_Graph(room_order_list):
1738
1739
1740 """
1741
1742 This function takes a room_order_list as input (that is, a list in the form
1743 [initial_room, Room1, Room2, Room3, ..., RoomN] which describes the order we
1744 visit rooms in (note that Roomi could be equal to Roomj even for i =/= j)) and
1745 returns a dictionary where the keys are vertices whose values are lists of the
1746 other vertices that they are connected to. Each vertex represents a deallocation
1747 combination for the room that it corresponds to.
1748
1749 If the edges are directed, then this can be viewed as a multitree with some
1750 dummy root vertex and then each generation corresponds to a Room.
1751
1752 """
1753
1754 room_count = 0
1755
1756 #### Encode a dummy root node to make finding paths easier
1757 graph = {('root', room_count - 1) : []}
1758
1759
1760 iteration_count = 0
1761 ### for all rooms except for the last one
1762 for room in room_order_list[0:len(room_order_list)-1]:
1763
1764 print("Build_Room_Deallocation_Combination_Graph: %d out of %d" %(iteration_count, len(room_order_list) - 1))
1765 iteration_count += 1
1766
1767 combination_list = Generate_Deallocation_Combinations(room)
1768
1769 for combination in combination_list:
1770
1771 for key in graph.keys():
1772
1773 ### If the key is from the previous generation, then append every combination to its list
1774 if key[1] == room_count - 1:
1775
1776 graph[key].append(combination)
1777
1778 graph[(combination, room_count)] = []
1779
1780 room_count += 1
1781
1782 return graph
1783
1784
1785def Find_Leaves(graph):
1786
1787 """
1788
1789 This function takes a graph (really a dictionary) created by Build_Room_Deallocation_Combination_Graph()
1790 and returns a list of all of its leaves
1791
1792 """
1793
1794 leaf_list = []
1795
1796 for key in graph:
1797 # only leaves will point to empty lists
1798 if graph[key] == []:
1799 leaf_list.append(key)
1800
1801 return leaf_list
1802
1803
1804def Find_All_Paths(graph, start, end, path=[]):
1805
1806 """
1807
1808 This function takes a graph (really a dictionary) and start and end vertices
1809 as input and returns a list of all paths from start to end
1810
1811 TODO: maybe don't rely on hardcoding what the root's key is and instead write
1812 a function to find it (though hardcode is prob faster if you don't make mistakes)
1813
1814 I will use this to find all paths from ('root', -1) [note that I am hardcoding
1815 this instead of just finding a root without any parent] to a given lead, and
1816 I will do this for all leafs (which I can get by doing Find_Leaves(graph))
1817
1818 """
1819
1820
1821 path = path + [start]
1822 if start == end:
1823 return [path]
1824 if not (start in graph):
1825 return []
1826 paths = []
1827 for vertex in graph[start]:
1828 if vertex not in path:
1829 newpaths = Find_All_Paths(graph, vertex, end, path)
1830 for newpath in newpaths:
1831 paths.append(newpath)
1832 return paths
1833
1834
1835def Find_All_Deallocation_Combination_Paths(graph):
1836
1837 """
1838
1839 TODO: Note that I hardcode what the key of the root vertex is: ('root', -1)
1840
1841 This returns a list of all (n-1)-permutations of deallocation combinations
1842 for a given room_order_list (where we assume there are n rooms we travel to
1843 including the initial room). This gives us the thing we called D1
1844
1845 """
1846
1847 all_deallocation_combination_paths = []
1848
1849 leaf_list = Find_Leaves(graph)
1850
1851 iteration_count = 0
1852 for leaf in leaf_list:
1853
1854 print("Find_All_Deallocation_Combination_Paths: %d out of %d" %(iteration_count, len(leaf_list)))
1855 iteration_count += 1
1856
1857 # I hardcode the root key to be ('root', -1)
1858 path_to_leaf = Find_All_Paths(graph, ('root', -1), leaf)
1859
1860 all_deallocation_combination_paths = all_deallocation_combination_paths + path_to_leaf
1861
1862
1863 ##### Since every key is a tuple in the form (combination, number), get rid of number part
1864 for path in all_deallocation_combination_paths:
1865 for vertex in path:
1866 path[path.index(vertex)] = vertex[0]
1867
1868 return all_deallocation_combination_paths
1869
1870
1871
1872
1873def Generate_Action_Permutations(room_order_list, allocation_list):
1874
1875 """
1876
1877 THIS IS THE FUNCTION THAT FINALLY GIVES US ALL OF THE PERMUTATIONS OF THINGS
1878 TO DO FOR A GIVEN room_order_list and the allocation_list.
1879
1880
1881
1882 WE WILL RUN THIS FUNCTION ON EVERY PERMUTATION OF ROOM ORDER LISTS USING
1883 Generate_All_Room_Order_Lists(Initial_Room, Room_List, Max_Transition_Count)
1884
1885
1886 ONCE WE DO THAT WE WILL HAVE EVERY SINGLE PERMUTATION THAT WE WANT TO TEST
1887
1888 """
1889
1890 allocation_permutations = Generate_Allocation_Permutations(allocation_list)
1891
1892 ##### Now we want all (n-1)-permutations of allocation permutations
1893 A1 = list(itertools.permutations(allocation_permutations, len(room_order_list) - 1))
1894
1895 #### deallocation combination graph
1896 graph = Build_Room_Deallocation_Combination_Graph(room_order_list)
1897
1898 D1 = Find_All_Deallocation_Combination_Paths(graph)
1899
1900 ###########################################################################
1901
1902 # create output list o
1903 o = []
1904 for i in range(len(A1)):
1905
1906 print("Generate_Action_Permutations: %d out of %d" %(i, len(A1)))
1907
1908 for j in range(len(D1)):
1909 for b in range(2**(len(room_order_list) - 1)):
1910 # create new empty list p
1911 p = []
1912 for k in range(len(room_order_list) - 1):
1913 p.append(room_order_list[k])
1914
1915 if bin(b)[2:].zfill(len(room_order_list)-1) == 1:
1916
1917 # add each element of A1[i][k] to p
1918 for element in A1[i][k]:
1919 p.append(element)
1920 # add each element of D1[j][k] to p
1921 for element in D1[j][k]:
1922 p.append(element)
1923
1924 elif bin(b)[2:].zfill(len(room_order_list)-1) == 0:
1925
1926 # add each element of D1[j][k] to p
1927 for element in D1[j][k]:
1928 p.append(element)
1929 # add each element of A1[i][k] to p
1930 for element in A1[i][k]:
1931 p.append(element)
1932
1933 # Add the last room to p
1934 p.append(room_order_list[len(room_order_list)-1])
1935 # append p to o
1936 o = o + p
1937
1938 return o
1939
1940
1941
1942def Generate_Heap_Permutations(Initial_Room, Room_List, Max_Transition_Count, allocation_list):
1943
1944 """
1945
1946 This function takes the initial room, the Room List, the Maximum Number of Transitions
1947 that we want to allow, and the allocation list as input and returns every permutation
1948 for heap manip setups to try (possibilities currently mostly limited by allocation_list)
1949
1950 WE WILL USE THIS FUNCTION IN THE HEAP MANIP SOLVER
1951
1952 """
1953
1954 heap_permutations = []
1955
1956 All_Room_Order_Lists = Generate_All_Room_Order_Lists(Initial_Room, Room_List, Max_Transition_Count)
1957
1958 iteration_count= 0
1959 for room_order_list in All_Room_Order_Lists:
1960
1961 print("Iteration %d out of %d" %(iteration_count, len(All_Room_Order_Lists)))
1962
1963 action_permutations = Generate_Action_Permutations(room_order_list, allocation_list)
1964
1965 heap_permutations = heap_permutations + action_permutations
1966
1967 iteration_count += 1
1968
1969
1970 print("HEAP PERMUTATION GENERATION COMPLETE")
1971
1972 return heap_permutations
1973
1974
1975
1976###############################################################################
1977###############################################################################
1978###############################################################################
1979###############################################################################
1980###############################################################################
1981###############################################################################
1982###############################################################################
1983
1984def Actor_Is_In_Heap(Heap, actor):
1985
1986 """
1987
1988 actor is the Actor that we want to check for
1989
1990 This function will return True if this Actor is in the Heap and False otherwise
1991
1992 """
1993
1994 actor_is_in_heap = False
1995
1996 for entry in Heap:
1997
1998 if type(entry) == Actor and entry == actor:
1999
2000 actor_is_in_heap = True
2001
2002 return actor_is_in_heap
2003
2004def Actor_Is_In_Room(room, actor):
2005
2006 """
2007
2008 actor is the Actor that we want to check for
2009
2010 This function will return True if this Actor is in the room and False otherwise
2011
2012 """
2013
2014 actor_is_in_room = False
2015
2016 for entry in room.priority_queue:
2017
2018 if type(entry) == Actor and entry == actor:
2019
2020 actor_is_in_room = True
2021
2022 return actor_is_in_room
2023
2024
2025
2026def Bomb_And_Smoke_Superslide(Heap, Room_Number, Overlay_dict):
2027
2028 """
2029
2030 This function allocates a bomb, then allocates smoke (this happens when the bomb explodes)
2031
2032 """
2033
2034 Bomb = Actor(name='Bomb', Id='0009', size=516, category=0, overlay_type='B', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
2035
2036 Allocate(Heap, Bomb, Overlay_dict)
2037
2038 Smoke = Actor(name='Smoke', Id='00A2', size=11908, category=0, overlay_type='A', unloadable=True, address=0, room_number=Room_Number, priority=0, from_spawner=False, transition=False, clearable=False, cleared=False)
2039
2040 Allocate(Heap, Smoke, Overlay_dict)
2041
2042
2043
2044
2045
2046def Copy_Room_List(Room_List):
2047
2048 """
2049
2050 This function takes a list of all Rooms, Room_List, as input
2051 and returns a list of copies of all of the Rooms in Room_List
2052
2053 """
2054
2055 ##### First we want a list of all shared entries between the Room priority queues
2056
2057 shared_actor_list = []
2058
2059 for room1 in Room_List:
2060 for room2 in Room_List:
2061
2062 if room2 != room1:
2063
2064 for actor1 in room1.priority_queue:
2065 for actor2 in room2.priority_queue:
2066 if (actor1 == actor2) and (actor1 not in shared_actor_list):
2067
2068 shared_actor_list.append(actor1)
2069
2070 ##### Now make a list of copies of each entry of the above list
2071
2072 shared_actor_copy_list = []
2073 for actor in shared_actor_list:
2074 shared_actor_copy_list.append(copy(actor))
2075
2076 Room_List_Copy = []
2077
2078 for room in Room_List:
2079
2080 priority_queue_copy = []
2081
2082 for actor in room.priority_queue:
2083
2084 if actor not in shared_actor_list:
2085
2086 priority_queue_copy.append(copy(actor))
2087
2088 elif actor in shared_actor_list:
2089 append_count = 0
2090 for actor2 in shared_actor_copy_list:
2091
2092 # If all attributes of the actor and the copy are the same, then assume they are copies of each other
2093 if actor2.name == actor.name and actor2.Id == actor.Id and actor2.size == actor.size and actor2.category == actor.category and actor2.overlay_type == actor.overlay_type and actor2.unloadable == actor.unloadable and actor2.address == actor.address and actor2.room_number == actor.room_number and actor2.priority == actor.priority and actor2.from_spawner == actor.from_spawner and actor2.transition == actor.transition and actor2.clearable == actor.clearable and actor2.cleared == actor.cleared:
2094 # append the copy
2095 priority_queue_copy.append(actor2)
2096 append_count += 1
2097
2098 if append_count > 1:
2099 print("ERROR: There were two or more copies of the same Actor in shared_actor_copy_list (Copy_Room_List() error message)")
2100
2101
2102 room_copy = Room(number=room.number, priority_queue=priority_queue_copy, clock_exists=room.clock_exists, clock_priority=room.clock_priority)
2103
2104 Room_List_Copy.append(room_copy)
2105
2106 return Room_List_Copy
2107
2108
2109
2110
2111def Main_Actor_Attributes_Match(actor1, actor2):
2112
2113 """
2114
2115 This function returns True is the two Actors taken as input have the same
2116 values for all of their main attributes and False otherwise
2117
2118 the main attributes do not include things like "address" and such that can
2119 change as the state updates
2120
2121 """
2122
2123 main_actor_attributes_match = False
2124
2125 if actor1.name == actor2.name and actor1.Id == actor2.Id and actor1.size == actor2.size and actor1.category == actor2.category and actor1.overlay_type == actor2.overlay_type and actor1.unloadable == actor2.unloadable and actor1.room_number is actor2.room_number and actor1.priority is actor2.priority and actor1.from_spawner == actor2.from_spawner and actor1.transition == actor2.transition and actor1.clearable == actor2.clearable:
2126 main_actor_attributes_match = True
2127
2128 return main_actor_attributes_match
2129
2130
2131def Main_Overlay_Attributes_Match(overlay1, overlay2):
2132
2133 main_overlay_attributes_match = False
2134
2135 if overlay1.Id == overlay2.Id and overlay1.size == overlay2.size:
2136 main_overlay_attributes_match = True
2137
2138 return main_overlay_attributes_match
2139
2140
2141def Copy_Overlay_Dict(Overlay_Dict):
2142
2143 overlay_dict_copy = {}
2144
2145 for key in Overlay_Dict:
2146 overlay_dict_copy[key] = copy(Overlay_Dict[key])
2147
2148 return overlay_dict_copy
2149
2150
2151def Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy):
2152
2153 """
2154
2155 This function takes the Heap as input and returns a copy of the Heap where
2156 every actor copy in the Heap copy is the same class instance as each corresponding
2157 actor in the room list copy priority queues (same for Overlay_Dict_Copy)
2158
2159 """
2160
2161 Heap_Copy = []
2162
2163 for entry in Heap:
2164
2165 entry_allocated = False
2166 not_allocated_count = 0
2167 while entry_allocated is False:
2168
2169 if not_allocated_count > 4:
2170 print("UHHHHHHHHHHHHHHHHHHHHHHHH (Copy_Heap() Error Message)")
2171
2172 if type(entry) == Node:
2173
2174 Heap_Copy.append(copy(entry))
2175 entry_allocated = True
2176
2177 elif type(entry) == Overlay:
2178
2179 for key in Overlay_Dict_Copy:
2180 if Main_Overlay_Attributes_Match(Overlay_Dict_Copy[key], entry) == True:
2181 Heap_Copy.append(Overlay_Dict_Copy[key])
2182 entry_allocated = True
2183
2184 elif type(entry) == Actor:
2185
2186 allocated_count = 0
2187 for room in Room_List_Copy:
2188
2189 if entry_allocated == True:
2190 break
2191
2192 for actor in room.priority_queue:
2193
2194 if allocated_count > 1:
2195 print("ERROR: tried to allocate multiple copies (Copy_Heap() Error Message)")
2196
2197 if Main_Actor_Attributes_Match(entry, actor) == True:
2198 Heap_Copy.append(actor)
2199 allocated_count += 1
2200 entry_allocated = True
2201 break
2202
2203 # If it isn't in any of the priority queues, then it must be something you spawned
2204 if entry_allocated == False:
2205 Heap_Copy.append(copy(entry))
2206 entry_allocated = True
2207
2208 else:
2209 print("ERROR: entry in Heap is not an Actor, Node, or Overlay (Copy_Heap() error message)")
2210
2211 not_allocated_count += 1
2212 return Heap_Copy
2213
2214
2215def Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy):
2216
2217 """
2218
2219 This function takes the Grabbable_Dict as input and returns a copy of the it where
2220 each transition in it is a the same Actor class instance copy as the ones used in
2221 the priority queues of the Rooms in Room_List_Copy
2222
2223 """
2224
2225 grabbable_dict_copy = {}
2226
2227 for pot in Grabbable_Dict:
2228
2229 pot_in_dict = False
2230
2231
2232 for room in Room_List_Copy:
2233 if pot_in_dict == True:
2234 break
2235 for actor in room.priority_queue:
2236 if Main_Actor_Attributes_Match(pot, actor) == True:
2237
2238 key = actor
2239
2240 for room1 in Room_List_Copy:
2241 if pot_in_dict == True:
2242 break
2243 for actor1 in room1.priority_queue:
2244
2245 # Finding the transition
2246 if Main_Actor_Attributes_Match(Grabbable_Dict[pot][1], actor1):
2247
2248 grabbable_dict_copy[key] = [Grabbable_Dict[pot][0], actor1]
2249 pot_in_dict = True
2250
2251 return grabbable_dict_copy
2252
2253
2254def Find_Actor_Copy(actor, Room_List_Copy):
2255
2256 """
2257
2258 This function takes an Actor as input (actor) and a copy of the list of rooms
2259 (Room_List_Copy) and returns the copy of the inputted actor that is found in
2260 the priority queue of a Room in Room_List_Copy
2261
2262 """
2263
2264 actor_copy = None
2265
2266 copy_found = False
2267 for room in Room_List_Copy:
2268 if copy_found == True:
2269 break
2270 for actor1 in room.priority_queue:
2271 if Main_Actor_Attributes_Match(actor1, actor):
2272 actor_copy = actor1
2273 copy_found = True
2274 break
2275
2276 return actor_copy
2277
2278
2279"""
2280
2281TODO: Make the solver take the initial heap layout as input so that it is easy
2282to test successive heap manip setups in the future
2283
2284DO NOT FORGET TO CLEAR ALL OF THE BAD BATS IF YOU THINK THAT THAT IS SOMETHING
2285THAT YOU WANT TO DO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2286
2287ALSO IGNORE THAT FUNCTION BELOW, COMPLETELY REWRITE FROM SCRATCH BUT MAYBE READ
2288IT FIRST TO SEE IF IT REMINDS YOU OF ANY IDEAS YOU HAD
2289
2290"""
2291
2292
2293def Randomized_Solver(Initial_Room, Room_List, Max_Transition_Count, allocation_list, Grabbable_Dict, Overlay_Dict, filename, Offset_List, Initial_Heap):
2294
2295 """
2296
2297 This function does not currently account for the possibility that you might need to break
2298 another pot in order to superslide off of a given pot. While this might not be strictly
2299 true for the pot we currently use in deku palace, it would be good at add more information
2300 to Grabbable_Dict to account for this
2301
2302 """
2303
2304 """
2305
2306 Okay, the Initial_Heap argument will not work as I initially intended because of things
2307 like rupee clusters being cleared, etc. So if I want to test a Heap from an initial Heap
2308 distribution, then I will have to hardcode it to perform the necessary steps to get to it each time
2309
2310 """
2311
2312 """
2313
2314 filename is the complete name (i.e. including the path) that we want to write to
2315
2316 This function will randomly choose solutions to test (it may have repeats)
2317
2318 Offset_List is a list of offsets that we want to check for. The grabbable object (e.g. a pot)
2319 will be first when calculating the offset. So if doing chest SRM, we want
2320 pot - chest = 0x160 or pot - chest = 0x1F0, so we want Offset_List = [0x160, 0x1F0]
2321 We make this Offset_List by default
2322
2323 Grabbable_dict is a dictionary of the grabbable actors (such as pots) that
2324 we want to attempt to use for superslide SRM where the keys are the grabbable
2325 actors and the values are 3-bit strings where each bit means:
2326
2327 100 : Possible to enter Plane with both Bomb and Smoke loaded
2328 010 : Possible to enter Plane with Smoke loaded, but no Bomb loaded
2329 001 : Possible to enter Plane with no Smoke loaded
2330
2331 """
2332
2333 angle_solution_count = 0
2334 position_solution_count = 0
2335 permutation_count = 0
2336
2337 ### Keep doing this forever (infinite loop so we keep trying new permutations)
2338 while True:
2339
2340 all_room_load_lists = Generate_Almost_All_Room_Load_Permutations(Initial_Room, Room_List, Max_Transition_Count)
2341
2342 for room_load_list in all_room_load_lists:
2343
2344 if permutation_count%500 == 0:
2345 print("%d Permutations Tested %d Angle Solutions %d Position Solutions" %(permutation_count, angle_solution_count, position_solution_count))
2346 permutation_count += 1
2347
2348 Heap = copy(Initial_Heap)
2349
2350 ##### Initialize the actor addresses and other attributes each time
2351
2352 for room in Room_List:
2353
2354 for actor in room.priority_queue:
2355
2356 actor.address = 0
2357 actor.cleared = False
2358
2359 ##### Clear all bad bats (optional, but I want to do this for beneath the graveyard)
2360 Clear_Instances('015B', room)
2361 ###################################################################
2362
2363 #####
2364 ##### Perform seuqence of steps here if you want to initialize your heap to something
2365 #####
2366
2367 # We will use this to collect things we do in the permutation to help output the solution
2368 action_list = []
2369
2370 room_count = 0
2371 # NOTE: the first "transition" is actually not a transition; it is the initial room
2372 for transition in room_load_list[0:len(room_load_list)-1]:
2373
2374 room = Current_Room(room_load_list[0:room_count + 1], Room_List)
2375
2376 # If this is the Initial_Room AND the Heap is empty, then we want to load the scene
2377 if (room_count is 0) and (len(Heap) == 2):
2378
2379 if room != Initial_Room:
2380 print("ERROR: first entry in room_load_list is not Initial_Room (Randomnized_Solver() Error Message)")
2381
2382 Load_Scene(Heap, Initial_Room, Overlay_Dict)
2383 action_list.append("Load Scene: Room %d" %(Initial_Room.number))
2384
2385 ##### NOW WE DO DEALLOCATION/ALLOCATION STEPS AFTER LOADING THE SCENE
2386
2387
2388 """
2389
2390 Now randomly (with some chosen distribution) choose things to allocate
2391 and/or things to deallocate (in your current room). Make it so that
2392 you can only choose a specific action once. For example, if allocation_list
2393 has ['bomb', 'bomb, 'bomb', 'fish'] in it, then make it so you can only use
2394 fish once, but you can use bomb 3 times
2395
2396 Somehow try to encode that hookshot/charged spin are mutually exclusive
2397 and that if either of them exist then they must be the last action
2398
2399 Allow yourself to deallocate things before allocating things even
2400 though it might be impossible or slow in some cases
2401
2402 """
2403
2404 # Do a coinflip to decide between allocating or deallocating first
2405 decision_coin_flip = np.random.uniform(0,1)
2406
2407 # With probability 1/2, we allocate first and deallocate second
2408 # if we allocate first, don't allow 'Charged Spin Attack'
2409 if decision_coin_flip > .5:
2410
2411 explosive_count = 0
2412 droppable_count = 0
2413
2414 ##### ALLOCATION
2415 for action in allocation_list:
2416
2417 # whether or not we add an action is based off of this
2418 coin_flip = np.random.uniform(0,1)
2419
2420 if action == 'Smoke' and coin_flip > .5:
2421
2422 Allocate_Smoke(Heap, room.number, Overlay_Dict)
2423 action_list.append("Allocate: Smoke")
2424
2425 elif action == 'Chu' and coin_flip > .5 and explosive_count < 3:
2426
2427 Allocate_Chu(Heap, room.number, Overlay_Dict)
2428 action_list.append("Allocate: Chu")
2429 explosive_count += 1
2430
2431 elif action == 'Arrow' and coin_flip > .5:
2432
2433 Allocate_Arrow(Heap, room.number, Overlay_Dict)
2434 action_list.append("Allocate: Arrow")
2435
2436 elif action == 'Bomb' and coin_flip > .5 and explosive_count < 3:
2437
2438 Allocate_Bomb(Heap, room.number, Overlay_Dict)
2439 action_list.append("Allocate: Bomb")
2440 explosive_count += 1
2441
2442 elif action == 'Zora Fins' and coin_flip > .5:
2443
2444 Allocate_Zora_Fins(Heap, room.number, Overlay_Dict)
2445 action_list.append("Allocate: Zora Fins")
2446
2447 elif action == 'Fish' and coin_flip > .5 and droppable_count < 2:
2448
2449 Allocate_Fish(Heap, room.number, Overlay_Dict)
2450 action_list.append("Allocate: Fish")
2451 droppable_count += 1
2452
2453 elif action == 'Bugs' and coin_flip > .5 and droppable_count < 2:
2454
2455 Allocate_Bugs(Heap, room.number, Overlay_Dict)
2456 action_list.append("Allocate: Bugs")
2457 droppable_count += 1
2458
2459 elif action == 'Hookshot' and coin_flip > .5:
2460
2461 Allocate_Hookshot(Heap, room.number, Overlay_Dict)
2462 action_list.append("Allocate: Hookshot")
2463
2464 ### We don't include 'Charged Spin Attack' in this
2465
2466 ##### DEALLOCATION
2467 for actor in room.priority_queue:
2468
2469 # whether or not we deallocate an actor is based off of this
2470 coin_flip = np.random.uniform(0,1)
2471
2472 ##### HARDCODE TO NOT ALLOW GOLD SKULLTULA OR SPIDER WEBS DEALLOCATE BECAUSE FASTER FOR 100%
2473 if actor.unloadable == True and Actor_Is_In_Heap(Heap, actor) == True and coin_flip > .5 and actor.Id != '0050' and actor.Id != '01F4' and actor.Id != '0125':
2474
2475
2476 if actor.Id == '00E8' or actor.name == 'Collectible (Rupee from Rupee Cluster)':
2477
2478 Deallocate(Heap, actor, Overlay_Dict)
2479 # There is at most one rupee cluster per room, so this is fine to clear it
2480 Clear_Instances('00E8', room)
2481 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2482
2483 # THESE PRIORITIES ARE HARDCODED FOR ROOM 3 OF OCEANSIDE!!!!!!!
2484 elif actor.Id == '01E7' and (actor.priority == 0 or actor.priority == 1 or actor.priority == 2):
2485
2486 table_bonk_deallocation_count = 0
2487 for entry in Heap:
2488 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 0:
2489 Deallocate(Heap, entry, Overlay_Dict)
2490 table_bonk_deallocation_count += 1
2491
2492 for entry in Heap:
2493 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 1:
2494 Deallocate(Heap, entry, Overlay_Dict)
2495 table_bonk_deallocation_count += 1
2496
2497 for entry in Heap:
2498 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 2:
2499 Deallocate(Heap, entry, Overlay_Dict)
2500 table_bonk_deallocation_count += 1
2501
2502 if table_bonk_deallocation_count != 3:
2503 print("ERROR: table_bonk_deallocation_count is not 3 (Randomized_Solver() error)")
2504
2505 action_list.append("Deallocate: " + actor.name + " (Priority 0, 1, and 2) [Bonk Oceanside Table]")
2506
2507
2508 # if the actor is clearable AND isn't a bad bat, then clear it when deallocating it if it isn't already cleared
2509 elif actor.clearable == True and actor.cleared == False and actor.Id != '015B':
2510
2511 Deallocate(Heap, actor, Overlay_Dict)
2512 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2513 # CLEAR THE ACTOR
2514 Clear_Instance(actor, room)
2515
2516 else:
2517
2518 Deallocate(Heap, actor, Overlay_Dict)
2519 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2520
2521
2522 # With probability 1/2, we deallocate first and allocate second
2523 elif decision_coin_flip <= .5:
2524
2525 explosive_count = 0
2526 droppable_count = 0
2527 hookshot_exists = False
2528
2529 ##### DEALLOCATION
2530 for actor in room.priority_queue:
2531
2532 # whether or not we deallocate an actor is based off of this
2533 coin_flip = np.random.uniform(0,1)
2534
2535 ##### HARDCODE TO NOT ALLOW GOLD SKULLTULA OR SPIDER WEBS DEALLOCATE BECAUSE FASTER FOR 100%
2536 if actor.unloadable == True and Actor_Is_In_Heap(Heap, actor) == True and coin_flip > .5 and actor.Id != '0050' and actor.Id != '01F4' and actor.Id != '0125':
2537
2538
2539 if actor.Id == '00E8' or actor.name == 'Collectible (Rupee from Rupee Cluster)':
2540
2541 Deallocate(Heap, actor, Overlay_Dict)
2542 # There is at most one rupee cluster per room, so this is fine to clear it
2543 Clear_Instances('00E8', room)
2544 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2545
2546 # THESE PRIORITIES ARE HARDCODED FOR ROOM 3 OF OCEANSIDE!!!!!!!
2547 elif actor.Id == '01E7' and (actor.priority == 0 or actor.priority == 1 or actor.priority == 2):
2548
2549 table_bonk_deallocation_count = 0
2550 for entry in Heap:
2551 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 0:
2552 Deallocate(Heap, entry, Overlay_Dict)
2553 table_bonk_deallocation_count += 1
2554
2555 for entry in Heap:
2556 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 1:
2557 Deallocate(Heap, entry, Overlay_Dict)
2558 table_bonk_deallocation_count += 1
2559
2560 for entry in Heap:
2561 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 2:
2562 Deallocate(Heap, entry, Overlay_Dict)
2563 table_bonk_deallocation_count += 1
2564
2565 if table_bonk_deallocation_count != 3:
2566 print("ERROR: table_bonk_deallocation_count is not 3 (Randomized_Solver() error)")
2567
2568 action_list.append("Deallocate: " + actor.name + " (Priority 0, 1, and 2) [Bonk Oceanside Table]")
2569
2570
2571 # if the actor is clearable AND isn't a bad bat, then clear it when deallocating it if it isn't already cleared
2572 elif actor.clearable == True and actor.cleared == False and actor.Id != '015B':
2573
2574 Deallocate(Heap, actor, Overlay_Dict)
2575 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2576 # CLEAR THE ACTOR
2577 Clear_Instance(actor, room)
2578
2579 else:
2580
2581 Deallocate(Heap, actor, Overlay_Dict)
2582 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2583
2584
2585 ##### ALLOCATION
2586 for action in allocation_list:
2587
2588 # whether or not we add an action is based off of this
2589 coin_flip = np.random.uniform(0,1)
2590
2591 if action == 'Smoke' and coin_flip > .5:
2592
2593 Allocate_Smoke(Heap, room.number, Overlay_Dict)
2594 action_list.append("Allocate: Smoke")
2595
2596 elif action == 'Chu' and coin_flip > .5 and explosive_count < 3:
2597
2598 Allocate_Chu(Heap, room.number, Overlay_Dict)
2599 action_list.append("Allocate: Chu")
2600 explosive_count += 1
2601
2602 elif action == 'Arrow' and coin_flip > .5:
2603
2604 Allocate_Arrow(Heap, room.number, Overlay_Dict)
2605 action_list.append("Allocate: Arrow")
2606
2607 elif action == 'Bomb' and coin_flip > .5 and explosive_count < 3:
2608
2609 Allocate_Bomb(Heap, room.number, Overlay_Dict)
2610 action_list.append("Allocate: Bomb")
2611 explosive_count += 1
2612
2613 elif action == 'Zora Fins' and coin_flip > .5:
2614
2615 Allocate_Zora_Fins(Heap, room.number, Overlay_Dict)
2616 action_list.append("Allocate: Zora Fins")
2617
2618 elif action == 'Fish' and coin_flip > .5 and droppable_count < 2:
2619
2620 Allocate_Fish(Heap, room.number, Overlay_Dict)
2621 action_list.append("Allocate: Fish")
2622 droppable_count += 1
2623
2624 elif action == 'Bugs' and coin_flip > .5 and droppable_count < 2:
2625
2626 Allocate_Bugs(Heap, room.number, Overlay_Dict)
2627 action_list.append("Allocate: Bugs")
2628 droppable_count += 1
2629
2630 elif action == 'Hookshot' and coin_flip > .5:
2631
2632 Allocate_Hookshot(Heap, room.number, Overlay_Dict)
2633 action_list.append("Allocate: Hookshot")
2634 hookshot_exists = True
2635
2636 elif action == 'Charged Spin Attack' and (hookshot_exists is False) and coin_flip > .5:
2637
2638 Allocate_Charged_Spin_Attack(Heap, room.number, Overlay_Dict)
2639 action_list.append("Allocate: Charged Spin Attack")
2640
2641
2642 else:
2643
2644 Load_Room(Heap, room, transition, Overlay_Dict)
2645
2646 action_list.append("Load Room: Room %d" %(room.number) + " with " + transition.name + " %d" %(transition.priority))
2647
2648 """
2649
2650 Now randomly (with some chosen distribution) choose things to allocate
2651 and/or things to deallocate (in your current room). Make it so that
2652 you can only choose a specific action once. For example, if allocation_list
2653 has ['bomb', 'bomb, 'bomb', 'fish'] in it, then make it so you can only use
2654 fish once, but you can use bomb 3 times
2655
2656 Somehow try to encode that hookshot/charged spin are mutually exclusive
2657 and that if either of them exist then they must be the last action
2658
2659 Allow yourself to deallocate things before allocating things even
2660 though it might be impossible or slow in some cases
2661
2662 """
2663
2664 # Do a coinflip to decide between allocating or deallocating first
2665 decision_coin_flip = np.random.uniform(0,1)
2666
2667 # With probability 1/2, we allocate first and deallocate second
2668 # if we allocate first, don't allow 'Charged Spin Attack'
2669 if decision_coin_flip > .5:
2670
2671 explosive_count = 0
2672 droppable_count = 0
2673
2674 ##### ALLOCATION
2675 for action in allocation_list:
2676
2677 # whether or not we add an action is based off of this
2678 coin_flip = np.random.uniform(0,1)
2679
2680 if action == 'Smoke' and coin_flip > .5:
2681
2682 Allocate_Smoke(Heap, room.number, Overlay_Dict)
2683 action_list.append("Allocate: Smoke")
2684
2685 elif action == 'Chu' and coin_flip > .5 and explosive_count < 3:
2686
2687 Allocate_Chu(Heap, room.number, Overlay_Dict)
2688 action_list.append("Allocate: Chu")
2689 explosive_count += 1
2690
2691 elif action == 'Arrow' and coin_flip > .5:
2692
2693 Allocate_Arrow(Heap, room.number, Overlay_Dict)
2694 action_list.append("Allocate: Arrow")
2695
2696 elif action == 'Bomb' and coin_flip > .5 and explosive_count < 3:
2697
2698 Allocate_Bomb(Heap, room.number, Overlay_Dict)
2699 action_list.append("Allocate: Bomb")
2700 explosive_count += 1
2701
2702 elif action == 'Zora Fins' and coin_flip > .5:
2703
2704 Allocate_Zora_Fins(Heap, room.number, Overlay_Dict)
2705 action_list.append("Allocate: Zora Fins")
2706
2707 elif action == 'Fish' and coin_flip > .5 and droppable_count < 2:
2708
2709 Allocate_Fish(Heap, room.number, Overlay_Dict)
2710 action_list.append("Allocate: Fish")
2711 droppable_count += 1
2712
2713 elif action == 'Bugs' and coin_flip > .5 and droppable_count < 2:
2714
2715 Allocate_Bugs(Heap, room.number, Overlay_Dict)
2716 action_list.append("Allocate: Bugs")
2717 droppable_count += 1
2718
2719 elif action == 'Hookshot' and coin_flip > .5:
2720
2721 Allocate_Hookshot(Heap, room.number, Overlay_Dict)
2722 action_list.append("Allocate: Hookshot")
2723
2724 ### We don't include 'Charged Spin Attack' in this
2725
2726 ##### DEALLOCATION
2727 for actor in room.priority_queue:
2728
2729 # whether or not we deallocate an actor is based off of this
2730 coin_flip = np.random.uniform(0,1)
2731
2732 ##### HARDCODE TO NOT ALLOW GOLD SKULLTULA OR SPIDER WEBS DEALLOCATE BECAUSE FASTER FOR 100%
2733 if actor.unloadable == True and Actor_Is_In_Heap(Heap, actor) == True and coin_flip > .5 and actor.Id != '0050' and actor.Id != '01F4' and actor.Id != '0125':
2734
2735
2736 if actor.Id == '00E8' or actor.name == 'Collectible (Rupee from Rupee Cluster)':
2737
2738 Deallocate(Heap, actor, Overlay_Dict)
2739 # There is at most one rupee cluster per room, so this is fine to clear it
2740 Clear_Instances('00E8', room)
2741 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2742
2743 # THESE PRIORITIES ARE HARDCODED FOR ROOM 3 OF OCEANSIDE!!!!!!!
2744 elif actor.Id == '01E7' and (actor.priority == 0 or actor.priority == 1 or actor.priority == 2):
2745
2746 table_bonk_deallocation_count = 0
2747 for entry in Heap:
2748 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 0:
2749 Deallocate(Heap, entry, Overlay_Dict)
2750 table_bonk_deallocation_count += 1
2751
2752 for entry in Heap:
2753 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 1:
2754 Deallocate(Heap, entry, Overlay_Dict)
2755 table_bonk_deallocation_count += 1
2756
2757 for entry in Heap:
2758 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 2:
2759 Deallocate(Heap, entry, Overlay_Dict)
2760 table_bonk_deallocation_count += 1
2761
2762 if table_bonk_deallocation_count != 3:
2763 print("ERROR: table_bonk_deallocation_count is not 3 (Randomized_Solver() error)")
2764
2765 action_list.append("Deallocate: " + actor.name + " (Priority 0, 1, and 2) [Bonk Oceanside Table]")
2766
2767
2768 # if the actor is clearable AND isn't a bad bat, then clear it when deallocating it if it isn't already cleared
2769 elif actor.clearable == True and actor.cleared == False and actor.Id != '015B':
2770
2771 Deallocate(Heap, actor, Overlay_Dict)
2772 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2773 # CLEAR THE ACTOR
2774 Clear_Instance(actor, room)
2775
2776 else:
2777
2778 Deallocate(Heap, actor, Overlay_Dict)
2779 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2780
2781
2782 # With probability 1/2, we deallocate first and allocate second
2783 elif decision_coin_flip <= .5:
2784
2785 explosive_count = 0
2786 droppable_count = 0
2787 hookshot_exists = False
2788
2789 ##### DEALLOCATION
2790 for actor in room.priority_queue:
2791
2792 # whether or not we deallocate an actor is based off of this
2793 coin_flip = np.random.uniform(0,1)
2794
2795 ##### HARDCODE TO NOT ALLOW GOLD SKULLTULA OR SPIDER WEBS DEALLOCATE BECAUSE FASTER FOR 100%
2796 if actor.unloadable == True and Actor_Is_In_Heap(Heap, actor) == True and coin_flip > .5 and actor.Id != '0050' and actor.Id != '01F4' and actor.Id != '0125':
2797
2798
2799 if actor.Id == '00E8' or actor.name == 'Collectible (Rupee from Rupee Cluster)':
2800
2801 Deallocate(Heap, actor, Overlay_Dict)
2802 # There is at most one rupee cluster per room, so this is fine to clear it
2803 Clear_Instances('00E8', room)
2804 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2805
2806 # THESE PRIORITIES ARE HARDCODED FOR ROOM 3 OF OCEANSIDE!!!!!!!
2807 elif actor.Id == '01E7' and (actor.priority == 0 or actor.priority == 1 or actor.priority == 2):
2808
2809 table_bonk_deallocation_count = 0
2810 for entry in Heap:
2811 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 0:
2812 Deallocate(Heap, entry, Overlay_Dict)
2813 table_bonk_deallocation_count += 1
2814
2815 for entry in Heap:
2816 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 1:
2817 Deallocate(Heap, entry, Overlay_Dict)
2818 table_bonk_deallocation_count += 1
2819
2820 for entry in Heap:
2821 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 2:
2822 Deallocate(Heap, entry, Overlay_Dict)
2823 table_bonk_deallocation_count += 1
2824
2825 if table_bonk_deallocation_count != 3:
2826 print("ERROR: table_bonk_deallocation_count is not 3 (Randomized_Solver() error)")
2827
2828 action_list.append("Deallocate: " + actor.name + " (Priority 0, 1, and 2) [Bonk Oceanside Table]")
2829
2830
2831 # if the actor is clearable AND isn't a bad bat, then clear it when deallocating it if it isn't already cleared
2832 elif actor.clearable == True and actor.cleared == False and actor.Id != '015B':
2833
2834 Deallocate(Heap, actor, Overlay_Dict)
2835 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2836 # CLEAR THE ACTOR
2837 Clear_Instance(actor, room)
2838
2839 else:
2840
2841 Deallocate(Heap, actor, Overlay_Dict)
2842 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2843
2844
2845 ##### ALLOCATION
2846 for action in allocation_list:
2847
2848 # whether or not we add an action is based off of this
2849 coin_flip = np.random.uniform(0,1)
2850
2851 if action == 'Smoke' and coin_flip > .5:
2852
2853 Allocate_Smoke(Heap, room.number, Overlay_Dict)
2854 action_list.append("Allocate: Smoke")
2855
2856 elif action == 'Chu' and coin_flip > .5 and explosive_count < 3:
2857
2858 Allocate_Chu(Heap, room.number, Overlay_Dict)
2859 action_list.append("Allocate: Chu")
2860 explosive_count += 1
2861
2862 elif action == 'Arrow' and coin_flip > .5:
2863
2864 Allocate_Arrow(Heap, room.number, Overlay_Dict)
2865 action_list.append("Allocate: Arrow")
2866
2867 elif action == 'Bomb' and coin_flip > .5 and explosive_count < 3:
2868
2869 Allocate_Bomb(Heap, room.number, Overlay_Dict)
2870 action_list.append("Allocate: Bomb")
2871 explosive_count += 1
2872
2873 elif action == 'Zora Fins' and coin_flip > .5:
2874
2875 Allocate_Zora_Fins(Heap, room.number, Overlay_Dict)
2876 action_list.append("Allocate: Zora Fins")
2877
2878 elif action == 'Fish' and coin_flip > .5 and droppable_count < 2:
2879
2880 Allocate_Fish(Heap, room.number, Overlay_Dict)
2881 action_list.append("Allocate: Fish")
2882 droppable_count += 1
2883
2884 elif action == 'Bugs' and coin_flip > .5 and droppable_count < 2:
2885
2886 Allocate_Bugs(Heap, room.number, Overlay_Dict)
2887 action_list.append("Allocate: Bugs")
2888 droppable_count += 1
2889
2890 elif action == 'Hookshot' and coin_flip > .5:
2891
2892 Allocate_Hookshot(Heap, room.number, Overlay_Dict)
2893 action_list.append("Allocate: Hookshot")
2894 hookshot_exists = True
2895
2896 elif action == 'Charged Spin Attack' and (hookshot_exists is False) and coin_flip > .5:
2897
2898 Allocate_Charged_Spin_Attack(Heap, room.number, Overlay_Dict)
2899 action_list.append("Allocate: Charged Spin Attack")
2900
2901
2902 room_count += 1
2903
2904 ##### Now we load the last room in room_order_list
2905 current_room = Current_Room(room_load_list, Room_List)
2906 most_recent_transition = room_load_list[-1]
2907 Load_Room(Heap, current_room, most_recent_transition, Overlay_Dict)
2908
2909 action_list.append("Load Room: Room %d" %(current_room.number) + " with " + most_recent_transition.name + " %d" %(most_recent_transition.priority))
2910
2911
2912 """
2913
2914 Now that we have iterated through all of the rooms, we want to check to see
2915 if we are in a room with a valid grabbale object. If so, then store the addresses
2916 of all of them and make a copy of the current Heap state. From here, we want to try
2917 every possibility in the sense that we want to check every valid grabbable object
2918 in every room that we can get to and also check every superslide case that is possible
2919 (based on the binary number associated with each valid grabbable object) and then
2920 check if either the Angle or Position (input this into the function via Offset_List)
2921 line up with the chest or deku guard
2922
2923 There aren't too many possibilities from here in practice, so we might as well check them all
2924
2925 Also encode that if we superslide into a room with a chest/deku guard, then we must
2926 exit the room and then reenter it (or enter another room with a chest/deku guard; we will
2927 test every case) and after doing that we will check the chest/deku guard addresses
2928 and see if any of them line up with any of the pots that we stored the addresses of
2929
2930 We'll eventually want to write stuff to a text file, so maybe set file as an input argument
2931 or just hardcode it, not sure
2932
2933 """
2934
2935 """
2936
2937 WE MAKE THE ASSUMPTION THAT YOU LAND IN A ROOM THAT EITHER IS A ROOM
2938 WITH A CHEST/DEKU GUARD OR A ROOM THAT NEIGHBORS A ROOM WITH A CHEST/DEKU GUARD
2939 BECAUSE I CANNOT THINK OF ANY PLACES WHERE THIS WOULDN'T HAPPEN WHEN TESTING
2940 SUPERSLIDE SRM (ZORA FIN WOULD BE DIFFERENT, BUT THIS SOLVER DOESN'T TEST IT)
2941
2942 Also, before supersliding, we assume that you're in a room that either has
2943 a valid grabbable object, or is next to a room with a valid grabbable object.
2944 Of course, this means fewer possibilities are being tested in a place like
2945 oceanside, but there are already so many possibilities to test to begin with that
2946 this probably isn't a big deal for now. This also affects deku palace, but maybe
2947 I'll change this by the time I work on deku palace (because if you end in Room2,
2948 then nothing happens)
2949
2950 """
2951
2952 """
2953
2954 Nevermind some of those other comments, here is what I'm really assuming.
2955
2956 I will be assuming that if you end in a room without a valid grabbable
2957 actor, then it will search all neighbors of that room for valid grabbable
2958 actors and if none of those have valid grabbable objects then it will
2959 search all of those neighbors and choose the first one it finds (this
2960 will allow for ending in Room 2 in Deku Palace). Otherwise it does nothing
2961 (though this will never happen for the cases I plan on checking for now)
2962
2963 (*Coded)If you are in a room with a valid grabbable actor and no chest/deku guard,
2964 then we will check the addresses of all valid grabbable actors in this room
2965 and superslide into the chest room, exit and reenter it. Then we will check the address of the
2966 chest and see if it lines up with any of the pot addresses from the previous
2967 room.
2968
2969 (*Coded)If you are in a room with a valid grabbable actor AND a chest/deku guard, then
2970 you will record the valid grabbable actor addresses then superslide to exit the
2971 room and then check all neighbors of the room you enter for having a chest/deku guard
2972 and test all of them
2973
2974
2975
2976 """
2977
2978 valid_grabbable_actor_room_list = []
2979
2980 for room in Room_List:
2981 if Valid_Grabbable_In_Room(room, Grabbable_Dict) is True:
2982 valid_grabbable_actor_room_list.append(room)
2983
2984 # This gives a list of all ways we can exit our current room
2985 #transition_list_possibilities = Generate_Room_Load_Permutations(current_room, Room_List, 1)
2986
2987 ##### Case 1: there is a valid grabbable actor in the current room, but no chest/deku guard (the guard thing doesn't matter because this never happens in palace anyway)
2988 if (current_room in valid_grabbable_actor_room_list) and (Chest_In_Room(current_room) is False) and (Deku_Guard_In_Room(current_room) is False):
2989
2990 valid_pot_list = []
2991 pot_address_list = []
2992
2993 for pot in Grabbable_Dict:
2994
2995 if Actor_Is_In_Room(current_room, pot) is True:
2996 valid_pot_list.append(pot)
2997 pot_address_list.append(pot.address)
2998
2999 """
3000
3001 Now for each pot in valid_pot_list, we want to test every applicable
3002 superslide scenario
3003
3004 Before each one, we need to copy the current state and then modify the copies
3005 to check for the solution
3006
3007 """
3008
3009 for pot in valid_pot_list:
3010
3011 # both bomb and smoke loaded on superslide
3012 if Grabbable_Dict[pot][0][0] == '1':
3013
3014 action_list100 = []
3015
3016 # COPY STATE
3017 #######################################################
3018 Room_List_Copy = Copy_Room_List(Room_List)
3019 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3020
3021 room_copy_dict = {}
3022 for room in Room_List_Copy:
3023 room_copy_dict[room.number] = room
3024
3025 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3026
3027 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3028 #######################################################
3029
3030 Bomb_And_Smoke_Superslide(Heap_Copy, current_room.number, Overlay_Dict_Copy)
3031 action_list100.append("Superslide with Bomb and Smoke still allocated")
3032
3033 # The room we superslide into through the plane corresponding to the given pot
3034 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3035
3036 destination_room_copy = room_copy_dict[destination_room.number]
3037 current_room_copy = room_copy_dict[current_room.number]
3038
3039 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3040 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3041
3042 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3043 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3044
3045 # Now exit the chest room
3046 Load_Room(Heap_Copy, current_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3047 action_list100.append("Load Room: Room %d" %(current_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3048
3049 # Now reenter the chest room
3050 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3051 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3052
3053 ##### Now check for chests/deku guards
3054
3055 chest_guard_list = []
3056
3057 for entry in Heap_Copy:
3058
3059 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3060 chest_guard_list.append(entry)
3061
3062 soln_found = False
3063 for entry in chest_guard_list:
3064 if (pot.address - entry.address) in Offset_List:
3065
3066 action_list100.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3067
3068 if (pot.address - entry.address) == 0x160:
3069 angle_solution_count += 1
3070 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3071 elif (pot.address - entry.address) == 0x1F0:
3072 position_solution_count += 1
3073 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3074
3075 soln_found = True
3076
3077 if soln_found is True:
3078 total_action_list = action_list + action_list100
3079
3080 # the "a" argument is important so we don't overwrite previous solutions
3081 with open(filename, "a") as file:
3082
3083 for action in total_action_list:
3084
3085 file.write(action + "\n")
3086 file.write("-----\n")
3087
3088
3089 ##### Only smoke is loaded from superslide
3090 elif Grabbable_Dict[pot][0][1] == '1':
3091
3092 action_list010 = []
3093
3094 # COPY STATE
3095 #######################################################
3096 Room_List_Copy = Copy_Room_List(Room_List)
3097 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3098
3099 room_copy_dict = {}
3100 for room in Room_List_Copy:
3101 room_copy_dict[room.number] = room
3102
3103 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3104
3105 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3106 #######################################################
3107
3108 Allocate_Smoke(Heap_Copy, current_room.number, Overlay_Dict_Copy)
3109 action_list010.append("Superslide with Smoke still allocated")
3110
3111 # The room we superslide into through the plane corresponding to the given pot
3112 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3113
3114 destination_room_copy = room_copy_dict[destination_room.number]
3115 current_room_copy = room_copy_dict[current_room.number]
3116
3117 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3118 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3119
3120 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3121 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3122
3123 # Now exit the chest room
3124 Load_Room(Heap_Copy, current_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3125 action_list010.append("Load Room: Room %d" %(current_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3126
3127 # Now reenter the chest room
3128 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3129 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3130
3131
3132 ##### Now check for chests/deku guards
3133
3134 chest_guard_list = []
3135
3136 for entry in Heap_Copy:
3137
3138 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3139 chest_guard_list.append(entry)
3140
3141 soln_found = False
3142 for entry in chest_guard_list:
3143 if (pot.address - entry.address) in Offset_List:
3144
3145 action_list010.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3146
3147 if (pot.address - entry.address) == 0x160:
3148 angle_solution_count += 1
3149 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3150 elif (pot.address - entry.address) == 0x1F0:
3151 position_solution_count += 1
3152 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3153
3154 soln_found = True
3155
3156 if soln_found is True:
3157 total_action_list = action_list + action_list010
3158
3159 # the "a" argument is important so we don't overwrite previous solutions
3160 with open(filename, "a") as file:
3161
3162 for action in total_action_list:
3163
3164 file.write(action + "\n")
3165 file.write("-----\n")
3166
3167
3168 #### Bomb and Smoke are both unloaded
3169 elif Grabbable_Dict[pot][0][2] == '1':
3170
3171 action_list001 = []
3172
3173 # COPY STATE
3174 #######################################################
3175 Room_List_Copy = Copy_Room_List(Room_List)
3176 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3177
3178 room_copy_dict = {}
3179 for room in Room_List_Copy:
3180 room_copy_dict[room.number] = room
3181
3182 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3183
3184 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3185 #######################################################
3186
3187 # Do not allocate anything
3188 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
3189
3190 # The room we superslide into through the plane corresponding to the given pot
3191 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3192
3193 destination_room_copy = room_copy_dict[destination_room.number]
3194 current_room_copy = room_copy_dict[current_room.number]
3195
3196 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3197 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3198
3199 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3200 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3201
3202 # Now exit the chest room
3203 Load_Room(Heap_Copy, current_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3204 action_list001.append("Load Room: Room %d" %(current_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3205
3206 # Now reenter the chest room
3207 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3208 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3209
3210
3211 ##### Now check for chests/deku guards
3212
3213 chest_guard_list = []
3214
3215 for entry in Heap_Copy:
3216
3217 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3218 chest_guard_list.append(entry)
3219
3220 soln_found = False
3221 for entry in chest_guard_list:
3222 if (pot.address - entry.address) in Offset_List:
3223
3224 action_list001.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3225
3226 if (pot.address - entry.address) == 0x160:
3227 angle_solution_count += 1
3228 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3229 elif (pot.address - entry.address) == 0x1F0:
3230 position_solution_count += 1
3231 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3232
3233 soln_found = True
3234
3235 if soln_found is True:
3236 total_action_list = action_list + action_list001
3237
3238 # the "a" argument is important so we don't overwrite previous solutions
3239 with open(filename, "a") as file:
3240
3241 for action in total_action_list:
3242
3243 file.write(action + "\n")
3244 file.write("-----\n")
3245
3246
3247
3248 # Case 2: there is a valid grabbable actor in the current room AND there is a chest or deku guard
3249 elif (current_room in valid_grabbable_actor_room_list) and ((Chest_In_Room(current_room) is True) or (Deku_Guard_In_Room(current_room) is True)):
3250
3251 valid_pot_list = []
3252 pot_address_list = []
3253
3254 for pot in Grabbable_Dict:
3255
3256 if Actor_Is_In_Room(current_room, pot) is True:
3257 valid_pot_list.append(pot)
3258 pot_address_list.append(pot.address)
3259
3260
3261 """
3262
3263 Now for each pot in valid_pot_list, we want to test every applicable
3264 superslide scenario
3265
3266 Before each one, we need to copy the current state and then modify the copies
3267 to check for the solution
3268
3269 Also, for every case, we need to consider every possible room that contains
3270 a chest/deku guard that neighbors the room we just entered (meaning you
3271 will need to make copies of the copies of the state)
3272
3273 """
3274
3275 for pot in valid_pot_list:
3276
3277 # both bomb and smoke loaded on superslide
3278 if Grabbable_Dict[pot][0][0] == '1':
3279
3280 action_list100 = []
3281
3282 # COPY STATE
3283 #######################################################
3284 Room_List_Copy = Copy_Room_List(Room_List)
3285 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3286
3287 room_copy_dict = {}
3288 for room in Room_List_Copy:
3289 room_copy_dict[room.number] = room
3290
3291 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3292
3293 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3294 #######################################################
3295
3296 Bomb_And_Smoke_Superslide(Heap_Copy, current_room.number, Overlay_Dict_Copy)
3297 action_list100.append("Superslide with Bomb and Smoke still allocated")
3298
3299 # The room we superslide into through the plane corresponding to the given pot
3300 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3301
3302 destination_room_copy = room_copy_dict[destination_room.number]
3303
3304 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3305 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3306
3307 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3308 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3309
3310 """
3311
3312 Now we check all neighbors of our current room (destination_room) and for
3313 each neighbor that has a chest or deku guard in it, we will create a copy
3314 of our copy of the state, then enter each of them through each possible
3315 loading plane and then check the chest/guard addresses and see if anything
3316 lines up
3317
3318 """
3319
3320 for neighbor in Neighbors(destination_room, Room_List):
3321
3322 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3323
3324 for transition in Shared_Transitions(destination_room, neighbor):
3325
3326 # COPY STATE
3327 #######################################################
3328 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3329 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3330
3331 room_copy_dict_2 = {}
3332 for room in Room_List_Copy_2:
3333 room_copy_dict_2[room.number] = room
3334
3335 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3336
3337 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3338 #######################################################
3339
3340 action_list_2 = []
3341
3342 transition_copy = Find_Actor_Copy(transition, Room_List_Copy_2)
3343
3344 neighbor_copy = room_copy_dict_2[neighbor.number]
3345
3346 Load_Room(Heap_Copy_2, neighbor_copy, transition_copy, Overlay_Dict_Copy_2)
3347 action_list_2.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3348
3349
3350 ##### Now check for chests/deku guards
3351
3352 chest_guard_list = []
3353
3354 for entry in Heap_Copy_2:
3355
3356 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3357 chest_guard_list.append(entry)
3358
3359 soln_found = False
3360 for entry in chest_guard_list:
3361 if (pot.address - entry.address) in Offset_List:
3362
3363 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3364
3365 if (pot.address - entry.address) == 0x160:
3366 angle_solution_count += 1
3367 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3368 elif (pot.address - entry.address) == 0x1F0:
3369 position_solution_count += 1
3370 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3371
3372 soln_found = True
3373
3374 if soln_found is True:
3375 total_action_list = action_list + action_list100 + action_list_2
3376
3377 # the "a" argument is important so we don't overwrite previous solutions
3378 with open(filename, "a") as file:
3379
3380 for action in total_action_list:
3381
3382 file.write(action + "\n")
3383 file.write("-----\n")
3384
3385
3386 ##### Only smoke is loaded from superslide
3387 elif Grabbable_Dict[pot][0][1] == '1':
3388
3389 action_list010 = []
3390
3391 # COPY STATE
3392 #######################################################
3393 Room_List_Copy = Copy_Room_List(Room_List)
3394 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3395
3396 room_copy_dict = {}
3397 for room in Room_List_Copy:
3398 room_copy_dict[room.number] = room
3399
3400 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3401
3402 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3403 #######################################################
3404
3405 Allocate_Smoke(Heap_Copy, current_room.number, Overlay_Dict_Copy)
3406 action_list010.append("Superslide with Smoke still allocated")
3407
3408 # The room we superslide into through the plane corresponding to the given pot
3409 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3410
3411 destination_room_copy = room_copy_dict[destination_room.number]
3412
3413 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3414 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3415
3416 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3417 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3418
3419 """
3420
3421 Now we check all neighbors of our current room (destination_room) and for
3422 each neighbor that has a chest or deku guard in it, we will create a copy
3423 of our copy of the state, then enter each of them through each possible
3424 loading plane and then check the chest/guard addresses and see if anything
3425 lines up
3426
3427 """
3428
3429 for neighbor in Neighbors(destination_room, Room_List):
3430
3431 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3432
3433 for transition in Shared_Transitions(destination_room, neighbor):
3434
3435 # COPY STATE
3436 #######################################################
3437 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3438 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3439
3440 room_copy_dict_2 = {}
3441 for room in Room_List_Copy_2:
3442 room_copy_dict_2[room.number] = room
3443
3444 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3445
3446 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3447 #######################################################
3448
3449 action_list_2 = []
3450
3451 transition_copy = Find_Actor_Copy(transition, Room_List_Copy_2)
3452
3453 neighbor_copy = room_copy_dict_2[neighbor.number]
3454
3455 Load_Room(Heap_Copy_2, neighbor_copy, transition_copy, Overlay_Dict_Copy_2)
3456 action_list_2.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3457
3458
3459 ##### Now check for chests/deku guards
3460
3461 chest_guard_list = []
3462
3463 for entry in Heap_Copy_2:
3464
3465 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3466 chest_guard_list.append(entry)
3467
3468 soln_found = False
3469 for entry in chest_guard_list:
3470 if (pot.address - entry.address) in Offset_List:
3471
3472 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3473
3474 if (pot.address - entry.address) == 0x160:
3475 angle_solution_count += 1
3476 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3477 elif (pot.address - entry.address) == 0x1F0:
3478 position_solution_count += 1
3479 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3480
3481 soln_found = True
3482
3483 if soln_found is True:
3484 total_action_list = action_list + action_list010 + action_list_2
3485
3486 # the "a" argument is important so we don't overwrite previous solutions
3487 with open(filename, "a") as file:
3488
3489 for action in total_action_list:
3490
3491 file.write(action + "\n")
3492 file.write("-----\n")
3493
3494
3495 #### Bomb and Smoke are both unloaded
3496 elif Grabbable_Dict[pot][0][2] == '1':
3497
3498 action_list001 = []
3499
3500 # COPY STATE
3501 #######################################################
3502 Room_List_Copy = Copy_Room_List(Room_List)
3503 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3504
3505 room_copy_dict = {}
3506 for room in Room_List_Copy:
3507 room_copy_dict[room.number] = room
3508
3509 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3510
3511 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3512 #######################################################
3513
3514 # Do not allocate anything
3515 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
3516
3517 # The room we superslide into through the plane corresponding to the given pot
3518 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3519
3520 destination_room_copy = room_copy_dict[destination_room.number]
3521
3522 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3523 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3524
3525 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3526 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3527
3528 """
3529
3530 Now we check all neighbors of our current room (destination_room) and for
3531 each neighbor that has a chest or deku guard in it, we will create a copy
3532 of our copy of the state, then enter each of them through each possible
3533 loading plane and then check the chest/guard addresses and see if anything
3534 lines up
3535
3536 """
3537
3538 for neighbor in Neighbors(destination_room, Room_List):
3539
3540 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3541
3542 for transition in Shared_Transitions(destination_room, neighbor):
3543
3544 # COPY STATE
3545 #######################################################
3546 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3547 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3548
3549 room_copy_dict_2 = {}
3550 for room in Room_List_Copy_2:
3551 room_copy_dict_2[room.number] = room
3552
3553 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3554
3555 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3556 #######################################################
3557
3558 action_list_2 = []
3559
3560 transition_copy = Find_Actor_Copy(transition, Room_List_Copy_2)
3561
3562 neighbor_copy = room_copy_dict_2[neighbor.number]
3563
3564 Load_Room(Heap_Copy_2, neighbor_copy, transition_copy, Overlay_Dict_Copy_2)
3565 action_list_2.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3566
3567
3568 ##### Now check for chests/deku guards
3569
3570 chest_guard_list = []
3571
3572 for entry in Heap_Copy_2:
3573
3574 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3575 chest_guard_list.append(entry)
3576
3577 soln_found = False
3578 for entry in chest_guard_list:
3579 if (pot.address - entry.address) in Offset_List:
3580
3581 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3582
3583 if (pot.address - entry.address) == 0x160:
3584 angle_solution_count += 1
3585 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3586 elif (pot.address - entry.address) == 0x1F0:
3587 position_solution_count += 1
3588 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3589
3590 soln_found = True
3591
3592 if soln_found is True:
3593 total_action_list = action_list + action_list001 + action_list_2
3594
3595 # the "a" argument is important so we don't overwrite previous solutions
3596 with open(filename, "a") as file:
3597
3598 for action in total_action_list:
3599
3600 file.write(action + "\n")
3601 file.write("-----\n")
3602
3603
3604 ##### Case 3: there is NOT a valid grabbable actor in the current room
3605 elif (current_room not in valid_grabbable_actor_room_list):
3606
3607 for neighbor in Neighbors(current_room, Room_List):
3608
3609 ##### Valid grabbable actor in neighbor
3610 if neighbor in valid_grabbable_actor_room_list:
3611
3612
3613 # For every transition in Shared_Transitions(current_room, neighbor)
3614 for transition in Shared_Transitions(current_room, neighbor):
3615
3616 action_list_transition = []
3617
3618 ##### COPY THE STATE
3619 #######################################################
3620 Room_List_Copy = Copy_Room_List(Room_List)
3621 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3622
3623 room_copy_dict = {}
3624 for room in Room_List_Copy:
3625 room_copy_dict[room.number] = room
3626
3627 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3628
3629 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3630 #######################################################
3631
3632 ##### ENTER neighbor after copying it
3633
3634 neighbor_copy = room_copy_dict[neighbor.number]
3635 transition_copy = Find_Actor_Copy(transition, Room_List_Copy)
3636
3637 Load_Room(Heap_Copy, neighbor_copy, transition_copy, Overlay_Dict_Copy)
3638 action_list_transition.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3639
3640
3641 ##### Iterate through all pots in this room
3642
3643 valid_pot_list = []
3644 pot_address_list = []
3645
3646 for pot in Grabbable_Dict_Copy:
3647
3648 if Actor_Is_In_Room(neighbor_copy, pot) is True:
3649 valid_pot_list.append(pot)
3650 pot_address_list.append(pot.address)
3651
3652
3653
3654 # If there is a chest/guard, superslide, then check neighbors for chests/guards and test all (copy state)
3655 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3656
3657 for pot in valid_pot_list:
3658
3659 # both bomb and smoke loaded on superslide
3660 if Grabbable_Dict_Copy[pot][0][0] == '1':
3661
3662 action_list100 = []
3663
3664 # COPY STATE
3665 #######################################################
3666 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
3667 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
3668
3669 room_copy_dict_SS = {}
3670 for room in Room_List_Copy_SS:
3671 room_copy_dict_SS[room.number] = room
3672
3673 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
3674
3675 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
3676 #######################################################
3677
3678 Bomb_And_Smoke_Superslide(Heap_Copy_SS, neighbor.number, Overlay_Dict_Copy_SS)
3679 action_list100.append("Superslide with Bomb and Smoke still allocated")
3680
3681 # The room we superslide into through the plane corresponding to the given pot
3682 destination_room = Current_Room([neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
3683
3684 destination_room_copy = room_copy_dict_SS[destination_room.number]
3685
3686 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
3687 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
3688
3689 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
3690 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3691
3692 """
3693
3694 Now we check all neighbors of our current room (destination_room) and for
3695 each neighbor that has a chest or deku guard in it, we will create a copy
3696 of our copy of the state, then enter each of them through each possible
3697 loading plane and then check the chest/guard addresses and see if anything
3698 lines up
3699
3700 """
3701
3702 for bordering_room in Neighbors(destination_room, Room_List):
3703
3704 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
3705
3706 for loading_plane in Shared_Transitions(destination_room, bordering_room):
3707
3708 # COPY STATE
3709 #######################################################
3710 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
3711 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
3712
3713 room_copy_dict_2 = {}
3714 for room in Room_List_Copy_2:
3715 room_copy_dict_2[room.number] = room
3716
3717 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
3718
3719 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
3720 #######################################################
3721
3722 action_list_2 = []
3723
3724 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
3725
3726 bordering_room_copy = room_copy_dict_2[bordering_room.number]
3727
3728 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
3729 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
3730
3731
3732 ##### Now check for chests/deku guards
3733
3734 chest_guard_list = []
3735
3736 for entry in Heap_Copy_2:
3737
3738 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3739 chest_guard_list.append(entry)
3740
3741 soln_found = False
3742 for entry in chest_guard_list:
3743 if (pot.address - entry.address) in Offset_List:
3744
3745 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3746
3747 if (pot.address - entry.address) == 0x160:
3748 angle_solution_count += 1
3749 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3750 elif (pot.address - entry.address) == 0x1F0:
3751 position_solution_count += 1
3752 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3753
3754 soln_found = True
3755
3756 if soln_found is True:
3757 total_action_list = action_list + action_list_transition + action_list100 + action_list_2
3758
3759 # the "a" argument is important so we don't overwrite previous solutions
3760 with open(filename, "a") as file:
3761
3762 for action in total_action_list:
3763
3764 file.write(action + "\n")
3765 file.write("-----\n")
3766
3767
3768
3769 ##### Only smoke is loaded from superslide
3770 elif Grabbable_Dict_Copy[pot][0][1] == '1':
3771
3772 action_list010 = []
3773
3774 # COPY STATE
3775 #######################################################
3776 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
3777 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
3778
3779 room_copy_dict_SS = {}
3780 for room in Room_List_Copy_SS:
3781 room_copy_dict_SS[room.number] = room
3782
3783 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
3784
3785 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
3786 #######################################################
3787
3788 Allocate_Smoke(Heap_Copy_SS, neighbor.number, Overlay_Dict_Copy_SS)
3789 action_list010.append("Superslide with Smoke still allocated")
3790
3791 # The room we superslide into through the plane corresponding to the given pot
3792 destination_room = Current_Room([neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
3793
3794 destination_room_copy = room_copy_dict_SS[destination_room.number]
3795
3796 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
3797 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
3798
3799 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
3800 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3801
3802 """
3803
3804 Now we check all neighbors of our current room (destination_room) and for
3805 each neighbor that has a chest or deku guard in it, we will create a copy
3806 of our copy of the state, then enter each of them through each possible
3807 loading plane and then check the chest/guard addresses and see if anything
3808 lines up
3809
3810 """
3811
3812 for bordering_room in Neighbors(destination_room, Room_List):
3813
3814 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
3815
3816 for loading_plane in Shared_Transitions(destination_room, bordering_room):
3817
3818 # COPY STATE
3819 #######################################################
3820 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
3821 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
3822
3823 room_copy_dict_2 = {}
3824 for room in Room_List_Copy_2:
3825 room_copy_dict_2[room.number] = room
3826
3827 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
3828
3829 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
3830 #######################################################
3831
3832 action_list_2 = []
3833
3834 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
3835
3836 bordering_room_copy = room_copy_dict_2[bordering_room.number]
3837
3838 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
3839 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
3840
3841
3842 ##### Now check for chests/deku guards
3843
3844 chest_guard_list = []
3845
3846 for entry in Heap_Copy_2:
3847
3848 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3849 chest_guard_list.append(entry)
3850
3851 soln_found = False
3852 for entry in chest_guard_list:
3853 if (pot.address - entry.address) in Offset_List:
3854
3855 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3856
3857 if (pot.address - entry.address) == 0x160:
3858 angle_solution_count += 1
3859 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3860 elif (pot.address - entry.address) == 0x1F0:
3861 position_solution_count += 1
3862 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3863
3864 soln_found = True
3865
3866 if soln_found is True:
3867 total_action_list = action_list + action_list_transition + action_list010 + action_list_2
3868
3869 # the "a" argument is important so we don't overwrite previous solutions
3870 with open(filename, "a") as file:
3871
3872 for action in total_action_list:
3873
3874 file.write(action + "\n")
3875 file.write("-----\n")
3876
3877
3878 #### Bomb and Smoke are both unloaded
3879 elif Grabbable_Dict_Copy[pot][0][2] == '1':
3880
3881 action_list001 = []
3882
3883 # COPY STATE
3884 #######################################################
3885 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
3886 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
3887
3888 room_copy_dict_SS = {}
3889 for room in Room_List_Copy_SS:
3890 room_copy_dict_SS[room.number] = room
3891
3892 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
3893
3894 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
3895 #######################################################
3896
3897 # Do not allocate anything
3898 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
3899
3900 # The room we superslide into through the plane corresponding to the given pot
3901 destination_room = Current_Room([neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
3902
3903 destination_room_copy = room_copy_dict_SS[destination_room.number]
3904
3905 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
3906 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
3907
3908 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
3909 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3910
3911 """
3912
3913 Now we check all neighbors of our current room (destination_room) and for
3914 each neighbor that has a chest or deku guard in it, we will create a copy
3915 of our copy of the state, then enter each of them through each possible
3916 loading plane and then check the chest/guard addresses and see if anything
3917 lines up
3918
3919 """
3920
3921 for bordering_room in Neighbors(destination_room, Room_List):
3922
3923 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
3924
3925 for loading_plane in Shared_Transitions(destination_room, bordering_room):
3926
3927 # COPY STATE
3928 #######################################################
3929 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
3930 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
3931
3932 room_copy_dict_2 = {}
3933 for room in Room_List_Copy_2:
3934 room_copy_dict_2[room.number] = room
3935
3936 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
3937
3938 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
3939 #######################################################
3940
3941 action_list_2 = []
3942
3943 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
3944
3945 bordering_room_copy = room_copy_dict_2[bordering_room.number]
3946
3947 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
3948 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
3949
3950
3951 ##### Now check for chests/deku guards
3952
3953 chest_guard_list = []
3954
3955 for entry in Heap_Copy_2:
3956
3957 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3958 chest_guard_list.append(entry)
3959
3960 soln_found = False
3961 for entry in chest_guard_list:
3962 if (pot.address - entry.address) in Offset_List:
3963
3964 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
3965
3966 if (pot.address - entry.address) == 0x160:
3967 angle_solution_count += 1
3968 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3969 elif (pot.address - entry.address) == 0x1F0:
3970 position_solution_count += 1
3971 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3972
3973 soln_found = True
3974
3975 if soln_found is True:
3976 total_action_list = action_list + action_list_transition + action_list001 + action_list_2
3977
3978 # the "a" argument is important so we don't overwrite previous solutions
3979 with open(filename, "a") as file:
3980
3981 for action in total_action_list:
3982
3983 file.write(action + "\n")
3984 file.write("-----\n")
3985
3986
3987
3988 # If there isn't a chest/guard, superslide (into chest/guard room by assumption), then exit then reenter it (this case never happens in palace, so this is an okay assumption)
3989 elif Chest_In_Room(neighbor) == False and Deku_Guard_In_Room(neighbor) == False:
3990
3991 for pot in valid_pot_list:
3992
3993 # both bomb and smoke loaded on superslide
3994 if Grabbable_Dict_Copy[pot][0][0] == '1':
3995
3996 action_list100 = []
3997
3998 # COPY STATE
3999 #######################################################
4000 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4001 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4002
4003 room_copy_dict_2 = {}
4004 for room in Room_List_Copy_2:
4005 room_copy_dict_2[room.number] = room
4006
4007 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4008
4009 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4010 #######################################################
4011
4012 Bomb_And_Smoke_Superslide(Heap_Copy_2, neighbor_copy.number, Overlay_Dict_Copy_2)
4013 action_list100.append("Superslide with Bomb and Smoke still allocated")
4014
4015 # The room we superslide into through the plane corresponding to the given pot
4016 destination_room = Current_Room([neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4017
4018 destination_room_copy = room_copy_dict_2[destination_room.number]
4019 neighbor_copy_2 = room_copy_dict_2[neighbor_copy.number]
4020
4021 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4022 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4023
4024 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4025 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4026
4027 # Now exit the chest room
4028 Load_Room(Heap_Copy_2, neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4029 action_list100.append("Load Room: Room %d" %(neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4030
4031 # Now reenter the chest room
4032 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4033 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4034
4035 ##### Now check for chests/deku guards
4036
4037 chest_guard_list = []
4038
4039 for entry in Heap_Copy_2:
4040
4041 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4042 chest_guard_list.append(entry)
4043
4044 soln_found = False
4045 for entry in chest_guard_list:
4046 if (pot.address - entry.address) in Offset_List:
4047
4048 action_list100.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4049
4050 if (pot.address - entry.address) == 0x160:
4051 angle_solution_count += 1
4052 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4053 elif (pot.address - entry.address) == 0x1F0:
4054 position_solution_count += 1
4055 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4056
4057 soln_found = True
4058
4059 if soln_found is True:
4060 total_action_list = action_list + action_list_transition + action_list100
4061
4062 # the "a" argument is important so we don't overwrite previous solutions
4063 with open(filename, "a") as file:
4064
4065 for action in total_action_list:
4066
4067 file.write(action + "\n")
4068 file.write("-----\n")
4069
4070
4071
4072 ##### Only smoke is loaded from superslide
4073 elif Grabbable_Dict_Copy[pot][0][1] == '1':
4074
4075 action_list010 = []
4076
4077 # COPY STATE
4078 #######################################################
4079 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4080 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4081
4082 room_copy_dict_2 = {}
4083 for room in Room_List_Copy_2:
4084 room_copy_dict_2[room.number] = room
4085
4086 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4087
4088 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4089 #######################################################
4090
4091 Allocate_Smoke(Heap_Copy_2, neighbor_copy.number, Overlay_Dict_Copy_2)
4092 action_list010.append("Superslide with Smoke still allocated")
4093
4094 # The room we superslide into through the plane corresponding to the given pot
4095 destination_room = Current_Room([neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4096
4097 destination_room_copy = room_copy_dict_2[destination_room.number]
4098 neighbor_copy_2 = room_copy_dict_2[neighbor_copy.number]
4099
4100 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4101 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4102
4103 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4104 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4105
4106 # Now exit the chest room
4107 Load_Room(Heap_Copy_2, neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4108 action_list010.append("Load Room: Room %d" %(neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4109
4110 # Now reenter the chest room
4111 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4112 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4113
4114 ##### Now check for chests/deku guards
4115
4116 chest_guard_list = []
4117
4118 for entry in Heap_Copy_2:
4119
4120 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4121 chest_guard_list.append(entry)
4122
4123 soln_found = False
4124 for entry in chest_guard_list:
4125 if (pot.address - entry.address) in Offset_List:
4126
4127 action_list010.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4128
4129 if (pot.address - entry.address) == 0x160:
4130 angle_solution_count += 1
4131 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4132 elif (pot.address - entry.address) == 0x1F0:
4133 position_solution_count += 1
4134 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4135
4136 soln_found = True
4137
4138 if soln_found is True:
4139 total_action_list = action_list + action_list_transition + action_list010
4140
4141 # the "a" argument is important so we don't overwrite previous solutions
4142 with open(filename, "a") as file:
4143
4144 for action in total_action_list:
4145
4146 file.write(action + "\n")
4147 file.write("-----\n")
4148
4149
4150
4151 #### Bomb and Smoke are both unloaded
4152 elif Grabbable_Dict_Copy[pot][0][2] == '1':
4153
4154 action_list001 = []
4155
4156 # COPY STATE
4157 #######################################################
4158 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4159 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4160
4161 room_copy_dict_2 = {}
4162 for room in Room_List_Copy_2:
4163 room_copy_dict_2[room.number] = room
4164
4165 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4166
4167 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4168 #######################################################
4169
4170 # Do not allocate anything
4171 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
4172
4173 # The room we superslide into through the plane corresponding to the given pot
4174 destination_room = Current_Room([neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4175
4176 destination_room_copy = room_copy_dict_2[destination_room.number]
4177 neighbor_copy_2 = room_copy_dict_2[neighbor_copy.number]
4178
4179 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4180 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4181
4182 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4183 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4184
4185 # Now exit the chest room
4186 Load_Room(Heap_Copy_2, neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4187 action_list001.append("Load Room: Room %d" %(neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4188
4189 # Now reenter the chest room
4190 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4191 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4192
4193 ##### Now check for chests/deku guards
4194
4195 chest_guard_list = []
4196
4197 for entry in Heap_Copy_2:
4198
4199 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4200 chest_guard_list.append(entry)
4201
4202 soln_found = False
4203 for entry in chest_guard_list:
4204 if (pot.address - entry.address) in Offset_List:
4205
4206 action_list001.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4207
4208 if (pot.address - entry.address) == 0x160:
4209 angle_solution_count += 1
4210 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4211 elif (pot.address - entry.address) == 0x1F0:
4212 position_solution_count += 1
4213 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4214
4215 soln_found = True
4216
4217 if soln_found is True:
4218 total_action_list = action_list + action_list_transition + action_list001
4219
4220 # the "a" argument is important so we don't overwrite previous solutions
4221 with open(filename, "a") as file:
4222
4223 for action in total_action_list:
4224
4225 file.write(action + "\n")
4226 file.write("-----\n")
4227
4228
4229 ##### No valid grabbable actor in neighbor
4230 elif neighbor not in valid_grabbable_actor_room_list:
4231
4232 for new_neighbor in Neighbors(neighbor, Room_List):
4233
4234 # if new neighbor has a valid grabbable actor... (Otherwise, we do nothing)
4235 if new_neighbor in valid_grabbable_actor_room_list:
4236
4237
4238 for neighbor_transition in Shared_Transitions(current_room, neighbor):
4239 for new_neighbor_transition in Shared_Transitions(neighbor, new_neighbor):
4240
4241 action_list_transition = []
4242
4243 ##### COPY THE STATE
4244 #######################################################
4245 Room_List_Copy = Copy_Room_List(Room_List)
4246 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
4247
4248 room_copy_dict = {}
4249 for room in Room_List_Copy:
4250 room_copy_dict[room.number] = room
4251
4252 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
4253
4254 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
4255 #######################################################
4256
4257 neighbor_copy = room_copy_dict[neighbor.number]
4258 neighbor_transition_copy = Find_Actor_Copy(neighbor_transition, Room_List_Copy)
4259
4260 new_neighbor_copy = room_copy_dict[new_neighbor.number]
4261 new_neighbor_transition_copy = Find_Actor_Copy(new_neighbor_transition, Room_List_Copy)
4262
4263 ##### ENTER neighbor
4264
4265 Load_Room(Heap_Copy, neighbor_copy, neighbor_transition_copy, Overlay_Dict_Copy)
4266 action_list_transition.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + neighbor_transition_copy.name + " %d" %(neighbor_transition_copy.priority))
4267
4268 ##### ENTER new_neighbor
4269
4270 Load_Room(Heap_Copy, new_neighbor_copy, new_neighbor_transition_copy, Overlay_Dict_Copy)
4271 action_list_transition.append("Load Room: Room %d" %(new_neighbor_copy.number) + " with " + new_neighbor_transition_copy.name + " %d" %(new_neighbor_transition_copy.priority))
4272
4273
4274 ##### Iterate through all pots in this room
4275
4276 valid_pot_list = []
4277 pot_address_list = []
4278
4279 for pot in Grabbable_Dict_Copy:
4280
4281 if Actor_Is_In_Room(new_neighbor_copy, pot) is True:
4282 valid_pot_list.append(pot)
4283 pot_address_list.append(pot.address)
4284
4285 # If there is a chest/guard, superslide, then check neighbors for chests/guards and test all (copy state)
4286 if Chest_In_Room(new_neighbor) == True or Deku_Guard_In_Room(new_neighbor) == True:
4287
4288 for pot in valid_pot_list:
4289
4290 # both bomb and smoke loaded on superslide
4291 if Grabbable_Dict_Copy[pot][0][0] == '1':
4292
4293 action_list100 = []
4294
4295 # COPY STATE
4296 #######################################################
4297 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
4298 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
4299
4300 room_copy_dict_SS = {}
4301 for room in Room_List_Copy_SS:
4302 room_copy_dict_SS[room.number] = room
4303
4304 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
4305
4306 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
4307 #######################################################
4308
4309 Bomb_And_Smoke_Superslide(Heap_Copy_SS, new_neighbor.number, Overlay_Dict_Copy_SS)
4310 action_list100.append("Superslide with Bomb and Smoke still allocated")
4311
4312 # The room we superslide into through the plane corresponding to the given pot
4313 destination_room = Current_Room([new_neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4314
4315 destination_room_copy = room_copy_dict_SS[destination_room.number]
4316
4317 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
4318 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
4319
4320 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
4321 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4322
4323 """
4324
4325 Now we check all neighbors of our current room (destination_room) and for
4326 each neighbor that has a chest or deku guard in it, we will create a copy
4327 of our copy of the state, then enter each of them through each possible
4328 loading plane and then check the chest/guard addresses and see if anything
4329 lines up
4330
4331 """
4332
4333 for bordering_room in Neighbors(destination_room, Room_List):
4334
4335 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
4336
4337 for loading_plane in Shared_Transitions(destination_room, bordering_room):
4338
4339 # COPY STATE
4340 #######################################################
4341 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
4342 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
4343
4344 room_copy_dict_2 = {}
4345 for room in Room_List_Copy_2:
4346 room_copy_dict_2[room.number] = room
4347
4348 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
4349
4350 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
4351 #######################################################
4352
4353 action_list_2 = []
4354
4355 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
4356
4357 bordering_room_copy = room_copy_dict_2[bordering_room.number]
4358
4359 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
4360 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
4361
4362
4363 ##### Now check for chests/deku guards
4364
4365 chest_guard_list = []
4366
4367 for entry in Heap_Copy_2:
4368
4369 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4370 chest_guard_list.append(entry)
4371
4372 soln_found = False
4373 for entry in chest_guard_list:
4374 if (pot.address - entry.address) in Offset_List:
4375
4376 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4377
4378 if (pot.address - entry.address) == 0x160:
4379 angle_solution_count += 1
4380 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4381 elif (pot.address - entry.address) == 0x1F0:
4382 position_solution_count += 1
4383 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4384
4385 soln_found = True
4386
4387 if soln_found is True:
4388 total_action_list = action_list + action_list_transition + action_list100 + action_list_2
4389
4390 # the "a" argument is important so we don't overwrite previous solutions
4391 with open(filename, "a") as file:
4392
4393 for action in total_action_list:
4394
4395 file.write(action + "\n")
4396 file.write("-----\n")
4397
4398
4399
4400 ##### Only smoke is loaded from superslide
4401 elif Grabbable_Dict_Copy[pot][0][1] == '1':
4402
4403 action_list010 = []
4404
4405 # COPY STATE
4406 #######################################################
4407 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
4408 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
4409
4410 room_copy_dict_SS = {}
4411 for room in Room_List_Copy_SS:
4412 room_copy_dict_SS[room.number] = room
4413
4414 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
4415
4416 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
4417 #######################################################
4418
4419 Allocate_Smoke(Heap_Copy_SS, new_neighbor.number, Overlay_Dict_Copy_SS)
4420 action_list010.append("Superslide with Smoke still allocated")
4421
4422 # The room we superslide into through the plane corresponding to the given pot
4423 destination_room = Current_Room([new_neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4424
4425 destination_room_copy = room_copy_dict_SS[destination_room.number]
4426
4427 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
4428 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
4429
4430 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
4431 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4432
4433 """
4434
4435 Now we check all neighbors of our current room (destination_room) and for
4436 each neighbor that has a chest or deku guard in it, we will create a copy
4437 of our copy of the state, then enter each of them through each possible
4438 loading plane and then check the chest/guard addresses and see if anything
4439 lines up
4440
4441 """
4442
4443 for bordering_room in Neighbors(destination_room, Room_List):
4444
4445 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
4446
4447 for loading_plane in Shared_Transitions(destination_room, bordering_room):
4448
4449 # COPY STATE
4450 #######################################################
4451 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
4452 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
4453
4454 room_copy_dict_2 = {}
4455 for room in Room_List_Copy_2:
4456 room_copy_dict_2[room.number] = room
4457
4458 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
4459
4460 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
4461 #######################################################
4462
4463 action_list_2 = []
4464
4465 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
4466
4467 bordering_room_copy = room_copy_dict_2[bordering_room.number]
4468
4469 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
4470 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
4471
4472
4473 ##### Now check for chests/deku guards
4474
4475 chest_guard_list = []
4476
4477 for entry in Heap_Copy_2:
4478
4479 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4480 chest_guard_list.append(entry)
4481
4482 soln_found = False
4483 for entry in chest_guard_list:
4484 if (pot.address - entry.address) in Offset_List:
4485
4486 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4487
4488 if (pot.address - entry.address) == 0x160:
4489 angle_solution_count += 1
4490 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4491 elif (pot.address - entry.address) == 0x1F0:
4492 position_solution_count += 1
4493 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4494
4495 soln_found = True
4496
4497 if soln_found is True:
4498 total_action_list = action_list + action_list_transition + action_list010 + action_list_2
4499
4500 # the "a" argument is important so we don't overwrite previous solutions
4501 with open(filename, "a") as file:
4502
4503 for action in total_action_list:
4504
4505 file.write(action + "\n")
4506 file.write("-----\n")
4507
4508
4509 #### Bomb and Smoke are both unloaded
4510 elif Grabbable_Dict_Copy[pot][0][2] == '1':
4511
4512 action_list001 = []
4513
4514 # COPY STATE
4515 #######################################################
4516 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
4517 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
4518
4519 room_copy_dict_SS = {}
4520 for room in Room_List_Copy_SS:
4521 room_copy_dict_SS[room.number] = room
4522
4523 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
4524
4525 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
4526 #######################################################
4527
4528 # Do not allocate anything
4529 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
4530
4531 # The room we superslide into through the plane corresponding to the given pot
4532 destination_room = Current_Room([new_neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4533
4534 destination_room_copy = room_copy_dict_SS[destination_room.number]
4535
4536 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
4537 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
4538
4539 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
4540 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4541
4542 """
4543
4544 Now we check all neighbors of our current room (destination_room) and for
4545 each neighbor that has a chest or deku guard in it, we will create a copy
4546 of our copy of the state, then enter each of them through each possible
4547 loading plane and then check the chest/guard addresses and see if anything
4548 lines up
4549
4550 """
4551
4552 for bordering_room in Neighbors(destination_room, Room_List):
4553
4554 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
4555
4556 for loading_plane in Shared_Transitions(destination_room, bordering_room):
4557
4558 # COPY STATE
4559 #######################################################
4560 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
4561 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
4562
4563 room_copy_dict_2 = {}
4564 for room in Room_List_Copy_2:
4565 room_copy_dict_2[room.number] = room
4566
4567 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
4568
4569 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
4570 #######################################################
4571
4572 action_list_2 = []
4573
4574 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
4575
4576 bordering_room_copy = room_copy_dict_2[bordering_room.number]
4577
4578 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
4579 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
4580
4581
4582 ##### Now check for chests/deku guards
4583
4584 chest_guard_list = []
4585
4586 for entry in Heap_Copy_2:
4587
4588 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4589 chest_guard_list.append(entry)
4590
4591 soln_found = False
4592 for entry in chest_guard_list:
4593 if (pot.address - entry.address) in Offset_List:
4594
4595 action_list_2.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4596
4597 if (pot.address - entry.address) == 0x160:
4598 angle_solution_count += 1
4599 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4600 elif (pot.address - entry.address) == 0x1F0:
4601 position_solution_count += 1
4602 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4603
4604 soln_found = True
4605
4606 if soln_found is True:
4607 total_action_list = action_list + action_list_transition + action_list001 + action_list_2
4608
4609 # the "a" argument is important so we don't overwrite previous solutions
4610 with open(filename, "a") as file:
4611
4612 for action in total_action_list:
4613
4614 file.write(action + "\n")
4615 file.write("-----\n")
4616
4617
4618
4619 # If there isn't a chest/guard, superslide (into chest/guard room by assumption), then exit then reenter it (this case never happens in palace, so this is an okay assumption)
4620 elif Chest_In_Room(new_neighbor) == False and Deku_Guard_In_Room(new_neighbor) == False:
4621
4622 for pot in valid_pot_list:
4623
4624 # both bomb and smoke loaded on superslide
4625 if Grabbable_Dict_Copy[pot][0][0] == '1':
4626
4627 action_list100 = []
4628
4629 # COPY STATE
4630 #######################################################
4631 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4632 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4633
4634 room_copy_dict_2 = {}
4635 for room in Room_List_Copy_2:
4636 room_copy_dict_2[room.number] = room
4637
4638 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4639
4640 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4641 #######################################################
4642
4643 Bomb_And_Smoke_Superslide(Heap_Copy_2, new_neighbor_copy.number, Overlay_Dict_Copy_2)
4644 action_list100.append("Superslide with Bomb and Smoke still allocated")
4645
4646 # The room we superslide into through the plane corresponding to the given pot
4647 destination_room = Current_Room([new_neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4648
4649 destination_room_copy = room_copy_dict_2[destination_room.number]
4650 new_neighbor_copy_2 = room_copy_dict_2[new_neighbor_copy.number]
4651
4652 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4653 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4654
4655 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4656 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4657
4658 # Now exit the chest room
4659 Load_Room(Heap_Copy_2, new_neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4660 action_list100.append("Load Room: Room %d" %(new_neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4661
4662 # Now reenter the chest room
4663 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4664 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4665
4666 ##### Now check for chests/deku guards
4667
4668 chest_guard_list = []
4669
4670 for entry in Heap_Copy_2:
4671
4672 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4673 chest_guard_list.append(entry)
4674
4675 soln_found = False
4676 for entry in chest_guard_list:
4677 if (pot.address - entry.address) in Offset_List:
4678
4679 action_list100.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4680
4681 if (pot.address - entry.address) == 0x160:
4682 angle_solution_count += 1
4683 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4684 elif (pot.address - entry.address) == 0x1F0:
4685 position_solution_count += 1
4686 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4687
4688 soln_found = True
4689
4690 if soln_found is True:
4691 total_action_list = action_list + action_list_transition + action_list100
4692
4693 # the "a" argument is important so we don't overwrite previous solutions
4694 with open(filename, "a") as file:
4695
4696 for action in total_action_list:
4697
4698 file.write(action + "\n")
4699 file.write("-----\n")
4700
4701
4702
4703 ##### Only smoke is loaded from superslide
4704 elif Grabbable_Dict_Copy[pot][0][1] == '1':
4705
4706 action_list010 = []
4707
4708 # COPY STATE
4709 #######################################################
4710 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4711 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4712
4713 room_copy_dict_2 = {}
4714 for room in Room_List_Copy_2:
4715 room_copy_dict_2[room.number] = room
4716
4717 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4718
4719 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4720 #######################################################
4721
4722 Allocate_Smoke(Heap_Copy_2, new_neighbor_copy.number, Overlay_Dict_Copy_2)
4723 action_list010.append("Superslide with Smoke still allocated")
4724
4725 # The room we superslide into through the plane corresponding to the given pot
4726 destination_room = Current_Room([new_neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4727
4728 destination_room_copy = room_copy_dict_2[destination_room.number]
4729 new_neighbor_copy_2 = room_copy_dict_2[new_neighbor_copy.number]
4730
4731 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4732 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4733
4734 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4735 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4736
4737 # Now exit the chest room
4738 Load_Room(Heap_Copy_2, new_neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4739 action_list010.append("Load Room: Room %d" %(new_neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4740
4741 # Now reenter the chest room
4742 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4743 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4744
4745 ##### Now check for chests/deku guards
4746
4747 chest_guard_list = []
4748
4749 for entry in Heap_Copy_2:
4750
4751 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4752 chest_guard_list.append(entry)
4753
4754 soln_found = False
4755 for entry in chest_guard_list:
4756 if (pot.address - entry.address) in Offset_List:
4757
4758 action_list010.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4759
4760 if (pot.address - entry.address) == 0x160:
4761 angle_solution_count += 1
4762 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4763 elif (pot.address - entry.address) == 0x1F0:
4764 position_solution_count += 1
4765 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4766
4767 soln_found = True
4768
4769 if soln_found is True:
4770 total_action_list = action_list + action_list_transition + action_list010
4771
4772 # the "a" argument is important so we don't overwrite previous solutions
4773 with open(filename, "a") as file:
4774
4775 for action in total_action_list:
4776
4777 file.write(action + "\n")
4778 file.write("-----\n")
4779
4780
4781
4782 #### Bomb and Smoke are both unloaded
4783 elif Grabbable_Dict_Copy[pot][0][2] == '1':
4784
4785 action_list001 = []
4786
4787 # COPY STATE
4788 #######################################################
4789 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4790 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4791
4792 room_copy_dict_2 = {}
4793 for room in Room_List_Copy_2:
4794 room_copy_dict_2[room.number] = room
4795
4796 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4797
4798 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4799 #######################################################
4800
4801 # Do not allocate anything
4802 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
4803
4804 # The room we superslide into through the plane corresponding to the given pot
4805 destination_room = Current_Room([new_neighbor_copy, Grabbable_Dict_Copy[pot][1]], Room_List_Copy)
4806
4807 destination_room_copy = room_copy_dict_2[destination_room.number]
4808 new_neighbor_copy_2 = room_copy_dict_2[new_neighbor_copy.number]
4809
4810 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4811 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4812
4813 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4814 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4815
4816 # Now exit the chest room
4817 Load_Room(Heap_Copy_2, new_neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4818 action_list001.append("Load Room: Room %d" %(new_neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4819
4820 # Now reenter the chest room
4821 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4822 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4823
4824 ##### Now check for chests/deku guards
4825
4826 chest_guard_list = []
4827
4828 for entry in Heap_Copy_2:
4829
4830 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4831 chest_guard_list.append(entry)
4832
4833 soln_found = False
4834 for entry in chest_guard_list:
4835 if (pot.address - entry.address) in Offset_List:
4836
4837 action_list001.append("SOLUTION: " + pot.name + " (Priority %d)" %(pot.priority) + " from Room %d" %(pot.room_number) + " lines up with " + entry.name + " (Priority %d)" %(entry.priority) + " from Room %d" %(entry.room_number) + " with offset: " + hex(pot.address - entry.address))
4838
4839 if (pot.address - entry.address) == 0x160:
4840 angle_solution_count += 1
4841 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4842 elif (pot.address - entry.address) == 0x1F0:
4843 position_solution_count += 1
4844 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4845
4846 soln_found = True
4847
4848 if soln_found is True:
4849 total_action_list = action_list + action_list_transition + action_list001
4850
4851 # the "a" argument is important so we don't overwrite previous solutions
4852 with open(filename, "a") as file:
4853
4854 for action in total_action_list:
4855
4856 file.write(action + "\n")
4857 file.write("-----\n")
4858
4859
4860
4861
4862###############################################################################
4863###############################################################################
4864###############################################################################
4865###############################################################################
4866###############################################################################
4867###############################################################################
4868###############################################################################
4869###############################################################################
4870###############################################################################
4871###############################################################################
4872###############################################################################
4873###############################################################################
4874###############################################################################
4875###############################################################################
4876###############################################################################
4877###############################################################################
4878###############################################################################
4879###############################################################################
4880###############################################################################
4881###############################################################################
4882###############################################################################
4883###############################################################################
4884###############################################################################
4885###############################################################################
4886###############################################################################
4887###############################################################################
4888###############################################################################
4889###############################################################################
4890###############################################################################
4891###############################################################################
4892###############################################################################
4893###############################################################################
4894###############################################################################
4895###############################################################################
4896###############################################################################
4897###############################################################################
4898###############################################################################
4899###############################################################################
4900###############################################################################
4901###############################################################################
4902###############################################################################
4903###############################################################################
4904###############################################################################
4905###############################################################################
4906###############################################################################
4907###############################################################################
4908###############################################################################
4909###############################################################################
4910
4911
4912
4913
4914
4915
4916
4917"""
4918
4919 Before proceeding, we should define all of the transitions we plan on passing through
4920
4921 Since "Beneath the Graveyard" is relatively simple and I currently only want to consider
4922 passing through a single plane, I will just define Plane_1 to be the plane shared between
4923 Room0 and Room1
4924
4925 This loading plane happens the be the second element in Room0_queue, so I will define it based on that
4926
4927"""
4928
4929Oceanside_Plane_0 = Oceanside_Room3_queue[0]
4930
4931
4932
4933
4934
4935"""
4936
4937 Grabbable_dict is a dictionary of the grabbable actors (such as pots) that
4938 we want to attempt to use for superslide SRM where the keys are the grabbable
4939 actors and the values are lists with 3-bit strings where each bit means:
4940
4941 100 : Possible to enter Plane with both Bomb and Smoke loaded
4942 010 : Possible to enter Plane with Smoke loaded, but no Bomb loaded
4943 001 : Possible to enter Plane with no Smoke loaded
4944
4945 and Transitions, where the transitions are the ones you can superslide through
4946
4947
4948"""
4949
4950Oceanside_Grabbable_dict = {
4951 Oceanside_Room3_queue[6] : ['010', Oceanside_Plane_0],
4952 Oceanside_Room3_queue[7] : ['010', Oceanside_Plane_0]
4953 }
4954
4955
4956Hardcoded_Allocation_List_0 = [
4957 'Smoke',
4958 'Chu',
4959 'Chu',
4960 'Chu',
4961 'Arrow',
4962 'Arrow',
4963 'Arrow',
4964 'Arrow',
4965 'Arrow',
4966 'Bomb',
4967 'Bomb',
4968 'Bomb',
4969 'Zora Fins',
4970 'Fish',
4971 'Fish',
4972 'Bugs',
4973 'Bugs',
4974 'Hookshot',
4975 'Charged Spin Attack'
4976 ]
4977
4978Hardcoded_Allocation_List_2 = [
4979 'Smoke',
4980 'Arrow',
4981 'Arrow',
4982 'Arrow',
4983 'Arrow',
4984 'Arrow',
4985 'Bomb',
4986 'Bomb',
4987 'Bomb',
4988 'Hookshot',
4989 'Charged Spin Attack'
4990 ]
4991
4992
4993
4994save_path = "C:\\Users\\doldop\\Documents\\Bizhawk RAM Watch\\scripts\\"
4995name_of_file = "14solver"
4996complete_name = save_path + name_of_file + ".txt"
4997
4998Heap = [Node(0x40B140, node_size), Node(0x5FFFFF, node_size)]
4999
5000Randomized_Solver(Oceanside_Room3, Oceanside_Room_List, 5, Hardcoded_Allocation_List_0, Oceanside_Grabbable_dict, Overlay_dict, complete_name, [0x160, 0x1F0], Heap)
5001
5002
5003"""
5004
5005SOME ASSUMPTIONS ABOUT THIS SCRIPT:
5006
5007 - THE SOLVER AUTOMATICALLY CLEARS ALL BAD BATS AT THE START
5008
5009 - WE DO NOT DEALLOCATE WEBS OR GOLD SKULLTULAS IN OCEANSIDE BECAUSE WE WANT
5010 A SETUP THAT DOES NOT NEED SONG OF TIME STORAGE TO DO REPEATEDLY. EVEN IF IT
5011 ALLOWED DEALLOCATIONG GOLD SKULLTULAS, IT DOES NOT ACCOUNT FOR THE TOKENS AND
5012 IT ASSUMES DEALLOCATING A GOLD SKULLTULA IS EQUIVALENT TO PICKING UP ITS TOKEN
5013
5014 - WE ASSUME THAT WE ALWAYS PERFORM THE DEALLOCATION STEPS BEFORE THE ALLOCATION
5015 STEPS BECAUSE IT IS EASIER TO DEAL WITH SOLUTIONS WITH THIS QUALITY
5016
5017 - THIS SCRIPT HARDCODES HOW WE DEALLOCATE THE 01E7 BONK ACTORS FOR THE OCEANSIDE
5018 ROOM 3 TABLE
5019
5020 TODO: (DEKU PALACE CONTEXT) DEFINE ALLOCATION LISTS FOR SPECIFIC ROOMS
5021 (NOT SURE OF BEST WAY TO DO THIS YET) ALSO WANT TO ASSERT THAT A POT NEEDS
5022 TO BREAK BEFORE PALACE SUPERSLIDE FOR ONE OF THE POTS (I THINK; NEEDS TESTING)
5023
5024
5025
5026
5027"""