Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- - This script does NOT handle spawners (except for rupee clusters)
- - This script does NOT handle scarecrow memory leak
- - This script does not account for ISoT memory leak for solution options
- """
- """
- Note: Node size is 0x10 = 16 on English and 0x30 = 48 on JP
- """
- version = 'English'
- if version == 'English':
- node_size = 0x10
- elif version == 'JP':
- nodesize = 0x30
- else:
- print('Error: Invalid Version (choose "English" or "JP" )')
- class Actor:
- """
- name: name of the actor, some string
- Id: Actor id, string of 4 integers
- size: the size of an actor instance for this actor (number of bytes, in decimal)
- category: the actor category (category 5 is treated differently than others)
- For now, giving everything not category 5 a category of 0
- overlay_type: determines where the AF loads in the heap
- unloadable: a boolean for whether or not it is possible to deallocate this actor without changing rooms
- address: the memory address of the actor in decimal (can convert to a hex string for output)
- Note: The earliest address we handle is 0x40B150 = 4239696. All addresses must be multiples of 16
- room_number: the number of the room these actors are associated with; if the actor is a transition (i..e Plane
- or Door), then set room_numer = False
- priority: an index to differentiate copies of the same instance
- from_spawner: True or False (True if it is from a spawner, like rupees from a cluster; False otherwise)
- 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
- 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
- cleared: True if the flag was set to clear this actor, False otherwise
- """
- def __init__(self, name, Id, size, category, overlay_type, unloadable, address, room_number, priority, from_spawner, transition, clearable, cleared):
- self.name = name
- self.Id = Id
- self.size = size
- self.category = category
- self.overlay_type = overlay_type
- self.unloadable = unloadable
- self.address = address
- self.room_number = room_number
- self.priority = priority
- self.from_spawner = from_spawner
- self.transition = transition
- self.clearable = clearable
- self.cleared = cleared
- class Room:
- """
- number: the room number (i.e. Room 0 has number 0)
- priority_queue: this will be the list of actor instances of the room, in order
- clock_exists: boolean for whether or not the clock is an actor in the queue
- clock_priority: if clock_exists == False, then clock_priority will be a number
- to determine where in the queue the clock should be loaded, for
- example, if clock_priority is 2, then it means that the clock
- should be the 3rd actor to appear in the queue (first index is 0)
- """
- def __init__(self, number, priority_queue, clock_exists, clock_priority):
- self.number = number
- self.priority_queue = priority_queue
- self.clock_exists = clock_exists
- self.clock_priority = clock_priority
- class Node:
- """
- address: which address in memory the node is at (as a base-10 integer for now)
- size: nodes should be 16 bytes (english), so input 16
- """
- def __init__(self, address, size):
- self.address = address
- self.size = size
- class Overlay:
- def __init__(self, address, Id, size):
- self.address = address
- self.Id = Id
- self.size = size
- """
- We define the Clock actor ahead of time as it is not necessarily present in each room
- """
- 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)
- Room0_queue = [
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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)
- ]
- Room1_queue = [
- 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),
- Room0_queue[1],
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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),
- 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)
- ]
- ###############################################################################
- Room0 = Room(0, Room0_queue, False, 2)
- Room1 = Room(1, Room1_queue, False, 2)
- """
- In Overlay_dict we collect all of the Overlays of Type A, where the keys are
- the corresponding actor ids
- """
- # NOTE: This must be named "Overlay_dict" because it is hardcoded in some functions, like the Deallocate() function
- Overlay_dict = {
- '015A' : Overlay(address=0, Id='015A', size=6000),
- '00E8' : Overlay(address=0, Id='00E8', size=1984),
- '0170' : Overlay(address=0, Id='0170', size=10688),
- '0039' : Overlay(address=0, Id='0039', size=3552),
- '0082' : Overlay(address=0, Id='0082', size=9040),
- '0158' : Overlay(address=0, Id='0158', size=1104),
- '015B' : Overlay(address=0, Id='015B', size=6048),
- '0006' : Overlay(address=0, Id='0006', size=8640)
- }
- """
- Here we collect a list of Actor Ids for spawners. So far this includes:
- 00E8: Rupee Cluster
- """
- Spawner_Ids = ['00E8']
- """
- We initialize the Heap as a list, putting a node with address 0x40B140 in the 0th entry
- and we place a dummy node at the end of the Heap so that there will always exist two
- consecutive nodes for us to define a condition for which free space in the Heap exists
- Keep in mind that the 0x5FFFFF address in the dummy node will not reflect the actual
- address of the corresponding node in-game, but it also isn't relevant to heap manipulation
- since it is so far down
- """
- Heap = [Node(0x40B140, node_size), Node(0x5FFFFF, node_size)]
- def Overlay_In_Heap(Heap, overlay):
- """
- Overlay is the overlay that we want to check whether or not it is in the Heap
- This function will return True if Overlay is in the Heap and False otherwise
- """
- overlay_in_heap = False
- for entry in Heap:
- if type(entry) == Overlay and entry.Id == overlay.Id:
- overlay_in_heap = True
- return overlay_in_heap
- def Actor_Id_In_Heap(Heap, actor_id):
- """
- actor_id is the Id that we want to check for
- This function will return True if there exists an Actor in the Heap that
- has actor_id as its Id and it will return False otherwise
- """
- actor_id_in_heap = False
- for entry in Heap:
- if type(entry) == Actor and entry.Id == actor_id:
- actor_id_in_heap = True
- return actor_id_in_heap
- def Find_Gaps(Heap):
- """
- This function will find all consecutive nodes and output a list of 4-tuples
- where the first two entries correspond to the indices of each node in the list
- and the last two entries correspond to the addresses of each node
- The list should be in order, from the start of the Heap to the end of the Heap
- """
- consecutive_node_count = 0
- node_1_address = 0
- node_2_address = 0
- node_1_index = 0
- node_2_index = 0
- consecutive_node_list = []
- for entry in Heap:
- if type(entry) == Node and consecutive_node_count == 0:
- node_1_address = entry.address
- node_1_index = Heap.index(entry)
- consecutive_node_count += 1
- elif type(entry) == Node and consecutive_node_count == 1:
- node_2_address = entry.address
- node_2_index = Heap.index(entry)
- consecutive_node_list.append((node_1_index, node_2_index, node_1_address, node_2_address))
- consecutive_node_count += 1
- elif type(entry) != Node:
- consecutive_node_count = 0
- elif type(entry) == Node and consecutive_node_count > 1:
- consecutive_node_count += 1
- print("ERROR: More than 2 consecutive nodes!! (Find_Gaps() Error Message)")
- return consecutive_node_list
- def Allocate(Heap, actor, Overlay_Dict):
- """
- actor is the actor that we want to allocate into the Heap
- Overlay_Dict is a dictionary where the keys are the actor ids which point to the corresponding Overlays
- This function will account for placing nodes and overlays
- """
- #Overlay = Overlay_Dict[actor.Id]
- #Overlay_Allocated = False
- #if Overlay_In_Heap(Heap, Overlay) == True:
- # Overlay_Allocated = True
- Actor_Allocated = False
- """
- ##### Not yet defined, not sure if I will bother; not really necessary. Probably should for debugging
- if Actor_In_Heap == True:
- print('Error: This Actor is already allocated!! (Error message from Allocate() function)')
- """
- gap_list = Find_Gaps(Heap)
- # Because we initialize the Heap with 2 nodes, there should always be at least one gap
- if len(gap_list) < 1:
- print('ERROR: len(gap_list) < 1 in Allocate() function')
- # If the Overlay is type A and the Overlay is not already in the Heap, then we want to allocate the overlay first
- if actor.overlay_type == 'A':
- ##### We only define Overlay for Type A overlays because Overlay_Dict only has Type A overlays
- Overlay = Overlay_Dict[actor.Id]
- Overlay_Allocated = False
- if Overlay_In_Heap(Heap, Overlay) == True:
- Overlay_Allocated = True
- if Overlay_In_Heap(Heap, Overlay) == False:
- for gap in gap_list:
- if Overlay_Allocated == True:
- break ##### This ensures we don't add in the same Overlay multiple times
- node_2_index = gap[1]
- node_1_address = gap[2]
- node_2_address = gap[3]
- gap_size = node_2_address - node_1_address - node_size
- ##### Case 1: the Overlay can fit, but there is NOT enough space for an extra node
- # Note that gap_size is always a multiple of 16
- if Overlay.size <= gap_size and Overlay.size > gap_size - 2*node_size:
- Overlay.address = node_1_address + node_size
- Heap.insert(node_2_index, Overlay)
- Overlay_Allocated = True
- ##### Case 2: the Overlay can fit and a new node can also fit
- elif Overlay.size <= gap_size and Overlay.size <= gap_size - 2*node_size:
- Overlay.address = node_1_address + node_size
- Heap.insert(node_2_index, Overlay)
- ########### ADD IN THE NODE HERE
- if Overlay.size%16 > 0:
- Heap.insert(node_2_index + 1, Node(address=Overlay.address + Overlay.size + (16 - Overlay.size%16), size=node_size))
- elif Overlay.size%16 == 0:
- Heap.insert(node_2_index + 1, Node(address=Overlay.address + Overlay.size, size=node_size))
- Overlay_Allocated = True
- ############ Now the overlay (if applicable) has been allocated. Now we need to allocate the actor.
- ##### We need to update the gaps_list to account for the overlay being allocated in the Heap already
- gap_list = Find_Gaps(Heap)
- for gap in gap_list:
- if Actor_Allocated == True:
- break ##### This ensures we don't add in the same Actor multiple times
- node_2_index = gap[1]
- node_1_address = gap[2]
- node_2_address = gap[3]
- gap_size = node_2_address - node_1_address - node_size
- ##### Case 1: the Actor can fit, but there is NOT enough space for an extra node
- # Note that gap_size is always a multiple of 16
- if actor.size <= gap_size and actor.size > gap_size - 2*node_size:
- actor.address = node_1_address + node_size
- Heap.insert(node_2_index, actor)
- Actor_Allocated = True
- ##### Case 2: the Actor can fit and a new node can also fit
- elif actor.size <= gap_size and actor.size <= gap_size - 2*node_size:
- actor.address = node_1_address + node_size
- Heap.insert(node_2_index, actor)
- ########### ADD IN THE NODE HERE
- if actor.size%16 > 0:
- Heap.insert(node_2_index + 1, Node(address=actor.address + actor.size + (16 - actor.size%16), size=node_size))
- elif actor.size%16 == 0:
- Heap.insert(node_2_index + 1, Node(address=actor.address + actor.size, size=node_size))
- Actor_Allocated = True
- def Borders_Node(Heap, entry):
- """
- This function takes an entry of the Heap as input and determines whether or
- not this entry is adjacent to a node in the heap (the purpose of this is to
- check if a node is bordering another node since actors and overlays should
- be bordering two nodes under every circumstance)
- Returns True if the entry is bordering a node, returns False otherwise
- """
- borders_node = False
- entry_index = Heap.index(entry)
- border_1_is_node = False
- border_2_is_node = False
- if entry_index != 0:
- border_1 = Heap[entry_index - 1]
- if type(border_1) == Node:
- border_1_is_node = True
- if entry_index != len(Heap) - 1:
- border_2 = Heap[entry_index + 1]
- if type(border_2) == Node:
- border_2_is_node = True
- if border_1_is_node == True or border_2_is_node == True:
- borders_node = True
- return borders_node
- def Deallocate(Heap, actor):
- """
- actor is the actor that we want to be deallocated from the Heap
- This function will account for removing nodes and overlays
- ##### Remove the actor AND node if applicable
- ##### Check if any actors with the same Id are still in the Heap
- ##### if not (and the actor has overlay Type A), then remove the overlay
- We only remove a node if it is part of a gap before deallocating the actor
- That is, we only remove a node if it borders another node before the actor is deallocated
- """
- if type(actor) != Actor:
- print("ERROR: Attempted to deallocate something other than an Actor (Deallocate() function error message)")
- # The index of where the actor is in the Heap before being deallocated; this will change after we remove the first node
- actor_index = Heap.index(actor)
- ##### First check the node above the actor in the Heap
- node_1 = Heap[actor_index - 1]
- if type(node_1) != Node:
- print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
- if Borders_Node(Heap, node_1) == True:
- Heap.remove(node_1)
- ########## Now the first node has been removed and the indices of the Heap shift
- ##### Now we check the node below the actor in the Heap
- # The index of where the actor is in the Heap before being deallocated; this will change after we remove the first node
- actor_index = Heap.index(actor)
- node_2 = Heap[actor_index + 1]
- if type(node_2) != Node:
- print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
- if Borders_Node(Heap, node_2) == True:
- Heap.remove(node_2)
- ###########################################################################
- ##### Now we have removed both of the nodes, if applicable and we must remove the actor itself
- Heap.remove(actor)
- """
- Now if the actor has a Type A overlay, then we must check if the Heap contains
- any other actors that have the same Id as actor and if not, then we must also
- remove its overlay from the Heap
- We must also account for removing the nodes around the overlay, if applicable
- """
- if actor.overlay_type == 'A' and Actor_Id_In_Heap(Heap, actor.Id) == False:
- ##### First check the node above the overlay
- overlay_index = Heap.index(Overlay_dict[actor.Id])
- node1 = Heap[overlay_index - 1]
- if type(node1) != Node:
- print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
- if Borders_Node(Heap, node1) == True:
- Heap.remove(node1)
- ##### Now we check the node below the overlay
- overlay_index = Heap.index(Overlay_dict[actor.Id])
- node2 = Heap[overlay_index + 1]
- if type(node2) != Node:
- print("ERROR: One of the nodes is not actually a node! (Deallocate() function error message)")
- if Borders_Node(Heap, node2) == True:
- Heap.remove(node2)
- ###########################################################################
- ##### Now we have removed both of the nodes, if applicable and we must remove the overlay itself
- Heap.remove(Overlay_dict[actor.Id])
- def Load_Scene(Heap, room):
- if len(Heap) != 2:
- print("ERROR: Attempted to use Load_Scene() with an inappropriate Heap")
- entry_count = 0
- for entry in room.priority_queue:
- ##### 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
- if entry_count == room.clock_priority and room.clock_exists == False:
- ##### Allocate the 3-Day Clock actor
- Allocate(Heap, Clock, Overlay_dict)
- entry_count += 1
- ##### Allocate the entry in the room's priority queue
- Allocate(Heap, entry, Overlay_dict)
- entry_count += 1
- ##### Now that all of the actors have been allocated, we want to add in all of the actors that the spawners spawn
- """
- NOTE: THIS DOES NOT HANDLE SPAWNERS OTHER THAN RUPEE CLUSTERS AT THE MOMENT
- In the future, it will need to be considered how the actors created by spawners
- prioritize over each other... Spring MV is maybe the only place where this really matters
- """
- ##### Check for Rupee Cluster
- if Overlay_In_Heap(Heap, Overlay_dict['00E8']) == True:
- for j in range(7):
- 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)
- Allocate(Heap, rupee, Overlay_dict)
- def Actor_From_Room_In_Heap(Heap, Room_Number):
- """
- This function takes the Heap and the number of the Room in question as input
- It returns True if there exists an Actor in the Heap with the inputted Room_Number and False otherwise
- """
- actor_from_room_in_heap = False
- for entry in Heap:
- if type(entry) == Actor and entry.room_number is Room_Number:
- actor_from_room_in_heap = True
- return actor_from_room_in_heap
- def Cleared_Actor_In_Heap(Heap):
- """
- This function returns True if there is a cleared actor in the Heap and False otherwise
- """
- cleared_actor_in_heap = False
- for entry in Heap:
- if type(entry) == Actor and entry.cleared == True:
- cleared_actor_in_heap = True
- return cleared_actor_in_heap
- def Shared_Transition_Count(Heap, Room_Number_1, Room_Number_2):
- """
- This function returns the number of transitions (Planes/Doors) that are shared between
- the two rooms with room numbers Room_Number_1 and Room_Number_2
- """
- shared_transition_count = 0
- for entry in Heap:
- if type(entry) == Actor and entry.transition != False:
- 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):
- shared_transition_count += 1
- return shared_transition_count
- def Is_Shared_Transition(actor, Room_Number_1, Room_Number_2):
- """
- If actor is a transition shared between Rooms with numbers Room_Number_1 and Room_Number_2,
- then this function returns True. Otherwise it returns False
- """
- is_shared_transition = False
- if type(actor) == Actor and actor.transition != False:
- 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):
- is_shared_transition == True
- return is_shared_transition
- def Transition_Is_In_Room(actor, Room_Number):
- transition_is_in_room = False
- if type(actor) == Actor and actor.transition != False:
- if actor.transition[0] == Room_Number or actor.transition[1] == Room_Number:
- transition_is_in_room = True
- return transition_is_in_room
- def Find_Clock_List(Heap):
- """
- This function finds all clock actor instances in the Heap and returns a list of them, in order
- """
- clock_list = []
- for entry in Heap:
- if type(entry) == Actor and entry.Id == '015A':
- clock_list.append(entry)
- return clock_list
- def Load_Room(Heap, room, transition):
- """
- This function updates the Heap after you enter room through transition
- For example, you might enter Room0 through Plane1 or Door3
- Before executing the script, should probably define Plane1, Plane2, ...
- Door1, Door2, ..., etc. as the corresponding entries from the room queues.
- This will make the code more readable when looking for solutions
- * First we load all of the actors from the new room
- * Next, we deallocate everything (well, not literally everything...) from the previous room
- Things that this function needs to handle:
- - make sure that you check if each actor was cleared or not (if clearable == True, otherwise it isn't applicable)
- and then check if it is Category 5 to determine if it loads and immediately deallocates or not
- - checking which clock to deallocate (i.e. deallocate the one that comes later
- on in the Heap if there are more than one). Maybe define a Find_Clocks function
- - make sure transition never deallocates and never attempts to allocate
- - make sure that the other Transitions unload and then reload (if applicable) after all of
- the stuff from the previous room deallocated
- - when deallocating stuff from the room that isn't the room you're entering, be sure
- not to deallocate the clock. Also be careful of relevant Transitions as they don't have
- actual room numbers (replaced with False)
- - allocate stuff from spawners after the fact (even after planes)
- """
- if transition not in Heap:
- print('2222222222')
- if transition not in room.priority_queue:
- print('44444444')
- if (transition not in Heap) or (transition not in room.priority_queue):
- print("ERROR: Attempted to use Load_Room() with an invalid transition")
- current_room_number = -1
- new_room_number = room.number
- if transition.transition[0] == room.number:
- current_room_number = transition.transition[1]
- elif transition.transition[1] == room.number:
- current_room_number = transition.transition[0]
- else:
- print("ERROR: Error with transition list (Load_Room() error message)")
- """
- First we load all of the actors from the new room, EXCEPT for: the plane/door
- we pass through AND any other shared transitions AND any actors with both
- cleared == True and Category == 5 (these ones never attempt to load)
- """
- for actor in room.priority_queue:
- ### If the actor is not a Transition OR if the actor is a transition but doesn't connect to the current room
- if (actor.transition == False) or (actor.transition != False and actor.transition[0] != current_room_number and actor.transition[1] != current_room_number):
- ### If the actor is Category 5, then only attempt to load it if it has not been cleared
- if actor.category != 5 or actor.cleared == False:
- Allocate(Heap, actor, Overlay_dict)
- """
- - Now all of the relevant actors from the new room have been allocated
- - Now we need to immediately deallocate any actors with Clearable == True and Cleared == True
- - We also need to deallocate any transitions which are shared between the current room and the new room
- EXCEPT for transition itself (the transition that we passed through to get to the new room)
- - We also need to deallocate the second clock actor in the Heap if it exists (do this after everything else for simplicity)
- Note that "current_room_number" is the room number of the room we were in before loading the new room
- """
- 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:
- for entry in Heap:
- 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):
- Deallocate(Heap, entry)
- ########## Now we will find all of the clocks and deallocate the second clock if it exists (and report error if more than two clocks)
- Clock_List = Find_Clock_List(Heap)
- if len(Clock_List) > 2:
- print("ERROR: More than 2 Clocks in the Actor Heap (Load_Room() Error Message)")
- elif len(Clock_List) < 1:
- print("ERROR: No Clock Actor Instance in the Actor Heap (Load_Room() Error Message)")
- ##### If there are two clocks, then we deallocate the second clock that appears in the Heap
- if len(Clock_List) > 1:
- Deallocate(Heap, Clock_List[1])
- ##### Now we allocate any shared transitions EXCEPT for transition itself (the door/plane we entered to get into this room)
- for entry in room.priority_queue:
- # If entry is a shared transition and is NOT the transition that we passed through
- if (type(entry) == Actor) and (entry.transition != False) and Is_Shared_Transition(entry, current_room_number, new_room_number) == True and (entry != transition):
- Allocate(Heap, entry, Overlay_dict)
- ###################################### Now we only have to account for allocating things from spawners
- """
- NOTE: THIS DOES NOT HANDLE SPAWNERS OTHER THAN RUPEE CLUSTERS AT THE MOMENT
- In the future, it will need to be considered how the actors created by spawners
- prioritize over each other... Spring MV is maybe the only place where this really matters
- """
- ##### Check for Rupee Cluster
- if Overlay_In_Heap(Heap, Overlay_dict['00E8']) == True:
- for j in range(7):
- 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)
- Allocate(Heap, rupee, Overlay_dict)
- def Display_Heap(Heap):
- for entry in Heap:
- if type(entry) == Node:
- print(hex(entry.address) + '-----' + 'NODE-----------------')
- elif type(entry) == Overlay:
- print(hex(entry.address) + ' ' + entry.Id + ' ' + 'OVERLAY')
- elif type(entry) == Actor:
- print(hex(entry.address) + ' ' + entry.Id + ' ' + 'INSTANCE')
- else:
- print("ERROR!!! Unexpected Entry Type in Heap!!!!!!!!!")
- ###############################################################################
- """
- Before proceeding, we should define all of the transitions we plan on passing through
- Since "Beneath the Graveyard" is relatively simple and I currently only want to consider
- passing through a single plane, I will just define Plane_1 to be the plane shared between
- Room0 and Room1
- This loading plane happens the be the second element in Room0_queue, so I will define it based on that
- """
- Plane_1 = Room0_queue[1]
- """
- Below this we can consider a sequence of Room loads and then display the Heap
- """
- Load_Scene(Heap, Room0)
- Load_Room(Heap, Room1, Plane_1)
- Load_Room(Heap, Room0, Plane_1)
- Load_Room(Heap, Room1, Plane_1)
- Load_Room(Heap, Room0, Plane_1)
- Display_Heap(Heap)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement