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