Big enemizer updates

Fix sheets
Health + damage rando
Logical kill rooms
This commit is contained in:
aerinon
2023-03-30 16:12:46 -06:00
parent d85a63ece1
commit a0b781521f
22 changed files with 2224 additions and 947 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -124,7 +124,6 @@ def boss_writes(world, player, rom):
eye_number = random.randint(0, 8) # randomize moldorm eyes (var + 1)
rom.write_byte(snes_to_pc(0x368102), eye_number) # enemizer flag
rom.write_byte(snes_to_pc(0x1DDBB3), eye_number) # loop variable
# todo: flag vitreous key fix (prize on the eyes)
data_tables = world.data_tables[player]
arrghus_can_swim = True
water_tiles_on = True

View File

@@ -0,0 +1,8 @@
from Utils import load_yaml
class DamageTable:
def __init__(self):
self.damage_table = load_yaml(['source', 'enemizer', 'damage_table.yaml'])
self.enemy_damage = load_yaml(['source', 'enemizer', 'enemy_damage_table.yaml'])

View File

@@ -1,46 +1,24 @@
import RaceRandom as random
from Utils import snes_to_pc
from source.dungeon.EnemyList import SpriteType
from source.dungeon.EnemyList import SpriteType, EnemySprite
from source.dungeon.RoomList import Room010C
from source.enemizer.SpriteSheets import sub_group_choices, setup_required_dungeon_groups
from source.enemizer.SpriteSheets import sub_group_choices
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets
from source.enemizer.TilePattern import tile_patterns
water_rooms = {
0x16, 0x28, 0x34, 0x36, 0x38, 0x46, 0x66
} # these room need to be locked on the gfx ID : 17
# todo: task list
# anti-fairy shutter logic
# check cucco, implement flag for certain immune enemies that are okay in shutter rooms
# Room 0x16 (sprites 4,5,6 need to be water but 0-3 don't)
#
shutter_sprites = {
0xb8: {0, 1, 2, 3, 4, 5}, 0xb: {4, 5, 6, 7, 8, 9}, 0x1b: {3, 4, 5}, 0x4b: {0, 3, 4}, 0x4: {9, 13, 14},
0x24: {3, 5, 6}, # not sure about 6 - bunny beam under pot
0x24: {3, 4, 5, 6}, # not sure about 6 - bunny beam under pot
0x28: {0, 1, 2, 3, 4}, 0xe: {0, 1, 2, 3}, 0x2e: {0, 1, 2, 3, 4, 5}, 0x3e: {1, 2}, 0x6e: {0, 1, 2, 3, 4},
0x31: {7, 8, 10}, 0x44: {2, 3, 5}, 0x45: {1, 2, 3}, 0x53: {5, 6, 8, 9, 10}, 0x75: {0, 2, 3, 4, 5},
0x85: {2, 3, 4, 5}, 0x5d: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, 0x6b: {5, 6, 7, 8, 9, 10, 11, 12, 13},
0x6d: {0, 1, 2, 3, 4, 5, 6, 7, 8}, 0x7b: {3, 4, 8}, 0x7d: {4, 5, 6, 7, 8}, 0x8d: {0, 1, 2, 3, 4},
0x6d: {0, 1, 2, 3, 4, 5, 6, 7, 8}, 0x7b: {2, 3, 4, 5, 8, 9, 10}, 0x7d: {4, 5, 6, 7, 8, 10}, 0x8d: {0, 1, 2, 3, 4},
0xa5: {0, 1, 2, 3, 4, 5, 6, 7}, 0x71: {0, 1}, 0xd8: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
0xb0: {0, 1, 2, 3, 4, 5, 7, 8, 9, 10}, 0xc0: {0, 1, 2}, 0xe0: {0, 1, 2, 3}, 0xb2: {5, 6, 7, 10, 11},
0xd2: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 0xef: {0, 1, 2}, 0x10c: {4, 5, 6, 7}, 0x123: {0, 1, 2, 3}
}
water_sprites = {
0x16: {4, 5, 6}, 0x28: {0, 1, 2, 3}, 0x34: {0, 1, 2}, 0x36: {1, 2, 5, 7, 8}, 0x38: {0, 1, 2, 4, 5, 6},
}
# not really shutters: only tiles:
# 0xb6 TR Tile, TR Pokey 1, Chain chomp?
# 0x87 hera tile room?
# 0x3d gt minihelma?
# 0x8d gt tile room?
# 0x96 gt torch cross?
def setup_specific_requirements(data_tables):
requirements = data_tables.sprite_requirements
water_groups = set()
@@ -78,7 +56,6 @@ def get_possible_sheets(room_id, data_tables, specific, uw_sheets):
# forced_req = set()
key_needed = False
killable_needed = room_id in shutter_sprites
water_needed = room_id in water_rooms
for sheet in uw_sheets:
if room_id in sheet.room_set:
@@ -116,16 +93,14 @@ def get_possible_sheets(room_id, data_tables, specific, uw_sheets):
exclude_all_groups = set()
exclude_all_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
if water_needed:
if water_groups:
match_any_room_groups.update(water_groups)
for i in range(0, 4):
if water_sub_groups[i]:
match_any_sub_groups[i].update(water_sub_groups[i])
else: # exclude water stuff
exclude_all_groups.update(water_groups)
for i in range(0, 4):
exclude_all_sub_groups[i].update(water_sub_groups[i])
if room_id in data_tables.room_requirements:
required_groups = data_tables.room_requirements[room_id]
for idx, grp in enumerate(required_groups):
if grp is not None:
if isinstance(grp, tuple):
match_any_sub_groups[idx].update(grp)
else:
match_all_sub_groups[idx] = {grp}
if key_needed:
if key_groups:
@@ -142,16 +117,15 @@ def get_possible_sheets(room_id, data_tables, specific, uw_sheets):
possible_sheets = []
for sheet in uw_sheets:
str(sheet)
if match_all_room_groups and sheet not in match_all_room_groups:
if match_all_room_groups and sheet.id not in match_all_room_groups:
continue
if any(match_all_sub_groups[i] and sheet.sub_groups[i] not in match_all_sub_groups[i] for i in range(0, 4)):
continue
if exclude_all_groups and sheet in exclude_all_groups:
if exclude_all_groups and sheet.id in exclude_all_groups:
continue
if any(exclude_all_sub_groups[i] and sheet.sub_groups[i] in exclude_all_sub_groups[i] for i in range(0, 4)):
continue
if match_any_room_groups and sheet not in match_any_sub_groups:
if match_any_room_groups and sheet.id not in match_any_sub_groups:
continue
test_subs = [i for i in range(0, 4) if match_any_sub_groups[i]]
if test_subs and all(sheet.sub_groups[i] not in match_any_sub_groups[i] for i in test_subs):
@@ -160,21 +134,50 @@ def get_possible_sheets(room_id, data_tables, specific, uw_sheets):
return possible_sheets
def get_possible_ow_sheets(area_id, ow_sheets):
# requirements = data_tables.sprite_requirements
def get_possible_ow_sheets(area_id, ow_sheets, data_tables):
requirements = data_tables.sprite_requirements
for sheet in ow_sheets:
if area_id in sheet.room_set:
return [sheet]
# not sure I need to match anything else at this point
return ow_sheets
match_all_room_groups = set()
match_all_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
for sprite in data_tables.ow_enemy_table[area_id]:
sprite_secondary = 0 if sprite.sub_type != SpriteType.Overlord else sprite.sub_type
key = (sprite.kind, sprite_secondary)
if key not in requirements:
continue
req = requirements[key]
if isinstance(req, dict):
req = req[area_id]
if req.static or not req.can_randomize:
if req.groups:
match_all_room_groups.intersection_update(req.groups)
if not match_all_room_groups:
match_all_room_groups = set(req.groups)
for i in range(0, 4):
if req.sub_groups[i]:
match_all_sub_groups[i].intersection_update(req.sub_groups[i])
if not match_all_sub_groups[i]:
match_all_sub_groups[i] = set(req.sub_groups[i])
possible_sheets = []
for sheet in ow_sheets:
if match_all_room_groups and sheet.id not in match_all_room_groups:
continue
if any(match_all_sub_groups[i] and sheet.sub_groups[i] not in match_all_sub_groups[i] for i in range(0, 4)):
continue
possible_sheets.append(sheet)
return possible_sheets
def find_candidate_sprites(data_tables, sheet_range):
def find_candidate_sprites(data_tables, sheet_range, uw=True):
requirements = data_tables.sprite_requirements
uw_sprite_candidates = []
uw_sheet_candidates = []
sprite_candidates = []
sheet_candidates = []
all_sheets = []
candidate_groups = set()
candidate_sub_groups = {0: set(), 1: set(), 2: set(), 3: set()}
@@ -182,22 +185,24 @@ def find_candidate_sprites(data_tables, sheet_range):
for k, r in requirements.items():
if isinstance(r, dict):
continue
if not r.static and r.uw_valid and not r.dont_use:
valid_flag = (uw and r.uw_valid) or (not uw and r.ow_valid)
if not r.static and valid_flag and not r.dont_use:
candidate_groups.update(r.groups)
for i in range(0, 4):
candidate_sub_groups[i].update(r.sub_groups[i])
uw_sprite_candidates.append(k)
sprite_candidates.append(k)
for num in sheet_range:
sheet = data_tables.sprite_sheets[num]
all_sheets.append(sheet)
if candidate_groups and sheet not in candidate_groups:
continue
test_subs = [i for i in range(0, 4) if candidate_sub_groups[i]]
if test_subs and all(sheet.sub_groups[i] not in candidate_sub_groups[i] for i in test_subs):
continue
uw_sheet_candidates.append(sheet)
sheet_candidates.append(sheet)
return uw_sprite_candidates, uw_sheet_candidates
return sprite_candidates, sheet_candidates, all_sheets
def get_possible_enemy_sprites(room_id, sheet, uw_sprites, data_tables):
@@ -217,7 +222,7 @@ def get_possible_enemy_sprites_ow(sheet, sprites, data_tables):
requirement = data_tables.sprite_requirements[sprite]
if isinstance(requirement, dict):
continue
if sheet.valid_sprite(requirement):
if sheet.valid_sprite(requirement) and requirement.ow_valid:
ret.append(requirement)
return ret
@@ -232,7 +237,7 @@ def get_randomize_able_sprites(room_id, data_tables):
req = data_tables.sprite_requirements[key]
if isinstance(req, dict):
continue
if not req.static and req.can_randomize:
if not req.static and req.can_randomize and not sprite.static:
sprite_table[idx] = sprite
return sprite_table
@@ -252,61 +257,66 @@ def get_randomize_able_sprites_ow(area_id, data_tables):
return sprite_table
# RandomizeRooms(optionFlags);
def randomize_underworld_rooms(data_tables):
# RoomCollection.RandomizeRoomSpriteGroups
# randomize room sprite sheets
specific = setup_specific_requirements(data_tables)
uw_candidates, uw_sheets = find_candidate_sprites(data_tables, range(65, 124))
uw_candidates, uw_sheets, all_sheets = find_candidate_sprites(data_tables, range(65, 124))
for room_id in range(0, 0x128):
if room_id in {0, 1, 3, 6, 7, 0xd, 0x14, 0x1c, 0x20, 0x29, 0x30, 0x33,
0x4d, 0x5a, 0x7F, 0x90, 0xa4, 0xac, 0xc8, 0xde}:
0x4d, 0x5a, 0x90, 0xa4, 0xac, 0xc8, 0xde}:
continue
if room_id not in data_tables.uw_enemy_table.room_map:
continue
# sprite_reqs = data_tables.sprite_requirements
randomizeable_sprites = get_randomize_able_sprites(room_id, data_tables)
if not randomizeable_sprites:
candidate_sheets = get_possible_sheets(room_id, data_tables, specific, all_sheets)
chosen_sheet = random.choice(candidate_sheets)
data_tables.room_headers[room_id].sprite_sheet = chosen_sheet.id - 0x40
if randomizeable_sprites:
candidate_sheets = get_possible_sheets(room_id, data_tables, specific, uw_sheets)
candidate_sheets = get_possible_sheets(room_id, data_tables, specific, all_sheets)
done = False
while not done:
chosen_sheet = random.choice(candidate_sheets)
data_tables.room_headers[room_id].sprite_sheet = chosen_sheet.id - 0x40
candidate_sprites = get_possible_enemy_sprites(room_id, chosen_sheet, uw_candidates, data_tables)
randomized = True
if room_id in water_rooms:
water_sprites = [x for x in candidate_sprites if x.water_only]
if len(water_sprites) == 0:
randomized = False
wallmaster_chosen = room_id in {0x0039, 0x0049, 0x0056, 0x0057, 0x0068, 0x008d}
for i, sprite in randomizeable_sprites.items():
# filter out water if necessary
candidate_sprites = [x for x in candidate_sprites if not x.water_only or sprite.water]
# filter out wallmaster if already on tile
if wallmaster_chosen:
candidate_sprites = [x for x in candidate_sprites if x.sprite != EnemySprite.Wallmaster]
if sprite.drops_item:
choice_list = [x for x in candidate_sprites if x.good_for_key_drop()]
elif room_id in shutter_sprites and i in shutter_sprites[room_id]:
choice_list = [x for x in candidate_sprites if x.good_for_shutter()]
else:
for i, sprite in randomizeable_sprites.items():
chosen = random.choice(water_sprites)
sprite.kind = chosen.sprite
else:
# todo: stal sprites
for i, sprite in randomizeable_sprites.items():
if sprite.drops_item:
choice_list = [x for x in candidate_sprites if x.good_for_key_drop() and not x.water_only]
elif room_id in shutter_sprites and i in shutter_sprites[room_id]:
choice_list = [x for x in candidate_sprites if x.good_for_shutter() and not x.water_only]
else:
choice_list = [x for x in candidate_sprites if not x.water_only]
if len(choice_list) == 0:
randomized = False
break
chosen = random.choice(choice_list)
sprite.kind = chosen.sprite
choice_list = [x for x in candidate_sprites if not x.water_only]
choice_list = filter_choices(choice_list, room_id, i, data_tables.uw_enemy_denials)
if len(choice_list) == 0:
randomized = False
break
weight = [data_tables.uw_weights[r.sprite] for r in choice_list]
chosen = random.choices(choice_list, weight, k=1)[0]
sprite.kind = chosen.sprite
if chosen.sprite == EnemySprite.Wallmaster:
wallmaster_chosen = True
sprite.kind = 0x09
sprite.sub_type = SpriteType.Overlord
done = randomized
# done with sprites
# done with rooms
def randomize_overworld_enemies(data_tables, randomize_bush_sprites):
# todo: decision on stump/bird
# original kodongo discovery?
# rom.write_byte(snes_to_pc(0x09CF4F), 0x10) //move bird from tree stump in lost woods
ow_candidates, ow_sheets = find_candidate_sprites(data_tables, range(1, 64))
def filter_choices(options, room_id, sprite_idx, denials):
key = room_id, sprite_idx
return [x for x in options if key not in denials or x.sprite not in denials[key]]
def randomize_overworld_enemies(data_tables):
ow_candidates, ow_sheets, all_sheets = find_candidate_sprites(data_tables, range(1, 64), False)
areas_to_randomize = [0, 2, 3, 5, 7, 0xA, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x1a, 0x1b, 0x1d, 0x1e, 0x22, 0x25, 0x28, 0x29, 0x2A, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x32, 0x33, 0x34, 0x35, 0x37, 0x3a, 0x3b, 0x3c, 0x3f]
@@ -314,28 +324,85 @@ def randomize_overworld_enemies(data_tables, randomize_bush_sprites):
area_list += [0x80, 0x81] + [x + 0x90 for x in areas_to_randomize] # specials + post aga LW
for area_id in area_list:
randomizeable_sprites = get_randomize_able_sprites_ow(area_id, data_tables)
if randomizeable_sprites:
candidate_sheets = get_possible_ow_sheets(area_id, ow_sheets)
if not randomizeable_sprites:
candidate_sheets = get_possible_ow_sheets(area_id, all_sheets, data_tables)
chosen_sheet = random.choice(candidate_sheets)
data_tables.overworld_sprite_sheets[area_id] = chosen_sheet
candidate_sprites = get_possible_enemy_sprites_ow(chosen_sheet, ow_candidates, data_tables)
else:
candidate_sheets = get_possible_ow_sheets(area_id, ow_sheets, data_tables)
chosen_sheet = random.choice(candidate_sheets)
data_tables.overworld_sprite_sheets[area_id] = chosen_sheet
candidate_sprites = get_possible_enemy_sprites_ow(chosen_sheet, ow_candidates, data_tables)
for i, sprite in randomizeable_sprites.items():
chosen = random.choice(candidate_sprites)
sprite.kind = chosen
if randomize_bush_sprites:
pass
# todo: randomize the bush sprite
weight = [data_tables.ow_weights[r.sprite] for r in candidate_sprites]
chosen = random.choices(candidate_sprites, weight, k=1)[0]
sprite.kind = chosen.sprite
# randomize the bush sprite per area
weight = [data_tables.ow_weights[r.sprite] for r in candidate_sprites]
bush_sprite_choice = random.choices(candidate_sprites, weight, k=1)[0]
data_tables.bush_sprite_table[area_id] = bush_sprite_choice
# damage and health tables only go to F2
skip_sprites = {
EnemySprite.ArmosKnight, EnemySprite.Lanmolas, EnemySprite.Moldorm, EnemySprite.Mothula, EnemySprite.Arrghus,
EnemySprite.HelmasaurKing, EnemySprite.Vitreous, EnemySprite.TrinexxRockHead, EnemySprite.TrinexxFireHead,
EnemySprite.TrinexxIceHead, EnemySprite.Blind, EnemySprite.Kholdstare, EnemySprite.KholdstareShell,
EnemySprite.FallingIce, EnemySprite.Arrghi, EnemySprite.Agahnim, EnemySprite.Ganon,
EnemySprite.PositionTarget, EnemySprite.Boulders
}
def randomize_enemies(world, player):
if world.enemy_shuffle[player] != 'none':
data_tables = world.data_tables[player]
randomize_underworld_sprite_sheets(data_tables.sprite_sheets)
randomize_underworld_sprite_sheets(data_tables.sprite_sheets, data_tables)
randomize_underworld_rooms(data_tables)
randomize_overworld_sprite_sheets(data_tables.sprite_sheets)
randomize_overworld_enemies(data_tables, world.enemy_shuffle[player] == 'random')
# todo: health shuffle
# todo: damage shuffle
randomize_overworld_enemies(data_tables)
# fix thief stats
subclass_table = world.damage_table[player].damage_table['SubClassTable']
subclass_table[EnemySprite.Thief] = subclass_table[EnemySprite.GreenEyegoreMimic]
data_tables.enemy_stats[EnemySprite.Thief].health = 4
# todo: could turn droppable on here if we wanted
# health shuffle
if world.enemy_health[player] != 'default':
stats = world.data_tables[player].enemy_stats
min_health = {'easy': 1, 'normal': 2, 'hard': 2, 'expert': 4}
max_health = {'easy': 4, 'normal': 15, 'hard': 25, 'expert': 50}
min_h = min_health[world.enemy_health[player]]
max_h = max_health[world.enemy_health[player]]
for sprite, stat in stats.items():
if sprite == EnemySprite.Octorok4Way:
stat.health = stats[EnemySprite.Octorok].health # these guys share data
elif sprite not in skip_sprites:
if isinstance(stat.health, tuple):
stat.health = random.randint(min_h, max_h), random.randint(min_h, max_h)
else:
stat.health = random.randint(min_h, max_h)
if world.enemy_damage[player] != 'default':
stats = world.data_tables[player].enemy_stats
# randomize damage groupings
for sprite, stat in stats.items():
if sprite == EnemySprite.Octorok4Way:
stat.damage = stats[EnemySprite.Octorok].damage # these guys share data
elif sprite not in skip_sprites:
if isinstance(stat.damage, tuple):
stat.damage = random.randint(0, 8), random.randint(0, 8)
else:
stat.damage = random.randint(0, 8)
# randomize bump table
for i in range(0, 10):
max_damage = 64 if i == 9 or world.enemy_damage[player] == 'random' else 32
green_mail = random.randint(0, max_damage)
if world.enemy_damage[player] == 'random':
blue_mail = random.randint(0, max_damage)
red_mail = random.randint(0, max_damage)
else:
blue_mail = (green_mail * 3) // 4
red_mail = (green_mail * 3) // 8
world.data_tables[player].enemy_damage[i] = [green_mail, blue_mail, red_mail]
def write_enemy_shuffle_settings(world, player, rom):

View File

@@ -3,41 +3,83 @@ from collections import Counter, defaultdict
from source.dungeon.EnemyList import enemy_names, SpriteType
from source.enemizer.Enemizer import randomize_underworld_rooms
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets
from source.rom.DataTables import init_data_tables
from source.enemizer.DamageTables import DamageTable
import RaceRandom as random
if __name__ == '__main__':
random.seed(42)
stats = defaultdict(Counter)
column_headers = {}
def calculate_odds():
ctr_uw = Counter()
ctr_ow = Counter()
for trial in range(0, 100):
world = SimpleNamespace(pottery={1: 'none'})
world = SimpleNamespace(pottery={1: 'none'}, damage_table={1: DamageTable()})
data_tables = init_data_tables(world, 1)
randomize_underworld_sprite_sheets(data_tables.sprite_sheets)
randomize_underworld_rooms(data_tables)
for room_id, enemy_list in data_tables.uw_enemy_table.room_map.items():
# print(f'Room {hex(room_id)}:')
for i, sprite in enumerate(enemy_list):
if sprite.sub_type == SpriteType.Overlord:
result = f'O{hex(sprite.kind)}'
else:
result = enemy_names[sprite.kind]
if result not in column_headers:
column_headers[result] = None
stats[(room_id, i)][result] += 1
with open('result.csv', 'w') as result_file:
result_file.write('room_id,slot,')
result_file.write(','.join(column_headers.keys()))
result_file.write('\n')
randomize_underworld_sprite_sheets(data_tables.sprite_sheets, data_tables)
randomize_overworld_sprite_sheets(data_tables.sprite_sheets)
for key, counter in stats.items():
rid, slot = key
result_file.write(f'{rid},{slot}')
for result_item in column_headers.keys():
result_file.write(f',{counter[result_item]}')
result_file.write('\n')
for num in range(65, 124):
sheet = data_tables.sprite_sheets[num]
ret = []
for req in data_tables.sprite_requirements.values():
if not isinstance(req, dict) and sheet.valid_sprite(req) and not req.overlord and not req.static:
ret.append(enemy_names[req.sprite])
for x in ret:
ctr_uw[x] += 1
for num in range(1, 64):
sheet = data_tables.sprite_sheets[num]
ret = []
for req in data_tables.sprite_requirements.values():
if not isinstance(req, dict) and sheet.valid_sprite(req) and not req.overlord and not req.static:
ret.append(enemy_names[req.sprite])
for x in ret:
ctr_ow[x] += 1
ttl = sum(ctr_uw.values())
print(f'UW: # Total {ttl}')
for k, v in ctr_uw.items():
weight = round(.01 * ttl * 100 / v)
print(f' {k}: {weight} # {v*100/ttl:.5f}% raw:{v}')
ttl = sum(ctr_ow.values())
print(f'OW: # Total {ttl}')
for k, v in ctr_ow.items():
weight = round(.01 * ttl * 100 / v)
print(f' {k}: {weight} # {v*100/ttl:.5f}% raw:{v}')
if __name__ == '__main__':
calculate_odds()
# random.seed(42)
#
# stats = defaultdict(Counter)
# column_headers = {}
#
# for trial in range(0, 100):
# world = SimpleNamespace(pottery={1: 'none'})
# data_tables = init_data_tables(world, 1)
#
# randomize_underworld_sprite_sheets(data_tables.sprite_sheets)
# randomize_underworld_rooms(data_tables)
# for room_id, enemy_list in data_tables.uw_enemy_table.room_map.items():
# # print(f'Room {hex(room_id)}:')
# for i, sprite in enumerate(enemy_list):
# if sprite.sub_type == SpriteType.Overlord:
# result = f'O{hex(sprite.kind)}'
# else:
# result = enemy_names[sprite.kind]
# if result not in column_headers:
# column_headers[result] = None
# stats[(room_id, i)][result] += 1
# with open('result.csv', 'w') as result_file:
# result_file.write('room_id,slot,')
# result_file.write(','.join(column_headers.keys()))
# result_file.write('\n')
#
# for key, counter in stats.items():
# rid, slot = key
# result_file.write(f'{rid},{slot}')
# for result_item in column_headers.keys():
# result_file.write(f',{counter[result_item]}')
# result_file.write('\n')

View File

@@ -0,0 +1,494 @@
import math
from collections import defaultdict
import RaceRandom as random
from source.logic.Rule import RuleFactory
from source.dungeon.EnemyList import EnemySprite
# these are for drops only
def defeat_rule_single(world, player, enemy_sprite, region):
if enemy_sprite.kind == EnemySprite.Terrorpin:
# must be flipped
return has('Hammer', player)
elif enemy_sprite.kind == EnemySprite.RedBari:
# must be burned to drop
return or_rule(has('Fire Rod', player), and_rule(has_sword(player), has('Bombos', player)))
vln = enemy_vulnerability(world, player, enemy_sprite, region)
rules = []
if vln['Blunt'] != 0:
rules.append(has_blunt_weapon(player))
if vln['Stun'] != 0:
rules.append(buzzblob_rule(player))
if vln['Somaria'] != 0:
rules.append(somaria_rule(world, player, vln['Somaria']))
if vln['Byrna'] != 0:
rules.append(byrna_rule(world, player, vln['Byrna']))
if vln['Master'] != 0:
rules.append(has_class_2_weapon(player))
if vln['Bow'] != 0:
rules.append(bow_rule(world, player, vln['Bow']))
if vln['Silvers'] != 0:
rules.append(silvers_rule(world, player, vln['Silvers']))
if vln['Bomb'] != 0:
rules.append(bombs_rule(world, player, vln['Bomb']))
if vln['Hookshot'] != 0:
rules.append(has('Hookshot', player))
if vln['IceRod'] != 0:
rules.append(ice_rod_rule(world, player, vln['IceRod']))
if vln['FireRod'] != 0:
rules.append(fire_rod_rule(world, player, vln['FireRod']))
if vln['Boomerang'] != 0:
rules.append(has_boomerang(player))
if vln['Powder'] != 0:
rules.append(magic_powder_rule(world, player, vln['Powder']))
# skip medallions if vln to Blunt?
if vln['Bombos'] != 0 and vln['Blunt'] == 0:
rules.append(medallion_rule(world, player, 'Bombos', vln['Bombos']))
if vln['Ether'] != 0 and vln['Blunt'] == 0:
rules.append(medallion_rule(world, player, 'Ether', vln['Ether']))
if vln['Quake'] != 0 and vln['Blunt'] == 0:
rules.append(medallion_rule(world, player, 'Quake', vln['Quake']))
if enemy_sprite.kind == EnemySprite.StalfosKnight:
# must be bombed to be made vulnerable
return and_rule(can_use_bombs(world, player), or_rule(*rules))
return or_rule(*rules)
damage_cost = {
'Bomb': 1, 'Bow': 1, 'Silvers': 1,
'Powder': .5, 'Somaria': .5, 'Byrna': 1.125,
'FireRod': 1, 'IceRod': 1,
'Bombos': 2, 'Ether': 2, 'Quake': 2
}
# damage_set = ['Blunt', 'Stun', 'Master', 'Tempered', 'Boomerang', 'Hookshot', 'Bomb', 'Silvers', 'Bow',
# 'Somaria', 'Powder', 'FireRod', 'IceRod', 'Byrna', 'Bombos', 'Ether', 'Quake']
# these are for "challenge" rooms
def defeat_rule_multiple(world, player, enemy_sprite_region_pairs):
vln_list = {}
for sprite, region in enemy_sprite_region_pairs:
vln_list[(sprite, region)] = enemy_vulnerability(world, player, sprite, region)
# damage_accounting = {x: list(y) for x, y in damage_types.items()}
used_resources = {'Bomb': 0, 'Arrow': 0, 'Magic': 0}
required_rules = []
picky_enemies = []
hammer_required = False
bombs_required = False
for key, vln in vln_list.items():
if key[0] == EnemySprite.Terrorpin:
if not hammer_required:
required_rules.append(has('Hammer', player))
hammer_required = True
picky_enemies.append(key)
continue
if key[0] == EnemySprite.StalfosKnight:
if not bombs_required:
required_rules.append(bombs_rule(world, player, 1))
bombs_required = True
used_resources['Bomb'] += 1
picky_enemies.append(key)
continue
vln_types = [k for k in vln.keys() if vln[k] != 0]
if len(vln_types) == 1:
d_type = vln_types[0]
required_rules.append(defeat_rule_single(world, player, key[0], key[1]))
picky_enemies.append(key)
if d_type in damage_cost:
cost = damage_cost[d_type]
if d_type == 'Bomb':
used_resources['Bomb'] += cost
elif d_type in ['Bow', 'Silvers']:
used_resources['Arrow'] += cost
else:
used_resources['Magic'] += cost
vln_list = {k: v for k, v in vln_list.items() if k not in picky_enemies}
while len(vln_list) > 0:
optional_clears = find_possible_rules(vln_list, used_resources, world, player)
if len(optional_clears) == 0:
raise Exception('Kill rules seems to be insufficient for this enemy set, please report:'
+ ', '.join([str(x) for x, y in enemy_sprite_region_pairs]))
# find rules which kill the most
# idea: this could be multiple criteria: most-constrained then which method kills the most
best_rules = {}
best_size = 0
for vln_option in optional_clears.keys():
if len(vln_option) > best_size:
best_size = len(vln_option)
best_rules.clear()
best_rules[vln_option] = optional_clears[vln_option]
elif len(vln_option) == best_size: # assumes vln_option is different from prior options
best_rules[vln_option] = optional_clears[vln_option]
if len(best_rules) == 1:
vln_option, rule_pair_list = next(iter(best_rules.items()))
else:
vln_option, rule_pair_list = random.choice(list(best_rules.items()))
if best_size == 0:
raise Exception('Invulnerable enemy? rules seems to be insufficient for this enemy set, please report:'
+ ', '.join([str(x) for x, y in enemy_sprite_region_pairs]))
new_vln_list = {vln_kv[0]: vln_kv[1] for idx, vln_kv in enumerate(vln_list.items()) if idx not in vln_option}
rules_to_add = [rule for rule, resources in rule_pair_list]
resources_to_use = [resources for rule, resources in rule_pair_list]
required_rules.append(or_rule(*rules_to_add))
for r in resources_to_use:
for k, v in r.items():
used_resources[k] += v
vln_list = new_vln_list
return and_rule(*required_rules)
def find_possible_rules(vln_list, used_resources, world, player):
optional_clears = defaultdict(list)
blunt_marker = defaultdict(bool)
for damage_type in ['Blunt', 'Stun', 'Master', 'Boomerang', 'Hookshot']:
# all_vln = all(vln[damage_type] != 0 for vln in vln_list.values())
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
if vln_sub_list:
if damage_type == 'Blunt':
optional_clears[vln_sub_list].append((has_blunt_weapon(player), {}))
blunt_marker[vln_sub_list] = True
if damage_type == 'Stun':
optional_clears[vln_sub_list].append((buzzblob_rule(player), {}))
if damage_type == 'Master' and not blunt_marker[vln_sub_list]:
optional_clears[vln_sub_list].append((has_class_2_weapon(player), {}))
if damage_type == 'Boomerang':
optional_clears[vln_sub_list].append((has('Hookshot', player), {}))
elif damage_type == 'Hookshot':
optional_clears[vln_sub_list].append((has_boomerang(player), {}))
damage_type = 'Bomb'
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
if vln_sub_list:
hits = needed_resources(damage_type, vln_list)
if hits + used_resources['Bomb'] <= 8:
optional_clears[vln_sub_list].append(
(bombs_rule(world, player, hits + used_resources['Bomb']), {'Bomb': hits}))
for damage_type in ['Bow', 'Silvers']:
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
if vln_sub_list:
hits = needed_resources(damage_type, vln_list)
resources = {'Arrow': hits}
if damage_type == 'Bow' and hits + used_resources['Arrow'] <= 25:
optional_clears[vln_sub_list].append(
(bow_rule(world, player, hits + used_resources['Arrow']), resources))
if damage_type == 'Silvers' and hits + used_resources['Arrow'] <= 25:
optional_clears[vln_sub_list].append(
(silvers_rule(world, player, hits + used_resources['Arrow']), resources))
for damage_type in ['Powder', 'Somaria', 'Byrna', 'FireRod', 'IceRod', 'Bombos', 'Ether', 'Quake']:
vln_sub_list = frozenset({idx for idx, vln in enumerate(vln_list.values()) if vln[damage_type] != 0})
if vln_sub_list:
hits = needed_resources(damage_type, vln_list)
resources = {'Magic': damage_cost[damage_type] * hits}
if damage_type == 'Powder' and math.ceil(hits / 16) * 8 + used_resources['Magic'] <= 160:
flag = min(vln[damage_type] for vln in vln_list.values())
flag = flag if flag < 0 else (hits + used_resources['Magic'] * 2)
optional_clears[vln_sub_list].append((magic_powder_rule(world, player, flag), resources))
elif damage_type == 'Somaria' and math.ceil(hits / 64) * 8 + used_resources['Magic'] <= 160:
flag = min(vln[damage_type] for vln in vln_list.values())
flag = flag if flag < 0 else (hits + used_resources['Magic'] * 8)
optional_clears[vln_sub_list].append((somaria_rule(world, player, flag), resources))
elif damage_type == 'Byrna' and math.ceil(hits / 7) * 8 + used_resources['Magic'] <= 160:
flag = min(vln[damage_type] for vln in vln_list.values())
flag = flag if flag < 0 else (hits + used_resources['Magic'] * 7 / 8)
optional_clears[vln_sub_list].append((byrna_rule(world, player, flag), resources))
elif damage_type == 'FireRod' and hits + used_resources['Magic'] <= 160:
flag = min(vln[damage_type] for vln in vln_list.values())
flag = flag if flag < 0 else (hits + used_resources['Magic'])
optional_clears[vln_sub_list].append((fire_rod_rule(world, player, flag), resources))
elif damage_type == 'IceRod' and hits + used_resources['Magic'] <= 160:
flag = min(vln[damage_type] for vln in vln_list.values())
flag = flag if flag < 0 else (hits + used_resources['Magic'])
optional_clears[vln_sub_list].append((ice_rod_rule(world, player, flag), resources))
elif hits * 2 + used_resources['Magic'] <= 160 and not blunt_marker[vln_sub_list]:
flag = min(vln[damage_type] for vln in vln_list.values())
flag = flag if flag < 0 else (hits + used_resources['Magic'] / 2)
optional_clears[vln_sub_list].append((medallion_rule(world, player, damage_type, flag), resources))
return optional_clears
def needed_resources(damage_type, vln_list):
return sum(vln[damage_type] if vln[damage_type] >= 0 else 1 for vln in vln_list.values() if vln[damage_type] != 0)
special_rules_check = {
'Swamp Waterway': None,
'Hera Back': [5, 6],
'GT Petting Zoo': [1, 4, 5, 7],
'Mimic Cave': [3, 4],
'Ice Hookshot Ledge': None,
'TR Hub Ledges': [3, 4, 5, 6, 7],
'Old Man Cave': None,
'Old Man House Back': [4, 5, 6],
'Death Mountain Return Cave (left)': None,
'Death Mountain Return Cave (right)': [1, 2, 3, 6, 7]
}
def special_rules_for_region(world, player, region_name, location, original_rule):
if region_name == 'Swamp Waterway': # todo: check on enemizer interaction
return or_rule(medallion_rule(world, player, 'Quake', 1),
medallion_rule(world, player, 'Ether', 1),
medallion_rule(world, player, 'Bombos', 1))
elif region_name in ['Hera Back', 'GT Petting Zoo', 'Mimic Cave']:
enemy_number = int(location.name.split('#')[1])
if enemy_number in special_rules_check[region_name]:
return and_rule(original_rule, has_boomerang(player))
else:
return original_rule
elif region_name in ['TR Hub Ledges', 'Ice Hookshot Ledge', 'Old Man Cave', 'Old Man House Back',
'Death Mountain Return Cave (left)', 'Death Mountain Return Cave (right)']:
enemy_number = int(location.name.split('#')[1])
if special_rules_check[region_name] is None or enemy_number in special_rules_check[region_name]:
return and_rule(original_rule, or_rule(has_boomerang(player), has('Hookshot', player)))
else:
return original_rule
return original_rule
def has_blunt_weapon(player):
return or_rule(has_sword(player), has('Hammer', player))
def buzzblob_rule(player):
return or_rule(has('Golden Sword', player),
and_rule(has_blunt_weapon(player),
or_rule(has_boomerang(player), has('Hookshot', player)))) # freeze it?
def has_class_2_weapon(player):
return or_rule(has_beam_sword(player), has('Hammer', player))
def somaria_rule(world, player, somaria_hits):
if somaria_hits == -1:
return has('Cane of Somaria', player) # insta-kill somaria? - not in vanilla
else:
magic_needed = math.ceil(somaria_hits / 64) * 8 # 64 hits per magic bar - 80 max?
if magic_needed > 8:
return and_rule(has('Cane of Somaria', player), can_extend_magic(world, player, magic_needed))
else:
return has('Cane of Somaria', player)
def byrna_rule(world, player, byrna_hits):
if byrna_hits == -1:
return has('Cane of Byrna', player) # insta-kill byrna? - not in vanilla
else:
magic_needed = math.ceil(byrna_hits / 7) * 8 # 7 hits per magic bar - generous?
if magic_needed > 8:
return and_rule(has('Cane of Byrna', player), can_extend_magic(world, player, magic_needed))
else:
return has('Cane of Byrna', player)
def bow_rule(world, player, arrows):
if arrows == -1 or 0 < arrows <= 25:
return can_shoot_normal_arrows(world, player)
return RuleFactory.static_rule(False)
def silvers_rule(world, player, arrows):
if arrows == -1 or 0 < arrows <= 25:
return can_shoot_silver_arrows(world, player)
return RuleFactory.static_rule(False)
def bombs_rule(world, player, bombs):
if bombs == -1 or 0 < bombs <= 8:
return can_use_bombs(world, player)
return RuleFactory.static_rule(False)
def ice_rod_rule(world, player, shots):
if shots == -1:
return has('Ice Rod', player)
if shots > 8:
return and_rule(has('Ice Rod', player), can_extend_magic(world, player, shots))
else:
return has('Ice Rod', player)
def fire_rod_rule(world, player, shots):
if shots == -1:
return has('Fire Rod', player)
if shots > 8:
return and_rule(has('Fire Rod', player), can_extend_magic(world, player, shots))
else:
return has('Fire Rod', player)
def magic_powder_rule(world, player, shots):
if shots == -1:
return has('Magic Powder', player)
if shots == -2:
# todo: other resources possible I guess - harder to keep track of though
return and_rule(has('Magic Powder', player), or_rule(has_blunt_weapon(player), has('Hookshot', player)))
magic_needed = math.ceil(shots / 16) * 8 # 16 tries per magic bar, that could be tight...
if magic_needed > 8:
return and_rule(has('Magic Powder', player), can_extend_magic(world, player, shots))
else:
return has('Magic Powder', player)
def medallion_rule(world, player, medallion, shots):
if shots == -1:
return and_rule(has(medallion, player), has_sword(player))
if shots == -2:
return and_rule(has(medallion, player), has_sword(player))
magic_needed = shots * 2
if magic_needed > 8:
return and_rule(has(medallion, player), has_sword(player), can_extend_magic(world, player, shots))
else:
return and_rule(has(medallion, player), has_sword(player))
def or_rule(*rules):
return RuleFactory.disj(rules)
def and_rule(*rules):
return RuleFactory.conj(rules)
def has(item, player, count=1):
return RuleFactory.item(item, player, count)
def has_sword(player):
return or_rule(
has('Fighter Sword', player), has('Master Sword', player),
has('Tempered Sword', player), has('Golden Sword', player)
)
def has_beam_sword(player):
return or_rule(
has('Master Sword', player), has('Tempered Sword', player), has('Golden Sword', player)
)
def has_class_3_sword(player):
return or_rule(
has('Tempered Sword', player), has('Golden Sword', player)
)
def can_extend_magic(world, player, magic, flag_t=False):
potion_shops = (find_shops_that_sell('Blue Potion', world, player) |
find_shops_that_sell('Green Potion', world, player))
return RuleFactory.extend_magic(player, magic, world.difficulty_adjustments[player], potion_shops, flag_t)
# class 0 damage (subtypes 1 and 2)
def has_boomerang(player):
return or_rule(has('Blue Boomerang', player), has('Red_Boomerang', player))
def find_shops_that_sell(item, world, player):
return {shop.region for shop in world.shops[player] if shop.has_unlimited(item) and shop.region.player == player}
def can_shoot_normal_arrows(world, player):
if world.bow_mode[player].startswith('retro'):
shops = find_shops_that_sell('Single Arrow', world, player)
# retro+shopsanity, shops may not sell the Single Arrow at all
if world.bow_mode[player] == 'retro_silvers':
# non-progressive silvers grant wooden arrows, so shop may not be needed
return and_rule(has('Bow', player), or_rule(RuleFactory.unlimited('Single Arrow', player, shops),
has('Single Arrow', player), has('Silver Arrows', player)))
else:
return and_rule(has('Bow', player), or_rule(RuleFactory.unlimited('Single Arrow', player, shops),
has('Single Arrow', player)))
return has('Bow', player)
def can_shoot_silver_arrows(world, player):
# retro_silver requires the silver arrows item which is sufficient for the quiver
if world.bow_mode[player] == 'retro':
shops = find_shops_that_sell('Single Arrow', world, player)
# retro+shopsanity, shops may not sell the Single Arrow at all
return and_rule(has('Silver Arrows', player), or_rule(RuleFactory.unlimited('Single Arrow', player, shops),
has('Single Arrow', player)))
return and_rule(has('Bow', player), has('Silver Arrows', player))
def can_use_bombs(world, player):
return or_rule(RuleFactory.static_rule(not world.bombbag[player]), has('Bomb Upgrade (+10)', player))
def enemy_vulnerability(world, player, enemy_sprite, region):
damage_table = world.damage_table[player].damage_table
stats = world.data_tables[player].enemy_stats
damage_src = damage_table['DamageSource']
sub_class_table = damage_table['SubClassTable']
enemy_sub_class = sub_class_table[enemy_sprite.kind]
vulnerability = defaultdict(int)
c1 = number_of_hits('Sword1', damage_src, enemy_sub_class, stats, enemy_sprite, region)
if c1 != 0:
if enemy_sprite.kind == EnemySprite.Buzzblob:
vulnerability['Stun'] = -1
else:
vulnerability['Blunt'] = -1
vulnerability['Master'] = -1
vulnerability['Somaria'] = c1
vulnerability['Byrna'] = c1
else:
c2 = number_of_hits('Sword3', damage_src, enemy_sub_class, stats, enemy_sprite, region)
if c2 != 0:
vulnerability['Master'] = -1 # currently Lynels are only vulnerable to only master spins or above
hits = number_of_hits('Arrow', damage_src, enemy_sub_class, stats, enemy_sprite, region)
if hits != 0:
vulnerability['Bow'] = hits
hits = number_of_hits('SilverArrow', damage_src, enemy_sub_class, stats, enemy_sprite, region)
if hits != 0:
vulnerability['Silvers'] = hits
for method in ['Bomb', 'Hookshot', 'FireRod', 'IceRod', 'Boomerang', 'Powder', 'Bombos', 'Ether', 'Quake']:
hits = number_of_hits(method, damage_src, enemy_sub_class, stats, enemy_sprite, region)
if hits != 0:
vulnerability[method] = hits
return vulnerability
def number_of_hits(source_name, damage_src, enemy_sub_class, stats, enemy_sprite, region):
damage_class = damage_src[source_name]['class']
sub_class = enemy_sub_class[damage_class]
damage_amount = damage_src[source_name]['subclass'][sub_class]
if damage_amount == 0:
return 0
elif damage_amount <= 0x64:
health = stats[enemy_sprite.kind].health
if isinstance(health, tuple):
if enemy_sprite.kind in [EnemySprite.Tektite, EnemySprite.HardhatBeetle]:
idx = enemy_sprite.tile_x & 0x1
health = health[idx]
elif region.is_light_world and region.is_dark_world:
health = min(health)
elif region.is_light_world:
health = health[0]
elif region.is_dark_world:
health = health[1]
else:
health = max(health)
return math.ceil(health / damage_amount)
elif damage_amount in [0xF9, 0xFA, 0xFD]:
# -1 faired or incinerated; -2 blobbed
# F9: fairy, defeated, but doesn't drop anything
# FA: blobbed - can you kill a blob? = -2
# FD: incinerated
return -1 if damage_amount != 0xFA else -2
else:
return 0

View File

@@ -2,10 +2,14 @@ from source.dungeon.EnemyList import Sprite, EnemySprite
vanilla_sprites_ow = {}
def create_sprite(area_id, kind, tile_x, tile_y, region=None, address=None):
def create_sprite(area_id, kind, tile_x, tile_y, region=None, address=None, fix=True, water=False):
if area_id not in vanilla_sprites_ow:
vanilla_sprites_ow[area_id] = []
sprite = Sprite(area_id, kind, 0, 0, tile_x, tile_y, region, False, None)
if water:
sprite.water = True
if fix:
sprite.static = True
sprite.original_address = address
vanilla_sprites_ow[area_id].append(sprite)
@@ -76,7 +80,7 @@ def init_vanilla_sprites_ow():
create_sprite(0x4a, EnemySprite.Ropa, 0x0E, 0x18, '', 0x09CBEE)
create_sprite(0x4a, EnemySprite.Stal, 0x14, 0x1A, '', 0x09CBF1)
# Screen4F:
create_sprite(0x4f, EnemySprite.FireballZora, 0x19, 0x08, '', 0x09CBF5)
create_sprite(0x4f, EnemySprite.FireballZora, 0x19, 0x08, '', 0x09CBF5, water=True)
create_sprite(0x4f, EnemySprite.Catfish, 0x04, 0x0B, '', 0x09CBF8)
create_sprite(0x4f, EnemySprite.Stal, 0x18, 0x0D, '', 0x09CBFB)
create_sprite(0x4f, EnemySprite.Ropa, 0x1A, 0x11, '', 0x09CBFE)
@@ -123,13 +127,13 @@ def init_vanilla_sprites_ow():
create_sprite(0x55, EnemySprite.Bee, 0x0A, 0x1A, '', 0x09CC6D)
create_sprite(0x55, EnemySprite.Ropa, 0x1A, 0x1B, '', 0x09CC70)
# Screen56:
create_sprite(0x56, EnemySprite.FireballZora, 0x0A, 0x06, '', 0x09CC74)
create_sprite(0x56, EnemySprite.FireballZora, 0x13, 0x0A, '', 0x09CC77)
create_sprite(0x56, EnemySprite.FireballZora, 0x0A, 0x06, '', 0x09CC74, water=True)
create_sprite(0x56, EnemySprite.FireballZora, 0x13, 0x0A, '', 0x09CC77, water=True)
create_sprite(0x56, EnemySprite.Bee, 0x04, 0x0E, '', 0x09CC7A)
create_sprite(0x56, EnemySprite.Ropa, 0x11, 0x17, '', 0x09CC7D)
create_sprite(0x56, EnemySprite.Ropa, 0x05, 0x1A, '', 0x09CC80)
# Screen57:
create_sprite(0x57, EnemySprite.FireballZora, 0x0C, 0x04, '', 0x09CC84)
create_sprite(0x57, EnemySprite.FireballZora, 0x0C, 0x04, '', 0x09CC84, water=True)
create_sprite(0x57, EnemySprite.Octorok, 0x16, 0x08, '', 0x09CC87)
create_sprite(0x57, EnemySprite.Octorok, 0x18, 0x0A, '', 0x09CC8A)
create_sprite(0x57, EnemySprite.Octorok, 0x0E, 0x0E, '', 0x09CC8D)
@@ -257,17 +261,17 @@ def init_vanilla_sprites_ow():
create_sprite(0x6f, EnemySprite.Stal, 0x09, 0x17, '', 0x09CDDD)
# Screen70:
create_sprite(0x70, EnemySprite.Raven, 0x21, 0x1B, '', 0x09CDE1)
create_sprite(0x70, EnemySprite.FireballZora, 0x2B, 0x1C, '', 0x09CDE4)
create_sprite(0x70, EnemySprite.FireballZora, 0x12, 0x21, '', 0x09CDE7)
create_sprite(0x70, EnemySprite.Swamola, 0x1B, 0x24, '', 0x09CDEA)
create_sprite(0x70, EnemySprite.Swamola, 0x10, 0x27, '', 0x09CDED)
create_sprite(0x70, EnemySprite.FireballZora, 0x2B, 0x1C, '', 0x09CDE4, water=True)
create_sprite(0x70, EnemySprite.FireballZora, 0x12, 0x21, '', 0x09CDE7, water=True)
create_sprite(0x70, EnemySprite.Swamola, 0x1B, 0x24, '', 0x09CDEA, water=True)
create_sprite(0x70, EnemySprite.Swamola, 0x10, 0x27, '', 0x09CDED, water=True)
create_sprite(0x70, EnemySprite.Raven, 0x07, 0x28, '', 0x09CDF0)
create_sprite(0x70, EnemySprite.FireballZora, 0x16, 0x2B, '', 0x09CDF3)
create_sprite(0x70, EnemySprite.FireballZora, 0x1E, 0x2E, '', 0x09CDF6)
create_sprite(0x70, EnemySprite.Swamola, 0x17, 0x33, '', 0x09CDF9)
create_sprite(0x70, EnemySprite.FireballZora, 0x11, 0x38, '', 0x09CDFC)
create_sprite(0x70, EnemySprite.FireballZora, 0x23, 0x2B, '', 0x09CDFF)
create_sprite(0x70, EnemySprite.Swamola, 0x27, 0x2C, '', 0x09CE02)
create_sprite(0x70, EnemySprite.FireballZora, 0x16, 0x2B, '', 0x09CDF3, water=True)
create_sprite(0x70, EnemySprite.FireballZora, 0x1E, 0x2E, '', 0x09CDF6, water=True)
create_sprite(0x70, EnemySprite.Swamola, 0x17, 0x33, '', 0x09CDF9, water=True)
create_sprite(0x70, EnemySprite.FireballZora, 0x11, 0x38, '', 0x09CDFC, water=True)
create_sprite(0x70, EnemySprite.FireballZora, 0x23, 0x2B, '', 0x09CDFF, water=True)
create_sprite(0x70, EnemySprite.Swamola, 0x27, 0x2C, '', 0x09CE02, water=True)
# Screen72:
create_sprite(0x72, EnemySprite.TalkingTree, 0x1B, 0x0B, '', 0x09CE06)
create_sprite(0x72, EnemySprite.BlueGuard, 0x10, 0x0D, '', 0x09CE09)
@@ -293,31 +297,31 @@ def init_vanilla_sprites_ow():
create_sprite(0x75, EnemySprite.BlueGuard, 0x09, 0x07, '', 0x09CE3F)
create_sprite(0x75, EnemySprite.BlueGuard, 0x0B, 0x09, '', 0x09CE42)
create_sprite(0x75, EnemySprite.Octorok, 0x07, 0x13, '', 0x09CE45)
create_sprite(0x75, EnemySprite.GreenZirro, 0x18, 0x16, '', 0x09CE48)
create_sprite(0x75, EnemySprite.GreenZirro, 0x18, 0x16, '', 0x09CE48, water=True)
create_sprite(0x75, EnemySprite.Pikit, 0x09, 0x17, '', 0x09CE4B)
create_sprite(0x75, EnemySprite.FireballZora, 0x30, 0x0C, '', 0x09CE4E)
create_sprite(0x75, EnemySprite.FireballZora, 0x30, 0x0C, '', 0x09CE4E, water=True)
create_sprite(0x75, EnemySprite.BlueZirro, 0x29, 0x11, '', 0x09CE51)
create_sprite(0x75, EnemySprite.GreenZirro, 0x36, 0x15, '', 0x09CE54)
create_sprite(0x75, EnemySprite.Pikit, 0x31, 0x1F, '', 0x09CE57)
create_sprite(0x75, EnemySprite.FireballZora, 0x1B, 0x22, '', 0x09CE5A)
create_sprite(0x75, EnemySprite.GreenZirro, 0x14, 0x28, '', 0x09CE5D)
create_sprite(0x75, EnemySprite.FireballZora, 0x1B, 0x22, '', 0x09CE5A, water=True)
create_sprite(0x75, EnemySprite.GreenZirro, 0x14, 0x28, '', 0x09CE5D, water=True)
create_sprite(0x75, EnemySprite.Pikit, 0x16, 0x2E, '', 0x09CE60)
create_sprite(0x75, EnemySprite.GreenZirro, 0x19, 0x32, '', 0x09CE63)
create_sprite(0x75, EnemySprite.BlueZirro, 0x0A, 0x35, '', 0x09CE66)
create_sprite(0x75, EnemySprite.Ropa, 0x08, 0x39, '', 0x09CE69)
create_sprite(0x75, EnemySprite.FireballZora, 0x1B, 0x39, '', 0x09CE6C)
create_sprite(0x75, EnemySprite.FireballZora, 0x1B, 0x39, '', 0x09CE6C, water=True)
create_sprite(0x75, EnemySprite.Pikit, 0x2A, 0x26, '', 0x09CE6F)
create_sprite(0x75, EnemySprite.GreenZirro, 0x32, 0x28, '', 0x09CE72)
create_sprite(0x75, EnemySprite.FireballZora, 0x2A, 0x2C, '', 0x09CE75)
create_sprite(0x75, EnemySprite.FireballZora, 0x32, 0x35, '', 0x09CE78)
create_sprite(0x75, EnemySprite.FireballZora, 0x2A, 0x2C, '', 0x09CE75, water=True)
create_sprite(0x75, EnemySprite.FireballZora, 0x32, 0x35, '', 0x09CE78, water=True)
create_sprite(0x75, EnemySprite.Octorok, 0x37, 0x39, '', 0x09CE7B)
# Screen77:
create_sprite(0x77, EnemySprite.Octorok, 0x11, 0x08, '', 0x09CE7F)
create_sprite(0x77, EnemySprite.Stal, 0x09, 0x0A, '', 0x09CE82)
create_sprite(0x77, EnemySprite.BlueZirro, 0x0D, 0x0B, '', 0x09CE85)
create_sprite(0x77, EnemySprite.Octorok, 0x18, 0x11, '', 0x09CE88)
create_sprite(0x77, EnemySprite.FireballZora, 0x07, 0x12, '', 0x09CE8B)
create_sprite(0x77, EnemySprite.FireballZora, 0x12, 0x19, '', 0x09CE8E)
create_sprite(0x77, EnemySprite.FireballZora, 0x07, 0x12, '', 0x09CE8B, water=True)
create_sprite(0x77, EnemySprite.FireballZora, 0x12, 0x19, '', 0x09CE8E, water=True)
# Screen7A:
create_sprite(0x7a, EnemySprite.Hinox, 0x06, 0x07, '', 0x09CE92)
create_sprite(0x7a, EnemySprite.Ropa, 0x16, 0x09, '', 0x09CE95)
@@ -341,7 +345,7 @@ def init_vanilla_sprites_ow():
create_sprite(0x7f, EnemySprite.GreenZirro, 0x10, 0x06, '', 0x09CEC5)
create_sprite(0x7f, EnemySprite.Octorok, 0x16, 0x06, '', 0x09CEC8)
create_sprite(0x7f, EnemySprite.Whirlpool, 0x07, 0x0C, '', 0x09CECB)
create_sprite(0x7f, EnemySprite.FireballZora, 0x07, 0x0E, '', 0x09CECE)
create_sprite(0x7f, EnemySprite.FireballZora, 0x07, 0x0E, '', 0x09CECE, water=True)
create_sprite(0x7f, EnemySprite.GreenZirro, 0x0D, 0x13, '', 0x09CED1)
create_sprite(0x7f, EnemySprite.Pikit, 0x16, 0x14, '', 0x09CED4)
create_sprite(0x7f, EnemySprite.Octorok, 0x0F, 0x17, '', 0x09CED7)
@@ -356,34 +360,34 @@ def init_vanilla_sprites_ow():
create_sprite(0x80, EnemySprite.Hobo, 0x16, 0x04, '', 0x09CEF0)
# Screen81:
create_sprite(0x81, EnemySprite.HeartPiece, 0x1B, 0x26, '', 0x09CEF4)
create_sprite(0x81, EnemySprite.Zora, 0x0A, 0x06, '', 0x09CEF7)
create_sprite(0x81, EnemySprite.Zora, 0x1C, 0x06, '', 0x09CEFA)
create_sprite(0x81, EnemySprite.FireballZora, 0x11, 0x07, '', 0x09CEFD)
create_sprite(0x81, EnemySprite.Zora, 0x16, 0x0A, '', 0x09CF00)
create_sprite(0x81, EnemySprite.FireballZora, 0x1A, 0x0A, '', 0x09CF03)
create_sprite(0x81, EnemySprite.FireballZora, 0x09, 0x0C, '', 0x09CF06)
create_sprite(0x81, EnemySprite.FireballZora, 0x12, 0x0D, '', 0x09CF09)
create_sprite(0x81, EnemySprite.Zora, 0x1A, 0x12, '', 0x09CF0C)
create_sprite(0x81, EnemySprite.Zora, 0x07, 0x13, '', 0x09CF0F)
create_sprite(0x81, EnemySprite.Zora, 0x14, 0x13, '', 0x09CF12)
create_sprite(0x81, EnemySprite.Zora, 0x08, 0x18, '', 0x09CF15)
create_sprite(0x81, EnemySprite.Zora, 0x04, 0x1C, '', 0x09CF18)
create_sprite(0x81, EnemySprite.Zora, 0x0A, 0x06, '', 0x09CEF7, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x1C, 0x06, '', 0x09CEFA, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x11, 0x07, '', 0x09CEFD, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x16, 0x0A, '', 0x09CF00, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x1A, 0x0A, '', 0x09CF03, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x09, 0x0C, '', 0x09CF06, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x12, 0x0D, '', 0x09CF09, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x1A, 0x12, '', 0x09CF0C, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x07, 0x13, '', 0x09CF0F, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x14, 0x13, '', 0x09CF12, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x08, 0x18, '', 0x09CF15, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x04, 0x1C, '', 0x09CF18, water=True)
create_sprite(0x81, EnemySprite.KingZora, 0x3B, 0x04, '', 0x09CF1B)
create_sprite(0x81, EnemySprite.FireballZora, 0x27, 0x08, '', 0x09CF1E)
create_sprite(0x81, EnemySprite.FireballZora, 0x2D, 0x08, '', 0x09CF21)
create_sprite(0x81, EnemySprite.Zora, 0x22, 0x0E, '', 0x09CF24)
create_sprite(0x81, EnemySprite.FireballZora, 0x2D, 0x0E, '', 0x09CF27)
create_sprite(0x81, EnemySprite.FireballZora, 0x21, 0x14, '', 0x09CF2A)
create_sprite(0x81, EnemySprite.Zora, 0x0D, 0x20, '', 0x09CF2D)
create_sprite(0x81, EnemySprite.Zora, 0x08, 0x31, '', 0x09CF30)
create_sprite(0x81, EnemySprite.FireballZora, 0x14, 0x31, '', 0x09CF33)
create_sprite(0x81, EnemySprite.Zora, 0x0C, 0x33, '', 0x09CF36)
create_sprite(0x81, EnemySprite.FireballZora, 0x0E, 0x35, '', 0x09CF39)
create_sprite(0x81, EnemySprite.Zora, 0x08, 0x38, '', 0x09CF3C)
create_sprite(0x81, EnemySprite.Zora, 0x3B, 0x28, '', 0x09CF3F)
create_sprite(0x81, EnemySprite.Zora, 0x3A, 0x2B, '', 0x09CF42)
create_sprite(0x81, EnemySprite.Zora, 0x2D, 0x35, '', 0x09CF45)
create_sprite(0x81, EnemySprite.Zora, 0x37, 0x36, '', 0x09CF48)
create_sprite(0x81, EnemySprite.FireballZora, 0x27, 0x08, '', 0x09CF1E, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x2D, 0x08, '', 0x09CF21, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x22, 0x0E, '', 0x09CF24, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x2D, 0x0E, '', 0x09CF27, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x21, 0x14, '', 0x09CF2A, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x0D, 0x20, '', 0x09CF2D, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x08, 0x31, '', 0x09CF30, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x14, 0x31, '', 0x09CF33, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x0C, 0x33, '', 0x09CF36, water=True)
create_sprite(0x81, EnemySprite.FireballZora, 0x0E, 0x35, '', 0x09CF39, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x08, 0x38, '', 0x09CF3C, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x3B, 0x28, '', 0x09CF3F, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x3A, 0x2B, '', 0x09CF42, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x2D, 0x35, '', 0x09CF45, water=True)
create_sprite(0x81, EnemySprite.Zora, 0x37, 0x36, '', 0x09CF48, water=True)
# Screen00_1:
create_sprite(0x0, EnemySprite.FakeMasterSword, 0x07, 0x12, '', 0x09CF4C)
create_sprite(0x0, EnemySprite.Raven, 0x12, 0x0B, '', 0x09CF4F)
@@ -450,7 +454,7 @@ def init_vanilla_sprites_ow():
# Screen0F_1:
create_sprite(0xf, EnemySprite.Waterfall, 0x06, 0x02, '', 0x09CFFD)
create_sprite(0xf, EnemySprite.Crab, 0x0D, 0x0D, '', 0x09D000)
create_sprite(0xf, EnemySprite.FireballZora, 0x05, 0x10, '', 0x09D003)
create_sprite(0xf, EnemySprite.FireballZora, 0x05, 0x10, '', 0x09D003, water=True)
create_sprite(0xf, EnemySprite.Crab, 0x11, 0x12, '', 0x09D006)
create_sprite(0xf, EnemySprite.Whirlpool, 0x08, 0x13, '', 0x09D009)
create_sprite(0xf, EnemySprite.Raven, 0x1C, 0x15, '', 0x09D00C)
@@ -513,9 +517,10 @@ def init_vanilla_sprites_ow():
create_sprite(0x1a, EnemySprite.GreenGuard, 0x0C, 0x0E, '', 0x09D0A3)
create_sprite(0x1a, EnemySprite.Faerie, 0x0D, 0x11, '', 0x09D0A6)
create_sprite(0x1a, EnemySprite.BlueRupee, 0x17, 0x17, '', 0x09D0A9)
create_sprite(0x1a, EnemySprite.SmallHeart, 0x0A, 0x18, '', 0x09D0AC)
create_sprite(0x1a, EnemySprite.RedSpearGuard, 0x0F, 0x18, '', 0x09D0AF)
# create_sprite(0x1a, EnemySprite.SmallHeart, 0x0A, 0x18, '', 0x09D0AC)
create_sprite(0x1a, EnemySprite.RedSpearGuard, 0x0F, 0x18, '', 0x09D0AC) # was 0x09D0AF
# Screen1B_1:
create_sprite(0x1b, EnemySprite.Wiseman, 0x19, 0x12, '', 0x09D0B0)
create_sprite(0x1b, EnemySprite.LightningGate, 0x1F, 0x06, '', 0x09D0B3)
create_sprite(0x1b, EnemySprite.RedBushGuard, 0x09, 0x11, '', 0x09D0B6)
create_sprite(0x1b, EnemySprite.RedBushGuard, 0x0A, 0x13, '', 0x09D0B9)
@@ -556,7 +561,7 @@ def init_vanilla_sprites_ow():
create_sprite(0x1e, EnemySprite.ArmosStatue, 0x3D, 0x29, '', 0x09D11E)
create_sprite(0x1e, EnemySprite.Octorok, 0x2E, 0x3B, '', 0x09D121)
# Screen22_1:
create_sprite(0x22, EnemySprite.BunnyBeam, 0x0C, 0x04, '', 0x09D125)
create_sprite(0x22, EnemySprite.BunnyBeam, 0x0C, 0x04, '', 0x09D125, fix=True) # smithy smoke
create_sprite(0x22, EnemySprite.GreenGuard, 0x17, 0x12, '', 0x09D128)
create_sprite(0x22, EnemySprite.Cucco, 0x12, 0x14, '', 0x09D12B)
# Screen25_1:
@@ -595,7 +600,7 @@ def init_vanilla_sprites_ow():
# Screen2E_1:
create_sprite(0x2e, EnemySprite.BlueGuard, 0x0E, 0x0C, '', 0x09D186)
create_sprite(0x2e, EnemySprite.BlueGuard, 0x17, 0x0E, '', 0x09D189)
create_sprite(0x2e, EnemySprite.FireballZora, 0x05, 0x12, '', 0x09D18C)
create_sprite(0x2e, EnemySprite.FireballZora, 0x05, 0x12, '', 0x09D18C, water=True)
create_sprite(0x2e, EnemySprite.Octorok, 0x19, 0x17, '', 0x09D18F)
# Screen2F_1:
create_sprite(0x2f, EnemySprite.BlueGuard, 0x0F, 0x0C, '', 0x09D193)
@@ -650,30 +655,30 @@ def init_vanilla_sprites_ow():
create_sprite(0x35, EnemySprite.HeartPiece, 0x19, 0x13, '', 0x09D21C)
create_sprite(0x35, EnemySprite.Buzzblob, 0x19, 0x14, '', 0x09D21F)
create_sprite(0x35, EnemySprite.Crab, 0x07, 0x17, '', 0x09D222)
create_sprite(0x35, EnemySprite.FireballZora, 0x11, 0x17, '', 0x09D225)
create_sprite(0x35, EnemySprite.FireballZora, 0x25, 0x0D, '', 0x09D228)
create_sprite(0x35, EnemySprite.FireballZora, 0x11, 0x17, '', 0x09D225, water=True)
create_sprite(0x35, EnemySprite.FireballZora, 0x25, 0x0D, '', 0x09D228, water=True)
create_sprite(0x35, EnemySprite.Buzzblob, 0x27, 0x1F, '', 0x09D22B)
create_sprite(0x35, EnemySprite.Buzzblob, 0x2F, 0x1F, '', 0x09D22E)
create_sprite(0x35, EnemySprite.Octorok, 0x0A, 0x35, '', 0x09D231)
create_sprite(0x35, EnemySprite.FireballZora, 0x14, 0x35, '', 0x09D234)
create_sprite(0x35, EnemySprite.FireballZora, 0x14, 0x35, '', 0x09D234, water=True)
create_sprite(0x35, EnemySprite.Raven, 0x0F, 0x35, '', 0x09D237)
create_sprite(0x35, EnemySprite.Octorok, 0x0B, 0x39, '', 0x09D23A)
create_sprite(0x35, EnemySprite.Buzzblob, 0x19, 0x3A, '', 0x09D23D)
create_sprite(0x35, EnemySprite.Crab, 0x11, 0x3B, '', 0x09D240)
create_sprite(0x35, EnemySprite.FireballZora, 0x24, 0x2B, '', 0x09D243)
create_sprite(0x35, EnemySprite.FireballZora, 0x24, 0x2B, '', 0x09D243, water=True)
create_sprite(0x35, EnemySprite.Whirlpool, 0x29, 0x2B, '', 0x09D246)
create_sprite(0x35, EnemySprite.FireballZora, 0x39, 0x31, '', 0x09D249)
create_sprite(0x35, EnemySprite.FireballZora, 0x21, 0x36, '', 0x09D24C)
create_sprite(0x35, EnemySprite.FireballZora, 0x39, 0x31, '', 0x09D249, water=True)
create_sprite(0x35, EnemySprite.FireballZora, 0x21, 0x36, '', 0x09D24C, water=True)
create_sprite(0x35, EnemySprite.Buzzblob, 0x32, 0x37, '', 0x09D24F)
create_sprite(0x35, EnemySprite.Buzzblob, 0x34, 0x39, '', 0x09D252)
create_sprite(0x35, EnemySprite.Crab, 0x2E, 0x3A, '', 0x09D255)
# Screen37_1:
create_sprite(0x35, EnemySprite.Crab, 0x08, 0x08, '', 0x09D259)
create_sprite(0x35, EnemySprite.Crab, 0x10, 0x08, '', 0x09D25C)
create_sprite(0x37, EnemySprite.Crab, 0x08, 0x08, '', 0x09D259)
create_sprite(0x37, EnemySprite.Crab, 0x10, 0x08, '', 0x09D25C)
create_sprite(0x37, EnemySprite.Crab, 0x0F, 0x0B, '', 0x09D25F)
create_sprite(0x37, EnemySprite.Crab, 0x16, 0x11, '', 0x09D262)
create_sprite(0x37, EnemySprite.Raven, 0x0C, 0x15, '', 0x09D265)
create_sprite(0x37, EnemySprite.FireballZora, 0x12, 0x19, '', 0x09D268)
create_sprite(0x37, EnemySprite.FireballZora, 0x12, 0x19, '', 0x09D268, water=True)
# Screen3A_1:
create_sprite(0x3a, EnemySprite.Locksmith, 0x17, 0x05, '', 0x09D26C)
create_sprite(0x3a, EnemySprite.Raven, 0x0E, 0x09, '', 0x09D26F)
@@ -682,10 +687,10 @@ def init_vanilla_sprites_ow():
# Screen3B_1:
create_sprite(0x3b, EnemySprite.GreenBushGuard, 0x13, 0x06, '', 0x09D279)
create_sprite(0x3b, EnemySprite.BlueArcher, 0x0C, 0x0A, '', 0x09D27C)
create_sprite(0x3b, EnemySprite.FloppingFish, 0x13, 0x0D, '', 0x09D27F)
create_sprite(0x3b, EnemySprite.FloppingFish, 0x13, 0x0D, '', 0x09D27F, water=True)
create_sprite(0x3b, EnemySprite.Raven, 0x08, 0x0B, '', 0x09D282)
create_sprite(0x3b, EnemySprite.HeartPiece, 0x14, 0x0E, '', 0x09D285)
create_sprite(0x3b, EnemySprite.FloppingFish, 0x1B, 0x10, '', 0x09D288)
create_sprite(0x3b, EnemySprite.FloppingFish, 0x1B, 0x10, '', 0x09D288, water=True)
create_sprite(0x3b, EnemySprite.Toppo, 0x0F, 0x14, '', 0x09D28B)
create_sprite(0x3b, EnemySprite.Raven, 0x14, 0x1B, '', 0x09D28E)
# Screen3C_1:
@@ -699,7 +704,7 @@ def init_vanilla_sprites_ow():
# Screen3F_1:
create_sprite(0x3f, EnemySprite.Octorok, 0x11, 0x04, '', 0x09D2A8)
create_sprite(0x3f, EnemySprite.Octorok, 0x16, 0x05, '', 0x09D2AB)
create_sprite(0x3f, EnemySprite.FireballZora, 0x08, 0x0B, '', 0x09D2AE)
create_sprite(0x3f, EnemySprite.FireballZora, 0x08, 0x0B, '', 0x09D2AE, water=True)
create_sprite(0x3f, EnemySprite.Whirlpool, 0x07, 0x0C, '', 0x09D2B1)
create_sprite(0x3f, EnemySprite.Octoballoon, 0x10, 0x16, '', 0x09D2B4)
# Screen00_2:
@@ -768,8 +773,8 @@ def init_vanilla_sprites_ow():
# Screen0F_2:
create_sprite(0x9f, EnemySprite.Waterfall, 0x06, 0x02, '', 0x09D369)
create_sprite(0x9f, EnemySprite.Crab, 0x0D, 0x0D, '', 0x09D36C)
create_sprite(0x9f, EnemySprite.FireballZora, 0x05, 0x10, '', 0x09D36F)
create_sprite(0x9f, EnemySprite.FireballZora, 0x0A, 0x11, '', 0x09D372)
create_sprite(0x9f, EnemySprite.FireballZora, 0x05, 0x10, '', 0x09D36F, water=True)
create_sprite(0x9f, EnemySprite.FireballZora, 0x0A, 0x11, '', 0x09D372, water=True)
create_sprite(0x9f, EnemySprite.Crab, 0x11, 0x12, '', 0x09D375)
create_sprite(0x9f, EnemySprite.Whirlpool, 0x08, 0x13, '', 0x09D378)
create_sprite(0x9f, EnemySprite.Octorok4Way, 0x0E, 0x17, '', 0x09D37B)
@@ -834,9 +839,10 @@ def init_vanilla_sprites_ow():
create_sprite(0xaa, EnemySprite.BlueGuard, 0x0F, 0x08, '', 0x09D418)
create_sprite(0xaa, EnemySprite.BlueGuard, 0x0C, 0x0E, '', 0x09D41B)
create_sprite(0xaa, EnemySprite.Faerie, 0x0D, 0x11, '', 0x09D41E)
create_sprite(0xaa, EnemySprite.SmallHeart, 0x0A, 0x18, '', 0x09D421)
create_sprite(0xaa, EnemySprite.UsainBolt, 0x0F, 0x18, '', 0x09D424)
# create_sprite(0xaa, EnemySprite.SmallHeart, 0x0A, 0x18, '', 0x09D421)
create_sprite(0xaa, EnemySprite.UsainBolt, 0x0F, 0x18, '', 0x09D421) # was 0x09D424
# Screen1B_2:
create_sprite(0x1b, EnemySprite.Wiseman, 0x19, 0x12, '', 0x09D425)
create_sprite(0xab, EnemySprite.UsainBolt, 0x06, 0x0D, '', 0x09D428)
create_sprite(0xab, EnemySprite.Apple, 0x16, 0x14, '', 0x09D42B)
create_sprite(0xab, EnemySprite.UsainBolt, 0x1F, 0x1A, '', 0x09D42E)
@@ -874,7 +880,7 @@ def init_vanilla_sprites_ow():
create_sprite(0xae, EnemySprite.Faerie, 0x22, 0x37, '', 0x09D48A)
create_sprite(0xae, EnemySprite.UsainBolt, 0x2D, 0x3A, '', 0x09D48D)
# Screen22_2:
create_sprite(0xb2, EnemySprite.BunnyBeam, 0x0C, 0x04, '', 0x09D491)
create_sprite(0xb2, EnemySprite.BunnyBeam, 0x0C, 0x04, '', 0x09D491, fix=True) # smithy smoke
create_sprite(0xb2, EnemySprite.Cucco, 0x0C, 0x14, '', 0x09D494)
create_sprite(0xb2, EnemySprite.Cucco, 0x12, 0x14, '', 0x09D497)
# Screen25_2:
@@ -915,13 +921,13 @@ def init_vanilla_sprites_ow():
create_sprite(0xbd, EnemySprite.Octorok4Way, 0x0F, 0x08, '', 0x09D4F5)
create_sprite(0xbd, EnemySprite.BlueGuard, 0x12, 0x0B, '', 0x09D4F8)
create_sprite(0xbd, EnemySprite.UsainBolt, 0x12, 0x16, '', 0x09D4FB)
create_sprite(0xbd, EnemySprite.FireballZora, 0x1C, 0x17, '', 0x09D4FE)
create_sprite(0xbd, EnemySprite.FireballZora, 0x1C, 0x17, '', 0x09D4FE, water=True)
# Screen2E_2:
create_sprite(0xbe, EnemySprite.Faerie, 0x0C, 0x09, '', 0x09D502)
create_sprite(0xbe, EnemySprite.Bee, 0x14, 0x0B, '', 0x09D505)
create_sprite(0xbe, EnemySprite.UsainBolt, 0x0E, 0x0C, '', 0x09D508)
create_sprite(0xbe, EnemySprite.BlueGuard, 0x17, 0x0E, '', 0x09D50B)
create_sprite(0xbe, EnemySprite.FireballZora, 0x05, 0x12, '', 0x09D50E)
create_sprite(0xbe, EnemySprite.FireballZora, 0x05, 0x12, '', 0x09D50E, water=True)
create_sprite(0xbe, EnemySprite.Octorok, 0x19, 0x17, '', 0x09D511)
# Screen2F_2:
create_sprite(0xbf, EnemySprite.UsainBolt, 0x0F, 0x0C, '', 0x09D515)
@@ -973,22 +979,22 @@ def init_vanilla_sprites_ow():
create_sprite(0xc5, EnemySprite.UsainBolt, 0x0A, 0x0C, '', 0x09D595)
create_sprite(0xc5, EnemySprite.HeartPiece, 0x19, 0x13, '', 0x09D598)
create_sprite(0xc5, EnemySprite.Buzzblob, 0x19, 0x14, '', 0x09D59B)
create_sprite(0xc5, EnemySprite.FireballZora, 0x11, 0x17, '', 0x09D59E)
create_sprite(0xc5, EnemySprite.FireballZora, 0x11, 0x17, '', 0x09D59E, water=True)
create_sprite(0xc5, EnemySprite.Octorok4Way, 0x38, 0x0A, '', 0x09D5A1)
create_sprite(0xc5, EnemySprite.FireballZora, 0x25, 0x0D, '', 0x09D5A4)
create_sprite(0xc5, EnemySprite.FireballZora, 0x37, 0x19, '', 0x09D5A7)
create_sprite(0xc5, EnemySprite.FireballZora, 0x25, 0x0D, '', 0x09D5A4, water=True)
create_sprite(0xc5, EnemySprite.FireballZora, 0x37, 0x19, '', 0x09D5A7, water=True)
create_sprite(0xc5, EnemySprite.Buzzblob, 0x27, 0x1F, '', 0x09D5AA)
create_sprite(0xc5, EnemySprite.Buzzblob, 0x2F, 0x1F, '', 0x09D5AD)
create_sprite(0xc5, EnemySprite.FireballZora, 0x1B, 0x26, '', 0x09D5B0)
create_sprite(0xc5, EnemySprite.FireballZora, 0x1B, 0x26, '', 0x09D5B0, water=True)
create_sprite(0xc5, EnemySprite.Raven, 0x0D, 0x2F, '', 0x09D5B3)
create_sprite(0xc5, EnemySprite.Octorok, 0x06, 0x34, '', 0x09D5B6)
create_sprite(0xc5, EnemySprite.Octorok, 0x0A, 0x35, '', 0x09D5B9)
create_sprite(0xc5, EnemySprite.FireballZora, 0x14, 0x35, '', 0x09D5BC)
create_sprite(0xc5, EnemySprite.FireballZora, 0x14, 0x35, '', 0x09D5BC, water=True)
create_sprite(0xc5, EnemySprite.Octorok, 0x0B, 0x39, '', 0x09D5BF)
create_sprite(0xc5, EnemySprite.Buzzblob, 0x19, 0x3A, '', 0x09D5C2)
create_sprite(0xc5, EnemySprite.Whirlpool, 0x29, 0x2B, '', 0x09D5C5)
create_sprite(0xc5, EnemySprite.FireballZora, 0x39, 0x31, '', 0x09D5C8)
create_sprite(0xc5, EnemySprite.FireballZora, 0x21, 0x36, '', 0x09D5CB)
create_sprite(0xc5, EnemySprite.FireballZora, 0x39, 0x31, '', 0x09D5C8, water=True)
create_sprite(0xc5, EnemySprite.FireballZora, 0x21, 0x36, '', 0x09D5CB, water=True)
create_sprite(0xc5, EnemySprite.Buzzblob, 0x32, 0x37, '', 0x09D5CE)
create_sprite(0xc5, EnemySprite.Buzzblob, 0x34, 0x39, '', 0x09D5D1)
# Screen37_2:
@@ -996,7 +1002,7 @@ def init_vanilla_sprites_ow():
create_sprite(0xc7, EnemySprite.Crab, 0x10, 0x08, '', 0x09D5D8)
create_sprite(0xc7, EnemySprite.Crab, 0x0F, 0x0B, '', 0x09D5DB)
create_sprite(0xc7, EnemySprite.Crab, 0x16, 0x11, '', 0x09D5DE)
create_sprite(0xc7, EnemySprite.FireballZora, 0x12, 0x19, '', 0x09D5E1)
create_sprite(0xc7, EnemySprite.FireballZora, 0x12, 0x19, '', 0x09D5E1, water=True)
# Screen3A_2:
create_sprite(0xca, EnemySprite.Locksmith, 0x17, 0x05, '', 0x09D5E5)
create_sprite(0xca, EnemySprite.Hoarder2, 0x0B, 0x0A, '', 0x09D5E8)
@@ -1007,7 +1013,7 @@ def init_vanilla_sprites_ow():
create_sprite(0xca, EnemySprite.UsainBolt, 0x11, 0x0F, '', 0x09D5F7)
create_sprite(0xca, EnemySprite.Hoarder2, 0x17, 0x17, '', 0x09D5FA)
# Screen3B_2:
create_sprite(0xcb, EnemySprite.FloppingFish, 0x13, 0x0D, '', 0x09D5FE)
create_sprite(0xcb, EnemySprite.FloppingFish, 0x13, 0x0D, '', 0x09D5FE, water=True)
create_sprite(0xcb, EnemySprite.Octorok, 0x0C, 0x0F, '', 0x09D601)
create_sprite(0xcb, EnemySprite.HeartPiece, 0x14, 0x0E, '', 0x09D604)
create_sprite(0xcb, EnemySprite.Octorok4Way, 0x0F, 0x14, '', 0x09D607)
@@ -1022,5 +1028,5 @@ def init_vanilla_sprites_ow():
# Screen3F_2:
create_sprite(0xcf, EnemySprite.Octorok4Way, 0x16, 0x05, '', 0x09D621)
create_sprite(0xcf, EnemySprite.Whirlpool, 0x07, 0x0C, '', 0x09D624)
create_sprite(0xcf, EnemySprite.FireballZora, 0x06, 0x13, '', 0x09D627)
create_sprite(0xcf, EnemySprite.FireballZora, 0x06, 0x13, '', 0x09D627, water=True)
create_sprite(0xcf, EnemySprite.Octoballoon, 0x11, 0x16, '', 0x09D62A)

View File

@@ -165,14 +165,12 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.Moldorm).exalt().sub_group(2, 0x30),
SpriteRequirement(EnemySprite.Octorok4Way).sub_group(2, 0xc),
SpriteRequirement(EnemySprite.Cucco).immune().sub_group(3, [0x15, 0x50]).exclude(NoFlyingRooms),
# todo: Buzzblob kill rule for mimics
SpriteRequirement(EnemySprite.Buzzblob).sub_group(3, 0x11),
SpriteRequirement(EnemySprite.Snapdragon).sub_group(0, 0x16).sub_group(2, 0x17),
SpriteRequirement(EnemySprite.Octoballoon).no_drop().sub_group(2, 0xc).exclude(NoFlyingRooms),
SpriteRequirement(EnemySprite.Hinox).sub_group(0, 0x16),
SpriteRequirement(EnemySprite.Moblin).sub_group(2, 0x17),
SpriteRequirement(EnemySprite.MiniHelmasaur).sub_group(1, 0x1e),
# todo: antifairy kill rule
SpriteRequirement(EnemySprite.AntiFairy).no_drop().sub_group(3, [0x52, 0x53])
.exclude(NoFlyingRooms).exclude({0x40}), # no anti-fairies in aga tower bridge room
SpriteRequirement(EnemySprite.Wiseman).affix().sub_group(2, 0x4c),
@@ -180,7 +178,7 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.MiniMoldorm).sub_group(1, 0x1e),
SpriteRequirement(EnemySprite.Poe).no_drop().sub_group(3, 0x15).exclude(NoFlyingRooms),
SpriteRequirement(EnemySprite.Smithy).affix().sub_group(1, 0x1d).sub_group(3, 0x15),
SpriteRequirement(EnemySprite.Statue).affix().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.Statue).stasis().immune().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.CrystalSwitch).affix().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.SickKid).affix().sub_group(0, 0x51),
SpriteRequirement(EnemySprite.Sluggula).sub_group(2, 0x25),
@@ -188,10 +186,8 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.Ropa).sub_group(0, 0x16),
SpriteRequirement(EnemySprite.RedBari).no_drop().sub_group(0, 0x1f),
SpriteRequirement(EnemySprite.BlueBari).sub_group(0, 0x1f),
# todo: don't randomize red/blue bari in room 0x7F
SpriteRequirement(EnemySprite.TalkingTree).affix().sub_group(0, 0x15),
SpriteRequirement(EnemySprite.HardhatBeetle).sub_group(1, 0x1e),
# todo: deadrock kill rule for mimics (not sure why ice spike room...)
SpriteRequirement(EnemySprite.Deadrock).sub_group(3, 0x10).exclude({0x7f, 0x10c}),
SpriteRequirement(EnemySprite.DarkWorldHintNpc).affix(), # no groups?
SpriteRequirement(EnemySprite.AdultNpc).affix().sub_group(0, [0xe, 0x4f]),
@@ -233,8 +229,8 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.KingZora).affix().sub_group(3, 0x44),
SpriteRequirement(EnemySprite.ArmosKnight).exalt().sub_group(3, 0x1d),
SpriteRequirement(EnemySprite.Lanmolas).exalt().sub_group(3, 0x31),
SpriteRequirement(EnemySprite.FireballZora).immerse().uw_skip().sub_group(2, [0xc, 0x18]),
SpriteRequirement(EnemySprite.Zora).immerse().no_drop().uw_skip().sub_group(2, 0xc).sub_group(3, 0x44),
SpriteRequirement(EnemySprite.FireballZora).immerse().no_drop().sub_group(2, [0xc, 0x18]), # .uw_skip() test
SpriteRequirement(EnemySprite.Zora).no_drop().sub_group(2, 0xc).sub_group(3, 0x44), # .uw_skip() test
SpriteRequirement(EnemySprite.DesertStatue).affix().sub_group(2, 0x12),
SpriteRequirement(EnemySprite.Crab).sub_group(2, 0xc),
SpriteRequirement(EnemySprite.LostWoodsBird).affix().sub_group(2, 0x37).sub_group(3, 0x36),
@@ -245,11 +241,11 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.RollerVerticalDown).immune().sub_group(2, 0x27).exclude(NoBeamosOrTrapRooms),
SpriteRequirement(EnemySprite.RollerHorizontalLeft).immune().sub_group(2, 0x27).exclude(NoBeamosOrTrapRooms),
SpriteRequirement(EnemySprite.RollerHorizontalRight).immune().sub_group(2, 0x27).exclude(NoBeamosOrTrapRooms),
SpriteRequirement(EnemySprite.Beamos).immune().sub_group(1, 0x2c).exclude(NoBeamosOrTrapRooms),
SpriteRequirement(EnemySprite.Beamos).no_drop().sub_group(1, 0x2c).exclude(NoBeamosOrTrapRooms),
SpriteRequirement(EnemySprite.MasterSword).affix().sub_group(2, 0x37).sub_group(3, 0x36),
# these are excluded for now
SpriteRequirement(EnemySprite.DebirandoPit).skip().sub_group(0, 0x2f),
SpriteRequirement(EnemySprite.Debirando).skip().sub_group(0, 0x2f),
SpriteRequirement(EnemySprite.DebirandoPit).sub_group(0, 0x2f), # skip
SpriteRequirement(EnemySprite.Debirando).sub_group(0, 0x2f), # skip
SpriteRequirement(EnemySprite.ArcheryNpc).affix().sub_group(0, 0x4b),
SpriteRequirement(EnemySprite.WallCannonVertLeft).affix().sub_group(0, 0x2f),
SpriteRequirement(EnemySprite.WallCannonVertRight).affix().sub_group(0, 0x2f),
@@ -270,17 +266,16 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.Agahnim).exalt().sub_group(0, 0x55).sub_group(1, [0x1a, 0x3d]).sub_group(2, 0x42)
.sub_group(3, 0x43),
SpriteRequirement(EnemySprite.FloatingSkull).no_drop().sub_group(0, 0x1f).exclude(NoFlyingRooms),
SpriteRequirement(EnemySprite.BigSpike).sub_group(3, [0x52, 0x53]).no_drop(),
SpriteRequirement(EnemySprite.FirebarCW).immune().sub_group(0, 0x1f),
SpriteRequirement(EnemySprite.FirebarCCW).immune().sub_group(0, 0x1f),
# todo: don't randomize these in GT Torch Cross and TR Dark Ride? was that ever implemented?
SpriteRequirement(EnemySprite.Firesnake).immune().sub_group(0, 0x1f),
SpriteRequirement(EnemySprite.Hover).immerse().sub_group(2, 0x22).exclude(NoFlyingRooms),
# todo: leave them in swamp palace entrance...
SpriteRequirement(EnemySprite.AntiFairyCircle).skip().no_drop().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.Firesnake).no_drop().sub_group(0, 0x1f),
SpriteRequirement(EnemySprite.Hover).sub_group(2, 0x22), # .exclude(NoFlyingRooms), might be okay now
SpriteRequirement(EnemySprite.AntiFairyCircle).no_drop().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.GreenEyegoreMimic).sub_group(2, 0x2e),
SpriteRequirement(EnemySprite.RedEyegoreMimic).sub_group(2, 0x2e),
# kodongos apparently broken?
SpriteRequirement(EnemySprite.Kodongo).skip().sub_group(2, 0x2a),
SpriteRequirement(EnemySprite.Kodongo).sub_group(2, 0x2a),
SpriteRequirement(EnemySprite.Mothula).exalt().sub_group(2, 0x38).sub_group(3, 0x52),
SpriteRequirement(EnemySprite.SpikeBlock).immune().sub_group(3, [0x52, 0x53]).exclude(NoBeamosOrTrapRooms)
.exclude({0x28}), # why exclude sp entrance?
@@ -289,19 +284,17 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.Arrghi).exalt().sub_group(2, 0x39),
SpriteRequirement(EnemySprite.Terrorpin).sub_group(2, 0x2a).exclude({0x10c}), # probably fine in mimic now
SpriteRequirement(EnemySprite.Blob).sub_group(1, 0x20),
# todo: wallmaster overlords
SpriteRequirement(EnemySprite.Wallmaster).immune().ow_skip().sub_group(2, 0x23)
.allow(WallmasterValidRooms),
SpriteRequirement(EnemySprite.StalfosKnight).sub_group(1, 0x10).exclude({0x10c}),
SpriteRequirement(EnemySprite.StalfosKnight).sub_group(1, 0x20).exclude({0x10c}),
SpriteRequirement(EnemySprite.HelmasaurKing).exalt().sub_group(2, 0x3a).sub_group(3, 0x3e),
SpriteRequirement(EnemySprite.Bumper).affix().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.Bumper).immune().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.LaserEyeLeft).affix().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.LaserEyeRight).affix().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.LaserEyeTop).affix().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.LaserEyeBottom).affix().sub_group(3, [0x52, 0x53]),
SpriteRequirement(EnemySprite.Pengator).sub_group(2, 0x26),
SpriteRequirement(EnemySprite.Kyameron).no_drop().immerse().sub_group(2, 0x22),
# todo: leave them in swamp palace entrance...
SpriteRequirement(EnemySprite.Wizzrobe).sub_group(2, [0x25, 0x29]),
SpriteRequirement(EnemySprite.Zoro).no_drop().sub_group(1, 0x20),
SpriteRequirement(EnemySprite.Babasu).no_drop().sub_group(1, 0x20),
@@ -351,11 +344,12 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.TrinexxFireHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f),
SpriteRequirement(EnemySprite.TrinexxIceHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f),
SpriteRequirement(EnemySprite.Blind).exalt().sub_group(1, 0x2c).sub_group(2, 0x3b),
SpriteRequirement(EnemySprite.Swamola).immerse().no_drop().sub_group(3, 0x19),
SpriteRequirement(EnemySprite.Swamola).no_drop().sub_group(3, 0x19),
SpriteRequirement(EnemySprite.Lynel).sub_group(3, 0x14),
SpriteRequirement(EnemySprite.BunnyBeam).affix(),
SpriteRequirement(EnemySprite.BunnyBeam).no_drop().ow_skip(),
SpriteRequirement(EnemySprite.FloppingFish).uw_skip().immune(),
SpriteRequirement(EnemySprite.Stal).skip(),
SpriteRequirement(EnemySprite.Stal),
SpriteRequirement(EnemySprite.Landmine).skip(),
SpriteRequirement(EnemySprite.DiggingGameNPC).affix().sub_group(1, 0x2a),
SpriteRequirement(EnemySprite.Ganon).exalt().sub_group(0, 0x21).sub_group(1, 0x41)
.sub_group(2, 0x45).sub_group(3, 0x33),
@@ -366,7 +360,7 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.CastleMantle).affix().sub_group(0, 0x5d),
SpriteRequirement(EnemySprite.MedallionTablet).affix().sub_group(2, 0x12),
# todo: overlord requirements
# overlord requirements - encapsulated mostly in the required sheets
SpriteRequirement(2, 7).affix().sub_group(2, 46),
SpriteRequirement(3, 7).affix().sub_group(2, 46),
SpriteRequirement(5, 7).affix().sub_group(0, 31),
@@ -399,7 +393,7 @@ def init_sprite_requirements():
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 14).sub_group(2, 74).sub_group(3, 90)
.allow({0x123, 0x124}),
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 14).sub_group(2, 74).sub_group(3, 80)
.allow({0x125}),
.allow({0x125, 0x100}),
SpriteRequirement(EnemySprite.Shopkeeper).affix().sub_group(0, 21).allow({0x11e}),
]
complex_r = {}
@@ -513,7 +507,7 @@ def init_sprite_sheets(requirements):
return sheets
def setup_required_dungeon_groups(sheets):
def setup_required_dungeon_groups(sheets, data_tables):
sheets[did(1)].add_sprite_to_sheet([70, 73, 28, 82], {0xe4, 0xf0}) # old man
# various npcs
@@ -540,53 +534,47 @@ def setup_required_dungeon_groups(sheets):
([None, None, None, 80], [0x108]), # chicken house
([14, 30, None, None], [0x123]), # mini moldorm (shutter door)
([None, None, 34, None], [0x36, 0x46, 0x66, 0x76]), # pirogusu spawners
([None, 32, None, None], [0x3e, 0x9f]), # babasu spawners
([None, 32, None, None], [0x9f]), # babasu spawners
([31, None, None, None], [0x7f]), # force baris
([None, None, 35, None], [0x39, 0x49, 0x56, 0x57, 0x68, 0x8d]), # wallmasters
([None, None, 35, None], [0x39, 0x49, 0x8d]), # wallmasters
# bumpers - why the split - because of other requirements -
([None, None, None, (82, 83)], [0x17, 0x2a, 0x4c, 0x59, 0x67, 0x68, 0x7e, 0x8b, 0xeb, 0xfb]),
([None, None, None, (82, 83)], [0x17, 0x2a, 0x4c, 0x59, 0x67, 0x7e, 0x8b, 0xeb, 0xfb]),
# crystal switches - split for some reason
([None, None, None, (82, 83)], [0xb, 0x13, 0x1b, 0x1e, 0x2a, 0x2b, 0x31, 0x3e, 0x5b, 0x6b, 0x77, 0xb7, 0x8b, 0x91, 0x92, 0x9b, 0x9d, 0xa1, 0xab, 0xb6, 0xbf, 0xc1, 0xc4, 0xef]),
([None, None, None, (82, 83)], [0xb, 0x13, 0x1b, 0x1e, 0x2a, 0x2b, 0x31, 0x5b, 0x6b, 0x77, 0x8b,
0x91, 0x92, 0x9b, 0x9d, 0xa1, 0xab, 0xb6, 0xbf, 0xc1, 0xc4, 0xef]),
# laser eyes - split for some reason
([None, None, None, (82, 83)], [0x13, 0x23, 0x96, 0xa5, 0xc5, 0xd5]),
# statues - split for some reason
([None, None, None, (82, 83)], [0x26, 0x2b, 0x40, 0x4a, 0x57, 0x6b, 0x7b]),
([None, None, None, (82, 83)], [0x26, 0x2b, 0x40, 0x4a, 0x6b, 0x7b]),
# non-optional
([None, None, None, 82], [0x2, 0x58, 0x64, 0x8c, 0x10b]), # pull switches
([None, None, None, 82], [0x1a, 0x3d, 0x44, 0x56, 0x5e, 0x7c, 0x95, 0xc3]), # collapsing bridges
([None, None, None, 82], [0x2, 0x58, 0x64, 0x8c, 0x10b]), # pull switches
([None, None, None, 82], [0x1a, 0x3d, 0x44, 0x5e, 0x7c, 0x95, 0xc3]), # collapsing bridges
([None, None, None, 83], [0x4, 0x3f, 0xce]), # pull tongue
([None, None, None, 83], [0x35, 0x37, 0x76]), # swamp drains
([None, None, 34, None], [0x28]), # tektike forced? - spawn chest
([None, None, 37, None], [0x97]), # wizzrobe spawner - in middle of room...
# combined
([None, 32, None, (82, 83)], [0x3e]), # babasu spawners + crystal switch
([None, None, 35, 82], [0x56]), # wallmaster + collasping bridge
([None, None, 35, (82, 83)], [0x57, 0x68]), # wallmaster + statue and wallmaster + bumpers
([None, None, 34, 83], [0x76]), # swamp drain + pirogusu spawners
# allow some sprites / increase odds:
([72, 73, None, None], []), # allow for blue archer + greenbush
([None, 73, 19, None], []), # allow for green knife guard
([None, None, 12, 68], []), # increase odds for zora
([22, None, 23, None], []), # increase odds for snapdragon
]
data_tables.room_requirements = {}
# find home for the free_sheet_reqs
for pair in free_sheet_reqs:
groups, room_list = pair
possible_sheets = []
found_match = False
for num in range(65, 124):
sheet = sheets[num]
valid = True
match = True
for idx, value in enumerate(groups):
if value is not None and sheet.locked[idx]:
valid = False
if (sheet.sub_groups[idx] not in value if isinstance(value, tuple)
else value != sheet.sub_groups[idx]):
match = False
elif value is not None:
match = False
if match:
found_match = True
break
if valid:
possible_sheets.append(sheet)
if not found_match:
chosen_sheet = random.choice(possible_sheets)
chosen_groups = [(random.choice(g) if isinstance(g, tuple) else g) for g in groups]
chosen_sheet.add_sprite_to_sheet(chosen_groups, room_list)
for room in room_list:
data_tables.room_requirements[room] = groups
find_matching_sheet(groups, sheets, range(65, 124), room_list)
# RandomizeRooms(optionFlags);
@@ -594,15 +582,15 @@ def setup_required_dungeon_groups(sheets):
# roomCollection.RandomizeRoomSpriteGroups(spriteGroupCollection, optionFlags);
# more stuff
sub_group_choices = {
0: [22, 31, 47, 14], # 70, 72 for guards
0: [22, 31, 47, 14, 72, 70], # 70, 72 for guards #72 specifically for BlueArcher/GreenBush
1: [44, 30, 32], # 73, 13
2: [12, 18, 23, 24, 28, 46, 34, 35, 39, 40, 38, 41, 36, 37, 42],
3: [17, 16, 27, 20, 82, 83]
2: [12, 18, 23, 24, 28, 46, 34, 35, 39, 40, 38, 41, 36, 37, 42, 19], # 19 for GreenKnifeGuard
3: [17, 16, 27, 20, 82, 83, 25, 68] # 25 for Swamola, 68 for Zora (walking?)
}
def randomize_underworld_sprite_sheets(sheets):
setup_required_dungeon_groups(sheets)
def randomize_underworld_sprite_sheets(sheets, data_tables):
setup_required_dungeon_groups(sheets, data_tables)
for num in range(65, 124): # sheets 0x41 to 0x7B inclusive
sheet = sheets[num]
@@ -624,7 +612,7 @@ def setup_required_overworld_groups(sheets):
sheets[1].add_sprite_to_sheet([None, None, 76, 63], {0x1B, 0xAB}) # Hyrule Castle (pre/post-Aga)
sheets[6].add_sprite_to_sheet([None, None, None, None], {0x22, 0x28, 0xB2, 0xB8}) # Smithy/Race (pre/post-Aga)
sheets[8].add_sprite_to_sheet([None, None, 18, None], {0x30, 0xC0}) # Desert (pre/post-Aga)
sheets[10].add_sprite_to_sheet([None, None, None, None], {0x3A, 0xCA}) # M-rock (pre/post-Aga)
sheets[10].add_sprite_to_sheet([None, None, None, 17], {0x3A, 0xCA}) # M-rock (pre/post-Aga)
sheets[22].add_sprite_to_sheet([None, None, 24, None], {0x4F, 0xDF}) # Catfish (pre/post-Aga)
sheets[21].add_sprite_to_sheet([21, None, None, 21], {0x62, 0xF2}) # Smith DW (pre/post-Aga)
sheets[27].add_sprite_to_sheet([None, 42, None, None], {0x68, 0xF8}) # Dig Game (pre/post-Aga)
@@ -637,12 +625,50 @@ def setup_required_overworld_groups(sheets):
sheets[26].add_sprite_to_sheet([15, None, None, None], {0x92}) # Lumberjacks post-Aga
sheets[23].add_sprite_to_sheet([None, None, None, 25], {0x5E, 0xEE}) # PoD pre/post-Aga
free_sheet_reqs = [
[72, 73, None, None], # allow for blue archer + green bush
[None, 73, 19, None], # allow for green knife guard
[22, None, 23, None], # increase odds for snapdragon
[70, 73, None, None], # guards group (ballnchain, redbush, redjav, cannon, bomb, bluesain
]
for group in free_sheet_reqs:
find_matching_sheet(group, sheets, range(1, 64))
def find_matching_sheet(groups, sheets, search_sheets, room_list=None):
possible_sheets = []
found_match = False
for num in search_sheets:
sheet = sheets[num]
valid = True
match = True
for idx, value in enumerate(groups):
if value is not None and sheet.locked[idx]:
valid = False
if (sheet.sub_groups[idx] not in value if isinstance(value, tuple)
else value != sheet.sub_groups[idx]):
match = False
elif value is not None:
match = False
if match:
found_match = True
break
if valid:
possible_sheets.append(sheet)
if not found_match:
chosen_sheet = random.choice(possible_sheets)
chosen_groups = [(random.choice(g) if isinstance(g, tuple) else g) for g in groups]
chosen_sheet.add_sprite_to_sheet(chosen_groups, room_list)
def randomize_overworld_sprite_sheets(sheets):
setup_required_overworld_groups(sheets)
for num in range(1, 64): # sheets 0x1 to 0x3F inclusive
sheet = sheets[num]
if num == 6: # skip this group, would like to know why though
continue
for idx in range(0, 4):
if not sheet.locked[idx]:
sheet.sub_groups[idx] = random.choice(sub_group_choices[idx])

View File

@@ -0,0 +1,10 @@
0x00: [0x02, 0x01, 0x01]
0x01: [0x04, 0x04, 0x04]
0x02: [0x00, 0x00, 0x00]
0x03: [0x08, 0x04, 0x02]
0x04: [0x08, 0x08, 0x08]
0x05: [0x10, 0x08, 0x04]
0x06: [0x20, 0x10, 0x08]
0x07: [0x20, 0x18, 0x10]
0x08: [0x18, 0x10, 0x08] # Roller class damage
0x09: [0x40, 0x30, 0x18] # Ganon class damage - max 8 hearts

View File

@@ -0,0 +1,198 @@
UW: # Total 82753
AntiFairy: 50 # f1.99026% raw:1647
Statue: 50 # f1.99026% raw:1647
BlueGuard: 124 # f0.80480% raw:666
GreenGuard: 157 # f0.63563% raw:526
RedSpearGuard: 124 # f0.80480% raw:666
BluesainBolt: 567 # f0.17643% raw:146
UsainBolt: 124 # f0.80480% raw:666
RedJavelinGuard: 662 # f0.15105% raw:125
RedBushGuard: 662 # f0.15105% raw:125
BombGuard: 662 # f0.15105% raw:125
BallNChain: 662 # f0.15105% raw:125
CannonTrooper: 662 # f0.15105% raw:125
CricketRat: 169 # f0.59212% raw:490
Snake: 169 # f0.59212% raw:490
Keese: 169 # f0.59212% raw:490
BigSpike: 50 # f1.99026% raw:1647
AntiFairyCircle: 50 # f1.99026% raw:1647
SpikeBlock: 50 # f1.99026% raw:1647
Bumper: 50 # f1.99026% raw:1647
BunnyBeam: 14 # f7.12965% raw:5900
FloppingFish: 14 # f7.12965% raw:5900
Stal: 14 # f7.12965% raw:5900
Landmine: 14 # f7.12965% raw:5900
Octorok: 159 # f0.62717% raw:519
RedBari: 99 # f1.01386% raw:839
BlueBari: 99 # f1.01386% raw:839
FireballZora: 159 # f0.62717% raw:519
SparkCW: 99 # f1.01386% raw:839
SparkCCW: 99 # f1.01386% raw:839
FloatingSkull: 99 # f1.01386% raw:839
FirebarCW: 99 # f1.01386% raw:839
FirebarCCW: 99 # f1.01386% raw:839
Firesnake: 99 # f1.01386% raw:839
Stalfos: 99 # f1.01386% raw:839
Raven: 92 # f1.09120% raw:903
Vulture: 400 # f0.25014% raw:207
Buzzblob: 196 # f0.51116% raw:423
Hoarder: 196 # f0.51116% raw:423
Hoarder2: 196 # f0.51116% raw:423
Geldman: 400 # f0.25014% raw:207
Toppo: 196 # f0.51116% raw:423
FakeMasterSword: 196 # f0.51116% raw:423
MiniHelmasaur: 56 # f1.79450% raw:1485
MiniMoldorm: 56 # f1.79450% raw:1485
HardhatBeetle: 56 # f1.79450% raw:1485
Lynel: 172 # f0.58246% raw:482
Deadrock: 176 # f0.56796% raw:470
ArmosStatue: 176 # f0.56796% raw:470
Hover: 211 # f0.47370% raw:392
Blob: 52 # f1.90930% raw:1580
StalfosKnight: 52 # f1.90930% raw:1580
Kyameron: 211 # f0.47370% raw:392
Zoro: 52 # f1.90930% raw:1580
Babasu: 52 # f1.90930% raw:1580
Tektite: 176 # f0.56796% raw:470
Popo: 56 # f1.77516% raw:1469
Popo2: 56 # f1.77516% raw:1469
Beamos: 56 # f1.77516% raw:1469
DebirandoPit: 110 # f0.90510% raw:749
Debirando: 110 # f0.90510% raw:749
Leever: 110 # f0.90510% raw:749
GreenEyegoreMimic: 270 # f0.36978% raw:306
RedEyegoreMimic: 270 # f0.36978% raw:306
Swamola: 172 # f0.58004% raw:480
GreenZirro: 191 # f0.52324% raw:433
BlueZirro: 191 # f0.52324% raw:433
Pikit: 191 # f0.52324% raw:433
Cucco: 207 # f0.48337% raw:400
Moblin: 281 # f0.35648% raw:295
Octorok4Way: 273 # f0.36615% raw:303
Octoballoon: 273 # f0.36615% raw:303
Zora: 690 # f0.14501% raw:120
Crab: 273 # f0.36615% raw:303
Thief: 81 # f1.22896% raw:1017
Wizzrobe: 155 # f0.64529% raw:534
Poe: 828 # f0.12084% raw:100
Hinox: 109 # f0.92081% raw:762
Ropa: 109 # f0.92081% raw:762
Pengator: 294 # f0.33956% raw:281
Freezor: 294 # f0.33956% raw:281
Sluggula: 239 # f0.41811% raw:346
RollerVerticalUp: 280 # f0.35769% raw:296
RollerVerticalDown: 280 # f0.35769% raw:296
RollerHorizontalLeft: 280 # f0.35769% raw:296
RollerHorizontalRight: 280 # f0.35769% raw:296
Pokey: 280 # f0.35769% raw:296
Chainchomp: 280 # f0.35769% raw:296
Gibdo: 196 # f0.51116% raw:423
Wallmaster: 196 # f0.51116% raw:423
GreenKnifeGuard: 773 # f0.12930% raw:107
BlueArcher: 632 # f0.15830% raw:131
GreenBushGuard: 632 # f0.15830% raw:131
Snapdragon: 690 # f0.14501% raw:120
Kodongo: 368 # f0.27189% raw:225
Terrorpin: 368 # f0.27189% raw:225
BlueZazak: 400 # f0.25014% raw:207
RedZazak: 400 # f0.25014% raw:207
Gibo: 400 # f0.25014% raw:207
OW: # Total 94707
Popo: 50 # f2.00513% raw:1899
Popo2: 50 # f2.00513% raw:1899
Beamos: 50 # f2.00513% raw:1899
DebirandoPit: 100 # f1.00415% raw:951
Debirando: 100 # f1.00415% raw:951
Leever: 100 # f1.00415% raw:951
BunnyBeam: 15 # f6.65210% raw:6300
FloppingFish: 15 # f6.65210% raw:6300
Stal: 15 # f6.65210% raw:6300
Landmine: 15 # f6.65210% raw:6300
MiniHelmasaur: 49 # f2.03364% raw:1926
AntiFairy: 73 # f1.36738% raw:1295
MiniMoldorm: 49 # f2.03364% raw:1926
Statue: 73 # f1.36738% raw:1295
HardhatBeetle: 49 # f2.03364% raw:1926
BigSpike: 73 # f1.36738% raw:1295
AntiFairyCircle: 73 # f1.36738% raw:1295
GreenEyegoreMimic: 316 # f0.31677% raw:300
RedEyegoreMimic: 316 # f0.31677% raw:300
SpikeBlock: 73 # f1.36738% raw:1295
Bumper: 73 # f1.36738% raw:1295
Hinox: 87 # f1.14353% raw:1083
Ropa: 87 # f1.14353% raw:1083
CricketRat: 160 # f0.62509% raw:592
Snake: 160 # f0.62509% raw:592
Keese: 160 # f0.62509% raw:592
GreenZirro: 151 # f0.66415% raw:629
BlueZirro: 151 # f0.66415% raw:629
Pikit: 151 # f0.66415% raw:629
Raven: 61 # f1.64719% raw:1560
RollerVerticalUp: 272 # f0.36745% raw:348
RollerVerticalDown: 272 # f0.36745% raw:348
RollerHorizontalLeft: 272 # f0.36745% raw:348
RollerHorizontalRight: 272 # f0.36745% raw:348
Pokey: 272 # f0.36745% raw:348
Chainchomp: 272 # f0.36745% raw:348
Swamola: 128 # f0.78030% raw:739
Cucco: 316 # f0.31677% raw:300
BlueGuard: 239 # f0.41813% raw:396
GreenGuard: 239 # f0.41813% raw:396
RedSpearGuard: 239 # f0.41813% raw:396
UsainBolt: 239 # f0.41813% raw:396
Buzzblob: 115 # f0.86688% raw:821
Hoarder: 115 # f0.86688% raw:821
RedBari: 98 # f1.01999% raw:966
BlueBari: 98 # f1.01999% raw:966
Hoarder2: 115 # f0.86688% raw:821
Toppo: 115 # f0.86688% raw:821
SparkCW: 98 # f1.01999% raw:966
SparkCCW: 98 # f1.01999% raw:966
FloatingSkull: 98 # f1.01999% raw:966
FirebarCW: 98 # f1.01999% raw:966
FirebarCCW: 98 # f1.01999% raw:966
Firesnake: 98 # f1.01999% raw:966
Stalfos: 98 # f1.01999% raw:966
FakeMasterSword: 115 # f0.86688% raw:821
Vulture: 184 # f0.54484% raw:516
Geldman: 184 # f0.54484% raw:516
Blob: 50 # f1.98401% raw:1879
StalfosKnight: 50 # f1.98401% raw:1879
Zoro: 50 # f1.98401% raw:1879
Babasu: 50 # f1.98401% raw:1879
Octorok: 112 # f0.89011% raw:843
Octorok4Way: 226 # f0.44242% raw:419
Octoballoon: 226 # f0.44242% raw:419
FireballZora: 112 # f0.89011% raw:843
Crab: 226 # f0.44242% raw:419
Thief: 90 # f1.11713% raw:1058
Zora: 686 # f0.14571% raw:138
Deadrock: 127 # f0.78769% raw:746
ArmosStatue: 127 # f0.78769% raw:746
Tektite: 127 # f0.78769% raw:746
Hover: 301 # f0.33260% raw:315
Kyameron: 301 # f0.33260% raw:315
Pengator: 274 # f0.36534% raw:346
Freezor: 274 # f0.36534% raw:346
BlueArcher: 824 # f0.12143% raw:115
GreenBushGuard: 824 # f0.12143% raw:115
Kodongo: 287 # f0.34844% raw:330
Terrorpin: 287 # f0.34844% raw:330
Wizzrobe: 152 # f0.65676% raw:622
Poe: 474 # f0.21118% raw:200
Snapdragon: 596 # f0.16789% raw:159
Moblin: 221 # f0.45298% raw:429
Lynel: 145 # f0.69161% raw:655
BlueZazak: 308 # f0.32416% raw:307
RedZazak: 308 # f0.32416% raw:307
Gibo: 308 # f0.32416% raw:307
Gibdo: 290 # f0.34528% raw:327
Wallmaster: 290 # f0.34528% raw:327
GreenKnifeGuard: 853 # f0.11720% raw:111
BluesainBolt: 803 # f0.12459% raw:118
RedJavelinGuard: 803 # f0.12459% raw:118
RedBushGuard: 803 # f0.12459% raw:118
BombGuard: 803 # f0.12459% raw:118
BallNChain: 803 # f0.12459% raw:118
CannonTrooper: 803 # f0.12459% raw:118
Sluggula: 302 # f0.33155% raw:314

View File

@@ -0,0 +1,354 @@
- [0x0002, 0, ["RollerVerticalDown"]] #"Sewers - Rat Pots - Rat 1"
- [0x0002, 1, ["RollerVerticalDown"]] #"Sewers - Rat Pots - Rat 2"
- [0x0002, 2, ["RollerVerticalUp"]] #"Sewers - Rat Pots - Rat 3"
- [0x0002, 3, ["RollerVerticalUp"]] #"Sewers - Rat Pots - Rat 4"
- [0x0002, 15, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft"]] #"Sewers - Rat Pots - Rat 6"
- [0x0002, 16, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft"]] #"Sewers - Rat Pots - Rat 7"
- [0x000a, 0, ["RollerVerticalDown", "RollerVerticalUp"]] #"Palace of Darkness - Basement Ledge - Terrorpin 1"
- [0x000a, 1, ["RollerHorizontalRight", "RollerHorizontalLeft"]] #"Palace of Darkness - Basement Ledge - Terrorpin 2"
- [0x000b, 1, ["RollerVerticalDown", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Callback - Terrorpin 1"
- [0x000e, 0, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft"]] #"Ice Palace - Entrance - Freezor"
- [0x000e, 1, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft"]] #"Ice Palace - Bari Key - Top Bari"
- [0x000e, 2, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft"]] #"Ice Palace - Bari Key - Middle Bari"
- [0x0016, 0, ["RollerVerticalDown", "RollerVerticalUp", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Pool - Zol 1"
- [0x0016, 1, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Pool - Zol 2"
- [0x0016, 2, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Pool - Blue Bari"
- [0x0016, 3, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Pool - Zol 3"
- [0x0017, 5, ["Beamos", "AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Tower Of Hera - Bumper Room - Fire Bar (Clockwise)"
- [0x0019, 0, ["SparkCW", "SparkCCW", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Palace of Darkness - Dark Maze - Kodongo 1"
- [0x0019, 1, ["RollerVerticalUp"]] #"Palace of Darkness - Dark Maze - Kodongo 2"
- [0x0019, 2, ["RollerVerticalDown", "RollerVerticalUp"]] #"Palace of Darkness - Dark Maze - Kodongo 3"
- [0x0019, 3, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft"]] #"Palace of Darkness - Dark Maze - Kodongo 4"
- [0x001a, 0, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Compass Room - Mini Helmasaur 1"
- [0x001a, 5, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Compass Room - Mini Helmasaur 2"
- [0x001b, 3, ["Beamos", "AntiFairyCircle", "Bumper"]] #"Palace of Darkness - Mimics 2 - Red Eyegore"
- [0x001b, 4, ["RollerVerticalUp"]] #"Palace of Darkness - Mimics 2 - Green Eyegore L"
- [0x001e, 3, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "BigSpike", "Bumper"]] #"Ice Palace - Blob Ambush - Red Bari 3"
- [0x001e, 4, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "BigSpike", "Bumper"]] #"Ice Palace - Blob Ambush - Red Bari 4"
- [0x001e, 5, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ice Palace - Blob Ambush - Zol 1"
- [0x001e, 6, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ice Palace - Blob Ambush - Zol 2"
- [0x001f, 0, ["RollerHorizontalRight"]] #"Ice Palace - Big Key View - Pengator 1"
- [0x0021, 3, ["RollerVerticalDown", "RollerVerticalUp"]] #"Sewers - Dark U - Rat 2"
- [0x0021, 4, ["RollerVerticalDown", "RollerVerticalUp"]] #"Sewers - Dark U - Rat 3"
- [0x0026, 1, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Big Spoon - Red Bari 1"
- [0x0026, 8, ["AntiFairyCircle", "Bumper"]] #"Swamp Palace - Big Spoon - Red Bari 3"
- [0x0026, 9, ["RollerHorizontalRight"]] #"Swamp Palace - Big Spoon - Kyameron"
- [0x0027, 0, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalLeft", "FirebarCW"]] #"Tower Of Hera - Petting Zoo - Mini Moldorm 1"
- [0x0027, 1, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Tower Of Hera - Petting Zoo - Mini Moldorm 2"
- [0x0027, 2, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Tower Of Hera - Petting Zoo - Mini Moldorm 3"
- [0x0027, 5, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Tower Of Hera - Petting Zoo - Kodongo 1"
- [0x0028, 4, ["RollerVerticalUp"]] #"Swamp Palace - Entrance Ledge - Spike Trap"
- [0x002a, 2, ["SparkCW", "SparkCCW", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "SpikeBlock"]] #"Palace of Darkness - Arena Main - Hardhat Beetle 1"
- [0x002a, 3, ["Statue", "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Arena Main - Hardhat Beetle 2"
- [0x002a, 6, ["RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Arena Main - Hardhat Beetle 5"
- [0x002b, 5, ["RollerHorizontalRight"]] #"Palace of Darkness - Fairies - Red Bari 2"
- [0x002e, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW"]] #"Ice Palace - Penguin Chest - Pengator 1"
- [0x002e, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW"]] #"Ice Palace - Penguin Chest - Pengator 2"
- [0x002e, 2, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW"]] #"Ice Palace - Penguin Chest - Pengator 3"
- [0x002e, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW"]] #"Ice Palace - Penguin Chest - Pengator 4"
- [0x002e, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW"]] #"Ice Palace - Penguin Chest - Pengator 5"
- [0x002e, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW"]] #"Ice Palace - Penguin Chest - Pengator 6"
- [0x0034, 0, ["SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - West Wing - Hover 1"
- [0x0034, 1, ["SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - West Wing - Hover 2"
- [0x0034, 2, ["SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - West Wing - Kyameron"
- [0x0034, 4, ["Statue", "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - West Wing - Zol"
- [0x0035, 6, ["RollerHorizontalRight"]] #"Swamp Palace - West Lever - Stalfos 2"
- [0x0035, 9, ["RollerHorizontalRight", "Beamos", "AntiFairyCircle", "Bumper"]] #"Swamp Palace - West Lever - Blue Bari"
- [0x0036, 7, ["RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper"]] #"Swamp Palace - Lobby - Hover 3"
- [0x0037, 7, ["RollerHorizontalRight"]] #"Swamp Palace - Water 1 - Blue Bari"
- [0x0038, 4, ["RollerHorizontalRight"]] #"Swamp Palace - Long Hall - Kyameron 2"
- [0x0039, 3, ["RollerVerticalUp", "RollerHorizontalLeft"]] #"Skull Woods - Play Pen - Mini Helmasaur"
- [0x0039, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW"]] #"Skull Woods - Play Pen - Spike Trap 1"
- [0x0039, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft"]] #"Skull Woods - Play Pen - Hardhat Beetle"
- [0x0039, 6, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW"]] #"Skull Woods - Play Pen - Spike Trap 2"
- [0x003c, 1, ["SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Hookshot Cave - Blue Bari 1"
- [0x003c, 2, ["SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Hookshot Cave - Blue Bari 2"
- [0x003d, 9, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Torches 2 - Spark (Counterclockwise)"
- [0x003d, 10, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Torches 2 - Spark (Clockwise) 1"
- [0x003d, 12, ["AntiFairyCircle", "Bumper"]] #"Ganon's Tower - Torches 2 - Bunny Beam"
- [0x003d, 13, ["AntiFairyCircle", "Bumper"]] #"Ganon's Tower - Torches 2 - Antifairy"
#- [0x003e, 3, ["Kodongo"]] #"Ice Palace - Conveyor - Babasu 1"
#- [0x003e, 4, ["Kodongo"]] #"Ice Palace - Conveyor - Babasu 2"
#- [0x003e, 6, ["Kodongo"]] #"Ice Palace - Conveyor - Babasu 3"
#- [0x003e, 7, ["Kodongo"]] #"Ice Palace - Conveyor - Babasu 4"
- [0x003f, 1, ["RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper"]] #"Ice Palace - P Room - Stalfos Knight 1"
- [0x003f, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - P Room - Stalfos Knight 2"
- [0x0040, 0, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] # Agahnims Tower - Bridge - Blue Guard 1
- [0x0040, 1, ["Statue", "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] # Agahnims Tower - Bridge - Blue Guard 2
- [0x0041, 0, ["RollerHorizontalLeft"]] #"Sewers - Dark Cactus - Rat 1"
- [0x0041, 1, ["RollerVerticalDown", "RollerHorizontalRight"]] #"Sewers - Dark Cactus - Rat 2"
- [0x0041, 2, ["RollerVerticalUp"]] #"Sewers - Dark Cactus - Rat 3"
- [0x0042, 0, ["SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Sewers - Dark Rope Corridor - Rope 1"
- [0x0042, 1, ["SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Sewers - Dark Rope Corridor - Rope 2"
- [0x0042, 2, ["SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Sewers - Dark Rope Corridor - Rope 3"
- [0x0042, 3, ["SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Sewers - Dark Rope Corridor - Rope 4"
- [0x0042, 4, ["SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Sewers - Dark Rope Corridor - Rope 5"
- [0x0042, 5, ["SparkCW", "SparkCCW", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Sewers - Dark Rope Corridor - Rope 6"
- [0x0044, 4, ["RollerVerticalUp", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Thieves' Town - Joke Room - Zol"
- [0x0044, 6, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "BigSpike"]] #"Thieves' Town - Joke Room - Red Bari"
- [0x0044, 8, ["Statue", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Thieves' Town - Joke Room - Blue Bari 4"
- [0x0045, 1, ["RollerVerticalUp", "RollerVerticalDown"]] #"Thieves' Town - Basement Block Totems - Red Zazak"
- [0x0045, 7, ["AntiFairyCircle", "Bumper"]] #"Thieves' Town - Cells - Blue Zazak 4"
- [0x0045, 8, ["RollerHorizontalRight"]] #"Thieves' Town - Cells - Zol"
- [0x0046, 0, ["RollerVerticalUp", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Swamp Palace - Big O Top - Hover 1"
- [0x0046, 2, ["RollerVerticalDown", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Swamp Palace - Big O Top - Hover 2"
- [0x0046, 4, ["RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Swamp Palace - Big O Top - Hover 3"
- [0x0049, 5, ["RollerVerticalUp", "RollerVerticalDown"]] #"Skull Woods - Bari Pits - Gibdo 2"
- [0x0049, 7, ["RollerVerticalUp", "RollerVerticalDown"]] #"Skull Woods - Bari Pits - Gibdo 4"
- [0x0049, 8, ["Beamos", "AntiFairyCircle", "Bumper"]] #"Skull Woods - Bari Pits - Gibdo 5"
- [0x004b, 0, ["Beamos", "AntiFairyCircle", "Bumper"]] #"Palace of Darkness - Mimics 1 - Red Eyegore"
- [0x004b, 1, ["RollerHorizontalRight"]] #"Palace of Darkness - Warp Hint - Antifairy 1"
- [0x004b, 5, ["RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Palace of Darkness - Jelly Hall - Blue Bari 1"
- [0x004b, 6, ["AntiFairyCircle", "BigSpike"]] #"Palace of Darkness - Jelly Hall - Blue Bari 2"
- [0x004b, 7, ["AntiFairyCircle", "BigSpike"]] #"Palace of Darkness - Jelly Hall - Blue Bari 3"
- [0x004e, 0, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Blob Alley - Zol 1"
- [0x004e, 1, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Blob Alley - Zol 2"
- [0x004e, 2, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Blob Alley - Zol 3"
- [0x0050, 0, ["RollerVerticalUp", "RollerVerticalDown"]] #"Hyrule Castle - North West Passage - Green Guard"
- [0x0050, 1, ["RollerVerticalUp", "RollerVerticalDown"]] #"Hyrule Castle - North West Passage - Green Knife Guard 1"
- [0x0050, 2, ["RollerVerticalUp", "RollerVerticalDown"]] #"Hyrule Castle - North West Passage - Green Knife Guard 2"
- [0x0052, 0, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper"]] #"Hyrule Castle - North East Passage - Green Guard"
- [0x0052, 1, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper"]] #"Hyrule Castle - North East Passage - Green Knife Guard 1"
- [0x0052, 2, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper"]] #"Hyrule Castle - North East Passage - Green Knife Guard 2"
- [0x0053, 1, ["AntiFairyCircle", "Bumper"]] #"Desert Palace - Bridge - Beamos 1"
- [0x0053, 5, ["RollerVerticalDown"]] #"Desert Palace - Popo Genocide - Popo TL"
- [0x0053, 7, ["Beamos", "AntiFairyCircle", "Bumper"]] #"Desert Palace - Bridge - Popo 5"
- [0x0055, 1, ["RollerVerticalUp", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Secret Passage Exit - Green Knife Guard 1"
- [0x0057, 2, ["RollerVerticalUp", "AntiFairyCircle", "Bumper"]] #"Skull Woods - Big Key Room - Spike Trap"
- [0x0057, 7, ["RollerVerticalUp", "RollerVerticalDown"]] #"Skull Woods - Big Key Room - Gibdo 2"
- [0x0057, 12, ["RollerVerticalUp", "RollerVerticalDown"]] #"Skull Woods - Big Key Room - Gibdo 6"
- [0x0057, 13, ["RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper"]] #"Skull Woods - Big Key Room - Blue Bari 1"
- [0x0057, 14, ["RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper"]] #"Skull Woods - Big Key Room - Blue Bari 2"
- [0x0058, 7, ["RollerHorizontalLeft"]] #"Skull Woods - Lever Room - Hardhat Beetle 2"
- [0x0059, 0, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Skull Woods - Bridge Room - Mini Moldorm 1"
- [0x0059, 1, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Skull Woods - Bridge Room - Mini Moldorm 2"
- [0x0059, 9, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Skull Woods - Bridge Room - Gibdo 1"
- [0x005e, 3, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Ice Palace - Pit Trap - Big Spike Trap"
- [0x005e, 4, ["RollerVerticalUp", "RollerVerticalDown"]] #"Ice Palace - Pit Trap - Fire Bar (Clockwise)"
- [0x005f, 0, ["RollerVerticalDown", "RollerHorizontalLeft"]] #"Ice Palace - Bari University - Blue Bari 1"
- [0x005f, 1, ["RollerVerticalDown", "RollerHorizontalRight"]] #"Ice Palace - Bari University - Blue Bari 2"
- [0x0060, 0, ["RollerVerticalUp", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Hyrule Castle - West - Blue Guard"
- [0x0062, 0, ["RollerVerticalUp", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Hyrule Castle - East - Blue Guard"
- [0x0064, 0, ["Kodongo"]] #"Thieves' Town - Attic Hall Left - Keese 1"
- [0x0064, 2, ["Kodongo"]] #"Thieves' Town - Attic Hall Left - Keese 2"
- [0x0064, 4, ["RollerHorizontalLeft", "RollerHorizontalRight"]] #"Thieves' Town - Attic Hall Left - Rat 1"
- [0x0065, 0, ["RollerVerticalUp", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Thieves' Town - Attic Window - Rat 1"
- [0x0065, 1, ["RollerHorizontalLeft", "RollerHorizontalRight"]] #"Thieves' Town - Attic Window - Rat 2"
- [0x0065, 2, ["Beamos", "AntiFairyCircle", "Bumper"]] #"Thieves' Town - Attic Window - Rat 3"
- [0x0066, 0, ["Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Swamp Palace - Waterfall Room - Hover 1"
- [0x0067, 1, ["RollerVerticalUp", "RollerVerticalDown"]] #"Skull Woods - Firebar Pits - Blue Bari 1"
- [0x0067, 3, ["RollerVerticalUp", "RollerVerticalDown"]] #"Skull Woods - Firebar Pits - Hardhat Beetle 1"
- [0x0067, 5, ["RollerVerticalDown"]] #"Skull Woods - Firebar Pits - Hardhat Beetle 3"
- [0x0067, 6, ["RollerVerticalDown"]] #"Skull Woods - Firebar Pits - Hardhat Beetle 4"
- [0x0067, 7, ["Beamos", "AntiFairyCircle", "Bumper"]] #"Skull Woods - Firebar Pits - Fire Bar (Clockwise)"
- [0x006a, 0, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Dark Alley - Terrorpin 1"
- [0x006a, 1, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Dark Alley - Terrorpin 2"
- [0x006a, 2, ["RollerVerticalUp", "RollerVerticalDown"]] #"Palace of Darkness - Dark Alley - Antifairy 1"
- [0x006a, 4, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Dark Alley - Terrorpin 3"
- [0x006a, 5, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Dark Alley - Terrorpin 4"
- [0x006b, 7, ["RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "Bumper"]] #"Ganon's Tower - Mimics 1 - Spike Trap 1"
- [0x0071, 0, ["RollerHorizontalLeft"]] #"Hyrule Castle - Basement Trap - Green Guard"
- [0x0074, 0, ["AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Desert Palace - North Hallway - Red Devalant 1"
- [0x0074, 1, ["AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Desert Palace - North Hallway - Red Devalant 2"
- [0x0074, 4, ["AntiFairyCircle", "Bumper"]] #"Desert Palace - North Hallway - Leever 1"
- [0x0074, 5, ["AntiFairyCircle", "Bumper"]] #"Desert Palace - North Hallway - Leever 2"
- [0x0075, 6, ["Kodongo"]] #"Desert Palace - Trap Room - Moving Cannon (Right)"
- [0x0075, 7, ["Kodongo"]] #"Desert Palace - Trap Room - Moving Cannon (Left)"
- [0x0076, 1, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Toilet Left - Hover 1"
- [0x0076, 2, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Toilet Left - Kyameron"
- [0x0076, 3, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Toilet Left - Hover 2"
- [0x0076, 4, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Swamp Palace - Toilet Left - Zol"
- [0x0076, 6, ["RollerVerticalDown", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Swamp Palace - Toilet Left - Blue Bari"
- [0x007b, 0, ["RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - DMs Room - Blue Bari 1"
- [0x007b, 1, ["AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - DMs Room - Blue Bari 2"
- [0x007b, 6, ["Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - DMs Room - Statue"
- [0x007b, 7, ["Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - DMs Room - Hardhat Beetle"
- [0x007c, 1, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Randomizer Room - Fire Bar (Counterclockwise)"
- [0x007c, 2, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Randomizer Room - Spike Trap"
- [0x007c, 3, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Randomizer Room - Fire Bar (Clockwise)"
- [0x007c, 4, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Randomizer Room - Hardhat Beetle"
- [0x007d, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - The Zoo - Fire Snake 1"
- [0x007d, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - The Zoo - Fire Snake 2"
- [0x007d, 2, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - The Zoo - Fire Snake 3"
- [0x007d, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - The Zoo - Fire Snake 4"
- [0x007d, 7, ["RollerVerticalUp", "RollerHorizontalLeft"]] #"Ganon's Tower - The Zoo - Mini Helmasaur"
- [0x007d, 8, ["RollerVerticalUp", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Ganon's Tower - The Zoo - Red Bari"
- [0x007f, 0, ["Statue", "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock"]] #"Ice Palace - Big Spikes - Red Bari 1"
- [0x007f, 1, ["Statue", "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock"]] #"Ice Palace - Big Spikes - Red Bari 2"
- [0x007f, 2, ["Statue", "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock"]] #"Ice Palace - Big Spikes - Red Bari 3"
- [0x007f, 3, ["Statue", "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock"]] #"Ice Palace - Big Spikes - Red Bari 4"
- [0x007f, 4, ["RollerVerticalDown"]] #"Ice Palace - Big Spikes - Big Spike Trap 1"
- [0x007f, 5, ["RollerVerticalDown"]] #"Ice Palace - Big Spikes - Big Spike Trap 2"
- [0x0082, 0, ["RollerVerticalDown"]] #"Hyrule Castle - Basement Playpit - Blue Guard 1"
- [0x0082, 2, ["RollerVerticalUp"]] #"Hyrule Castle - Basement Playpit - Blue Guard 3"
- [0x0083, 0, ["RollerVerticalUp", "RollerVerticalDown"]] #"Desert Palace - Left Hallway - Blue Devalant 1"
- [0x0084, 0, ["RollerVerticalDown", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Desert Palace - Main Room - Left - Leever 1"
- [0x0084, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Desert Palace - Main Room - Left - Leever 2"
- [0x0085, 2, ["RollerHorizontalRight"]] #"Desert Palace - Compass Room - Popo TL"
- [0x0085, 7, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Desert Palace - Right Hallway - Leever 2"
- [0x008b, 4, ["Statue", "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper"]] #"Ganon's Tower - Map Room - Spike Trap"
- [0x008b, 6, ["Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Map Room - Fire Bar (Clockwise)"
- [0x008b, 7, ["Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Map Room - Fire Bar (Counterclockwise)"
- [0x008d, 1, ["AntiFairyCircle", "Bumper"]] #"Ganon's Tower - Tile Room - Yomo Medusa T"
- [0x008d, 7, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Tile Room - Spike Trap"
- [0x008d, 8, ["RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Tile Room - Stalfos"
- [0x008d, 9, ["Statue", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Tile Room - Fire Bar (Clockwise)"
- [0x008d, 10, ["RollerVerticalUp", "RollerVerticalDown"]] #"Ganon's Tower - Tile Room - Blue Bari 1"
- [0x008d, 12, ["RollerVerticalUp", "RollerVerticalDown"]] #"Ganon's Tower - Tile Room - Blue Bari 2"
- [0x0092, 8, ["RollerVerticalUp", "Beamos", "AntiFairyCircle", "Bumper"]] #"Misery Mire - Dark Weave - Spike Trap"
- [0x0092, 9, ["RollerHorizontalRight"]] #"Misery Mire - Dark Weave - Antifairy 3"
- [0x0092, 10, ["RollerHorizontalLeft"]] #"Misery Mire - Dark Weave - Stalfos"
- [0x0095, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock"]] #"Ganon's Tower - Conveyer Falling Bridge - Red Spear Guard 1"
- [0x0095, 1, ["Statue", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Conveyer Falling Bridge - Red Spear Guard 2"
- [0x0095, 2, ["Statue", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Conveyer Falling Bridge - Red Spear Guard 3"
- [0x0095, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "SpikeBlock"]] #"Ganon's Tower - Conveyer Falling Bridge - Red Spear Guard 4"
- [0x0096, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Torches 1 - Fire Bar (Clockwise)"
- [0x0096, 1, ["Kodongo"]] #"Ganon's Tower - Torches 1 - Laser Eye (Left) 1"
- [0x0096, 2, ["Kodongo"]] #"Ganon's Tower - Torches 1 - Laser Eye (Left) 2"
- [0x0096, 3, ["Kodongo"]] #"Ganon's Tower - Torches 1 - Laser Eye (Left) 3"
- [0x0096, 4, ["Kodongo"]] #"Ganon's Tower - Torches 1 - Laser Eye (Left) 4"
- [0x0098, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Entrance - Zol 1"
- [0x0098, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Entrance - Zol 2"
- [0x0098, 2, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Entrance - Zol 3"
- [0x0098, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Entrance - Zol 4"
- [0x0098, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Entrance - Zol 5"
- [0x009b, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Spike Switch - Spike Trap 1"
- [0x009b, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Spike Switch - Spike Trap 2"
- [0x009b, 6, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Spike Switch - Yomo Medusa"
- [0x009b, 7, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Spike Switch - Spike Trap 4"
- [0x009b, 8, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Spike Switch - Spike Trap 5"
- [0x009b, 9, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Spike Switch - Spike Trap 6"
- [0x009b, 10, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Spike Switch - Spike Trap 7"
- [0x009c, 1, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Invisible Floor Maze - Mini Helmasaur"
- [0x009c, 2, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Invisible Floor Maze - Hardhat Beetle 2"
- [0x009c, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Invisible Floor Maze - Hardhat Beetle 3"
- [0x009c, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Invisible Floor Maze - Hardhat Beetle 4"
- [0x009c, 5, ["RollerVerticalUp", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Invisible Floor Maze - Hardhat Beetle 5"
- [0x009d, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ganon's Tower - Compass Room - Gibdo 2"
- [0x009d, 6, ["RollerHorizontalLeft", "RollerHorizontalRight"]] #"Ganon's Tower - Compass Room - Blue Bari 1"
- [0x009d, 7, ["RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Compass Room - Blue Bari 2"
- [0x009d, 8, ["RollerHorizontalLeft", "RollerHorizontalRight"]] #"Ganon's Tower - Compass Room - Blue Bari 3"
- [0x009e, 0, ["RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Fairy Drop - blue - Red Bari 1"
- [0x009e, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Fairy Drop - blue - Red Bari 2"
- [0x009e, 2, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Fairy Drop - blue - Stalfos Knight"
- [0x009e, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Fairy Drop - blue - Red Bari 3"
- [0x009f, 0, ["Kodongo"]] #"Ice Palace - Pottery Barn - Babasu 1"
- [0x009f, 1, ["Kodongo"]] #"Ice Palace - Pottery Barn - Babasu 2"
- [0x009f, 2, ["Kodongo"]] #"Ice Palace - Pottery Barn - Babasu 3"
- [0x009f, 3, ["Kodongo"]] #"Ice Palace - Pottery Barn - Babasu 4"
- [0x00a0, 1, ["RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Boss Antichamber - Antifairy"
- [0x00a1, 2, ["Statue", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Fish Room - Spark (Clockwise) 2"
- [0x00a5, 8, ["Kodongo"]] #"Ganon's Tower - Laser Bridge - Laser Eye (Down) L"
- [0x00a5, 9, ["Kodongo"]] #"Ganon's Tower - Laser Bridge - Laser Eye (Down) R"
- [0x00a5, 10, ["RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ganon's Tower - Laser Bridge - Red Spear Guard"
- [0x00a8, 1, ["RollerVerticalUp", "RollerHorizontalLeft"]] #"Eastern Palace - West Wing - Top - Stalfos 2"
- [0x00a8, 3, ["RollerVerticalDown", "RollerHorizontalLeft"]] #"Eastern Palace - West Wing - Top - Stalfos 4"
- [0x00aa, 4, ["AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - East Wing - Top - Stalfos 3"
- [0x00aa, 5, ["Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - East Wing - Top - Popo B 2"
- [0x00ab, 7, ["RollerVerticalUp", "RollerHorizontalLeft"]] #"Thieves' Town - Spike Dodge - Spike Trap 6"
- [0x00ae, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ice Palace - Ice T - Blue Bari 1"
- [0x00ae, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Ice Palace - Ice T - Blue Bari 2"
- [0x00af, 0, ["RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Ice Palace - Ice Clock - Fire Bar (Clockwise)"
- [0x00b1, 2, ["RollerVerticalUp", "RollerVerticalDown"]] #"Misery Mire - Hourglass - Spike Trap 1"
- [0x00b1, 3, ["RollerVerticalUp", "RollerVerticalDown"]] #"Misery Mire - Hourglass - Spike Trap 2"
- [0x00b2, 6, ["RollerVerticalUp", "RollerHorizontalLeft"]] #"Misery Mire - Sluggula Cross - Sluggula TR"
- [0x00b2, 8, ["RollerVerticalDown"]] #"Misery Mire - Popo Push - Medusa 1"
- [0x00b2, 9, ["RollerVerticalUp"]] #"Misery Mire - Sluggula Cross - Sluggula BL"
- [0x00b3, 0, ["RollerVerticalUp", "RollerHorizontalRight", "BigSpike", "SpikeBlock"]] #"Misery Mire - Spike Room - Stalfos 1"
- [0x00b3, 2, ["Statue", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "Bumper"]] #"Misery Mire - Spike Room - Beamos"
- [0x00b3, 3, ["AntiFairyCircle", "Bumper"]] #"Misery Mire - Spike Room - Yomo Medusa"
- [0x00b6, 7, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Turtle Rock - Tile Room - Zol 1"
- [0x00b6, 8, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Turtle Rock - Tile Room - Zol 2"
- [0x00ba, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Eastern Palace - Dark Stalfos - Antifairy 1"
- [0x00ba, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Eastern Palace - Dark Stalfos - Antifairy 2"
- [0x00ba, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Eastern Palace - Dark Stalfos - Popo B 1"
- [0x00ba, 6, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Eastern Palace - Dark Stalfos - Popo B 2"
- [0x00bb, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Thieves' Town - Spikeveyer - Gibo 1"
- [0x00bb, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "Bumper"]] #"Thieves' Town - Spikeveyer - Antifairy 1"
- [0x00bb, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Thieves' Town - Spikeveyer - Gibo 3"
- [0x00bb, 6, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Thieves' Town - Spikeveyer - Fire Snake"
- [0x00bb, 7, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Thieves' Town - Spikeveyer - Gibo 4"
- [0x00bb, 8, ["RollerHorizontalLeft", "RollerHorizontalRight"]] #"Thieves' Town - Spikeveyer - Gibo 5"
- [0x00bb, 9, ["RollerHorizontalLeft", "RollerHorizontalRight"]] #"Thieves' Town - Spikeveyer - Antifairy 2"
- [0x00bc, 6, ["AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Thieves' Town - Toilet - Stalfos 2"
- [0x00bc, 7, ["AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Thieves' Town - Toilet - Stalfos 3"
- [0x00bc, 8, ["RollerVerticalUp", "RollerVerticalDown"]] #"Thieves' Town - Toilet - Stalfos 4"
- [0x00c1, 3, ["RollerVerticalUp", "RollerHorizontalLeft"]] #"Misery Mire - 4 Rails - Stalfos 1"
- [0x00c2, 0, ["RollerHorizontalLeft", "RollerHorizontalRight"]] #"Misery Mire - Main Lobby - blue - Fire Snake 1"
- [0x00c3, 1, ["Kodongo"]] #"Misery Mire - Falling Bridge - Laser Eye (Left) 1"
- [0x00c3, 2, ["Kodongo"]] #"Misery Mire - Falling Bridge - Laser Eye (Right) 1"
- [0x00c3, 3, ["Kodongo"]] #"Misery Mire - Falling Bridge - Laser Eye (Left) 2"
- [0x00c3, 4, ["Kodongo"]] #"Misery Mire - Falling Bridge - Laser Eye (Right) 2"
- [0x00c5, 0, ["Kodongo"]] #"Turtle Rock - Catwalk - Laser Eye (Left) 1"
- [0x00c5, 1, ["Kodongo"]] #"Turtle Rock - Catwalk - Laser Eye (Right) 1"
- [0x00c5, 2, ["Kodongo"]] #"Turtle Rock - Catwalk - Laser Eye (Left) 2"
- [0x00c5, 3, ["Kodongo"]] #"Turtle Rock - Catwalk - Laser Eye (Right) 2"
- [0x00c5, 4, ["Kodongo"]] #"Turtle Rock - Catwalk - Laser Eye (Left) 3"
- [0x00c5, 5, ["Kodongo"]] #"Turtle Rock - Catwalk - Laser Eye (Right) 3"
- [0x00c5, 6, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Turtle Rock - Catwalk - Mini Helmasaur"
- [0x00c5, 7, ["Statue"]] #"Turtle Rock - Catwalk - Laser Eye (Left) 4"
- [0x00cb, 3, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Thieves' Town - Grand Room NW - Zol 1"
- [0x00cb, 5, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Thieves' Town - Grand Room NW - Zol 2"
- [0x00ce, 0, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "Antifairy", "BigSpike", "FirebarCCW", "Bumper"]] #"Ice Palace - Over Boss - top - Red Bari 1"
- [0x00ce, 1, ["RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "Antifairy", "BigSpike", "FirebarCW", "Bumper"]] #"Ice Palace - Over Boss - top - Red Bari 2"
- [0x00ce, 3, ["SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "Antifairy", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper"]] #"Ice Palace - Over Boss - top - Statue"
- [0x00d0, 6, ["Statue", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] # Agahnims Tower - Dark Maze - Blue Guard 2
- [0x00d2, 8, ["RollerVerticalDown", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Misery Mire - Mire 2 - Popo BL"
- [0x00d5, 0, ["Kodongo"]] #"Turtle Rock - Eye Bridge - Laser Eye (Left) 1"
- [0x00d5, 1, ["Kodongo"]] #"Turtle Rock - Eye Bridge - Laser Eye (Right) 1"
- [0x00d5, 2, ["Kodongo"]] #"Turtle Rock - Eye Bridge - Laser Eye (Left) 2"
- [0x00d5, 3, ["Kodongo"]] #"Turtle Rock - Eye Bridge - Laser Eye (Right) 2"
- [0x00d5, 4, ["Statue", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper"]] #"Turtle Rock - Eye Bridge - Hardhat Beetle"
- [0x00d8, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Red Eyegore L"
- [0x00d8, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Red Eyegore R"
- [0x00d8, 2, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Popo B TL"
- [0x00d8, 3, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Popo B TR"
- [0x00d8, 4, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Popo B LT"
- [0x00d8, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Popo B RT"
- [0x00d8, 6, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Popo LB"
- [0x00d8, 7, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Eastern Palace - Kill Room 2 - Popo RB"
- [0x00d8, 8, ["Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Eastern Palace - Kill Room 1 - Red Eyegore"
- [0x00d9, 1, ["RollerHorizontalRight"]] #"Eastern Palace - Dodgeball - Green Eyegore 1"
- [0x00dc, 9, ["RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Thieves' Town - Grand Room SE - Fire Snake 2"
- [0x00df, 0, ["RollerVerticalDown", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Paradox Cave - Top - Mini Moldorm 1"
- [0x00df, 1, ["RollerVerticalDown", "RollerHorizontalRight", "AntiFairyCircle"]] #"Paradox Cave - Top - Mini Moldorm 2"
- [0x00e4, 0, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Old Man Home - Keese 1"
- [0x00e4, 1, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Old Man Home - Keese 2"
- [0x00e4, 2, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Old Man Home - Keese 3"
#- [0x00e5, 3, ["Kodongo"]] #"Old Man Home Circle - Keese 4"
- [0x00e5, 4, ["RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Kodongo", "Bumper"]] #"Old Man Home Circle - Keese 5"
- [0x00e5, 5, ["RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Kodongo", "Bumper"]] #"Old Man Home Circle - Keese 6"
- [0x00e7, 0, [ "RollerVerticalUp", "Kodongo", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 1"
- [0x00e7, 1, [ "RollerVerticalUp", "Kodongo", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 2"
- [0x00e7, 2, [ "Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Death Mountain Descent Cave Right - Keese 3"
- [0x00e7, 3, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 4"
- [0x00e7, 4, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 5"
- [0x00e7, 5, [ "Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Death Mountain Descent Cave Right - Keese 6"
- [0x00e7, 6, [ "Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Death Mountain Descent Cave Right - Keese 7"
- [0x00e8, 0, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "SpikeBlock", "Bumper"]] #"Super Bunny Exit - Hardhat Beetle 1"
- [0x00e8, 1, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Super Bunny Exit - Hardhat Beetle 2"
- [0x00ee, 0, ["RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper"]] #"Sprial Cave Top - Mini Moldorm 1"
- [0x00ee, 1, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Sprial Cave Top - Mini Moldorm 2"
- [0x00ee, 2, ["RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Sprial Cave Top - Mini Moldorm 3"
- [0x00ee, 3, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Sprial Cave Top - Blue Bari 1"
- [0x00ee, 4, ["RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Sprial Cave Top - Blue Bari 2"
- [0x00ef, 1, ["RollerVerticalUp", "RollerVerticalDown"]] #"Paradox Cave - Middle - Mini Moldorm 2"
#- [0x00f0, 0, ["Kodongo"]] #"Old Man Cave Ledge - Keese 1"
#- [0x00f0, 1, ["Kodongo"]] #"Old Man Cave Ledge - Keese 2"
#- [0x00f0, 2, ["Kodongo"]] #"Old Man Cave Ledge - Keese 3"
#- [0x00f0, 3, ["Kodongo"]] #"Old Man Cave Ledge - Keese 4"
#- [0x00f0, 4, ["Kodongo"]] #"Old Man Cave Ledge - Keese 5"
#- [0x00f0, 5, ["Kodongo"]] #"Old Man Cave Ledge - Keese 6"
#- [0x00f0, 6, ["Kodongo"]] #"Old Man Cave Ledge - Keese 7"
#- [0x00f0, 7, ["Kodongo"]] #"Old Man Cave Ledge - Keese 8"
#- [0x00f0, 9, ["Kodongo"]] #"Old Man Cave Ledge - Keese 9"
- [0x00f1, 0, ["Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Old Man Maze - Keese 1"
- [0x00f1, 1, ["Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Old Man Maze - Keese 2"
- [0x00f1, 2, ["Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Old Man Maze - Keese 3"
- [0x00f1, 3, ["Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Old Man Maze - Keese 4"
- [0x00f1, 4, ["Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Old Man Maze - Keese 5"
- [0x00f1, 5, ["Kodongo", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight"]] #"Old Man Maze - Keese 6"
#- [0x00f1, 6, ["Kodongo"]] #"Old Man Maze - Keese 7"
#- [0x00f1, 7, ["Kodongo"]] #"Old Man Maze - Keese 8"
#- [0x00f1, 8, ["Kodongo"]] #"Old Man Maze - Keese 9"
#- [0x00f1, 9, ["Kodongo"]] #"Old Man Maze - Keese 10"

View File

@@ -104,6 +104,8 @@ class RuleFactory(object):
rule = Rule(RuleType.Conjunction)
rule_lambda = None
for r in rules:
if r is None:
continue
if r.rule_type == RuleType.Conjunction:
rule.sub_rules.extend(r.sub_rules) # todo: this extension for the lambda calc
elif r.rule_type == RuleType.Static and r.principal: # remove static flag if unnecessary
@@ -126,6 +128,8 @@ class RuleFactory(object):
rule = Rule(RuleType.Disjunction)
rule_lambda = None
for r in rules:
if r is None:
continue
if r.rule_type == RuleType.Disjunction:
rule.sub_rules.extend(r.sub_rules) # todo: this extension for the lambda calc
elif r.rule_type == RuleType.Static and not r.principal: # remove static flag if unnecessary

View File

@@ -1,8 +1,9 @@
from collections import defaultdict
from Utils import snes_to_pc, int24_as_bytes, int16_as_bytes
from Utils import snes_to_pc, int24_as_bytes, int16_as_bytes, load_yaml
from source.dungeon.EnemyList import EnemyTable, init_vanilla_sprites, vanilla_sprites, init_enemy_stats
from source.dungeon.EnemyList import EnemyTable, init_vanilla_sprites, vanilla_sprites, init_enemy_stats, EnemySprite
from source.dungeon.EnemyList import sprite_translation
from source.dungeon.RoomHeader import init_room_headers
from source.dungeon.RoomList import Room0127
from source.enemizer.OwEnemyList import init_vanilla_sprites_ow, vanilla_sprites_ow
@@ -14,7 +15,7 @@ def convert_area_id_to_offset(area_id):
return area_id
if 0x40 <= area_id < 0x80:
return area_id + 0x40
if 0x90 <= area_id < 0xCF:
if 0x90 <= area_id <= 0xCF:
return area_id - 0x50
raise Exception(f'{hex(area_id)} is not a valid area id for offset math')
@@ -31,12 +32,24 @@ class DataTables:
# associated data
self.sprite_requirements = None
self.room_requirements = None
self.enemy_stats = None
self.enemy_damage = None
self.bush_sprite_table = {}
def write_to_rom(self, rom, colorize_pots=False):
# enemizer conditions
self.uw_enemy_denials = {}
for denial in load_yaml(['source', 'enemizer', 'uw_enemy_deny.yaml']):
self.uw_enemy_denials[denial[0], denial[1]] = {sprite_translation[x] for x in denial[2]}
# todo: ow_denials
weights = load_yaml(['source', 'enemizer', 'enemy_weight.yaml'])
self.uw_weights = {sprite_translation[k]: v for k, v in weights['UW'].items()}
self.ow_weights = {sprite_translation[k]: v for k, v in weights['OW'].items()}
def write_to_rom(self, rom, colorize_pots=False, increase_bush_sprite_chance=False):
if self.pot_secret_table.size() > 0x11c0:
raise Exception('Pot table is too big for current area')
self.pot_secret_table.write_pot_data_to_rom(rom, colorize_pots)
self.pot_secret_table.write_pot_data_to_rom(rom, colorize_pots, self)
for room_id, header in self.room_headers.items():
data_location = (0x30DA00 + room_id * 14) & 0xFFFF
rom.write_bytes(snes_to_pc(0x04F1E2) + room_id * 2, int16_as_bytes(data_location))
@@ -58,19 +71,73 @@ class DataTables:
if self.uw_enemy_table.size() > 0x2800:
raise Exception('Sprite table is too big for current area')
self.uw_enemy_table.write_sprite_data_to_rom(rom)
for area_id, sheet_number in self.overworld_sprite_sheets.items():
for area_id, sheet in self.overworld_sprite_sheets.items():
if area_id in [0x80, 0x81]:
offset = area_id - 0x80 # 02E575 for special areas?
rom.write_byte(snes_to_pc(0x02E576+offset), sheet_number)
rom.write_byte(snes_to_pc(0x02E576+offset), sheet.id)
else:
offset = convert_area_id_to_offset(area_id)
rom.write_byte(snes_to_pc(0x00FA81+offset), sheet_number)
rom.write_byte(snes_to_pc(0x00FA81+offset), sheet.id)
# _00FA81 is LW normal
# _00FAC1 is LW post-aga
# _00FB01 is DW
for area, sprite_list in vanilla_sprites_ow.items():
for area, sprite_list in self.ow_enemy_table.items():
for sprite in sprite_list:
rom.write_bytes(snes_to_pc(sprite.original_address), sprite.sprite_data_ow())
for sprite, stats in self.enemy_stats.items():
# write health to rom
if stats.health is not None:
if isinstance(stats.health, tuple):
if sprite == EnemySprite.Octorok4Way: # skip this one
continue
if sprite in special_health_table:
a1, a2 = special_health_table[sprite]
rom.write_byte(snes_to_pc(a1), stats.health[0])
rom.write_byte(snes_to_pc(a2), stats.health[1])
else:
rom.write_byte(snes_to_pc(0x0DB173+int(sprite)), stats.health)
# write damage class to rom
if stats.damage is not None:
if isinstance(stats.damage, tuple):
if sprite == EnemySprite.Octorok4Way: # skip this one
continue
if sprite in special_damage_table:
a1, a2 = special_damage_table[sprite]
rom.write_byte(snes_to_pc(a1), stats.dmask | stats.damage[0])
rom.write_byte(snes_to_pc(a2), stats.dmask | stats.damage[1])
else:
rom.write_byte(snes_to_pc(0x0DB266+int(sprite)), stats.dmask | stats.damage)
# write damage table to rom
for idx, damage_list in self.enemy_damage.items():
rom.write_bytes(snes_to_pc(0x06F42D + idx * 3), damage_list)
# write bush spawns to rom:
for area_id, bush_sprite in self.bush_sprite_table.items():
rom.write_byte(snes_to_pc(0x368120 + area_id), bush_sprite.sprite)
if increase_bush_sprite_chance:
rom.write_bytes(snes_to_pc(0x1AFBBB), [
0x01, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x12,
0x0F, 0x01, 0x0F, 0x0F, 0x11, 0x0F, 0x0F, 0x03
])
special_health_table = {
EnemySprite.Octorok: (0x068F76, 0x068F77),
EnemySprite.HardhatBeetle: (0x06911F, 0x069120),
EnemySprite.Tektite: (0x068D97, 0x068D98),
EnemySprite.CricketRat: (0x068876, 0x068877),
EnemySprite.Keese: (0x06888A, 0x06888B),
EnemySprite.Snake: (0x0688A6, 0x0688A7),
EnemySprite.Raven: (0x068965, 0x068966)
}
special_damage_table = {
EnemySprite.Octorok: (0x068F74, 0x068F75),
EnemySprite.Tektite: (0x068D99, 0x068D9A),
EnemySprite.CricketRat: (0x068874, 0x068875),
EnemySprite.Keese: (0x068888, 0x068889),
EnemySprite.Snake: (0x0688A4, 0x0688A5),
EnemySprite.Raven: (0x068963, 0x068964)
}
def init_data_tables(world, player):
@@ -93,4 +160,6 @@ def init_data_tables(world, player):
for area, sprite_list in vanilla_sprites_ow.items():
for sprite in sprite_list:
data_tables.ow_enemy_table[area].append(sprite.copy())
data_tables.enemy_damage = {k: list(v) for k, v in world.damage_table[player].enemy_damage.items()}
# todo: more denials based on enemy drops
return data_tables