Advertisement
Guest User

srm

a guest
Dec 9th, 2019
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 37.90 KB | None | 0 0
  1.  
  2. """
  3.  
  4. - This script does NOT handle spawners (except for rupee clusters)
  5. - This script does NOT handle scarecrow memory leak
  6.  
  7. - This script does not account for ISoT memory leak for solution options
  8.  
  9.  
  10. """
  11.  
  12.  
  13.  
  14. """
  15.  
  16. Note: Node size is 0x10 = 16 on English and 0x30 = 48 on JP
  17.  
  18. """
  19.  
  20. version = 'English'
  21.  
  22. if version == 'English':
  23.     node_size = 0x10
  24. elif version == 'JP':
  25.     nodesize = 0x30
  26. else:
  27.     print('Error: Invalid Version (choose "English" or "JP" )')
  28.  
  29.  
  30.  
  31. class Actor:
  32.    
  33.     """
  34.    
  35.    name: name of the actor, some string
  36.    
  37.    Id: Actor id, string of 4 integers
  38.    
  39.    size: the size of an actor instance for this actor (number of bytes, in decimal)
  40.    
  41.    category: the actor category (category 5 is treated differently than others)
  42.              For now, giving everything not category 5 a category of 0
  43.  
  44.    overlay_type: determines where the AF loads in the heap
  45.    
  46.    unloadable: a boolean for whether or not it is possible to deallocate this actor without changing rooms
  47.    
  48.    address: the memory address of the actor in decimal (can convert to a hex string for output)
  49.             Note: The earliest address we handle is 0x40B150 = 4239696. All addresses must be multiples of 16
  50.            
  51.    room_number: the number of the room these actors are associated with; if the actor is a transition (i..e Plane
  52.                or Door), then set room_numer = False
  53.                
  54.    
  55.    priority: an index to differentiate copies of the same instance
  56.    
  57.    from_spawner: True or False (True if it is from a spawner, like rupees from a cluster; False otherwise)
  58.    
  59.    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
  60.    
  61.    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
  62.    
  63.    cleared: True if the flag was set to clear this actor, False otherwise
  64.    
  65.    """
  66.    
  67.     def __init__(self, name, Id, size, category, overlay_type, unloadable, address, room_number, priority, from_spawner, transition, clearable, cleared):
  68.         self.name = name
  69.         self.Id = Id
  70.         self.size = size
  71.         self.category = category
  72.         self.overlay_type = overlay_type
  73.         self.unloadable = unloadable
  74.         self.address = address
  75.         self.room_number = room_number
  76.         self.priority = priority
  77.         self.from_spawner = from_spawner
  78.         self.transition = transition
  79.         self.clearable = clearable
  80.         self.cleared = cleared
  81.  
  82. class Room:
  83.    
  84.     """
  85.    
  86.    number: the room number (i.e. Room 0 has number 0)
  87.    
  88.    priority_queue: this will be the list of actor instances of the room, in order
  89.    
  90.    clock_exists: boolean for whether or not the clock is an actor in the queue
  91.    
  92.    clock_priority: if clock_exists == False, then clock_priority will be a number
  93.                    to determine where in the queue the clock should be loaded, for
  94.                    example, if clock_priority is 2, then it means that the clock
  95.                    should be the 3rd actor to appear in the queue (first index is 0)
  96.    
  97.    """
  98.    
  99.     def __init__(self, number, priority_queue, clock_exists, clock_priority):
  100.         self.number = number
  101.         self.priority_queue = priority_queue
  102.         self.clock_exists = clock_exists
  103.         self.clock_priority = clock_priority
  104.  
  105. class Node:
  106.    
  107.     """
  108.    address: which address in memory the node is at (as a base-10 integer for now)
  109.    
  110.    size: nodes should be 16 bytes (english), so input 16
  111.    
  112.    """
  113.    
  114.     def __init__(self, address, size):
  115.         self.address = address
  116.         self.size = size
  117.  
  118. class Overlay:
  119.    
  120.     def __init__(self, address, Id, size):
  121.         self.address = address
  122.         self.Id = Id
  123.         self.size = size
  124.  
  125.  
  126. """
  127.  
  128. We define the Clock actor ahead of time as it is not necessarily present in each room
  129.  
  130. """
  131.  
  132.  
  133. Clock = 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)
  134.  
  135.  
  136.  
  137. Room0_queue = [
  138.         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),
  139.         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),
  140.         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),
  141.         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),
  142.         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),
  143.         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),
  144.         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),
  145.         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),
  146.         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),
  147.         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)
  148.         ]
  149.  
  150.  
  151. Room1_queue = [
  152.         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),
  153.         Room0_queue[1],
  154.         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),
  155.         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),
  156.         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),
  157.         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),
  158.         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),
  159.         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),
  160.         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),
  161.         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),
  162.         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),
  163.         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),
  164.         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),
  165.         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),
  166.         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),
  167.         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),
  168.         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),
  169.         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),
  170.         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),
  171.         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),
  172.         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),
  173.         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),
  174.         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),
  175.         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),
  176.         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),
  177.         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),
  178.         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),
  179.         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),
  180.         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)
  181.         ]
  182.  
  183. ###############################################################################
  184.  
  185. Room0 = Room(0, Room0_queue, False, 2)
  186. Room1 = Room(1, Room1_queue, False, 2)
  187.  
  188. """
  189.  
  190. In Overlay_dict we collect all of the Overlays of Type A, where the keys are
  191. the corresponding actor ids
  192.  
  193. """
  194.  
  195. # NOTE: This must be named "Overlay_dict" because it is hardcoded in some functions, like the Deallocate() function
  196. Overlay_dict = {
  197.         '015A' : Overlay(address=0, Id='015A', size=6000),
  198.         '00E8' : Overlay(address=0, Id='00E8', size=1984),
  199.         '0170' : Overlay(address=0, Id='0170', size=10688),
  200.         '0039' : Overlay(address=0, Id='0039', size=3552),
  201.         '0082' : Overlay(address=0, Id='0082', size=9040),
  202.         '0158' : Overlay(address=0, Id='0158', size=1104),
  203.         '015B' : Overlay(address=0, Id='015B', size=6048),
  204.         '0006' : Overlay(address=0, Id='0006', size=8640)
  205.             }
  206.  
  207.  
  208. """
  209.  
  210. Here we collect a list of Actor Ids for spawners. So far this includes:
  211.    
  212.    00E8: Rupee Cluster
  213.  
  214. """
  215.  
  216. Spawner_Ids = ['00E8']
  217.  
  218.  
  219. """
  220.  
  221. We initialize the Heap as a list, putting a node with address 0x40B140 in the 0th entry
  222. and we place a dummy node at the end of the Heap so that there will always exist two
  223. consecutive nodes for us to define a condition for which free space in the Heap exists
  224.  
  225. Keep in mind that the 0x5FFFFF address in the dummy node will not reflect the actual
  226. address of the corresponding node in-game, but it also isn't relevant to heap manipulation
  227. since it is so far down
  228.  
  229. """
  230.  
  231.  
  232. Heap = [Node(0x40B140, node_size), Node(0x5FFFFF, node_size)]
  233.  
  234.  
  235.  
  236. def Overlay_In_Heap(Heap, overlay):
  237.    
  238.     """
  239.    
  240.    Overlay is the overlay that we want to check whether or not it is in the Heap
  241.    
  242.    This function will return True if Overlay is in the Heap and False otherwise
  243.    
  244.    """
  245.    
  246.     overlay_in_heap = False
  247.    
  248.     for entry in Heap:
  249.        
  250.         if type(entry) == Overlay and entry.Id == overlay.Id:
  251.            
  252.             overlay_in_heap = True
  253.        
  254.     return overlay_in_heap
  255.  
  256.  
  257. def Actor_Id_In_Heap(Heap, actor_id):
  258.    
  259.     """
  260.    
  261.    actor_id is the Id that we want to check for
  262.    
  263.    This function will return True if there exists an Actor in the Heap that
  264.    has actor_id as its Id and it will return False otherwise
  265.    
  266.    """
  267.    
  268.     actor_id_in_heap = False
  269.    
  270.     for entry in Heap:
  271.        
  272.         if type(entry) == Actor and entry.Id == actor_id:
  273.            
  274.             actor_id_in_heap = True
  275.    
  276.     return actor_id_in_heap
  277.  
  278.  
  279. def Find_Gaps(Heap):
  280.    
  281.     """
  282.    
  283.    This function will find all consecutive nodes and output a list of 4-tuples
  284.    where the first two entries correspond to the indices of each node in the list
  285.    and the last two entries correspond to the addresses of each node
  286.    
  287.    The list should be in order, from the start of the Heap to the end of the Heap
  288.    
  289.    """
  290.    
  291.     consecutive_node_count = 0
  292.    
  293.     node_1_address = 0
  294.     node_2_address = 0
  295.     node_1_index = 0
  296.     node_2_index = 0
  297.    
  298.     consecutive_node_list = []
  299.     for entry in Heap:
  300.         if type(entry) == Node and consecutive_node_count == 0:
  301.             node_1_address = entry.address
  302.             node_1_index = Heap.index(entry)
  303.             consecutive_node_count += 1
  304.         elif type(entry) == Node and consecutive_node_count == 1:
  305.             node_2_address = entry.address
  306.             node_2_index = Heap.index(entry)
  307.            
  308.             consecutive_node_list.append((node_1_index, node_2_index, node_1_address, node_2_address))
  309.            
  310.             consecutive_node_count += 1
  311.         elif type(entry) != Node:
  312.             consecutive_node_count = 0
  313.         elif type(entry) == Node and consecutive_node_count > 1:
  314.             consecutive_node_count += 1
  315.             print("ERROR: More than 2 consecutive nodes!! (Find_Gaps() Error Message)")
  316.        
  317.    
  318.     return consecutive_node_list
  319.    
  320.  
  321.  
  322.  
  323. def Allocate(Heap, actor, Overlay_Dict):
  324.    
  325.     """
  326.    
  327.    actor is the actor that we want to allocate into the Heap
  328.    
  329.    Overlay_Dict is a dictionary where the keys are the actor ids which point to the corresponding Overlays
  330.    
  331.    This function will account for placing nodes and overlays
  332.    
  333.    """
  334.    
  335.    
  336.     #Overlay = Overlay_Dict[actor.Id]
  337.    
  338.     #Overlay_Allocated = False
  339.    
  340.     #if Overlay_In_Heap(Heap, Overlay) == True:
  341.     #    Overlay_Allocated = True
  342.    
  343.     Actor_Allocated = False
  344.    
  345.     """
  346.    ##### Not yet defined, not sure if I will bother; not really necessary. Probably should for debugging
  347.    if Actor_In_Heap == True:
  348.        print('Error: This Actor is already allocated!! (Error message from Allocate() function)')
  349.    """
  350.    
  351.     gap_list = Find_Gaps(Heap)
  352.    
  353.     # Because we initialize the Heap with 2 nodes, there should always be at least one gap
  354.     if len(gap_list) < 1:
  355.         print('ERROR: len(gap_list) < 1 in Allocate() function')
  356.    
  357.    
  358.     # If the Overlay is type A and the Overlay is not already in the Heap, then we want to allocate the overlay first
  359.     if actor.overlay_type == 'A':
  360.        
  361.         ##### We only define Overlay for Type A overlays because Overlay_Dict only has Type A overlays
  362.         Overlay = Overlay_Dict[actor.Id]
  363.         Overlay_Allocated = False
  364.        
  365.         if Overlay_In_Heap(Heap, Overlay) == True:
  366.             Overlay_Allocated = True
  367.        
  368.        
  369.         if Overlay_In_Heap(Heap, Overlay) == False:
  370.        
  371.             for gap in gap_list:
  372.                
  373.                 if Overlay_Allocated == True:
  374.                     break ##### This ensures we don't add in the same Overlay multiple times
  375.                
  376.                 node_2_index = gap[1]
  377.                 node_1_address = gap[2]
  378.                 node_2_address = gap[3]
  379.                
  380.                 gap_size = node_2_address - node_1_address - node_size
  381.                
  382.                 ##### Case 1: the Overlay can fit, but there is NOT enough space for an extra node
  383.                 # Note that gap_size is always a multiple of 16
  384.                
  385.                 if Overlay.size <= gap_size and Overlay.size > gap_size - 2*node_size:
  386.                    
  387.                     Overlay.address = node_1_address + node_size
  388.                     Heap.insert(node_2_index, Overlay)
  389.                     Overlay_Allocated = True
  390.                    
  391.                
  392.                 ##### Case 2: the Overlay can fit and a new node can also fit
  393.                
  394.                 elif Overlay.size <= gap_size and Overlay.size <= gap_size - 2*node_size:
  395.                    
  396.                     Overlay.address = node_1_address + node_size
  397.                     Heap.insert(node_2_index, Overlay)
  398.                    
  399.                     ########### ADD IN THE NODE HERE
  400.                     if Overlay.size%16 > 0:
  401.                         Heap.insert(node_2_index + 1, Node(address=Overlay.address + Overlay.size + (16 - Overlay.size%16), size=node_size))
  402.                     elif Overlay.size%16 == 0:
  403.                         Heap.insert(node_2_index + 1, Node(address=Overlay.address + Overlay.size, size=node_size))
  404.                        
  405.                     Overlay_Allocated = True
  406.                
  407.     ############ Now the overlay (if applicable) has been allocated. Now we need to allocate the actor.
  408.    
  409.     ##### We need to update the gaps_list to account for the overlay being allocated in the Heap already
  410.     gap_list = Find_Gaps(Heap)
  411.    
  412.     for gap in gap_list:
  413.        
  414.         if Actor_Allocated == True:
  415.             break ##### This ensures we don't add in the same Actor multiple times
  416.        
  417.         node_2_index = gap[1]
  418.         node_1_address = gap[2]
  419.         node_2_address = gap[3]
  420.        
  421.         gap_size = node_2_address - node_1_address - node_size
  422.        
  423.         ##### Case 1: the Actor can fit, but there is NOT enough space for an extra node
  424.         # Note that gap_size is always a multiple of 16
  425.        
  426.         if actor.size <= gap_size and actor.size > gap_size - 2*node_size:
  427.            
  428.             actor.address = node_1_address + node_size
  429.             Heap.insert(node_2_index, actor)
  430.             Actor_Allocated = True
  431.            
  432.        
  433.         ##### Case 2: the Actor can fit and a new node can also fit
  434.        
  435.         elif actor.size <= gap_size and actor.size <= gap_size - 2*node_size:
  436.            
  437.             actor.address = node_1_address + node_size
  438.             Heap.insert(node_2_index, actor)
  439.            
  440.             ########### ADD IN THE NODE HERE
  441.             if actor.size%16 > 0:
  442.                 Heap.insert(node_2_index + 1, Node(address=actor.address + actor.size + (16 - actor.size%16), size=node_size))
  443.             elif actor.size%16 == 0:
  444.                 Heap.insert(node_2_index + 1, Node(address=actor.address + actor.size, size=node_size))
  445.                    
  446.             Actor_Allocated = True
  447.  
  448. def Borders_Node(Heap, entry):
  449.    
  450.     """
  451.    
  452.    This function takes an entry of the Heap as input and determines whether or
  453.    not this entry is adjacent to a node in the heap (the purpose of this is to
  454.    check if a node is bordering another node since actors and overlays should
  455.    be bordering two nodes under every circumstance)
  456.    
  457.    Returns True if the entry is bordering a node, returns False otherwise    
  458.    
  459.    """
  460.    
  461.     borders_node = False
  462.    
  463.     entry_index = Heap.index(entry)
  464.    
  465.     border_1_is_node = False
  466.     border_2_is_node = False
  467.    
  468.     if entry_index != 0:
  469.         border_1 = Heap[entry_index - 1]
  470.         if type(border_1) == Node:
  471.             border_1_is_node = True
  472.    
  473.     if entry_index != len(Heap) - 1:
  474.         border_2 = Heap[entry_index + 1]
  475.         if type(border_2) == Node:
  476.             border_2_is_node = True
  477.    
  478.     if border_1_is_node == True or border_2_is_node == True:
  479.         borders_node = True
  480.    
  481.     return borders_node
  482.        
  483.  
  484.  
  485. def Deallocate(Heap, actor):
  486.    
  487.    
  488.     """
  489.    
  490.    actor is the actor that we want to be deallocated from the Heap
  491.    
  492.    This function will account for removing nodes and overlays
  493.    
  494.    ##### Remove the actor AND node if applicable
  495.    ##### Check if any actors with the same Id are still in the Heap
  496.    ##### if not (and the actor has overlay Type A), then remove the overlay
  497.    
  498.    We only remove a node if it is part of a gap before deallocating the actor
  499.    That is, we only remove a node if it borders another node before the actor is deallocated
  500.    
  501.    """
  502.    
  503.     if type(actor) != Actor:
  504.         print("ERROR: Attempted to deallocate something other than an Actor (Deallocate() function error message)")
  505.    
  506.     # The index of where the actor is in the Heap before being deallocated; this will change after we remove the first node
  507.     actor_index = Heap.index(actor)
  508.    
  509.     ##### First check the node above the actor in the Heap
  510.     node_1 = Heap[actor_index - 1]
  511.     if type(node_1) != Node:
  512.         print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
  513.    
  514.     if Borders_Node(Heap, node_1) == True:
  515.         Heap.remove(node_1)
  516.        
  517.     ########## Now the first node has been removed and the indices of the Heap shift
  518.    
  519.     ##### Now we check the node below the actor in the Heap
  520.    
  521.     # The index of where the actor is in the Heap before being deallocated; this will change after we remove the first node
  522.     actor_index = Heap.index(actor)
  523.    
  524.     node_2 = Heap[actor_index + 1]
  525.     if type(node_2) != Node:
  526.         print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
  527.    
  528.     if Borders_Node(Heap, node_2) == True:
  529.         Heap.remove(node_2)
  530.    
  531.     ###########################################################################
  532.     ##### Now we have removed both of the nodes, if applicable and we must remove the actor itself
  533.    
  534.     Heap.remove(actor)
  535.    
  536.     """
  537.    
  538.    Now if the actor has a Type A overlay, then we must check if the Heap contains
  539.    any other actors that have the same Id as actor and if not, then we must also
  540.    remove its overlay from the Heap
  541.    
  542.    We must also account for removing the nodes around the overlay, if applicable
  543.    
  544.    """
  545.    
  546.     if actor.overlay_type == 'A' and Actor_Id_In_Heap(Heap, actor.Id) == False:
  547.        
  548.         ##### First check the node above the overlay
  549.         overlay_index = Heap.index(Overlay_dict[actor.Id])
  550.         node1 = Heap[overlay_index - 1]
  551.        
  552.         if type(node1) != Node:
  553.             print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
  554.        
  555.         if Borders_Node(Heap, node1) == True:
  556.             Heap.remove(node1)
  557.        
  558.        
  559.         ##### Now we check the node below the overlay
  560.         overlay_index = Heap.index(Overlay_dict[actor.Id])
  561.         node2 = Heap[overlay_index + 1]
  562.        
  563.         if type(node2) != Node:
  564.             print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
  565.        
  566.         if Borders_Node(Heap, node2) == True:
  567.             Heap.remove(node2)
  568.        
  569.         ###########################################################################
  570.         ##### Now we have removed both of the nodes, if applicable and we must remove the overlay itself
  571.        
  572.         Heap.remove(Overlay_dict[actor.Id])
  573.  
  574.  
  575.  
  576. def Load_Scene(Heap, room):
  577.    
  578.     if len(Heap) != 2:
  579.         print("ERROR: Attempted to use Load_Scene() with an inappropriate Heap")
  580.    
  581.     entry_count = 0
  582.     for entry in room.priority_queue:
  583.        
  584.         ##### 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
  585.         if entry_count == room.clock_priority and room.clock_exists == False:
  586.            
  587.             ##### Allocate the 3-Day Clock actor
  588.             Allocate(Heap, Clock, Overlay_dict)
  589.             entry_count += 1
  590.        
  591.         ##### Allocate the entry in the room's priority queue
  592.         Allocate(Heap, entry, Overlay_dict)
  593.        
  594.         entry_count += 1
  595.    
  596.     ##### Now that all of the actors have been allocated, we want to add in all of the actors that the spawners spawn
  597.    
  598.     """
  599.    
  600.    NOTE: THIS DOES NOT HANDLE SPAWNERS OTHER THAN RUPEE CLUSTERS AT THE MOMENT
  601.    
  602.    In the future, it will need to be considered how the actors created by spawners
  603.    prioritize over each other... Spring MV is maybe the only place where this really matters
  604.    
  605.    """
  606.    
  607.     ##### Check for Rupee Cluster
  608.     if Overlay_In_Heap(Heap, Overlay_dict['00E8']) == True:
  609.        
  610.         for j in range(7):
  611.             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)
  612.            
  613.             Allocate(Heap, rupee, Overlay_dict)
  614.  
  615.  
  616.  
  617. def Actor_From_Room_In_Heap(Heap, Room_Number):
  618.    
  619.     """
  620.    
  621.    This function takes the Heap and the number of the Room in question as input
  622.    It returns True if there exists an Actor in the Heap with the inputted Room_Number and False otherwise
  623.    
  624.    """
  625.    
  626.     actor_from_room_in_heap = False
  627.    
  628.     for entry in Heap:
  629.        
  630.         if type(entry) == Actor and entry.room_number is Room_Number:
  631.            
  632.             actor_from_room_in_heap = True
  633.    
  634.     return actor_from_room_in_heap
  635.  
  636. def Cleared_Actor_In_Heap(Heap):
  637.    
  638.     """
  639.    
  640.    This function returns True if there is a cleared actor in the Heap and False otherwise
  641.    
  642.    """
  643.    
  644.     cleared_actor_in_heap = False
  645.    
  646.     for entry in Heap:
  647.        
  648.         if type(entry) == Actor and entry.cleared == True:
  649.            
  650.             cleared_actor_in_heap = True
  651.        
  652.     return cleared_actor_in_heap
  653.  
  654.  
  655. def Shared_Transition_Count(Heap, Room_Number_1, Room_Number_2):
  656.    
  657.     """
  658.    
  659.    This function returns the number of transitions (Planes/Doors) that are shared between
  660.    the two rooms with room numbers Room_Number_1 and Room_Number_2
  661.    
  662.    """
  663.    
  664.     shared_transition_count = 0
  665.    
  666.     for entry in Heap:
  667.        
  668.         if type(entry) == Actor and entry.transition != False:
  669.            
  670.             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):
  671.                
  672.                 shared_transition_count += 1
  673.    
  674.     return shared_transition_count
  675.  
  676. def Is_Shared_Transition(actor, Room_Number_1, Room_Number_2):
  677.    
  678.     """
  679.    
  680.    If actor is a transition shared between Rooms with numbers Room_Number_1 and Room_Number_2,
  681.    then this function returns True. Otherwise it returns False
  682.    
  683.    """
  684.    
  685.     is_shared_transition = False
  686.    
  687.     if type(actor) == Actor and actor.transition != False:
  688.        
  689.         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):
  690.            
  691.             is_shared_transition == True
  692.    
  693.     return is_shared_transition
  694.        
  695.  
  696. def Transition_Is_In_Room(actor, Room_Number):
  697.    
  698.     transition_is_in_room = False
  699.    
  700.     if type(actor) == Actor and actor.transition != False:
  701.        
  702.         if actor.transition[0] == Room_Number or actor.transition[1] == Room_Number:
  703.            
  704.             transition_is_in_room = True
  705.    
  706.     return transition_is_in_room
  707.  
  708.  
  709. def Find_Clock_List(Heap):
  710.    
  711.     """
  712.    
  713.    This function finds all clock actor instances in the Heap and returns a list of them, in order
  714.    
  715.    """
  716.    
  717.     clock_list = []
  718.    
  719.     for entry in Heap:
  720.        
  721.         if type(entry) == Actor and entry.Id == '015A':
  722.            
  723.             clock_list.append(entry)
  724.    
  725.     return clock_list
  726.    
  727.  
  728. def Load_Room(Heap, room, transition):
  729.    
  730.    
  731.     """
  732.    
  733.    This function updates the Heap after you enter room through transition
  734.    For example, you might enter Room0 through Plane1 or Door3
  735.    
  736.    Before executing the script, should probably define Plane1, Plane2, ...
  737.    Door1, Door2, ..., etc. as the corresponding entries from the room queues.
  738.    This will make the code more readable when looking for solutions
  739.    
  740.    
  741.    * First we load all of the actors from the new room
  742.    * Next, we deallocate everything (well, not literally everything...) from the previous room
  743.    
  744.    
  745.    Things that this function needs to handle:
  746.        
  747.        - make sure that you check if each actor was cleared or not (if clearable == True, otherwise it isn't applicable)
  748.        and then check if it is Category 5 to determine if it loads and immediately deallocates or not
  749.        
  750.        - checking which clock to deallocate (i.e. deallocate the one that comes later
  751.        on in the Heap if there are more than one). Maybe define a Find_Clocks function
  752.        
  753.        - make sure transition never deallocates and never attempts to allocate
  754.        
  755.        - make sure that the other Transitions unload and then reload (if applicable) after all of
  756.        the stuff from the previous room deallocated
  757.        
  758.        - when deallocating stuff from the room that isn't the room you're entering, be sure
  759.        not to deallocate the clock. Also be careful of relevant Transitions as they don't have
  760.        actual room numbers (replaced with False)
  761.        
  762.        - allocate stuff from spawners after the fact (even after planes)
  763.        
  764.    
  765.    """
  766.    
  767.     if transition not in Heap:
  768.         print('2222222222')
  769.        
  770.     if transition not in room.priority_queue:
  771.         print('44444444')
  772.    
  773.     if (transition not in Heap) or (transition not in room.priority_queue):
  774.         print("ERROR: Attempted to use Load_Room() with an invalid transition")
  775.    
  776.     current_room_number = -1
  777.     new_room_number = room.number
  778.    
  779.     if transition.transition[0] == room.number:
  780.         current_room_number = transition.transition[1]
  781.     elif transition.transition[1] == room.number:
  782.         current_room_number = transition.transition[0]
  783.     else:
  784.         print("ERROR: Error with transition list (Load_Room() error message)")
  785.    
  786.     """
  787.    First we load all of the actors from the new room, EXCEPT for: the plane/door
  788.    we pass through AND any other shared transitions AND any actors with both
  789.    cleared == True and Category == 5 (these ones never attempt to load)
  790.    """
  791.    
  792.     for actor in room.priority_queue:
  793.        
  794.         ### If the actor is not a Transition OR if the actor is a transition but doesn't connect to the current room
  795.         if (actor.transition == False) or (actor.transition != False and actor.transition[0] != current_room_number and actor.transition[1] != current_room_number):
  796.            
  797.             ### If the actor is Category 5, then only attempt to load it if it has not been cleared
  798.             if actor.category != 5 or actor.cleared == False:
  799.                
  800.                 Allocate(Heap, actor, Overlay_dict)
  801.    
  802.     """
  803.    - Now all of the relevant actors from the new room have been allocated
  804.    - Now we need to immediately deallocate any actors with Clearable == True and Cleared == True
  805.    - We also need to deallocate any transitions which are shared between the current room and the new room
  806.      EXCEPT for transition itself (the transition that we passed through to get to the new room)
  807.    - We also need to deallocate the second clock actor in the Heap if it exists (do this after everything else for simplicity)
  808.      
  809.      Note that "current_room_number" is the room number of the room we were in before loading the new room
  810.    """
  811.  
  812.     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:
  813.        
  814.         for entry in Heap:
  815.            
  816.             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):
  817.                
  818.                 Deallocate(Heap, entry)
  819.    
  820.     ########## Now we will find all of the clocks and deallocate the second clock if it exists (and report error if more than two clocks)
  821.    
  822.     Clock_List = Find_Clock_List(Heap)
  823.    
  824.     if len(Clock_List) > 2:
  825.         print("ERROR: More than 2 Clocks in the Actor Heap (Load_Room() Error Message)")
  826.     elif len(Clock_List) < 1:
  827.         print("ERROR: No Clock Actor Instance in the Actor Heap (Load_Room() Error Message)")
  828.    
  829.     ##### If there are two clocks, then we deallocate the second clock that appears in the Heap
  830.     if len(Clock_List) > 1:
  831.        
  832.         Deallocate(Heap, Clock_List[1])
  833.    
  834.    
  835.     ##### Now we allocate any shared transitions EXCEPT for transition itself (the door/plane we entered to get into this room)
  836.    
  837.     for entry in room.priority_queue:
  838.        
  839.         # If entry is a shared transition and is NOT the transition that we passed through
  840.         if (type(entry) == Actor) and (entry.transition != False) and Is_Shared_Transition(entry, current_room_number, new_room_number) == True and (entry != transition):
  841.            
  842.             Allocate(Heap, entry, Overlay_dict)
  843.    
  844.     ###################################### Now we only have to account for allocating things from spawners
  845.    
  846.    
  847.     """
  848.    
  849.    NOTE: THIS DOES NOT HANDLE SPAWNERS OTHER THAN RUPEE CLUSTERS AT THE MOMENT
  850.    
  851.    In the future, it will need to be considered how the actors created by spawners
  852.    prioritize over each other... Spring MV is maybe the only place where this really matters
  853.    
  854.    """
  855.    
  856.     ##### Check for Rupee Cluster
  857.     if Overlay_In_Heap(Heap, Overlay_dict['00E8']) == True:
  858.        
  859.         for j in range(7):
  860.             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)
  861.            
  862.             Allocate(Heap, rupee, Overlay_dict)
  863.        
  864.  
  865.  
  866.  
  867.  
  868. def Display_Heap(Heap):
  869.    
  870.     for entry in Heap:
  871.        
  872.         if type(entry) == Node:
  873.            
  874.             print(hex(entry.address) + '-----' + 'NODE-----------------')
  875.            
  876.         elif type(entry) == Overlay:
  877.            
  878.             print(hex(entry.address) + '     ' + entry.Id + '     ' + 'OVERLAY')
  879.        
  880.         elif type(entry) == Actor:
  881.            
  882.             print(hex(entry.address) + '     ' + entry.Id + '     ' + 'INSTANCE')
  883.        
  884.         else:
  885.             print("ERROR!!! Unexpected Entry Type in Heap!!!!!!!!!")
  886.  
  887.  
  888. ###############################################################################
  889.  
  890.  
  891. """
  892.  
  893. Before proceeding, we should define all of the transitions we plan on passing through
  894.  
  895. Since "Beneath the Graveyard" is relatively simple and I currently only want to consider
  896. passing through a single plane, I will just define Plane_1 to be the plane shared between
  897. Room0 and Room1
  898.  
  899. This loading plane happens the be the second element in Room0_queue, so I will define it based on that
  900.  
  901. """
  902.  
  903. Plane_1 = Room0_queue[1]
  904.  
  905.  
  906. """
  907.  
  908. Below this we can consider a sequence of Room loads and then display the Heap
  909.  
  910. """
  911.  
  912.  
  913. Load_Scene(Heap, Room0)
  914.  
  915.  
  916. Load_Room(Heap, Room1, Plane_1)
  917.  
  918. Load_Room(Heap, Room0, Plane_1)
  919.  
  920. Load_Room(Heap, Room1, Plane_1)
  921.  
  922. Load_Room(Heap, Room0, Plane_1)
  923.  
  924.  
  925. Display_Heap(Heap)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement