· 6 years ago · Dec 21, 2019, 08:20 AM
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 else:
2386
2387 Load_Room(Heap, room, transition, Overlay_Dict)
2388
2389 action_list.append("Load Room: Room %d" %(room.number) + " with " + transition.name + " %d" %(transition.priority))
2390
2391 """
2392
2393 Now randomly (with some chosen distribution) choose things to allocate
2394 and/or things to deallocate (in your current room). Make it so that
2395 you can only choose a specific action once. For example, if allocation_list
2396 has ['bomb', 'bomb, 'bomb', 'fish'] in it, then make it so you can only use
2397 fish once, but you can use bomb 3 times
2398
2399 Somehow try to encode that hookshot/charged spin are mutually exclusive
2400 and that if either of them exist then they must be the last action
2401
2402 Allow yourself to deallocate things before allocating things even
2403 though it might be impossible or slow in some cases
2404
2405 """
2406
2407 # Do a coinflip to decide between allocating or deallocating first
2408 decision_coin_flip = np.random.uniform(0,1)
2409
2410 # With probability 1/2, we allocate first and deallocate second
2411 # if we allocate first, don't allow 'Charged Spin Attack'
2412 if decision_coin_flip > .5:
2413
2414 explosive_count = 0
2415 droppable_count = 0
2416
2417 ##### ALLOCATION
2418 for action in allocation_list:
2419
2420 # whether or not we add an action is based off of this
2421 coin_flip = decision_coin_flip = np.random.uniform(0,1)
2422
2423 if action == 'Smoke' and coin_flip > .5:
2424
2425 Allocate_Smoke(Heap, room.number, Overlay_Dict)
2426 action_list.append("Allocate: Smoke")
2427
2428 elif action == 'Chu' and coin_flip > .5 and explosive_count < 3:
2429
2430 Allocate_Chu(Heap, room.number, Overlay_Dict)
2431 action_list.append("Allocate: Chu")
2432 explosive_count += 1
2433
2434 elif action == 'Arrow' and coin_flip > .5:
2435
2436 Allocate_Arrow(Heap, room.number, Overlay_Dict)
2437 action_list.append("Allocate: Arrow")
2438
2439 elif action == 'Bomb' and coin_flip > .5 and explosive_count < 3:
2440
2441 Allocate_Bomb(Heap, room.number, Overlay_Dict)
2442 action_list.append("Allocate: Bomb")
2443 explosive_count += 1
2444
2445 elif action == 'Zora Fins' and coin_flip > .5:
2446
2447 Allocate_Zora_Fins(Heap, room.number, Overlay_Dict)
2448 action_list.append("Allocate: Zora Fins")
2449
2450 elif action == 'Fish' and coin_flip > .5 and droppable_count < 2:
2451
2452 Allocate_Fish(Heap, room.number, Overlay_Dict)
2453 action_list.append("Allocate: Fish")
2454 droppable_count += 1
2455
2456 elif action == 'Bugs' and coin_flip > .5 and droppable_count < 2:
2457
2458 Allocate_Bugs(Heap, room.number, Overlay_Dict)
2459 action_list.append("Allocate: Bugs")
2460 droppable_count += 1
2461
2462 elif action == 'Hookshot' and coin_flip > .5:
2463
2464 Allocate_Hookshot(Heap, room.number, Overlay_Dict)
2465 action_list.append("Allocate: Hookshot")
2466
2467 ### We don't include 'Charged Spin Attack' in this
2468
2469 ##### DEALLOCATION
2470 for actor in room.priority_queue:
2471
2472 # whether or not we deallocate an actor is based off of this
2473 coin_flip = decision_coin_flip = np.random.uniform(0,1)
2474
2475 ##### HARDCODE TO NOT ALLOW GOLD SKULLTULA OR SPIDER WEBS DEALLOCATE BECAUSE FASTER FOR 100%
2476 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':
2477
2478
2479 if actor.Id == '00E8' or actor.name == 'Collectible (Rupee from Rupee Cluster)':
2480
2481 Deallocate(Heap, actor, Overlay_Dict)
2482 # There is at most one rupee cluster per room, so this is fine to clear it
2483 Clear_Instances('00E8', room)
2484 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2485
2486 # THESE PRIORITIES ARE HARDCODED FOR ROOM 3 OF OCEANSIDE!!!!!!!
2487 elif actor.Id == '01E7' and (actor.priority == 0 or actor.priority == 1 or actor.priority == 2):
2488
2489 table_bonk_deallocation_count = 0
2490 for entry in Heap:
2491 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 0:
2492 Deallocate(Heap, entry, Overlay_Dict)
2493 table_bonk_deallocation_count += 1
2494
2495 for entry in Heap:
2496 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 1:
2497 Deallocate(Heap, entry, Overlay_Dict)
2498 table_bonk_deallocation_count += 1
2499
2500 for entry in Heap:
2501 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 2:
2502 Deallocate(Heap, entry, Overlay_Dict)
2503 table_bonk_deallocation_count += 1
2504
2505 if table_bonk_deallocation_count != 3:
2506 print("ERROR: table_bonk_deallocation_count is not 3 (Randomized_Solver() error)")
2507
2508 action_list.append("Deallocate: " + actor.name + " (Priority 0, 1, and 2) [Bonk Oceanside Table]")
2509
2510
2511 # if the actor is clearable AND isn't a bad bat, then clear it when deallocating it if it isn't already cleared
2512 elif actor.clearable == True and actor.cleared == False and actor.Id != '015B':
2513
2514 Deallocate(Heap, actor, Overlay_Dict)
2515 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2516 # CLEAR THE ACTOR
2517 Clear_Instance(actor, room)
2518
2519 else:
2520
2521 Deallocate(Heap, actor, Overlay_Dict)
2522 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2523
2524
2525 # With probability 1/2, we deallocate first and allocate second
2526 elif decision_coin_flip <= .5:
2527
2528 explosive_count = 0
2529 droppable_count = 0
2530 hookshot_exists = False
2531
2532 ##### DEALLOCATION
2533 for actor in room.priority_queue:
2534
2535 # whether or not we deallocate an actor is based off of this
2536 coin_flip = decision_coin_flip = np.random.uniform(0,1)
2537
2538 ##### HARDCODE TO NOT ALLOW GOLD SKULLTULA OR SPIDER WEBS DEALLOCATE BECAUSE FASTER FOR 100%
2539 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':
2540
2541
2542 if actor.Id == '00E8' or actor.name == 'Collectible (Rupee from Rupee Cluster)':
2543
2544 Deallocate(Heap, actor, Overlay_Dict)
2545 # There is at most one rupee cluster per room, so this is fine to clear it
2546 Clear_Instances('00E8', room)
2547 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2548
2549 # THESE PRIORITIES ARE HARDCODED FOR ROOM 3 OF OCEANSIDE!!!!!!!
2550 elif actor.Id == '01E7' and (actor.priority == 0 or actor.priority == 1 or actor.priority == 2):
2551
2552 table_bonk_deallocation_count = 0
2553 for entry in Heap:
2554 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 0:
2555 Deallocate(Heap, entry, Overlay_Dict)
2556 table_bonk_deallocation_count += 1
2557
2558 for entry in Heap:
2559 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 1:
2560 Deallocate(Heap, entry, Overlay_Dict)
2561 table_bonk_deallocation_count += 1
2562
2563 for entry in Heap:
2564 if type(entry) == Actor and entry.Id == '01E7' and entry.priority == 2:
2565 Deallocate(Heap, entry, Overlay_Dict)
2566 table_bonk_deallocation_count += 1
2567
2568 if table_bonk_deallocation_count != 3:
2569 print("ERROR: table_bonk_deallocation_count is not 3 (Randomized_Solver() error)")
2570
2571 action_list.append("Deallocate: " + actor.name + " (Priority 0, 1, and 2) [Bonk Oceanside Table]")
2572
2573
2574 # if the actor is clearable AND isn't a bad bat, then clear it when deallocating it if it isn't already cleared
2575 elif actor.clearable == True and actor.cleared == False and actor.Id != '015B':
2576
2577 Deallocate(Heap, actor, Overlay_Dict)
2578 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2579 # CLEAR THE ACTOR
2580 Clear_Instance(actor, room)
2581
2582 else:
2583
2584 Deallocate(Heap, actor, Overlay_Dict)
2585 action_list.append("Deallocate: " + actor.name + " (Priority %d)" %(actor.priority))
2586
2587
2588 ##### ALLOCATION
2589 for action in allocation_list:
2590
2591 # whether or not we add an action is based off of this
2592 coin_flip = decision_coin_flip = np.random.uniform(0,1)
2593
2594 if action == 'Smoke' and coin_flip > .5:
2595
2596 Allocate_Smoke(Heap, room.number, Overlay_Dict)
2597 action_list.append("Allocate: Smoke")
2598
2599 elif action == 'Chu' and coin_flip > .5 and explosive_count < 3:
2600
2601 Allocate_Chu(Heap, room.number, Overlay_Dict)
2602 action_list.append("Allocate: Chu")
2603 explosive_count += 1
2604
2605 elif action == 'Arrow' and coin_flip > .5:
2606
2607 Allocate_Arrow(Heap, room.number, Overlay_Dict)
2608 action_list.append("Allocate: Arrow")
2609
2610 elif action == 'Bomb' and coin_flip > .5 and explosive_count < 3:
2611
2612 Allocate_Bomb(Heap, room.number, Overlay_Dict)
2613 action_list.append("Allocate: Bomb")
2614 explosive_count += 1
2615
2616 elif action == 'Zora Fins' and coin_flip > .5:
2617
2618 Allocate_Zora_Fins(Heap, room.number, Overlay_Dict)
2619 action_list.append("Allocate: Zora Fins")
2620
2621 elif action == 'Fish' and coin_flip > .5 and droppable_count < 2:
2622
2623 Allocate_Fish(Heap, room.number, Overlay_Dict)
2624 action_list.append("Allocate: Fish")
2625 droppable_count += 1
2626
2627 elif action == 'Bugs' and coin_flip > .5 and droppable_count < 2:
2628
2629 Allocate_Bugs(Heap, room.number, Overlay_Dict)
2630 action_list.append("Allocate: Bugs")
2631 droppable_count += 1
2632
2633 elif action == 'Hookshot' and coin_flip > .5:
2634
2635 Allocate_Hookshot(Heap, room.number, Overlay_Dict)
2636 action_list.append("Allocate: Hookshot")
2637 hookshot_exists = True
2638
2639 elif action == 'Charged Spin Attack' and (hookshot_exists is False) and coin_flip > .5:
2640
2641 Allocate_Charged_Spin_Attack(Heap, room.number, Overlay_Dict)
2642 action_list.append("Allocate: Charged Spin Attack")
2643
2644
2645 room_count += 1
2646
2647 ##### Now we load the last room in room_order_list
2648 current_room = Current_Room(room_load_list, Room_List)
2649 most_recent_transition = room_load_list[-1]
2650 Load_Room(Heap, current_room, most_recent_transition, Overlay_Dict)
2651
2652 action_list.append("Load Room: Room %d" %(current_room.number) + " with " + most_recent_transition.name + " %d" %(most_recent_transition.priority))
2653
2654
2655 """
2656
2657 Now that we have iterated through all of the rooms, we want to check to see
2658 if we are in a room with a valid grabbale object. If so, then store the addresses
2659 of all of them and make a copy of the current Heap state. From here, we want to try
2660 every possibility in the sense that we want to check every valid grabbable object
2661 in every room that we can get to and also check every superslide case that is possible
2662 (based on the binary number associated with each valid grabbable object) and then
2663 check if either the Angle or Position (input this into the function via Offset_List)
2664 line up with the chest or deku guard
2665
2666 There aren't too many possibilities from here in practice, so we might as well check them all
2667
2668 Also encode that if we superslide into a room with a chest/deku guard, then we must
2669 exit the room and then reenter it (or enter another room with a chest/deku guard; we will
2670 test every case) and after doing that we will check the chest/deku guard addresses
2671 and see if any of them line up with any of the pots that we stored the addresses of
2672
2673 We'll eventually want to write stuff to a text file, so maybe set file as an input argument
2674 or just hardcode it, not sure
2675
2676 """
2677
2678 """
2679
2680 WE MAKE THE ASSUMPTION THAT YOU LAND IN A ROOM THAT EITHER IS A ROOM
2681 WITH A CHEST/DEKU GUARD OR A ROOM THAT NEIGHBORS A ROOM WITH A CHEST/DEKU GUARD
2682 BECAUSE I CANNOT THINK OF ANY PLACES WHERE THIS WOULDN'T HAPPEN WHEN TESTING
2683 SUPERSLIDE SRM (ZORA FIN WOULD BE DIFFERENT, BUT THIS SOLVER DOESN'T TEST IT)
2684
2685 Also, before supersliding, we assume that you're in a room that either has
2686 a valid grabbable object, or is next to a room with a valid grabbable object.
2687 Of course, this means fewer possibilities are being tested in a place like
2688 oceanside, but there are already so many possibilities to test to begin with that
2689 this probably isn't a big deal for now. This also affects deku palace, but maybe
2690 I'll change this by the time I work on deku palace (because if you end in Room2,
2691 then nothing happens)
2692
2693 """
2694
2695 """
2696
2697 Nevermind some of those other comments, here is what I'm really assuming.
2698
2699 I will be assuming that if you end in a room without a valid grabbable
2700 actor, then it will search all neighbors of that room for valid grabbable
2701 actors and if none of those have valid grabbable objects then it will
2702 search all of those neighbors and choose the first one it finds (this
2703 will allow for ending in Room 2 in Deku Palace). Otherwise it does nothing
2704 (though this will never happen for the cases I plan on checking for now)
2705
2706 (*Coded)If you are in a room with a valid grabbable actor and no chest/deku guard,
2707 then we will check the addresses of all valid grabbable actors in this room
2708 and superslide into the chest room, exit and reenter it. Then we will check the address of the
2709 chest and see if it lines up with any of the pot addresses from the previous
2710 room.
2711
2712 (*Coded)If you are in a room with a valid grabbable actor AND a chest/deku guard, then
2713 you will record the valid grabbable actor addresses then superslide to exit the
2714 room and then check all neighbors of the room you enter for having a chest/deku guard
2715 and test all of them
2716
2717
2718
2719 """
2720
2721 valid_grabbable_actor_room_list = []
2722
2723 for room in Room_List:
2724 if Valid_Grabbable_In_Room(room, Grabbable_Dict) is True:
2725 valid_grabbable_actor_room_list.append(room)
2726
2727 # This gives a list of all ways we can exit our current room
2728 #transition_list_possibilities = Generate_Room_Load_Permutations(current_room, Room_List, 1)
2729
2730 ##### 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)
2731 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):
2732
2733 valid_pot_list = []
2734 pot_address_list = []
2735
2736 for pot in Grabbable_Dict:
2737
2738 if Actor_Is_In_Room(current_room, pot) is True:
2739 valid_pot_list.append(pot)
2740 pot_address_list.append(pot.address)
2741
2742 """
2743
2744 Now for each pot in valid_pot_list, we want to test every applicable
2745 superslide scenario
2746
2747 Before each one, we need to copy the current state and then modify the copies
2748 to check for the solution
2749
2750 """
2751
2752 for pot in valid_pot_list:
2753
2754 # both bomb and smoke loaded on superslide
2755 if Grabbable_Dict[pot][0][0] == '1':
2756
2757 action_list100 = []
2758
2759 # COPY STATE
2760 #######################################################
2761 Room_List_Copy = Copy_Room_List(Room_List)
2762 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
2763
2764 room_copy_dict = {}
2765 for room in Room_List_Copy:
2766 room_copy_dict[room.number] = room
2767
2768 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
2769
2770 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
2771 #######################################################
2772
2773 Bomb_And_Smoke_Superslide(Heap_Copy, current_room.number, Overlay_Dict_Copy)
2774 action_list100.append("Superslide with Bomb and Smoke still allocated")
2775
2776 # The room we superslide into through the plane corresponding to the given pot
2777 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
2778
2779 destination_room_copy = room_copy_dict[destination_room.number]
2780 current_room_copy = room_copy_dict[current_room.number]
2781
2782 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
2783 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
2784
2785 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2786 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2787
2788 # Now exit the chest room
2789 Load_Room(Heap_Copy, current_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2790 action_list100.append("Load Room: Room %d" %(current_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2791
2792 # Now reenter the chest room
2793 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2794 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2795
2796 ##### Now check for chests/deku guards
2797
2798 chest_guard_list = []
2799
2800 for entry in Heap_Copy:
2801
2802 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
2803 chest_guard_list.append(entry)
2804
2805 soln_found = False
2806 for entry in chest_guard_list:
2807 if (pot.address - entry.address) in Offset_List:
2808
2809 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))
2810
2811 if (pot.address - entry.address) == 0x160:
2812 angle_solution_count += 1
2813 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
2814 elif (pot.address - entry.address) == 0x1F0:
2815 position_solution_count += 1
2816 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
2817
2818 soln_found = True
2819
2820 if soln_found is True:
2821 total_action_list = action_list + action_list100
2822
2823 # the "a" argument is important so we don't overwrite previous solutions
2824 with open(filename, "a") as file:
2825
2826 for action in total_action_list:
2827
2828 file.write(action + "\n")
2829 file.write("-----\n")
2830
2831
2832 ##### Only smoke is loaded from superslide
2833 elif Grabbable_Dict[pot][0][1] == '1':
2834
2835 action_list010 = []
2836
2837 # COPY STATE
2838 #######################################################
2839 Room_List_Copy = Copy_Room_List(Room_List)
2840 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
2841
2842 room_copy_dict = {}
2843 for room in Room_List_Copy:
2844 room_copy_dict[room.number] = room
2845
2846 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
2847
2848 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
2849 #######################################################
2850
2851 Allocate_Smoke(Heap_Copy, current_room.number, Overlay_Dict_Copy)
2852 action_list010.append("Superslide with Smoke still allocated")
2853
2854 # The room we superslide into through the plane corresponding to the given pot
2855 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
2856
2857 destination_room_copy = room_copy_dict[destination_room.number]
2858 current_room_copy = room_copy_dict[current_room.number]
2859
2860 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
2861 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
2862
2863 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2864 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2865
2866 # Now exit the chest room
2867 Load_Room(Heap_Copy, current_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2868 action_list010.append("Load Room: Room %d" %(current_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2869
2870 # Now reenter the chest room
2871 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2872 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2873
2874
2875 ##### Now check for chests/deku guards
2876
2877 chest_guard_list = []
2878
2879 for entry in Heap_Copy:
2880
2881 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
2882 chest_guard_list.append(entry)
2883
2884 soln_found = False
2885 for entry in chest_guard_list:
2886 if (pot.address - entry.address) in Offset_List:
2887
2888 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))
2889
2890 if (pot.address - entry.address) == 0x160:
2891 angle_solution_count += 1
2892 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
2893 elif (pot.address - entry.address) == 0x1F0:
2894 position_solution_count += 1
2895 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
2896
2897 soln_found = True
2898
2899 if soln_found is True:
2900 total_action_list = action_list + action_list010
2901
2902 # the "a" argument is important so we don't overwrite previous solutions
2903 with open(filename, "a") as file:
2904
2905 for action in total_action_list:
2906
2907 file.write(action + "\n")
2908 file.write("-----\n")
2909
2910
2911 #### Bomb and Smoke are both unloaded
2912 elif Grabbable_Dict[pot][0][2] == '1':
2913
2914 action_list001 = []
2915
2916 # COPY STATE
2917 #######################################################
2918 Room_List_Copy = Copy_Room_List(Room_List)
2919 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
2920
2921 room_copy_dict = {}
2922 for room in Room_List_Copy:
2923 room_copy_dict[room.number] = room
2924
2925 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
2926
2927 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
2928 #######################################################
2929
2930 # Do not allocate anything
2931 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
2932
2933 # The room we superslide into through the plane corresponding to the given pot
2934 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
2935
2936 destination_room_copy = room_copy_dict[destination_room.number]
2937 current_room_copy = room_copy_dict[current_room.number]
2938
2939 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
2940 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
2941
2942 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2943 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2944
2945 # Now exit the chest room
2946 Load_Room(Heap_Copy, current_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2947 action_list001.append("Load Room: Room %d" %(current_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2948
2949 # Now reenter the chest room
2950 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
2951 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
2952
2953
2954 ##### Now check for chests/deku guards
2955
2956 chest_guard_list = []
2957
2958 for entry in Heap_Copy:
2959
2960 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
2961 chest_guard_list.append(entry)
2962
2963 soln_found = False
2964 for entry in chest_guard_list:
2965 if (pot.address - entry.address) in Offset_List:
2966
2967 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))
2968
2969 if (pot.address - entry.address) == 0x160:
2970 angle_solution_count += 1
2971 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
2972 elif (pot.address - entry.address) == 0x1F0:
2973 position_solution_count += 1
2974 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
2975
2976 soln_found = True
2977
2978 if soln_found is True:
2979 total_action_list = action_list + action_list001
2980
2981 # the "a" argument is important so we don't overwrite previous solutions
2982 with open(filename, "a") as file:
2983
2984 for action in total_action_list:
2985
2986 file.write(action + "\n")
2987 file.write("-----\n")
2988
2989
2990
2991 # Case 2: there is a valid grabbable actor in the current room AND there is a chest or deku guard
2992 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)):
2993
2994 valid_pot_list = []
2995 pot_address_list = []
2996
2997 for pot in Grabbable_Dict:
2998
2999 if Actor_Is_In_Room(current_room, pot) is True:
3000 valid_pot_list.append(pot)
3001 pot_address_list.append(pot.address)
3002
3003
3004 """
3005
3006 Now for each pot in valid_pot_list, we want to test every applicable
3007 superslide scenario
3008
3009 Before each one, we need to copy the current state and then modify the copies
3010 to check for the solution
3011
3012 Also, for every case, we need to consider every possible room that contains
3013 a chest/deku guard that neighbors the room we just entered (meaning you
3014 will need to make copies of the copies of the state)
3015
3016 """
3017
3018 for pot in valid_pot_list:
3019
3020 # both bomb and smoke loaded on superslide
3021 if Grabbable_Dict[pot][0][0] == '1':
3022
3023 action_list100 = []
3024
3025 # COPY STATE
3026 #######################################################
3027 Room_List_Copy = Copy_Room_List(Room_List)
3028 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3029
3030 room_copy_dict = {}
3031 for room in Room_List_Copy:
3032 room_copy_dict[room.number] = room
3033
3034 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3035
3036 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3037 #######################################################
3038
3039 Bomb_And_Smoke_Superslide(Heap_Copy, current_room.number, Overlay_Dict_Copy)
3040 action_list100.append("Superslide with Bomb and Smoke still allocated")
3041
3042 # The room we superslide into through the plane corresponding to the given pot
3043 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3044
3045 destination_room_copy = room_copy_dict[destination_room.number]
3046
3047 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3048 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3049
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 """
3054
3055 Now we check all neighbors of our current room (destination_room) and for
3056 each neighbor that has a chest or deku guard in it, we will create a copy
3057 of our copy of the state, then enter each of them through each possible
3058 loading plane and then check the chest/guard addresses and see if anything
3059 lines up
3060
3061 """
3062
3063 for neighbor in Neighbors(destination_room, Room_List):
3064
3065 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3066
3067 for transition in Shared_Transitions(destination_room, neighbor):
3068
3069 # COPY STATE
3070 #######################################################
3071 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3072 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3073
3074 room_copy_dict_2 = {}
3075 for room in Room_List_Copy_2:
3076 room_copy_dict_2[room.number] = room
3077
3078 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3079
3080 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3081 #######################################################
3082
3083 action_list_2 = []
3084
3085 transition_copy = Find_Actor_Copy(transition, Room_List_Copy_2)
3086
3087 neighbor_copy = room_copy_dict_2[neighbor.number]
3088
3089 Load_Room(Heap_Copy_2, neighbor_copy, transition_copy, Overlay_Dict_Copy_2)
3090 action_list_2.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3091
3092
3093 ##### Now check for chests/deku guards
3094
3095 chest_guard_list = []
3096
3097 for entry in Heap_Copy_2:
3098
3099 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3100 chest_guard_list.append(entry)
3101
3102 soln_found = False
3103 for entry in chest_guard_list:
3104 if (pot.address - entry.address) in Offset_List:
3105
3106 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))
3107
3108 if (pot.address - entry.address) == 0x160:
3109 angle_solution_count += 1
3110 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3111 elif (pot.address - entry.address) == 0x1F0:
3112 position_solution_count += 1
3113 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3114
3115 soln_found = True
3116
3117 if soln_found is True:
3118 total_action_list = action_list + action_list100 + action_list_2
3119
3120 # the "a" argument is important so we don't overwrite previous solutions
3121 with open(filename, "a") as file:
3122
3123 for action in total_action_list:
3124
3125 file.write(action + "\n")
3126 file.write("-----\n")
3127
3128
3129 ##### Only smoke is loaded from superslide
3130 elif Grabbable_Dict[pot][0][1] == '1':
3131
3132 action_list010 = []
3133
3134 # COPY STATE
3135 #######################################################
3136 Room_List_Copy = Copy_Room_List(Room_List)
3137 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3138
3139 room_copy_dict = {}
3140 for room in Room_List_Copy:
3141 room_copy_dict[room.number] = room
3142
3143 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3144
3145 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3146 #######################################################
3147
3148 Allocate_Smoke(Heap_Copy, current_room.number, Overlay_Dict_Copy)
3149 action_list010.append("Superslide with Smoke still allocated")
3150
3151 # The room we superslide into through the plane corresponding to the given pot
3152 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3153
3154 destination_room_copy = room_copy_dict[destination_room.number]
3155
3156 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3157 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3158
3159 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3160 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3161
3162 """
3163
3164 Now we check all neighbors of our current room (destination_room) and for
3165 each neighbor that has a chest or deku guard in it, we will create a copy
3166 of our copy of the state, then enter each of them through each possible
3167 loading plane and then check the chest/guard addresses and see if anything
3168 lines up
3169
3170 """
3171
3172 for neighbor in Neighbors(destination_room, Room_List):
3173
3174 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3175
3176 for transition in Shared_Transitions(destination_room, neighbor):
3177
3178 # COPY STATE
3179 #######################################################
3180 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3181 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3182
3183 room_copy_dict_2 = {}
3184 for room in Room_List_Copy_2:
3185 room_copy_dict_2[room.number] = room
3186
3187 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3188
3189 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3190 #######################################################
3191
3192 action_list_2 = []
3193
3194 transition_copy = Find_Actor_Copy(transition, Room_List_Copy_2)
3195
3196 neighbor_copy = room_copy_dict_2[neighbor.number]
3197
3198 Load_Room(Heap_Copy_2, neighbor_copy, transition_copy, Overlay_Dict_Copy_2)
3199 action_list_2.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3200
3201
3202 ##### Now check for chests/deku guards
3203
3204 chest_guard_list = []
3205
3206 for entry in Heap_Copy_2:
3207
3208 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3209 chest_guard_list.append(entry)
3210
3211 soln_found = False
3212 for entry in chest_guard_list:
3213 if (pot.address - entry.address) in Offset_List:
3214
3215 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))
3216
3217 if (pot.address - entry.address) == 0x160:
3218 angle_solution_count += 1
3219 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3220 elif (pot.address - entry.address) == 0x1F0:
3221 position_solution_count += 1
3222 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3223
3224 soln_found = True
3225
3226 if soln_found is True:
3227 total_action_list = action_list + action_list010 + action_list_2
3228
3229 # the "a" argument is important so we don't overwrite previous solutions
3230 with open(filename, "a") as file:
3231
3232 for action in total_action_list:
3233
3234 file.write(action + "\n")
3235 file.write("-----\n")
3236
3237
3238 #### Bomb and Smoke are both unloaded
3239 elif Grabbable_Dict[pot][0][2] == '1':
3240
3241 action_list001 = []
3242
3243 # COPY STATE
3244 #######################################################
3245 Room_List_Copy = Copy_Room_List(Room_List)
3246 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3247
3248 room_copy_dict = {}
3249 for room in Room_List_Copy:
3250 room_copy_dict[room.number] = room
3251
3252 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3253
3254 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3255 #######################################################
3256
3257 # Do not allocate anything
3258 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
3259
3260 # The room we superslide into through the plane corresponding to the given pot
3261 destination_room = Current_Room([current_room, Grabbable_Dict[pot][1]], Room_List)
3262
3263 destination_room_copy = room_copy_dict[destination_room.number]
3264
3265 pot_copy = Find_Actor_Copy(pot, Room_List_Copy)
3266 superslide_transition_copy = Grabbable_Dict_Copy[pot_copy][1]
3267
3268 Load_Room(Heap_Copy, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy)
3269 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3270
3271 """
3272
3273 Now we check all neighbors of our current room (destination_room) and for
3274 each neighbor that has a chest or deku guard in it, we will create a copy
3275 of our copy of the state, then enter each of them through each possible
3276 loading plane and then check the chest/guard addresses and see if anything
3277 lines up
3278
3279 """
3280
3281 for neighbor in Neighbors(destination_room, Room_List):
3282
3283 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3284
3285 for transition in Shared_Transitions(destination_room, neighbor):
3286
3287 # COPY STATE
3288 #######################################################
3289 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3290 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3291
3292 room_copy_dict_2 = {}
3293 for room in Room_List_Copy_2:
3294 room_copy_dict_2[room.number] = room
3295
3296 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3297
3298 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3299 #######################################################
3300
3301 action_list_2 = []
3302
3303 transition_copy = Find_Actor_Copy(transition, Room_List_Copy_2)
3304
3305 neighbor_copy = room_copy_dict_2[neighbor.number]
3306
3307 Load_Room(Heap_Copy_2, neighbor_copy, transition_copy, Overlay_Dict_Copy_2)
3308 action_list_2.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3309
3310
3311 ##### Now check for chests/deku guards
3312
3313 chest_guard_list = []
3314
3315 for entry in Heap_Copy_2:
3316
3317 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3318 chest_guard_list.append(entry)
3319
3320 soln_found = False
3321 for entry in chest_guard_list:
3322 if (pot.address - entry.address) in Offset_List:
3323
3324 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))
3325
3326 if (pot.address - entry.address) == 0x160:
3327 angle_solution_count += 1
3328 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3329 elif (pot.address - entry.address) == 0x1F0:
3330 position_solution_count += 1
3331 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3332
3333 soln_found = True
3334
3335 if soln_found is True:
3336 total_action_list = action_list + action_list001 + action_list_2
3337
3338 # the "a" argument is important so we don't overwrite previous solutions
3339 with open(filename, "a") as file:
3340
3341 for action in total_action_list:
3342
3343 file.write(action + "\n")
3344 file.write("-----\n")
3345
3346
3347 ##### Case 3: there is NOT a valid grabbable actor in the current room
3348 elif (current_room not in valid_grabbable_actor_room_list):
3349
3350 for neighbor in Neighbors(current_room, Room_List):
3351
3352 ##### Valid grabbable actor in neighbor
3353 if neighbor in valid_grabbable_actor_room_list:
3354
3355
3356 ##### Iterate through all pots in this room
3357
3358 valid_pot_list = []
3359 pot_address_list = []
3360
3361 for pot in Grabbable_Dict:
3362
3363 if Actor_Is_In_Room(neighbor, pot) is True:
3364 valid_pot_list.append(pot)
3365 pot_address_list.append(pot.address)
3366
3367 # For every transition in Shared_Transitions(current_room, neighbor)
3368 for transition in Shared_Transitions(current_room, neighbor):
3369
3370 action_list_transition = []
3371
3372 ##### COPY THE STATE
3373 #######################################################
3374 Room_List_Copy = Copy_Room_List(Room_List)
3375 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3376
3377 room_copy_dict = {}
3378 for room in Room_List_Copy:
3379 room_copy_dict[room.number] = room
3380
3381 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
3382
3383 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
3384 #######################################################
3385
3386 ##### ENTER neighbor after copying it
3387
3388 neighbor_copy = room_copy_dict[neighbor.number]
3389 transition_copy = Find_Actor_Copy(transition, Room_List_Copy)
3390
3391 Load_Room(Heap_Copy, neighbor_copy, transition_copy, Overlay_Dict_Copy)
3392 action_list_transition.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + transition_copy.name + " %d" %(transition_copy.priority))
3393
3394
3395 # If there is a chest/guard, superslide, then check neighbors for chests/guards and test all (copy state)
3396 if Chest_In_Room(neighbor) == True or Deku_Guard_In_Room(neighbor) == True:
3397
3398 for pot in valid_pot_list:
3399
3400 # both bomb and smoke loaded on superslide
3401 if Grabbable_Dict[pot][0][0] == '1':
3402
3403 action_list100 = []
3404
3405 # COPY STATE
3406 #######################################################
3407 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
3408 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
3409
3410 room_copy_dict_SS = {}
3411 for room in Room_List_Copy_SS:
3412 room_copy_dict_SS[room.number] = room
3413
3414 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
3415
3416 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
3417 #######################################################
3418
3419 Bomb_And_Smoke_Superslide(Heap_Copy_SS, neighbor.number, Overlay_Dict_Copy_SS)
3420 action_list100.append("Superslide with Bomb and Smoke still allocated")
3421
3422 # The room we superslide into through the plane corresponding to the given pot
3423 destination_room = Current_Room([neighbor, Grabbable_Dict[pot][1]], Room_List)
3424
3425 destination_room_copy = room_copy_dict_SS[destination_room.number]
3426
3427 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
3428 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
3429
3430 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
3431 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3432
3433 """
3434
3435 Now we check all neighbors of our current room (destination_room) and for
3436 each neighbor that has a chest or deku guard in it, we will create a copy
3437 of our copy of the state, then enter each of them through each possible
3438 loading plane and then check the chest/guard addresses and see if anything
3439 lines up
3440
3441 """
3442
3443 for bordering_room in Neighbors(destination_room, Room_List):
3444
3445 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
3446
3447 for loading_plane in Shared_Transitions(destination_room, bordering_room):
3448
3449 # COPY STATE
3450 #######################################################
3451 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
3452 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
3453
3454 room_copy_dict_2 = {}
3455 for room in Room_List_Copy_2:
3456 room_copy_dict_2[room.number] = room
3457
3458 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
3459
3460 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
3461 #######################################################
3462
3463 action_list_2 = []
3464
3465 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
3466
3467 bordering_room_copy = room_copy_dict_2[bordering_room.number]
3468
3469 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
3470 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
3471
3472
3473 ##### Now check for chests/deku guards
3474
3475 chest_guard_list = []
3476
3477 for entry in Heap_Copy_2:
3478
3479 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3480 chest_guard_list.append(entry)
3481
3482 soln_found = False
3483 for entry in chest_guard_list:
3484 if (pot.address - entry.address) in Offset_List:
3485
3486 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))
3487
3488 if (pot.address - entry.address) == 0x160:
3489 angle_solution_count += 1
3490 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3491 elif (pot.address - entry.address) == 0x1F0:
3492 position_solution_count += 1
3493 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3494
3495 soln_found = True
3496
3497 if soln_found is True:
3498 total_action_list = action_list + action_list_transition + action_list100 + action_list_2
3499
3500 # the "a" argument is important so we don't overwrite previous solutions
3501 with open(filename, "a") as file:
3502
3503 for action in total_action_list:
3504
3505 file.write(action + "\n")
3506 file.write("-----\n")
3507
3508
3509
3510 ##### Only smoke is loaded from superslide
3511 elif Grabbable_Dict[pot][0][1] == '1':
3512
3513 action_list010 = []
3514
3515 # COPY STATE
3516 #######################################################
3517 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
3518 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
3519
3520 room_copy_dict_SS = {}
3521 for room in Room_List_Copy_SS:
3522 room_copy_dict_SS[room.number] = room
3523
3524 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
3525
3526 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
3527 #######################################################
3528
3529 Allocate_Smoke(Heap_Copy_SS, neighbor.number, Overlay_Dict_Copy_SS)
3530 action_list010.append("Superslide with Smoke still allocated")
3531
3532 # The room we superslide into through the plane corresponding to the given pot
3533 destination_room = Current_Room([neighbor, Grabbable_Dict[pot][1]], Room_List)
3534
3535 destination_room_copy = room_copy_dict_SS[destination_room.number]
3536
3537 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
3538 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
3539
3540 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
3541 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3542
3543 """
3544
3545 Now we check all neighbors of our current room (destination_room) and for
3546 each neighbor that has a chest or deku guard in it, we will create a copy
3547 of our copy of the state, then enter each of them through each possible
3548 loading plane and then check the chest/guard addresses and see if anything
3549 lines up
3550
3551 """
3552
3553 for bordering_room in Neighbors(destination_room, Room_List):
3554
3555 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
3556
3557 for loading_plane in Shared_Transitions(destination_room, bordering_room):
3558
3559 # COPY STATE
3560 #######################################################
3561 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
3562 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
3563
3564 room_copy_dict_2 = {}
3565 for room in Room_List_Copy_2:
3566 room_copy_dict_2[room.number] = room
3567
3568 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
3569
3570 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
3571 #######################################################
3572
3573 action_list_2 = []
3574
3575 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
3576
3577 bordering_room_copy = room_copy_dict_2[bordering_room.number]
3578
3579 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
3580 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
3581
3582
3583 ##### Now check for chests/deku guards
3584
3585 chest_guard_list = []
3586
3587 for entry in Heap_Copy_2:
3588
3589 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3590 chest_guard_list.append(entry)
3591
3592 soln_found = False
3593 for entry in chest_guard_list:
3594 if (pot.address - entry.address) in Offset_List:
3595
3596 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))
3597
3598 if (pot.address - entry.address) == 0x160:
3599 angle_solution_count += 1
3600 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3601 elif (pot.address - entry.address) == 0x1F0:
3602 position_solution_count += 1
3603 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3604
3605 soln_found = True
3606
3607 if soln_found is True:
3608 total_action_list = action_list + action_list_transition + action_list010 + action_list_2
3609
3610 # the "a" argument is important so we don't overwrite previous solutions
3611 with open(filename, "a") as file:
3612
3613 for action in total_action_list:
3614
3615 file.write(action + "\n")
3616 file.write("-----\n")
3617
3618
3619 #### Bomb and Smoke are both unloaded
3620 elif Grabbable_Dict[pot][0][2] == '1':
3621
3622 action_list001 = []
3623
3624 # COPY STATE
3625 #######################################################
3626 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
3627 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
3628
3629 room_copy_dict_SS = {}
3630 for room in Room_List_Copy_SS:
3631 room_copy_dict_SS[room.number] = room
3632
3633 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
3634
3635 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
3636 #######################################################
3637
3638 # Do not allocate anything
3639 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
3640
3641 # The room we superslide into through the plane corresponding to the given pot
3642 destination_room = Current_Room([neighbor, Grabbable_Dict[pot][1]], Room_List)
3643
3644 destination_room_copy = room_copy_dict_SS[destination_room.number]
3645
3646 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
3647 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
3648
3649 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
3650 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3651
3652 """
3653
3654 Now we check all neighbors of our current room (destination_room) and for
3655 each neighbor that has a chest or deku guard in it, we will create a copy
3656 of our copy of the state, then enter each of them through each possible
3657 loading plane and then check the chest/guard addresses and see if anything
3658 lines up
3659
3660 """
3661
3662 for bordering_room in Neighbors(destination_room, Room_List):
3663
3664 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
3665
3666 for loading_plane in Shared_Transitions(destination_room, bordering_room):
3667
3668 # COPY STATE
3669 #######################################################
3670 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
3671 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
3672
3673 room_copy_dict_2 = {}
3674 for room in Room_List_Copy_2:
3675 room_copy_dict_2[room.number] = room
3676
3677 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
3678
3679 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
3680 #######################################################
3681
3682 action_list_2 = []
3683
3684 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
3685
3686 bordering_room_copy = room_copy_dict_2[bordering_room.number]
3687
3688 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
3689 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
3690
3691
3692 ##### Now check for chests/deku guards
3693
3694 chest_guard_list = []
3695
3696 for entry in Heap_Copy_2:
3697
3698 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3699 chest_guard_list.append(entry)
3700
3701 soln_found = False
3702 for entry in chest_guard_list:
3703 if (pot.address - entry.address) in Offset_List:
3704
3705 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))
3706
3707 if (pot.address - entry.address) == 0x160:
3708 angle_solution_count += 1
3709 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3710 elif (pot.address - entry.address) == 0x1F0:
3711 position_solution_count += 1
3712 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3713
3714 soln_found = True
3715
3716 if soln_found is True:
3717 total_action_list = action_list + action_list_transition + action_list001 + action_list_2
3718
3719 # the "a" argument is important so we don't overwrite previous solutions
3720 with open(filename, "a") as file:
3721
3722 for action in total_action_list:
3723
3724 file.write(action + "\n")
3725 file.write("-----\n")
3726
3727
3728
3729 # 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)
3730 elif Chest_In_Room(neighbor) == False and Deku_Guard_In_Room(neighbor) == False:
3731
3732 for pot in valid_pot_list:
3733
3734 # both bomb and smoke loaded on superslide
3735 if Grabbable_Dict[pot][0][0] == '1':
3736
3737 action_list100 = []
3738
3739 # COPY STATE
3740 #######################################################
3741 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3742 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3743
3744 room_copy_dict_2 = {}
3745 for room in Room_List_Copy_2:
3746 room_copy_dict_2[room.number] = room
3747
3748 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3749
3750 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3751 #######################################################
3752
3753 Bomb_And_Smoke_Superslide(Heap_Copy_2, neighbor_copy.number, Overlay_Dict_Copy_2)
3754 action_list100.append("Superslide with Bomb and Smoke still allocated")
3755
3756 # The room we superslide into through the plane corresponding to the given pot
3757 destination_room = Current_Room([neighbor, Grabbable_Dict[pot][1]], Room_List)
3758
3759 destination_room_copy = room_copy_dict_2[destination_room.number]
3760 neighbor_copy_2 = room_copy_dict_2[neighbor_copy.number]
3761
3762 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
3763 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
3764
3765 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
3766 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3767
3768 # Now exit the chest room
3769 Load_Room(Heap_Copy_2, neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
3770 action_list100.append("Load Room: Room %d" %(neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3771
3772 # Now reenter the chest room
3773 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
3774 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3775
3776 ##### Now check for chests/deku guards
3777
3778 chest_guard_list = []
3779
3780 for entry in Heap_Copy_2:
3781
3782 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3783 chest_guard_list.append(entry)
3784
3785 soln_found = False
3786 for entry in chest_guard_list:
3787 if (pot.address - entry.address) in Offset_List:
3788
3789 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))
3790
3791 if (pot.address - entry.address) == 0x160:
3792 angle_solution_count += 1
3793 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3794 elif (pot.address - entry.address) == 0x1F0:
3795 position_solution_count += 1
3796 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3797
3798 soln_found = True
3799
3800 if soln_found is True:
3801 total_action_list = action_list + action_list_transition + action_list100
3802
3803 # the "a" argument is important so we don't overwrite previous solutions
3804 with open(filename, "a") as file:
3805
3806 for action in total_action_list:
3807
3808 file.write(action + "\n")
3809 file.write("-----\n")
3810
3811
3812
3813 ##### Only smoke is loaded from superslide
3814 elif Grabbable_Dict[pot][0][1] == '1':
3815
3816 action_list010 = []
3817
3818 # COPY STATE
3819 #######################################################
3820 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3821 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
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, Room_List_Copy_2, Overlay_Dict_Copy_2)
3828
3829 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3830 #######################################################
3831
3832 Allocate_Smoke(Heap_Copy_2, neighbor_copy.number, Overlay_Dict_Copy_2)
3833 action_list010.append("Superslide with Smoke still allocated")
3834
3835 # The room we superslide into through the plane corresponding to the given pot
3836 destination_room = Current_Room([neighbor, Grabbable_Dict[pot][1]], Room_List)
3837
3838 destination_room_copy = room_copy_dict_2[destination_room.number]
3839 neighbor_copy_2 = room_copy_dict_2[neighbor_copy.number]
3840
3841 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
3842 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
3843
3844 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
3845 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3846
3847 # Now exit the chest room
3848 Load_Room(Heap_Copy_2, neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
3849 action_list010.append("Load Room: Room %d" %(neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3850
3851 # Now reenter the chest room
3852 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
3853 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3854
3855 ##### Now check for chests/deku guards
3856
3857 chest_guard_list = []
3858
3859 for entry in Heap_Copy_2:
3860
3861 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3862 chest_guard_list.append(entry)
3863
3864 soln_found = False
3865 for entry in chest_guard_list:
3866 if (pot.address - entry.address) in Offset_List:
3867
3868 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))
3869
3870 if (pot.address - entry.address) == 0x160:
3871 angle_solution_count += 1
3872 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3873 elif (pot.address - entry.address) == 0x1F0:
3874 position_solution_count += 1
3875 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3876
3877 soln_found = True
3878
3879 if soln_found is True:
3880 total_action_list = action_list + action_list_transition + action_list010
3881
3882 # the "a" argument is important so we don't overwrite previous solutions
3883 with open(filename, "a") as file:
3884
3885 for action in total_action_list:
3886
3887 file.write(action + "\n")
3888 file.write("-----\n")
3889
3890
3891
3892 #### Bomb and Smoke are both unloaded
3893 elif Grabbable_Dict[pot][0][2] == '1':
3894
3895 action_list001 = []
3896
3897 # COPY STATE
3898 #######################################################
3899 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
3900 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
3901
3902 room_copy_dict_2 = {}
3903 for room in Room_List_Copy_2:
3904 room_copy_dict_2[room.number] = room
3905
3906 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
3907
3908 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
3909 #######################################################
3910
3911 # Do not allocate anything
3912 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
3913
3914 # The room we superslide into through the plane corresponding to the given pot
3915 destination_room = Current_Room([neighbor, Grabbable_Dict[pot][1]], Room_List)
3916
3917 destination_room_copy = room_copy_dict_2[destination_room.number]
3918 neighbor_copy_2 = room_copy_dict_2[neighbor_copy.number]
3919
3920 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
3921 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
3922
3923 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
3924 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3925
3926 # Now exit the chest room
3927 Load_Room(Heap_Copy_2, neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
3928 action_list001.append("Load Room: Room %d" %(neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3929
3930 # Now reenter the chest room
3931 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
3932 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
3933
3934 ##### Now check for chests/deku guards
3935
3936 chest_guard_list = []
3937
3938 for entry in Heap_Copy_2:
3939
3940 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
3941 chest_guard_list.append(entry)
3942
3943 soln_found = False
3944 for entry in chest_guard_list:
3945 if (pot.address - entry.address) in Offset_List:
3946
3947 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))
3948
3949 if (pot.address - entry.address) == 0x160:
3950 angle_solution_count += 1
3951 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3952 elif (pot.address - entry.address) == 0x1F0:
3953 position_solution_count += 1
3954 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
3955
3956 soln_found = True
3957
3958 if soln_found is True:
3959 total_action_list = action_list + action_list_transition + action_list001
3960
3961 # the "a" argument is important so we don't overwrite previous solutions
3962 with open(filename, "a") as file:
3963
3964 for action in total_action_list:
3965
3966 file.write(action + "\n")
3967 file.write("-----\n")
3968
3969
3970 ##### No valid grabbable actor in neighbor
3971 elif neighbor not in valid_grabbable_actor_room_list:
3972
3973 for new_neighbor in Neighbors(neighbor, Room_List):
3974
3975 # if new neighbor has a valid grabbable actor... (Otherwise, we do nothing)
3976 if new_neighbor in valid_grabbable_actor_room_list:
3977
3978 ##### Iterate through all pots in this room
3979
3980 valid_pot_list = []
3981 pot_address_list = []
3982
3983 for pot in Grabbable_Dict:
3984
3985 if Actor_Is_In_Room(new_neighbor, pot) is True:
3986 valid_pot_list.append(pot)
3987 pot_address_list.append(pot.address)
3988
3989 for neighbor_transition in Shared_Transitions(current_room, neighbor):
3990 for new_neighbor_transition in Shared_Transitions(neighbor, new_neighbor):
3991
3992 action_list_transition = []
3993
3994 ##### COPY THE STATE
3995 #######################################################
3996 Room_List_Copy = Copy_Room_List(Room_List)
3997 Overlay_Dict_Copy = Copy_Overlay_Dict(Overlay_Dict)
3998
3999 room_copy_dict = {}
4000 for room in Room_List_Copy:
4001 room_copy_dict[room.number] = room
4002
4003 Heap_Copy = Copy_Heap(Heap, Room_List_Copy, Overlay_Dict_Copy)
4004
4005 Grabbable_Dict_Copy = Copy_Grabbable_Dict(Grabbable_Dict, Room_List_Copy)
4006 #######################################################
4007
4008 neighbor_copy = room_copy_dict[neighbor.number]
4009 neighbor_transition_copy = Find_Actor_Copy(neighbor_transition, Room_List_Copy)
4010
4011 new_neighbor_copy = room_copy_dict[new_neighbor.number]
4012 new_neighbor_transition_copy = Find_Actor_Copy(new_neighbor_transition, Room_List_Copy)
4013
4014 ##### ENTER neighbor
4015
4016 Load_Room(Heap_Copy, neighbor_copy, neighbor_transition_copy, Overlay_Dict_Copy)
4017 action_list_transition.append("Load Room: Room %d" %(neighbor_copy.number) + " with " + neighbor_transition_copy.name + " %d" %(neighbor_transition_copy.priority))
4018
4019 ##### ENTER new_neighbor
4020
4021 Load_Room(Heap_Copy, new_neighbor_copy, new_neighbor_transition_copy, Overlay_Dict_Copy)
4022 action_list_transition.append("Load Room: Room %d" %(new_neighbor_copy.number) + " with " + new_neighbor_transition_copy.name + " %d" %(new_neighbor_transition_copy.priority))
4023
4024
4025 # If there is a chest/guard, superslide, then check neighbors for chests/guards and test all (copy state)
4026 if Chest_In_Room(new_neighbor) == True or Deku_Guard_In_Room(new_neighbor) == True:
4027
4028 for pot in valid_pot_list:
4029
4030 # both bomb and smoke loaded on superslide
4031 if Grabbable_Dict[pot][0][0] == '1':
4032
4033 action_list100 = []
4034
4035 # COPY STATE
4036 #######################################################
4037 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
4038 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
4039
4040 room_copy_dict_SS = {}
4041 for room in Room_List_Copy_SS:
4042 room_copy_dict_SS[room.number] = room
4043
4044 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
4045
4046 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
4047 #######################################################
4048
4049 Bomb_And_Smoke_Superslide(Heap_Copy_SS, new_neighbor.number, Overlay_Dict_Copy_SS)
4050 action_list100.append("Superslide with Bomb and Smoke still allocated")
4051
4052 # The room we superslide into through the plane corresponding to the given pot
4053 destination_room = Current_Room([new_neighbor, Grabbable_Dict[pot][1]], Room_List)
4054
4055 destination_room_copy = room_copy_dict_SS[destination_room.number]
4056
4057 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
4058 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
4059
4060 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
4061 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4062
4063 """
4064
4065 Now we check all neighbors of our current room (destination_room) and for
4066 each neighbor that has a chest or deku guard in it, we will create a copy
4067 of our copy of the state, then enter each of them through each possible
4068 loading plane and then check the chest/guard addresses and see if anything
4069 lines up
4070
4071 """
4072
4073 for bordering_room in Neighbors(destination_room, Room_List):
4074
4075 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
4076
4077 for loading_plane in Shared_Transitions(destination_room, bordering_room):
4078
4079 # COPY STATE
4080 #######################################################
4081 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
4082 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
4083
4084 room_copy_dict_2 = {}
4085 for room in Room_List_Copy_2:
4086 room_copy_dict_2[room.number] = room
4087
4088 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
4089
4090 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
4091 #######################################################
4092
4093 action_list_2 = []
4094
4095 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
4096
4097 bordering_room_copy = room_copy_dict_2[bordering_room.number]
4098
4099 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
4100 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
4101
4102
4103 ##### Now check for chests/deku guards
4104
4105 chest_guard_list = []
4106
4107 for entry in Heap_Copy_2:
4108
4109 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4110 chest_guard_list.append(entry)
4111
4112 soln_found = False
4113 for entry in chest_guard_list:
4114 if (pot.address - entry.address) in Offset_List:
4115
4116 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))
4117
4118 if (pot.address - entry.address) == 0x160:
4119 angle_solution_count += 1
4120 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4121 elif (pot.address - entry.address) == 0x1F0:
4122 position_solution_count += 1
4123 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4124
4125 soln_found = True
4126
4127 if soln_found is True:
4128 total_action_list = action_list + action_list_transition + action_list100 + action_list_2
4129
4130 # the "a" argument is important so we don't overwrite previous solutions
4131 with open(filename, "a") as file:
4132
4133 for action in total_action_list:
4134
4135 file.write(action + "\n")
4136 file.write("-----\n")
4137
4138
4139
4140 ##### Only smoke is loaded from superslide
4141 elif Grabbable_Dict[pot][0][1] == '1':
4142
4143 action_list010 = []
4144
4145 # COPY STATE
4146 #######################################################
4147 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
4148 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
4149
4150 room_copy_dict_SS = {}
4151 for room in Room_List_Copy_SS:
4152 room_copy_dict_SS[room.number] = room
4153
4154 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
4155
4156 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
4157 #######################################################
4158
4159 Allocate_Smoke(Heap_Copy_SS, new_neighbor.number, Overlay_Dict_Copy_SS)
4160 action_list010.append("Superslide with Smoke still allocated")
4161
4162 # The room we superslide into through the plane corresponding to the given pot
4163 destination_room = Current_Room([new_neighbor, Grabbable_Dict[pot][1]], Room_List)
4164
4165 destination_room_copy = room_copy_dict_SS[destination_room.number]
4166
4167 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
4168 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
4169
4170 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
4171 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4172
4173 """
4174
4175 Now we check all neighbors of our current room (destination_room) and for
4176 each neighbor that has a chest or deku guard in it, we will create a copy
4177 of our copy of the state, then enter each of them through each possible
4178 loading plane and then check the chest/guard addresses and see if anything
4179 lines up
4180
4181 """
4182
4183 for bordering_room in Neighbors(destination_room, Room_List):
4184
4185 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
4186
4187 for loading_plane in Shared_Transitions(destination_room, bordering_room):
4188
4189 # COPY STATE
4190 #######################################################
4191 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
4192 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
4193
4194 room_copy_dict_2 = {}
4195 for room in Room_List_Copy_2:
4196 room_copy_dict_2[room.number] = room
4197
4198 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
4199
4200 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
4201 #######################################################
4202
4203 action_list_2 = []
4204
4205 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
4206
4207 bordering_room_copy = room_copy_dict_2[bordering_room.number]
4208
4209 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
4210 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
4211
4212
4213 ##### Now check for chests/deku guards
4214
4215 chest_guard_list = []
4216
4217 for entry in Heap_Copy_2:
4218
4219 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4220 chest_guard_list.append(entry)
4221
4222 soln_found = False
4223 for entry in chest_guard_list:
4224 if (pot.address - entry.address) in Offset_List:
4225
4226 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))
4227
4228 if (pot.address - entry.address) == 0x160:
4229 angle_solution_count += 1
4230 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4231 elif (pot.address - entry.address) == 0x1F0:
4232 position_solution_count += 1
4233 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4234
4235 soln_found = True
4236
4237 if soln_found is True:
4238 total_action_list = action_list + action_list_transition + action_list010 + action_list_2
4239
4240 # the "a" argument is important so we don't overwrite previous solutions
4241 with open(filename, "a") as file:
4242
4243 for action in total_action_list:
4244
4245 file.write(action + "\n")
4246 file.write("-----\n")
4247
4248
4249 #### Bomb and Smoke are both unloaded
4250 elif Grabbable_Dict[pot][0][2] == '1':
4251
4252 action_list001 = []
4253
4254 # COPY STATE
4255 #######################################################
4256 Room_List_Copy_SS = Copy_Room_List(Room_List_Copy)
4257 Overlay_Dict_Copy_SS = Copy_Overlay_Dict(Overlay_Dict_Copy)
4258
4259 room_copy_dict_SS = {}
4260 for room in Room_List_Copy_SS:
4261 room_copy_dict_SS[room.number] = room
4262
4263 Heap_Copy_SS = Copy_Heap(Heap_Copy, Room_List_Copy_SS, Overlay_Dict_Copy_SS)
4264
4265 Grabbable_Dict_Copy_SS = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_SS)
4266 #######################################################
4267
4268 # Do not allocate anything
4269 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
4270
4271 # The room we superslide into through the plane corresponding to the given pot
4272 destination_room = Current_Room([new_neighbor, Grabbable_Dict[pot][1]], Room_List)
4273
4274 destination_room_copy = room_copy_dict_SS[destination_room.number]
4275
4276 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_SS)
4277 superslide_transition_copy = Grabbable_Dict_Copy_SS[pot_copy][1]
4278
4279 Load_Room(Heap_Copy_SS, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_SS)
4280 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4281
4282 """
4283
4284 Now we check all neighbors of our current room (destination_room) and for
4285 each neighbor that has a chest or deku guard in it, we will create a copy
4286 of our copy of the state, then enter each of them through each possible
4287 loading plane and then check the chest/guard addresses and see if anything
4288 lines up
4289
4290 """
4291
4292 for bordering_room in Neighbors(destination_room, Room_List):
4293
4294 if Chest_In_Room(bordering_room) == True or Deku_Guard_In_Room(bordering_room) == True:
4295
4296 for loading_plane in Shared_Transitions(destination_room, bordering_room):
4297
4298 # COPY STATE
4299 #######################################################
4300 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy_SS)
4301 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy_SS)
4302
4303 room_copy_dict_2 = {}
4304 for room in Room_List_Copy_2:
4305 room_copy_dict_2[room.number] = room
4306
4307 Heap_Copy_2 = Copy_Heap(Heap_Copy_SS, Room_List_Copy_2, Overlay_Dict_Copy_2)
4308
4309 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy_SS, Room_List_Copy_2)
4310 #######################################################
4311
4312 action_list_2 = []
4313
4314 loading_plane_copy = Find_Actor_Copy(loading_plane, Room_List_Copy_2)
4315
4316 bordering_room_copy = room_copy_dict_2[bordering_room.number]
4317
4318 Load_Room(Heap_Copy_2, bordering_room_copy, loading_plane_copy, Overlay_Dict_Copy_2)
4319 action_list_2.append("Load Room: Room %d" %(bordering_room_copy.number) + " with " + loading_plane_copy.name + " %d" %(loading_plane_copy.priority))
4320
4321
4322 ##### Now check for chests/deku guards
4323
4324 chest_guard_list = []
4325
4326 for entry in Heap_Copy_2:
4327
4328 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4329 chest_guard_list.append(entry)
4330
4331 soln_found = False
4332 for entry in chest_guard_list:
4333 if (pot.address - entry.address) in Offset_List:
4334
4335 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))
4336
4337 if (pot.address - entry.address) == 0x160:
4338 angle_solution_count += 1
4339 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4340 elif (pot.address - entry.address) == 0x1F0:
4341 position_solution_count += 1
4342 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4343
4344 soln_found = True
4345
4346 if soln_found is True:
4347 total_action_list = action_list + action_list_transition + action_list001 + action_list_2
4348
4349 # the "a" argument is important so we don't overwrite previous solutions
4350 with open(filename, "a") as file:
4351
4352 for action in total_action_list:
4353
4354 file.write(action + "\n")
4355 file.write("-----\n")
4356
4357
4358
4359 # 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)
4360 elif Chest_In_Room(new_neighbor) == False and Deku_Guard_In_Room(new_neighbor) == False:
4361
4362 for pot in valid_pot_list:
4363
4364 # both bomb and smoke loaded on superslide
4365 if Grabbable_Dict[pot][0][0] == '1':
4366
4367 action_list100 = []
4368
4369 # COPY STATE
4370 #######################################################
4371 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4372 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4373
4374 room_copy_dict_2 = {}
4375 for room in Room_List_Copy_2:
4376 room_copy_dict_2[room.number] = room
4377
4378 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4379
4380 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4381 #######################################################
4382
4383 Bomb_And_Smoke_Superslide(Heap_Copy_2, new_neighbor_copy.number, Overlay_Dict_Copy_2)
4384 action_list100.append("Superslide with Bomb and Smoke still allocated")
4385
4386 # The room we superslide into through the plane corresponding to the given pot
4387 destination_room = Current_Room([new_neighbor, Grabbable_Dict[pot][1]], Room_List)
4388
4389 destination_room_copy = room_copy_dict_2[destination_room.number]
4390 new_neighbor_copy_2 = room_copy_dict_2[new_neighbor_copy.number]
4391
4392 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4393 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4394
4395 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4396 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4397
4398 # Now exit the chest room
4399 Load_Room(Heap_Copy_2, new_neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4400 action_list100.append("Load Room: Room %d" %(new_neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4401
4402 # Now reenter the chest room
4403 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4404 action_list100.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4405
4406 ##### Now check for chests/deku guards
4407
4408 chest_guard_list = []
4409
4410 for entry in Heap_Copy_2:
4411
4412 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4413 chest_guard_list.append(entry)
4414
4415 soln_found = False
4416 for entry in chest_guard_list:
4417 if (pot.address - entry.address) in Offset_List:
4418
4419 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))
4420
4421 if (pot.address - entry.address) == 0x160:
4422 angle_solution_count += 1
4423 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4424 elif (pot.address - entry.address) == 0x1F0:
4425 position_solution_count += 1
4426 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4427
4428 soln_found = True
4429
4430 if soln_found is True:
4431 total_action_list = action_list + action_list_transition + action_list100
4432
4433 # the "a" argument is important so we don't overwrite previous solutions
4434 with open(filename, "a") as file:
4435
4436 for action in total_action_list:
4437
4438 file.write(action + "\n")
4439 file.write("-----\n")
4440
4441
4442
4443 ##### Only smoke is loaded from superslide
4444 elif Grabbable_Dict[pot][0][1] == '1':
4445
4446 action_list010 = []
4447
4448 # COPY STATE
4449 #######################################################
4450 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4451 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4452
4453 room_copy_dict_2 = {}
4454 for room in Room_List_Copy_2:
4455 room_copy_dict_2[room.number] = room
4456
4457 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4458
4459 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4460 #######################################################
4461
4462 Allocate_Smoke(Heap_Copy_2, new_neighbor_copy.number, Overlay_Dict_Copy_2)
4463 action_list010.append("Superslide with Smoke still allocated")
4464
4465 # The room we superslide into through the plane corresponding to the given pot
4466 destination_room = Current_Room([new_neighbor, Grabbable_Dict[pot][1]], Room_List)
4467
4468 destination_room_copy = room_copy_dict_2[destination_room.number]
4469 new_neighbor_copy_2 = room_copy_dict_2[new_neighbor_copy.number]
4470
4471 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4472 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4473
4474 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4475 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4476
4477 # Now exit the chest room
4478 Load_Room(Heap_Copy_2, new_neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4479 action_list010.append("Load Room: Room %d" %(new_neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4480
4481 # Now reenter the chest room
4482 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4483 action_list010.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4484
4485 ##### Now check for chests/deku guards
4486
4487 chest_guard_list = []
4488
4489 for entry in Heap_Copy_2:
4490
4491 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4492 chest_guard_list.append(entry)
4493
4494 soln_found = False
4495 for entry in chest_guard_list:
4496 if (pot.address - entry.address) in Offset_List:
4497
4498 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))
4499
4500 if (pot.address - entry.address) == 0x160:
4501 angle_solution_count += 1
4502 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4503 elif (pot.address - entry.address) == 0x1F0:
4504 position_solution_count += 1
4505 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4506
4507 soln_found = True
4508
4509 if soln_found is True:
4510 total_action_list = action_list + action_list_transition + action_list010
4511
4512 # the "a" argument is important so we don't overwrite previous solutions
4513 with open(filename, "a") as file:
4514
4515 for action in total_action_list:
4516
4517 file.write(action + "\n")
4518 file.write("-----\n")
4519
4520
4521
4522 #### Bomb and Smoke are both unloaded
4523 elif Grabbable_Dict[pot][0][2] == '1':
4524
4525 action_list001 = []
4526
4527 # COPY STATE
4528 #######################################################
4529 Room_List_Copy_2 = Copy_Room_List(Room_List_Copy)
4530 Overlay_Dict_Copy_2 = Copy_Overlay_Dict(Overlay_Dict_Copy)
4531
4532 room_copy_dict_2 = {}
4533 for room in Room_List_Copy_2:
4534 room_copy_dict_2[room.number] = room
4535
4536 Heap_Copy_2 = Copy_Heap(Heap_Copy, Room_List_Copy_2, Overlay_Dict_Copy_2)
4537
4538 Grabbable_Dict_Copy_2 = Copy_Grabbable_Dict(Grabbable_Dict_Copy, Room_List_Copy_2)
4539 #######################################################
4540
4541 # Do not allocate anything
4542 action_list001.append("Superslide with Bomb and Smoke unloaded when passing plane")
4543
4544 # The room we superslide into through the plane corresponding to the given pot
4545 destination_room = Current_Room([new_neighbor, Grabbable_Dict[pot][1]], Room_List)
4546
4547 destination_room_copy = room_copy_dict_2[destination_room.number]
4548 new_neighbor_copy_2 = room_copy_dict_2[new_neighbor_copy.number]
4549
4550 pot_copy = Find_Actor_Copy(pot, Room_List_Copy_2)
4551 superslide_transition_copy = Grabbable_Dict_Copy_2[pot_copy][1]
4552
4553 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4554 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4555
4556 # Now exit the chest room
4557 Load_Room(Heap_Copy_2, new_neighbor_copy_2, superslide_transition_copy, Overlay_Dict_Copy_2)
4558 action_list001.append("Load Room: Room %d" %(new_neighbor_copy_2.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4559
4560 # Now reenter the chest room
4561 Load_Room(Heap_Copy_2, destination_room_copy, superslide_transition_copy, Overlay_Dict_Copy_2)
4562 action_list001.append("Load Room: Room %d" %(destination_room_copy.number) + " with " + superslide_transition_copy.name + " %d" %(superslide_transition_copy.priority))
4563
4564 ##### Now check for chests/deku guards
4565
4566 chest_guard_list = []
4567
4568 for entry in Heap_Copy_2:
4569
4570 if type(entry) == Actor and (entry.Id == '0006' or entry.Id == '017A'):
4571 chest_guard_list.append(entry)
4572
4573 soln_found = False
4574 for entry in chest_guard_list:
4575 if (pot.address - entry.address) in Offset_List:
4576
4577 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))
4578
4579 if (pot.address - entry.address) == 0x160:
4580 angle_solution_count += 1
4581 print("ANGLE SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4582 elif (pot.address - entry.address) == 0x1F0:
4583 position_solution_count += 1
4584 print("Z POSITION SOLUTION FOUND (CHEST)!!!!!!!!!!!")
4585
4586 soln_found = True
4587
4588 if soln_found is True:
4589 total_action_list = action_list + action_list_transition + action_list001
4590
4591 # the "a" argument is important so we don't overwrite previous solutions
4592 with open(filename, "a") as file:
4593
4594 for action in total_action_list:
4595
4596 file.write(action + "\n")
4597 file.write("-----\n")
4598
4599
4600
4601
4602###############################################################################
4603###############################################################################
4604###############################################################################
4605###############################################################################
4606###############################################################################
4607###############################################################################
4608###############################################################################
4609###############################################################################
4610###############################################################################
4611###############################################################################
4612###############################################################################
4613###############################################################################
4614###############################################################################
4615###############################################################################
4616###############################################################################
4617###############################################################################
4618###############################################################################
4619###############################################################################
4620###############################################################################
4621###############################################################################
4622###############################################################################
4623###############################################################################
4624###############################################################################
4625###############################################################################
4626###############################################################################
4627###############################################################################
4628###############################################################################
4629###############################################################################
4630###############################################################################
4631###############################################################################
4632###############################################################################
4633###############################################################################
4634###############################################################################
4635###############################################################################
4636###############################################################################
4637###############################################################################
4638###############################################################################
4639###############################################################################
4640###############################################################################
4641###############################################################################
4642###############################################################################
4643###############################################################################
4644###############################################################################
4645###############################################################################
4646###############################################################################
4647###############################################################################
4648###############################################################################
4649###############################################################################
4650
4651
4652
4653
4654
4655
4656
4657"""
4658
4659 Before proceeding, we should define all of the transitions we plan on passing through
4660
4661 Since "Beneath the Graveyard" is relatively simple and I currently only want to consider
4662 passing through a single plane, I will just define Plane_1 to be the plane shared between
4663 Room0 and Room1
4664
4665 This loading plane happens the be the second element in Room0_queue, so I will define it based on that
4666
4667"""
4668
4669Oceanside_Plane_0 = Oceanside_Room3_queue[0]
4670
4671
4672
4673
4674
4675"""
4676
4677 Grabbable_dict is a dictionary of the grabbable actors (such as pots) that
4678 we want to attempt to use for superslide SRM where the keys are the grabbable
4679 actors and the values are lists with 3-bit strings where each bit means:
4680
4681 100 : Possible to enter Plane with both Bomb and Smoke loaded
4682 010 : Possible to enter Plane with Smoke loaded, but no Bomb loaded
4683 001 : Possible to enter Plane with no Smoke loaded
4684
4685 and Transitions, where the transitions are the ones you can superslide through
4686
4687
4688"""
4689
4690Oceanside_Grabbable_dict = {
4691 Oceanside_Room3_queue[6] : ['010', Oceanside_Plane_0],
4692 Oceanside_Room3_queue[7] : ['010', Oceanside_Plane_0]
4693 }
4694
4695
4696Hardcoded_Allocation_List0 = [
4697 'Smoke',
4698 'Chu',
4699 'Chu',
4700 'Chu',
4701 'Arrow',
4702 'Arrow',
4703 'Arrow',
4704 'Arrow',
4705 'Arrow',
4706 'Bomb',
4707 'Bomb',
4708 'Bomb',
4709 'Zora Fins',
4710 'Fish',
4711 'Fish',
4712 'Bugs',
4713 'Bugs',
4714 'Hookshot',
4715 'Charged Spin Attack'
4716 ]
4717
4718Hardcoded_Allocation_List_2 = [
4719 'Smoke',
4720 'Arrow',
4721 'Arrow',
4722 'Arrow',
4723 'Arrow',
4724 'Arrow',
4725 'Bomb',
4726 'Bomb',
4727 'Bomb',
4728 'Hookshot',
4729 'Charged Spin Attack'
4730 ]
4731
4732
4733# CHANGE THIS PATH TO WHERE YOU HAVE: solver oceanside4.txt
4734save_path = "C:\\Users\\abcxyz\\Documents\\Bizhawk RAM Watch\\scripts\\"
4735name_of_file = "solver oceanside4"
4736complete_name = save_path + name_of_file + ".txt"
4737
4738Heap = [Node(0x40B140, node_size), Node(0x5FFFFF, node_size)]
4739
4740Randomized_Solver(Oceanside_Room3, Oceanside_Room_List, 5, Hardcoded_Allocation_List_2, Oceanside_Grabbable_dict, Overlay_dict, complete_name, [0x160, 0x1F0], Heap)