mirror of
				https://github.com/MarioSpore/Grinch-AP.git
				synced 2025-10-21 20:21:32 -06:00 
			
		
		
		
	
		
			
	
	
		
			121 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			121 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | from math import ceil | ||
|  | 
 | ||
|  | from .LocationList import location_table | ||
|  | 
 | ||
|  | # Create a dict of dicts of the format: | ||
|  | # { | ||
|  | #   scene_number_n : { | ||
|  | #       room_setup_number: max_flags | ||
|  | #   } | ||
|  | # } | ||
|  | # where room_setup_number defines the room + scene setup as ((setup << 6) + room) for scene n | ||
|  | # and max_flags is the highest used enemy flag for that setup/room | ||
|  | def get_collectible_flag_table(world): | ||
|  |     scene_flags = {} | ||
|  |     alt_list = [] | ||
|  |     for i in range(0, 101): | ||
|  |         max_room_num = 0 | ||
|  |         max_enemy_flag = 0 | ||
|  |         scene_flags[i] = {} | ||
|  |         for location in world.get_locations(): | ||
|  |             if(location.scene == i and location.type in ["Freestanding", "Pot", "FlyingPot", "Crate", "SmallCrate", "Beehive", "RupeeTower"]): | ||
|  |                 default = location.default | ||
|  |                 if(isinstance(default, list)): #List of alternative room/setup/flag to use | ||
|  |                     primary_tuple = default[0] | ||
|  |                     for c in range(1,len(default)): | ||
|  |                         alt_list.append((location, default[c], primary_tuple)) | ||
|  |                     default = location.default[0] #Use the first tuple as the primary tuple | ||
|  |                 if(isinstance(default, tuple)): | ||
|  |                     room, setup, flag = default | ||
|  |                     room_setup = room + (setup << 6) | ||
|  |                     if(room_setup in scene_flags[i].keys()): | ||
|  |                         curr_room_max_flag = scene_flags[i][room_setup] | ||
|  |                         if flag > curr_room_max_flag: | ||
|  |                             scene_flags[i][room_setup] = flag | ||
|  |                     else: | ||
|  |                         scene_flags[i][room_setup] = flag | ||
|  |         if len(scene_flags[i].keys()) == 0: | ||
|  |             del scene_flags[i] | ||
|  |         #scene_flags.append((i, max_enemy_flag)) | ||
|  |     return (scene_flags, alt_list) | ||
|  | 
 | ||
|  | # Create a byte array from the scene flag table created by get_collectible_flag_table | ||
|  | def get_collectible_flag_table_bytes(scene_flag_table): | ||
|  |     num_flag_bytes = 0 | ||
|  |     bytes = bytearray() | ||
|  |     bytes.append(len(scene_flag_table.keys())) | ||
|  |     for scene_id in scene_flag_table.keys(): | ||
|  |         rooms = scene_flag_table[scene_id] | ||
|  |         room_count = len(rooms.keys()) | ||
|  |         bytes.append(scene_id) | ||
|  |         bytes.append(room_count) | ||
|  |         for room in rooms: | ||
|  |             bytes.append(room) | ||
|  |             bytes.append((num_flag_bytes & 0xFF00) >> 8) | ||
|  |             bytes.append(num_flag_bytes & 0x00FF ) | ||
|  |             num_flag_bytes += ceil((rooms[room] + 1) / 8) | ||
|  |              | ||
|  |     return bytes, num_flag_bytes | ||
|  | 
 | ||
|  | def get_alt_list_bytes(alt_list): | ||
|  |     bytes = bytearray() | ||
|  |     for entry in alt_list: | ||
|  |         location, alt, primary = entry | ||
|  |         room, scene_setup, flag = alt | ||
|  |         alt_override = (room << 8) + (scene_setup << 14) + flag | ||
|  |         room, scene_setup, flag = primary | ||
|  |         primary_override = (room << 8) + (scene_setup << 14) + flag | ||
|  |         bytes.append(location.scene) | ||
|  |         bytes.append(0x06) | ||
|  |         bytes.append((alt_override & 0xFF00) >> 8) | ||
|  |         bytes.append(alt_override & 0xFF) | ||
|  |         bytes.append(location.scene) | ||
|  |         bytes.append(0x06) | ||
|  |         bytes.append((primary_override & 0xFF00) >> 8) | ||
|  |         bytes.append(primary_override & 0xFF) | ||
|  |     return bytes | ||
|  | 
 | ||
|  | # AP method to retrieve address + bit for each item | ||
|  | # Based on get_collectible_flag_offset in the C code | ||
|  | def get_collectible_flag_addresses(world, collectible_scene_flags_table): | ||
|  | 
 | ||
|  |     # Ported directly from get_items.c | ||
|  |     def get_collectible_flag_offset(scene: int, room: int, setup_id: int) -> int: | ||
|  |         num_scenes = collectible_scene_flags_table[0] | ||
|  |         index = 1 | ||
|  |         scene_id = 0 | ||
|  |         room_id = 0 | ||
|  |         room_setup_count = 0 | ||
|  |         room_byte_offset = 0 | ||
|  |         # Loop through collectible_scene_flags_table until we find the right scene | ||
|  |         while num_scenes > 0: | ||
|  |             scene_id = collectible_scene_flags_table[index] | ||
|  |             room_setup_count = collectible_scene_flags_table[index+1] | ||
|  |             index += 2 | ||
|  |             if scene_id == scene:  # found the scene | ||
|  |                 # Loop through each room/setup combination until we find the right one. | ||
|  |                 for i in range(room_setup_count): | ||
|  |                     room_id = collectible_scene_flags_table[index] & 0x3F | ||
|  |                     setup_id_temp = (collectible_scene_flags_table[index] & 0xC0) >> 6 | ||
|  |                     room_byte_offset = (collectible_scene_flags_table[index+1] << 8) + collectible_scene_flags_table[index+2] | ||
|  |                     index += 3 | ||
|  |                     if room_id == room and setup_id_temp == setup_id: | ||
|  |                         return room_byte_offset | ||
|  |             else:  # Not the right scene, skip to the next one | ||
|  |                 index += 3 * room_setup_count | ||
|  |             num_scenes -= 1 | ||
|  |         return -1 | ||
|  | 
 | ||
|  |     collectible_flag_addresses = {} | ||
|  |     for location in world.get_locations(): | ||
|  |         if location.type in ["Freestanding", "Pot", "FlyingPot", "Crate", "SmallCrate", "Beehive", "RupeeTower"]: | ||
|  |             default = location.default | ||
|  |             if isinstance(default, list): | ||
|  |                 default = default[0] | ||
|  |             room, setup, flag = default | ||
|  |             offset = get_collectible_flag_offset(location.scene, room, setup) | ||
|  |             item_id = location.address | ||
|  |             collectible_flag_addresses[item_id] = [offset, flag] | ||
|  |     return collectible_flag_addresses | ||
|  | 
 |