SMW: v1.1 Content Update (#1344)

* Make Bowser unkillable on Egg Hunt

* Increment Data Package version

Changed a location name.

* Baseline for Bowser Rooms shuffling

* Add boss shuffle

* Remove extra space

* Overworld Palette Shuffle

* Fix Literature Trap typo

* Handle Queuing traps and new Timer Trap

* Fix trap name and actually create them

* Early Climb and Overworld Speed

* Add correct tooltip for Early Climb

* Tooltip text edit

* Address unconnected regions

* Add option to fully exclude Special Zone levels from the seed

* Fix Chocolate Island 4 Dragon Coins logic

* Update worlds/smw/Client.py to use `getattr`
This commit is contained in:
PoryGone 2023-01-29 23:53:56 -05:00 committed by GitHub
parent 428344b6bc
commit dc2aa5f41e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 425 additions and 58 deletions

View File

@ -136,6 +136,15 @@ valid_background_colors = {
0xFFF45A: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Castle
}
valid_ow_palettes = {
0x2D1E: [0x00, 0x01, 0x03], # Main OW
0x2D1F: [0x00, 0x03, 0x04], # Yoshi's Island
0x2D20: [0x00, 0x01, 0x03, 0x04], # Vanilla Dome
0x2D21: [0x00, 0x02, 0x03, 0x04], # Forest of Illusion
0x2D22: [0x00, 0x01, 0x03, 0x04], # Valley of Bowser
0x2D24: [0x00, 0x02, 0x03], # Star Road
}
def generate_shuffled_level_music(world, player):
shuffled_level_music = level_music_value_data.copy()
@ -158,6 +167,12 @@ def generate_shuffled_ow_music(world, player):
return shuffled_ow_music
def generate_shuffled_ow_palettes(rom, world, player):
if world.overworld_palette_shuffle[player]:
for address, valid_palettes in valid_ow_palettes.items():
chosen_palette = world.random.choice(valid_palettes)
rom.write_byte(address, chosen_palette)
def generate_shuffled_header_data(rom, world, player):
if world.music_shuffle[player] != "full" and not world.foreground_palette_shuffle[player] and not world.background_palette_shuffle[player]:
return

View File

@ -169,7 +169,74 @@ class SMWSNIClient(SNIClient):
await snes_flush_writes(ctx)
return
def add_trap_to_queue(self, trap_item, trap_msg):
self.trap_queue = getattr(self, "trap_queue", [])
self.trap_queue.append((trap_item, trap_msg))
async def handle_trap_queue(self, ctx):
from SNIClient import snes_buffered_write, snes_flush_writes, snes_read
if not hasattr(self, "trap_queue") or len(self.trap_queue) == 0:
return
game_state = await snes_read(ctx, SMW_GAME_STATE_ADDR, 0x1)
if game_state[0] != 0x14:
return
mario_state = await snes_read(ctx, SMW_MARIO_STATE_ADDR, 0x1)
if mario_state[0] != 0x00:
return
pause_state = await snes_read(ctx, SMW_PAUSE_ADDR, 0x1)
if pause_state[0] != 0x00:
return
next_trap, message = self.trap_queue.pop(0)
from worlds.smw.Rom import trap_rom_data
if next_trap.item in trap_rom_data:
trap_active = await snes_read(ctx, WRAM_START + trap_rom_data[next_trap.item][0], 0x3)
if next_trap.item == 0xBC0016:
# Timer Trap
if trap_active[0] == 0 or (trap_active[0] == 1 and trap_active[1] == 0 and trap_active[2] == 0):
# Trap already active
self.add_trap_to_queue(next_trap, message)
return
else:
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0], bytes([0x01]))
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0] + 1, bytes([0x00]))
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0] + 2, bytes([0x00]))
else:
if trap_active[0] > 0:
# Trap already active
self.add_trap_to_queue(next_trap, message)
return
else:
verify_game_state = await snes_read(ctx, SMW_GAME_STATE_ADDR, 0x1)
if verify_game_state[0] == 0x14 and len(trap_rom_data[next_trap.item]) > 2:
snes_buffered_write(ctx, SMW_SFX_ADDR, bytes([trap_rom_data[next_trap.item][2]]))
new_item_count = trap_rom_data[next_trap.item][1]
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0], bytes([new_item_count]))
current_level = await snes_read(ctx, SMW_CURRENT_LEVEL_ADDR, 0x1)
if current_level[0] in SMW_BAD_TEXT_BOX_LEVELS:
return
boss_state = await snes_read(ctx, SMW_BOSS_STATE_ADDR, 0x1)
if boss_state[0] in SMW_BOSS_STATES:
return
active_boss = await snes_read(ctx, SMW_ACTIVE_BOSS_ADDR, 0x1)
if active_boss[0] != 0x00:
return
if ctx.receive_option == 1 or (ctx.receive_option == 2 and ((next_trap.flags & 1) != 0)):
self.add_message_to_queue(message)
async def game_watcher(self, ctx):
@ -229,13 +296,14 @@ class SMWSNIClient(SNIClient):
await snes_flush_writes(ctx)
await self.handle_message_queue(ctx)
await self.handle_trap_queue(ctx)
new_checks = []
event_data = await snes_read(ctx, SMW_EVENT_ROM_DATA, 0x60)
progress_data = bytearray(await snes_read(ctx, SMW_PROGRESS_DATA, 0x0F))
dragon_coins_data = bytearray(await snes_read(ctx, SMW_DRAGON_COINS_DATA, 0x0C))
dragon_coins_active = await snes_read(ctx, SMW_DRAGON_COINS_ACTIVE_ADDR, 0x1)
from worlds.smw.Rom import item_rom_data, ability_rom_data
from worlds.smw.Rom import item_rom_data, ability_rom_data, trap_rom_data
from worlds.smw.Levels import location_id_to_level_id, level_info_dict
from worlds import AutoWorldRegister
for loc_name, level_data in location_id_to_level_id.items():
@ -307,7 +375,7 @@ class SMWSNIClient(SNIClient):
ctx.location_names[item.location], recv_index, len(ctx.items_received)))
if ctx.receive_option == 1 or (ctx.receive_option == 2 and ((item.flags & 1) != 0)):
if item.item != 0xBC0012:
if item.item != 0xBC0012 and item.item not in trap_rom_data:
# Don't send messages for Boss Tokens
item_name = ctx.item_names[item.item]
player_name = ctx.player_names[item.player]
@ -316,7 +384,13 @@ class SMWSNIClient(SNIClient):
self.add_message_to_queue(receive_message)
snes_buffered_write(ctx, SMW_RECV_PROGRESS_ADDR, bytes([recv_index]))
if item.item in item_rom_data:
if item.item in trap_rom_data:
item_name = ctx.item_names[item.item]
player_name = ctx.player_names[item.player]
receive_message = generate_received_text(item_name, player_name)
self.add_trap_to_queue(item, receive_message)
elif item.item in item_rom_data:
item_count = await snes_read(ctx, WRAM_START + item_rom_data[item.item][0], 0x1)
increment = item_rom_data[item.item][1]

View File

@ -49,6 +49,7 @@ trap_table = {
ItemName.ice_trap: ItemData(0xBC0013, False, True),
ItemName.stun_trap: ItemData(0xBC0014, False, True),
ItemName.literature_trap: ItemData(0xBC0015, False, True),
ItemName.timer_trap: ItemData(0xBC0016, False, True),
}
event_table = {

View File

@ -1,6 +1,80 @@
from .Names import LocationName
class BowserRoom():
name: str
exitAddress: int
roomID: int
def __init__(self, name: str, exitAddress: int, roomID: int):
self.name = name
self.exitAddress = exitAddress
self.roomID = roomID
full_bowser_rooms = [
BowserRoom("Hallway 1 - Door 1", 0x3A680, 0x0D),
BowserRoom("Hallway 1 - Door 2", 0x3A684, 0x0D),
BowserRoom("Hallway 1 - Door 3", 0x3A688, 0x0D),
BowserRoom("Hallway 1 - Door 4", 0x3A68C, 0x0D),
BowserRoom("Hallway 2 - Door 1", 0x3A8CB, 0xD0),
BowserRoom("Hallway 2 - Door 2", 0x3A8CF, 0xD0),
BowserRoom("Hallway 2 - Door 3", 0x3A8D3, 0xD0),
BowserRoom("Hallway 2 - Door 4", 0x3A8D7, 0xD0),
BowserRoom("Room 1", 0x3A705, 0xD4),
BowserRoom("Room 2", 0x3A763, 0xD3),
BowserRoom("Room 3", 0x3A800, 0xD2),
BowserRoom("Room 4", 0x3A83D, 0xD1),
BowserRoom("Room 5", 0x3A932, 0xCF),
BowserRoom("Room 6", 0x3A9E1, 0xCE),
BowserRoom("Room 7", 0x3AA75, 0xCD),
BowserRoom("Room 8", 0x3AAC7, 0xCC),
]
standard_bowser_rooms = [
BowserRoom("Room 1", 0x3A705, 0xD4),
BowserRoom("Room 2", 0x3A763, 0xD3),
BowserRoom("Room 3", 0x3A800, 0xD2),
BowserRoom("Room 4", 0x3A83D, 0xD1),
BowserRoom("Room 5", 0x3A932, 0xCF),
BowserRoom("Room 6", 0x3A9E1, 0xCE),
BowserRoom("Room 7", 0x3AA75, 0xCD),
BowserRoom("Room 8", 0x3AAC7, 0xCC),
]
class BossRoom():
name: str
exitAddress: int
exitAddressAlt: int
roomID: int
def __init__(self, name: str, exitAddress: int, roomID: int, exitAddressAlt=None):
self.name = name
self.exitAddress = exitAddress
self.roomID = roomID
self.exitAddressAlt = exitAddressAlt
submap_boss_rooms = [
BossRoom("#1 Lemmy Koopa", 0x311E3, 0xF6), # Submap 0x1F6
BossRoom("#3 Lemmy Koopa", 0x33749, 0xF2), # Submap 0x1F2
BossRoom("Valley Reznor", 0x3A132, 0xDE), # Submap 0x1DE
BossRoom("#7 Larry Koopa", 0x3A026, 0xEB), # Submap 0x1EB
]
ow_boss_rooms = [
BossRoom("#2 Morton Koopa Jr.", 0x3209B, 0xE5), # OW 0x0E5
BossRoom("Vanilla Reznor", 0x33EAB, 0xDF), # OW 0x0DF
BossRoom("#4 Ludwig von Koopa", 0x346EA, 0xD9), # OW 0x0D9
BossRoom("Forest Reznor", 0x3643E, 0xD5, 0x36442), # OW 0x0D5
BossRoom("#5 Roy Koopa", 0x35ABC, 0xCC), # OW 0x0CC
BossRoom("Chocolate Reznor", 0x3705B, 0xE2), # OW 0x0E2
BossRoom("#6 Wendy O. Koopa", 0x38BB5, 0xD3), # OW 0x0D3
]
class SMWPath():
thisEndDirection: int
otherLevelID: int
@ -203,6 +277,9 @@ hard_single_levels = [
0x3B,
0x3A,
0x37,
]
special_zone_levels = [
0x4E,
0x4F,
0x50,
@ -443,6 +520,7 @@ def generate_level_list(world, player):
world.random.shuffle(easy_single_levels_copy)
hard_single_levels_copy = hard_single_levels.copy()
world.random.shuffle(hard_single_levels_copy)
special_zone_levels_copy = special_zone_levels.copy()
easy_double_levels_copy = easy_double_levels.copy()
world.random.shuffle(easy_double_levels_copy)
hard_double_levels_copy = hard_double_levels.copy()
@ -474,6 +552,8 @@ def generate_level_list(world, player):
shuffled_level_list.append(0x16)
single_levels_copy = (easy_single_levels_copy.copy() + hard_single_levels_copy.copy())
if not world.exclude_special_zone[player]:
single_levels_copy.extend(special_zone_levels_copy)
world.random.shuffle(single_levels_copy)
castle_fortress_levels_copy = (easy_castle_fortress_levels_copy.copy() + hard_castle_fortress_levels_copy.copy())
@ -566,14 +646,17 @@ def generate_level_list(world, player):
# Special Zone
shuffled_level_list.append(0x4D)
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
if not world.exclude_special_zone[player]:
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
shuffled_level_list.append(single_levels_copy.pop(0))
else:
shuffled_level_list.extend(special_zone_levels_copy)
shuffled_level_list.append(0x48)
return shuffled_level_list

View File

@ -212,6 +212,28 @@ all_locations = {
**yoshi_house_location_table,
}
special_zone_level_names = [
LocationName.special_zone_1_exit_1,
LocationName.special_zone_2_exit_1,
LocationName.special_zone_3_exit_1,
LocationName.special_zone_4_exit_1,
LocationName.special_zone_5_exit_1,
LocationName.special_zone_6_exit_1,
LocationName.special_zone_7_exit_1,
LocationName.special_zone_8_exit_1,
]
special_zone_dragon_coin_names = [
LocationName.special_zone_1_dragon,
LocationName.special_zone_2_dragon,
LocationName.special_zone_3_dragon,
LocationName.special_zone_4_dragon,
LocationName.special_zone_5_dragon,
LocationName.special_zone_6_dragon,
LocationName.special_zone_7_dragon,
LocationName.special_zone_8_dragon,
]
location_table = {}

View File

@ -26,6 +26,7 @@ blue_switch_palace = "Blue Switch Palace"
ice_trap = "Ice Trap"
stun_trap = "Stun Trap"
literature_trap = "Literature Trap"
timer_trap = "Timer Trap"
# Other Definitions
victory = "The Princess"

View File

@ -25,7 +25,7 @@ lit_trap_text_list = [
[[0x18, 0x4e, 0x54, 0x1f, 0x47, 0x40, 0x55, 0x44, 0x1f, 0x41, 0x51, 0x40, 0x48, 0x4d, 0x52, 0x1f, 0x48, 0xcd, 0x58, 0x4e, 0x54, 0x51, 0x1f, 0x47, 0x44, 0x40, 0x43, 0x1b, 0x1f, 0x18, 0x4e, 0x54, 0x9f, 0x47, 0x40, 0x55, 0x44, 0x1f, 0x45, 0x44, 0x44, 0x53, 0x1f, 0x48, 0x4d, 0x1f, 0x58, 0x4e, 0x54, 0x51, 0x9f, 0x52, 0x47, 0x4e, 0x44, 0x52, 0x1b, 0x1f, 0x18, 0x4e, 0x54, 0x1f, 0x42, 0x40, 0x4d, 0x9f, 0x52, 0x53, 0x44, 0x44, 0x51, 0x1f, 0x58, 0x4e, 0x54, 0x51, 0x52, 0x44, 0x4b, 0x45, 0x1f, 0x40, 0x4d, 0xd8, 0x43, 0x48, 0x51, 0x44, 0x42, 0x53, 0x48, 0x4e, 0x4d, 0x1f, 0x58, 0x4e, 0x54, 0x9f, 0x42, 0x47, 0x4e, 0x4e, 0x52, 0x44, 0x1b, 0x1f, 0x18, 0x4e, 0x54, 0x5d, 0x51, 0x44, 0x1f, 0x4e, 0x4d, 0x9f, 0x58, 0x4e, 0x54, 0x51, 0x1f, 0x4e, 0x56, 0x4d, 0x1b, 0x1f, 0x0, 0x4d, 0x43, 0x1f, 0x58, 0x4e, 0x54, 0x9f, ], [0x4a, 0x4d, 0x4e, 0x56, 0x1f, 0x56, 0x47, 0x40, 0x53, 0x1f, 0x58, 0x4e, 0x54, 0x9f, 0x4a, 0x4d, 0x4e, 0x56, 0x1b, 0x1f, 0x0, 0x4d, 0x43, 0x1f, 0x18, 0xe, 0x14, 0x1f, 0x40, 0x51, 0x44, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4e, 0x4d, 0x44, 0x1f, 0x56, 0x47, 0x4e, 0x5d, 0x4b, 0x4b, 0x9f, 0x43, 0x44, 0x42, 0x48, 0x43, 0x44, 0x1f, 0x56, 0x47, 0x44, 0x51, 0x44, 0x1f, 0x53, 0x4e, 0x9f, 0x46, 0x4e, 0x1b, 0x1b, 0x1b, 0x1f, 0x1c, 0x12, 0x54, 0x44, 0x52, 0x52, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
[[0x16, 0x47, 0x44, 0x4d, 0x1f, 0x58, 0x4e, 0x54, 0x1f, 0x47, 0x40, 0x55, 0x44, 0x9f, 0x44, 0x4b, 0x48, 0x4c, 0x48, 0x4d, 0x40, 0x53, 0x44, 0x43, 0x1f, 0x40, 0x4b, 0x4b, 0x9f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x48, 0x52, 0x9f, 0x48, 0x4c, 0x4f, 0x4e, 0x52, 0x52, 0x48, 0x41, 0x4b, 0x44, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x4d, 0x9f, 0x56, 0x47, 0x40, 0x53, 0x44, 0x55, 0x44, 0x51, 0x1f, 0x51, 0x44, 0x4c, 0x40, 0x48, 0x4d, 0x52, 0x1d, 0x9f, 0x47, 0x4e, 0x56, 0x44, 0x55, 0x44, 0x51, 0x9f, 0x48, 0x4c, 0x4f, 0x51, 0x4e, 0x41, 0x40, 0x41, 0x4b, 0x44, 0x1d, 0x1f, 0x4c, 0x54, 0x52, 0x53, 0x9f, 0x41, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x53, 0x51, 0x54, 0x53, 0x47, 0x1b, 0x9f, ], [0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
[[0x5d, 0xc, 0x58, 0x1f, 0x4c, 0x48, 0x4d, 0x43, 0x1d, 0x5d, 0x1f, 0x47, 0x44, 0x9f, 0x52, 0x40, 0x48, 0x43, 0x1d, 0x1f, 0x5d, 0x51, 0x44, 0x41, 0x44, 0x4b, 0x52, 0x1f, 0x40, 0x53, 0x9f, 0x52, 0x53, 0x40, 0x46, 0x4d, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1b, 0x1f, 0x6, 0x48, 0x55, 0x44, 0x9f, 0x4c, 0x44, 0x1f, 0x4f, 0x51, 0x4e, 0x41, 0x4b, 0x44, 0x4c, 0x52, 0x1d, 0x1f, 0x46, 0x48, 0x55, 0x44, 0x9f, 0x4c, 0x44, 0x1f, 0x56, 0x4e, 0x51, 0x4a, 0x1d, 0x1f, 0x46, 0x48, 0x55, 0x44, 0x1f, 0x4c, 0x44, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x40, 0x41, 0x52, 0x53, 0x51, 0x54, 0x52, 0x44, 0x9f, 0x42, 0x51, 0x58, 0x4f, 0x53, 0x4e, 0x46, 0x51, 0x40, 0x4c, 0x1f, 0x4e, 0x51, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x48, 0x4d, 0x53, 0x51, 0x48, 0x42, 0x40, 0x53, 0x44, 0x9f, ], [0x40, 0x4d, 0x40, 0x4b, 0x58, 0x52, 0x48, 0x52, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x1f, 0x8, 0x1f, 0x40, 0xcc, 0x48, 0x4d, 0x1f, 0x4c, 0x58, 0x1f, 0x4e, 0x56, 0x4d, 0x1f, 0x4f, 0x51, 0x4e, 0x4f, 0x44, 0x51, 0x9f, 0x40, 0x53, 0x4c, 0x4e, 0x52, 0x4f, 0x47, 0x44, 0x51, 0x44, 0x1b, 0x1f, 0x8, 0x1f, 0x42, 0x40, 0x4d, 0x9f, 0x43, 0x48, 0x52, 0x4f, 0x44, 0x4d, 0x52, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x4d, 0x1f, 0x56, 0x48, 0x53, 0xc7, 0x40, 0x51, 0x53, 0x48, 0x45, 0x48, 0x42, 0x48, 0x40, 0x4b, 0x9f, 0x52, 0x53, 0x48, 0x4c, 0x54, 0x4b, 0x40, 0x4d, 0x53, 0x52, 0x1b, 0x1f, 0x1, 0x54, 0x53, 0x1f, 0x8, 0x9f, 0x40, 0x41, 0x47, 0x4e, 0x51, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x43, 0x54, 0x4b, 0x4b, 0x9f, 0x51, 0x4e, 0x54, 0x53, 0x48, 0x4d, 0x44, 0x1f, 0x4e, 0x45, 0x9f, ], [0x44, 0x57, 0x48, 0x52, 0x53, 0x44, 0x4d, 0x42, 0x44, 0x1b, 0x1f, 0x8, 0x1f, 0x42, 0x51, 0x40, 0x55, 0xc4, 0x45, 0x4e, 0x51, 0x1f, 0x4c, 0x44, 0x4d, 0x53, 0x40, 0x4b, 0x9f, 0x44, 0x57, 0x40, 0x4b, 0x53, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1b, 0x1f, 0x13, 0x47, 0x40, 0x53, 0x9f, 0x48, 0x52, 0x1f, 0x56, 0x47, 0x58, 0x1f, 0x8, 0x1f, 0x47, 0x40, 0x55, 0x44, 0x9f, 0x42, 0x47, 0x4e, 0x52, 0x44, 0x4d, 0x1f, 0x4c, 0x58, 0x1f, 0x4e, 0x56, 0x4d, 0x9f, 0x4f, 0x40, 0x51, 0x53, 0x48, 0x42, 0x54, 0x4b, 0x40, 0x51, 0x9f, 0x4f, 0x51, 0x4e, 0x45, 0x44, 0x52, 0x52, 0x48, 0x4e, 0x4d, 0x1d, 0x1f, 0x4e, 0x51, 0x9f, 0x51, 0x40, 0x53, 0x47, 0x44, 0x51, 0x1f, 0x42, 0x51, 0x44, 0x40, 0x53, 0x44, 0x43, 0x1f, 0x48, 0x53, 0x9d, ], [0x45, 0x4e, 0x51, 0x1f, 0x8, 0x1f, 0x40, 0x4c, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x4e, 0x4d, 0x4b, 0x58, 0x9f, 0x4e, 0x4d, 0x44, 0x1f, 0x48, 0x4d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x56, 0x4e, 0x51, 0x4b, 0x43, 0x1b, 0xdd, 0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
[[0xb, 0x48, 0x45, 0x44, 0x1f, 0x48, 0x52, 0x1f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x4b, 0xd8, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x40, 0x4d, 0x9f, 0x40, 0x4d, 0x58, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x53, 0x47, 0xc4, 0x4c, 0x48, 0x4d, 0x43, 0x1f, 0x4e, 0x45, 0x1f, 0x4c, 0x40, 0x4d, 0x1f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x48, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x1b, 0x1f, 0x16, 0x44, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4d, 0x4e, 0x53, 0x1f, 0x43, 0x40, 0x51, 0x44, 0x1f, 0x53, 0x4e, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x44, 0x48, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x9f, ], [0x51, 0x44, 0x40, 0x4b, 0x4b, 0x58, 0x1f, 0x4c, 0x44, 0x51, 0x44, 0x9f, 0x42, 0x4e, 0x4c, 0x4c, 0x4e, 0x4d, 0x4f, 0x4b, 0x40, 0x42, 0x44, 0x52, 0x1f, 0x4e, 0x45, 0x9f, 0x44, 0x57, 0x48, 0x52, 0x53, 0x44, 0x4d, 0x42, 0x44, 0x1b, 0x1f, 0x8, 0x45, 0x1f, 0x56, 0x44, 0x9f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x1f, 0x45, 0x4b, 0x58, 0x1f, 0x4e, 0x54, 0x53, 0x1f, 0x4e, 0x45, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x56, 0x48, 0x4d, 0x43, 0x4e, 0x56, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x9f, 0x48, 0x4d, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x1d, 0x1f, 0x47, 0x4e, 0x55, 0x44, 0x51, 0x9f, 0x4e, 0x55, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x52, 0x1f, 0x46, 0x51, 0x44, 0x40, 0x53, 0x9f, 0x42, 0x48, 0x53, 0x58, 0x1d, 0x1f, 0x46, 0x44, 0x4d, 0x53, 0x4b, 0x58, 0x9f, ], [0x51, 0x44, 0x4c, 0x4e, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x51, 0x4e, 0x4e, 0x45, 0x52, 0x1d, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x40, 0x4d, 0x43, 0x1f, 0x4f, 0x44, 0x44, 0x4f, 0x1f, 0x48, 0x4d, 0x1f, 0x40, 0xd3, 0x53, 0x47, 0x44, 0x1f, 0x50, 0x54, 0x44, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x9f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x1f, 0x46, 0x4e, 0x48, 0x4d, 0x46, 0x9f, 0x4e, 0x4d, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x9f, 0x42, 0x4e, 0x48, 0x4d, 0x42, 0x48, 0x43, 0x44, 0x4d, 0x42, 0x44, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x4b, 0x40, 0x4d, 0x4d, 0x48, 0x4d, 0x46, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x42, 0x51, 0x4e, 0x52, 0x52, 0x1c, 0x4f, 0x54, 0x51, 0x4f, 0x4e, 0x52, 0x44, 0x52, 0x1d, 0x9f, ], [0x53, 0x47, 0x44, 0x1f, 0x56, 0x4e, 0x4d, 0x43, 0x44, 0x51, 0x45, 0x54, 0x4b, 0x9f, 0x42, 0x47, 0x40, 0x48, 0x4d, 0x52, 0x1f, 0x4e, 0x45, 0x1f, 0x44, 0x55, 0x44, 0x4d, 0x53, 0x52, 0x1d, 0x9f, 0x56, 0x4e, 0x51, 0x4a, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x47, 0x51, 0x4e, 0x54, 0x46, 0x47, 0x9f, 0x46, 0x44, 0x4d, 0x44, 0x51, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x52, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x4b, 0x44, 0x40, 0x43, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x4e, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x4e, 0x54, 0x53, 0x51, 0x44, 0x9f, 0x51, 0x44, 0x52, 0x54, 0x4b, 0x53, 0x52, 0x1d, 0x1f, 0x48, 0x53, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4c, 0x40, 0x4a, 0x44, 0x1f, 0x40, 0x4b, 0x4b, 0x1f, 0x45, 0x48, 0x42, 0x53, 0x48, 0x4e, 0x4d, 0x9f, ], [0x56, 0x48, 0x53, 0x47, 0x1f, 0x48, 0x53, 0x52, 0x9f, 0x42, 0x4e, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x48, 0x4e, 0x4d, 0x40, 0x4b, 0x48, 0x53, 0x48, 0x44, 0x52, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x45, 0x4e, 0x51, 0x44, 0x52, 0x44, 0x44, 0x4d, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x4b, 0x54, 0x52, 0x48, 0x4e, 0x4d, 0x52, 0x1f, 0x4c, 0x4e, 0x52, 0x53, 0x9f, 0x52, 0x53, 0x40, 0x4b, 0x44, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x54, 0x4d, 0x4f, 0x51, 0x4e, 0x45, 0x48, 0x53, 0x40, 0x41, 0x4b, 0x44, 0x1b, 0x9f, 0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, ]],
[[0xb, 0x48, 0x45, 0x44, 0x1f, 0x48, 0x52, 0x1f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x4b, 0xd8, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x40, 0x4d, 0x9f, 0x40, 0x4d, 0x58, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x53, 0x47, 0xc4, 0x4c, 0x48, 0x4d, 0x43, 0x1f, 0x4e, 0x45, 0x1f, 0x4c, 0x40, 0x4d, 0x1f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x48, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x1b, 0x1f, 0x16, 0x44, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4d, 0x4e, 0x53, 0x1f, 0x43, 0x40, 0x51, 0x44, 0x1f, 0x53, 0x4e, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x44, 0x48, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x9f, ], [0x51, 0x44, 0x40, 0x4b, 0x4b, 0x58, 0x1f, 0x4c, 0x44, 0x51, 0x44, 0x9f, 0x42, 0x4e, 0x4c, 0x4c, 0x4e, 0x4d, 0x4f, 0x4b, 0x40, 0x42, 0x44, 0x52, 0x1f, 0x4e, 0x45, 0x9f, 0x44, 0x57, 0x48, 0x52, 0x53, 0x44, 0x4d, 0x42, 0x44, 0x1b, 0x1f, 0x8, 0x45, 0x1f, 0x56, 0x44, 0x9f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x1f, 0x45, 0x4b, 0x58, 0x1f, 0x4e, 0x54, 0x53, 0x1f, 0x4e, 0x45, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x56, 0x48, 0x4d, 0x43, 0x4e, 0x56, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x9f, 0x48, 0x4d, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x1d, 0x1f, 0x47, 0x4e, 0x55, 0x44, 0x51, 0x9f, 0x4e, 0x55, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x52, 0x1f, 0x46, 0x51, 0x44, 0x40, 0x53, 0x9f, 0x42, 0x48, 0x53, 0x58, 0x1d, 0x1f, 0x46, 0x44, 0x4d, 0x53, 0x4b, 0x58, 0x9f, ], [0x51, 0x44, 0x4c, 0x4e, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x51, 0x4e, 0x4e, 0x45, 0x52, 0x1d, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x4f, 0x44, 0x44, 0x4f, 0x1f, 0x48, 0x4d, 0x1f, 0x40, 0xd3, 0x53, 0x47, 0x44, 0x1f, 0x50, 0x54, 0x44, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x9f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x1f, 0x46, 0x4e, 0x48, 0x4d, 0x46, 0x9f, 0x4e, 0x4d, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x9f, 0x42, 0x4e, 0x48, 0x4d, 0x42, 0x48, 0x43, 0x44, 0x4d, 0x42, 0x44, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x4b, 0x40, 0x4d, 0x4d, 0x48, 0x4d, 0x46, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x42, 0x51, 0x4e, 0x52, 0x52, 0x1c, 0x4f, 0x54, 0x51, 0x4f, 0x4e, 0x52, 0x44, 0x52, 0x1d, 0x9f, ], [0x53, 0x47, 0x44, 0x1f, 0x56, 0x4e, 0x4d, 0x43, 0x44, 0x51, 0x45, 0x54, 0x4b, 0x9f, 0x42, 0x47, 0x40, 0x48, 0x4d, 0x52, 0x1f, 0x4e, 0x45, 0x1f, 0x44, 0x55, 0x44, 0x4d, 0x53, 0x52, 0x1d, 0x9f, 0x56, 0x4e, 0x51, 0x4a, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x47, 0x51, 0x4e, 0x54, 0x46, 0x47, 0x9f, 0x46, 0x44, 0x4d, 0x44, 0x51, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x52, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x4b, 0x44, 0x40, 0x43, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x4e, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x4e, 0x54, 0x53, 0x51, 0x44, 0x9f, 0x51, 0x44, 0x52, 0x54, 0x4b, 0x53, 0x52, 0x1d, 0x1f, 0x48, 0x53, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4c, 0x40, 0x4a, 0x44, 0x1f, 0x40, 0x4b, 0x4b, 0x1f, 0x45, 0x48, 0x42, 0x53, 0x48, 0x4e, 0x4d, 0x9f, ], [0x56, 0x48, 0x53, 0x47, 0x1f, 0x48, 0x53, 0x52, 0x9f, 0x42, 0x4e, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x48, 0x4e, 0x4d, 0x40, 0x4b, 0x48, 0x53, 0x48, 0x44, 0x52, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x45, 0x4e, 0x51, 0x44, 0x52, 0x44, 0x44, 0x4d, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x4b, 0x54, 0x52, 0x48, 0x4e, 0x4d, 0x52, 0x1f, 0x4c, 0x4e, 0x52, 0x53, 0x9f, 0x52, 0x53, 0x40, 0x4b, 0x44, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x54, 0x4d, 0x4f, 0x51, 0x4e, 0x45, 0x48, 0x53, 0x40, 0x41, 0x4b, 0x44, 0x1b, 0x9f, 0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, ]],
[[0x13, 0x47, 0x44, 0x1f, 0x52, 0x53, 0x4e, 0x51, 0x58, 0x1f, 0x52, 0x4e, 0x1f, 0x45, 0x40, 0x51, 0x1b, 0x9f, 0x8, 0x4d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x41, 0x44, 0x46, 0x48, 0x4d, 0x4d, 0x48, 0x4d, 0x46, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x14, 0x4d, 0x48, 0x55, 0x44, 0x51, 0x52, 0x44, 0x1f, 0x56, 0x40, 0x52, 0x9f, 0x42, 0x51, 0x44, 0x40, 0x53, 0x44, 0x43, 0x1b, 0x1f, 0x13, 0x47, 0x48, 0x52, 0x1f, 0x47, 0x40, 0x52, 0x9f, 0x4c, 0x40, 0x43, 0x44, 0x1f, 0x40, 0x1f, 0x4b, 0x4e, 0x53, 0x1f, 0x4e, 0x45, 0x9f, 0x4f, 0x44, 0x4e, 0x4f, 0x4b, 0x44, 0x1f, 0x55, 0x44, 0x51, 0x58, 0x1f, 0x40, 0x4d, 0x46, 0x51, 0x58, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x41, 0x44, 0x44, 0x4d, 0x1f, 0x56, 0x48, 0x43, 0x44, 0x4b, 0x58, 0x9f, 0x51, 0x44, 0x46, 0x40, 0x51, 0x43, 0x44, 0x43, 0x1f, 0x40, 0x52, 0x1f, 0x40, 0x1f, 0x41, 0x40, 0x43, 0x9f, ], [0x4c, 0x4e, 0x55, 0x44, 0x1b, 0x1f, 0x1c, 0x0, 0x43, 0x40, 0x4c, 0x52, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
[[0x5, 0x4e, 0x51, 0x1f, 0x48, 0x4d, 0x52, 0x53, 0x40, 0x4d, 0x42, 0x44, 0x1d, 0x1f, 0x4e, 0x4d, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4f, 0x4b, 0x40, 0x4d, 0x44, 0x53, 0x1f, 0x4, 0x40, 0x51, 0x53, 0x47, 0x1d, 0x9f, 0x4c, 0x40, 0x4d, 0x1f, 0x47, 0x40, 0x43, 0x1f, 0x40, 0x4b, 0x56, 0x40, 0x58, 0x52, 0x9f, 0x40, 0x52, 0x52, 0x54, 0x4c, 0x44, 0x43, 0x1f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x47, 0x44, 0x9f, 0x56, 0x40, 0x52, 0x1f, 0x4c, 0x4e, 0x51, 0x44, 0x9f, 0x48, 0x4d, 0x53, 0x44, 0x4b, 0x4b, 0x48, 0x46, 0x44, 0x4d, 0x53, 0x1f, 0x53, 0x47, 0x40, 0x4d, 0x9f, 0x43, 0x4e, 0x4b, 0x4f, 0x47, 0x48, 0x4d, 0x52, 0x1f, 0x41, 0x44, 0x42, 0x40, 0x54, 0x52, 0x44, 0x9f, 0x47, 0x44, 0x1f, 0x47, 0x40, 0x43, 0x1f, 0x40, 0x42, 0x47, 0x48, 0x44, 0x55, 0x44, 0x43, 0x1f, 0x52, 0xce, ], [0x4c, 0x54, 0x42, 0x47, 0x1c, 0x53, 0x47, 0x44, 0x1f, 0x56, 0x47, 0x44, 0x44, 0x4b, 0x1d, 0x9f, 0xd, 0x44, 0x56, 0x1f, 0x18, 0x4e, 0x51, 0x4a, 0x1d, 0x1f, 0x56, 0x40, 0x51, 0x52, 0x1f, 0x40, 0x4d, 0xc3, 0x52, 0x4e, 0x1f, 0x4e, 0x4d, 0x1c, 0x56, 0x47, 0x48, 0x4b, 0x52, 0x53, 0x1f, 0x40, 0x4b, 0x4b, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x43, 0x4e, 0x4b, 0x4f, 0x47, 0x48, 0x4d, 0x52, 0x1f, 0x47, 0x40, 0x43, 0x9f, 0x44, 0x55, 0x44, 0x51, 0x1f, 0x43, 0x4e, 0x4d, 0x44, 0x1f, 0x56, 0x40, 0x52, 0x1f, 0x4c, 0x54, 0x42, 0xca, 0x40, 0x41, 0x4e, 0x54, 0x53, 0x1f, 0x48, 0x4d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x56, 0x40, 0x53, 0x44, 0xd1, 0x47, 0x40, 0x55, 0x48, 0x4d, 0x46, 0x1f, 0x40, 0x1f, 0x46, 0x4e, 0x4e, 0x43, 0x9f, 0x53, 0x48, 0x4c, 0x44, 0x1b, 0x1f, 0x1, 0x54, 0x53, 0x9f, ], [0x42, 0x4e, 0x4d, 0x55, 0x44, 0x51, 0x52, 0x44, 0x4b, 0x58, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x43, 0x4e, 0x4b, 0x4f, 0x47, 0x48, 0x4d, 0x52, 0x1f, 0x47, 0x40, 0x43, 0x9f, 0x40, 0x4b, 0x56, 0x40, 0x58, 0x52, 0x1f, 0x41, 0x44, 0x4b, 0x48, 0x44, 0x55, 0x44, 0x43, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x53, 0x47, 0x44, 0x58, 0x1f, 0x56, 0x44, 0x51, 0x44, 0x1f, 0x45, 0x40, 0xd1, 0x4c, 0x4e, 0x51, 0x44, 0x1f, 0x48, 0x4d, 0x53, 0x44, 0x4b, 0x4b, 0x48, 0x46, 0x44, 0x4d, 0x53, 0x9f, 0x53, 0x47, 0x40, 0x4d, 0x1f, 0x4c, 0x40, 0x4d, 0x1b, 0x45, 0x4e, 0x51, 0x9f, 0x4f, 0x51, 0x44, 0x42, 0x48, 0x52, 0x44, 0x4b, 0x58, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x52, 0x40, 0x4c, 0xc4, 0x51, 0x44, 0x40, 0x52, 0x4e, 0x4d, 0x52, 0x1b, 0x1f, 0x1c, 0x0, 0x43, 0x40, 0x4c, 0x52, 0x1f, 0x9f, ]],
[[0x8, 0x53, 0x1f, 0x48, 0x52, 0x1f, 0x4a, 0x4d, 0x4e, 0x56, 0x4d, 0x1f, 0x53, 0x47, 0x40, 0x53, 0x9f, 0x53, 0x47, 0x44, 0x51, 0x44, 0x1f, 0x40, 0x51, 0x44, 0x1f, 0x40, 0x4d, 0x9f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x1f, 0x4d, 0x54, 0x4c, 0x41, 0x44, 0x51, 0x1f, 0x4e, 0xc5, 0x56, 0x4e, 0x51, 0x4b, 0x43, 0x52, 0x1d, 0x1f, 0x52, 0x48, 0x4c, 0x4f, 0x4b, 0x58, 0x9f, 0x41, 0x44, 0x42, 0x40, 0x54, 0x52, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x51, 0x44, 0x1f, 0x48, 0x52, 0x9f, 0x40, 0x4d, 0x1f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x1f, 0x40, 0x4c, 0x4e, 0x54, 0x4d, 0xd3, 0x4e, 0x45, 0x1f, 0x52, 0x4f, 0x40, 0x42, 0x44, 0x1f, 0x45, 0x4e, 0x51, 0x1f, 0x53, 0x47, 0x44, 0x4c, 0x9f, 0x53, 0x4e, 0x1f, 0x41, 0x44, 0x1f, 0x48, 0x4d, 0x1b, 0x1f, 0x7, 0x4e, 0x56, 0x44, 0x55, 0x44, 0x51, 0x9d, ], [0x4d, 0x4e, 0x53, 0x1f, 0x44, 0x55, 0x44, 0x51, 0x58, 0x1f, 0x4e, 0x4d, 0x44, 0x1f, 0x4e, 0x45, 0x9f, 0x53, 0x47, 0x44, 0x4c, 0x1f, 0x48, 0x52, 0x1f, 0x48, 0x4d, 0x47, 0x40, 0x41, 0x48, 0x53, 0x44, 0x43, 0x9b, 0x13, 0x47, 0x44, 0x51, 0x44, 0x45, 0x4e, 0x51, 0x44, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x51, 0x44, 0x9f, 0x4c, 0x54, 0x52, 0x53, 0x1f, 0x41, 0x44, 0x1f, 0x40, 0x1f, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x9f, 0x4d, 0x54, 0x4c, 0x41, 0x44, 0x51, 0x1f, 0x4e, 0x45, 0x9f, 0x48, 0x4d, 0x47, 0x40, 0x41, 0x48, 0x53, 0x44, 0x43, 0x1f, 0x56, 0x4e, 0x51, 0x4b, 0x43, 0x52, 0x1b, 0x9f, 0x0, 0x4d, 0x58, 0x1f, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x1f, 0x4d, 0x54, 0x4c, 0x41, 0x44, 0x51, 0x9f, 0x43, 0x48, 0x55, 0x48, 0x43, 0x44, 0x43, 0x1f, 0x41, 0x58, 0x9f, ], [0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x58, 0x1f, 0x48, 0x52, 0x1f, 0x40, 0x52, 0x9f, 0x4d, 0x44, 0x40, 0x51, 0x1f, 0x53, 0x4e, 0x1f, 0x4d, 0x4e, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x1f, 0x40, 0xd2, 0x4c, 0x40, 0x4a, 0x44, 0x52, 0x1f, 0x4d, 0x4e, 0x1f, 0x4e, 0x43, 0x43, 0x52, 0x1d, 0x1f, 0x52, 0x4e, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x40, 0x55, 0x44, 0x51, 0x40, 0x46, 0x44, 0x9f, 0x4f, 0x4e, 0x4f, 0x54, 0x4b, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1f, 0x4e, 0x45, 0x1f, 0x40, 0x4b, 0x4b, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4f, 0x4b, 0x40, 0x4d, 0x44, 0x53, 0x52, 0x1f, 0x48, 0x4d, 0x1f, 0x53, 0x47, 0xc4, 0x14, 0x4d, 0x48, 0x55, 0x44, 0x51, 0x52, 0x44, 0x1f, 0x42, 0x40, 0x4d, 0x1f, 0x41, 0x44, 0x9f, 0x52, 0x40, 0x48, 0x43, 0x1f, 0x53, 0x4e, 0x1f, 0x41, 0x44, 0x1f, 0x59, 0x44, 0x51, 0x4e, 0x1b, 0x9f, ], [0x5, 0x51, 0x4e, 0x4c, 0x1f, 0x53, 0x47, 0x48, 0x52, 0x1f, 0x48, 0x53, 0x9f, 0x45, 0x4e, 0x4b, 0x4b, 0x4e, 0x56, 0x52, 0x1f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x4e, 0x4f, 0x54, 0x4b, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1f, 0x4e, 0x45, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x56, 0x47, 0x4e, 0x4b, 0x44, 0x1f, 0x14, 0x4d, 0x48, 0x55, 0x44, 0x51, 0x52, 0x44, 0x1f, 0x48, 0x52, 0x9f, 0x40, 0x4b, 0x52, 0x4e, 0x1f, 0x59, 0x44, 0x51, 0x4e, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x40, 0x4d, 0x58, 0x1f, 0x4f, 0x44, 0x4e, 0x4f, 0x4b, 0x44, 0x9f, 0x58, 0x4e, 0x54, 0x1f, 0x4c, 0x40, 0x58, 0x1f, 0x4c, 0x44, 0x44, 0x53, 0x1f, 0x45, 0x51, 0x4e, 0x4c, 0x9f, 0x53, 0x48, 0x4c, 0x44, 0x1f, 0x53, 0x4e, 0x1f, 0x53, 0x48, 0x4c, 0x44, 0x1f, 0x40, 0x51, 0x44, 0x9f, ], [0x4c, 0x44, 0x51, 0x44, 0x4b, 0x58, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x51, 0x4e, 0x43, 0x54, 0x42, 0x53, 0x52, 0x1f, 0x4e, 0x45, 0x1f, 0x40, 0x9f, 0x43, 0x44, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x43, 0x9f, 0x48, 0x4c, 0x40, 0x46, 0x48, 0x4d, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1b, 0x9f, 0x1c, 0x0, 0x43, 0x40, 0x4c, 0x52, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, ]],

View File

@ -58,7 +58,7 @@ class BowserCastleDoors(Choice):
Vanilla: Front and Back Doors behave as vanilla
Fast: Both doors behave as the Back Door
Slow: Both doors behave as the Front Door
"Front Door" requires beating all 8 Rooms
"Front Door" rooms depend on the `bowser_castle_rooms` option
"Back Door" only requires going through the dark hallway to Bowser
"""
display_name = "Bowser Castle Doors"
@ -68,6 +68,40 @@ class BowserCastleDoors(Choice):
default = 0
class BowserCastleRooms(Choice):
"""
How the rooms of Bowser's Castle Front Door behave
Vanilla: You can choose which rooms to enter, as in vanilla
Random Two Room: Two random rooms are chosen
Random Five Room: Five random rooms are chosen
Gauntlet: All eight rooms must be cleared
Labyrinth: Which room leads to Bowser?
"""
display_name = "Bowser Castle Rooms"
option_vanilla = 0
option_random_two_room = 1
option_random_five_room = 2
option_gauntlet = 3
option_labyrinth = 4
default = 1
class BossShuffle(Choice):
"""
How the rooms of Bowser's Castle Front Door behave
None: Bosses are not shuffled
Simple: Four Reznors and the seven Koopalings are shuffled around
Full: Each boss location gets a fully random boss
Singularity: One or two bosses are chosen and placed at every boss location
"""
display_name = "Boss Shuffle"
option_none = 0
option_simple = 1
option_full = 2
option_singularity = 3
default = 0
class LevelShuffle(Toggle):
"""
Whether levels are shuffled
@ -75,6 +109,14 @@ class LevelShuffle(Toggle):
display_name = "Level Shuffle"
class ExcludeSpecialZone(Toggle):
"""
If active, this option will prevent any progression items from being placed in Special Zone levels.
Additionally, if Level Shuffle is active, Special Zone levels will not be shuffled away from their vanilla tiles.
"""
display_name = "Exclude Special Zone"
class SwapDonutGhostHouseExits(Toggle):
"""
If enabled, this option will swap which overworld direction the two exits of the level at the Donut Ghost House
@ -148,6 +190,13 @@ class LiteratureTrapWeight(BaseTrapWeight):
display_name = "Literature Trap Weight"
class TimerTrapWeight(BaseTrapWeight):
"""
Likelihood of a receiving a trap which causes the timer to run low
"""
display_name = "Timer Trap Weight"
class Autosave(DefaultOnToggle):
"""
Whether a save prompt will appear after every level
@ -155,6 +204,25 @@ class Autosave(DefaultOnToggle):
display_name = "Autosave"
class EarlyClimb(Toggle):
"""
Force Climb to appear early in the seed as a local item.
This is particularly useful to prevent BK when Level Shuffle is disabled
"""
display_name = "Early Climb"
class OverworldSpeed(Choice):
"""
How fast Mario moves on the overworld
"""
display_name = "Overworld Speed"
option_slow = 0
option_vanilla = 1
option_fast = 2
default = 1
class MusicShuffle(Choice):
"""
Music shuffle type
@ -201,6 +269,13 @@ class BackgroundPaletteShuffle(Toggle):
display_name = "Background Palette Shuffle"
class OverworldPaletteShuffle(Toggle):
"""
Whether to shuffle overworld palettes
"""
display_name = "Overworld Palette Shuffle"
class StartingLifeCount(Range):
"""
How many extra lives to start the game with
@ -220,7 +295,10 @@ smw_options: typing.Dict[str, type(Option)] = {
"percentage_of_yoshi_eggs": PercentageOfYoshiEggs,
"dragon_coin_checks": DragonCoinChecks,
"bowser_castle_doors": BowserCastleDoors,
"bowser_castle_rooms": BowserCastleRooms,
"level_shuffle": LevelShuffle,
"exclude_special_zone": ExcludeSpecialZone,
"boss_shuffle": BossShuffle,
"swap_donut_gh_exits": SwapDonutGhostHouseExits,
#"display_sent_item_popups": DisplaySentItemPopups,
"display_received_item_popups": DisplayReceivedItemPopups,
@ -228,10 +306,14 @@ smw_options: typing.Dict[str, type(Option)] = {
"ice_trap_weight": IceTrapWeight,
"stun_trap_weight": StunTrapWeight,
"literature_trap_weight": LiteratureTrapWeight,
"timer_trap_weight": TimerTrapWeight,
"autosave": Autosave,
"early_climb": EarlyClimb,
"overworld_speed": OverworldSpeed,
"music_shuffle": MusicShuffle,
"mario_palette": MarioPalette,
"foreground_palette_shuffle": ForegroundPaletteShuffle,
"background_palette_shuffle": BackgroundPaletteShuffle,
"overworld_palette_shuffle": OverworldPaletteShuffle,
"starting_life_count": StartingLifeCount,
}

View File

@ -11,14 +11,6 @@ def create_regions(world, player: int, active_locations):
menu_region = create_region(world, player, active_locations, 'Menu', None)
yoshis_island_region = create_region(world, player, active_locations, LocationName.yoshis_island_region, None)
donut_plains_region = create_region(world, player, active_locations, LocationName.donut_plains_region, None)
vanilla_dome_region = create_region(world, player, active_locations, LocationName.vanilla_dome_region, None)
twin_bridges_region = create_region(world, player, active_locations, LocationName.twin_bridges_region, None)
forest_of_illusion_region = create_region(world, player, active_locations, LocationName.forest_of_illusion_region, None)
chocolate_island_region = create_region(world, player, active_locations, LocationName.chocolate_island_region, None)
valley_of_bowser_region = create_region(world, player, active_locations, LocationName.valley_of_bowser_region, None)
star_road_region = create_region(world, player, active_locations, LocationName.star_road_region, None)
special_zone_region = create_region(world, player, active_locations, LocationName.special_zone_region, None)
yoshis_house_tile = create_region(world, player, active_locations, LocationName.yoshis_house_tile, None)
@ -472,14 +464,6 @@ def create_regions(world, player: int, active_locations):
world.regions += [
menu_region,
yoshis_island_region,
donut_plains_region,
vanilla_dome_region,
twin_bridges_region,
forest_of_illusion_region,
chocolate_island_region,
valley_of_bowser_region,
star_road_region,
special_zone_region,
yoshis_house_tile,
yoshis_house_region,
yoshis_island_1_tile,
@ -824,7 +808,7 @@ def create_regions(world, player: int, active_locations):
(state.has(ItemName.yellow_switch_palace, player) or state.has(ItemName.red_switch_palace, player)))))
add_location_to_region(world, player, active_locations, LocationName.chocolate_island_3_region, LocationName.chocolate_island_3_dragon)
add_location_to_region(world, player, active_locations, LocationName.chocolate_island_4_region, LocationName.chocolate_island_4_dragon,
lambda state: (state.has(ItemName.mario_run, player) and
lambda state: (state.has(ItemName.p_switch, player) and
state.has(ItemName.progressive_powerup, player, 3)))
add_location_to_region(world, player, active_locations, LocationName.chocolate_island_5_region, LocationName.chocolate_island_5_dragon,
lambda state: (state.has(ItemName.mario_swim, player) or
@ -866,6 +850,8 @@ def connect_regions(world, player, level_to_tile_dict):
names: typing.Dict[str, int] = {}
connect(world, player, names, "Menu", LocationName.yoshis_island_region)
connect(world, player, names, LocationName.yoshis_island_region, LocationName.yoshis_house_tile)
connect(world, player, names, LocationName.yoshis_house_tile, LocationName.donut_plains_top_secret)
connect(world, player, names, LocationName.yoshis_island_region, LocationName.yoshis_island_1_tile)
connect(world, player, names, LocationName.yoshis_island_region, LocationName.yoshis_island_2_tile)

View File

@ -1,7 +1,7 @@
import Utils
from worlds.Files import APDeltaPatch
from .Aesthetics import generate_shuffled_header_data
from .Levels import level_info_dict
from .Aesthetics import generate_shuffled_header_data, generate_shuffled_ow_palettes
from .Levels import level_info_dict, full_bowser_rooms, standard_bowser_rooms, submap_boss_rooms, ow_boss_rooms
from .Names.TextBox import generate_goal_text, title_text_mapping, generate_text_box
USHASH = 'cdd3c8c37322978ca8669b34bc89c804'
@ -36,18 +36,13 @@ item_rom_data = {
0xBC000F: [0x1F27, 0x1, 0x1C], # Green Switch Palace
0xBC0010: [0x1F2A, 0x1, 0x1C], # Red Switch Palace
0xBC0011: [0x1F29, 0x1, 0x1C], # Blue Switch Palace
0xBC0013: [0x0086, 0x1, 0x0E], # Ice Trap
0xBC0014: [0x18BD, 0x7F, 0x18], # Stun Trap
}
music_rom_data = [
]
level_music_ids = [
]
trap_rom_data = {
0xBC0013: [0x0086, 0x1, 0x0E], # Ice Trap
0xBC0014: [0x18BD, 0x7F, 0x18], # Stun Trap
0xBC0016: [0x0F31, 0x1], # Timer Trap
}
class SMWDeltaPatch(APDeltaPatch):
@ -728,6 +723,103 @@ def handle_swap_donut_gh_exits(rom):
rom.write_bytes(0x26371, bytes([0x32]))
def handle_bowser_rooms(rom, world, player):
if world.bowser_castle_rooms[player] == "random_two_room":
chosen_rooms = world.random.sample(standard_bowser_rooms, 2)
rom.write_byte(0x3A680, chosen_rooms[0].roomID)
rom.write_byte(0x3A684, chosen_rooms[0].roomID)
rom.write_byte(0x3A688, chosen_rooms[0].roomID)
rom.write_byte(0x3A68C, chosen_rooms[0].roomID)
for i in range(1, len(chosen_rooms)):
rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID)
rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD)
elif world.bowser_castle_rooms[player] == "random_five_room":
chosen_rooms = world.random.sample(standard_bowser_rooms, 5)
rom.write_byte(0x3A680, chosen_rooms[0].roomID)
rom.write_byte(0x3A684, chosen_rooms[0].roomID)
rom.write_byte(0x3A688, chosen_rooms[0].roomID)
rom.write_byte(0x3A68C, chosen_rooms[0].roomID)
for i in range(1, len(chosen_rooms)):
rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID)
rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD)
elif world.bowser_castle_rooms[player] == "gauntlet":
chosen_rooms = standard_bowser_rooms.copy()
world.random.shuffle(chosen_rooms)
rom.write_byte(0x3A680, chosen_rooms[0].roomID)
rom.write_byte(0x3A684, chosen_rooms[0].roomID)
rom.write_byte(0x3A688, chosen_rooms[0].roomID)
rom.write_byte(0x3A68C, chosen_rooms[0].roomID)
for i in range(1, len(chosen_rooms)):
rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID)
rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD)
elif world.bowser_castle_rooms[player] == "labyrinth":
bowser_rooms_copy = full_bowser_rooms.copy()
entrance_point = bowser_rooms_copy.pop(0)
world.random.shuffle(bowser_rooms_copy)
rom.write_byte(entrance_point.exitAddress, bowser_rooms_copy[0].roomID)
for i in range(0, len(bowser_rooms_copy) - 1):
rom.write_byte(bowser_rooms_copy[i].exitAddress, bowser_rooms_copy[i+1].roomID)
rom.write_byte(bowser_rooms_copy[len(bowser_rooms_copy)-1].exitAddress, 0xBD)
def handle_boss_shuffle(rom, world, player):
if world.boss_shuffle[player] == "simple":
submap_boss_rooms_copy = submap_boss_rooms.copy()
ow_boss_rooms_copy = ow_boss_rooms.copy()
world.random.shuffle(submap_boss_rooms_copy)
world.random.shuffle(ow_boss_rooms_copy)
for i in range(len(submap_boss_rooms_copy)):
rom.write_byte(submap_boss_rooms[i].exitAddress, submap_boss_rooms_copy[i].roomID)
for i in range(len(ow_boss_rooms_copy)):
rom.write_byte(ow_boss_rooms[i].exitAddress, ow_boss_rooms_copy[i].roomID)
if ow_boss_rooms[i].exitAddressAlt is not None:
rom.write_byte(ow_boss_rooms[i].exitAddressAlt, ow_boss_rooms_copy[i].roomID)
elif world.boss_shuffle[player] == "full":
for i in range(len(submap_boss_rooms)):
chosen_boss = world.random.choice(submap_boss_rooms)
rom.write_byte(submap_boss_rooms[i].exitAddress, chosen_boss.roomID)
for i in range(len(ow_boss_rooms)):
chosen_boss = world.random.choice(ow_boss_rooms)
rom.write_byte(ow_boss_rooms[i].exitAddress, chosen_boss.roomID)
if ow_boss_rooms[i].exitAddressAlt is not None:
rom.write_byte(ow_boss_rooms[i].exitAddressAlt, chosen_boss.roomID)
elif world.boss_shuffle[player] == "singularity":
chosen_submap_boss = world.random.choice(submap_boss_rooms)
chosen_ow_boss = world.random.choice(ow_boss_rooms)
for i in range(len(submap_boss_rooms)):
rom.write_byte(submap_boss_rooms[i].exitAddress, chosen_submap_boss.roomID)
for i in range(len(ow_boss_rooms)):
rom.write_byte(ow_boss_rooms[i].exitAddress, chosen_ow_boss.roomID)
if ow_boss_rooms[i].exitAddressAlt is not None:
rom.write_byte(ow_boss_rooms[i].exitAddressAlt, chosen_ow_boss.roomID)
def patch_rom(world, rom, player, active_level_dict):
local_random = world.slot_seeds[player]
@ -739,18 +831,8 @@ def patch_rom(world, rom, player, active_level_dict):
intro_text = generate_text_box("Bowser has stolen all of Mario's abilities. Can you help Mario travel across Dinosaur land to get them back and save the Princess from him?")
rom.write_bytes(0x2A5D9, intro_text)
# Force all 8 Bowser's Castle Rooms
rom.write_byte(0x3A680, 0xD4)
rom.write_byte(0x3A684, 0xD4)
rom.write_byte(0x3A688, 0xD4)
rom.write_byte(0x3A68C, 0xD4)
rom.write_byte(0x3A705, 0xD3)
rom.write_byte(0x3A763, 0xD2)
rom.write_byte(0x3A800, 0xD1)
rom.write_byte(0x3A83D, 0xCF)
rom.write_byte(0x3A932, 0xCE)
rom.write_byte(0x3A9E1, 0xCD)
rom.write_byte(0x3AA75, 0xCC)
handle_bowser_rooms(rom, world, player)
handle_boss_shuffle(rom, world, player)
# Prevent Title Screen Deaths
rom.write_byte(0x1C6A, 0x80)
@ -805,6 +887,11 @@ def patch_rom(world, rom, player, active_level_dict):
if world.autosave[player]:
rom.write_bytes(0x20F93, bytearray([0x00]))
if world.overworld_speed[player] == "fast":
rom.write_bytes(0x21414, bytearray([0x20, 0x10]))
elif world.overworld_speed[player] == "slow":
rom.write_bytes(0x21414, bytearray([0x05, 0x05]))
# Starting Life Count
rom.write_bytes(0x1E25, bytearray([world.starting_life_count[player].value - 1]))
@ -835,6 +922,8 @@ def patch_rom(world, rom, player, active_level_dict):
if world.music_shuffle[player] != "none":
handle_music_shuffle(rom, world, player)
generate_shuffled_ow_palettes(rom, world, player)
generate_shuffled_header_data(rom, world, player)
if world.swap_donut_gh_exits[player]:

View File

@ -5,12 +5,12 @@ import threading
from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification
from .Items import SMWItem, ItemData, item_table
from .Locations import SMWLocation, all_locations, setup_locations
from .Locations import SMWLocation, all_locations, setup_locations, special_zone_level_names, special_zone_dragon_coin_names
from .Options import smw_options
from .Regions import create_regions, connect_regions
from .Levels import full_level_list, generate_level_list, location_id_to_level_id
from .Rules import set_rules
from ..generic.Rules import add_rule
from ..generic.Rules import add_rule, exclusion_rules
from .Names import ItemName, LocationName
from .Client import SMWSNIClient
from ..AutoWorld import WebWorld, World
@ -41,7 +41,7 @@ class SMWWorld(World):
game: str = "Super Mario World"
option_definitions = smw_options
topology_present = False
data_version = 2
data_version = 3
required_client_version = (0, 3, 5)
item_name_to_id = {name: data.code for name, data in item_table.items()}
@ -74,6 +74,10 @@ class SMWWorld(World):
return slot_data
def generate_early(self):
if self.multiworld.early_climb[self.player]:
self.multiworld.local_early_items[self.player][ItemName.mario_climb] = 1
def generate_basic(self):
itempool: typing.List[SMWItem] = []
@ -89,6 +93,15 @@ class SMWWorld(World):
add_rule(self.multiworld.get_region(LocationName.chocolate_island_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 5))
add_rule(self.multiworld.get_region(LocationName.valley_of_bowser_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 6))
if self.multiworld.exclude_special_zone[self.player]:
exclusion_pool = set()
if self.multiworld.dragon_coin_checks[self.player]:
exclusion_pool.update(special_zone_level_names)
exclusion_pool.update(special_zone_dragon_coin_names)
elif self.multiworld.number_of_yoshi_eggs[self.player].value <= 72:
exclusion_pool.update(special_zone_level_names)
exclusion_rules(self.multiworld, self.player, exclusion_pool)
total_required_locations = 96
if self.multiworld.dragon_coin_checks[self.player]:
total_required_locations += 49
@ -120,6 +133,7 @@ class SMWWorld(World):
trap_weights += ([ItemName.ice_trap] * self.multiworld.ice_trap_weight[self.player].value)
trap_weights += ([ItemName.stun_trap] * self.multiworld.stun_trap_weight[self.player].value)
trap_weights += ([ItemName.literature_trap] * self.multiworld.literature_trap_weight[self.player].value)
trap_weights += ([ItemName.timer_trap] * self.multiworld.timer_trap_weight[self.player].value)
trap_count = 0 if (len(trap_weights) == 0) else math.ceil(junk_count * (self.multiworld.trap_fill_percentage[self.player].value / 100.0))
junk_count -= trap_count